mirror of
https://git.kernel.org/pub/scm/network/iproute2/iproute2.git
synced 2024-11-15 22:15:13 +08:00
8589eb4efd
Every tool in the iproute2 package have one or more function to show an help message to the user. Some of these functions print the help line by line with a series of printf call, e.g. ip/xfrm_state.c does 60 fprintf calls. If we group all the calls to a single one and just concatenate strings, we save a lot of libc calls and thus object size. The size difference of the compiled binaries calculated with bloat-o-meter is: ip/ip: add/remove: 0/0 grow/shrink: 5/15 up/down: 103/-4796 (-4693) Total: Before=672591, After=667898, chg -0.70% ip/rtmon: add/remove: 0/0 grow/shrink: 0/1 up/down: 0/-54 (-54) Total: Before=48879, After=48825, chg -0.11% tc/tc: add/remove: 0/2 grow/shrink: 31/10 up/down: 882/-6133 (-5251) Total: Before=351912, After=346661, chg -1.49% bridge/bridge: add/remove: 0/0 grow/shrink: 0/1 up/down: 0/-459 (-459) Total: Before=70502, After=70043, chg -0.65% misc/lnstat: add/remove: 0/1 grow/shrink: 1/0 up/down: 48/-486 (-438) Total: Before=9960, After=9522, chg -4.40% tipc/tipc: add/remove: 0/0 grow/shrink: 1/1 up/down: 18/-62 (-44) Total: Before=79182, After=79138, chg -0.06% While at it, indent some strings which were starting at column 0, and use tabs where possible, to have a consistent style across helps. Signed-off-by: Matteo Croce <mcroce@redhat.com> Signed-off-by: David Ahern <dsahern@gmail.com>
166 lines
3.9 KiB
C
166 lines
3.9 KiB
C
/*
|
|
* f_fw.c FW filter.
|
|
*
|
|
* This program is free software; you can redistribute 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: Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru>
|
|
*
|
|
*/
|
|
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <unistd.h>
|
|
#include <fcntl.h>
|
|
#include <sys/socket.h>
|
|
#include <netinet/in.h>
|
|
#include <arpa/inet.h>
|
|
#include <string.h>
|
|
#include <linux/if.h> /* IFNAMSIZ */
|
|
#include "utils.h"
|
|
#include "tc_util.h"
|
|
|
|
static void explain(void)
|
|
{
|
|
fprintf(stderr,
|
|
"Usage: ... fw [ classid CLASSID ] [ indev DEV ] [ action ACTION_SPEC ]\n"
|
|
" CLASSID := Push matching packets to the class identified by CLASSID with format X:Y\n"
|
|
" CLASSID is parsed as hexadecimal input.\n"
|
|
" DEV := specify device for incoming device classification.\n"
|
|
" ACTION_SPEC := Apply an action on matching packets.\n"
|
|
" NOTE: handle is represented as HANDLE[/FWMASK].\n"
|
|
" FWMASK is 0xffffffff by default.\n");
|
|
}
|
|
|
|
static int fw_parse_opt(struct filter_util *qu, char *handle, int argc, char **argv, struct nlmsghdr *n)
|
|
{
|
|
struct tcmsg *t = NLMSG_DATA(n);
|
|
struct rtattr *tail;
|
|
__u32 mask = 0;
|
|
int mask_set = 0;
|
|
|
|
if (handle) {
|
|
char *slash;
|
|
|
|
if ((slash = strchr(handle, '/')) != NULL)
|
|
*slash = '\0';
|
|
if (get_u32(&t->tcm_handle, handle, 0)) {
|
|
fprintf(stderr, "Illegal \"handle\"\n");
|
|
return -1;
|
|
}
|
|
if (slash) {
|
|
if (get_u32(&mask, slash+1, 0)) {
|
|
fprintf(stderr, "Illegal \"handle\" mask\n");
|
|
return -1;
|
|
}
|
|
mask_set = 1;
|
|
}
|
|
}
|
|
|
|
if (argc == 0)
|
|
return 0;
|
|
|
|
tail = addattr_nest(n, 4096, TCA_OPTIONS);
|
|
|
|
if (mask_set)
|
|
addattr32(n, MAX_MSG, TCA_FW_MASK, mask);
|
|
|
|
while (argc > 0) {
|
|
if (matches(*argv, "classid") == 0 ||
|
|
matches(*argv, "flowid") == 0) {
|
|
unsigned int handle;
|
|
|
|
NEXT_ARG();
|
|
if (get_tc_classid(&handle, *argv)) {
|
|
fprintf(stderr, "Illegal \"classid\"\n");
|
|
return -1;
|
|
}
|
|
addattr_l(n, 4096, TCA_FW_CLASSID, &handle, 4);
|
|
} else if (matches(*argv, "police") == 0) {
|
|
NEXT_ARG();
|
|
if (parse_police(&argc, &argv, TCA_FW_POLICE, n)) {
|
|
fprintf(stderr, "Illegal \"police\"\n");
|
|
return -1;
|
|
}
|
|
continue;
|
|
} else if (matches(*argv, "action") == 0) {
|
|
NEXT_ARG();
|
|
if (parse_action(&argc, &argv, TCA_FW_ACT, n)) {
|
|
fprintf(stderr, "Illegal fw \"action\"\n");
|
|
return -1;
|
|
}
|
|
continue;
|
|
} else if (strcmp(*argv, "indev") == 0) {
|
|
char d[IFNAMSIZ+1] = {};
|
|
|
|
argc--;
|
|
argv++;
|
|
if (argc < 1) {
|
|
fprintf(stderr, "Illegal indev\n");
|
|
return -1;
|
|
}
|
|
strncpy(d, *argv, sizeof(d) - 1);
|
|
addattr_l(n, MAX_MSG, TCA_FW_INDEV, d, strlen(d) + 1);
|
|
} else if (strcmp(*argv, "help") == 0) {
|
|
explain();
|
|
return -1;
|
|
} else {
|
|
fprintf(stderr, "What is \"%s\"?\n", *argv);
|
|
explain();
|
|
return -1;
|
|
}
|
|
argc--; argv++;
|
|
}
|
|
addattr_nest_end(n, tail);
|
|
return 0;
|
|
}
|
|
|
|
static int fw_print_opt(struct filter_util *qu, FILE *f, struct rtattr *opt, __u32 handle)
|
|
{
|
|
struct rtattr *tb[TCA_FW_MAX+1];
|
|
|
|
if (opt == NULL)
|
|
return 0;
|
|
|
|
parse_rtattr_nested(tb, TCA_FW_MAX, opt);
|
|
|
|
if (handle || tb[TCA_FW_MASK]) {
|
|
__u32 mark = 0, mask = 0;
|
|
|
|
if (handle)
|
|
mark = handle;
|
|
if (tb[TCA_FW_MASK] &&
|
|
(mask = rta_getattr_u32(tb[TCA_FW_MASK])) != 0xFFFFFFFF)
|
|
fprintf(f, "handle 0x%x/0x%x ", mark, mask);
|
|
else
|
|
fprintf(f, "handle 0x%x ", handle);
|
|
}
|
|
|
|
if (tb[TCA_FW_CLASSID]) {
|
|
SPRINT_BUF(b1);
|
|
fprintf(f, "classid %s ", sprint_tc_classid(rta_getattr_u32(tb[TCA_FW_CLASSID]), b1));
|
|
}
|
|
|
|
if (tb[TCA_FW_POLICE])
|
|
tc_print_police(f, tb[TCA_FW_POLICE]);
|
|
if (tb[TCA_FW_INDEV]) {
|
|
struct rtattr *idev = tb[TCA_FW_INDEV];
|
|
|
|
fprintf(f, "input dev %s ", rta_getattr_str(idev));
|
|
}
|
|
|
|
if (tb[TCA_FW_ACT]) {
|
|
fprintf(f, "\n");
|
|
tc_print_action(f, tb[TCA_FW_ACT], 0);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
struct filter_util fw_filter_util = {
|
|
.id = "fw",
|
|
.parse_fopt = fw_parse_opt,
|
|
.print_fopt = fw_print_opt,
|
|
};
|