Network devices are not accessed through device nodes and they do not have major and minor numbers. Instead, a network device is allocated a name by the kernel, based on a string and an instance number. Here is an example of the way a network driver registers an interface:
my_netdev = alloc_netdev(0, "net%d", NET_NAME_UNKNOWN, netdev_setup); ret = register_netdev(my_netdev);
This creates a network device named net0
the first time it is called, net1
the second, and so on. More common names are lo
, eth0
, and wlan0
.
Note that this is the name it starts off with; device managers, such as udev
, may change to something different later on.
Usually, the network interface name is only used when configuring the network using utilities such as ip
and ifconfig
to establish a network address and route. Thereafter, you interact with the network driver indirectly by opening sockets, and let the network layer decide how to route them to the right interface.
However, it is possible to access network devices directly from user space by creating a socket and using the ioctl
commands listed in include/linux/sockios.h
. For example, this program uses SIOCGIFHWADDR
to query the driver for the hardware (MAC) address:
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <sys/ioctl.h> #include <linux/sockios.h> #include <net/if.h> int main (int argc, char *argv[]) { int s; int ret; struct ifreq ifr; int i; if (argc != 2) { printf("Usage %s [network interface]\n", argv[0]); return 1; } s = socket(PF_INET, SOCK_DGRAM, 0); if (s < 0) { perror("socket"); return 1; } strcpy(ifr.ifr_name, argv[1]); ret = ioctl(s, SIOCGIFHWADDR, &ifr); if (ret < 0) { perror("ioctl"); return 1; } for (i = 0; i < 6; i++) printf("%02x:", (unsigned char)ifr.ifr_hwaddr.sa_data[i]); printf("\n"); close(s); return 0; }
This is a standard device, ioctl
, which is handled by the network layer on the driver's behalf, but it is possible to define your own ioctl
numbers and handle them in a custom network driver.