From nobody@FreeBSD.org  Wed Feb 15 22:28:31 2012
Return-Path: <public@macfreek.nl>
Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34])
	by hub.freebsd.org (Postfix) with ESMTP id 862CF1065670
	for <freebsd-gnats-submit@FreeBSD.org>; Wed, 15 Feb 2012 22:28:31 +0000 (UTC)
	(envelope-from nobody@FreeBSD.org)
Received: from red.freebsd.org (red.freebsd.org [IPv6:2001:4f8:fff6::22])
	by mx1.freebsd.org (Postfix) with ESMTP id 74B6D8FC1E
	for <freebsd-gnats-submit@FreeBSD.org>; Wed, 15 Feb 2012 22:28:31 +0000 (UTC)
Received: from red.freebsd.org (localhost [127.0.0.1])
	by red.freebsd.org (8.14.4/8.14.4) with ESMTP id q1FMSVDt075886
	for <freebsd-gnats-submit@FreeBSD.org>; Wed, 15 Feb 2012 22:28:31 GMT
	(envelope-from nobody@red.freebsd.org)
Received: (from nobody@localhost)
	by red.freebsd.org (8.14.4/8.14.4/Submit) id q1FMSVVO075885;
	Wed, 15 Feb 2012 22:28:31 GMT
	(envelope-from nobody)
Message-Id: <201202152228.q1FMSVVO075885@red.freebsd.org>
Date: Wed, 15 Feb 2012 22:28:31 GMT
From: Freek Dijkstra <public@macfreek.nl>
To: freebsd-gnats-submit@FreeBSD.org
Subject: [ipfw] loopback interface is not marking ipv6 packets
X-Send-Pr-Version: www-3.1
X-GNATS-Notify:

>Number:         165190
>Category:       kern
>Synopsis:       [ipfw] [lo] [patch] loopback interface is not marking ipv6 packets
>Confidential:   no
>Severity:       serious
>Priority:       medium
>Responsible:    freebsd-ipfw
>State:          open
>Quarter:        
>Keywords:       
>Date-Required:  
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Wed Feb 15 22:30:10 UTC 2012
>Closed-Date:    
>Last-Modified:  Mon Feb 20 00:07:36 UTC 2012
>Originator:     Freek Dijkstra
>Release:        9.0-RELEASE
>Organization:
>Environment:
FreeBSD 9.0-RELEASE FreeBSD 9.0-RELEASE #0: Tue Jan  3 07:15:25 UTC 2012     root@obrian.cse.buffalo.edu:/usr/obj/usr/src/sys/GENERIC  i386
>Description:
ipfw matches and reports the incorrect interface for IPv6 traffic via the loopback interface.

E.g.
> ipfw: 2 Count ICMPv6:128.0 [2001:610:767:4ec1::1] [2001:610:767:4ec1::1] out via lo0
> ipfw: 2 Count ICMPv6:128.0 [2001:610:767:4ec1::1] [2001:610:767:4ec1::1] in via em0
(the in via em0 should be in via lo0).
>How-To-Repeat:
Steps to reproduce:
1. Determine a global IPv6 address of your host. In this report, 2001:610:767:4ec1::1 is used.
2. Verify that the routing table has an entry associating this IP address with the loopback interface. E.g.:
% route get -inet6 2001:610:767:4ec1::1
   route to: 2001:610:767:4ec1::1
destination: 2001:610:767:4ec1::1
  interface: lo0
3. Add the following rules to ipfw:
# ipfw add 1 count log ipv6 from me6 to me6 recv lo0
# ipfw add 2 count log ipv6 from me6 to me6 not recv lo0
4. Run sudo sysctl net.inet.ip.fw.one_pass=0
5. Ping the local IP:
% ping6 -c 1 2001:610:767:4ec1::1
6. examine the IPFW log file.

Expected result:
I expected rule 1 to match:
> ipfw: 1 Count ICMPv6:128.0 [2001:610:767:4ec1::1] [2001:610:767:4ec1::1] out via lo0
> ipfw: 1 Count ICMPv6:128.0 [2001:610:767:4ec1::1] [2001:610:767:4ec1::1] in via lo0
> ipfw: 1 Count ICMPv6:129.0 [2001:610:767:4ec1::1] [2001:610:767:4ec1::1] out via lo0
> ipfw: 1 Count ICMPv6:129.0 [2001:610:767:4ec1::1] [2001:610:767:4ec1::1] in via lo0

