[PATCH v2] Enhance "net" command to display IPv6 address of network interface

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Currently, the "net" command displays only the IPv4 address of a network
interface, it doesn't support outputting IPv6 address yet. For example:

Without the patch:
  crash> net
     NET_DEVICE     NAME   IP ADDRESS(ES)
  ffff8d01b1205000  lo     127.0.0.1
  ffff8d0087e40000  eno1   192.168.122.2

With the patch:
  crash> net
     NET_DEVICE     NAME   IP ADDRESS(ES)   INET6 ADDRESS
  ffff8d01b1205000  lo     127.0.0.1 ::1
  ffff8d0087e40000  eno1   192.168.122.2 xxxx:xx:x:xxxx:xxxx:xxx:xxxx:xxxx, yyyy::yyyy:yyy:yyyy:yyyy

Related kernel commit:
502a2ffd7376 ("ipv6: convert idev_list to list macros")

Reported-by: Buland Kumar Singh <bsingh@xxxxxxxxxx>
Signed-off-by: Lianbo Jiang <lijiang@xxxxxxxxxx>
---
 defs.h    |   6 +++
 net.c     | 123 +++++++++++++++++++++++++++++++++++++++++++++++++++---
 symbols.c |  12 ++++++
 3 files changed, 135 insertions(+), 6 deletions(-)

