Clean up divert_packet(). Function does not return error, make it
authorbluhm <bluhm@openbsd.org>
Thu, 5 May 2022 16:44:22 +0000 (16:44 +0000)
committerbluhm <bluhm@openbsd.org>
Thu, 5 May 2022 16:44:22 +0000 (16:44 +0000)
void.  Introduce mutex and refcounting for inp like in the other
PCB functions.
OK sashan@

sys/net/pf.c
sys/netinet/ip_divert.c
sys/netinet/ip_divert.h
sys/netinet6/ip6_divert.c
sys/netinet6/ip6_divert.h

index e774a8b..6872d1a 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: pf.c,v 1.1128 2022/05/03 13:32:47 sashan Exp $ */
+/*     $OpenBSD: pf.c,v 1.1129 2022/05/05 16:44:22 bluhm Exp $ */
 
 /*
  * Copyright (c) 2001 Daniel Hartmeier
@@ -7403,13 +7403,13 @@ done:
        case PF_DIVERT:
                switch (pd.af) {
                case AF_INET:
-                       if (!divert_packet(pd.m, pd.dir, r->divert.port))
-                               pd.m = NULL;
+                       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.port))
-                               pd.m = NULL;
+                       divert6_packet(pd.m, pd.dir, r->divert.port);
+                       pd.m = NULL;
                        break;
 #endif /* INET6 */
                }
index 5b987fb..187bbe8 100644 (file)
@@ -1,4 +1,4 @@
-/*      $OpenBSD: ip_divert.c,v 1.66 2022/02/25 23:51:03 guenther Exp $ */
+/*      $OpenBSD: ip_divert.c,v 1.67 2022/05/05 16:44:22 bluhm Exp $ */
 
 /*
  * Copyright (c) 2009 Michele Marchetto <michele@openbsd.org>
@@ -171,30 +171,37 @@ fail:
        return (error ? error : EINVAL);
 }
 
-int
+void
 divert_packet(struct mbuf *m, int dir, u_int16_t divert_port)
 {
-       struct inpcb *inp;
-       struct socket *sa = NULL;
-       struct sockaddr_in addr;
+       struct inpcb *inp = NULL;
+       struct socket *so;
+       struct sockaddr_in sin;
 
-       inp = NULL;
        divstat_inc(divs_ipackets);
 
        if (m->m_len < sizeof(struct ip) &&
            (m = m_pullup(m, sizeof(struct ip))) == NULL) {
                divstat_inc(divs_errors);
-               return (0);
+               goto bad;
        }
 
+       mtx_enter(&divbtable.inpt_mtx);
        TAILQ_FOREACH(inp, &divbtable.inpt_queue, inp_queue) {
-               if (inp->inp_lport == divert_port)
-                       break;
+               if (inp->inp_lport != divert_port)
+                       continue;
+               in_pcbref(inp);
+               break;
+       }
+       mtx_leave(&divbtable.inpt_mtx);
+       if (inp == NULL) {
+               divstat_inc(divs_noport);
+               goto bad;
        }
 
-       memset(&addr, 0, sizeof(addr));
-       addr.sin_family = AF_INET;
-       addr.sin_len = sizeof(addr);
+       memset(&sin, 0, sizeof(sin));
+       sin.sin_family = AF_INET;
+       sin.sin_len = sizeof(sin);
 
        if (dir == PF_IN) {
                struct ifaddr *ifa;
@@ -202,37 +209,34 @@ divert_packet(struct mbuf *m, int dir, u_int16_t divert_port)
 
                ifp = if_get(m->m_pkthdr.ph_ifidx);
                if (ifp == NULL) {
-                       m_freem(m);
-                       return (0);
+                       divstat_inc(divs_errors);
+                       goto bad;
                }
                TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list) {
                        if (ifa->ifa_addr->sa_family != AF_INET)
                                continue;
-                       addr.sin_addr.s_addr = satosin(
-                           ifa->ifa_addr)->sin_addr.s_addr;
+                       sin.sin_addr = satosin(ifa->ifa_addr)->sin_addr;
                        break;
                }
                if_put(ifp);
        }
 
-       if (inp) {
-               sa = inp->inp_socket;
-               if (sbappendaddr(sa, &sa->so_rcv, sintosa(&addr), m, NULL) == 0) {
-                       divstat_inc(divs_fullsock);
-                       m_freem(m);
-                       return (0);
-               } else {
-                       KERNEL_LOCK();
-                       sorwakeup(inp->inp_socket);
-                       KERNEL_UNLOCK();
-               }
+       so = inp->inp_socket;
+       if (sbappendaddr(so, &so->so_rcv, sintosa(&sin), m, NULL) == 0) {
+               divstat_inc(divs_fullsock);
+               goto bad;
        }
+       KERNEL_LOCK();
+       sorwakeup(inp->inp_socket);
+       KERNEL_UNLOCK();
 
-       if (sa == NULL) {
-               divstat_inc(divs_noport);
-               m_freem(m);
-       }
-       return (0);
+       in_pcbunref(inp);
+       return;
+
+ bad:
+       if (inp != NULL)
+               in_pcbunref(inp);
+       m_freem(m);
 }
 
 /*ARGSUSED*/
