Changeset View
Changeset View
Standalone View
Standalone View
sys/netinet6/udp6_usrreq.c
Show First 20 Lines • Show All 125 Lines • ▼ Show 20 Lines | |||||
#include <security/mac/mac_framework.h> | #include <security/mac/mac_framework.h> | ||||
VNET_DEFINE(int, zero_checksum_port) = 0; | VNET_DEFINE(int, zero_checksum_port) = 0; | ||||
#define V_zero_checksum_port VNET(zero_checksum_port) | #define V_zero_checksum_port VNET(zero_checksum_port) | ||||
SYSCTL_INT(_net_inet6_udp6, OID_AUTO, rfc6935_port, CTLFLAG_VNET | CTLFLAG_RW, | SYSCTL_INT(_net_inet6_udp6, OID_AUTO, rfc6935_port, CTLFLAG_VNET | CTLFLAG_RW, | ||||
&VNET_NAME(zero_checksum_port), 0, | &VNET_NAME(zero_checksum_port), 0, | ||||
"Zero UDP checksum allowed for traffic to/from this port."); | "Zero UDP checksum allowed for traffic to/from this port."); | ||||
/* netinet/udp_usrreqs.c */ | |||||
pr_abort_t udp_abort; | |||||
pr_disconnect_t udp_disconnect; | |||||
pr_send_t udp_send; | |||||
melifaro: We already include `netinet/udp_var.h`, which contains `udp_input()` and other similar… | |||||
Done Inline ActionsI think that when a function is shared only between two files, it is better not make it officially public. glebius: I think that when a function is shared only between two files, it is better not make it… | |||||
/* | /* | ||||
* UDP protocol implementation. | * UDP protocol implementation. | ||||
* Per RFC 768, August, 1980. | * Per RFC 768, August, 1980. | ||||
*/ | */ | ||||
extern struct protosw inetsw[]; | |||||
static void udp6_detach(struct socket *so); | static void udp6_detach(struct socket *so); | ||||
static int | static int | ||||
udp6_append(struct inpcb *inp, struct mbuf *n, int off, | udp6_append(struct inpcb *inp, struct mbuf *n, int off, | ||||
struct sockaddr_in6 *fromsa) | struct sockaddr_in6 *fromsa) | ||||
{ | { | ||||
struct socket *so; | struct socket *so; | ||||
struct mbuf *opts = NULL, *tmp_opts; | struct mbuf *opts = NULL, *tmp_opts; | ||||
▲ Show 20 Lines • Show All 624 Lines • ▼ Show 20 Lines | if ((inp->inp_flags & IN6P_IPV6_V6ONLY) == 0) { | ||||
int hasv4addr; | int hasv4addr; | ||||
if (sin6 == NULL) | if (sin6 == NULL) | ||||
hasv4addr = (inp->inp_vflag & INP_IPV4); | hasv4addr = (inp->inp_vflag & INP_IPV4); | ||||
else | else | ||||
hasv4addr = IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr) | hasv4addr = IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr) | ||||
? 1 : 0; | ? 1 : 0; | ||||
if (hasv4addr) { | if (hasv4addr) { | ||||
struct pr_usrreqs *pru; | |||||
/* | /* | ||||
* XXXRW: We release UDP-layer locks before calling | * XXXRW: We release UDP-layer locks before calling | ||||
* udp_send() in order to avoid recursion. However, | * udp_send() in order to avoid recursion. However, | ||||
* this does mean there is a short window where inp's | * this does mean there is a short window where inp's | ||||
* fields are unstable. Could this lead to a | * fields are unstable. Could this lead to a | ||||
* potential race in which the factors causing us to | * potential race in which the factors causing us to | ||||
* select the UDPv4 output routine are invalidated? | * select the UDPv4 output routine are invalidated? | ||||
*/ | */ | ||||
INP_UNLOCK(inp); | INP_UNLOCK(inp); | ||||
if (sin6) | if (sin6) | ||||
in6_sin6_2_sin_in_sock((struct sockaddr *)sin6); | in6_sin6_2_sin_in_sock((struct sockaddr *)sin6); | ||||
pru = inetsw[ip_protox[nxt]].pr_usrreqs; | |||||
/* addr will just be freed in sendit(). */ | /* addr will just be freed in sendit(). */ | ||||
return ((*pru->pru_send)(so, flags_arg | PRUS_IPV6, m, | return (udp_send(so, flags_arg | PRUS_IPV6, m, | ||||
(struct sockaddr *)sin6, control, td)); | (struct sockaddr *)sin6, control, td)); | ||||
} | } | ||||
} else | } else | ||||
#endif | #endif | ||||
if (sin6 && IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)) { | if (sin6 && IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)) { | ||||
/* | /* | ||||
* Given this is either an IPv6-only socket or no INET is | * Given this is either an IPv6-only socket or no INET is | ||||
* supported we will fail the send if the given destination | * supported we will fail the send if the given destination | ||||
▲ Show 20 Lines • Show All 194 Lines • ▼ Show 20 Lines | udp6_abort(struct socket *so) | ||||
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_abort: inp == NULL")); | KASSERT(inp != NULL, ("udp6_abort: 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; | |||||
uint8_t nxt; | |||||
nxt = (inp->inp_socket->so_proto->pr_protocol == IPPROTO_UDP) ? | |||||
IPPROTO_UDP : IPPROTO_UDPLITE; | |||||
INP_WUNLOCK(inp); | INP_WUNLOCK(inp); | ||||
pru = inetsw[ip_protox[nxt]].pr_usrreqs; | udp_abort(so); | ||||
(*pru->pru_abort)(so); | |||||
return; | return; | ||||
} | } | ||||
#endif | #endif | ||||
if (!IN6_IS_ADDR_UNSPECIFIED(&inp->in6p_faddr)) { | if (!IN6_IS_ADDR_UNSPECIFIED(&inp->in6p_faddr)) { | ||||
INP_HASH_WLOCK(pcbinfo); | INP_HASH_WLOCK(pcbinfo); | ||||
in6_pcbdisconnect(inp); | in6_pcbdisconnect(inp); | ||||
inp->in6p_laddr = in6addr_any; | inp->in6p_laddr = in6addr_any; | ||||
▲ Show 20 Lines • Show All 104 Lines • ▼ Show 20 Lines | udp6_close(struct socket *so) | ||||
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_close: inp == NULL")); | KASSERT(inp != NULL, ("udp6_close: 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; | |||||
uint8_t nxt; | |||||
nxt = (inp->inp_socket->so_proto->pr_protocol == IPPROTO_UDP) ? | |||||
IPPROTO_UDP : IPPROTO_UDPLITE; | |||||
INP_WUNLOCK(inp); | INP_WUNLOCK(inp); | ||||
pru = inetsw[ip_protox[nxt]].pr_usrreqs; | (void)udp_disconnect(so); | ||||
(*pru->pru_disconnect)(so); | |||||
return; | return; | ||||
} | } | ||||
#endif | #endif | ||||
if (!IN6_IS_ADDR_UNSPECIFIED(&inp->in6p_faddr)) { | if (!IN6_IS_ADDR_UNSPECIFIED(&inp->in6p_faddr)) { | ||||
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); | ||||
▲ Show 20 Lines • Show All 128 Lines • ▼ Show 20 Lines | udp6_disconnect(struct socket *so) | ||||
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; | |||||
uint8_t nxt; | |||||
nxt = (inp->inp_socket->so_proto->pr_protocol == IPPROTO_UDP) ? | |||||
IPPROTO_UDP : IPPROTO_UDPLITE; | |||||
INP_WUNLOCK(inp); | INP_WUNLOCK(inp); | ||||
pru = inetsw[ip_protox[nxt]].pr_usrreqs; | (void)udp_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)) { | ||||
INP_WUNLOCK(inp); | INP_WUNLOCK(inp); | ||||
return (ENOTCONN); | return (ENOTCONN); | ||||
} | } | ||||
▲ Show 20 Lines • Show All 55 Lines • Show Last 20 Lines |
We already include netinet/udp_var.h, which contains udp_input() and other similar functions definitions. Maybe worth putting these definitions there?