Commit 449b824a authored by Nicolas Dichtel's avatar Nicolas Dichtel Committed by Stephen Hemminger

ipmonitor: allows to monitor in several netns

With this patch, it's now possible to listen in all netns that have an nsid
assigned into the netns where the socket is opened.
Signed-off-by: default avatarNicolas Dichtel <nicolas.dichtel@6wind.com>
parent 3b0006f8
...@@ -20,6 +20,8 @@ struct rtnl_handle ...@@ -20,6 +20,8 @@ struct rtnl_handle
__u32 dump; __u32 dump;
int proto; int proto;
FILE *dump_fp; FILE *dump_fp;
#define RTNL_HANDLE_F_LISTEN_ALL_NSID 0x01
int flags;
}; };
extern int rcvbuf; extern int rcvbuf;
...@@ -42,6 +44,7 @@ extern int rtnl_dump_request(struct rtnl_handle *rth, int type, void *req, ...@@ -42,6 +44,7 @@ extern int rtnl_dump_request(struct rtnl_handle *rth, int type, void *req,
__attribute__((warn_unused_result)); __attribute__((warn_unused_result));
struct rtnl_ctrl_data { struct rtnl_ctrl_data {
int nsid;
}; };
typedef int (*rtnl_filter_t)(const struct sockaddr_nl *, typedef int (*rtnl_filter_t)(const struct sockaddr_nl *,
...@@ -125,6 +128,7 @@ static inline const char *rta_getattr_str(const struct rtattr *rta) ...@@ -125,6 +128,7 @@ static inline const char *rta_getattr_str(const struct rtattr *rta)
return (const char *)RTA_DATA(rta); return (const char *)RTA_DATA(rta);
} }
extern int rtnl_listen_all_nsid(struct rtnl_handle *);
extern int rtnl_listen(struct rtnl_handle *, rtnl_listen_filter_t handler, extern int rtnl_listen(struct rtnl_handle *, rtnl_listen_filter_t handler,
void *jarg); void *jarg);
extern int rtnl_from_file(FILE *, rtnl_listen_filter_t handler, extern int rtnl_from_file(FILE *, rtnl_listen_filter_t handler,
......
...@@ -26,22 +26,30 @@ ...@@ -26,22 +26,30 @@
static void usage(void) __attribute__((noreturn)); static void usage(void) __attribute__((noreturn));
int prefix_banner; int prefix_banner;
int listen_all_nsid;
static void usage(void) static void usage(void)
{ {
fprintf(stderr, "Usage: ip monitor [ all | LISTofOBJECTS ] [ FILE ]" fprintf(stderr, "Usage: ip monitor [ all | LISTofOBJECTS ] [ FILE ] "
"[ label ] [dev DEVICE]\n"); "[ label ] [all-nsid] [dev DEVICE]\n");
fprintf(stderr, "LISTofOBJECTS := link | address | route | mroute | prefix |\n"); fprintf(stderr, "LISTofOBJECTS := link | address | route | mroute | prefix |\n");
fprintf(stderr, " neigh | netconf | rule | nsid\n"); fprintf(stderr, " neigh | netconf | rule | nsid\n");
fprintf(stderr, "FILE := file FILENAME\n"); fprintf(stderr, "FILE := file FILENAME\n");
exit(-1); 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) if (timestamp)
print_timestamp(fp); 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) if (prefix_banner)
fprintf(fp, "%s", label); fprintf(fp, "%s", label);
} }
...@@ -66,11 +74,11 @@ static int accept_msg(const struct sockaddr_nl *who, ...@@ -66,11 +74,11 @@ static int accept_msg(const struct sockaddr_nl *who,
if (r->rtm_family == RTNL_FAMILY_IPMR || if (r->rtm_family == RTNL_FAMILY_IPMR ||
r->rtm_family == RTNL_FAMILY_IP6MR) { r->rtm_family == RTNL_FAMILY_IP6MR) {
print_headers(fp, "[MROUTE]"); print_headers(fp, "[MROUTE]", ctrl);
print_mroute(who, n, arg); print_mroute(who, n, arg);
return 0; return 0;
} else { } else {
print_headers(fp, "[ROUTE]"); print_headers(fp, "[ROUTE]", ctrl);
print_route(who, n, arg); print_route(who, n, arg);
return 0; return 0;
} }
...@@ -78,17 +86,17 @@ static int accept_msg(const struct sockaddr_nl *who, ...@@ -78,17 +86,17 @@ static int accept_msg(const struct sockaddr_nl *who,
if (n->nlmsg_type == RTM_NEWLINK || n->nlmsg_type == RTM_DELLINK) { if (n->nlmsg_type == RTM_NEWLINK || n->nlmsg_type == RTM_DELLINK) {
ll_remember_index(who, n, NULL); ll_remember_index(who, n, NULL);
print_headers(fp, "[LINK]"); print_headers(fp, "[LINK]", ctrl);
print_linkinfo(who, n, arg); print_linkinfo(who, n, arg);
return 0; return 0;
} }
if (n->nlmsg_type == RTM_NEWADDR || n->nlmsg_type == RTM_DELADDR) { 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); print_addrinfo(who, n, arg);
return 0; return 0;
} }
if (n->nlmsg_type == RTM_NEWADDRLABEL || n->nlmsg_type == RTM_DELADDRLABEL) { 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); print_addrlabel(who, n, arg);
return 0; return 0;
} }
...@@ -101,22 +109,22 @@ static int accept_msg(const struct sockaddr_nl *who, ...@@ -101,22 +109,22 @@ static int accept_msg(const struct sockaddr_nl *who,
return 0; return 0;
} }
print_headers(fp, "[NEIGH]"); print_headers(fp, "[NEIGH]", ctrl);
print_neigh(who, n, arg); print_neigh(who, n, arg);
return 0; return 0;
} }
if (n->nlmsg_type == RTM_NEWPREFIX) { if (n->nlmsg_type == RTM_NEWPREFIX) {
print_headers(fp, "[PREFIX]"); print_headers(fp, "[PREFIX]", ctrl);
print_prefix(who, n, arg); print_prefix(who, n, arg);
return 0; return 0;
} }
if (n->nlmsg_type == RTM_NEWRULE || n->nlmsg_type == RTM_DELRULE) { 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); print_rule(who, n, arg);
return 0; return 0;
} }
if (n->nlmsg_type == RTM_NEWNETCONF) { if (n->nlmsg_type == RTM_NEWNETCONF) {
print_headers(fp, "[NETCONF]"); print_headers(fp, "[NETCONF]", ctrl);
print_netconf(who, ctrl, n, arg); print_netconf(who, ctrl, n, arg);
return 0; return 0;
} }
...@@ -125,7 +133,7 @@ static int accept_msg(const struct sockaddr_nl *who, ...@@ -125,7 +133,7 @@ static int accept_msg(const struct sockaddr_nl *who,
return 0; return 0;
} }
if (n->nlmsg_type == RTM_NEWNSID || n->nlmsg_type == RTM_DELNSID) { 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); print_nsid(who, n, arg);
return 0; return 0;
} }
...@@ -178,6 +186,8 @@ int do_ipmonitor(int argc, char **argv) ...@@ -178,6 +186,8 @@ int do_ipmonitor(int argc, char **argv)
file = *argv; file = *argv;
} else if (matches(*argv, "label") == 0) { } else if (matches(*argv, "label") == 0) {
prefix_banner = 1; prefix_banner = 1;
} else if (matches(*argv, "all-nsid") == 0) {
listen_all_nsid = 1;
} else if (matches(*argv, "link") == 0) { } else if (matches(*argv, "link") == 0) {
llink=1; llink=1;
groups = 0; groups = 0;
...@@ -284,6 +294,9 @@ int do_ipmonitor(int argc, char **argv) ...@@ -284,6 +294,9 @@ int do_ipmonitor(int argc, char **argv)
if (rtnl_open(&rth, groups) < 0) if (rtnl_open(&rth, groups) < 0)
exit(1); exit(1);
if (listen_all_nsid && rtnl_listen_all_nsid(&rth) < 0)
exit(1);
ll_init_map(&rth); ll_init_map(&rth);
netns_map_init(); netns_map_init();
......
...@@ -25,6 +25,10 @@ ...@@ -25,6 +25,10 @@
#include "libnetlink.h" #include "libnetlink.h"
#ifndef SOL_NETLINK
#define SOL_NETLINK 270
#endif
int rcvbuf = 1024 * 1024; int rcvbuf = 1024 * 1024;
void rtnl_close(struct rtnl_handle *rth) void rtnl_close(struct rtnl_handle *rth)
...@@ -418,6 +422,19 @@ int rtnl_talk(struct rtnl_handle *rtnl, struct nlmsghdr *n, pid_t peer, ...@@ -418,6 +422,19 @@ int rtnl_talk(struct rtnl_handle *rtnl, struct nlmsghdr *n, pid_t peer,
} }
} }
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, int rtnl_listen(struct rtnl_handle *rtnl,
rtnl_listen_filter_t handler, rtnl_listen_filter_t handler,
void *jarg) void *jarg)
...@@ -433,6 +450,12 @@ int rtnl_listen(struct rtnl_handle *rtnl, ...@@ -433,6 +450,12 @@ int rtnl_listen(struct rtnl_handle *rtnl,
.msg_iovlen = 1, .msg_iovlen = 1,
}; };
char buf[16384]; 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)); memset(&nladdr, 0, sizeof(nladdr));
nladdr.nl_family = AF_NETLINK; nladdr.nl_family = AF_NETLINK;
...@@ -441,6 +464,9 @@ int rtnl_listen(struct rtnl_handle *rtnl, ...@@ -441,6 +464,9 @@ int rtnl_listen(struct rtnl_handle *rtnl,
iov.iov_base = buf; iov.iov_base = buf;
while (1) { while (1) {
struct rtnl_ctrl_data ctrl;
struct cmsghdr *cmsg;
iov.iov_len = sizeof(buf); iov.iov_len = sizeof(buf);
status = recvmsg(rtnl->fd, &msg, 0); status = recvmsg(rtnl->fd, &msg, 0);
...@@ -461,6 +487,21 @@ int rtnl_listen(struct rtnl_handle *rtnl, ...@@ -461,6 +487,21 @@ int rtnl_listen(struct rtnl_handle *rtnl,
fprintf(stderr, "Sender address length == %d\n", msg.msg_namelen); fprintf(stderr, "Sender address length == %d\n", msg.msg_namelen);
exit(1); 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); ) { for (h = (struct nlmsghdr*)buf; status >= sizeof(*h); ) {
int err; int err;
int len = h->nlmsg_len; int len = h->nlmsg_len;
...@@ -475,7 +516,7 @@ int rtnl_listen(struct rtnl_handle *rtnl, ...@@ -475,7 +516,7 @@ int rtnl_listen(struct rtnl_handle *rtnl,
exit(1); exit(1);
} }
err = handler(&nladdr, NULL, h, jarg); err = handler(&nladdr, &ctrl, h, jarg);
if (err < 0) if (err < 0)
return err; return err;
......
...@@ -14,6 +14,8 @@ ip-monitor, rtmon \- state monitoring ...@@ -14,6 +14,8 @@ ip-monitor, rtmon \- state monitoring
] [ ] [
.BI label .BI label
] [ ] [
.BI all-nsid
] [
.BI dev " DEVICE " .BI dev " DEVICE "
] ]
.sp .sp
...@@ -46,6 +48,8 @@ command is the first in the command line and then the object list follows: ...@@ -46,6 +48,8 @@ command is the first in the command line and then the object list follows:
] [ ] [
.BI label .BI label
] [ ] [
.BI all-nsid
] [
.BI dev " DEVICE " .BI dev " DEVICE "
] ]
...@@ -74,6 +78,19 @@ show the family of the message. For example: ...@@ -74,6 +78,19 @@ show the family of the message. For example:
.in -2 .in -2
.sp .sp
.P
If the
.BI all-nsid
option is set, the program listens to all network namespaces that have a
nsid assigned into the network namespace were the program is running.
A prefix is displayed to show the network namespace where the message
originates. Example:
.sp
.in +2
[nsid 0]10.16.0.112 dev eth0 lladdr 00:04:23:df:2f:d0 REACHABLE
.in -2
.sp
.P .P
If the If the
.BI file .BI file
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment