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) {
|
||||
NEXT_ARG();
|
||||
char *endptr;
|
||||
size_t nstates = sizeof(port_states) / sizeof(*port_states);
|
||||
size_t nstates = ARRAY_SIZE(port_states);
|
||||
|
||||
state = strtol(*argv, &endptr, 10);
|
||||
if (!(**argv != '\0' && *endptr == '\0')) {
|
||||
|
|
|
|||
|
|
@ -61,6 +61,7 @@ static struct
|
|||
int group;
|
||||
int master;
|
||||
char *kind;
|
||||
char *slave_kind;
|
||||
} filter;
|
||||
|
||||
static int do_link;
|
||||
|
|
@ -94,9 +95,9 @@ static void usage(void)
|
|||
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");
|
||||
fprintf(stderr, " bridge | bond | ipoib | ip6tnl | ipip | sit | vxlan | lowpan |\n");
|
||||
fprintf(stderr, " gre | gretap | ip6gre | ip6gretap | vti | nlmon | can |\n");
|
||||
fprintf(stderr, " bond_slave | ipvlan | geneve | bridge_slave | vrf | hsr}\n");
|
||||
|
||||
exit(-1);
|
||||
}
|
||||
|
|
@ -206,18 +207,27 @@ static void print_linkmode(FILE *f, struct rtattr *tb)
|
|||
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];
|
||||
int attr = slave ? IFLA_INFO_SLAVE_KIND : IFLA_INFO_KIND;
|
||||
|
||||
parse_rtattr_nested(linkinfo, IFLA_INFO_MAX, tb);
|
||||
|
||||
if (linkinfo[IFLA_INFO_KIND])
|
||||
return RTA_DATA(linkinfo[IFLA_INFO_KIND]);
|
||||
if (linkinfo[attr])
|
||||
return RTA_DATA(linkinfo[attr]);
|
||||
|
||||
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)
|
||||
{
|
||||
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)
|
||||
return -1;
|
||||
|
||||
if (filter.kind) {
|
||||
if (tb[IFLA_LINKINFO]) {
|
||||
char *kind = parse_link_kind(tb[IFLA_LINKINFO]);
|
||||
if (filter.kind && match_link_kind(tb, filter.kind, 0))
|
||||
return -1;
|
||||
|
||||
if (strcmp(kind, filter.kind))
|
||||
return -1;
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
if (filter.slave_kind && match_link_kind(tb, filter.slave_kind, 1))
|
||||
return -1;
|
||||
|
||||
if (n->nlmsg_type == RTM_DELLINK)
|
||||
fprintf(fp, "Deleted ");
|
||||
|
|
@ -781,16 +786,11 @@ int print_linkinfo(const struct sockaddr_nl *who,
|
|||
} else if (filter.master > 0)
|
||||
return -1;
|
||||
|
||||
if (filter.kind) {
|
||||
if (tb[IFLA_LINKINFO]) {
|
||||
char *kind = parse_link_kind(tb[IFLA_LINKINFO]);
|
||||
if (filter.kind && match_link_kind(tb, filter.kind, 0))
|
||||
return -1;
|
||||
|
||||
if (strcmp(kind, filter.kind))
|
||||
return -1;
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
if (filter.slave_kind && match_link_kind(tb, filter.slave_kind, 1))
|
||||
return -1;
|
||||
|
||||
if (n->nlmsg_type == RTM_DELLINK)
|
||||
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);
|
||||
filter.master = ifindex;
|
||||
} else if (strcmp(*argv, "type") == 0) {
|
||||
int soff;
|
||||
|
||||
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 {
|
||||
if (strcmp(*argv, "dev") == 0) {
|
||||
NEXT_ARG();
|
||||
|
|
|
|||
|
|
@ -839,7 +839,6 @@ static int iproute_modify(int cmd, unsigned int flags, int argc, char **argv)
|
|||
int table_ok = 0;
|
||||
int raw = 0;
|
||||
int type_ok = 0;
|
||||
static int hz;
|
||||
|
||||
memset(&req, 0, sizeof(req));
|
||||
|
||||
|
|
@ -923,9 +922,7 @@ static int iproute_modify(int cmd, unsigned int flags, int argc, char **argv)
|
|||
NEXT_ARG();
|
||||
if (get_u32(&expires, *argv, 0))
|
||||
invarg("\"expires\" value is invalid\n", *argv);
|
||||
if (!hz)
|
||||
hz = get_user_hz();
|
||||
addattr32(&req.n, sizeof(req), RTA_EXPIRES, expires*hz);
|
||||
addattr32(&req.n, sizeof(req), RTA_EXPIRES, expires);
|
||||
} else if (matches(*argv, "metric") == 0 ||
|
||||
matches(*argv, "priority") == 0 ||
|
||||
strcmp(*argv, "preference") == 0) {
|
||||
|
|
|
|||
|
|
@ -235,7 +235,7 @@ error.
|
|||
|
||||
.B 1
|
||||
- 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
|
||||
|
||||
.B 2
|
||||
|
|
@ -256,7 +256,7 @@ STP BPDUs.
|
|||
|
||||
.TP
|
||||
.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
|
||||
cause the port to stop processing STP BPDUs.
|
||||
|
||||
|
|
|
|||
|
|
@ -98,7 +98,9 @@ ip-address \- protocol address management
|
|||
.ti -8
|
||||
.IR TYPE " := [ "
|
||||
.BR bridge " | "
|
||||
.BR bridge_slave " |"
|
||||
.BR bond " | "
|
||||
.BR bond_slave " |"
|
||||
.BR can " | "
|
||||
.BR dummy " | "
|
||||
.BR hsr " | "
|
||||
|
|
@ -118,6 +120,7 @@ ip-address \- protocol address management
|
|||
.BR ip6gre " |"
|
||||
.BR ip6gretap " |"
|
||||
.BR vti " |"
|
||||
.BR vrf " |"
|
||||
.BR nlmon " |"
|
||||
.BR ipvlan " |"
|
||||
.BR lowpan " |"
|
||||
|
|
|
|||
|
|
@ -30,6 +30,7 @@
|
|||
|
||||
#include <json_writer.h>
|
||||
#include <SNAPSHOT.h>
|
||||
#include "utils.h"
|
||||
|
||||
int dump_zeros;
|
||||
int reset_history;
|
||||
|
|
@ -95,7 +96,7 @@ static int useless_number(const char *id)
|
|||
{
|
||||
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)
|
||||
return 1;
|
||||
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) {
|
||||
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) {
|
||||
sscanf(buf, "%*s%d", ((int *)s) + i);
|
||||
cnt--;
|
||||
|
|
@ -1043,6 +1043,7 @@ static void inet_addr_print(const inet_prefix *a, int port, unsigned int ifindex
|
|||
struct aafilter {
|
||||
inet_prefix addr;
|
||||
int port;
|
||||
unsigned int iface;
|
||||
struct aafilter *next;
|
||||
};
|
||||
|
||||
|
|
@ -1157,7 +1158,12 @@ static int run_ssfilter(struct ssfilter *f, struct sockstat *s)
|
|||
|
||||
return s->lport <= a->port;
|
||||
}
|
||||
case SSF_DEVCOND:
|
||||
{
|
||||
struct aafilter *a = (void *)f->pred;
|
||||
|
||||
return s->iface == a->iface;
|
||||
}
|
||||
/* Yup. It is recursion. Sorry. */
|
||||
case SSF_AND:
|
||||
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:
|
||||
{
|
||||
char *a1, *a2, *a;
|
||||
char *a1 = NULL, *a2 = NULL, *a;
|
||||
int l1, l2;
|
||||
|
||||
l1 = ssfilter_bytecompile(f->pred, &a1);
|
||||
l2 = ssfilter_bytecompile(f->post, &a2);
|
||||
if (!l1 || !l2) {
|
||||
free(a1);
|
||||
free(a2);
|
||||
return 0;
|
||||
}
|
||||
if (!(a = malloc(l1+l2))) abort();
|
||||
memcpy(a, a1, l1);
|
||||
memcpy(a+l1, a2, l2);
|
||||
|
|
@ -1288,11 +1299,16 @@ static int ssfilter_bytecompile(struct ssfilter *f, char **bytecode)
|
|||
}
|
||||
case SSF_OR:
|
||||
{
|
||||
char *a1, *a2, *a;
|
||||
char *a1 = NULL, *a2 = NULL, *a;
|
||||
int l1, l2;
|
||||
|
||||
l1 = ssfilter_bytecompile(f->pred, &a1);
|
||||
l2 = ssfilter_bytecompile(f->post, &a2);
|
||||
if (!l1 || !l2) {
|
||||
free(a1);
|
||||
free(a2);
|
||||
return 0;
|
||||
}
|
||||
if (!(a = malloc(l1+l2+4))) abort();
|
||||
memcpy(a, a1, l1);
|
||||
memcpy(a+l1+4, a2, l2);
|
||||
|
|
@ -1303,16 +1319,25 @@ static int ssfilter_bytecompile(struct ssfilter *f, char **bytecode)
|
|||
}
|
||||
case SSF_NOT:
|
||||
{
|
||||
char *a1, *a;
|
||||
char *a1 = NULL, *a;
|
||||
int l1;
|
||||
|
||||
l1 = ssfilter_bytecompile(f->pred, &a1);
|
||||
if (!l1) {
|
||||
free(a1);
|
||||
return 0;
|
||||
}
|
||||
if (!(a = malloc(l1+4))) abort();
|
||||
memcpy(a, a1, l1);
|
||||
free(a1);
|
||||
*(struct inet_diag_bc_op *)(a+l1) = (struct inet_diag_bc_op){ INET_DIAG_BC_JMP, 4, 8 };
|
||||
*bytecode = a;
|
||||
return l1+4;
|
||||
}
|
||||
case SSF_DEVCOND:
|
||||
{
|
||||
/* bytecompile for SSF_DEVCOND not supported yet */
|
||||
return 0;
|
||||
}
|
||||
default:
|
||||
abort();
|
||||
|
|
@ -1402,6 +1427,27 @@ static int xll_name_to_index(const char *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)
|
||||
{
|
||||
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 inet_diag_msg *r = NLMSG_DATA(nlh);
|
||||
struct sockstat s = {};
|
||||
|
||||
parse_rtattr(tb, INET_DIAG_MAX, (struct rtattr *)(r+1),
|
||||
nlh->nlmsg_len - NLMSG_LENGTH(sizeof(*r)));
|
||||
|
||||
s.state = r->idiag_state;
|
||||
s.local.family = s.remote.family = r->idiag_family;
|
||||
s.lport = ntohs(r->id.idiag_sport);
|
||||
s.rport = ntohs(r->id.idiag_dport);
|
||||
s.wq = r->idiag_wqueue;
|
||||
s.rq = r->idiag_rqueue;
|
||||
s.ino = r->idiag_inode;
|
||||
s.uid = r->idiag_uid;
|
||||
s.iface = r->id.idiag_if;
|
||||
s.sk = cookie_sk_get(&r->id.idiag_cookie[0]);
|
||||
s->state = r->idiag_state;
|
||||
s->local.family = s->remote.family = r->idiag_family;
|
||||
s->lport = ntohs(r->id.idiag_sport);
|
||||
s->rport = ntohs(r->id.idiag_dport);
|
||||
s->wq = r->idiag_wqueue;
|
||||
s->rq = r->idiag_rqueue;
|
||||
s->ino = r->idiag_inode;
|
||||
s->uid = r->idiag_uid;
|
||||
s->iface = r->id.idiag_if;
|
||||
s->sk = cookie_sk_get(&r->id.idiag_cookie[0]);
|
||||
|
||||
if (s.local.family == AF_INET) {
|
||||
s.local.bytelen = s.remote.bytelen = 4;
|
||||
} else {
|
||||
s.local.bytelen = s.remote.bytelen = 16;
|
||||
}
|
||||
if (s->local.family == AF_INET)
|
||||
s->local.bytelen = s->remote.bytelen = 4;
|
||||
else
|
||||
s->local.bytelen = s->remote.bytelen = 16;
|
||||
|
||||
memcpy(s.local.data, r->id.idiag_src, s.local.bytelen);
|
||||
memcpy(s.remote.data, r->id.idiag_dst, 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);
|
||||
}
|
||||
|
||||
if (f && f->f && run_ssfilter(f->f, &s) == 0)
|
||||
return 0;
|
||||
static int inet_show_sock(struct nlmsghdr *nlh,
|
||||
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])
|
||||
protocol = *(__u8 *)RTA_DATA(tb[INET_DIAG_PROTOCOL]);
|
||||
|
||||
inet_stats_print(&s, protocol);
|
||||
inet_stats_print(s, protocol);
|
||||
|
||||
if (show_options) {
|
||||
struct tcpstat t = {};
|
||||
|
|
@ -2085,8 +2137,8 @@ static int inet_show_sock(struct nlmsghdr *nlh, struct filter *f, int protocol)
|
|||
}
|
||||
|
||||
if (show_details) {
|
||||
sock_details_print(&s);
|
||||
if (s.local.family == AF_INET6 && tb[INET_DIAG_SKV6ONLY]) {
|
||||
sock_details_print(s);
|
||||
if (s->local.family == AF_INET6 && tb[INET_DIAG_SKV6ONLY]) {
|
||||
unsigned char v6only;
|
||||
|
||||
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 rtattr rta;
|
||||
struct iovec iov[3];
|
||||
int iovlen = 1;
|
||||
|
||||
if (protocol == IPPROTO_UDP)
|
||||
return -1;
|
||||
|
|
@ -2156,18 +2209,21 @@ static int tcpdiag_send(int fd, int protocol, struct filter *f)
|
|||
};
|
||||
if (f->f) {
|
||||
bclen = ssfilter_bytecompile(f->f, &bc);
|
||||
rta.rta_type = INET_DIAG_REQ_BYTECODE;
|
||||
rta.rta_len = RTA_LENGTH(bclen);
|
||||
iov[1] = (struct iovec){ &rta, sizeof(rta) };
|
||||
iov[2] = (struct iovec){ bc, bclen };
|
||||
req.nlh.nlmsg_len += RTA_LENGTH(bclen);
|
||||
if (bclen) {
|
||||
rta.rta_type = INET_DIAG_REQ_BYTECODE;
|
||||
rta.rta_len = RTA_LENGTH(bclen);
|
||||
iov[1] = (struct iovec){ &rta, sizeof(rta) };
|
||||
iov[2] = (struct iovec){ bc, bclen };
|
||||
req.nlh.nlmsg_len += RTA_LENGTH(bclen);
|
||||
iovlen = 3;
|
||||
}
|
||||
}
|
||||
|
||||
msg = (struct msghdr) {
|
||||
.msg_name = (void *)&nladdr,
|
||||
.msg_namelen = sizeof(nladdr),
|
||||
.msg_iov = iov,
|
||||
.msg_iovlen = f->f ? 3 : 1,
|
||||
.msg_iovlen = iovlen,
|
||||
};
|
||||
|
||||
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 rtattr rta;
|
||||
struct iovec iov[3];
|
||||
int iovlen = 1;
|
||||
|
||||
if (family == PF_UNSPEC)
|
||||
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) {
|
||||
bclen = ssfilter_bytecompile(f->f, &bc);
|
||||
rta.rta_type = INET_DIAG_REQ_BYTECODE;
|
||||
rta.rta_len = RTA_LENGTH(bclen);
|
||||
iov[1] = (struct iovec){ &rta, sizeof(rta) };
|
||||
iov[2] = (struct iovec){ bc, bclen };
|
||||
req.nlh.nlmsg_len += RTA_LENGTH(bclen);
|
||||
if (bclen) {
|
||||
rta.rta_type = INET_DIAG_REQ_BYTECODE;
|
||||
rta.rta_len = RTA_LENGTH(bclen);
|
||||
iov[1] = (struct iovec){ &rta, sizeof(rta) };
|
||||
iov[2] = (struct iovec){ bc, bclen };
|
||||
req.nlh.nlmsg_len += RTA_LENGTH(bclen);
|
||||
iovlen = 3;
|
||||
}
|
||||
}
|
||||
|
||||
msg = (struct msghdr) {
|
||||
.msg_name = (void *)&nladdr,
|
||||
.msg_namelen = sizeof(nladdr),
|
||||
.msg_iov = iov,
|
||||
.msg_iovlen = f->f ? 3 : 1,
|
||||
.msg_iovlen = iovlen,
|
||||
};
|
||||
|
||||
if (sendmsg(fd, &msg, 0) < 0) {
|
||||
|
|
@ -2268,9 +2328,16 @@ static int show_one_inet_sock(const struct sockaddr_nl *addr,
|
|||
int err;
|
||||
struct inet_diag_arg *diag_arg = arg;
|
||||
struct inet_diag_msg *r = NLMSG_DATA(h);
|
||||
struct sockstat s = {};
|
||||
|
||||
if (!(diag_arg->f->families & (1 << r->idiag_family)))
|
||||
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 (errno == EOPNOTSUPP || errno == ENOENT) {
|
||||
/* 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;
|
||||
}
|
||||
}
|
||||
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 0;
|
||||
|
|
@ -2345,6 +2414,7 @@ static int tcp_show_netlink_file(struct filter *f)
|
|||
while (1) {
|
||||
int status, err;
|
||||
struct nlmsghdr *h = (struct nlmsghdr *)buf;
|
||||
struct sockstat s = {};
|
||||
|
||||
status = fread(buf, 1, sizeof(*h), fp);
|
||||
if (status < 0) {
|
||||
|
|
@ -2383,7 +2453,12 @@ static int tcp_show_netlink_file(struct filter *f)
|
|||
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)
|
||||
return err;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@
|
|||
#define SSF_S_GE 7
|
||||
#define SSF_S_LE 8
|
||||
#define SSF_S_AUTO 9
|
||||
#define SSF_DEVCOND 10
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
|
|
@ -20,3 +21,4 @@ struct ssfilter
|
|||
|
||||
int ssfilter_parse(struct ssfilter **f, int argc, char **argv, FILE *fp);
|
||||
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 '&'
|
||||
%nonassoc '!'
|
||||
|
|
@ -108,6 +108,14 @@ expr: DCOND HOSTCOND
|
|||
{
|
||||
$$ = 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
|
||||
{
|
||||
|
|
@ -237,6 +245,10 @@ int yylex(void)
|
|||
tok_type = SPORT;
|
||||
return SPORT;
|
||||
}
|
||||
if (strcmp(curtok, "dev") == 0) {
|
||||
tok_type = DEVNAME;
|
||||
return DEVNAME;
|
||||
}
|
||||
if (strcmp(curtok, ">=") == 0 ||
|
||||
strcmp(curtok, "ge") == 0 ||
|
||||
strcmp(curtok, "geq") == 0)
|
||||
|
|
@ -263,6 +275,14 @@ int yylex(void)
|
|||
tok_type = 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);
|
||||
if (yylval == NULL) {
|
||||
fprintf(stderr, "Cannot parse dst/src address.\n");
|
||||
|
|
|
|||
Loading…
Reference in New Issue