naccyde / rpms / iproute

Forked from rpms/iproute 9 months ago
Clone

Blame SOURCES/iproute2-3.10.0-ip-xfrm-monitor-allows-to-monitor-in-several-netns.patch

a4b897
From 3873ff54417f7e514197d069bcad187ca2ec3b86 Mon Sep 17 00:00:00 2001
a4b897
From: Phil Sutter <psutter@redhat.com>
a4b897
Date: Mon, 10 Aug 2015 17:26:16 +0200
a4b897
Subject: [PATCH] {ip,xfrm}monitor: allows to monitor in several netns
a4b897
a4b897
This is a combination of six commits:
a4b897
a4b897
commit c1f4d1640efa2ba2219861852b351d5c369c3715
a4b897
Author: Phil Sutter <psutter@redhat.com>
a4b897
Date:   Mon Aug 10 17:26:16 2015 +0200
a4b897
a4b897
    include/linux/netlink.h: add NETLINK_LISTEN_ALL_NSID
a4b897
a4b897
    This is a selective backport for the following patches and will be replaced by
a4b897
    full linux header update backports soon.
a4b897
a4b897
commit 2503247d58c36f9197144790455626bae105342a
a4b897
Author: Nicolas Dichtel <nicolas.dichtel@6wind.com>
a4b897
Date:   Wed May 20 16:19:57 2015 +0200
a4b897
a4b897
    man: update ip monitor page
a4b897
a4b897
    Add label option.
a4b897
a4b897
    Signed-off-by: Nicolas Dichtel <nicolas.dichtel@6wind.com>
a4b897
a4b897
commit 0628cddd9d5c0cb9ed0e0aba136e50de93487150
a4b897
Author: Nicolas Dichtel <nicolas.dichtel@6wind.com>
a4b897
Date:   Wed May 20 16:19:58 2015 +0200
a4b897
a4b897
    libnetlink: introduce rtnl_listen_filter_t
a4b897
a4b897
    There is no functional change with this commit. It only prepares the next one.
a4b897
a4b897
    Signed-off-by: Nicolas Dichtel <nicolas.dichtel@6wind.com>
a4b897
a4b897
commit 3b0006f8183e09eda5f2f11667f2b9d36fcd8c16
a4b897
Author: Nicolas Dichtel <nicolas.dichtel@6wind.com>
a4b897
Date:   Wed May 20 16:19:59 2015 +0200
a4b897
a4b897
    ipmonitor: introduce print_headers
a4b897
a4b897
    The goal of this patch is to avoid code duplication.
a4b897
a4b897
    Signed-off-by: Nicolas Dichtel <nicolas.dichtel@6wind.com>
a4b897
a4b897
commit 449b824ad19679f66164e1e97513f36eee0d004e
a4b897
Author: Nicolas Dichtel <nicolas.dichtel@6wind.com>
a4b897
Date:   Wed May 20 16:20:00 2015 +0200
a4b897
a4b897
    ipmonitor: allows to monitor in several netns
a4b897
a4b897
    With this patch, it's now possible to listen in all netns that have an nsid
a4b897
    assigned into the netns where the socket is opened.
a4b897
a4b897
    Signed-off-by: Nicolas Dichtel <nicolas.dichtel@6wind.com>
a4b897
a4b897
commit b6ec53e3008aaf2acc3db146e24bc9a365e4b6c2
a4b897
Author: Nicolas Dichtel <nicolas.dichtel@6wind.com>
a4b897
Date:   Wed May 20 16:20:01 2015 +0200
a4b897
a4b897
    xfrmmonitor: allows to monitor in several netns
a4b897
a4b897
    With this patch, it's now possible to listen in all netns that have an nsid
a4b897
    assigned into the netns where is socket is opened.
a4b897
a4b897
    Signed-off-by: Nicolas Dichtel <nicolas.dichtel@6wind.com>
a4b897
a4b897
There were multiple conflicts to resolve due to the following missing commits:
a4b897
- c16298b ip xfrm mon: Add objects list to the usage output
a4b897
- 2271779 ip monitor: Dont print timestamp or banner-label for cloned routes
a4b897
- 0018565 add ability to filter neighbour discovery by protocol
a4b897
- 488c41d ip: Add label option to ip monitor
a4b897
- e557212 netlink: extend buffers to 16K
a4b897
- 093b764 ip monitor: Allow to filter events by dev
a4b897
---
a4b897
 bridge/monitor.c        |  1 +
a4b897
 genl/ctrl.c             | 17 ++++++++++-----
a4b897
 include/libnetlink.h    | 15 +++++++++++--
a4b897
 include/linux/netlink.h |  1 +
a4b897
 ip/ip_common.h          |  1 +
a4b897
 ip/ipaddress.c          |  8 +++++--
a4b897
 ip/iplink.c             |  1 +
a4b897
 ip/ipmonitor.c          | 58 ++++++++++++++++++++++++++++++-------------------
a4b897
 ip/ipnetconf.c          | 11 ++++++++--
a4b897
 ip/ipnetns.c            |  1 +
a4b897
 ip/iproute.c            |  9 +++++---
a4b897
 ip/rtmon.c              | 12 +++++++---
a4b897
 ip/xfrm_monitor.c       | 15 ++++++++++++-
a4b897
 lib/libnetlink.c        | 49 +++++++++++++++++++++++++++++++++++++----
a4b897
 man/man3/libnetlink.3   |  7 +++---
a4b897
 man/man8/ip-monitor.8   | 36 ++++++++++++++++++++++++++++++
a4b897
 man/man8/ip-xfrm.8      | 21 +++++++++++++++++-
a4b897
 tc/tc_monitor.c         |  1 +
a4b897
 18 files changed, 216 insertions(+), 48 deletions(-)
