PERFORCE change 145387 for review
Gleb Kurtsou
gk at FreeBSD.org
Thu Jul 17 19:58:21 UTC 2008
http://perforce.freebsd.org/chv.cgi?CH=145387
Change 145387 by gk at gk_h1 on 2008/07/17 19:58:11
commit some *work in progress* support for layer2 filtering with pf
Affected files ...
.. //depot/projects/soc2008/gk_l2filter/sbin-pfctl/parse.y#2 edit
.. //depot/projects/soc2008/gk_l2filter/sbin-pfctl/pf_print_state.c#2 edit
.. //depot/projects/soc2008/gk_l2filter/sbin-pfctl/pfctl.h#2 edit
.. //depot/projects/soc2008/gk_l2filter/sbin-pfctl/pfctl_parser.c#2 edit
.. //depot/projects/soc2008/gk_l2filter/sbin-pfctl/pfctl_parser.h#2 edit
.. //depot/projects/soc2008/gk_l2filter/sys-pf/net/pf.c#2 edit
.. //depot/projects/soc2008/gk_l2filter/sys-pf/net/pfvar.h#2 edit
Differences ...
==== //depot/projects/soc2008/gk_l2filter/sbin-pfctl/parse.y#2 (text+ko) ====
@@ -409,7 +409,7 @@
%}
-%token PASS BLOCK SCRUB RETURN IN OS OUT LOG QUICK ON FROM TO FLAGS
+%token PASS BLOCK SCRUB RETURN IN OS OUT LOG QUICK ON ETHER FROM TO FLAGS
%token RETURNRST RETURNICMP RETURNICMP6 PROTO INET INET6 ALL ANY ICMPTYPE
%token ICMP6TYPE CODE KEEP MODULATE STATE PORT RDR NAT BINAT ARROW NODF
%token MINTTL ERROR ALLOWOPTS FASTROUTE FILENAME ROUTETO DUPTO REPLYTO NO LABEL
@@ -442,7 +442,7 @@
%type <v.icmp> icmp6_list icmp6_item
%type <v.fromto> fromto
%type <v.peer> ipportspec from to
-%type <v.host> ipspec xhost host dynaddr host_list
+%type <v.host> ipspec ether xhost host dynaddr host_list
%type <v.host> redir_host_list redirspec
%type <v.host> route_host route_host_list routespec
%type <v.os> os xos os_list
@@ -2471,12 +2471,21 @@
}
;
-xhost : not host {
+ether : /* empty */ { $$ = NULL; }
+ | ETHER ANY { $$ = NULL; }
+ | ETHER STRING { $$ = host_ether($2); free($2); }
+ ;
+
+xhost : not host ether {
struct node_host *n;
for (n = $2; n != NULL; n = n->next)
n->not = $1;
$$ = $2;
+ if ($3) {
+ $$->addr_ether = $3->addr_ether;
+ free($3);
+ }
}
| not NOROUTE {
$$ = calloc(1, sizeof(struct node_host));
@@ -4723,11 +4732,13 @@
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];
@@ -4894,6 +4905,7 @@
{ "drop", DROP},
{ "drop-ovl", FRAGDROP},
{ "dup-to", DUPTO},
+ { "ether", ETHER},
{ "fastroute", FASTROUTE},
{ "file", FILENAME},
{ "fingerprints", FINGERPRINTS},
==== //depot/projects/soc2008/gk_l2filter/sbin-pfctl/pf_print_state.c#2 (text+ko) ====
@@ -122,6 +122,20 @@
}
void
+print_addr_ether(struct pf_addr_ether *addr, int verbose)
+{
+ if ((addr->flags & PFAE_CHECK) == 0)
+ return;
+ if (addr->flags & PFAE_MULTICAST) {
+ printf(" ether multicast");
+ } else {
+ u_int8_t *ea = addr->octet;
+ printf(" ether %02x:%02x:%02x:%02x:%02x:%02x",
+ ea[0], ea[1], ea[2], ea[3], ea[4], ea[5]);
+ }
+}
+
+void
print_name(struct pf_addr *addr, sa_family_t af)
{
char host[NI_MAXHOST];
==== //depot/projects/soc2008/gk_l2filter/sbin-pfctl/pfctl.h#2 (text+ko) ====
@@ -117,6 +117,7 @@
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#2 (text+ko) ====
@@ -46,6 +46,7 @@
#include <netinet/ip_icmp.h>
#include <netinet/icmp6.h>
#include <net/pfvar.h>
+#include <net/ethernet.h>
#include <arpa/inet.h>
#include <stdio.h>
@@ -381,6 +382,7 @@
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],
@@ -393,6 +395,7 @@
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],
@@ -1419,6 +1422,31 @@
}
struct node_host *
+host_ether(const char *s)
+{
+ struct ether_addr addr;
+ struct node_host *h = NULL;
+
+ h = calloc(1, sizeof(*h));
+ if (h == NULL)
+ err(1, "host_ether: malloc");
+
+ if (strcmp(s, "multicast") == 0) {
+ h->addr_ether.flags = PFAE_CHECK | PFAE_MULTICAST;
+ return (h);
+ }
+ if (!ether_aton_r(s, &addr)) {
+ 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;
+
+ return (h);
+}
+
+struct node_host *
host_if(const char *s, int mask)
{
struct node_host *n, *h = NULL;
==== //depot/projects/soc2008/gk_l2filter/sbin-pfctl/pfctl_parser.h#2 (text+ko) ====
@@ -112,6 +112,7 @@
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;
@@ -296,6 +297,7 @@
struct node_host *ifa_exists(const char *);
struct node_host *ifa_lookup(const char *, int);
struct node_host *host(const char *);
+struct node_host *host_ether(const char *);
int append_addr(struct pfr_buffer *, char *, int);
int append_addr_host(struct pfr_buffer *,
==== //depot/projects/soc2008/gk_l2filter/sys-pf/net/pf.c#2 (text+ko) ====
@@ -335,6 +335,8 @@
kif, &key, PF_LAN_EXT); \
if (*state == NULL || (*state)->timeout == PFTM_PURGE) \
return (PF_DROP); \
+ if (!pf_state_check_ether(*state, pd, direction)) \
+ return (PF_DROP); \
if (direction == PF_OUT && \
(((*state)->rule.ptr->rt == PF_ROUTETO && \
(*state)->rule.ptr->direction == PF_OUT) || \
@@ -699,6 +701,67 @@
}
}
+static __inline int
+pf_addr_ether_pass(struct pf_addr_ether *want, u_int8_t *ea)
+{
+ static struct pf_addr_ether mask = {
+ .octet = { 0xff, 0xff, 0xff, 0xff, 0xff,0xff },
+ .flags = 0
+ };
+ if ((want->flags & PFAE_CHECK) == 0)
+ return (1);
+ if (want->flags & PFAE_MULTICAST) {
+ return (ETHER_IS_MULTICAST(ea));
+ }
+
+#define EA_CMP(a) (*((u_int64_t*)(a)) & *((u_int64_t*)&mask))
+ return (EA_CMP(want) == EA_CMP(ea));
+#undef EA_CMP
+}
+
+static __inline int
+pf_rule_check_ether(struct pf_rule *r, struct pf_pdesc *pd)
+{
+ if (!pd->eh) {
+ if ((r->src.addr_ether.flags & PFAE_CHECK) ||
+ (r->dst.addr_ether.flags & PFAE_CHECK))
+ return (0);
+ return (1);
+ }
+
+ if (pf_addr_ether_pass(&r->src.addr_ether, pd->eh->ether_shost) &&
+ pf_addr_ether_pass(&r->dst.addr_ether, pd->eh->ether_dhost))
+ return (1);
+
+ return (0);
+}
+
+static __inline int
+pf_state_check_ether(struct pf_state *state, struct pf_pdesc *pd, int direction)
+{
+ struct pf_rule *r;
+ struct pf_addr_ether *src, *dst;
+
+ if (!pd->eh)
+ return (1);
+
+ r = state->rule.ptr;
+
+ if (direction == state->direction) {
+ src = &r->src.addr_ether;
+ dst = &r->dst.addr_ether;
+ } else {
+ src = &r->dst.addr_ether;
+ dst = &r->src.addr_ether;
+ }
+
+ if (pf_addr_ether_pass(src, pd->eh->ether_shost) &&
+ pf_addr_ether_pass(dst, pd->eh->ether_dhost))
+ return (1);
+
+ return (0);
+}
+
void
pf_init_threshold(struct pf_threshold *threshold,
u_int32_t limit, u_int32_t seconds)
@@ -3356,6 +3419,8 @@
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_check_ether(r, pd))
+ r = TAILQ_NEXT(r, entries);
else {
if (r->tag)
tag = r->tag;
@@ -3775,6 +3840,8 @@
r = TAILQ_NEXT(r, entries);
else if (r->os_fingerprint != PF_OSFP_ANY)
r = TAILQ_NEXT(r, entries);
+ else if (!pf_rule_check_ether(r, pd))
+ r = TAILQ_NEXT(r, entries);
else {
if (r->tag)
tag = r->tag;
@@ -4112,6 +4179,8 @@
r = TAILQ_NEXT(r, entries);
else if (r->os_fingerprint != PF_OSFP_ANY)
r = TAILQ_NEXT(r, entries);
+ else if (!pf_rule_check_ether(r, pd))
+ r = TAILQ_NEXT(r, entries);
else {
if (r->tag)
tag = r->tag;
@@ -4371,6 +4440,8 @@
r = TAILQ_NEXT(r, entries);
else if (r->os_fingerprint != PF_OSFP_ANY)
r = TAILQ_NEXT(r, entries);
+ else if (!pf_rule_check_ether(r, pd))
+ r = TAILQ_NEXT(r, entries);
else {
if (r->tag)
tag = r->tag;
@@ -4596,6 +4667,8 @@
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_check_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#2 (text+ko) ====
@@ -165,6 +165,14 @@
#define PFI_AFLAG_MODEMASK 0x07
#define PFI_AFLAG_NOALIAS 0x08
+#define PFAE_CHECK 0x01
+#define PFAE_MULTICAST 0x02
+
+struct pf_addr_ether {
+ u_int8_t octet[6];
+ u_int16_t flags;
+};
+
struct pf_addr_wrap {
union {
struct {
@@ -436,6 +444,7 @@
u_int16_t port[2];
u_int8_t neg;
u_int8_t port_op;
+ struct pf_addr_ether addr_ether;
};
struct pf_pooladdr {
More information about the p4-projects
mailing list