Make divert lookup similar for all socket types. If PF_TAG_DIVERTED
authorbluhm <bluhm@openbsd.org>
Mon, 4 Dec 2017 13:40:34 +0000 (13:40 +0000)
committerbluhm <bluhm@openbsd.org>
Mon, 4 Dec 2017 13:40:34 +0000 (13:40 +0000)
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 sashan@ visa@

sys/netinet/in_pcb.c
sys/netinet/ip_input.c
sys/netinet/raw_ip.c
sys/netinet/tcp_input.c
sys/netinet6/raw_ip6.c

index 785a34c..82c9575 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: in_pcb.c,v 1.226 2017/12/01 12:40:58 bluhm Exp $      */
+/*     $OpenBSD: in_pcb.c,v 1.227 2017/12/04 13:40:34 bluhm Exp $      */
 /*     $NetBSD: in_pcb.c,v 1.25 1996/02/13 23:41:53 christos Exp $     */
 
 /*
@@ -1147,10 +1147,19 @@ in_pcblookup_listen(struct inpcbtable *table, struct in_addr laddr,
        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 *table, struct in6_addr *laddr,
        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 695cf41..8428a89 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: ip_input.c,v 1.334 2017/11/23 13:45:46 mpi Exp $      */
+/*     $OpenBSD: ip_input.c,v 1.335 2017/12/04 13:40:34 bluhm Exp $    */
 /*     $NetBSD: ip_input.c,v 1.30 1996/03/16 23:53:58 christos Exp $   */
 
 /*
@@ -1769,12 +1769,15 @@ ip_savecontrol(struct inpcb *inp, struct mbuf **mp, struct ip *ip,
        }
        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 85986a6..79f2a0c 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: raw_ip.c,v 1.107 2017/11/28 16:05:46 bluhm Exp $      */
+/*     $OpenBSD: raw_ip.c,v 1.108 2017/12/04 13:40:34 bluhm Exp $      */
 /*     $NetBSD: raw_ip.c,v 1.25 1996/02/18 18:58:33 christos Exp $     */
 
 /*
@@ -121,6 +121,7 @@ rip_input(struct mbuf **mp, int *offp, int proto, int af)
        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, int proto, int af)
        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, int proto, int af)
 
                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 1112bce..d52fd57 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: tcp_input.c,v 1.353 2017/12/01 10:33:33 bluhm Exp $   */
+/*     $OpenBSD: tcp_input.c,v 1.354 2017/12/04 13:40:34 bluhm Exp $   */
 /*     $NetBSD: tcp_input.c,v 1.23 1996/02/13 23:43:44 christos Exp $  */
 
 /*
@@ -3454,9 +3454,6 @@ syn_cache_get(struct sockaddr *src, struct sockaddr *dst, struct tcphdr *th,
        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, struct sockaddr *dst, struct tcphdr *th,
        }
 
 #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;
+
+               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 17987db..8824f88 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: raw_ip6.c,v 1.124 2017/11/28 16:05:46 bluhm Exp $     */
+/*     $OpenBSD: raw_ip6.c,v 1.125 2017/12/04 13:40:35 bluhm Exp $     */
 /*     $KAME: raw_ip6.c,v 1.69 2001/03/04 15:55:44 itojun Exp $        */
 
 /*
@@ -122,6 +122,7 @@ rip6_input(struct mbuf **mp, int *offp, int proto, int af)
        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, int proto, int af)
        /* 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, int proto, int af)
                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))