1 /* $OpenBSD: pfctl_parser.c,v 1.194.2.1 2004/05/05 04:00:50 brad Exp $ */
2 /* $DragonFly: src/usr.sbin/pfctl/pfctl_parser.c,v 1.1 2004/09/21 21:25:28 joerg Exp $ */
5 * Copyright (c) 2001 Daniel Hartmeier
6 * Copyright (c) 2002,2003 Henning Brauer
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
13 * - Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * - Redistributions in binary form must reproduce the above
16 * copyright notice, this list of conditions and the following
17 * disclaimer in the documentation and/or other materials provided
18 * with the distribution.
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
23 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
24 * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
25 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
26 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
27 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
28 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
30 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31 * POSSIBILITY OF SUCH DAMAGE.
35 #include <sys/param.h>
36 #include <sys/ioctl.h>
37 #include <sys/socket.h>
39 #include <netinet/in.h>
40 #include <netinet/in_systm.h>
41 #include <netinet/ip.h>
42 #include <netinet/ip_icmp.h>
43 #include <netinet/icmp6.h>
44 #include <net/pf/pfvar.h>
45 #include <arpa/inet.h>
57 #include "pfctl_parser.h"
60 void print_op (u_int8_t
, const char *, const char *);
61 void print_port (u_int8_t
, u_int16_t
, u_int16_t
, const char *);
62 void print_ugid (u_int8_t
, unsigned, unsigned, const char *, unsigned);
63 void print_flags (u_int8_t
);
64 void print_fromto(struct pf_rule_addr
*, pf_osfp_t
,
65 struct pf_rule_addr
*, u_int8_t
, u_int8_t
, int);
66 int ifa_skip_if(const char *filter
, struct node_host
*p
);
68 struct node_host
*host_if(const char *, int);
69 static struct node_host
*host_v4(const char *);
70 struct node_host
*host_v6(const char *, int);
71 struct node_host
*host_dns(const char *, int, int);
73 const char *tcpflags
= "FSRPAUEW";
75 static const struct icmptypeent icmp_type
[] = {
76 { "echoreq", ICMP_ECHO
},
77 { "echorep", ICMP_ECHOREPLY
},
78 { "unreach", ICMP_UNREACH
},
79 { "squench", ICMP_SOURCEQUENCH
},
80 { "redir", ICMP_REDIRECT
},
81 { "althost", ICMP_ALTHOSTADDR
},
82 { "routeradv", ICMP_ROUTERADVERT
},
83 { "routersol", ICMP_ROUTERSOLICIT
},
84 { "timex", ICMP_TIMXCEED
},
85 { "paramprob", ICMP_PARAMPROB
},
86 { "timereq", ICMP_TSTAMP
},
87 { "timerep", ICMP_TSTAMPREPLY
},
88 { "inforeq", ICMP_IREQ
},
89 { "inforep", ICMP_IREQREPLY
},
90 { "maskreq", ICMP_MASKREQ
},
91 { "maskrep", ICMP_MASKREPLY
},
92 { "trace", ICMP_TRACEROUTE
},
93 { "dataconv", ICMP_DATACONVERR
},
94 { "mobredir", ICMP_MOBILE_REDIRECT
},
95 { "ipv6-where", ICMP_IPV6_WHEREAREYOU
},
96 { "ipv6-here", ICMP_IPV6_IAMHERE
},
97 { "mobregreq", ICMP_MOBILE_REGREQUEST
},
98 { "mobregrep", ICMP_MOBILE_REGREPLY
},
99 { "skip", ICMP_SKIP
},
100 { "photuris", ICMP_PHOTURIS
}
103 static const struct icmptypeent icmp6_type
[] = {
104 { "unreach", ICMP6_DST_UNREACH
},
105 { "toobig", ICMP6_PACKET_TOO_BIG
},
106 { "timex", ICMP6_TIME_EXCEEDED
},
107 { "paramprob", ICMP6_PARAM_PROB
},
108 { "echoreq", ICMP6_ECHO_REQUEST
},
109 { "echorep", ICMP6_ECHO_REPLY
},
110 { "groupqry", ICMP6_MEMBERSHIP_QUERY
},
111 { "listqry", MLD_LISTENER_QUERY
},
112 { "grouprep", ICMP6_MEMBERSHIP_REPORT
},
113 { "listenrep", MLD_LISTENER_REPORT
},
114 { "groupterm", ICMP6_MEMBERSHIP_REDUCTION
},
115 { "listendone", MLD_LISTENER_DONE
},
116 { "routersol", ND_ROUTER_SOLICIT
},
117 { "routeradv", ND_ROUTER_ADVERT
},
118 { "neighbrsol", ND_NEIGHBOR_SOLICIT
},
119 { "neighbradv", ND_NEIGHBOR_ADVERT
},
120 { "redir", ND_REDIRECT
},
121 { "routrrenum", ICMP6_ROUTER_RENUMBERING
},
122 { "wrureq", ICMP6_WRUREQUEST
},
123 { "wrurep", ICMP6_WRUREPLY
},
124 { "fqdnreq", ICMP6_FQDN_QUERY
},
125 { "fqdnrep", ICMP6_FQDN_REPLY
},
126 { "niqry", ICMP6_NI_QUERY
},
127 { "nirep", ICMP6_NI_REPLY
},
128 { "mtraceresp", MLD_MTRACE_RESP
},
129 { "mtrace", MLD_MTRACE
}
132 static const struct icmpcodeent icmp_code
[] = {
133 { "net-unr", ICMP_UNREACH
, ICMP_UNREACH_NET
},
134 { "host-unr", ICMP_UNREACH
, ICMP_UNREACH_HOST
},
135 { "proto-unr", ICMP_UNREACH
, ICMP_UNREACH_PROTOCOL
},
136 { "port-unr", ICMP_UNREACH
, ICMP_UNREACH_PORT
},
137 { "needfrag", ICMP_UNREACH
, ICMP_UNREACH_NEEDFRAG
},
138 { "srcfail", ICMP_UNREACH
, ICMP_UNREACH_SRCFAIL
},
139 { "net-unk", ICMP_UNREACH
, ICMP_UNREACH_NET_UNKNOWN
},
140 { "host-unk", ICMP_UNREACH
, ICMP_UNREACH_HOST_UNKNOWN
},
141 { "isolate", ICMP_UNREACH
, ICMP_UNREACH_ISOLATED
},
142 { "net-prohib", ICMP_UNREACH
, ICMP_UNREACH_NET_PROHIB
},
143 { "host-prohib", ICMP_UNREACH
, ICMP_UNREACH_HOST_PROHIB
},
144 { "net-tos", ICMP_UNREACH
, ICMP_UNREACH_TOSNET
},
145 { "host-tos", ICMP_UNREACH
, ICMP_UNREACH_TOSHOST
},
146 { "filter-prohib", ICMP_UNREACH
, ICMP_UNREACH_FILTER_PROHIB
},
147 { "host-preced", ICMP_UNREACH
, ICMP_UNREACH_HOST_PRECEDENCE
},
148 { "cutoff-preced", ICMP_UNREACH
, ICMP_UNREACH_PRECEDENCE_CUTOFF
},
149 { "redir-net", ICMP_REDIRECT
, ICMP_REDIRECT_NET
},
150 { "redir-host", ICMP_REDIRECT
, ICMP_REDIRECT_HOST
},
151 { "redir-tos-net", ICMP_REDIRECT
, ICMP_REDIRECT_TOSNET
},
152 { "redir-tos-host", ICMP_REDIRECT
, ICMP_REDIRECT_TOSHOST
},
153 { "normal-adv", ICMP_ROUTERADVERT
, ICMP_ROUTERADVERT_NORMAL
},
154 { "common-adv", ICMP_ROUTERADVERT
, ICMP_ROUTERADVERT_NOROUTE_COMMON
},
155 { "transit", ICMP_TIMXCEED
, ICMP_TIMXCEED_INTRANS
},
156 { "reassemb", ICMP_TIMXCEED
, ICMP_TIMXCEED_REASS
},
157 { "badhead", ICMP_PARAMPROB
, ICMP_PARAMPROB_ERRATPTR
},
158 { "optmiss", ICMP_PARAMPROB
, ICMP_PARAMPROB_OPTABSENT
},
159 { "badlen", ICMP_PARAMPROB
, ICMP_PARAMPROB_LENGTH
},
160 { "unknown-ind", ICMP_PHOTURIS
, ICMP_PHOTURIS_UNKNOWN_INDEX
},
161 { "auth-fail", ICMP_PHOTURIS
, ICMP_PHOTURIS_AUTH_FAILED
},
162 { "decrypt-fail", ICMP_PHOTURIS
, ICMP_PHOTURIS_DECRYPT_FAILED
}
165 static const struct icmpcodeent icmp6_code
[] = {
166 { "admin-unr", ICMP6_DST_UNREACH
, ICMP6_DST_UNREACH_ADMIN
},
167 { "noroute-unr", ICMP6_DST_UNREACH
, ICMP6_DST_UNREACH_NOROUTE
},
168 { "notnbr-unr", ICMP6_DST_UNREACH
, ICMP6_DST_UNREACH_NOTNEIGHBOR
},
169 { "beyond-unr", ICMP6_DST_UNREACH
, ICMP6_DST_UNREACH_BEYONDSCOPE
},
170 { "addr-unr", ICMP6_DST_UNREACH
, ICMP6_DST_UNREACH_ADDR
},
171 { "port-unr", ICMP6_DST_UNREACH
, ICMP6_DST_UNREACH_NOPORT
},
172 { "transit", ICMP6_TIME_EXCEEDED
, ICMP6_TIME_EXCEED_TRANSIT
},
173 { "reassemb", ICMP6_TIME_EXCEEDED
, ICMP6_TIME_EXCEED_REASSEMBLY
},
174 { "badhead", ICMP6_PARAM_PROB
, ICMP6_PARAMPROB_HEADER
},
175 { "nxthdr", ICMP6_PARAM_PROB
, ICMP6_PARAMPROB_NEXTHEADER
},
176 { "redironlink", ND_REDIRECT
, ND_REDIRECT_ONLINK
},
177 { "redirrouter", ND_REDIRECT
, ND_REDIRECT_ROUTER
}
180 const struct pf_timeout pf_timeouts
[] = {
181 { "tcp.first", PFTM_TCP_FIRST_PACKET
},
182 { "tcp.opening", PFTM_TCP_OPENING
},
183 { "tcp.established", PFTM_TCP_ESTABLISHED
},
184 { "tcp.closing", PFTM_TCP_CLOSING
},
185 { "tcp.finwait", PFTM_TCP_FIN_WAIT
},
186 { "tcp.closed", PFTM_TCP_CLOSED
},
187 { "udp.first", PFTM_UDP_FIRST_PACKET
},
188 { "udp.single", PFTM_UDP_SINGLE
},
189 { "udp.multiple", PFTM_UDP_MULTIPLE
},
190 { "icmp.first", PFTM_ICMP_FIRST_PACKET
},
191 { "icmp.error", PFTM_ICMP_ERROR_REPLY
},
192 { "other.first", PFTM_OTHER_FIRST_PACKET
},
193 { "other.single", PFTM_OTHER_SINGLE
},
194 { "other.multiple", PFTM_OTHER_MULTIPLE
},
195 { "frag", PFTM_FRAG
},
196 { "interval", PFTM_INTERVAL
},
197 { "adaptive.start", PFTM_ADAPTIVE_START
},
198 { "adaptive.end", PFTM_ADAPTIVE_END
},
199 { "src.track", PFTM_SRC_NODE
},
203 const struct icmptypeent
*
204 geticmptypebynumber(u_int8_t type
, sa_family_t af
)
208 if (af
!= AF_INET6
) {
209 for (i
=0; i
< (sizeof (icmp_type
) / sizeof(icmp_type
[0]));
211 if (type
== icmp_type
[i
].type
)
212 return (&icmp_type
[i
]);
215 for (i
=0; i
< (sizeof (icmp6_type
) /
216 sizeof(icmp6_type
[0])); i
++) {
217 if (type
== icmp6_type
[i
].type
)
218 return (&icmp6_type
[i
]);
224 const struct icmptypeent
*
225 geticmptypebyname(char *w
, sa_family_t af
)
229 if (af
!= AF_INET6
) {
230 for (i
=0; i
< (sizeof (icmp_type
) / sizeof(icmp_type
[0]));
232 if (!strcmp(w
, icmp_type
[i
].name
))
233 return (&icmp_type
[i
]);
236 for (i
=0; i
< (sizeof (icmp6_type
) /
237 sizeof(icmp6_type
[0])); i
++) {
238 if (!strcmp(w
, icmp6_type
[i
].name
))
239 return (&icmp6_type
[i
]);
245 const struct icmpcodeent
*
246 geticmpcodebynumber(u_int8_t type
, u_int8_t code
, sa_family_t af
)
250 if (af
!= AF_INET6
) {
251 for (i
=0; i
< (sizeof (icmp_code
) / sizeof(icmp_code
[0]));
253 if (type
== icmp_code
[i
].type
&&
254 code
== icmp_code
[i
].code
)
255 return (&icmp_code
[i
]);
258 for (i
=0; i
< (sizeof (icmp6_code
) /
259 sizeof(icmp6_code
[0])); i
++) {
260 if (type
== icmp6_code
[i
].type
&&
261 code
== icmp6_code
[i
].code
)
262 return (&icmp6_code
[i
]);
268 const struct icmpcodeent
*
269 geticmpcodebyname(u_long type
, char *w
, sa_family_t af
)
273 if (af
!= AF_INET6
) {
274 for (i
=0; i
< (sizeof (icmp_code
) / sizeof(icmp_code
[0]));
276 if (type
== icmp_code
[i
].type
&&
277 !strcmp(w
, icmp_code
[i
].name
))
278 return (&icmp_code
[i
]);
281 for (i
=0; i
< (sizeof (icmp6_code
) /
282 sizeof(icmp6_code
[0])); i
++) {
283 if (type
== icmp6_code
[i
].type
&&
284 !strcmp(w
, icmp6_code
[i
].name
))
285 return (&icmp6_code
[i
]);
292 print_op(u_int8_t op
, const char *a1
, const char *a2
)
295 printf(" %s >< %s", a1
, a2
);
296 else if (op
== PF_OP_XRG
)
297 printf(" %s <> %s", a1
, a2
);
298 else if (op
== PF_OP_EQ
)
300 else if (op
== PF_OP_NE
)
301 printf(" != %s", a1
);
302 else if (op
== PF_OP_LT
)
304 else if (op
== PF_OP_LE
)
305 printf(" <= %s", a1
);
306 else if (op
== PF_OP_GT
)
308 else if (op
== PF_OP_GE
)
309 printf(" >= %s", a1
);
310 else if (op
== PF_OP_RRG
)
311 printf(" %s:%s", a1
, a2
);
315 print_port(u_int8_t op
, u_int16_t p1
, u_int16_t p2
, const char *proto
)
320 s
= getservbyport(p1
, proto
);
323 snprintf(a1
, sizeof(a1
), "%u", p1
);
324 snprintf(a2
, sizeof(a2
), "%u", p2
);
326 if (s
!= NULL
&& (op
== PF_OP_EQ
|| op
== PF_OP_NE
))
327 print_op(op
, s
->s_name
, a2
);
329 print_op(op
, a1
, a2
);
333 print_ugid(u_int8_t op
, unsigned u1
, unsigned u2
, const char *t
, unsigned umax
)
337 snprintf(a1
, sizeof(a1
), "%u", u1
);
338 snprintf(a2
, sizeof(a2
), "%u", u2
);
340 if (u1
== umax
&& (op
== PF_OP_EQ
|| op
== PF_OP_NE
))
341 print_op(op
, "unknown", a2
);
343 print_op(op
, a1
, a2
);
347 print_flags(u_int8_t f
)
351 for (i
= 0; tcpflags
[i
]; ++i
)
353 printf("%c", tcpflags
[i
]);
357 print_fromto(struct pf_rule_addr
*src
, pf_osfp_t osfp
, struct pf_rule_addr
*dst
,
358 sa_family_t af
, u_int8_t proto
, int verbose
)
360 char buf
[PF_OSFP_LEN
*3];
361 if (src
->addr
.type
== PF_ADDR_ADDRMASK
&&
362 dst
->addr
.type
== PF_ADDR_ADDRMASK
&&
363 PF_AZERO(&src
->addr
.v
.a
.addr
, AF_INET6
) &&
364 PF_AZERO(&src
->addr
.v
.a
.mask
, AF_INET6
) &&
365 PF_AZERO(&dst
->addr
.v
.a
.addr
, AF_INET6
) &&
366 PF_AZERO(&dst
->addr
.v
.a
.mask
, AF_INET6
) &&
367 !src
->not && !dst
->not &&
368 !src
->port_op
&& !dst
->port_op
&&
375 print_addr(&src
->addr
, af
, verbose
);
377 print_port(src
->port_op
, src
->port
[0],
379 proto
== IPPROTO_TCP
? "tcp" : "udp");
380 if (osfp
!= PF_OSFP_ANY
)
381 printf(" os \"%s\"", pfctl_lookup_fingerprint(osfp
, buf
,
387 print_addr(&dst
->addr
, af
, verbose
);
389 print_port(dst
->port_op
, dst
->port
[0],
391 proto
== IPPROTO_TCP
? "tcp" : "udp");
396 print_pool(struct pf_pool
*pool
, u_int16_t p1
, u_int16_t p2
,
397 sa_family_t af
, int id
)
399 struct pf_pooladdr
*pooladdr
;
401 if ((TAILQ_FIRST(&pool
->list
) != NULL
) &&
402 TAILQ_NEXT(TAILQ_FIRST(&pool
->list
), entries
) != NULL
)
404 TAILQ_FOREACH(pooladdr
, &pool
->list
, entries
){
409 print_addr(&pooladdr
->addr
, af
, 0);
412 if (PF_AZERO(&pooladdr
->addr
.v
.a
.addr
, af
))
413 printf("%s", pooladdr
->ifname
);
415 printf("(%s ", pooladdr
->ifname
);
416 print_addr(&pooladdr
->addr
, af
, 0);
423 if (TAILQ_NEXT(pooladdr
, entries
) != NULL
)
425 else if (TAILQ_NEXT(TAILQ_FIRST(&pool
->list
), entries
) != NULL
)
430 if ((p1
!= PF_NAT_PROXY_PORT_LOW
||
431 p2
!= PF_NAT_PROXY_PORT_HIGH
) && (p1
!= 0 || p2
!= 0)) {
433 printf(" port %u", p1
);
435 printf(" port %u:%u", p1
, p2
);
440 printf(" port %u", p1
);
441 if (p2
&& (p2
!= p1
))
448 switch (pool
->opts
& PF_POOL_TYPEMASK
) {
451 case PF_POOL_BITMASK
:
457 case PF_POOL_SRCHASH
:
458 printf(" source-hash 0x%08x%08x%08x%08x",
459 pool
->key
.key32
[0], pool
->key
.key32
[1],
460 pool
->key
.key32
[2], pool
->key
.key32
[3]);
462 case PF_POOL_ROUNDROBIN
:
463 printf(" round-robin");
466 if (pool
->opts
& PF_POOL_STICKYADDR
)
467 printf(" sticky-address");
468 if (id
== PF_NAT
&& p1
== 0 && p2
== 0)
469 printf(" static-port");
472 const char *pf_reasons
[PFRES_MAX
+1] = PFRES_NAMES
;
473 const char *pf_fcounters
[FCNT_MAX
+1] = FCNT_NAMES
;
474 const char *pf_scounters
[FCNT_MAX
+1] = FCNT_NAMES
;
477 print_status(struct pf_status
*s
, int opts
)
484 runtime
= time(NULL
) - s
->since
;
485 running
= s
->running
? "Enabled" : "Disabled";
488 unsigned sec
, min
, hrs
, day
= runtime
;
496 snprintf(statline
, sizeof(statline
),
497 "Status: %s for %u days %.2u:%.2u:%.2u",
498 running
, day
, hrs
, min
, sec
);
500 snprintf(statline
, sizeof(statline
), "Status: %s", running
);
501 printf("%-44s", statline
);
504 printf("%15s\n\n", "Debug: None");
506 case PF_DEBUG_URGENT
:
507 printf("%15s\n\n", "Debug: Urgent");
510 printf("%15s\n\n", "Debug: Misc");
513 printf("%15s\n\n", "Debug: Loud");
516 printf("Hostid: 0x%08x\n\n", ntohl(s
->hostid
));
517 if (s
->ifname
[0] != 0) {
518 printf("Interface Stats for %-16s %5s %16s\n",
519 s
->ifname
, "IPv4", "IPv6");
520 printf(" %-25s %14llu %16llu\n", "Bytes In",
521 (unsigned long long)s
->bcounters
[0][0],
522 (unsigned long long)s
->bcounters
[1][0]);
523 printf(" %-25s %14llu %16llu\n", "Bytes Out",
524 (unsigned long long)s
->bcounters
[0][1],
525 (unsigned long long)s
->bcounters
[1][1]);
526 printf(" Packets In\n");
527 printf(" %-23s %14llu %16llu\n", "Passed",
528 (unsigned long long)s
->pcounters
[0][0][PF_PASS
],
529 (unsigned long long)s
->pcounters
[1][0][PF_PASS
]);
530 printf(" %-23s %14llu %16llu\n", "Blocked",
531 (unsigned long long)s
->pcounters
[0][0][PF_DROP
],
532 (unsigned long long)s
->pcounters
[1][0][PF_DROP
]);
533 printf(" Packets Out\n");
534 printf(" %-23s %14llu %16llu\n", "Passed",
535 (unsigned long long)s
->pcounters
[0][1][PF_PASS
],
536 (unsigned long long)s
->pcounters
[1][1][PF_PASS
]);
537 printf(" %-23s %14llu %16llu\n\n", "Blocked",
538 (unsigned long long)s
->pcounters
[0][1][PF_DROP
],
539 (unsigned long long)s
->pcounters
[1][1][PF_DROP
]);
541 printf("%-27s %14s %16s\n", "State Table", "Total", "Rate");
542 printf(" %-25s %14u %14s\n", "current entries", s
->states
, "");
543 for (i
= 0; i
< FCNT_MAX
; i
++) {
544 printf(" %-25s %14llu ", pf_fcounters
[i
],
545 (unsigned long long)s
->fcounters
[i
]);
548 (double)s
->fcounters
[i
] / (double)runtime
);
550 printf("%14s\n", "");
552 if (opts
& PF_OPT_VERBOSE
) {
553 printf("Source Tracking Table\n");
554 printf(" %-25s %14u %14s\n", "current entries",
556 for (i
= 0; i
< SCNT_MAX
; i
++) {
557 printf(" %-25s %14lld ", pf_scounters
[i
],
561 (double)s
->scounters
[i
] / (double)runtime
);
563 printf("%14s\n", "");
566 printf("Counters\n");
567 for (i
= 0; i
< PFRES_MAX
; i
++) {
568 printf(" %-25s %14llu ", pf_reasons
[i
],
569 (unsigned long long)s
->counters
[i
]);
572 (double)s
->counters
[i
] / (double)runtime
);
574 printf("%14s\n", "");
579 print_src_node(struct pf_src_node
*sn
, int opts
)
581 struct pf_addr_wrap aw
;
584 memset(&aw
, 0, sizeof(aw
));
585 if (sn
->af
== AF_INET
)
586 aw
.v
.a
.mask
.addr32
[0] = 0xffffffff;
588 memset(&aw
.v
.a
.mask
, 0xff, sizeof(aw
.v
.a
.mask
));
590 aw
.v
.a
.addr
= sn
->addr
;
591 print_addr(&aw
, sn
->af
, opts
& PF_OPT_VERBOSE2
);
593 aw
.v
.a
.addr
= sn
->raddr
;
594 print_addr(&aw
, sn
->af
, opts
& PF_OPT_VERBOSE2
);
595 printf(" (%d states)\n", sn
->states
);
596 if (opts
& PF_OPT_VERBOSE
) {
597 sec
= sn
->creation
% 60;
599 min
= sn
->creation
% 60;
601 printf(" age %.2u:%.2u:%.2u", sn
->creation
, min
, sec
);
602 if (sn
->states
== 0) {
603 sec
= sn
->expire
% 60;
605 min
= sn
->expire
% 60;
607 printf(", expires in %.2u:%.2u:%.2u",
608 sn
->expire
, min
, sec
);
610 printf(", %u pkts, %u bytes", sn
->packets
, sn
->bytes
);
611 switch (sn
->ruletype
) {
613 if (sn
->rule
.nr
!= (uint32_t)(-1))
614 printf(", nat rule %u", sn
->rule
.nr
);
617 if (sn
->rule
.nr
!= (uint32_t)(-1))
618 printf(", rdr rule %u", sn
->rule
.nr
);
621 if (sn
->rule
.nr
!= (uint32_t)(-1))
622 printf(", filter rule %u", sn
->rule
.nr
);
630 print_rule(struct pf_rule
*r
, int verbose
)
632 static const char *actiontypes
[] = { "pass", "block", "scrub", "nat",
633 "no nat", "binat", "no binat", "rdr", "no rdr" };
634 static const char *anchortypes
[] = { "anchor", "anchor", "anchor",
635 "nat-anchor", "nat-anchor", "binat-anchor", "binat-anchor",
636 "rdr-anchor", "rdr-anchor" };
640 printf("@%d ", r
->nr
);
641 if (r
->action
> PF_NORDR
)
642 printf("action(%d)", r
->action
);
643 else if (r
->anchorname
[0])
644 printf("%s %s", anchortypes
[r
->action
], r
->anchorname
);
646 printf("%s", actiontypes
[r
->action
]);
650 if (r
->action
== PF_DROP
) {
651 if (r
->rule_flag
& PFRULE_RETURN
)
653 else if (r
->rule_flag
& PFRULE_RETURNRST
) {
655 printf(" return-rst");
657 printf(" return-rst(ttl %d)", r
->return_ttl
);
658 } else if (r
->rule_flag
& PFRULE_RETURNICMP
) {
659 const struct icmpcodeent
*ic
, *ic6
;
661 ic
= geticmpcodebynumber(r
->return_icmp
>> 8,
662 r
->return_icmp
& 255, AF_INET
);
663 ic6
= geticmpcodebynumber(r
->return_icmp6
>> 8,
664 r
->return_icmp6
& 255, AF_INET6
);
668 printf(" return-icmp");
670 printf("(%u)", r
->return_icmp
& 255);
672 printf("(%s)", ic
->name
);
675 printf(" return-icmp6");
677 printf("(%u)", r
->return_icmp6
& 255);
679 printf("(%s)", ic6
->name
);
682 printf(" return-icmp");
684 printf("(%u, ", r
->return_icmp
& 255);
686 printf("(%s, ", ic
->name
);
688 printf("%u)", r
->return_icmp6
& 255);
690 printf("%s)", ic6
->name
);
696 if (r
->direction
== PF_IN
)
698 else if (r
->direction
== PF_OUT
)
702 else if (r
->log
== 2)
708 printf(" on ! %s", r
->ifname
);
710 printf(" on %s", r
->ifname
);
713 if (r
->rt
== PF_ROUTETO
)
715 else if (r
->rt
== PF_REPLYTO
)
717 else if (r
->rt
== PF_DUPTO
)
719 else if (r
->rt
== PF_FASTROUTE
)
720 printf(" fastroute");
721 if (r
->rt
!= PF_FASTROUTE
) {
723 print_pool(&r
->rpool
, 0, 0, r
->af
, PF_PASS
);
727 if (r
->af
== AF_INET
)
735 if ((p
= getprotobynumber(r
->proto
)) != NULL
)
736 printf(" proto %s", p
->p_name
);
738 printf(" proto %u", r
->proto
);
740 print_fromto(&r
->src
, r
->os_fingerprint
, &r
->dst
, r
->af
, r
->proto
,
743 print_ugid(r
->uid
.op
, r
->uid
.uid
[0], r
->uid
.uid
[1], "user",
746 print_ugid(r
->gid
.op
, r
->gid
.gid
[0], r
->gid
.gid
[1], "group",
748 if (r
->flags
|| r
->flagset
) {
750 print_flags(r
->flags
);
752 print_flags(r
->flagset
);
755 const struct icmptypeent
*it
;
757 it
= geticmptypebynumber(r
->type
-1, r
->af
);
758 if (r
->af
!= AF_INET6
)
759 printf(" icmp-type");
761 printf(" icmp6-type");
763 printf(" %s", it
->name
);
765 printf(" %u", r
->type
-1);
767 const struct icmpcodeent
*ic
;
769 ic
= geticmpcodebynumber(r
->type
-1, r
->code
-1, r
->af
);
771 printf(" code %s", ic
->name
);
773 printf(" code %u", r
->code
-1);
777 printf(" tos 0x%2.2x", r
->tos
);
778 if (r
->keep_state
== PF_STATE_NORMAL
)
779 printf(" keep state");
780 else if (r
->keep_state
== PF_STATE_MODULATE
)
781 printf(" modulate state");
782 else if (r
->keep_state
== PF_STATE_SYNPROXY
)
783 printf(" synproxy state");
785 if (r
->max_states
|| r
->max_src_nodes
|| r
->max_src_states
)
787 if (r
->rule_flag
& PFRULE_NOSYNC
)
789 if (r
->rule_flag
& PFRULE_SRCTRACK
)
791 if (r
->rule_flag
& (PFRULE_IFBOUND
| PFRULE_GRBOUND
))
793 for (i
= 0; !opts
&& i
< PFTM_MAX
; ++i
)
799 printf("max %u", r
->max_states
);
802 if (r
->rule_flag
& PFRULE_NOSYNC
) {
808 if (r
->rule_flag
& PFRULE_SRCTRACK
) {
811 printf("source-track");
812 if (r
->rule_flag
& PFRULE_RULESRCTRACK
)
818 if (r
->max_src_states
) {
821 printf("max-src-states %u", r
->max_src_states
);
824 if (r
->max_src_nodes
) {
827 printf("max-src-nodes %u", r
->max_src_nodes
);
830 if (r
->rule_flag
& PFRULE_IFBOUND
) {
836 if (r
->rule_flag
& PFRULE_GRBOUND
) {
839 printf("group-bound");
842 for (i
= 0; i
< PFTM_MAX
; ++i
)
847 printf("%s %u", pf_timeouts
[i
].name
,
852 if (r
->rule_flag
& PFRULE_FRAGMENT
)
854 if (r
->rule_flag
& PFRULE_NODF
)
856 if (r
->rule_flag
& PFRULE_RANDOMID
)
857 printf(" random-id");
859 printf(" min-ttl %d", r
->min_ttl
);
861 printf(" max-mss %d", r
->max_mss
);
863 printf(" allow-opts");
864 if (r
->action
== PF_SCRUB
) {
865 if (r
->rule_flag
& PFRULE_REASSEMBLE_TCP
)
866 printf(" reassemble tcp");
868 if (r
->rule_flag
& PFRULE_FRAGDROP
)
869 printf(" fragment drop-ovl");
870 else if (r
->rule_flag
& PFRULE_FRAGCROP
)
871 printf(" fragment crop");
873 printf(" fragment reassemble");
876 printf(" label \"%s\"", r
->label
);
877 if (r
->qname
[0] && r
->pqname
[0])
878 printf(" queue(%s, %s)", r
->qname
, r
->pqname
);
879 else if (r
->qname
[0])
880 printf(" queue %s", r
->qname
);
882 printf(" tag %s", r
->tagname
);
883 if (r
->match_tagname
[0]) {
884 if (r
->match_tag_not
)
886 printf(" tagged %s", r
->match_tagname
);
888 if (!r
->anchorname
[0] && (r
->action
== PF_NAT
||
889 r
->action
== PF_BINAT
|| r
->action
== PF_RDR
)) {
891 print_pool(&r
->rpool
, r
->rpool
.proxy_port
[0],
892 r
->rpool
.proxy_port
[1], r
->af
, r
->action
);
898 print_tabledef(const char *name
, int flags
, int addrs
,
899 struct node_tinithead
*nodes
)
901 struct node_tinit
*ti
, *nti
;
904 printf("table <%s>", name
);
905 if (flags
& PFR_TFLAG_CONST
)
907 if (flags
& PFR_TFLAG_PERSIST
)
909 SIMPLEQ_FOREACH(ti
, nodes
, entries
) {
911 printf(" file \"%s\"", ti
->file
);
916 for (h
= ti
->host
; h
!= NULL
; h
= h
->next
) {
917 printf(h
->not ? " !" : " ");
918 print_addr(&h
->addr
, h
->af
, 0);
920 nti
= SIMPLEQ_NEXT(ti
, entries
);
921 if (nti
!= NULL
&& nti
->file
== NULL
)
922 ti
= nti
; /* merge lists */
928 if (addrs
&& SIMPLEQ_EMPTY(nodes
))
939 for (p
= s
; *p
; p
++) {
940 if ((q
= strchr(tcpflags
, *p
)) == NULL
)
943 f
|= 1 << (q
- tcpflags
);
945 return (f
? f
: PF_TH_ALL
);
949 set_ipmask(struct node_host
*h
, u_int8_t b
)
951 struct pf_addr
*m
, *n
;
954 m
= &h
->addr
.v
.a
.mask
;
956 for (i
= 0; i
< 4; i
++)
960 m
->addr32
[j
++] = 0xffffffff;
963 for (i
= 31; i
> 31-b
; --i
)
964 m
->addr32
[j
] |= (1 << i
);
966 m
->addr32
[j
] = htonl(m
->addr32
[j
]);
968 /* Mask off bits of the address that will never be used. */
969 n
= &h
->addr
.v
.a
.addr
;
970 if (h
->addr
.type
== PF_ADDR_ADDRMASK
)
971 for (i
= 0; i
< 4; i
++)
972 n
->addr32
[i
] = n
->addr32
[i
] & m
->addr32
[i
];
976 check_netmask(struct node_host
*h
, sa_family_t af
)
978 struct node_host
*n
= NULL
;
981 for (n
= h
; n
!= NULL
; n
= n
->next
) {
982 if (h
->addr
.type
== PF_ADDR_TABLE
)
984 m
= &h
->addr
.v
.a
.mask
;
985 /* fix up netmask for dynaddr */
986 if (af
== AF_INET
&& h
->addr
.type
== PF_ADDR_DYNIFTL
&&
987 unmask(m
, AF_INET6
) > 32)
989 /* netmasks > 32 bit are invalid on v4 */
991 (m
->addr32
[1] || m
->addr32
[2] || m
->addr32
[3])) {
992 fprintf(stderr
, "netmask %u invalid for IPv4 address\n",
993 unmask(m
, AF_INET6
));
1000 /* interface lookup routines */
1002 struct node_host
*iftab
;
1007 struct ifaddrs
*ifap
, *ifa
;
1008 struct node_host
*n
= NULL
, *h
= NULL
;
1009 struct pfr_buffer b
;
1010 const struct pfi_if
*p
;
1012 if (getifaddrs(&ifap
) < 0)
1013 err(1, "getifaddrs");
1015 for (ifa
= ifap
; ifa
; ifa
= ifa
->ifa_next
) {
1016 if (!(ifa
->ifa_addr
->sa_family
== AF_INET
||
1017 ifa
->ifa_addr
->sa_family
== AF_INET6
||
1018 ifa
->ifa_addr
->sa_family
== AF_LINK
))
1020 n
= calloc(1, sizeof(struct node_host
));
1022 err(1, "address: calloc");
1023 n
->af
= ifa
->ifa_addr
->sa_family
;
1024 n
->ifa_flags
= ifa
->ifa_flags
;
1026 if (n
->af
== AF_INET6
&&
1027 IN6_IS_ADDR_LINKLOCAL(&((struct sockaddr_in6
*)
1028 ifa
->ifa_addr
)->sin6_addr
) &&
1029 ((struct sockaddr_in6
*)ifa
->ifa_addr
)->sin6_scope_id
==
1031 struct sockaddr_in6
*sin6
;
1033 sin6
= (struct sockaddr_in6
*)ifa
->ifa_addr
;
1034 sin6
->sin6_scope_id
= sin6
->sin6_addr
.s6_addr
[2] << 8 |
1035 sin6
->sin6_addr
.s6_addr
[3];
1036 sin6
->sin6_addr
.s6_addr
[2] = 0;
1037 sin6
->sin6_addr
.s6_addr
[3] = 0;
1041 if (n
->af
== AF_INET
) {
1042 memcpy(&n
->addr
.v
.a
.addr
, &((struct sockaddr_in
*)
1043 ifa
->ifa_addr
)->sin_addr
.s_addr
,
1044 sizeof(struct in_addr
));
1045 memcpy(&n
->addr
.v
.a
.mask
, &((struct sockaddr_in
*)
1046 ifa
->ifa_netmask
)->sin_addr
.s_addr
,
1047 sizeof(struct in_addr
));
1048 if (ifa
->ifa_broadaddr
!= NULL
)
1049 memcpy(&n
->bcast
, &((struct sockaddr_in
*)
1050 ifa
->ifa_broadaddr
)->sin_addr
.s_addr
,
1051 sizeof(struct in_addr
));
1052 if (ifa
->ifa_dstaddr
!= NULL
)
1053 memcpy(&n
->peer
, &((struct sockaddr_in
*)
1054 ifa
->ifa_dstaddr
)->sin_addr
.s_addr
,
1055 sizeof(struct in_addr
));
1056 } else if (n
->af
== AF_INET6
) {
1057 memcpy(&n
->addr
.v
.a
.addr
, &((struct sockaddr_in6
*)
1058 ifa
->ifa_addr
)->sin6_addr
.s6_addr
,
1059 sizeof(struct in6_addr
));
1060 memcpy(&n
->addr
.v
.a
.mask
, &((struct sockaddr_in6
*)
1061 ifa
->ifa_netmask
)->sin6_addr
.s6_addr
,
1062 sizeof(struct in6_addr
));
1063 if (ifa
->ifa_broadaddr
!= NULL
)
1064 memcpy(&n
->bcast
, &((struct sockaddr_in6
*)
1065 ifa
->ifa_broadaddr
)->sin6_addr
.s6_addr
,
1066 sizeof(struct in6_addr
));
1067 if (ifa
->ifa_dstaddr
!= NULL
)
1068 memcpy(&n
->peer
, &((struct sockaddr_in6
*)
1069 ifa
->ifa_dstaddr
)->sin6_addr
.s6_addr
,
1070 sizeof(struct in6_addr
));
1071 n
->ifindex
= ((struct sockaddr_in6
*)
1072 ifa
->ifa_addr
)->sin6_scope_id
;
1074 if ((n
->ifname
= strdup(ifa
->ifa_name
)) == NULL
)
1075 err(1, "ifa_load: strdup");
1086 /* add interface groups, including clonable and dynamic stuff */
1087 bzero(&b
, sizeof(b
));
1088 b
.pfrb_type
= PFRB_IFACES
;
1090 if (pfr_buf_grow(&b
, b
.pfrb_size
))
1091 err(1, "ifa_load: pfr_buf_grow");
1092 b
.pfrb_size
= b
.pfrb_msize
;
1093 if (pfi_get_ifaces(NULL
, b
.pfrb_caddr
, &b
.pfrb_size
,
1095 err(1, "ifa_load: pfi_get_ifaces");
1096 if (b
.pfrb_size
<= b
.pfrb_msize
)
1099 PFRB_FOREACH(p
, &b
) {
1100 n
= calloc(1, sizeof(struct node_host
));
1102 err(1, "address: calloc");
1104 n
->ifa_flags
= PF_IFA_FLAG_GROUP
;
1105 if (p
->pfif_flags
& PFI_IFLAG_DYNAMIC
)
1106 n
->ifa_flags
|= PF_IFA_FLAG_DYNAMIC
;
1107 if (p
->pfif_flags
& PFI_IFLAG_CLONABLE
)
1108 n
->ifa_flags
|= PF_IFA_FLAG_CLONABLE
;
1109 if (!strcmp(p
->pfif_name
, "lo"))
1110 n
->ifa_flags
|= IFF_LOOPBACK
;
1111 if ((n
->ifname
= strdup(p
->pfif_name
)) == NULL
)
1112 err(1, "ifa_load: strdup");
1128 ifa_exists(const char *ifa_name
, int group_ok
)
1130 struct node_host
*n
;
1131 char *p
, buf
[IFNAMSIZ
];
1134 group
= !isdigit(ifa_name
[strlen(ifa_name
) - 1]);
1135 if (group
&& !group_ok
)
1140 for (n
= iftab
; n
; n
= n
->next
) {
1141 if (n
->af
== AF_LINK
&& !strncmp(n
->ifname
, ifa_name
, IFNAMSIZ
))
1145 /* look for clonable and/or dynamic interface */
1146 strlcpy(buf
, ifa_name
, sizeof(buf
));
1147 for (p
= buf
+ strlen(buf
) - 1; p
> buf
&& isdigit(*p
); p
--)
1149 for (n
= iftab
; n
!= NULL
; n
= n
->next
)
1150 if (n
->af
== AF_LINK
&&
1151 !strncmp(n
->ifname
, buf
, IFNAMSIZ
))
1153 if (n
!= NULL
&& n
->ifa_flags
&
1154 (PF_IFA_FLAG_DYNAMIC
| PF_IFA_FLAG_CLONABLE
))
1155 return (n
); /* XXX */
1161 ifa_lookup(const char *ifa_name
, int flags
)
1163 struct node_host
*p
= NULL
, *h
= NULL
, *n
= NULL
;
1164 int got4
= 0, got6
= 0;
1165 const char *last_if
= NULL
;
1167 if (!strncmp(ifa_name
, "self", IFNAMSIZ
))
1173 for (p
= iftab
; p
; p
= p
->next
) {
1174 if (ifa_skip_if(ifa_name
, p
))
1176 if ((flags
& PFI_AFLAG_BROADCAST
) && p
->af
!= AF_INET
)
1178 if ((flags
& PFI_AFLAG_BROADCAST
) &&
1179 !(p
->ifa_flags
& IFF_BROADCAST
))
1181 if ((flags
& PFI_AFLAG_PEER
) &&
1182 !(p
->ifa_flags
& IFF_POINTOPOINT
))
1184 if ((flags
& PFI_AFLAG_NETWORK
) && p
->ifindex
> 0)
1186 if (last_if
== NULL
|| strcmp(last_if
, p
->ifname
))
1188 last_if
= p
->ifname
;
1189 if ((flags
& PFI_AFLAG_NOALIAS
) && p
->af
== AF_INET
&& got4
)
1191 if ((flags
& PFI_AFLAG_NOALIAS
) && p
->af
== AF_INET6
&& got6
)
1193 if (p
->af
== AF_INET
)
1197 n
= calloc(1, sizeof(struct node_host
));
1199 err(1, "address: calloc");
1201 if (flags
& PFI_AFLAG_BROADCAST
)
1202 memcpy(&n
->addr
.v
.a
.addr
, &p
->bcast
,
1203 sizeof(struct pf_addr
));
1204 else if (flags
& PFI_AFLAG_PEER
)
1205 memcpy(&n
->addr
.v
.a
.addr
, &p
->peer
,
1206 sizeof(struct pf_addr
));
1208 memcpy(&n
->addr
.v
.a
.addr
, &p
->addr
.v
.a
.addr
,
1209 sizeof(struct pf_addr
));
1210 if (flags
& PFI_AFLAG_NETWORK
)
1211 set_ipmask(n
, unmask(&p
->addr
.v
.a
.mask
, n
->af
));
1213 if (n
->af
== AF_INET
) {
1214 if (p
->ifa_flags
& IFF_LOOPBACK
&&
1215 p
->ifa_flags
& IFF_LINK1
)
1216 memcpy(&n
->addr
.v
.a
.mask
,
1218 sizeof(struct pf_addr
));
1224 n
->ifindex
= p
->ifindex
;
1239 ifa_skip_if(const char *filter
, struct node_host
*p
)
1243 if (p
->af
!= AF_INET
&& p
->af
!= AF_INET6
)
1245 if (filter
== NULL
|| !*filter
)
1247 if (!strcmp(p
->ifname
, filter
))
1248 return (0); /* exact match */
1250 if (n
< 1 || n
>= IFNAMSIZ
)
1251 return (1); /* sanity check */
1252 if (filter
[n
-1] >= '0' && filter
[n
-1] <= '9')
1253 return (1); /* only do exact match in that case */
1254 if (strncmp(p
->ifname
, filter
, n
))
1255 return (1); /* prefix doesn't match */
1256 return (p
->ifname
[n
] < '0' || p
->ifname
[n
] > '9');
1263 struct node_host
*h
= NULL
;
1264 int mask
, v4mask
, v6mask
, cont
= 1;
1267 if ((p
= strrchr(s
, '/')) != NULL
) {
1268 mask
= strtol(p
+1, &q
, 0);
1269 if (!q
|| *q
|| mask
> 128 || q
== (p
+1)) {
1270 fprintf(stderr
, "invalid netmask\n");
1273 if ((ps
= malloc(strlen(s
) - strlen(p
) + 1)) == NULL
)
1274 err(1, "host: malloc");
1275 strlcpy(ps
, s
, strlen(s
) - strlen(p
) + 1);
1276 v4mask
= v6mask
= mask
;
1278 if ((ps
= strdup(s
)) == NULL
)
1279 err(1, "host: strdup");
1285 /* interface with this name exists? */
1286 if (cont
&& (h
= host_if(ps
, mask
)) != NULL
)
1290 if (cont
&& (h
= host_v4(s
)) != NULL
)
1294 if (cont
&& (h
= host_v6(ps
, v6mask
)) != NULL
)
1298 if (cont
&& (h
= host_dns(ps
, v4mask
, v6mask
)) != NULL
)
1302 if (h
== NULL
|| cont
== 1) {
1303 fprintf(stderr
, "no IP address found for %s\n", s
);
1310 host_if(const char *s
, int mask
)
1312 struct node_host
*n
, *h
= NULL
;
1316 if ((ps
= strdup(s
)) == NULL
)
1317 err(1, "host_if: strdup");
1318 while ((p
= strrchr(ps
, ':')) != NULL
) {
1319 if (!strcmp(p
+1, "network"))
1320 flags
|= PFI_AFLAG_NETWORK
;
1321 else if (!strcmp(p
+1, "broadcast"))
1322 flags
|= PFI_AFLAG_BROADCAST
;
1323 else if (!strcmp(p
+1, "peer"))
1324 flags
|= PFI_AFLAG_PEER
;
1325 else if (!strcmp(p
+1, "0"))
1326 flags
|= PFI_AFLAG_NOALIAS
;
1333 if (flags
& (flags
- 1) & PFI_AFLAG_MODEMASK
) { /* Yep! */
1334 fprintf(stderr
, "illegal combination of interface modifiers\n");
1338 if ((flags
& (PFI_AFLAG_NETWORK
|PFI_AFLAG_BROADCAST
)) && mask
> -1) {
1339 fprintf(stderr
, "network or broadcast lookup, but "
1340 "extra netmask given\n");
1344 if (ifa_exists(ps
, 1) || !strncmp(ps
, "self", IFNAMSIZ
)) {
1345 /* interface with this name exists */
1346 h
= ifa_lookup(ps
, flags
);
1347 for (n
= h
; n
!= NULL
&& mask
> -1; n
= n
->next
)
1348 set_ipmask(n
, mask
);
1355 static struct node_host
*
1356 host_v4(const char *s
)
1358 struct node_host
*h
= NULL
;
1362 memset(&ina
, 0, sizeof(struct in_addr
));
1363 if (strrchr(s
, '/') != NULL
) {
1364 if ((bits
= inet_net_pton(AF_INET
, s
, &ina
, sizeof(ina
))) == -1)
1367 if (inet_pton(AF_INET
, s
, &ina
) != 1)
1371 h
= calloc(1, sizeof(struct node_host
));
1373 err(1, "address: calloc");
1376 h
->addr
.v
.a
.addr
.addr32
[0] = ina
.s_addr
;
1377 set_ipmask(h
, bits
);
1385 host_v6(const char *s
, int mask
)
1387 struct addrinfo hints
, *res
;
1388 struct node_host
*h
= NULL
;
1390 memset(&hints
, 0, sizeof(hints
));
1391 hints
.ai_family
= AF_INET6
;
1392 hints
.ai_socktype
= SOCK_DGRAM
; /*dummy*/
1393 hints
.ai_flags
= AI_NUMERICHOST
;
1394 if (getaddrinfo(s
, "0", &hints
, &res
) == 0) {
1395 h
= calloc(1, sizeof(struct node_host
));
1397 err(1, "address: calloc");
1400 memcpy(&h
->addr
.v
.a
.addr
,
1401 &((struct sockaddr_in6
*)res
->ai_addr
)->sin6_addr
,
1402 sizeof(h
->addr
.v
.a
.addr
));
1404 ((struct sockaddr_in6
*)res
->ai_addr
)->sin6_scope_id
;
1405 set_ipmask(h
, mask
);
1415 host_dns(const char *s
, int v4mask
, int v6mask
)
1417 struct addrinfo hints
, *res0
, *res
;
1418 struct node_host
*n
, *h
= NULL
;
1419 int error
, noalias
= 0;
1420 int got4
= 0, got6
= 0;
1423 if ((ps
= strdup(s
)) == NULL
)
1424 err(1, "host_if: strdup");
1425 if ((p
= strrchr(ps
, ':')) != NULL
&& !strcmp(p
, ":0")) {
1429 memset(&hints
, 0, sizeof(hints
));
1430 hints
.ai_family
= PF_UNSPEC
;
1431 hints
.ai_socktype
= SOCK_STREAM
; /* DUMMY */
1432 error
= getaddrinfo(ps
, NULL
, &hints
, &res0
);
1436 for (res
= res0
; res
; res
= res
->ai_next
) {
1437 if (res
->ai_family
!= AF_INET
&&
1438 res
->ai_family
!= AF_INET6
)
1441 if (res
->ai_family
== AF_INET
) {
1451 n
= calloc(1, sizeof(struct node_host
));
1453 err(1, "host_dns: calloc");
1455 n
->af
= res
->ai_family
;
1456 if (res
->ai_family
== AF_INET
) {
1457 memcpy(&n
->addr
.v
.a
.addr
,
1458 &((struct sockaddr_in
*)
1459 res
->ai_addr
)->sin_addr
.s_addr
,
1460 sizeof(struct in_addr
));
1461 set_ipmask(n
, v4mask
);
1463 memcpy(&n
->addr
.v
.a
.addr
,
1464 &((struct sockaddr_in6
*)
1465 res
->ai_addr
)->sin6_addr
.s6_addr
,
1466 sizeof(struct in6_addr
));
1468 ((struct sockaddr_in6
*)
1469 res
->ai_addr
)->sin6_scope_id
;
1470 set_ipmask(n
, v6mask
);
1488 * convert a hostname to a list of addresses and put them in the given buffer.
1490 * if set to 1, only simple addresses are accepted (no netblock, no "!").
1493 append_addr(struct pfr_buffer
*b
, char *s
, int test
)
1496 struct node_host
*h
, *n
;
1499 for (r
= s
; *r
== '!'; r
++)
1501 if ((n
= host(r
)) == NULL
) {
1505 rv
= append_addr_host(b
, n
, test
, not);
1510 } while (n
!= NULL
);
1515 * same as previous function, but with a pre-parsed input and the ability
1516 * to "negate" the result. Does not free the node_host list.
1518 * setting it to 1 is equivalent to adding "!" in front of parameter s.
1521 append_addr_host(struct pfr_buffer
*b
, struct node_host
*n
, int test
, int not)
1524 struct pfr_addr addr
;
1527 bzero(&addr
, sizeof(addr
));
1528 addr
.pfra_not
= n
->not ^ not;
1529 addr
.pfra_af
= n
->af
;
1530 addr
.pfra_net
= unmask(&n
->addr
.v
.a
.mask
, n
->af
);
1533 addr
.pfra_ip4addr
.s_addr
= n
->addr
.v
.a
.addr
.addr32
[0];
1537 memcpy(&addr
.pfra_ip6addr
, &n
->addr
.v
.a
.addr
.v6
,
1538 sizeof(struct in6_addr
));
1545 if ((test
&& (not || addr
.pfra_net
!= bits
)) ||
1546 addr
.pfra_net
> bits
) {
1550 if (pfr_buf_add(b
, &addr
))
1552 } while ((n
= n
->next
) != NULL
);
1558 pfctl_add_trans(struct pfr_buffer
*buf
, int rs_num
, const char *anchor
,
1559 const char *ruleset
)
1561 struct pfioc_trans_e trans
;
1563 bzero(&trans
, sizeof(trans
));
1564 trans
.rs_num
= rs_num
;
1565 if (strlcpy(trans
.anchor
, anchor
,
1566 sizeof(trans
.anchor
)) >= sizeof(trans
.anchor
) ||
1567 strlcpy(trans
.ruleset
, ruleset
,
1568 sizeof(trans
.ruleset
)) >= sizeof(trans
.ruleset
))
1569 errx(1, "pfctl_add_trans: strlcpy");
1571 return pfr_buf_add(buf
, &trans
);
1575 pfctl_get_ticket(struct pfr_buffer
*buf
, int rs_num
, const char *anchor
,
1576 const char *ruleset
)
1578 const struct pfioc_trans_e
*p
;
1580 PFRB_FOREACH(p
, buf
)
1581 if (rs_num
== p
->rs_num
&& !strcmp(anchor
, p
->anchor
) &&
1582 !strcmp(ruleset
, p
->ruleset
))
1584 errx(1, "pfr_get_ticket: assertion failed");
1588 pfctl_trans(int dev
, struct pfr_buffer
*buf
, u_long cmd
, int from
)
1590 struct pfioc_trans trans
;
1592 bzero(&trans
, sizeof(trans
));
1593 trans
.size
= buf
->pfrb_size
- from
;
1594 trans
.esize
= sizeof(struct pfioc_trans_e
);
1595 trans
.array
= ((struct pfioc_trans_e
*)buf
->pfrb_caddr
) + from
;
1596 return ioctl(dev
, cmd
, &trans
);