Hi,

I would like to simplify the reverse pcb lookup logic.  The
PF_TAG_TRANSLATE_LOCALHOST security check predates the divert
feature.  It prevents that you accidentally use redirect where a
divert-to would be appropriate.

Instead of spreading the logic into tcp and udp input, we could
just check the flag during pcb listen lookup.  This also reduces
parameters of in_pcblookup_listen().

I also cleaned up the #if, if, else if, else logic in
in_pcblookup_listen().  Set the default in front, do the special
pf things afterwards.

ok?

bluhm

Index: net/pf.c
===================================================================
RCS file: /data/mirror/openbsd/cvs/src/sys/net/pf.c,v
retrieving revision 1.1048
diff -u -p -r1.1048 pf.c
--- net/pf.c    28 Nov 2017 16:05:46 -0000      1.1048
+++ net/pf.c    30 Nov 2017 16:56:32 -0000
@@ -3224,7 +3224,7 @@ pf_socket_lookup(struct pf_pdesc *pd)
                inp = in_pcbhashlookup(tb, saddr->v4, sport, daddr->v4, dport,
                    pd->rdomain);
                if (inp == NULL) {
-                       inp = in_pcblookup_listen(tb, daddr->v4, dport, 0,
+                       inp = in_pcblookup_listen(tb, daddr->v4, dport,
                            NULL, pd->rdomain);
                        if (inp == NULL)
                                return (-1);
@@ -3235,7 +3235,7 @@ pf_socket_lookup(struct pf_pdesc *pd)
                inp = in6_pcbhashlookup(tb, &saddr->v6, sport, &daddr->v6,
                    dport, pd->rdomain);
                if (inp == NULL) {
-                       inp = in6_pcblookup_listen(tb, &daddr->v6, dport, 0,
+                       inp = in6_pcblookup_listen(tb, &daddr->v6, dport,
                            NULL, pd->rdomain);
                        if (inp == NULL)
                                return (-1);
@@ -6971,7 +6971,7 @@ done:
        /*
         * connections redirected to loopback should not match sockets
         * bound specifically to loopback due to security implications,
-        * see tcp_input() and in_pcblookup_listen().
+        * see in_pcblookup_listen().
         */
        if (pd.destchg)
                if ((pd.af == AF_INET && (ntohl(pd.dst->v4.s_addr) >>
Index: netinet/in_pcb.c
===================================================================
RCS file: /data/mirror/openbsd/cvs/src/sys/netinet/in_pcb.c,v
retrieving revision 1.224
diff -u -p -r1.224 in_pcb.c
--- netinet/in_pcb.c    11 Aug 2017 19:53:02 -0000      1.224
+++ netinet/in_pcb.c    30 Nov 2017 16:29:58 -0000
@@ -1133,7 +1133,7 @@ in6_pcbhashlookup(struct inpcbtable *tab
  */
 struct inpcb *
 in_pcblookup_listen(struct inpcbtable *table, struct in_addr laddr,
-    u_int lport_arg, int reverse, struct mbuf *m, u_int rdomain)
+    u_int lport_arg, struct mbuf *m, u_int rdomain)
 {
        struct inpcbhead *head;
        struct in_addr *key1, *key2;
@@ -1141,6 +1141,8 @@ in_pcblookup_listen(struct inpcbtable *t
        u_int16_t lport = lport_arg;
 
        rdomain = rtable_l2(rdomain);   /* convert passed rtableid to rdomain */
+       key1 = &laddr;
+       key2 = &zeroin_addr;
 #if NPF > 0
        if (m && m->m_pkthdr.pf.flags & PF_TAG_DIVERTED) {
                struct pf_divert *divert;
@@ -1149,15 +1151,11 @@ in_pcblookup_listen(struct inpcbtable *t
                        return (NULL);
                key1 = key2 = &divert->addr.v4;
                lport = divert->port;
-       } else
-#endif
-       if (reverse) {
+       } else if (m && m->m_pkthdr.pf.flags & PF_TAG_TRANSLATE_LOCALHOST) {
                key1 = &zeroin_addr;
                key2 = &laddr;
-       } else {
-               key1 = &laddr;
-               key2 = &zeroin_addr;
        }
+#endif
 
        head = INPCBHASH(table, &zeroin_addr, 0, key1, lport, rdomain);
        LIST_FOREACH(inp, head, inp_hash) {
@@ -1206,7 +1204,7 @@ in_pcblookup_listen(struct inpcbtable *t
 #ifdef INET6
 struct inpcb *
 in6_pcblookup_listen(struct inpcbtable *table, struct in6_addr *laddr,
-    u_int lport_arg, int reverse, struct mbuf *m, u_int rtable)
+    u_int lport_arg, struct mbuf *m, u_int rtable)
 {
        struct inpcbhead *head;
        struct in6_addr *key1, *key2;
@@ -1214,6 +1212,8 @@ in6_pcblookup_listen(struct inpcbtable *
        u_int16_t lport = lport_arg;
 
        rtable = rtable_l2(rtable);     /* convert passed rtableid to rdomain */
+       key1 = laddr;
+       key2 = &zeroin6_addr;
 #if NPF > 0
        if (m && m->m_pkthdr.pf.flags & PF_TAG_DIVERTED) {
                struct pf_divert *divert;
@@ -1222,15 +1222,11 @@ in6_pcblookup_listen(struct inpcbtable *
                        return (NULL);
                key1 = key2 = &divert->addr.v6;
                lport = divert->port;
-       } else
-#endif
-       if (reverse) {
+       } else if (m && m->m_pkthdr.pf.flags & PF_TAG_TRANSLATE_LOCALHOST) {
                key1 = &zeroin6_addr;
                key2 = laddr;
-       } else {
-               key1 = laddr;
-               key2 = &zeroin6_addr;
        }
+#endif
 
        head = IN6PCBHASH(table, &zeroin6_addr, 0, key1, lport, rtable);
        LIST_FOREACH(inp, head, inp_hash) {
Index: netinet/in_pcb.h
===================================================================
RCS file: /data/mirror/openbsd/cvs/src/sys/netinet/in_pcb.h,v
retrieving revision 1.105
diff -u -p -r1.105 in_pcb.h
--- netinet/in_pcb.h    6 Oct 2017 21:14:55 -0000       1.105
+++ netinet/in_pcb.h    30 Nov 2017 15:58:42 -0000
@@ -263,16 +263,15 @@ struct inpcb *
         in_pcbhashlookup(struct inpcbtable *, struct in_addr,
                               u_int, struct in_addr, u_int, u_int);
 struct inpcb *
-        in_pcblookup_listen(struct inpcbtable *, struct in_addr, u_int, int,
+        in_pcblookup_listen(struct inpcbtable *, struct in_addr, u_int,
            struct mbuf *, u_int);
 #ifdef INET6
 struct inpcb *
         in6_pcbhashlookup(struct inpcbtable *, const struct in6_addr *,
                               u_int, const struct in6_addr *, u_int, u_int);
 struct inpcb *
-        in6_pcblookup_listen(struct inpcbtable *,
-                              struct in6_addr *, u_int, int, struct mbuf *,
-                              u_int);
+        in6_pcblookup_listen(struct inpcbtable *, struct in6_addr *, u_int,
+           struct mbuf *, u_int);
 int     in6_pcbaddrisavail(struct inpcb *, struct sockaddr_in6 *, int,
            struct proc *);
 int     in6_pcbconnect(struct inpcb *, struct mbuf *);
Index: netinet/tcp_input.c
===================================================================
RCS file: /data/mirror/openbsd/cvs/src/sys/netinet/tcp_input.c,v
retrieving revision 1.352
diff -u -p -r1.352 tcp_input.c
--- netinet/tcp_input.c 20 Nov 2017 10:35:24 -0000      1.352
+++ netinet/tcp_input.c 30 Nov 2017 16:01:58 -0000
@@ -548,22 +548,17 @@ findpcb:
                }
        }
        if (inp == NULL) {
-               int     inpl_reverse = 0;
-               if (m->m_pkthdr.pf.flags & PF_TAG_TRANSLATE_LOCALHOST)
-                       inpl_reverse = 1;
                tcpstat_inc(tcps_pcbhashmiss);
                switch (af) {
 #ifdef INET6
                case AF_INET6:
-                       inp = in6_pcblookup_listen(&tcbtable,
-                           &ip6->ip6_dst, th->th_dport, inpl_reverse, m,
-                           m->m_pkthdr.ph_rtableid);
+                       inp = in6_pcblookup_listen(&tcbtable, &ip6->ip6_dst,
+                           th->th_dport, m, m->m_pkthdr.ph_rtableid);
                        break;
 #endif /* INET6 */
                case AF_INET:
-                       inp = in_pcblookup_listen(&tcbtable,
-                           ip->ip_dst, th->th_dport, inpl_reverse, m,
-                           m->m_pkthdr.ph_rtableid);
+                       inp = in_pcblookup_listen(&tcbtable, ip->ip_dst,
+                           th->th_dport, m, m->m_pkthdr.ph_rtableid);
                        break;
                }
                /*
Index: netinet/tcp_usrreq.c
===================================================================
RCS file: /data/mirror/openbsd/cvs/src/sys/netinet/tcp_usrreq.c,v
retrieving revision 1.160
diff -u -p -r1.160 tcp_usrreq.c
--- netinet/tcp_usrreq.c        20 Nov 2017 10:35:24 -0000      1.160
+++ netinet/tcp_usrreq.c        30 Nov 2017 16:30:22 -0000
@@ -818,12 +818,12 @@ tcp_ident(void *oldp, size_t *oldlenp, v
 #ifdef INET6
                case AF_INET6:
                        inp = in6_pcblookup_listen(&tcbtable,
-                           &l6, lin6->sin6_port, 0, NULL, tir.rdomain);
+                           &l6, lin6->sin6_port, NULL, tir.rdomain);
                        break;
 #endif
                case AF_INET:
                        inp = in_pcblookup_listen(&tcbtable,
-                           lin->sin_addr, lin->sin_port, 0, NULL, tir.rdomain);
+                           lin->sin_addr, lin->sin_port, NULL, tir.rdomain);
                        break;
                }
        }
Index: netinet/udp_usrreq.c
===================================================================
RCS file: /data/mirror/openbsd/cvs/src/sys/netinet/udp_usrreq.c,v
retrieving revision 1.244
diff -u -p -r1.244 udp_usrreq.c
--- netinet/udp_usrreq.c        20 Nov 2017 10:35:24 -0000      1.244
+++ netinet/udp_usrreq.c        30 Nov 2017 16:32:32 -0000
@@ -528,20 +528,15 @@ udp_input(struct mbuf **mp, int *offp, i
                    ip->ip_dst, uh->uh_dport, m->m_pkthdr.ph_rtableid);
        }
        if (inp == 0) {
-               int     inpl_reverse = 0;
-               if (m->m_pkthdr.pf.flags & PF_TAG_TRANSLATE_LOCALHOST)
-                       inpl_reverse = 1;
                udpstat_inc(udps_pcbhashmiss);
 #ifdef INET6
                if (ip6) {
-                       inp = in6_pcblookup_listen(&udbtable,
-                           &ip6->ip6_dst, uh->uh_dport, inpl_reverse, m,
-                           m->m_pkthdr.ph_rtableid);
+                       inp = in6_pcblookup_listen(&udbtable, &ip6->ip6_dst,
+                           uh->uh_dport, m, m->m_pkthdr.ph_rtableid);
                } else
 #endif /* INET6 */
-               inp = in_pcblookup_listen(&udbtable,
-                   ip->ip_dst, uh->uh_dport, inpl_reverse, m,
-                   m->m_pkthdr.ph_rtableid);
+               inp = in_pcblookup_listen(&udbtable, ip->ip_dst,
+                   uh->uh_dport, m, m->m_pkthdr.ph_rtableid);
                if (inp == 0) {
                        udpstat_inc(udps_noport);
                        if (m->m_flags & (M_BCAST | M_MCAST)) {
@@ -801,7 +796,7 @@ udp6_ctlinput(int cmd, struct sockaddr *
                         * is really ours.
                         */
                        else if (in6_pcblookup_listen(&udbtable,
-                           &sa6_src.sin6_addr, uh.uh_sport, 0,
+                           &sa6_src.sin6_addr, uh.uh_sport, NULL,
                            rdomain))
                                valid = 1;
 #endif

Reply via email to