summaryrefslogtreecommitdiffstats
path: root/sbin/ipfw
diff options
context:
space:
mode:
Diffstat (limited to 'sbin/ipfw')
-rw-r--r--sbin/ipfw/dummynet.c9
-rw-r--r--sbin/ipfw/ipfw2.c36
-rw-r--r--sbin/ipfw/ipfw2.h3
-rw-r--r--sbin/ipfw/tables.c133
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
OpenPOWER on IntegriCloud