The divert structure was using the port number to indicate that
authorbluhm <bluhm@openbsd.org>
Tue, 28 Nov 2017 16:05:46 +0000 (16:05 +0000)
committerbluhm <bluhm@openbsd.org>
Tue, 28 Nov 2017 16:05:46 +0000 (16:05 +0000)
divert-to or divert-reply was active.  If the address was also set,
it meant divert-to.  Divert packet used a separate structure.  This
is confusing and makes it hard to add new features.  It is better
to have a divert type that explicitly says what is configured.
Adapt the pf rule struct in kernel and pfctl, no functional change.
Note that kernel and pfctl have to be updated together.
OK sashan@

sbin/pfctl/parse.y
sbin/pfctl/pfctl_parser.c
sys/net/pf.c
sys/net/pf_ioctl.c
sys/net/pfvar.h
sys/netinet/raw_ip.c
sys/netinet6/raw_ip6.c

index 8b95b5d..06615c9 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: parse.y,v 1.667 2017/11/27 23:21:50 bluhm Exp $       */
+/*     $OpenBSD: parse.y,v 1.668 2017/11/28 16:05:46 bluhm Exp $       */
 
 /*
  * Copyright (c) 2001 Markus Friedl.  All rights reserved.
@@ -4084,7 +4084,7 @@ rule_consistent(struct pf_rule *r, int anchor_call)
        /* Basic rule sanity check. */
        switch (r->action) {
        case PF_MATCH:
-               if (r->divert.port) {
+               if (r->divert.type != PF_DIVERT_NONE) {
                        yyerror("divert is not supported on match rules");
                        problems++;
                }
@@ -4445,16 +4445,18 @@ expand_divertspec(struct pf_rule *r, struct divertspec *ds)
                        r->divert.addr = ds->addr->addr.v.a.addr;
                }
                r->divert.port = ds->port;
+               r->divert.type = ds->type;
                return (0);
        case PF_DIVERT_REPLY:
                if (r->direction == PF_IN) {
                        yyerror("divert-reply used with incoming rule");
                        return (1);
                }
-               r->divert.port = 1;  /* some random value */
+               r->divert.type = ds->type;
                return (0);
        case PF_DIVERT_PACKET:
-               r->divert_packet.port = ds->port;
+               r->divert.port = ds->port;
+               r->divert.type = ds->type;
                return (0);
        }
        return (1);
index 5963b6b..f0e4388 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: pfctl_parser.c,v 1.317 2017/11/13 11:30:11 henning Exp $ */
+/*     $OpenBSD: pfctl_parser.c,v 1.318 2017/11/28 16:05:47 bluhm Exp $ */
 
 /*
  * Copyright (c) 2001 Daniel Hartmeier
@@ -1077,24 +1077,31 @@ print_rule(struct pf_rule *r, const char *anchor_call, int opts)
        }
        if (r->rtableid != -1)
                printf(" rtable %u", r->rtableid);
-       if (r->divert.port) {
-               if (PF_AZERO(&r->divert.addr, AF_INET6)) {
-                       printf(" divert-reply");
-               } else {
-                       /* XXX cut&paste from print_addr */
-                       char buf[48];
+       switch (r->divert.type) {
+       case PF_DIVERT_NONE:
+               break;
+       case PF_DIVERT_TO: {
+               /* XXX cut&paste from print_addr */
+               char buf[48];
 
-                       printf(" divert-to ");
-                       if (inet_ntop(r->af, &r->divert.addr, buf,
-                           sizeof(buf)) == NULL)
-                               printf("?");
-                       else
-                               printf("%s", buf);
-                       printf(" port %u", ntohs(r->divert.port));
-               }
+               printf(" divert-to ");
+               if (inet_ntop(r->af, &r->divert.addr, buf, sizeof(buf)) == NULL)
+                       printf("?");
+               else
+                       printf("%s", buf);
+               printf(" port %u", ntohs(r->divert.port));
+               break;
+       }
+       case PF_DIVERT_REPLY:
+               printf(" divert-reply");
+               break;
+       case PF_DIVERT_PACKET:
+               printf(" divert-packet port %u", ntohs(r->divert.port));
+               break;
+       default:
+               printf(" divert ???");
+               break;
        }
