From nobody@FreeBSD.org  Mon Oct 30 07:06:48 2006
Return-Path: <nobody@FreeBSD.org>
Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125])
	by hub.freebsd.org (Postfix) with ESMTP id CE3EE16A40F
	for <freebsd-gnats-submit@FreeBSD.org>; Mon, 30 Oct 2006 07:06:48 +0000 (UTC)
	(envelope-from nobody@FreeBSD.org)
Received: from www.freebsd.org (www.freebsd.org [216.136.204.117])
	by mx1.FreeBSD.org (Postfix) with ESMTP id 7CAD343D55
	for <freebsd-gnats-submit@FreeBSD.org>; Mon, 30 Oct 2006 07:06:48 +0000 (GMT)
	(envelope-from nobody@FreeBSD.org)
Received: from www.freebsd.org (localhost [127.0.0.1])
	by www.freebsd.org (8.13.1/8.13.1) with ESMTP id k9U76mcC063965
	for <freebsd-gnats-submit@FreeBSD.org>; Mon, 30 Oct 2006 07:06:48 GMT
	(envelope-from nobody@www.freebsd.org)
Received: (from nobody@localhost)
	by www.freebsd.org (8.13.1/8.13.1/Submit) id k9U76m7W063964;
	Mon, 30 Oct 2006 07:06:48 GMT
	(envelope-from nobody)
Message-Id: <200610300706.k9U76m7W063964@www.freebsd.org>
Date: Mon, 30 Oct 2006 07:06:48 GMT
From: Stephen Halpin<seh-10lzx4@mail.quadrizen.com>
To: freebsd-gnats-submit@FreeBSD.org
Subject: ipfw(8) sometimes treat ipv6 input as ipv4 (another variation on PR 91245)
X-Send-Pr-Version: www-3.0

>Number:         104921
>Category:       bin
>Synopsis:       [patch] ipfw(8) sometimes treats ipv6 input as ipv4 (another variation on PR 91245)
>Confidential:   no
>Severity:       non-critical
>Priority:       medium
>Responsible:    melifaro
>State:          patched
>Quarter:        
>Keywords:       
>Date-Required:  
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Mon Oct 30 07:10:19 GMT 2006
>Closed-Date:    
>Last-Modified:  Sat May 18 04:50:43 UTC 2013
>Originator:     Stephen Halpin
>Release:        FreeBSD 6.2-BETA2
>Organization:
None
>Environment:
FreeBSD  6.2-BETA2 FreeBSD 6.2-BETA2 #0: Mon Oct  2 03:32:44 UTC 2006     root@opus.cse.buffalo.edu:/usr/obj/usr/src/sys/SMP  i386

>Description:
Some IPv6 address specifiers are still incorrectly interpreted as IPv4 addresses.  In this particular variation, if a list of addresses starting with an IPv6 host address and followed by either an IPv6 host or network address.  Both source and destination address parsing exhibit this problem.
>How-To-Repeat:
ipfw add allow udp from any to 2000::1,2002::/16

It will result in the error:

ipfw: bad netmask ``:1,2002::/16''

Similarly:

ipfw add allow udp from 2000::1,2002::1 to any

results in the error:

ipfw: bad netmask ``:1,2002::1''

