From nobody@FreeBSD.org  Mon Oct 15 16:34:57 2007
Return-Path: <nobody@FreeBSD.org>
Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34])
	by hub.freebsd.org (Postfix) with ESMTP id 4254116A419
	for <freebsd-gnats-submit@FreeBSD.org>; Mon, 15 Oct 2007 16:34:57 +0000 (UTC)
	(envelope-from nobody@FreeBSD.org)
Received: from www.freebsd.org (www.freebsd.org [IPv6:2001:4f8:fff6::21])
	by mx1.freebsd.org (Postfix) with ESMTP id 3445713C44B
	for <freebsd-gnats-submit@FreeBSD.org>; Mon, 15 Oct 2007 16:34:57 +0000 (UTC)
	(envelope-from nobody@FreeBSD.org)
Received: from www.freebsd.org (localhost [127.0.0.1])
	by www.freebsd.org (8.14.1/8.14.1) with ESMTP id l9FGYmRe072701
	for <freebsd-gnats-submit@FreeBSD.org>; Mon, 15 Oct 2007 16:34:48 GMT
	(envelope-from nobody@www.freebsd.org)
Received: (from nobody@localhost)
	by www.freebsd.org (8.14.1/8.14.1/Submit) id l9FGYmvn072700;
	Mon, 15 Oct 2007 16:34:48 GMT
	(envelope-from nobody)
Message-Id: <200710151634.l9FGYmvn072700@www.freebsd.org>
Date: Mon, 15 Oct 2007 16:34:48 GMT
From: Fabian Wenk <fabian@wenks.ch>
To: freebsd-gnats-submit@FreeBSD.org
Subject: ipfw(8) fwd with IPv6 treats input as IPv4
X-Send-Pr-Version: www-3.1
X-GNATS-Notify:

>Number:         117214
>Category:       bin
>Synopsis:       ipfw(8) fwd with IPv6 treats input as IPv4
>Confidential:   no
>Severity:       serious
>Priority:       high
>Responsible:    bz
>State:          closed
>Quarter:        
>Keywords:       
>Date-Required:  
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Mon Oct 15 16:40:00 UTC 2007
>Closed-Date:    Fri Mar 15 23:34:32 UTC 2013
>Last-Modified:  Fri Mar 15 23:34:32 UTC 2013
>Originator:     Fabian Wenk
>Release:        FreeBSD 6.2-RELEASE-p7
>Organization:
>Environment:
FreeBSD new-batman.home4u.ch 6.2-RELEASE-p7 FreeBSD 6.2-RELEASE-p7 #3: Tue Aug 21 16:11:16 CEST 2007     root@new-batman.home4u.ch:/usr/obj/usr/src/sys/BATMAN  amd64
>Description:
I have a setup with two Internet connections and doing source based routing
through ipfw fwd. This works perfectly for IPv4. The similar command lines
for IPv6 gives the following 2 variants of errors:

root@new-batman:~# ipfw add 25050 fwd 2002:d908:d3e3::1 ip6 from 2002:d908:d3e3:1:2e0:81ff:fe47:bb8c to not 2002:d908:d3e3:1::/64,2002:3e02:55b4:2::/64,::1/128
ipfw: illegal forwarding port ``d908:d3e3::1''
root@new-batman:~#

The error "illegal forwarding port" depends on the first parts of the used
IPv6 address, with the other IPv6 address the error is different (treats
and uses it as IPv4 address):

root@new-batman:~# ipfw add 25051 fwd 2002:3e02:55b4:2:2e0:81ff:fe47:bb87 ip6 from 2002:3e02:55b4:2:2e0:81ff:fe47:bb8d to not 2002:d908:d3e3:1::/64,2002:3e02:55b4:2::/64,::1/128
25051 fwd 0.0.7.210,3 ip6 from 2002:3e02:55b4:2:2e0:81ff:fe47:bb8d to not 2002:3e02:55b4:2::/64,2002:d908:d3e3:1::/64,::1
root@new-batman:~#

ipfw show presents the second error (source is something like a broken IPv4
address):

root@new-batman:~# ipfw show | grep 25051
25051  0    0 fwd 0.0.7.210,3 ip6 from 2002:3e02:55b4:2:2e0:81ff:fe47:bb8d to not 2002:3e02:55b4:2::/64,2002:d908:d3e3:1::/64,::1
root@new-batman:~#


This could be something similar like in PR bin/104921, but this does not fix
the fwd problem.
>How-To-Repeat:
ipfw add fwd <IPv6-address> ...
>Fix:


>Release-Note:
>Audit-Trail:
Responsible-Changed-From-To: freebsd-bugs->freebsd-ipfw 
Responsible-Changed-By: brucec 
Responsible-Changed-When: Wed Mar 25 17:18:47 UTC 2009 
Responsible-Changed-Why:  
Over to maintainer(s). 

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

From: Lars Eggert <lars.eggert@nokia.com>
To: bug-followup@FreeBSD.org, fabian@wenks.ch
Cc:  
Subject: Re: bin/117214: ipfw(8) fwd with IPv6 treats input as IPv4
Date: Sat, 22 Aug 2009 02:27:44 +0300

 I still see this on 7.2-STABLE:
 
 [root@fit: ~] uname -a
 FreeBSD fit.nokia.com 7.2-STABLE FreeBSD 7.2-STABLE #18: Fri Jun 26  
 15:43:17 EEST 2009     root@fit.nokia.com:/usr/obj/usr/src/sys/FIT  i386
 
 [root@fit: ~] ipfw add 64010 fwd 2001:2060:40:1::1 ip6 from  
 2001:2060:40:1::123,2001:2060:40:1::124 to not  
 2001:0708:0040:fff2::1/64 out
 64010 fwd 0.0.7.209,2060 ip6 from  
 2001:2060:40:1::123,2001:2060:40:1::124 to not 2001:708:40:fff2::/64 out
 
 [root@fit: ~] ipfw show 64010
 64010         0           0 fwd 0.0.7.209,2060 ip6 from  
 2001:2060:40:1::123,2001:2060:40:1::124 to not 2001:708:40:fff2::/64 out
 
Responsible-Changed-From-To: freebsd-ipfw->bz 
Responsible-Changed-By: emaste 
Responsible-Changed-When: Tue Jul 5 13:57:09 UTC 2011 
Responsible-Changed-Why:  
Sandvine has a patch to implement ipv6 fwd that bz@'s going to clean 
up and get into the tree. 

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

From: "Bjoern A. Zeeb" <bz@FreeBSD.org>
To: bug-followup@FreeBSD.org, fabian@wenks.ch, 
    Lars Eggert <lars.eggert@nokia.com>
Cc:  
Subject: Re: bin/117214: ipfw(8) fwd with IPv6 treats input as IPv4
Date: Tue, 19 Jul 2011 19:37:48 +0000 (UTC)

 Hi,
 
 could you give this patch a try.  A version for HEAD can be found
 here:
 
  	http://people.freebsd.org/~bz/20110718-01-ipfw-fwd-ipv6-pr117214.diff
 
 and a version for stable/8 here:
 
  	http://people.freebsd.org/~bz/20110719-01-ipfw-fwd-ipv6-pr117214.diff
 
 
 You will need to rebuild world and your kernel with the appropriate options.
 
 Thanks,
 Bjoern
 
 -- 
 Bjoern A. Zeeb                                 You have to have visions!
           Stop bit received. Insert coin for new address family.

From: Fabian Wenk <fabian@wenks.ch>
To: "Bjoern A. Zeeb" <bz@FreeBSD.org>
Cc: bug-followup@FreeBSD.org, Lars Eggert <lars.eggert@nokia.com>
Subject: Re: bin/117214: ipfw(8) fwd with IPv6 treats input as IPv4
Date: Wed, 20 Jul 2011 16:50:16 +0200

 Hello Bjoern
 
 On 19.07.2011 21:37, Bjoern A. Zeeb wrote:
 > could you give this patch a try.  A version for HEAD can be found
 > here:
 >
 >   	http://people.freebsd.org/~bz/20110718-01-ipfw-fwd-ipv6-pr117214.diff
 >
 > and a version for stable/8 here:
 >
 >   	http://people.freebsd.org/~bz/20110719-01-ipfw-fwd-ipv6-pr117214.diff
 
 My systems are currently running with 7.3-RELEASE, so I tried this 
 one, but it gave to many rejects. I do not know if it would be 
 possible (and even make sense) to create this patch for 7.3 or 7.4 
 (as I will do this upgrade anyway). Should I send you the output 
 and .rej files?
 
 Else I would install a test system with 8-STABLE and create the 
 same network setup.
 
 
 bye
 Fabian

From: lars.eggert@nokia.com
To: fabian@wenks.ch
Cc: bz@FreeBSD.org, bug-followup@FreeBSD.org
Subject: Re: bin/117214: ipfw(8) fwd with IPv6 treats input as IPv4
Date: Wed, 20 Jul 2011 11:15:55 -0400

 I'm running stable, but I won't be physically near the box for a few weeks and am hesitant to patch it from remote.
 
 On Jul 20, 2011, at 10:50, Fabian Wenk <fabian@wenks.ch> wrote:
 
 > Hello Bjoern
 > 
 > On 19.07.2011 21:37, Bjoern A. Zeeb wrote:
 >> could you give this patch a try.  A version for HEAD can be found
 >> here:
 >> 
 >>      http://people.freebsd.org/~bz/20110718-01-ipfw-fwd-ipv6-pr117214.diff
 >> 
 >> and a version for stable/8 here:
 >> 
 >>      http://people.freebsd.org/~bz/20110719-01-ipfw-fwd-ipv6-pr117214.diff
 > 
 > My systems are currently running with 7.3-RELEASE, so I tried this 
 > one, but it gave to many rejects. I do not know if it would be 
 > possible (and even make sense) to create this patch for 7.3 or 7.4 
 > (as I will do this upgrade anyway). Should I send you the output 
 > and .rej files?
 > 
 > Else I would install a test system with 8-STABLE and create the 
 > same network setup.
 > 
 > 
 > bye
 > Fabian
 
