Blame net.c

Packit bf408e
/* net.c - core analysis suite
Packit bf408e
 *
Packit bf408e
 * Copyright (C) 1999, 2000, 2001, 2002 Mission Critical Linux, Inc.
Packit bf408e
 * Copyright (C) 2002-2016 David Anderson
Packit bf408e
 * Copyright (C) 2002-2016 Red Hat, Inc. All rights reserved.
Packit bf408e
 *
Packit bf408e
 * This program is free software; you can redistribute it and/or modify
Packit bf408e
 * it under the terms of the GNU General Public License as published by
Packit bf408e
 * the Free Software Foundation; either version 2 of the License, or
Packit bf408e
 * (at your option) any later version.
Packit bf408e
 *
Packit bf408e
 * This program is distributed in the hope that it will be useful,
Packit bf408e
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit bf408e
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
Packit bf408e
 * GNU General Public License for more details.
Packit bf408e
 */
Packit bf408e
Packit bf408e
#include "defs.h"
Packit bf408e
#include <netinet/in.h>
Packit bf408e
#include <netdb.h>
Packit bf408e
#include <net/if_arp.h>
Packit bf408e
#include <arpa/inet.h>
Packit bf408e
Packit bf408e
/*
Packit bf408e
 *  Cache values we need that can change based on OS version, or any other
Packit bf408e
 *  variables static to this file.  These are setup in net_init().  Dump 
Packit bf408e
 *  the table during runtime via "help -n".
Packit bf408e
 */
Packit bf408e
struct net_table {
Packit bf408e
	ulong flags;
Packit bf408e
        char *netdevice;    /* name of net device */
Packit bf408e
	char *dev_name_t;   /* readmem ID's */
Packit bf408e
        char *dev_type_t;
Packit bf408e
	char *dev_addr_t;
Packit bf408e
	long dev_name;
Packit bf408e
	long dev_next;
Packit bf408e
	long dev_type;
Packit bf408e
	long dev_addr_len;
Packit bf408e
	long dev_ip_ptr;
Packit bf408e
	long in_device_ifa_list;
Packit bf408e
	long in_ifaddr_ifa_next;
Packit bf408e
	long in_ifaddr_ifa_address;
Packit bf408e
	int net_device_name_index;
Packit bf408e
} net_table = { 0 };
Packit bf408e
Packit bf408e
struct net_table *net = &net_table;
Packit bf408e
Packit bf408e
#define NETDEV_INIT       (0x1)
Packit bf408e
#define STRUCT_DEVICE     (0x2)
Packit bf408e
#define STRUCT_NET_DEVICE (0x4)
Packit bf408e
#define SOCK_V1           (0x8)
Packit bf408e
#define SOCK_V2           (0x10)
Packit bf408e
#define NO_INET_SOCK      (0x20)
Packit bf408e
Packit bf408e
#define	DEV_NAME_MAX	100
Packit bf408e
struct devinfo {
Packit bf408e
	char		dev_name[DEV_NAME_MAX];
Packit bf408e
	unsigned char	dev_addr_len;
Packit bf408e
	short		dev_type;
Packit bf408e
};
Packit bf408e
Packit bf408e
#define BYTES_IP_ADDR	15	/* bytes to print IP addr (xxx.xxx.xxx.xxx) */
Packit bf408e
#define BYTES_PORT_NUM	5	/* bytes to print port number */
Packit bf408e
/* bytes needed for <ip address>:<port> notation */
Packit bf408e
#define BYTES_IP_TUPLE	(BYTES_IP_ADDR + BYTES_PORT_NUM + 1)
Packit bf408e
Packit bf408e
static void show_net_devices(ulong);
Packit bf408e
static void show_net_devices_v2(ulong);
Packit bf408e
static void show_net_devices_v3(ulong);
Packit bf408e
static void print_neighbour_q(ulong, int);
Packit bf408e
static void get_netdev_info(ulong, struct devinfo *);
Packit bf408e
static void get_device_name(ulong, char *);
Packit bf408e
static long get_device_address(ulong, char **, long);
Packit bf408e
static void get_sock_info(ulong, char *);
Packit bf408e
static void dump_arp(void);
Packit bf408e
static void arp_state_to_flags(unsigned char);
Packit bf408e
static void dump_ether_hw(unsigned char *, int);
Packit bf408e
static void dump_sockets(ulong, struct reference *);
Packit bf408e
static int  sym_socket_dump(ulong, int, int, ulong, struct reference *);
Packit bf408e
static void dump_hw_addr(unsigned char *, int);
Packit bf408e
static char *dump_in6_addr_port(uint16_t *, uint16_t, char *, int *);
Packit bf408e
Packit bf408e
Packit bf408e
#define MK_TYPE_T(f,s,m)						\
Packit bf408e
do {									\
Packit bf408e
	(f) = malloc(strlen(s) + strlen(m) + 2);			\
Packit bf408e
	if ((f) == NULL) {						\
Packit bf408e
		error(WARNING, "malloc fail for type %s.%s", (s), (m));	\
Packit bf408e
	} else {							\
Packit bf408e
		sprintf((f), "%s %s", (s), (m));			\
Packit bf408e
	}								\
Packit bf408e
} while(0)
Packit bf408e
Packit bf408e
void
Packit bf408e
net_init(void)
Packit bf408e
{
Packit bf408e
	/*
Packit bf408e
	 * Note the order of the following checks.  The device struct was
Packit bf408e
	 * renamed to net_device in 2.3, but there may be another struct
Packit bf408e
	 * called 'device' so we check for the new one first.
Packit bf408e
	 */
Packit bf408e
	STRUCT_SIZE_INIT(net_device, "net_device");
Packit bf408e
Packit bf408e
	if (VALID_STRUCT(net_device)) {
Packit bf408e
		net->netdevice = "net_device";
Packit bf408e
		net->dev_next = MEMBER_OFFSET_INIT(net_device_next,
Packit bf408e
			"net_device", "next");
Packit bf408e
		net->dev_name = MEMBER_OFFSET_INIT(net_device_name, 
Packit bf408e
			"net_device", "name");
Packit bf408e
		net->dev_type = MEMBER_OFFSET_INIT(net_device_type,
Packit bf408e
			"net_device", "type");
Packit bf408e
                net->dev_addr_len = MEMBER_OFFSET_INIT(net_device_addr_len,
Packit bf408e
			"net_device", "addr_len");
Packit bf408e
		net->dev_ip_ptr = MEMBER_OFFSET_INIT(net_device_ip_ptr,
Packit bf408e
			"net_device", "ip_ptr");
Packit bf408e
		MEMBER_OFFSET_INIT(net_device_dev_list, "net_device", "dev_list");
Packit bf408e
		MEMBER_OFFSET_INIT(net_dev_base_head, "net", "dev_base_head");
Packit bf408e
		ARRAY_LENGTH_INIT(net->net_device_name_index,
Packit bf408e
			net_device_name, "net_device.name", NULL, sizeof(char));
Packit bf408e
		net->flags |= (NETDEV_INIT|STRUCT_NET_DEVICE);
Packit bf408e
	} else {
Packit bf408e
		STRUCT_SIZE_INIT(device, "device");
Packit bf408e
		if (VALID_STRUCT(device)) {
Packit bf408e
			net->netdevice = "device";
Packit bf408e
			net->dev_next = MEMBER_OFFSET_INIT(device_next, 
Packit bf408e
				"device", "next");
Packit bf408e
			net->dev_name = MEMBER_OFFSET_INIT(device_name, 
Packit bf408e
				"device", "name");
Packit bf408e
	                net->dev_type = MEMBER_OFFSET_INIT(device_type, 
Packit bf408e
				"device", "type");
Packit bf408e
			net->dev_ip_ptr = MEMBER_OFFSET_INIT(device_ip_ptr, 
Packit bf408e
				"device", "ip_ptr");
Packit bf408e
	                net->dev_addr_len = MEMBER_OFFSET_INIT(device_addr_len, 
Packit bf408e
				"device", "addr_len");
Packit bf408e
			net->flags |= (NETDEV_INIT|STRUCT_DEVICE);
Packit bf408e
		} else 
Packit bf408e
			error(WARNING, 
Packit bf408e
				"net_init: unknown device type for net device");
Packit bf408e
	}
Packit bf408e
	if (VALID_MEMBER(task_struct_nsproxy))
Packit bf408e
		MEMBER_OFFSET_INIT(nsproxy_net_ns, "nsproxy", "net_ns");
Packit bf408e
Packit bf408e
	if (net->flags & NETDEV_INIT) {
Packit bf408e
		MK_TYPE_T(net->dev_name_t, net->netdevice, "name");
Packit bf408e
		MK_TYPE_T(net->dev_type_t, net->netdevice, "type");
Packit bf408e
		MK_TYPE_T(net->dev_addr_t, net->netdevice, "addr_len");
Packit bf408e
Packit bf408e
		MEMBER_OFFSET_INIT(socket_sk, "socket", "sk");
Packit bf408e
		MEMBER_OFFSET_INIT(neighbour_next, "neighbour", "next");
Packit bf408e
        	MEMBER_OFFSET_INIT(neighbour_primary_key,  
Packit bf408e
			"neighbour", "primary_key");
Packit bf408e
        	MEMBER_OFFSET_INIT(neighbour_ha, "neighbour", "ha");
Packit bf408e
        	MEMBER_OFFSET_INIT(neighbour_dev, "neighbour", "dev");
Packit bf408e
        	MEMBER_OFFSET_INIT(neighbour_nud_state,  
Packit bf408e
			"neighbour", "nud_state");
Packit bf408e
		MEMBER_OFFSET_INIT(neigh_table_nht_ptr, "neigh_table", "nht");
Packit bf408e
		if (VALID_MEMBER(neigh_table_nht_ptr)) {
Packit bf408e
			MEMBER_OFFSET_INIT(neigh_table_hash_mask,
Packit bf408e
				"neigh_hash_table", "hash_mask");
Packit bf408e
			MEMBER_OFFSET_INIT(neigh_table_hash_shift,
Packit bf408e
				"neigh_hash_table", "hash_shift");
Packit bf408e
			MEMBER_OFFSET_INIT(neigh_table_hash_buckets,
Packit bf408e
				"neigh_hash_table", "hash_buckets");
Packit bf408e
		} else {
Packit bf408e
			MEMBER_OFFSET_INIT(neigh_table_hash_buckets,
Packit bf408e
				"neigh_table", "hash_buckets");
Packit bf408e
			MEMBER_OFFSET_INIT(neigh_table_hash_mask,
Packit bf408e
				"neigh_table", "hash_mask");
Packit bf408e
		}
Packit bf408e
		MEMBER_OFFSET_INIT(neigh_table_key_len,
Packit bf408e
			"neigh_table", "key_len");
Packit bf408e
Packit bf408e
        	MEMBER_OFFSET_INIT(in_device_ifa_list,  
Packit bf408e
			"in_device", "ifa_list");
Packit bf408e
        	MEMBER_OFFSET_INIT(in_ifaddr_ifa_next,  
Packit bf408e
			"in_ifaddr", "ifa_next");
Packit bf408e
        	MEMBER_OFFSET_INIT(in_ifaddr_ifa_address, 
Packit bf408e
			"in_ifaddr", "ifa_address");
Packit bf408e
Packit bf408e
		STRUCT_SIZE_INIT(sock, "sock");
Packit bf408e
Packit bf408e
                MEMBER_OFFSET_INIT(sock_family, "sock", "family");
Packit bf408e
		if (VALID_MEMBER(sock_family)) {
Packit bf408e
                	MEMBER_OFFSET_INIT(sock_daddr, "sock", "daddr");
Packit bf408e
                	MEMBER_OFFSET_INIT(sock_rcv_saddr, "sock", "rcv_saddr");
Packit bf408e
                	MEMBER_OFFSET_INIT(sock_dport, "sock", "dport");
Packit bf408e
                	MEMBER_OFFSET_INIT(sock_sport, "sock", "sport");
Packit bf408e
                	MEMBER_OFFSET_INIT(sock_num, "sock", "num");
Packit bf408e
                	MEMBER_OFFSET_INIT(sock_type, "sock", "type");
Packit bf408e
			net->flags |= SOCK_V1;
Packit bf408e
Packit bf408e
		} else {
Packit bf408e
			/*
Packit bf408e
			 * struct sock {
Packit bf408e
        		 *	struct sock_common      __sk_common;
Packit bf408e
			 * #define sk_family __sk_common.skc_family
Packit bf408e
			 *      ...
Packit bf408e
			 */
Packit bf408e
			MEMBER_OFFSET_INIT(sock_common_skc_family,
Packit bf408e
				"sock_common", "skc_family");
Packit bf408e
			MEMBER_OFFSET_INIT(sock_sk_type, "sock", "sk_type");
Packit bf408e
			/*
Packit bf408e
			 *  struct inet_sock {
Packit bf408e
        		 *	struct sock       sk;
Packit bf408e
        		 *	struct ipv6_pinfo *pinet6;
Packit bf408e
        		 *	struct inet_opt   inet;
Packit bf408e
			 *  };
Packit bf408e
			 */
Packit bf408e
			STRUCT_SIZE_INIT(inet_sock, "inet_sock");
Packit bf408e
			STRUCT_SIZE_INIT(socket, "socket");
Packit bf408e
Packit bf408e
			if (STRUCT_EXISTS("inet_opt")) {
Packit bf408e
				MEMBER_OFFSET_INIT(inet_sock_inet, "inet_sock", "inet");
Packit bf408e
				MEMBER_OFFSET_INIT(inet_opt_daddr, "inet_opt", "daddr");
Packit bf408e
				MEMBER_OFFSET_INIT(inet_opt_rcv_saddr, "inet_opt", "rcv_saddr");
Packit bf408e
				MEMBER_OFFSET_INIT(inet_opt_dport, "inet_opt", "dport");
Packit bf408e
				MEMBER_OFFSET_INIT(inet_opt_sport, "inet_opt", "sport");
Packit bf408e
				MEMBER_OFFSET_INIT(inet_opt_num, "inet_opt", "num");
Packit bf408e
			} else {	/* inet_opt moved to inet_sock */
Packit bf408e
				ASSIGN_OFFSET(inet_sock_inet) = 0;
Packit bf408e
				if (MEMBER_EXISTS("inet_sock", "daddr")) {
Packit bf408e
					MEMBER_OFFSET_INIT(inet_opt_daddr, "inet_sock", "daddr");
Packit bf408e
					MEMBER_OFFSET_INIT(inet_opt_rcv_saddr, "inet_sock", "rcv_saddr");
Packit bf408e
					MEMBER_OFFSET_INIT(inet_opt_dport, "inet_sock", "dport");
Packit bf408e
					MEMBER_OFFSET_INIT(inet_opt_sport, "inet_sock", "sport");
Packit bf408e
					MEMBER_OFFSET_INIT(inet_opt_num, "inet_sock", "num");
Packit bf408e
				} else if (MEMBER_EXISTS("inet_sock", "inet_daddr")) {
Packit bf408e
					MEMBER_OFFSET_INIT(inet_opt_daddr, "inet_sock", "inet_daddr");
Packit bf408e
					MEMBER_OFFSET_INIT(inet_opt_rcv_saddr, "inet_sock", "inet_rcv_saddr");
Packit bf408e
					MEMBER_OFFSET_INIT(inet_opt_dport, "inet_sock", "inet_dport");
Packit bf408e
					MEMBER_OFFSET_INIT(inet_opt_sport, "inet_sock", "inet_sport");
Packit bf408e
					MEMBER_OFFSET_INIT(inet_opt_num, "inet_sock", "inet_num");
Packit bf408e
				} else if ((MEMBER_OFFSET("inet_sock", "sk") == 0) &&
Packit bf408e
				    (MEMBER_OFFSET("sock", "__sk_common") == 0)) {
Packit bf408e
					MEMBER_OFFSET_INIT(inet_opt_daddr, "sock_common", "skc_daddr");
Packit bf408e
					if (INVALID_MEMBER(inet_opt_daddr))
Packit bf408e
						ANON_MEMBER_OFFSET_INIT(inet_opt_daddr, "sock_common", 
Packit bf408e
							"skc_daddr");
Packit bf408e
					MEMBER_OFFSET_INIT(inet_opt_rcv_saddr, "sock_common", "skc_rcv_saddr");
Packit bf408e
					if (INVALID_MEMBER(inet_opt_rcv_saddr))
Packit bf408e
						ANON_MEMBER_OFFSET_INIT(inet_opt_rcv_saddr, "sock_common",
Packit bf408e
							"skc_rcv_saddr");
Packit bf408e
					MEMBER_OFFSET_INIT(inet_opt_dport, "inet_sock", "inet_dport");
Packit bf408e
					if (INVALID_MEMBER(inet_opt_dport)) {
Packit bf408e
						MEMBER_OFFSET_INIT(inet_opt_dport, "sock_common", 
Packit bf408e
							"skc_dport");
Packit bf408e
						if (INVALID_MEMBER(inet_opt_dport))
Packit bf408e
							ANON_MEMBER_OFFSET_INIT(inet_opt_dport, "sock_common", 
Packit bf408e
								"skc_dport");
Packit bf408e
					}
Packit bf408e
					MEMBER_OFFSET_INIT(inet_opt_sport, "inet_sock", "inet_sport");
Packit bf408e
					MEMBER_OFFSET_INIT(inet_opt_num, "inet_sock", "inet_num");
Packit bf408e
					if (INVALID_MEMBER(inet_opt_num)) {
Packit bf408e
						MEMBER_OFFSET_INIT(inet_opt_num, "sock_common", "skc_num");
Packit bf408e
						if (INVALID_MEMBER(inet_opt_num))
Packit bf408e
							ANON_MEMBER_OFFSET_INIT(inet_opt_num, "sock_common", 
Packit bf408e
							"skc_num");
Packit bf408e
					}
Packit bf408e
				}
Packit bf408e
			}	
Packit bf408e
Packit bf408e
			if (VALID_STRUCT(inet_sock) && 
Packit bf408e
			    INVALID_MEMBER(inet_sock_inet)) {
Packit bf408e
				/*
Packit bf408e
				 *  gdb can't seem to figure out the inet_sock
Packit bf408e
				 *  in later 2.6 kernels, returning this:
Packit bf408e
				 *
Packit bf408e
				 *  struct inet_sock {
Packit bf408e
				 *      <no data fields>
Packit bf408e
			         *  }
Packit bf408e
				 *  
Packit bf408e
				 *  It does know the struct size, so kludge it
Packit bf408e
			         *  to subtract the size of the inet_opt struct
Packit bf408e
				 *  from the size of the containing inet_sock.
Packit bf408e
				 */
Packit bf408e
				net->flags |= NO_INET_SOCK;
Packit bf408e
				ASSIGN_OFFSET(inet_sock_inet) = 
Packit bf408e
				    SIZE(inet_sock) - STRUCT_SIZE("inet_opt");
Packit bf408e
			}
Packit bf408e
Packit bf408e
			/* 
Packit bf408e
			 *  If necessary, set inet_sock size and inet_sock_inet offset,
Packit bf408e
			 *  accounting for the configuration-dependent, intervening,
Packit bf408e
			 *  struct ipv6_pinfo pointer located in between the sock and 
Packit bf408e
			 *  inet_opt members of the inet_sock.
Packit bf408e
			 */
Packit bf408e
			if (!VALID_STRUCT(inet_sock)) 
Packit bf408e
			{
Packit bf408e
				if (symbol_exists("tcpv6_protocol") && 
Packit bf408e
				    symbol_exists("udpv6_protocol")) {
Packit bf408e
					ASSIGN_SIZE(inet_sock) = SIZE(sock) + 
Packit bf408e
						sizeof(void *) + STRUCT_SIZE("inet_opt");
Packit bf408e
					ASSIGN_OFFSET(inet_sock_inet) = SIZE(sock) + 
Packit bf408e
						sizeof(void *);
Packit bf408e
				} else {
Packit bf408e
					ASSIGN_SIZE(inet_sock) = SIZE(sock) + 
Packit bf408e
						STRUCT_SIZE("inet_opt");
Packit bf408e
					ASSIGN_OFFSET(inet_sock_inet) = SIZE(sock);
Packit bf408e
				}
Packit bf408e
			}
Packit bf408e
Packit bf408e
			MEMBER_OFFSET_INIT(ipv6_pinfo_rcv_saddr, "ipv6_pinfo", "rcv_saddr");
Packit bf408e
			MEMBER_OFFSET_INIT(ipv6_pinfo_daddr, "ipv6_pinfo", "daddr");
Packit bf408e
			STRUCT_SIZE_INIT(in6_addr, "in6_addr");
Packit bf408e
			MEMBER_OFFSET_INIT(socket_alloc_vfs_inode, "socket_alloc", "vfs_inode");
Packit bf408e
Packit bf408e
			net->flags |= SOCK_V2;
Packit bf408e
		}
Packit bf408e
	}	
Packit bf408e
}
Packit bf408e
Packit bf408e
/*
Packit bf408e
 * The net command...
Packit bf408e
 */
