naccyde / rpms / iproute

Forked from rpms/iproute 7 months ago
Clone

Blame SOURCES/iproute2-3.10.0-lib.patch

a4b897
commit f389090cd1dc2f9945c19f837ade98bd733015cb
a4b897
Author: Pavel Šimerda <psimerda@redhat.com>
a4b897
Date:   Thu May 28 23:39:22 2015 +0200
a4b897
a4b897
    backport selected library functions
a4b897
a4b897
diff --git a/include/libnetlink.h b/include/libnetlink.h
a4b897
index ec3d657..5dcc0c3 100644
a4b897
--- a/include/libnetlink.h
a4b897
+++ b/include/libnetlink.h
a4b897
@@ -18,6 +18,7 @@ struct rtnl_handle
a4b897
 	struct sockaddr_nl	peer;
a4b897
 	__u32			seq;
a4b897
 	__u32			dump;
a4b897
+	FILE		       *dump_fp;
a4b897
 };
a4b897
 
a4b897
 extern int rcvbuf;
a4b897
@@ -68,11 +69,15 @@ extern int parse_rtattr(struct rtattr *tb[], int max, struct rtattr *rta, int le
a4b897
 extern int parse_rtattr_flags(struct rtattr *tb[], int max, struct rtattr *rta,
a4b897
 			      int len, unsigned short flags);
a4b897
 extern int parse_rtattr_byindex(struct rtattr *tb[], int max, struct rtattr *rta, int len);
a4b897
+extern struct rtattr *parse_rtattr_one(int type, struct rtattr *rta, int len);
a4b897
 extern int __parse_rtattr_nested_compat(struct rtattr *tb[], int max, struct rtattr *rta, int len);
a4b897
 
a4b897
 #define parse_rtattr_nested(tb, max, rta) \
a4b897
 	(parse_rtattr((tb), (max), RTA_DATA(rta), RTA_PAYLOAD(rta)))
a4b897
 
a4b897
+#define parse_rtattr_one_nested(type, rta) \
a4b897
+	(parse_rtattr_one(type, RTA_DATA(rta), RTA_PAYLOAD(rta)))
a4b897
+
a4b897
 #define parse_rtattr_nested_compat(tb, max, rta, data, len) \
a4b897
 	({ data = RTA_PAYLOAD(rta) >= len ? RTA_DATA(rta) : NULL;	\
a4b897
 		__parse_rtattr_nested_compat(tb, max, rta, len); })
a4b897
@@ -140,5 +145,17 @@ extern int rtnl_from_file(FILE *, rtnl_filter_t handler,
a4b897
 #define NDTA_PAYLOAD(n) NLMSG_PAYLOAD(n,sizeof(struct ndtmsg))
a4b897
 #endif
a4b897
 
a4b897
+#ifndef NETNS_RTA
a4b897
+#define NETNS_RTA(r) \
a4b897
+	((struct rtattr*)(((char*)(r)) + NLMSG_ALIGN(sizeof(struct rtgenmsg))))
a4b897
+#endif
a4b897
+#ifndef NETNS_PAYLOAD
a4b897
+#define NETNS_PAYLOAD(n)	NLMSG_PAYLOAD(n,sizeof(struct rtgenmsg))
a4b897
+#endif
a4b897
+
a4b897
+/* User defined nlmsg_type which is used mostly for logging netlink
a4b897
+ * messages from dump file */
a4b897
+#define NLMSG_TSTAMP	15
a4b897
+
a4b897
 #endif /* __LIBNETLINK_H__ */
a4b897
 
a4b897
diff --git a/include/namespace.h b/include/namespace.h
a4b897
new file mode 100644
a4b897
index 0000000..a2ac7dc
a4b897
--- /dev/null
a4b897
+++ b/include/namespace.h
a4b897
@@ -0,0 +1,54 @@
a4b897
+#ifndef __NAMESPACE_H__
a4b897
+#define __NAMESPACE_H__ 1
a4b897
+
a4b897
+#include <sched.h>
a4b897
+#include <sys/mount.h>
a4b897
+#include <sys/syscall.h>
a4b897
+#include <errno.h>
a4b897
+
a4b897
+#define NETNS_RUN_DIR "/var/run/netns"
a4b897
+#define NETNS_ETC_DIR "/etc/netns"
a4b897
+
a4b897
+#ifndef CLONE_NEWNET
a4b897
+#define CLONE_NEWNET 0x40000000	/* New network namespace (lo, device, names sockets, etc) */
a4b897
+#endif
a4b897
+
a4b897
+#ifndef MNT_DETACH
a4b897
+#define MNT_DETACH	0x00000002	/* Just detach from the tree */
a4b897
+#endif /* MNT_DETACH */
a4b897
+
a4b897
+/* sys/mount.h may be out too old to have these */
a4b897
+#ifndef MS_REC
a4b897
+#define MS_REC		16384
a4b897
+#endif
a4b897
+
a4b897
+#ifndef MS_SLAVE
a4b897
+#define MS_SLAVE	(1 << 19)
a4b897
+#endif
a4b897
+
a4b897
+#ifndef MS_SHARED
a4b897
+#define MS_SHARED	(1 << 20)
a4b897
+#endif
a4b897
+
a4b897
+#ifndef HAVE_SETNS
a4b897
+static inline int setns(int fd, int nstype)
a4b897
+{
a4b897
+#ifdef __NR_setns
a4b897
+	return syscall(__NR_setns, fd, nstype);
a4b897
+#else
a4b897
+	errno = ENOSYS;
a4b897
+	return -1;
a4b897
+#endif
a4b897
+}
a4b897
+#endif /* HAVE_SETNS */
a4b897
+
a4b897
+extern int netns_switch(char *netns);
a4b897
+extern int netns_get_fd(const char *netns);
a4b897
+extern int netns_foreach(int (*func)(char *nsname, void *arg), void *arg);
a4b897
+
a4b897
+struct netns_func {
a4b897
+	int (*func)(char *nsname, void *arg);
a4b897
+	void *arg;
a4b897
+};
a4b897
+
a4b897
+#endif /* __NAMESPACE_H__ */
a4b897
diff --git a/include/rt_names.h b/include/rt_names.h
a4b897
index 37adbd3..c0ea4f9 100644
a4b897
--- a/include/rt_names.h
a4b897
+++ b/include/rt_names.h
a4b897
@@ -8,6 +8,7 @@ const char *rtnl_rtscope_n2a(int id, char *buf, int len);
a4b897
 const char *rtnl_rttable_n2a(__u32 id, char *buf, int len);
a4b897
 const char *rtnl_rtrealm_n2a(int id, char *buf, int len);
a4b897
 const char *rtnl_dsfield_n2a(int id, char *buf, int len);
a4b897
+const char *rtnl_group_n2a(int id, char *buf, int len);
a4b897
 
a4b897
 int rtnl_rtprot_a2n(__u32 *id, const char *arg);
a4b897
 int rtnl_rtscope_a2n(__u32 *id, const char *arg);
a4b897
@@ -28,5 +29,7 @@ int ll_addr_a2n(char *lladdr, int len, const char *arg);
a4b897
 const char * ll_proto_n2a(unsigned short id, char *buf, int len);
a4b897
 int ll_proto_a2n(unsigned short *id, const char *buf);
a4b897
 
a4b897
+const char *nl_proto_n2a(int id, char *buf, int len);
a4b897
+int nl_proto_a2n(__u32 *id, const char *arg);
a4b897
 
a4b897
 #endif
a4b897
diff --git a/include/utils.h b/include/utils.h
a4b897
index 24ff19f..ca05b02 100644
a4b897
--- a/include/utils.h
a4b897
+++ b/include/utils.h
a4b897
@@ -5,12 +5,15 @@
a4b897
 #include <asm/types.h>
a4b897
 #include <resolv.h>
a4b897
 #include <stdlib.h>
a4b897
+#include <stdbool.h>
a4b897
 
a4b897
 #include "libnetlink.h"
a4b897
 #include "ll_map.h"
a4b897
 #include "rtm_map.h"
a4b897
 
a4b897
 extern int preferred_family;
a4b897
+extern int human_readable;
a4b897
+extern int use_iec;
a4b897
 extern int show_stats;
a4b897
 extern int show_details;
a4b897
 extern int show_raw;
a4b897
@@ -20,6 +23,7 @@ extern int timestamp;
a4b897
 extern char * _SL_;
a4b897
 extern int max_flush_loops;
a4b897
 extern int batch_mode;
a4b897
+extern bool do_all;
a4b897
 
a4b897
 #ifndef IPPROTO_ESP
a4b897
 #define IPPROTO_ESP	50
a4b897
@@ -151,9 +155,16 @@ int print_timestamp(FILE *fp);
a4b897
 extern int cmdlineno;
a4b897
 extern ssize_t getcmdline(char **line, size_t *len, FILE *in);
a4b897
 extern int makeargs(char *line, char *argv[], int maxargs);
a4b897
+extern int inet_get_addr(const char *src, __u32 *dst, struct in6_addr *dst6);
a4b897
 
a4b897
 struct iplink_req;
a4b897
 int iplink_parse(int argc, char **argv, struct iplink_req *req,
a4b897
 		char **name, char **type, char **link, char **dev,
a4b897
 		int *group);
a4b897
+
a4b897
+extern int do_each_netns(int (*func)(char *nsname, void *arg), void *arg,
a4b897
+		bool show_label);
a4b897
+
a4b897
+char *int_to_str(int val, char *buf);
a4b897
+
a4b897
 #endif /* __UTILS_H__ */
a4b897
diff --git a/lib/Makefile b/lib/Makefile
a4b897
index a42b885..66f89f1 100644
a4b897
--- a/lib/Makefile
a4b897
+++ b/lib/Makefile
a4b897
@@ -1,8 +1,12 @@
a4b897
 include ../Config
a4b897
 
a4b897
+ifeq ($(IP_CONFIG_SETNS),y)
a4b897
+	CFLAGS += -DHAVE_SETNS
a4b897
+endif
a4b897
+
a4b897
 CFLAGS += -fPIC
a4b897
 
a4b897
-UTILOBJ=utils.o rt_names.o ll_types.o ll_proto.o ll_addr.o inet_proto.o
a4b897
+UTILOBJ=utils.o rt_names.o ll_types.o ll_proto.o ll_addr.o inet_proto.o namespace.o
a4b897
 
a4b897
 NLOBJ=libgenl.o ll_map.o libnetlink.o
a4b897
 
a4b897
diff --git a/lib/namespace.c b/lib/namespace.c
a4b897
new file mode 100644
a4b897
index 0000000..c03a103
a4b897
--- /dev/null
a4b897
+++ b/lib/namespace.c
a4b897
@@ -0,0 +1,123 @@
a4b897
+/*
a4b897
+ * namespace.c
a4b897
+ *
a4b897
+ *		This program is free software; you can redistribute it and/or
a4b897
+ *		modify it under the terms of the GNU General Public License
a4b897
+ *		as published by the Free Software Foundation; either version
a4b897
+ *		2 of the License, or (at your option) any later version.
a4b897
+ */
a4b897
+
a4b897
+#include <fcntl.h>
a4b897
+#include <dirent.h>
a4b897
+
a4b897
+#include "utils.h"
a4b897
+#include "namespace.h"
a4b897
+
a4b897
+static void bind_etc(const char *name)
a4b897
+{
a4b897
+	char etc_netns_path[MAXPATHLEN];
a4b897
+	char netns_name[MAXPATHLEN];
a4b897
+	char etc_name[MAXPATHLEN];
a4b897
+	struct dirent *entry;
a4b897
+	DIR *dir;
a4b897
+
a4b897
+	snprintf(etc_netns_path, sizeof(etc_netns_path), "%s/%s", NETNS_ETC_DIR, name);
a4b897
+	dir = opendir(etc_netns_path);
a4b897
+	if (!dir)
a4b897
+		return;
a4b897
+
a4b897
+	while ((entry = readdir(dir)) != NULL) {
a4b897
+		if (strcmp(entry->d_name, ".") == 0)
a4b897
+			continue;
a4b897
+		if (strcmp(entry->d_name, "..") == 0)
a4b897
+			continue;
a4b897
+		snprintf(netns_name, sizeof(netns_name), "%s/%s", etc_netns_path, entry->d_name);
a4b897
+		snprintf(etc_name, sizeof(etc_name), "/etc/%s", entry->d_name);
a4b897
+		if (mount(netns_name, etc_name, "none", MS_BIND, NULL) < 0) {
a4b897
+			fprintf(stderr, "Bind %s -> %s failed: %s\n",
a4b897
+				netns_name, etc_name, strerror(errno));
a4b897
+		}
a4b897
+	}
a4b897
+	closedir(dir);
a4b897
+}
a4b897
+
a4b897
+int netns_switch(char *name)
a4b897
+{
a4b897
+	char net_path[MAXPATHLEN];
a4b897
+	int netns;
a4b897
+
a4b897
+	snprintf(net_path, sizeof(net_path), "%s/%s", NETNS_RUN_DIR, name);
a4b897
+	netns = open(net_path, O_RDONLY | O_CLOEXEC);
a4b897
+	if (netns < 0) {
a4b897
+		fprintf(stderr, "Cannot open network namespace \"%s\": %s\n",
a4b897
+			name, strerror(errno));
a4b897
+		return -1;
a4b897
+	}
a4b897
+
a4b897
+	if (setns(netns, CLONE_NEWNET) < 0) {
a4b897
+		fprintf(stderr, "setting the network namespace \"%s\" failed: %s\n",
a4b897
+			name, strerror(errno));
a4b897
+		return -1;
a4b897
+	}
a4b897
+
a4b897
+	if (unshare(CLONE_NEWNS) < 0) {
a4b897
+		fprintf(stderr, "unshare failed: %s\n", strerror(errno));
a4b897
+		return -1;
a4b897
+	}
a4b897
+	/* Don't let any mounts propagate back to the parent */
a4b897
+	if (mount("", "/", "none", MS_SLAVE | MS_REC, NULL)) {
a4b897
+		fprintf(stderr, "\"mount --make-rslave /\" failed: %s\n",
a4b897
+			strerror(errno));
a4b897
+		return -1;
a4b897
+	}
a4b897
+	/* Mount a version of /sys that describes the network namespace */
a4b897
+	if (umount2("/sys", MNT_DETACH) < 0) {
a4b897
+		fprintf(stderr, "umount of /sys failed: %s\n", strerror(errno));
a4b897
+		return -1;
a4b897
+	}
a4b897
+	if (mount(name, "/sys", "sysfs", 0, NULL) < 0) {
a4b897
+		fprintf(stderr, "mount of /sys failed: %s\n",strerror(errno));
a4b897
+		return -1;
a4b897
+	}
a4b897
+
a4b897
+	/* Setup bind mounts for config files in /etc */
a4b897
+	bind_etc(name);
a4b897
+	return 0;
a4b897
+}
a4b897
+
a4b897
+int netns_get_fd(const char *name)
a4b897
+{
a4b897
+	char pathbuf[MAXPATHLEN];
a4b897
+	const char *path, *ptr;
a4b897
+
a4b897
+	path = name;
a4b897
+	ptr = strchr(name, '/');
a4b897
+	if (!ptr) {
a4b897
+		snprintf(pathbuf, sizeof(pathbuf), "%s/%s",
a4b897
+			NETNS_RUN_DIR, name );
a4b897
+		path = pathbuf;
a4b897
+	}
a4b897
+	return open(path, O_RDONLY);
a4b897
+}
a4b897
+
a4b897
+int netns_foreach(int (*func)(char *nsname, void *arg), void *arg)
a4b897
+{
a4b897
+	DIR *dir;
a4b897
+	struct dirent *entry;
a4b897
+
a4b897
+	dir = opendir(NETNS_RUN_DIR);
a4b897
+	if (!dir)
a4b897
+		return -1;
a4b897
+
a4b897
+	while ((entry = readdir(dir)) != NULL) {
a4b897
+		if (strcmp(entry->d_name, ".") == 0)
a4b897
+			continue;
a4b897
+		if (strcmp(entry->d_name, "..") == 0)
a4b897
+			continue;
a4b897
+		if (func(entry->d_name, arg))
a4b897
+			break;
a4b897
+	}
a4b897
+
a4b897
+	closedir(dir);
a4b897
+	return 0;
a4b897
+}
a4b897
diff --git a/lib/rt_names.c b/lib/rt_names.c
a4b897
index 02f1417..c2e60de 100644
a4b897
--- a/lib/rt_names.c
a4b897
+++ b/lib/rt_names.c
a4b897
@@ -500,3 +500,104 @@ int rtnl_group_a2n(int *id, const char *arg)
a4b897
 	*id = i;
a4b897
 	return 0;
a4b897
 }
a4b897
+
a4b897
+const char *rtnl_group_n2a(int id, char *buf, int len)
a4b897
+{
a4b897
+	struct rtnl_hash_entry *entry;
a4b897
+	int i;
a4b897
+
a4b897
+	if (!rtnl_group_init)
a4b897
+		rtnl_group_initialize();
a4b897
+
a4b897
+	for (i=0; i<256; i++) {
a4b897
+		entry = rtnl_group_hash[i];
a4b897
+		if (entry && entry->id == id) {
a4b897
+			return entry->name;
a4b897
+		}
a4b897
+	}
a4b897
+
a4b897
+	snprintf(buf, len, "%d", id);
a4b897
+	return buf;
a4b897
+}
a4b897
+
a4b897
+static char *nl_proto_tab[256] = {
a4b897
+	[NETLINK_ROUTE]          = "rtnl",
a4b897
+	[NETLINK_UNUSED]         = "unused",
a4b897
+	[NETLINK_USERSOCK]       = "usersock",
a4b897
+	[NETLINK_FIREWALL]       = "fw",
a4b897
+	[NETLINK_SOCK_DIAG]      = "tcpdiag",
a4b897
+	[NETLINK_NFLOG]          = "nflog",
a4b897
+	[NETLINK_XFRM]           = "xfrm",
a4b897
+	[NETLINK_SELINUX]        = "selinux",
a4b897
+	[NETLINK_ISCSI]          = "iscsi",
a4b897
+	[NETLINK_AUDIT]          = "audit",
a4b897
+	[NETLINK_FIB_LOOKUP]     = "fiblookup",
a4b897
+	[NETLINK_CONNECTOR]      = "connector",
a4b897
+	[NETLINK_NETFILTER]      = "nft",
a4b897
+	[NETLINK_IP6_FW]         = "ip6fw",
a4b897
+	[NETLINK_DNRTMSG]        = "dec-rt",
a4b897
+	[NETLINK_KOBJECT_UEVENT] = "uevent",
a4b897
+	[NETLINK_GENERIC]        = "genl",
a4b897
+	[NETLINK_SCSITRANSPORT]  = "scsi-trans",
a4b897
+	[NETLINK_ECRYPTFS]       = "ecryptfs",
a4b897
+	[NETLINK_RDMA]           = "rdma",
a4b897
+	[NETLINK_CRYPTO]         = "crypto",
a4b897
+};
a4b897
+
a4b897
+static int nl_proto_init;
a4b897
+
a4b897
+static void nl_proto_initialize(void)
a4b897
+{
a4b897
+	nl_proto_init = 1;
a4b897
+	rtnl_tab_initialize(CONFDIR "/nl_protos",
a4b897
+			    nl_proto_tab, 256);
a4b897
+}
a4b897
+
a4b897
+const char *nl_proto_n2a(int id, char *buf, int len)
a4b897
+{
a4b897
+	if (id < 0 || id >= 256) {
a4b897
+		snprintf(buf, len, "%u", id);
a4b897
+		return buf;
a4b897
+	}
a4b897
+
a4b897
+	if (!nl_proto_init)
a4b897
+		nl_proto_initialize();
a4b897
+
a4b897
+	if (nl_proto_tab[id])
a4b897
+		return nl_proto_tab[id];
a4b897
+
a4b897
+	snprintf(buf, len, "%u", id);
a4b897
+	return buf;
a4b897
+}
a4b897
+
a4b897
+int nl_proto_a2n(__u32 *id, const char *arg)
a4b897
+{
a4b897
+	static char *cache = NULL;
a4b897
+	static unsigned long res;
a4b897
+	char *end;
a4b897
+	int i;
a4b897
+
a4b897
+	if (cache && strcmp(cache, arg) == 0) {
a4b897
+		*id = res;
a4b897
+		return 0;
a4b897
+	}
a4b897
+
a4b897
+	if (!nl_proto_init)
a4b897
+		nl_proto_initialize();
a4b897
+
a4b897
+	for (i = 0; i < 256; i++) {
a4b897
+		if (nl_proto_tab[i] &&
a4b897
+		    strcmp(nl_proto_tab[i], arg) == 0) {
a4b897
+			cache = nl_proto_tab[i];
a4b897
+			res = i;
a4b897
+			*id = res;
a4b897
+			return 0;
a4b897
+		}
a4b897
+	}
a4b897
+
a4b897
+	res = strtoul(arg, &end, 0);
a4b897
+	if (!end || end == arg || *end || res > 255)
a4b897
+		return -1;
a4b897
+	*id = res;
a4b897
+	return 0;
a4b897
+}
a4b897
diff --git a/lib/utils.c b/lib/utils.c
a4b897
index 0f9de02..299b485 100644
a4b897
--- a/lib/utils.c
a4b897
+++ b/lib/utils.c
a4b897
@@ -31,6 +31,7 @@
a4b897
 
a4b897
 
a4b897
 #include "utils.h"
a4b897
+#include "namespace.h"
a4b897
 
a4b897
 int get_integer(int *val, const char *arg, int base)
a4b897
 {
a4b897
@@ -864,3 +865,44 @@ int makeargs(char *line, char *argv[], int maxargs)
a4b897
 
a4b897
 	return argc;
a4b897
 }
a4b897
+
a4b897
+int inet_get_addr(const char *src, __u32 *dst, struct in6_addr *dst6)
a4b897
+{
a4b897
+	if (strchr(src, ':'))
a4b897
+		return inet_pton(AF_INET6, src, dst6);
a4b897
+	else
a4b897
+		return inet_pton(AF_INET, src, dst);
a4b897
+}
a4b897
+
a4b897
+static int on_netns(char *nsname, void *arg)
a4b897
+{
a4b897
+	struct netns_func *f = arg;
a4b897
+
a4b897
+	if (netns_switch(nsname))
a4b897
+		return -1;
a4b897
+
a4b897
+	return f->func(nsname, f->arg);
a4b897
+}
a4b897
+
a4b897
+static int on_netns_label(char *nsname, void *arg)
a4b897
+{
a4b897
+	printf("\nnetns: %s\n", nsname);
a4b897
+	return on_netns(nsname, arg);
a4b897
+}
a4b897
+
a4b897
+int do_each_netns(int (*func)(char *nsname, void *arg), void *arg,
a4b897
+		bool show_label)
a4b897
+{
a4b897
+	struct netns_func nsf = { .func = func, .arg = arg };
a4b897
+
a4b897
+	if (show_label)
a4b897
+		return netns_foreach(on_netns_label, &nsf;;
a4b897
+
a4b897
+	return netns_foreach(on_netns, &nsf;;
a4b897
+}
a4b897
+
a4b897
+char *int_to_str(int val, char *buf)
a4b897
+{
a4b897
+	sprintf(buf, "%d", val);
a4b897
+	return buf;
a4b897
+}
a4b897
diff --git a/misc/Makefile b/misc/Makefile
a4b897
index a59ff87..a516bd8 100644
a4b897
--- a/misc/Makefile
a4b897
+++ b/misc/Makefile
a4b897
@@ -5,6 +5,10 @@ TARGETS=ss nstat ifstat rtacct arpd lnstat
a4b897
 
a4b897
 include ../Config
a4b897
 
a4b897
+ifeq ($(IP_CONFIG_SETNS),y)
a4b897
+	CFLAGS += -DHAVE_SETNS
a4b897
+endif
a4b897
+
a4b897
 all: $(TARGETS)
a4b897
 
a4b897
 ss: $(SSOBJ)