route: ensure RTM_IFINFO is sent first when bring interface down/up
[dragonfly.git] / usr.sbin / pfctl / pfctl_parser.c
1 /*      $OpenBSD: pfctl_parser.c,v 1.240 2008/06/10 20:55:02 mcbride Exp $ */
2
3 /*
4  * Copyright (c) 2001 Daniel Hartmeier
5  * Copyright (c) 2002,2003 Henning Brauer
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  *
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.
18  *
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.
31  *
32  */
33
34 #include <sys/user.h>
35 #include <sys/types.h>
36 #include <sys/ioctl.h>
37 #include <sys/socket.h>
38 #include <sys/param.h>
39 #include <net/if.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>
47
48 #include <stdio.h>
49 #include <stdlib.h>
50 #include <string.h>
51 #include <ctype.h>
52 #include <netdb.h>
53 #include <stdarg.h>
54 #include <errno.h>
55 #include <err.h>
56 #include <ifaddrs.h>
57 #include <unistd.h>
58
59 #include "pfctl_parser.h"
60 #include "pfctl.h"
61
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);
69
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);
75
76 const char *tcpflags = "FSRPAUEW";
77
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 }
104 };
105
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 }
133 };
134
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 }
166 };
167
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 }
181 };
182
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 },
204         { NULL,                 0 }
205 };
206
207 const struct icmptypeent *
208 geticmptypebynumber(u_int8_t type, sa_family_t af)
209 {
210         unsigned int    i;
211
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]);
216                 }
217         } else {
218                 for (i=0; i < NELEM(icmp6_type); i++) {
219                         if (type == icmp6_type[i].type)
220                                  return (&icmp6_type[i]);
221                 }
222         }
223         return (NULL);
224 }
225
226 const struct icmptypeent *
227 geticmptypebyname(char *w, sa_family_t af)
228 {
229         unsigned int    i;
230
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]);
235                 }
236         } else {
237                 for (i=0; i < NELEM(icmp6_type); i++) {
238                         if (!strcmp(w, icmp6_type[i].name))
239                                 return (&icmp6_type[i]);
240                 }
241         }
242         return (NULL);
243 }
244
245 const struct icmpcodeent *
246 geticmpcodebynumber(u_int8_t type, u_int8_t code, sa_family_t af)
247 {
248         unsigned int    i;
249
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]);
255                 }
256         } else {
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]);
261                 }
262         }
263         return (NULL);
264 }
265
266 const struct icmpcodeent *
267 geticmpcodebyname(u_long type, char *w, sa_family_t af)
268 {
269         unsigned int    i;
270
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]);
276                 }
277         } else {
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]);
282                 }
283         }
284         return (NULL);
285 }
286
287 void
288 print_op(u_int8_t op, const char *a1, const char *a2)
289 {
290         if (op == PF_OP_IRG)
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)
295                 printf(" = %s", a1);
296         else if (op == PF_OP_NE)
297                 printf(" != %s", a1);
298         else if (op == PF_OP_LT)
299                 printf(" < %s", a1);
300         else if (op == PF_OP_LE)
301                 printf(" <= %s", a1);
302         else if (op == PF_OP_GT)
303                 printf(" > %s", a1);
304         else if (op == PF_OP_GE)
305                 printf(" >= %s", a1);
306         else if (op == PF_OP_RRG)
307                 printf(" %s:%s", a1, a2);
308 }
309
310 void
311 print_port(u_int8_t op, u_int16_t p1, u_int16_t p2, const char *proto)
312 {
313         char             a1[6], a2[6];
314         struct servent  *s;
315
316         s = getservbyport(p1, proto);
317         p1 = ntohs(p1);
318         p2 = ntohs(p2);
319         snprintf(a1, sizeof(a1), "%u", p1);
320         snprintf(a2, sizeof(a2), "%u", p2);
321         printf(" port");
322         if (s != NULL && (op == PF_OP_EQ || op == PF_OP_NE))
323                 print_op(op, s->s_name, a2);
324         else
325                 print_op(op, a1, a2);
326 }
327
328 void
329 print_ugid(u_int8_t op, unsigned u1, unsigned u2, const char *t, unsigned umax)
330 {
331         char    a1[11], a2[11];
332
333         snprintf(a1, sizeof(a1), "%u", u1);
334         snprintf(a2, sizeof(a2), "%u", u2);
335         printf(" %s", t);
336         if (u1 == umax && (op == PF_OP_EQ || op == PF_OP_NE))
337                 print_op(op, "unknown", a2);
338         else
339                 print_op(op, a1, a2);
340 }
341
342 void
343 print_flags(u_int8_t f)
344 {
345         int     i;
346
347         for (i = 0; tcpflags[i]; ++i)
348                 if (f & (1 << i))
349                         printf("%c", tcpflags[i]);
350 }
351
352 void
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)
355 {
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 &&
365             osfp == PF_OSFP_ANY)
366                 printf(" all");
367         else {
368                 printf(" from ");
369                 if (src->neg)
370                         printf("! ");
371                 print_addr(&src->addr, af, verbose);
372                 if (src->port_op)
373                         print_port(src->port_op, src->port[0],
374                             src->port[1],
375                             proto == IPPROTO_TCP ? "tcp" : "udp");
376                 if (osfp != PF_OSFP_ANY)
377                         printf(" os \"%s\"", pfctl_lookup_fingerprint(osfp, buf,
378                             sizeof(buf)));
379
380                 printf(" to ");
381                 if (dst->neg)
382                         printf("! ");
383                 print_addr(&dst->addr, af, verbose);
384                 if (dst->port_op)
385                         print_port(dst->port_op, dst->port[0],
386                             dst->port[1],
387                             proto == IPPROTO_TCP ? "tcp" : "udp");
388         }
389 }
390
391 void
392 print_pool(struct pf_pool *pool, u_int16_t p1, u_int16_t p2,
393     sa_family_t af, int id)
394 {
395         struct pf_pooladdr      *pooladdr;
396
397         if ((TAILQ_FIRST(&pool->list) != NULL) &&
398             TAILQ_NEXT(TAILQ_FIRST(&pool->list), entries) != NULL)
399                 printf("{ ");
400         TAILQ_FOREACH(pooladdr, &pool->list, entries){
401                 switch (id) {
402                 case PF_NAT:
403                 case PF_RDR:
404                 case PF_BINAT:
405                         print_addr(&pooladdr->addr, af, 0);
406                         break;
407                 case PF_PASS:
408                         if (PF_AZERO(&pooladdr->addr.v.a.addr, af))
409                                 printf("%s", pooladdr->ifname);
410                         else {
411                                 printf("(%s ", pooladdr->ifname);
412                                 print_addr(&pooladdr->addr, af, 0);
413                                 printf(")");
414                         }
415                         break;
416                 default:
417                         break;
418                 }
419                 if (TAILQ_NEXT(pooladdr, entries) != NULL)
420                         printf(", ");
421                 else if (TAILQ_NEXT(TAILQ_FIRST(&pool->list), entries) != NULL)
422                         printf(" }");
423         }
424         switch (id) {
425         case PF_NAT:
426                 if ((p1 != PF_NAT_PROXY_PORT_LOW ||
427                     p2 != PF_NAT_PROXY_PORT_HIGH) && (p1 != 0 || p2 != 0)) {
428                         if (p1 == p2)
429                                 printf(" port %u", p1);
430                         else
431                                 printf(" port %u:%u", p1, p2);
432                 }
433                 break;
434         case PF_RDR:
435                 if (p1) {
436                         printf(" port %u", p1);
437                         if (p2 && (p2 != p1))
438                                 printf(":%u", p2);
439                 }
440                 break;
441         default:
442                 break;
443         }
444         switch (pool->opts & PF_POOL_TYPEMASK) {
445         case PF_POOL_NONE:
446                 break;
447         case PF_POOL_BITMASK:
448                 printf(" bitmask");
449                 break;
450         case PF_POOL_RANDOM:
451                 printf(" random");
452                 break;
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]);
457                 break;
458         case PF_POOL_ROUNDROBIN:
459                 printf(" round-robin");
460                 break;
461         }
462         if (pool->opts & PF_POOL_STICKYADDR)
463                 printf(" sticky-address");
464         if (id == PF_NAT && p1 == 0 && p2 == 0)
465                 printf(" static-port");
466 }
467
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;
472
473 void
474 print_status(struct pf_status *s, int opts)
475 {
476         char                    statline[80];
477         const char *running;
478         time_t                  runtime;
479         int                     i;
480         char                    buf[PF_MD5_DIGEST_LENGTH * 2 + 1];
481         static const char       hex[] = "0123456789abcdef";
482
483         runtime = time(NULL) - s->since;
484         running = s->running ? "Enabled" : "Disabled";
485
486         if (s->since) {
487                 unsigned int    sec, min, hrs, day = runtime;
488
489                 sec = day % 60;
490                 day /= 60;
491                 min = day % 60;
492                 day /= 60;
493                 hrs = day % 24;
494                 day /= 24;
495                 snprintf(statline, sizeof(statline),
496                     "Status: %s for %u days %.2u:%.2u:%.2u",
497                     running, day, hrs, min, sec);
498         } else
499                 snprintf(statline, sizeof(statline), "Status: %s", running);
500         printf("%-44s", statline);
501         switch (s->debug) {
502         case PF_DEBUG_NONE:
503                 printf("%15s\n\n", "Debug: None");
504                 break;
505         case PF_DEBUG_URGENT:
506                 printf("%15s\n\n", "Debug: Urgent");
507                 break;
508         case PF_DEBUG_MISC:
509                 printf("%15s\n\n", "Debug: Misc");
510                 break;
511         case PF_DEBUG_NOISY:
512                 printf("%15s\n\n", "Debug: Loud");
513                 break;
514         }
515
516         if (opts & PF_OPT_VERBOSE) {
517                 printf("Hostid:   0x%08x\n", ntohl(s->hostid));
518
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];
522                 }
523                 buf[i + i] = '\0';
524                 printf("Checksum: 0x%s\n\n", buf);
525         }
526
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]);
550         }
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]);
556                 if (runtime > 0)
557                         printf("%14.1f/s\n",
558                             (double)s->fcounters[i] / (double)runtime);
559                 else
560                         printf("%14s\n", "");
561         }
562         if (opts & PF_OPT_VERBOSE) {
563                 printf("Source Tracking Table\n");
564                 printf("  %-25s %14u %14s\n", "current entries",
565                     s->src_nodes, "");
566                 for (i = 0; i < SCNT_MAX; i++) {
567                         printf("  %-25s %14lld ", pf_scounters[i],
568                                     (unsigned long long)s->scounters[i]);
569                         if (runtime > 0)
570                                 printf("%14.1f/s\n",
571                                     (double)s->scounters[i] / (double)runtime);
572                         else
573                                 printf("%14s\n", "");
574                 }
575         }
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]);
580                 if (runtime > 0)
581                         printf("%14.1f/s\n",
582                             (double)s->counters[i] / (double)runtime);
583                 else
584                         printf("%14s\n", "");
585         }
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]);
591                         if (runtime > 0)
592                                 printf("%14.1f/s\n",
593                                     (double)s->lcounters[i] / (double)runtime);
594                         else
595                                 printf("%14s\n", "");
596                 }
597         }
598 }
599
600 void
601 print_src_node(struct pf_src_node *sn, int opts)
602 {
603         struct pf_addr_wrap aw;
604         int min, sec;
605
606         memset(&aw, 0, sizeof(aw));
607         if (sn->af == AF_INET)
608                 aw.v.a.mask.addr32[0] = 0xffffffff;
609         else
610                 memset(&aw.v.a.mask, 0xff, sizeof(aw.v.a.mask));
611
612         aw.v.a.addr = sn->addr;
613         print_addr(&aw, sn->af, opts & PF_OPT_VERBOSE2);
614         printf(" -> ");
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;
622                 sn->creation /= 60;
623                 min = sn->creation % 60;
624                 sn->creation /= 60;
625                 printf("   age %.2u:%.2u:%.2u", sn->creation, min, sec);
626                 if (sn->states == 0) {
627                         sec = sn->expire % 60;
628                         sn->expire /= 60;
629                         min = sn->expire % 60;
630                         sn->expire /= 60;
631                         printf(", expires in %.2u:%.2u:%.2u",
632                             sn->expire, min, sec);
633                 }
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) {
638                 case PF_NAT:
639                         if (sn->rule.nr != (uint32_t)(-1))
640                                 printf(", nat rule %u", sn->rule.nr);
641                         break;
642                 case PF_RDR:
643                         if (sn->rule.nr != (uint32_t)(-1))
644                                 printf(", rdr rule %u", sn->rule.nr);
645                         break;
646                 case PF_PASS:
647                         if (sn->rule.nr != (uint32_t)(-1))
648                                 printf(", filter rule %u", sn->rule.nr);
649                         break;
650                 }
651                 printf("\n");
652         }
653 }
654
655 void
656 print_rule(struct pf_rule *r, const char *anchor_call, int verbose)
657 {
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" };
663         int     i, opts;
664
665         if (verbose)
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]);
672                 } else
673                         printf("%s \"%s\"", anchortypes[r->action],
674                             anchor_call);
675         } else {
676                 printf("%s", actiontypes[r->action]);
677                 if (r->natpass)
678                         printf(" pass");
679         }
680         if (r->action == PF_DROP) {
681                 if (r->rule_flag & PFRULE_RETURN)
682                         printf(" return");
683                 else if (r->rule_flag & PFRULE_RETURNRST) {
684                         if (!r->return_ttl)
685                                 printf(" return-rst");
686                         else
687                                 printf(" return-rst(ttl %d)", r->return_ttl);
688                 } else if (r->rule_flag & PFRULE_RETURNICMP) {
689                         const struct icmpcodeent        *ic, *ic6;
690
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);
695
696                         switch (r->af) {
697                         case AF_INET:
698                                 printf(" return-icmp");
699                                 if (ic == NULL)
700                                         printf("(%u)", r->return_icmp & 255);
701                                 else
702                                         printf("(%s)", ic->name);
703                                 break;
704                         case AF_INET6:
705                                 printf(" return-icmp6");
706                                 if (ic6 == NULL)
707                                         printf("(%u)", r->return_icmp6 & 255);
708                                 else
709                                         printf("(%s)", ic6->name);
710                                 break;
711                         default:
712                                 printf(" return-icmp");
713                                 if (ic == NULL)
714                                         printf("(%u, ", r->return_icmp & 255);
715                                 else
716                                         printf("(%s, ", ic->name);
717                                 if (ic6 == NULL)
718                                         printf("%u)", r->return_icmp6 & 255);
719                                 else
720                                         printf("%s)", ic6->name);
721                                 break;
722                         }
723                 } else
724                         printf(" drop");
725         }
726         if (r->direction == PF_IN)
727                 printf(" in");
728         else if (r->direction == PF_OUT)
729                 printf(" out");
730         if (r->log) {
731                 printf(" log");
732                 if (r->log & ~PF_LOG || r->logif) {
733                         int count = 0;
734
735                         printf(" (");
736                         if (r->log & PF_LOG_ALL)
737                                 printf("%sall", count++ ? ", " : "");
738                         if (r->log & PF_LOG_SOCKET_LOOKUP)
739                                 printf("%suser", count++ ? ", " : "");
740                         if (r->logif)
741                                 printf("%sto pflog%u", count++ ? ", " : "",
742                                     r->logif);
743                         printf(")");
744                 }
745         }
746         if (r->quick)
747                 printf(" quick");
748         if (r->ifname[0]) {
749                 if (r->ifnot)
750                         printf(" on ! %s", r->ifname);
751                 else
752                         printf(" on %s", r->ifname);
753         }
754         if (r->rt) {
755                 if (r->rt == PF_ROUTETO)
756                         printf(" route-to");
757                 else if (r->rt == PF_REPLYTO)
758                         printf(" reply-to");
759                 else if (r->rt == PF_DUPTO)
760                         printf(" dup-to");
761                 else if (r->rt == PF_FASTROUTE)
762                         printf(" fastroute");
763                 if (r->rt != PF_FASTROUTE) {
764                         printf(" ");
765                         print_pool(&r->rpool, 0, 0, r->af, PF_PASS);
766                 }
767         }
768         if (r->af) {
769                 if (r->af == AF_INET)
770                         printf(" inet");
771                 else
772                         printf(" inet6");
773         }
774         if (r->proto) {
775                 struct protoent *p;
776
777                 if ((p = getprotobynumber(r->proto)) != NULL)
778                         printf(" proto %s", p->p_name);
779                 else
780                         printf(" proto %u", r->proto);
781         }
782         print_fromto(&r->src, r->os_fingerprint, &r->dst, r->af, r->proto,
783             verbose);
784         if (r->uid.op)
785                 print_ugid(r->uid.op, r->uid.uid[0], r->uid.uid[1], "user",
786                     UID_MAX);
787         if (r->gid.op)
788                 print_ugid(r->gid.op, r->gid.gid[0], r->gid.gid[1], "group",
789                     GID_MAX);
790         if (r->flags || r->flagset) {
791                 printf(" flags ");
792                 print_flags(r->flags);
793                 printf("/");
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");
800         if (r->type) {
801                 const struct icmptypeent        *it;
802
803                 it = geticmptypebynumber(r->type-1, r->af);
804                 if (r->af != AF_INET6)
805                         printf(" icmp-type");
806                 else
807                         printf(" icmp6-type");
808                 if (it != NULL)
809                         printf(" %s", it->name);
810                 else
811                         printf(" %u", r->type-1);
812                 if (r->code) {
813                         const struct icmpcodeent        *ic;
814
815                         ic = geticmpcodebynumber(r->type-1, r->code-1, r->af);
816                         if (ic != NULL)
817                                 printf(" code %s", ic->name);
818                         else
819                                 printf(" code %u", r->code-1);
820                 }
821         }
822         if (r->tos)
823                 printf(" tos 0x%2.2x", r->tos);
824         if (!r->keep_state && r->action == PF_PASS && !anchor_call[0])
825                 printf(" no state");
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");
832         if (r->prob) {
833                 char    buf[20];
834
835                 snprintf(buf, sizeof(buf), "%f", r->prob*100.0/(UINT_MAX+1.0));
836                 for (i = strlen(buf)-1; i > 0; i--) {
837                         if (buf[i] == '0')
838                                 buf[i] = '\0';
839                         else {
840                                 if (buf[i] == '.')
841                                         buf[i] = '\0';
842                                 break;
843                         }
844                 }
845                 printf(" probability %s%%", buf);
846         }
847         opts = 0;
848         if (r->max_states || r->max_src_nodes || r->max_src_states)
849                 opts = 1;
850         if (r->pickup_mode)
851                 opts = 1;
852         if (r->rule_flag & PFRULE_NOSYNC)
853                 opts = 1;
854         if (r->rule_flag & PFRULE_SRCTRACK)
855                 opts = 1;
856         if (r->rule_flag & PFRULE_IFBOUND)
857                 opts = 1;
858         if (r->rule_flag & PFRULE_STATESLOPPY)
859                 opts = 1;
860         for (i = 0; !opts && i < PFTM_MAX; ++i)
861                 if (r->timeout[i])
862                         opts = 1;
863         if (opts) {
864                 printf(" (");
865                 switch(r->pickup_mode) {
866                 case PF_PICKUPS_UNSPECIFIED:
867                         break;
868                 case PF_PICKUPS_DISABLED:
869                         printf("no-pickups");
870                         opts = 0;
871                         break;
872                 case PF_PICKUPS_HASHONLY:
873                         printf("hash-only");
874                         opts = 0;
875                         break;
876                 case PF_PICKUPS_ENABLED:
877                         printf("pickups");
878                         opts = 0;
879                         break;
880                 default:
881                         printf("unknown-pickups-mode-%d", r->pickup_mode);
882                         break;
883                 }
884                 if (r->max_states) {
885                         if (!opts)
886                                 printf(", ");
887                         printf("max %u", r->max_states);
888                         opts = 0;
889                 }
890                 if (r->rule_flag & PFRULE_NOSYNC) {
891                         if (!opts)
892                                 printf(", ");
893                         printf("no-sync");
894                         opts = 0;
895                 }
896                 if (r->rule_flag & PFRULE_SRCTRACK) {
897                         if (!opts)
898                                 printf(", ");
899                         printf("source-track");
900                         if (r->rule_flag & PFRULE_RULESRCTRACK)
901                                 printf(" rule");
902                         else
903                                 printf(" global");
904                         opts = 0;
905                 }
906                 if (r->max_src_states) {
907                         if (!opts)
908                                 printf(", ");
909                         printf("max-src-states %u", r->max_src_states);
910                         opts = 0;
911                 }
912                 if (r->max_src_conn) {
913                         if (!opts)
914                                 printf(", ");
915                         printf("max-src-conn %u", r->max_src_conn);
916                         opts = 0;
917                 }
918                 if (r->max_src_conn_rate.limit) {
919                         if (!opts)
920                                 printf(", ");
921                         printf("max-src-conn-rate %u/%u",
922                             r->max_src_conn_rate.limit,
923                             r->max_src_conn_rate.seconds);
924                         opts = 0;
925                 }
926                 if (r->max_src_nodes) {
927                         if (!opts)
928                                 printf(", ");
929                         printf("max-src-nodes %u", r->max_src_nodes);
930                         opts = 0;
931                 }
932                 if (r->overload_tblname[0]) {
933                         if (!opts)
934                                 printf(", ");
935                         printf("overload <%s>", r->overload_tblname);
936                         if (r->flush)
937                                 printf(" flush");
938                         if (r->flush & PF_FLUSH_GLOBAL)
939                                 printf(" global");
940                 }
941                 if (r->rule_flag & PFRULE_IFBOUND) {
942                         if (!opts)
943                                 printf(", ");
944                         printf("if-bound");
945                         opts = 0;
946                 }
947                 if (r->rule_flag & PFRULE_STATESLOPPY) {
948                         if (!opts)
949                                 printf(", ");
950                         printf("sloppy");
951                         opts = 0;
952                 }
953                 for (i = 0; i < PFTM_MAX; ++i)
954                         if (r->timeout[i]) {
955                                 int j;
956
957                                 if (!opts)
958                                         printf(", ");
959                                 opts = 0;
960                                 for (j = 0; pf_timeouts[j].name != NULL;
961                                     ++j)
962                                         if (pf_timeouts[j].timeout == i)
963                                                 break;
964                                 printf("%s %u", pf_timeouts[j].name == NULL ?
965                                     "inv.timeout" : pf_timeouts[j].name,
966                                     r->timeout[i]);
967                         }
968                 printf(")");
969         }
970         if (r->rule_flag & PFRULE_FRAGMENT)
971                 printf(" fragment");
972         if (r->rule_flag & PFRULE_NODF)
973                 printf(" no-df");
974         if (r->rule_flag & PFRULE_RANDOMID)
975                 printf(" random-id");
976         if (r->min_ttl)
977                 printf(" min-ttl %d", r->min_ttl);
978         if (r->max_mss)
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);
982         if (r->allow_opts)
983                 printf(" allow-opts");
984         if (r->action == PF_SCRUB) {
985                 if (r->rule_flag & PFRULE_REASSEMBLE_TCP)
986                         printf(" reassemble tcp");
987
988                 if (r->rule_flag & PFRULE_FRAGDROP)
989                         printf(" fragment drop-ovl");
990                 else if (r->rule_flag & PFRULE_FRAGCROP)
991                         printf(" fragment crop");
992                 else
993                         printf(" fragment reassemble");
994         }
995         if (r->label[0])
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);
1001         if (r->tagname[0])
1002                 printf(" tag %s", r->tagname);
1003         if (r->match_tagname[0]) {
1004                 if (r->match_tag_not)
1005                         printf(" !");
1006                 printf(" tagged %s", r->match_tagname);
1007         }
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");
1013                 } else {
1014                         /* XXX cut&paste from print_addr */
1015                         char buf[48];
1016
1017                         printf(" divert-to ");
1018                         if (inet_ntop(r->af, &r->divert.addr, buf,
1019                             sizeof(buf)) == NULL)
1020                                 printf("?");
1021                         else
1022                                 printf("%s", buf);
1023                         printf(" port %u", ntohs(r->divert.port));
1024                 }
1025         }
1026         if (!anchor_call[0] && (r->action == PF_NAT ||
1027             r->action == PF_BINAT || r->action == PF_RDR)) {
1028                 printf(" -> ");
1029                 print_pool(&r->rpool, r->rpool.proxy_port[0],
1030                     r->rpool.proxy_port[1], r->af, r->action);
1031         }
1032 }
1033
1034 void
1035 print_tabledef(const char *name, int flags, int addrs,
1036     struct node_tinithead *nodes)
1037 {
1038         struct node_tinit       *ti, *nti;
1039         struct node_host        *h;
1040
1041         printf("table <%s>", name);
1042         if (flags & PFR_TFLAG_CONST)
1043                 printf(" const");
1044         if (flags & PFR_TFLAG_PERSIST)
1045                 printf(" persist");
1046         if (flags & PFR_TFLAG_COUNTERS)
1047                 printf(" counters");
1048         SIMPLEQ_FOREACH(ti, nodes, entries) {
1049                 if (ti->file) {
1050                         printf(" file \"%s\"", ti->file);
1051                         continue;
1052                 }
1053                 printf(" {");
1054                 for (;;) {
1055                         for (h = ti->host; h != NULL; h = h->next) {
1056                                 printf(h->not ? " !" : " ");
1057                                 print_addr(&h->addr, h->af, 0);
1058                         }
1059                         nti = SIMPLEQ_NEXT(ti, entries);
1060                         if (nti != NULL && nti->file == NULL)
1061                                 ti = nti;       /* merge lists */
1062                         else
1063                                 break;
1064                 }
1065                 printf(" }");
1066         }
1067         if (addrs && SIMPLEQ_EMPTY(nodes))
1068                 printf(" { }");
1069         printf("\n");
1070 }
1071
1072 int
1073 parse_flags(const char *s)
1074 {
1075         const char      *p, *q;
1076         u_int8_t         f = 0;
1077
1078         for (p = s; *p; p++) {
1079                 if ((q = strchr(tcpflags, *p)) == NULL)
1080                         return -1;
1081                 else
1082                         f |= 1 << (q - tcpflags);
1083         }
1084         return (f ? f : PF_TH_ALL);
1085 }
1086
1087 void
1088 set_ipmask(struct node_host *h, u_int8_t b)
1089 {
1090         struct pf_addr  *m, *n;
1091         int              i, j = 0;
1092
1093         m = &h->addr.v.a.mask;
1094         memset(m, 0, sizeof(*m));
1095
1096         while (b >= 32) {
1097                 m->addr32[j++] = 0xffffffff;
1098                 b -= 32;
1099         }
1100         for (i = 31; i > 31-b; --i)
1101                 m->addr32[j] |= (1 << i);
1102         if (b)
1103                 m->addr32[j] = htonl(m->addr32[j]);
1104
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];
1110 }
1111
1112 int
1113 check_netmask(struct node_host *h, sa_family_t af)
1114 {
1115         struct node_host        *n = NULL;
1116         struct pf_addr  *m;
1117
1118         for (n = h; n != NULL; n = n->next) {
1119                 if (h->addr.type == PF_ADDR_TABLE)
1120                         continue;
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)
1125                         set_ipmask(n, 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));
1131                         return (1);
1132                 }
1133         }
1134         return (0);
1135 }
1136
1137 /* interface lookup routines */
1138
1139 struct node_host        *iftab;
1140
1141 void
1142 ifa_load(void)
1143 {
1144         struct ifaddrs          *ifap, *ifa;
1145         struct node_host        *n = NULL, *h = NULL;
1146
1147         if (getifaddrs(&ifap) < 0)
1148                 err(1, "getifaddrs");
1149
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))
1154                                 continue;
1155                 n = calloc(1, sizeof(struct node_host));
1156                 if (n == NULL)
1157                         err(1, "address: calloc");
1158                 n->af = ifa->ifa_addr->sa_family;
1159                 n->ifa_flags = ifa->ifa_flags;
1160 #ifdef __KAME__
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 ==
1165                     0) {
1166                         struct sockaddr_in6     *sin6;
1167
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;
1173                 }
1174 #endif
1175                 n->ifindex = 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;
1208                 }
1209                 if ((n->ifname = strdup(ifa->ifa_name)) == NULL)
1210                         err(1, "ifa_load: strdup");
1211                 n->next = NULL;
1212                 n->tail = n;
1213                 if (h == NULL)
1214                         h = n;
1215                 else {
1216                         h->tail->next = n;
1217                         h->tail = n;
1218                 }
1219         }
1220
1221         iftab = h;
1222         freeifaddrs(ifap);
1223 }
1224
1225 struct node_host *
1226 ifa_exists(const char *ifa_name)
1227 {
1228         struct node_host        *n;
1229         struct ifgroupreq       ifgr;
1230         int                     s;
1231
1232         if (iftab == NULL)
1233                 ifa_load();
1234
1235         /* check wether this is a group */
1236         if ((s = socket(AF_INET, SOCK_DGRAM, 0)) == -1)
1237                 err(1, "socket");
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)
1243                         err(1, "calloc");
1244                 if ((n->ifname = strdup(ifa_name)) == NULL)
1245                         err(1, "strdup");
1246                 close(s);
1247                 return (n);
1248         }
1249         close(s);
1250
1251         for (n = iftab; n; n = n->next) {
1252                 if (n->af == AF_LINK && !strncmp(n->ifname, ifa_name, IFNAMSIZ))
1253                         return (n);
1254         }
1255
1256         return (NULL);
1257 }
1258
1259 struct node_host *
1260 ifa_grouplookup(const char *ifa_name, int flags)
1261 {
1262         struct ifg_req          *ifg;
1263         struct ifgroupreq        ifgr;
1264         int                      s;
1265         size_t          len;
1266         struct node_host        *n, *h = NULL;
1267
1268         if ((s = socket(AF_INET, SOCK_DGRAM, 0)) == -1)
1269                 err(1, "socket");
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) {
1273                 close(s);
1274                 return (NULL);
1275         }
1276
1277         len = ifgr.ifgr_len;
1278         if ((ifgr.ifgr_groups = calloc(1, len)) == NULL)
1279                 err(1, "calloc");
1280         if (ioctl(s, SIOCGIFGMEMB, (caddr_t)&ifgr) == -1)
1281                 err(1, "SIOCGIFGMEMB");
1282
1283         for (ifg = ifgr.ifgr_groups; ifg && len >= sizeof(struct ifg_req);
1284             ifg++) {
1285                 len -= sizeof(struct ifg_req);
1286                 if ((n = ifa_lookup(ifg->ifgrq_member, flags)) == NULL)
1287                         continue;
1288                 if (h == NULL)
1289                         h = n;
1290                 else {
1291                         h->tail->next = n;
1292                         h->tail = n->tail;
1293                 }
1294         }
1295         free(ifgr.ifgr_groups);
1296         close(s);
1297
1298         return (h);
1299 }
1300
1301 struct node_host *
1302 ifa_lookup(const char *ifa_name, int flags)
1303 {
1304         struct node_host        *p = NULL, *h = NULL, *n = NULL;
1305         int                      got4 = 0, got6 = 0;
1306         const char               *last_if = NULL;
1307
1308         if ((h = ifa_grouplookup(ifa_name, flags)) != NULL)
1309                 return (h);
1310
1311         if (!strncmp(ifa_name, "self", IFNAMSIZ))
1312                 ifa_name = NULL;
1313
1314         if (iftab == NULL)
1315                 ifa_load();
1316
1317         for (p = iftab; p; p = p->next) {
1318                 if (ifa_skip_if(ifa_name, p))
1319                         continue;
1320                 if ((flags & PFI_AFLAG_BROADCAST) && p->af != AF_INET)
1321                         continue;
1322                 if ((flags & PFI_AFLAG_BROADCAST) &&
1323                     !(p->ifa_flags & IFF_BROADCAST))
1324                         continue;
1325                 if ((flags & PFI_AFLAG_PEER) &&
1326                     !(p->ifa_flags & IFF_POINTOPOINT))
1327                         continue;
1328                 if ((flags & PFI_AFLAG_NETWORK) && p->ifindex > 0)
1329                         continue;
1330                 if (last_if == NULL || strcmp(last_if, p->ifname))
1331                         got4 = got6 = 0;
1332                 last_if = p->ifname;
1333                 if ((flags & PFI_AFLAG_NOALIAS) && p->af == AF_INET && got4)
1334                         continue;
1335                 if ((flags & PFI_AFLAG_NOALIAS) && p->af == AF_INET6 && got6)
1336                         continue;
1337                 if (p->af == AF_INET)
1338                         got4 = 1;
1339                 else
1340                         got6 = 1;
1341                 n = calloc(1, sizeof(struct node_host));
1342                 if (n == NULL)
1343                         err(1, "address: calloc");
1344                 n->af = p->af;
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));
1351                 else
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));
1356                 else {
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,
1361                                             &p->addr.v.a.mask,
1362                                             sizeof(struct pf_addr));
1363                                 else
1364                                         set_ipmask(n, 32);
1365                         } else
1366                                 set_ipmask(n, 128);
1367                 }
1368                 n->ifindex = p->ifindex;
1369
1370                 n->next = NULL;
1371                 n->tail = n;
1372                 if (h == NULL)
1373                         h = n;
1374                 else {
1375                         h->tail->next = n;
1376                         h->tail = n;
1377                 }
1378         }
1379         return (h);
1380 }
1381
1382 int
1383 ifa_skip_if(const char *filter, struct node_host *p)
1384 {
1385         int     n;
1386
1387         if (p->af != AF_INET && p->af != AF_INET6)
1388                 return (1);
1389         if (filter == NULL || !*filter)
1390                 return (0);
1391         if (!strcmp(p->ifname, filter))
1392                 return (0);     /* exact match */
1393         n = strlen(filter);
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');
1401 }
1402
1403
1404 struct node_host *
1405 host(const char *s)
1406 {
1407         struct node_host        *h = NULL;
1408         int                      mask, v4mask, v6mask, cont = 1;
1409         char                    *p, *q, *ps;
1410
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);
1415                         return (NULL);
1416                 }
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;
1421         } else {
1422                 if ((ps = strdup(s)) == NULL)
1423                         err(1, "host: strdup");
1424                 v4mask = 32;
1425                 v6mask = 128;
1426                 mask = -1;
1427         }
1428
1429         /* interface with this name exists? */
1430         if (cont && (h = host_if(ps, mask)) != NULL)
1431                 cont = 0;
1432
1433         /* IPv4 address? */
1434         if (cont && (h = host_v4(s)) != NULL)
1435                 cont = 0;
1436
1437         /* IPv6 address? */
1438         if (cont && (h = host_v6(ps, v6mask)) != NULL)
1439                 cont = 0;
1440
1441         /* dns lookup */
1442         if (cont && (h = host_dns(ps, v4mask, v6mask)) != NULL)
1443                 cont = 0;
1444         free(ps);
1445
1446         if (h == NULL || cont == 1) {
1447                 fprintf(stderr, "no IP address found for %s\n", s);
1448                 return (NULL);
1449         }
1450         return (h);
1451 }
1452
1453 struct node_host *
1454 host_if(const char *s, int mask)
1455 {
1456         struct node_host        *n, *h = NULL;
1457         char                    *p, *ps;
1458         int                      flags = 0;
1459
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;
1471                 else {
1472                         free(ps);
1473                         return (NULL);
1474                 }
1475                 *p = '\0';
1476         }
1477         if (flags & (flags - 1) & PFI_AFLAG_MODEMASK) { /* Yep! */
1478                 fprintf(stderr, "illegal combination of interface modifiers\n");
1479                 free(ps);
1480                 return (NULL);
1481         }
1482         if ((flags & (PFI_AFLAG_NETWORK|PFI_AFLAG_BROADCAST)) && mask > -1) {
1483                 fprintf(stderr, "network or broadcast lookup, but "
1484                     "extra netmask given\n");
1485                 free(ps);
1486                 return (NULL);
1487         }
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);
1493         }
1494
1495         free(ps);
1496         return (h);
1497 }
1498
1499 static struct node_host *
1500 host_v4(const char *s)
1501 {
1502         struct node_host        *h = NULL;
1503         struct in_addr           ina;
1504         int                      bits = 32;
1505
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)
1509                         return (NULL);
1510         } else {
1511                 if (inet_pton(AF_INET, s, &ina) != 1)
1512                         return (NULL);
1513         }
1514
1515         h = calloc(1, sizeof(struct node_host));
1516         if (h == NULL)
1517                 err(1, "address: calloc");
1518         h->ifname = NULL;
1519         h->af = AF_INET;
1520         h->addr.v.a.addr.addr32[0] = ina.s_addr;
1521         set_ipmask(h, bits);
1522         h->next = NULL;
1523         h->tail = h;
1524
1525         return (h);
1526 }
1527
1528 struct node_host *
1529 host_v6(const char *s, int mask)
1530 {
1531         struct addrinfo          hints, *res;
1532         struct node_host        *h = NULL;
1533
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));
1540                 if (h == NULL)
1541                         err(1, "address: calloc");
1542                 h->ifname = NULL;
1543                 h->af = AF_INET6;
1544                 memcpy(&h->addr.v.a.addr,
1545                     &((struct sockaddr_in6 *)res->ai_addr)->sin6_addr,
1546                     sizeof(h->addr.v.a.addr));
1547                 h->ifindex =
1548                     ((struct sockaddr_in6 *)res->ai_addr)->sin6_scope_id;
1549                 set_ipmask(h, mask);
1550                 freeaddrinfo(res);
1551                 h->next = NULL;
1552                 h->tail = h;
1553         }
1554
1555         return (h);
1556 }
1557
1558 struct node_host *
1559 host_dns(const char *s, int v4mask, int v6mask)
1560 {
1561         struct addrinfo          hints, *res0, *res;
1562         struct node_host        *n, *h = NULL;
1563         int                      error, noalias = 0;
1564         int                      got4 = 0, got6 = 0;
1565         char                    *p, *ps;
1566
1567         if ((ps = strdup(s)) == NULL)
1568                 err(1, "host_dns: strdup");
1569         if ((p = strrchr(ps, ':')) != NULL && !strcmp(p, ":0")) {
1570                 noalias = 1;
1571                 *p = '\0';
1572         }
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);
1577         if (error) {
1578                 free(ps);
1579                 return (h);
1580         }
1581
1582         for (res = res0; res; res = res->ai_next) {
1583                 if (res->ai_family != AF_INET &&
1584                     res->ai_family != AF_INET6)
1585                         continue;
1586                 if (noalias) {
1587                         if (res->ai_family == AF_INET) {
1588                                 if (got4)
1589                                         continue;
1590                                 got4 = 1;
1591                         } else {
1592                                 if (got6)
1593                                         continue;
1594                                 got6 = 1;
1595                         }
1596                 }
1597                 n = calloc(1, sizeof(struct node_host));
1598                 if (n == NULL)
1599                         err(1, "host_dns: calloc");
1600                 n->ifname = NULL;
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);
1608                 } else {
1609                         memcpy(&n->addr.v.a.addr,
1610                             &((struct sockaddr_in6 *)
1611                             res->ai_addr)->sin6_addr.s6_addr,
1612                             sizeof(struct in6_addr));
1613                         n->ifindex =
1614                             ((struct sockaddr_in6 *)
1615                             res->ai_addr)->sin6_scope_id;
1616                         set_ipmask(n, v6mask);
1617                 }
1618                 n->next = NULL;
1619                 n->tail = n;
1620                 if (h == NULL)
1621                         h = n;
1622                 else {
1623                         h->tail->next = n;
1624                         h->tail = n;
1625                 }
1626         }
1627         freeaddrinfo(res0);
1628         free(ps);
1629
1630         return (h);
1631 }
1632
1633 /*
1634  * convert a hostname to a list of addresses and put them in the given buffer.
1635  * test:
1636  *      if set to 1, only simple addresses are accepted (no netblock, no "!").
1637  */
1638 int
1639 append_addr(struct pfr_buffer *b, char *s, int test)
1640 {
1641         char                     *r;
1642         struct node_host        *h, *n;
1643         int                      rv, not = 0;
1644
1645         for (r = s; *r == '!'; r++)
1646                 not = !not;
1647         if ((n = host(r)) == NULL) {
1648                 errno = 0;
1649                 return (-1);
1650         }
1651         rv = append_addr_host(b, n, test, not);
1652         do {
1653                 h = n;
1654                 n = n->next;
1655                 free(h);
1656         } while (n != NULL);
1657         return (rv);
1658 }
1659
1660 /*
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.
1663  * not:
1664  *      setting it to 1 is equivalent to adding "!" in front of parameter s.
1665  */
1666 int
1667 append_addr_host(struct pfr_buffer *b, struct node_host *n, int test, int not)
1668 {
1669         int                      bits;
1670         struct pfr_addr          addr;
1671
1672         do {
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);
1677                 switch (n->af) {
1678                 case AF_INET:
1679                         addr.pfra_ip4addr.s_addr = n->addr.v.a.addr.addr32[0];
1680                         bits = 32;
1681                         break;
1682                 case AF_INET6:
1683                         memcpy(&addr.pfra_ip6addr, &n->addr.v.a.addr.v6,
1684                             sizeof(struct in6_addr));
1685                         bits = 128;
1686                         break;
1687                 default:
1688                         errno = EINVAL;
1689                         return (-1);
1690                 }
1691                 if ((test && (not || addr.pfra_net != bits)) ||
1692                     addr.pfra_net > bits) {
1693                         errno = EINVAL;
1694                         return (-1);
1695                 }
1696                 if (pfr_buf_add(b, &addr))
1697                         return (-1);
1698         } while ((n = n->next) != NULL);
1699
1700         return (0);
1701 }
1702
1703 int
1704 pfctl_add_trans(struct pfr_buffer *buf, int rs_num, const char *anchor)
1705 {
1706         struct pfioc_trans_e trans;
1707
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");
1713
1714         return pfr_buf_add(buf, &trans);
1715 }
1716
1717 u_int32_t
1718 pfctl_get_ticket(struct pfr_buffer *buf, int rs_num, const char *anchor)
1719 {
1720         const struct pfioc_trans_e *p;
1721
1722         PFRB_FOREACH(p, buf)
1723                 if (rs_num == p->rs_num && !strcmp(anchor, p->anchor))
1724                         return (p->ticket);
1725         errx(1, "pfctl_get_ticket: assertion failed");
1726 }
1727
1728 int
1729 pfctl_trans(int dev, struct pfr_buffer *buf, u_long cmd, int from)
1730 {
1731         struct pfioc_trans trans;
1732
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);
1738 }