source: rtems-libbsd/freebsd/contrib/pf/pfctl/pfctl_parser.c @ 084d4db

4.11
Last change on this file since 084d4db was 084d4db, checked in by Christian Mauderer <Christian.Mauderer@…>, on 07/05/16 at 14:07:37

pfctl: Import sources from FreeBSD.

  • Property mode set to 100644
File size: 44.3 KB
Line 
1#include <machine/rtems-bsd-user-space.h>
2
3/*      $OpenBSD: pfctl_parser.c,v 1.240 2008/06/10 20:55:02 mcbride Exp $ */
4
5/*
6 * Copyright (c) 2001 Daniel Hartmeier
7 * Copyright (c) 2002,2003 Henning Brauer
8 * All rights reserved.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 *
14 *    - Redistributions of source code must retain the above copyright
15 *      notice, this list of conditions and the following disclaimer.
16 *    - Redistributions in binary form must reproduce the above
17 *      copyright notice, this list of conditions and the following
18 *      disclaimer in the documentation and/or other materials provided
19 *      with the distribution.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
25 * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
27 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
29 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
31 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
32 * POSSIBILITY OF SUCH DAMAGE.
33 *
34 */
35
36#include <sys/cdefs.h>
37__FBSDID("$FreeBSD$");
38
39#include <rtems/bsd/sys/types.h>
40#include <sys/ioctl.h>
41#include <sys/socket.h>
42#include <rtems/bsd/sys/param.h>
43#include <sys/proc.h>
44#include <net/if.h>
45#include <netinet/in.h>
46#include <netinet/in_systm.h>
47#include <netinet/ip.h>
48#include <netinet/ip_icmp.h>
49#include <netinet/icmp6.h>
50#include <net/pfvar.h>
51#include <arpa/inet.h>
52
53#include <stdio.h>
54#include <stdlib.h>
55#include <string.h>
56#include <ctype.h>
57#include <netdb.h>
58#include <stdarg.h>
59#include <errno.h>
60#include <err.h>
61#include <ifaddrs.h>
62#include <unistd.h>
63
64#include "pfctl_parser.h"
65#include "pfctl.h"
66
67void             print_op (u_int8_t, const char *, const char *);
68void             print_port (u_int8_t, u_int16_t, u_int16_t, const char *, int);
69void             print_ugid (u_int8_t, unsigned, unsigned, const char *, unsigned);
70void             print_flags (u_int8_t);
71void             print_fromto(struct pf_rule_addr *, pf_osfp_t,
72                    struct pf_rule_addr *, u_int8_t, u_int8_t, int, int);
73int              ifa_skip_if(const char *filter, struct node_host *p);
74
75struct node_host        *ifa_grouplookup(const char *, int);
76struct node_host        *host_if(const char *, int);
77struct node_host        *host_v4(const char *, int);
78struct node_host        *host_v6(const char *, int);
79struct node_host        *host_dns(const char *, int, int);
80
81const char *tcpflags = "FSRPAUEW";
82
83static const struct icmptypeent icmp_type[] = {
84        { "echoreq",    ICMP_ECHO },
85        { "echorep",    ICMP_ECHOREPLY },
86        { "unreach",    ICMP_UNREACH },
87        { "squench",    ICMP_SOURCEQUENCH },
88        { "redir",      ICMP_REDIRECT },
89        { "althost",    ICMP_ALTHOSTADDR },
90        { "routeradv",  ICMP_ROUTERADVERT },
91        { "routersol",  ICMP_ROUTERSOLICIT },
92        { "timex",      ICMP_TIMXCEED },
93        { "paramprob",  ICMP_PARAMPROB },
94        { "timereq",    ICMP_TSTAMP },
95        { "timerep",    ICMP_TSTAMPREPLY },
96        { "inforeq",    ICMP_IREQ },
97        { "inforep",    ICMP_IREQREPLY },
98        { "maskreq",    ICMP_MASKREQ },
99        { "maskrep",    ICMP_MASKREPLY },
100        { "trace",      ICMP_TRACEROUTE },
101        { "dataconv",   ICMP_DATACONVERR },
102        { "mobredir",   ICMP_MOBILE_REDIRECT },
103        { "ipv6-where", ICMP_IPV6_WHEREAREYOU },
104        { "ipv6-here",  ICMP_IPV6_IAMHERE },
105        { "mobregreq",  ICMP_MOBILE_REGREQUEST },
106        { "mobregrep",  ICMP_MOBILE_REGREPLY },
107        { "skip",       ICMP_SKIP },
108        { "photuris",   ICMP_PHOTURIS }
109};
110
111static const struct icmptypeent icmp6_type[] = {
112        { "unreach",    ICMP6_DST_UNREACH },
113        { "toobig",     ICMP6_PACKET_TOO_BIG },
114        { "timex",      ICMP6_TIME_EXCEEDED },
115        { "paramprob",  ICMP6_PARAM_PROB },
116        { "echoreq",    ICMP6_ECHO_REQUEST },
117        { "echorep",    ICMP6_ECHO_REPLY },
118        { "groupqry",   ICMP6_MEMBERSHIP_QUERY },
119        { "listqry",    MLD_LISTENER_QUERY },
120        { "grouprep",   ICMP6_MEMBERSHIP_REPORT },
121        { "listenrep",  MLD_LISTENER_REPORT },
122        { "groupterm",  ICMP6_MEMBERSHIP_REDUCTION },
123        { "listendone", MLD_LISTENER_DONE },
124        { "routersol",  ND_ROUTER_SOLICIT },
125        { "routeradv",  ND_ROUTER_ADVERT },
126        { "neighbrsol", ND_NEIGHBOR_SOLICIT },
127        { "neighbradv", ND_NEIGHBOR_ADVERT },
128        { "redir",      ND_REDIRECT },
129        { "routrrenum", ICMP6_ROUTER_RENUMBERING },
130        { "wrureq",     ICMP6_WRUREQUEST },
131        { "wrurep",     ICMP6_WRUREPLY },
132        { "fqdnreq",    ICMP6_FQDN_QUERY },
133        { "fqdnrep",    ICMP6_FQDN_REPLY },
134        { "niqry",      ICMP6_NI_QUERY },
135        { "nirep",      ICMP6_NI_REPLY },
136        { "mtraceresp", MLD_MTRACE_RESP },
137        { "mtrace",     MLD_MTRACE }
138};
139
140static const struct icmpcodeent icmp_code[] = {
141        { "net-unr",            ICMP_UNREACH,   ICMP_UNREACH_NET },
142        { "host-unr",           ICMP_UNREACH,   ICMP_UNREACH_HOST },
143        { "proto-unr",          ICMP_UNREACH,   ICMP_UNREACH_PROTOCOL },
144        { "port-unr",           ICMP_UNREACH,   ICMP_UNREACH_PORT },
145        { "needfrag",           ICMP_UNREACH,   ICMP_UNREACH_NEEDFRAG },
146        { "srcfail",            ICMP_UNREACH,   ICMP_UNREACH_SRCFAIL },
147        { "net-unk",            ICMP_UNREACH,   ICMP_UNREACH_NET_UNKNOWN },
148        { "host-unk",           ICMP_UNREACH,   ICMP_UNREACH_HOST_UNKNOWN },
149        { "isolate",            ICMP_UNREACH,   ICMP_UNREACH_ISOLATED },
150        { "net-prohib",         ICMP_UNREACH,   ICMP_UNREACH_NET_PROHIB },
151        { "host-prohib",        ICMP_UNREACH,   ICMP_UNREACH_HOST_PROHIB },
152        { "net-tos",            ICMP_UNREACH,   ICMP_UNREACH_TOSNET },
153        { "host-tos",           ICMP_UNREACH,   ICMP_UNREACH_TOSHOST },
154        { "filter-prohib",      ICMP_UNREACH,   ICMP_UNREACH_FILTER_PROHIB },
155        { "host-preced",        ICMP_UNREACH,   ICMP_UNREACH_HOST_PRECEDENCE },
156        { "cutoff-preced",      ICMP_UNREACH,   ICMP_UNREACH_PRECEDENCE_CUTOFF },
157        { "redir-net",          ICMP_REDIRECT,  ICMP_REDIRECT_NET },
158        { "redir-host",         ICMP_REDIRECT,  ICMP_REDIRECT_HOST },
159        { "redir-tos-net",      ICMP_REDIRECT,  ICMP_REDIRECT_TOSNET },
160        { "redir-tos-host",     ICMP_REDIRECT,  ICMP_REDIRECT_TOSHOST },
161        { "normal-adv",         ICMP_ROUTERADVERT, ICMP_ROUTERADVERT_NORMAL },
162        { "common-adv",         ICMP_ROUTERADVERT, ICMP_ROUTERADVERT_NOROUTE_COMMON },
163        { "transit",            ICMP_TIMXCEED,  ICMP_TIMXCEED_INTRANS },
164        { "reassemb",           ICMP_TIMXCEED,  ICMP_TIMXCEED_REASS },
165        { "badhead",            ICMP_PARAMPROB, ICMP_PARAMPROB_ERRATPTR },
166        { "optmiss",            ICMP_PARAMPROB, ICMP_PARAMPROB_OPTABSENT },
167        { "badlen",             ICMP_PARAMPROB, ICMP_PARAMPROB_LENGTH },
168        { "unknown-ind",        ICMP_PHOTURIS,  ICMP_PHOTURIS_UNKNOWN_INDEX },
169        { "auth-fail",          ICMP_PHOTURIS,  ICMP_PHOTURIS_AUTH_FAILED },
170        { "decrypt-fail",       ICMP_PHOTURIS,  ICMP_PHOTURIS_DECRYPT_FAILED }
171};
172
173static const struct icmpcodeent icmp6_code[] = {
174        { "admin-unr", ICMP6_DST_UNREACH, ICMP6_DST_UNREACH_ADMIN },
175        { "noroute-unr", ICMP6_DST_UNREACH, ICMP6_DST_UNREACH_NOROUTE },
176        { "notnbr-unr", ICMP6_DST_UNREACH, ICMP6_DST_UNREACH_NOTNEIGHBOR },
177        { "beyond-unr", ICMP6_DST_UNREACH, ICMP6_DST_UNREACH_BEYONDSCOPE },
178        { "addr-unr", ICMP6_DST_UNREACH, ICMP6_DST_UNREACH_ADDR },
179        { "port-unr", ICMP6_DST_UNREACH, ICMP6_DST_UNREACH_NOPORT },
180        { "transit", ICMP6_TIME_EXCEEDED, ICMP6_TIME_EXCEED_TRANSIT },
181        { "reassemb", ICMP6_TIME_EXCEEDED, ICMP6_TIME_EXCEED_REASSEMBLY },
182        { "badhead", ICMP6_PARAM_PROB, ICMP6_PARAMPROB_HEADER },
183        { "nxthdr", ICMP6_PARAM_PROB, ICMP6_PARAMPROB_NEXTHEADER },
184        { "redironlink", ND_REDIRECT, ND_REDIRECT_ONLINK },
185        { "redirrouter", ND_REDIRECT, ND_REDIRECT_ROUTER }
186};
187
188const struct pf_timeout pf_timeouts[] = {
189        { "tcp.first",          PFTM_TCP_FIRST_PACKET },
190        { "tcp.opening",        PFTM_TCP_OPENING },
191        { "tcp.established",    PFTM_TCP_ESTABLISHED },
192        { "tcp.closing",        PFTM_TCP_CLOSING },
193        { "tcp.finwait",        PFTM_TCP_FIN_WAIT },
194        { "tcp.closed",         PFTM_TCP_CLOSED },
195        { "tcp.tsdiff",         PFTM_TS_DIFF },
196        { "udp.first",          PFTM_UDP_FIRST_PACKET },
197        { "udp.single",         PFTM_UDP_SINGLE },
198        { "udp.multiple",       PFTM_UDP_MULTIPLE },
199        { "icmp.first",         PFTM_ICMP_FIRST_PACKET },
200        { "icmp.error",         PFTM_ICMP_ERROR_REPLY },
201        { "other.first",        PFTM_OTHER_FIRST_PACKET },
202        { "other.single",       PFTM_OTHER_SINGLE },
203        { "other.multiple",     PFTM_OTHER_MULTIPLE },
204        { "frag",               PFTM_FRAG },
205        { "interval",           PFTM_INTERVAL },
206        { "adaptive.start",     PFTM_ADAPTIVE_START },
207        { "adaptive.end",       PFTM_ADAPTIVE_END },
208        { "src.track",          PFTM_SRC_NODE },
209        { NULL,                 0 }
210};
211
212const struct icmptypeent *
213geticmptypebynumber(u_int8_t type, sa_family_t af)
214{
215        unsigned int    i;
216
217        if (af != AF_INET6) {
218                for (i=0; i < (sizeof (icmp_type) / sizeof(icmp_type[0]));
219                    i++) {
220                        if (type == icmp_type[i].type)
221                                return (&icmp_type[i]);
222                }
223        } else {
224                for (i=0; i < (sizeof (icmp6_type) /
225                    sizeof(icmp6_type[0])); i++) {
226                        if (type == icmp6_type[i].type)
227                                 return (&icmp6_type[i]);
228                }
229        }
230        return (NULL);
231}
232
233const struct icmptypeent *
234geticmptypebyname(char *w, sa_family_t af)
235{
236        unsigned int    i;
237
238        if (af != AF_INET6) {
239                for (i=0; i < (sizeof (icmp_type) / sizeof(icmp_type[0]));
240                    i++) {
241                        if (!strcmp(w, icmp_type[i].name))
242                                return (&icmp_type[i]);
243                }
244        } else {
245                for (i=0; i < (sizeof (icmp6_type) /
246                    sizeof(icmp6_type[0])); i++) {
247                        if (!strcmp(w, icmp6_type[i].name))
248                                return (&icmp6_type[i]);
249                }
250        }
251        return (NULL);
252}
253
254const struct icmpcodeent *
255geticmpcodebynumber(u_int8_t type, u_int8_t code, sa_family_t af)
256{
257        unsigned int    i;
258
259        if (af != AF_INET6) {
260                for (i=0; i < (sizeof (icmp_code) / sizeof(icmp_code[0]));
261                    i++) {
262                        if (type == icmp_code[i].type &&
263                            code == icmp_code[i].code)
264                                return (&icmp_code[i]);
265                }
266        } else {
267                for (i=0; i < (sizeof (icmp6_code) /
268                    sizeof(icmp6_code[0])); i++) {
269                        if (type == icmp6_code[i].type &&
270                            code == icmp6_code[i].code)
271                                return (&icmp6_code[i]);
272                }
273        }
274        return (NULL);
275}
276
277const struct icmpcodeent *
278geticmpcodebyname(u_long type, char *w, sa_family_t af)
279{
280        unsigned int    i;
281
282        if (af != AF_INET6) {
283                for (i=0; i < (sizeof (icmp_code) / sizeof(icmp_code[0]));
284                    i++) {
285                        if (type == icmp_code[i].type &&
286                            !strcmp(w, icmp_code[i].name))
287                                return (&icmp_code[i]);
288                }
289        } else {
290                for (i=0; i < (sizeof (icmp6_code) /
291                    sizeof(icmp6_code[0])); i++) {
292                        if (type == icmp6_code[i].type &&
293                            !strcmp(w, icmp6_code[i].name))
294                                return (&icmp6_code[i]);
295                }
296        }
297        return (NULL);
298}
299
300void
301print_op(u_int8_t op, const char *a1, const char *a2)
302{
303        if (op == PF_OP_IRG)
304                printf(" %s >< %s", a1, a2);
305        else if (op == PF_OP_XRG)
306                printf(" %s <> %s", a1, a2);
307        else if (op == PF_OP_EQ)
308                printf(" = %s", a1);
309        else if (op == PF_OP_NE)
310                printf(" != %s", a1);
311        else if (op == PF_OP_LT)
312                printf(" < %s", a1);
313        else if (op == PF_OP_LE)
314                printf(" <= %s", a1);
315        else if (op == PF_OP_GT)
316                printf(" > %s", a1);
317        else if (op == PF_OP_GE)
318                printf(" >= %s", a1);
319        else if (op == PF_OP_RRG)
320                printf(" %s:%s", a1, a2);
321}
322
323void
324print_port(u_int8_t op, u_int16_t p1, u_int16_t p2, const char *proto, int numeric)
325{
326        char             a1[6], a2[6];
327        struct servent  *s;
328
329        if (!numeric)
330                s = getservbyport(p1, proto);
331        else
332                s = NULL;
333        p1 = ntohs(p1);
334        p2 = ntohs(p2);
335        snprintf(a1, sizeof(a1), "%u", p1);
336        snprintf(a2, sizeof(a2), "%u", p2);
337        printf(" port");
338        if (s != NULL && (op == PF_OP_EQ || op == PF_OP_NE))
339                print_op(op, s->s_name, a2);
340        else
341                print_op(op, a1, a2);
342}
343
344void
345print_ugid(u_int8_t op, unsigned u1, unsigned u2, const char *t, unsigned umax)
346{
347        char    a1[11], a2[11];
348
349        snprintf(a1, sizeof(a1), "%u", u1);
350        snprintf(a2, sizeof(a2), "%u", u2);
351        printf(" %s", t);
352        if (u1 == umax && (op == PF_OP_EQ || op == PF_OP_NE))
353                print_op(op, "unknown", a2);
354        else
355                print_op(op, a1, a2);
356}
357
358void
359print_flags(u_int8_t f)
360{
361        int     i;
362
363        for (i = 0; tcpflags[i]; ++i)
364                if (f & (1 << i))
365                        printf("%c", tcpflags[i]);
366}
367
368void
369print_fromto(struct pf_rule_addr *src, pf_osfp_t osfp, struct pf_rule_addr *dst,
370    sa_family_t af, u_int8_t proto, int verbose, int numeric)
371{
372        char buf[PF_OSFP_LEN*3];
373        if (src->addr.type == PF_ADDR_ADDRMASK &&
374            dst->addr.type == PF_ADDR_ADDRMASK &&
375            PF_AZERO(&src->addr.v.a.addr, AF_INET6) &&
376            PF_AZERO(&src->addr.v.a.mask, AF_INET6) &&
377            PF_AZERO(&dst->addr.v.a.addr, AF_INET6) &&
378            PF_AZERO(&dst->addr.v.a.mask, AF_INET6) &&
379            !src->neg && !dst->neg &&
380            !src->port_op && !dst->port_op &&
381            osfp == PF_OSFP_ANY)
382                printf(" all");
383        else {
384                printf(" from ");
385                if (src->neg)
386                        printf("! ");
387                print_addr(&src->addr, af, verbose);
388                if (src->port_op)
389                        print_port(src->port_op, src->port[0],
390                            src->port[1],
391                            proto == IPPROTO_TCP ? "tcp" : "udp",
392                            numeric);
393                if (osfp != PF_OSFP_ANY)
394                        printf(" os \"%s\"", pfctl_lookup_fingerprint(osfp, buf,
395                            sizeof(buf)));
396
397                printf(" to ");
398                if (dst->neg)
399                        printf("! ");
400                print_addr(&dst->addr, af, verbose);
401                if (dst->port_op)
402                        print_port(dst->port_op, dst->port[0],
403                            dst->port[1],
404                            proto == IPPROTO_TCP ? "tcp" : "udp",
405                            numeric);
406        }
407}
408
409void
410print_pool(struct pf_pool *pool, u_int16_t p1, u_int16_t p2,
411    sa_family_t af, int id)
412{
413        struct pf_pooladdr      *pooladdr;
414
415        if ((TAILQ_FIRST(&pool->list) != NULL) &&
416            TAILQ_NEXT(TAILQ_FIRST(&pool->list), entries) != NULL)
417                printf("{ ");
418        TAILQ_FOREACH(pooladdr, &pool->list, entries){
419                switch (id) {
420                case PF_NAT:
421                case PF_RDR:
422                case PF_BINAT:
423                        print_addr(&pooladdr->addr, af, 0);
424                        break;
425                case PF_PASS:
426                        if (PF_AZERO(&pooladdr->addr.v.a.addr, af))
427                                printf("%s", pooladdr->ifname);
428                        else {
429                                printf("(%s ", pooladdr->ifname);
430                                print_addr(&pooladdr->addr, af, 0);
431                                printf(")");
432                        }
433                        break;
434                default:
435                        break;
436                }
437                if (TAILQ_NEXT(pooladdr, entries) != NULL)
438                        printf(", ");
439                else if (TAILQ_NEXT(TAILQ_FIRST(&pool->list), entries) != NULL)
440                        printf(" }");
441        }
442        switch (id) {
443        case PF_NAT:
444                if ((p1 != PF_NAT_PROXY_PORT_LOW ||
445                    p2 != PF_NAT_PROXY_PORT_HIGH) && (p1 != 0 || p2 != 0)) {
446                        if (p1 == p2)
447                                printf(" port %u", p1);
448                        else
449                                printf(" port %u:%u", p1, p2);
450                }
451                break;
452        case PF_RDR:
453                if (p1) {
454                        printf(" port %u", p1);
455                        if (p2 && (p2 != p1))
456                                printf(":%u", p2);
457                }
458                break;
459        default:
460                break;
461        }
462        switch (pool->opts & PF_POOL_TYPEMASK) {
463        case PF_POOL_NONE:
464                break;
465        case PF_POOL_BITMASK:
466                printf(" bitmask");
467                break;
468        case PF_POOL_RANDOM:
469                printf(" random");
470                break;
471        case PF_POOL_SRCHASH:
472                printf(" source-hash 0x%08x%08x%08x%08x",
473                    pool->key.key32[0], pool->key.key32[1],
474                    pool->key.key32[2], pool->key.key32[3]);
475                break;
476        case PF_POOL_ROUNDROBIN:
477                printf(" round-robin");
478                break;
479        }
480        if (pool->opts & PF_POOL_STICKYADDR)
481                printf(" sticky-address");
482        if (id == PF_NAT && p1 == 0 && p2 == 0)
483                printf(" static-port");
484}
485
486const char      *pf_reasons[PFRES_MAX+1] = PFRES_NAMES;
487const char      *pf_lcounters[LCNT_MAX+1] = LCNT_NAMES;
488const char      *pf_fcounters[FCNT_MAX+1] = FCNT_NAMES;
489const char      *pf_scounters[FCNT_MAX+1] = FCNT_NAMES;
490
491void
492print_status(struct pf_status *s, int opts)
493{
494        char                    statline[80], *running;
495        time_t                  runtime;
496        int                     i;
497        char                    buf[PF_MD5_DIGEST_LENGTH * 2 + 1];
498        static const char       hex[] = "0123456789abcdef";
499
500        runtime = time(NULL) - s->since;
501        running = s->running ? "Enabled" : "Disabled";
502
503        if (s->since) {
504                unsigned int    sec, min, hrs, day = runtime;
505
506                sec = day % 60;
507                day /= 60;
508                min = day % 60;
509                day /= 60;
510                hrs = day % 24;
511                day /= 24;
512                snprintf(statline, sizeof(statline),
513                    "Status: %s for %u days %.2u:%.2u:%.2u",
514                    running, day, hrs, min, sec);
515        } else
516                snprintf(statline, sizeof(statline), "Status: %s", running);
517        printf("%-44s", statline);
518        switch (s->debug) {
519        case PF_DEBUG_NONE:
520                printf("%15s\n\n", "Debug: None");
521                break;
522        case PF_DEBUG_URGENT:
523                printf("%15s\n\n", "Debug: Urgent");
524                break;
525        case PF_DEBUG_MISC:
526                printf("%15s\n\n", "Debug: Misc");
527                break;
528        case PF_DEBUG_NOISY:
529                printf("%15s\n\n", "Debug: Loud");
530                break;
531        }
532
533        if (opts & PF_OPT_VERBOSE) {
534                printf("Hostid:   0x%08x\n", ntohl(s->hostid));
535
536                for (i = 0; i < PF_MD5_DIGEST_LENGTH; i++) {
537                        buf[i + i] = hex[s->pf_chksum[i] >> 4];
538                        buf[i + i + 1] = hex[s->pf_chksum[i] & 0x0f];
539                }
540                buf[i + i] = '\0';
541                printf("Checksum: 0x%s\n\n", buf);
542        }
543
544        if (s->ifname[0] != 0) {
545                printf("Interface Stats for %-16s %5s %16s\n",
546                    s->ifname, "IPv4", "IPv6");
547                printf("  %-25s %14llu %16llu\n", "Bytes In",
548                    (unsigned long long)s->bcounters[0][0],
549                    (unsigned long long)s->bcounters[1][0]);
550                printf("  %-25s %14llu %16llu\n", "Bytes Out",
551                    (unsigned long long)s->bcounters[0][1],
552                    (unsigned long long)s->bcounters[1][1]);
553                printf("  Packets In\n");
554                printf("    %-23s %14llu %16llu\n", "Passed",
555                    (unsigned long long)s->pcounters[0][0][PF_PASS],
556                    (unsigned long long)s->pcounters[1][0][PF_PASS]);
557                printf("    %-23s %14llu %16llu\n", "Blocked",
558                    (unsigned long long)s->pcounters[0][0][PF_DROP],
559                    (unsigned long long)s->pcounters[1][0][PF_DROP]);
560                printf("  Packets Out\n");
561                printf("    %-23s %14llu %16llu\n", "Passed",
562                    (unsigned long long)s->pcounters[0][1][PF_PASS],
563                    (unsigned long long)s->pcounters[1][1][PF_PASS]);
564                printf("    %-23s %14llu %16llu\n\n", "Blocked",
565                    (unsigned long long)s->pcounters[0][1][PF_DROP],
566                    (unsigned long long)s->pcounters[1][1][PF_DROP]);
567        }
568        printf("%-27s %14s %16s\n", "State Table", "Total", "Rate");
569        printf("  %-25s %14u %14s\n", "current entries", s->states, "");
570        for (i = 0; i < FCNT_MAX; i++) {
571                printf("  %-25s %14llu ", pf_fcounters[i],
572                            (unsigned long long)s->fcounters[i]);
573                if (runtime > 0)
574                        printf("%14.1f/s\n",
575                            (double)s->fcounters[i] / (double)runtime);
576                else
577                        printf("%14s\n", "");
578        }
579        if (opts & PF_OPT_VERBOSE) {
580                printf("Source Tracking Table\n");
581                printf("  %-25s %14u %14s\n", "current entries",
582                    s->src_nodes, "");
583                for (i = 0; i < SCNT_MAX; i++) {
584                        printf("  %-25s %14lld ", pf_scounters[i],
585#ifdef __FreeBSD__
586                                    (long long)s->scounters[i]);
587#else
588                                    s->scounters[i]);
589#endif
590                        if (runtime > 0)
591                                printf("%14.1f/s\n",
592                                    (double)s->scounters[i] / (double)runtime);
593                        else
594                                printf("%14s\n", "");
595                }
596        }
597        printf("Counters\n");
598        for (i = 0; i < PFRES_MAX; i++) {
599                printf("  %-25s %14llu ", pf_reasons[i],
600                    (unsigned long long)s->counters[i]);
601                if (runtime > 0)
602                        printf("%14.1f/s\n",
603                            (double)s->counters[i] / (double)runtime);
604                else
605                        printf("%14s\n", "");
606        }
607        if (opts & PF_OPT_VERBOSE) {
608                printf("Limit Counters\n");
609                for (i = 0; i < LCNT_MAX; i++) {
610                        printf("  %-25s %14lld ", pf_lcounters[i],
611#ifdef __FreeBSD__
612                                    (unsigned long long)s->lcounters[i]);
613#else
614                                    s->lcounters[i]);
615#endif
616                        if (runtime > 0)
617                                printf("%14.1f/s\n",
618                                    (double)s->lcounters[i] / (double)runtime);
619                        else
620                                printf("%14s\n", "");
621                }
622        }
623}
624
625void
626print_src_node(struct pf_src_node *sn, int opts)
627{
628        struct pf_addr_wrap aw;
629        int min, sec;
630
631        memset(&aw, 0, sizeof(aw));
632        if (sn->af == AF_INET)
633                aw.v.a.mask.addr32[0] = 0xffffffff;
634        else
635                memset(&aw.v.a.mask, 0xff, sizeof(aw.v.a.mask));
636
637        aw.v.a.addr = sn->addr;
638        print_addr(&aw, sn->af, opts & PF_OPT_VERBOSE2);
639        printf(" -> ");
640        aw.v.a.addr = sn->raddr;
641        print_addr(&aw, sn->af, opts & PF_OPT_VERBOSE2);
642        printf(" ( states %u, connections %u, rate %u.%u/%us )\n", sn->states,
643            sn->conn, sn->conn_rate.count / 1000,
644            (sn->conn_rate.count % 1000) / 100, sn->conn_rate.seconds);
645        if (opts & PF_OPT_VERBOSE) {
646                sec = sn->creation % 60;
647                sn->creation /= 60;
648                min = sn->creation % 60;
649                sn->creation /= 60;
650                printf("   age %.2u:%.2u:%.2u", sn->creation, min, sec);
651                if (sn->states == 0) {
652                        sec = sn->expire % 60;
653                        sn->expire /= 60;
654                        min = sn->expire % 60;
655                        sn->expire /= 60;
656                        printf(", expires in %.2u:%.2u:%.2u",
657                            sn->expire, min, sec);
658                }
659                printf(", %llu pkts, %llu bytes",
660#ifdef __FreeBSD__
661                    (unsigned long long)(sn->packets[0] + sn->packets[1]),
662                    (unsigned long long)(sn->bytes[0] + sn->bytes[1]));
663#else
664                    sn->packets[0] + sn->packets[1],
665                    sn->bytes[0] + sn->bytes[1]);
666#endif
667                switch (sn->ruletype) {
668                case PF_NAT:
669                        if (sn->rule.nr != -1)
670                                printf(", nat rule %u", sn->rule.nr);
671                        break;
672                case PF_RDR:
673                        if (sn->rule.nr != -1)
674                                printf(", rdr rule %u", sn->rule.nr);
675                        break;
676                case PF_PASS:
677                        if (sn->rule.nr != -1)
678                                printf(", filter rule %u", sn->rule.nr);
679                        break;
680                }
681                printf("\n");
682        }
683}
684
685void
686print_rule(struct pf_rule *r, const char *anchor_call, int verbose, int numeric)
687{
688        static const char *actiontypes[] = { "pass", "block", "scrub",
689            "no scrub", "nat", "no nat", "binat", "no binat", "rdr", "no rdr" };
690        static const char *anchortypes[] = { "anchor", "anchor", "anchor",
691            "anchor", "nat-anchor", "nat-anchor", "binat-anchor",
692            "binat-anchor", "rdr-anchor", "rdr-anchor" };
693        int     i, opts;
694
695        if (verbose)
696                printf("@%d ", r->nr);
697        if (r->action > PF_NORDR)
698                printf("action(%d)", r->action);
699        else if (anchor_call[0]) {
700                if (anchor_call[0] == '_') {
701                        printf("%s", anchortypes[r->action]);
702                } else
703                        printf("%s \"%s\"", anchortypes[r->action],
704                            anchor_call);
705        } else {
706                printf("%s", actiontypes[r->action]);
707                if (r->natpass)
708                        printf(" pass");
709        }
710        if (r->action == PF_DROP) {
711                if (r->rule_flag & PFRULE_RETURN)
712                        printf(" return");
713                else if (r->rule_flag & PFRULE_RETURNRST) {
714                        if (!r->return_ttl)
715                                printf(" return-rst");
716                        else
717                                printf(" return-rst(ttl %d)", r->return_ttl);
718                } else if (r->rule_flag & PFRULE_RETURNICMP) {
719                        const struct icmpcodeent        *ic, *ic6;
720
721                        ic = geticmpcodebynumber(r->return_icmp >> 8,
722                            r->return_icmp & 255, AF_INET);
723                        ic6 = geticmpcodebynumber(r->return_icmp6 >> 8,
724                            r->return_icmp6 & 255, AF_INET6);
725
726                        switch (r->af) {
727                        case AF_INET:
728                                printf(" return-icmp");
729                                if (ic == NULL)
730                                        printf("(%u)", r->return_icmp & 255);
731                                else
732                                        printf("(%s)", ic->name);
733                                break;
734                        case AF_INET6:
735                                printf(" return-icmp6");
736                                if (ic6 == NULL)
737                                        printf("(%u)", r->return_icmp6 & 255);
738                                else
739                                        printf("(%s)", ic6->name);
740                                break;
741                        default:
742                                printf(" return-icmp");
743                                if (ic == NULL)
744                                        printf("(%u, ", r->return_icmp & 255);
745                                else
746                                        printf("(%s, ", ic->name);
747                                if (ic6 == NULL)
748                                        printf("%u)", r->return_icmp6 & 255);
749                                else
750                                        printf("%s)", ic6->name);
751                                break;
752                        }
753                } else
754                        printf(" drop");
755        }
756        if (r->direction == PF_IN)
757                printf(" in");
758        else if (r->direction == PF_OUT)
759                printf(" out");
760        if (r->log) {
761                printf(" log");
762                if (r->log & ~PF_LOG || r->logif) {
763                        int count = 0;
764
765                        printf(" (");
766                        if (r->log & PF_LOG_ALL)
767                                printf("%sall", count++ ? ", " : "");
768                        if (r->log & PF_LOG_SOCKET_LOOKUP)
769                                printf("%suser", count++ ? ", " : "");
770                        if (r->logif)
771                                printf("%sto pflog%u", count++ ? ", " : "",
772                                    r->logif);
773                        printf(")");
774                }
775        }
776        if (r->quick)
777                printf(" quick");
778        if (r->ifname[0]) {
779                if (r->ifnot)
780                        printf(" on ! %s", r->ifname);
781                else
782                        printf(" on %s", r->ifname);
783        }
784        if (r->rt) {
785                if (r->rt == PF_ROUTETO)
786                        printf(" route-to");
787                else if (r->rt == PF_REPLYTO)
788                        printf(" reply-to");
789                else if (r->rt == PF_DUPTO)
790                        printf(" dup-to");
791                else if (r->rt == PF_FASTROUTE)
792                        printf(" fastroute");
793                if (r->rt != PF_FASTROUTE) {
794                        printf(" ");
795                        print_pool(&r->rpool, 0, 0, r->af, PF_PASS);
796                }
797        }
798        if (r->af) {
799                if (r->af == AF_INET)
800                        printf(" inet");
801                else
802                        printf(" inet6");
803        }
804        if (r->proto) {
805                struct protoent *p;
806
807                if ((p = getprotobynumber(r->proto)) != NULL)
808                        printf(" proto %s", p->p_name);
809                else
810                        printf(" proto %u", r->proto);
811        }
812        print_fromto(&r->src, r->os_fingerprint, &r->dst, r->af, r->proto,
813            verbose, numeric);
814        if (r->uid.op)
815                print_ugid(r->uid.op, r->uid.uid[0], r->uid.uid[1], "user",
816                    UID_MAX);
817        if (r->gid.op)
818                print_ugid(r->gid.op, r->gid.gid[0], r->gid.gid[1], "group",
819                    GID_MAX);
820        if (r->flags || r->flagset) {
821                printf(" flags ");
822                print_flags(r->flags);
823                printf("/");
824                print_flags(r->flagset);
825        } else if (r->action == PF_PASS &&
826            (!r->proto || r->proto == IPPROTO_TCP) &&
827            !(r->rule_flag & PFRULE_FRAGMENT) &&
828            !anchor_call[0] && r->keep_state)
829                printf(" flags any");
830        if (r->type) {
831                const struct icmptypeent        *it;
832
833                it = geticmptypebynumber(r->type-1, r->af);
834                if (r->af != AF_INET6)
835                        printf(" icmp-type");
836                else
837                        printf(" icmp6-type");
838                if (it != NULL)
839                        printf(" %s", it->name);
840                else
841                        printf(" %u", r->type-1);
842                if (r->code) {
843                        const struct icmpcodeent        *ic;
844
845                        ic = geticmpcodebynumber(r->type-1, r->code-1, r->af);
846                        if (ic != NULL)
847                                printf(" code %s", ic->name);
848                        else
849                                printf(" code %u", r->code-1);
850                }
851        }
852        if (r->tos)
853                printf(" tos 0x%2.2x", r->tos);
854        if (!r->keep_state && r->action == PF_PASS && !anchor_call[0])
855                printf(" no state");
856        else if (r->keep_state == PF_STATE_NORMAL)
857                printf(" keep state");
858        else if (r->keep_state == PF_STATE_MODULATE)
859                printf(" modulate state");
860        else if (r->keep_state == PF_STATE_SYNPROXY)
861                printf(" synproxy state");
862        if (r->prob) {
863                char    buf[20];
864
865                snprintf(buf, sizeof(buf), "%f", r->prob*100.0/(UINT_MAX+1.0));
866                for (i = strlen(buf)-1; i > 0; i--) {
867                        if (buf[i] == '0')
868                                buf[i] = '\0';
869                        else {
870                                if (buf[i] == '.')
871                                        buf[i] = '\0';
872                                break;
873                        }
874                }
875                printf(" probability %s%%", buf);
876        }
877        opts = 0;
878        if (r->max_states || r->max_src_nodes || r->max_src_states)
879                opts = 1;
880        if (r->rule_flag & PFRULE_NOSYNC)
881                opts = 1;
882        if (r->rule_flag & PFRULE_SRCTRACK)
883                opts = 1;
884        if (r->rule_flag & PFRULE_IFBOUND)
885                opts = 1;
886        if (r->rule_flag & PFRULE_STATESLOPPY)
887                opts = 1;
888        for (i = 0; !opts && i < PFTM_MAX; ++i)
889                if (r->timeout[i])
890                        opts = 1;
891        if (opts) {
892                printf(" (");
893                if (r->max_states) {
894                        printf("max %u", r->max_states);
895                        opts = 0;
896                }
897                if (r->rule_flag & PFRULE_NOSYNC) {
898                        if (!opts)
899                                printf(", ");
900                        printf("no-sync");
901                        opts = 0;
902                }
903                if (r->rule_flag & PFRULE_SRCTRACK) {
904                        if (!opts)
905                                printf(", ");
906                        printf("source-track");
907                        if (r->rule_flag & PFRULE_RULESRCTRACK)
908                                printf(" rule");
909                        else
910                                printf(" global");
911                        opts = 0;
912                }
913                if (r->max_src_states) {
914                        if (!opts)
915                                printf(", ");
916                        printf("max-src-states %u", r->max_src_states);
917                        opts = 0;
918                }
919                if (r->max_src_conn) {
920                        if (!opts)
921                                printf(", ");
922                        printf("max-src-conn %u", r->max_src_conn);
923                        opts = 0;
924                }
925                if (r->max_src_conn_rate.limit) {
926                        if (!opts)
927                                printf(", ");
928                        printf("max-src-conn-rate %u/%u",
929                            r->max_src_conn_rate.limit,
930                            r->max_src_conn_rate.seconds);
931                        opts = 0;
932                }
933                if (r->max_src_nodes) {
934                        if (!opts)
935                                printf(", ");
936                        printf("max-src-nodes %u", r->max_src_nodes);
937                        opts = 0;
938                }
939                if (r->overload_tblname[0]) {
940                        if (!opts)
941                                printf(", ");
942                        printf("overload <%s>", r->overload_tblname);
943                        if (r->flush)
944                                printf(" flush");
945                        if (r->flush & PF_FLUSH_GLOBAL)
946                                printf(" global");
947                }
948                if (r->rule_flag & PFRULE_IFBOUND) {
949                        if (!opts)
950                                printf(", ");
951                        printf("if-bound");
952                        opts = 0;
953                }
954                if (r->rule_flag & PFRULE_STATESLOPPY) {
955                        if (!opts)
956                                printf(", ");
957                        printf("sloppy");
958                        opts = 0;
959                }
960                if (r->rule_flag & PFRULE_PFLOW) {
961                        if (!opts)
962                                printf(", ");
963                        printf("pflow");
964                        opts = 0;
965                }
966                for (i = 0; i < PFTM_MAX; ++i)
967                        if (r->timeout[i]) {
968                                int j;
969
970                                if (!opts)
971                                        printf(", ");
972                                opts = 0;
973                                for (j = 0; pf_timeouts[j].name != NULL;
974                                    ++j)
975                                        if (pf_timeouts[j].timeout == i)
976                                                break;
977                                printf("%s %u", pf_timeouts[j].name == NULL ?
978                                    "inv.timeout" : pf_timeouts[j].name,
979                                    r->timeout[i]);
980                        }
981                printf(")");
982        }
983        if (r->rule_flag & PFRULE_FRAGMENT)
984                printf(" fragment");
985        if (r->rule_flag & PFRULE_NODF)
986                printf(" no-df");
987        if (r->rule_flag & PFRULE_RANDOMID)
988                printf(" random-id");
989        if (r->min_ttl)
990                printf(" min-ttl %d", r->min_ttl);
991        if (r->max_mss)
992                printf(" max-mss %d", r->max_mss);
993        if (r->rule_flag & PFRULE_SET_TOS)
994                printf(" set-tos 0x%2.2x", r->set_tos);
995        if (r->allow_opts)
996                printf(" allow-opts");
997        if (r->action == PF_SCRUB) {
998                if (r->rule_flag & PFRULE_REASSEMBLE_TCP)
999                        printf(" reassemble tcp");
1000
1001                if (r->rule_flag & PFRULE_FRAGDROP)
1002                        printf(" fragment drop-ovl");
1003                else if (r->rule_flag & PFRULE_FRAGCROP)
1004                        printf(" fragment crop");
1005                else
1006                        printf(" fragment reassemble");
1007        }
1008        if (r->label[0])
1009                printf(" label \"%s\"", r->label);
1010        if (r->qname[0] && r->pqname[0])
1011                printf(" queue(%s, %s)", r->qname, r->pqname);
1012        else if (r->qname[0])
1013                printf(" queue %s", r->qname);
1014        if (r->tagname[0])
1015                printf(" tag %s", r->tagname);
1016        if (r->match_tagname[0]) {
1017                if (r->match_tag_not)
1018                        printf(" !");
1019                printf(" tagged %s", r->match_tagname);
1020        }
1021        if (r->rtableid != -1)
1022                printf(" rtable %u", r->rtableid);
1023        if (r->divert.port) {
1024#ifdef __FreeBSD__
1025                printf(" divert-to %u", ntohs(r->divert.port));
1026#else
1027                if (PF_AZERO(&r->divert.addr, r->af)) {
1028                        printf(" divert-reply");
1029                } else {
1030                        /* XXX cut&paste from print_addr */
1031                        char buf[48];
1032
1033                        printf(" divert-to ");
1034                        if (inet_ntop(r->af, &r->divert.addr, buf,
1035                            sizeof(buf)) == NULL)
1036                                printf("?");
1037                        else
1038                                printf("%s", buf);
1039                        printf(" port %u", ntohs(r->divert.port));
1040                }
1041#endif
1042        }
1043        if (!anchor_call[0] && (r->action == PF_NAT ||
1044            r->action == PF_BINAT || r->action == PF_RDR)) {
1045                printf(" -> ");
1046                print_pool(&r->rpool, r->rpool.proxy_port[0],
1047                    r->rpool.proxy_port[1], r->af, r->action);
1048        }
1049}
1050
1051void
1052print_tabledef(const char *name, int flags, int addrs,
1053    struct node_tinithead *nodes)
1054{
1055        struct node_tinit       *ti, *nti;
1056        struct node_host        *h;
1057
1058        printf("table <%s>", name);
1059        if (flags & PFR_TFLAG_CONST)
1060                printf(" const");
1061        if (flags & PFR_TFLAG_PERSIST)
1062                printf(" persist");
1063        if (flags & PFR_TFLAG_COUNTERS)
1064                printf(" counters");
1065        SIMPLEQ_FOREACH(ti, nodes, entries) {
1066                if (ti->file) {
1067                        printf(" file \"%s\"", ti->file);
1068                        continue;
1069                }
1070                printf(" {");
1071                for (;;) {
1072                        for (h = ti->host; h != NULL; h = h->next) {
1073                                printf(h->not ? " !" : " ");
1074                                print_addr(&h->addr, h->af, 0);
1075                        }
1076                        nti = SIMPLEQ_NEXT(ti, entries);
1077                        if (nti != NULL && nti->file == NULL)
1078                                ti = nti;       /* merge lists */
1079                        else
1080                                break;
1081                }
1082                printf(" }");
1083        }
1084        if (addrs && SIMPLEQ_EMPTY(nodes))
1085                printf(" { }");
1086        printf("\n");
1087}
1088
1089int
1090parse_flags(char *s)
1091{
1092        char            *p, *q;
1093        u_int8_t         f = 0;
1094
1095        for (p = s; *p; p++) {
1096                if ((q = strchr(tcpflags, *p)) == NULL)
1097                        return -1;
1098                else
1099                        f |= 1 << (q - tcpflags);
1100        }
1101        return (f ? f : PF_TH_ALL);
1102}
1103
1104void
1105set_ipmask(struct node_host *h, u_int8_t b)
1106{
1107        struct pf_addr  *m, *n;
1108        int              i, j = 0;
1109
1110        m = &h->addr.v.a.mask;
1111        memset(m, 0, sizeof(*m));
1112
1113        while (b >= 32) {
1114                m->addr32[j++] = 0xffffffff;
1115                b -= 32;
1116        }
1117        for (i = 31; i > 31-b; --i)
1118                m->addr32[j] |= (1 << i);
1119        if (b)
1120                m->addr32[j] = htonl(m->addr32[j]);
1121
1122        /* Mask off bits of the address that will never be used. */
1123        n = &h->addr.v.a.addr;
1124        if (h->addr.type == PF_ADDR_ADDRMASK)
1125                for (i = 0; i < 4; i++)
1126                        n->addr32[i] = n->addr32[i] & m->addr32[i];
1127}
1128
1129int
1130check_netmask(struct node_host *h, sa_family_t af)
1131{
1132        struct node_host        *n = NULL;
1133        struct pf_addr  *m;
1134
1135        for (n = h; n != NULL; n = n->next) {
1136                if (h->addr.type == PF_ADDR_TABLE)
1137                        continue;
1138                m = &h->addr.v.a.mask;
1139                /* fix up netmask for dynaddr */
1140                if (af == AF_INET && h->addr.type == PF_ADDR_DYNIFTL &&
1141                    unmask(m, AF_INET6) > 32)
1142                        set_ipmask(n, 32);
1143                /* netmasks > 32 bit are invalid on v4 */
1144                if (af == AF_INET &&
1145                    (m->addr32[1] || m->addr32[2] || m->addr32[3])) {
1146                        fprintf(stderr, "netmask %u invalid for IPv4 address\n",
1147                            unmask(m, AF_INET6));
1148                        return (1);
1149                }
1150        }
1151        return (0);
1152}
1153
1154/* interface lookup routines */
1155
1156struct node_host        *iftab;
1157
1158void
1159ifa_load(void)
1160{
1161        struct ifaddrs          *ifap, *ifa;
1162        struct node_host        *n = NULL, *h = NULL;
1163
1164        if (getifaddrs(&ifap) < 0)
1165                err(1, "getifaddrs");
1166
1167        for (ifa = ifap; ifa; ifa = ifa->ifa_next) {
1168                if (!(ifa->ifa_addr->sa_family == AF_INET ||
1169                    ifa->ifa_addr->sa_family == AF_INET6 ||
1170                    ifa->ifa_addr->sa_family == AF_LINK))
1171                                continue;
1172                n = calloc(1, sizeof(struct node_host));
1173                if (n == NULL)
1174                        err(1, "address: calloc");
1175                n->af = ifa->ifa_addr->sa_family;
1176                n->ifa_flags = ifa->ifa_flags;
1177#ifdef __KAME__
1178                if (n->af == AF_INET6 &&
1179                    IN6_IS_ADDR_LINKLOCAL(&((struct sockaddr_in6 *)
1180                    ifa->ifa_addr)->sin6_addr) &&
1181                    ((struct sockaddr_in6 *)ifa->ifa_addr)->sin6_scope_id ==
1182                    0) {
1183                        struct sockaddr_in6     *sin6;
1184
1185                        sin6 = (struct sockaddr_in6 *)ifa->ifa_addr;
1186                        sin6->sin6_scope_id = sin6->sin6_addr.s6_addr[2] << 8 |
1187                            sin6->sin6_addr.s6_addr[3];
1188                        sin6->sin6_addr.s6_addr[2] = 0;
1189                        sin6->sin6_addr.s6_addr[3] = 0;
1190                }
1191#endif
1192                n->ifindex = 0;
1193                if (n->af == AF_INET) {
1194                        memcpy(&n->addr.v.a.addr, &((struct sockaddr_in *)
1195                            ifa->ifa_addr)->sin_addr.s_addr,
1196                            sizeof(struct in_addr));
1197                        memcpy(&n->addr.v.a.mask, &((struct sockaddr_in *)
1198                            ifa->ifa_netmask)->sin_addr.s_addr,
1199                            sizeof(struct in_addr));
1200                        if (ifa->ifa_broadaddr != NULL)
1201                                memcpy(&n->bcast, &((struct sockaddr_in *)
1202                                    ifa->ifa_broadaddr)->sin_addr.s_addr,
1203                                    sizeof(struct in_addr));
1204                        if (ifa->ifa_dstaddr != NULL)
1205                                memcpy(&n->peer, &((struct sockaddr_in *)
1206                                    ifa->ifa_dstaddr)->sin_addr.s_addr,
1207                                    sizeof(struct in_addr));
1208                } else if (n->af == AF_INET6) {
1209                        memcpy(&n->addr.v.a.addr, &((struct sockaddr_in6 *)
1210                            ifa->ifa_addr)->sin6_addr.s6_addr,
1211                            sizeof(struct in6_addr));
1212                        memcpy(&n->addr.v.a.mask, &((struct sockaddr_in6 *)
1213                            ifa->ifa_netmask)->sin6_addr.s6_addr,
1214                            sizeof(struct in6_addr));
1215                        if (ifa->ifa_broadaddr != NULL)
1216                                memcpy(&n->bcast, &((struct sockaddr_in6 *)
1217                                    ifa->ifa_broadaddr)->sin6_addr.s6_addr,
1218                                    sizeof(struct in6_addr));
1219                        if (ifa->ifa_dstaddr != NULL)
1220                                 memcpy(&n->peer, &((struct sockaddr_in6 *)
1221                                    ifa->ifa_dstaddr)->sin6_addr.s6_addr,
1222                                    sizeof(struct in6_addr));
1223                        n->ifindex = ((struct sockaddr_in6 *)
1224                            ifa->ifa_addr)->sin6_scope_id;
1225                }
1226                if ((n->ifname = strdup(ifa->ifa_name)) == NULL)
1227                        err(1, "ifa_load: strdup");
1228                n->next = NULL;
1229                n->tail = n;
1230                if (h == NULL)
1231                        h = n;
1232                else {
1233                        h->tail->next = n;
1234                        h->tail = n;
1235                }
1236        }
1237
1238        iftab = h;
1239        freeifaddrs(ifap);
1240}
1241
1242struct node_host *
1243ifa_exists(const char *ifa_name)
1244{
1245        struct node_host        *n;
1246        struct ifgroupreq       ifgr;
1247        int                     s;
1248
1249        if (iftab == NULL)
1250                ifa_load();
1251
1252        /* check wether this is a group */
1253        if ((s = socket(AF_INET, SOCK_DGRAM, 0)) == -1)
1254                err(1, "socket");
1255        bzero(&ifgr, sizeof(ifgr));
1256        strlcpy(ifgr.ifgr_name, ifa_name, sizeof(ifgr.ifgr_name));
1257        if (ioctl(s, SIOCGIFGMEMB, (caddr_t)&ifgr) == 0) {
1258                /* fake a node_host */
1259                if ((n = calloc(1, sizeof(*n))) == NULL)
1260                        err(1, "calloc");
1261                if ((n->ifname = strdup(ifa_name)) == NULL)
1262                        err(1, "strdup");
1263                close(s);
1264                return (n);
1265        }
1266        close(s);
1267
1268        for (n = iftab; n; n = n->next) {
1269                if (n->af == AF_LINK && !strncmp(n->ifname, ifa_name, IFNAMSIZ))
1270                        return (n);
1271        }
1272
1273        return (NULL);
1274}
1275
1276struct node_host *
1277ifa_grouplookup(const char *ifa_name, int flags)
1278{
1279        struct ifg_req          *ifg;
1280        struct ifgroupreq        ifgr;
1281        int                      s, len;
1282        struct node_host        *n, *h = NULL;
1283
1284        if ((s = socket(AF_INET, SOCK_DGRAM, 0)) == -1)
1285                err(1, "socket");
1286        bzero(&ifgr, sizeof(ifgr));
1287        strlcpy(ifgr.ifgr_name, ifa_name, sizeof(ifgr.ifgr_name));
1288        if (ioctl(s, SIOCGIFGMEMB, (caddr_t)&ifgr) == -1) {
1289                close(s);
1290                return (NULL);
1291        }
1292
1293        len = ifgr.ifgr_len;
1294        if ((ifgr.ifgr_groups = calloc(1, len)) == NULL)
1295                err(1, "calloc");
1296        if (ioctl(s, SIOCGIFGMEMB, (caddr_t)&ifgr) == -1)
1297                err(1, "SIOCGIFGMEMB");
1298
1299        for (ifg = ifgr.ifgr_groups; ifg && len >= sizeof(struct ifg_req);
1300            ifg++) {
1301                len -= sizeof(struct ifg_req);
1302                if ((n = ifa_lookup(ifg->ifgrq_member, flags)) == NULL)
1303                        continue;
1304                if (h == NULL)
1305                        h = n;
1306                else {
1307                        h->tail->next = n;
1308                        h->tail = n->tail;
1309                }
1310        }
1311        free(ifgr.ifgr_groups);
1312        close(s);
1313
1314        return (h);
1315}
1316
1317struct node_host *
1318ifa_lookup(const char *ifa_name, int flags)
1319{
1320        struct node_host        *p = NULL, *h = NULL, *n = NULL;
1321        int                      got4 = 0, got6 = 0;
1322        const char               *last_if = NULL;
1323
1324        if ((h = ifa_grouplookup(ifa_name, flags)) != NULL)
1325                return (h);
1326
1327        if (!strncmp(ifa_name, "self", IFNAMSIZ))
1328                ifa_name = NULL;
1329
1330        if (iftab == NULL)
1331                ifa_load();
1332
1333        for (p = iftab; p; p = p->next) {
1334                if (ifa_skip_if(ifa_name, p))
1335                        continue;
1336                if ((flags & PFI_AFLAG_BROADCAST) && p->af != AF_INET)
1337                        continue;
1338                if ((flags & PFI_AFLAG_BROADCAST) &&
1339                    !(p->ifa_flags & IFF_BROADCAST))
1340                        continue;
1341                if ((flags & PFI_AFLAG_PEER) &&
1342                    !(p->ifa_flags & IFF_POINTOPOINT))
1343                        continue;
1344                if ((flags & PFI_AFLAG_NETWORK) && p->ifindex > 0)
1345                        continue;
1346                if (last_if == NULL || strcmp(last_if, p->ifname))
1347                        got4 = got6 = 0;
1348                last_if = p->ifname;
1349                if ((flags & PFI_AFLAG_NOALIAS) && p->af == AF_INET && got4)
1350                        continue;
1351                if ((flags & PFI_AFLAG_NOALIAS) && p->af == AF_INET6 && got6)
1352                        continue;
1353                if (p->af == AF_INET)
1354                        got4 = 1;
1355                else
1356                        got6 = 1;
1357                n = calloc(1, sizeof(struct node_host));
1358                if (n == NULL)
1359                        err(1, "address: calloc");
1360                n->af = p->af;
1361                if (flags & PFI_AFLAG_BROADCAST)
1362                        memcpy(&n->addr.v.a.addr, &p->bcast,
1363                            sizeof(struct pf_addr));
1364                else if (flags & PFI_AFLAG_PEER)
1365                        memcpy(&n->addr.v.a.addr, &p->peer,
1366                            sizeof(struct pf_addr));
1367                else
1368                        memcpy(&n->addr.v.a.addr, &p->addr.v.a.addr,
1369                            sizeof(struct pf_addr));
1370                if (flags & PFI_AFLAG_NETWORK)
1371                        set_ipmask(n, unmask(&p->addr.v.a.mask, n->af));
1372                else {
1373                        if (n->af == AF_INET) {
1374                                if (p->ifa_flags & IFF_LOOPBACK &&
1375                                    p->ifa_flags & IFF_LINK1)
1376                                        memcpy(&n->addr.v.a.mask,
1377                                            &p->addr.v.a.mask,
1378                                            sizeof(struct pf_addr));
1379                                else
1380                                        set_ipmask(n, 32);
1381                        } else
1382                                set_ipmask(n, 128);
1383                }
1384                n->ifindex = p->ifindex;
1385
1386                n->next = NULL;
1387                n->tail = n;
1388                if (h == NULL)
1389                        h = n;
1390                else {
1391                        h->tail->next = n;
1392                        h->tail = n;
1393                }
1394        }
1395        return (h);
1396}
1397
1398int
1399ifa_skip_if(const char *filter, struct node_host *p)
1400{
1401        int     n;
1402
1403        if (p->af != AF_INET && p->af != AF_INET6)
1404                return (1);
1405        if (filter == NULL || !*filter)
1406                return (0);
1407        if (!strcmp(p->ifname, filter))
1408                return (0);     /* exact match */
1409        n = strlen(filter);
1410        if (n < 1 || n >= IFNAMSIZ)
1411                return (1);     /* sanity check */
1412        if (filter[n-1] >= '0' && filter[n-1] <= '9')
1413                return (1);     /* only do exact match in that case */
1414        if (strncmp(p->ifname, filter, n))
1415                return (1);     /* prefix doesn't match */
1416        return (p->ifname[n] < '0' || p->ifname[n] > '9');
1417}
1418
1419
1420struct node_host *
1421host(const char *s)
1422{
1423        struct node_host        *h = NULL;
1424        int                      mask, v4mask, v6mask, cont = 1;
1425        char                    *p, *q, *ps;
1426
1427        if ((p = strrchr(s, '/')) != NULL) {
1428                mask = strtol(p+1, &q, 0);
1429                if (!q || *q || mask > 128 || q == (p+1)) {
1430                        fprintf(stderr, "invalid netmask '%s'\n", p);
1431                        return (NULL);
1432                }
1433                if ((ps = malloc(strlen(s) - strlen(p) + 1)) == NULL)
1434                        err(1, "host: malloc");
1435                strlcpy(ps, s, strlen(s) - strlen(p) + 1);
1436                v4mask = v6mask = mask;
1437        } else {
1438                if ((ps = strdup(s)) == NULL)
1439                        err(1, "host: strdup");
1440                v4mask = 32;
1441                v6mask = 128;
1442                mask = -1;
1443        }
1444
1445        /* interface with this name exists? */
1446        if (cont && (h = host_if(ps, mask)) != NULL)
1447                cont = 0;
1448
1449        /* IPv4 address? */
1450        if (cont && (h = host_v4(s, mask)) != NULL)
1451                cont = 0;
1452
1453        /* IPv6 address? */
1454        if (cont && (h = host_v6(ps, v6mask)) != NULL)
1455                cont = 0;
1456
1457        /* dns lookup */
1458        if (cont && (h = host_dns(ps, v4mask, v6mask)) != NULL)
1459                cont = 0;
1460        free(ps);
1461
1462        if (h == NULL || cont == 1) {
1463                fprintf(stderr, "no IP address found for %s\n", s);
1464                return (NULL);
1465        }
1466        return (h);
1467}
1468
1469struct node_host *
1470host_if(const char *s, int mask)
1471{
1472        struct node_host        *n, *h = NULL;
1473        char                    *p, *ps;
1474        int                      flags = 0;
1475
1476        if ((ps = strdup(s)) == NULL)
1477                err(1, "host_if: strdup");
1478        while ((p = strrchr(ps, ':')) != NULL) {
1479                if (!strcmp(p+1, "network"))
1480                        flags |= PFI_AFLAG_NETWORK;
1481                else if (!strcmp(p+1, "broadcast"))
1482                        flags |= PFI_AFLAG_BROADCAST;
1483                else if (!strcmp(p+1, "peer"))
1484                        flags |= PFI_AFLAG_PEER;
1485                else if (!strcmp(p+1, "0"))
1486                        flags |= PFI_AFLAG_NOALIAS;
1487                else {
1488                        free(ps);
1489                        return (NULL);
1490                }
1491                *p = '\0';
1492        }
1493        if (flags & (flags - 1) & PFI_AFLAG_MODEMASK) { /* Yep! */
1494                fprintf(stderr, "illegal combination of interface modifiers\n");
1495                free(ps);
1496                return (NULL);
1497        }
1498        if ((flags & (PFI_AFLAG_NETWORK|PFI_AFLAG_BROADCAST)) && mask > -1) {
1499                fprintf(stderr, "network or broadcast lookup, but "
1500                    "extra netmask given\n");
1501                free(ps);
1502                return (NULL);
1503        }
1504        if (ifa_exists(ps) || !strncmp(ps, "self", IFNAMSIZ)) {
1505                /* interface with this name exists */
1506                h = ifa_lookup(ps, flags);
1507                for (n = h; n != NULL && mask > -1; n = n->next)
1508                        set_ipmask(n, mask);
1509        }
1510
1511        free(ps);
1512        return (h);
1513}
1514
1515struct node_host *
1516host_v4(const char *s, int mask)
1517{
1518        struct node_host        *h = NULL;
1519        struct in_addr           ina;
1520        int                      bits = 32;
1521
1522        memset(&ina, 0, sizeof(struct in_addr));
1523        if (strrchr(s, '/') != NULL) {
1524                if ((bits = inet_net_pton(AF_INET, s, &ina, sizeof(ina))) == -1)
1525                        return (NULL);
1526        } else {
1527                if (inet_pton(AF_INET, s, &ina) != 1)
1528                        return (NULL);
1529        }
1530
1531        h = calloc(1, sizeof(struct node_host));
1532        if (h == NULL)
1533                err(1, "address: calloc");
1534        h->ifname = NULL;
1535        h->af = AF_INET;
1536        h->addr.v.a.addr.addr32[0] = ina.s_addr;
1537        set_ipmask(h, bits);
1538        h->next = NULL;
1539        h->tail = h;
1540
1541        return (h);
1542}
1543
1544struct node_host *
1545host_v6(const char *s, int mask)
1546{
1547        struct addrinfo          hints, *res;
1548        struct node_host        *h = NULL;
1549
1550        memset(&hints, 0, sizeof(hints));
1551        hints.ai_family = AF_INET6;
1552        hints.ai_socktype = SOCK_DGRAM; /*dummy*/
1553        hints.ai_flags = AI_NUMERICHOST;
1554        if (getaddrinfo(s, "0", &hints, &res) == 0) {
1555                h = calloc(1, sizeof(struct node_host));
1556                if (h == NULL)
1557                        err(1, "address: calloc");
1558                h->ifname = NULL;
1559                h->af = AF_INET6;
1560                memcpy(&h->addr.v.a.addr,
1561                    &((struct sockaddr_in6 *)res->ai_addr)->sin6_addr,
1562                    sizeof(h->addr.v.a.addr));
1563                h->ifindex =
1564                    ((struct sockaddr_in6 *)res->ai_addr)->sin6_scope_id;
1565                set_ipmask(h, mask);
1566                freeaddrinfo(res);
1567                h->next = NULL;
1568                h->tail = h;
1569        }
1570
1571        return (h);
1572}
1573
1574struct node_host *
1575host_dns(const char *s, int v4mask, int v6mask)
1576{
1577        struct addrinfo          hints, *res0, *res;
1578        struct node_host        *n, *h = NULL;
1579        int                      error, noalias = 0;
1580        int                      got4 = 0, got6 = 0;
1581        char                    *p, *ps;
1582
1583        if ((ps = strdup(s)) == NULL)
1584                err(1, "host_dns: strdup");
1585        if ((p = strrchr(ps, ':')) != NULL && !strcmp(p, ":0")) {
1586                noalias = 1;
1587                *p = '\0';
1588        }
1589        memset(&hints, 0, sizeof(hints));
1590        hints.ai_family = PF_UNSPEC;
1591        hints.ai_socktype = SOCK_STREAM; /* DUMMY */
1592        error = getaddrinfo(ps, NULL, &hints, &res0);
1593        if (error) {
1594                free(ps);
1595                return (h);
1596        }
1597
1598        for (res = res0; res; res = res->ai_next) {
1599                if (res->ai_family != AF_INET &&
1600                    res->ai_family != AF_INET6)
1601                        continue;
1602                if (noalias) {
1603                        if (res->ai_family == AF_INET) {
1604                                if (got4)
1605                                        continue;
1606                                got4 = 1;
1607                        } else {
1608                                if (got6)
1609                                        continue;
1610                                got6 = 1;
1611                        }
1612                }
1613                n = calloc(1, sizeof(struct node_host));
1614                if (n == NULL)
1615                        err(1, "host_dns: calloc");
1616                n->ifname = NULL;
1617                n->af = res->ai_family;
1618                if (res->ai_family == AF_INET) {
1619                        memcpy(&n->addr.v.a.addr,
1620                            &((struct sockaddr_in *)
1621                            res->ai_addr)->sin_addr.s_addr,
1622                            sizeof(struct in_addr));
1623                        set_ipmask(n, v4mask);
1624                } else {
1625                        memcpy(&n->addr.v.a.addr,
1626                            &((struct sockaddr_in6 *)
1627                            res->ai_addr)->sin6_addr.s6_addr,
1628                            sizeof(struct in6_addr));
1629                        n->ifindex =
1630                            ((struct sockaddr_in6 *)
1631                            res->ai_addr)->sin6_scope_id;
1632                        set_ipmask(n, v6mask);
1633                }
1634                n->next = NULL;
1635                n->tail = n;
1636                if (h == NULL)
1637                        h = n;
1638                else {
1639                        h->tail->next = n;
1640                        h->tail = n;
1641                }
1642        }
1643        freeaddrinfo(res0);
1644        free(ps);
1645
1646        return (h);
1647}
1648
1649/*
1650 * convert a hostname to a list of addresses and put them in the given buffer.
1651 * test:
1652 *      if set to 1, only simple addresses are accepted (no netblock, no "!").
1653 */
1654int
1655append_addr(struct pfr_buffer *b, char *s, int test)
1656{
1657        char                     *r;
1658        struct node_host        *h, *n;
1659        int                      rv, not = 0;
1660
1661        for (r = s; *r == '!'; r++)
1662                not = !not;
1663        if ((n = host(r)) == NULL) {
1664                errno = 0;
1665                return (-1);
1666        }
1667        rv = append_addr_host(b, n, test, not);
1668        do {
1669                h = n;
1670                n = n->next;
1671                free(h);
1672        } while (n != NULL);
1673        return (rv);
1674}
1675
1676/*
1677 * same as previous function, but with a pre-parsed input and the ability
1678 * to "negate" the result. Does not free the node_host list.
1679 * not:
1680 *      setting it to 1 is equivalent to adding "!" in front of parameter s.
1681 */
1682int
1683append_addr_host(struct pfr_buffer *b, struct node_host *n, int test, int not)
1684{
1685        int                      bits;
1686        struct pfr_addr          addr;
1687
1688        do {
1689                bzero(&addr, sizeof(addr));
1690                addr.pfra_not = n->not ^ not;
1691                addr.pfra_af = n->af;
1692                addr.pfra_net = unmask(&n->addr.v.a.mask, n->af);
1693                switch (n->af) {
1694                case AF_INET:
1695                        addr.pfra_ip4addr.s_addr = n->addr.v.a.addr.addr32[0];
1696                        bits = 32;
1697                        break;
1698                case AF_INET6:
1699                        memcpy(&addr.pfra_ip6addr, &n->addr.v.a.addr.v6,
1700                            sizeof(struct in6_addr));
1701                        bits = 128;
1702                        break;
1703                default:
1704                        errno = EINVAL;
1705                        return (-1);
1706                }
1707                if ((test && (not || addr.pfra_net != bits)) ||
1708                    addr.pfra_net > bits) {
1709                        errno = EINVAL;
1710                        return (-1);
1711                }
1712                if (pfr_buf_add(b, &addr))
1713                        return (-1);
1714        } while ((n = n->next) != NULL);
1715
1716        return (0);
1717}
1718
1719int
1720pfctl_add_trans(struct pfr_buffer *buf, int rs_num, const char *anchor)
1721{
1722        struct pfioc_trans_e trans;
1723
1724        bzero(&trans, sizeof(trans));
1725        trans.rs_num = rs_num;
1726        if (strlcpy(trans.anchor, anchor,
1727            sizeof(trans.anchor)) >= sizeof(trans.anchor))
1728                errx(1, "pfctl_add_trans: strlcpy");
1729
1730        return pfr_buf_add(buf, &trans);
1731}
1732
1733u_int32_t
1734pfctl_get_ticket(struct pfr_buffer *buf, int rs_num, const char *anchor)
1735{
1736        struct pfioc_trans_e *p;
1737
1738        PFRB_FOREACH(p, buf)
1739                if (rs_num == p->rs_num && !strcmp(anchor, p->anchor))
1740                        return (p->ticket);
1741        errx(1, "pfctl_get_ticket: assertion failed");
1742}
1743
1744int
1745pfctl_trans(int dev, struct pfr_buffer *buf, u_long cmd, int from)
1746{
1747        struct pfioc_trans trans;
1748
1749        bzero(&trans, sizeof(trans));
1750        trans.size = buf->pfrb_size - from;
1751        trans.esize = sizeof(struct pfioc_trans_e);
1752        trans.array = ((struct pfioc_trans_e *)buf->pfrb_caddr) + from;
1753        return ioctl(dev, cmd, &trans);
1754}
Note: See TracBrowser for help on using the repository browser.