Getting List of Network Devices Inside the Linux Kernel

Getting list of network devices inside the Linux kernel

This ought to do the trick:

#include <linux/netdevice.h>

struct net_device *dev;

read_lock(&dev_base_lock);

dev = first_net_device(&init_net);
while (dev) {
printk(KERN_INFO "found [%s]\n", dev->name);
dev = next_net_device(dev);
}

read_unlock(&dev_base_lock);

How to get information about wireless net_devices

if(net_device->ieee80211_ptr != NULL)? The ieee80211_ptr is a struct wireless_dev*. This structure should give you access to most of the values you requested. In struct wireless_dev is struct wiphy *wiphy;, you can use this to get a cfg80211_registered_device with wiphy_to_dev().

The gateway address is unrelated to wireless. I doubt devices have any gateway information but you need the interface name in net_device to find the route. The route is IP related and has nothing to do with a device. Good luck.

List all devices bound to a driver

Yes, simply register functions with A when driver B loads and call same function whenever device list is required.
e.g

Driver A <<< register_func(func_ptr_list); export register_func
Driver B <<< Call register_func with function list.

Multiple driver talks to each other using similar function element. for example Look at module_int for cxgb4 and cxgb4i

Obtain interface netmask in Linux kernel module

There is a pretty easy way to get it.

Network device is described by struct net_device.

<linux/netdevice.h>:

struct net_device {
...
struct in_device __rcu *ip_ptr;
...

net_device has a pointer to "inet" device (in_device).

<linux/inetdevice.h>:

struct in_device {
...
struct in_ifaddr *ifa_list; /* IP ifaddr chain */
...

which finnaly points to chain of in_ifaddr that contains all the interface info:

struct in_ifaddr {
struct hlist_node hash;
struct in_ifaddr *ifa_next;
struct in_device *ifa_dev;
struct rcu_head rcu_head;
__be32 ifa_local;
__be32 ifa_address;
__be32 ifa_mask;
__u32 ifa_rt_priority;
__be32 ifa_broadcast;
unsigned char ifa_scope;
unsigned char ifa_prefixlen;
__u32 ifa_flags;
char ifa_label[IFNAMSIZ];

/* In seconds, relative to tstamp. Expiry is at tstamp + HZ * lft. */
__u32 ifa_valid_lft;
__u32 ifa_preferred_lft;
unsigned long ifa_cstamp; /* created timestamp */
unsigned long ifa_tstamp; /* updated timestamp */
};

To make my answer more versatile, here is an abstract example (without binding to netfilter and skb devices logic):

struct in_ifaddr *ifa;
struct net_device *dev = dev_get_by_name(&init_net, "wlp7s0");
if(!dev) {
printk(KERN_ERR "Can't obtain device\n");
return;
}

// roughly
rcu_read_lock();
for(ifa = rcu_dereference(dev->ip_ptr->ifa_list);
ifa;
ifa = rcu_dereference(ifa->ifa_next))
printk("address: %pI4, mask: %pI4\n", &ifa->ifa_address, &ifa->ifa_mask);
rcu_read_unlock();

From example you can see that you can handle the whole chain(that @larsks mentioned in comment) depending on some specific logic.

P.S. don't forget to include <linux/netdevice.h> and <linux/inetdevice.h>.

How to get network device stats?

There is simpler approach. copied from http://man7.org/linux/man-pages/man3/getifaddrs.3.html

VERSIONS top

   The getifaddrs() function first appeared in glibc 2.3, but before
glibc 2.3.3, the implementation supported only IPv4 addresses; IPv6
support was added in glibc 2.3.3. Support of address families other
than IPv4 is available only on kernels that support netlink.

#include <arpa/inet.h>
#include <sys/socket.h>
#include <netdb.h>
#include <ifaddrs.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <linux/if_link.h>

int main(int argc, char *argv[])
{
struct ifaddrs *ifaddr, *ifa;
int family, s, n;
char host[NI_MAXHOST];

if (getifaddrs(&ifaddr) == -1) {
perror("getifaddrs");
exit(EXIT_FAILURE);
}

/* Walk through linked list, maintaining head pointer so we
can free list later */

for (ifa = ifaddr, n = 0; ifa != NULL; ifa = ifa->ifa_next, n++) {
if (ifa->ifa_addr == NULL)
continue;

family = ifa->ifa_addr->sa_family;

/* Display interface name and family (including symbolic
form of the latter for the common families) */

printf("%-8s %s (%d)\n",
ifa->ifa_name,
(family == AF_PACKET) ? "AF_PACKET" :
(family == AF_INET) ? "AF_INET" :
(family == AF_INET6) ? "AF_INET6" : "???",
family);

/* For an AF_INET* interface address, display the address */

if (family == AF_INET || family == AF_INET6) {
s = getnameinfo(ifa->ifa_addr,
(family == AF_INET) ? sizeof(struct sockaddr_in) :
sizeof(struct sockaddr_in6),
host, NI_MAXHOST,
NULL, 0, NI_NUMERICHOST);
if (s != 0) {
printf("getnameinfo() failed: %s\n", gai_strerror(s));
exit(EXIT_FAILURE);
}

printf("\t\taddress: <%s>\n", host);

} else if (family == AF_PACKET && ifa->ifa_data != NULL) {
struct rtnl_link_stats *stats = (struct rtnl_link_stats *)ifa->ifa_data;

printf("\t\ttx_packets = %10u; rx_packets = %10u\n"
"\t\ttx_bytes = %10u; rx_bytes = %10u\n",
stats->tx_packets, stats->rx_packets,
stats->tx_bytes, stats->rx_bytes);
}
}

freeifaddrs(ifaddr);
exit(EXIT_SUCCESS);
}


Related Topics



Leave a reply



Submit