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@xxxxxxxxxx> --- 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..dd1c7c2 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(task_struct_nsproxy)) { + 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 -- Crash-utility mailing list Crash-utility@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/crash-utility