Hi,
Sorry, please ignore this patch. And I will post v2 with minor modifications later.

Thanks.
Lianbo
On Mon, Feb 27, 2023 at 8:10 PM Lianbo Jiang <lijiang@redhat.com> wrote:
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@redhat.com>
Signed-off-by: Lianbo Jiang <lijiang@redhat.com>
---
 defs.h    |   6 +++
 net.c     | 119 ++++++++++++++++++++++++++++++++++++++++++++++++++++--
 symbols.c |  12 ++++++
 3 files changed, 133 insertions(+), 4 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..5da2042d83ad 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));

@@ -478,6 +487,13 @@ show_net_devices(ulong task)
                fprintf(fp, "%-6s ", 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));

@@ -531,6 +547,13 @@ show_net_devices_v2(ulong task)
                fprintf(fp, "%-6s ", 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