State-Changed-From-To: open->patched 
State-Changed-By: bz 
State-Changed-When: Sat Aug 20 17:05:12 UTC 2011 
State-Changed-Why:  
Committed to HEAD, will be part of upcoming FreeBSD 9. 
Will merge to 8 in a while and consider 7. 

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

From: dfilter@FreeBSD.ORG (dfilter service)
To: bug-followup@FreeBSD.org
Cc:  
Subject: Re: bin/117214: commit references a PR
Date: Sat, 20 Aug 2011 17:05:25 +0000 (UTC)

 Author: bz
 Date: Sat Aug 20 17:05:11 2011
 New Revision: 225044
 URL: http://svn.freebsd.org/changeset/base/225044
 
 Log:
   Add support for IPv6 to ipfw fwd:
   Distinguish IPv4 and IPv6 addresses and optional port numbers in
   user space to set the option for the correct protocol family.
   Add support in the kernel for carrying the new IPv6 destination
   address and port.
   Add support to TCP and UDP for IPv6 and fix UDP IPv4 to not change
   the address in the IP header.
   Add support for IPv6 forwarding to a non-local destination.
   Add a regession test uitilizing VIMAGE to check all 20 possible
   combinations I could think of.
   
   Obtained from:	David Dolson at Sandvine Incorporated
   		(original version for ipfw fwd IPv6 support)
   Sponsored by:	Sandvine Incorporated
   PR:		bin/117214
   MFC after:	4 weeks
   Approved by:	re (kib)
 
 Added:
   head/tools/regression/ipfw/
   head/tools/regression/ipfw/fwd/
   head/tools/regression/ipfw/fwd/vimage-fwd.sh   (contents, props changed)
 Modified:
   head/sbin/ipfw/ipfw.8
   head/sbin/ipfw/ipfw2.c
   head/sys/netinet/ip_fw.h
   head/sys/netinet/ipfw/ip_fw2.c
   head/sys/netinet/ipfw/ip_fw_log.c
   head/sys/netinet/ipfw/ip_fw_pfil.c
   head/sys/netinet/ipfw/ip_fw_private.h
   head/sys/netinet/ipfw/ip_fw_sockopt.c
   head/sys/netinet/tcp_input.c
   head/sys/netinet/udp_usrreq.c
   head/sys/netinet6/ip6_forward.c
   head/sys/netinet6/ip6_input.c
   head/sys/netinet6/ip6_output.c
   head/sys/netinet6/udp6_usrreq.c
 
 Modified: head/sbin/ipfw/ipfw.8
 ==============================================================================
 --- head/sbin/ipfw/ipfw.8	Sat Aug 20 16:43:47 2011	(r225043)
 +++ head/sbin/ipfw/ipfw.8	Sat Aug 20 17:05:11 2011	(r225044)
 @@ -1,7 +1,7 @@
  .\"
  .\" $FreeBSD$
  .\"
 -.Dd June 29, 2011
 +.Dd August 20, 2011
  .Dt IPFW 8
  .Os
  .Sh NAME
 @@ -726,7 +726,7 @@ The search terminates.
  Change the next-hop on matching packets to
  .Ar ipaddr ,
  which can be an IP address or a host name.
 -The next hop can also be supplied by the last table
 +For IPv4, the next hop can also be supplied by the last table
  looked up for the packet by using the
  .Cm tablearg
  keyword instead of an explicit address.
 
 Modified: head/sbin/ipfw/ipfw2.c
 ==============================================================================
 --- head/sbin/ipfw/ipfw2.c	Sat Aug 20 16:43:47 2011	(r225043)
 +++ head/sbin/ipfw/ipfw2.c	Sat Aug 20 17:05:11 2011	(r225044)
 @@ -1111,6 +1111,18 @@ show_ipfw(struct ip_fw *rule, int pcwidt
  		    }
  			break;
  
 +		case O_FORWARD_IP6:
 +		    {
 +			char buf[4 + INET6_ADDRSTRLEN + 1];
 +			ipfw_insn_sa6 *s = (ipfw_insn_sa6 *)cmd;
 +
 +			printf("fwd %s", inet_ntop(AF_INET6, &s->sa.sin6_addr,
 +			    buf, sizeof(buf)));
 +			if (s->sa.sin6_port)
 +				printf(",%d", s->sa.sin6_port);
 +		    }
 +			break;
 +
  		case O_LOG: /* O_LOG is printed last */
  			logptr = (ipfw_insn_log *)cmd;
  			break;
 @@ -2809,40 +2821,96 @@ chkarg:
  		break;
  
  	case TOK_FORWARD: {
 -		ipfw_insn_sa *p = (ipfw_insn_sa *)action;
 +		/*
 +		 * Locate the address-port separator (':' or ',').
 +		 * Could be one of the following:
 +		 *	hostname:port
 +		 *	IPv4 a.b.c.d,port
 +		 *	IPv4 a.b.c.d:port
 +		 *	IPv6 w:x:y::z,port
 +		 * The ':' can only be used with hostname and IPv4 address.
 +		 * XXX-BZ Should we also support [w:x:y::z]:port?
 +		 */
 +		struct sockaddr_storage result;
 +		struct addrinfo *res;
  		char *s, *end;
 +		int family;
 +		u_short port_number;
  
  		NEED1("missing forward address[:port]");
  
 -		action->opcode = O_FORWARD_IP;
 -		action->len = F_INSN_SIZE(ipfw_insn_sa);
 -
 -		/*
 -		 * In the kernel we assume AF_INET and use only
 -		 * sin_port and sin_addr. Remember to set sin_len as
 -		 * the routing code seems to use it too.
 -		 */
 -		p->sa.sin_family = AF_INET;
 -		p->sa.sin_len = sizeof(struct sockaddr_in);
 -		p->sa.sin_port = 0;
  		/*
  		 * locate the address-port separator (':' or ',')
  		 */
 -		s = strchr(*av, ':');
 -		if (s == NULL)
 -			s = strchr(*av, ',');
 +		s = strchr(*av, ',');
 +		if (s == NULL) {
 +			/* Distinguish between IPv4:port and IPv6 cases. */
 +			s = strchr(*av, ':');
 +			if (s && strchr(s+1, ':'))
 +				s = NULL; /* no port */
 +		}
 +
 +		port_number = 0;
  		if (s != NULL) {
 +			/* Terminate host portion and set s to start of port. */
  			*(s++) = '\0';
  			i = strtoport(s, &end, 0 /* base */, 0 /* proto */);
  			if (s == end)
  				errx(EX_DATAERR,
  				    "illegal forwarding port ``%s''", s);
 -			p->sa.sin_port = (u_short)i;
 +			port_number = (u_short)i;
 +		}
 +
 +		if (_substrcmp(*av, "tablearg") == 0) {
 +			family = PF_INET;
 +			((struct sockaddr_in*)&result)->sin_addr.s_addr =
 +			    INADDR_ANY;
 +		} else {
 +			/* 
 +			 * Resolve the host name or address to a family and a
 +			 * network representation of the addres.
 +			 */
 +			if (getaddrinfo(*av, NULL, NULL, &res))
 +				errx(EX_DATAERR, NULL);
 +			/* Just use the first host in the answer. */
 +			family = res->ai_family;
 +			memcpy(&result, res->ai_addr, res->ai_addrlen);
 +			freeaddrinfo(res);
 +		}
 +
 + 		if (family == PF_INET) {
 +			ipfw_insn_sa *p = (ipfw_insn_sa *)action;
 +
 +			action->opcode = O_FORWARD_IP;
 +			action->len = F_INSN_SIZE(ipfw_insn_sa);
 +
 +			/*
 +			 * In the kernel we assume AF_INET and use only
 +			 * sin_port and sin_addr. Remember to set sin_len as
 +			 * the routing code seems to use it too.
 +			 */
 +			p->sa.sin_len = sizeof(struct sockaddr_in);
 +			p->sa.sin_family = AF_INET;
 +			p->sa.sin_port = port_number;
 +			p->sa.sin_addr.s_addr =
 +			     ((struct sockaddr_in *)&result)->sin_addr.s_addr;
 +		} else if (family == PF_INET6) {
 +			ipfw_insn_sa6 *p = (ipfw_insn_sa6 *)action;
 +
 +			action->opcode = O_FORWARD_IP6;
 +			action->len = F_INSN_SIZE(ipfw_insn_sa6);
 +
 +			p->sa.sin6_len = sizeof(struct sockaddr_in6);
 +			p->sa.sin6_family = AF_INET6;
 +			p->sa.sin6_port = port_number;
 +			p->sa.sin6_flowinfo = 0;
 +			p->sa.sin6_scope_id = 0;
 +			/* No table support for v6 yet. */
 +			bcopy(&((struct sockaddr_in6*)&result)->sin6_addr,
 +			    &p->sa.sin6_addr, sizeof(p->sa.sin6_addr));
 +		} else {
 +			errx(EX_DATAERR, "Invalid address family in forward action");
  		}
 -		if (_substrcmp(*av, "tablearg") == 0)
 -			p->sa.sin_addr.s_addr = INADDR_ANY;
 -		else
 -			lookup_host(*av, &(p->sa.sin_addr));
  		av++;
  		break;
  	    }
 
 Modified: head/sys/netinet/ip_fw.h
 ==============================================================================
 --- head/sys/netinet/ip_fw.h	Sat Aug 20 16:43:47 2011	(r225043)
 +++ head/sys/netinet/ip_fw.h	Sat Aug 20 17:05:11 2011	(r225044)
 @@ -203,6 +203,8 @@ enum ipfw_opcodes {		/* arguments (4 byt
  
  	O_CALLRETURN,		/* arg1=called rule number */
  
 +	O_FORWARD_IP6,		/* fwd sockaddr_in6             */
 +
  	O_LAST_OPCODE		/* not an opcode!		*/
  };
  
 @@ -299,6 +301,14 @@ typedef struct  _ipfw_insn_sa {
  } ipfw_insn_sa;
  
  /*
 + * This is used to forward to a given address (ipv6).
 + */
 +typedef struct _ipfw_insn_sa6 {
 +	ipfw_insn o;
 +	struct sockaddr_in6 sa;
 +} ipfw_insn_sa6;
 +
 +/*
   * This is used for MAC addr-mask pairs.
   */
  typedef struct	_ipfw_insn_mac {
 
 Modified: head/sys/netinet/ipfw/ip_fw2.c
 ==============================================================================
 --- head/sys/netinet/ipfw/ip_fw2.c	Sat Aug 20 16:43:47 2011	(r225043)
 +++ head/sys/netinet/ipfw/ip_fw2.c	Sat Aug 20 17:05:11 2011	(r225044)
 @@ -796,6 +796,7 @@ set_match(struct ip_fw_args *args, int s
   *
   *	args->rule	Pointer to the last matching rule (in/out)
   *	args->next_hop	Socket we are forwarding to (out).
 + *	args->next_hop6	IPv6 next hop we are forwarding to (out).
   *	args->f_id	Addresses grabbed from the packet (out)
   * 	args->rule.info	a cookie depending on rule action
   *
 @@ -2281,6 +2282,23 @@ do {								\
  				done = 1;       /* exit outer loop */
  				break;
  
 +#ifdef INET6
 +			case O_FORWARD_IP6:
 +				if (args->eh)	/* not valid on layer2 pkts */
 +					break;
 +				if (q == NULL || q->rule != f ||
 +				    dyn_dir == MATCH_FORWARD) {
 +					struct sockaddr_in6 *sin6;
 +
 +					sin6 = &(((ipfw_insn_sa6 *)cmd)->sa);
 +					args->next_hop6 = sin6;
 +				}
 +				retval = IP_FW_PASS;
 +				l = 0;		/* exit inner loop */
 +				done = 1;	/* exit outer loop */
 +				break;
 +#endif
 +
  			case O_NETGRAPH:
  			case O_NGTEE:
  				set_match(args, f_pos, chain);
 
 Modified: head/sys/netinet/ipfw/ip_fw_log.c
 ==============================================================================
 --- head/sys/netinet/ipfw/ip_fw_log.c	Sat Aug 20 16:43:47 2011	(r225043)
 +++ head/sys/netinet/ipfw/ip_fw_log.c	Sat Aug 20 17:05:11 2011	(r225044)
 @@ -167,7 +167,7 @@ ipfw_log(struct ip_fw *f, u_int hlen, st
  {
  	char *action;
  	int limit_reached = 0;
 -	char action2[40], proto[128], fragment[32];
 +	char action2[92], proto[128], fragment[32];
  
  	if (V_fw_verbose == 0) {
  #ifndef WITHOUT_BPF
 @@ -290,6 +290,21 @@ ipfw_log(struct ip_fw *f, u_int hlen, st
  				    sa->sa.sin_port);
  			}
  			break;
 +#ifdef INET6
 +		case O_FORWARD_IP6: {
 +			char buf[INET6_ADDRSTRLEN];
 +			ipfw_insn_sa6 *sa = (ipfw_insn_sa6 *)cmd;
 +			int len;
 +
 +			len = snprintf(SNPARGS(action2, 0), "Forward to [%s]",
 +			    ip6_sprintf(buf, &sa->sa.sin6_addr));
 +
 +			if (sa->sa.sin6_port)
 +				snprintf(SNPARGS(action2, len), ":%u",
 +				    sa->sa.sin6_port);
 +			}
 +			break;
 +#endif
  		case O_NETGRAPH:
  			snprintf(SNPARGS(action2, 0), "Netgraph %d",
  				cmd->arg1);
 
 Modified: head/sys/netinet/ipfw/ip_fw_pfil.c
 ==============================================================================
 --- head/sys/netinet/ipfw/ip_fw_pfil.c	Sat Aug 20 16:43:47 2011	(r225043)
 +++ head/sys/netinet/ipfw/ip_fw_pfil.c	Sat Aug 20 17:05:11 2011	(r225044)
 @@ -152,13 +152,26 @@ again:
  	switch (ipfw) {
  	case IP_FW_PASS:
  		/* next_hop may be set by ipfw_chk */
 -		if (args.next_hop == NULL)
 +		if (args.next_hop == NULL && args.next_hop6 == NULL)
  			break; /* pass */
  #ifndef IPFIREWALL_FORWARD
  		ret = EACCES;
  #else
  	    {
  		struct m_tag *fwd_tag;
 +		size_t len;
 +
 +		KASSERT(args.next_hop == NULL || args.next_hop6 == NULL,
 +		    ("%s: both next_hop=%p and next_hop6=%p not NULL", __func__,
 +		     args.next_hop, args.next_hop6));
 +#ifdef INET6
 +		if (args.next_hop6 != NULL)
 +			len = sizeof(struct sockaddr_in6);
 +#endif
 +#ifdef INET
 +		if (args.next_hop != NULL)
 +			len = sizeof(struct sockaddr_in);
 +#endif
  
  		/* Incoming packets should not be tagged so we do not
  		 * m_tag_find. Outgoing packets may be tagged, so we
 @@ -169,18 +182,28 @@ again:
  		if (fwd_tag != NULL) {
  			m_tag_unlink(*m0, fwd_tag);
  		} else {
 -			fwd_tag = m_tag_get(PACKET_TAG_IPFORWARD,
 -				sizeof(struct sockaddr_in), M_NOWAIT);
 +			fwd_tag = m_tag_get(PACKET_TAG_IPFORWARD, len,
 +			    M_NOWAIT);
  			if (fwd_tag == NULL) {
  				ret = EACCES;
  				break; /* i.e. drop */
  			}
  		}
 -		bcopy(args.next_hop, (fwd_tag+1), sizeof(struct sockaddr_in));
 +#ifdef INET6
 +		if (args.next_hop6 != NULL) {
 +			bcopy(args.next_hop6, (fwd_tag+1), len);
 +			if (in6_localip(&args.next_hop6->sin6_addr))
 +				(*m0)->m_flags |= M_FASTFWD_OURS;
 +		}
 +#endif
 +#ifdef INET
 +		if (args.next_hop != NULL) {
 +			bcopy(args.next_hop, (fwd_tag+1), len);
 +			if (in_localip(args.next_hop->sin_addr))
 +				(*m0)->m_flags |= M_FASTFWD_OURS;
 +		}
 +#endif
  		m_tag_prepend(*m0, fwd_tag);
 -
 -		if (in_localip(args.next_hop->sin_addr))
 -			(*m0)->m_flags |= M_FASTFWD_OURS;
  	    }
  #endif
  		break;
 
 Modified: head/sys/netinet/ipfw/ip_fw_private.h
 ==============================================================================
 --- head/sys/netinet/ipfw/ip_fw_private.h	Sat Aug 20 16:43:47 2011	(r225043)
 +++ head/sys/netinet/ipfw/ip_fw_private.h	Sat Aug 20 17:05:11 2011	(r225044)
 @@ -86,6 +86,7 @@ struct ip_fw_args {
  	struct mbuf	*m;		/* the mbuf chain		*/
  	struct ifnet	*oif;		/* output interface		*/
  	struct sockaddr_in *next_hop;	/* forward address		*/
 +	struct sockaddr_in6 *next_hop6; /* ipv6 forward address		*/
  
  	/*
  	 * On return, it points to the matching rule.
 
 Modified: head/sys/netinet/ipfw/ip_fw_sockopt.c
 ==============================================================================
 --- head/sys/netinet/ipfw/ip_fw_sockopt.c	Sat Aug 20 16:43:47 2011	(r225043)
 +++ head/sys/netinet/ipfw/ip_fw_sockopt.c	Sat Aug 20 17:05:11 2011	(r225044)
 @@ -723,6 +723,17 @@ check_ipfw_struct(struct ip_fw *rule, in
  			return EINVAL;
  #endif
  
 +#ifdef INET6
 +		case O_FORWARD_IP6:
 +#ifdef IPFIREWALL_FORWARD
 +			if (cmdlen != F_INSN_SIZE(ipfw_insn_sa6))
 +				goto bad_size;
 +			goto check_action;
 +#else
 +			return (EINVAL);
 +#endif
 +#endif /* INET6 */
 +
  		case O_DIVERT:
  		case O_TEE:
  			if (ip_divert_ptr == NULL)
 
 Modified: head/sys/netinet/tcp_input.c
 ==============================================================================
 --- head/sys/netinet/tcp_input.c	Sat Aug 20 16:43:47 2011	(r225043)
 +++ head/sys/netinet/tcp_input.c	Sat Aug 20 17:05:11 2011	(r225044)
 @@ -573,11 +573,9 @@ tcp_input(struct mbuf *m, int off0)
  	uint8_t sig_checked = 0;
  #endif
  	uint8_t iptos = 0;
 -#ifdef INET
  #ifdef IPFIREWALL_FORWARD
  	struct m_tag *fwd_tag;
  #endif
 -#endif /* INET */
  #ifdef INET6
  	struct ip6_hdr *ip6 = NULL;
  	int isipv6;
 @@ -776,14 +774,55 @@ findpcb:
  	}
  #endif
  
 -#ifdef INET
  #ifdef IPFIREWALL_FORWARD
  	/*
  	 * Grab info from PACKET_TAG_IPFORWARD tag prepended to the chain.
  	 */
  	fwd_tag = m_tag_find(m, PACKET_TAG_IPFORWARD, NULL);
 +#endif /* IPFIREWALL_FORWARD */
  
 -	if (fwd_tag != NULL && isipv6 == 0) {	/* IPv6 support is not yet */
 +#ifdef INET6
 +#ifdef IPFIREWALL_FORWARD
 +	if (isipv6 && fwd_tag != NULL) {
 +		struct sockaddr_in6 *next_hop6;
 +
 +		next_hop6 = (struct sockaddr_in6 *)(fwd_tag + 1);
 +		/*
 +		 * Transparently forwarded. Pretend to be the destination.
 +		 * Already got one like this?
 +		 */
 +		inp = in6_pcblookup_mbuf(&V_tcbinfo,
 +		    &ip6->ip6_src, th->th_sport, &ip6->ip6_dst, th->th_dport,
 +		    INPLOOKUP_WLOCKPCB, m->m_pkthdr.rcvif, m);
 +		if (!inp) {
 +			/*
 +			 * It's new.  Try to find the ambushing socket.
 +			 * Because we've rewritten the destination address,
 +			 * any hardware-generated hash is ignored.
 +			 */
 +			inp = in6_pcblookup(&V_tcbinfo, &ip6->ip6_src,
 +			    th->th_sport, &next_hop6->sin6_addr,
 +			    next_hop6->sin6_port ? ntohs(next_hop6->sin6_port) :
 +			    th->th_dport, INPLOOKUP_WILDCARD |
 +			    INPLOOKUP_WLOCKPCB, m->m_pkthdr.rcvif);
 +		}
 +		/* Remove the tag from the packet.  We don't need it anymore. */
 +		m_tag_delete(m, fwd_tag);
 +	} else
 +#endif /* IPFIREWALL_FORWARD */
 +	if (isipv6) {
 +		inp = in6_pcblookup_mbuf(&V_tcbinfo, &ip6->ip6_src,
 +		    th->th_sport, &ip6->ip6_dst, th->th_dport,
 +		    INPLOOKUP_WILDCARD | INPLOOKUP_WLOCKPCB,
 +		    m->m_pkthdr.rcvif, m);
 +	}
 +#endif /* INET6 */
 +#if defined(INET6) && defined(INET)
 +	else
 +#endif
 +#ifdef INET
 +#ifdef IPFIREWALL_FORWARD
 +	if (fwd_tag != NULL) {
  		struct sockaddr_in *next_hop;
  
  		next_hop = (struct sockaddr_in *)(fwd_tag+1);
 @@ -810,25 +849,11 @@ findpcb:
  		m_tag_delete(m, fwd_tag);
  	} else
  #endif /* IPFIREWALL_FORWARD */
 +		inp = in_pcblookup_mbuf(&V_tcbinfo, ip->ip_src,
 +		    th->th_sport, ip->ip_dst, th->th_dport,
 +		    INPLOOKUP_WILDCARD | INPLOOKUP_WLOCKPCB,
 +		    m->m_pkthdr.rcvif, m);
  #endif /* INET */
 -	{
 -#ifdef INET6
 -		if (isipv6)
 -			inp = in6_pcblookup_mbuf(&V_tcbinfo, &ip6->ip6_src,
 -			    th->th_sport, &ip6->ip6_dst, th->th_dport,
 -			    INPLOOKUP_WILDCARD | INPLOOKUP_WLOCKPCB,
 -			    m->m_pkthdr.rcvif, m);
 -#endif
 -#if defined(INET) && defined(INET6)
 -		else
 -#endif
 -#ifdef INET
 -			inp = in_pcblookup_mbuf(&V_tcbinfo, ip->ip_src,
 -			    th->th_sport, ip->ip_dst, th->th_dport,
 -			    INPLOOKUP_WILDCARD | INPLOOKUP_WLOCKPCB,
 -			    m->m_pkthdr.rcvif, m);
 -#endif
 -	}
  
  	/*
  	 * If the INPCB does not exist then all data in the incoming
 
 Modified: head/sys/netinet/udp_usrreq.c
 ==============================================================================
 --- head/sys/netinet/udp_usrreq.c	Sat Aug 20 16:43:47 2011	(r225043)
 +++ head/sys/netinet/udp_usrreq.c	Sat Aug 20 17:05:11 2011	(r225044)
 @@ -441,28 +441,6 @@ udp_input(struct mbuf *m, int off)
  	} else
  		UDPSTAT_INC(udps_nosum);
  
 -#ifdef IPFIREWALL_FORWARD
 -	/*
 -	 * Grab info from PACKET_TAG_IPFORWARD tag prepended to the chain.
 -	 */
 -	fwd_tag = m_tag_find(m, PACKET_TAG_IPFORWARD, NULL);
 -	if (fwd_tag != NULL) {
 -		struct sockaddr_in *next_hop;
 -
 -		/*
 -		 * Do the hack.
 -		 */
 -		next_hop = (struct sockaddr_in *)(fwd_tag + 1);
 -		ip->ip_dst = next_hop->sin_addr;
 -		uh->uh_dport = ntohs(next_hop->sin_port);
 -
 -		/*
 -		 * Remove the tag from the packet.  We don't need it anymore.
 -		 */
 -		m_tag_delete(m, fwd_tag);
 -	}
 -#endif
 -
  	if (IN_MULTICAST(ntohl(ip->ip_dst.s_addr)) ||
  	    in_broadcast(ip->ip_dst, ifp)) {
  		struct inpcb *last;
 @@ -568,9 +546,41 @@ udp_input(struct mbuf *m, int off)
  	/*
  	 * Locate pcb for datagram.
  	 */
 -	inp = in_pcblookup_mbuf(&V_udbinfo, ip->ip_src, uh->uh_sport,
 -	    ip->ip_dst, uh->uh_dport, INPLOOKUP_WILDCARD | INPLOOKUP_RLOCKPCB,
 -	    ifp, m);
 +#ifdef IPFIREWALL_FORWARD
 +	/*
 +	 * Grab info from PACKET_TAG_IPFORWARD tag prepended to the chain.
 +	 */
 +	fwd_tag = m_tag_find(m, PACKET_TAG_IPFORWARD, NULL);
 +	if (fwd_tag != NULL) {
 +		struct sockaddr_in *next_hop;
 +
 +		next_hop = (struct sockaddr_in *)(fwd_tag + 1);
 +
 +		/*
 +		 * Transparently forwarded. Pretend to be the destination.
 +		 * Already got one like this?
 +		 */
 +		inp = in_pcblookup_mbuf(&V_udbinfo, ip->ip_src, uh->uh_sport,
 +		    ip->ip_dst, uh->uh_dport, INPLOOKUP_RLOCKPCB, ifp, m);
 +		if (!inp) {
 +			/*
 +			 * It's new.  Try to find the ambushing socket.
 +			 * Because we've rewritten the destination address,
 +			 * any hardware-generated hash is ignored.
 +			 */
 +			inp = in_pcblookup(&V_udbinfo, ip->ip_src,
 +			    uh->uh_sport, next_hop->sin_addr,
 +			    next_hop->sin_port ? htons(next_hop->sin_port) :
 +			    uh->uh_dport, INPLOOKUP_WILDCARD |
 +			    INPLOOKUP_RLOCKPCB, ifp);
 +		}
 +		/* Remove the tag from the packet. We don't need it anymore. */
 +		m_tag_delete(m, fwd_tag);
 +	} else
 +#endif /* IPFIREWALL_FORWARD */
 +		inp = in_pcblookup_mbuf(&V_udbinfo, ip->ip_src, uh->uh_sport,
 +		    ip->ip_dst, uh->uh_dport, INPLOOKUP_WILDCARD |
 +		    INPLOOKUP_RLOCKPCB, ifp, m);
  	if (inp == NULL) {
  		if (udp_log_in_vain) {
  			char buf[4*sizeof "123"];
 
 Modified: head/sys/netinet6/ip6_forward.c
 ==============================================================================
 --- head/sys/netinet6/ip6_forward.c	Sat Aug 20 16:43:47 2011	(r225043)
 +++ head/sys/netinet6/ip6_forward.c	Sat Aug 20 17:05:11 2011	(r225044)
 @@ -34,6 +34,7 @@ __FBSDID("$FreeBSD$");
  
  #include "opt_inet.h"
  #include "opt_inet6.h"
 +#include "opt_ipfw.h"
  #include "opt_ipsec.h"
  #include "opt_ipstealth.h"
  
 @@ -50,6 +51,7 @@ __FBSDID("$FreeBSD$");
  #include <sys/syslog.h>
  
  #include <net/if.h>
 +#include <net/netisr.h>
  #include <net/route.h>
  #include <net/pfil.h>
  
 @@ -98,11 +100,17 @@ ip6_forward(struct mbuf *m, int srcrt)
  	struct mbuf *mcopy = NULL;
  	struct ifnet *origifp;	/* maybe unnecessary */
  	u_int32_t inzone, outzone;
 -	struct in6_addr src_in6, dst_in6;
 +	struct in6_addr src_in6, dst_in6, odst;
  #ifdef IPSEC
  	struct secpolicy *sp = NULL;
  	int ipsecrt = 0;
  #endif
 +#ifdef SCTP
 +	int sw_csum;
 +#endif
 +#ifdef IPFIREWALL_FORWARD
 +	struct m_tag *fwd_tag;
 +#endif
  	char ip6bufs[INET6_ADDRSTRLEN], ip6bufd[INET6_ADDRSTRLEN];
  
  #ifdef IPSEC
 @@ -345,13 +353,15 @@ ip6_forward(struct mbuf *m, int srcrt)
  		goto skip_routing;
  skip_ipsec:
  #endif
 -
 +again:
  	bzero(&rin6, sizeof(struct route_in6));
  	dst = (struct sockaddr_in6 *)&rin6.ro_dst;
  	dst->sin6_len = sizeof(struct sockaddr_in6);
  	dst->sin6_family = AF_INET6;
  	dst->sin6_addr = ip6->ip6_dst;
 -
 +#ifdef IPFIREWALL_FORWARD
 +again2:
 +#endif
  	rin6.ro_rt = rtalloc1((struct sockaddr *)dst, 0, 0);
  	if (rin6.ro_rt != NULL)
  		RT_UNLOCK(rin6.ro_rt);
 @@ -554,6 +564,7 @@ skip_routing:
  	if (!PFIL_HOOKED(&V_inet6_pfil_hook))
  		goto pass;
  
 +	odst = ip6->ip6_dst;
  	/* Run through list of hooks for output packets. */
  	error = pfil_run_hooks(&V_inet6_pfil_hook, &m, rt->rt_ifp, PFIL_OUT, NULL);
  	if (error != 0)
 @@ -562,6 +573,59 @@ skip_routing:
  		goto freecopy;
  	ip6 = mtod(m, struct ip6_hdr *);
  
 +	/* See if destination IP address was changed by packet filter. */
 +	if (!IN6_ARE_ADDR_EQUAL(&odst, &ip6->ip6_dst)) {
 +		m->m_flags |= M_SKIP_FIREWALL;
 +		/* If destination is now ourself drop to ip6_input(). */
 +		if (in6_localip(&ip6->ip6_dst)) {
 +			m->m_flags |= M_FASTFWD_OURS;
 +			if (m->m_pkthdr.rcvif == NULL)
 +				m->m_pkthdr.rcvif = V_loif;
 +			if (m->m_pkthdr.csum_flags & CSUM_DELAY_DATA) {
 +				m->m_pkthdr.csum_flags |=
 +				    CSUM_DATA_VALID | CSUM_PSEUDO_HDR;
 +				m->m_pkthdr.csum_data = 0xffff;
 +			}
 +			m->m_pkthdr.csum_flags |=
 +			    CSUM_IP_CHECKED | CSUM_IP_VALID;
 +#ifdef SCTP
 +			if (m->m_pkthdr.csum_flags & CSUM_SCTP)
 +				m->m_pkthdr.csum_flags |= CSUM_SCTP_VALID;
 +#endif
 +			error = netisr_queue(NETISR_IPV6, m);
 +			goto out;
 +		} else
 +			goto again;	/* Redo the routing table lookup. */
 +	}
 +
 +#ifdef IPFIREWALL_FORWARD
 +	/* See if local, if yes, send it to netisr. */
 +	if (m->m_flags & M_FASTFWD_OURS) {
 +		if (m->m_pkthdr.rcvif == NULL)
 +			m->m_pkthdr.rcvif = V_loif;
 +		if (m->m_pkthdr.csum_flags & CSUM_DELAY_DATA) {
 +			m->m_pkthdr.csum_flags |=
 +			    CSUM_DATA_VALID | CSUM_PSEUDO_HDR;
 +			m->m_pkthdr.csum_data = 0xffff;
 +		}
 +#ifdef SCTP
 +		if (m->m_pkthdr.csum_flags & CSUM_SCTP)
 +		m->m_pkthdr.csum_flags |= CSUM_SCTP_VALID;
 +#endif   
 +		error = netisr_queue(NETISR_IPV6, m);
 +		goto out;
 +	}
 +	/* Or forward to some other address? */
 +	fwd_tag = m_tag_find(m, PACKET_TAG_IPFORWARD, NULL);
 +	if (fwd_tag) {
 +		dst = (struct sockaddr_in6 *)&rin6.ro_dst;
 +		bcopy((fwd_tag+1), dst, sizeof(struct sockaddr_in6));
 +		m->m_flags |= M_SKIP_FIREWALL;
 +		m_tag_delete(m, fwd_tag);
 +		goto again2;
 +	}
 +#endif /* IPFIREWALL_FORWARD */
 +
  pass:
  	error = nd6_output(rt->rt_ifp, origifp, m, dst, rt);
  	if (error) {
 
 Modified: head/sys/netinet6/ip6_input.c
 ==============================================================================
 --- head/sys/netinet6/ip6_input.c	Sat Aug 20 16:43:47 2011	(r225043)
 +++ head/sys/netinet6/ip6_input.c	Sat Aug 20 17:05:11 2011	(r225044)
 @@ -65,6 +65,7 @@ __FBSDID("$FreeBSD$");
  
  #include "opt_inet.h"
  #include "opt_inet6.h"
 +#include "opt_ipfw.h"
  #include "opt_ipsec.h"
  #include "opt_route.h"
  
 @@ -91,6 +92,7 @@ __FBSDID("$FreeBSD$");
  #include <net/vnet.h>
  
  #include <netinet/in.h>
 +#include <netinet/ip_var.h>
  #include <netinet/in_systm.h>
  #include <net/if_llatbl.h>
  #ifdef INET
 @@ -357,6 +359,17 @@ ip6_input(struct mbuf *m)
  	 */
  	ip6_delaux(m);
  
 +	if (m->m_flags & M_FASTFWD_OURS) {
 +		/*
 +		 * Firewall changed destination to local.
 +		 */
 +		m->m_flags &= ~M_FASTFWD_OURS;
 +		ours = 1;
 +		deliverifp = m->m_pkthdr.rcvif;
 +		ip6 = mtod(m, struct ip6_hdr *);
 +		goto hbhcheck;
 +	}
 +
  	/*
  	 * mbuf statistics
  	 */
 @@ -533,6 +546,24 @@ ip6_input(struct mbuf *m)
  	ip6 = mtod(m, struct ip6_hdr *);
  	srcrt = !IN6_ARE_ADDR_EQUAL(&odst, &ip6->ip6_dst);
  
 +#ifdef IPFIREWALL_FORWARD
 +	if (m->m_flags & M_FASTFWD_OURS) {
 +		m->m_flags &= ~M_FASTFWD_OURS;
 +		ours = 1;
 +		deliverifp = m->m_pkthdr.rcvif;
 +		goto hbhcheck;
 +	}
 +	if (m_tag_find(m, PACKET_TAG_IPFORWARD, NULL) != NULL) {
 +		/*
 +		 * Directly ship the packet on.  This allows forwarding
 +		 * packets originally destined to us to some other directly
 +		 * connected host.
 +		 */
 +		ip6_forward(m, 1);
 +		goto out;
 +	}
 +#endif /* IPFIREWALL_FORWARD */
 +
  passin:
  	/*
  	 * Disambiguate address scope zones (if there is ambiguity).
 
 Modified: head/sys/netinet6/ip6_output.c
 ==============================================================================
 --- head/sys/netinet6/ip6_output.c	Sat Aug 20 16:43:47 2011	(r225043)
 +++ head/sys/netinet6/ip6_output.c	Sat Aug 20 17:05:11 2011	(r225044)
 @@ -65,6 +65,7 @@ __FBSDID("$FreeBSD$");
  
  #include "opt_inet.h"
  #include "opt_inet6.h"
 +#include "opt_ipfw.h"
  #include "opt_ipsec.h"
  #include "opt_sctp.h"
  #include "opt_route.h"
 @@ -90,6 +91,7 @@ __FBSDID("$FreeBSD$");
  
  #include <netinet/in.h>
  #include <netinet/in_var.h>
 +#include <netinet/ip_var.h>
  #include <netinet6/in6_var.h>
  #include <netinet/ip6.h>
  #include <netinet/icmp6.h>
 @@ -229,6 +231,9 @@ ip6_output(struct mbuf *m0, struct ip6_p
  	int segleft_org = 0;
  	struct secpolicy *sp = NULL;
  #endif /* IPSEC */
 +#ifdef IPFIREWALL_FORWARD
 +	struct m_tag *fwd_tag;
 +#endif
  
  	ip6 = mtod(m, struct ip6_hdr *);
  	if (ip6 == NULL) {
 @@ -850,7 +855,8 @@ again:
  	if (!IN6_ARE_ADDR_EQUAL(&odst, &ip6->ip6_dst)) {
  		m->m_flags |= M_SKIP_FIREWALL;
  		/* If destination is now ourself drop to ip6_input(). */
 -		if (in6_localaddr(&ip6->ip6_dst)) {
 +		if (in6_localip(&ip6->ip6_dst)) {
 +			m->m_flags |= M_FASTFWD_OURS;
  			if (m->m_pkthdr.rcvif == NULL)
  				m->m_pkthdr.rcvif = V_loif;
  			if (m->m_pkthdr.csum_flags & CSUM_DELAY_DATA) {
 @@ -870,7 +876,33 @@ again:
  			goto again;	/* Redo the routing table lookup. */
  	}
  
 -	/* XXX: IPFIREWALL_FORWARD */
 +#ifdef IPFIREWALL_FORWARD
 +	/* See if local, if yes, send it to netisr. */
 +	if (m->m_flags & M_FASTFWD_OURS) {
 +		if (m->m_pkthdr.rcvif == NULL)
 +			m->m_pkthdr.rcvif = V_loif;
 +		if (m->m_pkthdr.csum_flags & CSUM_DELAY_DATA) {
 +			m->m_pkthdr.csum_flags |=
 +			    CSUM_DATA_VALID | CSUM_PSEUDO_HDR;
 +			m->m_pkthdr.csum_data = 0xffff;
 +		}
 +#ifdef SCTP
 +		if (m->m_pkthdr.csum_flags & CSUM_SCTP)
 +		m->m_pkthdr.csum_flags |= CSUM_SCTP_VALID;
 +#endif   
 +		error = netisr_queue(NETISR_IPV6, m);
 +		goto done;
 +	}
 +	/* Or forward to some other address? */
 +	fwd_tag = m_tag_find(m, PACKET_TAG_IPFORWARD, NULL);
 +	if (fwd_tag) {
 +		dst = (struct sockaddr_in6 *)&ro->ro_dst;
 +		bcopy((fwd_tag+1), dst, sizeof(struct sockaddr_in6));
 +		m->m_flags |= M_SKIP_FIREWALL;
 +		m_tag_delete(m, fwd_tag);
 +		goto again;
 +	}
 +#endif /* IPFIREWALL_FORWARD */
  
  passout:
  	/*
 
 Modified: head/sys/netinet6/udp6_usrreq.c
 ==============================================================================
 --- head/sys/netinet6/udp6_usrreq.c	Sat Aug 20 16:43:47 2011	(r225043)
 +++ head/sys/netinet6/udp6_usrreq.c	Sat Aug 20 17:05:11 2011	(r225044)
 @@ -71,6 +71,7 @@ __FBSDID("$FreeBSD$");
  
  #include "opt_inet.h"
  #include "opt_inet6.h"
 +#include "opt_ipfw.h"
  #include "opt_ipsec.h"
  
  #include <sys/param.h>
 @@ -181,6 +182,9 @@ udp6_input(struct mbuf **mp, int *offp, 
  	int off = *offp;
  	int plen, ulen;
  	struct sockaddr_in6 fromsa;
 +#ifdef IPFIREWALL_FORWARD
 +	struct m_tag *fwd_tag;
 +#endif
  
  	ifp = m->m_pkthdr.rcvif;
  	ip6 = mtod(m, struct ip6_hdr *);
 @@ -377,9 +381,43 @@ udp6_input(struct mbuf **mp, int *offp, 
  	/*
  	 * Locate pcb for datagram.
  	 */
 -	inp = in6_pcblookup_mbuf(&V_udbinfo, &ip6->ip6_src, uh->uh_sport,
 -	    &ip6->ip6_dst, uh->uh_dport, INPLOOKUP_WILDCARD |
 -	    INPLOOKUP_RLOCKPCB, m->m_pkthdr.rcvif, m);
 +#ifdef IPFIREWALL_FORWARD
 +	/*
 +	 * Grab info from PACKET_TAG_IPFORWARD tag prepended to the chain.
 +	 */
 +	fwd_tag = m_tag_find(m, PACKET_TAG_IPFORWARD, NULL);
 +	if (fwd_tag != NULL) {
 +		struct sockaddr_in6 *next_hop6;
 +
 +		next_hop6 = (struct sockaddr_in6 *)(fwd_tag + 1);
 +
 +		/*
 +		 * Transparently forwarded. Pretend to be the destination.
 +		 * Already got one like this?
 +		 */
 +		inp = in6_pcblookup_mbuf(&V_udbinfo,
 +		    &ip6->ip6_src, uh->uh_sport, &ip6->ip6_dst, uh->uh_dport,
 +		    INPLOOKUP_RLOCKPCB, m->m_pkthdr.rcvif, m);
 +		if (!inp) {
 +			/*
 +			 * It's new.  Try to find the ambushing socket.
 +			 * Because we've rewritten the destination address,
 +			 * any hardware-generated hash is ignored.
 +			 */
 +			inp = in6_pcblookup(&V_udbinfo, &ip6->ip6_src,
 +			    uh->uh_sport, &next_hop6->sin6_addr,
 +			    next_hop6->sin6_port ? htons(next_hop6->sin6_port) :
 +			    uh->uh_dport, INPLOOKUP_WILDCARD |
 +			    INPLOOKUP_RLOCKPCB, m->m_pkthdr.rcvif);
 +		}
 +		/* Remove the tag from the packet. We don't need it anymore. */
 +		m_tag_delete(m, fwd_tag);
 +	} else
 +#endif /* IPFIREWALL_FORWARD */
 +		inp = in6_pcblookup_mbuf(&V_udbinfo, &ip6->ip6_src,
 +		    uh->uh_sport, &ip6->ip6_dst, uh->uh_dport,
 +		    INPLOOKUP_WILDCARD | INPLOOKUP_RLOCKPCB,
 +		    m->m_pkthdr.rcvif, m);
  	if (inp == NULL) {
  		if (udp_log_in_vain) {
  			char ip6bufs[INET6_ADDRSTRLEN];
 
 Added: head/tools/regression/ipfw/fwd/vimage-fwd.sh
 ==============================================================================
 --- /dev/null	00:00:00 1970	(empty, because file is newly added)
 +++ head/tools/regression/ipfw/fwd/vimage-fwd.sh	Sat Aug 20 17:05:11 2011	(r225044)
 @@ -0,0 +1,369 @@
 +#!/bin/sh
 +#-
 +# Copyright (c) 2010, "Bjoern A. Zeeb" <bz@FreeBSD.org>
 +# Copyright (c) 2011, Sandvine Incorporated ULC.
 +# All rights reserved.
 +#
 +# Redistribution and use in source and binary forms, with or without
 +# modification, are permitted provided that the following conditions
 +# are met:
 +# 1. Redistributions of source code must retain the above copyright
 +#    notice, this list of conditions and the following disclaimer.
 +# 2. Redistributions in binary form must reproduce the above copyright
 +#    notice, this list of conditions and the following disclaimer in the
 +#    documentation and/or other materials provided with the distribution.
 +#
 +# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
 +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 +# ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
 +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 +# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 +# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 +# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 +# SUCH DAMAGE.
 +#
 +# $FreeBSD$
 +#
 +
 +#
 +# Test ipfw fwd for IPv4 and IPv6 using VIMAGE, testing that as well.
 +# For no test the packet header contents must be changed but always
 +# keeping the original destination.
 +#
 +
 +case `id -u` in
 +0)	;;
 +*)	echo "ERROR: Must be run as superuser." >&2
 +	exit 2
 +esac
 +
 +epair_base()
 +{
 +	local ep
 +	
 +	ep=`ifconfig epair create`
 +	expr ${ep} : '\(.*\).'
 +}
 +
 +debug_err()
 +{
 +	local _p
 +	_p="$1"
 +
 +	case "${DEBUG}" in
 +	"")	;;
 +	*)
 +		echo " ~~ start of debug ~~"
 +		echo " ~~ left:"
 +		jexec ${ljid} /sbin/ipfw show
 +		echo " ~~ middle:"
 +		jexec ${mjid} /sbin/ipfw show
 +		echo " ~~ right:"
 +		jexec ${rjid} /sbin/ipfw show
 +		echo " ~~ result file:"
 +		cat ${_p}.1
 +		echo " ~~ log file:"
 +		cat ${_p}
 +		echo " ~~ end of debug ~~"
 +		;;
 +	esac
 +}
 +
 +check_cleanup_result_file()
 +{
 +	local _p
 +	_p="$1"
 +
 +	if test ! -s ${_p}.1; then
 +		echo "FAIL (output file empty)."
 +		debug_err ${_p}
 +	else
 +		read line < ${_p}.1
 +		# Netcat adds 'X's in udp mode.
 +		l="/${line#*/}"
 +		if test "${l}" = "${_p}"; then
 +			echo "PASS."
 +		else
 +			echo "FAIL (expected: '${_p}' got '${l}')."
 +			debug_err ${_p}
 +		fi
 +	fi
 +
 +	rm -f ${_p}.1
 +	rm -f ${_p}
 +}
 +
 +# Transparent proxy scenario (local address).
 +run_test_tp()
 +{
 +	local _descr
 +	local _sip _dip _fip _fport _dport _p
 +	local _nc_af _nc_p
 +	local _lport
 +	descr="$1"
 +	_sip="$2"
 +	_dip="$3"
 +	_fip="$4"
 +	_fport="$5"
 +	_dport="$6"
 +	_p="$7"
 +	_nc_af="$8"
 +
 +	_lport=${_dport}
 +	case "${_fport}" in
 +	"")	_lport="${_dport}" ;;
 +	*)	_lport="${_fport#,}" ;;
 +	esac
 +
 +	case "${_p}" in
 +	udp)	_nc_p="-u" ;;
 +	esac
 +
 +	OUT=`mktemp -t "ipfwfwd$$-XXXXXX"`
 +	echo -n "${descr} (${OUT}).."
 +	(
 +	jexec ${ljid} /sbin/ipfw -f flush
 +	jexec ${ljid} /sbin/ipfw -f zero
 +	jexec ${mjid} /sbin/ipfw -f flush
 +	jexec ${mjid} /sbin/ipfw -f zero
 +	jexec ${rjid} /sbin/ipfw -f flush
 +	jexec ${rjid} /sbin/ipfw -f zero
 +	jexec ${mjid} /sbin/ipfw add 100 fwd ${_fip}${_fport} ${_p} from ${_sip} to ${_dip}
 +
 +	jexec ${mjid} /bin/sh -c "nc -w 10 ${_nc_af} -n ${_nc_p} -l ${_fip} ${_lport} > ${OUT}.1 &"
 +	jexec ${rjid} /bin/sh -c "echo '${OUT}' | nc -w 1 -v ${_nc_af} -n ${_nc_p} ${_dip} ${_dport}"
 +	) > ${OUT} 2>&1
 +	check_cleanup_result_file "${OUT}"
 +}
 +
 +# Transparent redirect scenario (non-local address).
 +run_test_nh()
 +{
 +	local _descr
 +	local _sip _dip _fip _fport _dport _p
 +	local _nc_af _nc_p
 +	local _lport
 +	descr="$1"
 
 *** DIFF OUTPUT TRUNCATED AT 1000 LINES ***
 _______________________________________________
 svn-src-all@freebsd.org mailing list
 http://lists.freebsd.org/mailman/listinfo/svn-src-all
 To unsubscribe, send any mail to "svn-src-all-unsubscribe@freebsd.org"
 

From: dfilter@FreeBSD.ORG (dfilter service)
To: bug-followup@FreeBSD.org
Cc:  
Subject: Re: bin/117214: commit references a PR
Date: Sat, 27 Aug 2011 08:50:16 +0000 (UTC)

 Author: bz
 Date: Sat Aug 27 08:49:55 2011
 New Revision: 225209
 URL: http://svn.freebsd.org/changeset/base/225209
 
 Log:
   When adding IPv6 fwd support to ipfw in r225044 these two files were
   not committed.  Initialize next_hop6 to align with the IPv4 code.
   
   PR:		bin/117214
   MFC after:	3 weeks
   X-MFC with:	r225044
   Approved by:	re (kib)
 
 Modified:
   head/sys/net/if_bridge.c
   head/sys/net/if_ethersubr.c
 
 Modified: head/sys/net/if_bridge.c
 ==============================================================================
 --- head/sys/net/if_bridge.c	Sat Aug 27 06:54:08 2011	(r225208)
 +++ head/sys/net/if_bridge.c	Sat Aug 27 08:49:55 2011	(r225209)
 @@ -3083,6 +3083,7 @@ bridge_pfil(struct mbuf **mp, struct ifn
  		args.m = *mp;
  		args.oif = ifp;
  		args.next_hop = NULL;
 +		args.next_hop6 = NULL;
  		args.eh = &eh2;
  		args.inp = NULL;	/* used by ipfw uid/gid/jail rules */
  		i = V_ip_fw_chk_ptr(&args);
 
 Modified: head/sys/net/if_ethersubr.c
 ==============================================================================
 --- head/sys/net/if_ethersubr.c	Sat Aug 27 06:54:08 2011	(r225208)
 +++ head/sys/net/if_ethersubr.c	Sat Aug 27 08:49:55 2011	(r225209)
 @@ -499,6 +499,7 @@ ether_ipfw_chk(struct mbuf **m0, struct 
  	args.m = m;		/* the packet we are looking at		*/
  	args.oif = dst;		/* destination, if any			*/
  	args.next_hop = NULL;	/* we do not support forward yet	*/
 +	args.next_hop6 = NULL;	/* we do not support forward yet	*/
  	args.eh = &save_eh;	/* MAC header for bridged/MAC packets	*/
  	args.inp = NULL;	/* used by ipfw uid/gid/jail rules	*/
  	i = V_ip_fw_chk_ptr(&args);
 _______________________________________________
 svn-src-all@freebsd.org mailing list
 http://lists.freebsd.org/mailman/listinfo/svn-src-all
 To unsubscribe, send any mail to "svn-src-all-unsubscribe@freebsd.org"
 

From: Fabian Wenk <fabian@wenks.ch>
To: "Bjoern A. Zeeb" <bz@FreeBSD.org>
Cc: bug-followup@FreeBSD.org, Lars Eggert <lars.eggert@nokia.com>
Subject: Re: bin/117214: ipfw(8) fwd with IPv6 treats input as IPv4
Date: Mon, 07 Nov 2011 22:38:53 +0100

 Hello Bjoern
 
 On 19.07.2011 21:37, Bjoern A. Zeeb wrote:
 > and a version for stable/8 here:
 >
 >   	http://people.freebsd.org/~bz/20110719-01-ipfw-fwd-ipv6-pr117214.diff
 
 I now have tested your patch on a stable/8 system (synced this 
 morning). Now fwd rules with IPv6 are possible, but do not work 
 as expected and as it is working with IPv4.
 
 IPv6 Network setup:
 em0 2001:8a8:1005:1::10/64
 em1 2001:8a8:1005:2::184/64
 default gateway to 2001:8a8:1005:1::1
 
 IPFW fwd rules:
 ipfw add 25050 fwd 2001:8a8:1005:1::1 ip6 from 
 2001:8a8:1005:1::10 to not 
 2001:8a8:1005:1::/64,2001:8a8:1005:2::/64,::1
 ipfw add 25051 fwd 2001:8a8:1005:2::180 ip6 from 
 2001:8a8:1005:2::184 to not 
 2001:8a8:1005:2::/64,2001:8a8:1005:1::/64,::1
 
 When using ping6 from a remote host to both IPv6 addresses (first 
 2001:8a8:1005:1::10, second 2001:8a8:1005:2::184), then as seen 
 with tcpdump (output below) the request is coming in through the 
 correct interface, but the answer is always going out through em0 
 (where the default gateway is). According to the fwd rule the 
 second ping6 answer should go out through em1, as 
 2001:8a8:1005:2::180 is on that LAN. Also traceroute6 goes out 
 the wrong interface (output at the end). Both scenarios do work 
 correctly with IPv4 (and corresponding fwd rules).
 
 root@freebsd8:~ # tcpdump -i em0 host remote.example.com
 tcpdump: verbose output suppressed, use -v or -vv for full 
 protocol decode
 listening on em0, link-type EN10MB (Ethernet), capture size 96 bytes
 21:07:33.842258 IP6 remote.example.com > freebsd8.wenks.ch: 
 ICMP6, echo request, seq 0, length 16
 21:07:33.842297 IP6 freebsd8.wenks.ch > remote.example.com: 
 ICMP6, echo reply, seq 0, length 16
 21:07:38.798322 IP6 freebsd8.wenks.ch > remote.example.com: 
 ICMP6, echo reply, seq 0, length 16
 
 
 root@freebsd8:~ # tcpdump -i em1 host remote.example.com
 tcpdump: verbose output suppressed, use -v or -vv for full 
 protocol decode
 listening on em1, link-type EN10MB (Ethernet), capture size 96 bytes
 21:07:38.798275 IP6 remote.example.com > freebsd8.wenks.ch: 
 ICMP6, echo request, seq 0, length 16
 
 
 root@freebsd8:~ # traceroute6 -n -s 2001:8a8:1005:2::184 
 remote.example.com
 traceroute6 to remote.example.com (2002:xxxx:xxxx:x::86) from 
 2001:8a8:1005:2::184, 64 hops max, 12 byte packets
   1  2001:8a8:1005:1::1  1.051 ms  0.860 ms  0.834 ms
   2  2001:8a8:0:185::1  3.630 ms  3.469 ms  3.637 ms
   3  2001:8a8:1:3::34  3.579 ms  3.629 ms  3.540 ms
   4  2001:7f8:24::29  16.145 ms  16.110 ms  15.718 ms
 
 
 bye
 Fabian

From: "Bjoern A. Zeeb" <bz@FreeBSD.org>
To: Fabian Wenk <fabian@wenks.ch>
Cc: bug-followup@FreeBSD.org
Subject: Re: bin/117214: ipfw(8) fwd with IPv6 treats input as IPv4
Date: Sat, 10 Dec 2011 10:59:54 +0000 (UTC)

 On Mon, 7 Nov 2011, Fabian Wenk wrote:
 
 > I now have tested your patch on a stable/8 system (synced this morning). Now 
 > fwd rules with IPv6 are possible, but do not work as expected and as it is 
 > working with IPv4.
 ...
 > When using ping6 from a remote host to both IPv6 addresses (first 
 > 2001:8a8:1005:1::10, second 2001:8a8:1005:2::184), then as seen with tcpdump 
 > (output below) the request is coming in through the correct interface, but 
 > the answer is always going out through em0 (where the default gateway is). 
 > According to the fwd rule the second ping6 answer should go out through em1, 
 > as 2001:8a8:1005:2::180 is on that LAN. Also traceroute6 goes out the wrong 
 > interface (output at the end). Both scenarios do work correctly with IPv4 
 > (and corresponding fwd rules).
 
 This all seems to indicate that there's a problem with icmp6 handling.
 Do you have any further updates on this?
 
 -- 
 Bjoern A. Zeeb                                 You have to have visions!
           Stop bit received. Insert coin for new address family.

From: Fabian Wenk <fabian@wenks.ch>
To: "Bjoern A. Zeeb" <bz@FreeBSD.org>
Cc: bug-followup@FreeBSD.org
Subject: Re: bin/117214: ipfw(8) fwd with IPv6 treats input as IPv4
Date: Sun, 11 Dec 2011 21:36:07 +0100

 Hello Bjoern
 
 On 10.12.2011 11:59, Bjoern A. Zeeb wrote:
 > This all seems to indicate that there's a problem with icmp6 handling.
 > Do you have any further updates on this?
 
 I did just the same tests with telnet from an outside system to 
 port 22. It is the same behavior as with ping and traceroute. 
 Requests to the second interface (with IP 2001:8a8:1005:2::184) 
 came in through em1 (which is correct), but the out traffic (with 
 source IP 2001:8a8:1005:2::184) goes out through em0 (because of 
 the default gateway?) instead of em1 (where is should go 
 according to the fwd rule).
 
 I do not know, what else I should do to test / resolve this 
 further. If it would help you, I can give you access to this system.
 
 
 bye
 Fabian

From: niels=freebsd-gnats@bakker.net (Niels Bakker)
To: bug-followup@FreeBSD.org, fabian@wenks.ch
Cc:  
Subject: Re: bin/117214: ipfw(8) fwd with IPv6 treats input as IPv4
Date: Fri, 30 Mar 2012 22:22:58 +0200

 Hello,
 
 I'm seeing the same thing on FreeBSD 9.0.  I have three IPv6 
 delegations connected to three different providers and am trying to 
 avoid sending spoofed packets (from the upstreams' point of view), but 
 this isn't working.  If it's any consolation, it appears that pf's 
 `route-to' doesn't work either.
 
 Regards,
 
 
 	-- Niels.

From: "Alexander V. Chernikov" <melifaro@FreeBSD.org>
To: bug-followup@FreeBSD.org, fabian@wenks.ch
Cc:  
Subject: Re: bin/117214: ipfw(8) fwd with IPv6 treats input as IPv4
Date: Sun, 06 May 2012 15:47:23 +0400

 This is a multi-part message in MIME format.
 --------------090800010905090900010500
 Content-Type: text/plain; charset=ISO-8859-1; format=flowed
 Content-Transfer-Encoding: 7bit
 
 Please try the attached patch
 
 P.S. if GNATS fails to show it correctly, here is the direct link:
 http://static.ipfw.ru/patches/ipfw_fwd6.diff
 
 
 --------------090800010905090900010500
 Content-Type: text/plain;
  name="ipfw_fwd6.diff"
 Content-Transfer-Encoding: 7bit
 Content-Disposition: attachment;
  filename="ipfw_fwd6.diff"
 
 Index: sys/netinet6/ip6_output.c
 ===================================================================
 --- sys/netinet6/ip6_output.c	(revision 234899)
 +++ sys/netinet6/ip6_output.c	(working copy)
 @@ -232,7 +232,10 @@ ip6_output(struct mbuf *m0, struct ip6_pktopts *op
  	struct secpolicy *sp = NULL;
  #endif /* IPSEC */
  #ifdef IPFIREWALL_FORWARD
 -	struct m_tag *fwd_tag;
 +	struct m_tag *fwd_tag = NULL;
 +	struct sockaddr_in6 fwd_sa;
 +
 +	memset(&fwd_sa, 0, sizeof(fwd_sa));
  #endif
  
  	ip6 = mtod(m, struct ip6_hdr *);
 @@ -600,10 +603,17 @@ again:
  	/* adjust pointer */
  	ip6 = mtod(m, struct ip6_hdr *);
  
 +#ifdef IPFIREWALL_FORWARD
 +	if (fwd_tag == NULL) {
 +#endif
  	bzero(&dst_sa, sizeof(dst_sa));
  	dst_sa.sin6_family = AF_INET6;
  	dst_sa.sin6_len = sizeof(dst_sa);
  	dst_sa.sin6_addr = ip6->ip6_dst;
 +#ifdef IPFIREWALL_FORWARD
 +	} else
 +		dst_sa = fwd_sa;
 +#endif
  	if (flevalid) {
  		rt = ro->ro_rt;
  		ifp = ro->ro_rt->rt_ifp;
 @@ -899,8 +909,8 @@ again:
  	/* Or forward to some other address? */
  	fwd_tag = m_tag_find(m, PACKET_TAG_IPFORWARD, NULL);
  	if (fwd_tag) {
 -		dst = (struct sockaddr_in6 *)&ro->ro_dst;
 -		bcopy((fwd_tag+1), dst, sizeof(struct sockaddr_in6));
 +		bcopy((fwd_tag+1), &fwd_sa, sizeof(struct sockaddr_in6));
 +		dst = &fwd_sa;
  		m->m_flags |= M_SKIP_FIREWALL;
  		m_tag_delete(m, fwd_tag);
  		goto again;
 
 --------------090800010905090900010500--

From: Andrey Zonov <andrey@zonov.org>
To: bug-followup@FreeBSD.org, fabian@wenks.ch, 
 niels=freebsd-gnats@bakker.net
Cc:  
Subject: Re: bin/117214: ipfw(8) fwd with IPv6 treats input as IPv4
Date: Sun, 06 May 2012 15:50:38 +0400

 Hi,
 
 pf works fine, but you have to remember that NDP should not be 
 forwarded.  Try something like this:
 
 if = bce0
 gw = "fdf2:d236:f91d:104::"
 me = "fdf2:d236:f91d:104::/64"
 mc = "ff02::/16"
 
 pass out quick route-to ($if $gw) from $me to ! $mc no state
 
 -- 
 Andrey Zonov

From: Fabian Wenk <fabian@wenks.ch>
To: "Alexander V. Chernikov" <melifaro@FreeBSD.org>
Cc: bug-followup@FreeBSD.org
Subject: Re: bin/117214: ipfw(8) fwd with IPv6 treats input as IPv4
Date: Thu, 24 May 2012 19:27:08 +0200

 Hello Alexander
 
 On 06.05.2012 13:47, Alexander V. Chernikov wrote:
 > Please try the attached patch
 >
 > P.S. if GNATS fails to show it correctly, here is the direct link:
 > http://static.ipfw.ru/patches/ipfw_fwd6.diff
 
 Finally I got time to test your patch on a FreeBSD RELENG_9 
 (check out done on 21 May 2012). It did not cleanly apply on 
 RELENG_8. I have rebuilt and installed the kernel and rebooted.
 
 Something is still failing and no traffic with the second IP 
 address as source goes out.
 
 IPv6 Network setup:
 em0 2001:8a8:1005:1::10/64
 em1 2001:8a8:1005:2::184/64
 default gateway to 2001:8a8:1005:1::1
 
 IPFW fwd rules for IPv6:
 ipfw add 25050 fwd 2001:8a8:1005:1::1 ip6 from 
 2001:8a8:1005:1::10 to not 
 2001:8a8:1005:1::/64,2001:8a8:1005:2::/64,::1
 ipfw add 25051 fwd 2001:8a8:1005:2::180 ip6 from 
 2001:8a8:1005:2::184 to not 
 2001:8a8:1005:2::/64,2001:8a8:1005:1::/64,::1
 
 And default gateway is pointing to: 2001:8a8:1005:1::1
 
 
 Here the few tests I have run:
 
 root@freebsd9:~ # traceroute6 -n -s 2001:8a8:1005:1::10 cam.switch.ch
 traceroute6 to cam.switch.ch (2001:620:0:13::10) from 
 2001:8a8:1005:1::10, 64 hops max, 12 byte packets
   1  2001:8a8:1005:1::1  0.713 ms  0.599 ms  0.628 ms
   2  2001:8a8:0:185::1  3.612 ms  5.346 ms  3.469 ms
   3  2001:8a8:1:33::35  3.702 ms  5.409 ms  3.398 ms
   4  2001:7f8:24::35  3.791 ms  5.585 ms  3.748 ms
   5  2001:620:0:c00a::1  4.836 ms  5.675 ms  3.872 ms
   6  2001:620:0:13::10  4.323 ms  5.917 ms  4.175 ms
 
 root@freebsd9:~ # ipfw show | grep fwd | grep ip6
 25050  18  1080 fwd 2001:8a8:1005:1::1 ip6 from 
 2001:8a8:1005:1::10 to not 
 2001:8a8:1005:1::/64,2001:8a8:1005:2::/64,::1
 25051   0     0 fwd 2001:8a8:1005:2::180 ip6 from 
 2001:8a8:1005:2::184 to not 
 2001:8a8:1005:2::/64,2001:8a8:1005:1::/64,::1
 
 root@freebsd9:~ # traceroute6 -n -s 2001:8a8:1005:2::184 
 cam.switch.ch
 traceroute6 to cam.switch.ch (2001:620:0:13::10) from 
 2001:8a8:1005:2::184, 64 hops max, 12 byte packets
   1  2001:8a8:1005:2::184  2999.113 ms !A  2999.907 ms !A 
 2999.971 ms !A
 
 root@freebsd9:~ # ipfw show | grep fwd | grep ip6
 25050  18  1080 fwd 2001:8a8:1005:1::1 ip6 from 
 2001:8a8:1005:1::10 to not 
 2001:8a8:1005:1::/64,2001:8a8:1005:2::/64,::1
 25051  12   828 fwd 2001:8a8:1005:2::180 ip6 from 
 2001:8a8:1005:2::184 to not 
 2001:8a8:1005:2::/64,2001:8a8:1005:1::/64,::1
 
 
 With the second traceroute (-s 2001:8a8:1005:2::184), I do not 
 see any traffic going out either interface (checked with 
 tcpdump). But the ipfw fwd rules show packets gone through rule 
 25051.
 
 
 Are this information enough for you, or could you tell me which 
 other tests I should try?
 
 
 bye
 Fabian
State-Changed-From-To: patched->closed 
State-Changed-By: eadler 
State-Changed-When: Fri Mar 15 23:34:31 UTC 2013 
State-Changed-Why:  
MFCed/fixed by now or it will never be MFCed 

http://www.freebsd.org/cgi/query-pr.cgi?pr=117214 
>Unformatted:
