static void usage(void) __attribute__((noreturn));
int prefix_banner;
+int listen_all_nsid;
static void usage(void)
{
- fprintf(stderr, "Usage: ip monitor [ all | LISTofOBJECTS ] [ FILE ]"
- "[ label ] [dev DEVICE]\n");
+ fprintf(stderr, "Usage: ip monitor [ all | LISTofOBJECTS ] [ FILE ] "
+ "[ label ] [all-nsid] [dev DEVICE]\n");
fprintf(stderr, "LISTofOBJECTS := link | address | route | mroute | prefix |\n");
fprintf(stderr, " neigh | netconf | rule | nsid\n");
fprintf(stderr, "FILE := file FILENAME\n");
exit(-1);
}
-static void print_headers(FILE *fp, char *label)
+static void print_headers(FILE *fp, char *label, struct rtnl_ctrl_data *ctrl)
{
if (timestamp)
print_timestamp(fp);
+ if (listen_all_nsid) {
+ if (ctrl == NULL || ctrl->nsid < 0)
+ fprintf(fp, "[nsid current]");
+ else
+ fprintf(fp, "[nsid %d]", ctrl->nsid);
+ }
+
if (prefix_banner)
fprintf(fp, "%s", label);
}
if (r->rtm_family == RTNL_FAMILY_IPMR ||
r->rtm_family == RTNL_FAMILY_IP6MR) {
- print_headers(fp, "[MROUTE]");
+ print_headers(fp, "[MROUTE]", ctrl);
print_mroute(who, n, arg);
return 0;
} else {
- print_headers(fp, "[ROUTE]");
+ print_headers(fp, "[ROUTE]", ctrl);
print_route(who, n, arg);
return 0;
}
if (n->nlmsg_type == RTM_NEWLINK || n->nlmsg_type == RTM_DELLINK) {
ll_remember_index(who, n, NULL);
- print_headers(fp, "[LINK]");
+ print_headers(fp, "[LINK]", ctrl);
print_linkinfo(who, n, arg);
return 0;
}
if (n->nlmsg_type == RTM_NEWADDR || n->nlmsg_type == RTM_DELADDR) {
- print_headers(fp, "[ADDR]");
+ print_headers(fp, "[ADDR]", ctrl);
print_addrinfo(who, n, arg);
return 0;
}
if (n->nlmsg_type == RTM_NEWADDRLABEL || n->nlmsg_type == RTM_DELADDRLABEL) {
- print_headers(fp, "[ADDRLABEL]");
+ print_headers(fp, "[ADDRLABEL]", ctrl);
print_addrlabel(who, n, arg);
return 0;
}
return 0;
}
- print_headers(fp, "[NEIGH]");
+ print_headers(fp, "[NEIGH]", ctrl);
print_neigh(who, n, arg);
return 0;
}
if (n->nlmsg_type == RTM_NEWPREFIX) {
- print_headers(fp, "[PREFIX]");
+ print_headers(fp, "[PREFIX]", ctrl);
print_prefix(who, n, arg);
return 0;
}
if (n->nlmsg_type == RTM_NEWRULE || n->nlmsg_type == RTM_DELRULE) {
- print_headers(fp, "[RULE]");
+ print_headers(fp, "[RULE]", ctrl);
print_rule(who, n, arg);
return 0;
}
if (n->nlmsg_type == RTM_NEWNETCONF) {
- print_headers(fp, "[NETCONF]");
+ print_headers(fp, "[NETCONF]", ctrl);
print_netconf(who, ctrl, n, arg);
return 0;
}
return 0;
}
if (n->nlmsg_type == RTM_NEWNSID || n->nlmsg_type == RTM_DELNSID) {
- print_headers(fp, "[NSID]");
+ print_headers(fp, "[NSID]", ctrl);
print_nsid(who, n, arg);
return 0;
}
file = *argv;
} else if (matches(*argv, "label") == 0) {
prefix_banner = 1;
+ } else if (matches(*argv, "all-nsid") == 0) {
+ listen_all_nsid = 1;
} else if (matches(*argv, "link") == 0) {
llink=1;
groups = 0;
if (rtnl_open(&rth, groups) < 0)
exit(1);
+ if (listen_all_nsid && rtnl_listen_all_nsid(&rth) < 0)
+ exit(1);
+
ll_init_map(&rth);
netns_map_init();
#include "libnetlink.h"
+#ifndef SOL_NETLINK
+#define SOL_NETLINK 270
+#endif
+
int rcvbuf = 1024 * 1024;
void rtnl_close(struct rtnl_handle *rth)
}
}
+int rtnl_listen_all_nsid(struct rtnl_handle *rth)
+{
+ unsigned int on = 1;
+
+ if (setsockopt(rth->fd, SOL_NETLINK, NETLINK_LISTEN_ALL_NSID, &on,
+ sizeof(on)) < 0) {
+ perror("NETLINK_LISTEN_ALL_NSID");
+ return -1;
+ }
+ rth->flags |= RTNL_HANDLE_F_LISTEN_ALL_NSID;
+ return 0;
+}
+
int rtnl_listen(struct rtnl_handle *rtnl,
rtnl_listen_filter_t handler,
void *jarg)
.msg_iovlen = 1,
};
char buf[16384];
+ char cmsgbuf[BUFSIZ];
+
+ if (rtnl->flags & RTNL_HANDLE_F_LISTEN_ALL_NSID) {
+ msg.msg_control = &cmsgbuf;
+ msg.msg_controllen = sizeof(cmsgbuf);
+ }
memset(&nladdr, 0, sizeof(nladdr));
nladdr.nl_family = AF_NETLINK;
iov.iov_base = buf;
while (1) {
+ struct rtnl_ctrl_data ctrl;
+ struct cmsghdr *cmsg;
+
iov.iov_len = sizeof(buf);
status = recvmsg(rtnl->fd, &msg, 0);
fprintf(stderr, "Sender address length == %d\n", msg.msg_namelen);
exit(1);
}
+
+ if (rtnl->flags & RTNL_HANDLE_F_LISTEN_ALL_NSID) {
+ memset(&ctrl, 0, sizeof(ctrl));
+ ctrl.nsid = -1;
+ for (cmsg = CMSG_FIRSTHDR(&msg); cmsg;
+ cmsg = CMSG_NXTHDR(&msg, cmsg))
+ if (cmsg->cmsg_level == SOL_NETLINK &&
+ cmsg->cmsg_type == NETLINK_LISTEN_ALL_NSID &&
+ cmsg->cmsg_len == CMSG_LEN(sizeof(int))) {
+ int *data = (int *)CMSG_DATA(cmsg);
+
+ ctrl.nsid = *data;
+ }
+ }
+
for (h = (struct nlmsghdr*)buf; status >= sizeof(*h); ) {
int err;
int len = h->nlmsg_len;
exit(1);
}
- err = handler(&nladdr, NULL, h, jarg);
+ err = handler(&nladdr, &ctrl, h, jarg);
if (err < 0)
return err;