mirror_iproute2/tc/em_cmp.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

186 lines
4.6 KiB
C

/*
* em_cmp.c Simple comparison 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"
#include <linux/tc_ematch/tc_em_cmp.h>
extern struct ematch_util cmp_ematch_util;
static void cmp_print_usage(FILE *fd)
{
fprintf(fd,
"Usage: cmp(ALIGN at OFFSET [ ATTRS ] { eq | lt | gt } VALUE)\n" \
"where: ALIGN := { u8 | u16 | u32 }\n" \
" ATTRS := [ layer LAYER ] [ mask MASK ] [ trans ]\n" \
" LAYER := { link | network | transport | 0..%d }\n" \
"\n" \
"Example: cmp(u16 at 3 layer 2 mask 0xff00 gt 20)\n",
TCF_LAYER_MAX);
}
static int cmp_parse_eopt(struct nlmsghdr *n, struct tcf_ematch_hdr *hdr,
struct bstr *args)
{
struct bstr *a;
int align, opnd = 0;
unsigned long offset = 0, layer = TCF_LAYER_NETWORK, mask = 0, value = 0;
int offset_present = 0, value_present = 0;
struct tcf_em_cmp cmp = {};
#define PARSE_ERR(CARG, FMT, ARGS...) \
em_parse_error(EINVAL, args, CARG, &cmp_ematch_util, FMT, ##ARGS)
if (args == NULL)
return PARSE_ERR(args, "cmp: missing arguments");
if (!bstrcmp(args, "u8"))
align = TCF_EM_ALIGN_U8;
else if (!bstrcmp(args, "u16"))
align = TCF_EM_ALIGN_U16;
else if (!bstrcmp(args, "u32"))
align = TCF_EM_ALIGN_U32;
else
return PARSE_ERR(args, "cmp: invalid alignment");
for (a = bstr_next(args); a; a = bstr_next(a)) {
if (!bstrcmp(a, "at")) {
if (a->next == NULL)
return PARSE_ERR(a, "cmp: missing argument");
a = bstr_next(a);
offset = bstrtoul(a);
if (offset == ULONG_MAX)
return PARSE_ERR(a, "cmp: invalid offset, " \
"must be numeric");
offset_present = 1;
} else if (!bstrcmp(a, "layer")) {
if (a->next == NULL)
return PARSE_ERR(a, "cmp: missing argument");
a = bstr_next(a);
layer = parse_layer(a);
if (layer == INT_MAX) {
layer = bstrtoul(a);
if (layer == ULONG_MAX)
return PARSE_ERR(a, "cmp: invalid " \
"layer");
}
if (layer > TCF_LAYER_MAX)
return PARSE_ERR(a, "cmp: illegal layer, " \
"must be in 0..%d", TCF_LAYER_MAX);
} else if (!bstrcmp(a, "mask")) {
if (a->next == NULL)
return PARSE_ERR(a, "cmp: missing argument");
a = bstr_next(a);
mask = bstrtoul(a);
if (mask == ULONG_MAX)
return PARSE_ERR(a, "cmp: invalid mask");
} else if (!bstrcmp(a, "trans")) {
cmp.flags |= TCF_EM_CMP_TRANS;
} else if (!bstrcmp(a, "eq") || !bstrcmp(a, "gt") ||
!bstrcmp(a, "lt")) {
if (!bstrcmp(a, "eq"))
opnd = TCF_EM_OPND_EQ;
else if (!bstrcmp(a, "gt"))
opnd = TCF_EM_OPND_GT;
else if (!bstrcmp(a, "lt"))
opnd = TCF_EM_OPND_LT;
if (a->next == NULL)
return PARSE_ERR(a, "cmp: missing argument");
a = bstr_next(a);
value = bstrtoul(a);
if (value == ULONG_MAX)
return PARSE_ERR(a, "cmp: invalid value");
value_present = 1;
} else
return PARSE_ERR(a, "nbyte: unknown parameter");
}
if (offset_present == 0 || value_present == 0)
return PARSE_ERR(a, "cmp: offset and value required");
cmp.val = (__u32) value;
cmp.mask = (__u32) mask;
cmp.off = (__u16) offset;
cmp.align = (__u8) align;
cmp.layer = (__u8) layer;
cmp.opnd = (__u8) opnd;
addraw_l(n, MAX_MSG, hdr, sizeof(*hdr));
addraw_l(n, MAX_MSG, &cmp, sizeof(cmp));
#undef PARSE_ERR
return 0;
}
static int cmp_print_eopt(FILE *fd, struct tcf_ematch_hdr *hdr, void *data,
int data_len)
{
struct tcf_em_cmp *cmp = data;
if (data_len < sizeof(*cmp)) {
fprintf(stderr, "CMP header size mismatch\n");
return -1;
}
if (cmp->align == TCF_EM_ALIGN_U8)
fprintf(fd, "u8 ");
else if (cmp->align == TCF_EM_ALIGN_U16)
fprintf(fd, "u16 ");
else if (cmp->align == TCF_EM_ALIGN_U32)
fprintf(fd, "u32 ");
fprintf(fd, "at %d layer %d ", cmp->off, cmp->layer);
if (cmp->mask)
fprintf(fd, "mask 0x%x ", cmp->mask);
if (cmp->flags & TCF_EM_CMP_TRANS)
fprintf(fd, "trans ");
if (cmp->opnd == TCF_EM_OPND_EQ)
fprintf(fd, "eq ");
else if (cmp->opnd == TCF_EM_OPND_LT)
fprintf(fd, "lt ");
else if (cmp->opnd == TCF_EM_OPND_GT)
fprintf(fd, "gt ");
fprintf(fd, "%d", cmp->val);
return 0;
}
struct ematch_util cmp_ematch_util = {
.kind = "cmp",
.kind_num = TCF_EM_CMP,
.parse_eopt = cmp_parse_eopt,
.print_eopt = cmp_print_eopt,
.print_usage = cmp_print_usage
};