aboutsummaryrefslogtreecommitdiff
path: root/sys/netinet/udp_usrreq.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/netinet/udp_usrreq.c')
-rw-r--r--sys/netinet/udp_usrreq.c42
1 files changed, 22 insertions, 20 deletions
diff --git a/sys/netinet/udp_usrreq.c b/sys/netinet/udp_usrreq.c
index 4b565fcc4f86..5860c579e749 100644
--- a/sys/netinet/udp_usrreq.c
+++ b/sys/netinet/udp_usrreq.c
@@ -368,10 +368,9 @@ udp_append(struct inpcb *inp, struct ip *ip, struct mbuf *n, int off,
sorwakeup_locked(so);
}
-void
-udp_input(struct mbuf *m, int off)
+int
+udp_input(struct mbuf **mp, int *offp, int proto)
{
- int iphlen = off;
struct ip *ip;
struct udphdr *uh;
struct ifnet *ifp;
@@ -380,11 +379,14 @@ udp_input(struct mbuf *m, int off)
struct inpcbinfo *pcbinfo;
struct ip save_ip;
struct sockaddr_in udp_in;
+ struct mbuf *m;
struct m_tag *fwd_tag;
- int cscov_partial;
- uint8_t pr;
+ int cscov_partial, iphlen;
+ m = *mp;
+ iphlen = *offp;
ifp = m->m_pkthdr.rcvif;
+ *mp = NULL;
UDPSTAT_INC(udps_ipackets);
/*
@@ -404,13 +406,12 @@ udp_input(struct mbuf *m, int off)
if (m->m_len < iphlen + sizeof(struct udphdr)) {
if ((m = m_pullup(m, iphlen + sizeof(struct udphdr))) == NULL) {
UDPSTAT_INC(udps_hdrops);
- return;
+ return (IPPROTO_DONE);
}
ip = mtod(m, struct ip *);
}
uh = (struct udphdr *)((caddr_t)ip + iphlen);
- pr = ip->ip_p;
- cscov_partial = (pr == IPPROTO_UDPLITE) ? 1 : 0;
+ cscov_partial = (proto == IPPROTO_UDPLITE) ? 1 : 0;
/*
* Destination port of 0 is illegal, based on RFC768.
@@ -434,7 +435,7 @@ udp_input(struct mbuf *m, int off)
*/
len = ntohs((u_short)uh->uh_ulen);
ip_len = ntohs(ip->ip_len) - iphlen;
- if (pr == IPPROTO_UDPLITE && len == 0) {
+ if (proto == IPPROTO_UDPLITE && len == 0) {
/* Zero means checksum over the complete packet. */
len = ip_len;
cscov_partial = 0;
@@ -444,7 +445,7 @@ udp_input(struct mbuf *m, int off)
UDPSTAT_INC(udps_badlen);
goto badunlocked;
}
- if (pr == IPPROTO_UDP)
+ if (proto == IPPROTO_UDP)
m_adj(m, len - ip_len);
}
@@ -470,14 +471,14 @@ udp_input(struct mbuf *m, int off)
else
uh_sum = in_pseudo(ip->ip_src.s_addr,
ip->ip_dst.s_addr, htonl((u_short)len +
- m->m_pkthdr.csum_data + pr));
+ m->m_pkthdr.csum_data + proto));
uh_sum ^= 0xffff;
} else {
char b[9];
bcopy(((struct ipovly *)ip)->ih_x1, b, 9);
bzero(((struct ipovly *)ip)->ih_x1, 9);
- ((struct ipovly *)ip)->ih_len = (pr == IPPROTO_UDP) ?
+ ((struct ipovly *)ip)->ih_len = (proto == IPPROTO_UDP) ?
uh->uh_ulen : htons(ip_len);
uh_sum = in_cksum(m, len + sizeof (struct ip));
bcopy(b, ((struct ipovly *)ip)->ih_x1, 9);
@@ -485,12 +486,12 @@ udp_input(struct mbuf *m, int off)
if (uh_sum) {
UDPSTAT_INC(udps_badsum);
m_freem(m);
- return;
+ return (IPPROTO_DONE);
}
} else
UDPSTAT_INC(udps_nosum);
- pcbinfo = get_inpcbinfo(pr);
+ pcbinfo = get_inpcbinfo(proto);
if (IN_MULTICAST(ntohl(ip->ip_dst.s_addr)) ||
in_broadcast(ip->ip_dst, ifp)) {
struct inpcb *last;
@@ -498,7 +499,7 @@ udp_input(struct mbuf *m, int off)
struct ip_moptions *imo;
INP_INFO_RLOCK(pcbinfo);
- pcblist = get_pcblist(pr);
+ pcblist = get_pcblist(proto);
last = NULL;
LIST_FOREACH(inp, pcblist, inp_list) {
if (inp->inp_lport != uh->uh_dport)
@@ -592,7 +593,7 @@ udp_input(struct mbuf *m, int off)
udp_append(last, ip, m, iphlen, &udp_in);
INP_RUNLOCK(last);
INP_INFO_RUNLOCK(pcbinfo);
- return;
+ return (IPPROTO_DONE);
}
/*
@@ -654,7 +655,7 @@ udp_input(struct mbuf *m, int off)
goto badunlocked;
*ip = save_ip;
icmp_error(m, ICMP_UNREACH, ICMP_UNREACH_PORT, 0, 0);
- return;
+ return (IPPROTO_DONE);
}
/*
@@ -664,7 +665,7 @@ udp_input(struct mbuf *m, int off)
if (inp->inp_ip_minttl && inp->inp_ip_minttl > ip->ip_ttl) {
INP_RUNLOCK(inp);
m_freem(m);
- return;
+ return (IPPROTO_DONE);
}
if (cscov_partial) {
struct udpcb *up;
@@ -673,17 +674,18 @@ udp_input(struct mbuf *m, int off)
if (up->u_rxcslen > len) {
INP_RUNLOCK(inp);
m_freem(m);
- return;
+ return (IPPROTO_DONE);
}
}
UDP_PROBE(receive, NULL, inp, ip, inp, uh);
udp_append(inp, ip, m, iphlen, &udp_in);
INP_RUNLOCK(inp);
- return;
+ return (IPPROTO_DONE);
badunlocked:
m_freem(m);
+ return (IPPROTO_DONE);
}
#endif /* INET */