Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 12 Jan 2014 00:24:33 +0200
From:      Guy Yur <guyyur@gmail.com>
To:        freebsd-net@freebsd.org, freebsd-arm@freebsd.org
Subject:   Re: 10.0-RC1, armv6: "pfctl -s state" crashes on BeagleBone Black due to unaligned access
Message-ID:  <CAC67Hz9Z5xv_m9F0WY5OZAFaFsuUNXtKx5gpTBpGipfn2ArYkg@mail.gmail.com>

index | next in thread | raw e-mail

[-- Attachment #1 --]
Hi,

New patch that adds new aligned state structs and new ioctls.

A trade-off of allowing correct alignment and improved speed for
architectures that require alignment at the cost of extra maintenance
when the state structs need to be extended.

I duplicated the structs pfsync_state_scrub, pfsync_state_peer,
pfsync_state_key and pfsync_state as non __packed structures.
(pfsync_state_key is not marked as __packed, should it be?)

pfsync_state_export also duplicated for the new struct.

In the new state struct I reordered creatorid before the packets array
to keep alignment on 8 bytes.
packets and bytes converted to u_int64_t instead of array of u_int32_t
(they are u_int64_t in the internal pf_state).

sizeof(struct pf_addr) = 16;              16 % 4 = 0
sizeof(struct pfioc_state2_scrub) = 8;    8 % 4 = 0
sizeof(struct pfioc_state2_peer) = 28;    28 % 4 = 0
sizeof(struct pfioc_state2_key) = 36;     36 % 4 = 0
sizeof(struct pfioc_state2) = 232;        232 % 8 = 0

offsetof(struct pfioc_state2, src) = 96;         96 % 4 = 0
offsetof(struct pfioc_state2, dst) = 124;        124 % 4 = 0
offsetof(struct pfioc_state2, rt_addr) = 152;    152 % 4 = 0
offsetof(struct pfioc_state2, rule) = 168;       168 % 4 = 0
offsetof(struct pfioc_state2, packets) = 192;    192 % 8 = 0

The export for the new struct is done in host byte order which is used
by the internal pf_state structure (except for pf_addr, id and creatorid
which are kept in network order).

I didn't bother creating a new version of DIOCADDSTATE since it is only
used for pfsync and it receives only one pfioc_state / pfsync_state.


Tested both of the new ioctls on the BeagleBone Black by modifying pfctl
to also issue the single state ioctl with the (id,creatorid) of the last
entry found in the print loop.

I am not sure about the new structs and ioctls naming and there might
be style bugs.


Also attached a patch to constify the print functions in pfctl if there
is interest in that.  Needs to be applied after the new structs patch.


P.S.
Are alignment traps disabled on the Raspberry Pi?
I wasn't able to cause a user space crash on the Pi with unaligned access.


Regards,
Guy

[-- Attachment #2 --]
Index: sys/net/pfvar.h
===================================================================
--- sys/net/pfvar.h	(revision 260492)
+++ sys/net/pfvar.h	(working copy)
@@ -943,6 +943,23 @@ extern pflog_packet_t		*pflog_packet_ptr;
 	}								\
 } while (0)
 
+#define pf_state_peer_htoh(s,d) do {		\
+	(d)->seqlo = (s)->seqlo;		\
+	(d)->seqhi = (s)->seqhi;		\
+	(d)->seqdiff = (s)->seqdiff;		\
+	(d)->max_win = (s)->max_win;		\
+	(d)->mss = (s)->mss;			\
+	(d)->state = (s)->state;		\
+	(d)->wscale = (s)->wscale;		\
+	if ((s)->scrub) {						\
+		(d)->scrub.pfss_flags = 				\
+		    (s)->scrub->pfss_flags & PFSS_TIMESTAMP;		\
+		(d)->scrub.pfss_ttl = (s)->scrub->pfss_ttl;		\
+		(d)->scrub.pfss_ts_mod = (s)->scrub->pfss_ts_mod;	\
+		(d)->scrub.scrub_flag = PFSYNC_SCRUB_FLAG_VALID;	\
+	}								\
+} while (0)
+
 #define pf_state_counter_hton(s,d) do {				\
 	d[0] = htonl((s>>32)&0xffffffff);			\
 	d[1] = htonl(s&0xffffffff);				\
