summaryrefslogtreecommitdiffstats
path: root/sys/netinet6/udp6_usrreq.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/netinet6/udp6_usrreq.c')
-rw-r--r--sys/netinet6/udp6_usrreq.c57
1 files changed, 49 insertions, 8 deletions
diff --git a/sys/netinet6/udp6_usrreq.c b/sys/netinet6/udp6_usrreq.c
index 20913e6..0e58be5 100644
--- a/sys/netinet6/udp6_usrreq.c
+++ b/sys/netinet6/udp6_usrreq.c
@@ -269,10 +269,18 @@ udp6_input(mp, offp, proto)
* and m_copy() will copy M_PKTHDR
* only if offset is 0.
*/
- if (last->in6p_flags & IN6P_CONTROLOPTS
- || last->in6p_socket->so_options & SO_TIMESTAMP)
+ if (last->in6p_flags & IN6P_CONTROLOPTS)
ip6_savecontrol(last, &opts,
ip6, n);
+ else {
+ SOCK_LOCK(last->in6p_socket);
+ if (last->in6p_socket->so_options & SO_TIMESTAMP) {
+ SOCK_UNLOCK(last->in6p_socket);
+ ip6_savecontrol(last, &opts,
+ ip6, n);
+ } else
+ SOCK_UNLOCK(last->in6p_socket);
+ }
m_adj(n, off + sizeof(struct udphdr));
if (sbappendaddr(&last->in6p_socket->so_rcv,
@@ -282,8 +290,11 @@ udp6_input(mp, offp, proto)
if (opts)
m_freem(opts);
udpstat.udps_fullsock++;
- } else
+ } else {
+ SOCK_LOCK(last->in6p_socket);
sorwakeup(last->in6p_socket);
+ SOCK_UNLOCK(last->in6p_socket);
+ }
opts = NULL;
}
}
@@ -296,9 +307,13 @@ udp6_input(mp, offp, proto)
* port. It assumes that an application will never
* clear these options after setting them.
*/
+ SOCK_LOCK(last->in6p_socket);
if ((last->in6p_socket->so_options &
- (SO_REUSEPORT|SO_REUSEADDR)) == 0)
+ (SO_REUSEPORT|SO_REUSEADDR)) == 0) {
+ SOCK_UNLOCK(last->in6p_socket);
break;
+ } else
+ SOCK_UNLOCK(last->in6p_socket);
}
if (last == NULL) {
@@ -320,9 +335,16 @@ udp6_input(mp, offp, proto)
goto bad;
}
#endif /* IPSEC */
- if (last->in6p_flags & IN6P_CONTROLOPTS
- || last->in6p_socket->so_options & SO_TIMESTAMP)
+ if (last->in6p_flags & IN6P_CONTROLOPTS)
ip6_savecontrol(last, &opts, ip6, m);
+ else {
+ SOCK_LOCK(last->in6p_socket);
+ if (last->in6p_socket->so_options & SO_TIMESTAMP) {
+ SOCK_UNLOCK(last->in6p_socket);
+ ip6_savecontrol(last, &opts, ip6, m);
+ } else
+ SOCK_UNLOCK(last->in6p_socket);
+ }
m_adj(m, off + sizeof(struct udphdr));
if (sbappendaddr(&last->in6p_socket->so_rcv,
@@ -331,7 +353,9 @@ udp6_input(mp, offp, proto)
udpstat.udps_fullsock++;
goto bad;
}
+ SOCK_LOCK(last->in6p_socket);
sorwakeup(last->in6p_socket);
+ SOCK_UNLOCK(last->in6p_socket);
return IPPROTO_DONE;
}
/*
@@ -375,9 +399,16 @@ udp6_input(mp, offp, proto)
*/
init_sin6(&udp_in6, m); /* general init */
udp_in6.sin6_port = uh->uh_sport;
- if (in6p->in6p_flags & IN6P_CONTROLOPTS
- || in6p->in6p_socket->so_options & SO_TIMESTAMP)
+ if (in6p->in6p_flags & IN6P_CONTROLOPTS)
ip6_savecontrol(in6p, &opts, ip6, m);
+ else {
+ SOCK_LOCK(in6p->in6p_socket);
+ if (in6p->in6p_socket->so_options & SO_TIMESTAMP) {
+ SOCK_UNLOCK(in6p->in6p_socket);
+ ip6_savecontrol(in6p, &opts, ip6, m);
+ } else
+ SOCK_UNLOCK(in6p->in6p_socket);
+ }
m_adj(m, off + sizeof(struct udphdr));
if (sbappendaddr(&in6p->in6p_socket->so_rcv,
(struct sockaddr *)&udp_in6,
@@ -385,7 +416,9 @@ udp6_input(mp, offp, proto)
udpstat.udps_fullsock++;
goto bad;
}
+ SOCK_LOCK(in6p->in6p_socket);
sorwakeup(in6p->in6p_socket);
+ SOCK_UNLOCK(in6p->in6p_socket);
return IPPROTO_DONE;
bad:
if (m)
@@ -509,7 +542,9 @@ udp6_abort(struct socket *so)
inp = sotoinpcb(so);
if (inp == 0)
return EINVAL; /* ??? possible? panic instead? */
+ SOCK_LOCK(so);
soisdisconnected(so);
+ SOCK_UNLOCK(so);
s = splnet();
in6_pcbdetach(inp);
splx(s);
@@ -614,7 +649,9 @@ udp6_connect(struct socket *so, struct sockaddr *nam, struct thread *td)
if (error == 0) {
inp->inp_vflag |= INP_IPV4;
inp->inp_vflag &= ~INP_IPV6;
+ SOCK_LOCK(so);
soisconnected(so);
+ SOCK_UNLOCK(so);
}
return error;
}
@@ -629,7 +666,9 @@ udp6_connect(struct socket *so, struct sockaddr *nam, struct thread *td)
inp->inp_vflag &= ~INP_IPV4;
inp->inp_vflag |= INP_IPV6;
}
+ SOCK_LOCK(so);
soisconnected(so);
+ SOCK_UNLOCK(so);
}
return error;
}
@@ -673,7 +712,9 @@ udp6_disconnect(struct socket *so)
in6_pcbdisconnect(inp);
inp->in6p_laddr = in6addr_any;
splx(s);
+ SOCK_LOCK(so);
so->so_state &= ~SS_ISCONNECTED; /* XXX */
+ SOCK_UNLOCK(so);
return 0;
}
OpenPOWER on IntegriCloud