diff --git a/defs.h b/defs.h
index e76af3c78b69..1f2cf6e0ce01 100644
--- a/defs.h
+++ b/defs.h
@@ -2208,6 +2208,12 @@ struct offset_table {                    /* stash of commonly-used offsets */
 	long sock_common_skc_v6_daddr;
 	long sock_common_skc_v6_rcv_saddr;
 	long inactive_task_frame_bp;
+	long net_device_ip6_ptr;
+	long inet6_dev_addr_list;
+	long inet6_ifaddr_addr;
+	long inet6_ifaddr_if_list;
+	long inet6_ifaddr_if_next;
+	long in6_addr_in6_u;
 };
 
 struct size_table {         /* stash of commonly-used sizes */
diff --git a/net.c b/net.c
index aa445ab7ee13..52336762c85c 100644
--- a/net.c
+++ b/net.c
@@ -41,6 +41,7 @@ struct net_table {
 	long in_ifaddr_ifa_next;
 	long in_ifaddr_ifa_address;
 	int net_device_name_index;
+	long dev_ip6_ptr;
 } net_table = { 0 };
 
 struct net_table *net = &net_table;
@@ -71,6 +72,7 @@ static void print_neighbour_q(ulong, int);
 static void get_netdev_info(ulong, struct devinfo *);
 static void get_device_name(ulong, char *);
 static long get_device_address(ulong, char **, long);
+static void get_device_ip6_address(ulong, char **, long);
 static void get_sock_info(ulong, char *);
 static void dump_arp(void);
 static void arp_state_to_flags(unsigned char);
@@ -114,6 +116,13 @@ net_init(void)
 		net->dev_ip_ptr = MEMBER_OFFSET_INIT(net_device_ip_ptr,
 			"net_device", "ip_ptr");
 		MEMBER_OFFSET_INIT(net_device_dev_list, "net_device", "dev_list");
+		net->dev_ip6_ptr = MEMBER_OFFSET_INIT(net_device_ip6_ptr, "net_device", "ip6_ptr");
+		MEMBER_OFFSET_INIT(inet6_dev_addr_list, "inet6_dev", "addr_list");
+		MEMBER_OFFSET_INIT(inet6_ifaddr_addr, "inet6_ifaddr", "addr");
+		MEMBER_OFFSET_INIT(inet6_ifaddr_if_list, "inet6_ifaddr", "if_list");
+		MEMBER_OFFSET_INIT(inet6_ifaddr_if_next, "inet6_ifaddr", "if_next");
+		MEMBER_OFFSET_INIT(in6_addr_in6_u, "in6_addr", "in6_u");
+
 		MEMBER_OFFSET_INIT(net_dev_base_head, "net", "dev_base_head");
 		ARRAY_LENGTH_INIT(net->net_device_name_index,
 			net_device_name, "net_device.name", NULL, sizeof(char));
@@ -466,7 +475,7 @@ show_net_devices(ulong task)
 	buf = GETBUF(buflen);
 	flen = MAX(VADDR_PRLEN, strlen(net->netdevice));
 
-	fprintf(fp, "%s  NAME   IP ADDRESS(ES)\n",
+	fprintf(fp, "%s  NAME   IP ADDRESS(ES)   INET6 ADDRESS\n",
 		mkstring(upper_case(net->netdevice, buf), 
 			flen, CENTER|LJUST, NULL));
 
@@ -477,7 +486,14 @@ show_net_devices(ulong task)
 		get_device_name(next, buf);
 		fprintf(fp, "%-6s ", buf);
 
-		buflen = get_device_address(next, &buf, buflen);
+		get_device_address(next, &buf, buflen);
+
+		if (strlen(buf) > 0)
+			fprintf(fp, "%-6s ", buf);
+		else
+			fprintf(fp, "\t\t");
+
+		get_device_ip6_address(next, &buf, buflen);
 		fprintf(fp, "%s\n", buf);
 
         	readmem(next+net->dev_next, KVADDR, &next, 
@@ -503,7 +519,7 @@ show_net_devices_v2(ulong task)
 	buf = GETBUF(buflen);
 	flen = MAX(VADDR_PRLEN, strlen(net->netdevice));
 
-	fprintf(fp, "%s  NAME   IP ADDRESS(ES)\n",
+	fprintf(fp, "%s  NAME   IP ADDRESS(ES)   INET6 ADDRESS\n",
 		mkstring(upper_case(net->netdevice, buf), 
 			flen, CENTER|LJUST, NULL));
 
@@ -530,7 +546,14 @@ show_net_devices_v2(ulong task)
 		get_device_name(ld->list_ptr[i], buf);
 		fprintf(fp, "%-6s ", buf);
 
-		buflen = get_device_address(ld->list_ptr[i], &buf, buflen);
+		get_device_address(ld->list_ptr[i], &buf, buflen);
+
+		if (strlen(buf) > 0)
+			fprintf(fp, "%-6s ", buf);
+		else
+			fprintf(fp, "\t\t");
+
+		get_device_ip6_address(ld->list_ptr[i], &buf, buflen);
 		fprintf(fp, "%s\n", buf);
 	}
 	
@@ -556,7 +579,7 @@ show_net_devices_v3(ulong task)
 	buf = GETBUF(buflen);
 	flen = MAX(VADDR_PRLEN, strlen(net->netdevice));
 
-	fprintf(fp, "%s  NAME   IP ADDRESS(ES)\n",
+	fprintf(fp, "%s  NAME   IP ADDRESS(ES)   INET6 ADDRESS\n",
 		mkstring(upper_case(net->netdevice, buf), 
 			flen, CENTER|LJUST, NULL));
 
@@ -593,7 +616,14 @@ show_net_devices_v3(ulong task)
 		get_device_name(ld->list_ptr[i], buf);
 		fprintf(fp, "%-6s ", buf);
 
-		buflen = get_device_address(ld->list_ptr[i], &buf, buflen);
+		get_device_address(ld->list_ptr[i], &buf, buflen);
+
+		if (strlen(buf) > 0)
+			fprintf(fp, "%-6s ", buf);
+		else
+			fprintf(fp, "\t\t");
+
+		get_device_ip6_address(ld->list_ptr[i], &buf, buflen);
 		fprintf(fp, "%s\n", buf);
 	}
 	
@@ -925,6 +955,87 @@ get_device_address(ulong devaddr, char **bufp, long buflen)
 	return buflen;
 }
 
+static void
+get_device_ip6_address(ulong devaddr, char **bufp, long buflen)
+{
+	ulong ip6_ptr = 0, i, cnt = 0, pos = 0, bufsize = buflen;
+	struct list_data list_data, *ld;
+	struct in6_addr ip6_addr;
+	char *buf;
+	char str[INET6_ADDRSTRLEN + 1] = {0};
+	char buffer[INET6_ADDRSTRLEN + 4] = {0};
+	uint len = 0;
+
+	buf = *bufp;
+	BZERO(buf, buflen);
+
+	readmem(devaddr + net->dev_ip6_ptr, KVADDR,
+		&ip6_ptr, sizeof(ulong), "ip6_ptr", FAULT_ON_ERROR);
+
+	if (!ip6_ptr)
+		return;
+
+	if (MEMBER_TYPE("inet6_dev", "addr_list") == TYPE_CODE_PTR) {
+		ulong addrp = 0;
+		/*
+		 * 502a2ffd7376 ("ipv6: convert idev_list to list macros")
+		 * v2.6.35-rc1~473^2~733
+		 */
+		readmem(ip6_ptr + OFFSET(inet6_dev_addr_list), KVADDR,
+			&addrp, sizeof(void *), "addr_list", FAULT_ON_ERROR);
+
+		while (addrp) {
+			readmem(addrp + OFFSET(in6_addr_in6_u), KVADDR, &ip6_addr,
+				sizeof(struct in6_addr), "in6_addr.in6_u", FAULT_ON_ERROR);
+			inet_ntop(AF_INET6, (void*)&ip6_addr, str, INET6_ADDRSTRLEN);
+			sprintf(buffer, "%s%s", pos ? ", " : "", str);
+			len = strlen(buffer);
+
+			if (pos + len >= bufsize) {
+				RESIZEBUF(*bufp, bufsize, bufsize + buflen);
+				buf = *bufp;
+				BZERO(buf + bufsize, buflen);
+				bufsize += buflen;
+			}
+			BCOPY(buffer, &buf[pos], len);
+			pos += len;
+			readmem(addrp + OFFSET(inet6_ifaddr_if_next), KVADDR, &addrp,
+				sizeof(void *), "inet6_ifaddr.if_next", FAULT_ON_ERROR);
+		}
+
+		return;
+	}
+
+	ld =  &list_data;
+	BZERO(ld, sizeof(struct list_data));
+	ld->flags |= LIST_ALLOCATE;
+	ld->start = ip6_ptr + OFFSET(inet6_dev_addr_list);
+	cnt = do_list(ld);
+
+	for (i = 1; i < cnt; i++) {
+		ulong addr;
+
+		addr = ld->list_ptr[i] + OFFSET(inet6_ifaddr_addr);
+		addr -= OFFSET(inet6_ifaddr_if_list);
+		readmem(addr + OFFSET(in6_addr_in6_u), KVADDR, &ip6_addr,
+			sizeof(struct in6_addr), "in6_addr.in6_u", FAULT_ON_ERROR);
+
+		inet_ntop(AF_INET6, (void*)&ip6_addr, str, INET6_ADDRSTRLEN);
+		sprintf(buffer, "%s%s", pos ? ", " : "", str);
+		len = strlen(buffer);
+
+		if (pos + len >= bufsize) {
+			RESIZEBUF(*bufp, bufsize, bufsize + buflen);
+			buf = *bufp;
+			BZERO(buf + bufsize, buflen);
+			bufsize += buflen;
+		}
+		BCOPY(buffer, &buf[pos], len);
+		pos += len;
+	}
+
+	FREEBUF(ld->list_ptr);
+}
 /*
  *  Get the family, type, local and destination address/port pairs.
  */
diff --git a/symbols.c b/symbols.c
index a974fc9141a0..c8bdeb841cdc 100644
--- a/symbols.c
+++ b/symbols.c
@@ -9787,6 +9787,18 @@ dump_offset_table(char *spec, ulong makestruct)
         	OFFSET(net_device_addr_len));
 	fprintf(fp, "             net_device_ip_ptr: %ld\n",
         	OFFSET(net_device_ip_ptr));
+	fprintf(fp, "            net_device_ip6_ptr: %ld\n",
+		OFFSET(net_device_ip6_ptr));
+	fprintf(fp, "           inet6_dev_addr_list: %ld\n",
+		OFFSET(inet6_dev_addr_list));
+	fprintf(fp, "             inet6_ifaddr_addr: %ld\n",
+		OFFSET(inet6_ifaddr_addr));
+	fprintf(fp, "          inet6_ifaddr_if_list: %ld\n",
+		OFFSET(inet6_ifaddr_if_list));
+	fprintf(fp, "          inet6_ifaddr_if_next: %ld\n",
+		OFFSET(inet6_ifaddr_if_next));
+	fprintf(fp, "                in6_addr_in6_u: %ld\n",
+		OFFSET(in6_addr_in6_u));
 	fprintf(fp, "           net_device_dev_list: %ld\n",
 		OFFSET(net_device_dev_list));
 	fprintf(fp, "             net_dev_base_head: %ld\n",
-- 
2.37.1

--
Crash-utility mailing list
Crash-utility@xxxxxxxxxx
https://listman.redhat.com/mailman/listinfo/crash-utility
Contribution Guidelines: https://github.com/crash-utility/crash/wiki




[Index of Archives]     [Fedora Development]     [Fedora Desktop]     [Fedora SELinux]     [Yosemite News]     [KDE Users]     [Fedora Tools]

 

Powered by Linux