From owner-svn-src-stable-12@freebsd.org Fri Jan 10 22:10:02 2020 Return-Path: Delivered-To: svn-src-stable-12@mailman.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mailman.nyi.freebsd.org (Postfix) with ESMTP id AA98C1F5204; Fri, 10 Jan 2020 22:10:02 +0000 (UTC) (envelope-from bz@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) server-signature RSA-PSS (4096 bits) client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "Let's Encrypt Authority X3" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 47vcbt4631z4CkK; Fri, 10 Jan 2020 22:10:02 +0000 (UTC) (envelope-from bz@FreeBSD.org) Received: from repo.freebsd.org (repo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id 880D520AF3; Fri, 10 Jan 2020 22:10:02 +0000 (UTC) (envelope-from bz@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.37]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id 00AMA2ZL088793; Fri, 10 Jan 2020 22:10:02 GMT (envelope-from bz@FreeBSD.org) Received: (from bz@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id 00AMA2GY088791; Fri, 10 Jan 2020 22:10:02 GMT (envelope-from bz@FreeBSD.org) Message-Id: <202001102210.00AMA2GY088791@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: bz set sender to bz@FreeBSD.org using -f From: "Bjoern A. Zeeb" Date: Fri, 10 Jan 2020 22:10:02 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-12@freebsd.org Subject: svn commit: r356616 - in stable/12: sys/netinet6 tests/sys/netinet6/frag6 X-SVN-Group: stable-12 X-SVN-Commit-Author: bz X-SVN-Commit-Paths: in stable/12: sys/netinet6 tests/sys/netinet6/frag6 X-SVN-Commit-Revision: 356616 X-SVN-Commit-Repository: base MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-stable-12@freebsd.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: SVN commit messages for only the 12-stable src tree List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 10 Jan 2020 22:10:02 -0000 Author: bz Date: Fri Jan 10 22:10:01 2020 New Revision: 356616 URL: https://svnweb.freebsd.org/changeset/base/356616 Log: MFC r354542: frag6: properly handle atomic fragments according to RFCs. RFC 8200 says: "If the fragment is a whole datagram (that is, both the Fragment Offset field and the M flag are zero), then it does not need any further reassembly and should be processed as a fully reassembled packet (i.e., updating Next Header, adjust Payload Length, removing the Fragment header, etc.). .." That means we should remove the fragment header and make all the adjustments rather than just skipping over the fragment header. The difference should be noticeable in that a properly handled atomic fragment triggering an ICMPv6 message at an upper layer (e.g. dest unreach, unreachable port) will not include the fragment header. Update the test cases to also test for an unfragmentable part. That is needed so that the next header is properly updated (not just lengths). Modified: stable/12/sys/netinet6/frag6.c stable/12/tests/sys/netinet6/frag6/frag6_03.py stable/12/tests/sys/netinet6/frag6/frag6_03.sh Directory Properties: stable/12/ (props changed) Modified: stable/12/sys/netinet6/frag6.c ============================================================================== --- stable/12/sys/netinet6/frag6.c Fri Jan 10 22:00:39 2020 (r356615) +++ stable/12/sys/netinet6/frag6.c Fri Jan 10 22:10:01 2020 (r356616) @@ -395,6 +395,8 @@ frag6_input(struct mbuf **mp, int *offp, int proto) m = *mp; offset = *offp; + M_ASSERTPKTHDR(m); + ip6 = mtod(m, struct ip6_hdr *); #ifndef PULLDOWN_TEST IP6_EXTHDR_CHECK(m, offset, sizeof(struct ip6_frag), IPPROTO_DONE); @@ -437,23 +439,36 @@ frag6_input(struct mbuf **mp, int *offp, int proto) IP6STAT_INC(ip6s_fragments); in6_ifstat_inc(dstifp, ifs6_reass_reqd); - /* Offset now points to data portion. */ - offset += sizeof(struct ip6_frag); - /* * Handle "atomic" fragments (offset and m bit set to 0) upfront, - * unrelated to any reassembly. Still need to remove the frag hdr. + * unrelated to any reassembly. We need to remove the frag hdr + * which is ugly. * See RFC 6946 and section 4.5 of RFC 8200. */ if ((ip6f->ip6f_offlg & ~IP6F_RESERVED_MASK) == 0) { /* XXX-BZ we want dedicated counters for this. */ IP6STAT_INC(ip6s_reassembled); - /* XXX-BZ handle correctly. */ + nxt = ip6f->ip6f_nxt; + /* + * Set nxt(-hdr field value) to the original value. + * We cannot just set ip6->ip6_nxt as there might be + * an unfragmentable part with extension headers and + * we must update the last one. + */ + m_copyback(m, ip6_get_prevhdr(m, offset), sizeof(uint8_t), + (caddr_t)&nxt); + ip6->ip6_plen = htons(ntohs(ip6->ip6_plen) - + sizeof(struct ip6_frag)); + if (ip6_deletefraghdr(m, offset, M_NOWAIT) != 0) + goto dropfrag2; + m->m_pkthdr.len -= sizeof(struct ip6_frag); in6_ifstat_inc(dstifp, ifs6_reass_ok); - *offp = offset; - m->m_flags |= M_FRAGMENTED; - return (ip6f->ip6f_nxt); + *mp = m; + return (nxt); } + + /* Offset now points to data portion. */ + offset += sizeof(struct ip6_frag); /* Get fragment length and discard 0-byte fragments. */ frgpartlen = sizeof(struct ip6_hdr) + ntohs(ip6->ip6_plen) - offset; Modified: stable/12/tests/sys/netinet6/frag6/frag6_03.py ============================================================================== --- stable/12/tests/sys/netinet6/frag6/frag6_03.py Fri Jan 10 22:00:39 2020 (r356615) +++ stable/12/tests/sys/netinet6/frag6/frag6_03.py Fri Jan 10 22:10:01 2020 (r356616) @@ -101,6 +101,33 @@ def main(): if not sniffer.foundCorrectPacket: sys.exit(1) + + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # ## + # + # Atomic fragment with extension header. + # + # A: Nothing listening on UDP port. + # R: ICMPv6 dst unreach, unreach port. + # + # Start sniffing on recvif + sniffer = Sniffer(args, check_icmp6_error) + + ip6f01 = sp.Ether() / \ + sp.IPv6(src=args.src[0], dst=args.to[0]) / \ + sp.IPv6ExtHdrDestOpt(options = \ + sp.PadN(optdata="\x00\x00\x00\x00\x00\x00")) / \ + sp.IPv6ExtHdrFragment(offset=0, m=0, id=0x3001) / \ + sp.UDP(dport=3456, sport=6543) + if args.debug : + ip6f01.display() + sp.sendp(ip6f01, iface=args.sendif[0], verbose=False) + + sleep(0.10) + sniffer.setEnd() + sniffer.join() + if not sniffer.foundCorrectPacket: + sys.exit(1) + sys.exit(0) if __name__ == '__main__': Modified: stable/12/tests/sys/netinet6/frag6/frag6_03.sh ============================================================================== --- stable/12/tests/sys/netinet6/frag6/frag6_03.sh Fri Jan 10 22:00:39 2020 (r356615) +++ stable/12/tests/sys/netinet6/frag6/frag6_03.sh Fri Jan 10 22:10:01 2020 (r356616) @@ -67,12 +67,12 @@ frag6_03_check_stats() { # Check selection of global UDP stats. # cat < ${HOME}/filter-${jname}.txt - 1 + 2 0 0 0 0 - 1 + 2 0 0 0 @@ -94,11 +94,11 @@ EOF 0 0 0 - 1 + 2 0 0 0 - 1 + 2 0 0 0 @@ -124,12 +124,12 @@ EOF # XXX-TODO check output histogram (just too hard to parse [no multi-line-grep]) # cat < ${HOME}/filter-${jname}.txt - 1 + 2 0 0 0 0 - 1 + 2 0 0 0 @@ -170,8 +170,8 @@ EOF 0 0 0 - 1 - 1 + 2 + 2 0 EOF count=`jexec ${jname} netstat -s -p ip6 -I ${ifname} --libxo xml,pretty | grep -E -x -c -f ${HOME}/filter-${jname}.txt` @@ -196,8 +196,8 @@ EOF 0 0 0 - 1 - 1 + 2 + 2 0 0 0