diff options
author | sam <sam@FreeBSD.org> | 2003-11-08 22:53:41 +0000 |
---|---|---|
committer | sam <sam@FreeBSD.org> | 2003-11-08 22:53:41 +0000 |
commit | b88d477c4e8d1f8d84c66c3e619ae1fb9e239711 (patch) | |
tree | a35521b91293ec5e459b954e8d8de9dddfeb5770 /sys/netinet/raw_ip.c | |
parent | 354edc9c36ffffe61593e23f55a43078edf473fb (diff) | |
download | FreeBSD-src-b88d477c4e8d1f8d84c66c3e619ae1fb9e239711.zip FreeBSD-src-b88d477c4e8d1f8d84c66c3e619ae1fb9e239711.tar.gz |
add some missing locking
Supported by: FreeBSD Foundation
Diffstat (limited to 'sys/netinet/raw_ip.c')
-rw-r--r-- | sys/netinet/raw_ip.c | 92 |
1 files changed, 75 insertions, 17 deletions
diff --git a/sys/netinet/raw_ip.c b/sys/netinet/raw_ip.c index 0484f32..1c861f4 100644 --- a/sys/netinet/raw_ip.c +++ b/sys/netinet/raw_ip.c @@ -556,6 +556,21 @@ rip_attach(struct socket *so, int proto, struct thread *td) return 0; } +static void +rip_pcbdetach(struct socket *so, struct inpcb *inp) +{ + INP_INFO_WLOCK_ASSERT(&ripcbinfo); + INP_LOCK_ASSERT(inp); + + if (so == ip_mrouter && ip_mrouter_done) + ip_mrouter_done(); + if (ip_rsvp_force_done) + ip_rsvp_force_done(so); + if (so == ip_rsvpd) + ip_rsvp_done(); + in_pcbdetach(inp); +} + static int rip_detach(struct socket *so) { @@ -569,13 +584,7 @@ rip_detach(struct socket *so) return EINVAL; } INP_LOCK(inp); - if (so == ip_mrouter && ip_mrouter_done) - ip_mrouter_done(); - if (ip_rsvp_force_done) - ip_rsvp_force_done(so); - if (so == ip_rsvpd) - ip_rsvp_done(); - in_pcbdetach(inp); + rip_pcbdetach(so, inp); INP_INFO_WUNLOCK(&ripcbinfo); return 0; } @@ -583,9 +592,19 @@ rip_detach(struct socket *so) static int rip_abort(struct socket *so) { + struct inpcb *inp; + + INP_INFO_WLOCK(&ripcbinfo); + inp = sotoinpcb(so); + if (inp == 0) { + INP_INFO_WUNLOCK(&ripcbinfo); + return EINVAL; /* ??? possible? panic instead? */ + } + INP_LOCK(inp); soisdisconnected(so); if (so->so_state & SS_NOFDREF) - return rip_detach(so); + rip_pcbdetach(so, inp); + INP_INFO_WUNLOCK(&ripcbinfo); return 0; } @@ -600,43 +619,73 @@ rip_disconnect(struct socket *so) static int rip_bind(struct socket *so, struct sockaddr *nam, struct thread *td) { - struct inpcb *inp = sotoinpcb(so); struct sockaddr_in *addr = (struct sockaddr_in *)nam; + struct inpcb *inp; if (nam->sa_len != sizeof(*addr)) return EINVAL; - if (TAILQ_EMPTY(&ifnet) || ((addr->sin_family != AF_INET) && - (addr->sin_family != AF_IMPLINK)) || + if (TAILQ_EMPTY(&ifnet) || + (addr->sin_family != AF_INET && addr->sin_family != AF_IMPLINK) || (addr->sin_addr.s_addr && ifa_ifwithaddr((struct sockaddr *)addr) == 0)) return EADDRNOTAVAIL; + + INP_INFO_WLOCK(&ripcbinfo); + inp = sotoinpcb(so); + if (inp == 0) { + INP_INFO_WUNLOCK(&ripcbinfo); + return EINVAL; + } + INP_LOCK(inp); inp->inp_laddr = addr->sin_addr; + INP_UNLOCK(inp); + INP_INFO_WUNLOCK(&ripcbinfo); return 0; } static int rip_connect(struct socket *so, struct sockaddr *nam, struct thread *td) { - struct inpcb *inp = sotoinpcb(so); struct sockaddr_in *addr = (struct sockaddr_in *)nam; + struct inpcb *inp; if (nam->sa_len != sizeof(*addr)) return EINVAL; if (TAILQ_EMPTY(&ifnet)) return EADDRNOTAVAIL; - if ((addr->sin_family != AF_INET) && - (addr->sin_family != AF_IMPLINK)) + if (addr->sin_family != AF_INET && addr->sin_family != AF_IMPLINK) return EAFNOSUPPORT; + + INP_INFO_WLOCK(&ripcbinfo); + inp = sotoinpcb(so); + if (inp == 0) { + INP_INFO_WUNLOCK(&ripcbinfo); + return EINVAL; + } + INP_LOCK(inp); inp->inp_faddr = addr->sin_addr; soisconnected(so); + INP_UNLOCK(inp); + INP_INFO_WUNLOCK(&ripcbinfo); return 0; } static int rip_shutdown(struct socket *so) { + struct inpcb *inp; + + INP_INFO_RLOCK(&ripcbinfo); + inp = sotoinpcb(so); + if (inp == 0) { + INP_INFO_RUNLOCK(&ripcbinfo); + return EINVAL; + } + INP_LOCK(inp); + INP_INFO_RUNLOCK(&ripcbinfo); socantsendmore(so); + INP_UNLOCK(inp); return 0; } @@ -644,23 +693,32 @@ static int rip_send(struct socket *so, int flags, struct mbuf *m, struct sockaddr *nam, struct mbuf *control, struct thread *td) { - struct inpcb *inp = sotoinpcb(so); - register u_long dst; + struct inpcb *inp; + u_long dst; + int ret; + INP_INFO_WLOCK(&ripcbinfo); + inp = sotoinpcb(so); if (so->so_state & SS_ISCONNECTED) { if (nam) { + INP_INFO_WUNLOCK(&ripcbinfo); m_freem(m); return EISCONN; } dst = inp->inp_faddr.s_addr; } else { if (nam == NULL) { + INP_INFO_WUNLOCK(&ripcbinfo); m_freem(m); return ENOTCONN; } dst = ((struct sockaddr_in *)nam)->sin_addr.s_addr; } - return rip_output(m, so, dst); + INP_LOCK(inp); + ret = rip_output(m, so, dst); + INP_UNLOCK(inp); + INP_INFO_WUNLOCK(&ripcbinfo); + return ret; } static int |