PERFORCE change 145552 for review

Gleb Kurtsou gk at FreeBSD.org
Mon Jul 21 10:11:39 UTC 2008


http://perforce.freebsd.org/chv.cgi?CH=145552

Change 145552 by gk at gk_h1 on 2008/07/21 10:11:02

	save ethernet address in pf_addr_wrap.
	improve stateful filtering: check against ether addresses from packet
	but not from rule created the state.
	extend PF_MISMATCHAW to support ethernet addresses: PF_MISMATCHAW_L2.
	nuke now unused pf_rule_match_addr_ether.

Affected files ...

.. //depot/projects/soc2008/gk_l2filter/sbin-pfctl/parse.y#3 edit
.. //depot/projects/soc2008/gk_l2filter/sbin-pfctl/pf_print_state.c#3 edit
.. //depot/projects/soc2008/gk_l2filter/sbin-pfctl/pfctl.h#3 edit
.. //depot/projects/soc2008/gk_l2filter/sbin-pfctl/pfctl_parser.c#3 edit
.. //depot/projects/soc2008/gk_l2filter/sbin-pfctl/pfctl_parser.h#3 edit
.. //depot/projects/soc2008/gk_l2filter/sys-pf/net/pf.c#4 edit
.. //depot/projects/soc2008/gk_l2filter/sys-pf/net/pfvar.h#4 edit

Differences ...

==== //depot/projects/soc2008/gk_l2filter/sbin-pfctl/parse.y#3 (text+ko) ====

@@ -2483,7 +2483,7 @@
 				n->not = $1;
 			$$ = $2;
 			if ($3) {
-				$$->addr_ether = $3->addr_ether;
+				$$->addr.v.a.addr_ether = $3->addr.v.a.addr_ether;
 				free($3);
 			}
 		}
@@ -4732,13 +4732,11 @@
 		r->ifnot = interface->not;
 		r->proto = proto->proto;
 		r->src.addr = src_host->addr;
-		r->src.addr_ether = src_host->addr_ether;
 		r->src.neg = src_host->not;
 		r->src.port[0] = src_port->port[0];
 		r->src.port[1] = src_port->port[1];
 		r->src.port_op = src_port->op;
 		r->dst.addr = dst_host->addr;
-		r->dst.addr_ether = dst_host->addr_ether;
 		r->dst.neg = dst_host->not;
 		r->dst.port[0] = dst_port->port[0];
 		r->dst.port[1] = dst_port->port[1];

==== //depot/projects/soc2008/gk_l2filter/sbin-pfctl/pf_print_state.c#3 (text+ko) ====

@@ -50,6 +50,7 @@
 #include "pfctl.h"
 
 void	print_name(struct pf_addr *, sa_family_t);
+static void	print_addr_ether(struct pf_addr_ether *, int );
 
 void
 print_addr(struct pf_addr_wrap *addr, sa_family_t af, int verbose)
@@ -119,9 +120,11 @@
 		if (bits != (af == AF_INET ? 32 : 128))
 			printf("/%d", bits);
 	}
+
+	print_addr_ether(&addr->v.a.addr_ether, verbose);
 }
 
