From owner-p4-projects@FreeBSD.ORG Mon Jul 21 10:11:39 2008 Return-Path: Delivered-To: p4-projects@freebsd.org Received: by hub.freebsd.org (Postfix, from userid 32767) id EDCDA1065671; Mon, 21 Jul 2008 10:11:38 +0000 (UTC) Delivered-To: perforce@FreeBSD.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id B1D33106566C for ; Mon, 21 Jul 2008 10:11:38 +0000 (UTC) (envelope-from gk@FreeBSD.org) Received: from repoman.freebsd.org (repoman.freebsd.org [IPv6:2001:4f8:fff6::29]) by mx1.freebsd.org (Postfix) with ESMTP id 904EE8FC18 for ; Mon, 21 Jul 2008 10:11:38 +0000 (UTC) (envelope-from gk@FreeBSD.org) Received: from repoman.freebsd.org (localhost [127.0.0.1]) by repoman.freebsd.org (8.14.1/8.14.1) with ESMTP id m6LABclF086739 for ; Mon, 21 Jul 2008 10:11:38 GMT (envelope-from gk@FreeBSD.org) Received: (from perforce@localhost) by repoman.freebsd.org (8.14.2/8.14.1/Submit) id m6LABc1g086737 for perforce@freebsd.org; Mon, 21 Jul 2008 10:11:38 GMT (envelope-from gk@FreeBSD.org) Date: Mon, 21 Jul 2008 10:11:38 GMT Message-Id: <200807211011.m6LABc1g086737@repoman.freebsd.org> X-Authentication-Warning: repoman.freebsd.org: perforce set sender to gk@FreeBSD.org using -f From: Gleb Kurtsou To: Perforce Change Reviews Cc: Subject: PERFORCE change 145552 for review X-BeenThere: p4-projects@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: p4 projects tree changes List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 21 Jul 2008 10:11:39 -0000 http://perforce.freebsd.org/chv.cgi?CH=145552 Change 145552 by gk@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);