-       if (r->divert_packet.port)
-               printf(" divert-packet port %u", ntohs(r->divert_packet.port));
 
        if (!anchor_call[0] && r->nat.addr.type != PF_ADDR_NONE &&
            r->rule_flag & PFRULE_AFTO) {
index ebedf21..01e60ba 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: pf.c,v 1.1047 2017/11/22 12:28:49 bluhm Exp $ */
+/*     $OpenBSD: pf.c,v 1.1048 2017/11/28 16:05:46 bluhm Exp $ */
 
 /*
  * Copyright (c) 2001 Daniel Hartmeier
@@ -1380,7 +1380,8 @@ pf_remove_divert_state(struct pf_state_key *sk)
 
        TAILQ_FOREACH(si, &sk->states, entry) {
                if (sk == si->s->key[PF_SK_STACK] && si->s->rule.ptr &&
-                   si->s->rule.ptr->divert.port) {
+                   (si->s->rule.ptr->divert.type == PF_DIVERT_TO ||
+                   si->s->rule.ptr->divert.type == PF_DIVERT_REPLY)) {
                        pf_remove_state(si->s);
                        break;
                }
@@ -6981,18 +6982,21 @@ done:
        if (pd.destchg && pd.dir == PF_OUT)
                pd.m->m_pkthdr.pf.flags |= PF_TAG_REROUTE;
 
-       if (pd.dir == PF_IN && action == PF_PASS && r->divert.port) {
+       if (pd.dir == PF_IN && action == PF_PASS &&
+           (r->divert.type == PF_DIVERT_TO ||
+           r->divert.type == PF_DIVERT_REPLY)) {
                struct pf_divert *divert;
 
                if ((divert = pf_get_divert(pd.m))) {
                        pd.m->m_pkthdr.pf.flags |= PF_TAG_DIVERTED;
+                       divert->addr = r->divert.addr;
                        divert->port = r->divert.port;
                        divert->rdomain = pd.rdomain;
-                       divert->addr = r->divert.addr;
+                       divert->type = r->divert.type;
                }
        }
 
-       if (action == PF_PASS && r->divert_packet.port)
+       if (action == PF_PASS && r->divert.type == PF_DIVERT_PACKET)
                action = PF_DIVERT;
 
 #if NPFLOG > 0
@@ -7023,13 +7027,12 @@ done:
        case PF_DIVERT:
                switch (pd.af) {
                case AF_INET:
-                       if (!divert_packet(pd.m, pd.dir, r->divert_packet.port))
+                       if (!divert_packet(pd.m, pd.dir, r->divert.port))
                                pd.m = NULL;
                        break;
 #ifdef INET6
                case AF_INET6:
-                       if (!divert6_packet(pd.m, pd.dir,
-                           r->divert_packet.port))
+                       if (!divert6_packet(pd.m, pd.dir, r->divert.port))
                                pd.m = NULL;
                        break;
 #endif /* INET6 */
index e392d53..ece1937 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: pf_ioctl.c,v 1.325 2017/11/13 11:30:11 henning Exp $ */
+/*     $OpenBSD: pf_ioctl.c,v 1.326 2017/11/28 16:05:46 bluhm Exp $ */
 
 /*
  * Copyright (c) 2001 Daniel Hartmeier
@@ -2796,8 +2796,7 @@ pf_rule_copyin(struct pf_rule *from, struct pf_rule *to,
        to->flush = from->flush;
        to->divert.addr = from->divert.addr;
        to->divert.port = from->divert.port;
-       to->divert_packet.addr = from->divert_packet.addr;
-       to->divert_packet.port = from->divert_packet.port;
+       to->divert.type = from->divert.type;
        to->prio = from->prio;
        to->set_prio[0] = from->set_prio[0];
        to->set_prio[1] = from->set_prio[1];
index ae849b4..27dcefb 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: pfvar.h,v 1.468 2017/11/27 23:21:50 bluhm Exp $ */
+/*     $OpenBSD: pfvar.h,v 1.469 2017/11/28 16:05:46 bluhm Exp $ */
 
 /*
  * Copyright (c) 2001 Daniel Hartmeier
@@ -590,7 +590,8 @@ struct pf_rule {
        struct {
                struct pf_addr          addr;
                u_int16_t               port;
-       }                       divert, divert_packet;
+               u_int8_t                type;
+       }                       divert;
 
        SLIST_ENTRY(pf_rule)     gcle;
        struct pf_ruleset       *ruleset;
@@ -1394,6 +1395,7 @@ struct pf_divert {
        struct pf_addr  addr;
        u_int16_t       port;
        u_int16_t       rdomain;
+       u_int8_t        type;
 };
 
 enum pf_divert_types {
index d969c5e..85986a6 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: raw_ip.c,v 1.106 2017/11/20 10:35:24 mpi Exp $        */
+/*     $OpenBSD: raw_ip.c,v 1.107 2017/11/28 16:05:46 bluhm Exp $      */
 /*     $NetBSD: raw_ip.c,v 1.25 1996/02/18 18:58:33 christos Exp $     */
 
 /*
@@ -149,7 +149,7 @@ rip_input(struct mbuf **mp, int *offp, int proto, int af)
                        /* XXX rdomain support */
                        if ((divert = pf_find_divert(m)) == NULL)
                                continue;
-                       if (!divert->addr.v4.s_addr)
+                       if (divert->type == PF_DIVERT_REPLY)
                                goto divert_reply;
                        if (inp->inp_laddr.s_addr != divert->addr.v4.s_addr)
                                continue;
index 0c0bd3b..17987db 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: raw_ip6.c,v 1.123 2017/11/20 10:35:24 mpi Exp $       */
+/*     $OpenBSD: raw_ip6.c,v 1.124 2017/11/28 16:05:46 bluhm Exp $     */
 /*     $KAME: raw_ip6.c,v 1.69 2001/03/04 15:55:44 itojun Exp $        */
 
 /*
@@ -152,7 +152,7 @@ rip6_input(struct mbuf **mp, int *offp, int proto, int af)
                        /* XXX rdomain support */
                        if ((divert = pf_find_divert(m)) == NULL)
                                continue;
-                       if (IN6_IS_ADDR_UNSPECIFIED(&divert->addr.v6))
+                       if (divert->type == PF_DIVERT_REPLY)
                                goto divert_reply;
                        if (!IN6_ARE_ADDR_EQUAL(&in6p->inp_laddr6,
                            &divert->addr.v6))