iproute2/tc/m_mirred.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

301 lines
6.1 KiB
C

/*
* m_egress.c ingress/egress packet mirror/redir actions module
*
* 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: J Hadi Salim (hadi@cyberus.ca)
*
* TODO: Add Ingress support
*
*/
#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 "utils.h"
#include "tc_util.h"
#include "tc_common.h"
#include <linux/tc_act/tc_mirred.h>
static void
explain(void)
{
fprintf(stderr, "Usage: mirred <DIRECTION> <ACTION> [index INDEX] <dev DEVICENAME>\n");
fprintf(stderr, "where:\n");
fprintf(stderr, "\tDIRECTION := <ingress | egress>\n");
fprintf(stderr, "\tACTION := <mirror | redirect>\n");
fprintf(stderr, "\tINDEX is the specific policy instance id\n");
fprintf(stderr, "\tDEVICENAME is the devicename\n");
}
static void
usage(void)
{
explain();
exit(-1);
}
static const char *mirred_n2a(int action)
{
switch (action) {
case TCA_EGRESS_REDIR:
return "Egress Redirect";
case TCA_INGRESS_REDIR:
return "Ingress Redirect";
case TCA_EGRESS_MIRROR:
return "Egress Mirror";
case TCA_INGRESS_MIRROR:
return "Ingress Mirror";
default:
return "unknown";
}
}
static int
parse_egress(struct action_util *a, int *argc_p, char ***argv_p,
int tca_id, struct nlmsghdr *n)
{
int argc = *argc_p;
char **argv = *argv_p;
int ok = 0, iok = 0, mirror = 0, redir = 0;
struct tc_mirred p = {};
struct rtattr *tail;
char d[16] = {};
while (argc > 0) {
if (matches(*argv, "action") == 0) {
break;
} else if (matches(*argv, "egress") == 0) {
NEXT_ARG();
ok++;
continue;
} else {
if (matches(*argv, "index") == 0) {
NEXT_ARG();
if (get_u32(&p.index, *argv, 10)) {
fprintf(stderr, "Illegal \"index\"\n");
return -1;
}
iok++;
if (!ok) {
argc--;
argv++;
break;
}
} else if (!ok) {
fprintf(stderr, "was expecting egress (%s)\n", *argv);
break;
} else if (!mirror && matches(*argv, "mirror") == 0) {
mirror = 1;
if (redir) {
fprintf(stderr, "Can't have both mirror and redir\n");
return -1;
}
p.eaction = TCA_EGRESS_MIRROR;
p.action = TC_ACT_PIPE;
ok++;
} else if (!redir && matches(*argv, "redirect") == 0) {
redir = 1;
if (mirror) {
fprintf(stderr, "Can't have both mirror and redir\n");
return -1;
}
p.eaction = TCA_EGRESS_REDIR;
p.action = TC_ACT_STOLEN;
ok++;
} else if ((redir || mirror) && matches(*argv, "dev") == 0) {
NEXT_ARG();
if (strlen(d))
duparg("dev", *argv);
strncpy(d, *argv, sizeof(d)-1);
argc--;
argv++;
break;
}
}
NEXT_ARG();
}
if (!ok && !iok) {
return -1;
}
if (d[0]) {
int idx;
ll_init_map(&rth);
if ((idx = ll_name_to_index(d)) == 0) {
fprintf(stderr, "Cannot find device \"%s\"\n", d);
return -1;
}
p.ifindex = idx;
}
if (argc && p.eaction == TCA_EGRESS_MIRROR) {
if (matches(*argv, "reclassify") == 0) {
p.action = TC_POLICE_RECLASSIFY;
NEXT_ARG();
} else if (matches(*argv, "pipe") == 0) {
p.action = TC_POLICE_PIPE;
NEXT_ARG();
} else if (matches(*argv, "drop") == 0 ||
matches(*argv, "shot") == 0) {
p.action = TC_POLICE_SHOT;
NEXT_ARG();
} else if (matches(*argv, "continue") == 0) {
p.action = TC_POLICE_UNSPEC;
NEXT_ARG();
} else if (matches(*argv, "pass") == 0 ||
matches(*argv, "ok") == 0) {
p.action = TC_POLICE_OK;
NEXT_ARG();
}
}
if (argc) {
if (iok && matches(*argv, "index") == 0) {
fprintf(stderr, "mirred: Illegal double index\n");
return -1;
} else {
if (matches(*argv, "index") == 0) {
NEXT_ARG();
if (get_u32(&p.index, *argv, 10)) {
fprintf(stderr, "mirred: Illegal \"index\"\n");
return -1;
}
argc--;
argv++;
}
}
}
tail = NLMSG_TAIL(n);
addattr_l(n, MAX_MSG, tca_id, NULL, 0);
addattr_l(n, MAX_MSG, TCA_MIRRED_PARMS, &p, sizeof(p));
tail->rta_len = (void *) NLMSG_TAIL(n) - (void *) tail;
*argc_p = argc;
*argv_p = argv;
return 0;
}
static int
parse_mirred(struct action_util *a, int *argc_p, char ***argv_p,
int tca_id, struct nlmsghdr *n)
{
int argc = *argc_p;
char **argv = *argv_p;
if (argc < 0) {
fprintf(stderr, "mirred bad argument count %d\n", argc);
return -1;
}
if (matches(*argv, "mirred") == 0) {
NEXT_ARG();
} else {
fprintf(stderr, "mirred bad argument %s\n", *argv);
return -1;
}
if (matches(*argv, "egress") == 0 || matches(*argv, "index") == 0) {
int ret = parse_egress(a, &argc, &argv, tca_id, n);
if (ret == 0) {
*argc_p = argc;
*argv_p = argv;
return 0;
}
} else if (matches(*argv, "ingress") == 0) {
fprintf(stderr, "mirred ingress not supported at the moment\n");
} else if (matches(*argv, "help") == 0) {
usage();
} else {
fprintf(stderr, "mirred option not supported %s\n", *argv);
}
return -1;
}
static int
print_mirred(struct action_util *au, FILE * f, struct rtattr *arg)
{
struct tc_mirred *p;
struct rtattr *tb[TCA_MIRRED_MAX + 1];
const char *dev;
SPRINT_BUF(b1);
if (arg == NULL)
return -1;
parse_rtattr_nested(tb, TCA_MIRRED_MAX, arg);
if (tb[TCA_MIRRED_PARMS] == NULL) {
fprintf(f, "[NULL mirred parameters]");
return -1;
}
p = RTA_DATA(tb[TCA_MIRRED_PARMS]);
/*
ll_init_map(&rth);
*/
if ((dev = ll_index_to_name(p->ifindex)) == 0) {
fprintf(stderr, "Cannot find device %d\n", p->ifindex);
return -1;
}
fprintf(f, "mirred (%s to device %s) %s", mirred_n2a(p->eaction), dev, action_n2a(p->action, b1, sizeof (b1)));
fprintf(f, "\n ");
fprintf(f, "\tindex %d ref %d bind %d", p->index, p->refcnt, p->bindcnt);
if (show_stats) {
if (tb[TCA_MIRRED_TM]) {
struct tcf_t *tm = RTA_DATA(tb[TCA_MIRRED_TM]);
print_tm(f, tm);
}
}
fprintf(f, "\n ");
return 0;
}
struct action_util mirred_action_util = {
.id = "mirred",
.parse_aopt = parse_mirred,
.print_aopt = print_mirred,
};