From nobody@FreeBSD.org  Fri Apr  4 08:29:16 2014
Return-Path: <nobody@FreeBSD.org>
Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1])
	(using TLSv1 with cipher ADH-AES256-SHA (256/256 bits))
	(No client certificate requested)
	by hub.freebsd.org (Postfix) with ESMTPS id DBDECCB
	for <freebsd-gnats-submit@FreeBSD.org>; Fri,  4 Apr 2014 08:29:16 +0000 (UTC)
Received: from cgiserv.freebsd.org (cgiserv.freebsd.org [IPv6:2001:1900:2254:206a::50:4])
	(using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits))
	(Client did not present a certificate)
	by mx1.freebsd.org (Postfix) with ESMTPS id C98A7D70
	for <freebsd-gnats-submit@FreeBSD.org>; Fri,  4 Apr 2014 08:29:16 +0000 (UTC)
Received: from cgiserv.freebsd.org ([127.0.1.6])
	by cgiserv.freebsd.org (8.14.8/8.14.8) with ESMTP id s348TGRp015163
	for <freebsd-gnats-submit@FreeBSD.org>; Fri, 4 Apr 2014 08:29:16 GMT
	(envelope-from nobody@cgiserv.freebsd.org)
Received: (from nobody@localhost)
	by cgiserv.freebsd.org (8.14.8/8.14.8/Submit) id s348TGpu015162;
	Fri, 4 Apr 2014 08:29:16 GMT
	(envelope-from nobody)
Message-Id: <201404040829.s348TGpu015162@cgiserv.freebsd.org>
Date: Fri, 4 Apr 2014 08:29:16 GMT
From: Daniel Engberg <daniel.engberg.lists@pyret.net>
To: freebsd-gnats-submit@FreeBSD.org
Subject: ICMP / NAT issues using pf on -CURRENT
X-Send-Pr-Version: www-3.1
X-GNATS-Notify:

>Number:         188253
>Category:       kern
>Synopsis:       [pf] ICMP / NAT issues using pf on -CURRENT
>Confidential:   no
>Severity:       non-critical
>Priority:       low
>Responsible:    glebius
>State:          closed
>Quarter:        
>Keywords:       
>Date-Required:  
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Fri Apr 04 08:30:02 UTC 2014
>Closed-Date:    Wed Apr 16 09:25:06 UTC 2014
>Last-Modified:  Wed Apr 16 09:30:00 UTC 2014
>Originator:     Daniel Engberg
>Release:        FreeBSD 11.0-CURRENT
>Organization:
>Environment:
FreeBSD miyuki.pyret.net 11.0-CURRENT FreeBSD 11.0-CURRENT #2 r263658: Sun Mar 23 12:06:39 CET 2014     diizzy@miyuki.pyret.net:/usr/obj/usr/src/sys/MIYUKI  amd64
>Description:
Sent to mailing-list back in February, bug confirmed by other user.

http://lists.freebsd.org/pipermail/freebsd-pf/2014-February/007300.html
http://lists.freebsd.org/pipermail/freebsd-pf/2014-March/007327.html

r261486 and r263658 experiences the same issues
>How-To-Repeat:
Enable NAT and try to use ICMP ping on a client behind NAT
>Fix:


>Release-Note:
>Audit-Trail:
Responsible-Changed-From-To: freebsd-bugs->freebsd-pf 
Responsible-Changed-By: linimon 
Responsible-Changed-When: Wed Apr 16 01:32:29 UTC 2014 
Responsible-Changed-Why:  
Over to maintainer(s). 

http://www.freebsd.org/cgi/query-pr.cgi?pr=188253 
Responsible-Changed-From-To: freebsd-pf->glebius 
Responsible-Changed-By: glebius 
Responsible-Changed-When: Wed Apr 16 07:19:11 UTC 2014 
Responsible-Changed-Why:  
I must take care of this. 

http://www.freebsd.org/cgi/query-pr.cgi?pr=188253 
State-Changed-From-To: open->closed 
State-Changed-By: glebius 
State-Changed-When: Wed Apr 16 09:23:45 UTC 2014 
State-Changed-Why:  
Fixed. 

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