@@ -1440,6 +1457,55 @@ struct pfioc_state {
 	struct pfsync_state	state;
 };
 
+struct pfioc_state2_scrub {
+	u_int16_t	pfss_flags;
+	u_int8_t	pfss_ttl;	/* stashed TTL		*/
+#define PFIOC_SCRUB_FLAG_VALID		PFSYNC_SCRUB_FLAG_VALID
+	u_int8_t	scrub_flag;
+	u_int32_t	pfss_ts_mod;	/* timestamp modulation	*/
+};
+
+struct pfioc_state2_peer {
+	struct pfioc_state2_scrub scrub;	/* state is scrubbed	*/
+	u_int32_t	seqlo;		/* Max sequence number sent	*/
+	u_int32_t	seqhi;		/* Max the other end ACKd + win	*/
+	u_int32_t	seqdiff;	/* Sequence number modulator	*/
+	u_int16_t	max_win;	/* largest window (pre scaling)	*/
+	u_int16_t	mss;		/* Maximum segment size option	*/
+	u_int8_t	state;		/* active state level		*/
+	u_int8_t	wscale;		/* window scaling factor	*/
+};
+
+struct pfioc_state2_key {
+	struct pf_addr	 addr[2];
+	u_int16_t	 port[2];
+};
+
+struct pfioc_state2 {
+	u_int64_t	 id;
+	char		 ifname[IFNAMSIZ];
+	struct pfioc_state2_key	key[2];
+	struct pfioc_state2_peer src;
+	struct pfioc_state2_peer dst;
+	struct pf_addr	 rt_addr;
+	u_int32_t	 rule;
+	u_int32_t	 anchor;
+	u_int32_t	 nat_rule;
+	u_int32_t	 creation;
+	u_int32_t	 expire;
+	u_int32_t	 creatorid;
+	u_int64_t	 packets[2];
+	u_int64_t	 bytes[2];
+	sa_family_t	 af;
+	u_int8_t	 proto;
+	u_int8_t	 direction;
+	u_int8_t	 log;
+	u_int8_t	 state_flags;
+	u_int8_t	 timeout;
+	u_int8_t	 sync_flags;
+	u_int8_t	 updates;
+};
+
 struct pfioc_src_node_kill {
 	sa_family_t psnk_af;
 	struct pf_rule_addr psnk_src;
@@ -1468,6 +1534,14 @@ struct pfioc_states {
 #define ps_states	ps_u.psu_states
 };
 
+struct pfioc_states2 {
+	int	ps_len;
+	union {
+		caddr_t			 psu_buf;
+		struct pfioc_state2	*psu_states;
+	} ps_u;
+};
+
 struct pfioc_src_nodes {
 	int	psn_len;
 	union {
@@ -1642,6 +1716,8 @@ struct pf_ifspeed {
 	u_int32_t		baudrate;
 };
 #define	DIOCGIFSPEED	_IOWR('D', 92, struct pf_ifspeed)
+#define DIOCGETSTATE2	_IOWR('D', 93, struct pfioc_state2)
+#define DIOCGETSTATES2	_IOWR('D', 94, struct pfioc_states2)
 
 #ifdef _KERNEL
 struct pf_srchash {
Index: sys/netpfil/pf/pf_ioctl.c
===================================================================
--- sys/netpfil/pf/pf_ioctl.c	(revision 260492)
+++ sys/netpfil/pf/pf_ioctl.c	(working copy)
@@ -108,6 +108,8 @@ static int		 pf_commit_rules(u_int32_t, int, char
 static int		 pf_addr_setup(struct pf_ruleset *,
 			    struct pf_addr_wrap *, sa_family_t);
 static void		 pf_addr_copyout(struct pf_addr_wrap *);
+static void		 pfioc_state2_export(struct pfioc_state2 *sp,
+			    struct pf_state *st);
 
 VNET_DEFINE(struct pf_rule,	pf_default_rule);
 
@@ -1003,6 +1005,8 @@ pfioctl(struct cdev *dev, u_long cmd, caddr_t addr
 		case DIOCGIFSPEED:
 		case DIOCSETIFFLAG:
 		case DIOCCLRIFFLAG:
+		case DIOCGETSTATE2:
+		case DIOCGETSTATES2:
 			break;
 		case DIOCRCLRTABLES:
 		case DIOCRADDTABLES:
@@ -1041,6 +1045,8 @@ pfioctl(struct cdev *dev, u_long cmd, caddr_t addr
 		case DIOCGETSRCNODES:
 		case DIOCIGETIFACES:
 		case DIOCGIFSPEED:
+		case DIOCGETSTATE2:
+		case DIOCGETSTATES2:
 			break;
 		case DIOCRCLRTABLES:
 		case DIOCRADDTABLES:
@@ -1758,6 +1764,68 @@ DIOCGETSTATES_full:
 		break;
 	}
 
+	case DIOCGETSTATE2: {
+		struct pfioc_state2	*ps = (struct pfioc_state2 *)addr;
+		struct pf_state		*s;
+
+		s = pf_find_state_byid(ps->id, ps->creatorid);
+		if (s == NULL) {
+			error = ENOENT;
+			break;
+		}
+
+		pfioc_state2_export(ps, s);
+		PF_STATE_UNLOCK(s);
+		break;
+	}
+
+	case DIOCGETSTATES2: {
+		struct pfioc_states2	*ps = (struct pfioc_states2 *)addr;
+		struct pf_state		*s;
+		struct pfioc_state2	*pstore, *p;
+		int i, nr;
+
+		if (ps->ps_len == 0) {
+			nr = uma_zone_get_cur(V_pf_state_z);
+			ps->ps_len = sizeof(struct pfioc_state2) * nr;
+			break;
+		}
+
+		p = pstore = malloc(ps->ps_len, M_TEMP, M_WAITOK);
+		nr = 0;
+
+		for (i = 0; i <= V_pf_hashmask; i++) {
+			struct pf_idhash *ih = &V_pf_idhash[i];
+
+			PF_HASHROW_LOCK(ih);
+			LIST_FOREACH(s, &ih->states, entry) {
+
+				if (s->timeout == PFTM_UNLINKED)
+					continue;
+
+				if ((nr+1) * sizeof(*p) > ps->ps_len) {
+					PF_HASHROW_UNLOCK(ih);
+					goto DIOCGETSTATES2_full;
+				}
+				pfioc_state2_export(p, s);
+				p++;
+				nr++;
+			}
+			PF_HASHROW_UNLOCK(ih);
+		}
+DIOCGETSTATES2_full:
+		error = copyout(pstore, ps->ps_states,
+		    sizeof(struct pfioc_state2) * nr);
+		if (error) {
+			free(pstore, M_TEMP);
+			break;
+		}
+		ps->ps_len = sizeof(struct pfioc_state2) * nr;
+		free(pstore, M_TEMP);
+
+		break;
+	}
+
 	case DIOCGETSTATUS: {
 		struct pf_status *s = (struct pf_status *)addr;
 		PF_RULES_RLOCK();
@@ -3308,6 +3376,66 @@ pfsync_state_export(struct pfsync_state *sp, struc
 }
 
 static void
+pfioc_state2_export(struct pfioc_state2 *sp, struct pf_state *st)
+{
+	bzero(sp, sizeof(struct pfioc_state2));
+
+	/* copy from state key */
+	sp->key[PF_SK_WIRE].addr[0] = st->key[PF_SK_WIRE]->addr[0];
+	sp->key[PF_SK_WIRE].addr[1] = st->key[PF_SK_WIRE]->addr[1];
+	sp->key[PF_SK_WIRE].port[0] = st->key[PF_SK_WIRE]->port[0];
+	sp->key[PF_SK_WIRE].port[1] = st->key[PF_SK_WIRE]->port[1];
+	sp->key[PF_SK_STACK].addr[0] = st->key[PF_SK_STACK]->addr[0];
+	sp->key[PF_SK_STACK].addr[1] = st->key[PF_SK_STACK]->addr[1];
+	sp->key[PF_SK_STACK].port[0] = st->key[PF_SK_STACK]->port[0];
+	sp->key[PF_SK_STACK].port[1] = st->key[PF_SK_STACK]->port[1];
+	sp->proto = st->key[PF_SK_WIRE]->proto;
+	sp->af = st->key[PF_SK_WIRE]->af;
+
+	/* copy from state */
+	strlcpy(sp->ifname, st->kif->pfik_name, sizeof(sp->ifname));
+	bcopy(&st->rt_addr, &sp->rt_addr, sizeof(sp->rt_addr));
+	sp->creation = time_uptime - st->creation;
+	sp->expire = pf_state_expires(st);
+	if (sp->expire <= time_uptime)
+		sp->expire = 0;
+	else
+		sp->expire = sp->expire - time_uptime;
+
+	sp->direction = st->direction;
+	sp->log = st->log;
+	sp->timeout = st->timeout;
+	sp->state_flags = st->state_flags;
+	if (st->src_node)
+		sp->sync_flags |= PFSYNC_FLAG_SRCNODE;
+	if (st->nat_src_node)
+		sp->sync_flags |= PFSYNC_FLAG_NATSRCNODE;
+
+	sp->id = st->id;
+	sp->creatorid = st->creatorid;
+	pf_state_peer_htoh(&st->src, &sp->src);
+	pf_state_peer_htoh(&st->dst, &sp->dst);
+
+	if (st->rule.ptr == NULL)
+		sp->rule = -1;
+	else
+		sp->rule = st->rule.ptr->nr;
+	if (st->anchor.ptr == NULL)
+		sp->anchor = -1;
+	else
+		sp->anchor = st->anchor.ptr->nr;
+	if (st->nat_rule.ptr == NULL)
+		sp->nat_rule = -1;
+	else
+		sp->nat_rule = st->nat_rule.ptr->nr;
+
+	sp->packets[0] = st->packets[0];
+	sp->packets[1] = st->packets[1];
+	sp->bytes[0] = st->bytes[0];
+	sp->bytes[1] = st->bytes[1];
+}
+
+static void
 pf_tbladdr_copyout(struct pf_addr_wrap *aw)
 {
 	struct pfr_ktable *kt;
Index: sbin/pfctl/pf_print_state.c
===================================================================
--- sbin/pfctl/pf_print_state.c	(revision 260492)
+++ sbin/pfctl/pf_print_state.c	(working copy)
@@ -194,21 +194,20 @@ print_host(struct pf_addr *addr, u_int16_t port, s
 }
 
 void
-print_seq(struct pfsync_state_peer *p)
+print_seq(struct pfioc_state2_peer *p)
 {
 	if (p->seqdiff)
-		printf("[%u + %u](+%u)", ntohl(p->seqlo),
-		    ntohl(p->seqhi) - ntohl(p->seqlo), ntohl(p->seqdiff));
+		printf("[%u + %u](+%u)", p->seqlo, p->seqhi - p->seqlo,
+		    p->seqdiff);
 	else
-		printf("[%u + %u]", ntohl(p->seqlo),
-		    ntohl(p->seqhi) - ntohl(p->seqlo));
+		printf("[%u + %u]", p->seqlo, p->seqhi - p->seqlo);
 }
 
 void
-print_state(struct pfsync_state *s, int opts)
+print_state(struct pfioc_state2 *s, int opts)
 {
-	struct pfsync_state_peer *src, *dst;
-	struct pfsync_state_key *sk, *nk;
+	struct pfioc_state2_peer *src, *dst;
+	struct pfioc_state2_key *sk, *nk;
 	struct protoent *p;
 	int min, sec;
 
@@ -296,10 +295,8 @@ void
 	}
 
 	if (opts & PF_OPT_VERBOSE) {
-		u_int64_t packets[2];
-		u_int64_t bytes[2];
-		u_int32_t creation = ntohl(s->creation);
-		u_int32_t expire = ntohl(s->expire);
+		u_int32_t creation = s->creation;
+		u_int32_t expire = s->expire;
 
 		sec = creation % 60;
 		creation /= 60;
@@ -312,19 +309,13 @@ void
 		expire /= 60;
 		printf(", expires in %.2u:%.2u:%.2u", expire, min, sec);
 
-		bcopy(s->packets[0], &packets[0], sizeof(u_int64_t));
-		bcopy(s->packets[1], &packets[1], sizeof(u_int64_t));
-		bcopy(s->bytes[0], &bytes[0], sizeof(u_int64_t));
-		bcopy(s->bytes[1], &bytes[1], sizeof(u_int64_t));
 		printf(", %ju:%ju pkts, %ju:%ju bytes",
-		    (uintmax_t )be64toh(packets[0]),
-		    (uintmax_t )be64toh(packets[1]),
-		    (uintmax_t )be64toh(bytes[0]),
-		    (uintmax_t )be64toh(bytes[1]));
-		if (ntohl(s->anchor) != -1)
-			printf(", anchor %u", ntohl(s->anchor));
-		if (ntohl(s->rule) != -1)
-			printf(", rule %u", ntohl(s->rule));
+		    (uintmax_t)s->packets[0], (uintmax_t)s->packets[1],
+		    (uintmax_t)s->bytes[0], (uintmax_t)s->bytes[1]);
+		if (s->anchor != -1)
+			printf(", anchor %u", s->anchor);
+		if (s->rule != -1)
+			printf(", rule %u", s->rule);
 		if (s->state_flags & PFSTATE_SLOPPY)
 			printf(", sloppy");
 		if (s->sync_flags & PFSYNC_FLAG_SRCNODE)
@@ -334,11 +325,8 @@ void
 		printf("\n");
 	}
 	if (opts & PF_OPT_VERBOSE2) {
-		u_int64_t id;
-
-		bcopy(&s->id, &id, sizeof(u_int64_t));
 		printf("   id: %016jx creatorid: %08x",
-		    (uintmax_t )be64toh(id), ntohl(s->creatorid));
+		    (uintmax_t)be64toh(s->id), ntohl(s->creatorid));
 		printf("\n");
 	}
 }
Index: sbin/pfctl/pfctl.c
===================================================================
--- sbin/pfctl/pfctl.c	(revision 260492)
+++ sbin/pfctl/pfctl.c	(working copy)
@@ -1054,8 +1054,8 @@ done:
 int
 pfctl_show_states(int dev, const char *iface, int opts)
 {
-	struct pfioc_states ps;
-	struct pfsync_state *p;
+	struct pfioc_states2 ps;
+	struct pfioc_state2 *p;
 	char *inbuf = NULL, *newinbuf = NULL;
 	unsigned int len = 0;
 	int i, dotitle = (opts & PF_OPT_SHOWALL);
@@ -1069,12 +1069,12 @@ pfctl_show_states(int dev, const char *iface, int
 				err(1, "realloc");
 			ps.ps_buf = inbuf = newinbuf;
 		}
-		if (ioctl(dev, DIOCGETSTATES, &ps) < 0) {
-			warn("DIOCGETSTATES");
+		if (ioctl(dev, DIOCGETSTATES2, &ps) < 0) {
+			warn("DIOCGETSTATES2");
 			free(inbuf);
 			return (-1);
 		}
-		if (ps.ps_len + sizeof(struct pfioc_states) < len)
+		if (ps.ps_len + sizeof(struct pfioc_states2) < len)
 			break;
 		if (len == 0 && ps.ps_len == 0)
 			goto done;
Index: sbin/pfctl/pfctl.h
===================================================================
--- sbin/pfctl/pfctl.h	(revision 260492)
+++ sbin/pfctl/pfctl.h	(working copy)
@@ -117,8 +117,8 @@ char		*rate2str(double);
 
 void	 print_addr(struct pf_addr_wrap *, sa_family_t, int);
 void	 print_host(struct pf_addr *, u_int16_t p, sa_family_t, int);
-void	 print_seq(struct pfsync_state_peer *);
-void	 print_state(struct pfsync_state *, int);
+void	 print_seq(struct pfioc_state2_peer *);
+void	 print_state(struct pfioc_state2 *, int);
 int	 unmask(struct pf_addr *, sa_family_t);
 
 int	 pfctl_cmdline_symset(char *);

[-- Attachment #3 --]
--- sbin/pfctl/pfctl.h.orig	2014-01-11 21:20:57.000000000 +0200
+++ sbin/pfctl/pfctl.h	2014-01-11 21:22:30.000000000 +0200
@@ -115,11 +115,11 @@ void		 pfaltq_store(struct pf_altq *);
 struct pf_altq	*pfaltq_lookup(const char *);
 char		*rate2str(double);
 
-void	 print_addr(struct pf_addr_wrap *, sa_family_t, int);
-void	 print_host(struct pf_addr *, u_int16_t p, sa_family_t, int);
-void	 print_seq(struct pfioc_state2_peer *);
-void	 print_state(struct pfioc_state2 *, int);
-int	 unmask(struct pf_addr *, sa_family_t);
+void	 print_addr(const struct pf_addr_wrap *, sa_family_t, int);
+void	 print_host(const struct pf_addr *, u_int16_t p, sa_family_t, int);
+void	 print_seq(const struct pfioc_state2_peer *);
+void	 print_state(const struct pfioc_state2 *, int);
+int	 unmask(const struct pf_addr *, sa_family_t);
 
 int	 pfctl_cmdline_symset(char *);
 int	 pfctl_add_trans(struct pfr_buffer *, int, const char *);
--- sbin/pfctl/pfctl_parser.h.orig	2014-01-11 14:00:13.000000000 +0200
+++ sbin/pfctl/pfctl_parser.h	2014-01-11 21:37:02.000000000 +0200
@@ -292,7 +292,7 @@ extern const struct pf_timeout pf_timeou
 
 void			 set_ipmask(struct node_host *, u_int8_t);
 int			 check_netmask(struct node_host *, sa_family_t);
-int			 unmask(struct pf_addr *, sa_family_t);
+int			 unmask(const struct pf_addr *, sa_family_t);
 void			 ifa_load(void);
 struct node_host	*ifa_exists(const char *);
 struct node_host	*ifa_lookup(const char *, int);
--- sbin/pfctl/pf_print_state.c.orig	2014-01-11 21:21:30.000000000 +0200
+++ sbin/pfctl/pf_print_state.c	2014-01-11 21:38:15.000000000 +0200
@@ -50,10 +50,10 @@ __FBSDID("$FreeBSD: releng/10.0/sbin/pfc
 #include "pfctl_parser.h"
 #include "pfctl.h"
 
-void	print_name(struct pf_addr *, sa_family_t);
+void	print_name(const struct pf_addr *, sa_family_t);
 
 void
-print_addr(struct pf_addr_wrap *addr, sa_family_t af, int verbose)
+print_addr(const struct pf_addr_wrap *addr, sa_family_t af, int verbose)
 {
 	switch (addr->type) {
 	case PF_ADDR_DYNIFTL:
@@ -134,7 +134,7 @@ print_addr(struct pf_addr_wrap *addr, sa
 }
 
 void
-print_name(struct pf_addr *addr, sa_family_t af)
+print_name(const struct pf_addr *addr, sa_family_t af)
 {
 	char host[NI_MAXHOST];
 
@@ -167,7 +167,7 @@ print_name(struct pf_addr *addr, sa_fami
 }
 
 void
-print_host(struct pf_addr *addr, u_int16_t port, sa_family_t af, int opts)
+print_host(const struct pf_addr *addr, u_int16_t port, sa_family_t af, int opts)
 {
 	if (opts & PF_OPT_USEDNS)
 		print_name(addr, af);
@@ -194,7 +194,7 @@ print_host(struct pf_addr *addr, u_int16
 }
 
 void
-print_seq(struct pfioc_state2_peer *p)
+print_seq(const struct pfioc_state2_peer *p)
 {
 	if (p->seqdiff)
 		printf("[%u + %u](+%u)", p->seqlo, p->seqhi - p->seqlo,
@@ -204,12 +204,13 @@ print_seq(struct pfioc_state2_peer *p)
 }
 
 void
-print_state(struct pfioc_state2 *s, int opts)
+print_state(const struct pfioc_state2 *s, int opts)
 {
-	struct pfioc_state2_peer *src, *dst;
-	struct pfioc_state2_key *sk, *nk;
-	struct protoent *p;
+	const struct pfioc_state2_peer *src, *dst;
+	const struct pfioc_state2_key *sk, *nk;
+	const struct protoent *p;
 	int min, sec;
+	u_int16_t sport[2], nport[2];
 
 	if (s->direction == PF_OUT) {
 		src = &s->src;
@@ -217,14 +218,24 @@ print_state(struct pfioc_state2 *s, int 
 		sk = &s->key[PF_SK_STACK];
 		nk = &s->key[PF_SK_WIRE];
 		if (s->proto == IPPROTO_ICMP || s->proto == IPPROTO_ICMPV6) 
-			sk->port[0] = nk->port[0];
+			sport[0] = nk->port[0];
+		else
+			sport[0] = sk->port[0];
+		sport[1] = sk->port[1];
+		nport[0] = nk->port[0];
+		nport[1] = nk->port[1];
 	} else {
 		src = &s->dst;
 		dst = &s->src;
 		sk = &s->key[PF_SK_WIRE];
 		nk = &s->key[PF_SK_STACK];
+		sport[0] = sk->port[0];
 		if (s->proto == IPPROTO_ICMP || s->proto == IPPROTO_ICMPV6) 
-			sk->port[1] = nk->port[1];
+			sport[1] = nk->port[1];
+		else
+			sport[1] = sk->port[1];
+		nport[0] = nk->port[0];
+		nport[1] = nk->port[1];
 	}
 	printf("%s ", s->ifname);
 	if ((p = getprotobynumber(s->proto)) != NULL)
@@ -232,22 +243,22 @@ print_state(struct pfioc_state2 *s, int 
 	else
 		printf("%u ", s->proto);
 
-	print_host(&nk->addr[1], nk->port[1], s->af, opts);
+	print_host(&nk->addr[1], nport[1], s->af, opts);
 	if (PF_ANEQ(&nk->addr[1], &sk->addr[1], s->af) ||
-	    nk->port[1] != sk->port[1]) {
+	    nport[1] != sport[1]) {
 		printf(" (");
-		print_host(&sk->addr[1], sk->port[1], s->af, opts);
+		print_host(&sk->addr[1], sport[1], s->af, opts);
 		printf(")");
 	}
 	if (s->direction == PF_OUT)
 		printf(" -> ");
 	else
 		printf(" <- ");
-	print_host(&nk->addr[0], nk->port[0], s->af, opts);
+	print_host(&nk->addr[0], nport[0], s->af, opts);
 	if (PF_ANEQ(&nk->addr[0], &sk->addr[0], s->af) ||
-	    nk->port[0] != sk->port[0]) {
+	    nport[0] != sport[0]) {
 		printf(" (");
-		print_host(&sk->addr[0], sk->port[0], s->af, opts);
+		print_host(&sk->addr[0], sport[0], s->af, opts);
 		printf(")");
 	}
 
@@ -332,7 +343,7 @@ print_state(struct pfioc_state2 *s, int 
 }
 
 int
-unmask(struct pf_addr *m, sa_family_t af)
+unmask(const struct pf_addr *m, sa_family_t af)
 {
 	int i = 31, j = 0, b = 0;
 	u_int32_t tmp;
help

Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?CAC67Hz9Z5xv_m9F0WY5OZAFaFsuUNXtKx5gpTBpGipfn2ArYkg>