>Fix:
The original proposed fix for 91245 would have caught this, but that fix was changed to use a strrchr to find the last '/' in the address list before passing it to inet_pton(AF_INET6,... to see if it is an IPv6 address.  I'm guessing someone was using the n.n.n.n:m.m.m.m format for multiple IPv4 addresses and they were incorrectly being identified by the original proposed fix as an IPv6 address.  As to why strrchr (reverse search) was used instead of strchr isn't obvious, and if there was a reason, it should be used to evaluate the effectiveness of what I'm proposing.

It's my understanding by looking at this that we want to scan up to the first ',' or the first '/' to find the first IPv6 address without any mask information and pass that to inet_pton(AF_INET6,... to see if it really is an IPv6 address.  To that end, I propose the following:

*** ipfw2.c.start	Mon Oct 30 01:19:40 2006
--- ipfw2.c	Mon Oct 30 01:36:48 2006
***************
*** 3791,3797 ****
  
  	if ((host = strdup(av)) == NULL)
  		return NULL;
! 	if ((ch = strrchr(host, '/')) != NULL)
  		*ch = '\0';
  
  	if (proto == IPPROTO_IPV6  || strcmp(av, "me6") == 0 ||
--- 3791,3797 ----
  
  	if ((host = strdup(av)) == NULL)
  		return NULL;
! 	if ((ch = strpbrk(host, "/,")) != NULL)
  		*ch = '\0';
  
  	if (proto == IPPROTO_IPV6  || strcmp(av, "me6") == 0 ||
***************
*** 3817,3823 ****
  
  	if ((host = strdup(av)) == NULL)
  		return NULL;
! 	if ((ch = strrchr(host, '/')) != NULL)
  		*ch = '\0';
  
  	if (proto == IPPROTO_IPV6  || strcmp(av, "me6") == 0 ||
--- 3817,3823 ----
  
  	if ((host = strdup(av)) == NULL)
  		return NULL;
! 	if ((ch = strpbrk(host, "/,")) != NULL)
  		*ch = '\0';
  
  	if (proto == IPPROTO_IPV6  || strcmp(av, "me6") == 0 ||

>Release-Note:
>Audit-Trail:
Responsible-Changed-From-To: freebsd-bugs->freebsd-ipfw 
Responsible-Changed-By: linimon 
Responsible-Changed-When: Mon Oct 30 09:10:35 UTC 2006 
Responsible-Changed-Why:  
Over to maintainer(s). 

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

From: "Stephen E. Halpin" <seh-k3t3z4@mail.quadrizen.com>
To: bug-followup@FreeBSD.org,
 seh-k3t3z4@mail.quadrizen.com
Cc:  
Subject: Re: bin/104921: [patch] ipfw(8) sometimes treats ipv6 input as ipv4 (another variation on PR 91245)
Date: Mon, 21 Apr 2008 03:14:22 -0400

 (Note updated e-mail address...)
 
 The same problem exists in FreeBSD 6.3, and essentially the same set  
 of diffs work:
 
 *** ipfw2.c.orig	Sun Oct 14 04:58:01 2007
 --- ipfw2.c	Sun Jan 20 12:35:46 2008
 ***************
 *** 3816,3822 ****
 
    	if ((host = strdup(av)) == NULL)
    		return NULL;
 ! 	if ((ch = strrchr(host, '/')) != NULL)
    		*ch = '\0';
 
    	if (proto == IPPROTO_IPV6  || strcmp(av, "me6") == 0 ||
 --- 3816,3822 ----
 
    	if ((host = strdup(av)) == NULL)
    		return NULL;
 ! 	if ((ch = strpbrk(host, "/,")) != NULL)
    		*ch = '\0';
 
    	if (proto == IPPROTO_IPV6  || strcmp(av, "me6") == 0 ||
 ***************
 *** 3842,3848 ****
 
    	if ((host = strdup(av)) == NULL)
    		return NULL;
 ! 	if ((ch = strrchr(host, '/')) != NULL)
    		*ch = '\0';
 
    	if (proto == IPPROTO_IPV6  || strcmp(av, "me6") == 0 ||
 --- 3842,3848 ----
 
    	if ((host = strdup(av)) == NULL)
    		return NULL;
 ! 	if ((ch = strpbrk(host, "/,")) != NULL)
    		*ch = '\0';
 
    	if (proto == IPPROTO_IPV6  || strcmp(av, "me6") == 0 ||
 
 -Steve

From: Lars Eggert <lars.eggert@nokia.com>
To: bug-followup@FreeBSD.org, seh-10lzx4@mail.quadrizen.com
Cc:  
Subject: Re: bin/104921: [patch] ipfw(8) sometimes treats ipv6 input as ipv4 (another variation on PR 91245)
Date: Sat, 22 Aug 2009 02:27:27 +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
 

From: Lev Serebryakov <lev@FreeBSD.org>
To: bug-followup@FreeBSD.org, seh-10lzx4@mail.quadrizen.com
Cc: freebsd-ipfw@FreeBSD.org, freebsd-net@freebsd.org
Subject: Re: bin/104921: [patch] ipfw(8) sometimes treats ipv6 input as ipv4 (another variation on PR 91245)
Date: Wed, 20 Apr 2011 16:36:55 +0400

 Hello, Bug-followup.
 
   It is still valid for 8.2-STABLE:
 
 gateway# ipfw add 50000 allow ipv6-icmp from any to 2001:470:1f09:hhhh::/64=
 ,2001:470:hhhh:1::/64,2001:470:hhhh:2::/64 icmp6types 1,2,3,4,128,129 keep-=
 state
 ipfw: bad netmask ``470:1f09:hhhh::/64''
 gateway# uname -a
 FreeBSD gateway.home.serebryakov.spb.ru 8.2-STABLE FreeBSD 8.2-STABLE #0: F=
 ri Apr 15 16:57:44 MSD 2011     lev@vmware-8-32.home.serebryakov.spb.ru:/us=
 r/obj/nanobsd.gateway-net5501/usr/src/sys/NET5501  i386
 
   It is very annoying bug, because "allow" rule can be divided into
 one-rule-per-network, but "deny ... NOT IPv6,IPv6,..." is hard to
 emulate (with multiple skipto rules).
 
 --=20
 // Black Lion AKA Lev Serebryakov <lev@FreeBSD.org>
 

From: Ryan Steinmetz <zi@FreeBSD.org>
To: bug-followup@FreeBSD.org
Cc:  
Subject: Re: bin/104921: [patch] ipfw(8) sometimes treats ipv6 input as ipv4
 (another variation on PR 91245)
Date: Sat, 24 Sep 2011 08:42:20 -0400

 I can confirm this issue also exists on 8.2 as of today.  It appears as
 if ipfw is incorrectly assuming that an IPv6 address is an invalid IPv4
 address with a mask.
 
 For example:
 2001:1:2:3::4,2001:1:2:3::5 is treated as an IPv4 address of 2001 with a
 mask of 1:2:3::4 (as if it were specified as 1.2.3.4:255.255.255.0).
 
 Specifying the IPv6 address without the comma results in a successful
 rule being created.
 
 -- 
 Ryan Steinmetz
 PGP: EF36 D45A 5CA9 28B1 A550  18CD A43C D111 7AD7 FAF2

From: Sergey Matveychuk <sem@FreeBSD.org>
To: bug-followup@FreeBSD.org, seh-10lzx4@mail.quadrizen.com
Cc:  
Subject: Re: bin/104921: [patch] ipfw(8) sometimes treats ipv6 input as ipv4
 (another variation on PR 91245)
Date: Mon, 27 Feb 2012 17:45:38 +0400

 The same for 9.0 :(
Responsible-Changed-From-To: freebsd-ipfw->melifaro 
Responsible-Changed-By: melifaro 
Responsible-Changed-When: Sat May 18 04:45:03 UTC 2013 
Responsible-Changed-Why:  
Take 

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

From: dfilter@FreeBSD.ORG (dfilter service)
To: bug-followup@FreeBSD.org
Cc:  
Subject: Re: bin/104921: commit references a PR
Date: Sat, 18 May 2013 04:49:08 +0000 (UTC)

 Author: melifaro
 Date: Sat May 18 04:49:00 2013
 New Revision: 250759
 URL: http://svnweb.freebsd.org/changeset/base/250759
 
 Log:
   Fix ipfw(8) sets of ipv6 addresses handling.
   Conditionally use stack buffer instead of calling strdup().
   
   PR:		bin/104921
   MFC after:	2 weeks
 
 Modified:
   head/sbin/ipfw/ipfw2.c
 
 Modified: head/sbin/ipfw/ipfw2.c
 ==============================================================================
 --- head/sbin/ipfw/ipfw2.c	Fri May 17 23:14:18 2013	(r250758)
 +++ head/sbin/ipfw/ipfw2.c	Sat May 18 04:49:00 2013	(r250759)
 @@ -2779,13 +2779,19 @@ static ipfw_insn *
  add_src(ipfw_insn *cmd, char *av, u_char proto, int cblen)
  {
  	struct in6_addr a;
 -	char *host, *ch;
 +	char *host, *ch, buf[INET6_ADDRSTRLEN];
  	ipfw_insn *ret = NULL;
 +	int len;
  
 -	if ((host = strdup(av)) == NULL)
 -		return NULL;
 -	if ((ch = strrchr(host, '/')) != NULL)
 -		*ch = '\0';
 +	/* Copy first address in set if needed */
 +	if ((ch = strpbrk(av, "/,")) != NULL) {
 +		len = ch - av;
 +		strlcpy(buf, av, sizeof(buf));
 +		if (len < sizeof(buf))
 +			buf[len] = '\0';
 +		host = buf;
 +	} else
 +		host = av;
  
  	if (proto == IPPROTO_IPV6  || strcmp(av, "me6") == 0 ||
  	    inet_pton(AF_INET6, host, &a) == 1)
 @@ -2797,7 +2803,6 @@ add_src(ipfw_insn *cmd, char *av, u_char
  	if (ret == NULL && strcmp(av, "any") != 0)
  		ret = cmd;
  
 -	free(host);
  	return ret;
  }
  
 @@ -2805,13 +2810,19 @@ static ipfw_insn *
  add_dst(ipfw_insn *cmd, char *av, u_char proto, int cblen)
  {
  	struct in6_addr a;
 -	char *host, *ch;
 +	char *host, *ch, buf[INET6_ADDRSTRLEN];
  	ipfw_insn *ret = NULL;
 +	int len;
  
 -	if ((host = strdup(av)) == NULL)
 -		return NULL;
 -	if ((ch = strrchr(host, '/')) != NULL)
 -		*ch = '\0';
 +	/* Copy first address in set if needed */
 +	if ((ch = strpbrk(av, "/,")) != NULL) {
 +		len = ch - av;
 +		strlcpy(buf, av, sizeof(buf));
 +		if (len < sizeof(buf))
 +			buf[len] = '\0';
 +		host = buf;
 +	} else
 +		host = av;
  
  	if (proto == IPPROTO_IPV6  || strcmp(av, "me6") == 0 ||
  	    inet_pton(AF_INET6, host, &a) == 1)
 @@ -2823,7 +2834,6 @@ add_dst(ipfw_insn *cmd, char *av, u_char
  	if (ret == NULL && strcmp(av, "any") != 0)
  		ret = cmd;
  
 -	free(host);
  	return ret;
  }
  
 _______________________________________________
 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"
 
State-Changed-From-To: open->patched 
State-Changed-By: melifaro 
State-Changed-When: Sat May 18 04:50:19 UTC 2013 
State-Changed-Why:  
Fixed in HEAD. 

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