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
This commit is contained in:
parent
92c71ab30b
commit
89924e5865
@ -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);
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user