From owner-svn-src-all@FreeBSD.ORG Wed Apr 29 10:12:01 2009 Return-Path: Delivered-To: svn-src-all@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id DF3E2106564A; Wed, 29 Apr 2009 10:12:01 +0000 (UTC) (envelope-from bms@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id CDA0C8FC20; Wed, 29 Apr 2009 10:12:01 +0000 (UTC) (envelope-from bms@FreeBSD.org) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.3/8.14.3) with ESMTP id n3TAC1B2076042; Wed, 29 Apr 2009 10:12:01 GMT (envelope-from bms@svn.freebsd.org) Received: (from bms@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id n3TAC1rd076041; Wed, 29 Apr 2009 10:12:01 GMT (envelope-from bms@svn.freebsd.org) Message-Id: <200904291012.n3TAC1rd076041@svn.freebsd.org> From: Bruce M Simpson Date: Wed, 29 Apr 2009 10:12:01 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r191657 - head/sys/netinet X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: "SVN commit messages for the entire src tree \(except for " user" and " projects" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 29 Apr 2009 10:12:02 -0000 Author: bms Date: Wed Apr 29 10:12:01 2009 New Revision: 191657 URL: http://svn.freebsd.org/changeset/base/191657 Log: 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. Modified: head/sys/netinet/igmp.c Modified: head/sys/netinet/igmp.c ============================================================================== --- head/sys/netinet/igmp.c Wed Apr 29 10:02:50 2009 (r191656) +++ head/sys/netinet/igmp.c Wed Apr 29 10:12:01 2009 (r191657) @@ -86,7 +86,7 @@ __FBSDID("$FreeBSD$"); #include #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 ifq 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 ifq 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 ifq 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 ifq "%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 ifq * 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 ifq } 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 ifq 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);