diff options
author | Luiz Otavio O Souza <luiz@netgate.com> | 2016-10-17 11:42:07 -0500 |
---|---|---|
committer | Luiz Otavio O Souza <luiz@netgate.com> | 2016-10-17 11:42:07 -0500 |
commit | 1fc9408b335ef6e8863019212c12a4bc99ed8e75 (patch) | |
tree | d596bf9272949b7a08a45bf2748cb22ad93856e5 /sbin/ipfw/tables.c | |
parent | 8e8562b56cdfb18651bb57597721fe3abb96796d (diff) | |
download | FreeBSD-src-1fc9408b335ef6e8863019212c12a4bc99ed8e75.zip FreeBSD-src-1fc9408b335ef6e8863019212c12a4bc99ed8e75.tar.gz |
Add ipfw support to MAC address tables.
The l2 filter implementation on ipfw works with MAC address pairs as it happens on wire (first destination and then source).
The table entries works in the same way, but the MAC address pair has to be passed in a single argument:
$ ipfw table create l2 type mac
$ ipfw table add "00:01:02:03:04:05 0a:0b:0c:0d:0e:0f"
added: 00:01:02:03:04:05 0a:0b:0c:0d:0e:0f 0
$ ipfw table add "00:01:02:03:04:05 any"
added: 00:01:02:03:04:05 any 0
$ ipfw table l2 add "any 0a:0b:0c:0d:0e:0f"
added: any 0a:0b:0c:0d:0e:0f 0
The MAC tables can also hold an optinal value used to implement additional features (skipto, fib, pipe, tag, nat, ...).
$ ipfw table l2 add "00:01:02:03:04:05 0a:0b:0c:0d:0e:ff" 1234
added: 00:01:02:03:04:05 0a:0b:0c:0d:0e:ff 1234
$ ipfw table l2 list
--- table(l2), set(0) ---
00:01:02:03:04:05 0a:0b:0c:0d:0e:0f 0
any 0a:0b:0c:0d:0e:0f 0
00:01:02:03:04:05 any 0
00:01:02:03:04:05 0a:0b:0c:0d:0e:ff 1234
Rule example:
$ ipfw add pass MAC 1:2:3:4:5:6 2:3:4:5:6:7 via igb0
00100 allow ip from any to any MAC 01:02:03:04:05:06 02:03:04:05:06:07 via igb0
$ ipfw add pass MAC table\(l2\) via igb0
00000 allow ip from any to any MAC table(l2) via igb0
$ ipfw list
00100 allow ip from any to any MAC 01:02:03:04:05:06 02:03:04:05:06:07 via igb0
00200 allow ip from any to any MAC table(l2) via igb0
00300 allow ip from any to any
65535 deny ip from any to any
Diffstat (limited to 'sbin/ipfw/tables.c')
-rw-r--r-- | sbin/ipfw/tables.c | 48 |
1 files changed, 48 insertions, 0 deletions
diff --git a/sbin/ipfw/tables.c b/sbin/ipfw/tables.c index 5b0dd95..704e706 100644 --- a/sbin/ipfw/tables.c +++ b/sbin/ipfw/tables.c @@ -31,6 +31,7 @@ #include <string.h> #include <sysexits.h> +#include <net/ethernet.h> #include <net/if.h> #include <netinet/in.h> #include <netinet/ip_fw.h> @@ -79,6 +80,7 @@ static int tables_foreach(table_cb_t *f, void *arg, int sort); static struct _s_x tabletypes[] = { { "addr", IPFW_TABLE_ADDR }, { "iface", IPFW_TABLE_INTERFACE }, + { "mac", IPFW_TABLE_MAC2 }, { "number", IPFW_TABLE_NUMBER }, { "flow", IPFW_TABLE_FLOW }, { NULL, 0 } @@ -1161,6 +1163,26 @@ tentry_fill_key_type(char *arg, ipfw_obj_tentry *tentry, uint8_t type, af = AF_INET; } break; + case IPFW_TABLE_MAC2: { + char *src, *dst; + struct mac_entry *mac; + + dst = arg; + if ((p = strchr(arg, ' ')) == NULL) + errx(EX_DATAERR, "bad mac address pair: %s", arg); + *p = '\0'; + src = p + 1; + + mac = (struct mac_entry *)&tentry->k.mac; + get_mac_addr_mask(dst, mac->addr, mac->mask); /* dst */ + get_mac_addr_mask(src, &(mac->addr[ETHER_ADDR_LEN]), + &(mac->mask[ETHER_ADDR_LEN])); /* src */ + + masklen = ETHER_ADDR_LEN * 8; + type = IPFW_TABLE_MAC2; + af = AF_LINK; + } + break; case IPFW_TABLE_INTERFACE: /* Assume interface name. Copy significant data only */ mask = MIN(strlen(arg), IF_NAMESIZE - 1); @@ -1793,6 +1815,26 @@ table_show_value(char *buf, size_t bufsize, ipfw_table_value *v, } static void +print_mac(uint8_t *addr, uint8_t *mask) +{ + int l; + + l = contigmask(mask, 48); + if (l == 0) + printf(" any"); + else { + printf(" %02x:%02x:%02x:%02x:%02x:%02x", + addr[0], addr[1], addr[2], addr[3], addr[4], addr[5]); + if (l == -1) + printf("&%02x:%02x:%02x:%02x:%02x:%02x", + mask[0], mask[1], mask[2], + mask[3], mask[4], mask[5]); + else if (l < 48) + printf("/%d", l); + } +} + +static void table_show_entry(ipfw_xtable_info *i, ipfw_obj_tentry *tent) { char *comma, tbuf[128], pval[128]; @@ -1808,6 +1850,12 @@ table_show_entry(ipfw_xtable_info *i, ipfw_obj_tentry *tent) inet_ntop(tent->subtype, &tent->k, tbuf, sizeof(tbuf)); printf("%s/%u %s\n", tbuf, tent->masklen, pval); break; + case IPFW_TABLE_MAC2: + /* Ethernet MAC address */ + print_mac(tent->k.mac.addr, tent->k.mac.mask); + print_mac(tent->k.mac.addr + 6, tent->k.mac.mask + 6); + printf(" %s\n", pval); + break; case IPFW_TABLE_INTERFACE: /* Interface names */ printf("%s %s\n", tent->k.iface, pval); |