summaryrefslogtreecommitdiffstats
path: root/sys/netinet/ip_output.c
diff options
context:
space:
mode:
authorrwatson <rwatson@FreeBSD.org>2004-12-05 22:08:37 +0000
committerrwatson <rwatson@FreeBSD.org>2004-12-05 22:08:37 +0000
commit338b787cfd398c95a913a9b05fa1cf75127562df (patch)
tree9b08c18aaf7221e87bdaa7522e7a0d830830206d /sys/netinet/ip_output.c
parentf2988d54dee0ffdc5f894558569060c50692848d (diff)
downloadFreeBSD-src-338b787cfd398c95a913a9b05fa1cf75127562df.zip
FreeBSD-src-338b787cfd398c95a913a9b05fa1cf75127562df.tar.gz
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
Diffstat (limited to 'sys/netinet/ip_output.c')
-rw-r--r--sys/netinet/ip_output.c20
1 files changed, 14 insertions, 6 deletions
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);
}
OpenPOWER on IntegriCloud