diff options
author | Alexander Bluhm <bluhm@cvs.openbsd.org> | 2024-04-16 12:40:41 +0000 |
---|---|---|
committer | Alexander Bluhm <bluhm@cvs.openbsd.org> | 2024-04-16 12:40:41 +0000 |
commit | 989891d6ea337764b983eb195f21039b0e3ae440 (patch) | |
tree | 13a2ddcabfae2308696e93ee5b17ccb18bd01524 /sys/netinet6 | |
parent | bf10c52847ea519e51b68a84d67f6070bfec05ac (diff) |
Run raw IPv6 input in parallel.
Get rip6_input() in the same shape as rip_input(). Call
soisdisconnected() from rip6_disconnect(). This means that the raw
IP socket cannot be reconnected later. Now raw IPv6 behaves like
IPv4 in this regard, KAME code is quite inconsistent here. Also
make sure that there is no race between disconnect, input and wakeup.
The inpcb fileds inp_icmp6filt and inp_cksum6 are protected by
exclusive net lock in icmp6_ctloutput(). With all that, mark raw
IPv6 sockets to handle input in parallel.
OK mvs@
Diffstat (limited to 'sys/netinet6')
-rw-r--r-- | sys/netinet6/in6_proto.c | 6 | ||||
-rw-r--r-- | sys/netinet6/raw_ip6.c | 26 |
2 files changed, 20 insertions, 12 deletions
diff --git a/sys/netinet6/in6_proto.c b/sys/netinet6/in6_proto.c index db218af06c4..f73e00b4d2c 100644 --- a/sys/netinet6/in6_proto.c +++ b/sys/netinet6/in6_proto.c @@ -1,4 +1,4 @@ -/* $OpenBSD: in6_proto.c,v 1.113 2024/01/11 14:15:12 bluhm Exp $ */ +/* $OpenBSD: in6_proto.c,v 1.114 2024/04/16 12:40:40 bluhm Exp $ */ /* $KAME: in6_proto.c,v 1.66 2000/10/10 15:35:47 itojun Exp $ */ /* @@ -158,7 +158,7 @@ const struct protosw inet6sw[] = { .pr_type = SOCK_RAW, .pr_domain = &inet6domain, .pr_protocol = IPPROTO_RAW, - .pr_flags = PR_ATOMIC|PR_ADDR, + .pr_flags = PR_ATOMIC|PR_ADDR|PR_MPINPUT, .pr_input = rip6_input, .pr_ctlinput = rip6_ctlinput, .pr_ctloutput = rip6_ctloutput, @@ -322,7 +322,7 @@ const struct protosw inet6sw[] = { /* raw wildcard */ .pr_type = SOCK_RAW, .pr_domain = &inet6domain, - .pr_flags = PR_ATOMIC|PR_ADDR, + .pr_flags = PR_ATOMIC|PR_ADDR|PR_MPINPUT, .pr_input = rip6_input, .pr_ctloutput = rip6_ctloutput, .pr_usrreqs = &rip6_usrreqs, diff --git a/sys/netinet6/raw_ip6.c b/sys/netinet6/raw_ip6.c index 177eeb8e88b..5804af2624f 100644 --- a/sys/netinet6/raw_ip6.c +++ b/sys/netinet6/raw_ip6.c @@ -1,4 +1,4 @@ -/* $OpenBSD: raw_ip6.c,v 1.182 2024/02/13 12:22:09 bluhm Exp $ */ +/* $OpenBSD: raw_ip6.c,v 1.183 2024/04/16 12:40:40 bluhm Exp $ */ /* $KAME: raw_ip6.c,v 1.69 2001/03/04 15:55:44 itojun Exp $ */ /* @@ -155,9 +155,9 @@ rip6_input(struct mbuf **mp, int *offp, int proto, int af) } else rip6stat_inc(rip6s_ipackets); - bzero(&rip6src, sizeof(rip6src)); - rip6src.sin6_len = sizeof(struct sockaddr_in6); + memset(&rip6src, 0, sizeof(rip6src)); rip6src.sin6_family = AF_INET6; + rip6src.sin6_len = sizeof(rip6src); /* KAME hack: recover scopeid */ in6_recoverscope(&rip6src, &ip6->ip6_src); @@ -186,7 +186,13 @@ rip6_input(struct mbuf **mp, int *offp, int proto, int af) TAILQ_FOREACH(inp, &rawin6pcbtable.inpt_queue, inp_queue) { KASSERT(ISSET(inp->inp_flags, INP_IPV6)); - if (inp->inp_socket->so_rcv.sb_state & SS_CANTRCVMORE) + /* + * Packet must not be inserted after disconnected wakeup + * call. To avoid race, check again when holding receive + * buffer mutex. + */ + if (ISSET(READ_ONCE(inp->inp_socket->so_rcv.sb_state), + SS_CANTRCVMORE)) continue; if (rtable_l2(inp->inp_rtableid) != rtable_l2(m->m_pkthdr.ph_rtableid)) @@ -264,7 +270,7 @@ rip6_input(struct mbuf **mp, int *offp, int proto, int af) n = m_copym(m, 0, M_COPYALL, M_NOWAIT); if (n != NULL) { struct socket *so = inp->inp_socket; - int ret; + int ret = 0; if (inp->inp_flags & IN6P_CONTROLOPTS) ip6_savecontrol(inp, n, &opts); @@ -272,12 +278,14 @@ rip6_input(struct mbuf **mp, int *offp, int proto, int af) m_adj(n, *offp); mtx_enter(&so->so_rcv.sb_mtx); - ret = sbappendaddr(so, &so->so_rcv, - sin6tosa(&rip6src), n, opts); + 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) { - /* should notify about lost packet */ m_freem(n); m_freem(opts); rip6stat_inc(rip6s_fullsock); @@ -727,7 +735,7 @@ rip6_disconnect(struct socket *so) if ((so->so_state & SS_ISCONNECTED) == 0) return (ENOTCONN); - so->so_state &= ~SS_ISCONNECTED; /* XXX */ + soisdisconnected(so); mtx_enter(&rawin6pcbtable.inpt_mtx); inp->inp_faddr6 = in6addr_any; mtx_leave(&rawin6pcbtable.inpt_mtx); |