mirror_iproute2/tc/em_u32.c
Phil Sutter d17b136f7d Use C99 style initializers everywhere
This big patch was compiled by vimgrepping for memset calls and changing
to C99 initializer if applicable. One notable exception is the
initialization of union bpf_attr in tc/tc_bpf.c: changing it would break
for older gcc versions (at least <=3.4.6).

Calls to memset for struct rtattr pointer fields for parse_rtattr*()
were just dropped since they are not needed.

The changes here allowed the compiler to discover some unused variables,
so get rid of them, too.

Signed-off-by: Phil Sutter <phil@nwl.cc>
Acked-by: David Ahern <dsa@cumulusnetworks.com>
2016-07-20 12:05:24 -07:00

177 lines
3.9 KiB
C

/*
* em_u32.c U32 Ematch
*
* This program is free software; you can distribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version
* 2 of the License, or (at your option) any later version.
*
* Authors: Thomas Graf <tgraf@suug.ch>
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <syslog.h>
#include <fcntl.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <string.h>
#include <errno.h>
#include "m_ematch.h"
extern struct ematch_util u32_ematch_util;
static void u32_print_usage(FILE *fd)
{
fprintf(fd,
"Usage: u32(ALIGN VALUE MASK at [ nexthdr+ ] OFFSET)\n" \
"where: ALIGN := { u8 | u16 | u32 }\n" \
"\n" \
"Example: u32(u16 0x1122 0xffff at nexthdr+4)\n");
}
static int u32_parse_eopt(struct nlmsghdr *n, struct tcf_ematch_hdr *hdr,
struct bstr *args)
{
struct bstr *a;
int align, nh_len;
unsigned long key, mask, offmask = 0, offset;
struct tc_u32_key u_key = {};
#define PARSE_ERR(CARG, FMT, ARGS...) \
em_parse_error(EINVAL, args, CARG, &u32_ematch_util, FMT, ##ARGS)
if (args == NULL)
return PARSE_ERR(args, "u32: missing arguments");
if (!bstrcmp(args, "u8"))
align = 1;
else if (!bstrcmp(args, "u16"))
align = 2;
else if (!bstrcmp(args, "u32"))
align = 4;
else
return PARSE_ERR(args, "u32: invalid alignment");
a = bstr_next(args);
if (a == NULL)
return PARSE_ERR(a, "u32: missing key");
key = bstrtoul(a);
if (key == ULONG_MAX)
return PARSE_ERR(a, "u32: invalid key, must be numeric");
a = bstr_next(a);
if (a == NULL)
return PARSE_ERR(a, "u32: missing mask");
mask = bstrtoul(a);
if (mask == ULONG_MAX)
return PARSE_ERR(a, "u32: invalid mask, must be numeric");
a = bstr_next(a);
if (a == NULL || bstrcmp(a, "at") != 0)
return PARSE_ERR(a, "u32: missing \"at\"");
a = bstr_next(a);
if (a == NULL)
return PARSE_ERR(a, "u32: missing offset");
nh_len = strlen("nexthdr+");
if (a->len > nh_len && !memcmp(a->data, "nexthdr+", nh_len)) {
char buf[a->len - nh_len + 1];
offmask = -1;
memcpy(buf, a->data + nh_len, a->len - nh_len);
offset = strtoul(buf, NULL, 0);
} else if (!bstrcmp(a, "nexthdr+")) {
a = bstr_next(a);
if (a == NULL)
return PARSE_ERR(a, "u32: missing offset");
offset = bstrtoul(a);
} else
offset = bstrtoul(a);
if (offset == ULONG_MAX)
return PARSE_ERR(a, "u32: invalid offset");
if (a->next)
return PARSE_ERR(a->next, "u32: unexpected trailer");
switch (align) {
case 1:
if (key > 0xFF)
return PARSE_ERR(a, "Illegal key (>0xFF)");
if (mask > 0xFF)
return PARSE_ERR(a, "Illegal mask (>0xFF)");
key <<= 24 - ((offset & 3) * 8);
mask <<= 24 - ((offset & 3) * 8);
offset &= ~3;
break;
case 2:
if (key > 0xFFFF)
return PARSE_ERR(a, "Illegal key (>0xFFFF)");
if (mask > 0xFFFF)
return PARSE_ERR(a, "Illegal mask (>0xFFFF)");
if ((offset & 3) == 0) {
key <<= 16;
mask <<= 16;
}
offset &= ~3;
break;
}
key = htonl(key);
mask = htonl(mask);
if (offset % 4)
return PARSE_ERR(a, "u32: invalid offset alignment, " \
"must be aligned to 4.");
key &= mask;
u_key.mask = mask;
u_key.val = key;
u_key.off = offset;
u_key.offmask = offmask;
addraw_l(n, MAX_MSG, hdr, sizeof(*hdr));
addraw_l(n, MAX_MSG, &u_key, sizeof(u_key));
#undef PARSE_ERR
return 0;
}
static int u32_print_eopt(FILE *fd, struct tcf_ematch_hdr *hdr, void *data,
int data_len)
{
struct tc_u32_key *u_key = data;
if (data_len < sizeof(*u_key)) {
fprintf(stderr, "U32 header size mismatch\n");
return -1;
}
fprintf(fd, "%08x/%08x at %s%d",
(unsigned int) ntohl(u_key->val),
(unsigned int) ntohl(u_key->mask),
u_key->offmask ? "nexthdr+" : "",
u_key->off);
return 0;
}
struct ematch_util u32_ematch_util = {
.kind = "u32",
.kind_num = TCF_EM_U32,
.parse_eopt = u32_parse_eopt,
.print_eopt = u32_print_eopt,
.print_usage = u32_print_usage
};