From 9ad11dd8a4348109f18573d3f8f9759a154fa5a6 Mon Sep 17 00:00:00 2001 From: Robert Watson Date: Mon, 21 Apr 2008 12:06:41 +0000 Subject: [PATCH] With IPv4 raw sockets, read lock rather than write lock the inpcb when receiving or transmitting. With IPv6 raw sockets, read lock rather than write lock the inpcb when receiving. Unfortunately, IPv6 source address selection appears to require a write lock on the inpcb for the time being. MFC after: 3 months --- sys/netinet/raw_ip.c | 30 +++++++++++++++--------------- sys/netinet6/raw_ip6.c | 10 +++++----- 2 files changed, 20 insertions(+), 20 deletions(-) diff --git a/sys/netinet/raw_ip.c b/sys/netinet/raw_ip.c index ead521978c18..23ab1fed11ec 100644 --- a/sys/netinet/raw_ip.c +++ b/sys/netinet/raw_ip.c @@ -155,7 +155,7 @@ raw_append(struct inpcb *last, struct ip *ip, struct mbuf *n) { int policyfail = 0; - INP_WLOCK_ASSERT(last); + INP_RLOCK_ASSERT(last); #ifdef IPSEC /* check AH/ESP integrity. */ @@ -209,10 +209,10 @@ rip_input(struct mbuf *m, int off) ripsrc.sin_addr = ip->ip_src; last = NULL; LIST_FOREACH(inp, &ripcb, inp_list) { - INP_WLOCK(inp); + INP_RLOCK(inp); if (inp->inp_ip_p && inp->inp_ip_p != proto) { docontinue: - INP_WUNLOCK(inp); + INP_RUNLOCK(inp); continue; } #ifdef INET6 @@ -236,14 +236,14 @@ rip_input(struct mbuf *m, int off) if (n != NULL) (void) raw_append(last, ip, n); /* XXX count dropped packet */ - INP_WUNLOCK(last); + INP_RUNLOCK(last); } last = inp; } if (last != NULL) { if (raw_append(last, ip, m) != 0) ipstat.ips_delivered--; - INP_WUNLOCK(last); + INP_RUNLOCK(last); } else { m_freem(m); ipstat.ips_noproto++; @@ -278,7 +278,7 @@ rip_output(struct mbuf *m, struct socket *so, u_long dst) if (m == NULL) return(ENOBUFS); - INP_WLOCK(inp); + INP_RLOCK(inp); ip = mtod(m, struct ip *); ip->ip_tos = inp->inp_ip_tos; if (inp->inp_flags & INP_DONTFRAG) @@ -299,12 +299,12 @@ rip_output(struct mbuf *m, struct socket *so, u_long dst) m_freem(m); return(EMSGSIZE); } - INP_WLOCK(inp); + INP_RLOCK(inp); ip = mtod(m, struct ip *); if (jailed(inp->inp_socket->so_cred)) { if (ip->ip_src.s_addr != htonl(prison_getip(inp->inp_socket->so_cred))) { - INP_WUNLOCK(inp); + INP_RUNLOCK(inp); m_freem(m); return (EPERM); } @@ -315,7 +315,7 @@ rip_output(struct mbuf *m, struct socket *so, u_long dst) && inp->inp_options) || (ip->ip_len > m->m_pkthdr.len) || (ip->ip_len < (ip->ip_hl << 2))) { - INP_WUNLOCK(inp); + INP_RUNLOCK(inp); m_freem(m); return EINVAL; } @@ -335,7 +335,7 @@ rip_output(struct mbuf *m, struct socket *so, u_long dst) error = ip_output(m, inp->inp_options, NULL, flags, inp->inp_moptions, inp); - INP_WUNLOCK(inp); + INP_RUNLOCK(inp); return error; } @@ -851,13 +851,13 @@ rip_pcblist(SYSCTL_HANDLER_ARGS) INP_INFO_RLOCK(&ripcbinfo); for (inp = LIST_FIRST(ripcbinfo.ipi_listhead), i = 0; inp && i < n; inp = LIST_NEXT(inp, inp_list)) { - INP_WLOCK(inp); + INP_RLOCK(inp); if (inp->inp_gencnt <= gencnt && cr_canseesocket(req->td->td_ucred, inp->inp_socket) == 0) { /* XXX held references? */ inp_list[i++] = inp; } - INP_WUNLOCK(inp); + INP_RUNLOCK(inp); } INP_INFO_RUNLOCK(&ripcbinfo); n = i; @@ -865,7 +865,7 @@ rip_pcblist(SYSCTL_HANDLER_ARGS) error = 0; for (i = 0; i < n; i++) { inp = inp_list[i]; - INP_WLOCK(inp); + INP_RLOCK(inp); if (inp->inp_gencnt <= gencnt) { struct xinpcb xi; bzero(&xi, sizeof(xi)); @@ -874,10 +874,10 @@ rip_pcblist(SYSCTL_HANDLER_ARGS) bcopy(inp, &xi.xi_inp, sizeof *inp); if (inp->inp_socket) sotoxsocket(inp->inp_socket, &xi.xi_socket); - INP_WUNLOCK(inp); + INP_RUNLOCK(inp); error = SYSCTL_OUT(req, &xi, sizeof xi); } else - INP_WUNLOCK(inp); + INP_RUNLOCK(inp); } if (!error) { /* diff --git a/sys/netinet6/raw_ip6.c b/sys/netinet6/raw_ip6.c index c12bde1334c2..b791872430d7 100644 --- a/sys/netinet6/raw_ip6.c +++ b/sys/netinet6/raw_ip6.c @@ -154,10 +154,10 @@ rip6_input(struct mbuf **mp, int *offp, int proto) INP_INFO_RLOCK(&ripcbinfo); LIST_FOREACH(in6p, &ripcb, inp_list) { - INP_WLOCK(in6p); + INP_RLOCK(in6p); if ((in6p->in6p_vflag & INP_IPV6) == 0) { docontinue: - INP_WUNLOCK(in6p); + INP_RUNLOCK(in6p); continue; } if (in6p->in6p_ip6_nxt && @@ -207,7 +207,7 @@ docontinue: sorwakeup(last->in6p_socket); opts = NULL; } - INP_WUNLOCK(last); + INP_RUNLOCK(last); } last = in6p; } @@ -220,7 +220,7 @@ docontinue: ipsec6stat.in_polvio++; ip6stat.ip6s_delivered--; /* do not inject data into pcb */ - INP_WUNLOCK(last); + INP_RUNLOCK(last); } else #endif /* IPSEC */ if (last) { @@ -237,7 +237,7 @@ docontinue: rip6stat.rip6s_fullsock++; } else sorwakeup(last->in6p_socket); - INP_WUNLOCK(last); + INP_RUNLOCK(last); } else { rip6stat.rip6s_nosock++; if (m->m_flags & M_MCAST)