Merge branch 'master' into net-next

This commit is contained in:
Stephen Hemminger 2016-06-14 16:33:24 -07:00
commit 5c05c1d4a2
7 changed files with 302 additions and 196 deletions

View File

@ -75,8 +75,11 @@ static void usage(void)
fprintf(stderr, "Usage: ip address {add|change|replace} IFADDR dev IFNAME [ LIFETIME ]\n");
fprintf(stderr, " [ CONFFLAG-LIST ]\n");
fprintf(stderr, " ip address del IFADDR dev IFNAME [mngtmpaddr]\n");
fprintf(stderr, " ip address {show|save|flush} [ dev IFNAME ] [ scope SCOPE-ID ]\n");
fprintf(stderr, " ip address {save|flush} [ dev IFNAME ] [ scope SCOPE-ID ]\n");
fprintf(stderr, " [ to PREFIX ] [ FLAG-LIST ] [ label LABEL ] [up]\n");
fprintf(stderr, " ip address [ show [ dev IFNAME ] [ scope SCOPE-ID ] [ master DEVICE ]\n");
fprintf(stderr, " [ type TYPE ] [ to PREFIX ] [ FLAG-LIST ]\n");
fprintf(stderr, " [ label LABEL ] [up] ]\n");
fprintf(stderr, " ip address {showdump|restore}\n");
fprintf(stderr, "IFADDR := PREFIX | ADDR peer PREFIX\n");
fprintf(stderr, " [ broadcast ADDR ] [ anycast ADDR ]\n");
@ -90,6 +93,10 @@ static void usage(void)
fprintf(stderr, "CONFFLAG := [ home | nodad | mngtmpaddr | noprefixroute | autojoin ]\n");
fprintf(stderr, "LIFETIME := [ valid_lft LFT ] [ preferred_lft LFT ]\n");
fprintf(stderr, "LFT := forever | SECONDS\n");
fprintf(stderr, "TYPE := { vlan | veth | vcan | dummy | ifb | macvlan | macvtap |\n");
fprintf(stderr, " bridge | bond | ipoib | ip6tnl | ipip | sit | vxlan |\n");
fprintf(stderr, " gre | gretap | ip6gre | ip6gretap | vti | nlmon |\n");
fprintf(stderr, " bond_slave | ipvlan | geneve | bridge_slave | vrf }\n");
exit(-1);
}
@ -1613,7 +1620,7 @@ static int ipaddr_list_flush_or_save(int argc, char **argv, int action)
if (!ifindex)
invarg("Device does not exist\n", *argv);
filter.master = ifindex;
} else if (do_link && strcmp(*argv, "type") == 0) {
} else if (strcmp(*argv, "type") == 0) {
NEXT_ARG();
filter.kind = *argv;
} else {

View File

@ -924,6 +924,7 @@ __u8 *hexstring_a2n(const char *str, __u8 *buf, int blen, unsigned int *len)
strncpy(tmpstr, str, 2);
tmpstr[2] = '\0';
errno = 0;
tmp = strtoul(tmpstr, &endptr, 16);
if (errno != 0 || tmp > 0xFF || *endptr != '\0')
return NULL;

View File

@ -23,7 +23,7 @@ ip-address \- protocol address management
.IB IFADDR " dev " IFNAME " [ " mngtmpaddr " ]"
.ti -8
.BR "ip address" " { " show " | " save " | " flush " } [ " dev
.BR "ip address" " { " save " | " flush " } [ " dev
.IR IFNAME " ] [ "
.B scope
.IR SCOPE-ID " ] [ "
@ -32,6 +32,21 @@ ip-address \- protocol address management
.B label
.IR PATTERN " ] [ " up " ]"
.ti -8
.BR "ip address" " [ " show " [ " dev
.IR IFNAME " ] [ "
.B scope
.IR SCOPE-ID " ] [ "
.B to
.IR PREFIX " ] [ " FLAG-LIST " ] [ "
.B label
.IR PATTERN " ] [ "
.B master
.IR DEVICE " ] [ "
.B type
.IR TYPE " ] [ "
.BR up " ] ]"
.ti -8
.BR "ip address" " { " showdump " | " restore " }"
@ -80,6 +95,34 @@ ip-address \- protocol address management
.BR forever " |"
.IR SECONDS " ]"
.ti -8
.IR TYPE " := [ "
.BR bridge " | "
.BR bond " | "
.BR can " | "
.BR dummy " | "
.BR hsr " | "
.BR ifb " | "
.BR ipoib " |"
.BR macvlan " | "
.BR macvtap " | "
.BR vcan " | "
.BR veth " | "
.BR vlan " | "
.BR vxlan " |"
.BR ip6tnl " |"
.BR ipip " |"
.BR sit " |"
.BR gre " |"
.BR gretap " |"
.BR ip6gre " |"
.BR ip6gretap " |"
.BR vti " |"
.BR nlmon " |"
.BR ipvlan " |"
.BR lowpan " |"
.BR geneve " ]"
.SH "DESCRIPTION"
The
.B address
@ -229,6 +272,14 @@ only list addresses with labels matching the
.I PATTERN
is a usual shell style pattern.
.TP
.BI master " DEVICE"
only list interfaces enslaved to this master device.
.TP
.BI type " TYPE"
only list interfaces of the given type.
.TP
.B up
only list running interfaces.
@ -280,8 +331,8 @@ This command flushes the protocol addresses selected by some criteria.
.PP
This command has the same arguments as
.B show.
The difference is that it does not run when no arguments are given.
.BR show " except that " type " and " master " selectors are not supported."
Another difference is that it does not run when no arguments are given.
.PP
.B Warning:

View File

@ -141,6 +141,8 @@ ip-link \- network device configuration
.br
.RB "[ " spoofchk " { " on " | " off " } ]"
.br
.RB "[ " query_rss " { " on " | " off " } ]"
.br
.RB "[ " state " { " auto " | " enable " | " disable " } ]"
.br
.RB "[ " trust " { " on " | " off " } ] ]"
@ -1159,6 +1161,9 @@ parameter must be specified.
.BI spoofchk " on|off"
- turn packet spoof checking on or off for the specified VF.
.sp
.BI query_rss " on|off"
- toggle the ability of querying the RSS configuration of a specific VF. VF RSS information like RSS hash key may be considered sensitive on some devices where this information is shared between VF and PF and thus its querying may be prohibited by default.
.sp
.BI state " auto|enable|disable"
- set the virtual link state as seen by the specified VF. Setting to auto means a
reflection of the PF link state, enable lets the VF to communicate with other VFs on

View File

@ -30,16 +30,18 @@ extern int show_pretty;
static void explain(void)
{
fprintf(stderr, "Usage: ... u32 [ match SELECTOR ... ] [ link HTID ] [ classid CLASSID ]\n");
fprintf(stderr, " [ action ACTION_SPEC ] [ offset OFFSET_SPEC ]\n");
fprintf(stderr, " [ ht HTID ] [ hashkey HASHKEY_SPEC ]\n");
fprintf(stderr, " [ sample SAMPLE ]\n");
fprintf(stderr, "or u32 divisor DIVISOR\n");
fprintf(stderr, "\n");
fprintf(stderr, "Where: SELECTOR := SAMPLE SAMPLE ...\n");
fprintf(stderr, " SAMPLE := { ip | ip6 | udp | tcp | icmp | u{32|16|8} | mark } SAMPLE_ARGS [divisor DIVISOR]\n");
fprintf(stderr, " FILTERID := X:Y:Z\n");
fprintf(stderr, "\nNOTE: CLASSID is parsed at hexadecimal input.\n");
fprintf(stderr,
"Usage: ... u32 [ match SELECTOR ... ] [ link HTID ] [ classid CLASSID ]\n"
" [ action ACTION_SPEC ] [ offset OFFSET_SPEC ]\n"
" [ ht HTID ] [ hashkey HASHKEY_SPEC ]\n"
" [ sample SAMPLE ] [skip-hw | skip-sw]\n"
"or u32 divisor DIVISOR\n"
"\n"
"Where: SELECTOR := SAMPLE SAMPLE ...\n"
" SAMPLE := { ip | ip6 | udp | tcp | icmp | u{32|16|8} | mark }\n"
" SAMPLE_ARGS [ divisor DIVISOR ]\n"
" FILTERID := X:Y:Z\n"
"\nNOTE: CLASSID is parsed at hexadecimal input.\n");
}
static int get_u32_handle(__u32 *handle, const char *str)
@ -993,6 +995,7 @@ static int u32_parse_opt(struct filter_util *qu, char *handle,
int sample_ok = 0;
__u32 htid = 0;
__u32 order = 0;
__u32 flags = 0;
memset(&sel, 0, sizeof(sel));
@ -1152,6 +1155,14 @@ static int u32_parse_opt(struct filter_util *qu, char *handle,
}
terminal_ok++;
continue;
} else if (strcmp(*argv, "skip_hw") == 0) {
NEXT_ARG();
flags |= TCA_CLS_FLAGS_SKIP_HW;
continue;
} else if (strcmp(*argv, "skip_sw") == 0) {
NEXT_ARG();
flags |= TCA_CLS_FLAGS_SKIP_SW;
continue;
} else if (strcmp(*argv, "help") == 0) {
explain();
return -1;
@ -1182,6 +1193,16 @@ static int u32_parse_opt(struct filter_util *qu, char *handle,
addattr_l(n, MAX_MSG, TCA_U32_SEL, &sel,
sizeof(sel.sel) +
sel.sel.nkeys * sizeof(struct tc_u32_key));
if (flags) {
if (!(flags ^ (TCA_CLS_FLAGS_SKIP_HW |
TCA_CLS_FLAGS_SKIP_SW))) {
fprintf(stderr,
"skip_hw and skip_sw are mutually exclusive\n");
return -1;
}
addattr_l(n, MAX_MSG, TCA_U32_FLAGS, &flags, 4);
}
tail->rta_len = (void *) NLMSG_TAIL(n) - (void *) tail;
return 0;
}
@ -1202,9 +1223,9 @@ static int u32_print_opt(struct filter_util *qu, FILE *f, struct rtattr *opt,
SPRINT_BUF(b1);
fprintf(f, "fh %s ", sprint_u32_handle(handle, b1));
}
if (TC_U32_NODE(handle)) {
if (TC_U32_NODE(handle))
fprintf(f, "order %d ", TC_U32_NODE(handle));
}
if (tb[TCA_U32_SEL]) {
if (RTA_PAYLOAD(tb[TCA_U32_SEL]) < sizeof(*sel))
@ -1240,6 +1261,15 @@ static int u32_print_opt(struct filter_util *qu, FILE *f, struct rtattr *opt,
b1));
}
if (tb[TCA_U32_FLAGS]) {
__u32 flags = rta_getattr_u32(tb[TCA_U32_FLAGS]);
if (flags & TCA_CLS_FLAGS_SKIP_HW)
fprintf(f, "skip_hw ");
if (flags & TCA_CLS_FLAGS_SKIP_SW)
fprintf(f, "skip_sw ");
}
if (tb[TCA_U32_PCNT]) {
if (RTA_PAYLOAD(tb[TCA_U32_PCNT]) < sizeof(*pf)) {
fprintf(f, "Broken perf counters\n");
@ -1298,14 +1328,15 @@ static int u32_print_opt(struct filter_util *qu, FILE *f, struct rtattr *opt,
fprintf(f, "\n");
tc_print_police(f, tb[TCA_U32_POLICE]);
}
if (tb[TCA_U32_INDEV]) {
struct rtattr *idev = tb[TCA_U32_INDEV];
fprintf(f, "\n input dev %s\n", rta_getattr_str(idev));
}
if (tb[TCA_U32_ACT]) {
if (tb[TCA_U32_ACT])
tc_print_action(f, tb[TCA_U32_ACT]);
}
return 0;
}

View File

@ -32,38 +32,41 @@
static struct m_pedit_util *pedit_list;
static int pedit_debug;
static void
explain(void)
static void explain(void)
{
fprintf(stderr, "Usage: ... pedit munge <MUNGE> [CONTROL]\n");
fprintf(stderr,
"Where: MUNGE := <RAW>|<LAYERED>\n"
"\t<RAW>:= <OFFSETC>[ATC]<CMD>\n \t\tOFFSETC:= offset <offval> <u8|u16|u32>\n "
"\t\tATC:= at <atval> offmask <maskval> shift <shiftval>\n \t\tNOTE: offval is byte offset, must be multiple of 4\n "
"\t\tNOTE: maskval is a 32 bit hex number\n \t\tNOTE: shiftval is a is a shift value\n "
"\t\tCMD:= clear | invert | set <setval>| retain\n \t<LAYERED>:= ip <ipdata> | ip6 <ip6data> \n "
"\t<RAW>:= <OFFSETC>[ATC]<CMD>\n \t\tOFFSETC:= offset <offval> <u8|u16|u32>\n"
"\t\tATC:= at <atval> offmask <maskval> shift <shiftval>\n"
"\t\tNOTE: offval is byte offset, must be multiple of 4\n"
"\t\tNOTE: maskval is a 32 bit hex number\n \t\tNOTE: shiftval is a is a shift value\n"
"\t\tCMD:= clear | invert | set <setval>| retain\n"
"\t<LAYERED>:= ip <ipdata> | ip6 <ip6data>\n"
" \t\t| udp <udpdata> | tcp <tcpdata> | icmp <icmpdata>\n"
"\tCONTROL:= reclassify | pipe | drop | continue | pass\n"
"For Example usage look at the examples directory\n");
}
static void
usage(void)
static void usage(void)
{
explain();
exit(-1);
}
static int
pedit_parse_nopopt (int *argc_p, char ***argv_p, struct tc_pedit_sel *sel, struct tc_pedit_key *tkey)
static int pedit_parse_nopopt(int *argc_p, char ***argv_p,
struct tc_pedit_sel *sel,
struct tc_pedit_key *tkey)
{
int argc = *argc_p;
char **argv = *argv_p;
if (argc) {
fprintf(stderr, "Unknown action hence option \"%s\" is unparsable\n", *argv);
return -1;
fprintf(stderr,
"Unknown action hence option \"%s\" is unparsable\n",
*argv);
return -1;
}
return 0;
@ -75,7 +78,7 @@ static struct m_pedit_util *get_pedit_kind(const char *str)
static void *pBODY;
void *dlh;
char buf[256];
struct m_pedit_util *p;
struct m_pedit_util *p;
for (p = pedit_list; p; p = p->next) {
if (strcmp(p->id, str) == 0)
@ -107,15 +110,14 @@ noexist:
p = malloc(sizeof(*p));
if (p) {
memset(p, 0, sizeof(*p));
strncpy(p->id, str, sizeof(p->id)-1);
strncpy(p->id, str, sizeof(p->id) - 1);
p->parse_peopt = pedit_parse_nopopt;
goto reg;
}
return p;
}
int
pack_key(struct tc_pedit_sel *sel, struct tc_pedit_key *tkey)
int pack_key(struct tc_pedit_sel *sel, struct tc_pedit_key *tkey)
{
int hwm = sel->nkeys;
@ -137,9 +139,8 @@ pack_key(struct tc_pedit_sel *sel, struct tc_pedit_key *tkey)
return 0;
}
int
pack_key32(__u32 retain, struct tc_pedit_sel *sel, struct tc_pedit_key *tkey)
int pack_key32(__u32 retain, struct tc_pedit_sel *sel,
struct tc_pedit_key *tkey)
{
if (tkey->off > (tkey->off & ~3)) {
fprintf(stderr,
@ -152,11 +153,11 @@ pack_key32(__u32 retain, struct tc_pedit_sel *sel, struct tc_pedit_key *tkey)
return pack_key(sel, tkey);
}
int
pack_key16(__u32 retain, struct tc_pedit_sel *sel, struct tc_pedit_key *tkey)
int pack_key16(__u32 retain, struct tc_pedit_sel *sel,
struct tc_pedit_key *tkey)
{
int ind, stride;
__u32 m[4] = {0x0000FFFF, 0xFF0000FF, 0xFFFF0000};
__u32 m[4] = { 0x0000FFFF, 0xFF0000FF, 0xFFFF0000 };
if (tkey->val > 0xFFFF || tkey->mask > 0xFFFF) {
fprintf(stderr, "pack_key16 bad value\n");
@ -177,19 +178,20 @@ pack_key16(__u32 retain, struct tc_pedit_sel *sel, struct tc_pedit_key *tkey)
tkey->off &= ~3;
if (pedit_debug)
printf("pack_key16: Final val %08x mask %08x\n", tkey->val, tkey->mask);
printf("pack_key16: Final val %08x mask %08x\n",
tkey->val, tkey->mask);
return pack_key(sel, tkey);
}
int
pack_key8(__u32 retain, struct tc_pedit_sel *sel, struct tc_pedit_key *tkey)
int pack_key8(__u32 retain, struct tc_pedit_sel *sel, struct tc_pedit_key *tkey)
{
int ind, stride;
__u32 m[4] = {0x00FFFFFF, 0xFF00FFFF, 0xFFFF00FF, 0xFFFFFF00};
__u32 m[4] = { 0x00FFFFFF, 0xFF00FFFF, 0xFFFF00FF, 0xFFFFFF00 };
if (tkey->val > 0xFF || tkey->mask > 0xFF) {
fprintf(stderr, "pack_key8 bad value (val %x mask %x\n", tkey->val, tkey->mask);
fprintf(stderr, "pack_key8 bad value (val %x mask %x\n",
tkey->val, tkey->mask);
return -1;
}
@ -202,12 +204,12 @@ pack_key8(__u32 retain, struct tc_pedit_sel *sel, struct tc_pedit_key *tkey)
tkey->off &= ~3;
if (pedit_debug)
printf("pack_key8: Final word off %d val %08x mask %08x\n", tkey->off, tkey->val, tkey->mask);
printf("pack_key8: Final word off %d val %08x mask %08x\n",
tkey->off, tkey->val, tkey->mask);
return pack_key(sel, tkey);
}
int
parse_val(int *argc_p, char ***argv_p, __u32 *val, int type)
int parse_val(int *argc_p, char ***argv_p, __u32 *val, int type)
{
int argc = *argc_p;
char **argv = *argv_p;
@ -216,7 +218,7 @@ parse_val(int *argc_p, char ***argv_p, __u32 *val, int type)
return -1;
if (type == TINT)
return get_integer((int *) val, *argv, 0);
return get_integer((int *)val, *argv, 0);
if (type == TU32)
return get_u32(val, *argv, 0);
@ -224,22 +226,21 @@ parse_val(int *argc_p, char ***argv_p, __u32 *val, int type)
if (type == TIPV4) {
inet_prefix addr;
if (get_prefix_1(&addr, *argv, AF_INET)) {
if (get_prefix_1(&addr, *argv, AF_INET))
return -1;
}
*val = addr.data[0];
return 0;
}
if (type == TIPV6) {
/* not implemented yet */
return -1;
}
if (type == TIPV6)
return -1; /* not implemented yet */
return -1;
}
int
parse_cmd(int *argc_p, char ***argv_p, __u32 len, int type, __u32 retain, struct tc_pedit_sel *sel, struct tc_pedit_key *tkey)
int parse_cmd(int *argc_p, char ***argv_p, __u32 len, int type, __u32 retain,
struct tc_pedit_sel *sel, struct tc_pedit_key *tkey)
{
__u32 mask = 0, val = 0;
__u32 o = 0xFF;
@ -251,7 +252,8 @@ parse_cmd(int *argc_p, char ***argv_p, __u32 len, int type, __u32 retain, struct
return -1;
if (pedit_debug)
printf("parse_cmd argc %d %s offset %d length %d\n", argc, *argv, tkey->off, len);
printf("parse_cmd argc %d %s offset %d length %d\n",
argc, *argv, tkey->off, len);
if (len == 2)
o = 0xFFFF;
@ -271,13 +273,15 @@ parse_cmd(int *argc_p, char ***argv_p, __u32 len, int type, __u32 retain, struct
return -1;
}
argc--; argv++;
argc--;
argv++;
if (argc && matches(*argv, "retain") == 0) {
NEXT_ARG();
if (parse_val(&argc, &argv, &retain, TU32))
return -1;
argc--; argv++;
argc--;
argv++;
}
tkey->val = val;
@ -302,15 +306,16 @@ parse_cmd(int *argc_p, char ***argv_p, __u32 len, int type, __u32 retain, struct
return -1;
done:
if (pedit_debug)
printf("parse_cmd done argc %d %s offset %d length %d\n", argc, *argv, tkey->off, len);
printf("parse_cmd done argc %d %s offset %d length %d\n",
argc, *argv, tkey->off, len);
*argc_p = argc;
*argv_p = argv;
return res;
}
int
parse_offset(int *argc_p, char ***argv_p, struct tc_pedit_sel *sel, struct tc_pedit_key *tkey)
int parse_offset(int *argc_p, char ***argv_p, struct tc_pedit_sel *sel,
struct tc_pedit_key *tkey)
{
int off;
__u32 len, retain;
@ -331,7 +336,6 @@ parse_offset(int *argc_p, char ***argv_p, struct tc_pedit_sel *sel, struct tc_pe
if (argc <= 0)
return -1;
if (matches(*argv, "u32") == 0) {
len = 4;
retain = 0xFFFFFFFF;
@ -386,8 +390,7 @@ done:
return res;
}
static int
parse_munge(int *argc_p, char ***argv_p, struct tc_pedit_sel *sel)
static int parse_munge(int *argc_p, char ***argv_p, struct tc_pedit_sel *sel)
{
struct tc_pedit_key tkey;
int argc = *argc_p;
@ -433,8 +436,8 @@ done:
return res;
}
int
parse_pedit(struct action_util *a, int *argc_p, char ***argv_p, int tca_id, struct nlmsghdr *n)
int parse_pedit(struct action_util *a, int *argc_p, char ***argv_p, int tca_id,
struct nlmsghdr *n)
{
struct {
struct tc_pedit_sel sel;
@ -459,13 +462,15 @@ parse_pedit(struct action_util *a, int *argc_p, char ***argv_p, int tca_id, stru
usage();
} else if (matches(*argv, "munge") == 0) {
if (!ok) {
fprintf(stderr, "Illegal pedit construct (%s)\n", *argv);
fprintf(stderr, "Bad pedit construct (%s)\n",
*argv);
explain();
return -1;
}
NEXT_ARG();
if (parse_munge(&argc, &argv, &sel.sel)) {
fprintf(stderr, "Illegal pedit construct (%s)\n", *argv);
fprintf(stderr, "Bad pedit construct (%s)\n",
*argv);
explain();
return -1;
}
@ -489,7 +494,7 @@ parse_pedit(struct action_util *a, int *argc_p, char ***argv_p, int tca_id, stru
sel.sel.action = TC_ACT_PIPE;
NEXT_ARG();
} else if (matches(*argv, "drop") == 0 ||
matches(*argv, "shot") == 0) {
matches(*argv, "shot") == 0) {
sel.sel.action = TC_ACT_SHOT;
NEXT_ARG();
} else if (matches(*argv, "continue") == 0) {
@ -517,16 +522,17 @@ parse_pedit(struct action_util *a, int *argc_p, char ***argv_p, int tca_id, stru
tail = NLMSG_TAIL(n);
addattr_l(n, MAX_MSG, tca_id, NULL, 0);
addattr_l(n, MAX_MSG, TCA_PEDIT_PARMS, &sel, sizeof(sel.sel)+sel.sel.nkeys*sizeof(struct tc_pedit_key));
tail->rta_len = (void *) NLMSG_TAIL(n) - (void *) tail;
addattr_l(n, MAX_MSG, TCA_PEDIT_PARMS, &sel,
sizeof(sel.sel) +
sel.sel.nkeys * sizeof(struct tc_pedit_key));
tail->rta_len = (void *)NLMSG_TAIL(n) - (void *)tail;
*argc_p = argc;
*argv_p = argv;
return 0;
}
int
print_pedit(struct action_util *au, FILE * f, struct rtattr *arg)
int print_pedit(struct action_util *au, FILE *f, struct rtattr *arg)
{
struct tc_pedit_sel *sel;
struct rtattr *tb[TCA_PEDIT_MAX + 1];
@ -544,8 +550,10 @@ print_pedit(struct action_util *au, FILE * f, struct rtattr *arg)
}
sel = RTA_DATA(tb[TCA_PEDIT_PARMS]);
fprintf(f, " pedit action %s keys %d\n ", action_n2a(sel->action, b1, sizeof (b1)), sel->nkeys);
fprintf(f, "\t index %d ref %d bind %d", sel->index, sel->refcnt, sel->bindcnt);
fprintf(f, " pedit action %s keys %d\n ",
action_n2a(sel->action, b1, sizeof(b1)), sel->nkeys);
fprintf(f, "\t index %d ref %d bind %d", sel->index, sel->refcnt,
sel->bindcnt);
if (show_stats) {
if (tb[TCA_PEDIT_TM]) {
@ -561,21 +569,20 @@ print_pedit(struct action_util *au, FILE * f, struct rtattr *arg)
for (i = 0; i < sel->nkeys; i++, key++) {
fprintf(f, "\n\t key #%d", i);
fprintf(f, " at %d: val %08x mask %08x",
(unsigned int)key->off,
(unsigned int)ntohl(key->val),
(unsigned int)ntohl(key->mask));
(unsigned int)key->off,
(unsigned int)ntohl(key->val),
(unsigned int)ntohl(key->mask));
}
} else {
fprintf(f, "\npedit %x keys %d is not LEGIT", sel->index, sel->nkeys);
fprintf(f, "\npedit %x keys %d is not LEGIT", sel->index,
sel->nkeys);
}
fprintf(f, "\n ");
return 0;
}
int
pedit_print_xstats(struct action_util *au, FILE *f, struct rtattr *xstats)
int pedit_print_xstats(struct action_util *au, FILE *f, struct rtattr *xstats)
{
return 0;
}

226
tc/m_xt.c
View File

@ -39,8 +39,10 @@
#endif
#ifndef __ALIGN_KERNEL
#define __ALIGN_KERNEL(x, a) __ALIGN_KERNEL_MASK(x, (typeof(x))(a) - 1)
#define __ALIGN_KERNEL_MASK(x, mask) (((x) + (mask)) & ~(mask))
#define __ALIGN_KERNEL(x, a) \
__ALIGN_KERNEL_MASK(x, (typeof(x))(a) - 1)
#define __ALIGN_KERNEL_MASK(x, mask) \
(((x) + (mask)) & ~(mask))
#endif
#ifndef ALIGN
@ -51,7 +53,7 @@ static const char *tname = "mangle";
char *lib_dir;
static const char *ipthooks[] = {
static const char * const ipthooks[] = {
"NF_IP_PRE_ROUTING",
"NF_IP_LOCAL_IN",
"NF_IP_FORWARD",
@ -116,89 +118,100 @@ static void set_lib_dir(void)
}
static int get_xtables_target_opts(struct xtables_globals *globals,
struct xtables_target *m)
{
struct option *opts;
#if (XTABLES_VERSION_CODE >= 6)
opts = xtables_options_xfrm(globals->orig_opts,
globals->opts,
m->x6_options,
&m->option_offset);
#else
opts = xtables_merge_options(globals->opts,
m->extra_opts,
&m->option_offset);
#endif
if (!opts)
return -1;
globals->opts = opts;
return 0;
}
static int parse_ipt(struct action_util *a, int *argc_p,
char ***argv_p, int tca_id, struct nlmsghdr *n)
{
struct xtables_target *m = NULL;
struct ipt_entry fw;
struct rtattr *tail;
int c;
int rargc = *argc_p;
char **argv = *argv_p;
int argc = 0, iargc = 0;
int argc;
char k[16];
int size = 0;
int iok = 0, ok = 0;
__u32 hook = 0, index = 0;
struct option *opts = NULL;
xtables_init_all(&tcipt_globals, NFPROTO_IPV4);
/* copy tcipt_globals because .opts will be modified by iptables */
struct xtables_globals tmp_tcipt_globals = tcipt_globals;
xtables_init_all(&tmp_tcipt_globals, NFPROTO_IPV4);
set_lib_dir();
{
int i;
for (i = 0; i < rargc; i++) {
if (NULL == argv[i] || 0 == strcmp(argv[i], "action")) {
break;
}
}
iargc = argc = i;
/* parse only up until the next action */
for (argc = 0; argc < *argc_p; argc++) {
if (!argv[argc] || !strcmp(argv[argc], "action"))
break;
}
if (argc <= 2) {
fprintf(stderr, "bad arguments to ipt %d vs %d\n", argc, rargc);
fprintf(stderr,
"too few arguments for xt, need at least '-j <target>'\n");
return -1;
}
while (1) {
c = getopt_long(argc, argv, "j:", tcipt_globals.opts, NULL);
c = getopt_long(argc, argv, "j:", tmp_tcipt_globals.opts, NULL);
if (c == -1)
break;
switch (c) {
case 'j':
m = xtables_find_target(optarg, XTF_TRY_LOAD);
if (m != NULL) {
if (build_st(m, NULL) < 0) {
printf(" %s error\n", m->name);
return -1;
}
#if (XTABLES_VERSION_CODE >= 6)
opts = xtables_options_xfrm(tcipt_globals.orig_opts,
tcipt_globals.opts,
m->x6_options,
&m->option_offset);
#else
opts = xtables_merge_options(tcipt_globals.opts,
m->extra_opts,
&m->option_offset);
#endif
if (opts == NULL) {
fprintf(stderr, " failed to find additional options for target %s\n\n", optarg);
if (!m) {
fprintf(stderr,
" failed to find target %s\n\n",
optarg);
return -1;
} else
tcipt_globals.opts = opts;
} else {
fprintf(stderr, " failed to find target %s\n\n", optarg);
}
if (build_st(m, NULL) < 0) {
printf(" %s error\n", m->name);
return -1;
}
if (get_xtables_target_opts(&tmp_tcipt_globals,
m) < 0) {
fprintf(stderr,
" failed to find additional options for target %s\n\n",
optarg);
return -1;
}
ok++;
break;
default:
memset(&fw, 0, sizeof(fw));
#if (XTABLES_VERSION_CODE >= 6)
if (m != NULL && m->x6_parse != NULL) {
xtables_option_tpcall(c, argv, 0, m, NULL);
if (m != NULL && m->x6_parse != NULL) {
xtables_option_tpcall(c, argv, 0, m, NULL);
#else
if (m != NULL && m->parse != NULL) {
m->parse(c - m->option_offset, argv, 0, &m->tflags,
NULL, &m->t);
if (m != NULL && m->parse != NULL) {
m->parse(c - m->option_offset, argv, 0,
&m->tflags, NULL, &m->t);
#endif
} else {
fprintf(stderr, "failed to find target %s\n\n", optarg);
fprintf(stderr,
"failed to find target %s\n\n", optarg);
return -1;
}
@ -207,7 +220,7 @@ static int parse_ipt(struct action_util *a, int *argc_p,
}
}
if (iargc > optind) {
if (argc > optind) {
if (matches(argv[optind], "index") == 0) {
if (get_u32(&index, argv[optind + 1], 10)) {
fprintf(stderr, "Illegal \"index\"\n");
@ -250,8 +263,12 @@ static int parse_ipt(struct action_util *a, int *argc_p,
fprintf(stdout, "tablename: %s hook: %s\n ", tname, ipthooks[hook]);
fprintf(stdout, "\ttarget: ");
if (m)
m->print(NULL, m->t, 0);
if (m) {
if (m->print)
m->print(NULL, m->t, 0);
else
printf("%s ", m->name);
}
fprintf(stdout, " index %d\n", index);
if (strlen(tname) > 16) {
@ -269,9 +286,8 @@ static int parse_ipt(struct action_util *a, int *argc_p,
addattr_l(n, MAX_MSG, TCA_IPT_TARG, m->t, m->t->u.target_size);
tail->rta_len = (void *) NLMSG_TAIL(n) - (void *) tail;
argc -= optind;
argv += optind;
*argc_p = rargc - iargc;
*argc_p -= argc;
*argv_p = argv;
optind = 0;
@ -291,11 +307,11 @@ static int parse_ipt(struct action_util *a, int *argc_p,
}
static int
print_ipt(struct action_util *au, FILE * f, struct rtattr *arg)
print_ipt(struct action_util *au, FILE *f, struct rtattr *arg)
{
struct xtables_target *m;
struct rtattr *tb[TCA_IPT_MAX + 1];
struct xt_entry_target *t = NULL;
struct option *opts = NULL;
if (arg == NULL)
return -1;
@ -328,63 +344,51 @@ print_ipt(struct action_util *au, FILE * f, struct rtattr *arg)
if (tb[TCA_IPT_TARG] == NULL) {
fprintf(f, "\t[NULL ipt target parameters ]\n");
return -1;
} else {
struct xtables_target *m = NULL;
t = RTA_DATA(tb[TCA_IPT_TARG]);
m = xtables_find_target(t->u.user.name, XTF_TRY_LOAD);
if (m != NULL) {
if (build_st(m, t) < 0) {
fprintf(stderr, " %s error\n", m->name);
return -1;
}
#if (XTABLES_VERSION_CODE >= 6)
opts = xtables_options_xfrm(tmp_tcipt_globals.orig_opts,
tmp_tcipt_globals.opts,
m->x6_options,
&m->option_offset);
#else
opts = xtables_merge_options(tmp_tcipt_globals.opts,
m->extra_opts,
&m->option_offset);
#endif
if (opts == NULL) {
fprintf(stderr, " failed to find additional options for target %s\n\n", optarg);
return -1;
} else
tmp_tcipt_globals.opts = opts;
} else {
fprintf(stderr, " failed to find target %s\n\n",
t->u.user.name);
return -1;
}
fprintf(f, "\ttarget ");
m->print(NULL, m->t, 0);
if (tb[TCA_IPT_INDEX] == NULL) {
fprintf(f, " [NULL ipt target index ]\n");
} else {
__u32 index;
index = rta_getattr_u32(tb[TCA_IPT_INDEX]);
fprintf(f, "\n\tindex %d", index);
}
if (tb[TCA_IPT_CNT]) {
struct tc_cnt *c = RTA_DATA(tb[TCA_IPT_CNT]);
fprintf(f, " ref %d bind %d", c->refcnt, c->bindcnt);
}
if (show_stats) {
if (tb[TCA_IPT_TM]) {
struct tcf_t *tm = RTA_DATA(tb[TCA_IPT_TM]);
print_tm(f, tm);
}
}
fprintf(f, "\n");
}
t = RTA_DATA(tb[TCA_IPT_TARG]);
m = xtables_find_target(t->u.user.name, XTF_TRY_LOAD);
if (!m) {
fprintf(stderr, " failed to find target %s\n\n",
t->u.user.name);
return -1;
}
if (build_st(m, t) < 0) {
fprintf(stderr, " %s error\n", m->name);
return -1;
}
if (get_xtables_target_opts(&tmp_tcipt_globals, m) < 0) {
fprintf(stderr,
" failed to find additional options for target %s\n\n",
t->u.user.name);
return -1;
}
fprintf(f, "\ttarget ");
m->print(NULL, m->t, 0);
if (tb[TCA_IPT_INDEX] == NULL) {
fprintf(f, " [NULL ipt target index ]\n");
} else {
__u32 index;
index = rta_getattr_u32(tb[TCA_IPT_INDEX]);
fprintf(f, "\n\tindex %d", index);
}
if (tb[TCA_IPT_CNT]) {
struct tc_cnt *c = RTA_DATA(tb[TCA_IPT_CNT]);
fprintf(f, " ref %d bind %d", c->refcnt, c->bindcnt);
}
if (show_stats) {
if (tb[TCA_IPT_TM]) {
struct tcf_t *tm = RTA_DATA(tb[TCA_IPT_TM]);
print_tm(f, tm);
}
}
fprintf(f, "\n");
xtables_free_opts(1);
return 0;