From 338b787cfd398c95a913a9b05fa1cf75127562df Mon Sep 17 00:00:00 2001 From: rwatson Date: Sun, 5 Dec 2004 22:08:37 +0000 Subject: Pass the inpcb reference into ip_getmoptions() rather than just the inp->inp_moptions pointer, so that ip_getmoptions() can perform necessary locking when doing non-atomic reads. Lock the inpcb by default to copy any data to local variables, then unlock before performing sooptcopyout(). MFC after: 2 weeks --- sys/netinet/ip_output.c | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) (limited to 'sys/netinet/ip_output.c') diff --git a/sys/netinet/ip_output.c b/sys/netinet/ip_output.c index 2e0a535..5baccf8 100644 --- a/sys/netinet/ip_output.c +++ b/sys/netinet/ip_output.c @@ -97,8 +97,7 @@ static struct mbuf *ip_insertoptions(struct mbuf *, struct mbuf *, int *); static struct ifnet *ip_multicast_if(struct in_addr *, int *); static void ip_mloopback (struct ifnet *, struct mbuf *, struct sockaddr_in *, int); -static int ip_getmoptions - (struct sockopt *, struct ip_moptions *); +static int ip_getmoptions(struct inpcb *, struct sockopt *); static int ip_pcbopts(struct inpcb *, int, struct mbuf *); static int ip_setmoptions(struct inpcb *, struct sockopt *); @@ -1392,7 +1391,7 @@ ip_ctloutput(so, sopt) case IP_MULTICAST_LOOP: case IP_ADD_MEMBERSHIP: case IP_DROP_MEMBERSHIP: - error = ip_getmoptions(sopt, inp->inp_moptions); + error = ip_getmoptions(inp, sopt); break; #if defined(IPSEC) || defined(FAST_IPSEC) @@ -1863,15 +1862,17 @@ ip_setmoptions(struct inpcb *inp, struct sockopt *sopt) * Return the IP multicast options in response to user getsockopt(). */ static int -ip_getmoptions(sopt, imo) - struct sockopt *sopt; - register struct ip_moptions *imo; +ip_getmoptions(struct inpcb *inp, struct sockopt *sopt) { + struct ip_moptions *imo; struct in_addr addr; struct in_ifaddr *ia; int error, optval; u_char coptval; + INP_LOCK(inp); + imo = inp->inp_moptions; + error = 0; switch (sopt->sopt_name) { case IP_MULTICAST_VIF: @@ -1879,6 +1880,7 @@ ip_getmoptions(sopt, imo) optval = imo->imo_multicast_vif; else optval = -1; + INP_UNLOCK(inp); error = sooptcopyout(sopt, &optval, sizeof optval); break; @@ -1893,6 +1895,7 @@ ip_getmoptions(sopt, imo) addr.s_addr = (ia == NULL) ? INADDR_ANY : IA_SIN(ia)->sin_addr.s_addr; } + INP_UNLOCK(inp); error = sooptcopyout(sopt, &addr, sizeof addr); break; @@ -1901,6 +1904,7 @@ ip_getmoptions(sopt, imo) optval = coptval = IP_DEFAULT_MULTICAST_TTL; else optval = coptval = imo->imo_multicast_ttl; + INP_UNLOCK(inp); if (sopt->sopt_valsize == 1) error = sooptcopyout(sopt, &coptval, 1); else @@ -1912,6 +1916,7 @@ ip_getmoptions(sopt, imo) optval = coptval = IP_DEFAULT_MULTICAST_LOOP; else optval = coptval = imo->imo_multicast_loop; + INP_UNLOCK(inp); if (sopt->sopt_valsize == 1) error = sooptcopyout(sopt, &coptval, 1); else @@ -1919,9 +1924,12 @@ ip_getmoptions(sopt, imo) break; default: + INP_UNLOCK(inp); error = ENOPROTOOPT; break; } + INP_UNLOCK_ASSERT(inp); + return (error); } -- cgit v1.1