diff options
Diffstat (limited to 'sbin/ipfw')
-rw-r--r-- | sbin/ipfw/dummynet.c | 9 | ||||
-rw-r--r-- | sbin/ipfw/ipfw2.c | 36 | ||||
-rw-r--r-- | sbin/ipfw/ipfw2.h | 3 | ||||
-rw-r--r-- | sbin/ipfw/tables.c | 133 |
4 files changed, 167 insertions, 14 deletions
diff --git a/sbin/ipfw/dummynet.c b/sbin/ipfw/dummynet.c index 0aa3bb5c..c3a1d1e 100644 --- a/sbin/ipfw/dummynet.c +++ b/sbin/ipfw/dummynet.c @@ -23,6 +23,7 @@ */ #define NEW_AQM +#include <sys/limits.h> #include <sys/types.h> #include <sys/socket.h> /* XXX there are several sysctl leftover here */ @@ -794,7 +795,7 @@ is_valid_number(const char *s) * set clocking interface or bandwidth value */ static void -read_bandwidth(char *arg, int *bandwidth, char *if_name, int namelen) +read_bandwidth(char *arg, uint32_t *bandwidth, char *if_name, int namelen) { if (*bandwidth != -1) warnx("duplicate token, override bandwidth value!"); @@ -810,7 +811,7 @@ read_bandwidth(char *arg, int *bandwidth, char *if_name, int namelen) strlcpy(if_name, arg, namelen); *bandwidth = 0; } else { /* read bandwidth value */ - int bw; + uint64_t bw; char *end = NULL; bw = strtoul(arg, &end, 0); @@ -829,10 +830,10 @@ read_bandwidth(char *arg, int *bandwidth, char *if_name, int namelen) _substrcmp2(end, "by", "bytes") == 0) bw *= 8; - if (bw < 0) + if (bw > UINT_MAX) errx(EX_DATAERR, "bandwidth too large"); - *bandwidth = bw; + *bandwidth = (uint32_t)bw; if (if_name) if_name[0] = '\0'; } diff --git a/sbin/ipfw/ipfw2.c b/sbin/ipfw/ipfw2.c index 42722f5..0c51845 100644 --- a/sbin/ipfw/ipfw2.c +++ b/sbin/ipfw/ipfw2.c @@ -1293,6 +1293,19 @@ format_mac(struct buf_pr *bp, uint8_t *addr, uint8_t *mask) } static void +print_mac_lookup(struct buf_pr *bp, const struct format_opts *fo, ipfw_insn *cmd) +{ + char *t; + uint32_t *a = ((ipfw_insn_u32 *)cmd)->d; + + t = table_search_ctlv(fo->tstate, cmd->arg1); + bprintf(bp, " MAC table(%s", t); + if (F_LEN(cmd) == F_INSN_SIZE(ipfw_insn_u32)) + bprintf(bp, ",%u", *a); + bprintf(bp, ")"); +} + +static void print_mac(struct buf_pr *bp, ipfw_insn_mac *mac) { @@ -1493,6 +1506,9 @@ print_instruction(struct buf_pr *bp, const struct format_opts *fo, else bprintf(bp, " %u", cmd->arg1); break; + case O_MACADDR2_LOOKUP: + print_mac_lookup(bp, fo, cmd); + break; case O_MACADDR2: print_mac(bp, insntod(cmd, mac)); break; @@ -3337,7 +3353,7 @@ fill_iface(ipfw_insn_if *cmd, char *arg, int cblen, struct tidx *tstate) errx(EX_DATAERR, "bad ip address ``%s''", arg); } -static void +void get_mac_addr_mask(const char *p, uint8_t *addr, uint8_t *mask) { int i; @@ -3449,11 +3465,20 @@ fill_cmd(ipfw_insn *cmd, enum ipfw_opcodes opcode, int flags, uint16_t arg) * two microinstructions, and returns the pointer to the last one. */ static ipfw_insn * -add_mac(ipfw_insn *cmd, char *av[], int cblen) +add_mac(ipfw_insn *cmd, char *av[], int cblen, struct tidx *tstate) { ipfw_insn_mac *mac; - if ( ( av[0] == NULL ) || ( av[1] == NULL ) ) + if (av[0] == NULL) + errx(EX_DATAERR, "MAC dst src"); + + if (strncmp(av[0], "table(", 6) == 0) { + fill_table(cmd, av[0], O_MACADDR2_LOOKUP, tstate); + CHECK_CMDLEN; + return (cmd); + } + + if (av[1] == NULL) errx(EX_DATAERR, "MAC dst src"); cmd->opcode = O_MACADDR2; @@ -4772,8 +4797,9 @@ read_options: break; case TOK_MAC: - if (add_mac(cmd, av, cblen)) - av += 2; + if (add_mac(cmd, av, cblen, tstate)) + av += ((strncmp(*av, "table(", 6) == 0) ? + 1 : 2); break; case TOK_MACTYPE: diff --git a/sbin/ipfw/ipfw2.h b/sbin/ipfw/ipfw2.h index 9ed39e8..08a781f 100644 --- a/sbin/ipfw/ipfw2.h +++ b/sbin/ipfw/ipfw2.h @@ -262,6 +262,7 @@ enum tokens { TOK_UNLOCK, TOK_VLIST, TOK_OLIST, + TOK_ZEROCNT, /* NAT64 tokens */ TOK_NAT64STL, @@ -346,6 +347,8 @@ struct in6_addr; void n2mask(struct in6_addr *mask, int n); int contigmask(uint8_t *p, int len); +void get_mac_addr_mask(const char *p, uint8_t *addr, uint8_t *mask); + /* * Forward declarations to avoid include way too many headers. * C does not allow duplicated typedefs, so we use the base struct diff --git a/sbin/ipfw/tables.c b/sbin/ipfw/tables.c index 89bc363..5444870 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> @@ -53,6 +54,7 @@ static void table_lock(ipfw_obj_header *oh, int lock); static int table_swap(ipfw_obj_header *oh, char *second); static int table_get_info(ipfw_obj_header *oh, ipfw_xtable_info *i); static int table_show_info(ipfw_xtable_info *i, void *arg); +static void table_zerocnt(ipfw_obj_header *oh, int ac, char *av[]); static int table_destroy_one(ipfw_xtable_info *i, void *arg); static int table_flush_one(ipfw_xtable_info *i, void *arg); @@ -78,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 } @@ -113,6 +116,7 @@ static struct _s_x tablecmds[] = { { "atomic", TOK_ATOMIC }, { "lock", TOK_LOCK }, { "unlock", TOK_UNLOCK }, + { "zerocnt", TOK_ZEROCNT }, { NULL, 0 } }; @@ -297,6 +301,10 @@ ipfw_table_handler(int ac, char *av[]) ac--; av++; table_lookup(&oh, ac, av); break; + case TOK_ZEROCNT: + ac--; av++; + table_zerocnt(&oh, ac, av); + break; } } @@ -1134,11 +1142,65 @@ table_lookup(ipfw_obj_header *oh, int ac, char *av[]) table_show_entry(&xi, &xtent); } +static int +table_do_zerocnt(ipfw_obj_header *oh, char *key, ipfw_xtable_info *xi) +{ + char xbuf[sizeof(ipfw_obj_header) + sizeof(ipfw_obj_tentry)]; + ipfw_obj_tentry *tent; + uint8_t type; + uint32_t vmask; + + memcpy(xbuf, oh, sizeof(*oh)); + oh = (ipfw_obj_header *)xbuf; + tent = (ipfw_obj_tentry *)(oh + 1); + + memset(tent, 0, sizeof(*tent)); + tent->head.length = sizeof(*tent); + tent->idx = 1; + + tentry_fill_key(oh, tent, key, 0, &type, &vmask, xi); + oh->ntlv.type = type; + + if (do_set3(IP_FW_TABLE_XZEROCNT, &oh->opheader, sizeof(xbuf)) != 0) + return (errno); + + return (0); +} + +static void +table_zerocnt(ipfw_obj_header *oh, int ac, char *av[]) +{ + ipfw_xtable_info xi; + char key[64]; + int error; + + if (ac == 0) + errx(EX_USAGE, "address required"); + + strlcpy(key, *av, sizeof(key)); + + memset(&xi, 0, sizeof(xi)); + error = table_do_zerocnt(oh, key, &xi); + switch (error) { + case 0: + break; + case ESRCH: + errx(EX_UNAVAILABLE, "Table %s not found", oh->ntlv.name); + case ENOENT: + errx(EX_UNAVAILABLE, "Entry %s not found", *av); + case ENOTSUP: + errx(EX_UNAVAILABLE, "Table %s algo does not support " + "\"zero_cnt\" method", oh->ntlv.name); + default: + err(EX_OSERR, "getsockopt(IP_FW_TABLE_XZEROCNT)"); + } +} + static void tentry_fill_key_type(char *arg, ipfw_obj_tentry *tentry, uint8_t type, uint8_t tflags) { - char *p, *pp; + char *mac, *p, *pp; int mask, af; struct in6_addr *paddr, tmp; struct tflow_entry *tfe; @@ -1154,6 +1216,15 @@ tentry_fill_key_type(char *arg, ipfw_obj_tentry *tentry, uint8_t type, switch (type) { case IPFW_TABLE_ADDR: + /* Remove the ',' if exists */ + if ((p = strchr(arg, ',')) != NULL) { + *p = '\0'; + mac = p + 1; + if (ether_aton_r(mac, + (struct ether_addr *)&tentry->mac) == NULL) + errx(EX_DATAERR, "bad MAC address: %s", mac); + } + /* Remove / if exists */ if ((p = strchr(arg, '/')) != NULL) { *p = '\0'; @@ -1187,6 +1258,25 @@ 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; + af = AF_LINK; + } + break; case IPFW_TABLE_INTERFACE: /* Assume interface name. Copy significant data only */ mask = MIN(strlen(arg), IF_NAMESIZE - 1); @@ -1816,6 +1906,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]; @@ -1829,15 +1939,26 @@ table_show_entry(ipfw_xtable_info *i, ipfw_obj_tentry *tent) case IPFW_TABLE_ADDR: /* IPv4 or IPv6 prefixes */ inet_ntop(tent->subtype, &tent->k, tbuf, sizeof(tbuf)); - printf("%s/%u %s\n", tbuf, tent->masklen, pval); + if (tent->mac != 0) { + printf("%s/%u", tbuf, tent->masklen); + ether_ntoa_r((struct ether_addr *)&tent->mac, tbuf); + printf(" %s %s", tbuf, pval); + } else + printf("%s/%u %s", 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", pval); break; case IPFW_TABLE_INTERFACE: /* Interface names */ - printf("%s %s\n", tent->k.iface, pval); + printf("%s %s", tent->k.iface, pval); break; case IPFW_TABLE_NUMBER: /* numbers */ - printf("%u %s\n", tent->k.key, pval); + printf("%u %s", tent->k.key, pval); break; case IPFW_TABLE_FLOW: /* flows */ @@ -1880,8 +2001,10 @@ table_show_entry(ipfw_xtable_info *i, ipfw_obj_tentry *tent) comma = ","; } - printf(" %s\n", pval); + printf(" %s", pval); } + printf(" %ju %ju %ju\n", (uintmax_t)tent->pcnt, + (uintmax_t)tent->bcnt, (uintmax_t)tent->timestamp); } static int |