a4b897
a4b897
diff --git a/bridge/monitor.c b/bridge/monitor.c
a4b897
index 76e7d47..82cdff0 100644
a4b897
--- a/bridge/monitor.c
a4b897
+++ b/bridge/monitor.c
a4b897
@@ -47,6 +47,7 @@ static int show_mark(FILE *fp, const struct nlmsghdr *n)
a4b897
 }
a4b897
 
a4b897
 static int accept_msg(const struct sockaddr_nl *who,
a4b897
+		      struct rtnl_ctrl_data *ctrl,
a4b897
 		      struct nlmsghdr *n, void *arg)
a4b897
 {
a4b897
 	FILE *fp = arg;
a4b897
diff --git a/genl/ctrl.c b/genl/ctrl.c
a4b897
index 7c42578..48cbc35 100644
a4b897
--- a/genl/ctrl.c
a4b897
+++ b/genl/ctrl.c
a4b897
@@ -177,8 +177,9 @@ static int print_ctrl_grp(FILE *fp, struct rtattr *arg, __u32 ctrl_ver)
a4b897
 /*
a4b897
  * The controller sends one nlmsg per family
a4b897
 */
a4b897
-static int print_ctrl(const struct sockaddr_nl *who, struct nlmsghdr *n,
a4b897
-		      void *arg)
a4b897
+static int print_ctrl(const struct sockaddr_nl *who,
a4b897
+		      struct rtnl_ctrl_data *ctrl,
a4b897
+		      struct nlmsghdr *n, void *arg)
a4b897
 {
a4b897
 	struct rtattr *tb[CTRL_ATTR_MAX + 1];
a4b897
 	struct genlmsghdr *ghdr = NLMSG_DATA(n);
a4b897
@@ -281,6 +282,12 @@ static int print_ctrl(const struct sockaddr_nl *who, struct nlmsghdr *n,
a4b897
 	return 0;
a4b897
 }
a4b897
 
a4b897
+static int print_ctrl2(const struct sockaddr_nl *who,
a4b897
+		      struct nlmsghdr *n, void *arg)
a4b897
+{
a4b897
+	return print_ctrl(who, NULL, n, arg);
a4b897
+}
a4b897
+
a4b897
 static int ctrl_list(int cmd, int argc, char **argv)
a4b897
 {
a4b897
 	struct rtnl_handle rth;
a4b897
@@ -339,7 +346,7 @@ static int ctrl_list(int cmd, int argc, char **argv)
a4b897
 			goto ctrl_done;
a4b897
 		}
a4b897
 
a4b897
-		if (print_ctrl(NULL, nlh, (void *) stdout) < 0) {
a4b897
+		if (print_ctrl2(NULL, nlh, (void *) stdout) < 0) {
a4b897
 			fprintf(stderr, "Dump terminated\n");
a4b897
 			goto ctrl_done;
a4b897
 		}
a4b897
@@ -355,7 +362,7 @@ static int ctrl_list(int cmd, int argc, char **argv)
a4b897
 			goto ctrl_done;
a4b897
 		}
a4b897
 
a4b897
-		rtnl_dump_filter(&rth, print_ctrl, stdout);
a4b897
+		rtnl_dump_filter(&rth, print_ctrl2, stdout);
a4b897
 
a4b897
         }
a4b897
 
a4b897
@@ -408,5 +415,5 @@ static int parse_ctrl(struct genl_util *a, int argc, char **argv)
a4b897
 struct genl_util ctrl_genl_util = {
a4b897
 	.name = "ctrl",
a4b897
 	.parse_genlopt = parse_ctrl,
a4b897
-	.print_genlopt = print_ctrl,
a4b897
+	.print_genlopt = print_ctrl2,
a4b897
 };
a4b897
diff --git a/include/libnetlink.h b/include/libnetlink.h
a4b897
index 5dcc0c3..ae93336 100644
a4b897
--- a/include/libnetlink.h
a4b897
+++ b/include/libnetlink.h
a4b897
@@ -19,6 +19,8 @@ struct rtnl_handle
a4b897
 	__u32			seq;
a4b897
 	__u32			dump;
a4b897
 	FILE		       *dump_fp;
a4b897
+#define RTNL_HANDLE_F_LISTEN_ALL_NSID		0x01
a4b897
+	int			flags;
a4b897
 };
a4b897
 
a4b897
 extern int rcvbuf;
a4b897
@@ -31,9 +33,17 @@ extern int rtnl_wilddump_req_filter(struct rtnl_handle *rth, int fam, int type,
a4b897
 				    __u32 filt_mask);
a4b897
 extern int rtnl_dump_request(struct rtnl_handle *rth, int type, void *req, int len);
a4b897
 
a4b897
+struct rtnl_ctrl_data {
a4b897
+	int	nsid;
a4b897
+};
a4b897
+
a4b897
 typedef int (*rtnl_filter_t)(const struct sockaddr_nl *,
a4b897
 			     struct nlmsghdr *n, void *);
a4b897
 
a4b897
+typedef int (*rtnl_listen_filter_t)(const struct sockaddr_nl *,
a4b897
+				    struct rtnl_ctrl_data *,
a4b897
+				    struct nlmsghdr *n, void *);
a4b897
+
a4b897
 struct rtnl_dump_filter_arg
a4b897
 {
a4b897
 	rtnl_filter_t filter;
a4b897
@@ -105,9 +115,10 @@ static inline const char *rta_getattr_str(const struct rtattr *rta)
a4b897
 	return (const char *)RTA_DATA(rta);
a4b897
 }
a4b897
 