Packit bf408e
Packit bf408e
#define NETOPTS	  "N:asSR:xdn"
Packit bf408e
#define s_FLAG FOREACH_s_FLAG
Packit bf408e
#define S_FLAG FOREACH_S_FLAG
Packit bf408e
#define x_FLAG FOREACH_x_FLAG
Packit bf408e
#define d_FLAG FOREACH_d_FLAG
Packit bf408e
Packit bf408e
#define NET_REF_FOUND             (0x1)
Packit bf408e
#define NET_REF_HEXNUM            (0x2)
Packit bf408e
#define NET_REF_DECNUM            (0x4)
Packit bf408e
#define NET_TASK_HEADER_PRINTED   (0x8)
Packit bf408e
#define NET_SOCK_HEADER_PRINTED  (0x10)
Packit bf408e
#define NET_REF_FOUND_ITEM       (0x20)
Packit bf408e
Packit bf408e
#define NET_REFERENCE_CHECK(X)   (X)
Packit bf408e
#define NET_REFERENCE_FOUND(X)   ((X) && ((X)->cmdflags & NET_REF_FOUND))
Packit bf408e
Packit bf408e
void
Packit bf408e
cmd_net(void)
Packit bf408e
{
Packit bf408e
	int c;
Packit bf408e
	ulong sflag, nflag, aflag;
Packit bf408e
	ulong value;
Packit bf408e
	ulong task;
Packit bf408e
	struct task_context *tc = NULL;
Packit bf408e
	struct in_addr in_addr;
Packit bf408e
	struct reference reference, *ref;
Packit bf408e
Packit bf408e
	if (!(net->flags & NETDEV_INIT)) 
Packit bf408e
		error(FATAL, "net subsystem not initialized!");
Packit bf408e
Packit bf408e
	ref = NULL;
Packit bf408e
	sflag = nflag = aflag = 0;
Packit bf408e
	task = pid_to_task(0);
Packit bf408e
Packit bf408e
	while ((c = getopt(argcnt, args, NETOPTS)) != EOF) {
Packit bf408e
		switch (c) {
Packit bf408e
		case 'R':
Packit bf408e
			if (ref)
Packit bf408e
				error(INFO, "only one -R option allowed\n");
Packit bf408e
			else {
Packit bf408e
				ref = &reference;
Packit bf408e
				BZERO(ref, sizeof(struct reference));
Packit bf408e
				ref->str = optarg;
Packit bf408e
			}
Packit bf408e
			break;
Packit bf408e
Packit bf408e
		case 'a':
Packit bf408e
			dump_arp();
Packit bf408e
			aflag++;
Packit bf408e
			break;
Packit bf408e
Packit bf408e
		case 'N':
Packit bf408e
			value = stol(optarg, FAULT_ON_ERROR, NULL);
Packit bf408e
			in_addr.s_addr = (in_addr_t)value;
Packit bf408e
			fprintf(fp, "%s\n", inet_ntoa(in_addr));
Packit bf408e
			return;
Packit bf408e
Packit bf408e
		case 's':
Packit bf408e
			if (sflag & S_FLAG)
Packit bf408e
				error(INFO, 
Packit bf408e
				    "only one -s or -S option allowed\n");
Packit bf408e
			else
Packit bf408e
				sflag |= s_FLAG;
Packit bf408e
		        break;
Packit bf408e
Packit bf408e
		case 'S':
Packit bf408e
			if (sflag & s_FLAG)
Packit bf408e
				error(INFO, 
Packit bf408e
				    "only one -s or -S option allowed\n");
Packit bf408e
			else
Packit bf408e
				sflag |= S_FLAG;
Packit bf408e
            		break;
Packit bf408e
Packit bf408e
		case 'x':
Packit bf408e
			if (sflag & d_FLAG)
Packit bf408e
				error(FATAL,
Packit bf408e
					"-d and -x are mutually exclusive\n");
Packit bf408e
			sflag |= x_FLAG;
Packit bf408e
			break;
Packit bf408e
Packit bf408e
		case 'd':
Packit bf408e
			if (sflag & x_FLAG)
Packit bf408e
				error(FATAL,
Packit bf408e
					"-d and -x are mutually exclusive\n");
Packit bf408e
			sflag |= d_FLAG;
Packit bf408e
			break;
Packit bf408e
Packit bf408e
		case 'n':
Packit bf408e
			nflag = 1;
Packit bf408e
			task = CURRENT_TASK();
Packit bf408e
			if (args[optind]) {
Packit bf408e
				switch (str_to_context(args[optind],
Packit bf408e
					 &value, &tc)) {
Packit bf408e
				case STR_PID:
Packit bf408e
				case STR_TASK:
Packit bf408e
					task = tc->task;
Packit bf408e
				}
Packit bf408e
			}
Packit bf408e
			break;
Packit bf408e
Packit bf408e
		default:
Packit bf408e
			argerrs++;
Packit bf408e
			break;
Packit bf408e
		}
Packit bf408e
	}
Packit bf408e
Packit bf408e
	if (argerrs) 
Packit bf408e
		cmd_usage(pc->curcmd, SYNOPSIS);
Packit bf408e
Packit bf408e
	if (sflag & (s_FLAG|S_FLAG))
Packit bf408e
		dump_sockets(sflag, ref);
Packit bf408e
	else {
Packit bf408e
		if ((argcnt == 1) || nflag)
Packit bf408e
			show_net_devices(task);
Packit bf408e
		else if (!aflag)
Packit bf408e
			cmd_usage(pc->curcmd, SYNOPSIS);
Packit bf408e
	}
Packit bf408e
}
Packit bf408e
Packit bf408e
/*
Packit bf408e
 *  Just display the address and name of each net device.
Packit bf408e
 */
