Merge branch 'master' into net-next
This commit is contained in:
commit
f62f952fad
|
|
@ -319,7 +319,7 @@ static int brlink_modify(int argc, char **argv)
|
||||||
} else if (strcmp(*argv, "state") == 0) {
|
} else if (strcmp(*argv, "state") == 0) {
|
||||||
NEXT_ARG();
|
NEXT_ARG();
|
||||||
char *endptr;
|
char *endptr;
|
||||||
size_t nstates = sizeof(port_states) / sizeof(*port_states);
|
size_t nstates = ARRAY_SIZE(port_states);
|
||||||
|
|
||||||
state = strtol(*argv, &endptr, 10);
|
state = strtol(*argv, &endptr, 10);
|
||||||
if (!(**argv != '\0' && *endptr == '\0')) {
|
if (!(**argv != '\0' && *endptr == '\0')) {
|
||||||
|
|
|
||||||
|
|
@ -61,6 +61,7 @@ static struct
|
||||||
int group;
|
int group;
|
||||||
int master;
|
int master;
|
||||||
char *kind;
|
char *kind;
|
||||||
|
char *slave_kind;
|
||||||
} filter;
|
} filter;
|
||||||
|
|
||||||
static int do_link;
|
static int do_link;
|
||||||
|
|
@ -94,9 +95,9 @@ static void usage(void)
|
||||||
fprintf(stderr, "LIFETIME := [ valid_lft LFT ] [ preferred_lft LFT ]\n");
|
fprintf(stderr, "LIFETIME := [ valid_lft LFT ] [ preferred_lft LFT ]\n");
|
||||||
fprintf(stderr, "LFT := forever | SECONDS\n");
|
fprintf(stderr, "LFT := forever | SECONDS\n");
|
||||||
fprintf(stderr, "TYPE := { vlan | veth | vcan | dummy | ifb | macvlan | macvtap |\n");
|
fprintf(stderr, "TYPE := { vlan | veth | vcan | dummy | ifb | macvlan | macvtap |\n");
|
||||||
fprintf(stderr, " bridge | bond | ipoib | ip6tnl | ipip | sit | vxlan |\n");
|
fprintf(stderr, " bridge | bond | ipoib | ip6tnl | ipip | sit | vxlan | lowpan |\n");
|
||||||
fprintf(stderr, " gre | gretap | ip6gre | ip6gretap | vti | nlmon |\n");
|
fprintf(stderr, " gre | gretap | ip6gre | ip6gretap | vti | nlmon | can |\n");
|
||||||
fprintf(stderr, " bond_slave | ipvlan | geneve | bridge_slave | vrf }\n");
|
fprintf(stderr, " bond_slave | ipvlan | geneve | bridge_slave | vrf | hsr}\n");
|
||||||
|
|
||||||
exit(-1);
|
exit(-1);
|
||||||
}
|
}
|
||||||
|
|
@ -206,18 +207,27 @@ static void print_linkmode(FILE *f, struct rtattr *tb)
|
||||||
fprintf(f, "mode %s ", link_modes[mode]);
|
fprintf(f, "mode %s ", link_modes[mode]);
|
||||||
}
|
}
|
||||||
|
|
||||||
static char *parse_link_kind(struct rtattr *tb)
|
static char *parse_link_kind(struct rtattr *tb, bool slave)
|
||||||
{
|
{
|
||||||
struct rtattr *linkinfo[IFLA_INFO_MAX+1];
|
struct rtattr *linkinfo[IFLA_INFO_MAX+1];
|
||||||
|
int attr = slave ? IFLA_INFO_SLAVE_KIND : IFLA_INFO_KIND;
|
||||||
|
|
||||||
parse_rtattr_nested(linkinfo, IFLA_INFO_MAX, tb);
|
parse_rtattr_nested(linkinfo, IFLA_INFO_MAX, tb);
|
||||||
|
|
||||||
if (linkinfo[IFLA_INFO_KIND])
|
if (linkinfo[attr])
|
||||||
return RTA_DATA(linkinfo[IFLA_INFO_KIND]);
|
return RTA_DATA(linkinfo[attr]);
|
||||||
|
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int match_link_kind(struct rtattr **tb, char *kind, bool slave)
|
||||||
|
{
|
||||||
|
if (!tb[IFLA_LINKINFO])
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
return strcmp(parse_link_kind(tb[IFLA_LINKINFO], slave), kind);
|
||||||
|
}
|
||||||
|
|
||||||
static void print_linktype(FILE *fp, struct rtattr *tb)
|
static void print_linktype(FILE *fp, struct rtattr *tb)
|
||||||
{
|
{
|
||||||
struct rtattr *linkinfo[IFLA_INFO_MAX+1];
|
struct rtattr *linkinfo[IFLA_INFO_MAX+1];
|
||||||
|
|
@ -680,16 +690,11 @@ int print_linkinfo_brief(const struct sockaddr_nl *who,
|
||||||
} else if (filter.master > 0)
|
} else if (filter.master > 0)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
if (filter.kind) {
|
if (filter.kind && match_link_kind(tb, filter.kind, 0))
|
||||||
if (tb[IFLA_LINKINFO]) {
|
return -1;
|
||||||
char *kind = parse_link_kind(tb[IFLA_LINKINFO]);
|
|
||||||
|
|
||||||
if (strcmp(kind, filter.kind))
|
if (filter.slave_kind && match_link_kind(tb, filter.slave_kind, 1))
|
||||||
return -1;
|
return -1;
|
||||||
} else {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (n->nlmsg_type == RTM_DELLINK)
|
if (n->nlmsg_type == RTM_DELLINK)
|
||||||
fprintf(fp, "Deleted ");
|
fprintf(fp, "Deleted ");
|
||||||
|
|
@ -781,16 +786,11 @@ int print_linkinfo(const struct sockaddr_nl *who,
|
||||||
} else if (filter.master > 0)
|
} else if (filter.master > 0)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
if (filter.kind) {
|
if (filter.kind && match_link_kind(tb, filter.kind, 0))
|
||||||
if (tb[IFLA_LINKINFO]) {
|
return -1;
|
||||||
char *kind = parse_link_kind(tb[IFLA_LINKINFO]);
|
|
||||||
|
|
||||||
if (strcmp(kind, filter.kind))
|
if (filter.slave_kind && match_link_kind(tb, filter.slave_kind, 1))
|
||||||
return -1;
|
return -1;
|
||||||
} else {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (n->nlmsg_type == RTM_DELLINK)
|
if (n->nlmsg_type == RTM_DELLINK)
|
||||||
fprintf(fp, "Deleted ");
|
fprintf(fp, "Deleted ");
|
||||||
|
|
@ -1621,8 +1621,16 @@ static int ipaddr_list_flush_or_save(int argc, char **argv, int action)
|
||||||
invarg("Device does not exist\n", *argv);
|
invarg("Device does not exist\n", *argv);
|
||||||
filter.master = ifindex;
|
filter.master = ifindex;
|
||||||
} else if (strcmp(*argv, "type") == 0) {
|
} else if (strcmp(*argv, "type") == 0) {
|
||||||
|
int soff;
|
||||||
|
|
||||||
NEXT_ARG();
|
NEXT_ARG();
|
||||||
filter.kind = *argv;
|
soff = strlen(*argv) - strlen("_slave");
|
||||||
|
if (!strcmp(*argv + soff, "_slave")) {
|
||||||
|
(*argv)[soff] = '\0';
|
||||||
|
filter.slave_kind = *argv;
|
||||||
|
} else {
|
||||||
|
filter.kind = *argv;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
if (strcmp(*argv, "dev") == 0) {
|
if (strcmp(*argv, "dev") == 0) {
|
||||||
NEXT_ARG();
|
NEXT_ARG();
|
||||||
|
|
|
||||||
|
|
@ -839,7 +839,6 @@ static int iproute_modify(int cmd, unsigned int flags, int argc, char **argv)
|
||||||
int table_ok = 0;
|
int table_ok = 0;
|
||||||
int raw = 0;
|
int raw = 0;
|
||||||
int type_ok = 0;
|
int type_ok = 0;
|
||||||
static int hz;
|
|
||||||
|
|
||||||
memset(&req, 0, sizeof(req));
|
memset(&req, 0, sizeof(req));
|
||||||
|
|
||||||
|
|
@ -923,9 +922,7 @@ static int iproute_modify(int cmd, unsigned int flags, int argc, char **argv)
|
||||||
NEXT_ARG();
|
NEXT_ARG();
|
||||||
if (get_u32(&expires, *argv, 0))
|
if (get_u32(&expires, *argv, 0))
|
||||||
invarg("\"expires\" value is invalid\n", *argv);
|
invarg("\"expires\" value is invalid\n", *argv);
|
||||||
if (!hz)
|
addattr32(&req.n, sizeof(req), RTA_EXPIRES, expires);
|
||||||
hz = get_user_hz();
|
|
||||||
addattr32(&req.n, sizeof(req), RTA_EXPIRES, expires*hz);
|
|
||||||
} else if (matches(*argv, "metric") == 0 ||
|
} else if (matches(*argv, "metric") == 0 ||
|
||||||
matches(*argv, "priority") == 0 ||
|
matches(*argv, "priority") == 0 ||
|
||||||
strcmp(*argv, "preference") == 0) {
|
strcmp(*argv, "preference") == 0) {
|
||||||
|
|
|
||||||
|
|
@ -235,7 +235,7 @@ error.
|
||||||
|
|
||||||
.B 1
|
.B 1
|
||||||
- STP LISTENING state. Only valid if STP is enabled on the bridge. In this
|
- STP LISTENING state. Only valid if STP is enabled on the bridge. In this
|
||||||
state the port for list for STP BPDUs and drop all other traffic.
|
state the port listens for STP BPDUs and drops all other traffic frames.
|
||||||
.sp
|
.sp
|
||||||
|
|
||||||
.B 2
|
.B 2
|
||||||
|
|
@ -256,7 +256,7 @@ STP BPDUs.
|
||||||
|
|
||||||
.TP
|
.TP
|
||||||
.BR "guard on " or " guard off "
|
.BR "guard on " or " guard off "
|
||||||
Controls whether STP BPUDs will be processed by the bridge port. By default,
|
Controls whether STP BPDUs will be processed by the bridge port. By default,
|
||||||
the flag is turned off allowed BPDU processing. Turning this flag on will
|
the flag is turned off allowed BPDU processing. Turning this flag on will
|
||||||
cause the port to stop processing STP BPDUs.
|
cause the port to stop processing STP BPDUs.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -98,7 +98,9 @@ ip-address \- protocol address management
|
||||||
.ti -8
|
.ti -8
|
||||||
.IR TYPE " := [ "
|
.IR TYPE " := [ "
|
||||||
.BR bridge " | "
|
.BR bridge " | "
|
||||||
|
.BR bridge_slave " |"
|
||||||
.BR bond " | "
|
.BR bond " | "
|
||||||
|
.BR bond_slave " |"
|
||||||
.BR can " | "
|
.BR can " | "
|
||||||
.BR dummy " | "
|
.BR dummy " | "
|
||||||
.BR hsr " | "
|
.BR hsr " | "
|
||||||
|
|
@ -118,6 +120,7 @@ ip-address \- protocol address management
|
||||||
.BR ip6gre " |"
|
.BR ip6gre " |"
|
||||||
.BR ip6gretap " |"
|
.BR ip6gretap " |"
|
||||||
.BR vti " |"
|
.BR vti " |"
|
||||||
|
.BR vrf " |"
|
||||||
.BR nlmon " |"
|
.BR nlmon " |"
|
||||||
.BR ipvlan " |"
|
.BR ipvlan " |"
|
||||||
.BR lowpan " |"
|
.BR lowpan " |"
|
||||||
|
|
|
||||||
|
|
@ -30,6 +30,7 @@
|
||||||
|
|
||||||
#include <json_writer.h>
|
#include <json_writer.h>
|
||||||
#include <SNAPSHOT.h>
|
#include <SNAPSHOT.h>
|
||||||
|
#include "utils.h"
|
||||||
|
|
||||||
int dump_zeros;
|
int dump_zeros;
|
||||||
int reset_history;
|
int reset_history;
|
||||||
|
|
@ -95,7 +96,7 @@ static int useless_number(const char *id)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
for (i = 0; i < sizeof(useless_numbers)/sizeof(*useless_numbers); i++)
|
for (i = 0; i < ARRAY_SIZE(useless_numbers); i++)
|
||||||
if (strcmp(id, useless_numbers[i]) == 0)
|
if (strcmp(id, useless_numbers[i]) == 0)
|
||||||
return 1;
|
return 1;
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
||||||
159
misc/ss.c
159
misc/ss.c
|
|
@ -666,7 +666,7 @@ static int get_slabstat(struct slabstat *s)
|
||||||
while (fgets(buf, sizeof(buf), fp) != NULL) {
|
while (fgets(buf, sizeof(buf), fp) != NULL) {
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
for (i = 0; i < sizeof(slabstat_ids)/sizeof(slabstat_ids[0]); i++) {
|
for (i = 0; i < ARRAY_SIZE(slabstat_ids); i++) {
|
||||||
if (memcmp(buf, slabstat_ids[i], strlen(slabstat_ids[i])) == 0) {
|
if (memcmp(buf, slabstat_ids[i], strlen(slabstat_ids[i])) == 0) {
|
||||||
sscanf(buf, "%*s%d", ((int *)s) + i);
|
sscanf(buf, "%*s%d", ((int *)s) + i);
|
||||||
cnt--;
|
cnt--;
|
||||||
|
|
@ -1043,6 +1043,7 @@ static void inet_addr_print(const inet_prefix *a, int port, unsigned int ifindex
|
||||||
struct aafilter {
|
struct aafilter {
|
||||||
inet_prefix addr;
|
inet_prefix addr;
|
||||||
int port;
|
int port;
|
||||||
|
unsigned int iface;
|
||||||
struct aafilter *next;
|
struct aafilter *next;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -1157,7 +1158,12 @@ static int run_ssfilter(struct ssfilter *f, struct sockstat *s)
|
||||||
|
|
||||||
return s->lport <= a->port;
|
return s->lport <= a->port;
|
||||||
}
|
}
|
||||||
|
case SSF_DEVCOND:
|
||||||
|
{
|
||||||
|
struct aafilter *a = (void *)f->pred;
|
||||||
|
|
||||||
|
return s->iface == a->iface;
|
||||||
|
}
|
||||||
/* Yup. It is recursion. Sorry. */
|
/* Yup. It is recursion. Sorry. */
|
||||||
case SSF_AND:
|
case SSF_AND:
|
||||||
return run_ssfilter(f->pred, s) && run_ssfilter(f->post, s);
|
return run_ssfilter(f->pred, s) && run_ssfilter(f->post, s);
|
||||||
|
|
@ -1273,11 +1279,16 @@ static int ssfilter_bytecompile(struct ssfilter *f, char **bytecode)
|
||||||
|
|
||||||
case SSF_AND:
|
case SSF_AND:
|
||||||
{
|
{
|
||||||
char *a1, *a2, *a;
|
char *a1 = NULL, *a2 = NULL, *a;
|
||||||
int l1, l2;
|
int l1, l2;
|
||||||
|
|
||||||
l1 = ssfilter_bytecompile(f->pred, &a1);
|
l1 = ssfilter_bytecompile(f->pred, &a1);
|
||||||
l2 = ssfilter_bytecompile(f->post, &a2);
|
l2 = ssfilter_bytecompile(f->post, &a2);
|
||||||
|
if (!l1 || !l2) {
|
||||||
|
free(a1);
|
||||||
|
free(a2);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
if (!(a = malloc(l1+l2))) abort();
|
if (!(a = malloc(l1+l2))) abort();
|
||||||
memcpy(a, a1, l1);
|
memcpy(a, a1, l1);
|
||||||
memcpy(a+l1, a2, l2);
|
memcpy(a+l1, a2, l2);
|
||||||
|
|
@ -1288,11 +1299,16 @@ static int ssfilter_bytecompile(struct ssfilter *f, char **bytecode)
|
||||||
}
|
}
|
||||||
case SSF_OR:
|
case SSF_OR:
|
||||||
{
|
{
|
||||||
char *a1, *a2, *a;
|
char *a1 = NULL, *a2 = NULL, *a;
|
||||||
int l1, l2;
|
int l1, l2;
|
||||||
|
|
||||||
l1 = ssfilter_bytecompile(f->pred, &a1);
|
l1 = ssfilter_bytecompile(f->pred, &a1);
|
||||||
l2 = ssfilter_bytecompile(f->post, &a2);
|
l2 = ssfilter_bytecompile(f->post, &a2);
|
||||||
|
if (!l1 || !l2) {
|
||||||
|
free(a1);
|
||||||
|
free(a2);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
if (!(a = malloc(l1+l2+4))) abort();
|
if (!(a = malloc(l1+l2+4))) abort();
|
||||||
memcpy(a, a1, l1);
|
memcpy(a, a1, l1);
|
||||||
memcpy(a+l1+4, a2, l2);
|
memcpy(a+l1+4, a2, l2);
|
||||||
|
|
@ -1303,16 +1319,25 @@ static int ssfilter_bytecompile(struct ssfilter *f, char **bytecode)
|
||||||
}
|
}
|
||||||
case SSF_NOT:
|
case SSF_NOT:
|
||||||
{
|
{
|
||||||
char *a1, *a;
|
char *a1 = NULL, *a;
|
||||||
int l1;
|
int l1;
|
||||||
|
|
||||||
l1 = ssfilter_bytecompile(f->pred, &a1);
|
l1 = ssfilter_bytecompile(f->pred, &a1);
|
||||||
|
if (!l1) {
|
||||||
|
free(a1);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
if (!(a = malloc(l1+4))) abort();
|
if (!(a = malloc(l1+4))) abort();
|
||||||
memcpy(a, a1, l1);
|
memcpy(a, a1, l1);
|
||||||
free(a1);
|
free(a1);
|
||||||
*(struct inet_diag_bc_op *)(a+l1) = (struct inet_diag_bc_op){ INET_DIAG_BC_JMP, 4, 8 };
|
*(struct inet_diag_bc_op *)(a+l1) = (struct inet_diag_bc_op){ INET_DIAG_BC_JMP, 4, 8 };
|
||||||
*bytecode = a;
|
*bytecode = a;
|
||||||
return l1+4;
|
return l1+4;
|
||||||
|
}
|
||||||
|
case SSF_DEVCOND:
|
||||||
|
{
|
||||||
|
/* bytecompile for SSF_DEVCOND not supported yet */
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
abort();
|
abort();
|
||||||
|
|
@ -1402,6 +1427,27 @@ static int xll_name_to_index(const char *dev)
|
||||||
return ll_name_to_index(dev);
|
return ll_name_to_index(dev);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void *parse_devcond(char *name)
|
||||||
|
{
|
||||||
|
struct aafilter a = { .iface = 0 };
|
||||||
|
struct aafilter *res;
|
||||||
|
|
||||||
|
a.iface = xll_name_to_index(name);
|
||||||
|
if (a.iface == 0) {
|
||||||
|
char *end;
|
||||||
|
unsigned long res;
|
||||||
|
|
||||||
|
res = strtoul(name, &end, 0);
|
||||||
|
if (!end || end == name || *end || res > UINT_MAX)
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
res = malloc(sizeof(*res));
|
||||||
|
*res = a;
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
void *parse_hostcond(char *addr, bool is_port)
|
void *parse_hostcond(char *addr, bool is_port)
|
||||||
{
|
{
|
||||||
char *port = NULL;
|
char *port = NULL;
|
||||||
|
|
@ -2038,42 +2084,48 @@ static void tcp_show_info(const struct nlmsghdr *nlh, struct inet_diag_msg *r,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int inet_show_sock(struct nlmsghdr *nlh, struct filter *f, int protocol)
|
static void parse_diag_msg(struct nlmsghdr *nlh, struct sockstat *s)
|
||||||
{
|
{
|
||||||
struct rtattr *tb[INET_DIAG_MAX+1];
|
struct rtattr *tb[INET_DIAG_MAX+1];
|
||||||
struct inet_diag_msg *r = NLMSG_DATA(nlh);
|
struct inet_diag_msg *r = NLMSG_DATA(nlh);
|
||||||
struct sockstat s = {};
|
|
||||||
|
|
||||||
parse_rtattr(tb, INET_DIAG_MAX, (struct rtattr *)(r+1),
|
parse_rtattr(tb, INET_DIAG_MAX, (struct rtattr *)(r+1),
|
||||||
nlh->nlmsg_len - NLMSG_LENGTH(sizeof(*r)));
|
nlh->nlmsg_len - NLMSG_LENGTH(sizeof(*r)));
|
||||||
|
|
||||||
s.state = r->idiag_state;
|
s->state = r->idiag_state;
|
||||||
s.local.family = s.remote.family = r->idiag_family;
|
s->local.family = s->remote.family = r->idiag_family;
|
||||||
s.lport = ntohs(r->id.idiag_sport);
|
s->lport = ntohs(r->id.idiag_sport);
|
||||||
s.rport = ntohs(r->id.idiag_dport);
|
s->rport = ntohs(r->id.idiag_dport);
|
||||||
s.wq = r->idiag_wqueue;
|
s->wq = r->idiag_wqueue;
|
||||||
s.rq = r->idiag_rqueue;
|
s->rq = r->idiag_rqueue;
|
||||||
s.ino = r->idiag_inode;
|
s->ino = r->idiag_inode;
|
||||||
s.uid = r->idiag_uid;
|
s->uid = r->idiag_uid;
|
||||||
s.iface = r->id.idiag_if;
|
s->iface = r->id.idiag_if;
|
||||||
s.sk = cookie_sk_get(&r->id.idiag_cookie[0]);
|
s->sk = cookie_sk_get(&r->id.idiag_cookie[0]);
|
||||||
|
|
||||||
if (s.local.family == AF_INET) {
|
if (s->local.family == AF_INET)
|
||||||
s.local.bytelen = s.remote.bytelen = 4;
|
s->local.bytelen = s->remote.bytelen = 4;
|
||||||
} else {
|
else
|
||||||
s.local.bytelen = s.remote.bytelen = 16;
|
s->local.bytelen = s->remote.bytelen = 16;
|
||||||
}
|
|
||||||
|
|
||||||
memcpy(s.local.data, r->id.idiag_src, s.local.bytelen);
|
memcpy(s->local.data, r->id.idiag_src, s->local.bytelen);
|
||||||
memcpy(s.remote.data, r->id.idiag_dst, s.local.bytelen);
|
memcpy(s->remote.data, r->id.idiag_dst, s->local.bytelen);
|
||||||
|
}
|
||||||
|
|
||||||
if (f && f->f && run_ssfilter(f->f, &s) == 0)
|
static int inet_show_sock(struct nlmsghdr *nlh,
|
||||||
return 0;
|
struct sockstat *s,
|
||||||
|
int protocol)
|
||||||
|
{
|
||||||
|
struct rtattr *tb[INET_DIAG_MAX+1];
|
||||||
|
struct inet_diag_msg *r = NLMSG_DATA(nlh);
|
||||||
|
|
||||||
|
parse_rtattr(tb, INET_DIAG_MAX, (struct rtattr *)(r+1),
|
||||||
|
nlh->nlmsg_len - NLMSG_LENGTH(sizeof(*r)));
|
||||||
|
|
||||||
if (tb[INET_DIAG_PROTOCOL])
|
if (tb[INET_DIAG_PROTOCOL])
|
||||||
protocol = *(__u8 *)RTA_DATA(tb[INET_DIAG_PROTOCOL]);
|
protocol = *(__u8 *)RTA_DATA(tb[INET_DIAG_PROTOCOL]);
|
||||||
|
|
||||||
inet_stats_print(&s, protocol);
|
inet_stats_print(s, protocol);
|
||||||
|
|
||||||
if (show_options) {
|
if (show_options) {
|
||||||
struct tcpstat t = {};
|
struct tcpstat t = {};
|
||||||
|
|
@ -2085,8 +2137,8 @@ static int inet_show_sock(struct nlmsghdr *nlh, struct filter *f, int protocol)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (show_details) {
|
if (show_details) {
|
||||||
sock_details_print(&s);
|
sock_details_print(s);
|
||||||
if (s.local.family == AF_INET6 && tb[INET_DIAG_SKV6ONLY]) {
|
if (s->local.family == AF_INET6 && tb[INET_DIAG_SKV6ONLY]) {
|
||||||
unsigned char v6only;
|
unsigned char v6only;
|
||||||
|
|
||||||
v6only = *(__u8 *)RTA_DATA(tb[INET_DIAG_SKV6ONLY]);
|
v6only = *(__u8 *)RTA_DATA(tb[INET_DIAG_SKV6ONLY]);
|
||||||
|
|
@ -2121,6 +2173,7 @@ static int tcpdiag_send(int fd, int protocol, struct filter *f)
|
||||||
struct msghdr msg;
|
struct msghdr msg;
|
||||||
struct rtattr rta;
|
struct rtattr rta;
|
||||||
struct iovec iov[3];
|
struct iovec iov[3];
|
||||||
|
int iovlen = 1;
|
||||||
|
|
||||||
if (protocol == IPPROTO_UDP)
|
if (protocol == IPPROTO_UDP)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
@ -2156,18 +2209,21 @@ static int tcpdiag_send(int fd, int protocol, struct filter *f)
|
||||||
};
|
};
|
||||||
if (f->f) {
|
if (f->f) {
|
||||||
bclen = ssfilter_bytecompile(f->f, &bc);
|
bclen = ssfilter_bytecompile(f->f, &bc);
|
||||||
rta.rta_type = INET_DIAG_REQ_BYTECODE;
|
if (bclen) {
|
||||||
rta.rta_len = RTA_LENGTH(bclen);
|
rta.rta_type = INET_DIAG_REQ_BYTECODE;
|
||||||
iov[1] = (struct iovec){ &rta, sizeof(rta) };
|
rta.rta_len = RTA_LENGTH(bclen);
|
||||||
iov[2] = (struct iovec){ bc, bclen };
|
iov[1] = (struct iovec){ &rta, sizeof(rta) };
|
||||||
req.nlh.nlmsg_len += RTA_LENGTH(bclen);
|
iov[2] = (struct iovec){ bc, bclen };
|
||||||
|
req.nlh.nlmsg_len += RTA_LENGTH(bclen);
|
||||||
|
iovlen = 3;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
msg = (struct msghdr) {
|
msg = (struct msghdr) {
|
||||||
.msg_name = (void *)&nladdr,
|
.msg_name = (void *)&nladdr,
|
||||||
.msg_namelen = sizeof(nladdr),
|
.msg_namelen = sizeof(nladdr),
|
||||||
.msg_iov = iov,
|
.msg_iov = iov,
|
||||||
.msg_iovlen = f->f ? 3 : 1,
|
.msg_iovlen = iovlen,
|
||||||
};
|
};
|
||||||
|
|
||||||
if (sendmsg(fd, &msg, 0) < 0) {
|
if (sendmsg(fd, &msg, 0) < 0) {
|
||||||
|
|
@ -2188,6 +2244,7 @@ static int sockdiag_send(int family, int fd, int protocol, struct filter *f)
|
||||||
struct msghdr msg;
|
struct msghdr msg;
|
||||||
struct rtattr rta;
|
struct rtattr rta;
|
||||||
struct iovec iov[3];
|
struct iovec iov[3];
|
||||||
|
int iovlen = 1;
|
||||||
|
|
||||||
if (family == PF_UNSPEC)
|
if (family == PF_UNSPEC)
|
||||||
return tcpdiag_send(fd, protocol, f);
|
return tcpdiag_send(fd, protocol, f);
|
||||||
|
|
@ -2216,18 +2273,21 @@ static int sockdiag_send(int family, int fd, int protocol, struct filter *f)
|
||||||
};
|
};
|
||||||
if (f->f) {
|
if (f->f) {
|
||||||
bclen = ssfilter_bytecompile(f->f, &bc);
|
bclen = ssfilter_bytecompile(f->f, &bc);
|
||||||
rta.rta_type = INET_DIAG_REQ_BYTECODE;
|
if (bclen) {
|
||||||
rta.rta_len = RTA_LENGTH(bclen);
|
rta.rta_type = INET_DIAG_REQ_BYTECODE;
|
||||||
iov[1] = (struct iovec){ &rta, sizeof(rta) };
|
rta.rta_len = RTA_LENGTH(bclen);
|
||||||
iov[2] = (struct iovec){ bc, bclen };
|
iov[1] = (struct iovec){ &rta, sizeof(rta) };
|
||||||
req.nlh.nlmsg_len += RTA_LENGTH(bclen);
|
iov[2] = (struct iovec){ bc, bclen };
|
||||||
|
req.nlh.nlmsg_len += RTA_LENGTH(bclen);
|
||||||
|
iovlen = 3;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
msg = (struct msghdr) {
|
msg = (struct msghdr) {
|
||||||
.msg_name = (void *)&nladdr,
|
.msg_name = (void *)&nladdr,
|
||||||
.msg_namelen = sizeof(nladdr),
|
.msg_namelen = sizeof(nladdr),
|
||||||
.msg_iov = iov,
|
.msg_iov = iov,
|
||||||
.msg_iovlen = f->f ? 3 : 1,
|
.msg_iovlen = iovlen,
|
||||||
};
|
};
|
||||||
|
|
||||||
if (sendmsg(fd, &msg, 0) < 0) {
|
if (sendmsg(fd, &msg, 0) < 0) {
|
||||||
|
|
@ -2268,9 +2328,16 @@ static int show_one_inet_sock(const struct sockaddr_nl *addr,
|
||||||
int err;
|
int err;
|
||||||
struct inet_diag_arg *diag_arg = arg;
|
struct inet_diag_arg *diag_arg = arg;
|
||||||
struct inet_diag_msg *r = NLMSG_DATA(h);
|
struct inet_diag_msg *r = NLMSG_DATA(h);
|
||||||
|
struct sockstat s = {};
|
||||||
|
|
||||||
if (!(diag_arg->f->families & (1 << r->idiag_family)))
|
if (!(diag_arg->f->families & (1 << r->idiag_family)))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
parse_diag_msg(h, &s);
|
||||||
|
|
||||||
|
if (diag_arg->f->f && run_ssfilter(diag_arg->f->f, &s) == 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
if (diag_arg->f->kill && kill_inet_sock(h, arg) != 0) {
|
if (diag_arg->f->kill && kill_inet_sock(h, arg) != 0) {
|
||||||
if (errno == EOPNOTSUPP || errno == ENOENT) {
|
if (errno == EOPNOTSUPP || errno == ENOENT) {
|
||||||
/* Socket can't be closed, or is already closed. */
|
/* Socket can't be closed, or is already closed. */
|
||||||
|
|
@ -2280,7 +2347,9 @@ static int show_one_inet_sock(const struct sockaddr_nl *addr,
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ((err = inet_show_sock(h, diag_arg->f, diag_arg->protocol)) < 0)
|
|
||||||
|
err = inet_show_sock(h, &s, diag_arg->protocol);
|
||||||
|
if (err < 0)
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
@ -2345,6 +2414,7 @@ static int tcp_show_netlink_file(struct filter *f)
|
||||||
while (1) {
|
while (1) {
|
||||||
int status, err;
|
int status, err;
|
||||||
struct nlmsghdr *h = (struct nlmsghdr *)buf;
|
struct nlmsghdr *h = (struct nlmsghdr *)buf;
|
||||||
|
struct sockstat s = {};
|
||||||
|
|
||||||
status = fread(buf, 1, sizeof(*h), fp);
|
status = fread(buf, 1, sizeof(*h), fp);
|
||||||
if (status < 0) {
|
if (status < 0) {
|
||||||
|
|
@ -2383,7 +2453,12 @@ static int tcp_show_netlink_file(struct filter *f)
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
err = inet_show_sock(h, f, IPPROTO_TCP);
|
parse_diag_msg(h, &s);
|
||||||
|
|
||||||
|
if (f && f->f && run_ssfilter(f->f, &s) == 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
err = inet_show_sock(h, &s, IPPROTO_TCP);
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,7 @@
|
||||||
#define SSF_S_GE 7
|
#define SSF_S_GE 7
|
||||||
#define SSF_S_LE 8
|
#define SSF_S_LE 8
|
||||||
#define SSF_S_AUTO 9
|
#define SSF_S_AUTO 9
|
||||||
|
#define SSF_DEVCOND 10
|
||||||
|
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
|
|
||||||
|
|
@ -20,3 +21,4 @@ struct ssfilter
|
||||||
|
|
||||||
int ssfilter_parse(struct ssfilter **f, int argc, char **argv, FILE *fp);
|
int ssfilter_parse(struct ssfilter **f, int argc, char **argv, FILE *fp);
|
||||||
void *parse_hostcond(char *addr, bool is_port);
|
void *parse_hostcond(char *addr, bool is_port);
|
||||||
|
void *parse_devcond(char *name);
|
||||||
|
|
|
||||||
|
|
@ -36,7 +36,7 @@ static void yyerror(char *s)
|
||||||
|
|
||||||
%}
|
%}
|
||||||
|
|
||||||
%token HOSTCOND DCOND SCOND DPORT SPORT LEQ GEQ NEQ AUTOBOUND
|
%token HOSTCOND DCOND SCOND DPORT SPORT LEQ GEQ NEQ AUTOBOUND DEVCOND DEVNAME
|
||||||
%left '|'
|
%left '|'
|
||||||
%left '&'
|
%left '&'
|
||||||
%nonassoc '!'
|
%nonassoc '!'
|
||||||
|
|
@ -108,6 +108,14 @@ expr: DCOND HOSTCOND
|
||||||
{
|
{
|
||||||
$$ = alloc_node(SSF_NOT, alloc_node(SSF_SCOND, $3));
|
$$ = alloc_node(SSF_NOT, alloc_node(SSF_SCOND, $3));
|
||||||
}
|
}
|
||||||
|
| DEVNAME '=' DEVCOND
|
||||||
|
{
|
||||||
|
$$ = alloc_node(SSF_DEVCOND, $3);
|
||||||
|
}
|
||||||
|
| DEVNAME NEQ DEVCOND
|
||||||
|
{
|
||||||
|
$$ = alloc_node(SSF_NOT, alloc_node(SSF_DEVCOND, $3));
|
||||||
|
}
|
||||||
|
|
||||||
| AUTOBOUND
|
| AUTOBOUND
|
||||||
{
|
{
|
||||||
|
|
@ -237,6 +245,10 @@ int yylex(void)
|
||||||
tok_type = SPORT;
|
tok_type = SPORT;
|
||||||
return SPORT;
|
return SPORT;
|
||||||
}
|
}
|
||||||
|
if (strcmp(curtok, "dev") == 0) {
|
||||||
|
tok_type = DEVNAME;
|
||||||
|
return DEVNAME;
|
||||||
|
}
|
||||||
if (strcmp(curtok, ">=") == 0 ||
|
if (strcmp(curtok, ">=") == 0 ||
|
||||||
strcmp(curtok, "ge") == 0 ||
|
strcmp(curtok, "ge") == 0 ||
|
||||||
strcmp(curtok, "geq") == 0)
|
strcmp(curtok, "geq") == 0)
|
||||||
|
|
@ -263,6 +275,14 @@ int yylex(void)
|
||||||
tok_type = AUTOBOUND;
|
tok_type = AUTOBOUND;
|
||||||
return AUTOBOUND;
|
return AUTOBOUND;
|
||||||
}
|
}
|
||||||
|
if (tok_type == DEVNAME) {
|
||||||
|
yylval = (void*)parse_devcond(curtok);
|
||||||
|
if (yylval == NULL) {
|
||||||
|
fprintf(stderr, "Cannot parse device.\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
return DEVCOND;
|
||||||
|
}
|
||||||
yylval = (void*)parse_hostcond(curtok, tok_type == SPORT || tok_type == DPORT);
|
yylval = (void*)parse_hostcond(curtok, tok_type == SPORT || tok_type == DPORT);
|
||||||
if (yylval == NULL) {
|
if (yylval == NULL) {
|
||||||
fprintf(stderr, "Cannot parse dst/src address.\n");
|
fprintf(stderr, "Cannot parse dst/src address.\n");
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue