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.
34 #include <sys/types.h>
35 #include <sys/ioctl.h>
36 #include <sys/socket.h>
37 #include <sys/param.h>
39 #include <netinet/in.h>
40 #include <netinet/in_systm.h>
41 #include <netinet/ip.h>
42 #include <netinet/ip_icmp.h>
43 #include <netinet/icmp6.h>
44 #include <net/pf/pfvar.h>
45 #include <arpa/inet.h>
58 #include "pfctl_parser.h"
61 void print_op (u_int8_t
, const char *, const char *);
62 void print_port (u_int8_t
, u_int16_t
, u_int16_t
, const char *);
63 void print_ugid (u_int8_t
, unsigned, unsigned, const char *, unsigned);
64 void print_flags (u_int8_t
);
65 void print_fromto(struct pf_rule_addr
*, pf_osfp_t
,
66 struct pf_rule_addr
*, u_int8_t
, u_int8_t
, int);
67 int ifa_skip_if(const char *filter
, struct node_host
*p
);
69 struct node_host
*ifa_grouplookup(const char *, int);
70 struct node_host
*host_if(const char *, int);
71 static struct node_host
*host_v4(const char *);
72 struct node_host
*host_v6(const char *, int);
73 struct node_host
*host_dns(const char *, int, int);
75 const char *tcpflags
= "FSRPAUEW";
77 static const struct icmptypeent icmp_type
[] = {
78 { "echoreq", ICMP_ECHO
},
79 { "echorep", ICMP_ECHOREPLY
},
80 { "unreach", ICMP_UNREACH
},
81 { "squench", ICMP_SOURCEQUENCH
},
82 { "redir", ICMP_REDIRECT
},
83 { "althost", ICMP_ALTHOSTADDR
},
84 { "routeradv", ICMP_ROUTERADVERT
},
85 { "routersol", ICMP_ROUTERSOLICIT
},
86 { "timex", ICMP_TIMXCEED
},
87 { "paramprob", ICMP_PARAMPROB
},
88 { "timereq", ICMP_TSTAMP
},
89 { "timerep", ICMP_TSTAMPREPLY
},
90 { "inforeq", ICMP_IREQ
},
91 { "inforep", ICMP_IREQREPLY
},
92 { "maskreq", ICMP_MASKREQ
},
93 { "maskrep", ICMP_MASKREPLY
},
94 { "trace", ICMP_TRACEROUTE
},
95 { "dataconv", ICMP_DATACONVERR
},
96 { "mobredir", ICMP_MOBILE_REDIRECT
},
97 { "ipv6-where", ICMP_IPV6_WHEREAREYOU
},
98 { "ipv6-here", ICMP_IPV6_IAMHERE
},
99 { "mobregreq", ICMP_MOBILE_REGREQUEST
},
100 { "mobregrep", ICMP_MOBILE_REGREPLY
},
101 { "skip", ICMP_SKIP
},
102 { "photuris", ICMP_PHOTURIS
}
105 static const struct icmptypeent icmp6_type
[] = {
106 { "unreach", ICMP6_DST_UNREACH
},
107 { "toobig", ICMP6_PACKET_TOO_BIG
},
108 { "timex", ICMP6_TIME_EXCEEDED
},
109 { "paramprob", ICMP6_PARAM_PROB
},
110 { "echoreq", ICMP6_ECHO_REQUEST
},
111 { "echorep", ICMP6_ECHO_REPLY
},
112 { "groupqry", ICMP6_MEMBERSHIP_QUERY
},
113 { "listqry", MLD_LISTENER_QUERY
},
114 { "grouprep", ICMP6_MEMBERSHIP_REPORT
},
115 { "listenrep", MLD_LISTENER_REPORT
},
116 { "groupterm", ICMP6_MEMBERSHIP_REDUCTION
},
117 { "listendone", MLD_LISTENER_DONE
},
118 { "routersol", ND_ROUTER_SOLICIT
},
119 { "routeradv", ND_ROUTER_ADVERT
},
120 { "neighbrsol", ND_NEIGHBOR_SOLICIT
},
121 { "neighbradv", ND_NEIGHBOR_ADVERT
},
122 { "redir", ND_REDIRECT
},
123 { "routrrenum", ICMP6_ROUTER_RENUMBERING
},
124 { "wrureq", ICMP6_WRUREQUEST
},
125 { "wrurep", ICMP6_WRUREPLY
},
126 { "fqdnreq", ICMP6_FQDN_QUERY
},
127 { "fqdnrep", ICMP6_FQDN_REPLY
},
128 { "niqry", ICMP6_NI_QUERY
},
129 { "nirep", ICMP6_NI_REPLY
},
130 { "mtraceresp", MLD_MTRACE_RESP
},
131 { "mtrace", MLD_MTRACE
}
134 static const struct icmpcodeent icmp_code
[] = {
135 { "net-unr", ICMP_UNREACH
, ICMP_UNREACH_NET
},
136 { "host-unr", ICMP_UNREACH
, ICMP_UNREACH_HOST
},
137 { "proto-unr", ICMP_UNREACH
, ICMP_UNREACH_PROTOCOL
},
138 { "port-unr", ICMP_UNREACH
, ICMP_UNREACH_PORT
},
139 { "needfrag", ICMP_UNREACH
, ICMP_UNREACH_NEEDFRAG
},
140 { "srcfail", ICMP_UNREACH
, ICMP_UNREACH_SRCFAIL
},
141 { "net-unk", ICMP_UNREACH
, ICMP_UNREACH_NET_UNKNOWN
},
142 { "host-unk", ICMP_UNREACH
, ICMP_UNREACH_HOST_UNKNOWN
},
143 { "isolate", ICMP_UNREACH
, ICMP_UNREACH_ISOLATED
},
144 { "net-prohib", ICMP_UNREACH
, ICMP_UNREACH_NET_PROHIB
},
145 { "host-prohib", ICMP_UNREACH
, ICMP_UNREACH_HOST_PROHIB
},
146 { "net-tos", ICMP_UNREACH
, ICMP_UNREACH_TOSNET
},
147 { "host-tos", ICMP_UNREACH
, ICMP_UNREACH_TOSHOST
},
148 { "filter-prohib", ICMP_UNREACH
, ICMP_UNREACH_FILTER_PROHIB
},
149 { "host-preced", ICMP_UNREACH
, ICMP_UNREACH_HOST_PRECEDENCE
},
150 { "cutoff-preced", ICMP_UNREACH
, ICMP_UNREACH_PRECEDENCE_CUTOFF
},
151 { "redir-net", ICMP_REDIRECT
, ICMP_REDIRECT_NET
},
152 { "redir-host", ICMP_REDIRECT
, ICMP_REDIRECT_HOST
},
153 { "redir-tos-net", ICMP_REDIRECT
, ICMP_REDIRECT_TOSNET
},
154 { "redir-tos-host", ICMP_REDIRECT
, ICMP_REDIRECT_TOSHOST
},
155 { "normal-adv", ICMP_ROUTERADVERT
, ICMP_ROUTERADVERT_NORMAL
},
156 { "common-adv", ICMP_ROUTERADVERT
, ICMP_ROUTERADVERT_NOROUTE_COMMON
},
157 { "transit", ICMP_TIMXCEED
, ICMP_TIMXCEED_INTRANS
},
158 { "reassemb", ICMP_TIMXCEED
, ICMP_TIMXCEED_REASS
},
159 { "badhead", ICMP_PARAMPROB
, ICMP_PARAMPROB_ERRATPTR
},
160 { "optmiss", ICMP_PARAMPROB
, ICMP_PARAMPROB_OPTABSENT
},
161 { "badlen", ICMP_PARAMPROB
, ICMP_PARAMPROB_LENGTH
},
162 { "unknown-ind", ICMP_PHOTURIS
, ICMP_PHOTURIS_UNKNOWN_INDEX
},
163 { "auth-fail", ICMP_PHOTURIS
, ICMP_PHOTURIS_AUTH_FAILED
},
164 { "decrypt-fail", ICMP_PHOTURIS
, ICMP_PHOTURIS_DECRYPT_FAILED
}
167 static const struct icmpcodeent icmp6_code
[] = {
168 { "admin-unr", ICMP6_DST_UNREACH
, ICMP6_DST_UNREACH_ADMIN
},
169 { "noroute-unr", ICMP6_DST_UNREACH
, ICMP6_DST_UNREACH_NOROUTE
},
170 { "notnbr-unr", ICMP6_DST_UNREACH
, ICMP6_DST_UNREACH_NOTNEIGHBOR
},
171 { "beyond-unr", ICMP6_DST_UNREACH
, ICMP6_DST_UNREACH_BEYONDSCOPE
},
172 { "addr-unr", ICMP6_DST_UNREACH
, ICMP6_DST_UNREACH_ADDR
},
173 { "port-unr", ICMP6_DST_UNREACH
, ICMP6_DST_UNREACH_NOPORT
},
174 { "transit", ICMP6_TIME_EXCEEDED
, ICMP6_TIME_EXCEED_TRANSIT
},
175 { "reassemb", ICMP6_TIME_EXCEEDED
, ICMP6_TIME_EXCEED_REASSEMBLY
},
176 { "badhead", ICMP6_PARAM_PROB
, ICMP6_PARAMPROB_HEADER
},
177 { "nxthdr", ICMP6_PARAM_PROB
, ICMP6_PARAMPROB_NEXTHEADER
},
178 { "redironlink", ND_REDIRECT
, ND_REDIRECT_ONLINK
},
179 { "redirrouter", ND_REDIRECT
, ND_REDIRECT_ROUTER
}
182 const struct pf_timeout pf_timeouts
[] = {
183 { "tcp.first", PFTM_TCP_FIRST_PACKET
},
184 { "tcp.opening", PFTM_TCP_OPENING
},
185 { "tcp.established", PFTM_TCP_ESTABLISHED
},
186 { "tcp.closing", PFTM_TCP_CLOSING
},
187 { "tcp.finwait", PFTM_TCP_FIN_WAIT
},
188 { "tcp.closed", PFTM_TCP_CLOSED
},
189 { "tcp.tsdiff", PFTM_TS_DIFF
},
190 { "udp.first", PFTM_UDP_FIRST_PACKET
},
191 { "udp.single", PFTM_UDP_SINGLE
},
192 { "udp.multiple", PFTM_UDP_MULTIPLE
},
193 { "icmp.first", PFTM_ICMP_FIRST_PACKET
},
194 { "icmp.error", PFTM_ICMP_ERROR_REPLY
},
195 { "other.first", PFTM_OTHER_FIRST_PACKET
},
196 { "other.single", PFTM_OTHER_SINGLE
},
197 { "other.multiple", PFTM_OTHER_MULTIPLE
},
198 { "frag", PFTM_FRAG
},
199 { "interval", PFTM_INTERVAL
},
200 { "adaptive.start", PFTM_ADAPTIVE_START
},
201 { "adaptive.end", PFTM_ADAPTIVE_END
},
202 { "src.track", PFTM_SRC_NODE
},
206 const struct icmptypeent
*
207 geticmptypebynumber(u_int8_t type
, sa_family_t af
)
211 if (af
!= AF_INET6
) {
212 for (i
=0; i
< NELEM(icmp_type
); i
++) {
213 if (type
== icmp_type
[i
].type
)
214 return (&icmp_type
[i
]);
217 for (i
=0; i
< NELEM(icmp6_type
); i
++) {
218 if (type
== icmp6_type
[i
].type
)
219 return (&icmp6_type
[i
]);
225 const struct icmptypeent
*
226 geticmptypebyname(char *w
, sa_family_t af
)
230 if (af
!= AF_INET6
) {
231 for (i
=0; i
< NELEM(icmp_type
); i
++) {
232 if (!strcmp(w
, icmp_type
[i
].name
))
233 return (&icmp_type
[i
]);
236 for (i
=0; i
< NELEM(icmp6_type
); i
++) {
237 if (!strcmp(w
, icmp6_type
[i
].name
))
238 return (&icmp6_type
[i
]);
244 const struct icmpcodeent
*
245 geticmpcodebynumber(u_int8_t type
, u_int8_t code
, sa_family_t af
)
249 if (af
!= AF_INET6
) {
250 for (i
=0; i
< NELEM(icmp_code
); i
++) {
251 if (type
== icmp_code
[i
].type
&&
252 code
== icmp_code
[i
].code
)
253 return (&icmp_code
[i
]);
256 for (i
=0; i
< NELEM(icmp6_code
); i
++) {
257 if (type
== icmp6_code
[i
].type
&&
258 code
== icmp6_code
[i
].code
)
259 return (&icmp6_code
[i
]);
265 const struct icmpcodeent
*
266 geticmpcodebyname(u_long type
, char *w
, sa_family_t af
)
270 if (af
!= AF_INET6
) {
271 for (i
=0; i
< NELEM(icmp_code
); i
++) {
272 if (type
== icmp_code
[i
].type
&&
273 !strcmp(w
, icmp_code
[i
].name
))
274 return (&icmp_code
[i
]);
277 for (i
=0; i
< NELEM(icmp6_code
); i
++) {
278 if (type
== icmp6_code
[i
].type
&&
279 !strcmp(w
, icmp6_code
[i
].name
))
280 return (&icmp6_code
[i
]);
287 print_op(u_int8_t op
, const char *a1
, const char *a2
)
290 printf(" %s >< %s", a1
, a2
);
291 else if (op
== PF_OP_XRG
)
292 printf(" %s <> %s", a1
, a2
);
293 else if (op
== PF_OP_EQ
)
295 else if (op
== PF_OP_NE
)
296 printf(" != %s", a1
);
297 else if (op
== PF_OP_LT
)
299 else if (op
== PF_OP_LE
)
300 printf(" <= %s", a1
);
301 else if (op
== PF_OP_GT
)
303 else if (op
== PF_OP_GE
)
304 printf(" >= %s", a1
);
305 else if (op
== PF_OP_RRG
)
306 printf(" %s:%s", a1
, a2
);
310 print_port(u_int8_t op
, u_int16_t p1
, u_int16_t p2
, const char *proto
)
315 s
= getservbyport(p1
, proto
);
318 snprintf(a1
, sizeof(a1
), "%u", p1
);
319 snprintf(a2
, sizeof(a2
), "%u", p2
);
321 if (s
!= NULL
&& (op
== PF_OP_EQ
|| op
== PF_OP_NE
))
322 print_op(op
, s
->s_name
, a2
);
324 print_op(op
, a1
, a2
);
328 print_ugid(u_int8_t op
, unsigned u1
, unsigned u2
, const char *t
, unsigned umax
)
332 snprintf(a1
, sizeof(a1
), "%u", u1
);
333 snprintf(a2
, sizeof(a2
), "%u", u2
);
335 if (u1
== umax
&& (op
== PF_OP_EQ
|| op
== PF_OP_NE
))
336 print_op(op
, "unknown", a2
);
338 print_op(op
, a1
, a2
);
342 print_flags(u_int8_t f
)
346 for (i
= 0; tcpflags
[i
]; ++i
)
348 printf("%c", tcpflags
[i
]);
352 print_fromto(struct pf_rule_addr
*src
, pf_osfp_t osfp
, struct pf_rule_addr
*dst
,
353 sa_family_t af
, u_int8_t proto
, int verbose
)
355 char buf
[PF_OSFP_LEN
*3];
356 if (src
->addr
.type
== PF_ADDR_ADDRMASK
&&
357 dst
->addr
.type
== PF_ADDR_ADDRMASK
&&
358 PF_AZERO(&src
->addr
.v
.a
.addr
, AF_INET6
) &&
359 PF_AZERO(&src
->addr
.v
.a
.mask
, AF_INET6
) &&
360 PF_AZERO(&dst
->addr
.v
.a
.addr
, AF_INET6
) &&
361 PF_AZERO(&dst
->addr
.v
.a
.mask
, AF_INET6
) &&
362 !src
->neg
&& !dst
->neg
&&
363 !src
->port_op
&& !dst
->port_op
&&
370 print_addr(&src
->addr
, af
, verbose
);
372 print_port(src
->port_op
, src
->port
[0],
374 proto
== IPPROTO_TCP
? "tcp" : "udp");
375 if (osfp
!= PF_OSFP_ANY
)
376 printf(" os \"%s\"", pfctl_lookup_fingerprint(osfp
, buf
,
382 print_addr(&dst
->addr
, af
, verbose
);
384 print_port(dst
->port_op
, dst
->port
[0],
386 proto
== IPPROTO_TCP
? "tcp" : "udp");
391 print_pool(struct pf_pool
*pool
, u_int16_t p1
, u_int16_t p2
,
392 sa_family_t af
, int id
)
394 struct pf_pooladdr
*pooladdr
;
396 if ((TAILQ_FIRST(&pool
->list
) != NULL
) &&
397 TAILQ_NEXT(TAILQ_FIRST(&pool
->list
), entries
) != NULL
)
399 TAILQ_FOREACH(pooladdr
, &pool
->list
, entries
){
404 print_addr(&pooladdr
->addr
, af
, 0);
407 if (PF_AZERO(&pooladdr
->addr
.v
.a
.addr
, af
))
408 printf("%s", pooladdr
->ifname
);
410 printf("(%s ", pooladdr
->ifname
);
411 print_addr(&pooladdr
->addr
, af
, 0);
418 if (TAILQ_NEXT(pooladdr
, entries
) != NULL
)
420 else if (TAILQ_NEXT(TAILQ_FIRST(&pool
->list
), entries
) != NULL
)
425 if ((p1
!= PF_NAT_PROXY_PORT_LOW
||
426 p2
!= PF_NAT_PROXY_PORT_HIGH
) && (p1
!= 0 || p2
!= 0)) {
428 printf(" port %u", p1
);
430 printf(" port %u:%u", p1
, p2
);
435 printf(" port %u", p1
);
436 if (p2
&& (p2
!= p1
))
443 switch (pool
->opts
& PF_POOL_TYPEMASK
) {
446 case PF_POOL_BITMASK
:
452 case PF_POOL_SRCHASH
:
453 printf(" source-hash 0x%08x%08x%08x%08x",
454 pool
->key
.key32
[0], pool
->key
.key32
[1],
455 pool
->key
.key32
[2], pool
->key
.key32
[3]);
457 case PF_POOL_ROUNDROBIN
:
458 printf(" round-robin");
461 if (pool
->opts
& PF_POOL_STICKYADDR
)
462 printf(" sticky-address");
463 if (id
== PF_NAT
&& p1
== 0 && p2
== 0)
464 printf(" static-port");
467 const char *pf_reasons
[PFRES_MAX
+1] = PFRES_NAMES
;
468 const char *pf_lcounters
[LCNT_MAX
+1] = LCNT_NAMES
;
469 const char *pf_fcounters
[FCNT_MAX
+1] = FCNT_NAMES
;
470 const char *pf_scounters
[FCNT_MAX
+1] = FCNT_NAMES
;
473 print_status(struct pf_status
*s
, int opts
)
479 char buf
[PF_MD5_DIGEST_LENGTH
* 2 + 1];
480 static const char hex
[] = "0123456789abcdef";
482 runtime
= time(NULL
) - s
->since
;
483 running
= s
->running
? "Enabled" : "Disabled";
486 unsigned int sec
, min
, hrs
, day
= runtime
;
494 snprintf(statline
, sizeof(statline
),
495 "Status: %s for %u days %.2u:%.2u:%.2u",
496 running
, day
, hrs
, min
, sec
);
498 snprintf(statline
, sizeof(statline
), "Status: %s", running
);
499 printf("%-44s", statline
);
502 printf("%15s\n\n", "Debug: None");
504 case PF_DEBUG_URGENT
:
505 printf("%15s\n\n", "Debug: Urgent");
508 printf("%15s\n\n", "Debug: Misc");
511 printf("%15s\n\n", "Debug: Loud");
515 if (opts
& PF_OPT_VERBOSE
) {
516 printf("Hostid: 0x%08x\n", ntohl(s
->hostid
));
518 for (i
= 0; i
< PF_MD5_DIGEST_LENGTH
; i
++) {
519 buf
[i
+ i
] = hex
[s
->pf_chksum
[i
] >> 4];
520 buf
[i
+ i
+ 1] = hex
[s
->pf_chksum
[i
] & 0x0f];
523 printf("Checksum: 0x%s\n\n", buf
);
526 if (s
->ifname
[0] != 0) {
527 printf("Interface Stats for %-16s %5s %16s\n",
528 s
->ifname
, "IPv4", "IPv6");
529 printf(" %-25s %14llu %16llu\n", "Bytes In",
530 (unsigned long long)s
->bcounters
[0][0],
531 (unsigned long long)s
->bcounters
[1][0]);
532 printf(" %-25s %14llu %16llu\n", "Bytes Out",
533 (unsigned long long)s
->bcounters
[0][1],
534 (unsigned long long)s
->bcounters
[1][1]);
535 printf(" Packets In\n");
536 printf(" %-23s %14llu %16llu\n", "Passed",
537 (unsigned long long)s
->pcounters
[0][0][PF_PASS
],
538 (unsigned long long)s
->pcounters
[1][0][PF_PASS
]);
539 printf(" %-23s %14llu %16llu\n", "Blocked",
540 (unsigned long long)s
->pcounters
[0][0][PF_DROP
],
541 (unsigned long long)s
->pcounters
[1][0][PF_DROP
]);
542 printf(" Packets Out\n");
543 printf(" %-23s %14llu %16llu\n", "Passed",
544 (unsigned long long)s
->pcounters
[0][1][PF_PASS
],
545 (unsigned long long)s
->pcounters
[1][1][PF_PASS
]);
546 printf(" %-23s %14llu %16llu\n\n", "Blocked",
547 (unsigned long long)s
->pcounters
[0][1][PF_DROP
],
548 (unsigned long long)s
->pcounters
[1][1][PF_DROP
]);
550 printf("%-27s %14s %16s\n", "State Table", "Total", "Rate");
551 printf(" %-25s %14u %14s\n", "current entries", s
->states
, "");
552 for (i
= 0; i
< FCNT_MAX
; i
++) {
553 printf(" %-25s %14llu ", pf_fcounters
[i
],
554 (unsigned long long)s
->fcounters
[i
]);
557 (double)s
->fcounters
[i
] / (double)runtime
);
559 printf("%14s\n", "");
561 if (opts
& PF_OPT_VERBOSE
) {
562 printf("Source Tracking Table\n");
563 printf(" %-25s %14u %14s\n", "current entries",
565 for (i
= 0; i
< SCNT_MAX
; i
++) {
566 printf(" %-25s %14lld ", pf_scounters
[i
],
567 (unsigned long long)s
->scounters
[i
]);
570 (double)s
->scounters
[i
] / (double)runtime
);
572 printf("%14s\n", "");
575 printf("Counters\n");
576 for (i
= 0; i
< PFRES_MAX
; i
++) {
577 printf(" %-25s %14llu ", pf_reasons
[i
],
578 (unsigned long long)s
->counters
[i
]);
581 (double)s
->counters
[i
] / (double)runtime
);
583 printf("%14s\n", "");
585 if (opts
& PF_OPT_VERBOSE
) {
586 printf("Limit Counters\n");
587 for (i
= 0; i
< LCNT_MAX
; i
++) {
588 printf(" %-25s %14ju ", pf_lcounters
[i
],
589 (uintmax_t)s
->lcounters
[i
]);
592 (double)s
->lcounters
[i
] / (double)runtime
);
594 printf("%14s\n", "");
600 print_src_node(struct pf_src_node
*sn
, int opts
)
602 struct pf_addr_wrap aw
;
605 memset(&aw
, 0, sizeof(aw
));
606 if (sn
->af
== AF_INET
)
607 aw
.v
.a
.mask
.addr32
[0] = 0xffffffff;
609 memset(&aw
.v
.a
.mask
, 0xff, sizeof(aw
.v
.a
.mask
));
611 aw
.v
.a
.addr
= sn
->addr
;
612 print_addr(&aw
, sn
->af
, opts
& PF_OPT_VERBOSE2
);
614 aw
.v
.a
.addr
= sn
->raddr
;
615 print_addr(&aw
, sn
->af
, opts
& PF_OPT_VERBOSE2
);
616 printf(" ( states %u, connections %u, rate %u.%u/%us )\n", sn
->states
,
617 sn
->conn
, sn
->conn_rate
.count
/ 1000,
618 (sn
->conn_rate
.count
% 1000) / 100, sn
->conn_rate
.seconds
);
619 if (opts
& PF_OPT_VERBOSE
) {
620 sec
= sn
->creation
% 60;
622 min
= sn
->creation
% 60;
624 printf(" age %.2u:%.2u:%.2u", sn
->creation
, min
, sec
);
625 if (sn
->states
== 0) {
626 sec
= sn
->expire
% 60;
628 min
= sn
->expire
% 60;
630 printf(", expires in %.2u:%.2u:%.2u",
631 sn
->expire
, min
, sec
);
633 printf(", %ju pkts, %ju bytes",
634 (uintmax_t)sn
->packets
[0] + sn
->packets
[1],
635 (uintmax_t)sn
->bytes
[0] + sn
->bytes
[1]);
636 switch (sn
->ruletype
) {
638 if (sn
->rule
.nr
!= (uint32_t)(-1))
639 printf(", nat rule %u", sn
->rule
.nr
);
642 if (sn
->rule
.nr
!= (uint32_t)(-1))
643 printf(", rdr rule %u", sn
->rule
.nr
);
646 if (sn
->rule
.nr
!= (uint32_t)(-1))
647 printf(", filter rule %u", sn
->rule
.nr
);
655 print_rule(struct pf_rule
*r
, const char *anchor_call
, int verbose
)
657 static const char *actiontypes
[] = { "pass", "block", "scrub",
658 "no scrub", "nat", "no nat", "binat", "no binat", "rdr", "no rdr" };
659 static const char *anchortypes
[] = { "anchor", "anchor", "anchor",
660 "anchor", "nat-anchor", "nat-anchor", "binat-anchor",
661 "binat-anchor", "rdr-anchor", "rdr-anchor" };
665 printf("@%d ", r
->nr
);
666 if (r
->action
> PF_NORDR
)
667 printf("action(%d)", r
->action
);
668 else if (anchor_call
[0]) {
669 if (anchor_call
[0] == '_') {
670 printf("%s", anchortypes
[r
->action
]);
672 printf("%s \"%s\"", anchortypes
[r
->action
],
675 printf("%s", actiontypes
[r
->action
]);
679 if (r
->action
== PF_DROP
) {
680 if (r
->rule_flag
& PFRULE_RETURN
)
682 else if (r
->rule_flag
& PFRULE_RETURNRST
) {
684 printf(" return-rst");
686 printf(" return-rst(ttl %d)", r
->return_ttl
);
687 } else if (r
->rule_flag
& PFRULE_RETURNICMP
) {
688 const struct icmpcodeent
*ic
, *ic6
;
690 ic
= geticmpcodebynumber(r
->return_icmp
>> 8,
691 r
->return_icmp
& 255, AF_INET
);
692 ic6
= geticmpcodebynumber(r
->return_icmp6
>> 8,
693 r
->return_icmp6
& 255, AF_INET6
);
697 printf(" return-icmp");
699 printf("(%u)", r
->return_icmp
& 255);
701 printf("(%s)", ic
->name
);
704 printf(" return-icmp6");
706 printf("(%u)", r
->return_icmp6
& 255);
708 printf("(%s)", ic6
->name
);
711 printf(" return-icmp");
713 printf("(%u, ", r
->return_icmp
& 255);
715 printf("(%s, ", ic
->name
);
717 printf("%u)", r
->return_icmp6
& 255);
719 printf("%s)", ic6
->name
);
725 if (r
->direction
== PF_IN
)
727 else if (r
->direction
== PF_OUT
)
731 if (r
->log
& ~PF_LOG
|| r
->logif
) {
735 if (r
->log
& PF_LOG_ALL
)
736 printf("%sall", count
++ ? ", " : "");
737 if (r
->log
& PF_LOG_SOCKET_LOOKUP
)
738 printf("%suser", count
++ ? ", " : "");
740 printf("%sto pflog%u", count
++ ? ", " : "",
749 printf(" on ! %s", r
->ifname
);
751 printf(" on %s", r
->ifname
);
754 if (r
->rt
== PF_ROUTETO
)
756 else if (r
->rt
== PF_REPLYTO
)
758 else if (r
->rt
== PF_DUPTO
)
760 else if (r
->rt
== PF_FASTROUTE
)
761 printf(" fastroute");
762 if (r
->rt
!= PF_FASTROUTE
) {
764 print_pool(&r
->rpool
, 0, 0, r
->af
, PF_PASS
);
768 if (r
->af
== AF_INET
)
776 if ((p
= getprotobynumber(r
->proto
)) != NULL
)
777 printf(" proto %s", p
->p_name
);
779 printf(" proto %u", r
->proto
);
781 print_fromto(&r
->src
, r
->os_fingerprint
, &r
->dst
, r
->af
, r
->proto
,
784 print_ugid(r
->uid
.op
, r
->uid
.uid
[0], r
->uid
.uid
[1], "user",
787 print_ugid(r
->gid
.op
, r
->gid
.gid
[0], r
->gid
.gid
[1], "group",
789 if (r
->flags
|| r
->flagset
) {
791 print_flags(r
->flags
);
793 print_flags(r
->flagset
);
794 } else if (r
->action
== PF_PASS
&&
795 (!r
->proto
|| r
->proto
== IPPROTO_TCP
) &&
796 !(r
->rule_flag
& PFRULE_FRAGMENT
) &&
797 !anchor_call
[0] && r
->keep_state
)
798 printf(" flags any");
800 const struct icmptypeent
*it
;
802 it
= geticmptypebynumber(r
->type
-1, r
->af
);
803 if (r
->af
!= AF_INET6
)
804 printf(" icmp-type");
806 printf(" icmp6-type");
808 printf(" %s", it
->name
);
810 printf(" %u", r
->type
-1);
812 const struct icmpcodeent
*ic
;
814 ic
= geticmpcodebynumber(r
->type
-1, r
->code
-1, r
->af
);
816 printf(" code %s", ic
->name
);
818 printf(" code %u", r
->code
-1);
822 printf(" tos 0x%2.2x", r
->tos
);
823 if (!r
->keep_state
&& r
->action
== PF_PASS
&& !anchor_call
[0])
825 else if (r
->keep_state
== PF_STATE_NORMAL
)
826 printf(" keep state");
827 else if (r
->keep_state
== PF_STATE_MODULATE
)
828 printf(" modulate state");
829 else if (r
->keep_state
== PF_STATE_SYNPROXY
)
830 printf(" synproxy state");
834 snprintf(buf
, sizeof(buf
), "%f", r
->prob
*100.0/(UINT_MAX
+1.0));
835 for (i
= strlen(buf
)-1; i
> 0; i
--) {
844 printf(" probability %s%%", buf
);
847 if (r
->max_states
|| r
->max_src_nodes
|| r
->max_src_states
)
851 if (r
->rule_flag
& PFRULE_NOSYNC
)
853 if (r
->rule_flag
& PFRULE_SRCTRACK
)
855 if (r
->rule_flag
& PFRULE_IFBOUND
)
857 if (r
->rule_flag
& PFRULE_STATESLOPPY
)
859 for (i
= 0; !opts
&& i
< PFTM_MAX
; ++i
)
864 switch(r
->pickup_mode
) {
865 case PF_PICKUPS_UNSPECIFIED
:
867 case PF_PICKUPS_DISABLED
:
868 printf("no-pickups");
871 case PF_PICKUPS_HASHONLY
:
875 case PF_PICKUPS_ENABLED
:
880 printf("unknown-pickups-mode-%d", r
->pickup_mode
);
886 printf("max %u", r
->max_states
);
889 if (r
->rule_flag
& PFRULE_NOSYNC
) {
895 if (r
->rule_flag
& PFRULE_SRCTRACK
) {
898 printf("source-track");
899 if (r
->rule_flag
& PFRULE_RULESRCTRACK
)
905 if (r
->max_src_states
) {
908 printf("max-src-states %u", r
->max_src_states
);
911 if (r
->max_src_conn
) {
914 printf("max-src-conn %u", r
->max_src_conn
);
917 if (r
->max_src_conn_rate
.limit
) {
920 printf("max-src-conn-rate %u/%u",
921 r
->max_src_conn_rate
.limit
,
922 r
->max_src_conn_rate
.seconds
);
925 if (r
->max_src_nodes
) {
928 printf("max-src-nodes %u", r
->max_src_nodes
);
931 if (r
->overload_tblname
[0]) {
934 printf("overload <%s>", r
->overload_tblname
);
937 if (r
->flush
& PF_FLUSH_GLOBAL
)
940 if (r
->rule_flag
& PFRULE_IFBOUND
) {
946 if (r
->rule_flag
& PFRULE_STATESLOPPY
) {
952 for (i
= 0; i
< PFTM_MAX
; ++i
)
959 for (j
= 0; pf_timeouts
[j
].name
!= NULL
;
961 if (pf_timeouts
[j
].timeout
== i
)
963 printf("%s %u", pf_timeouts
[j
].name
== NULL
?
964 "inv.timeout" : pf_timeouts
[j
].name
,
969 if (r
->rule_flag
& PFRULE_FRAGMENT
)
971 if (r
->rule_flag
& PFRULE_NODF
)
973 if (r
->rule_flag
& PFRULE_RANDOMID
)
974 printf(" random-id");
976 printf(" min-ttl %d", r
->min_ttl
);
978 printf(" max-mss %d", r
->max_mss
);
979 if (r
->rule_flag
& PFRULE_SET_TOS
)
980 printf(" set-tos 0x%2.2x", r
->set_tos
);
982 printf(" allow-opts");
983 if (r
->action
== PF_SCRUB
) {
984 if (r
->rule_flag
& PFRULE_REASSEMBLE_TCP
)
985 printf(" reassemble tcp");
987 if (r
->rule_flag
& PFRULE_FRAGDROP
)
988 printf(" fragment drop-ovl");
989 else if (r
->rule_flag
& PFRULE_FRAGCROP
)
990 printf(" fragment crop");
992 printf(" fragment reassemble");
995 printf(" label \"%s\"", r
->label
);
996 if (r
->qname
[0] && r
->pqname
[0])
997 printf(" queue(%s, %s)", r
->qname
, r
->pqname
);
998 else if (r
->qname
[0])
999 printf(" queue %s", r
->qname
);
1001 printf(" tag %s", r
->tagname
);
1002 if (r
->match_tagname
[0]) {
1003 if (r
->match_tag_not
)
1005 printf(" tagged %s", r
->match_tagname
);
1007 if (r
->rtableid
!= -1)
1008 printf(" rtable %u", r
->rtableid
);
1009 if (r
->divert
.port
) {
1010 if (PF_AZERO(&r
->divert
.addr
, r
->af
)) {
1011 printf(" divert-reply");
1013 /* XXX cut&paste from print_addr */
1016 printf(" divert-to ");
1017 if (inet_ntop(r
->af
, &r
->divert
.addr
, buf
,
1018 sizeof(buf
)) == NULL
)
1022 printf(" port %u", ntohs(r
->divert
.port
));
1025 if (!anchor_call
[0] && (r
->action
== PF_NAT
||
1026 r
->action
== PF_BINAT
|| r
->action
== PF_RDR
)) {
1028 print_pool(&r
->rpool
, r
->rpool
.proxy_port
[0],
1029 r
->rpool
.proxy_port
[1], r
->af
, r
->action
);
1034 print_tabledef(const char *name
, int flags
, int addrs
,
1035 struct node_tinithead
*nodes
)
1037 struct node_tinit
*ti
, *nti
;
1038 struct node_host
*h
;
1040 printf("table <%s>", name
);
1041 if (flags
& PFR_TFLAG_CONST
)
1043 if (flags
& PFR_TFLAG_PERSIST
)
1045 if (flags
& PFR_TFLAG_COUNTERS
)
1046 printf(" counters");
1047 SIMPLEQ_FOREACH(ti
, nodes
, entries
) {
1049 printf(" file \"%s\"", ti
->file
);
1054 for (h
= ti
->host
; h
!= NULL
; h
= h
->next
) {
1055 printf(h
->not ? " !" : " ");
1056 print_addr(&h
->addr
, h
->af
, 0);
1058 nti
= SIMPLEQ_NEXT(ti
, entries
);
1059 if (nti
!= NULL
&& nti
->file
== NULL
)
1060 ti
= nti
; /* merge lists */
1066 if (addrs
&& SIMPLEQ_EMPTY(nodes
))
1072 parse_flags(const char *s
)
1077 for (p
= s
; *p
; p
++) {
1078 if ((q
= strchr(tcpflags
, *p
)) == NULL
)
1081 f
|= 1 << (q
- tcpflags
);
1083 return (f
? f
: PF_TH_ALL
);
1087 set_ipmask(struct node_host
*h
, u_int8_t b
)
1089 struct pf_addr
*m
, *n
;
1092 m
= &h
->addr
.v
.a
.mask
;
1093 memset(m
, 0, sizeof(*m
));
1096 m
->addr32
[j
++] = 0xffffffff;
1099 for (i
= 31; i
> 31-b
; --i
)
1100 m
->addr32
[j
] |= (1 << i
);
1102 m
->addr32
[j
] = htonl(m
->addr32
[j
]);
1104 /* Mask off bits of the address that will never be used. */
1105 n
= &h
->addr
.v
.a
.addr
;
1106 if (h
->addr
.type
== PF_ADDR_ADDRMASK
)
1107 for (i
= 0; i
< 4; i
++)
1108 n
->addr32
[i
] = n
->addr32
[i
] & m
->addr32
[i
];
1112 check_netmask(struct node_host
*h
, sa_family_t af
)
1114 struct node_host
*n
= NULL
;
1117 for (n
= h
; n
!= NULL
; n
= n
->next
) {
1118 if (h
->addr
.type
== PF_ADDR_TABLE
)
1120 m
= &h
->addr
.v
.a
.mask
;
1121 /* fix up netmask for dynaddr */
1122 if (af
== AF_INET
&& h
->addr
.type
== PF_ADDR_DYNIFTL
&&
1123 unmask(m
, AF_INET6
) > 32)
1125 /* netmasks > 32 bit are invalid on v4 */
1126 if (af
== AF_INET
&&
1127 (m
->addr32
[1] || m
->addr32
[2] || m
->addr32
[3])) {
1128 fprintf(stderr
, "netmask %u invalid for IPv4 address\n",
1129 unmask(m
, AF_INET6
));
1136 /* interface lookup routines */
1138 struct node_host
*iftab
;
1143 struct ifaddrs
*ifap
, *ifa
;
1144 struct node_host
*n
= NULL
, *h
= NULL
;
1146 if (getifaddrs(&ifap
) < 0)
1147 err(1, "getifaddrs");
1149 for (ifa
= ifap
; ifa
; ifa
= ifa
->ifa_next
) {
1150 if (!(ifa
->ifa_addr
->sa_family
== AF_INET
||
1151 ifa
->ifa_addr
->sa_family
== AF_INET6
||
1152 ifa
->ifa_addr
->sa_family
== AF_LINK
))
1154 n
= calloc(1, sizeof(struct node_host
));
1156 err(1, "address: calloc");
1157 n
->af
= ifa
->ifa_addr
->sa_family
;
1158 n
->ifa_flags
= ifa
->ifa_flags
;
1160 if (n
->af
== AF_INET6
&&
1161 IN6_IS_ADDR_LINKLOCAL(&((struct sockaddr_in6
*)
1162 ifa
->ifa_addr
)->sin6_addr
) &&
1163 ((struct sockaddr_in6
*)ifa
->ifa_addr
)->sin6_scope_id
==
1165 struct sockaddr_in6
*sin6
;
1167 sin6
= (struct sockaddr_in6
*)ifa
->ifa_addr
;
1168 sin6
->sin6_scope_id
= sin6
->sin6_addr
.s6_addr
[2] << 8 |
1169 sin6
->sin6_addr
.s6_addr
[3];
1170 sin6
->sin6_addr
.s6_addr
[2] = 0;
1171 sin6
->sin6_addr
.s6_addr
[3] = 0;
1175 if (n
->af
== AF_INET
) {
1176 memcpy(&n
->addr
.v
.a
.addr
, &((struct sockaddr_in
*)
1177 ifa
->ifa_addr
)->sin_addr
.s_addr
,
1178 sizeof(struct in_addr
));
1179 memcpy(&n
->addr
.v
.a
.mask
, &((struct sockaddr_in
*)
1180 ifa
->ifa_netmask
)->sin_addr
.s_addr
,
1181 sizeof(struct in_addr
));
1182 if (ifa
->ifa_broadaddr
!= NULL
)
1183 memcpy(&n
->bcast
, &((struct sockaddr_in
*)
1184 ifa
->ifa_broadaddr
)->sin_addr
.s_addr
,
1185 sizeof(struct in_addr
));
1186 if (ifa
->ifa_dstaddr
!= NULL
)
1187 memcpy(&n
->peer
, &((struct sockaddr_in
*)
1188 ifa
->ifa_dstaddr
)->sin_addr
.s_addr
,
1189 sizeof(struct in_addr
));
1190 } else if (n
->af
== AF_INET6
) {
1191 memcpy(&n
->addr
.v
.a
.addr
, &((struct sockaddr_in6
*)
1192 ifa
->ifa_addr
)->sin6_addr
.s6_addr
,
1193 sizeof(struct in6_addr
));
1194 memcpy(&n
->addr
.v
.a
.mask
, &((struct sockaddr_in6
*)
1195 ifa
->ifa_netmask
)->sin6_addr
.s6_addr
,
1196 sizeof(struct in6_addr
));
1197 if (ifa
->ifa_broadaddr
!= NULL
)
1198 memcpy(&n
->bcast
, &((struct sockaddr_in6
*)
1199 ifa
->ifa_broadaddr
)->sin6_addr
.s6_addr
,
1200 sizeof(struct in6_addr
));
1201 if (ifa
->ifa_dstaddr
!= NULL
)
1202 memcpy(&n
->peer
, &((struct sockaddr_in6
*)
1203 ifa
->ifa_dstaddr
)->sin6_addr
.s6_addr
,
1204 sizeof(struct in6_addr
));
1205 n
->ifindex
= ((struct sockaddr_in6
*)
1206 ifa
->ifa_addr
)->sin6_scope_id
;
1208 if ((n
->ifname
= strdup(ifa
->ifa_name
)) == NULL
)
1209 err(1, "ifa_load: strdup");
1225 ifa_exists(const char *ifa_name
)
1227 struct node_host
*n
;
1228 struct ifgroupreq ifgr
;
1234 /* check wether this is a group */
1235 if ((s
= socket(AF_INET
, SOCK_DGRAM
, 0)) == -1)
1237 bzero(&ifgr
, sizeof(ifgr
));
1238 strlcpy(ifgr
.ifgr_name
, ifa_name
, sizeof(ifgr
.ifgr_name
));
1239 if (ioctl(s
, SIOCGIFGMEMB
, (caddr_t
)&ifgr
) == 0) {
1240 /* fake a node_host */
1241 if ((n
= calloc(1, sizeof(*n
))) == NULL
)
1243 if ((n
->ifname
= strdup(ifa_name
)) == NULL
)
1250 for (n
= iftab
; n
; n
= n
->next
) {
1251 if (n
->af
== AF_LINK
&& !strncmp(n
->ifname
, ifa_name
, IFNAMSIZ
))
1259 ifa_grouplookup(const char *ifa_name
, int flags
)
1261 struct ifg_req
*ifg
;
1262 struct ifgroupreq ifgr
;
1265 struct node_host
*n
, *h
= NULL
;
1267 if ((s
= socket(AF_INET
, SOCK_DGRAM
, 0)) == -1)
1269 bzero(&ifgr
, sizeof(ifgr
));
1270 strlcpy(ifgr
.ifgr_name
, ifa_name
, sizeof(ifgr
.ifgr_name
));
1271 if (ioctl(s
, SIOCGIFGMEMB
, (caddr_t
)&ifgr
) == -1) {
1276 len
= ifgr
.ifgr_len
;
1277 if ((ifgr
.ifgr_groups
= calloc(1, len
)) == NULL
)
1279 if (ioctl(s
, SIOCGIFGMEMB
, (caddr_t
)&ifgr
) == -1)
1280 err(1, "SIOCGIFGMEMB");
1282 for (ifg
= ifgr
.ifgr_groups
; ifg
&& len
>= sizeof(struct ifg_req
);
1284 len
-= sizeof(struct ifg_req
);
1285 if ((n
= ifa_lookup(ifg
->ifgrq_member
, flags
)) == NULL
)
1294 free(ifgr
.ifgr_groups
);
1301 ifa_lookup(const char *ifa_name
, int flags
)
1303 struct node_host
*p
= NULL
, *h
= NULL
, *n
= NULL
;
1304 int got4
= 0, got6
= 0;
1305 const char *last_if
= NULL
;
1307 if ((h
= ifa_grouplookup(ifa_name
, flags
)) != NULL
)
1310 if (!strncmp(ifa_name
, "self", IFNAMSIZ
))
1316 for (p
= iftab
; p
; p
= p
->next
) {
1317 if (ifa_skip_if(ifa_name
, p
))
1319 if ((flags
& PFI_AFLAG_BROADCAST
) && p
->af
!= AF_INET
)
1321 if ((flags
& PFI_AFLAG_BROADCAST
) &&
1322 !(p
->ifa_flags
& IFF_BROADCAST
))
1324 if ((flags
& PFI_AFLAG_PEER
) &&
1325 !(p
->ifa_flags
& IFF_POINTOPOINT
))
1327 if ((flags
& PFI_AFLAG_NETWORK
) && p
->ifindex
> 0)
1329 if (last_if
== NULL
|| strcmp(last_if
, p
->ifname
))
1331 last_if
= p
->ifname
;
1332 if ((flags
& PFI_AFLAG_NOALIAS
) && p
->af
== AF_INET
&& got4
)
1334 if ((flags
& PFI_AFLAG_NOALIAS
) && p
->af
== AF_INET6
&& got6
)
1336 if ((flags
& PFI_AFLAG_NOALIAS
) && p
->af
== AF_INET6
&&
1337 IN6_IS_ADDR_LINKLOCAL(&p
->addr
.v
.a
.addr
.v6
))
1339 if (p
->af
== AF_INET
)
1343 n
= calloc(1, sizeof(struct node_host
));
1345 err(1, "address: calloc");
1347 if (flags
& PFI_AFLAG_BROADCAST
)
1348 memcpy(&n
->addr
.v
.a
.addr
, &p
->bcast
,
1349 sizeof(struct pf_addr
));
1350 else if (flags
& PFI_AFLAG_PEER
)
1351 memcpy(&n
->addr
.v
.a
.addr
, &p
->peer
,
1352 sizeof(struct pf_addr
));
1354 memcpy(&n
->addr
.v
.a
.addr
, &p
->addr
.v
.a
.addr
,
1355 sizeof(struct pf_addr
));
1356 if (flags
& PFI_AFLAG_NETWORK
)
1357 set_ipmask(n
, unmask(&p
->addr
.v
.a
.mask
, n
->af
));
1359 if (n
->af
== AF_INET
) {
1360 if (p
->ifa_flags
& IFF_LOOPBACK
&&
1361 p
->ifa_flags
& IFF_LINK1
)
1362 memcpy(&n
->addr
.v
.a
.mask
,
1364 sizeof(struct pf_addr
));
1370 n
->ifindex
= p
->ifindex
;
1385 ifa_skip_if(const char *filter
, struct node_host
*p
)
1389 if (p
->af
!= AF_INET
&& p
->af
!= AF_INET6
)
1391 if (filter
== NULL
|| !*filter
)
1393 if (!strcmp(p
->ifname
, filter
))
1394 return (0); /* exact match */
1396 if (n
< 1 || n
>= IFNAMSIZ
)
1397 return (1); /* sanity check */
1398 if (filter
[n
-1] >= '0' && filter
[n
-1] <= '9')
1399 return (1); /* only do exact match in that case */
1400 if (strncmp(p
->ifname
, filter
, n
))
1401 return (1); /* prefix doesn't match */
1402 return (p
->ifname
[n
] < '0' || p
->ifname
[n
] > '9');
1409 struct node_host
*h
= NULL
;
1410 int mask
, v4mask
, v6mask
, cont
= 1;
1413 if ((p
= strrchr(s
, '/')) != NULL
) {
1414 mask
= strtol(p
+1, &q
, 0);
1415 if (!q
|| *q
|| mask
> 128 || q
== (p
+1)) {
1416 fprintf(stderr
, "invalid netmask '%s'\n", p
);
1419 if ((ps
= malloc(strlen(s
) - strlen(p
) + 1)) == NULL
)
1420 err(1, "host: malloc");
1421 strlcpy(ps
, s
, strlen(s
) - strlen(p
) + 1);
1422 v4mask
= v6mask
= mask
;
1424 if ((ps
= strdup(s
)) == NULL
)
1425 err(1, "host: strdup");
1431 /* interface with this name exists? */
1432 if (cont
&& (h
= host_if(ps
, mask
)) != NULL
)
1436 if (cont
&& (h
= host_v4(s
)) != NULL
)
1440 if (cont
&& (h
= host_v6(ps
, v6mask
)) != NULL
)
1444 if (cont
&& (h
= host_dns(ps
, v4mask
, v6mask
)) != NULL
)
1448 if (h
== NULL
|| cont
== 1) {
1449 fprintf(stderr
, "no IP address found for %s\n", s
);
1456 host_if(const char *s
, int mask
)
1458 struct node_host
*n
, *h
= NULL
;
1462 if ((ps
= strdup(s
)) == NULL
)
1463 err(1, "host_if: strdup");
1464 while ((p
= strrchr(ps
, ':')) != NULL
) {
1465 if (!strcmp(p
+1, "network"))
1466 flags
|= PFI_AFLAG_NETWORK
;
1467 else if (!strcmp(p
+1, "broadcast"))
1468 flags
|= PFI_AFLAG_BROADCAST
;
1469 else if (!strcmp(p
+1, "peer"))
1470 flags
|= PFI_AFLAG_PEER
;
1471 else if (!strcmp(p
+1, "0"))
1472 flags
|= PFI_AFLAG_NOALIAS
;
1479 if (flags
& (flags
- 1) & PFI_AFLAG_MODEMASK
) { /* Yep! */
1480 fprintf(stderr
, "illegal combination of interface modifiers\n");
1484 if ((flags
& (PFI_AFLAG_NETWORK
|PFI_AFLAG_BROADCAST
)) && mask
> -1) {
1485 fprintf(stderr
, "network or broadcast lookup, but "
1486 "extra netmask given\n");
1490 if (ifa_exists(ps
) || !strncmp(ps
, "self", IFNAMSIZ
)) {
1491 /* interface with this name exists */
1492 h
= ifa_lookup(ps
, flags
);
1493 for (n
= h
; n
!= NULL
&& mask
> -1; n
= n
->next
)
1494 set_ipmask(n
, mask
);
1501 static struct node_host
*
1502 host_v4(const char *s
)
1504 struct node_host
*h
= NULL
;
1508 memset(&ina
, 0, sizeof(struct in_addr
));
1509 if (strrchr(s
, '/') != NULL
) {
1510 if ((bits
= inet_net_pton(AF_INET
, s
, &ina
, sizeof(ina
))) == -1)
1513 if (inet_pton(AF_INET
, s
, &ina
) != 1)
1517 h
= calloc(1, sizeof(struct node_host
));
1519 err(1, "address: calloc");
1522 h
->addr
.v
.a
.addr
.addr32
[0] = ina
.s_addr
;
1523 set_ipmask(h
, bits
);
1531 host_v6(const char *s
, int mask
)
1533 struct addrinfo hints
, *res
;
1534 struct node_host
*h
= NULL
;
1536 memset(&hints
, 0, sizeof(hints
));
1537 hints
.ai_family
= AF_INET6
;
1538 hints
.ai_socktype
= SOCK_DGRAM
; /*dummy*/
1539 hints
.ai_flags
= AI_NUMERICHOST
;
1540 if (getaddrinfo(s
, "0", &hints
, &res
) == 0) {
1541 h
= calloc(1, sizeof(struct node_host
));
1543 err(1, "address: calloc");
1546 memcpy(&h
->addr
.v
.a
.addr
,
1547 &((struct sockaddr_in6
*)res
->ai_addr
)->sin6_addr
,
1548 sizeof(h
->addr
.v
.a
.addr
));
1550 ((struct sockaddr_in6
*)res
->ai_addr
)->sin6_scope_id
;
1551 set_ipmask(h
, mask
);
1561 host_dns(const char *s
, int v4mask
, int v6mask
)
1563 struct addrinfo hints
, *res0
, *res
;
1564 struct node_host
*n
, *h
= NULL
;
1565 int error
, noalias
= 0;
1566 int got4
= 0, got6
= 0;
1569 if ((ps
= strdup(s
)) == NULL
)
1570 err(1, "host_dns: strdup");
1571 if ((p
= strrchr(ps
, ':')) != NULL
&& !strcmp(p
, ":0")) {
1575 memset(&hints
, 0, sizeof(hints
));
1576 hints
.ai_family
= PF_UNSPEC
;
1577 hints
.ai_socktype
= SOCK_STREAM
; /* DUMMY */
1578 error
= getaddrinfo(ps
, NULL
, &hints
, &res0
);
1584 for (res
= res0
; res
; res
= res
->ai_next
) {
1585 if (res
->ai_family
!= AF_INET
&&
1586 res
->ai_family
!= AF_INET6
)
1589 if (res
->ai_family
== AF_INET
) {
1599 n
= calloc(1, sizeof(struct node_host
));
1601 err(1, "host_dns: calloc");
1603 n
->af
= res
->ai_family
;
1604 if (res
->ai_family
== AF_INET
) {
1605 memcpy(&n
->addr
.v
.a
.addr
,
1606 &((struct sockaddr_in
*)
1607 res
->ai_addr
)->sin_addr
.s_addr
,
1608 sizeof(struct in_addr
));
1609 set_ipmask(n
, v4mask
);
1611 memcpy(&n
->addr
.v
.a
.addr
,
1612 &((struct sockaddr_in6
*)
1613 res
->ai_addr
)->sin6_addr
.s6_addr
,
1614 sizeof(struct in6_addr
));
1616 ((struct sockaddr_in6
*)
1617 res
->ai_addr
)->sin6_scope_id
;
1618 set_ipmask(n
, v6mask
);
1636 * convert a hostname to a list of addresses and put them in the given buffer.
1638 * if set to 1, only simple addresses are accepted (no netblock, no "!").
1641 append_addr(struct pfr_buffer
*b
, char *s
, int test
)
1644 struct node_host
*h
, *n
;
1647 for (r
= s
; *r
== '!'; r
++)
1649 if ((n
= host(r
)) == NULL
) {
1653 rv
= append_addr_host(b
, n
, test
, not);
1658 } while (n
!= NULL
);
1663 * same as previous function, but with a pre-parsed input and the ability
1664 * to "negate" the result. Does not free the node_host list.
1666 * setting it to 1 is equivalent to adding "!" in front of parameter s.
1669 append_addr_host(struct pfr_buffer
*b
, struct node_host
*n
, int test
, int not)
1672 struct pfr_addr addr
;
1675 bzero(&addr
, sizeof(addr
));
1676 addr
.pfra_not
= n
->not ^ not;
1677 addr
.pfra_af
= n
->af
;
1678 addr
.pfra_net
= unmask(&n
->addr
.v
.a
.mask
, n
->af
);
1681 addr
.pfra_ip4addr
.s_addr
= n
->addr
.v
.a
.addr
.addr32
[0];
1685 memcpy(&addr
.pfra_ip6addr
, &n
->addr
.v
.a
.addr
.v6
,
1686 sizeof(struct in6_addr
));
1693 if ((test
&& (not || addr
.pfra_net
!= bits
)) ||
1694 addr
.pfra_net
> bits
) {
1698 if (pfr_buf_add(b
, &addr
))
1700 } while ((n
= n
->next
) != NULL
);
1706 pfctl_add_trans(struct pfr_buffer
*buf
, int rs_num
, const char *anchor
)
1708 struct pfioc_trans_e trans
;
1710 bzero(&trans
, sizeof(trans
));
1711 trans
.rs_num
= rs_num
;
1712 if (strlcpy(trans
.anchor
, anchor
,
1713 sizeof(trans
.anchor
)) >= sizeof(trans
.anchor
))
1714 errx(1, "pfctl_add_trans: strlcpy");
1716 return pfr_buf_add(buf
, &trans
);
1720 pfctl_get_ticket(struct pfr_buffer
*buf
, int rs_num
, const char *anchor
)
1722 const struct pfioc_trans_e
*p
;
1724 PFRB_FOREACH(p
, buf
)
1725 if (rs_num
== p
->rs_num
&& !strcmp(anchor
, p
->anchor
))
1727 errx(1, "pfctl_get_ticket: assertion failed");
1731 pfctl_trans(int dev
, struct pfr_buffer
*buf
, u_long cmd
, int from
)
1733 struct pfioc_trans trans
;
1735 bzero(&trans
, sizeof(trans
));
1736 trans
.size
= buf
->pfrb_size
- from
;
1737 trans
.esize
= sizeof(struct pfioc_trans_e
);
1738 trans
.array
= ((struct pfioc_trans_e
*)buf
->pfrb_caddr
) + from
;
1739 return ioctl(dev
, cmd
, &trans
);