Packit bf408e
Packit bf408e
static void
Packit bf408e
show_net_devices(ulong task)
Packit bf408e
{
Packit bf408e
	ulong next;
Packit bf408e
	long flen;
Packit bf408e
	char *buf;
Packit bf408e
	long buflen = BUFSIZE;
Packit bf408e
Packit bf408e
	if (symbol_exists("dev_base_head")) {
Packit bf408e
		show_net_devices_v2(task);
Packit bf408e
		return;
Packit bf408e
	} else if (symbol_exists("init_net")) {
Packit bf408e
		show_net_devices_v3(task);
Packit bf408e
		return;
Packit bf408e
	}
Packit bf408e
Packit bf408e
	if (!symbol_exists("dev_base"))
Packit bf408e
		error(FATAL, "dev_base, dev_base_head or init_net do not exist!\n");
Packit bf408e
Packit bf408e
	get_symbol_data("dev_base", sizeof(void *), &next;;
Packit bf408e
Packit bf408e
	if (!net->netdevice || !next)
Packit bf408e
		return;
Packit bf408e
Packit bf408e
	buf = GETBUF(buflen);
Packit bf408e
	flen = MAX(VADDR_PRLEN, strlen(net->netdevice));
Packit bf408e
Packit bf408e
	fprintf(fp, "%s  NAME   IP ADDRESS(ES)\n",
Packit bf408e
		mkstring(upper_case(net->netdevice, buf), 
Packit bf408e
			flen, CENTER|LJUST, NULL));
Packit bf408e
Packit bf408e
	do {
Packit bf408e
                fprintf(fp, "%s  ", 
Packit bf408e
                    mkstring(buf, flen, CENTER|RJUST|LONG_HEX, MKSTR(next)));
Packit bf408e
Packit bf408e
		get_device_name(next, buf);
Packit bf408e
		fprintf(fp, "%-6s ", buf);
Packit bf408e
Packit bf408e
		buflen = get_device_address(next, &buf, buflen);
Packit bf408e
		fprintf(fp, "%s\n", buf);
Packit bf408e
Packit bf408e
        	readmem(next+net->dev_next, KVADDR, &next, 
Packit bf408e
			sizeof(void *), "(net_)device.next", FAULT_ON_ERROR);
Packit bf408e
	} while (next);
Packit bf408e
Packit bf408e
	FREEBUF(buf);
Packit bf408e
}
Packit bf408e
Packit bf408e
static void
Packit bf408e
show_net_devices_v2(ulong task)
Packit bf408e
{
Packit bf408e
	struct list_data list_data, *ld;
Packit bf408e
	char *net_device_buf;
Packit bf408e
	char *buf;
Packit bf408e
	long buflen = BUFSIZE;
Packit bf408e
	int ndevcnt, i;
Packit bf408e
	long flen;
Packit bf408e
Packit bf408e
	if (!net->netdevice) /* initialized in net_init() */
Packit bf408e
		return;
Packit bf408e
Packit bf408e
	buf = GETBUF(buflen);
Packit bf408e
	flen = MAX(VADDR_PRLEN, strlen(net->netdevice));
Packit bf408e
Packit bf408e
	fprintf(fp, "%s  NAME   IP ADDRESS(ES)\n",
Packit bf408e
		mkstring(upper_case(net->netdevice, buf), 
Packit bf408e
			flen, CENTER|LJUST, NULL));
Packit bf408e
Packit bf408e
	net_device_buf = GETBUF(SIZE(net_device));
Packit bf408e
Packit bf408e
	ld =  &list_data;
Packit bf408e
	BZERO(ld, sizeof(struct list_data));
Packit bf408e
	ld->flags |= LIST_ALLOCATE;
Packit bf408e
	get_symbol_data("dev_base_head", sizeof(void *), &ld->start);
Packit bf408e
	ld->end = symbol_value("dev_base_head");
Packit bf408e
	ld->list_head_offset = OFFSET(net_device_dev_list);
Packit bf408e
Packit bf408e
	ndevcnt = do_list(ld);
Packit bf408e
Packit bf408e
	for (i = 0; i < ndevcnt; ++i) {
Packit bf408e
		readmem(ld->list_ptr[i], KVADDR, net_device_buf,
Packit bf408e
			SIZE(net_device), "net_device buffer",
Packit bf408e
			FAULT_ON_ERROR);
Packit bf408e
Packit bf408e
                fprintf(fp, "%s  ",
Packit bf408e
			mkstring(buf, flen, CENTER|RJUST|LONG_HEX,
Packit bf408e
			MKSTR(ld->list_ptr[i])));
Packit bf408e
Packit bf408e
		get_device_name(ld->list_ptr[i], buf);
Packit bf408e
		fprintf(fp, "%-6s ", buf);
Packit bf408e
Packit bf408e
		buflen = get_device_address(ld->list_ptr[i], &buf, buflen);
Packit bf408e
		fprintf(fp, "%s\n", buf);
Packit bf408e
	}
Packit bf408e
	
Packit bf408e
	FREEBUF(ld->list_ptr);
Packit bf408e
	FREEBUF(net_device_buf);
Packit bf408e
	FREEBUF(buf);
Packit bf408e
}
Packit bf408e
Packit bf408e
static void
Packit bf408e
show_net_devices_v3(ulong task)
Packit bf408e
{
Packit bf408e
	ulong nsproxy_p, net_ns_p;
Packit bf408e
	struct list_data list_data, *ld;
Packit bf408e
	char *net_device_buf;
Packit bf408e
	char *buf;
Packit bf408e
	long buflen = BUFSIZE;
Packit bf408e
	int ndevcnt, i;
Packit bf408e
	long flen;
Packit bf408e
Packit bf408e
	if (!net->netdevice) /* initialized in net_init() */
Packit bf408e
		return;
Packit bf408e
Packit bf408e
	buf = GETBUF(buflen);
Packit bf408e
	flen = MAX(VADDR_PRLEN, strlen(net->netdevice));
Packit bf408e
Packit bf408e
	fprintf(fp, "%s  NAME   IP ADDRESS(ES)\n",
Packit bf408e
		mkstring(upper_case(net->netdevice, buf), 
Packit bf408e
			flen, CENTER|LJUST, NULL));
Packit bf408e
Packit bf408e
	net_device_buf = GETBUF(SIZE(net_device));
Packit bf408e
Packit bf408e
	ld =  &list_data;
Packit bf408e
	BZERO(ld, sizeof(struct list_data));
Packit bf408e
	ld->flags |= LIST_ALLOCATE;
Packit bf408e
	if (VALID_MEMBER(nsproxy_net_ns)) {
Packit bf408e
		readmem(task + OFFSET(task_struct_nsproxy), KVADDR, &nsproxy_p,
Packit bf408e
			sizeof(ulong), "task_struct.nsproxy", FAULT_ON_ERROR);
Packit bf408e
		if (!readmem(nsproxy_p + OFFSET(nsproxy_net_ns), KVADDR, &net_ns_p,
Packit bf408e
			sizeof(ulong), "nsproxy.net_ns", RETURN_ON_ERROR|QUIET))
Packit bf408e
			error(FATAL, "cannot determine net_namespace location!\n");
Packit bf408e
	} else
Packit bf408e
		net_ns_p = symbol_value("init_net");
Packit bf408e
	ld->start = ld->end = net_ns_p + OFFSET(net_dev_base_head);
Packit bf408e
	ld->list_head_offset = OFFSET(net_device_dev_list);
Packit bf408e
Packit bf408e
	ndevcnt = do_list(ld);
Packit bf408e
Packit bf408e
	/*
Packit bf408e
	 *  Skip the first entry (init_net).
Packit bf408e
	 */
Packit bf408e
	for (i = 1; i < ndevcnt; ++i) {
Packit bf408e
		readmem(ld->list_ptr[i], KVADDR, net_device_buf,
Packit bf408e
			SIZE(net_device), "net_device buffer",
Packit bf408e
			FAULT_ON_ERROR);
Packit bf408e
Packit bf408e
                fprintf(fp, "%s  ",
Packit bf408e
			mkstring(buf, flen, CENTER|RJUST|LONG_HEX,
Packit bf408e
			MKSTR(ld->list_ptr[i])));
Packit bf408e
Packit bf408e
		get_device_name(ld->list_ptr[i], buf);
Packit bf408e
		fprintf(fp, "%-6s ", buf);
Packit bf408e
Packit bf408e
		buflen = get_device_address(ld->list_ptr[i], &buf, buflen);
Packit bf408e
		fprintf(fp, "%s\n", buf);
Packit bf408e
	}
Packit bf408e
	
Packit bf408e
	FREEBUF(ld->list_ptr);
Packit bf408e
	FREEBUF(net_device_buf);
Packit bf408e
	FREEBUF(buf);
Packit bf408e
}
Packit bf408e
Packit bf408e
/*
Packit bf408e
 * Perform the actual work of dumping the ARP table...
Packit bf408e
 */
Packit bf408e
#define ARP_HEADING \
Packit bf408e
	"NEIGHBOUR        IP ADDRESS      HW TYPE    HW ADDRESS         DEVICE  STATE"
Packit bf408e
Packit bf408e
static void
Packit bf408e
dump_arp(void)
Packit bf408e
{
Packit bf408e
	ulong	arp_tbl;		/* address of arp_tbl */
Packit bf408e
	ulong	*hash_buckets;
Packit bf408e
	ulong	hash;
Packit bf408e
	long	hash_bytes;
Packit bf408e
	int	nhash_buckets = 0;
Packit bf408e
	int	key_len;
Packit bf408e
	int	i;
Packit bf408e
	int	header_printed = 0;
Packit bf408e
	int	hash_mask = 0;
Packit bf408e
	ulong	nht;
Packit bf408e
Packit bf408e
	if (!symbol_exists("arp_tbl")) 
Packit bf408e
		error(FATAL, "arp_tbl does not exist in this kernel\n");
Packit bf408e
Packit bf408e
	arp_tbl = symbol_value("arp_tbl");
Packit bf408e
Packit bf408e
	/*
Packit bf408e
	 *  NOTE: 2.6.8 -> 2.6.9 neigh_table struct changed from:
Packit bf408e
	 *
Packit bf408e
	 *    struct neighbour *hash_buckets[32];
Packit bf408e
	 *  to
Packit bf408e
	 *    struct neighbour **hash_buckets;
Packit bf408e
	 *
Packit bf408e
	 *  Use 'hash_mask' as indicator to decide if we're dealing
Packit bf408e
	 *  with an array or a pointer.
Packit bf408e
	 *
Packit bf408e
	 * Around 2.6.37 neigh_hash_table struct has been introduced
Packit bf408e
	 * and pointer to it has been added to neigh_table.
Packit bf408e
	 */
Packit bf408e
	if (VALID_MEMBER(neigh_table_nht_ptr)) {
Packit bf408e
		readmem(arp_tbl + OFFSET(neigh_table_nht_ptr),
Packit bf408e
			KVADDR, &nht, sizeof(nht),
Packit bf408e
			"neigh_table nht", FAULT_ON_ERROR);
Packit bf408e
		/* NB! Re-use of offsets like neigh_table_hash_mask
Packit bf408e
		 * with neigh_hash_table structure */
Packit bf408e
		if (VALID_MEMBER(neigh_table_hash_mask)) {
Packit bf408e
			readmem(nht + OFFSET(neigh_table_hash_mask),
Packit bf408e
				KVADDR, &hash_mask, sizeof(hash_mask),
Packit bf408e
				"neigh_hash_table hash_mask", FAULT_ON_ERROR);
Packit bf408e
Packit bf408e
			nhash_buckets = hash_mask + 1;
Packit bf408e
		} else if (VALID_MEMBER(neigh_table_hash_shift)) {
Packit bf408e
			readmem(nht + OFFSET(neigh_table_hash_shift),
Packit bf408e
				KVADDR, &hash_mask, sizeof(hash_mask),
Packit bf408e
				"neigh_hash_table hash_shift", FAULT_ON_ERROR);
Packit bf408e
Packit bf408e
			nhash_buckets = 1U << hash_mask;
Packit bf408e
		}
Packit bf408e
	} else if (VALID_MEMBER(neigh_table_hash_mask)) {
Packit bf408e
		readmem(arp_tbl + OFFSET(neigh_table_hash_mask),
Packit bf408e
			KVADDR, &hash_mask, sizeof(hash_mask),
Packit bf408e
			"neigh_table hash_mask", FAULT_ON_ERROR);
Packit bf408e
Packit bf408e
		nhash_buckets = hash_mask + 1;
Packit bf408e
	} else
Packit bf408e
		nhash_buckets = (i = ARRAY_LENGTH(neigh_table_hash_buckets)) ?
Packit bf408e
			i : get_array_length("neigh_table.hash_buckets", 
Packit bf408e
				NULL, sizeof(void *));
Packit bf408e
Packit bf408e
	if (nhash_buckets == 0) {
Packit bf408e
		option_not_supported('a');
Packit bf408e
		return;
Packit bf408e
	}
Packit bf408e
Packit bf408e
	hash_bytes = nhash_buckets * sizeof(*hash_buckets);
Packit bf408e
Packit bf408e
	hash_buckets = (ulong *)GETBUF(hash_bytes);
Packit bf408e
Packit bf408e
	readmem(arp_tbl + OFFSET(neigh_table_key_len),
Packit bf408e
		KVADDR, &key_len, sizeof(key_len),
Packit bf408e
		"neigh_table key_len", FAULT_ON_ERROR);
Packit bf408e
Packit bf408e
	if (VALID_MEMBER(neigh_table_nht_ptr)) {
Packit bf408e
		readmem(nht + OFFSET(neigh_table_hash_buckets),
Packit bf408e
			KVADDR, &hash, sizeof(hash),
Packit bf408e
			"neigh_hash_table hash_buckets ptr", FAULT_ON_ERROR);
Packit bf408e
Packit bf408e
		readmem(hash, KVADDR, hash_buckets, hash_bytes,
Packit bf408e
			"neigh_hash_table hash_buckets", FAULT_ON_ERROR);
Packit bf408e
	} else if (hash_mask) {
Packit bf408e
		readmem(arp_tbl + OFFSET(neigh_table_hash_buckets), 
Packit bf408e
			KVADDR, &hash, sizeof(hash),
Packit bf408e
			"neigh_table hash_buckets pointer", FAULT_ON_ERROR);
Packit bf408e
		
Packit bf408e
		readmem(hash,
Packit bf408e
			KVADDR, hash_buckets, hash_bytes,
Packit bf408e
			"neigh_table hash_buckets", FAULT_ON_ERROR);
Packit bf408e
	} else
Packit bf408e
		readmem(arp_tbl + OFFSET(neigh_table_hash_buckets), 
Packit bf408e
			KVADDR, hash_buckets, hash_bytes,
Packit bf408e
			"neigh_table hash_buckets", FAULT_ON_ERROR);
Packit bf408e
Packit bf408e
	for (i = 0; i < nhash_buckets; i++) {
Packit bf408e
		if (hash_buckets[i] != (ulong)NULL) {
Packit bf408e
			if (!header_printed) {
Packit bf408e
				fprintf(fp, "%s\n", ARP_HEADING);
Packit bf408e
				header_printed = 1;
Packit bf408e
			}
Packit bf408e
			print_neighbour_q(hash_buckets[i], key_len);
Packit bf408e
		}
Packit bf408e
	}
Packit bf408e
Packit bf408e
	fflush(fp);
Packit bf408e
Packit bf408e
	FREEBUF(hash_buckets);
Packit bf408e
}
Packit bf408e
Packit bf408e
/*
Packit bf408e
 * Dump out the relevant information of a neighbour structure for the
Packit bf408e
 * ARP table.
Packit bf408e
 */
Packit bf408e
static void
Packit bf408e
print_neighbour_q(ulong addr, int key_len)
Packit bf408e
{
Packit bf408e
	int i;
Packit bf408e
	ulong	dev;			/* dev address of this struct */
Packit bf408e
	unsigned char *ha_buf;		/* buffer for hardware address */
Packit bf408e
	uint	ha_size;		/* size of HW address */
Packit bf408e
	uint	ipaddr;			/* hold ipaddr (aka primary_key) */
Packit bf408e
	struct devinfo dinfo;
Packit bf408e
	unsigned char state;		/* state of ARP entry */
Packit bf408e
	struct in_addr in_addr;
Packit bf408e
Packit bf408e
	ha_size = (i = ARRAY_LENGTH(neighbour_ha)) ?
Packit bf408e
		i : get_array_length("neighbour.ha", NULL, sizeof(char));
Packit bf408e
	ha_buf = (unsigned char *)GETBUF(ha_size);
Packit bf408e
Packit bf408e
	while (addr) {
Packit bf408e
		readmem(addr + OFFSET(neighbour_primary_key), KVADDR, 
Packit bf408e
			&ipaddr, sizeof(ipaddr), "neighbour primary_key", 
Packit bf408e
			FAULT_ON_ERROR);
Packit bf408e
Packit bf408e
		readmem(addr + OFFSET(neighbour_ha), KVADDR, ha_buf, ha_size,
Packit bf408e
			"neighbour ha", FAULT_ON_ERROR);
Packit bf408e
Packit bf408e
		readmem(addr + OFFSET(neighbour_dev), KVADDR, &dev, sizeof(dev),
Packit bf408e
			"neighbour dev", FAULT_ON_ERROR);
Packit bf408e
		get_netdev_info(dev, &dinfo);
Packit bf408e
Packit bf408e
		readmem(addr + OFFSET(neighbour_nud_state), KVADDR, 
Packit bf408e
			&state, sizeof(state), "neighbour nud_state", 
Packit bf408e
			FAULT_ON_ERROR);
Packit bf408e
Packit bf408e
		in_addr.s_addr = ipaddr;
Packit bf408e
		fprintf(fp, "%-16lx %-16s", addr, inet_ntoa(in_addr));
Packit bf408e
Packit bf408e
		switch (dinfo.dev_type) {
Packit bf408e
		case ARPHRD_ETHER:
Packit bf408e
			/*
Packit bf408e
			 * Use the actual HW address size in the device struct
Packit bf408e
			 * rather than the max size of the array (as was done
Packit bf408e
			 * during the readmem() call above....
Packit bf408e
			 */
Packit bf408e
			fprintf(fp, "%-10s ", "ETHER");
Packit bf408e
			dump_ether_hw(ha_buf, dinfo.dev_addr_len);
Packit bf408e
			break;
Packit bf408e
		case ARPHRD_NETROM:
Packit bf408e
			fprintf(fp, "%-10s ", "NETROM");
Packit bf408e
			dump_hw_addr(ha_buf, dinfo.dev_addr_len);
Packit bf408e
			break;
Packit bf408e
		case ARPHRD_EETHER:
Packit bf408e
			fprintf(fp, "%-10s ", "EETHER");
Packit bf408e
			dump_hw_addr(ha_buf, dinfo.dev_addr_len);
Packit bf408e
			break;
Packit bf408e
		case ARPHRD_AX25:
Packit bf408e
			fprintf(fp, "%-10s ", "AX25");
Packit bf408e
			dump_hw_addr(ha_buf, dinfo.dev_addr_len);
Packit bf408e
			break;
Packit bf408e
		case ARPHRD_PRONET:
Packit bf408e
			fprintf(fp, "%-10s ", "PRONET");
Packit bf408e
			dump_hw_addr(ha_buf, dinfo.dev_addr_len);
Packit bf408e
			break;
Packit bf408e
		case ARPHRD_CHAOS:
Packit bf408e
			fprintf(fp, "%-10s ", "CHAOS");
Packit bf408e
			dump_hw_addr(ha_buf, dinfo.dev_addr_len);
Packit bf408e
			break;
Packit bf408e
		case ARPHRD_IEEE802:
Packit bf408e
			fprintf(fp, "%-10s ", "IEEE802");
Packit bf408e
			dump_hw_addr(ha_buf, dinfo.dev_addr_len);	
Packit bf408e
			break;
Packit bf408e
		case ARPHRD_ARCNET:
Packit bf408e
			fprintf(fp, "%-10s ", "ARCNET");
Packit bf408e
			dump_hw_addr(ha_buf, dinfo.dev_addr_len);
Packit bf408e
			break;
Packit bf408e
		case ARPHRD_APPLETLK:
Packit bf408e
			fprintf(fp, "%-10s ", "APPLETLK");
Packit bf408e
			dump_hw_addr(ha_buf, dinfo.dev_addr_len);
Packit bf408e
			break;
Packit bf408e
		case ARPHRD_DLCI:
Packit bf408e
			fprintf(fp, "%-10s ", "DLCI");
Packit bf408e
			dump_hw_addr(ha_buf, dinfo.dev_addr_len);
Packit bf408e
			break;
Packit bf408e
		case ARPHRD_METRICOM:
Packit bf408e
			fprintf(fp, "%-10s ", "METRICOM");
Packit bf408e
			dump_hw_addr(ha_buf, dinfo.dev_addr_len);
Packit bf408e
			break;
Packit bf408e
		default:
Packit bf408e
			fprintf(fp, "%-10s ", "UNKNOWN");
Packit bf408e
			dump_hw_addr(ha_buf, dinfo.dev_addr_len);
Packit bf408e
			break;
Packit bf408e
		}
Packit bf408e
Packit bf408e
		fprintf(fp, " %-6s  ", dinfo.dev_name);
Packit bf408e
Packit bf408e
		arp_state_to_flags(state);
Packit bf408e
Packit bf408e
		readmem(addr + OFFSET(neighbour_next), KVADDR, 
Packit bf408e
			&addr, sizeof(addr), "neighbour next", FAULT_ON_ERROR);
Packit bf408e
	}
Packit bf408e
Packit bf408e
	FREEBUF(ha_buf);
Packit bf408e
}
Packit bf408e
Packit bf408e
/*
Packit bf408e
 * read netdevice info.... 
Packit bf408e
 */
Packit bf408e
static void
Packit bf408e
get_netdev_info(ulong devaddr, struct devinfo *dip)
Packit bf408e
{
Packit bf408e
	short	dev_type;
Packit bf408e
Packit bf408e
	get_device_name(devaddr, dip->dev_name);
Packit bf408e
Packit bf408e
	readmem(devaddr + net->dev_type, KVADDR, 
Packit bf408e
		&dev_type, sizeof(dev_type), net->dev_type_t, FAULT_ON_ERROR);
Packit bf408e
Packit bf408e
	dip->dev_type = dev_type;
Packit bf408e
Packit bf408e
	readmem(devaddr + net->dev_addr_len, KVADDR,
Packit bf408e
		&dip->dev_addr_len, sizeof(dip->dev_addr_len), net->dev_addr_t,
Packit bf408e
		FAULT_ON_ERROR);
Packit bf408e
}
Packit bf408e
Packit bf408e
/*
Packit bf408e
 *  Get the device name.
Packit bf408e
 */
Packit bf408e
static void
Packit bf408e
get_device_name(ulong devaddr, char *buf)
Packit bf408e
{
Packit bf408e
	ulong	name_addr;
Packit bf408e
Packit bf408e
	switch (net->flags & (STRUCT_DEVICE|STRUCT_NET_DEVICE))
Packit bf408e
	{
Packit bf408e
	case STRUCT_NET_DEVICE:
Packit bf408e
		if (net->net_device_name_index > 0) {
Packit bf408e
                	readmem(devaddr + net->dev_name, KVADDR,
Packit bf408e
                        	buf, net->net_device_name_index, 
Packit bf408e
				net->dev_name_t, FAULT_ON_ERROR);
Packit bf408e
			return;
Packit bf408e
		} 
Packit bf408e
Packit bf408e
		/* fallthrough */
Packit bf408e
Packit bf408e
        case STRUCT_DEVICE:
Packit bf408e
                readmem(devaddr + net->dev_name, KVADDR,
Packit bf408e
                        &name_addr, sizeof(name_addr), net->dev_name_t,
Packit bf408e
                        FAULT_ON_ERROR);
Packit bf408e
                read_string(name_addr, buf, DEV_NAME_MAX);
Packit bf408e
                break;
Packit bf408e
	}
Packit bf408e
}
Packit bf408e
Packit bf408e
/*
Packit bf408e
 *  Get the device address.
Packit bf408e
 *
Packit bf408e
 *  {net_}device->ip_ptr points to in_device.
Packit bf408e
 *  in_device->in_ifaddr points to in_ifaddr list.
Packit bf408e
 *  in_ifaddr->ifa_address contains the address. 
Packit bf408e
 *  in_ifaddr->ifa_next points to the next in_ifaddr in the list (if any).
Packit bf408e
 * 
Packit bf408e
 */
Packit bf408e
static long
Packit bf408e
get_device_address(ulong devaddr, char **bufp, long buflen)
Packit bf408e
{
Packit bf408e
	ulong ip_ptr, ifa_list;
Packit bf408e
	struct in_addr ifa_address;
Packit bf408e
	char *buf;
Packit bf408e
	char buf2[BUFSIZE];
Packit bf408e
	long pos = 0;
Packit bf408e
Packit bf408e
	buf = *bufp;
Packit bf408e
	BZERO(buf, buflen);
Packit bf408e
	BZERO(buf2, BUFSIZE);
Packit bf408e
Packit bf408e
        readmem(devaddr + net->dev_ip_ptr, KVADDR,
Packit bf408e
        	&ip_ptr, sizeof(ulong), "ip_ptr", FAULT_ON_ERROR);
Packit bf408e
Packit bf408e
	if (!ip_ptr)
Packit bf408e
		return buflen;
Packit bf408e
Packit bf408e
        readmem(ip_ptr + OFFSET(in_device_ifa_list), KVADDR,
Packit bf408e
        	&ifa_list, sizeof(ulong), "ifa_list", FAULT_ON_ERROR);
Packit bf408e
Packit bf408e
	while (ifa_list) {
Packit bf408e
        	readmem(ifa_list + OFFSET(in_ifaddr_ifa_address), KVADDR,
Packit bf408e
        		&ifa_address, sizeof(struct in_addr), "ifa_address", 
Packit bf408e
			FAULT_ON_ERROR);
Packit bf408e
Packit bf408e
		sprintf(buf2, "%s%s", pos ? ", " : "", inet_ntoa(ifa_address));
Packit bf408e
		if (pos + strlen(buf2) >= buflen) {
Packit bf408e
			RESIZEBUF(*bufp, buflen, buflen * 2);
Packit bf408e
			buf = *bufp;
Packit bf408e
			BZERO(buf + buflen, buflen);
Packit bf408e
			buflen *= 2;
Packit bf408e
		}
Packit bf408e
		BCOPY(buf2, &buf[pos], strlen(buf2));
Packit bf408e
		pos += strlen(buf2);
Packit bf408e
Packit bf408e
        	readmem(ifa_list + OFFSET(in_ifaddr_ifa_next), KVADDR,
Packit bf408e
        		&ifa_list, sizeof(ulong), "ifa_next", FAULT_ON_ERROR);
Packit bf408e
	}
Packit bf408e
	return buflen;
Packit bf408e
}
Packit bf408e
Packit bf408e
/*
Packit bf408e
 *  Get the family, type, local and destination address/port pairs.
Packit bf408e
 */
Packit bf408e
static void
Packit bf408e
get_sock_info(ulong sock, char *buf)
Packit bf408e
{
Packit bf408e
	uint32_t daddr, rcv_saddr;
Packit bf408e
	uint16_t dport, sport;
Packit bf408e
	ushort family, type;
Packit bf408e
	ushort num ATTRIBUTE_UNUSED;
Packit bf408e
	char *sockbuf, *inet_sockbuf;
Packit bf408e
	ulong ipv6_pinfo, ipv6_rcv_saddr, ipv6_daddr;
Packit bf408e
	uint16_t u6_addr16_src[8];
Packit bf408e
	uint16_t u6_addr16_dest[8];
Packit bf408e
	char buf2[BUFSIZE];
Packit bf408e
	struct in_addr in_addr;
Packit bf408e
	int len;
Packit bf408e
Packit bf408e
	BZERO(buf, BUFSIZE);
Packit bf408e
	BZERO(buf2, BUFSIZE);
Packit bf408e
	sockbuf = inet_sockbuf = NULL;
Packit bf408e
	rcv_saddr = daddr = 0;
Packit bf408e
	dport = sport = 0;
Packit bf408e
	family = type = 0;
Packit bf408e
	ipv6_pinfo = 0;
Packit bf408e
Packit bf408e
	switch (net->flags & (SOCK_V1|SOCK_V2))
Packit bf408e
	{
Packit bf408e
	case SOCK_V1:
Packit bf408e
		sockbuf = GETBUF(SIZE(sock));
Packit bf408e
	        readmem(sock, KVADDR, sockbuf, SIZE(sock), 
Packit bf408e
			"sock buffer", FAULT_ON_ERROR);
Packit bf408e
	
Packit bf408e
		daddr = UINT(sockbuf + OFFSET(sock_daddr));
Packit bf408e
		rcv_saddr = UINT(sockbuf + OFFSET(sock_rcv_saddr));
Packit bf408e
		dport = USHORT(sockbuf + OFFSET(sock_dport));
Packit bf408e
		sport = USHORT(sockbuf + OFFSET(sock_sport));
Packit bf408e
		num = USHORT(sockbuf + OFFSET(sock_num));
Packit bf408e
		family = USHORT(sockbuf + OFFSET(sock_family));
Packit bf408e
		type = USHORT(sockbuf + OFFSET(sock_type));
Packit bf408e
		break;
Packit bf408e
Packit bf408e
	case SOCK_V2:
Packit bf408e
		inet_sockbuf = GETBUF(SIZE(inet_sock));
Packit bf408e
	        readmem(sock, KVADDR, inet_sockbuf, SIZE(inet_sock), 
Packit bf408e
			"inet_sock buffer", FAULT_ON_ERROR);
Packit bf408e
Packit bf408e
		daddr = UINT(inet_sockbuf + OFFSET(inet_sock_inet) +
Packit bf408e
			OFFSET(inet_opt_daddr));
Packit bf408e
		rcv_saddr = UINT(inet_sockbuf + OFFSET(inet_sock_inet) +
Packit bf408e
			OFFSET(inet_opt_rcv_saddr));
Packit bf408e
		dport = USHORT(inet_sockbuf + OFFSET(inet_sock_inet) +
Packit bf408e
			OFFSET(inet_opt_dport));
Packit bf408e
		sport = USHORT(inet_sockbuf + OFFSET(inet_sock_inet) +
Packit bf408e
			OFFSET(inet_opt_sport));
Packit bf408e
		num = USHORT(inet_sockbuf + OFFSET(inet_sock_inet) +
Packit bf408e
			OFFSET(inet_opt_num));
Packit bf408e
		family = USHORT(inet_sockbuf + OFFSET(sock_common_skc_family));
Packit bf408e
		type = USHORT(inet_sockbuf + OFFSET(sock_sk_type));
Packit bf408e
		ipv6_pinfo = ULONG(inet_sockbuf + SIZE(sock));
Packit bf408e
		break;
Packit bf408e
	}
Packit bf408e
Packit bf408e
	switch (family)
Packit bf408e
	{
Packit bf408e
	case AF_UNSPEC:
Packit bf408e
		sprintf(buf, "UNSPEC:"); break;
Packit bf408e
	case AF_UNIX: 
Packit bf408e
		sprintf(buf, "UNIX:"); break;
Packit bf408e
	case AF_INET: 
Packit bf408e
		sprintf(buf, "INET:"); break;
Packit bf408e
	case AF_AX25: 
Packit bf408e
		sprintf(buf, "AX25:"); break;
Packit bf408e
	case AF_IPX:  
Packit bf408e
		sprintf(buf, "IPX:"); break;
Packit bf408e
	case AF_APPLETALK:
Packit bf408e
		sprintf(buf, "APPLETALK:"); break;
Packit bf408e
	case AF_NETROM:
Packit bf408e
		sprintf(buf, "NETROM:"); break;
Packit bf408e
	case AF_BRIDGE:
Packit bf408e
		sprintf(buf, "BRIDGE:"); break;
Packit bf408e
	case AF_ATMPVC:
Packit bf408e
		sprintf(buf, "ATMPVC:"); break;
Packit bf408e
	case AF_X25:  
Packit bf408e
		sprintf(buf, "X25:"); break;
Packit bf408e
	case AF_INET6:
Packit bf408e
		sprintf(buf, "INET6:"); break;
Packit bf408e
	case AF_ROSE: 
Packit bf408e
		sprintf(buf, "ROSE:"); break;
Packit bf408e
	case AF_DECnet:
Packit bf408e
		sprintf(buf, "DECnet:"); break;
Packit bf408e
	case AF_NETBEUI:
Packit bf408e
		sprintf(buf, "NETBEUI:"); break;
Packit bf408e
	case AF_SECURITY: 
Packit bf408e
		sprintf(buf, "SECURITY/KEY:"); break;
Packit bf408e
	case AF_NETLINK: 
Packit bf408e
		sprintf(buf, "NETLINK/ROUTE:"); break;
Packit bf408e
	case AF_PACKET:  
Packit bf408e
		sprintf(buf, "PACKET:"); break;
Packit bf408e
	case AF_ASH:     
Packit bf408e
		sprintf(buf, "ASH:"); break;
Packit bf408e
	case AF_ECONET:  
Packit bf408e
		sprintf(buf, "ECONET:"); break;
Packit bf408e
	case AF_ATMSVC: 
Packit bf408e
		sprintf(buf, "ATMSVC:"); break;
Packit bf408e
	case AF_SNA:    
Packit bf408e
		sprintf(buf, "SNA:"); break;
Packit bf408e
	case AF_IRDA:   
Packit bf408e
		sprintf(buf, "IRDA:"); break;
Packit bf408e
#ifndef AF_PPPOX
Packit bf408e
#define AF_PPPOX 24
Packit bf408e
#endif
Packit bf408e
	case AF_PPPOX:  
Packit bf408e
		sprintf(buf, "PPPOX:"); break;
Packit bf408e
	default:
Packit bf408e
		sprintf(buf, "%d:", family); break;
Packit bf408e
	}
Packit bf408e
Packit bf408e
	switch (type)
Packit bf408e
	{
Packit bf408e
	case SOCK_STREAM:
Packit bf408e
		sprintf(&buf[strlen(buf)], "STREAM"); break;
Packit bf408e
	case SOCK_DGRAM:
Packit bf408e
		sprintf(&buf[strlen(buf)], "DGRAM "); break;
Packit bf408e
	case SOCK_RAW:
Packit bf408e
		sprintf(&buf[strlen(buf)], "RAW"); break;
Packit bf408e
	case SOCK_RDM: 
Packit bf408e
		sprintf(&buf[strlen(buf)], "RDM"); break;
Packit bf408e
	case SOCK_SEQPACKET:
Packit bf408e
		sprintf(&buf[strlen(buf)], "SEQPACKET"); break;
Packit bf408e
	case SOCK_PACKET:
Packit bf408e
		sprintf(&buf[strlen(buf)], "PACKET"); break;
Packit bf408e
	default:
Packit bf408e
		sprintf(&buf[strlen(buf)], "%d", type); break;
Packit bf408e
	}
Packit bf408e
Packit bf408e
	/* make sure we have room at the end... */
Packit bf408e
//	sprintf(&buf[strlen(buf)], "%s", space(MINSPACE-1));
Packit bf408e
	sprintf(&buf[strlen(buf)], " ");
Packit bf408e
           
Packit bf408e
	if (family == AF_INET) {
Packit bf408e
		if (BITS32()) {
Packit bf408e
			in_addr.s_addr = rcv_saddr;
Packit bf408e
			sprintf(&buf[strlen(buf)], "%*s-%-*d%s",
Packit bf408e
				BYTES_IP_ADDR,
Packit bf408e
				inet_ntoa(in_addr),
Packit bf408e
				BYTES_PORT_NUM,
Packit bf408e
				ntohs(sport),
Packit bf408e
				space(1));
Packit bf408e
			in_addr.s_addr = daddr;
Packit bf408e
			sprintf(&buf[strlen(buf)], "%*s-%-*d%s",
Packit bf408e
				BYTES_IP_ADDR,
Packit bf408e
				inet_ntoa(in_addr), 
Packit bf408e
				BYTES_PORT_NUM,
Packit bf408e
				ntohs(dport),
Packit bf408e
				space(1));
Packit bf408e
		} else {
Packit bf408e
			in_addr.s_addr = rcv_saddr;
Packit bf408e
	                sprintf(&buf[strlen(buf)], " %s-%d ",
Packit bf408e
	                        inet_ntoa(in_addr),
Packit bf408e
	                        ntohs(sport));
Packit bf408e
			in_addr.s_addr = daddr;
Packit bf408e
	                sprintf(&buf[strlen(buf)], "%s-%d",
Packit bf408e
	                        inet_ntoa(in_addr),
Packit bf408e
	                        ntohs(dport));
Packit bf408e
		}
Packit bf408e
	}
Packit bf408e
Packit bf408e
	if (sockbuf)
Packit bf408e
		FREEBUF(sockbuf);
Packit bf408e
	if (inet_sockbuf)
Packit bf408e
		FREEBUF(inet_sockbuf);
Packit bf408e
Packit bf408e
	if (family != AF_INET6)
Packit bf408e
		return;
Packit bf408e
Packit bf408e
	switch (net->flags & (SOCK_V1|SOCK_V2))
Packit bf408e
	{
Packit bf408e
	case SOCK_V1:
Packit bf408e
		break;
Packit bf408e
Packit bf408e
	case SOCK_V2:
Packit bf408e
		if (INVALID_MEMBER(ipv6_pinfo_rcv_saddr) ||
Packit bf408e
		    INVALID_MEMBER(ipv6_pinfo_daddr))
Packit bf408e
			break;
Packit bf408e
Packit bf408e
        	ipv6_rcv_saddr = ipv6_pinfo + OFFSET(ipv6_pinfo_rcv_saddr);
Packit bf408e
		ipv6_daddr = ipv6_pinfo + OFFSET(ipv6_pinfo_daddr);
Packit bf408e
Packit bf408e
		if (!readmem(ipv6_rcv_saddr, KVADDR, u6_addr16_src, SIZE(in6_addr),
Packit bf408e
                    "ipv6_rcv_saddr buffer", QUIET|RETURN_ON_ERROR))
Packit bf408e
			break;
Packit bf408e
                if (!readmem(ipv6_daddr, KVADDR, u6_addr16_dest, SIZE(in6_addr),
Packit bf408e
                    "ipv6_daddr buffer", QUIET|RETURN_ON_ERROR))
Packit bf408e
			break;
Packit bf408e
Packit bf408e
		sprintf(&buf[strlen(buf)], "%*s ", BITS32() ? 22 : 12,
Packit bf408e
			dump_in6_addr_port(u6_addr16_src, sport, buf2, &len));
Packit bf408e
		if (BITS32() && (len > 22))
Packit bf408e
			len = 1;
Packit bf408e
		mkstring(dump_in6_addr_port(u6_addr16_dest, dport, buf2, NULL),
Packit bf408e
			len, CENTER, NULL);
Packit bf408e
		sprintf(&buf[strlen(buf)], "%s", buf2);
Packit bf408e
Packit bf408e
		break;
Packit bf408e
	}
Packit bf408e
}
Packit bf408e
Packit bf408e
static char *
Packit bf408e
dump_in6_addr_port(uint16_t *addr, uint16_t port, char *buf, int *len)
Packit bf408e
{
Packit bf408e
	sprintf(buf, "%x:%x:%x:%x:%x:%x:%x:%x-%d",
Packit bf408e
                ntohs(addr[0]),
Packit bf408e
                ntohs(addr[1]),
Packit bf408e
                ntohs(addr[2]),
Packit bf408e
                ntohs(addr[3]),
Packit bf408e
                ntohs(addr[4]),
Packit bf408e
                ntohs(addr[5]),
Packit bf408e
                ntohs(addr[6]),
Packit bf408e
                ntohs(addr[7]),
Packit bf408e
                ntohs(port));
Packit bf408e
Packit bf408e
	if (len)
Packit bf408e
		*len = strlen(buf);
Packit bf408e
Packit bf408e
	return buf;
Packit bf408e
}
Packit bf408e
Packit bf408e
Packit bf408e
/*
Packit bf408e
 *	XXX - copied from neighbour.h !!!!!!
Packit bf408e
 *
Packit bf408e
 *      Neighbor Cache Entry States.
Packit bf408e
 */
Packit bf408e
#define NUD_INCOMPLETE  0x01
Packit bf408e
#define NUD_REACHABLE   0x02
Packit bf408e
#define NUD_STALE       0x04
Packit bf408e
#define NUD_DELAY       0x08
Packit bf408e
#define NUD_PROBE       0x10
Packit bf408e
#define NUD_FAILED      0x20
Packit bf408e
#define NUD_NOARP       0x40
Packit bf408e
#define NUD_PERMANENT   0x80
Packit bf408e
Packit bf408e
#define FLAGBUF_SIZE 100
Packit bf408e
Packit bf408e
#define FILLBUF(s)							\
Packit bf408e
do {									\
Packit bf408e
	char *bp;							\
Packit bf408e
	int blen;							\
Packit bf408e
	blen=strlen(flag_buffer);					\
Packit bf408e
	if ((blen + strlen(s)) < FLAGBUF_SIZE-2) {			\
Packit bf408e
		bp = &flag_buffer[blen];				\
Packit bf408e
		if (blen != 0) {					\
Packit bf408e
			sprintf(bp, "|%s", (s));			\
Packit bf408e
		} else {						\
Packit bf408e
			sprintf(bp, "%s", (s));				\
Packit bf408e
		}							\
Packit bf408e
	}								\
Packit bf408e
} while(0)
Packit bf408e
Packit bf408e
/*
Packit bf408e
 * Take the state of the ARP entry and print it out the flag associated
Packit bf408e
 * with the binary state...
Packit bf408e
 */
Packit bf408e
static void
Packit bf408e
arp_state_to_flags(unsigned char state)
Packit bf408e
{
Packit bf408e
	char flag_buffer[FLAGBUF_SIZE];
Packit bf408e
	int had_flags = 0;
Packit bf408e
Packit bf408e
	if (!state) { 
Packit bf408e
		fprintf(fp, "\n");
Packit bf408e
		return;
Packit bf408e
	}
Packit bf408e
Packit bf408e
	bzero(flag_buffer, FLAGBUF_SIZE);
Packit bf408e
Packit bf408e
	if (state & NUD_INCOMPLETE) {
Packit bf408e
		FILLBUF("INCOMPLETE");
Packit bf408e
		had_flags = 1;
Packit bf408e
	}
Packit bf408e
Packit bf408e
	if (state & NUD_REACHABLE) {
Packit bf408e
		FILLBUF("REACHABLE");
Packit bf408e
		had_flags = 1;
Packit bf408e
	}
Packit bf408e
Packit bf408e
	if (state & NUD_STALE) {
Packit bf408e
		FILLBUF("STALE");
Packit bf408e
		had_flags = 1;
Packit bf408e
	}
Packit bf408e
Packit bf408e
	if (state & NUD_DELAY) {
Packit bf408e
		FILLBUF("DELAY");
Packit bf408e
		had_flags = 1;
Packit bf408e
	}
Packit bf408e
Packit bf408e
	if (state & NUD_PROBE) {
Packit bf408e
		FILLBUF("PROBE");
Packit bf408e
		had_flags = 1;
Packit bf408e
	}
Packit bf408e
Packit bf408e
	if (state & NUD_FAILED) {
Packit bf408e
		FILLBUF("FAILED");
Packit bf408e
		had_flags = 1;
Packit bf408e
	}
Packit bf408e
Packit bf408e
	if (state & NUD_NOARP) {
Packit bf408e
		FILLBUF("NOARP");
Packit bf408e
		had_flags = 1;
Packit bf408e
	}
Packit bf408e
Packit bf408e
	if (state & NUD_PERMANENT) {
Packit bf408e
		FILLBUF("PERMANENT");
Packit bf408e
		had_flags = 1;
Packit bf408e
	}
Packit bf408e
Packit bf408e
	if (had_flags) {
Packit bf408e
		fprintf(fp, "%s\n", flag_buffer);
Packit bf408e
		/* fprintf(fp, "%29.29s%s)\n", " ",  flag_buffer); */
Packit bf408e
	}
Packit bf408e
}
Packit bf408e
Packit bf408e
#undef FILLBUF
Packit bf408e
Packit bf408e
/*
Packit bf408e
 * Print out a formatted ethernet HW address....
Packit bf408e
 */
Packit bf408e
static void
Packit bf408e
dump_ether_hw(unsigned char *ha, int len)
Packit bf408e
{
Packit bf408e
	int i;
Packit bf408e
Packit bf408e
	for (i = 0; i < len; i++) {
Packit bf408e
		char sep = ':';
Packit bf408e
		if (i == (len - 1)) {
Packit bf408e
			sep = ' ';
Packit bf408e
		}
Packit bf408e
		fprintf(fp, "%02x%c", ha[i], sep);
Packit bf408e
	}
Packit bf408e
}
Packit bf408e
Packit bf408e
/*
Packit bf408e
 * Catchall routine for dumping out a HA address whose format we
Packit bf408e
 * don't know about...
Packit bf408e
 */
Packit bf408e
static void
Packit bf408e
dump_hw_addr(unsigned char *ha, int len)
Packit bf408e
{
Packit bf408e
	int i;
Packit bf408e
Packit bf408e
	for (i = 0; i < len; i++) {
Packit bf408e
		fprintf(fp, "%02x ", ha[i]);
Packit bf408e
	}
Packit bf408e
}
Packit bf408e
Packit bf408e
/*
Packit bf408e
 *  help -N output
Packit bf408e
 */
Packit bf408e
void
Packit bf408e
dump_net_table(void)
Packit bf408e
{
Packit bf408e
	int others;
Packit bf408e
Packit bf408e
	others = 0;
Packit bf408e
	fprintf(fp, "              flags: %lx (", net->flags);
Packit bf408e
	if (net->flags & NETDEV_INIT)
Packit bf408e
		fprintf(fp, "%sNETDEV_INIT", others++ ? "|" : "");
Packit bf408e
	if (net->flags & STRUCT_DEVICE)
Packit bf408e
		fprintf(fp, "%sSTRUCT_DEVICE", others++ ? "|" : "");
Packit bf408e
	if (net->flags & STRUCT_NET_DEVICE)
Packit bf408e
		fprintf(fp, "%sSTRUCT_NET_DEVICE", others++ ? "|" : "");
Packit bf408e
	if (net->flags & NO_INET_SOCK)
Packit bf408e
		fprintf(fp, "%sNO_INET_SOCK", others++ ? "|" : "");
Packit bf408e
	if (net->flags & SOCK_V1)
Packit bf408e
		fprintf(fp, "%sSOCK_V1", others++ ? "|" : "");
Packit bf408e
	if (net->flags & SOCK_V2)
Packit bf408e
		fprintf(fp, "%sSOCK_V2", others++ ? "|" : "");
Packit bf408e
	fprintf(fp, ")\n");
Packit bf408e
Packit bf408e
	fprintf(fp, "            netdevice: \"%s\"\n", net->netdevice); 
Packit bf408e
	fprintf(fp, "           dev_name_t: \"%s\"\n", net->dev_name_t);
Packit bf408e
	fprintf(fp, "           dev_type_t: \"%s\"\n", net->dev_type_t);
Packit bf408e
	fprintf(fp, "           dev_addr_t: \"%s\"\n", net->dev_addr_t);
Packit bf408e
        fprintf(fp, "             dev_name: %ld\n", net->dev_name);
Packit bf408e
	fprintf(fp, "             dev_next: %ld\n", net->dev_next);
Packit bf408e
        fprintf(fp, "             dev_type: %ld\n", net->dev_type);
Packit bf408e
        fprintf(fp, "           dev_ip_ptr: %ld\n", net->dev_ip_ptr);
Packit bf408e
        fprintf(fp, "         dev_addr_len: %ld\n", net->dev_addr_len);
Packit bf408e
	fprintf(fp, "net_device_name_index: %d\n", net->net_device_name_index);
Packit bf408e
}
Packit bf408e
Packit bf408e
Packit bf408e
/*
Packit bf408e
 * Dump the open sockets for a given PID.
Packit bf408e
 */
Packit bf408e
static void
Packit bf408e
dump_sockets(ulong flag, struct reference *ref)
Packit bf408e
{
Packit bf408e
    	struct task_context *tc;
Packit bf408e
    	ulong value;
Packit bf408e
    	int subsequent;
Packit bf408e
Packit bf408e
    	if (!args[optind]) { 
Packit bf408e
		if (!NET_REFERENCE_CHECK(ref))
Packit bf408e
            		print_task_header(fp, CURRENT_CONTEXT(), 0);
Packit bf408e
        	dump_sockets_workhorse(CURRENT_TASK(), flag, ref);
Packit bf408e
        	return;
Packit bf408e
    	}
Packit bf408e
Packit bf408e
	subsequent = 0;
Packit bf408e
Packit bf408e
	while (args[optind]) {
Packit bf408e
Packit bf408e
                switch (str_to_context(args[optind], &value, &tc))
Packit bf408e
                {
Packit bf408e
                case STR_PID:
Packit bf408e
                        for (tc = pid_to_context(value); tc; tc = tc->tc_next) {
Packit bf408e
                                if (!NET_REFERENCE_CHECK(ref))
Packit bf408e
                                        print_task_header(fp, tc, subsequent++);
Packit bf408e
                                dump_sockets_workhorse(tc->task, flag, ref);
Packit bf408e
                        }
Packit bf408e
                        break;
Packit bf408e
Packit bf408e
                case STR_TASK:
Packit bf408e
                        if (!NET_REFERENCE_CHECK(ref))
Packit bf408e
                                print_task_header(fp, tc, subsequent++);
Packit bf408e
                        dump_sockets_workhorse(tc->task, flag, ref);
Packit bf408e
                        break;
Packit bf408e
Packit bf408e
                case STR_INVALID:
Packit bf408e
                        error(INFO, "%sinvalid task or pid value: %s\n",
Packit bf408e
				subsequent++ ? "\n" : "", args[optind]);
Packit bf408e
                        break;
Packit bf408e
                }
Packit bf408e
Packit bf408e
		optind++;
Packit bf408e
	}
Packit bf408e
}
Packit bf408e
Packit bf408e
/*
Packit bf408e
 *  Find all sockets in the designated task and call sym_socket_dump()
Packit bf408e
 *  to display them.
Packit bf408e
 */
Packit bf408e
void
Packit bf408e
dump_sockets_workhorse(ulong task, ulong flag, struct reference *ref)
Packit bf408e
{
Packit bf408e
	ulong files_struct_addr = 0, fdtable_addr = 0;
Packit bf408e
	int max_fdset = 0;
Packit bf408e
	int max_fds = 0;
Packit bf408e
	ulong open_fds_addr = 0;
Packit bf408e
	ulong *open_fds;
Packit bf408e
	int open_fds_size;
Packit bf408e
	ulong fd;
Packit bf408e
	ulong file;
Packit bf408e
	int i, j;
Packit bf408e
	int sockets_found = 0;
Packit bf408e
	ulong value;
Packit bf408e
Packit bf408e
       /* 
Packit bf408e
        * Steps to getting open sockets:
Packit bf408e
        *
Packit bf408e
        * 1)  task->files (struct files_struct)
Packit bf408e
        * 2)  files->fd   (struct file **)
Packit bf408e
        * 3)  cycle through from 0 to files->open_fds offset from *fd
Packit bf408e
        *     i.e.    fd[0], fd[1], fd[2]  are pointers to the first three
Packit bf408e
        *     open file descriptors.  Thus, we have:
Packit bf408e
        *         struct file *fd[0], *fd[1], *fd[2],...
Packit bf408e
        *
Packit bf408e
        * 4) file->f_dentry (struct dentry)
Packit bf408e
        * 5) dentry->d_inode (struct inode)
Packit bf408e
        * 6) S_ISSOCK(inode.mode)
Packit bf408e
        *      Assuming it _is_ a socket:
Packit bf408e
        * 7) inode.u (struct socket)   -- offset 0xdc from inode pointer
Packit bf408e
        */
Packit bf408e
Packit bf408e
	readmem(task + OFFSET(task_struct_files), KVADDR, &files_struct_addr,
Packit bf408e
            sizeof(void *), "task files contents", FAULT_ON_ERROR);
Packit bf408e
Packit bf408e
        if (files_struct_addr) {
Packit bf408e
                if (VALID_MEMBER(files_struct_max_fdset)) {
Packit bf408e
		 	readmem(files_struct_addr + OFFSET(files_struct_max_fdset),
Packit bf408e
		          	KVADDR, &max_fdset, sizeof(int),
Packit bf408e
				"files_struct max_fdset", FAULT_ON_ERROR);
Packit bf408e
		      	readmem(files_struct_addr + OFFSET(files_struct_max_fds),
Packit bf408e
        	        	KVADDR, &max_fds, sizeof(int), "files_struct max_fds",
Packit bf408e
                	   	FAULT_ON_ERROR);
Packit bf408e
                }
Packit bf408e
		else if (VALID_MEMBER(files_struct_fdt)) {
Packit bf408e
			readmem(files_struct_addr + OFFSET(files_struct_fdt), KVADDR,
Packit bf408e
				&fdtable_addr, sizeof(void *), "fdtable buffer",
Packit bf408e
				FAULT_ON_ERROR);
Packit bf408e
			if (VALID_MEMBER(fdtable_max_fdset))
Packit bf408e
		      		readmem(fdtable_addr + OFFSET(fdtable_max_fdset),
Packit bf408e
        	         		KVADDR, &max_fdset, sizeof(int),
Packit bf408e
					"fdtable_struct max_fdset", FAULT_ON_ERROR);
Packit bf408e
			else
Packit bf408e
				max_fdset = -1;
Packit bf408e
		      	readmem(fdtable_addr + OFFSET(fdtable_max_fds),
Packit bf408e
	      	            	KVADDR, &max_fds, sizeof(int), "fdtable_struct max_fds",
Packit bf408e
	               	    	FAULT_ON_ERROR);
Packit bf408e
    		}
Packit bf408e
	}
Packit bf408e
Packit bf408e
	if ((VALID_MEMBER(files_struct_fdt) && !fdtable_addr) ||
Packit bf408e
	    !files_struct_addr || (max_fdset == 0) || (max_fds == 0)) {
Packit bf408e
		if (!NET_REFERENCE_CHECK(ref))
Packit bf408e
			fprintf(fp, "No open sockets.\n");
Packit bf408e
		return;
Packit bf408e
	}
Packit bf408e
Packit bf408e
	if (VALID_MEMBER(fdtable_open_fds)){
Packit bf408e
		readmem(fdtable_addr + OFFSET(fdtable_open_fds), KVADDR,
Packit bf408e
     	  		&open_fds_addr, sizeof(void *), "files_struct open_fds addr",
Packit bf408e
	            	FAULT_ON_ERROR);
Packit bf408e
		readmem(fdtable_addr + OFFSET(fdtable_fd), KVADDR, &fd,
Packit bf408e
           		sizeof(void *), "files_struct fd addr", FAULT_ON_ERROR);
Packit bf408e
	} else {
Packit bf408e
		readmem(files_struct_addr + OFFSET(files_struct_open_fds), KVADDR,
Packit bf408e
            		&open_fds_addr, sizeof(void *), "files_struct open_fds addr",
Packit bf408e
	          	FAULT_ON_ERROR);
Packit bf408e
		readmem(files_struct_addr + OFFSET(files_struct_fd), KVADDR, &fd,
Packit bf408e
            		sizeof(void *), "files_struct fd addr", FAULT_ON_ERROR);
Packit bf408e
	}
Packit bf408e
Packit bf408e
	open_fds_size = MAX(max_fdset, max_fds) / BITS_PER_BYTE;
Packit bf408e
	open_fds = (ulong *)GETBUF(open_fds_size);
Packit bf408e
	if (!open_fds)
Packit bf408e
		return;
Packit bf408e
Packit bf408e
	if (open_fds_addr) 
Packit bf408e
		readmem(open_fds_addr, KVADDR, open_fds, open_fds_size,
Packit bf408e
	               	"files_struct open_fds", FAULT_ON_ERROR);
Packit bf408e
    	if (!open_fds_addr || !fd) { 
Packit bf408e
		if (!NET_REFERENCE_CHECK(ref))
Packit bf408e
			fprintf(fp, "No open sockets.\n");
Packit bf408e
		FREEBUF(open_fds);
Packit bf408e
        	return;
Packit bf408e
	}
Packit bf408e
Packit bf408e
	if (NET_REFERENCE_CHECK(ref)) {
Packit bf408e
                if (IS_A_NUMBER(ref->str)) {
Packit bf408e
	                if (hexadecimal_only(ref->str, 0)) {
Packit bf408e
	                        ref->hexval = htol(ref->str,
Packit bf408e
	                        	FAULT_ON_ERROR, NULL);
Packit bf408e
	                        ref->cmdflags |= NET_REF_HEXNUM;
Packit bf408e
	                } else {
Packit bf408e
	                        value = dtol(ref->str, FAULT_ON_ERROR, NULL);
Packit bf408e
	                        if (value <= MAX(max_fdset, max_fds)) {
Packit bf408e
	                                ref->decval = value;
Packit bf408e
	                                ref->cmdflags |= NET_REF_DECNUM;
Packit bf408e
	                        } else {
Packit bf408e
	                                ref->hexval = htol(ref->str,
Packit bf408e
						FAULT_ON_ERROR, NULL);
Packit bf408e
	                                ref->cmdflags |= NET_REF_HEXNUM;
Packit bf408e
	                        }
Packit bf408e
	                }
Packit bf408e
                }
Packit bf408e
		ref->ref1 = task;
Packit bf408e
	}
Packit bf408e
Packit bf408e
    	j = 0;
Packit bf408e
    	for (;;) {
Packit bf408e
	        unsigned long set;
Packit bf408e
	        i = j * BITS_PER_LONG;
Packit bf408e
	        if (((max_fdset >= 0) && (i >= max_fdset)) || (i >= max_fds))
Packit bf408e
	            	break;
Packit bf408e
	        set = open_fds[j++];
Packit bf408e
	        while (set) {
Packit bf408e
	            	if (set & 1) {
Packit bf408e
		                readmem(fd + i*sizeof(struct file *), KVADDR, 
Packit bf408e
		                        &file, sizeof(struct file *), 
Packit bf408e
		                        "fd file", FAULT_ON_ERROR);
Packit bf408e
		                if (file) {
Packit bf408e
		                    	if (sym_socket_dump(file, i, 
Packit bf408e
					    sockets_found, flag, ref)) {
Packit bf408e
		                        	sockets_found++;
Packit bf408e
					}
Packit bf408e
		                }
Packit bf408e
	            	}
Packit bf408e
	            	i++;
Packit bf408e
	            	set >>= 1;
Packit bf408e
	        }
Packit bf408e
        }
Packit bf408e
Packit bf408e
    	if (!sockets_found && !NET_REFERENCE_CHECK(ref))
Packit bf408e
        	fprintf(fp, "No open sockets.\n");
Packit bf408e
Packit bf408e
	if (NET_REFERENCE_FOUND(ref))
Packit bf408e
		fprintf(fp, "\n");
Packit bf408e
Packit bf408e
	FREEBUF(open_fds);
Packit bf408e
}
Packit bf408e
Packit bf408e
Packit bf408e
/*
Packit bf408e
 *  Dump a struct socket symbolically.  Dave makes this _very_ easy.
Packit bf408e
 *
Packit bf408e
 *  Return TRUE if we found a socket, FALSE otherwise.
Packit bf408e
 */
Packit bf408e
Packit bf408e
static char *socket_hdr_32 = 
Packit bf408e
"FD   SOCKET     SOCK    FAMILY:TYPE          SOURCE-PORT      DESTINATION-PORT";
Packit bf408e
static char *socket_hdr_64 = 
Packit bf408e
"FD      SOCKET            SOCK       FAMILY:TYPE SOURCE-PORT DESTINATION-PORT";
Packit bf408e
Packit bf408e
static int
Packit bf408e
sym_socket_dump(ulong file, 
Packit bf408e
		int fd, 
Packit bf408e
		int sockets_found, 
Packit bf408e
		ulong flag,
Packit bf408e
		struct reference *ref)
Packit bf408e
{
Packit bf408e
	uint16_t umode16 = 0;
Packit bf408e
	uint32_t umode32 = 0;
Packit bf408e
    	uint mode = 0;
Packit bf408e
    	ulong dentry = 0, inode = 0,
Packit bf408e
        struct_socket = 0;
Packit bf408e
	ulong sock = 0;
Packit bf408e
	char *file_buf, *dentry_buf, *inode_buf, *socket_buf;
Packit bf408e
	char buf1[BUFSIZE];
Packit bf408e
	char buf2[BUFSIZE];
Packit bf408e
	char *socket_hdr = BITS32() ? socket_hdr_32 : socket_hdr_64;
Packit bf408e
	unsigned int radix;
Packit bf408e
Packit bf408e
	file_buf = fill_file_cache(file);
Packit bf408e
	dentry = ULONG(file_buf + OFFSET(file_f_dentry));
Packit bf408e
Packit bf408e
	if (flag & d_FLAG)
Packit bf408e
		radix = 10;
Packit bf408e
	else if (flag & x_FLAG)
Packit bf408e
		radix = 16;
Packit bf408e
	else
Packit bf408e
		radix = 0;
Packit bf408e
Packit bf408e
    	if (!dentry)
Packit bf408e
        	return FALSE;
Packit bf408e
Packit bf408e
	dentry_buf = fill_dentry_cache(dentry);
Packit bf408e
	inode = ULONG(dentry_buf + OFFSET(dentry_d_inode));
Packit bf408e
Packit bf408e
    	if (!inode)
Packit bf408e
        	return FALSE; 
Packit bf408e
Packit bf408e
	inode_buf = fill_inode_cache(inode);
Packit bf408e
Packit bf408e
Packit bf408e
	switch (SIZE(umode_t))
Packit bf408e
	{
Packit bf408e
	case SIZEOF_32BIT:
Packit bf408e
		umode32 = UINT(inode_buf + OFFSET(inode_i_mode));
Packit bf408e
		break;
Packit bf408e
Packit bf408e
	case SIZEOF_16BIT:
Packit bf408e
		umode16 = USHORT(inode_buf + OFFSET(inode_i_mode));
Packit bf408e
		break;
Packit bf408e
	}
Packit bf408e
Packit bf408e
	if (SIZE(umode_t) == SIZEOF_32BIT)
Packit bf408e
		mode = umode32;
Packit bf408e
	else
Packit bf408e
		mode = (uint)umode16;
Packit bf408e
Packit bf408e
    	if (!S_ISSOCK(mode))
Packit bf408e
        	return FALSE;
Packit bf408e
Packit bf408e
	/* 
Packit bf408e
	 * 2.6 (SOCK_V2) -- socket is inode addr minus sizeof(struct socket) 
Packit bf408e
	 */
Packit bf408e
	switch (net->flags & (SOCK_V1|SOCK_V2))  
Packit bf408e
	{
Packit bf408e
	case SOCK_V1:
Packit bf408e
    		struct_socket = inode + OFFSET(inode_u);
Packit bf408e
		sock = ULONG(inode_buf + OFFSET(inode_u) + OFFSET(socket_sk));
Packit bf408e
		break;
Packit bf408e
Packit bf408e
	case SOCK_V2:
Packit bf408e
		if (!VALID_SIZE(inet_sock)) 
Packit bf408e
			error(FATAL, 
Packit bf408e
              	           "cannot determine what an inet_sock structure is\n");
Packit bf408e
    		struct_socket = inode - OFFSET(socket_alloc_vfs_inode);
Packit bf408e
		socket_buf = GETBUF(SIZE(socket));
Packit bf408e
                readmem(struct_socket, KVADDR, socket_buf,
Packit bf408e
                        SIZE(socket), "socket buffer", FAULT_ON_ERROR);
Packit bf408e
		sock = ULONG(socket_buf + OFFSET(socket_sk));
Packit bf408e
		FREEBUF(socket_buf);
Packit bf408e
		break;
Packit bf408e
	} 
Packit bf408e
Packit bf408e
	if (NET_REFERENCE_CHECK(ref)) {
Packit bf408e
		if ((ref->cmdflags & NET_REF_HEXNUM) &&
Packit bf408e
		    ((ref->hexval == sock) || (ref->hexval == struct_socket)))
Packit bf408e
			ref->cmdflags |= NET_REF_FOUND_ITEM;
Packit bf408e
		else if ((ref->cmdflags & NET_REF_DECNUM) &&
Packit bf408e
			(ref->decval == (ulong)fd))
Packit bf408e
			ref->cmdflags |= NET_REF_FOUND_ITEM;
Packit bf408e
                else if ((ref->cmdflags & NET_REF_HEXNUM) &&
Packit bf408e
                        (ref->hexval == (ulong)fd))
Packit bf408e
                        ref->cmdflags |= NET_REF_FOUND_ITEM;
Packit bf408e
Packit bf408e
		if (!(ref->cmdflags & NET_REF_FOUND_ITEM))
Packit bf408e
			return FALSE;
Packit bf408e
Packit bf408e
		ref->cmdflags &= ~NET_REF_FOUND_ITEM;
Packit bf408e
		ref->cmdflags |= NET_REF_FOUND;
Packit bf408e
Packit bf408e
		if (!(ref->cmdflags & NET_TASK_HEADER_PRINTED)) {
Packit bf408e
			print_task_header(fp, task_to_context(ref->ref1), 0);
Packit bf408e
			ref->cmdflags |= NET_TASK_HEADER_PRINTED;
Packit bf408e
		}
Packit bf408e
Packit bf408e
		if (!(ref->cmdflags & NET_SOCK_HEADER_PRINTED)) {
Packit bf408e
			sockets_found = 0;
Packit bf408e
			ref->cmdflags |= NET_SOCK_HEADER_PRINTED;
Packit bf408e
		}
Packit bf408e
	}
Packit bf408e
Packit bf408e
	switch (flag & (S_FLAG|s_FLAG))
Packit bf408e
	{
Packit bf408e
	case S_FLAG:
Packit bf408e
		fprintf(fp, "%sFD  %s  %s\n", sockets_found ? "\n" : "",
Packit bf408e
			mkstring(buf1, VADDR_PRLEN, CENTER|LJUST, "SOCKET"),
Packit bf408e
			mkstring(buf2, VADDR_PRLEN, CENTER|LJUST, "SOCK"));
Packit bf408e
		fprintf(fp, "%2d  %s  %s\n\n",
Packit bf408e
			fd, 
Packit bf408e
			mkstring(buf1, VADDR_PRLEN, RJUST|LONG_HEX, 
Packit bf408e
			MKSTR(struct_socket)),
Packit bf408e
			mkstring(buf2, VADDR_PRLEN, RJUST|LONG_HEX, 
Packit bf408e
			MKSTR(sock)));
Packit bf408e
Packit bf408e
    		dump_struct("socket", struct_socket, radix);
Packit bf408e
		switch (net->flags & (SOCK_V1|SOCK_V2))  
Packit bf408e
		{
Packit bf408e
		case SOCK_V1:
Packit bf408e
    			dump_struct("sock", sock, radix);
Packit bf408e
			break;
Packit bf408e
		case SOCK_V2:
Packit bf408e
			if (STRUCT_EXISTS("inet_sock") && !(net->flags & NO_INET_SOCK))
Packit bf408e
				dump_struct("inet_sock", sock, radix);
Packit bf408e
			else if (STRUCT_EXISTS("sock"))
Packit bf408e
				dump_struct("sock", sock, radix);
Packit bf408e
			else
Packit bf408e
				fprintf(fp, "\nunable to display inet_sock structure\n");
Packit bf408e
			break;
Packit bf408e
		}
Packit bf408e
		break;
Packit bf408e
Packit bf408e
	case s_FLAG:
Packit bf408e
		if (!sockets_found) {
Packit bf408e
			fprintf(fp, "%s\n", socket_hdr);
Packit bf408e
		}
Packit bf408e
		fprintf(fp, "%2d%s%s%s%s%s",
Packit bf408e
			fd, space(MINSPACE), 
Packit bf408e
			mkstring(buf1, VADDR_PRLEN, RJUST|LONG_HEX, 
Packit bf408e
			MKSTR(struct_socket)),
Packit bf408e
			space(MINSPACE),
Packit bf408e
			mkstring(buf2, VADDR_PRLEN, RJUST|LONG_HEX,
Packit bf408e
                        MKSTR(sock)),
Packit bf408e
		        space(MINSPACE)); 
Packit bf408e
Packit bf408e
		buf1[0] = NULLCHAR;
Packit bf408e
		get_sock_info(sock, buf1);
Packit bf408e
		fprintf(fp, "%s\n", buf1);
Packit bf408e
Packit bf408e
		return TRUE;
Packit bf408e
Packit bf408e
	default:
Packit bf408e
		error(FATAL, "illegal flag: %lx\n", flag);
Packit bf408e
	}
Packit bf408e
Packit bf408e
    	return TRUE;
Packit bf408e
}