Hi, This converts the pf rule structure to use the divert type.
Old semantics was: divert.port: divert-to or divert-reply divert.addr: divert-to divert_packet.port: divert-packet Now we have one divert structure with an explicit type. ok? bluhm Index: sys/net/pf.c =================================================================== RCS file: /data/mirror/openbsd/cvs/src/sys/net/pf.c,v retrieving revision 1.1047 diff -u -p -r1.1047 pf.c --- sys/net/pf.c 22 Nov 2017 12:28:49 -0000 1.1047 +++ sys/net/pf.c 27 Nov 2017 23:25:27 -0000 @@ -1380,7 +1380,8 @@ pf_remove_divert_state(struct pf_state_k 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: sys/net/pf_ioctl.c =================================================================== RCS file: /data/mirror/openbsd/cvs/src/sys/net/pf_ioctl.c,v retrieving revision 1.325 diff -u -p -r1.325 pf_ioctl.c --- sys/net/pf_ioctl.c 13 Nov 2017 11:30:11 -0000 1.325 +++ sys/net/pf_ioctl.c 27 Nov 2017 23:25:27 -0000 @@ -2796,8 +2796,7 @@ pf_rule_copyin(struct pf_rule *from, str 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: sys/net/pfvar.h =================================================================== RCS file: /data/mirror/openbsd/cvs/src/sys/net/pfvar.h,v retrieving revision 1.468 diff -u -p -r1.468 pfvar.h --- sys/net/pfvar.h 27 Nov 2017 23:21:50 -0000 1.468 +++ sys/net/pfvar.h 27 Nov 2017 23:25:27 -0000 @@ -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: sys/netinet/raw_ip.c =================================================================== RCS file: /data/mirror/openbsd/cvs/src/sys/netinet/raw_ip.c,v retrieving revision 1.106 diff -u -p -r1.106 raw_ip.c --- sys/netinet/raw_ip.c 20 Nov 2017 10:35:24 -0000 1.106 +++ sys/netinet/raw_ip.c 27 Nov 2017 23:25:27 -0000 @@ -149,7 +149,7 @@ rip_input(struct mbuf **mp, int *offp, i /* 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: sys/netinet6/raw_ip6.c =================================================================== RCS file: /data/mirror/openbsd/cvs/src/sys/netinet6/raw_ip6.c,v retrieving revision 1.123 diff -u -p -r1.123 raw_ip6.c --- sys/netinet6/raw_ip6.c 20 Nov 2017 10:35:24 -0000 1.123 +++ sys/netinet6/raw_ip6.c 27 Nov 2017 23:25:27 -0000 @@ -152,7 +152,7 @@ rip6_input(struct mbuf **mp, int *offp, /* 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)) Index: sbin/pfctl/parse.y =================================================================== RCS file: /data/mirror/openbsd/cvs/src/sbin/pfctl/parse.y,v retrieving revision 1.667 diff -u -p -r1.667 parse.y --- sbin/pfctl/parse.y 27 Nov 2017 23:21:50 -0000 1.667 +++ sbin/pfctl/parse.y 27 Nov 2017 23:32:44 -0000 @@ -4084,7 +4084,7 @@ rule_consistent(struct pf_rule *r, int a /* 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, str 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: sbin/pfctl/pfctl_parser.c =================================================================== RCS file: /data/mirror/openbsd/cvs/src/sbin/pfctl/pfctl_parser.c,v retrieving revision 1.317 diff -u -p -r1.317 pfctl_parser.c --- sbin/pfctl/pfctl_parser.c 13 Nov 2017 11:30:11 -0000 1.317 +++ sbin/pfctl/pfctl_parser.c 27 Nov 2017 23:32:44 -0000 @@ -1077,24 +1077,31 @@ print_rule(struct pf_rule *r, const char } 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) {