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
< NELEM(icmp_type
); i
++) {
214 if (type
== icmp_type
[i
].type
)
215 return (&icmp_type
[i
]);
218 for (i
=0; i
< NELEM(icmp6_type
); i
++) {
219 if (type
== icmp6_type
[i
].type
)
220 return (&icmp6_type
[i
]);
226 const struct icmptypeent
*
227 geticmptypebyname(char *w
, sa_family_t af
)
231 if (af
!= AF_INET6
) {
232 for (i
=0; i
< NELEM(icmp_type
); i
++) {
233 if (!strcmp(w
, icmp_type
[i
].name
))
234 return (&icmp_type
[i
]);
237 for (i
=0; i
< NELEM(icmp6_type
); 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
< NELEM(icmp_code
); i
++) {
252 if (type
== icmp_code
[i
].type
&&
253 code
== icmp_code
[i
].code
)
254 return (&icmp_code
[i
]);
257 for (i
=0; i
< NELEM(icmp6_code
); i
++) {
258 if (type
== icmp6_code
[i
].type
&&
259 code
== icmp6_code
[i
].code
)
260 return (&icmp6_code
[i
]);
266 const struct icmpcodeent
*
267 geticmpcodebyname(u_long type
, char *w
, sa_family_t af
)
271 if (af
!= AF_INET6
) {
272 for (i
=0; i
< NELEM(icmp_code
); i
++) {
273 if (type
== icmp_code
[i
].type
&&
274 !strcmp(w
, icmp_code
[i
].name
))
275 return (&icmp_code
[i
]);
278 for (i
=0; i
< NELEM(icmp6_code
); i
++) {
279 if (type
== icmp6_code
[i
].type
&&
280 !strcmp(w
, icmp6_code
[i
].name
))
281 return (&icmp6_code
[i
]);
288 print_op(u_int8_t op
, const char *a1
, const char *a2
)
291 printf(" %s >< %s", a1
, a2
);
292 else if (op
== PF_OP_XRG
)
293 printf(" %s <> %s", a1
, a2
);
294 else if (op
== PF_OP_EQ
)
296 else if (op
== PF_OP_NE
)
297 printf(" != %s", a1
);
298 else if (op
== PF_OP_LT
)
300 else if (op
== PF_OP_LE
)
301 printf(" <= %s", a1
);
302 else if (op
== PF_OP_GT
)
304 else if (op
== PF_OP_GE
)
305 printf(" >= %s", a1
);
306 else if (op
== PF_OP_RRG
)
307 printf(" %s:%s", a1
, a2
);
311 print_port(u_int8_t op
, u_int16_t p1
, u_int16_t p2
, const char *proto
)
316 s
= getservbyport(p1
, proto
);
319 snprintf(a1
, sizeof(a1
), "%u", p1
);
320 snprintf(a2
, sizeof(a2
), "%u", p2
);
322 if (s
!= NULL
&& (op
== PF_OP_EQ
|| op
== PF_OP_NE
))
323 print_op(op
, s
->s_name
, a2
);
325 print_op(op
, a1
, a2
);
329 print_ugid(u_int8_t op
, unsigned u1
, unsigned u2
, const char *t
, unsigned umax
)
333 snprintf(a1
, sizeof(a1
), "%u", u1
);
334 snprintf(a2
, sizeof(a2
), "%u", u2
);
336 if (u1
== umax
&& (op
== PF_OP_EQ
|| op
== PF_OP_NE
))
337 print_op(op
, "unknown", a2
);
339 print_op(op
, a1
, a2
);
343 print_flags(u_int8_t f
)
347 for (i
= 0; tcpflags
[i
]; ++i
)
349 printf("%c", tcpflags
[i
]);
353 print_fromto(struct pf_rule_addr
*src
, pf_osfp_t osfp
, struct pf_rule_addr
*dst
,
354 sa_family_t af
, u_int8_t proto
, int verbose
)
356 char buf
[PF_OSFP_LEN
*3];
357 if (src
->addr
.type
== PF_ADDR_ADDRMASK
&&
358 dst
->addr
.type
== PF_ADDR_ADDRMASK
&&
359 PF_AZERO(&src
->addr
.v
.a
.addr
, AF_INET6
) &&
360 PF_AZERO(&src
->addr
.v
.a
.mask
, AF_INET6
) &&
361 PF_AZERO(&dst
->addr
.v
.a
.addr
, AF_INET6
) &&
362 PF_AZERO(&dst
->addr
.v
.a
.mask
, AF_INET6
) &&
363 !src
->neg
&& !dst
->neg
&&
364 !src
->port_op
&& !dst
->port_op
&&
371 print_addr(&src
->addr
, af
, verbose
);
373 print_port(src
->port_op
, src
->port
[0],
375 proto
== IPPROTO_TCP
? "tcp" : "udp");
376 if (osfp
!= PF_OSFP_ANY
)
377 printf(" os \"%s\"", pfctl_lookup_fingerprint(osfp
, buf
,
383 print_addr(&dst
->addr
, af
, verbose
);
385 print_port(dst
->port_op
, dst
->port
[0],
387 proto
== IPPROTO_TCP
? "tcp" : "udp");
392 print_pool(struct pf_pool
*pool
, u_int16_t p1
, u_int16_t p2
,
393 sa_family_t af
, int id
)
395 struct pf_pooladdr
*pooladdr
;
397 if ((TAILQ_FIRST(&pool
->list
) != NULL
) &&
398 TAILQ_NEXT(TAILQ_FIRST(&pool
->list
), entries
) != NULL
)
400 TAILQ_FOREACH(pooladdr
, &pool
->list
, entries
){
405 print_addr(&pooladdr
->addr
, af
, 0);
408 if (PF_AZERO(&pooladdr
->addr
.v
.a
.addr
, af
))
409 printf("%s", pooladdr
->ifname
);
411 printf("(%s ", pooladdr
->ifname
);
412 print_addr(&pooladdr
->addr
, af
, 0);
419 if (TAILQ_NEXT(pooladdr
, entries
) != NULL
)
421 else if (TAILQ_NEXT(TAILQ_FIRST(&pool
->list
), entries
) != NULL
)
426 if ((p1
!= PF_NAT_PROXY_PORT_LOW
||
427 p2
!= PF_NAT_PROXY_PORT_HIGH
) && (p1
!= 0 || p2
!= 0)) {
429 printf(" port %u", p1
);
431 printf(" port %u:%u", p1
, p2
);
436 printf(" port %u", p1
);
437 if (p2
&& (p2
!= p1
))
444 switch (pool
->opts
& PF_POOL_TYPEMASK
) {
447 case PF_POOL_BITMASK
:
453 case PF_POOL_SRCHASH
:
454 printf(" source-hash 0x%08x%08x%08x%08x",
455 pool
->key
.key32
[0], pool
->key
.key32
[1],
456 pool
->key
.key32
[2], pool
->key
.key32
[3]);
458 case PF_POOL_ROUNDROBIN
:
459 printf(" round-robin");
462 if (pool
->opts
& PF_POOL_STICKYADDR
)
463 printf(" sticky-address");
464 if (id
== PF_NAT
&& p1
== 0 && p2
== 0)
465 printf(" static-port");
468 const char *pf_reasons
[PFRES_MAX
+1] = PFRES_NAMES
;
469 const char *pf_lcounters
[LCNT_MAX
+1] = LCNT_NAMES
;
470 const char *pf_fcounters
[FCNT_MAX
+1] = FCNT_NAMES
;
471 const char *pf_scounters
[FCNT_MAX
+1] = FCNT_NAMES
;
474 print_status(struct pf_status
*s
, int opts
)
480 char buf
[PF_MD5_DIGEST_LENGTH
* 2 + 1];
481 static const char hex
[] = "0123456789abcdef";
483 runtime
= time(NULL
) - s
->since
;
484 running
= s
->running
? "Enabled" : "Disabled";
487 unsigned int sec
, min
, hrs
, day
= runtime
;
495 snprintf(statline
, sizeof(statline
),
496 "Status: %s for %u days %.2u:%.2u:%.2u",
497 running
, day
, hrs
, min
, sec
);
499 snprintf(statline
, sizeof(statline
), "Status: %s", running
);
500 printf("%-44s", statline
);
503 printf("%15s\n\n", "Debug: None");
505 case PF_DEBUG_URGENT
:
506 printf("%15s\n\n", "Debug: Urgent");
509 printf("%15s\n\n", "Debug: Misc");
512 printf("%15s\n\n", "Debug: Loud");
516 if (opts
& PF_OPT_VERBOSE
) {
517 printf("Hostid: 0x%08x\n", ntohl(s
->hostid
));
519 for (i
= 0; i
< PF_MD5_DIGEST_LENGTH
; i
++) {
520 buf
[i
+ i
] = hex
[s
->pf_chksum
[i
] >> 4];
521 buf
[i
+ i
+ 1] = hex
[s
->pf_chksum
[i
] & 0x0f];
524 printf("Checksum: 0x%s\n\n", buf
);
527 if (s
->ifname
[0] != 0) {
528 printf("Interface Stats for %-16s %5s %16s\n",
529 s
->ifname
, "IPv4", "IPv6");
530 printf(" %-25s %14llu %16llu\n", "Bytes In",
531 (unsigned long long)s
->bcounters
[0][0],
532 (unsigned long long)s
->bcounters
[1][0]);
533 printf(" %-25s %14llu %16llu\n", "Bytes Out",
534 (unsigned long long)s
->bcounters
[0][1],
535 (unsigned long long)s
->bcounters
[1][1]);
536 printf(" Packets In\n");
537 printf(" %-23s %14llu %16llu\n", "Passed",
538 (unsigned long long)s
->pcounters
[0][0][PF_PASS
],
539 (unsigned long long)s
->pcounters
[1][0][PF_PASS
]);
540 printf(" %-23s %14llu %16llu\n", "Blocked",
541 (unsigned long long)s
->pcounters
[0][0][PF_DROP
],
542 (unsigned long long)s
->pcounters
[1][0][PF_DROP
]);
543 printf(" Packets Out\n");
544 printf(" %-23s %14llu %16llu\n", "Passed",
545 (unsigned long long)s
->pcounters
[0][1][PF_PASS
],
546 (unsigned long long)s
->pcounters
[1][1][PF_PASS
]);
547 printf(" %-23s %14llu %16llu\n\n", "Blocked",
548 (unsigned long long)s
->pcounters
[0][1][PF_DROP
],
549 (unsigned long long)s
->pcounters
[1][1][PF_DROP
]);
551 printf("%-27s %14s %16s\n", "State Table", "Total", "Rate");
552 printf(" %-25s %14u %14s\n", "current entries", s
->states
, "");
553 for (i
= 0; i
< FCNT_MAX
; i
++) {
554 printf(" %-25s %14llu ", pf_fcounters
[i
],
555 (unsigned long long)s
->fcounters
[i
]);
558 (double)s
->fcounters
[i
] / (double)runtime
);
560 printf("%14s\n", "");
562 if (opts
& PF_OPT_VERBOSE
) {
563 printf("Source Tracking Table\n");
564 printf(" %-25s %14u %14s\n", "current entries",
566 for (i
= 0; i
< SCNT_MAX
; i
++) {
567 printf(" %-25s %14lld ", pf_scounters
[i
],
568 (unsigned long long)s
->scounters
[i
]);
571 (double)s
->scounters
[i
] / (double)runtime
);
573 printf("%14s\n", "");
576 printf("Counters\n");
577 for (i
= 0; i
< PFRES_MAX
; i
++) {
578 printf(" %-25s %14llu ", pf_reasons
[i
],
579 (unsigned long long)s
->counters
[i
]);
582 (double)s
->counters
[i
] / (double)runtime
);
584 printf("%14s\n", "");
586 if (opts
& PF_OPT_VERBOSE
) {
587 printf("Limit Counters\n");
588 for (i
= 0; i
< LCNT_MAX
; i
++) {
589 printf(" %-25s %14ju ", pf_lcounters
[i
],
590 (uintmax_t)s
->lcounters
[i
]);
593 (double)s
->lcounters
[i
] / (double)runtime
);
595 printf("%14s\n", "");
601 print_src_node(struct pf_src_node
*sn
, int opts
)
603 struct pf_addr_wrap aw
;
606 memset(&aw
, 0, sizeof(aw
));
607 if (sn
->af
== AF_INET
)
608 aw
.v
.a
.mask
.addr32
[0] = 0xffffffff;
610 memset(&aw
.v
.a
.mask
, 0xff, sizeof(aw
.v
.a
.mask
));
612 aw
.v
.a
.addr
= sn
->addr
;
613 print_addr(&aw
, sn
->af
, opts
& PF_OPT_VERBOSE2
);
615 aw
.v
.a
.addr
= sn
->raddr
;
616 print_addr(&aw
, sn
->af
, opts
& PF_OPT_VERBOSE2
);
617 printf(" ( states %u, connections %u, rate %u.%u/%us )\n", sn
->states
,
618 sn
->conn
, sn
->conn_rate
.count
/ 1000,
619 (sn
->conn_rate
.count
% 1000) / 100, sn
->conn_rate
.seconds
);
620 if (opts
& PF_OPT_VERBOSE
) {
621 sec
= sn
->creation
% 60;
623 min
= sn
->creation
% 60;
625 printf(" age %.2u:%.2u:%.2u", sn
->creation
, min
, sec
);
626 if (sn
->states
== 0) {
627 sec
= sn
->expire
% 60;
629 min
= sn
->expire
% 60;
631 printf(", expires in %.2u:%.2u:%.2u",
632 sn
->expire
, min
, sec
);
634 printf(", %ju pkts, %ju bytes",
635 (uintmax_t)sn
->packets
[0] + sn
->packets
[1],
636 (uintmax_t)sn
->bytes
[0] + sn
->bytes
[1]);
637 switch (sn
->ruletype
) {
639 if (sn
->rule
.nr
!= (uint32_t)(-1))
640 printf(", nat rule %u", sn
->rule
.nr
);
643 if (sn
->rule
.nr
!= (uint32_t)(-1))
644 printf(", rdr rule %u", sn
->rule
.nr
);
647 if (sn
->rule
.nr
!= (uint32_t)(-1))
648 printf(", filter rule %u", sn
->rule
.nr
);
656 print_rule(struct pf_rule
*r
, const char *anchor_call
, int verbose
)
658 static const char *actiontypes
[] = { "pass", "block", "scrub",
659 "no scrub", "nat", "no nat", "binat", "no binat", "rdr", "no rdr" };
660 static const char *anchortypes
[] = { "anchor", "anchor", "anchor",
661 "anchor", "nat-anchor", "nat-anchor", "binat-anchor",
662 "binat-anchor", "rdr-anchor", "rdr-anchor" };
666 printf("@%d ", r
->nr
);
667 if (r
->action
> PF_NORDR
)
668 printf("action(%d)", r
->action
);
669 else if (anchor_call
[0]) {
670 if (anchor_call
[0] == '_') {
671 printf("%s", anchortypes
[r
->action
]);
673 printf("%s \"%s\"", anchortypes
[r
->action
],
676 printf("%s", actiontypes
[r
->action
]);
680 if (r
->action
== PF_DROP
) {
681 if (r
->rule_flag
& PFRULE_RETURN
)
683 else if (r
->rule_flag
& PFRULE_RETURNRST
) {
685 printf(" return-rst");
687 printf(" return-rst(ttl %d)", r
->return_ttl
);
688 } else if (r
->rule_flag
& PFRULE_RETURNICMP
) {
689 const struct icmpcodeent
*ic
, *ic6
;
691 ic
= geticmpcodebynumber(r
->return_icmp
>> 8,
692 r
->return_icmp
& 255, AF_INET
);
693 ic6
= geticmpcodebynumber(r
->return_icmp6
>> 8,
694 r
->return_icmp6
& 255, AF_INET6
);
698 printf(" return-icmp");
700 printf("(%u)", r
->return_icmp
& 255);
702 printf("(%s)", ic
->name
);
705 printf(" return-icmp6");
707 printf("(%u)", r
->return_icmp6
& 255);
709 printf("(%s)", ic6
->name
);
712 printf(" return-icmp");
714 printf("(%u, ", r
->return_icmp
& 255);
716 printf("(%s, ", ic
->name
);
718 printf("%u)", r
->return_icmp6
& 255);
720 printf("%s)", ic6
->name
);
726 if (r
->direction
== PF_IN
)
728 else if (r
->direction
== PF_OUT
)
732 if (r
->log
& ~PF_LOG
|| r
->logif
) {
736 if (r
->log
& PF_LOG_ALL
)
737 printf("%sall", count
++ ? ", " : "");
738 if (r
->log
& PF_LOG_SOCKET_LOOKUP
)
739 printf("%suser", count
++ ? ", " : "");
741 printf("%sto pflog%u", count
++ ? ", " : "",
750 printf(" on ! %s", r
->ifname
);
752 printf(" on %s", r
->ifname
);
755 if (r
->rt
== PF_ROUTETO
)
757 else if (r
->rt
== PF_REPLYTO
)
759 else if (r
->rt
== PF_DUPTO
)
761 else if (r
->rt
== PF_FASTROUTE
)
762 printf(" fastroute");
763 if (r
->rt
!= PF_FASTROUTE
) {
765 print_pool(&r
->rpool
, 0, 0, r
->af
, PF_PASS
);
769 if (r
->af
== AF_INET
)
777 if ((p
= getprotobynumber(r
->proto
)) != NULL
)
778 printf(" proto %s", p
->p_name
);
780 printf(" proto %u", r
->proto
);
782 print_fromto(&r
->src
, r
->os_fingerprint
, &r
->dst
, r
->af
, r
->proto
,
785 print_ugid(r
->uid
.op
, r
->uid
.uid
[0], r
->uid
.uid
[1], "user",
788 print_ugid(r
->gid
.op
, r
->gid
.gid
[0], r
->gid
.gid
[1], "group",
790 if (r
->flags
|| r
->flagset
) {
792 print_flags(r
->flags
);
794 print_flags(r
->flagset
);
795 } else if (r
->action
== PF_PASS
&&
796 (!r
->proto
|| r
->proto
== IPPROTO_TCP
) &&
797 !(r
->rule_flag
& PFRULE_FRAGMENT
) &&
798 !anchor_call
[0] && r
->keep_state
)
799 printf(" flags any");
801 const struct icmptypeent
*it
;
803 it
= geticmptypebynumber(r
->type
-1, r
->af
);
804 if (r
->af
!= AF_INET6
)
805 printf(" icmp-type");
807 printf(" icmp6-type");
809 printf(" %s", it
->name
);
811 printf(" %u", r
->type
-1);
813 const struct icmpcodeent
*ic
;
815 ic
= geticmpcodebynumber(r
->type
-1, r
->code
-1, r
->af
);
817 printf(" code %s", ic
->name
);
819 printf(" code %u", r
->code
-1);
823 printf(" tos 0x%2.2x", r
->tos
);
824 if (!r
->keep_state
&& r
->action
== PF_PASS
&& !anchor_call
[0])
826 else if (r
->keep_state
== PF_STATE_NORMAL
)
827 printf(" keep state");
828 else if (r
->keep_state
== PF_STATE_MODULATE
)
829 printf(" modulate state");
830 else if (r
->keep_state
== PF_STATE_SYNPROXY
)
831 printf(" synproxy state");
835 snprintf(buf
, sizeof(buf
), "%f", r
->prob
*100.0/(UINT_MAX
+1.0));
836 for (i
= strlen(buf
)-1; i
> 0; i
--) {
845 printf(" probability %s%%", buf
);
848 if (r
->max_states
|| r
->max_src_nodes
|| r
->max_src_states
)
852 if (r
->rule_flag
& PFRULE_NOSYNC
)
854 if (r
->rule_flag
& PFRULE_SRCTRACK
)
856 if (r
->rule_flag
& PFRULE_IFBOUND
)
858 if (r
->rule_flag
& PFRULE_STATESLOPPY
)
860 for (i
= 0; !opts
&& i
< PFTM_MAX
; ++i
)
865 switch(r
->pickup_mode
) {
866 case PF_PICKUPS_UNSPECIFIED
:
868 case PF_PICKUPS_DISABLED
:
869 printf("no-pickups");
872 case PF_PICKUPS_HASHONLY
:
876 case PF_PICKUPS_ENABLED
:
881 printf("unknown-pickups-mode-%d", r
->pickup_mode
);
887 printf("max %u", r
->max_states
);
890 if (r
->rule_flag
& PFRULE_NOSYNC
) {
896 if (r
->rule_flag
& PFRULE_SRCTRACK
) {
899 printf("source-track");
900 if (r
->rule_flag
& PFRULE_RULESRCTRACK
)
906 if (r
->max_src_states
) {
909 printf("max-src-states %u", r
->max_src_states
);
912 if (r
->max_src_conn
) {
915 printf("max-src-conn %u", r
->max_src_conn
);
918 if (r
->max_src_conn_rate
.limit
) {
921 printf("max-src-conn-rate %u/%u",
922 r
->max_src_conn_rate
.limit
,
923 r
->max_src_conn_rate
.seconds
);
926 if (r
->max_src_nodes
) {
929 printf("max-src-nodes %u", r
->max_src_nodes
);
932 if (r
->overload_tblname
[0]) {
935 printf("overload <%s>", r
->overload_tblname
);
938 if (r
->flush
& PF_FLUSH_GLOBAL
)
941 if (r
->rule_flag
& PFRULE_IFBOUND
) {
947 if (r
->rule_flag
& PFRULE_STATESLOPPY
) {
953 for (i
= 0; i
< PFTM_MAX
; ++i
)
960 for (j
= 0; pf_timeouts
[j
].name
!= NULL
;
962 if (pf_timeouts
[j
].timeout
== i
)
964 printf("%s %u", pf_timeouts
[j
].name
== NULL
?
965 "inv.timeout" : pf_timeouts
[j
].name
,
970 if (r
->rule_flag
& PFRULE_FRAGMENT
)
972 if (r
->rule_flag
& PFRULE_NODF
)
974 if (r
->rule_flag
& PFRULE_RANDOMID
)
975 printf(" random-id");
977 printf(" min-ttl %d", r
->min_ttl
);
979 printf(" max-mss %d", r
->max_mss
);
980 if (r
->rule_flag
& PFRULE_SET_TOS
)
981 printf(" set-tos 0x%2.2x", r
->set_tos
);
983 printf(" allow-opts");
984 if (r
->action
== PF_SCRUB
) {
985 if (r
->rule_flag
& PFRULE_REASSEMBLE_TCP
)
986 printf(" reassemble tcp");
988 if (r
->rule_flag
& PFRULE_FRAGDROP
)
989 printf(" fragment drop-ovl");
990 else if (r
->rule_flag
& PFRULE_FRAGCROP
)
991 printf(" fragment crop");
993 printf(" fragment reassemble");
996 printf(" label \"%s\"", r
->label
);
997 if (r
->qname
[0] && r
->pqname
[0])
998 printf(" queue(%s, %s)", r
->qname
, r
->pqname
);
999 else if (r
->qname
[0])
1000 printf(" queue %s", r
->qname
);
1002 printf(" tag %s", r
->tagname
);
1003 if (r
->match_tagname
[0]) {
1004 if (r
->match_tag_not
)
1006 printf(" tagged %s", r
->match_tagname
);
1008 if (r
->rtableid
!= -1)
1009 printf(" rtable %u", r
->rtableid
);
1010 if (r
->divert
.port
) {
1011 if (PF_AZERO(&r
->divert
.addr
, r
->af
)) {
1012 printf(" divert-reply");
1014 /* XXX cut&paste from print_addr */
1017 printf(" divert-to ");
1018 if (inet_ntop(r
->af
, &r
->divert
.addr
, buf
,
1019 sizeof(buf
)) == NULL
)
1023 printf(" port %u", ntohs(r
->divert
.port
));
1026 if (!anchor_call
[0] && (r
->action
== PF_NAT
||
1027 r
->action
== PF_BINAT
|| r
->action
== PF_RDR
)) {
1029 print_pool(&r
->rpool
, r
->rpool
.proxy_port
[0],
1030 r
->rpool
.proxy_port
[1], r
->af
, r
->action
);
1035 print_tabledef(const char *name
, int flags
, int addrs
,
1036 struct node_tinithead
*nodes
)
1038 struct node_tinit
*ti
, *nti
;
1039 struct node_host
*h
;
1041 printf("table <%s>", name
);
1042 if (flags
& PFR_TFLAG_CONST
)
1044 if (flags
& PFR_TFLAG_PERSIST
)
1046 if (flags
& PFR_TFLAG_COUNTERS
)
1047 printf(" counters");
1048 SIMPLEQ_FOREACH(ti
, nodes
, entries
) {
1050 printf(" file \"%s\"", ti
->file
);
1055 for (h
= ti
->host
; h
!= NULL
; h
= h
->next
) {
1056 printf(h
->not ? " !" : " ");
1057 print_addr(&h
->addr
, h
->af
, 0);
1059 nti
= SIMPLEQ_NEXT(ti
, entries
);
1060 if (nti
!= NULL
&& nti
->file
== NULL
)
1061 ti
= nti
; /* merge lists */
1067 if (addrs
&& SIMPLEQ_EMPTY(nodes
))
1073 parse_flags(const char *s
)
1078 for (p
= s
; *p
; p
++) {
1079 if ((q
= strchr(tcpflags
, *p
)) == NULL
)
1082 f
|= 1 << (q
- tcpflags
);
1084 return (f
? f
: PF_TH_ALL
);
1088 set_ipmask(struct node_host
*h
, u_int8_t b
)
1090 struct pf_addr
*m
, *n
;
1093 m
= &h
->addr
.v
.a
.mask
;
1094 memset(m
, 0, sizeof(*m
));
1097 m
->addr32
[j
++] = 0xffffffff;
1100 for (i
= 31; i
> 31-b
; --i
)
1101 m
->addr32
[j
] |= (1 << i
);
1103 m
->addr32
[j
] = htonl(m
->addr32
[j
]);
1105 /* Mask off bits of the address that will never be used. */
1106 n
= &h
->addr
.v
.a
.addr
;
1107 if (h
->addr
.type
== PF_ADDR_ADDRMASK
)
1108 for (i
= 0; i
< 4; i
++)
1109 n
->addr32
[i
] = n
->addr32
[i
] & m
->addr32
[i
];
1113 check_netmask(struct node_host
*h
, sa_family_t af
)
1115 struct node_host
*n
= NULL
;
1118 for (n
= h
; n
!= NULL
; n
= n
->next
) {
1119 if (h
->addr
.type
== PF_ADDR_TABLE
)
1121 m
= &h
->addr
.v
.a
.mask
;
1122 /* fix up netmask for dynaddr */
1123 if (af
== AF_INET
&& h
->addr
.type
== PF_ADDR_DYNIFTL
&&
1124 unmask(m
, AF_INET6
) > 32)
1126 /* netmasks > 32 bit are invalid on v4 */
1127 if (af
== AF_INET
&&
1128 (m
->addr32
[1] || m
->addr32
[2] || m
->addr32
[3])) {
1129 fprintf(stderr
, "netmask %u invalid for IPv4 address\n",
1130 unmask(m
, AF_INET6
));
1137 /* interface lookup routines */
1139 struct node_host
*iftab
;
1144 struct ifaddrs
*ifap
, *ifa
;
1145 struct node_host
*n
= NULL
, *h
= NULL
;
1147 if (getifaddrs(&ifap
) < 0)
1148 err(1, "getifaddrs");
1150 for (ifa
= ifap
; ifa
; ifa
= ifa
->ifa_next
) {
1151 if (!(ifa
->ifa_addr
->sa_family
== AF_INET
||
1152 ifa
->ifa_addr
->sa_family
== AF_INET6
||
1153 ifa
->ifa_addr
->sa_family
== AF_LINK
))
1155 n
= calloc(1, sizeof(struct node_host
));
1157 err(1, "address: calloc");
1158 n
->af
= ifa
->ifa_addr
->sa_family
;
1159 n
->ifa_flags
= ifa
->ifa_flags
;
1161 if (n
->af
== AF_INET6
&&
1162 IN6_IS_ADDR_LINKLOCAL(&((struct sockaddr_in6
*)
1163 ifa
->ifa_addr
)->sin6_addr
) &&
1164 ((struct sockaddr_in6
*)ifa
->ifa_addr
)->sin6_scope_id
==
1166 struct sockaddr_in6
*sin6
;
1168 sin6
= (struct sockaddr_in6
*)ifa
->ifa_addr
;
1169 sin6
->sin6_scope_id
= sin6
->sin6_addr
.s6_addr
[2] << 8 |
1170 sin6
->sin6_addr
.s6_addr
[3];
1171 sin6
->sin6_addr
.s6_addr
[2] = 0;
1172 sin6
->sin6_addr
.s6_addr
[3] = 0;
1176 if (n
->af
== AF_INET
) {
1177 memcpy(&n
->addr
.v
.a
.addr
, &((struct sockaddr_in
*)
1178 ifa
->ifa_addr
)->sin_addr
.s_addr
,
1179 sizeof(struct in_addr
));
1180 memcpy(&n
->addr
.v
.a
.mask
, &((struct sockaddr_in
*)
1181 ifa
->ifa_netmask
)->sin_addr
.s_addr
,
1182 sizeof(struct in_addr
));
1183 if (ifa
->ifa_broadaddr
!= NULL
)
1184 memcpy(&n
->bcast
, &((struct sockaddr_in
*)
1185 ifa
->ifa_broadaddr
)->sin_addr
.s_addr
,
1186 sizeof(struct in_addr
));
1187 if (ifa
->ifa_dstaddr
!= NULL
)
1188 memcpy(&n
->peer
, &((struct sockaddr_in
*)
1189 ifa
->ifa_dstaddr
)->sin_addr
.s_addr
,
1190 sizeof(struct in_addr
));
1191 } else if (n
->af
== AF_INET6
) {
1192 memcpy(&n
->addr
.v
.a
.addr
, &((struct sockaddr_in6
*)
1193 ifa
->ifa_addr
)->sin6_addr
.s6_addr
,
1194 sizeof(struct in6_addr
));
1195 memcpy(&n
->addr
.v
.a
.mask
, &((struct sockaddr_in6
*)
1196 ifa
->ifa_netmask
)->sin6_addr
.s6_addr
,
1197 sizeof(struct in6_addr
));
1198 if (ifa
->ifa_broadaddr
!= NULL
)
1199 memcpy(&n
->bcast
, &((struct sockaddr_in6
*)
1200 ifa
->ifa_broadaddr
)->sin6_addr
.s6_addr
,
1201 sizeof(struct in6_addr
));
1202 if (ifa
->ifa_dstaddr
!= NULL
)
1203 memcpy(&n
->peer
, &((struct sockaddr_in6
*)
1204 ifa
->ifa_dstaddr
)->sin6_addr
.s6_addr
,
1205 sizeof(struct in6_addr
));
1206 n
->ifindex
= ((struct sockaddr_in6
*)
1207 ifa
->ifa_addr
)->sin6_scope_id
;
1209 if ((n
->ifname
= strdup(ifa
->ifa_name
)) == NULL
)
1210 err(1, "ifa_load: strdup");
1226 ifa_exists(const char *ifa_name
)
1228 struct node_host
*n
;
1229 struct ifgroupreq ifgr
;
1235 /* check wether this is a group */
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
)
1251 for (n
= iftab
; n
; n
= n
->next
) {
1252 if (n
->af
== AF_LINK
&& !strncmp(n
->ifname
, ifa_name
, IFNAMSIZ
))
1260 ifa_grouplookup(const char *ifa_name
, int flags
)
1262 struct ifg_req
*ifg
;
1263 struct ifgroupreq ifgr
;
1266 struct node_host
*n
, *h
= NULL
;
1268 if ((s
= socket(AF_INET
, SOCK_DGRAM
, 0)) == -1)
1270 bzero(&ifgr
, sizeof(ifgr
));
1271 strlcpy(ifgr
.ifgr_name
, ifa_name
, sizeof(ifgr
.ifgr_name
));
1272 if (ioctl(s
, SIOCGIFGMEMB
, (caddr_t
)&ifgr
) == -1) {
1277 len
= ifgr
.ifgr_len
;
1278 if ((ifgr
.ifgr_groups
= calloc(1, len
)) == NULL
)
1280 if (ioctl(s
, SIOCGIFGMEMB
, (caddr_t
)&ifgr
) == -1)
1281 err(1, "SIOCGIFGMEMB");
1283 for (ifg
= ifgr
.ifgr_groups
; ifg
&& len
>= sizeof(struct ifg_req
);
1285 len
-= sizeof(struct ifg_req
);
1286 if ((n
= ifa_lookup(ifg
->ifgrq_member
, flags
)) == NULL
)
1295 free(ifgr
.ifgr_groups
);
1302 ifa_lookup(const char *ifa_name
, int flags
)
1304 struct node_host
*p
= NULL
, *h
= NULL
, *n
= NULL
;
1305 int got4
= 0, got6
= 0;
1306 const char *last_if
= NULL
;
1308 if ((h
= ifa_grouplookup(ifa_name
, flags
)) != NULL
)
1311 if (!strncmp(ifa_name
, "self", IFNAMSIZ
))
1317 for (p
= iftab
; p
; p
= p
->next
) {
1318 if (ifa_skip_if(ifa_name
, p
))
1320 if ((flags
& PFI_AFLAG_BROADCAST
) && p
->af
!= AF_INET
)
1322 if ((flags
& PFI_AFLAG_BROADCAST
) &&
1323 !(p
->ifa_flags
& IFF_BROADCAST
))
1325 if ((flags
& PFI_AFLAG_PEER
) &&
1326 !(p
->ifa_flags
& IFF_POINTOPOINT
))
1328 if ((flags
& PFI_AFLAG_NETWORK
) && p
->ifindex
> 0)
1330 if (last_if
== NULL
|| strcmp(last_if
, p
->ifname
))
1332 last_if
= p
->ifname
;
1333 if ((flags
& PFI_AFLAG_NOALIAS
) && p
->af
== AF_INET
&& got4
)
1335 if ((flags
& PFI_AFLAG_NOALIAS
) && p
->af
== AF_INET6
&& got6
)
1337 if (p
->af
== AF_INET
)
1341 n
= calloc(1, sizeof(struct node_host
));
1343 err(1, "address: calloc");
1345 if (flags
& PFI_AFLAG_BROADCAST
)
1346 memcpy(&n
->addr
.v
.a
.addr
, &p
->bcast
,
1347 sizeof(struct pf_addr
));
1348 else if (flags
& PFI_AFLAG_PEER
)
1349 memcpy(&n
->addr
.v
.a
.addr
, &p
->peer
,
1350 sizeof(struct pf_addr
));
1352 memcpy(&n
->addr
.v
.a
.addr
, &p
->addr
.v
.a
.addr
,
1353 sizeof(struct pf_addr
));
1354 if (flags
& PFI_AFLAG_NETWORK
)
1355 set_ipmask(n
, unmask(&p
->addr
.v
.a
.mask
, n
->af
));
1357 if (n
->af
== AF_INET
) {
1358 if (p
->ifa_flags
& IFF_LOOPBACK
&&
1359 p
->ifa_flags
& IFF_LINK1
)
1360 memcpy(&n
->addr
.v
.a
.mask
,
1362 sizeof(struct pf_addr
));
1368 n
->ifindex
= p
->ifindex
;
1383 ifa_skip_if(const char *filter
, struct node_host
*p
)
1387 if (p
->af
!= AF_INET
&& p
->af
!= AF_INET6
)
1389 if (filter
== NULL
|| !*filter
)
1391 if (!strcmp(p
->ifname
, filter
))
1392 return (0); /* exact match */
1394 if (n
< 1 || n
>= IFNAMSIZ
)
1395 return (1); /* sanity check */
1396 if (filter
[n
-1] >= '0' && filter
[n
-1] <= '9')
1397 return (1); /* only do exact match in that case */
1398 if (strncmp(p
->ifname
, filter
, n
))
1399 return (1); /* prefix doesn't match */
1400 return (p
->ifname
[n
] < '0' || p
->ifname
[n
] > '9');
1407 struct node_host
*h
= NULL
;
1408 int mask
, v4mask
, v6mask
, cont
= 1;
1411 if ((p
= strrchr(s
, '/')) != NULL
) {
1412 mask
= strtol(p
+1, &q
, 0);
1413 if (!q
|| *q
|| mask
> 128 || q
== (p
+1)) {
1414 fprintf(stderr
, "invalid netmask '%s'\n", p
);
1417 if ((ps
= malloc(strlen(s
) - strlen(p
) + 1)) == NULL
)
1418 err(1, "host: malloc");
1419 strlcpy(ps
, s
, strlen(s
) - strlen(p
) + 1);
1420 v4mask
= v6mask
= mask
;
1422 if ((ps
= strdup(s
)) == NULL
)
1423 err(1, "host: strdup");
1429 /* interface with this name exists? */
1430 if (cont
&& (h
= host_if(ps
, mask
)) != NULL
)
1434 if (cont
&& (h
= host_v4(s
)) != NULL
)
1438 if (cont
&& (h
= host_v6(ps
, v6mask
)) != NULL
)
1442 if (cont
&& (h
= host_dns(ps
, v4mask
, v6mask
)) != NULL
)
1446 if (h
== NULL
|| cont
== 1) {
1447 fprintf(stderr
, "no IP address found for %s\n", s
);
1454 host_if(const char *s
, int mask
)
1456 struct node_host
*n
, *h
= NULL
;
1460 if ((ps
= strdup(s
)) == NULL
)
1461 err(1, "host_if: strdup");
1462 while ((p
= strrchr(ps
, ':')) != NULL
) {
1463 if (!strcmp(p
+1, "network"))
1464 flags
|= PFI_AFLAG_NETWORK
;
1465 else if (!strcmp(p
+1, "broadcast"))
1466 flags
|= PFI_AFLAG_BROADCAST
;
1467 else if (!strcmp(p
+1, "peer"))
1468 flags
|= PFI_AFLAG_PEER
;
1469 else if (!strcmp(p
+1, "0"))
1470 flags
|= PFI_AFLAG_NOALIAS
;
1477 if (flags
& (flags
- 1) & PFI_AFLAG_MODEMASK
) { /* Yep! */
1478 fprintf(stderr
, "illegal combination of interface modifiers\n");
1482 if ((flags
& (PFI_AFLAG_NETWORK
|PFI_AFLAG_BROADCAST
)) && mask
> -1) {
1483 fprintf(stderr
, "network or broadcast lookup, but "
1484 "extra netmask given\n");
1488 if (ifa_exists(ps
) || !strncmp(ps
, "self", IFNAMSIZ
)) {
1489 /* interface with this name exists */
1490 h
= ifa_lookup(ps
, flags
);
1491 for (n
= h
; n
!= NULL
&& mask
> -1; n
= n
->next
)
1492 set_ipmask(n
, mask
);
1499 static struct node_host
*
1500 host_v4(const char *s
)
1502 struct node_host
*h
= NULL
;
1506 memset(&ina
, 0, sizeof(struct in_addr
));
1507 if (strrchr(s
, '/') != NULL
) {
1508 if ((bits
= inet_net_pton(AF_INET
, s
, &ina
, sizeof(ina
))) == -1)
1511 if (inet_pton(AF_INET
, s
, &ina
) != 1)
1515 h
= calloc(1, sizeof(struct node_host
));
1517 err(1, "address: calloc");
1520 h
->addr
.v
.a
.addr
.addr32
[0] = ina
.s_addr
;
1521 set_ipmask(h
, bits
);
1529 host_v6(const char *s
, int mask
)
1531 struct addrinfo hints
, *res
;
1532 struct node_host
*h
= NULL
;
1534 memset(&hints
, 0, sizeof(hints
));
1535 hints
.ai_family
= AF_INET6
;
1536 hints
.ai_socktype
= SOCK_DGRAM
; /*dummy*/
1537 hints
.ai_flags
= AI_NUMERICHOST
;
1538 if (getaddrinfo(s
, "0", &hints
, &res
) == 0) {
1539 h
= calloc(1, sizeof(struct node_host
));
1541 err(1, "address: calloc");
1544 memcpy(&h
->addr
.v
.a
.addr
,
1545 &((struct sockaddr_in6
*)res
->ai_addr
)->sin6_addr
,
1546 sizeof(h
->addr
.v
.a
.addr
));
1548 ((struct sockaddr_in6
*)res
->ai_addr
)->sin6_scope_id
;
1549 set_ipmask(h
, mask
);
1559 host_dns(const char *s
, int v4mask
, int v6mask
)
1561 struct addrinfo hints
, *res0
, *res
;
1562 struct node_host
*n
, *h
= NULL
;
1563 int error
, noalias
= 0;
1564 int got4
= 0, got6
= 0;
1567 if ((ps
= strdup(s
)) == NULL
)
1568 err(1, "host_dns: strdup");
1569 if ((p
= strrchr(ps
, ':')) != NULL
&& !strcmp(p
, ":0")) {
1573 memset(&hints
, 0, sizeof(hints
));
1574 hints
.ai_family
= PF_UNSPEC
;
1575 hints
.ai_socktype
= SOCK_STREAM
; /* DUMMY */
1576 error
= getaddrinfo(ps
, NULL
, &hints
, &res0
);
1582 for (res
= res0
; res
; res
= res
->ai_next
) {
1583 if (res
->ai_family
!= AF_INET
&&
1584 res
->ai_family
!= AF_INET6
)
1587 if (res
->ai_family
== AF_INET
) {
1597 n
= calloc(1, sizeof(struct node_host
));
1599 err(1, "host_dns: calloc");
1601 n
->af
= res
->ai_family
;
1602 if (res
->ai_family
== AF_INET
) {
1603 memcpy(&n
->addr
.v
.a
.addr
,
1604 &((struct sockaddr_in
*)
1605 res
->ai_addr
)->sin_addr
.s_addr
,
1606 sizeof(struct in_addr
));
1607 set_ipmask(n
, v4mask
);
1609 memcpy(&n
->addr
.v
.a
.addr
,
1610 &((struct sockaddr_in6
*)
1611 res
->ai_addr
)->sin6_addr
.s6_addr
,
1612 sizeof(struct in6_addr
));
1614 ((struct sockaddr_in6
*)
1615 res
->ai_addr
)->sin6_scope_id
;
1616 set_ipmask(n
, v6mask
);
1634 * convert a hostname to a list of addresses and put them in the given buffer.
1636 * if set to 1, only simple addresses are accepted (no netblock, no "!").
1639 append_addr(struct pfr_buffer
*b
, char *s
, int test
)
1642 struct node_host
*h
, *n
;
1645 for (r
= s
; *r
== '!'; r
++)
1647 if ((n
= host(r
)) == NULL
) {
1651 rv
= append_addr_host(b
, n
, test
, not);
1656 } while (n
!= NULL
);
1661 * same as previous function, but with a pre-parsed input and the ability
1662 * to "negate" the result. Does not free the node_host list.
1664 * setting it to 1 is equivalent to adding "!" in front of parameter s.
1667 append_addr_host(struct pfr_buffer
*b
, struct node_host
*n
, int test
, int not)
1670 struct pfr_addr addr
;
1673 bzero(&addr
, sizeof(addr
));
1674 addr
.pfra_not
= n
->not ^ not;
1675 addr
.pfra_af
= n
->af
;
1676 addr
.pfra_net
= unmask(&n
->addr
.v
.a
.mask
, n
->af
);
1679 addr
.pfra_ip4addr
.s_addr
= n
->addr
.v
.a
.addr
.addr32
[0];
1683 memcpy(&addr
.pfra_ip6addr
, &n
->addr
.v
.a
.addr
.v6
,
1684 sizeof(struct in6_addr
));
1691 if ((test
&& (not || addr
.pfra_net
!= bits
)) ||
1692 addr
.pfra_net
> bits
) {
1696 if (pfr_buf_add(b
, &addr
))
1698 } while ((n
= n
->next
) != NULL
);
1704 pfctl_add_trans(struct pfr_buffer
*buf
, int rs_num
, const char *anchor
)
1706 struct pfioc_trans_e trans
;
1708 bzero(&trans
, sizeof(trans
));
1709 trans
.rs_num
= rs_num
;
1710 if (strlcpy(trans
.anchor
, anchor
,
1711 sizeof(trans
.anchor
)) >= sizeof(trans
.anchor
))
1712 errx(1, "pfctl_add_trans: strlcpy");
1714 return pfr_buf_add(buf
, &trans
);
1718 pfctl_get_ticket(struct pfr_buffer
*buf
, int rs_num
, const char *anchor
)
1720 const struct pfioc_trans_e
*p
;
1722 PFRB_FOREACH(p
, buf
)
1723 if (rs_num
== p
->rs_num
&& !strcmp(anchor
, p
->anchor
))
1725 errx(1, "pfctl_get_ticket: assertion failed");
1729 pfctl_trans(int dev
, struct pfr_buffer
*buf
, u_long cmd
, int from
)
1731 struct pfioc_trans trans
;
1733 bzero(&trans
, sizeof(trans
));
1734 trans
.size
= buf
->pfrb_size
- from
;
1735 trans
.esize
= sizeof(struct pfioc_trans_e
);
1736 trans
.array
= ((struct pfioc_trans_e
*)buf
->pfrb_caddr
) + from
;
1737 return ioctl(dev
, cmd
, &trans
);