Hi, I want to make divert lookup similar for all socket types:
If PF_TAG_DIVERTED is set, pf_find_divert() cannot fail so put an assert there. Explicitly check all possible divert types, panic in the default case. For raw sockets call pf_find_divert() before of the socket loop. Divert reply should not match on TCP or UDP listen sockets. ok? bluhm Index: netinet/in_pcb.c =================================================================== RCS file: /data/mirror/openbsd/cvs/src/sys/netinet/in_pcb.c,v retrieving revision 1.226 diff -u -p -r1.226 in_pcb.c --- netinet/in_pcb.c 1 Dec 2017 12:40:58 -0000 1.226 +++ netinet/in_pcb.c 1 Dec 2017 14:00:45 -0000 @@ -1147,10 +1147,19 @@ in_pcblookup_listen(struct inpcbtable *t if (m && m->m_pkthdr.pf.flags & PF_TAG_DIVERTED) { struct pf_divert *divert; - if ((divert = pf_find_divert(m)) == NULL) + divert = pf_find_divert(m); + KASSERT(divert != NULL); + switch (divert->type) { + case PF_DIVERT_TO: + key1 = key2 = &divert->addr.v4; + lport = divert->port; + break; + case PF_DIVERT_REPLY: return (NULL); - key1 = key2 = &divert->addr.v4; - lport = divert->port; + default: + panic("%s: unknown divert type %d, mbuf %p, divert %p", + __func__, divert->type, m, divert); + } } else if (m && m->m_pkthdr.pf.flags & PF_TAG_TRANSLATE_LOCALHOST) { key1 = &zeroin_addr; key2 = &laddr; @@ -1218,10 +1227,19 @@ in6_pcblookup_listen(struct inpcbtable * if (m && m->m_pkthdr.pf.flags & PF_TAG_DIVERTED) { struct pf_divert *divert; - if ((divert = pf_find_divert(m)) == NULL) + divert = pf_find_divert(m); + KASSERT(divert != NULL); + switch (divert->type) { + case PF_DIVERT_TO: + key1 = key2 = &divert->addr.v6; + lport = divert->port; + break; + case PF_DIVERT_REPLY: return (NULL); - key1 = key2 = &divert->addr.v6; - lport = divert->port; + default: + panic("%s: unknown divert type %d, mbuf %p, divert %p", + __func__, divert->type, m, divert); + } } else if (m && m->m_pkthdr.pf.flags & PF_TAG_TRANSLATE_LOCALHOST) { key1 = &zeroin6_addr; key2 = laddr; Index: netinet/ip_input.c =================================================================== RCS file: /data/mirror/openbsd/cvs/src/sys/netinet/ip_input.c,v retrieving revision 1.334 diff -u -p -r1.334 ip_input.c --- netinet/ip_input.c 23 Nov 2017 13:45:46 -0000 1.334 +++ netinet/ip_input.c 1 Dec 2017 13:51:00 -0000 @@ -1769,12 +1769,15 @@ ip_savecontrol(struct inpcb *inp, struct } if (inp->inp_flags & INP_RECVRTABLE) { u_int rtableid = inp->inp_rtableid; + #if NPF > 0 - struct pf_divert *divert; + if (m && m->m_pkthdr.pf.flags & PF_TAG_DIVERTED) { + struct pf_divert *divert; - if (m && m->m_pkthdr.pf.flags & PF_TAG_DIVERTED && - (divert = pf_find_divert(m)) != NULL) + divert = pf_find_divert(m); + KASSERT(divert != NULL); rtableid = divert->rdomain; + } #endif *mp = sbcreatecontrol((caddr_t) &rtableid, Index: netinet/raw_ip.c =================================================================== RCS file: /data/mirror/openbsd/cvs/src/sys/netinet/raw_ip.c,v retrieving revision 1.107 diff -u -p -r1.107 raw_ip.c --- netinet/raw_ip.c 28 Nov 2017 16:05:46 -0000 1.107 +++ netinet/raw_ip.c 1 Dec 2017 15:21:11 -0000 @@ -121,6 +121,7 @@ rip_input(struct mbuf **mp, int *offp, i struct mbuf *m = *mp; struct ip *ip = mtod(m, struct ip *); struct inpcb *inp, *last = NULL; + struct in_addr *key; struct mbuf *opts = NULL; struct counters_ref ref; uint64_t *counters; @@ -128,6 +129,25 @@ rip_input(struct mbuf **mp, int *offp, i KASSERT(af == AF_INET); ripsrc.sin_addr = ip->ip_src; + key = &ip->ip_dst; +#if NPF > 0 + if (m->m_pkthdr.pf.flags & PF_TAG_DIVERTED) { + struct pf_divert *divert; + + divert = pf_find_divert(m); + KASSERT(divert != NULL); + switch (divert->type) { + case PF_DIVERT_TO: + key = &divert->addr.v4; + break; + case PF_DIVERT_REPLY: + break; + default: + panic("%s: unknown divert type %d, mbuf %p, divert %p", + __func__, divert->type, m, divert); + } + } +#endif NET_ASSERT_LOCKED(); TAILQ_FOREACH(inp, &rawcbtable.inpt_queue, inp_queue) { if (inp->inp_socket->so_state & SS_CANTRCVMORE) @@ -142,22 +162,8 @@ rip_input(struct mbuf **mp, int *offp, i if (inp->inp_ip.ip_p && inp->inp_ip.ip_p != ip->ip_p) continue; -#if NPF > 0 - if (m->m_pkthdr.pf.flags & PF_TAG_DIVERTED) { - struct pf_divert *divert; - - /* XXX rdomain support */ - if ((divert = pf_find_divert(m)) == NULL) - continue; - if (divert->type == PF_DIVERT_REPLY) - goto divert_reply; - if (inp->inp_laddr.s_addr != divert->addr.v4.s_addr) - continue; - } else - divert_reply: -#endif if (inp->inp_laddr.s_addr && - inp->inp_laddr.s_addr != ip->ip_dst.s_addr) + inp->inp_laddr.s_addr != key->s_addr) continue; if (inp->inp_faddr.s_addr && inp->inp_faddr.s_addr != ip->ip_src.s_addr) Index: netinet/tcp_input.c =================================================================== RCS file: /data/mirror/openbsd/cvs/src/sys/netinet/tcp_input.c,v retrieving revision 1.353 diff -u -p -r1.353 tcp_input.c --- netinet/tcp_input.c 1 Dec 2017 10:33:33 -0000 1.353 +++ netinet/tcp_input.c 1 Dec 2017 13:49:50 -0000 @@ -3454,9 +3454,6 @@ syn_cache_get(struct sockaddr *src, stru struct tcpcb *tp = NULL; struct mbuf *am; struct socket *oso; -#if NPF > 0 - struct pf_divert *divert = NULL; -#endif NET_ASSERT_LOCKED(); @@ -3517,10 +3514,13 @@ syn_cache_get(struct sockaddr *src, stru } #if NPF > 0 - if (m && m->m_pkthdr.pf.flags & PF_TAG_DIVERTED && - (divert = pf_find_divert(m)) != NULL) + if (m && m->m_pkthdr.pf.flags & PF_TAG_DIVERTED) { + struct pf_divert *divert = NULL; + + divert = pf_find_divert(m); + KASSERT(divert != NULL); inp->inp_rtableid = divert->rdomain; - else + } else #endif /* inherit rtable from listening socket */ inp->inp_rtableid = sc->sc_rtableid; Index: netinet6/raw_ip6.c =================================================================== RCS file: /data/mirror/openbsd/cvs/src/sys/netinet6/raw_ip6.c,v retrieving revision 1.124 diff -u -p -r1.124 raw_ip6.c --- netinet6/raw_ip6.c 28 Nov 2017 16:05:46 -0000 1.124 +++ netinet6/raw_ip6.c 1 Dec 2017 15:21:11 -0000 @@ -122,6 +122,7 @@ rip6_input(struct mbuf **mp, int *offp, struct ip6_hdr *ip6 = mtod(m, struct ip6_hdr *); struct inpcb *in6p; struct inpcb *last = NULL; + struct in6_addr *key; struct sockaddr_in6 rip6src; struct mbuf *opts = NULL; @@ -136,6 +137,26 @@ rip6_input(struct mbuf **mp, int *offp, /* KAME hack: recover scopeid */ in6_recoverscope(&rip6src, &ip6->ip6_src); + key = &ip6->ip6_dst; +#if NPF > 0 + if (m->m_pkthdr.pf.flags & PF_TAG_DIVERTED) { + struct pf_divert *divert; + + /* XXX rdomain support */ + divert = pf_find_divert(m); + KASSERT(divert != NULL); + switch (divert->type) { + case PF_DIVERT_TO: + key = &divert->addr.v6; + break; + case PF_DIVERT_REPLY: + break; + default: + panic("%s: unknown divert type %d, mbuf %p, divert %p", + __func__, divert->type, m, divert); + } + } +#endif NET_ASSERT_LOCKED(); TAILQ_FOREACH(in6p, &rawin6pcbtable.inpt_queue, inp_queue) { if (in6p->inp_socket->so_state & SS_CANTRCVMORE) @@ -145,23 +166,8 @@ rip6_input(struct mbuf **mp, int *offp, if ((in6p->inp_ipv6.ip6_nxt || proto == IPPROTO_ICMPV6) && in6p->inp_ipv6.ip6_nxt != proto) continue; -#if NPF > 0 - if (m->m_pkthdr.pf.flags & PF_TAG_DIVERTED) { - struct pf_divert *divert; - - /* XXX rdomain support */ - if ((divert = pf_find_divert(m)) == NULL) - continue; - if (divert->type == PF_DIVERT_REPLY) - goto divert_reply; - if (!IN6_ARE_ADDR_EQUAL(&in6p->inp_laddr6, - &divert->addr.v6)) - continue; - } else - divert_reply: -#endif if (!IN6_IS_ADDR_UNSPECIFIED(&in6p->inp_laddr6) && - !IN6_ARE_ADDR_EQUAL(&in6p->inp_laddr6, &ip6->ip6_dst)) + !IN6_ARE_ADDR_EQUAL(&in6p->inp_laddr6, key)) continue; if (!IN6_IS_ADDR_UNSPECIFIED(&in6p->inp_faddr6) && !IN6_ARE_ADDR_EQUAL(&in6p->inp_faddr6, &ip6->ip6_src))