Série: sockets
c
134 linhas
· Atualizado 2026-02-05
07-ioctl-link-layer.c
sockets/examples/c/07-ioctl-link-layer.c
/*
* ioctl() and the Link-Layer Driver
*
* Shows how to use ioctl() on a socket to query the kernel's network
* interface (link-layer) driver. Uses SIOCGIFCONF to list interfaces,
* then SIOCGIFFLAGS, SIOCGIFHWADDR (MAC), SIOCGIFMTU, and SIOCGIFADDR
* per interface.
*
* Link-layer ioctls use struct ifreq / struct ifconf and the net device
* ioctl codes (see netdevice(7) on Linux). The same socket is used only
* as a handle for ioctl(); no packets are sent.
*
* Linux-oriented (SIOCGIFHWADDR is Linux-specific). macOS/BSD use
* getifaddrs() for MAC and some other data.
*
* Compile (Linux): cc -o 07-ioctl-link-layer 07-ioctl-link-layer.c
* Run: ./07-ioctl-link-layer [interface-name]
* (no argument = list all interfaces)
*
* May require CAP_NET_ADMIN or root for some ioctls on restricted interfaces.
*/
#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <net/if.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#ifndef SIOCGIFHWADDR
/* Not defined on macOS/BSD */
#define SIOCGIFHWADDR 0x8927
#endif
#define IFLIST_SIZE (128 * sizeof(struct ifreq))
static void print_mac(unsigned char *data) {
printf("%02x:%02x:%02x:%02x:%02x:%02x",
data[0], data[1], data[2], data[3], data[4], data[5]);
}
static void list_one(int fd, const char *ifname) {
struct ifreq ifr;
struct sockaddr_in *sin;
char addr_buf[INET_ADDRSTRLEN];
memset(&ifr, 0, sizeof(ifr));
strncpy(ifr.ifr_name, ifname, IFNAMSIZ - 1);
ifr.ifr_name[IFNAMSIZ - 1] = '\0';
printf("Interface: %s\n", ifr.ifr_name);
if (ioctl(fd, SIOCGIFFLAGS, &ifr) == 0) {
printf(" Flags: %s%s%s\n",
(ifr.ifr_flags & IFF_UP) ? "UP " : "",
(ifr.ifr_flags & IFF_RUNNING) ? "RUNNING " : "",
(ifr.ifr_flags & IFF_LOOPBACK) ? "LOOPBACK" : "");
}
#ifdef __linux__
if (ioctl(fd, SIOCGIFHWADDR, &ifr) == 0) {
unsigned char *hw = (unsigned char *)ifr.ifr_hwaddr.sa_data;
printf(" MAC: ");
print_mac(hw);
printf("\n");
}
#else
(void)print_mac;
printf(" MAC: (use getifaddrs on this platform)\n");
#endif
if (ioctl(fd, SIOCGIFMTU, &ifr) == 0)
printf(" MTU: %d\n", ifr.ifr_mtu);
if (ioctl(fd, SIOCGIFADDR, &ifr) == 0) {
sin = (struct sockaddr_in *)&ifr.ifr_addr;
if (sin->sin_family == AF_INET && inet_ntop(AF_INET, &sin->sin_addr, addr_buf, sizeof(addr_buf)))
printf(" IPv4: %s\n", addr_buf);
}
printf("\n");
}
int main(int argc, char *argv[]) {
struct ifconf ifc;
struct ifreq *ifr;
char *buf;
int fd;
int i, n;
fd = socket(AF_INET, SOCK_DGRAM, 0);
if (fd < 0) {
perror("socket");
return 1;
}
buf = malloc(IFLIST_SIZE);
if (!buf) {
perror("malloc");
close(fd);
return 1;
}
memset(&ifc, 0, sizeof(ifc));
ifc.ifc_len = IFLIST_SIZE;
ifc.ifc_buf = buf;
if (ioctl(fd, SIOCGIFCONF, &ifc) < 0) {
perror("ioctl SIOCGIFCONF");
free(buf);
close(fd);
return 1;
}
ifr = ifc.ifc_req;
n = ifc.ifc_len / sizeof(struct ifreq);
if (argc >= 2) {
/* Query a single interface by name */
list_one(fd, argv[1]);
} else {
/* List all interfaces */
for (i = 0; i < n; i++)
list_one(fd, ifr[i].ifr_name);
}
free(buf);
close(fd);
return 0;
}
Artigos relacionados
sockets
c
Atualizado 2026-02-05
01-basic-tcp-server.c
01-basic-tcp-server.c — c source code from the sockets learning materials (sockets/examples/c/01-basic-tcp-server.c).
Ler artigo →
sockets
c
Atualizado 2026-02-05
02-basic-tcp-client.c
02-basic-tcp-client.c — c source code from the sockets learning materials (sockets/examples/c/02-basic-tcp-client.c).
Ler artigo →
sockets
c
Atualizado 2026-02-05
03-basic-udp-server.c
03-basic-udp-server.c — c source code from the sockets learning materials (sockets/examples/c/03-basic-udp-server.c).
Ler artigo →
sockets
c
Atualizado 2026-02-05
04-basic-udp-client.c
04-basic-udp-client.c — c source code from the sockets learning materials (sockets/examples/c/04-basic-udp-client.c).
Ler artigo →
sockets
c
Atualizado 2026-02-05
05-https-client.c
05-https-client.c — c source code from the sockets learning materials (sockets/examples/c/05-https-client.c).
Ler artigo →
sockets
c
Atualizado 2026-02-05
06-domain-to-ip.c
06-domain-to-ip.c — c source code from the sockets learning materials (sockets/examples/c/06-domain-to-ip.c).
Ler artigo →