From: dfilter@FreeBSD.ORG (dfilter service)
To: bug-followup@FreeBSD.org
Cc:  
Subject: Re: kern/188253: commit references a PR
Date: Wed, 16 Apr 2014 09:25:25 +0000 (UTC)

 Author: glebius
 Date: Wed Apr 16 09:25:20 2014
 New Revision: 264521
 URL: http://svnweb.freebsd.org/changeset/base/264521
 
 Log:
   Backout r257223,r257224,r257225,r257246,r257710. The changes caused
   some regressions in ICMP handling, and right now me and Baptiste
   are out of time on analyzing them.
   
   PR:		188253
 
 Modified:
   head/sys/netpfil/pf/pf.c
   head/sys/netpfil/pf/pf_lb.c
 
 Modified: head/sys/netpfil/pf/pf.c
 ==============================================================================
 --- head/sys/netpfil/pf/pf.c	Wed Apr 16 05:31:54 2014	(r264520)
 +++ head/sys/netpfil/pf/pf.c	Wed Apr 16 09:25:20 2014	(r264521)
 @@ -210,8 +210,6 @@ static void		 pf_change_ap(struct pf_add
  			    u_int16_t, u_int8_t, sa_family_t);
  static int		 pf_modulate_sack(struct mbuf *, int, struct pf_pdesc *,
  			    struct tcphdr *, struct pf_state_peer *);
 -static int		 pf_icmp_mapping(struct pf_pdesc *, uint8_t, int *,
 -			    int *, uint16_t *, uint16_t *);
  static void		 pf_change_icmp(struct pf_addr *, u_int16_t *,
  			    struct pf_addr *, struct pf_addr *, u_int16_t,
  			    u_int16_t *, u_int16_t *, u_int16_t *,
 @@ -258,10 +256,6 @@ static int		 pf_test_state_tcp(struct pf
  static int		 pf_test_state_udp(struct pf_state **, int,
  			    struct pfi_kif *, struct mbuf *, int,
  			    void *, struct pf_pdesc *);
 -static int		 pf_icmp_state_lookup(struct pf_state_key_cmp *,
 -			    struct pf_pdesc *, struct pf_state **, struct mbuf *,
 -			    int, struct pfi_kif *, uint16_t, uint16_t,
 -			    int, int *, int);
  static int		 pf_test_state_icmp(struct pf_state **, int,
  			    struct pfi_kif *, struct mbuf *, int,
  			    void *, struct pf_pdesc *, u_short *);
 @@ -310,8 +304,6 @@ VNET_DECLARE(int, pf_end_threads);
  
  VNET_DEFINE(struct pf_limit, pf_limits[PF_LIMIT_MAX]);
  
 -enum { PF_ICMP_MULTI_NONE, PF_ICMP_MULTI_SOLICITED, PF_ICMP_MULTI_LINK };
 -
  #define	PACKET_LOOPED(pd)	((pd)->pf_mtag &&			\
  				 (pd)->pf_mtag->flags & PF_PACKET_LOOPED)
  
 @@ -2057,155 +2049,6 @@ pf_change_a6(struct pf_addr *a, u_int16_
  }
  #endif /* INET6 */
  
 -static int
 -pf_icmp_mapping(struct pf_pdesc *pd, uint8_t type,
 -    int *icmp_dir, int *multi, uint16_t *icmpid, uint16_t *icmptype)
 -{
 -	/*
 -	 * ICMP types marked with PF_OUT are typically responses to
 -	 * PF_IN, and will match states in the opposite direction.
 -	 * PF_IN ICMP types need to match a state with that type.
 -	 */
 -	*icmp_dir = PF_OUT;
 -	*multi = PF_ICMP_MULTI_LINK;
 -	/* Queries (and responses) */
 -	switch (type) {
 -	case ICMP_ECHO:
 -		*icmp_dir = PF_IN;
 -	case ICMP_ECHOREPLY:
 -		*icmptype = ICMP_ECHO;
 -		*icmpid = pd->hdr.icmp->icmp_id;
 -		break;
 -
 -	case ICMP_TSTAMP:
 -		*icmp_dir = PF_IN;
 -	case ICMP_TSTAMPREPLY:
 -		*icmptype = ICMP_TSTAMP;
 -		*icmpid = pd->hdr.icmp->icmp_id;
 -		break;
 -
 -	case ICMP_IREQ:
 -		*icmp_dir = PF_IN;
 -	case ICMP_IREQREPLY:
 -		*icmptype = ICMP_IREQ;
 -		*icmpid = pd->hdr.icmp->icmp_id;
 -		break;
 -
 -	case ICMP_MASKREQ:
 -		*icmp_dir = PF_IN;
 -	case ICMP_MASKREPLY:
 -		*icmptype = ICMP_MASKREQ;
 -		*icmpid = pd->hdr.icmp->icmp_id;
 -		break;
 -
 -	case ICMP_IPV6_WHEREAREYOU:
 -		*icmp_dir = PF_IN;
 -	case ICMP_IPV6_IAMHERE:
 -		*icmptype = ICMP_IPV6_WHEREAREYOU;
 -		*icmpid = 0; /* Nothing sane to match on! */
 -		break;
 -
 -	case ICMP_MOBILE_REGREQUEST:
 -		*icmp_dir = PF_IN;
 -	case ICMP_MOBILE_REGREPLY:
 -		*icmptype = ICMP_MOBILE_REGREQUEST;
 -		*icmpid = 0; /* Nothing sane to match on! */
 -		break;
 -
 -	case ICMP_ROUTERSOLICIT:
 -		*icmp_dir = PF_IN;
 -	case ICMP_ROUTERADVERT:
 -		*icmptype = ICMP_MOBILE_REGREQUEST;
 -		*icmpid = 0; /* Nothing sane to match on! */
 -		break;
 -
 -#ifdef INET6
 -	case ICMP6_ECHO_REQUEST:
 -		*icmp_dir = PF_IN;
 -	case ICMP6_ECHO_REPLY:
 -		*icmptype = ICMP6_ECHO_REPLY;
 -		*icmpid = 0; /* Nothing sane to match on! */
 -		break;
 -
 -	case MLD_LISTENER_QUERY:
 -		*icmp_dir = PF_IN;
 -	case MLD_LISTENER_REPORT: {
 -		struct mld_hdr *mld = (void *)pd->hdr.icmp6;
 -
 -		*icmptype = MLD_LISTENER_QUERY;
 -		/* generate fake id for these messages */
 -		*icmpid = (mld->mld_addr.s6_addr32[0] ^
 -			mld->mld_addr.s6_addr32[1] ^
 -			mld->mld_addr.s6_addr32[2] ^
 -			mld->mld_addr.s6_addr32[3]) & 0xffff;
 -		break;
 -	}
 -
 -	/* ICMP6_FQDN and ICMP6_NI query/reply are the same type as ICMP6_WRU */
 -	case ICMP6_WRUREQUEST:
 -		*icmp_dir = PF_IN;
 -	case ICMP6_WRUREPLY:
 -		*icmptype = ICMP6_WRUREQUEST;
 -		*icmpid = 0; /* Nothing sane to match on! */
 -		break;
 -
 -	case MLD_MTRACE:
 -		*icmp_dir = PF_IN;
 -	case MLD_MTRACE_RESP:
 -		*icmptype = MLD_MTRACE;
 -		*icmpid = 0; /* Nothing sane to match on! */
 -		break;
 -
 -	case ND_NEIGHBOR_SOLICIT:
 -		*icmp_dir = PF_IN;
 -	case ND_NEIGHBOR_ADVERT: {
 -		struct nd_neighbor_solicit *nd = (void *)pd->hdr.icmp6;
 -
 -		*icmptype = ND_NEIGHBOR_SOLICIT;
 -		*multi = PF_ICMP_MULTI_SOLICITED;
 -		/* generate fake id for these messages */
 -		*icmpid = (nd->nd_ns_target.s6_addr32[0] ^
 -			nd->nd_ns_target.s6_addr32[1] ^
 -			nd->nd_ns_target.s6_addr32[2] ^
 -			nd->nd_ns_target.s6_addr32[3]) & 0xffff;
 -		break;
 -	}
 -
 -#endif /* INET6 */
 -	/* These ICMP types map to other connections */
 -	case ICMP_UNREACH:
 -	case ICMP_SOURCEQUENCH:
 -	case ICMP_REDIRECT:
 -	case ICMP_TIMXCEED:
 -	case ICMP_PARAMPROB:
 -#ifdef INET6
 -	/*
 -	 * ICMP6_TIME_EXCEEDED is the same type as ICMP_UNREACH
 -	 * ND_REDIRECT can't be in this list because the triggering packet
 -	 * header is optional.
 -	 */
 -	case ICMP6_PACKET_TOO_BIG:
 -#endif /* INET6 */
 -		/* These will not be used, but set them anyways */
 -		*icmp_dir = PF_IN;
 -		*icmptype = htons(type);
 -		*icmpid = 0;
 -		return (1);	/* These types are matched to other state */
 -	/*
 -	 * All remaining ICMP types get their own states,
 -	 * and will only match in one direction.
 -	 */
 -	default:
 -		*icmp_dir = PF_IN;
 -		*icmptype = type;
 -		*icmpid = 0;
 -		break;
 -	}
 -	*icmptype = htons(*icmptype);
 -
 -	return (0);
 -}
 -
  static void
  pf_change_icmp(struct pf_addr *ia, u_int16_t *ip, struct pf_addr *oa,
      struct pf_addr *na, u_int16_t np, u_int16_t *pc, u_int16_t *h2c,
 @@ -3180,8 +3023,8 @@ pf_test_rule(struct pf_rule **rm, struct
  	int			 tag = -1, rtableid = -1;
  	int			 asd = 0;
  	int			 match = 0;
 -	int			 state_icmp = 0, icmp_dir, multi;
 -	uint16_t		 sport = 0 , dport = 0, virtual_type = 0, virtual_id = 0;
 +	int			 state_icmp = 0;
 +	u_int16_t		 sport = 0, dport = 0;
  	u_int16_t		 bproto_sum = 0, bip_sum = 0;
  	u_int8_t		 icmptype = 0, icmpcode = 0;
  	struct pf_anchor_stackframe	anchor_stack[PF_ANCHOR_STACKSIZE];
 @@ -3210,38 +3053,33 @@ pf_test_rule(struct pf_rule **rm, struct
  	case IPPROTO_ICMP:
  		if (pd->af != AF_INET)
  			break;
 +		sport = dport = pd->hdr.icmp->icmp_id;
  		hdrlen = sizeof(*pd->hdr.icmp);
  		icmptype = pd->hdr.icmp->icmp_type;
  		icmpcode = pd->hdr.icmp->icmp_code;
  
 -		state_icmp = pf_icmp_mapping(pd, icmptype,
 -		    &icmp_dir, &multi, &virtual_id, &virtual_type);
 -		if (icmp_dir == PF_IN) {
 -			sport = virtual_id;
 -			dport = virtual_type;
 -		} else {
 -			sport = virtual_type;
 -			dport = virtual_id;
 -		}
 +		if (icmptype == ICMP_UNREACH ||
 +		    icmptype == ICMP_SOURCEQUENCH ||
 +		    icmptype == ICMP_REDIRECT ||
 +		    icmptype == ICMP_TIMXCEED ||
 +		    icmptype == ICMP_PARAMPROB)
 +			state_icmp++;
  		break;
  #endif /* INET */
  #ifdef INET6
  	case IPPROTO_ICMPV6:
  		if (af != AF_INET6)
  			break;
 +		sport = dport = pd->hdr.icmp6->icmp6_id;
  		hdrlen = sizeof(*pd->hdr.icmp6);
  		icmptype = pd->hdr.icmp6->icmp6_type;
  		icmpcode = pd->hdr.icmp6->icmp6_code;
  
 -		state_icmp = pf_icmp_mapping(pd, icmptype,
 -		    &icmp_dir, &multi, &virtual_id, &virtual_type);
 -		if (icmp_dir == PF_IN) {
 -			sport = virtual_id;
 -			dport = virtual_type;
 -		} else {
 -			sport = virtual_type;
 -			dport = virtual_id;
 -		}
 +		if (icmptype == ICMP6_DST_UNREACH ||
 +		    icmptype == ICMP6_PACKET_TOO_BIG ||
 +		    icmptype == ICMP6_TIME_EXCEEDED ||
 +		    icmptype == ICMP6_PARAM_PROB)
 +			state_icmp++;
  		break;
  #endif /* INET6 */
  	default:
 @@ -3311,6 +3149,7 @@ pf_test_rule(struct pf_rule **rm, struct
  			break;
  #ifdef INET
  		case IPPROTO_ICMP:
 +			nk->port[0] = nk->port[1];
  			if (PF_ANEQ(saddr, &nk->addr[pd->sidx], AF_INET))
  				pf_change_a(&saddr->v4.s_addr, pd->ip_sum,
  				    nk->addr[pd->sidx].v4.s_addr, 0);
 @@ -3319,12 +3158,11 @@ pf_test_rule(struct pf_rule **rm, struct
  				pf_change_a(&daddr->v4.s_addr, pd->ip_sum,
  				    nk->addr[pd->didx].v4.s_addr, 0);
  
 -			if (virtual_type == ICMP_ECHO &&
 -			     nk->port[pd->sidx] != pd->hdr.icmp->icmp_id) {
 +			if (nk->port[1] != pd->hdr.icmp->icmp_id) {
  				pd->hdr.icmp->icmp_cksum = pf_cksum_fixup(
  				    pd->hdr.icmp->icmp_cksum, sport,
 -				    nk->port[pd->sidx], 0);
 -				pd->hdr.icmp->icmp_id = nk->port[pd->sidx];
 +				    nk->port[1], 0);
 +				pd->hdr.icmp->icmp_id = nk->port[1];
  				pd->sport = &pd->hdr.icmp->icmp_id;
  			}
  			m_copyback(m, off, ICMP_MINLEN, (caddr_t)pd->hdr.icmp);
 @@ -4546,69 +4384,13 @@ pf_test_state_udp(struct pf_state **stat
  }
  
  static int
 -pf_icmp_state_lookup(struct pf_state_key_cmp *key, struct pf_pdesc *pd,
 -    struct pf_state **state, struct mbuf *m, int direction, struct pfi_kif *kif,
 -    uint16_t icmpid, uint16_t type, int icmp_dir, int *iidx, int multi)
 -{
 -
 -	key->af = pd->af;
 -	key->proto = pd->proto;
 -	if (icmp_dir == PF_IN) {
 -		*iidx = pd->sidx;
 -		key->port[pd->sidx] = icmpid;
 -		key->port[pd->didx] = type;
 -	} else {
 -		*iidx = pd->didx;
 -		key->port[pd->sidx] = type;
 -		key->port[pd->didx] = icmpid;
 -	}
 -#ifdef INET6
 -	if (pd->af == AF_INET6 && multi != PF_ICMP_MULTI_NONE) {
 -		switch (multi) {
 -		case PF_ICMP_MULTI_SOLICITED:
 -			key->addr[pd->sidx].addr32[0] = IPV6_ADDR_INT32_MLL;
 -			key->addr[pd->sidx].addr32[1] = 0;
 -			key->addr[pd->sidx].addr32[2] = IPV6_ADDR_INT32_ONE;
 -			key->addr[pd->sidx].addr32[3] = pd->src->addr32[3];
 -			key->addr[pd->sidx].addr8[12] = 0xff;
 -			break;
 -		case PF_ICMP_MULTI_LINK:
 -			key->addr[pd->sidx].addr32[0] = IPV6_ADDR_INT32_MLL;
 -			key->addr[pd->sidx].addr32[1] = 0;
 -			key->addr[pd->sidx].addr32[2] = 0;
 -			key->addr[pd->sidx].addr32[3] = IPV6_ADDR_INT32_ONE;
 -			break;
 -		}
 -	} else
 -#endif
 -		PF_ACPY(&key->addr[pd->sidx], pd->src, key->af);
 -	PF_ACPY(&key->addr[pd->didx], pd->dst, key->af);
 -
 -	STATE_LOOKUP(kif, key, direction, *state, pd);
 -
 -	/* Is this ICMP message flowing in right direction? */
 -	if ((*state)->rule.ptr->type &&
 -	    (((*state)->direction == direction) ?
 -	    PF_IN : PF_OUT) != icmp_dir) {
 -		if (V_pf_status.debug >= PF_DEBUG_MISC) {
 -			printf("pf: icmp type %d in wrong direction (%d): ",
 -			    icmp_dir, direction);
 -			pf_print_state(*state);
 -			printf("\n");
 -		}
 -		return (PF_DROP);
 -	}
 -	return (-1);
 -}
 -
 -static int
  pf_test_state_icmp(struct pf_state **state, int direction, struct pfi_kif *kif,
      struct mbuf *m, int off, void *h, struct pf_pdesc *pd, u_short *reason)
  {
  	struct pf_addr  *saddr = pd->src, *daddr = pd->dst;
 -	u_int16_t	 icmpid = 0, *icmpsum, virtual_id, virtual_type;
 +	u_int16_t	 icmpid = 0, *icmpsum;
  	u_int8_t	 icmptype;
 -	int		 icmp_dir, iidx, ret, multi;
 +	int		 state_icmp = 0;
  	struct pf_state_key_cmp key;
  
  	bzero(&key, sizeof(key));
 @@ -4619,6 +4401,12 @@ pf_test_state_icmp(struct pf_state **sta
  		icmpid = pd->hdr.icmp->icmp_id;
  		icmpsum = &pd->hdr.icmp->icmp_cksum;
  
 +		if (icmptype == ICMP_UNREACH ||
 +		    icmptype == ICMP_SOURCEQUENCH ||
 +		    icmptype == ICMP_REDIRECT ||
 +		    icmptype == ICMP_TIMXCEED ||
 +		    icmptype == ICMP_PARAMPROB)
 +			state_icmp++;
  		break;
  #endif /* INET */
  #ifdef INET6
 @@ -4627,35 +4415,34 @@ pf_test_state_icmp(struct pf_state **sta
  		icmpid = pd->hdr.icmp6->icmp6_id;
  		icmpsum = &pd->hdr.icmp6->icmp6_cksum;
  
 +		if (icmptype == ICMP6_DST_UNREACH ||
 +		    icmptype == ICMP6_PACKET_TOO_BIG ||
 +		    icmptype == ICMP6_TIME_EXCEEDED ||
 +		    icmptype == ICMP6_PARAM_PROB)
 +			state_icmp++;
  		break;
  #endif /* INET6 */
 -	default:
 -		panic("%s: proto %d\n", __func__, pd->proto);
  	}
  
 -	if (pf_icmp_mapping(pd, icmptype, &icmp_dir, &multi,
 -	    &virtual_id, &virtual_type) == 0) {
 +	if (!state_icmp) {
 +
  		/*
  		 * ICMP query/reply message not related to a TCP/UDP packet.
  		 * Search for an ICMP state.
  		 */
 -		ret = pf_icmp_state_lookup(&key, pd, state, m, direction,
 -		    kif, virtual_id, virtual_type, icmp_dir, &iidx,
 -		    PF_ICMP_MULTI_NONE);
 -		if (ret >= 0) {
 -			if (ret == PF_DROP && pd->af == AF_INET6 &&
 -			    icmp_dir == PF_OUT) {
 -				if (*state)
 -					PF_STATE_UNLOCK(*state);
 -				ret = pf_icmp_state_lookup(&key, pd, state, m,
 -				    direction, kif, virtual_id, virtual_type,
 -				    icmp_dir, &iidx, multi);
 -				if (ret >= 0)
 -					return (ret);
 -			} else
 -				return (ret);
 +		key.af = pd->af;
 +		key.proto = pd->proto;
 +		key.port[0] = key.port[1] = icmpid;
 +		if (direction == PF_IN)	{	/* wire side, straight */
 +			PF_ACPY(&key.addr[0], pd->src, key.af);
 +			PF_ACPY(&key.addr[1], pd->dst, key.af);
 +		} else {			/* stack side, reverse */
 +			PF_ACPY(&key.addr[1], pd->src, key.af);
 +			PF_ACPY(&key.addr[0], pd->dst, key.af);
  		}
  
 +		STATE_LOOKUP(kif, &key, direction, *state, pd);
 +
  		(*state)->expire = time_uptime;
  		(*state)->timeout = PFTM_ICMP_ERROR_REPLY;
  
 @@ -4678,13 +4465,14 @@ pf_test_state_icmp(struct pf_state **sta
  					    pd->ip_sum,
  					    nk->addr[pd->didx].v4.s_addr, 0);
  
 -				if (nk->port[iidx] !=
 +				if (nk->port[0] !=
  				    pd->hdr.icmp->icmp_id) {
  					pd->hdr.icmp->icmp_cksum =
  					    pf_cksum_fixup(
  					    pd->hdr.icmp->icmp_cksum, icmpid,
 -					    nk->port[iidx], 0);
 -					pd->hdr.icmp->icmp_id = nk->port[iidx];
 +					    nk->port[pd->sidx], 0);
 +					pd->hdr.icmp->icmp_id =
 +					    nk->port[pd->sidx];
  				}
  
  				m_copyback(m, off, ICMP_MINLEN,
 @@ -5034,15 +4822,13 @@ pf_test_state_icmp(struct pf_state **sta
  				return (PF_DROP);
  			}
  
 -			pd2.hdr.icmp = &iih;
 -			pf_icmp_mapping(&pd2, iih.icmp_type,
 -			    &icmp_dir, &multi, &virtual_id, &virtual_type);
 -
 -			ret = pf_icmp_state_lookup(&key, &pd2, state, m,
 -			    direction, kif, virtual_id, virtual_type,
 -			    icmp_dir, &iidx, PF_ICMP_MULTI_NONE);
 -			if (ret >= 0)
 -				return (ret);
 +			key.af = pd2.af;
 +			key.proto = IPPROTO_ICMP;
 +			PF_ACPY(&key.addr[pd2.sidx], pd2.src, key.af);
 +			PF_ACPY(&key.addr[pd2.didx], pd2.dst, key.af);
 +			key.port[0] = key.port[1] = iih.icmp_id;
 +
 +			STATE_LOOKUP(kif, &key, direction, *state, pd);
  
  			/* translate source/destination address, if necessary */
  			if ((*state)->key[PF_SK_WIRE] !=
 @@ -5052,20 +4838,20 @@ pf_test_state_icmp(struct pf_state **sta
  
  				if (PF_ANEQ(pd2.src,
  				    &nk->addr[pd2.sidx], pd2.af) ||
 -				    (virtual_type == ICMP_ECHO &&
 -				    nk->port[iidx] != iih.icmp_id))
 -					pf_change_icmp(pd2.src,
 -					    (virtual_type == ICMP_ECHO) ?
 -					    &iih.icmp_id : NULL,
 +				    nk->port[pd2.sidx] != iih.icmp_id)
 +					pf_change_icmp(pd2.src, &iih.icmp_id,
  					    daddr, &nk->addr[pd2.sidx],
  					    nk->port[pd2.sidx], NULL,
  					    pd2.ip_sum, icmpsum,
  					    pd->ip_sum, 0, AF_INET);
  
  				if (PF_ANEQ(pd2.dst,
 -				    &nk->addr[pd2.didx], pd2.af))
 -                                       pf_change_icmp(pd2.dst, NULL, NULL,
 -					    &nk->addr[pd2.didx], 0, NULL,
 +				    &nk->addr[pd2.didx], pd2.af) ||
 +				    nk->port[pd2.didx] != iih.icmp_id)
 +					pf_change_icmp(pd2.dst, &iih.icmp_id,
 +					    NULL, /* XXX Inbound NAT? */
 +					    &nk->addr[pd2.didx],
 +					    nk->port[pd2.didx], NULL,
  					    pd2.ip_sum, icmpsum,
  					    pd->ip_sum, 0, AF_INET);
  
 @@ -5089,26 +4875,13 @@ pf_test_state_icmp(struct pf_state **sta
  				return (PF_DROP);
  			}
  
 -			pd2.hdr.icmp6 = &iih;
 -			pf_icmp_mapping(&pd2, iih.icmp6_type,
 -			    &icmp_dir, &multi, &virtual_id, &virtual_type);
 -			ret = pf_icmp_state_lookup(&key, &pd2, state, m,
 -			    direction, kif, virtual_id, virtual_type,
 -			    icmp_dir, &iidx, PF_ICMP_MULTI_NONE);
 -			if (ret >= 0) {
 -				if (ret == PF_DROP && pd->af == AF_INET6 &&
 -				    icmp_dir == PF_OUT) {
 -					if (*state)
 -						PF_STATE_UNLOCK(*state);
 -					ret = pf_icmp_state_lookup(&key, pd,
 -					    state, m, direction, kif,
 -					    virtual_id, virtual_type,
 -					    icmp_dir, &iidx, multi);
 -					if (ret >= 0)
 -						return (ret);
 -				} else
 -					return (ret);
 -			}
 +			key.af = pd2.af;
 +			key.proto = IPPROTO_ICMPV6;
 +			PF_ACPY(&key.addr[pd2.sidx], pd2.src, key.af);
 +			PF_ACPY(&key.addr[pd2.didx], pd2.dst, key.af);
 +			key.port[0] = key.port[1] = iih.icmp6_id;
 +
 +			STATE_LOOKUP(kif, &key, direction, *state, pd);
  
  			/* translate source/destination address, if necessary */
  			if ((*state)->key[PF_SK_WIRE] !=
 @@ -5118,21 +4891,20 @@ pf_test_state_icmp(struct pf_state **sta
  
  				if (PF_ANEQ(pd2.src,
  				    &nk->addr[pd2.sidx], pd2.af) ||
 -			 	    ((virtual_type == ICMP6_ECHO_REQUEST) &&
 -				    nk->port[pd2.sidx] != iih.icmp6_id))
 -					pf_change_icmp(pd2.src,
 -					    (virtual_type == ICMP6_ECHO_REQUEST)
 -					    ? &iih.icmp6_id : NULL,
 +				    nk->port[pd2.sidx] != iih.icmp6_id)
 +					pf_change_icmp(pd2.src, &iih.icmp6_id,
  					    daddr, &nk->addr[pd2.sidx],
 -					    (virtual_type == ICMP6_ECHO_REQUEST)
 -					    ? nk->port[iidx] : 0, NULL,
 +					    nk->port[pd2.sidx], NULL,
  					    pd2.ip_sum, icmpsum,
  					    pd->ip_sum, 0, AF_INET6);
  
  				if (PF_ANEQ(pd2.dst,
 -				    &nk->addr[pd2.didx], pd2.af))
 -					pf_change_icmp(pd2.dst, NULL, NULL,
 -					    &nk->addr[pd2.didx], 0, NULL,
 +				    &nk->addr[pd2.didx], pd2.af) ||
 +				    nk->port[pd2.didx] != iih.icmp6_id)
 +					pf_change_icmp(pd2.dst, &iih.icmp6_id,
 +					    NULL, /* XXX Inbound NAT? */
 +					    &nk->addr[pd2.didx],
 +					    nk->port[pd2.didx], NULL,
  					    pd2.ip_sum, icmpsum,
  					    pd->ip_sum, 0, AF_INET6);
  
 @@ -6455,32 +6227,10 @@ pf_test6(int dir, struct ifnet *ifp, str
  	}
  
  	case IPPROTO_ICMPV6: {
 -		union {
 -			struct icmp6_hdr		icmp6;
 -			struct mld_hdr			mld;
 -			struct nd_neighbor_solicit	nd;
 -		} ih;
 -		size_t	icmp_hlen = sizeof(struct icmp6_hdr);
 +		struct icmp6_hdr	ih;
  
 -		pd.hdr.icmp6 = &ih.icmp6;
 -		if (!pf_pull_hdr(m, off, &ih, icmp_hlen,
 -		    &action, &reason, AF_INET6)) {
 -			log = action != PF_PASS;
 -			goto done;
 -		}
 -		/* ICMP headers we look further into to match state */
 -		switch (ih.icmp6.icmp6_type) {
 -		case MLD_LISTENER_QUERY:
 -		case MLD_LISTENER_REPORT:
 -			icmp_hlen = sizeof(struct mld_hdr);
 -			break;
 -		case ND_NEIGHBOR_SOLICIT:
 -		case ND_NEIGHBOR_ADVERT:
 -			icmp_hlen = sizeof(struct nd_neighbor_solicit);
 -			break;
 -		}
 -		if (icmp_hlen > sizeof(struct icmp6_hdr) &&
 -		    !pf_pull_hdr(m, off, &ih, icmp_hlen,
 +		pd.hdr.icmp6 = &ih;
 +		if (!pf_pull_hdr(m, off, &ih, sizeof(ih),
  		    &action, &reason, AF_INET6)) {
  			log = action != PF_PASS;
  			goto done;
 
 Modified: head/sys/netpfil/pf/pf_lb.c
 ==============================================================================
 --- head/sys/netpfil/pf/pf_lb.c	Wed Apr 16 05:31:54 2014	(r264520)
 +++ head/sys/netpfil/pf/pf_lb.c	Wed Apr 16 09:25:20 2014	(r264521)
 @@ -53,15 +53,6 @@ __FBSDID("$FreeBSD$");
  #include <net/pfvar.h>
  #include <net/if_pflog.h>
  
 -#include <netinet/in.h>
 -#include <netinet/ip.h>
 -#include <netinet/ip_icmp.h>
 -
 -#ifdef INET6
 -#include <netinet/ip6.h>
 -#include <netinet/icmp6.h>
 -#endif
 -
  #define DPFPRINTF(n, x)	if (V_pf_status.debug >= (n)) printf x
  
  static void		 pf_hash(struct pf_addr *, struct pf_addr *,
 @@ -232,21 +223,9 @@ pf_get_sport(sa_family_t af, u_int8_t pr
  	if (pf_map_addr(af, r, saddr, naddr, &init_addr, sn))
  		return (1);
  
 -	switch (proto) {
 -	case IPPROTO_ICMP:
 -		if (dport != htons(ICMP_ECHO))
 -			return (0);
 -		low = 1;
 -		high = 65535;
 -		break;
 -#ifdef INET6
 -	case IPPROTO_ICMPV6:
 -		if (dport != htons(ICMP6_ECHO_REQUEST))
 -			return (0);
 +	if (proto == IPPROTO_ICMP) {
  		low = 1;
  		high = 65535;
 -		break;
 -#endif
  	}
  
  	bzero(&key, sizeof(key));
 _______________________________________________
 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"
 
>Unformatted:
