Changeset View
Changeset View
Standalone View
Standalone View
head/sys/netinet/udp_usrreq.c
Show First 20 Lines • Show All 298 Lines • ▼ Show 20 Lines | |||||
* multicast). | * multicast). | ||||
*/ | */ | ||||
static int | static int | ||||
udp_append(struct inpcb *inp, struct ip *ip, struct mbuf *n, int off, | udp_append(struct inpcb *inp, struct ip *ip, struct mbuf *n, int off, | ||||
struct sockaddr_in *udp_in) | struct sockaddr_in *udp_in) | ||||
{ | { | ||||
struct sockaddr *append_sa; | struct sockaddr *append_sa; | ||||
struct socket *so; | struct socket *so; | ||||
struct mbuf *opts = NULL; | struct mbuf *tmpopts, *opts = NULL; | ||||
#ifdef INET6 | #ifdef INET6 | ||||
struct sockaddr_in6 udp_in6; | struct sockaddr_in6 udp_in6; | ||||
#endif | #endif | ||||
struct udpcb *up; | struct udpcb *up; | ||||
INP_LOCK_ASSERT(inp); | INP_LOCK_ASSERT(inp); | ||||
/* | /* | ||||
* Engage the tunneling protocol. | * Engage the tunneling protocol. | ||||
*/ | */ | ||||
up = intoudpcb(inp); | up = intoudpcb(inp); | ||||
if (up->u_tun_func != NULL) { | if (up->u_tun_func != NULL) { | ||||
in_pcbref(inp); | in_pcbref(inp); | ||||
INP_RUNLOCK(inp); | INP_RUNLOCK(inp); | ||||
(*up->u_tun_func)(n, off, inp, (struct sockaddr *)udp_in, | (*up->u_tun_func)(n, off, inp, (struct sockaddr *)&udp_in[0], | ||||
up->u_tun_ctx); | up->u_tun_ctx); | ||||
INP_RLOCK(inp); | INP_RLOCK(inp); | ||||
return (in_pcbrele_rlocked(inp)); | return (in_pcbrele_rlocked(inp)); | ||||
} | } | ||||
off += sizeof(struct udphdr); | off += sizeof(struct udphdr); | ||||
#if defined(IPSEC) || defined(IPSEC_SUPPORT) | #if defined(IPSEC) || defined(IPSEC_SUPPORT) | ||||
Show All 19 Lines | if (inp->inp_flags & INP_CONTROLOPTS || | ||||
inp->inp_socket->so_options & (SO_TIMESTAMP | SO_BINTIME)) { | inp->inp_socket->so_options & (SO_TIMESTAMP | SO_BINTIME)) { | ||||
#ifdef INET6 | #ifdef INET6 | ||||
if (inp->inp_vflag & INP_IPV6) | if (inp->inp_vflag & INP_IPV6) | ||||
(void)ip6_savecontrol_v4(inp, n, &opts, NULL); | (void)ip6_savecontrol_v4(inp, n, &opts, NULL); | ||||
else | else | ||||
#endif /* INET6 */ | #endif /* INET6 */ | ||||
ip_savecontrol(inp, &opts, ip, n); | ip_savecontrol(inp, &opts, ip, n); | ||||
} | } | ||||
if ((inp->inp_vflag & INP_IPV4) && (inp->inp_flags2 & INP_ORIGDSTADDR)) { | |||||
tmpopts = sbcreatecontrol((caddr_t)&udp_in[1], | |||||
sizeof(struct sockaddr_in), IP_ORIGDSTADDR, IPPROTO_IP); | |||||
if (tmpopts) { | |||||
if (opts) { | |||||
tmpopts->m_next = opts; | |||||
opts = tmpopts; | |||||
} else | |||||
opts = tmpopts; | |||||
} | |||||
} | |||||
#ifdef INET6 | #ifdef INET6 | ||||
if (inp->inp_vflag & INP_IPV6) { | if (inp->inp_vflag & INP_IPV6) { | ||||
bzero(&udp_in6, sizeof(udp_in6)); | bzero(&udp_in6, sizeof(udp_in6)); | ||||
udp_in6.sin6_len = sizeof(udp_in6); | udp_in6.sin6_len = sizeof(udp_in6); | ||||
udp_in6.sin6_family = AF_INET6; | udp_in6.sin6_family = AF_INET6; | ||||
in6_sin_2_v4mapsin6(udp_in, &udp_in6); | in6_sin_2_v4mapsin6(&udp_in[0], &udp_in6); | ||||
append_sa = (struct sockaddr *)&udp_in6; | append_sa = (struct sockaddr *)&udp_in6; | ||||
} else | } else | ||||
#endif /* INET6 */ | #endif /* INET6 */ | ||||
append_sa = (struct sockaddr *)udp_in; | append_sa = (struct sockaddr *)&udp_in[0]; | ||||
m_adj(n, off); | m_adj(n, off); | ||||
so = inp->inp_socket; | so = inp->inp_socket; | ||||
SOCKBUF_LOCK(&so->so_rcv); | SOCKBUF_LOCK(&so->so_rcv); | ||||
if (sbappendaddr_locked(&so->so_rcv, append_sa, n, opts) == 0) { | if (sbappendaddr_locked(&so->so_rcv, append_sa, n, opts) == 0) { | ||||
SOCKBUF_UNLOCK(&so->so_rcv); | SOCKBUF_UNLOCK(&so->so_rcv); | ||||
m_freem(n); | m_freem(n); | ||||
if (opts) | if (opts) | ||||
Show All 9 Lines | |||||
{ | { | ||||
struct ip *ip; | struct ip *ip; | ||||
struct udphdr *uh; | struct udphdr *uh; | ||||
struct ifnet *ifp; | struct ifnet *ifp; | ||||
struct inpcb *inp; | struct inpcb *inp; | ||||
uint16_t len, ip_len; | uint16_t len, ip_len; | ||||
struct inpcbinfo *pcbinfo; | struct inpcbinfo *pcbinfo; | ||||
struct ip save_ip; | struct ip save_ip; | ||||
struct sockaddr_in udp_in; | struct sockaddr_in udp_in[2]; | ||||
struct mbuf *m; | struct mbuf *m; | ||||
struct m_tag *fwd_tag; | struct m_tag *fwd_tag; | ||||
int cscov_partial, iphlen; | int cscov_partial, iphlen; | ||||
m = *mp; | m = *mp; | ||||
iphlen = *offp; | iphlen = *offp; | ||||
ifp = m->m_pkthdr.rcvif; | ifp = m->m_pkthdr.rcvif; | ||||
*mp = NULL; | *mp = NULL; | ||||
Show All 28 Lines | udp_input(struct mbuf **mp, int *offp, int proto) | ||||
*/ | */ | ||||
if (uh->uh_dport == 0) | if (uh->uh_dport == 0) | ||||
goto badunlocked; | goto badunlocked; | ||||
/* | /* | ||||
* Construct sockaddr format source address. Stuff source address | * Construct sockaddr format source address. Stuff source address | ||||
* and datagram in user buffer. | * and datagram in user buffer. | ||||
*/ | */ | ||||
bzero(&udp_in, sizeof(udp_in)); | bzero(&udp_in[0], sizeof(struct sockaddr_in) * 2); | ||||
udp_in.sin_len = sizeof(udp_in); | udp_in[0].sin_len = sizeof(struct sockaddr_in); | ||||
udp_in.sin_family = AF_INET; | udp_in[0].sin_family = AF_INET; | ||||
udp_in.sin_port = uh->uh_sport; | udp_in[0].sin_port = uh->uh_sport; | ||||
udp_in.sin_addr = ip->ip_src; | udp_in[0].sin_addr = ip->ip_src; | ||||
udp_in[1].sin_len = sizeof(struct sockaddr_in); | |||||
udp_in[1].sin_family = AF_INET; | |||||
udp_in[1].sin_port = uh->uh_dport; | |||||
udp_in[1].sin_addr = ip->ip_dst; | |||||
/* | /* | ||||
* Make mbuf data length reflect UDP length. If not enough data to | * Make mbuf data length reflect UDP length. If not enough data to | ||||
* reflect UDP length, drop. | * reflect UDP length, drop. | ||||
*/ | */ | ||||
len = ntohs((u_short)uh->uh_ulen); | len = ntohs((u_short)uh->uh_ulen); | ||||
ip_len = ntohs(ip->ip_len) - iphlen; | ip_len = ntohs(ip->ip_len) - iphlen; | ||||
if (proto == IPPROTO_UDPLITE && (len == 0 || len == ip_len)) { | if (proto == IPPROTO_UDPLITE && (len == 0 || len == ip_len)) { | ||||
▲ Show 20 Lines • Show All 112 Lines • ▼ Show 20 Lines | #endif | ||||
} | } | ||||
bzero(&group, sizeof(struct sockaddr_in)); | bzero(&group, sizeof(struct sockaddr_in)); | ||||
group.sin_len = sizeof(struct sockaddr_in); | group.sin_len = sizeof(struct sockaddr_in); | ||||
group.sin_family = AF_INET; | group.sin_family = AF_INET; | ||||
group.sin_addr = ip->ip_dst; | group.sin_addr = ip->ip_dst; | ||||
blocked = imo_multi_filter(imo, ifp, | blocked = imo_multi_filter(imo, ifp, | ||||
(struct sockaddr *)&group, | (struct sockaddr *)&group, | ||||
(struct sockaddr *)&udp_in); | (struct sockaddr *)&udp_in[0]); | ||||
if (blocked != MCAST_PASS) { | if (blocked != MCAST_PASS) { | ||||
if (blocked == MCAST_NOTGMEMBER) | if (blocked == MCAST_NOTGMEMBER) | ||||
IPSTAT_INC(ips_notmember); | IPSTAT_INC(ips_notmember); | ||||
if (blocked == MCAST_NOTSMEMBER || | if (blocked == MCAST_NOTSMEMBER || | ||||
blocked == MCAST_MUTED) | blocked == MCAST_MUTED) | ||||
UDPSTAT_INC(udps_filtermcast); | UDPSTAT_INC(udps_filtermcast); | ||||
INP_RUNLOCK(inp); | INP_RUNLOCK(inp); | ||||
continue; | continue; | ||||
} | } | ||||
} | } | ||||
if (last != NULL) { | if (last != NULL) { | ||||
struct mbuf *n; | struct mbuf *n; | ||||
if ((n = m_copym(m, 0, M_COPYALL, M_NOWAIT)) != | if ((n = m_copym(m, 0, M_COPYALL, M_NOWAIT)) != | ||||
NULL) { | NULL) { | ||||
UDP_PROBE(receive, NULL, last, ip, | UDP_PROBE(receive, NULL, last, ip, | ||||
last, uh); | last, uh); | ||||
if (udp_append(last, ip, n, iphlen, | if (udp_append(last, ip, n, iphlen, | ||||
&udp_in)) { | udp_in)) { | ||||
goto inp_lost; | goto inp_lost; | ||||
} | } | ||||
} | } | ||||
INP_RUNLOCK(last); | INP_RUNLOCK(last); | ||||
} | } | ||||
last = inp; | last = inp; | ||||
/* | /* | ||||
* Don't look for additional matches if this one does | * Don't look for additional matches if this one does | ||||
Show All 16 Lines | if (last == NULL) { | ||||
*/ | */ | ||||
UDPSTAT_INC(udps_noportbcast); | UDPSTAT_INC(udps_noportbcast); | ||||
if (inp) | if (inp) | ||||
INP_RUNLOCK(inp); | INP_RUNLOCK(inp); | ||||
INP_INFO_RUNLOCK(pcbinfo); | INP_INFO_RUNLOCK(pcbinfo); | ||||
goto badunlocked; | goto badunlocked; | ||||
} | } | ||||
UDP_PROBE(receive, NULL, last, ip, last, uh); | UDP_PROBE(receive, NULL, last, ip, last, uh); | ||||
if (udp_append(last, ip, m, iphlen, &udp_in) == 0) | if (udp_append(last, ip, m, iphlen, udp_in) == 0) | ||||
INP_RUNLOCK(last); | INP_RUNLOCK(last); | ||||
inp_lost: | inp_lost: | ||||
INP_INFO_RUNLOCK(pcbinfo); | INP_INFO_RUNLOCK(pcbinfo); | ||||
return (IPPROTO_DONE); | return (IPPROTO_DONE); | ||||
} | } | ||||
/* | /* | ||||
* Locate pcb for datagram. | * Locate pcb for datagram. | ||||
▲ Show 20 Lines • Show All 73 Lines • ▼ Show 20 Lines | if (cscov_partial) { | ||||
if (up->u_rxcslen == 0 || up->u_rxcslen > len) { | if (up->u_rxcslen == 0 || up->u_rxcslen > len) { | ||||
INP_RUNLOCK(inp); | INP_RUNLOCK(inp); | ||||
m_freem(m); | m_freem(m); | ||||
return (IPPROTO_DONE); | return (IPPROTO_DONE); | ||||
} | } | ||||
} | } | ||||
UDP_PROBE(receive, NULL, inp, ip, inp, uh); | UDP_PROBE(receive, NULL, inp, ip, inp, uh); | ||||
if (udp_append(inp, ip, m, iphlen, &udp_in) == 0) | if (udp_append(inp, ip, m, iphlen, udp_in) == 0) | ||||
INP_RUNLOCK(inp); | INP_RUNLOCK(inp); | ||||
return (IPPROTO_DONE); | return (IPPROTO_DONE); | ||||
badunlocked: | badunlocked: | ||||
m_freem(m); | m_freem(m); | ||||
return (IPPROTO_DONE); | return (IPPROTO_DONE); | ||||
} | } | ||||
#endif /* INET */ | #endif /* INET */ | ||||
▲ Show 20 Lines • Show All 1,071 Lines • Show Last 20 Lines |