index 11780b5..c902127 100644 (file)
@@ -1,4 +1,4 @@
-/*      $OpenBSD: ip_divert.h,v 1.14 2022/02/25 23:51:03 guenther Exp $ */
+/*      $OpenBSD: ip_divert.h,v 1.15 2022/05/05 16:44:22 bluhm Exp $ */
 
 /*
  * Copyright (c) 2009 Michele Marchetto <michele@openbsd.org>
@@ -66,7 +66,7 @@ divstat_inc(enum divstat_counters c)
 extern struct  inpcbtable      divbtable;
 
 void    divert_init(void);
-int     divert_packet(struct mbuf *, int, u_int16_t);
+void    divert_packet(struct mbuf *, int, u_int16_t);
 int     divert_sysctl(int *, u_int, void *, size_t *, void *, size_t);
 int     divert_usrreq(struct socket *,
            int, struct mbuf *, struct mbuf *, struct mbuf *, struct proc *);
index 083e093..35eb409 100644 (file)
@@ -1,4 +1,4 @@
-/*      $OpenBSD: ip6_divert.c,v 1.65 2022/02/25 23:51:04 guenther Exp $ */
+/*      $OpenBSD: ip6_divert.c,v 1.66 2022/05/05 16:44:22 bluhm Exp $ */
 
 /*
  * Copyright (c) 2009 Michele Marchetto <michele@openbsd.org>
@@ -177,30 +177,37 @@ fail:
        return (error ? error : EINVAL);
 }
 
-int
+void
 divert6_packet(struct mbuf *m, int dir, u_int16_t divert_port)
 {
-       struct inpcb *inp;
-       struct socket *sa = NULL;
-       struct sockaddr_in6 addr;
+       struct inpcb *inp = NULL;
+       struct socket *so;
+       struct sockaddr_in6 sin6;
 
-       inp = NULL;
        div6stat_inc(div6s_ipackets);
 
        if (m->m_len < sizeof(struct ip6_hdr) &&
            (m = m_pullup(m, sizeof(struct ip6_hdr))) == NULL) {
                div6stat_inc(div6s_errors);
-               return (0);
+               goto bad;
        }
 
+       mtx_enter(&divb6table.inpt_mtx);
        TAILQ_FOREACH(inp, &divb6table.inpt_queue, inp_queue) {
-               if (inp->inp_lport == divert_port)
-                       break;
+               if (inp->inp_lport != divert_port)
+                       continue;
+               in_pcbref(inp);
+               break;
+       }
+       mtx_leave(&divb6table.inpt_mtx);
+       if (inp == NULL) {
+               div6stat_inc(div6s_noport);
+               goto bad;
        }
 
-       memset(&addr, 0, sizeof(addr));
-       addr.sin6_family = AF_INET6;
-       addr.sin6_len = sizeof(addr);
+       memset(&sin6, 0, sizeof(sin6));
+       sin6.sin6_family = AF_INET6;
+       sin6.sin6_len = sizeof(sin6);
 
        if (dir == PF_IN) {
                struct ifaddr *ifa;
@@ -208,36 +215,34 @@ divert6_packet(struct mbuf *m, int dir, u_int16_t divert_port)
 
                ifp = if_get(m->m_pkthdr.ph_ifidx);
                if (ifp == NULL) {
-                       m_freem(m);
-                       return (0);
+                       div6stat_inc(div6s_errors);
+                       goto bad;
                }
                TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list) {
                        if (ifa->ifa_addr->sa_family != AF_INET6)
                                continue;
-                       addr.sin6_addr = satosin6(ifa->ifa_addr)->sin6_addr;
+                       sin6.sin6_addr = satosin6(ifa->ifa_addr)->sin6_addr;
                        break;
                }
                if_put(ifp);
        }
 
-       if (inp) {
-               sa = inp->inp_socket;
-               if (sbappendaddr(sa, &sa->so_rcv, sin6tosa(&addr), m, NULL) == 0) {
-                       div6stat_inc(div6s_fullsock);
-                       m_freem(m);
-                       return (0);
-               } else {
-                       KERNEL_LOCK();
-                       sorwakeup(inp->inp_socket);
-                       KERNEL_UNLOCK();
-               }
+       so = inp->inp_socket;
+       if (sbappendaddr(so, &so->so_rcv, sin6tosa(&sin6), m, NULL) == 0) {
+               div6stat_inc(div6s_fullsock);
+               goto bad;
        }
+       KERNEL_LOCK();
+       sorwakeup(inp->inp_socket);
+       KERNEL_UNLOCK();
 
-       if (sa == NULL) {
-               div6stat_inc(div6s_noport);
-               m_freem(m);
-       }
-       return (0);
+       in_pcbunref(inp);
+       return;
+
+ bad:
+       if (inp != NULL)
+               in_pcbunref(inp);
+       m_freem(m);
 }
 
 /*ARGSUSED*/
index 2cdac52..709cc2a 100644 (file)
@@ -1,4 +1,4 @@
-/*      $OpenBSD: ip6_divert.h,v 1.12 2022/02/25 23:51:04 guenther Exp $ */
+/*      $OpenBSD: ip6_divert.h,v 1.13 2022/05/05 16:44:22 bluhm Exp $ */
 
 /*
  * Copyright (c) 2009 Michele Marchetto <michele@openbsd.org>
@@ -66,7 +66,7 @@ div6stat_inc(enum div6stat_counters c)
 extern struct  inpcbtable      divb6table;
 
 void    divert6_init(void);
-int     divert6_packet(struct mbuf *, int, u_int16_t);
+void    divert6_packet(struct mbuf *, int, u_int16_t);
 int     divert6_sysctl(int *, u_int, void *, size_t *, void *, size_t);
 int     divert6_usrreq(struct socket *,
            int, struct mbuf *, struct mbuf *, struct mbuf *, struct proc *);