a4b897
-extern int rtnl_listen(struct rtnl_handle *, rtnl_filter_t handler,
a4b897
+extern int rtnl_listen_all_nsid(struct rtnl_handle *);
a4b897
+extern int rtnl_listen(struct rtnl_handle *, rtnl_listen_filter_t handler,
a4b897
 		       void *jarg);
a4b897
-extern int rtnl_from_file(FILE *, rtnl_filter_t handler,
a4b897
+extern int rtnl_from_file(FILE *, rtnl_listen_filter_t handler,
a4b897
 		       void *jarg);
a4b897
 
a4b897
 #define NLMSG_TAIL(nmsg) \
a4b897
diff --git a/include/linux/netlink.h b/include/linux/netlink.h
a4b897
index e0a09df..0c89ddd 100644
a4b897
--- a/include/linux/netlink.h
a4b897
+++ b/include/linux/netlink.h
a4b897
@@ -108,6 +108,7 @@ struct nlmsgerr {
a4b897
 #define NETLINK_NO_ENOBUFS	5
a4b897
 #define NETLINK_RX_RING		6
a4b897
 #define NETLINK_TX_RING		7
a4b897
+#define NETLINK_LISTEN_ALL_NSID	8
a4b897
 
a4b897
 struct nl_pktinfo {
a4b897
 	__u32	group;
a4b897
diff --git a/ip/ip_common.h b/ip/ip_common.h
a4b897
index 85529f0..bd36924 100644
a4b897
--- a/ip/ip_common.h
a4b897
+++ b/ip/ip_common.h
a4b897
@@ -29,6 +29,7 @@ extern int print_prefix(const struct sockaddr_nl *who,
a4b897
 extern int print_rule(const struct sockaddr_nl *who,
a4b897
 		      struct nlmsghdr *n, void *arg);
a4b897
 extern int print_netconf(const struct sockaddr_nl *who,
a4b897
+			 struct rtnl_ctrl_data *ctrl,
a4b897
 			 struct nlmsghdr *n, void *arg);
a4b897
 extern void netns_map_init(void);
a4b897
 extern int print_nsid(const struct sockaddr_nl *who,
a4b897
diff --git a/ip/ipaddress.c b/ip/ipaddress.c
a4b897
index 4650a2e..30fda4f 100644
a4b897
--- a/ip/ipaddress.c
a4b897
+++ b/ip/ipaddress.c
a4b897
@@ -1007,7 +1007,9 @@ static int save_nlmsg(const struct sockaddr_nl *who, struct nlmsghdr *n,
a4b897
 	return ret == n->nlmsg_len ? 0 : ret;
a4b897
 }
a4b897
 
a4b897
-static int show_handler(const struct sockaddr_nl *nl, struct nlmsghdr *n, void *arg)
a4b897
+static int show_handler(const struct sockaddr_nl *nl,
a4b897
+			struct rtnl_ctrl_data *ctrl,
a4b897
+			struct nlmsghdr *n, void *arg)
a4b897
 {
a4b897
 	struct ifaddrmsg *ifa = NLMSG_DATA(n);
a4b897
 
a4b897
@@ -1024,7 +1026,9 @@ static int ipaddr_showdump(void)
a4b897
 	exit(rtnl_from_file(stdin, &show_handler, NULL));
a4b897
 }
a4b897
 
a4b897
-static int restore_handler(const struct sockaddr_nl *nl, struct nlmsghdr *n, void *arg)
a4b897
+static int restore_handler(const struct sockaddr_nl *nl,
a4b897
+			   struct rtnl_ctrl_data *ctrl,
a4b897
+			   struct nlmsghdr *n, void *arg)
a4b897
 {
a4b897
 	int ret;
a4b897
 
a4b897
diff --git a/ip/iplink.c b/ip/iplink.c
a4b897
index e47cbdd..86ea23e 100644
a4b897
--- a/ip/iplink.c
a4b897
+++ b/ip/iplink.c
a4b897
@@ -163,6 +163,7 @@ static int get_addr_gen_mode(const char *mode)
a4b897
 static int have_rtnl_newlink = -1;
a4b897
 
a4b897
 static int accept_msg(const struct sockaddr_nl *who,
a4b897
+		      struct rtnl_ctrl_data *ctrl,
a4b897
 		      struct nlmsghdr *n, void *arg)
a4b897
 {
a4b897
 	struct nlmsgerr *err = (struct nlmsgerr *)NLMSG_DATA(n);
a4b897
diff --git a/ip/ipmonitor.c b/ip/ipmonitor.c
a4b897
index 148cf1e..131b6ac 100644
a4b897
--- a/ip/ipmonitor.c
a4b897
+++ b/ip/ipmonitor.c
a4b897
@@ -26,18 +26,36 @@
a4b897
 
a4b897
 static void usage(void) __attribute__((noreturn));
a4b897
 int prefix_banner;
a4b897
+int listen_all_nsid;
a4b897
 
a4b897
 static void usage(void)
a4b897
 {
a4b897
-	fprintf(stderr, "Usage: ip monitor [ all | LISTofOBJECTS ] [ FILE ]\n");
a4b897
+	fprintf(stderr, "Usage: ip monitor [ all | LISTofOBJECTS ] [ FILE ] "
a4b897
+			"[all-nsid] [dev DEVICE]\n");
a4b897
 	fprintf(stderr, "LISTofOBJECTS := link | address | route | mroute | prefix |\n");
a4b897
 	fprintf(stderr, "                 neigh | netconf | nsid\n");
a4b897
 	fprintf(stderr, "FILE := file FILENAME\n");
a4b897
 	exit(-1);
a4b897
 }
a4b897
 
a4b897
+static void print_headers(FILE *fp, char *label, struct rtnl_ctrl_data *ctrl)
a4b897
+{
a4b897
+	if (timestamp)
a4b897
+		print_timestamp(fp);
a4b897
+
a4b897
+	if (listen_all_nsid) {
a4b897
+		if (ctrl == NULL || ctrl->nsid < 0)
a4b897
+			fprintf(fp, "[nsid current]");
a4b897
+		else
a4b897
+			fprintf(fp, "[nsid %d]", ctrl->nsid);
a4b897
+	}
a4b897
+
a4b897
+	if (prefix_banner)
a4b897
+		fprintf(fp, "%s", label);
a4b897
+}
a4b897
 
a4b897
 static int accept_msg(const struct sockaddr_nl *who,
a4b897
+		      struct rtnl_ctrl_data *ctrl,
a4b897
 		      struct nlmsghdr *n, void *arg)
a4b897
 {
a4b897
 	FILE *fp = (FILE*)arg;
a4b897
@@ -56,59 +74,51 @@ static int accept_msg(const struct sockaddr_nl *who,
a4b897
 
a4b897
 		if (r->rtm_family == RTNL_FAMILY_IPMR ||
a4b897
 		    r->rtm_family == RTNL_FAMILY_IP6MR) {
a4b897
-			if (prefix_banner)
a4b897
-				fprintf(fp, "[MROUTE]");
a4b897
+			print_headers(fp, "[MROUTE]", ctrl);
a4b897
 			print_mroute(who, n, arg);
a4b897
 			return 0;
a4b897
 		} else {
a4b897
-			if (prefix_banner)
a4b897
-				fprintf(fp, "[ROUTE]");
a4b897
+			print_headers(fp, "[ROUTE]", ctrl);
a4b897
 			print_route(who, n, arg);
a4b897
 			return 0;
a4b897
 		}
a4b897
 	}
a4b897
+
a4b897
 	if (n->nlmsg_type == RTM_NEWLINK || n->nlmsg_type == RTM_DELLINK) {
a4b897
 		ll_remember_index(who, n, NULL);
a4b897
-		if (prefix_banner)
a4b897
-			fprintf(fp, "[LINK]");
a4b897
+		print_headers(fp, "[LINK]", ctrl);
a4b897
 		print_linkinfo(who, n, arg);
a4b897
 		return 0;
a4b897
 	}
a4b897
 	if (n->nlmsg_type == RTM_NEWADDR || n->nlmsg_type == RTM_DELADDR) {
a4b897
-		if (prefix_banner)
a4b897
-			fprintf(fp, "[ADDR]");
a4b897
+		print_headers(fp, "[ADDR]", ctrl);
a4b897
 		print_addrinfo(who, n, arg);
a4b897
 		return 0;
a4b897
 	}
a4b897
 	if (n->nlmsg_type == RTM_NEWADDRLABEL || n->nlmsg_type == RTM_DELADDRLABEL) {
a4b897
-		if (prefix_banner)
a4b897
-			fprintf(fp, "[ADDRLABEL]");
a4b897
+		print_headers(fp, "[ADDRLABEL]", ctrl);
a4b897
 		print_addrlabel(who, n, arg);
a4b897
 		return 0;
a4b897
 	}
a4b897
 	if (n->nlmsg_type == RTM_NEWNEIGH || n->nlmsg_type == RTM_DELNEIGH ||
a4b897
 	    n->nlmsg_type == RTM_GETNEIGH) {
a4b897
-		if (prefix_banner)
a4b897
-			fprintf(fp, "[NEIGH]");
a4b897
+		print_headers(fp, "[NEIGH]", ctrl);
a4b897
 		print_neigh(who, n, arg);
a4b897
 		return 0;
a4b897
 	}
a4b897
 	if (n->nlmsg_type == RTM_NEWPREFIX) {
a4b897
-		if (prefix_banner)
a4b897
-			fprintf(fp, "[PREFIX]");
a4b897
+		print_headers(fp, "[PREFIX]", ctrl);
a4b897
 		print_prefix(who, n, arg);
a4b897
 		return 0;
a4b897
 	}
a4b897
 	if (n->nlmsg_type == RTM_NEWRULE || n->nlmsg_type == RTM_DELRULE) {
a4b897
-		if (prefix_banner)
a4b897
-			fprintf(fp, "[RULE]");
a4b897
+		print_headers(fp, "[RULE]", ctrl);
a4b897
 		print_rule(who, n, arg);
a4b897
 		return 0;
a4b897
 	}
a4b897
 	if (n->nlmsg_type == RTM_NEWNETCONF) {
a4b897
-		if (prefix_banner)
a4b897
-			fprintf(fp, "[NETCONF]");
a4b897
-		print_netconf(who, n, arg);
a4b897
+		print_headers(fp, "[NETCONF]", ctrl);
a4b897
+		print_netconf(who, ctrl, n, arg);
a4b897
 		return 0;
a4b897
 	}
a4b897
 	if (n->nlmsg_type == 15) {
a4b897
@@ -128,8 +138,7 @@ static int accept_msg(const struct sockaddr_nl *who,
a4b897
 	    n->nlmsg_type == RTM_DELTFILTER)
a4b897
 		return 0;
a4b897
 	if (n->nlmsg_type == RTM_NEWNSID || n->nlmsg_type == RTM_DELNSID) {
a4b897
-		if (prefix_banner)
a4b897
-			fprintf(fp, "[NSID]");
a4b897
+		print_headers(fp, "[NSID]", ctrl);
a4b897
 		print_nsid(who, n, arg);
a4b897
 		return 0;
a4b897
 	}
a4b897
@@ -166,6 +175,8 @@ int do_ipmonitor(int argc, char **argv)
a4b897
 		if (matches(*argv, "file") == 0) {
a4b897
 			NEXT_ARG();
a4b897
 			file = *argv;
a4b897
+		} else if (matches(*argv, "all-nsid") == 0) {
a4b897
+			listen_all_nsid = 1;
a4b897
 		} else if (matches(*argv, "link") == 0) {
a4b897
 			llink=1;
a4b897
 			groups = 0;
a4b897
@@ -250,6 +261,9 @@ int do_ipmonitor(int argc, char **argv)
a4b897
 
a4b897
 	if (rtnl_open(&rth, groups) < 0)
a4b897
 		exit(1);
a4b897
+	if (listen_all_nsid && rtnl_listen_all_nsid(&rth) < 0)
a4b897
+		exit(1);
a4b897
+
a4b897
 	ll_init_map(&rth);
a4b897
 	netns_map_init();
a4b897
 
a4b897
diff --git a/ip/ipnetconf.c b/ip/ipnetconf.c
a4b897
index 9a77ecb..8e42132 100644
a4b897
--- a/ip/ipnetconf.c
a4b897
+++ b/ip/ipnetconf.c
a4b897
@@ -40,7 +40,8 @@ static void usage(void)
a4b897
 
a4b897
 #define NETCONF_RTA(r)	((struct rtattr*)(((char*)(r)) + NLMSG_ALIGN(sizeof(struct netconfmsg))))
a4b897
 
a4b897
-int print_netconf(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg)
a4b897
+int print_netconf(const struct sockaddr_nl *who, struct rtnl_ctrl_data *ctrl,
a4b897
+		  struct nlmsghdr *n, void *arg)
a4b897
 {
a4b897
 	FILE *fp = (FILE*)arg;
a4b897
 	struct netconfmsg *ncm = NLMSG_DATA(n);
a4b897
@@ -119,6 +120,12 @@ int print_netconf(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg)
a4b897
 	return 0;
a4b897
 }
a4b897
 
a4b897
+static int print_netconf2(const struct sockaddr_nl *who,
a4b897
+			  struct nlmsghdr *n, void *arg)
a4b897
+{
a4b897
+	return print_netconf(who, NULL, n, arg);
a4b897
+}
a4b897
+
a4b897
 static void ipnetconf_reset_filter(void)
a4b897
 {
a4b897
 	memset(&filter, 0, sizeof(filter));
a4b897
@@ -169,7 +176,7 @@ dump:
a4b897
 			perror("Cannot send dump request");
a4b897
 			exit(1);
a4b897
 		}
a4b897
-		if (rtnl_dump_filter(&rth, print_netconf, stdout) < 0) {
a4b897
+		if (rtnl_dump_filter(&rth, print_netconf2, stdout) < 0) {
a4b897
 			fprintf(stderr, "Dump terminated\n");
a4b897
 			exit(1);
a4b897
 		}
a4b897
diff --git a/ip/ipnetns.c b/ip/ipnetns.c
a4b897
index 438d59b..019f954 100644
a4b897
--- a/ip/ipnetns.c
a4b897
+++ b/ip/ipnetns.c
a4b897
@@ -43,6 +43,7 @@ static struct rtnl_handle rtnsh = { .fd = -1 };
a4b897
 static int have_rtnl_getnsid = -1;
a4b897
 
a4b897
 static int ipnetns_accept_msg(const struct sockaddr_nl *who,
a4b897
+			      struct rtnl_ctrl_data *ctrl,
a4b897
 			      struct nlmsghdr *n, void *arg)
a4b897
 {
a4b897
 	struct nlmsgerr *err = (struct nlmsgerr *)NLMSG_DATA(n);
a4b897
diff --git a/ip/iproute.c b/ip/iproute.c
a4b897
index 207301c..20980ab 100644
a4b897
--- a/ip/iproute.c
a4b897
+++ b/ip/iproute.c
a4b897
@@ -1539,8 +1539,9 @@ static int iproute_get(int argc, char **argv)
a4b897
 	exit(0);
a4b897
 }
a4b897
 
a4b897
-static int restore_handler(const struct sockaddr_nl *nl, struct nlmsghdr *n,
a4b897
-			   void *arg)
a4b897
+static int restore_handler(const struct sockaddr_nl *nl,
a4b897
+			   struct rtnl_ctrl_data *ctrl,
a4b897
+			   struct nlmsghdr *n, void *arg)
a4b897
 {
a4b897
 	int ret;
a4b897
 
a4b897
@@ -1582,7 +1583,9 @@ static int iproute_restore(void)
a4b897
 	exit(rtnl_from_file(stdin, &restore_handler, NULL));
a4b897
 }
a4b897
 
a4b897
-static int show_handler(const struct sockaddr_nl *nl, struct nlmsghdr *n, void *arg)
a4b897
+static int show_handler(const struct sockaddr_nl *nl,
a4b897
+			struct rtnl_ctrl_data *ctrl,
a4b897
+			struct nlmsghdr *n, void *arg)
a4b897
 {
a4b897
 	print_route(nl, n, stdout);
a4b897
 	return 0;
a4b897
diff --git a/ip/rtmon.c b/ip/rtmon.c
a4b897
index 9227eac..5094d22 100644
a4b897
--- a/ip/rtmon.c
a4b897
+++ b/ip/rtmon.c
a4b897
@@ -45,8 +45,8 @@ static void write_stamp(FILE *fp)
a4b897
 	fwrite((void*)n1, 1, NLMSG_ALIGN(n1->nlmsg_len), fp);
a4b897
 }
a4b897
 
a4b897
-static int dump_msg(const struct sockaddr_nl *who, struct nlmsghdr *n,
a4b897
-		    void *arg)
a4b897
+static int dump_msg(const struct sockaddr_nl *who, struct rtnl_ctrl_data *ctrl,
a4b897
+		    struct nlmsghdr *n, void *arg)
a4b897
 {
a4b897
 	FILE *fp = (FILE*)arg;
a4b897
 	if (!init_phase)
a4b897
@@ -56,6 +56,12 @@ static int dump_msg(const struct sockaddr_nl *who, struct nlmsghdr *n,
a4b897
 	return 0;
a4b897
 }
a4b897
 
a4b897
+static int dump_msg2(const struct sockaddr_nl *who,
a4b897
+		     struct nlmsghdr *n, void *arg)
a4b897
+{
a4b897
+	return dump_msg(who, NULL, n, arg);
a4b897
+}
a4b897
+
a4b897
 static void usage(void)
a4b897
 {
a4b897
 	fprintf(stderr, "Usage: rtmon file FILE [ all | LISTofOBJECTS]\n");
a4b897
@@ -163,7 +169,7 @@ main(int argc, char **argv)
a4b897
 
a4b897
 	write_stamp(fp);
a4b897
 
a4b897
-	if (rtnl_dump_filter(&rth, dump_msg, fp) < 0) {
a4b897
+	if (rtnl_dump_filter(&rth, dump_msg2, fp) < 0) {
a4b897
 		fprintf(stderr, "Dump terminated\n");
a4b897
 		return 1;
a4b897
 	}
a4b897
diff --git a/ip/xfrm_monitor.c b/ip/xfrm_monitor.c
a4b897
index 292193e..228aaf2 100644
a4b897
--- a/ip/xfrm_monitor.c
a4b897
+++ b/ip/xfrm_monitor.c
a4b897
@@ -36,10 +36,11 @@
a4b897
 #include "ip_common.h"
a4b897
 
a4b897
 static void usage(void) __attribute__((noreturn));
a4b897
+int listen_all_nsid;
a4b897
 
a4b897
 static void usage(void)
a4b897
 {
a4b897
-	fprintf(stderr, "Usage: ip xfrm monitor [ all | LISTofXFRM-OBJECTS ]\n");
a4b897
+	fprintf(stderr, "Usage: ip xfrm monitor [all-nsid] [ all | LISTofXFRM-OBJECTS ]\n");
a4b897
 	exit(-1);
a4b897
 }
a4b897
 
a4b897
@@ -291,6 +292,7 @@ static int xfrm_mapping_print(const struct sockaddr_nl *who,
a4b897
 }
a4b897
 
a4b897
 static int xfrm_accept_msg(const struct sockaddr_nl *who,
a4b897
+			   struct rtnl_ctrl_data *ctrl,
a4b897
 			   struct nlmsghdr *n, void *arg)
a4b897
 {
a4b897
 	FILE *fp = (FILE*)arg;
a4b897
@@ -298,6 +300,13 @@ static int xfrm_accept_msg(const struct sockaddr_nl *who,
a4b897
 	if (timestamp)
a4b897
 		print_timestamp(fp);
a4b897
 
a4b897
+	if (listen_all_nsid) {
a4b897
+		if (ctrl == NULL || ctrl->nsid < 0)
a4b897
+			fprintf(fp, "[nsid current]");
a4b897
+		else
a4b897
+			fprintf(fp, "[nsid %d]", ctrl->nsid);
a4b897
+	}
a4b897
+
a4b897
 	switch (n->nlmsg_type) {
a4b897
 	case XFRM_MSG_NEWSA:
a4b897
 	case XFRM_MSG_DELSA:
a4b897
@@ -360,6 +369,8 @@ int do_xfrm_monitor(int argc, char **argv)
a4b897
 		if (matches(*argv, "file") == 0) {
a4b897
 			NEXT_ARG();
a4b897
 			file = *argv;
a4b897
+		} else if (matches(*argv, "all-nsid") == 0) {
a4b897
+			listen_all_nsid = 1;
a4b897
 		} else if (matches(*argv, "acquire") == 0) {
a4b897
 			lacquire=1;
a4b897
 			groups = 0;
a4b897
@@ -412,6 +423,8 @@ int do_xfrm_monitor(int argc, char **argv)
a4b897
 
a4b897
 	if (rtnl_open_byproto(&rth, groups, NETLINK_XFRM) < 0)
a4b897
 		exit(1);
a4b897
+	if (listen_all_nsid && rtnl_listen_all_nsid(&rth) < 0)
a4b897
+		exit(1);
a4b897
 
a4b897
 	if (rtnl_listen(&rth, xfrm_accept_msg, (void*)stdout) < 0)
a4b897
 		exit(2);
a4b897
diff --git a/lib/libnetlink.c b/lib/libnetlink.c
a4b897
index baac6ae..0a989f4 100644
a4b897
--- a/lib/libnetlink.c
a4b897
+++ b/lib/libnetlink.c
a4b897
@@ -25,6 +25,10 @@
a4b897
 
a4b897
 #include "libnetlink.h"
a4b897
 
a4b897
+#ifndef SOL_NETLINK
a4b897
+#define SOL_NETLINK 270
a4b897
+#endif
a4b897
+
a4b897
 int rcvbuf = 1024 * 1024;
a4b897
 
a4b897
 void rtnl_close(struct rtnl_handle *rth)
a4b897
@@ -406,8 +410,21 @@ int rtnl_talk(struct rtnl_handle *rtnl, struct nlmsghdr *n, pid_t peer,
a4b897
 	}
a4b897
 }
a4b897
 
a4b897
+int rtnl_listen_all_nsid(struct rtnl_handle *rth)
a4b897
+{
a4b897
+	unsigned int on = 1;
a4b897
+
a4b897
+	if (setsockopt(rth->fd, SOL_NETLINK, NETLINK_LISTEN_ALL_NSID, &on,
a4b897
+		       sizeof(on)) < 0) {
a4b897
+		perror("NETLINK_LISTEN_ALL_NSID");
a4b897
+		return -1;
a4b897
+	}
a4b897
+	rth->flags |= RTNL_HANDLE_F_LISTEN_ALL_NSID;
a4b897
+	return 0;
a4b897
+}
a4b897
+
a4b897
 int rtnl_listen(struct rtnl_handle *rtnl,
a4b897
-		rtnl_filter_t handler,
a4b897
+		rtnl_listen_filter_t handler,
a4b897
 		void *jarg)
a4b897
 {
a4b897
 	int status;
a4b897
@@ -421,6 +438,12 @@ int rtnl_listen(struct rtnl_handle *rtnl,
a4b897
 		.msg_iovlen = 1,
a4b897
 	};
a4b897
 	char   buf[8192];
a4b897
+	char   cmsgbuf[BUFSIZ];
a4b897
+
a4b897
+	if (rtnl->flags & RTNL_HANDLE_F_LISTEN_ALL_NSID) {
a4b897
+		msg.msg_control = &cmsgbuf;
a4b897
+		msg.msg_controllen = sizeof(cmsgbuf);
a4b897
+	}
a4b897
 
a4b897
 	memset(&nladdr, 0, sizeof(nladdr));
a4b897
 	nladdr.nl_family = AF_NETLINK;
a4b897
@@ -429,6 +452,9 @@ int rtnl_listen(struct rtnl_handle *rtnl,
a4b897
 
a4b897
 	iov.iov_base = buf;
a4b897
 	while (1) {
a4b897
+		struct rtnl_ctrl_data ctrl;
a4b897
+		struct cmsghdr *cmsg;
a4b897
+
a4b897
 		iov.iov_len = sizeof(buf);
a4b897
 		status = recvmsg(rtnl->fd, &msg, 0);
a4b897
 
a4b897
@@ -449,6 +475,21 @@ int rtnl_listen(struct rtnl_handle *rtnl,
a4b897
 			fprintf(stderr, "Sender address length == %d\n", msg.msg_namelen);
a4b897
 			exit(1);
a4b897
 		}
a4b897
+
a4b897
+		if (rtnl->flags & RTNL_HANDLE_F_LISTEN_ALL_NSID) {
a4b897
+			memset(&ctrl, 0, sizeof(ctrl));
a4b897
+			ctrl.nsid = -1;
a4b897
+			for (cmsg = CMSG_FIRSTHDR(&msg;; cmsg;
a4b897
+			     cmsg = CMSG_NXTHDR(&msg, cmsg))
a4b897
+				if (cmsg->cmsg_level == SOL_NETLINK &&
a4b897
+				    cmsg->cmsg_type == NETLINK_LISTEN_ALL_NSID &&
a4b897
+				    cmsg->cmsg_len == CMSG_LEN(sizeof(int))) {
a4b897
+					int *data = (int *)CMSG_DATA(cmsg);
a4b897
+
a4b897
+					ctrl.nsid = *data;
a4b897
+				}
a4b897
+		}
a4b897
+
a4b897
 		for (h = (struct nlmsghdr*)buf; status >= sizeof(*h); ) {
a4b897
 			int err;
a4b897
 			int len = h->nlmsg_len;
a4b897
@@ -463,7 +504,7 @@ int rtnl_listen(struct rtnl_handle *rtnl,
a4b897
 				exit(1);
a4b897
 			}
a4b897
 
a4b897
-			err = handler(&nladdr, h, jarg);
a4b897
+			err = handler(&nladdr, &ctrl, h, jarg);
a4b897
 			if (err < 0)
a4b897
 				return err;
a4b897
 
a4b897
@@ -481,7 +522,7 @@ int rtnl_listen(struct rtnl_handle *rtnl,
a4b897
 	}
a4b897
 }
a4b897
 
a4b897
-int rtnl_from_file(FILE *rtnl, rtnl_filter_t handler,
a4b897
+int rtnl_from_file(FILE *rtnl, rtnl_listen_filter_t handler,
a4b897
 		   void *jarg)
a4b897
 {
a4b897
 	int status;
a4b897
@@ -529,7 +570,7 @@ int rtnl_from_file(FILE *rtnl, rtnl_filter_t handler,
a4b897
 			return -1;
a4b897
 		}
a4b897
 
a4b897
-		err = handler(&nladdr, h, jarg);
a4b897
+		err = handler(&nladdr, NULL, h, jarg);
a4b897
 		if (err < 0)
a4b897
 			return err;
a4b897
 	}
a4b897
diff --git a/man/man3/libnetlink.3 b/man/man3/libnetlink.3
a4b897
index e999bd6..99be9cc 100644
a4b897
--- a/man/man3/libnetlink.3
a4b897
+++ b/man/man3/libnetlink.3
a4b897
@@ -33,7 +33,8 @@ int rtnl_talk(struct rtnl_handle *rtnl, struct nlmsghdr *n, pid_t peer,
a4b897
 	      void *jarg)
a4b897
 .sp
a4b897
 int rtnl_listen(struct rtnl_handle *rtnl, 
a4b897
-	      int (*handler)(struct sockaddr_nl *,struct nlmsghdr *n, void *),
a4b897
+	      int (*handler)(struct sockaddr_nl *, struct rtnl_ctrl_data *,
a4b897
+			     struct nlmsghdr *n, void *),
a4b897
 	      void *jarg)
a4b897
 .sp
a4b897
 int rtnl_from_file(FILE *rtnl, 
a4b897
@@ -108,8 +109,8 @@ rtnl_listen
a4b897
 Receive netlink data after a request and pass it to 
a4b897
 .I handler.
a4b897
 .B handler
a4b897
-is a callback that gets the message source address, the message itself,
a4b897
-and the
a4b897
+is a callback that gets the message source address, anscillary data, the message
a4b897
+itself, and the
a4b897
 .B jarg
a4b897
 cookie as arguments. It will get called for all received messages.
a4b897
 Only one message bundle is received. If there is a message
a4b897
diff --git a/man/man8/ip-monitor.8 b/man/man8/ip-monitor.8
a4b897
index a710b34..91099f8 100644
a4b897
--- a/man/man8/ip-monitor.8
a4b897
+++ b/man/man8/ip-monitor.8
a4b897
@@ -11,6 +11,10 @@ ip-monitor, rtmon \- state monitoring
a4b897
 .BR  "monitor" " [ " all " |"
a4b897
 .IR OBJECT-LIST " ] ["
a4b897
 .BI file " FILENAME "
a4b897
+] [
a4b897
+.BI label
a4b897
+] [
a4b897
+.BI all-nsid
a4b897
 ]
a4b897
 .sp
a4b897
 
a4b897
@@ -26,6 +30,10 @@ command is the first in the command line and then the object list follows:
a4b897
 .BR "ip monitor" " [ " all " |"
a4b897
 .IR OBJECT-LIST " ] ["
a4b897
 .BI file " FILENAME "
a4b897
+] [
a4b897
+.BI label
a4b897
+] [
a4b897
+.BI all-nsid
a4b897
 ]
a4b897
 
a4b897
 .I OBJECT-LIST
a4b897
@@ -42,6 +50,32 @@ described in previous sections.
a4b897
 
a4b897
 .P
a4b897
 If the
a4b897
+.BI label
a4b897
+option is set, a prefix is displayed before each message to
a4b897
+show the family of the message. For example:
a4b897
+.sp
a4b897
+.in +2
a4b897
+[NEIGH]10.16.0.112 dev eth0 lladdr 00:04:23:df:2f:d0 REACHABLE
a4b897
+[LINK]3: eth1: <BROADCAST,MULTICAST> mtu 1500 qdisc pfifo_fast state DOWN group default
a4b897
+    link/ether 52:54:00:12:34:57 brd ff:ff:ff:ff:ff:ff
a4b897
+.in -2
a4b897
+.sp
a4b897
+
a4b897
+.P
a4b897
+If the
a4b897
+.BI all-nsid
a4b897
+option is set, the program listens to all network namespaces that have a
a4b897
+nsid assigned into the network namespace were the program is running.
a4b897
+A prefix is displayed to show the network namespace where the message
a4b897
+originates. Example:
a4b897
+.sp
a4b897
+.in +2
a4b897
+[nsid 0]10.16.0.112 dev eth0 lladdr 00:04:23:df:2f:d0 REACHABLE
a4b897
+.in -2
a4b897
+.sp
a4b897
+
a4b897
+.P
a4b897
+If the
a4b897
 .BI file
a4b897
 option is given, the program does not listen on RTNETLINK,
a4b897
 but opens the given file, and dumps its contents. The file
a4b897
@@ -75,3 +109,5 @@ of starting.
a4b897
 
a4b897
 .SH AUTHOR
a4b897
 Original Manpage by Michail Litvak <mci@owl.openwall.com>
a4b897
+.br
a4b897
+Manpage revised by Nicolas Dichtel <nicolas.dichtel@6wind.com>
a4b897
diff --git a/man/man8/ip-xfrm.8 b/man/man8/ip-xfrm.8
a4b897
index e305c0b..aea4fda 100644
a4b897
--- a/man/man8/ip-xfrm.8
a4b897
+++ b/man/man8/ip-xfrm.8
a4b897
@@ -359,7 +359,11 @@ ip-xfrm \- transform configuration
a4b897
 .BR required " | " use
a4b897
 
a4b897
 .ti -8
a4b897
-.BR "ip xfrm monitor" " [ " all " |"
a4b897
+.BR "ip xfrm monitor" " ["
a4b897
+.BI all-nsid
a4b897
+] [
a4b897
+.BI all
a4b897
+ |
a4b897
 .IR LISTofXFRM-OBJECTS " ]"
a4b897
 
a4b897
 .ti -8
a4b897
@@ -664,7 +668,22 @@ ip xfrm monitor 	state monitoring for xfrm objects
a4b897
 .PP
a4b897
 The xfrm objects to monitor can be optionally specified.
a4b897
 
a4b897
+.P
a4b897
+If the
a4b897
+.BI all-nsid
a4b897
+option is set, the program listens to all network namespaces that have a
a4b897
+nsid assigned into the network namespace were the program is running.
a4b897
+A prefix is displayed to show the network namespace where the message
a4b897
+originates. Example:
a4b897
+.sp
a4b897
+.in +2
a4b897
+[nsid 1]Flushed state proto 0
a4b897
+.in -2
a4b897
+.sp
a4b897
+
a4b897
 .SH AUTHOR
a4b897
 Manpage revised by David Ward <david.ward@ll.mit.edu>
a4b897
 .br
a4b897
 Manpage revised by Christophe Gouault <christophe.gouault@6wind.com>
a4b897
+.br
a4b897
+Manpage revised by Nicolas Dichtel <nicolas.dichtel@6wind.com>
a4b897
diff --git a/tc/tc_monitor.c b/tc/tc_monitor.c
a4b897
index 0efe034..cae3616 100644
a4b897
--- a/tc/tc_monitor.c
a4b897
+++ b/tc/tc_monitor.c
a4b897
@@ -36,6 +36,7 @@ static void usage(void)
a4b897
 
a4b897
 
a4b897
 static int accept_tcmsg(const struct sockaddr_nl *who,
a4b897
+			struct rtnl_ctrl_data *ctrl,
a4b897
 			struct nlmsghdr *n, void *arg)
a4b897
 {
a4b897
 	FILE *fp = (FILE*)arg;
a4b897
-- 
a4b897
1.8.3.1
a4b897