PERFORCE change 143248 for review
Gleb Kurtsou
gk at FreeBSD.org
Tue Jun 10 18:03:32 UTC 2008
http://perforce.freebsd.org/chv.cgi?CH=143248
Change 143248 by gk at gk_h1 on 2008/06/10 18:03:17
support filtering by mac in ipfw lookup tables
example:
~ # ipfw add allow ip from 'table(1)' to any in recv if_home
~ # ipfw table 1 add 192.168.1.1 ether 00:a0:c9:dd:23:47
Affected files ...
.. //depot/projects/soc2008/gk_l2filter/sbin-ipfw/ipfw2.c#3 edit
.. //depot/projects/soc2008/gk_l2filter/sys-netinet/ip_fw.h#4 edit
.. //depot/projects/soc2008/gk_l2filter/sys-netinet/ip_fw2.c#5 edit
Differences ...
==== //depot/projects/soc2008/gk_l2filter/sbin-ipfw/ipfw2.c#3 (text+ko) ====
@@ -5966,6 +5966,12 @@
if (lookup_host(*av, (struct in_addr *)&ent.addr) != 0)
errx(EX_NOHOST, "hostname ``%s'' unknown", *av);
ac--; av++;
+ ent.mac_addr = 0;
+ if (do_add && ac >= 2 && strcmp(*av, "mac") == 0) {
+ uint8_t mask[8];
+ get_mac_addr_mask(av[1], (uint8_t*)&ent.mac_addr, mask);
+ ac-=2; av+=2;
+ }
if (do_add && ac) {
unsigned int tval;
/* isdigit is a bit of a hack here.. */
@@ -6014,20 +6020,28 @@
err(EX_OSERR, "getsockopt(IP_FW_TABLE_LIST)");
for (a = 0; a < tbl->cnt; a++) {
unsigned int tval;
+ char tval_buf[128];
+ char tmac_buf[128];
tval = tbl->ent[a].value;
if (do_value_as_ip) {
- char tbuf[128];
- strncpy(tbuf, inet_ntoa(*(struct in_addr *)
- &tbl->ent[a].addr), 127);
/* inet_ntoa expects network order */
tval = htonl(tval);
- printf("%s/%u %s\n", tbuf, tbl->ent[a].masklen,
- inet_ntoa(*(struct in_addr *)&tval));
+ strlcpy(tval_buf, inet_ntoa(*(struct in_addr *)
+ &tval), sizeof(tval_buf));
+ } else {
+ snprintf(tval_buf, sizeof(tval_buf), "%u", tval);
+ }
+ if (tbl->ent[a].mac_addr) {
+ uint8_t *x = (uint8_t *)&tbl->ent[a].mac_addr;
+ snprintf(tmac_buf, sizeof(tmac_buf), "mac %02x:%02x:%02x:%02x:%02x:%02x ",
+ x[0], x[1], x[2], x[3], x[4], x[5]);
} else {
- printf("%s/%u %u\n",
- inet_ntoa(*(struct in_addr *)&tbl->ent[a].addr),
- tbl->ent[a].masklen, tval);
+ tmac_buf[0] = 0;
}
+
+ printf("%s/%u %s%s\n",
+ inet_ntoa(*(struct in_addr *)&tbl->ent[a].addr),
+ tbl->ent[a].masklen, tmac_buf, tval_buf);
}
} else
errx(EX_USAGE, "invalid table command %s", *av);
==== //depot/projects/soc2008/gk_l2filter/sys-netinet/ip_fw.h#4 (text+ko) ====
@@ -533,6 +533,7 @@
*/
typedef struct _ipfw_table_entry {
in_addr_t addr; /* network address */
+ u_int64_t mac_addr; /* mac address */
u_int32_t value; /* value */
u_int16_t tbl; /* table number */
u_int8_t masklen; /* mask length */
==== //depot/projects/soc2008/gk_l2filter/sys-netinet/ip_fw2.c#5 (text+ko) ====
@@ -153,6 +153,7 @@
struct table_entry {
struct radix_node rn[2];
struct sockaddr_in addr, mask;
+ u_int64_t mac_addr;
u_int32_t value;
};
@@ -1752,7 +1753,7 @@
static int
add_table_entry(struct ip_fw_chain *ch, uint16_t tbl, in_addr_t addr,
- uint8_t mlen, uint32_t value)
+ uint8_t mlen, u_int64_t mac_addr, uint32_t value)
{
struct radix_node_head *rnh;
struct table_entry *ent;
@@ -1767,6 +1768,7 @@
ent->addr.sin_len = ent->mask.sin_len = 8;
ent->mask.sin_addr.s_addr = htonl(mlen ? ~((1 << (32 - mlen)) - 1) : 0);
ent->addr.sin_addr.s_addr = addr & ent->mask.sin_addr.s_addr;
+ ent->mac_addr = mac_addr;
IPFW_WLOCK(&layer3_chain);
if (rnh->rnh_addaddr(&ent->addr, &ent->mask, rnh, (void *)ent) ==
NULL) {
@@ -1861,7 +1863,7 @@
static int
lookup_table(struct ip_fw_chain *ch, uint16_t tbl, in_addr_t addr,
- uint32_t *val)
+ struct ether_addr *ea, uint32_t *val)
{
struct radix_node_head *rnh;
struct table_entry *ent;
@@ -1874,6 +1876,10 @@
sa.sin_addr.s_addr = addr;
ent = (struct table_entry *)(rnh->rnh_lookup(&sa, NULL, rnh));
if (ent != NULL) {
+ if (ea && ent->mac_addr) {
+ if (ent->mac_addr != ((*(u_int64_t*)ea)))
+ return (0);
+ }
*val = ent->value;
return (1);
}
@@ -1918,6 +1924,7 @@
else
ent->masklen = 33 - ffs(ntohl(n->mask.sin_addr.s_addr));
ent->addr = n->addr.sin_addr.s_addr;
+ ent->mac_addr = n->mac_addr;
ent->value = n->value;
tbl->cnt++;
return (0);
@@ -2649,13 +2656,19 @@
case O_IP_SRC_LOOKUP:
case O_IP_DST_LOOKUP:
if (is_ipv4) {
+ struct ether_addr *ea = NULL;
uint32_t a =
(cmd->opcode == O_IP_DST_LOOKUP) ?
dst_ip.s_addr : src_ip.s_addr;
uint32_t v;
+ if (args->eh) {
+ ea = (struct ether_addr*)((cmd->opcode == O_IP_DST_LOOKUP) ?
+ args->eh->ether_dhost :
+ args->eh->ether_shost);
+ }
match = lookup_table(chain, cmd->arg1, a,
- &v);
+ ea, &v);
if (!match)
break;
if (cmdlen == F_INSN_SIZE(ipfw_insn_u32))
@@ -4267,7 +4280,7 @@
if (error)
break;
error = add_table_entry(&layer3_chain, ent.tbl,
- ent.addr, ent.masklen, ent.value);
+ ent.addr, ent.masklen, ent.mac_addr, ent.value);
}
break;
More information about the p4-projects
mailing list