2 /* $OpenBSD: pfctl_parser.c,v 1.234 2006/10/31 23:46:24 mcbride 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/types.h>
36 #include <sys/ioctl.h>
37 #include <sys/socket.h>
38 #include <sys/param.h>
40 #include <netinet/in.h>
41 #include <netinet/in_systm.h>
42 #include <netinet/ip.h>
43 #include <netinet/ip_icmp.h>
44 #include <netinet/icmp6.h>
45 #include <net/pfvar.h>
46 #include <arpa/inet.h>
59 #include "pfctl_parser.h"
63 #include <net/if_compat.h>
64 #endif /* __NetBSD__ */
66 void print_op (u_int8_t
, const char *, const char *);
67 void print_port (u_int8_t
, u_int16_t
, u_int16_t
, const char *);
68 void print_ugid (u_int8_t
, unsigned, unsigned, const char *, unsigned);
69 void print_flags (u_int8_t
);
70 void print_fromto(struct pf_rule_addr
*, pf_osfp_t
,
71 struct pf_rule_addr
*, u_int8_t
, u_int8_t
, int);
72 int ifa_skip_if(const char *filter
, struct node_host
*p
);
74 struct node_host
*ifa_grouplookup(const char *, int);
75 struct node_host
*host_if(const char *, int);
76 struct node_host
*host_v4(const char *, int);
77 struct node_host
*host_v6(const char *, int);
78 struct node_host
*host_dns(const char *, int, int);
80 const char *tcpflags
= "FSRPAUEW";
82 static const struct icmptypeent icmp_type
[] = {
83 { "echoreq", ICMP_ECHO
},
84 { "echorep", ICMP_ECHOREPLY
},
85 { "unreach", ICMP_UNREACH
},
86 { "squench", ICMP_SOURCEQUENCH
},
87 { "redir", ICMP_REDIRECT
},
88 #ifdef ICMP_ALTHOSTADDR
89 { "althost", ICMP_ALTHOSTADDR
},
91 { "routeradv", ICMP_ROUTERADVERT
},
92 { "routersol", ICMP_ROUTERSOLICIT
},
93 { "timex", ICMP_TIMXCEED
},
94 { "paramprob", ICMP_PARAMPROB
},
95 { "timereq", ICMP_TSTAMP
},
96 { "timerep", ICMP_TSTAMPREPLY
},
97 { "inforeq", ICMP_IREQ
},
98 { "inforep", ICMP_IREQREPLY
},
99 { "maskreq", ICMP_MASKREQ
},
100 { "maskrep", ICMP_MASKREPLY
},
101 #ifdef ICMP_TRACEROUTE
102 { "trace", ICMP_TRACEROUTE
},
104 #ifdef ICMP_DATACONVERR
105 { "dataconv", ICMP_DATACONVERR
},
107 #ifdef ICMP_MOBILE_REDIRECT
108 { "mobredir", ICMP_MOBILE_REDIRECT
},
110 #ifdef ICMP_IPV6_WHEREAREYOU
111 { "ipv6-where", ICMP_IPV6_WHEREAREYOU
},
113 #ifdef ICMP_IPV6_IAMHERE
114 { "ipv6-here", ICMP_IPV6_IAMHERE
},
116 #ifdef ICMP_MOBILE_REGREQUEST
117 { "mobregreq", ICMP_MOBILE_REGREQUEST
},
119 #ifdef ICMP_MOBILE_REGREPLY
120 { "mobregrep", ICMP_MOBILE_REGREPLY
},
123 { "skip", ICMP_SKIP
},
126 { "photuris", ICMP_PHOTURIS
}
130 static const struct icmptypeent icmp6_type
[] = {
131 { "unreach", ICMP6_DST_UNREACH
},
132 { "toobig", ICMP6_PACKET_TOO_BIG
},
133 { "timex", ICMP6_TIME_EXCEEDED
},
134 { "paramprob", ICMP6_PARAM_PROB
},
135 { "echoreq", ICMP6_ECHO_REQUEST
},
136 { "echorep", ICMP6_ECHO_REPLY
},
137 { "groupqry", ICMP6_MEMBERSHIP_QUERY
},
138 { "listqry", MLD_LISTENER_QUERY
},
139 { "grouprep", ICMP6_MEMBERSHIP_REPORT
},
140 { "listenrep", MLD_LISTENER_REPORT
},
141 { "groupterm", ICMP6_MEMBERSHIP_REDUCTION
},
142 { "listendone", MLD_LISTENER_DONE
},
143 { "routersol", ND_ROUTER_SOLICIT
},
144 { "routeradv", ND_ROUTER_ADVERT
},
145 { "neighbrsol", ND_NEIGHBOR_SOLICIT
},
146 { "neighbradv", ND_NEIGHBOR_ADVERT
},
147 { "redir", ND_REDIRECT
},
148 { "routrrenum", ICMP6_ROUTER_RENUMBERING
},
149 { "wrureq", ICMP6_WRUREQUEST
},
150 { "wrurep", ICMP6_WRUREPLY
},
151 { "fqdnreq", ICMP6_FQDN_QUERY
},
152 { "fqdnrep", ICMP6_FQDN_REPLY
},
153 { "niqry", ICMP6_NI_QUERY
},
154 { "nirep", ICMP6_NI_REPLY
},
155 { "mtraceresp", MLD_MTRACE_RESP
},
156 { "mtrace", MLD_MTRACE
}
159 static const struct icmpcodeent icmp_code
[] = {
160 { "net-unr", ICMP_UNREACH
, ICMP_UNREACH_NET
},
161 { "host-unr", ICMP_UNREACH
, ICMP_UNREACH_HOST
},
162 { "proto-unr", ICMP_UNREACH
, ICMP_UNREACH_PROTOCOL
},
163 { "port-unr", ICMP_UNREACH
, ICMP_UNREACH_PORT
},
164 { "needfrag", ICMP_UNREACH
, ICMP_UNREACH_NEEDFRAG
},
165 { "srcfail", ICMP_UNREACH
, ICMP_UNREACH_SRCFAIL
},
166 { "net-unk", ICMP_UNREACH
, ICMP_UNREACH_NET_UNKNOWN
},
167 { "host-unk", ICMP_UNREACH
, ICMP_UNREACH_HOST_UNKNOWN
},
168 { "isolate", ICMP_UNREACH
, ICMP_UNREACH_ISOLATED
},
169 { "net-prohib", ICMP_UNREACH
, ICMP_UNREACH_NET_PROHIB
},
170 { "host-prohib", ICMP_UNREACH
, ICMP_UNREACH_HOST_PROHIB
},
171 { "net-tos", ICMP_UNREACH
, ICMP_UNREACH_TOSNET
},
172 { "host-tos", ICMP_UNREACH
, ICMP_UNREACH_TOSHOST
},
173 #ifdef ICMP_UNREACH_FILTER_PROHIB
174 { "filter-prohib", ICMP_UNREACH
, ICMP_UNREACH_FILTER_PROHIB
},
176 #ifdef ICMP_UNREACH_HOST_PRECEDENCE
177 { "host-preced", ICMP_UNREACH
, ICMP_UNREACH_HOST_PRECEDENCE
},
179 #ifdef ICMP_UNREACH_PRECEDENCE_CUTOFF
180 { "cutoff-preced", ICMP_UNREACH
, ICMP_UNREACH_PRECEDENCE_CUTOFF
},
182 { "redir-net", ICMP_REDIRECT
, ICMP_REDIRECT_NET
},
183 { "redir-host", ICMP_REDIRECT
, ICMP_REDIRECT_HOST
},
184 { "redir-tos-net", ICMP_REDIRECT
, ICMP_REDIRECT_TOSNET
},
185 { "redir-tos-host", ICMP_REDIRECT
, ICMP_REDIRECT_TOSHOST
},
186 #ifdef ICMP_ROUTERADVERT_NORMAL
187 { "normal-adv", ICMP_ROUTERADVERT
, ICMP_ROUTERADVERT_NORMAL
},
189 #ifdef ICMP_ROUTERADVERT_NOROUTE_COMMON
190 { "common-adv", ICMP_ROUTERADVERT
, ICMP_ROUTERADVERT_NOROUTE_COMMON
},
192 { "transit", ICMP_TIMXCEED
, ICMP_TIMXCEED_INTRANS
},
193 { "reassemb", ICMP_TIMXCEED
, ICMP_TIMXCEED_REASS
},
194 #ifdef ICMP_PARAMPROB_ERRATPTR
195 { "badhead", ICMP_PARAMPROB
, ICMP_PARAMPROB_ERRATPTR
},
197 { "optmiss", ICMP_PARAMPROB
, ICMP_PARAMPROB_OPTABSENT
},
198 #ifdef ICMP_PARAMPROB_LENGTH
199 { "badlen", ICMP_PARAMPROB
, ICMP_PARAMPROB_LENGTH
},
202 { "unknown-ind", ICMP_PHOTURIS
, ICMP_PHOTURIS_UNKNOWN_INDEX
},
203 { "auth-fail", ICMP_PHOTURIS
, ICMP_PHOTURIS_AUTH_FAILED
},
204 { "decrypt-fail", ICMP_PHOTURIS
, ICMP_PHOTURIS_DECRYPT_FAILED
}
208 static const struct icmpcodeent icmp6_code
[] = {
209 { "admin-unr", ICMP6_DST_UNREACH
, ICMP6_DST_UNREACH_ADMIN
},
210 { "noroute-unr", ICMP6_DST_UNREACH
, ICMP6_DST_UNREACH_NOROUTE
},
211 { "notnbr-unr", ICMP6_DST_UNREACH
, ICMP6_DST_UNREACH_NOTNEIGHBOR
},
212 { "beyond-unr", ICMP6_DST_UNREACH
, ICMP6_DST_UNREACH_BEYONDSCOPE
},
213 { "addr-unr", ICMP6_DST_UNREACH
, ICMP6_DST_UNREACH_ADDR
},
214 { "port-unr", ICMP6_DST_UNREACH
, ICMP6_DST_UNREACH_NOPORT
},
215 { "transit", ICMP6_TIME_EXCEEDED
, ICMP6_TIME_EXCEED_TRANSIT
},
216 { "reassemb", ICMP6_TIME_EXCEEDED
, ICMP6_TIME_EXCEED_REASSEMBLY
},
217 { "badhead", ICMP6_PARAM_PROB
, ICMP6_PARAMPROB_HEADER
},
218 { "nxthdr", ICMP6_PARAM_PROB
, ICMP6_PARAMPROB_NEXTHEADER
},
219 { "redironlink", ND_REDIRECT
, ND_REDIRECT_ONLINK
},
220 { "redirrouter", ND_REDIRECT
, ND_REDIRECT_ROUTER
}
223 const struct pf_timeout pf_timeouts
[] = {
224 { "tcp.first", PFTM_TCP_FIRST_PACKET
},
225 { "tcp.opening", PFTM_TCP_OPENING
},
226 { "tcp.established", PFTM_TCP_ESTABLISHED
},
227 { "tcp.closing", PFTM_TCP_CLOSING
},
228 { "tcp.finwait", PFTM_TCP_FIN_WAIT
},
229 { "tcp.closed", PFTM_TCP_CLOSED
},
230 { "tcp.tsdiff", PFTM_TS_DIFF
},
231 { "udp.first", PFTM_UDP_FIRST_PACKET
},
232 { "udp.single", PFTM_UDP_SINGLE
},
233 { "udp.multiple", PFTM_UDP_MULTIPLE
},
234 { "icmp.first", PFTM_ICMP_FIRST_PACKET
},
235 { "icmp.error", PFTM_ICMP_ERROR_REPLY
},
236 { "other.first", PFTM_OTHER_FIRST_PACKET
},
237 { "other.single", PFTM_OTHER_SINGLE
},
238 { "other.multiple", PFTM_OTHER_MULTIPLE
},
239 { "frag", PFTM_FRAG
},
240 { "interval", PFTM_INTERVAL
},
241 { "adaptive.start", PFTM_ADAPTIVE_START
},
242 { "adaptive.end", PFTM_ADAPTIVE_END
},
243 { "src.track", PFTM_SRC_NODE
},
247 const struct icmptypeent
*
248 geticmptypebynumber(u_int8_t type
, sa_family_t af
)
252 if (af
!= AF_INET6
) {
253 for (i
=0; i
< (sizeof (icmp_type
) / sizeof(icmp_type
[0]));
255 if (type
== icmp_type
[i
].type
)
256 return (&icmp_type
[i
]);
259 for (i
=0; i
< (sizeof (icmp6_type
) /
260 sizeof(icmp6_type
[0])); i
++) {
261 if (type
== icmp6_type
[i
].type
)
262 return (&icmp6_type
[i
]);
268 const struct icmptypeent
*
269 geticmptypebyname(char *w
, sa_family_t af
)
273 if (af
!= AF_INET6
) {
274 for (i
=0; i
< (sizeof (icmp_type
) / sizeof(icmp_type
[0]));
276 if (!strcmp(w
, icmp_type
[i
].name
))
277 return (&icmp_type
[i
]);
280 for (i
=0; i
< (sizeof (icmp6_type
) /
281 sizeof(icmp6_type
[0])); i
++) {
282 if (!strcmp(w
, icmp6_type
[i
].name
))
283 return (&icmp6_type
[i
]);
289 const struct icmpcodeent
*
290 geticmpcodebynumber(u_int8_t type
, u_int8_t code
, sa_family_t af
)
294 if (af
!= AF_INET6
) {
295 for (i
=0; i
< (sizeof (icmp_code
) / sizeof(icmp_code
[0]));
297 if (type
== icmp_code
[i
].type
&&
298 code
== icmp_code
[i
].code
)
299 return (&icmp_code
[i
]);
302 for (i
=0; i
< (sizeof (icmp6_code
) /
303 sizeof(icmp6_code
[0])); i
++) {
304 if (type
== icmp6_code
[i
].type
&&
305 code
== icmp6_code
[i
].code
)
306 return (&icmp6_code
[i
]);
312 const struct icmpcodeent
*
313 geticmpcodebyname(u_long type
, char *w
, sa_family_t af
)
317 if (af
!= AF_INET6
) {
318 for (i
=0; i
< (sizeof (icmp_code
) / sizeof(icmp_code
[0]));
320 if (type
== icmp_code
[i
].type
&&
321 !strcmp(w
, icmp_code
[i
].name
))
322 return (&icmp_code
[i
]);
325 for (i
=0; i
< (sizeof (icmp6_code
) /
326 sizeof(icmp6_code
[0])); i
++) {
327 if (type
== icmp6_code
[i
].type
&&
328 !strcmp(w
, icmp6_code
[i
].name
))
329 return (&icmp6_code
[i
]);
336 print_op(u_int8_t op
, const char *a1
, const char *a2
)
339 printf(" %s >< %s", a1
, a2
);
340 else if (op
== PF_OP_XRG
)
341 printf(" %s <> %s", a1
, a2
);
342 else if (op
== PF_OP_EQ
)
344 else if (op
== PF_OP_NE
)
345 printf(" != %s", a1
);
346 else if (op
== PF_OP_LT
)
348 else if (op
== PF_OP_LE
)
349 printf(" <= %s", a1
);
350 else if (op
== PF_OP_GT
)
352 else if (op
== PF_OP_GE
)
353 printf(" >= %s", a1
);
354 else if (op
== PF_OP_RRG
)
355 printf(" %s:%s", a1
, a2
);
359 print_port(u_int8_t op
, u_int16_t p1
, u_int16_t p2
, const char *proto
)
364 s
= getservbyport(p1
, proto
);
367 snprintf(a1
, sizeof(a1
), "%u", p1
);
368 snprintf(a2
, sizeof(a2
), "%u", p2
);
370 if (s
!= NULL
&& (op
== PF_OP_EQ
|| op
== PF_OP_NE
))
371 print_op(op
, s
->s_name
, a2
);
373 print_op(op
, a1
, a2
);
377 print_ugid(u_int8_t op
, unsigned u1
, unsigned u2
, const char *t
, unsigned umax
)
381 snprintf(a1
, sizeof(a1
), "%u", u1
);
382 snprintf(a2
, sizeof(a2
), "%u", u2
);
384 if (u1
== umax
&& (op
== PF_OP_EQ
|| op
== PF_OP_NE
))
385 print_op(op
, "unknown", a2
);
387 print_op(op
, a1
, a2
);
391 print_flags(u_int8_t f
)
395 for (i
= 0; tcpflags
[i
]; ++i
)
397 printf("%c", tcpflags
[i
]);
401 print_fromto(struct pf_rule_addr
*src
, pf_osfp_t osfp
, struct pf_rule_addr
*dst
,
402 sa_family_t af
, u_int8_t proto
, int verbose
)
404 char buf
[PF_OSFP_LEN
*3];
405 if (src
->addr
.type
== PF_ADDR_ADDRMASK
&&
406 dst
->addr
.type
== PF_ADDR_ADDRMASK
&&
407 PF_AZERO(&src
->addr
.v
.a
.addr
, AF_INET6
) &&
408 PF_AZERO(&src
->addr
.v
.a
.mask
, AF_INET6
) &&
409 PF_AZERO(&dst
->addr
.v
.a
.addr
, AF_INET6
) &&
410 PF_AZERO(&dst
->addr
.v
.a
.mask
, AF_INET6
) &&
411 !src
->neg
&& !dst
->neg
&&
412 !src
->port_op
&& !dst
->port_op
&&
419 print_addr(&src
->addr
, af
, verbose
);
421 print_port(src
->port_op
, src
->port
[0],
423 proto
== IPPROTO_TCP
? "tcp" : "udp");
424 if (osfp
!= PF_OSFP_ANY
)
425 printf(" os \"%s\"", pfctl_lookup_fingerprint(osfp
, buf
,
431 print_addr(&dst
->addr
, af
, verbose
);
433 print_port(dst
->port_op
, dst
->port
[0],
435 proto
== IPPROTO_TCP
? "tcp" : "udp");
440 print_pool(struct pf_pool
*pool
, u_int16_t p1
, u_int16_t p2
,
441 sa_family_t af
, int id
)
443 struct pf_pooladdr
*pooladdr
;
445 if ((TAILQ_FIRST(&pool
->list
) != NULL
) &&
446 TAILQ_NEXT(TAILQ_FIRST(&pool
->list
), entries
) != NULL
)
448 TAILQ_FOREACH(pooladdr
, &pool
->list
, entries
){
453 print_addr(&pooladdr
->addr
, af
, 0);
456 if (PF_AZERO(&pooladdr
->addr
.v
.a
.addr
, af
))
457 printf("%s", pooladdr
->ifname
);
459 printf("(%s ", pooladdr
->ifname
);
460 print_addr(&pooladdr
->addr
, af
, 0);
467 if (TAILQ_NEXT(pooladdr
, entries
) != NULL
)
469 else if (TAILQ_NEXT(TAILQ_FIRST(&pool
->list
), entries
) != NULL
)
474 if ((p1
!= PF_NAT_PROXY_PORT_LOW
||
475 p2
!= PF_NAT_PROXY_PORT_HIGH
) && (p1
!= 0 || p2
!= 0)) {
477 printf(" port %u", p1
);
479 printf(" port %u:%u", p1
, p2
);
484 printf(" port %u", p1
);
485 if (p2
&& (p2
!= p1
))
492 switch (pool
->opts
& PF_POOL_TYPEMASK
) {
495 case PF_POOL_BITMASK
:
501 case PF_POOL_SRCHASH
:
502 printf(" source-hash 0x%08x%08x%08x%08x",
503 pool
->key
.key32
[0], pool
->key
.key32
[1],
504 pool
->key
.key32
[2], pool
->key
.key32
[3]);
506 case PF_POOL_ROUNDROBIN
:
507 printf(" round-robin");
510 if (pool
->opts
& PF_POOL_STICKYADDR
)
511 printf(" sticky-address");
512 if (id
== PF_NAT
&& p1
== 0 && p2
== 0)
513 printf(" static-port");
516 const char *pf_reasons
[PFRES_MAX
+1] = PFRES_NAMES
;
517 const char *pf_lcounters
[LCNT_MAX
+1] = LCNT_NAMES
;
518 const char *pf_fcounters
[FCNT_MAX
+1] = FCNT_NAMES
;
519 const char *pf_scounters
[FCNT_MAX
+1] = FCNT_NAMES
;
522 print_status(struct pf_status
*s
, int opts
)
524 char statline
[80], *running
;
527 char buf
[PF_MD5_DIGEST_LENGTH
* 2 + 1];
528 static const char hex
[] = "0123456789abcdef";
530 runtime
= time(NULL
) - s
->since
;
531 running
= s
->running
? "Enabled" : "Disabled";
534 unsigned sec
, min
, hrs
, day
= runtime
;
542 snprintf(statline
, sizeof(statline
),
543 "Status: %s for %u days %.2u:%.2u:%.2u",
544 running
, day
, hrs
, min
, sec
);
546 snprintf(statline
, sizeof(statline
), "Status: %s", running
);
547 printf("%-44s", statline
);
550 printf("%15s\n\n", "Debug: None");
552 case PF_DEBUG_URGENT
:
553 printf("%15s\n\n", "Debug: Urgent");
556 printf("%15s\n\n", "Debug: Misc");
559 printf("%15s\n\n", "Debug: Loud");
563 if (opts
& PF_OPT_VERBOSE
) {
564 printf("Hostid: 0x%08x\n", ntohl(s
->hostid
));
566 for (i
= 0; i
< PF_MD5_DIGEST_LENGTH
; i
++) {
567 buf
[i
+ i
] = hex
[s
->pf_chksum
[i
] >> 4];
568 buf
[i
+ i
+ 1] = hex
[s
->pf_chksum
[i
] & 0x0f];
571 printf("Checksum: 0x%s\n\n", buf
);
574 if (s
->ifname
[0] != 0) {
575 printf("Interface Stats for %-16s %5s %16s\n",
576 s
->ifname
, "IPv4", "IPv6");
577 printf(" %-25s %14llu %16llu\n", "Bytes In",
578 (unsigned long long)s
->bcounters
[0][0],
579 (unsigned long long)s
->bcounters
[1][0]);
580 printf(" %-25s %14llu %16llu\n", "Bytes Out",
581 (unsigned long long)s
->bcounters
[0][1],
582 (unsigned long long)s
->bcounters
[1][1]);
583 printf(" Packets In\n");
584 printf(" %-23s %14llu %16llu\n", "Passed",
585 (unsigned long long)s
->pcounters
[0][0][PF_PASS
],
586 (unsigned long long)s
->pcounters
[1][0][PF_PASS
]);
587 printf(" %-23s %14llu %16llu\n", "Blocked",
588 (unsigned long long)s
->pcounters
[0][0][PF_DROP
],
589 (unsigned long long)s
->pcounters
[1][0][PF_DROP
]);
590 printf(" Packets Out\n");
591 printf(" %-23s %14llu %16llu\n", "Passed",
592 (unsigned long long)s
->pcounters
[0][1][PF_PASS
],
593 (unsigned long long)s
->pcounters
[1][1][PF_PASS
]);
594 printf(" %-23s %14llu %16llu\n\n", "Blocked",
595 (unsigned long long)s
->pcounters
[0][1][PF_DROP
],
596 (unsigned long long)s
->pcounters
[1][1][PF_DROP
]);
598 printf("%-27s %14s %16s\n", "State Table", "Total", "Rate");
599 printf(" %-25s %14u %14s\n", "current entries", s
->states
, "");
600 for (i
= 0; i
< FCNT_MAX
; i
++) {
601 printf(" %-25s %14llu ", pf_fcounters
[i
],
602 (unsigned long long)s
->fcounters
[i
]);
605 (double)s
->fcounters
[i
] / (double)runtime
);
607 printf("%14s\n", "");
609 if (opts
& PF_OPT_VERBOSE
) {
610 printf("Source Tracking Table\n");
611 printf(" %-25s %14u %14s\n", "current entries",
613 for (i
= 0; i
< SCNT_MAX
; i
++) {
614 printf(" %-25s %14lld ", pf_scounters
[i
],
615 (unsigned long long)s
->scounters
[i
]);
618 (double)s
->scounters
[i
] / (double)runtime
);
620 printf("%14s\n", "");
623 printf("Counters\n");
624 for (i
= 0; i
< PFRES_MAX
; i
++) {
625 printf(" %-25s %14llu ", pf_reasons
[i
],
626 (unsigned long long)s
->counters
[i
]);
629 (double)s
->counters
[i
] / (double)runtime
);
631 printf("%14s\n", "");
633 if (opts
& PF_OPT_VERBOSE
) {
634 printf("Limit Counters\n");
635 for (i
= 0; i
< LCNT_MAX
; i
++) {
636 printf(" %-25s %14lld ", pf_lcounters
[i
],
637 (unsigned long long)s
->lcounters
[i
]);
640 (double)s
->lcounters
[i
] / (double)runtime
);
642 printf("%14s\n", "");
648 print_src_node(struct pf_src_node
*sn
, int opts
)
650 struct pf_addr_wrap aw
;
653 memset(&aw
, 0, sizeof(aw
));
654 if (sn
->af
== AF_INET
)
655 aw
.v
.a
.mask
.addr32
[0] = 0xffffffff;
657 memset(&aw
.v
.a
.mask
, 0xff, sizeof(aw
.v
.a
.mask
));
659 aw
.v
.a
.addr
= sn
->addr
;
660 print_addr(&aw
, sn
->af
, opts
& PF_OPT_VERBOSE2
);
662 aw
.v
.a
.addr
= sn
->raddr
;
663 print_addr(&aw
, sn
->af
, opts
& PF_OPT_VERBOSE2
);
664 printf(" ( states %u, connections %u, rate %u.%u/%us )\n", sn
->states
,
665 sn
->conn
, sn
->conn_rate
.count
/ 1000,
666 (sn
->conn_rate
.count
% 1000) / 100, sn
->conn_rate
.seconds
);
667 if (opts
& PF_OPT_VERBOSE
) {
668 sec
= sn
->creation
% 60;
670 min
= sn
->creation
% 60;
672 printf(" age %.2u:%.2u:%.2u", sn
->creation
, min
, sec
);
673 if (sn
->states
== 0) {
674 sec
= sn
->expire
% 60;
676 min
= sn
->expire
% 60;
678 printf(", expires in %.2u:%.2u:%.2u",
679 sn
->expire
, min
, sec
);
681 printf(", %llu pkts, %llu bytes",
682 (unsigned long long)sn
->packets
[0] + sn
->packets
[1],
683 (unsigned long long)sn
->bytes
[0] + sn
->bytes
[1]);
684 switch (sn
->ruletype
) {
686 if (sn
->rule
.nr
!= -1)
687 printf(", nat rule %u", sn
->rule
.nr
);
690 if (sn
->rule
.nr
!= -1)
691 printf(", rdr rule %u", sn
->rule
.nr
);
694 if (sn
->rule
.nr
!= -1)
695 printf(", filter rule %u", sn
->rule
.nr
);
703 print_rule(struct pf_rule
*r
, const char *anchor_call
, int verbose
)
705 static const char *actiontypes
[] = { "pass", "block", "scrub",
706 "no scrub", "nat", "no nat", "binat", "no binat", "rdr", "no rdr" };
707 static const char *anchortypes
[] = { "anchor", "anchor", "anchor",
708 "anchor", "nat-anchor", "nat-anchor", "binat-anchor",
709 "binat-anchor", "rdr-anchor", "rdr-anchor" };
713 printf("@%d ", r
->nr
);
714 if (r
->action
> PF_NORDR
)
715 printf("action(%d)", r
->action
);
716 else if (anchor_call
[0]) {
717 if (anchor_call
[0] == '_') {
718 printf("%s", anchortypes
[r
->action
]);
720 printf("%s \"%s\"", anchortypes
[r
->action
],
723 printf("%s", actiontypes
[r
->action
]);
727 if (r
->action
== PF_DROP
) {
728 if (r
->rule_flag
& PFRULE_RETURN
)
730 else if (r
->rule_flag
& PFRULE_RETURNRST
) {
732 printf(" return-rst");
734 printf(" return-rst(ttl %d)", r
->return_ttl
);
735 } else if (r
->rule_flag
& PFRULE_RETURNICMP
) {
736 const struct icmpcodeent
*ic
, *ic6
;
738 ic
= geticmpcodebynumber(r
->return_icmp
>> 8,
739 r
->return_icmp
& 255, AF_INET
);
740 ic6
= geticmpcodebynumber(r
->return_icmp6
>> 8,
741 r
->return_icmp6
& 255, AF_INET6
);
745 printf(" return-icmp");
747 printf("(%u)", r
->return_icmp
& 255);
749 printf("(%s)", ic
->name
);
752 printf(" return-icmp6");
754 printf("(%u)", r
->return_icmp6
& 255);
756 printf("(%s)", ic6
->name
);
759 printf(" return-icmp");
761 printf("(%u, ", r
->return_icmp
& 255);
763 printf("(%s, ", ic
->name
);
765 printf("%u)", r
->return_icmp6
& 255);
767 printf("%s)", ic6
->name
);
773 if (r
->direction
== PF_IN
)
775 else if (r
->direction
== PF_OUT
)
779 if (r
->log
& ~PF_LOG
|| r
->logif
) {
783 if (r
->log
& PF_LOG_ALL
)
784 printf("%sall", count
++ ? ", " : "");
785 if (r
->log
& PF_LOG_SOCKET_LOOKUP
)
786 printf("%suser", count
++ ? ", " : "");
788 printf("%sto pflog%u", count
++ ? ", " : "",
797 printf(" on ! %s", r
->ifname
);
799 printf(" on %s", r
->ifname
);
802 if (r
->rt
== PF_ROUTETO
)
804 else if (r
->rt
== PF_REPLYTO
)
806 else if (r
->rt
== PF_DUPTO
)
808 else if (r
->rt
== PF_FASTROUTE
)
809 printf(" fastroute");
810 if (r
->rt
!= PF_FASTROUTE
) {
812 print_pool(&r
->rpool
, 0, 0, r
->af
, PF_PASS
);
816 if (r
->af
== AF_INET
)
824 if ((p
= getprotobynumber(r
->proto
)) != NULL
)
825 printf(" proto %s", p
->p_name
);
827 printf(" proto %u", r
->proto
);
829 print_fromto(&r
->src
, r
->os_fingerprint
, &r
->dst
, r
->af
, r
->proto
,
832 print_ugid(r
->uid
.op
, r
->uid
.uid
[0], r
->uid
.uid
[1], "user",
835 print_ugid(r
->gid
.op
, r
->gid
.gid
[0], r
->gid
.gid
[1], "group",
837 if (r
->flags
|| r
->flagset
) {
839 print_flags(r
->flags
);
841 print_flags(r
->flagset
);
842 } else if (r
->action
== PF_PASS
&&
843 (!r
->proto
|| r
->proto
== IPPROTO_TCP
) &&
844 !(r
->rule_flag
& PFRULE_FRAGMENT
) &&
845 !anchor_call
[0] && r
->keep_state
)
846 printf(" flags any");
848 const struct icmptypeent
*it
;
850 it
= geticmptypebynumber(r
->type
-1, r
->af
);
851 if (r
->af
!= AF_INET6
)
852 printf(" icmp-type");
854 printf(" icmp6-type");
856 printf(" %s", it
->name
);
858 printf(" %u", r
->type
-1);
860 const struct icmpcodeent
*ic
;
862 ic
= geticmpcodebynumber(r
->type
-1, r
->code
-1, r
->af
);
864 printf(" code %s", ic
->name
);
866 printf(" code %u", r
->code
-1);
870 printf(" tos 0x%2.2x", r
->tos
);
871 if (!r
->keep_state
&& r
->action
== PF_PASS
&& !anchor_call
[0])
873 else if (r
->keep_state
== PF_STATE_NORMAL
)
874 printf(" keep state");
875 else if (r
->keep_state
== PF_STATE_MODULATE
)
876 printf(" modulate state");
877 else if (r
->keep_state
== PF_STATE_SYNPROXY
)
878 printf(" synproxy state");
882 snprintf(buf
, sizeof(buf
), "%f", r
->prob
*100.0/(UINT_MAX
+1.0));
883 for (i
= strlen(buf
)-1; i
> 0; i
--) {
892 printf(" probability %s%%", buf
);
895 if (r
->max_states
|| r
->max_src_nodes
|| r
->max_src_states
)
897 if (r
->rule_flag
& PFRULE_NOSYNC
)
899 if (r
->rule_flag
& PFRULE_SRCTRACK
)
901 if (r
->rule_flag
& PFRULE_IFBOUND
)
903 for (i
= 0; !opts
&& i
< PFTM_MAX
; ++i
)
909 printf("max %u", r
->max_states
);
912 if (r
->rule_flag
& PFRULE_NOSYNC
) {
918 if (r
->rule_flag
& PFRULE_SRCTRACK
) {
921 printf("source-track");
922 if (r
->rule_flag
& PFRULE_RULESRCTRACK
)
928 if (r
->max_src_states
) {
931 printf("max-src-states %u", r
->max_src_states
);
934 if (r
->max_src_conn
) {
937 printf("max-src-conn %u", r
->max_src_conn
);
940 if (r
->max_src_conn_rate
.limit
) {
943 printf("max-src-conn-rate %u/%u",
944 r
->max_src_conn_rate
.limit
,
945 r
->max_src_conn_rate
.seconds
);
948 if (r
->max_src_nodes
) {
951 printf("max-src-nodes %u", r
->max_src_nodes
);
954 if (r
->overload_tblname
[0]) {
957 printf("overload <%s>", r
->overload_tblname
);
960 if (r
->flush
& PF_FLUSH_GLOBAL
)
963 if (r
->rule_flag
& PFRULE_IFBOUND
) {
969 for (i
= 0; i
< PFTM_MAX
; ++i
)
976 for (j
= 0; pf_timeouts
[j
].name
!= NULL
;
978 if (pf_timeouts
[j
].timeout
== i
)
980 printf("%s %u", pf_timeouts
[j
].name
== NULL
?
981 "inv.timeout" : pf_timeouts
[j
].name
,
986 if (r
->rule_flag
& PFRULE_FRAGMENT
)
988 if (r
->rule_flag
& PFRULE_NODF
)
990 if (r
->rule_flag
& PFRULE_RANDOMID
)
991 printf(" random-id");
993 printf(" min-ttl %d", r
->min_ttl
);
995 printf(" max-mss %d", r
->max_mss
);
997 printf(" allow-opts");
998 if (r
->action
== PF_SCRUB
) {
999 if (r
->rule_flag
& PFRULE_REASSEMBLE_TCP
)
1000 printf(" reassemble tcp");
1002 if (r
->rule_flag
& PFRULE_FRAGDROP
)
1003 printf(" fragment drop-ovl");
1004 else if (r
->rule_flag
& PFRULE_FRAGCROP
)
1005 printf(" fragment crop");
1007 printf(" fragment reassemble");
1010 printf(" label \"%s\"", r
->label
);
1011 if (r
->qname
[0] && r
->pqname
[0])
1012 printf(" queue(%s, %s)", r
->qname
, r
->pqname
);
1013 else if (r
->qname
[0])
1014 printf(" queue %s", r
->qname
);
1016 printf(" tag %s", r
->tagname
);
1017 if (r
->match_tagname
[0]) {
1018 if (r
->match_tag_not
)
1020 printf(" tagged %s", r
->match_tagname
);
1022 if (r
->rtableid
!= -1)
1023 printf(" rtable %u", r
->rtableid
);
1024 if (!anchor_call
[0] && (r
->action
== PF_NAT
||
1025 r
->action
== PF_BINAT
|| r
->action
== PF_RDR
)) {
1027 print_pool(&r
->rpool
, r
->rpool
.proxy_port
[0],
1028 r
->rpool
.proxy_port
[1], r
->af
, r
->action
);
1033 print_tabledef(const char *name
, int flags
, int addrs
,
1034 struct node_tinithead
*nodes
)
1036 struct node_tinit
*ti
, *nti
;
1037 struct node_host
*h
;
1039 printf("table <%s>", name
);
1040 if (flags
& PFR_TFLAG_CONST
)
1042 if (flags
& PFR_TFLAG_PERSIST
)
1044 SIMPLEQ_FOREACH(ti
, nodes
, entries
) {
1046 printf(" file \"%s\"", ti
->file
);
1051 for (h
= ti
->host
; h
!= NULL
; h
= h
->next
) {
1052 printf(h
->not ? " !" : " ");
1053 print_addr(&h
->addr
, h
->af
, 0);
1055 nti
= SIMPLEQ_NEXT(ti
, entries
);
1056 if (nti
!= NULL
&& nti
->file
== NULL
)
1057 ti
= nti
; /* merge lists */
1063 if (addrs
&& SIMPLEQ_EMPTY(nodes
))
1069 parse_flags(char *s
)
1074 for (p
= s
; *p
; p
++) {
1075 if ((q
= strchr(tcpflags
, *p
)) == NULL
)
1078 f
|= 1 << (q
- tcpflags
);
1080 return (f
? f
: PF_TH_ALL
);
1084 set_ipmask(struct node_host
*h
, u_int8_t b
)
1086 struct pf_addr
*m
, *n
;
1089 m
= &h
->addr
.v
.a
.mask
;
1090 memset(m
, 0, sizeof(*m
));
1093 m
->addr32
[j
++] = 0xffffffff;
1096 for (i
= 31; i
> 31-b
; --i
)
1097 m
->addr32
[j
] |= (1 << i
);
1099 m
->addr32
[j
] = htonl(m
->addr32
[j
]);
1101 /* Mask off bits of the address that will never be used. */
1102 n
= &h
->addr
.v
.a
.addr
;
1103 if (h
->addr
.type
== PF_ADDR_ADDRMASK
)
1104 for (i
= 0; i
< 4; i
++)
1105 n
->addr32
[i
] = n
->addr32
[i
] & m
->addr32
[i
];
1109 check_netmask(struct node_host
*h
, sa_family_t af
)
1111 struct node_host
*n
= NULL
;
1114 for (n
= h
; n
!= NULL
; n
= n
->next
) {
1115 if (h
->addr
.type
== PF_ADDR_TABLE
)
1117 m
= &h
->addr
.v
.a
.mask
;
1118 /* fix up netmask for dynaddr */
1119 if (af
== AF_INET
&& h
->addr
.type
== PF_ADDR_DYNIFTL
&&
1120 unmask(m
, AF_INET6
) > 32)
1122 /* netmasks > 32 bit are invalid on v4 */
1123 if (af
== AF_INET
&&
1124 (m
->addr32
[1] || m
->addr32
[2] || m
->addr32
[3])) {
1125 fprintf(stderr
, "netmask %u invalid for IPv4 address\n",
1126 unmask(m
, AF_INET6
));
1133 /* interface lookup routines */
1135 struct node_host
*iftab
;
1140 struct ifaddrs
*ifap
, *ifa
;
1141 struct node_host
*n
= NULL
, *h
= NULL
;
1143 if (getifaddrs(&ifap
) < 0)
1144 err(1, "getifaddrs");
1146 for (ifa
= ifap
; ifa
; ifa
= ifa
->ifa_next
) {
1147 if (!(ifa
->ifa_addr
->sa_family
== AF_INET
||
1148 ifa
->ifa_addr
->sa_family
== AF_INET6
||
1149 ifa
->ifa_addr
->sa_family
== AF_LINK
))
1151 n
= calloc(1, sizeof(struct node_host
));
1153 err(1, "address: calloc");
1154 n
->af
= ifa
->ifa_addr
->sa_family
;
1155 n
->ifa_flags
= ifa
->ifa_flags
;
1157 if (n
->af
== AF_INET6
&&
1158 IN6_IS_ADDR_LINKLOCAL(&((struct sockaddr_in6
*)
1159 ifa
->ifa_addr
)->sin6_addr
) &&
1160 ((struct sockaddr_in6
*)ifa
->ifa_addr
)->sin6_scope_id
==
1162 struct sockaddr_in6
*sin6
;
1164 sin6
= (struct sockaddr_in6
*)ifa
->ifa_addr
;
1165 sin6
->sin6_scope_id
= sin6
->sin6_addr
.s6_addr
[2] << 8 |
1166 sin6
->sin6_addr
.s6_addr
[3];
1167 sin6
->sin6_addr
.s6_addr
[2] = 0;
1168 sin6
->sin6_addr
.s6_addr
[3] = 0;
1172 if (n
->af
== AF_INET
) {
1173 memcpy(&n
->addr
.v
.a
.addr
, &((struct sockaddr_in
*)
1174 ifa
->ifa_addr
)->sin_addr
.s_addr
,
1175 sizeof(struct in_addr
));
1176 memcpy(&n
->addr
.v
.a
.mask
, &((struct sockaddr_in
*)
1177 ifa
->ifa_netmask
)->sin_addr
.s_addr
,
1178 sizeof(struct in_addr
));
1179 if (ifa
->ifa_broadaddr
!= NULL
)
1180 memcpy(&n
->bcast
, &((struct sockaddr_in
*)
1181 ifa
->ifa_broadaddr
)->sin_addr
.s_addr
,
1182 sizeof(struct in_addr
));
1183 if (ifa
->ifa_dstaddr
!= NULL
)
1184 memcpy(&n
->peer
, &((struct sockaddr_in
*)
1185 ifa
->ifa_dstaddr
)->sin_addr
.s_addr
,
1186 sizeof(struct in_addr
));
1187 } else if (n
->af
== AF_INET6
) {
1188 memcpy(&n
->addr
.v
.a
.addr
, &((struct sockaddr_in6
*)
1189 ifa
->ifa_addr
)->sin6_addr
.s6_addr
,
1190 sizeof(struct in6_addr
));
1191 memcpy(&n
->addr
.v
.a
.mask
, &((struct sockaddr_in6
*)
1192 ifa
->ifa_netmask
)->sin6_addr
.s6_addr
,
1193 sizeof(struct in6_addr
));
1194 if (ifa
->ifa_broadaddr
!= NULL
)
1195 memcpy(&n
->bcast
, &((struct sockaddr_in6
*)
1196 ifa
->ifa_broadaddr
)->sin6_addr
.s6_addr
,
1197 sizeof(struct in6_addr
));
1198 if (ifa
->ifa_dstaddr
!= NULL
)
1199 memcpy(&n
->peer
, &((struct sockaddr_in6
*)
1200 ifa
->ifa_dstaddr
)->sin6_addr
.s6_addr
,
1201 sizeof(struct in6_addr
));
1202 n
->ifindex
= ((struct sockaddr_in6
*)
1203 ifa
->ifa_addr
)->sin6_scope_id
;
1205 if ((n
->ifname
= strdup(ifa
->ifa_name
)) == NULL
)
1206 err(1, "ifa_load: strdup");
1222 ifa_exists(const char *ifa_name
)
1224 struct node_host
*n
;
1226 struct ifgroupreq ifgr
;
1228 #endif /* !__NetBSD__ */
1233 /* check wether this is a group */
1235 /* XXXPF TODO investigate what's needed for NetBSD */
1236 if ((s
= socket(AF_INET
, SOCK_DGRAM
, 0)) == -1)
1238 bzero(&ifgr
, sizeof(ifgr
));
1239 strlcpy(ifgr
.ifgr_name
, ifa_name
, sizeof(ifgr
.ifgr_name
));
1240 if (ioctl(s
, SIOCGIFGMEMB
, (caddr_t
)&ifgr
) == 0) {
1241 /* fake a node_host */
1242 if ((n
= calloc(1, sizeof(*n
))) == NULL
)
1244 if ((n
->ifname
= strdup(ifa_name
)) == NULL
)
1250 #endif /* !__NetBSD__ */
1252 for (n
= iftab
; n
; n
= n
->next
) {
1253 if (n
->af
== AF_LINK
&& !strncmp(n
->ifname
, ifa_name
, IFNAMSIZ
))
1261 ifa_grouplookup(const char *ifa_name
, int flags
)
1264 /* XXXPF TODO investigate what's needed for NetBSD */
1268 struct ifg_req
*ifg
;
1269 struct ifgroupreq ifgr
;
1271 struct node_host
*n
, *h
= NULL
;
1273 if ((s
= socket(AF_INET
, SOCK_DGRAM
, 0)) == -1)
1275 bzero(&ifgr
, sizeof(ifgr
));
1276 strlcpy(ifgr
.ifgr_name
, ifa_name
, sizeof(ifgr
.ifgr_name
));
1277 if (ioctl(s
, SIOCGIFGMEMB
, (caddr_t
)&ifgr
) == -1) {
1282 len
= ifgr
.ifgr_len
;
1283 if ((ifgr
.ifgr_groups
= calloc(1, len
)) == NULL
)
1285 if (ioctl(s
, SIOCGIFGMEMB
, (caddr_t
)&ifgr
) == -1)
1286 err(1, "SIOCGIFGMEMB");
1288 for (ifg
= ifgr
.ifgr_groups
; ifg
&& len
>= sizeof(struct ifg_req
);
1290 len
-= sizeof(struct ifg_req
);
1291 if ((n
= ifa_lookup(ifg
->ifgrq_member
, flags
)) == NULL
)
1300 free(ifgr
.ifgr_groups
);
1304 #endif /* !__NetBSD__ */
1308 ifa_lookup(const char *ifa_name
, int flags
)
1310 struct node_host
*p
= NULL
, *h
= NULL
, *n
= NULL
;
1311 int got4
= 0, got6
= 0;
1312 const char *last_if
= NULL
;
1314 if ((h
= ifa_grouplookup(ifa_name
, flags
)) != NULL
)
1317 if (!strncmp(ifa_name
, "self", IFNAMSIZ
))
1323 for (p
= iftab
; p
; p
= p
->next
) {
1324 if (ifa_skip_if(ifa_name
, p
))
1326 if ((flags
& PFI_AFLAG_BROADCAST
) && p
->af
!= AF_INET
)
1328 if ((flags
& PFI_AFLAG_BROADCAST
) &&
1329 !(p
->ifa_flags
& IFF_BROADCAST
))
1331 if ((flags
& PFI_AFLAG_PEER
) &&
1332 !(p
->ifa_flags
& IFF_POINTOPOINT
))
1334 if ((flags
& PFI_AFLAG_NETWORK
) && p
->ifindex
> 0)
1336 if (last_if
== NULL
|| strcmp(last_if
, p
->ifname
))
1338 last_if
= p
->ifname
;
1339 if ((flags
& PFI_AFLAG_NOALIAS
) && p
->af
== AF_INET
&& got4
)
1341 if ((flags
& PFI_AFLAG_NOALIAS
) && p
->af
== AF_INET6
&& got6
)
1343 if (p
->af
== AF_INET
)
1347 n
= calloc(1, sizeof(struct node_host
));
1349 err(1, "address: calloc");
1351 if (flags
& PFI_AFLAG_BROADCAST
)
1352 memcpy(&n
->addr
.v
.a
.addr
, &p
->bcast
,
1353 sizeof(struct pf_addr
));
1354 else if (flags
& PFI_AFLAG_PEER
)
1355 memcpy(&n
->addr
.v
.a
.addr
, &p
->peer
,
1356 sizeof(struct pf_addr
));
1358 memcpy(&n
->addr
.v
.a
.addr
, &p
->addr
.v
.a
.addr
,
1359 sizeof(struct pf_addr
));
1360 if (flags
& PFI_AFLAG_NETWORK
)
1361 set_ipmask(n
, unmask(&p
->addr
.v
.a
.mask
, n
->af
));
1363 if (n
->af
== AF_INET
) {
1364 if (p
->ifa_flags
& IFF_LOOPBACK
&&
1365 p
->ifa_flags
& IFF_LINK1
)
1366 memcpy(&n
->addr
.v
.a
.mask
,
1368 sizeof(struct pf_addr
));
1374 n
->ifindex
= p
->ifindex
;
1389 ifa_skip_if(const char *filter
, struct node_host
*p
)
1393 if (p
->af
!= AF_INET
&& p
->af
!= AF_INET6
)
1395 if (filter
== NULL
|| !*filter
)
1397 if (!strcmp(p
->ifname
, filter
))
1398 return (0); /* exact match */
1400 if (n
< 1 || n
>= IFNAMSIZ
)
1401 return (1); /* sanity check */
1402 if (filter
[n
-1] >= '0' && filter
[n
-1] <= '9')
1403 return (1); /* only do exact match in that case */
1404 if (strncmp(p
->ifname
, filter
, n
))
1405 return (1); /* prefix doesn't match */
1406 return (p
->ifname
[n
] < '0' || p
->ifname
[n
] > '9');
1413 struct node_host
*h
= NULL
;
1414 int mask
, v4mask
, v6mask
, cont
= 1;
1417 if ((p
= strrchr(s
, '/')) != NULL
) {
1418 mask
= strtol(p
+1, &q
, 0);
1419 if (!q
|| *q
|| mask
> 128 || q
== (p
+1)) {
1420 fprintf(stderr
, "invalid netmask '%s'\n", p
);
1423 if ((ps
= malloc(strlen(s
) - strlen(p
) + 1)) == NULL
)
1424 err(1, "host: malloc");
1425 strlcpy(ps
, s
, strlen(s
) - strlen(p
) + 1);
1426 v4mask
= v6mask
= mask
;
1428 if ((ps
= strdup(s
)) == NULL
)
1429 err(1, "host: strdup");
1435 /* interface with this name exists? */
1436 if (cont
&& (h
= host_if(ps
, mask
)) != NULL
)
1440 if (cont
&& (h
= host_v4(s
, mask
)) != NULL
)
1444 if (cont
&& (h
= host_v6(ps
, v6mask
)) != NULL
)
1448 if (cont
&& (h
= host_dns(ps
, v4mask
, v6mask
)) != NULL
)
1452 if (h
== NULL
|| cont
== 1) {
1453 fprintf(stderr
, "no IP address found for %s\n", s
);
1460 host_if(const char *s
, int mask
)
1462 struct node_host
*n
, *h
= NULL
;
1466 if ((ps
= strdup(s
)) == NULL
)
1467 err(1, "host_if: strdup");
1468 while ((p
= strrchr(ps
, ':')) != NULL
) {
1469 if (!strcmp(p
+1, "network"))
1470 flags
|= PFI_AFLAG_NETWORK
;
1471 else if (!strcmp(p
+1, "broadcast"))
1472 flags
|= PFI_AFLAG_BROADCAST
;
1473 else if (!strcmp(p
+1, "peer"))
1474 flags
|= PFI_AFLAG_PEER
;
1475 else if (!strcmp(p
+1, "0"))
1476 flags
|= PFI_AFLAG_NOALIAS
;
1483 if (flags
& (flags
- 1) & PFI_AFLAG_MODEMASK
) { /* Yep! */
1484 fprintf(stderr
, "illegal combination of interface modifiers\n");
1488 if ((flags
& (PFI_AFLAG_NETWORK
|PFI_AFLAG_BROADCAST
)) && mask
> -1) {
1489 fprintf(stderr
, "network or broadcast lookup, but "
1490 "extra netmask given\n");
1494 if (ifa_exists(ps
) || !strncmp(ps
, "self", IFNAMSIZ
)) {
1495 /* interface with this name exists */
1496 h
= ifa_lookup(ps
, flags
);
1497 for (n
= h
; n
!= NULL
&& mask
> -1; n
= n
->next
)
1498 set_ipmask(n
, mask
);
1506 host_v4(const char *s
, int mask
)
1508 struct node_host
*h
= NULL
;
1512 memset(&ina
, 0, sizeof(struct in_addr
));
1513 if (strrchr(s
, '/') != NULL
) {
1514 if ((bits
= inet_net_pton(AF_INET
, s
, &ina
, sizeof(ina
))) == -1)
1517 if (inet_pton(AF_INET
, s
, &ina
) != 1)
1521 h
= calloc(1, sizeof(struct node_host
));
1523 err(1, "address: calloc");
1526 h
->addr
.v
.a
.addr
.addr32
[0] = ina
.s_addr
;
1527 set_ipmask(h
, bits
);
1535 host_v6(const char *s
, int mask
)
1537 struct addrinfo hints
, *res
;
1538 struct node_host
*h
= NULL
;
1540 memset(&hints
, 0, sizeof(hints
));
1541 hints
.ai_family
= AF_INET6
;
1542 hints
.ai_socktype
= SOCK_DGRAM
; /*dummy*/
1543 hints
.ai_flags
= AI_NUMERICHOST
;
1544 if (getaddrinfo(s
, "0", &hints
, &res
) == 0) {
1545 h
= calloc(1, sizeof(struct node_host
));
1547 err(1, "address: calloc");
1550 memcpy(&h
->addr
.v
.a
.addr
,
1551 &((struct sockaddr_in6
*)res
->ai_addr
)->sin6_addr
,
1552 sizeof(h
->addr
.v
.a
.addr
));
1554 ((struct sockaddr_in6
*)res
->ai_addr
)->sin6_scope_id
;
1555 set_ipmask(h
, mask
);
1565 host_dns(const char *s
, int v4mask
, int v6mask
)
1567 struct addrinfo hints
, *res0
, *res
;
1568 struct node_host
*n
, *h
= NULL
;
1569 int error
, noalias
= 0;
1570 int got4
= 0, got6
= 0;
1573 if ((ps
= strdup(s
)) == NULL
)
1574 err(1, "host_dns: strdup");
1575 if ((p
= strrchr(ps
, ':')) != NULL
&& !strcmp(p
, ":0")) {
1579 memset(&hints
, 0, sizeof(hints
));
1580 hints
.ai_family
= PF_UNSPEC
;
1581 hints
.ai_socktype
= SOCK_STREAM
; /* DUMMY */
1582 error
= getaddrinfo(ps
, NULL
, &hints
, &res0
);
1588 for (res
= res0
; res
; res
= res
->ai_next
) {
1589 if (res
->ai_family
!= AF_INET
&&
1590 res
->ai_family
!= AF_INET6
)
1593 if (res
->ai_family
== AF_INET
) {
1603 n
= calloc(1, sizeof(struct node_host
));
1605 err(1, "host_dns: calloc");
1607 n
->af
= res
->ai_family
;
1608 if (res
->ai_family
== AF_INET
) {
1609 memcpy(&n
->addr
.v
.a
.addr
,
1610 &((struct sockaddr_in
*)
1611 res
->ai_addr
)->sin_addr
.s_addr
,
1612 sizeof(struct in_addr
));
1613 set_ipmask(n
, v4mask
);
1615 memcpy(&n
->addr
.v
.a
.addr
,
1616 &((struct sockaddr_in6
*)
1617 res
->ai_addr
)->sin6_addr
.s6_addr
,
1618 sizeof(struct in6_addr
));
1620 ((struct sockaddr_in6
*)
1621 res
->ai_addr
)->sin6_scope_id
;
1622 set_ipmask(n
, v6mask
);
1640 * convert a hostname to a list of addresses and put them in the given buffer.
1642 * if set to 1, only simple addresses are accepted (no netblock, no "!").
1645 append_addr(struct pfr_buffer
*b
, char *s
, int test
)
1648 struct node_host
*h
, *n
;
1651 for (r
= s
; *r
== '!'; r
++)
1653 if ((n
= host(r
)) == NULL
) {
1657 rv
= append_addr_host(b
, n
, test
, not);
1662 } while (n
!= NULL
);
1667 * same as previous function, but with a pre-parsed input and the ability
1668 * to "negate" the result. Does not free the node_host list.
1670 * setting it to 1 is equivalent to adding "!" in front of parameter s.
1673 append_addr_host(struct pfr_buffer
*b
, struct node_host
*n
, int test
, int not)
1676 struct pfr_addr addr
;
1679 bzero(&addr
, sizeof(addr
));
1680 addr
.pfra_not
= n
->not ^ not;
1681 addr
.pfra_af
= n
->af
;
1682 addr
.pfra_net
= unmask(&n
->addr
.v
.a
.mask
, n
->af
);
1685 addr
.pfra_ip4addr
.s_addr
= n
->addr
.v
.a
.addr
.addr32
[0];
1689 memcpy(&addr
.pfra_ip6addr
, &n
->addr
.v
.a
.addr
.v6
,
1690 sizeof(struct in6_addr
));
1697 if ((test
&& (not || addr
.pfra_net
!= bits
)) ||
1698 addr
.pfra_net
> bits
) {
1702 if (pfr_buf_add(b
, &addr
))
1704 } while ((n
= n
->next
) != NULL
);
1710 pfctl_add_trans(struct pfr_buffer
*buf
, int rs_num
, const char *anchor
)
1712 struct pfioc_trans_e trans
;
1714 bzero(&trans
, sizeof(trans
));
1715 trans
.rs_num
= rs_num
;
1716 if (strlcpy(trans
.anchor
, anchor
,
1717 sizeof(trans
.anchor
)) >= sizeof(trans
.anchor
))
1718 errx(1, "pfctl_add_trans: strlcpy");
1720 return pfr_buf_add(buf
, &trans
);
1724 pfctl_get_ticket(struct pfr_buffer
*buf
, int rs_num
, const char *anchor
)
1726 struct pfioc_trans_e
*p
;
1728 PFRB_FOREACH(p
, buf
)
1729 if (rs_num
== p
->rs_num
&& !strcmp(anchor
, p
->anchor
))
1731 errx(1, "pfctl_get_ticket: assertion failed");
1735 pfctl_trans(int dev
, struct pfr_buffer
*buf
, u_long cmd
, int from
)
1737 struct pfioc_trans trans
;
1739 bzero(&trans
, sizeof(trans
));
1740 trans
.size
= buf
->pfrb_size
- from
;
1741 trans
.esize
= sizeof(struct pfioc_trans_e
);
1742 trans
.array
= ((struct pfioc_trans_e
*)buf
->pfrb_caddr
) + from
;
1743 return ioctl(dev
, cmd
, &trans
);