From: Alexander Bluhm Subject: raw IPv6 input loop iterator To: tech@openbsd.org Date: Thu, 7 Nov 2024 23:30:49 +0100 Hi, Here is the final part that implements inpcb iterator for rip6 input. While there, make rip_input() look more like rip6_input(). ok? bluhm Index: kern/kern_sysctl.c =================================================================== RCS file: /data/mirror/openbsd/cvs/src/sys/kern/kern_sysctl.c,v diff -u -p -r1.453 kern_sysctl.c --- kern/kern_sysctl.c 5 Nov 2024 22:44:20 -0000 1.453 +++ kern/kern_sysctl.c 7 Nov 2024 22:28:06 -0000 @@ -1714,8 +1714,11 @@ sysctl_file(int *name, u_int namelen, ch #ifdef INET6 mtx_enter(&rawin6pcbtable.inpt_mtx); TAILQ_FOREACH(inp, &rawin6pcbtable.inpt_queue, - inp_queue) + inp_queue) { + if (in_pcb_is_iterator(inp)) + continue; FILLSO(inp->inp_socket); + } mtx_leave(&rawin6pcbtable.inpt_mtx); #endif NET_UNLOCK(); Index: netinet/raw_ip.c =================================================================== RCS file: /data/mirror/openbsd/cvs/src/sys/netinet/raw_ip.c,v diff -u -p -r1.161 raw_ip.c --- netinet/raw_ip.c 5 Nov 2024 22:44:20 -0000 1.161 +++ netinet/raw_ip.c 7 Nov 2024 22:28:06 -0000 @@ -136,8 +136,6 @@ rip_input(struct mbuf **mp, int *offp, i struct inpcb_iterator iter = { .inp_table = NULL }; struct inpcb *inp, *last; struct in_addr *key; - struct counters_ref ref; - uint64_t *counters; struct sockaddr_in ripsrc; KASSERT(af == AF_INET); @@ -209,12 +207,15 @@ rip_input(struct mbuf **mp, int *offp, i mtx_leave(&rawcbtable.inpt_mtx); if (last == NULL) { - if (ip->ip_p != IPPROTO_ICMP) + struct counters_ref ref; + uint64_t *counters; + + if (ip->ip_p == IPPROTO_ICMP) { + m_freem(m); + } else { icmp_error(m, ICMP_UNREACH, ICMP_UNREACH_PROTOCOL, 0, 0); - else - m_freem(m); - + } counters = counters_enter(&ref, ipcounters); counters[ips_noproto]++; counters[ips_delivered]--; Index: netinet6/raw_ip6.c =================================================================== RCS file: /data/mirror/openbsd/cvs/src/sys/netinet6/raw_ip6.c,v diff -u -p -r1.185 raw_ip6.c --- netinet6/raw_ip6.c 12 Jul 2024 19:50:35 -0000 1.185 +++ netinet6/raw_ip6.c 7 Nov 2024 22:28:06 -0000 @@ -118,6 +118,9 @@ const struct pr_usrreqs rip6_usrreqs = { .pru_peeraddr = in6_peeraddr, }; +void rip6_sbappend(struct inpcb *, struct mbuf *, struct ip6_hdr *, int, + struct sockaddr_in6 *); + /* * Initialize raw connection block queue. */ @@ -133,8 +136,8 @@ rip6_input(struct mbuf **mp, int *offp, { struct mbuf *m = *mp; struct ip6_hdr *ip6 = mtod(m, struct ip6_hdr *); - struct inpcb *inp; - SIMPLEQ_HEAD(, inpcb) inpcblist; + struct inpcb_iterator iter = { .inp_table = NULL }; + struct inpcb *inp, *last; struct in6_addr *key; struct sockaddr_in6 rip6src; uint8_t type; @@ -177,10 +180,9 @@ rip6_input(struct mbuf **mp, int *offp, } } #endif - SIMPLEQ_INIT(&inpcblist); - rw_enter_write(&rawin6pcbtable.inpt_notify); mtx_enter(&rawin6pcbtable.inpt_mtx); - TAILQ_FOREACH(inp, &rawin6pcbtable.inpt_queue, inp_queue) { + last = inp = NULL; + while ((inp = in_pcb_iterator(&rawin6pcbtable, inp, &iter)) != NULL) { KASSERT(ISSET(inp->inp_flags, INP_IPV6)); /* @@ -226,17 +228,26 @@ rip6_input(struct mbuf **mp, int *offp, } } - in_pcbref(inp); - SIMPLEQ_INSERT_TAIL(&inpcblist, inp, inp_notify); + if (last != NULL) { + struct mbuf *n; + + mtx_leave(&rawin6pcbtable.inpt_mtx); + + n = m_copym(m, 0, M_COPYALL, M_NOWAIT); + if (n != NULL) + rip6_sbappend(last, n, ip6, *offp, &rip6src); + in_pcbunref(last); + + mtx_enter(&rawin6pcbtable.inpt_mtx); + } + last = in_pcbref(inp); } mtx_leave(&rawin6pcbtable.inpt_mtx); - if (SIMPLEQ_EMPTY(&inpcblist)) { + if (last == NULL) { struct counters_ref ref; uint64_t *counters; - rw_exit_write(&rawin6pcbtable.inpt_notify); - if (proto != IPPROTO_ICMPV6) { rip6stat_inc(rip6s_nosock); if (m->m_flags & M_MCAST) @@ -257,43 +268,36 @@ rip6_input(struct mbuf **mp, int *offp, return IPPROTO_DONE; } - while ((inp = SIMPLEQ_FIRST(&inpcblist)) != NULL) { - struct mbuf *n, *opts = NULL; - - SIMPLEQ_REMOVE_HEAD(&inpcblist, inp_notify); - if (SIMPLEQ_EMPTY(&inpcblist)) - n = m; - else - n = m_copym(m, 0, M_COPYALL, M_NOWAIT); - if (n != NULL) { - struct socket *so = inp->inp_socket; - int ret = 0; - - if (inp->inp_flags & IN6P_CONTROLOPTS) - ip6_savecontrol(inp, n, &opts); - /* strip intermediate headers */ - m_adj(n, *offp); - - mtx_enter(&so->so_rcv.sb_mtx); - if (!ISSET(inp->inp_socket->so_rcv.sb_state, - SS_CANTRCVMORE)) { - ret = sbappendaddr(so, &so->so_rcv, - sin6tosa(&rip6src), n, opts); - } - mtx_leave(&so->so_rcv.sb_mtx); - - if (ret == 0) { - m_freem(n); - m_freem(opts); - rip6stat_inc(rip6s_fullsock); - } else - sorwakeup(so); - } - in_pcbunref(inp); - } - rw_exit_write(&rawin6pcbtable.inpt_notify); + rip6_sbappend(last, m, ip6, *offp, &rip6src); + in_pcbunref(last); return IPPROTO_DONE; +} + +void +rip6_sbappend(struct inpcb *inp, struct mbuf *m, struct ip6_hdr *ip6, int hlen, + struct sockaddr_in6 *rip6src) +{ + struct socket *so = inp->inp_socket; + struct mbuf *opts = NULL; + int ret = 0; + + if (inp->inp_flags & IN6P_CONTROLOPTS) + ip6_savecontrol(inp, m, &opts); + /* strip intermediate headers */ + m_adj(m, hlen); + + mtx_enter(&so->so_rcv.sb_mtx); + if (!ISSET(inp->inp_socket->so_rcv.sb_state, SS_CANTRCVMORE)) + ret = sbappendaddr(so, &so->so_rcv, sin6tosa(rip6src), m, opts); + mtx_leave(&so->so_rcv.sb_mtx); + + if (ret == 0) { + m_freem(m); + m_freem(opts); + rip6stat_inc(rip6s_fullsock); + } else + sorwakeup(so); } void