-void
+static void
 print_addr_ether(struct pf_addr_ether *addr, int verbose)
 {
 	if ((addr->flags & PFAE_CHECK) == 0)

==== //depot/projects/soc2008/gk_l2filter/sbin-pfctl/pfctl.h#3 (text+ko) ====

@@ -117,7 +117,6 @@
 char		*rate2str(double);
 
 void	 print_addr(struct pf_addr_wrap *, sa_family_t, int);
-void	 print_addr_ether(struct pf_addr_ether *, int);
 void	 print_host(struct pf_state_host *, sa_family_t, int);
 void	 print_seq(struct pf_state_peer *);
 void	 print_state(struct pf_state *, int);

==== //depot/projects/soc2008/gk_l2filter/sbin-pfctl/pfctl_parser.c#3 (text+ko) ====

@@ -382,7 +382,6 @@
 		if (src->neg)
 			printf("! ");
 		print_addr(&src->addr, af, verbose);
-		print_addr_ether(&src->addr_ether, verbose);
 		if (src->port_op)
 			print_port(src->port_op, src->port[0],
 			    src->port[1],
@@ -395,7 +394,6 @@
 		if (dst->neg)
 			printf("! ");
 		print_addr(&dst->addr, af, verbose);
-		print_addr_ether(&dst->addr_ether, verbose);
 		if (dst->port_op)
 			print_port(dst->port_op, dst->port[0],
 			    dst->port[1],
@@ -1424,24 +1422,24 @@
 struct node_host *
 host_ether(const char *s)
 {
-	struct ether_addr	 addr;
+	struct pf_addr_ether	*addr;
 	struct node_host	*h = NULL;
 
 	h = calloc(1, sizeof(*h));
 	if (h == NULL)
 		err(1, "host_ether: malloc");
+	addr = &h->addr.v.a.addr_ether;
 
 	if (strcmp(s, "multicast") == 0) {
-		h->addr_ether.flags = PFAE_CHECK | PFAE_MULTICAST;
+		addr->flags = PFAE_CHECK | PFAE_MULTICAST;
 		return (h);
 	} 
-	if (!ether_aton_r(s, &addr)) {
+	if (!ether_aton_r(s, (struct ether_addr*)addr->octet)) {
 		fprintf(stderr, "can't parse ethernet address: %s\n", s);
 		free(h);
 		return (NULL);
 	}
-	memcpy(h->addr_ether.octet, addr.octet, ETHER_ADDR_LEN);
-	h->addr_ether.flags = PFAE_CHECK;
+	addr->flags = PFAE_CHECK;
 
 	return (h);
 }

==== //depot/projects/soc2008/gk_l2filter/sbin-pfctl/pfctl_parser.h#3 (text+ko) ====

@@ -112,7 +112,6 @@
 
 struct node_host {
 	struct pf_addr_wrap	 addr;
-	struct pf_addr_ether	 addr_ether;
 	struct pf_addr		 bcast;
 	struct pf_addr		 peer;
 	sa_family_t		 af;

==== //depot/projects/soc2008/gk_l2filter/sys-pf/net/pf.c#4 (text+ko) ====

@@ -702,49 +702,16 @@
 }
 
 static __inline int
-pf_match_addr_ether(struct pf_addr_ether *want, struct pf_addr_ether *a, int match_empty)
-{
-	static struct pf_addr_ether mask = {
-		.octet = { 0xff, 0xff, 0xff, 0xff, 0xff,0xff },
-		.flags = 0
-	};
-	if ((want->flags & PFAE_CHECK) == 0)
-		return (1);
-	if ((a->flags & PFAE_CHECK) == 0)
-		return (match_empty);
-	if (want->flags & PFAE_MULTICAST) {
-		return (ETHER_IS_MULTICAST(a->octet));
-	}
-	
-#define EA_CMP(x) (*((u_int64_t*)(x)) & *((u_int64_t*)&mask))
-	return (EA_CMP(want) == EA_CMP(a));
-#undef EA_CMP
-}
-
-static __inline int
-pf_rule_match_addr_ether(struct pf_rule *r, struct pf_pdesc *pd)
-{
-	if (pf_match_addr_ether(&r->src.addr_ether, &pd->src_ether, 0) &&
-		pf_match_addr_ether(&r->dst.addr_ether, &pd->dst_ether, 0))
-		return (1);
-
-	return (0);
-}
-
-static __inline int
 pf_state_match_addr_ether(struct pf_state *state, struct pf_pdesc *pd, int direction)
 {
-	struct pf_rule 		*r;
 	struct pf_addr_ether	*src, *dst;
 
-	r = state->rule.ptr;
-
-	if (direction == state->direction) {
-		src = &r->src.addr_ether;
-		dst = &r->dst.addr_ether;
+	if (state->direction == PF_OUT) {
+		src = &state->gwy.addr_ether;
+		dst = &state->ext.addr_ether;
 	} else {
-		src = &r->dst.addr_ether;
-		dst = &r->src.addr_ether;
+		dst = &state->lan.addr_ether;
+		src = &state->ext.addr_ether;
 	}
 
 	if (pf_match_addr_ether(src, &pd->src_ether, 1) &&
@@ -2161,6 +2128,26 @@
 }
 
 int
+pf_match_addr_ether(struct pf_addr_ether *want, struct pf_addr_ether *a, int match_empty)
+{
+	static struct pf_addr_ether mask = {
+		.octet = { 0xff, 0xff, 0xff, 0xff, 0xff,0xff },
+		.flags = 0
+	};
+	if (want == NULL || (want->flags & PFAE_CHECK) == 0)
+		return (1);
+	if (a == NULL || (a->flags & PFAE_CHECK) == 0)
+		return (match_empty);
+
+	if (want->flags & PFAE_MULTICAST) {
+		return (ETHER_IS_MULTICAST(a->octet));
+	}
+#define EA_CMP(x) (*((u_int64_t*)(x)) & *((u_int64_t*)&mask))
+	return (EA_CMP(want) == EA_CMP(a));
+#undef EA_CMP
+}
+
+int
 pf_match(u_int8_t op, u_int32_t a1, u_int32_t a2, u_int32_t p)
 {
 	switch (op) {
@@ -3368,14 +3355,14 @@
 			r = r->skip[PF_SKIP_AF].ptr;
 		else if (r->proto && r->proto != IPPROTO_TCP)
 			r = r->skip[PF_SKIP_PROTO].ptr;
-		else if (PF_MISMATCHAW(&r->src.addr, saddr, af,
-		    r->src.neg, kif))
+		else if (PF_MISMATCHAW_L2(&r->src.addr, saddr, &pd->src_ether,
+		    af, r->src.neg, kif))
 			r = r->skip[PF_SKIP_SRC_ADDR].ptr;
 		else if (r->src.port_op && !pf_match_port(r->src.port_op,
 		    r->src.port[0], r->src.port[1], th->th_sport))
 			r = r->skip[PF_SKIP_SRC_PORT].ptr;
-		else if (PF_MISMATCHAW(&r->dst.addr, daddr, af,
-		    r->dst.neg, NULL))
+		else if (PF_MISMATCHAW_L2(&r->dst.addr, daddr, &pd->dst_ether,
+		    af, r->dst.neg, NULL))
 			r = r->skip[PF_SKIP_DST_ADDR].ptr;
 		else if (r->dst.port_op && !pf_match_port(r->dst.port_op,
 		    r->dst.port[0], r->dst.port[1], th->th_dport))
@@ -3411,8 +3398,6 @@
 		else if (r->os_fingerprint != PF_OSFP_ANY && !pf_osfp_match(
 		    pf_osfp_fingerprint(pd, m, off, th), r->os_fingerprint))
 			r = TAILQ_NEXT(r, entries);
-		else if (!pf_rule_match_addr_ether(r, pd))
-			r = TAILQ_NEXT(r, entries);
 		else {
 			if (r->tag)
 				tag = r->tag;
@@ -3564,8 +3549,10 @@
 		if (direction == PF_OUT) {
 			PF_ACPY(&s->gwy.addr, saddr, af);
 			s->gwy.port = th->th_sport;		/* sport */
+			s->gwy.addr_ether = pd->src_ether;
 			PF_ACPY(&s->ext.addr, daddr, af);
 			s->ext.port = th->th_dport;
+			s->ext.addr_ether = pd->dst_ether;
 			if (nr != NULL) {
 				PF_ACPY(&s->lan.addr, &pd->baddr, af);
 				s->lan.port = bport;
@@ -3576,8 +3563,10 @@
 		} else {
 			PF_ACPY(&s->lan.addr, daddr, af);
 			s->lan.port = th->th_dport;
+			s->lan.addr_ether = pd->dst_ether;
 			PF_ACPY(&s->ext.addr, saddr, af);
 			s->ext.port = th->th_sport;
+			s->ext.addr_ether = pd->src_ether;
 			if (nr != NULL) {
 				PF_ACPY(&s->gwy.addr, &pd->baddr, af);
 				s->gwy.port = bport;
@@ -3792,14 +3781,14 @@
 			r = r->skip[PF_SKIP_AF].ptr;
 		else if (r->proto && r->proto != IPPROTO_UDP)
 			r = r->skip[PF_SKIP_PROTO].ptr;
-		else if (PF_MISMATCHAW(&r->src.addr, saddr, af,
-		    r->src.neg, kif))
+		else if (PF_MISMATCHAW_L2(&r->src.addr, saddr, &pd->src_ether,
+		    af, r->src.neg, kif))
 			r = r->skip[PF_SKIP_SRC_ADDR].ptr;
 		else if (r->src.port_op && !pf_match_port(r->src.port_op,
 		    r->src.port[0], r->src.port[1], uh->uh_sport))
 			r = r->skip[PF_SKIP_SRC_PORT].ptr;
-		else if (PF_MISMATCHAW(&r->dst.addr, daddr, af,
-		    r->dst.neg, NULL))
+		else if (PF_MISMATCHAW_L2(&r->dst.addr, daddr, &pd->dst_ether,
+		    af, r->dst.neg, NULL))
 			r = r->skip[PF_SKIP_DST_ADDR].ptr;
 		else if (r->dst.port_op && !pf_match_port(r->dst.port_op,
 		    r->dst.port[0], r->dst.port[1], uh->uh_dport))
@@ -3832,8 +3821,6 @@
 			r = TAILQ_NEXT(r, entries);
 		else if (r->os_fingerprint != PF_OSFP_ANY)
 			r = TAILQ_NEXT(r, entries);
-		else if (!pf_rule_match_addr_ether(r, pd))
-			r = TAILQ_NEXT(r, entries);
 		else {
 			if (r->tag)
 				tag = r->tag;
@@ -3963,8 +3950,10 @@
 		if (direction == PF_OUT) {
 			PF_ACPY(&s->gwy.addr, saddr, af);
 			s->gwy.port = uh->uh_sport;
+			s->gwy.addr_ether = pd->src_ether;
 			PF_ACPY(&s->ext.addr, daddr, af);
 			s->ext.port = uh->uh_dport;
+			s->ext.addr_ether = pd->dst_ether;
 			if (nr != NULL) {
 				PF_ACPY(&s->lan.addr, &pd->baddr, af);
 				s->lan.port = bport;
@@ -3975,8 +3964,10 @@
 		} else {
 			PF_ACPY(&s->lan.addr, daddr, af);
 			s->lan.port = uh->uh_dport;
+			s->lan.addr_ether = pd->dst_ether;
 			PF_ACPY(&s->ext.addr, saddr, af);
 			s->ext.port = uh->uh_sport;
+			s->ext.addr_ether = pd->src_ether;
 			if (nr != NULL) {
 				PF_ACPY(&s->gwy.addr, &pd->baddr, af);
 				s->gwy.port = bport;
@@ -4151,11 +4142,11 @@
 			r = r->skip[PF_SKIP_AF].ptr;
 		else if (r->proto && r->proto != pd->proto)
 			r = r->skip[PF_SKIP_PROTO].ptr;
-		else if (PF_MISMATCHAW(&r->src.addr, saddr, af,
-		    r->src.neg, kif))
+		else if (PF_MISMATCHAW_L2(&r->src.addr, saddr, &pd->src_ether,
+		    af, r->src.neg, kif))
 			r = r->skip[PF_SKIP_SRC_ADDR].ptr;
-		else if (PF_MISMATCHAW(&r->dst.addr, daddr, af,
-		    r->dst.neg, NULL))
+		else if (PF_MISMATCHAW_L2(&r->dst.addr, daddr, &pd->dst_ether,
+		    af, r->dst.neg, NULL))
 			r = r->skip[PF_SKIP_DST_ADDR].ptr;
 		else if (r->type && r->type != icmptype + 1)
 			r = TAILQ_NEXT(r, entries);
@@ -4171,8 +4162,6 @@
 			r = TAILQ_NEXT(r, entries);
 		else if (r->os_fingerprint != PF_OSFP_ANY)
 			r = TAILQ_NEXT(r, entries);
-		else if (!pf_rule_match_addr_ether(r, pd))
-			r = TAILQ_NEXT(r, entries);
 		else {
 			if (r->tag)
 				tag = r->tag;
@@ -4278,8 +4267,10 @@
 		if (direction == PF_OUT) {
 			PF_ACPY(&s->gwy.addr, saddr, af);
 			s->gwy.port = nport;
+			s->gwy.addr_ether = pd->src_ether;
 			PF_ACPY(&s->ext.addr, daddr, af);
 			s->ext.port = 0;
+			s->ext.addr_ether = pd->dst_ether;
 			if (nr != NULL) {
 				PF_ACPY(&s->lan.addr, &pd->baddr, af);
 				s->lan.port = bport;
@@ -4290,8 +4281,10 @@
 		} else {
 			PF_ACPY(&s->lan.addr, daddr, af);
 			s->lan.port = nport;
+			s->lan.addr_ether = pd->dst_ether;
 			PF_ACPY(&s->ext.addr, saddr, af);
 			s->ext.port = 0; 
+			s->ext.addr_ether = pd->src_ether;
 			if (nr != NULL) {
 				PF_ACPY(&s->gwy.addr, &pd->baddr, af);
 				s->gwy.port = bport;
@@ -4416,11 +4409,11 @@
 			r = r->skip[PF_SKIP_AF].ptr;
 		else if (r->proto && r->proto != pd->proto)
 			r = r->skip[PF_SKIP_PROTO].ptr;
-		else if (PF_MISMATCHAW(&r->src.addr, pd->src, af,
-		    r->src.neg, kif))
+		else if (PF_MISMATCHAW_L2(&r->src.addr, pd->src, &pd->src_ether,
+		    af, r->src.neg, kif))
 			r = r->skip[PF_SKIP_SRC_ADDR].ptr;
-		else if (PF_MISMATCHAW(&r->dst.addr, pd->dst, af,
-		    r->dst.neg, NULL))
+		else if (PF_MISMATCHAW_L2(&r->dst.addr, pd->dst, &pd->dst_ether,
+		    af, r->dst.neg, NULL))
 			r = r->skip[PF_SKIP_DST_ADDR].ptr;
 		else if (r->tos && !(r->tos == pd->tos))
 			r = TAILQ_NEXT(r, entries);
@@ -4432,8 +4425,6 @@
 			r = TAILQ_NEXT(r, entries);
 		else if (r->os_fingerprint != PF_OSFP_ANY)
 			r = TAILQ_NEXT(r, entries);
-		else if (!pf_rule_match_addr_ether(r, pd))
-			r = TAILQ_NEXT(r, entries);
 		else {
 			if (r->tag)
 				tag = r->tag;
@@ -4566,14 +4557,18 @@
 		s->af = af;
 		if (direction == PF_OUT) {
 			PF_ACPY(&s->gwy.addr, saddr, af);
+			s->gwy.addr_ether = pd->src_ether;
 			PF_ACPY(&s->ext.addr, daddr, af);
+			s->ext.addr_ether = pd->dst_ether;
 			if (nr != NULL)
 				PF_ACPY(&s->lan.addr, &pd->baddr, af);
 			else
 				PF_ACPY(&s->lan.addr, &s->gwy.addr, af);
 		} else {
 			PF_ACPY(&s->lan.addr, daddr, af);
+			s->lan.addr_ether = pd->dst_ether;
 			PF_ACPY(&s->ext.addr, saddr, af);
+			s->ext.addr_ether = pd->src_ether;
 			if (nr != NULL)
 				PF_ACPY(&s->gwy.addr, &pd->baddr, af);
 			else
@@ -4635,11 +4630,11 @@
 			r = r->skip[PF_SKIP_AF].ptr;
 		else if (r->proto && r->proto != pd->proto)
 			r = r->skip[PF_SKIP_PROTO].ptr;
-		else if (PF_MISMATCHAW(&r->src.addr, pd->src, af,
-		    r->src.neg, kif))
+		else if (PF_MISMATCHAW_L2(&r->src.addr, pd->src, &pd->src_ether,
+		    af, r->src.neg, kif))
 			r = r->skip[PF_SKIP_SRC_ADDR].ptr;
-		else if (PF_MISMATCHAW(&r->dst.addr, pd->dst, af,
-		    r->dst.neg, NULL))
+		else if (PF_MISMATCHAW_L2(&r->dst.addr, pd->dst, &pd->dst_ether,
+		    af, r->dst.neg, NULL))
 			r = r->skip[PF_SKIP_DST_ADDR].ptr;
 		else if (r->tos && !(r->tos == pd->tos))
 			r = TAILQ_NEXT(r, entries);
@@ -4659,8 +4654,6 @@
 			r = TAILQ_NEXT(r, entries);
 		else if (r->match_tag && !pf_match_tag(m, r, pd->pf_mtag, &tag))
 			r = TAILQ_NEXT(r, entries);
-		else if (!pf_rule_match_addr_ether(r, pd))
-			r = TAILQ_NEXT(r, entries);
 		else {
 			if (r->anchor == NULL) {
 				match = 1;

==== //depot/projects/soc2008/gk_l2filter/sys-pf/net/pfvar.h#4 (text+ko) ====

@@ -178,6 +178,7 @@
 		struct {
 			struct pf_addr		 addr;
 			struct pf_addr		 mask;
+			struct pf_addr_ether	 addr_ether;
 		}			 a;
 		char			 ifname[IFNAMSIZ];
 		char			 tblname[PF_TABLE_NAME_SIZE];
@@ -409,7 +410,7 @@
 #endif /* PF_INET6_ONLY */
 #endif /* PF_INET_INET6 */
 
-#define	PF_MISMATCHAW(aw, x, af, neg, ifp)				\
+#define	PF_MISMATCHAW_L2(aw, x, xl2, af, neg, ifp)			\
 	(								\
 		(((aw)->type == PF_ADDR_NOROUTE &&			\
 		    pf_routable((x), (af), NULL)) ||			\
@@ -424,11 +425,16 @@
 		((aw)->type == PF_ADDR_ADDRMASK &&			\
 		    !PF_AZERO(&(aw)->v.a.mask, (af)) &&			\
 		    !PF_MATCHA(0, &(aw)->v.a.addr,			\
-		    &(aw)->v.a.mask, (x), (af))))) !=			\
+		    &(aw)->v.a.mask, (x), (af)) &&			\
+		    !pf_match_addr_ether(&(aw)->v.a.addr_ether,		\
+		    xl2, 0)))) !=					\
 		(neg)							\
 	)
 
+#define	PF_MISMATCHAW(aw, x, af, neg, ifp)				\
+	PF_MISMATCHAW_L2(aw, x, NULL, af, neg, ifp)
 
+
 struct pf_rule_uid {
 	uid_t		 uid[2];
 	u_int8_t	 op;
@@ -444,7 +450,6 @@
 	u_int16_t		 port[2];
 	u_int8_t		 neg;
 	u_int8_t		 port_op;
-	struct pf_addr_ether	 addr_ether;
 };
 
 struct pf_pooladdr {
@@ -761,6 +766,8 @@
 
 struct pf_state_host {
 	struct pf_addr	addr;
+	struct pf_addr_ether
+			addr_ether;
 	u_int16_t	port;
 	u_int16_t	pad;
 };
@@ -1663,6 +1670,7 @@
 	    struct pf_pdesc *);
 int	pf_match_addr(u_int8_t, struct pf_addr *, struct pf_addr *,
 	    struct pf_addr *, sa_family_t);
+int	pf_match_addr_ether(struct pf_addr_ether *, struct pf_addr_ether *, int);
 int	pf_match(u_int8_t, u_int32_t, u_int32_t, u_int32_t);
 int	pf_match_port(u_int8_t, u_int16_t, u_int16_t, u_int16_t);
 int	pf_match_uid(u_int8_t, uid_t, uid_t, uid_t);


More information about the p4-projects mailing list