net without arguments shows network devices in init_net
net -n -- in network namespace of current task
net -n pid|taskp -- in network namespace of specified task
Signed-off-by: Vasily Averin <vvs(a)openvz.org>
---
defs.h | 1 +
help.c | 10 +++++++++-
net.c | 56 +++++++++++++++++++++++++++++++++++++++++---------------
symbols.c | 2 ++
4 files changed, 53 insertions(+), 16 deletions(-)
diff --git a/defs.h b/defs.h
index dc2d65a..d51936f 100644
--- a/defs.h
+++ b/defs.h
@@ -1923,6 +1923,7 @@ struct offset_table { /* stash of commonly-used
offsets */
long kernfs_node_parent;
long kmem_cache_cpu_partial;
long kmem_cache_cpu_cache;
+ long nsproxy_net_ns;
};
struct size_table { /* stash of commonly-used sizes */
diff --git a/help.c b/help.c
index 780966b..4f98aa5 100644
--- a/help.c
+++ b/help.c
@@ -6452,7 +6452,7 @@ NULL
char *help_net[] = {
"net",
"network command",
-"[-a] [[-s | -S [-xd]] [-R ref] [pid | taskp]] [-N addr]",
+"[-a] [[-s | -S [-xd]] [-R ref] [-n] [pid | taskp]] [-N addr]",
" Display various network related data:\n",
" -a display the ARP cache.",
" -s display open network socket/sock addresses, their family and
type,",
@@ -6465,6 +6465,9 @@ char *help_net[] = {
" -N addr translates an IPv4 address expressed as a decimal or hexadecimal",
" value into a standard numbers-and-dots notation.",
" -R ref socket or sock address, or file descriptor.",
+" For kernels supporting namespaces, the -n option may be used to",
+" display the network devices with respect to the network namespace"
+" of a current task or a task specified by pid or taskp:\n",
" pid a process PID.",
" taskp a hexadecimal task_struct pointer.\n",
" If no arguments are entered, the list of network devices, names and IP",
@@ -6479,6 +6482,11 @@ char *help_net[] = {
" c0249f20 lo 127.0.0.1",
" c7fe6d80 eth0 10.1.8.20",
" ",
+"\n %s> net -n 2618",
+" NET_DEVICE NAME IP ADDRESS(ES)",
+" ffff880456ee7020 lo 127.0.0.1",
+" ffff8804516a1020 eth0 10.1.9.223",
+" ",
" Dump the ARP cache:\n",
" %s> net -a",
" NEIGHBOUR IP ADDRESS HW TYPE HW ADDRESS DEVICE
STATE",
diff --git a/net.c b/net.c
index cdd424c..b6d9f25 100644
--- a/net.c
+++ b/net.c
@@ -64,9 +64,9 @@ struct devinfo {
/* bytes needed for <ip address>:<port> notation */
#define BYTES_IP_TUPLE (BYTES_IP_ADDR + BYTES_PORT_NUM + 1)
-static void show_net_devices(void);
-static void show_net_devices_v2(void);
-static void show_net_devices_v3(void);
+static void show_net_devices(ulong);
+static void show_net_devices_v2(ulong);
+static void show_net_devices_v3(ulong);
static void print_neighbour_q(ulong, int);
static void get_netdev_info(ulong, struct devinfo *);
static void get_device_name(ulong, char *);
@@ -137,6 +137,8 @@ net_init(void)
error(WARNING,
"net_init: unknown device type for net device");
}
+ if (VALID_MEMBER(task_struct_nsproxy))
+ MEMBER_OFFSET_INIT(nsproxy_net_ns, "nsproxy", "net_ns");
if (net->flags & NETDEV_INIT) {
MK_TYPE_T(net->dev_name_t, net->netdevice, "name");
@@ -304,7 +306,7 @@ net_init(void)
* The net command...
*/
-#define NETOPTS "N:asSR:xd"
+#define NETOPTS "N:asSR:xdn"
#define s_FLAG FOREACH_s_FLAG
#define S_FLAG FOREACH_S_FLAG
#define x_FLAG FOREACH_x_FLAG
@@ -324,8 +326,10 @@ void
cmd_net(void)
{
int c;
- ulong sflag;
+ ulong sflag, nflag;
ulong value;
+ ulong task;
+ struct task_context *tc = NULL;
struct in_addr in_addr;
struct reference reference, *ref;
@@ -333,7 +337,8 @@ cmd_net(void)
error(FATAL, "net subsystem not initialized!");
ref = NULL;
- sflag = 0;
+ sflag = nflag = 0;
+ task = pid_to_task(0);
while ((c = getopt(argcnt, args, NETOPTS)) != EOF) {
switch (c) {
@@ -387,6 +392,19 @@ cmd_net(void)
sflag |= d_FLAG;
break;
+ case 'n':
+ nflag = 1;
+ task = CURRENT_TASK();
+ if (args[optind]) {
+ switch (str_to_context(args[optind],
+ &value, &tc)) {
+ case STR_PID:
+ case STR_TASK:
+ task = tc->task;
+ }
+ }
+ break;
+
default:
argerrs++;
break;
@@ -399,8 +417,8 @@ cmd_net(void)
if (sflag)
dump_sockets(sflag, ref);
- if (argcnt == 1)
- show_net_devices();
+ if ((argcnt == 1) || nflag)
+ show_net_devices(task);
}
/*
@@ -408,17 +426,17 @@ cmd_net(void)
*/
static void
-show_net_devices(void)
+show_net_devices(ulong task)
{
ulong next;
long flen;
char buf[BUFSIZE];
if (symbol_exists("dev_base_head")) {
- show_net_devices_v2();
+ show_net_devices_v2(task);
return;
} else if (symbol_exists("init_net")) {
- show_net_devices_v3();
+ show_net_devices_v3(task);
return;
}
@@ -452,7 +470,7 @@ show_net_devices(void)
}
static void
-show_net_devices_v2(void)
+show_net_devices_v2(ulong task)
{
struct list_data list_data, *ld;
char *net_device_buf;
@@ -501,8 +519,9 @@ show_net_devices_v2(void)
}
static void
-show_net_devices_v3(void)
+show_net_devices_v3(ulong task)
{
+ ulong nsproxy_p, net_ns_p;
struct list_data list_data, *ld;
char *net_device_buf;
char buf[BUFSIZE];
@@ -523,8 +542,15 @@ show_net_devices_v3(void)
ld = &list_data;
BZERO(ld, sizeof(struct list_data));
ld->flags |= LIST_ALLOCATE;
- ld->start = ld->end =
- symbol_value("init_net") + OFFSET(net_dev_base_head);
+ if (VALID_MEMBER(nsproxy_net_ns)) {
+ readmem(task + OFFSET(task_struct_nsproxy), KVADDR, &nsproxy_p,
+ sizeof(ulong), "task_struct.nsproxy", FAULT_ON_ERROR);
+ if (!readmem(nsproxy_p + OFFSET(nsproxy_net_ns), KVADDR, &net_ns_p,
+ sizeof(ulong), "nsproxy.net_ns", RETURN_ON_ERROR|QUIET))
+ error(FATAL, "cannot determine net_namespace location!\n");
+ } else
+ net_ns_p = symbol_value("init_net");
+ ld->start = ld->end = net_ns_p + OFFSET(net_dev_base_head);
ld->list_head_offset = OFFSET(net_device_dev_list);
ndevcnt = do_list(ld);
diff --git a/symbols.c b/symbols.c
index cebff52..cb642f6 100644
--- a/symbols.c
+++ b/symbols.c
@@ -9295,6 +9295,8 @@ dump_offset_table(char *spec, ulong makestruct)
OFFSET(kern_ipc_perm_seq));
fprintf(fp, " nsproxy_ipc_ns: %ld\n",
OFFSET(nsproxy_ipc_ns));
+ fprintf(fp, " nsproxy_net_ns: %ld\n",
+ OFFSET(nsproxy_net_ns));
fprintf(fp, " shmem_inode_info_swapped: %ld\n",
OFFSET(shmem_inode_info_swapped));
fprintf(fp, " shmem_inode_info_vfs_inode: %ld\n",
--
1.9.1