summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/utils.h1
-rw-r--r--lib/utils.c35
-rw-r--r--tc/f_u32.c61
3 files changed, 64 insertions, 33 deletions
diff --git a/include/utils.h b/include/utils.h
index 7223a10d..5daed6b3 100644
--- a/include/utils.h
+++ b/include/utils.h
@@ -74,6 +74,7 @@ extern int get_addr_1(inet_prefix *dst, const char *arg, int family);
extern int get_prefix_1(inet_prefix *dst, char *arg, int family);
extern int get_addr(inet_prefix *dst, const char *arg, int family);
extern int get_prefix(inet_prefix *dst, char *arg, int family);
+extern int mask2bits(__u32 netmask);
extern int get_integer(int *val, const char *arg, int base);
extern int get_unsigned(unsigned *val, const char *arg, int base);
diff --git a/lib/utils.c b/lib/utils.c
index 84948513..d99deacd 100644
--- a/lib/utils.c
+++ b/lib/utils.c
@@ -47,27 +47,18 @@ int get_integer(int *val, const char *arg, int base)
return 0;
}
-/* a valid netmask must be 2^n - 1 */
-static int is_valid_netmask(const inet_prefix *addr)
-{
- uint32_t host;
-
- if (addr->family != AF_INET)
- return 0;
-
- host = ~ntohl(addr->data[0]);
-
- return (host & (host + 1)) == 0;
-}
-
-static unsigned cidr(const inet_prefix *addr)
+int mask2bits(__u32 netmask)
{
unsigned bits = 0;
- u_int32_t mask;
+ __u32 mask = ntohl(netmask);
+ __u32 host = ~mask;
- for (mask = ntohl(addr->data[0]); mask; mask <<= 1)
- ++bits;
+ /* a valid netmask must be 2^n - 1 */
+ if ((host & (host + 1)) != 0)
+ return -1;
+ for (; mask; mask <<= 1)
+ ++bits;
return bits;
}
@@ -79,11 +70,13 @@ static int get_netmask(unsigned *val, const char *arg, int base)
return 0;
/* try coverting dotted quad to CIDR */
- if (!get_addr_1(&addr, arg, AF_INET)) {
- if (is_valid_netmask(&addr))
+ if (!get_addr_1(&addr, arg, AF_INET) && addr.family == AF_INET) {
+ int b = mask2bits(addr.data[0]);
+
+ if (b >= 0) {
+ *val = b;
return 0;
-
- *val = cidr(&addr);
+ }
}
return -1;
diff --git a/tc/f_u32.c b/tc/f_u32.c
index 1ac671b3..91f2838b 100644
--- a/tc/f_u32.c
+++ b/tc/f_u32.c
@@ -473,7 +473,7 @@ done:
*argv_p = argv;
return res;
}
-
+
static int parse_ip6(int *argc_p, char ***argv_p, struct tc_u32_sel *sel)
{
int res = -1;
@@ -564,6 +564,7 @@ done:
return res;
}
+
static int parse_icmp(int *argc_p, char ***argv_p, struct tc_u32_sel *sel)
{
int res = -1;
@@ -771,7 +772,47 @@ static int parse_hashkey(int *argc_p, char ***argv_p, struct tc_u32_sel *sel)
return 0;
}
-static int u32_parse_opt(struct filter_util *qu, char *handle, int argc, char **argv, struct nlmsghdr *n)
+static void show_key(FILE *f, const struct tc_u32_key *key)
+{
+ char abuf[256];
+
+ if (show_raw)
+ goto raw;
+
+ switch (key->off) {
+ case 12:
+ case 16: {
+ int bits = mask2bits(key->mask);
+ if (bits >= 0) {
+ fprintf(f, "\n %s %s/%d\n",
+ key->off == 12 ? "src" : "dst",
+ inet_ntop(AF_INET, &key->val, abuf, sizeof(abuf)),
+ bits);
+ return;
+ }
+ }
+ break;
+
+ case 20:
+ case 22:
+ if (key->mask == ntohl(0xffff)) {
+ fprintf(f, "\n %s %u\n",
+ key->off == 20 ? "sport" : "dport",
+ (unsigned short) ntohl(key->val));
+ return;
+ }
+ }
+
+raw:
+ fprintf(f, "\n match %08x/%08x at %s%d",
+ (unsigned int)ntohl(key->val),
+ (unsigned int)ntohl(key->mask),
+ key->offmask ? "nexthdr+" : "",
+ key->off);
+}
+
+static int u32_parse_opt(struct filter_util *qu, char *handle,
+ int argc, char **argv, struct nlmsghdr *n)
{
struct {
struct tc_u32_sel sel;
@@ -966,7 +1007,8 @@ static int u32_parse_opt(struct filter_util *qu, char *handle, int argc, char **
return 0;
}
-static int u32_print_opt(struct filter_util *qu, FILE *f, struct rtattr *opt, __u32 handle)
+static int u32_print_opt(struct filter_util *qu, FILE *f, struct rtattr *opt,
+ __u32 handle)
{
struct rtattr *tb[TCA_U32_MAX+1];
struct tc_u32_sel *sel = NULL;
@@ -1037,17 +1079,12 @@ static int u32_print_opt(struct filter_util *qu, FILE *f, struct rtattr *opt, __
}
if (sel) {
- int i;
- struct tc_u32_key *key = sel->keys;
if (sel->nkeys) {
- for (i=0; i<sel->nkeys; i++, key++) {
- fprintf(f, "\n match %08x/%08x at %s%d",
- (unsigned int)ntohl(key->val),
- (unsigned int)ntohl(key->mask),
- key->offmask ? "nexthdr+" : "",
- key->off);
+ int i;
+ for (i=0; i<sel->nkeys; i++) {
+ show_key(f, sel->keys + i);
if (show_stats && NULL != pf)
- fprintf(f, " (success %lld ) ",
+ fprintf(f, " (success %llu ) ",
(unsigned long long) pf->kcnts[i]);
}
}