1 /* $OpenBSD: pfctl_parser.c,v 1.240 2008/06/10 20:55:02 mcbride Exp $ */
4 * Copyright (c) 2001 Daniel Hartmeier
5 * Copyright (c) 2002,2003 Henning Brauer
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
12 * - Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * - Redistributions in binary form must reproduce the above
15 * copyright notice, this list of conditions and the following
16 * disclaimer in the documentation and/or other materials provided
17 * with the distribution.
19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
22 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
23 * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
24 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
25 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
26 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
27 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
29 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30 * 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/pf/pfvar.h>
46 #include <arpa/inet.h>
59 #include "pfctl_parser.h"
62 void print_op (u_int8_t
, const char *, const char *);
63 void print_port (u_int8_t
, u_int16_t
, u_int16_t
, const char *);
64 void print_ugid (u_int8_t
, unsigned, unsigned, const char *, unsigned);
65 void print_flags (u_int8_t
);
66 void print_fromto(struct pf_rule_addr
*, pf_osfp_t
,
67 struct pf_rule_addr
*, u_int8_t
, u_int8_t
, int);
68 int ifa_skip_if(const char *filter
, struct node_host
*p
);
70 struct node_host
*ifa_grouplookup(const char *, int);
71 struct node_host
*host_if(const char *, int);
72 static struct node_host
*host_v4(const char *);
73 struct node_host
*host_v6(const char *, int);
74 struct node_host
*host_dns(const char *, int, int);
76 const char *tcpflags
= "FSRPAUEW";
78 static const struct icmptypeent icmp_type
[] = {
79 { "echoreq", ICMP_ECHO
},
80 { "echorep", ICMP_ECHOREPLY
},
81 { "unreach", ICMP_UNREACH
},
82 { "squench", ICMP_SOURCEQUENCH
},
83 { "redir", ICMP_REDIRECT
},
84 { "althost", ICMP_ALTHOSTADDR
},
85 { "routeradv", ICMP_ROUTERADVERT
},
86 { "routersol", ICMP_ROUTERSOLICIT
},
87 { "timex", ICMP_TIMXCEED
},
88 { "paramprob", ICMP_PARAMPROB
},
89 { "timereq", ICMP_TSTAMP
},
90 { "timerep", ICMP_TSTAMPREPLY
},
91 { "inforeq", ICMP_IREQ
},
92 { "inforep", ICMP_IREQREPLY
},
93 { "maskreq", ICMP_MASKREQ
},
94 { "maskrep", ICMP_MASKREPLY
},
95 { "trace", ICMP_TRACEROUTE
},
96 { "dataconv", ICMP_DATACONVERR
},
97 { "mobredir", ICMP_MOBILE_REDIRECT
},
98 { "ipv6-where", ICMP_IPV6_WHEREAREYOU
},
99 { "ipv6-here", ICMP_IPV6_IAMHERE
},
100 { "mobregreq", ICMP_MOBILE_REGREQUEST
},
101 { "mobregrep", ICMP_MOBILE_REGREPLY
},
102 { "skip", ICMP_SKIP
},
103 { "photuris", ICMP_PHOTURIS
}
106 static const struct icmptypeent icmp6_type
[] = {
107 { "unreach", ICMP6_DST_UNREACH
},
108 { "toobig", ICMP6_PACKET_TOO_BIG
},
109 { "timex", ICMP6_TIME_EXCEEDED
},
110 { "paramprob", ICMP6_PARAM_PROB
},
111 { "echoreq", ICMP6_ECHO_REQUEST
},
112 { "echorep", ICMP6_ECHO_REPLY
},
113 { "groupqry", ICMP6_MEMBERSHIP_QUERY
},
114 { "listqry", MLD_LISTENER_QUERY
},
115 { "grouprep", ICMP6_MEMBERSHIP_REPORT
},
116 { "listenrep", MLD_LISTENER_REPORT
},
117 { "groupterm", ICMP6_MEMBERSHIP_REDUCTION
},
118 { "listendone", MLD_LISTENER_DONE
},
119 { "routersol", ND_ROUTER_SOLICIT
},
120 { "routeradv", ND_ROUTER_ADVERT
},
121 { "neighbrsol", ND_NEIGHBOR_SOLICIT
},
122 { "neighbradv", ND_NEIGHBOR_ADVERT
},
123 { "redir", ND_REDIRECT
},
124 { "routrrenum", ICMP6_ROUTER_RENUMBERING
},
125 { "wrureq", ICMP6_WRUREQUEST
},
126 { "wrurep", ICMP6_WRUREPLY
},
127 { "fqdnreq", ICMP6_FQDN_QUERY
},
128 { "fqdnrep", ICMP6_FQDN_REPLY
},
129 { "niqry", ICMP6_NI_QUERY
},
130 { "nirep", ICMP6_NI_REPLY
},
131 { "mtraceresp", MLD_MTRACE_RESP
},
132 { "mtrace", MLD_MTRACE
}
135 static const struct icmpcodeent icmp_code
[] = {
136 { "net-unr", ICMP_UNREACH
, ICMP_UNREACH_NET
},
137 { "host-unr", ICMP_UNREACH
, ICMP_UNREACH_HOST
},
138 { "proto-unr", ICMP_UNREACH
, ICMP_UNREACH_PROTOCOL
},
139 { "port-unr", ICMP_UNREACH
, ICMP_UNREACH_PORT
},
140 { "needfrag", ICMP_UNREACH
, ICMP_UNREACH_NEEDFRAG
},
141 { "srcfail", ICMP_UNREACH
, ICMP_UNREACH_SRCFAIL
},
142 { "net-unk", ICMP_UNREACH
, ICMP_UNREACH_NET_UNKNOWN
},
143 { "host-unk", ICMP_UNREACH
, ICMP_UNREACH_HOST_UNKNOWN
},
144 { "isolate", ICMP_UNREACH
, ICMP_UNREACH_ISOLATED
},
145 { "net-prohib", ICMP_UNREACH
, ICMP_UNREACH_NET_PROHIB
},
146 { "host-prohib", ICMP_UNREACH
, ICMP_UNREACH_HOST_PROHIB
},
147 { "net-tos", ICMP_UNREACH
, ICMP_UNREACH_TOSNET
},
148 { "host-tos", ICMP_UNREACH
, ICMP_UNREACH_TOSHOST
},
149 { "filter-prohib", ICMP_UNREACH
, ICMP_UNREACH_FILTER_PROHIB
},
150 { "host-preced", ICMP_UNREACH
, ICMP_UNREACH_HOST_PRECEDENCE
},
151 { "cutoff-preced", ICMP_UNREACH
, ICMP_UNREACH_PRECEDENCE_CUTOFF
},
152 { "redir-net", ICMP_REDIRECT
, ICMP_REDIRECT_NET
},
153 { "redir-host", ICMP_REDIRECT
, ICMP_REDIRECT_HOST
},
154 { "redir-tos-net", ICMP_REDIRECT
, ICMP_REDIRECT_TOSNET
},
155 { "redir-tos-host", ICMP_REDIRECT
, ICMP_REDIRECT_TOSHOST
},
156 { "normal-adv", ICMP_ROUTERADVERT
, ICMP_ROUTERADVERT_NORMAL
},
157 { "common-adv", ICMP_ROUTERADVERT
, ICMP_ROUTERADVERT_NOROUTE_COMMON
},
158 { "transit", ICMP_TIMXCEED
, ICMP_TIMXCEED_INTRANS
},
159 { "reassemb", ICMP_TIMXCEED
, ICMP_TIMXCEED_REASS
},
160 { "badhead", ICMP_PARAMPROB
, ICMP_PARAMPROB_ERRATPTR
},
161 { "optmiss", ICMP_PARAMPROB
, ICMP_PARAMPROB_OPTABSENT
},
162 { "badlen", ICMP_PARAMPROB
, ICMP_PARAMPROB_LENGTH
},
163 { "unknown-ind", ICMP_PHOTURIS
, ICMP_PHOTURIS_UNKNOWN_INDEX
},
164 { "auth-fail", ICMP_PHOTURIS
, ICMP_PHOTURIS_AUTH_FAILED
},
165 { "decrypt-fail", ICMP_PHOTURIS
, ICMP_PHOTURIS_DECRYPT_FAILED
}
168 static const struct icmpcodeent icmp6_code
[] = {
169 { "admin-unr", ICMP6_DST_UNREACH
, ICMP6_DST_UNREACH_ADMIN
},
170 { "noroute-unr", ICMP6_DST_UNREACH
, ICMP6_DST_UNREACH_NOROUTE
},
171 { "notnbr-unr", ICMP6_DST_UNREACH
, ICMP6_DST_UNREACH_NOTNEIGHBOR
},
172 { "beyond-unr", ICMP6_DST_UNREACH
, ICMP6_DST_UNREACH_BEYONDSCOPE
},
173 { "addr-unr", ICMP6_DST_UNREACH
, ICMP6_DST_UNREACH_ADDR
},
174 { "port-unr", ICMP6_DST_UNREACH
, ICMP6_DST_UNREACH_NOPORT
},
175 { "transit", ICMP6_TIME_EXCEEDED
, ICMP6_TIME_EXCEED_TRANSIT
},
176 { "reassemb", ICMP6_TIME_EXCEEDED
, ICMP6_TIME_EXCEED_REASSEMBLY
},
177 { "badhead", ICMP6_PARAM_PROB
, ICMP6_PARAMPROB_HEADER
},
178 { "nxthdr", ICMP6_PARAM_PROB
, ICMP6_PARAMPROB_NEXTHEADER
},
179 { "redironlink", ND_REDIRECT
, ND_REDIRECT_ONLINK
},
180 { "redirrouter", ND_REDIRECT
, ND_REDIRECT_ROUTER
}
183 const struct pf_timeout pf_timeouts
[] = {
184 { "tcp.first", PFTM_TCP_FIRST_PACKET
},
185 { "tcp.opening", PFTM_TCP_OPENING
},
186 { "tcp.established", PFTM_TCP_ESTABLISHED
},
187 { "tcp.closing", PFTM_TCP_CLOSING
},
188 { "tcp.finwait", PFTM_TCP_FIN_WAIT
},
189 { "tcp.closed", PFTM_TCP_CLOSED
},
190 { "tcp.tsdiff", PFTM_TS_DIFF
},
191 { "udp.first", PFTM_UDP_FIRST_PACKET
},
192 { "udp.single", PFTM_UDP_SINGLE
},
193 { "udp.multiple", PFTM_UDP_MULTIPLE
},
194 { "icmp.first", PFTM_ICMP_FIRST_PACKET
},
195 { "icmp.error", PFTM_ICMP_ERROR_REPLY
},
196 { "other.first", PFTM_OTHER_FIRST_PACKET
},
197 { "other.single", PFTM_OTHER_SINGLE
},
198 { "other.multiple", PFTM_OTHER_MULTIPLE
},
199 { "frag", PFTM_FRAG
},
200 { "interval", PFTM_INTERVAL
},
201 { "adaptive.start", PFTM_ADAPTIVE_START
},
202 { "adaptive.end", PFTM_ADAPTIVE_END
},
203 { "src.track", PFTM_SRC_NODE
},
207 const struct icmptypeent
*
208 geticmptypebynumber(u_int8_t type
, sa_family_t af
)
212 if (af
!= AF_INET6
) {
213 for (i
=0; i
< (sizeof (icmp_type
) / sizeof(icmp_type
[0]));
215 if (type
== icmp_type
[i
].type
)
216 return (&icmp_type
[i
]);
219 for (i
=0; i
< (sizeof (icmp6_type
) /
220 sizeof(icmp6_type
[0])); i
++) {
221 if (type
== icmp6_type
[i
].type
)
222 return (&icmp6_type
[i
]);
228 const struct icmptypeent
*
229 geticmptypebyname(char *w
, sa_family_t af
)
233 if (af
!= AF_INET6
) {
234 for (i
=0; i
< (sizeof (icmp_type
) / sizeof(icmp_type
[0]));
236 if (!strcmp(w
, icmp_type
[i
].name
))
237 return (&icmp_type
[i
]);
240 for (i
=0; i
< (sizeof (icmp6_type
) /
241 sizeof(icmp6_type
[0])); i
++) {
242 if (!strcmp(w
, icmp6_type
[i
].name
))
243 return (&icmp6_type
[i
]);
249 const struct icmpcodeent
*
250 geticmpcodebynumber(u_int8_t type
, u_int8_t code
, sa_family_t af
)
254 if (af
!= AF_INET6
) {
255 for (i
=0; i
< (sizeof (icmp_code
) / sizeof(icmp_code
[0]));
257 if (type
== icmp_code
[i
].type
&&
258 code
== icmp_code
[i
].code
)
259 return (&icmp_code
[i
]);
262 for (i
=0; i
< (sizeof (icmp6_code
) /
263 sizeof(icmp6_code
[0])); i
++) {
264 if (type
== icmp6_code
[i
].type
&&
265 code
== icmp6_code
[i
].code
)
266 return (&icmp6_code
[i
]);
272 const struct icmpcodeent
*
273 geticmpcodebyname(u_long type
, char *w
, sa_family_t af
)
277 if (af
!= AF_INET6
) {
278 for (i
=0; i
< (sizeof (icmp_code
) / sizeof(icmp_code
[0]));
280 if (type
== icmp_code
[i
].type
&&
281 !strcmp(w
, icmp_code
[i
].name
))
282 return (&icmp_code
[i
]);
285 for (i
=0; i
< (sizeof (icmp6_code
) /
286 sizeof(icmp6_code
[0])); i
++) {
287 if (type
== icmp6_code
[i
].type
&&
288 !strcmp(w
, icmp6_code
[i
].name
))
289 return (&icmp6_code
[i
]);
296 print_op(u_int8_t op
, const char *a1
, const char *a2
)
299 printf(" %s >< %s", a1
, a2
);
300 else if (op
== PF_OP_XRG
)
301 printf(" %s <> %s", a1
, a2
);
302 else if (op
== PF_OP_EQ
)
304 else if (op
== PF_OP_NE
)
305 printf(" != %s", a1
);
306 else if (op
== PF_OP_LT
)
308 else if (op
== PF_OP_LE
)
309 printf(" <= %s", a1
);
310 else if (op
== PF_OP_GT
)
312 else if (op
== PF_OP_GE
)
313 printf(" >= %s", a1
);
314 else if (op
== PF_OP_RRG
)
315 printf(" %s:%s", a1
, a2
);
319 print_port(u_int8_t op
, u_int16_t p1
, u_int16_t p2
, const char *proto
)
324 s
= getservbyport(p1
, proto
);
327 snprintf(a1
, sizeof(a1
), "%u", p1
);
328 snprintf(a2
, sizeof(a2
), "%u", p2
);
330 if (s
!= NULL
&& (op
== PF_OP_EQ
|| op
== PF_OP_NE
))
331 print_op(op
, s
->s_name
, a2
);
333 print_op(op
, a1
, a2
);
337 print_ugid(u_int8_t op
, unsigned u1
, unsigned u2
, const char *t
, unsigned umax
)
341 snprintf(a1
, sizeof(a1
), "%u", u1
);
342 snprintf(a2
, sizeof(a2
), "%u", u2
);
344 if (u1
== umax
&& (op
== PF_OP_EQ
|| op
== PF_OP_NE
))
345 print_op(op
, "unknown", a2
);
347 print_op(op
, a1
, a2
);
351 print_flags(u_int8_t f
)
355 for (i
= 0; tcpflags
[i
]; ++i
)
357 printf("%c", tcpflags
[i
]);
361 print_fromto(struct pf_rule_addr
*src
, pf_osfp_t osfp
, struct pf_rule_addr
*dst
,
362 sa_family_t af
, u_int8_t proto
, int verbose
)
364 char buf
[PF_OSFP_LEN
*3];
365 if (src
->addr
.type
== PF_ADDR_ADDRMASK
&&
366 dst
->addr
.type
== PF_ADDR_ADDRMASK
&&
367 PF_AZERO(&src
->addr
.v
.a
.addr
, AF_INET6
) &&
368 PF_AZERO(&src
->addr
.v
.a
.mask
, AF_INET6
) &&
369 PF_AZERO(&dst
->addr
.v
.a
.addr
, AF_INET6
) &&
370 PF_AZERO(&dst
->addr
.v
.a
.mask
, AF_INET6
) &&
371 !src
->neg
&& !dst
->neg
&&
372 !src
->port_op
&& !dst
->port_op
&&
379 print_addr(&src
->addr
, af
, verbose
);
381 print_port(src
->port_op
, src
->port
[0],
383 proto
== IPPROTO_TCP
? "tcp" : "udp");
384 if (osfp
!= PF_OSFP_ANY
)
385 printf(" os \"%s\"", pfctl_lookup_fingerprint(osfp
, buf
,
391 print_addr(&dst
->addr
, af
, verbose
);
393 print_port(dst
->port_op
, dst
->port
[0],
395 proto
== IPPROTO_TCP
? "tcp" : "udp");
400 print_pool(struct pf_pool
*pool
, u_int16_t p1
, u_int16_t p2
,
401 sa_family_t af
, int id
)
403 struct pf_pooladdr
*pooladdr
;
405 if ((TAILQ_FIRST(&pool
->list
) != NULL
) &&
406 TAILQ_NEXT(TAILQ_FIRST(&pool
->list
), entries
) != NULL
)
408 TAILQ_FOREACH(pooladdr
, &pool
->list
, entries
){
413 print_addr(&pooladdr
->addr
, af
, 0);
416 if (PF_AZERO(&pooladdr
->addr
.v
.a
.addr
, af
))
417 printf("%s", pooladdr
->ifname
);
419 printf("(%s ", pooladdr
->ifname
);
420 print_addr(&pooladdr
->addr
, af
, 0);
427 if (TAILQ_NEXT(pooladdr
, entries
) != NULL
)
429 else if (TAILQ_NEXT(TAILQ_FIRST(&pool
->list
), entries
) != NULL
)
434 if ((p1
!= PF_NAT_PROXY_PORT_LOW
||
435 p2
!= PF_NAT_PROXY_PORT_HIGH
) && (p1
!= 0 || p2
!= 0)) {
437 printf(" port %u", p1
);
439 printf(" port %u:%u", p1
, p2
);
444 printf(" port %u", p1
);
445 if (p2
&& (p2
!= p1
))
452 switch (pool
->opts
& PF_POOL_TYPEMASK
) {
455 case PF_POOL_BITMASK
:
461 case PF_POOL_SRCHASH
:
462 printf(" source-hash 0x%08x%08x%08x%08x",
463 pool
->key
.key32
[0], pool
->key
.key32
[1],
464 pool
->key
.key32
[2], pool
->key
.key32
[3]);
466 case PF_POOL_ROUNDROBIN
:
467 printf(" round-robin");
470 if (pool
->opts
& PF_POOL_STICKYADDR
)
471 printf(" sticky-address");
472 if (id
== PF_NAT
&& p1
== 0 && p2
== 0)
473 printf(" static-port");
476 const char *pf_reasons
[PFRES_MAX
+1] = PFRES_NAMES
;
477 const char *pf_lcounters
[LCNT_MAX
+1] = LCNT_NAMES
;
478 const char *pf_fcounters
[FCNT_MAX
+1] = FCNT_NAMES
;
479 const char *pf_scounters
[FCNT_MAX
+1] = FCNT_NAMES
;
482 print_status(struct pf_status
*s
, int opts
)
488 char buf
[PF_MD5_DIGEST_LENGTH
* 2 + 1];
489 static const char hex
[] = "0123456789abcdef";
491 runtime
= time(NULL
) - s
->since
;
492 running
= s
->running
? "Enabled" : "Disabled";
495 unsigned int sec
, min
, hrs
, day
= runtime
;
503 snprintf(statline
, sizeof(statline
),
504 "Status: %s for %u days %.2u:%.2u:%.2u",
505 running
, day
, hrs
, min
, sec
);
507 snprintf(statline
, sizeof(statline
), "Status: %s", running
);
508 printf("%-44s", statline
);
511 printf("%15s\n\n", "Debug: None");
513 case PF_DEBUG_URGENT
:
514 printf("%15s\n\n", "Debug: Urgent");
517 printf("%15s\n\n", "Debug: Misc");
520 printf("%15s\n\n", "Debug: Loud");
524 if (opts
& PF_OPT_VERBOSE
) {
525 printf("Hostid: 0x%08x\n", ntohl(s
->hostid
));
527 for (i
= 0; i
< PF_MD5_DIGEST_LENGTH
; i
++) {
528 buf
[i
+ i
] = hex
[s
->pf_chksum
[i
] >> 4];
529 buf
[i
+ i
+ 1] = hex
[s
->pf_chksum
[i
] & 0x0f];
532 printf("Checksum: 0x%s\n\n", buf
);
535 if (s
->ifname
[0] != 0) {
536 printf("Interface Stats for %-16s %5s %16s\n",
537 s
->ifname
, "IPv4", "IPv6");
538 printf(" %-25s %14llu %16llu\n", "Bytes In",
539 (unsigned long long)s
->bcounters
[0][0],
540 (unsigned long long)s
->bcounters
[1][0]);
541 printf(" %-25s %14llu %16llu\n", "Bytes Out",
542 (unsigned long long)s
->bcounters
[0][1],
543 (unsigned long long)s
->bcounters
[1][1]);
544 printf(" Packets In\n");
545 printf(" %-23s %14llu %16llu\n", "Passed",
546 (unsigned long long)s
->pcounters
[0][0][PF_PASS
],
547 (unsigned long long)s
->pcounters
[1][0][PF_PASS
]);
548 printf(" %-23s %14llu %16llu\n", "Blocked",
549 (unsigned long long)s
->pcounters
[0][0][PF_DROP
],
550 (unsigned long long)s
->pcounters
[1][0][PF_DROP
]);
551 printf(" Packets Out\n");
552 printf(" %-23s %14llu %16llu\n", "Passed",
553 (unsigned long long)s
->pcounters
[0][1][PF_PASS
],
554 (unsigned long long)s
->pcounters
[1][1][PF_PASS
]);
555 printf(" %-23s %14llu %16llu\n\n", "Blocked",
556 (unsigned long long)s
->pcounters
[0][1][PF_DROP
],
557 (unsigned long long)s
->pcounters
[1][1][PF_DROP
]);
559 printf("%-27s %14s %16s\n", "State Table", "Total", "Rate");
560 printf(" %-25s %14u %14s\n", "current entries", s
->states
, "");
561 for (i
= 0; i
< FCNT_MAX
; i
++) {
562 printf(" %-25s %14llu ", pf_fcounters
[i
],
563 (unsigned long long)s
->fcounters
[i
]);
566 (double)s
->fcounters
[i
] / (double)runtime
);
568 printf("%14s\n", "");
570 if (opts
& PF_OPT_VERBOSE
) {
571 printf("Source Tracking Table\n");
572 printf(" %-25s %14u %14s\n", "current entries",
574 for (i
= 0; i
< SCNT_MAX
; i
++) {
575 printf(" %-25s %14lld ", pf_scounters
[i
],
576 (unsigned long long)s
->scounters
[i
]);
579 (double)s
->scounters
[i
] / (double)runtime
);
581 printf("%14s\n", "");
584 printf("Counters\n");
585 for (i
= 0; i
< PFRES_MAX
; i
++) {
586 printf(" %-25s %14llu ", pf_reasons
[i
],
587 (unsigned long long)s
->counters
[i
]);
590 (double)s
->counters
[i
] / (double)runtime
);
592 printf("%14s\n", "");
594 if (opts
& PF_OPT_VERBOSE
) {
595 printf("Limit Counters\n");
596 for (i
= 0; i
< LCNT_MAX
; i
++) {
597 printf(" %-25s %14ju ", pf_lcounters
[i
],
598 (uintmax_t)s
->lcounters
[i
]);
601 (double)s
->lcounters
[i
] / (double)runtime
);
603 printf("%14s\n", "");
609 print_src_node(struct pf_src_node
*sn
, int opts
)
611 struct pf_addr_wrap aw
;
614 memset(&aw
, 0, sizeof(aw
));
615 if (sn
->af
== AF_INET
)
616 aw
.v
.a
.mask
.addr32
[0] = 0xffffffff;
618 memset(&aw
.v
.a
.mask
, 0xff, sizeof(aw
.v
.a
.mask
));
620 aw
.v
.a
.addr
= sn
->addr
;
621 print_addr(&aw
, sn
->af
, opts
& PF_OPT_VERBOSE2
);
623 aw
.v
.a
.addr
= sn
->raddr
;
624 print_addr(&aw
, sn
->af
, opts
& PF_OPT_VERBOSE2
);
625 printf(" ( states %u, connections %u, rate %u.%u/%us )\n", sn
->states
,
626 sn
->conn
, sn
->conn_rate
.count
/ 1000,
627 (sn
->conn_rate
.count
% 1000) / 100, sn
->conn_rate
.seconds
);
628 if (opts
& PF_OPT_VERBOSE
) {
629 sec
= sn
->creation
% 60;
631 min
= sn
->creation
% 60;
633 printf(" age %.2u:%.2u:%.2u", sn
->creation
, min
, sec
);
634 if (sn
->states
== 0) {
635 sec
= sn
->expire
% 60;
637 min
= sn
->expire
% 60;
639 printf(", expires in %.2u:%.2u:%.2u",
640 sn
->expire
, min
, sec
);
642 printf(", %ju pkts, %ju bytes",
643 (uintmax_t)sn
->packets
[0] + sn
->packets
[1],
644 (uintmax_t)sn
->bytes
[0] + sn
->bytes
[1]);
645 switch (sn
->ruletype
) {
647 if (sn
->rule
.nr
!= (uint32_t)(-1))
648 printf(", nat rule %u", sn
->rule
.nr
);
651 if (sn
->rule
.nr
!= (uint32_t)(-1))
652 printf(", rdr rule %u", sn
->rule
.nr
);
655 if (sn
->rule
.nr
!= (uint32_t)(-1))
656 printf(", filter rule %u", sn
->rule
.nr
);
664 print_rule(struct pf_rule
*r
, const char *anchor_call
, int verbose
)
666 static const char *actiontypes
[] = { "pass", "block", "scrub",
667 "no scrub", "nat", "no nat", "binat", "no binat", "rdr", "no rdr" };
668 static const char *anchortypes
[] = { "anchor", "anchor", "anchor",
669 "anchor", "nat-anchor", "nat-anchor", "binat-anchor",
670 "binat-anchor", "rdr-anchor", "rdr-anchor" };
674 printf("@%d ", r
->nr
);
675 if (r
->action
> PF_NORDR
)
676 printf("action(%d)", r
->action
);
677 else if (anchor_call
[0]) {
678 if (anchor_call
[0] == '_') {
679 printf("%s", anchortypes
[r
->action
]);
681 printf("%s \"%s\"", anchortypes
[r
->action
],
684 printf("%s", actiontypes
[r
->action
]);
688 if (r
->action
== PF_DROP
) {
689 if (r
->rule_flag
& PFRULE_RETURN
)
691 else if (r
->rule_flag
& PFRULE_RETURNRST
) {
693 printf(" return-rst");
695 printf(" return-rst(ttl %d)", r
->return_ttl
);
696 } else if (r
->rule_flag
& PFRULE_RETURNICMP
) {
697 const struct icmpcodeent
*ic
, *ic6
;
699 ic
= geticmpcodebynumber(r
->return_icmp
>> 8,
700 r
->return_icmp
& 255, AF_INET
);
701 ic6
= geticmpcodebynumber(r
->return_icmp6
>> 8,
702 r
->return_icmp6
& 255, AF_INET6
);
706 printf(" return-icmp");
708 printf("(%u)", r
->return_icmp
& 255);
710 printf("(%s)", ic
->name
);
713 printf(" return-icmp6");
715 printf("(%u)", r
->return_icmp6
& 255);
717 printf("(%s)", ic6
->name
);
720 printf(" return-icmp");
722 printf("(%u, ", r
->return_icmp
& 255);
724 printf("(%s, ", ic
->name
);
726 printf("%u)", r
->return_icmp6
& 255);
728 printf("%s)", ic6
->name
);
734 if (r
->direction
== PF_IN
)
736 else if (r
->direction
== PF_OUT
)
740 if (r
->log
& ~PF_LOG
|| r
->logif
) {
744 if (r
->log
& PF_LOG_ALL
)
745 printf("%sall", count
++ ? ", " : "");
746 if (r
->log
& PF_LOG_SOCKET_LOOKUP
)
747 printf("%suser", count
++ ? ", " : "");
749 printf("%sto pflog%u", count
++ ? ", " : "",
758 printf(" on ! %s", r
->ifname
);
760 printf(" on %s", r
->ifname
);
763 if (r
->rt
== PF_ROUTETO
)
765 else if (r
->rt
== PF_REPLYTO
)
767 else if (r
->rt
== PF_DUPTO
)
769 else if (r
->rt
== PF_FASTROUTE
)
770 printf(" fastroute");
771 if (r
->rt
!= PF_FASTROUTE
) {
773 print_pool(&r
->rpool
, 0, 0, r
->af
, PF_PASS
);
777 if (r
->af
== AF_INET
)
785 if ((p
= getprotobynumber(r
->proto
)) != NULL
)
786 printf(" proto %s", p
->p_name
);
788 printf(" proto %u", r
->proto
);
790 print_fromto(&r
->src
, r
->os_fingerprint
, &r
->dst
, r
->af
, r
->proto
,
793 print_ugid(r
->uid
.op
, r
->uid
.uid
[0], r
->uid
.uid
[1], "user",
796 print_ugid(r
->gid
.op
, r
->gid
.gid
[0], r
->gid
.gid
[1], "group",
798 if (r
->flags
|| r
->flagset
) {
800 print_flags(r
->flags
);
802 print_flags(r
->flagset
);
803 } else if (r
->action
== PF_PASS
&&
804 (!r
->proto
|| r
->proto
== IPPROTO_TCP
) &&
805 !(r
->rule_flag
& PFRULE_FRAGMENT
) &&
806 !anchor_call
[0] && r
->keep_state
)
807 printf(" flags any");
809 const struct icmptypeent
*it
;
811 it
= geticmptypebynumber(r
->type
-1, r
->af
);
812 if (r
->af
!= AF_INET6
)
813 printf(" icmp-type");
815 printf(" icmp6-type");
817 printf(" %s", it
->name
);
819 printf(" %u", r
->type
-1);
821 const struct icmpcodeent
*ic
;
823 ic
= geticmpcodebynumber(r
->type
-1, r
->code
-1, r
->af
);
825 printf(" code %s", ic
->name
);
827 printf(" code %u", r
->code
-1);
831 printf(" tos 0x%2.2x", r
->tos
);
832 if (!r
->keep_state
&& r
->action
== PF_PASS
&& !anchor_call
[0])
834 else if (r
->keep_state
== PF_STATE_NORMAL
)
835 printf(" keep state");
836 else if (r
->keep_state
== PF_STATE_MODULATE
)
837 printf(" modulate state");
838 else if (r
->keep_state
== PF_STATE_SYNPROXY
)
839 printf(" synproxy state");
843 snprintf(buf
, sizeof(buf
), "%f", r
->prob
*100.0/(UINT_MAX
+1.0));
844 for (i
= strlen(buf
)-1; i
> 0; i
--) {
853 printf(" probability %s%%", buf
);
856 if (r
->max_states
|| r
->max_src_nodes
|| r
->max_src_states
)
860 if (r
->rule_flag
& PFRULE_NOSYNC
)
862 if (r
->rule_flag
& PFRULE_SRCTRACK
)
864 if (r
->rule_flag
& PFRULE_IFBOUND
)
866 if (r
->rule_flag
& PFRULE_STATESLOPPY
)
868 for (i
= 0; !opts
&& i
< PFTM_MAX
; ++i
)
873 switch(r
->pickup_mode
) {
874 case PF_PICKUPS_UNSPECIFIED
:
876 case PF_PICKUPS_DISABLED
:
877 printf("no-pickups");
880 case PF_PICKUPS_HASHONLY
:
884 case PF_PICKUPS_ENABLED
:
889 printf("unknown-pickups-mode-%d", r
->pickup_mode
);
895 printf("max %u", r
->max_states
);
898 if (r
->rule_flag
& PFRULE_NOSYNC
) {
904 if (r
->rule_flag
& PFRULE_SRCTRACK
) {
907 printf("source-track");
908 if (r
->rule_flag
& PFRULE_RULESRCTRACK
)
914 if (r
->max_src_states
) {
917 printf("max-src-states %u", r
->max_src_states
);
920 if (r
->max_src_conn
) {
923 printf("max-src-conn %u", r
->max_src_conn
);
926 if (r
->max_src_conn_rate
.limit
) {
929 printf("max-src-conn-rate %u/%u",
930 r
->max_src_conn_rate
.limit
,
931 r
->max_src_conn_rate
.seconds
);
934 if (r
->max_src_nodes
) {
937 printf("max-src-nodes %u", r
->max_src_nodes
);
940 if (r
->overload_tblname
[0]) {
943 printf("overload <%s>", r
->overload_tblname
);
946 if (r
->flush
& PF_FLUSH_GLOBAL
)
949 if (r
->rule_flag
& PFRULE_IFBOUND
) {
955 if (r
->rule_flag
& PFRULE_STATESLOPPY
) {
961 for (i
= 0; i
< PFTM_MAX
; ++i
)
968 for (j
= 0; pf_timeouts
[j
].name
!= NULL
;
970 if (pf_timeouts
[j
].timeout
== i
)
972 printf("%s %u", pf_timeouts
[j
].name
== NULL
?
973 "inv.timeout" : pf_timeouts
[j
].name
,
978 if (r
->rule_flag
& PFRULE_FRAGMENT
)
980 if (r
->rule_flag
& PFRULE_NODF
)
982 if (r
->rule_flag
& PFRULE_RANDOMID
)
983 printf(" random-id");
985 printf(" min-ttl %d", r
->min_ttl
);
987 printf(" max-mss %d", r
->max_mss
);
988 if (r
->rule_flag
& PFRULE_SET_TOS
)
989 printf(" set-tos 0x%2.2x", r
->set_tos
);
991 printf(" allow-opts");
992 if (r
->action
== PF_SCRUB
) {
993 if (r
->rule_flag
& PFRULE_REASSEMBLE_TCP
)
994 printf(" reassemble tcp");
996 if (r
->rule_flag
& PFRULE_FRAGDROP
)
997 printf(" fragment drop-ovl");
998 else if (r
->rule_flag
& PFRULE_FRAGCROP
)
999 printf(" fragment crop");
1001 printf(" fragment reassemble");
1004 printf(" label \"%s\"", r
->label
);
1005 if (r
->qname
[0] && r
->pqname
[0])
1006 printf(" queue(%s, %s)", r
->qname
, r
->pqname
);
1007 else if (r
->qname
[0])
1008 printf(" queue %s", r
->qname
);
1010 printf(" tag %s", r
->tagname
);
1011 if (r
->match_tagname
[0]) {
1012 if (r
->match_tag_not
)
1014 printf(" tagged %s", r
->match_tagname
);
1016 if (r
->rtableid
!= -1)
1017 printf(" rtable %u", r
->rtableid
);
1018 if (r
->divert
.port
) {
1019 if (PF_AZERO(&r
->divert
.addr
, r
->af
)) {
1020 printf(" divert-reply");
1022 /* XXX cut&paste from print_addr */
1025 printf(" divert-to ");
1026 if (inet_ntop(r
->af
, &r
->divert
.addr
, buf
,
1027 sizeof(buf
)) == NULL
)
1031 printf(" port %u", ntohs(r
->divert
.port
));
1034 if (!anchor_call
[0] && (r
->action
== PF_NAT
||
1035 r
->action
== PF_BINAT
|| r
->action
== PF_RDR
)) {
1037 print_pool(&r
->rpool
, r
->rpool
.proxy_port
[0],
1038 r
->rpool
.proxy_port
[1], r
->af
, r
->action
);
1043 print_tabledef(const char *name
, int flags
, int addrs
,
1044 struct node_tinithead
*nodes
)
1046 struct node_tinit
*ti
, *nti
;
1047 struct node_host
*h
;
1049 printf("table <%s>", name
);
1050 if (flags
& PFR_TFLAG_CONST
)
1052 if (flags
& PFR_TFLAG_PERSIST
)
1054 if (flags
& PFR_TFLAG_COUNTERS
)
1055 printf(" counters");
1056 SIMPLEQ_FOREACH(ti
, nodes
, entries
) {
1058 printf(" file \"%s\"", ti
->file
);
1063 for (h
= ti
->host
; h
!= NULL
; h
= h
->next
) {
1064 printf(h
->not ? " !" : " ");
1065 print_addr(&h
->addr
, h
->af
, 0);
1067 nti
= SIMPLEQ_NEXT(ti
, entries
);
1068 if (nti
!= NULL
&& nti
->file
== NULL
)
1069 ti
= nti
; /* merge lists */
1075 if (addrs
&& SIMPLEQ_EMPTY(nodes
))
1081 parse_flags(const char *s
)
1086 for (p
= s
; *p
; p
++) {
1087 if ((q
= strchr(tcpflags
, *p
)) == NULL
)
1090 f
|= 1 << (q
- tcpflags
);
1092 return (f
? f
: PF_TH_ALL
);
1096 set_ipmask(struct node_host
*h
, u_int8_t b
)
1098 struct pf_addr
*m
, *n
;
1101 m
= &h
->addr
.v
.a
.mask
;
1102 memset(m
, 0, sizeof(*m
));
1105 m
->addr32
[j
++] = 0xffffffff;
1108 for (i
= 31; i
> 31-b
; --i
)
1109 m
->addr32
[j
] |= (1 << i
);
1111 m
->addr32
[j
] = htonl(m
->addr32
[j
]);
1113 /* Mask off bits of the address that will never be used. */
1114 n
= &h
->addr
.v
.a
.addr
;
1115 if (h
->addr
.type
== PF_ADDR_ADDRMASK
)
1116 for (i
= 0; i
< 4; i
++)
1117 n
->addr32
[i
] = n
->addr32
[i
] & m
->addr32
[i
];
1121 check_netmask(struct node_host
*h
, sa_family_t af
)
1123 struct node_host
*n
= NULL
;
1126 for (n
= h
; n
!= NULL
; n
= n
->next
) {
1127 if (h
->addr
.type
== PF_ADDR_TABLE
)
1129 m
= &h
->addr
.v
.a
.mask
;
1130 /* fix up netmask for dynaddr */
1131 if (af
== AF_INET
&& h
->addr
.type
== PF_ADDR_DYNIFTL
&&
1132 unmask(m
, AF_INET6
) > 32)
1134 /* netmasks > 32 bit are invalid on v4 */
1135 if (af
== AF_INET
&&
1136 (m
->addr32
[1] || m
->addr32
[2] || m
->addr32
[3])) {
1137 fprintf(stderr
, "netmask %u invalid for IPv4 address\n",
1138 unmask(m
, AF_INET6
));
1145 /* interface lookup routines */
1147 struct node_host
*iftab
;
1152 struct ifaddrs
*ifap
, *ifa
;
1153 struct node_host
*n
= NULL
, *h
= NULL
;
1155 if (getifaddrs(&ifap
) < 0)
1156 err(1, "getifaddrs");
1158 for (ifa
= ifap
; ifa
; ifa
= ifa
->ifa_next
) {
1159 if (!(ifa
->ifa_addr
->sa_family
== AF_INET
||
1160 ifa
->ifa_addr
->sa_family
== AF_INET6
||
1161 ifa
->ifa_addr
->sa_family
== AF_LINK
))
1163 n
= calloc(1, sizeof(struct node_host
));
1165 err(1, "address: calloc");
1166 n
->af
= ifa
->ifa_addr
->sa_family
;
1167 n
->ifa_flags
= ifa
->ifa_flags
;
1169 if (n
->af
== AF_INET6
&&
1170 IN6_IS_ADDR_LINKLOCAL(&((struct sockaddr_in6
*)
1171 ifa
->ifa_addr
)->sin6_addr
) &&
1172 ((struct sockaddr_in6
*)ifa
->ifa_addr
)->sin6_scope_id
==
1174 struct sockaddr_in6
*sin6
;
1176 sin6
= (struct sockaddr_in6
*)ifa
->ifa_addr
;
1177 sin6
->sin6_scope_id
= sin6
->sin6_addr
.s6_addr
[2] << 8 |
1178 sin6
->sin6_addr
.s6_addr
[3];
1179 sin6
->sin6_addr
.s6_addr
[2] = 0;
1180 sin6
->sin6_addr
.s6_addr
[3] = 0;
1184 if (n
->af
== AF_INET
) {
1185 memcpy(&n
->addr
.v
.a
.addr
, &((struct sockaddr_in
*)
1186 ifa
->ifa_addr
)->sin_addr
.s_addr
,
1187 sizeof(struct in_addr
));
1188 memcpy(&n
->addr
.v
.a
.mask
, &((struct sockaddr_in
*)
1189 ifa
->ifa_netmask
)->sin_addr
.s_addr
,
1190 sizeof(struct in_addr
));
1191 if (ifa
->ifa_broadaddr
!= NULL
)
1192 memcpy(&n
->bcast
, &((struct sockaddr_in
*)
1193 ifa
->ifa_broadaddr
)->sin_addr
.s_addr
,
1194 sizeof(struct in_addr
));
1195 if (ifa
->ifa_dstaddr
!= NULL
)
1196 memcpy(&n
->peer
, &((struct sockaddr_in
*)
1197 ifa
->ifa_dstaddr
)->sin_addr
.s_addr
,
1198 sizeof(struct in_addr
));
1199 } else if (n
->af
== AF_INET6
) {
1200 memcpy(&n
->addr
.v
.a
.addr
, &((struct sockaddr_in6
*)
1201 ifa
->ifa_addr
)->sin6_addr
.s6_addr
,
1202 sizeof(struct in6_addr
));
1203 memcpy(&n
->addr
.v
.a
.mask
, &((struct sockaddr_in6
*)
1204 ifa
->ifa_netmask
)->sin6_addr
.s6_addr
,
1205 sizeof(struct in6_addr
));
1206 if (ifa
->ifa_broadaddr
!= NULL
)
1207 memcpy(&n
->bcast
, &((struct sockaddr_in6
*)
1208 ifa
->ifa_broadaddr
)->sin6_addr
.s6_addr
,
1209 sizeof(struct in6_addr
));
1210 if (ifa
->ifa_dstaddr
!= NULL
)
1211 memcpy(&n
->peer
, &((struct sockaddr_in6
*)
1212 ifa
->ifa_dstaddr
)->sin6_addr
.s6_addr
,
1213 sizeof(struct in6_addr
));
1214 n
->ifindex
= ((struct sockaddr_in6
*)
1215 ifa
->ifa_addr
)->sin6_scope_id
;
1217 if ((n
->ifname
= strdup(ifa
->ifa_name
)) == NULL
)
1218 err(1, "ifa_load: strdup");
1234 ifa_exists(const char *ifa_name
)
1236 struct node_host
*n
;
1237 struct ifgroupreq ifgr
;
1243 /* check wether this is a group */
1244 if ((s
= socket(AF_INET
, SOCK_DGRAM
, 0)) == -1)
1246 bzero(&ifgr
, sizeof(ifgr
));
1247 strlcpy(ifgr
.ifgr_name
, ifa_name
, sizeof(ifgr
.ifgr_name
));
1248 if (ioctl(s
, SIOCGIFGMEMB
, (caddr_t
)&ifgr
) == 0) {
1249 /* fake a node_host */
1250 if ((n
= calloc(1, sizeof(*n
))) == NULL
)
1252 if ((n
->ifname
= strdup(ifa_name
)) == NULL
)
1259 for (n
= iftab
; n
; n
= n
->next
) {
1260 if (n
->af
== AF_LINK
&& !strncmp(n
->ifname
, ifa_name
, IFNAMSIZ
))
1268 ifa_grouplookup(const char *ifa_name
, int flags
)
1270 struct ifg_req
*ifg
;
1271 struct ifgroupreq ifgr
;
1274 struct node_host
*n
, *h
= NULL
;
1276 if ((s
= socket(AF_INET
, SOCK_DGRAM
, 0)) == -1)
1278 bzero(&ifgr
, sizeof(ifgr
));
1279 strlcpy(ifgr
.ifgr_name
, ifa_name
, sizeof(ifgr
.ifgr_name
));
1280 if (ioctl(s
, SIOCGIFGMEMB
, (caddr_t
)&ifgr
) == -1) {
1285 len
= ifgr
.ifgr_len
;
1286 if ((ifgr
.ifgr_groups
= calloc(1, len
)) == NULL
)
1288 if (ioctl(s
, SIOCGIFGMEMB
, (caddr_t
)&ifgr
) == -1)
1289 err(1, "SIOCGIFGMEMB");
1291 for (ifg
= ifgr
.ifgr_groups
; ifg
&& len
>= sizeof(struct ifg_req
);
1293 len
-= sizeof(struct ifg_req
);
1294 if ((n
= ifa_lookup(ifg
->ifgrq_member
, flags
)) == NULL
)
1303 free(ifgr
.ifgr_groups
);
1310 ifa_lookup(const char *ifa_name
, int flags
)
1312 struct node_host
*p
= NULL
, *h
= NULL
, *n
= NULL
;
1313 int got4
= 0, got6
= 0;
1314 const char *last_if
= NULL
;
1316 if ((h
= ifa_grouplookup(ifa_name
, flags
)) != NULL
)
1319 if (!strncmp(ifa_name
, "self", IFNAMSIZ
))
1325 for (p
= iftab
; p
; p
= p
->next
) {
1326 if (ifa_skip_if(ifa_name
, p
))
1328 if ((flags
& PFI_AFLAG_BROADCAST
) && p
->af
!= AF_INET
)
1330 if ((flags
& PFI_AFLAG_BROADCAST
) &&
1331 !(p
->ifa_flags
& IFF_BROADCAST
))
1333 if ((flags
& PFI_AFLAG_PEER
) &&
1334 !(p
->ifa_flags
& IFF_POINTOPOINT
))
1336 if ((flags
& PFI_AFLAG_NETWORK
) && p
->ifindex
> 0)
1338 if (last_if
== NULL
|| strcmp(last_if
, p
->ifname
))
1340 last_if
= p
->ifname
;
1341 if ((flags
& PFI_AFLAG_NOALIAS
) && p
->af
== AF_INET
&& got4
)
1343 if ((flags
& PFI_AFLAG_NOALIAS
) && p
->af
== AF_INET6
&& got6
)
1345 if (p
->af
== AF_INET
)
1349 n
= calloc(1, sizeof(struct node_host
));
1351 err(1, "address: calloc");
1353 if (flags
& PFI_AFLAG_BROADCAST
)
1354 memcpy(&n
->addr
.v
.a
.addr
, &p
->bcast
,
1355 sizeof(struct pf_addr
));
1356 else if (flags
& PFI_AFLAG_PEER
)
1357 memcpy(&n
->addr
.v
.a
.addr
, &p
->peer
,
1358 sizeof(struct pf_addr
));
1360 memcpy(&n
->addr
.v
.a
.addr
, &p
->addr
.v
.a
.addr
,
1361 sizeof(struct pf_addr
));
1362 if (flags
& PFI_AFLAG_NETWORK
)
1363 set_ipmask(n
, unmask(&p
->addr
.v
.a
.mask
, n
->af
));
1365 if (n
->af
== AF_INET
) {
1366 if (p
->ifa_flags
& IFF_LOOPBACK
&&
1367 p
->ifa_flags
& IFF_LINK1
)
1368 memcpy(&n
->addr
.v
.a
.mask
,
1370 sizeof(struct pf_addr
));
1376 n
->ifindex
= p
->ifindex
;
1391 ifa_skip_if(const char *filter
, struct node_host
*p
)
1395 if (p
->af
!= AF_INET
&& p
->af
!= AF_INET6
)
1397 if (filter
== NULL
|| !*filter
)
1399 if (!strcmp(p
->ifname
, filter
))
1400 return (0); /* exact match */
1402 if (n
< 1 || n
>= IFNAMSIZ
)
1403 return (1); /* sanity check */
1404 if (filter
[n
-1] >= '0' && filter
[n
-1] <= '9')
1405 return (1); /* only do exact match in that case */
1406 if (strncmp(p
->ifname
, filter
, n
))
1407 return (1); /* prefix doesn't match */
1408 return (p
->ifname
[n
] < '0' || p
->ifname
[n
] > '9');
1415 struct node_host
*h
= NULL
;
1416 int mask
, v4mask
, v6mask
, cont
= 1;
1419 if ((p
= strrchr(s
, '/')) != NULL
) {
1420 mask
= strtol(p
+1, &q
, 0);
1421 if (!q
|| *q
|| mask
> 128 || q
== (p
+1)) {
1422 fprintf(stderr
, "invalid netmask '%s'\n", p
);
1425 if ((ps
= malloc(strlen(s
) - strlen(p
) + 1)) == NULL
)
1426 err(1, "host: malloc");
1427 strlcpy(ps
, s
, strlen(s
) - strlen(p
) + 1);
1428 v4mask
= v6mask
= mask
;
1430 if ((ps
= strdup(s
)) == NULL
)
1431 err(1, "host: strdup");
1437 /* interface with this name exists? */
1438 if (cont
&& (h
= host_if(ps
, mask
)) != NULL
)
1442 if (cont
&& (h
= host_v4(s
)) != NULL
)
1446 if (cont
&& (h
= host_v6(ps
, v6mask
)) != NULL
)
1450 if (cont
&& (h
= host_dns(ps
, v4mask
, v6mask
)) != NULL
)
1454 if (h
== NULL
|| cont
== 1) {
1455 fprintf(stderr
, "no IP address found for %s\n", s
);
1462 host_if(const char *s
, int mask
)
1464 struct node_host
*n
, *h
= NULL
;
1468 if ((ps
= strdup(s
)) == NULL
)
1469 err(1, "host_if: strdup");
1470 while ((p
= strrchr(ps
, ':')) != NULL
) {
1471 if (!strcmp(p
+1, "network"))
1472 flags
|= PFI_AFLAG_NETWORK
;
1473 else if (!strcmp(p
+1, "broadcast"))
1474 flags
|= PFI_AFLAG_BROADCAST
;
1475 else if (!strcmp(p
+1, "peer"))
1476 flags
|= PFI_AFLAG_PEER
;
1477 else if (!strcmp(p
+1, "0"))
1478 flags
|= PFI_AFLAG_NOALIAS
;
1485 if (flags
& (flags
- 1) & PFI_AFLAG_MODEMASK
) { /* Yep! */
1486 fprintf(stderr
, "illegal combination of interface modifiers\n");
1490 if ((flags
& (PFI_AFLAG_NETWORK
|PFI_AFLAG_BROADCAST
)) && mask
> -1) {
1491 fprintf(stderr
, "network or broadcast lookup, but "
1492 "extra netmask given\n");
1496 if (ifa_exists(ps
) || !strncmp(ps
, "self", IFNAMSIZ
)) {
1497 /* interface with this name exists */
1498 h
= ifa_lookup(ps
, flags
);
1499 for (n
= h
; n
!= NULL
&& mask
> -1; n
= n
->next
)
1500 set_ipmask(n
, mask
);
1507 static struct node_host
*
1508 host_v4(const char *s
)
1510 struct node_host
*h
= NULL
;
1514 memset(&ina
, 0, sizeof(struct in_addr
));
1515 if (strrchr(s
, '/') != NULL
) {
1516 if ((bits
= inet_net_pton(AF_INET
, s
, &ina
, sizeof(ina
))) == -1)
1519 if (inet_pton(AF_INET
, s
, &ina
) != 1)
1523 h
= calloc(1, sizeof(struct node_host
));
1525 err(1, "address: calloc");
1528 h
->addr
.v
.a
.addr
.addr32
[0] = ina
.s_addr
;
1529 set_ipmask(h
, bits
);
1537 host_v6(const char *s
, int mask
)
1539 struct addrinfo hints
, *res
;
1540 struct node_host
*h
= NULL
;
1542 memset(&hints
, 0, sizeof(hints
));
1543 hints
.ai_family
= AF_INET6
;
1544 hints
.ai_socktype
= SOCK_DGRAM
; /*dummy*/
1545 hints
.ai_flags
= AI_NUMERICHOST
;
1546 if (getaddrinfo(s
, "0", &hints
, &res
) == 0) {
1547 h
= calloc(1, sizeof(struct node_host
));
1549 err(1, "address: calloc");
1552 memcpy(&h
->addr
.v
.a
.addr
,
1553 &((struct sockaddr_in6
*)res
->ai_addr
)->sin6_addr
,
1554 sizeof(h
->addr
.v
.a
.addr
));
1556 ((struct sockaddr_in6
*)res
->ai_addr
)->sin6_scope_id
;
1557 set_ipmask(h
, mask
);
1567 host_dns(const char *s
, int v4mask
, int v6mask
)
1569 struct addrinfo hints
, *res0
, *res
;
1570 struct node_host
*n
, *h
= NULL
;
1571 int error
, noalias
= 0;
1572 int got4
= 0, got6
= 0;
1575 if ((ps
= strdup(s
)) == NULL
)
1576 err(1, "host_dns: strdup");
1577 if ((p
= strrchr(ps
, ':')) != NULL
&& !strcmp(p
, ":0")) {
1581 memset(&hints
, 0, sizeof(hints
));
1582 hints
.ai_family
= PF_UNSPEC
;
1583 hints
.ai_socktype
= SOCK_STREAM
; /* DUMMY */
1584 error
= getaddrinfo(ps
, NULL
, &hints
, &res0
);
1590 for (res
= res0
; res
; res
= res
->ai_next
) {
1591 if (res
->ai_family
!= AF_INET
&&
1592 res
->ai_family
!= AF_INET6
)
1595 if (res
->ai_family
== AF_INET
) {
1605 n
= calloc(1, sizeof(struct node_host
));
1607 err(1, "host_dns: calloc");
1609 n
->af
= res
->ai_family
;
1610 if (res
->ai_family
== AF_INET
) {
1611 memcpy(&n
->addr
.v
.a
.addr
,
1612 &((struct sockaddr_in
*)
1613 res
->ai_addr
)->sin_addr
.s_addr
,
1614 sizeof(struct in_addr
));
1615 set_ipmask(n
, v4mask
);
1617 memcpy(&n
->addr
.v
.a
.addr
,
1618 &((struct sockaddr_in6
*)
1619 res
->ai_addr
)->sin6_addr
.s6_addr
,
1620 sizeof(struct in6_addr
));
1622 ((struct sockaddr_in6
*)
1623 res
->ai_addr
)->sin6_scope_id
;
1624 set_ipmask(n
, v6mask
);
1642 * convert a hostname to a list of addresses and put them in the given buffer.
1644 * if set to 1, only simple addresses are accepted (no netblock, no "!").
1647 append_addr(struct pfr_buffer
*b
, char *s
, int test
)
1650 struct node_host
*h
, *n
;
1653 for (r
= s
; *r
== '!'; r
++)
1655 if ((n
= host(r
)) == NULL
) {
1659 rv
= append_addr_host(b
, n
, test
, not);
1664 } while (n
!= NULL
);
1669 * same as previous function, but with a pre-parsed input and the ability
1670 * to "negate" the result. Does not free the node_host list.
1672 * setting it to 1 is equivalent to adding "!" in front of parameter s.
1675 append_addr_host(struct pfr_buffer
*b
, struct node_host
*n
, int test
, int not)
1678 struct pfr_addr addr
;
1681 bzero(&addr
, sizeof(addr
));
1682 addr
.pfra_not
= n
->not ^ not;
1683 addr
.pfra_af
= n
->af
;
1684 addr
.pfra_net
= unmask(&n
->addr
.v
.a
.mask
, n
->af
);
1687 addr
.pfra_ip4addr
.s_addr
= n
->addr
.v
.a
.addr
.addr32
[0];
1691 memcpy(&addr
.pfra_ip6addr
, &n
->addr
.v
.a
.addr
.v6
,
1692 sizeof(struct in6_addr
));
1699 if ((test
&& (not || addr
.pfra_net
!= bits
)) ||
1700 addr
.pfra_net
> bits
) {
1704 if (pfr_buf_add(b
, &addr
))
1706 } while ((n
= n
->next
) != NULL
);
1712 pfctl_add_trans(struct pfr_buffer
*buf
, int rs_num
, const char *anchor
)
1714 struct pfioc_trans_e trans
;
1716 bzero(&trans
, sizeof(trans
));
1717 trans
.rs_num
= rs_num
;
1718 if (strlcpy(trans
.anchor
, anchor
,
1719 sizeof(trans
.anchor
)) >= sizeof(trans
.anchor
))
1720 errx(1, "pfctl_add_trans: strlcpy");
1722 return pfr_buf_add(buf
, &trans
);
1726 pfctl_get_ticket(struct pfr_buffer
*buf
, int rs_num
, const char *anchor
)
1728 const struct pfioc_trans_e
*p
;
1730 PFRB_FOREACH(p
, buf
)
1731 if (rs_num
== p
->rs_num
&& !strcmp(anchor
, p
->anchor
))
1733 errx(1, "pfctl_get_ticket: assertion failed");
1737 pfctl_trans(int dev
, struct pfr_buffer
*buf
, u_long cmd
, int from
)
1739 struct pfioc_trans trans
;
1741 bzero(&trans
, sizeof(trans
));
1742 trans
.size
= buf
->pfrb_size
- from
;
1743 trans
.esize
= sizeof(struct pfioc_trans_e
);
1744 trans
.array
= ((struct pfioc_trans_e
*)buf
->pfrb_caddr
) + from
;
1745 return ioctl(dev
, cmd
, &trans
);