summaryrefslogtreecommitdiffstats
path: root/sys/netinet/igmp.c
diff options
context:
space:
mode:
authorbms <bms@FreeBSD.org>2009-04-29 10:12:01 +0000
committerbms <bms@FreeBSD.org>2009-04-29 10:12:01 +0000
commitba39c52304a276c54e90a7c3b3822e0a6b4de606 (patch)
tree66776f18e40ab0083d8a3b75c4931c4952ceb4c4 /sys/netinet/igmp.c
parent1fa36791b4c4434acd4227dd9a799efb7dc6e857 (diff)
downloadFreeBSD-src-ba39c52304a276c54e90a7c3b3822e0a6b4de606.zip
FreeBSD-src-ba39c52304a276c54e90a7c3b3822e0a6b4de606.tar.gz
Fix a problem whereby enqueued IGMPv3 filter list changes would be
incorrectly output, if the RB-tree enumeration happened to reuse the same chain for a mode switch: that is, both ALLOW and BLOCK records were appended for the same group, in the same mbuf packet chain. This was introduced during an mbuf chain layout bug fix involving m_getptr(), which obviously cannot count from offset 0 on the second pass through the RB-tree when serializing the IGMPv3 group records into the pending mbuf chain. Cut over to KTR_INET for IGMPv3 CTR usage.
Diffstat (limited to 'sys/netinet/igmp.c')
-rw-r--r--sys/netinet/igmp.c27
1 files changed, 17 insertions, 10 deletions
diff --git a/sys/netinet/igmp.c b/sys/netinet/igmp.c
index f206249..1c618a3 100644
--- a/sys/netinet/igmp.c
+++ b/sys/netinet/igmp.c
@@ -86,7 +86,7 @@ __FBSDID("$FreeBSD$");
#include <security/mac/mac_framework.h>
#ifndef KTR_IGMPV3
-#define KTR_IGMPV3 KTR_SUBSYS
+#define KTR_IGMPV3 KTR_INET
#endif
static struct igmp_ifinfo *
@@ -2983,7 +2983,7 @@ igmp_v3_enqueue_filter_change(struct ifqueue *ifq, struct in_multi *inm)
struct ip_msource *ims, *nims;
struct mbuf *m, *m0, *md;
in_addr_t naddr;
- int m0srcs, nbytes, off, rsrcs, schanged;
+ int m0srcs, nbytes, npbytes, off, rsrcs, schanged;
int nallow, nblock;
uint8_t mode, now, then;
rectype_t crt, drt, nrt;
@@ -3001,6 +3001,7 @@ igmp_v3_enqueue_filter_change(struct ifqueue *ifq, struct in_multi *inm)
nrt = REC_NONE; /* record type for current node */
m0srcs = 0; /* # source which will fit in current mbuf chain */
nbytes = 0; /* # of bytes appended to group's state-change queue */
+ npbytes = 0; /* # of bytes appended this packet */
rsrcs = 0; /* # sources encoded in current record */
schanged = 0; /* # nodes encoded in overall filter change */
nallow = 0; /* # of source entries in ALLOW_NEW */
@@ -3047,6 +3048,7 @@ igmp_v3_enqueue_filter_change(struct ifqueue *ifq, struct in_multi *inm)
m0srcs = (ifp->if_mtu - IGMP_LEADINGSPACE -
sizeof(struct igmp_grouprec)) /
sizeof(in_addr_t);
+ npbytes = 0;
CTR1(KTR_IGMPV3,
"%s: allocated new packet", __func__);
}
@@ -3066,15 +3068,19 @@ igmp_v3_enqueue_filter_change(struct ifqueue *ifq, struct in_multi *inm)
"%s: m_append() failed", __func__);
return (-ENOMEM);
}
- nbytes += sizeof(struct igmp_grouprec);
- if (m == m0) {
- md = m_last(m);
+ npbytes += sizeof(struct igmp_grouprec);
+ if (m != m0) {
+ /* new packet; offset in c hain */
+ md = m_getptr(m, npbytes -
+ sizeof(struct igmp_grouprec), &off);
pig = (struct igmp_grouprec *)(mtod(md,
- uint8_t *) + md->m_len - nbytes);
+ uint8_t *) + off);
} else {
- md = m_getptr(m, 0, &off);
+ /* current packet; offset from last append */
+ md = m_last(m);
pig = (struct igmp_grouprec *)(mtod(md,
- uint8_t *) + off);
+ uint8_t *) + md->m_len -
+ sizeof(struct igmp_grouprec));
}
/*
* Begin walking the tree for this record type
@@ -3133,7 +3139,7 @@ igmp_v3_enqueue_filter_change(struct ifqueue *ifq, struct in_multi *inm)
* pass, back out of allocations.
*/
if (rsrcs == 0) {
- nbytes -= sizeof(struct igmp_grouprec);
+ npbytes -= sizeof(struct igmp_grouprec);
if (m != m0) {
CTR1(KTR_IGMPV3,
"%s: m_free(m)", __func__);
@@ -3146,7 +3152,7 @@ igmp_v3_enqueue_filter_change(struct ifqueue *ifq, struct in_multi *inm)
}
continue;
}
- nbytes += (rsrcs * sizeof(in_addr_t));
+ npbytes += (rsrcs * sizeof(in_addr_t));
if (crt == REC_ALLOW)
pig->ig_type = IGMP_ALLOW_NEW_SOURCES;
else if (crt == REC_BLOCK)
@@ -3159,6 +3165,7 @@ igmp_v3_enqueue_filter_change(struct ifqueue *ifq, struct in_multi *inm)
m->m_pkthdr.PH_vt.vt_nrecs++;
if (m != m0)
_IF_ENQUEUE(ifq, m);
+ nbytes += npbytes;
} while (nims != NULL);
drt |= crt;
crt = (~crt & REC_FULL);
OpenPOWER on IntegriCloud