Actual result:
Rule 2 matched:
> ipfw: 2 Count ICMPv6:128.0 [2001:610:767:4ec1::1] [2001:610:767:4ec1::1] out via lo0
> ipfw: 2 Count ICMPv6:128.0 [2001:610:767:4ec1::1] [2001:610:767:4ec1::1] in via em0
> ipfw: 2 Count ICMPv6:129.0 [2001:610:767:4ec1::1] [2001:610:767:4ec1::1] out via lo0
> ipfw: 2 Count ICMPv6:129.0 [2001:610:767:4ec1::1] [2001:610:767:4ec1::1] in via em0

Further analysis:
Adding rules for "xmit lo0" and "not xmit lo0" clearly show that according to ipfw, the packet is "xmit lo0 recv em0".

Beside using "route get" in step 2 above, there is another method to determine the interface that is used by the packet, the MTU size.
By default, the MTU of lo0 is 16384 bytes, and other interface have a MTU of 1500 bytes:
% ifconfig:
lo0: flags=8049<UP,LOOPBACK,RUNNING,MULTICAST> metric 0 mtu 16384
em0: flags=8843<UP,BROADCAST,RUNNING,SIMPLEX,MULTICAST> metric 0 mtu 1500

% ping6 -c 1 -D -s 16336 -b 32000 "2001:610:767:4ec1::1"
works fine
% ping6 -c 1 -D -s 16337 -b 32000 "2001:610:767:4ec1::1"
fails

Hence, the MTU is 16336 bytes payload + 48 byte overhead = 16384 bytes, so that indicates the actual interface used is lo0. It also indicates that em0 is not used: if both lo0 and em0 would be used, the smaller MTU of em0 would block larger packets, and this is not the case. Hence, em0 seems not used all, despite the reporting of ipfw.

>Fix:
Suggested by Julian Elischer: lo0 is not marking ipv6 packets.

>Release-Note:
>Audit-Trail:
Responsible-Changed-From-To: freebsd-i386->freebsd-net 
Responsible-Changed-By: julian 
Responsible-Changed-When: Wed Feb 15 15:46:19 PST 2012 
Responsible-Changed-Why:  
is a network problem not a 386 problem 

http://www.freebsd.org/cgi/query-pr.cgi?pr=165190 
Responsible-Changed-From-To: freebsd-net->freebsd-ipfw 
Responsible-Changed-By: linimon 
Responsible-Changed-When: Sun Feb 19 19:40:00 UTC 2012 
Responsible-Changed-Why:  
fix assignment. 

http://www.freebsd.org/cgi/query-pr.cgi?pr=165190 

From: Sergey Matveychuk <sem@FreeBSD.org>
To: bug-followup@FreeBSD.org, public@macfreek.nl
Cc:  
Subject: Re: kern/165190: [ipfw] [lo] loopback interface is not marking ipv6
 packets
Date: Mon, 20 Feb 2012 03:18:13 +0400

 This is a multi-part message in MIME format.
 --------------080202040908010900010503
 Content-Type: text/plain; charset=UTF-8; format=flowed
 Content-Transfer-Encoding: 7bit
 
 Julian wrongs here.
 
 Try the patch please.
 I've found the superfluous code in nd6.c when wrote a patch for 
 divert(4) and was very annoyed this loopback behaviour.
 For unknown reasons KAME authors decided to fake interface for loopback. 
 It differs from IPv4 code, so, I guess, it should be fixed. But I could 
 not proof it. Your example is better for this.
 
 --------------080202040908010900010503
 Content-Type: text/x-patch;
  name="nd6.c.diff"
 Content-Transfer-Encoding: 7bit
 Content-Disposition: attachment;
  filename="nd6.c.diff"
 
 --- sys/netinet6/nd6.c.orig	2011-02-25 17:48:54.000000000 +0300
 +++ sys/netinet6/nd6.c	2011-02-25 17:49:51.000000000 +0300
 @@ -1928,10 +1928,6 @@
  		}
  		return (error);
  	}
 -	if ((ifp->if_flags & IFF_LOOPBACK) != 0) {
 -		return ((*ifp->if_output)(origifp, m, (struct sockaddr *)dst,
 -		    NULL));
 -	}
  	error = (*ifp->if_output)(ifp, m, (struct sockaddr *)dst, NULL);
  	return (error);
  
 
 --------------080202040908010900010503--
>Unformatted:
