Changeset View
Standalone View
sys/netinet6/udp6_usrreq.c
Show First 20 Lines • Show All 1,177 Lines • ▼ Show 20 Lines | udp6_detach(struct socket *so) | ||||
udp_discardcb(up); | udp_discardcb(up); | ||||
} | } | ||||
static int | static int | ||||
udp6_disconnect(struct socket *so) | udp6_disconnect(struct socket *so) | ||||
{ | { | ||||
struct inpcb *inp; | struct inpcb *inp; | ||||
struct inpcbinfo *pcbinfo; | struct inpcbinfo *pcbinfo; | ||||
int error; | |||||
pcbinfo = udp_get_inpcbinfo(so->so_proto->pr_protocol); | pcbinfo = udp_get_inpcbinfo(so->so_proto->pr_protocol); | ||||
inp = sotoinpcb(so); | inp = sotoinpcb(so); | ||||
KASSERT(inp != NULL, ("udp6_disconnect: inp == NULL")); | KASSERT(inp != NULL, ("udp6_disconnect: inp == NULL")); | ||||
INP_WLOCK(inp); | INP_WLOCK(inp); | ||||
#ifdef INET | #ifdef INET | ||||
if (inp->inp_vflag & INP_IPV4) { | if (inp->inp_vflag & INP_IPV4) { | ||||
struct pr_usrreqs *pru; | struct pr_usrreqs *pru; | ||||
uint8_t nxt; | uint8_t nxt; | ||||
nxt = (inp->inp_socket->so_proto->pr_protocol == IPPROTO_UDP) ? | nxt = (inp->inp_socket->so_proto->pr_protocol == IPPROTO_UDP) ? | ||||
IPPROTO_UDP : IPPROTO_UDPLITE; | IPPROTO_UDP : IPPROTO_UDPLITE; | ||||
INP_WUNLOCK(inp); | INP_WUNLOCK(inp); | ||||
pru = inetsw[ip_protox[nxt]].pr_usrreqs; | pru = inetsw[ip_protox[nxt]].pr_usrreqs; | ||||
(void)(*pru->pru_disconnect)(so); | (void)(*pru->pru_disconnect)(so); | ||||
return (0); | return (0); | ||||
} | } | ||||
#endif | #endif | ||||
if (IN6_IS_ADDR_UNSPECIFIED(&inp->in6p_faddr)) { | if (IN6_IS_ADDR_UNSPECIFIED(&inp->in6p_faddr)) { | ||||
error = ENOTCONN; | |||||
goto out; | goto out; | ||||
} | } | ||||
INP_HASH_WLOCK(pcbinfo); | INP_HASH_WLOCK(pcbinfo); | ||||
in6_pcbdisconnect(inp); | in6_pcbdisconnect(inp); | ||||
inp->in6p_laddr = in6addr_any; | inp->in6p_laddr = in6addr_any; | ||||
INP_HASH_WUNLOCK(pcbinfo); | INP_HASH_WUNLOCK(pcbinfo); | ||||
SOCK_LOCK(so); | SOCK_LOCK(so); | ||||
so->so_state &= ~SS_ISCONNECTED; /* XXX */ | so->so_state &= ~SS_ISCONNECTED; /* XXX */ | ||||
SOCK_UNLOCK(so); | SOCK_UNLOCK(so); | ||||
out: | out: | ||||
INP_WUNLOCK(inp); | INP_WUNLOCK(inp); | ||||
return (0); | return (0); | ||||
rwatson: Surely the bug to fix here is a lack of "return (error)" rather than the setting of error? | |||||
kanAuthorUnsubmitted Not Done Inline ActionsIs the error code _expected_ in this condition? That is surely the real question :) kan: Is the error code _expected_ in this condition? That is surely the real question :) | |||||
rwatsonUnsubmitted Done Inline ActionsIt looks like in UDPv4, an error is expected to be returned: 1898 static int 1899 udp_disconnect(struct socket *so) 1900 { 1901 struct inpcb *inp; 1902 struct inpcbinfo *pcbinfo; 1903 1904 pcbinfo = udp_get_inpcbinfo(so->so_proto->pr_protocol); 1905 inp = sotoinpcb(so); 1906 KASSERT(inp != NULL, ("udp_disconnect: inp == NULL")); 1907 INP_WLOCK(inp); 1908 if (inp->inp_faddr.s_addr == INADDR_ANY) { 1909 INP_WUNLOCK(inp); 1910 return (ENOTCONN); 1911 } 1912 INP_HASH_WLOCK(pcbinfo); 1913 in_pcbdisconnect(inp); 1914 inp->inp_laddr.s_addr = INADDR_ANY; 1915 INP_HASH_WUNLOCK(pcbinfo); 1916 SOCK_LOCK(so); 1917 so->so_state &= ~SS_ISCONNECTED; /* XXX */ 1918 SOCK_UNLOCK(so); 1919 INP_WUNLOCK(inp); 1920 return (0); 1921 } So it is likely a UDPv6 bug that the error is not properly returned. rwatson: It looks like in UDPv4, an error is expected to be returned:
```
1898 static int
1899… | |||||
kanAuthorUnsubmitted Not Done Inline ActionsUmm, but the code above, that does ipv4 fallback is explicitly ignoring pru_disconnect's return code: (void)(*pru->pru_disconnect)(so); kan: Umm, but the code above, that does ipv4 fallback is explicitly ignoring pru_disconnect's return… | |||||
rwatsonUnsubmitted Not Done Inline ActionsSounds like another IPv6 bug, but perhaps out-of-scope for fixing in this particular patch. In general, I think we should be aiming for consistency with UDPv4 when it comes to UPv6 socket semantics, and differences are likely due to KAME bugs, changes made later to UDPv4 and not propagated to UDPv6, or bugs introduced in UDPv6 during fine-grained locking work. Thanks for making this change -- it's probably better than the alternative. rwatson: Sounds like another IPv6 bug, but perhaps out-of-scope for fixing in this particular patch. In… | |||||
} | } | ||||
static int | static int | ||||
udp6_send(struct socket *so, int flags, struct mbuf *m, | udp6_send(struct socket *so, int flags, struct mbuf *m, | ||||
struct sockaddr *addr, struct mbuf *control, struct thread *td) | struct sockaddr *addr, struct mbuf *control, struct thread *td) | ||||
{ | { | ||||
struct inpcb *inp; | struct inpcb *inp; | ||||
struct inpcbinfo *pcbinfo; | struct inpcbinfo *pcbinfo; | ||||
▲ Show 20 Lines • Show All 86 Lines • Show Last 20 Lines |
Surely the bug to fix here is a lack of "return (error)" rather than the setting of error?