aboutsummaryrefslogtreecommitdiff
path: root/sys/netinet/igmp.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/netinet/igmp.c')
-rw-r--r--sys/netinet/igmp.c38
1 files changed, 21 insertions, 17 deletions
diff --git a/sys/netinet/igmp.c b/sys/netinet/igmp.c
index 4e2294824bbd..5419bb55c9ab 100644
--- a/sys/netinet/igmp.c
+++ b/sys/netinet/igmp.c
@@ -1424,26 +1424,29 @@ out_locked:
return (0);
}
-void
-igmp_input(struct mbuf *m, int off)
+int
+igmp_input(struct mbuf **mp, int *offp, int proto)
{
int iphlen;
struct ifnet *ifp;
struct igmp *igmp;
struct ip *ip;
+ struct mbuf *m;
int igmplen;
int minlen;
int queryver;
CTR3(KTR_IGMPV3, "%s: called w/mbuf (%p,%d)", __func__, m, off);
+ m = *mp;
ifp = m->m_pkthdr.rcvif;
+ *mp = NULL;
IGMPSTAT_INC(igps_rcv_total);
ip = mtod(m, struct ip *);
- iphlen = off;
- igmplen = ntohs(ip->ip_len) - off;
+ iphlen = *offp;
+ igmplen = ntohs(ip->ip_len) - iphlen;
/*
* Validate lengths.
@@ -1451,7 +1454,7 @@ igmp_input(struct mbuf *m, int off)
if (igmplen < IGMP_MINLEN) {
IGMPSTAT_INC(igps_rcv_tooshort);
m_freem(m);
- return;
+ return (IPPROTO_DONE);
}
/*
@@ -1466,7 +1469,7 @@ igmp_input(struct mbuf *m, int off)
if ((m->m_flags & M_EXT || m->m_len < minlen) &&
(m = m_pullup(m, minlen)) == 0) {
IGMPSTAT_INC(igps_rcv_tooshort);
- return;
+ return (IPPROTO_DONE);
}
ip = mtod(m, struct ip *);
@@ -1479,7 +1482,7 @@ igmp_input(struct mbuf *m, int off)
if (in_cksum(m, igmplen)) {
IGMPSTAT_INC(igps_rcv_badsum);
m_freem(m);
- return;
+ return (IPPROTO_DONE);
}
m->m_data -= iphlen;
m->m_len += iphlen;
@@ -1492,7 +1495,7 @@ igmp_input(struct mbuf *m, int off)
if (igmp->igmp_type != IGMP_DVMRP && ip->ip_ttl != 1) {
IGMPSTAT_INC(igps_rcv_badttl);
m_freem(m);
- return;
+ return (IPPROTO_DONE);
}
switch (igmp->igmp_type) {
@@ -1507,7 +1510,7 @@ igmp_input(struct mbuf *m, int off)
} else {
IGMPSTAT_INC(igps_rcv_tooshort);
m_freem(m);
- return;
+ return (IPPROTO_DONE);
}
switch (queryver) {
@@ -1517,7 +1520,7 @@ igmp_input(struct mbuf *m, int off)
break;
if (igmp_input_v1_query(ifp, ip, igmp) != 0) {
m_freem(m);
- return;
+ return (IPPROTO_DONE);
}
break;
@@ -1527,7 +1530,7 @@ igmp_input(struct mbuf *m, int off)
break;
if (igmp_input_v2_query(ifp, ip, igmp) != 0) {
m_freem(m);
- return;
+ return (IPPROTO_DONE);
}
break;
@@ -1546,7 +1549,7 @@ igmp_input(struct mbuf *m, int off)
srclen = sizeof(struct in_addr) * nsrc;
if (nsrc * sizeof(in_addr_t) > srclen) {
IGMPSTAT_INC(igps_rcv_tooshort);
- return;
+ return (IPPROTO_DONE);
}
/*
* m_pullup() may modify m, so pullup in
@@ -1558,13 +1561,13 @@ igmp_input(struct mbuf *m, int off)
m->m_len < igmpv3len) &&
(m = m_pullup(m, igmpv3len)) == NULL) {
IGMPSTAT_INC(igps_rcv_tooshort);
- return;
+ return (IPPROTO_DONE);
}
igmpv3 = (struct igmpv3 *)(mtod(m, uint8_t *)
+ iphlen);
if (igmp_input_v3_query(ifp, ip, igmpv3) != 0) {
m_freem(m);
- return;
+ return (IPPROTO_DONE);
}
}
break;
@@ -1576,7 +1579,7 @@ igmp_input(struct mbuf *m, int off)
break;
if (igmp_input_v1_report(ifp, ip, igmp) != 0) {
m_freem(m);
- return;
+ return (IPPROTO_DONE);
}
break;
@@ -1587,7 +1590,7 @@ igmp_input(struct mbuf *m, int off)
IGMPSTAT_INC(igps_rcv_nora);
if (igmp_input_v2_report(ifp, ip, igmp) != 0) {
m_freem(m);
- return;
+ return (IPPROTO_DONE);
}
break;
@@ -1608,7 +1611,8 @@ igmp_input(struct mbuf *m, int off)
* Pass all valid IGMP packets up to any process(es) listening on a
* raw IGMP socket.
*/
- rip_input(m, off);
+ *mp = m;
+ return (rip_input(mp, offp, proto));
}