ioctl 获取网卡流量信息(ifconfig的实现)

本文内容自己暂未做验证,内容来自http://www.360doc.com/content/15/0806/18/18945873_489944405.shtml
主要临时记录下ifconfig 实际使用的ioctl cmd,方便日后查看

int main(int argc, char **argv)
{
……
 argc--;
 argv++;
 while (argc && *argv[0] == '-') {
 ……
}
打开内核支持的所有协议的套接字,主要是一个循环调用socket的过程
 if ((skfd = sockets_open(0)) < 0) {
 perror("socket");
 exit(1);
 }
 if (argc == 0) {
 int err = if_print((char *) NULL);
 (void) close(skfd);
 exit(err < 0);
 }
 spp = argv;
 safe_strncpy(ifr.ifr_name, *spp++, IFNAMSIZ);
 if (*spp == (char *) NULL) {
 int err = if_print(ifr.ifr_name);
 (void) close(skfd);
 exit(err < 0);
 }
 if ((ap = get_aftype(*spp)) != NULL)
 spp++;
 else
 ap = get_aftype(DFLT_AF);
 if (ap) {
 addr_family = ap->af;
 skfd = ap->fd;
 }
while (*spp != (char *) NULL) {
}
 switch (ap->af) {
 ……
 r = ioctl(fd, SIOCSIFADDR, &ifr);
 ……
}

在主函数中判断argc,如果仅仅是输入了ifconfig而没有任何参数,则输出全部网卡信息

 if (argc == 0) {
 int err = if_print((char *) NULL);
 (void) close(skfd);
 exit(err < 0);
 }

函数if_print 定义在ifconfig.c中,用来输出网卡地址等信息:

static int if_print(char *ifname)
{
 int res;
 if (ife_short) //如果是以省略模式输出
 printf(_("Iface MTU Met RX-OK RX-ERR RX-DRP RX-OVR TX-OK TX-ERR TXDRP TX-OVR Flg\n"));
 if (!ifname) { //如果ifname==NULL,则表示输出全部网卡的信息
 res = for_all_interfaces(do_if_print, &opt_a);
 } else { //否则仅仅输出ifname的。
 struct interface *ife;
 ife = lookup_interface(ifname);
 res = do_if_fetch(ife);
 if (res >= 0)
ife_print(ife);
 }
 return res;
}

这里,又涉及到两个函数的调用:for_all_interfaces和lookup_interface。先来看
for_all_interfaces
函数在interface.c中实现:
参数int (*doit) (struct interface *, void *)是一个指向函数的指针,为实际的功能函数,在上
层函数中传递过来的是do_if_print

int for_all_interfaces(int (*doit) (struct interface *, void *), void *cookie)
{
 struct interface *ife;
 if (!int_list && (if_readlist() < 0))
 return -1;
 for (ife = int_list; ife; ife = ife->next) {
 int err = doit(ife, cookie); //调用函数do_if_print实现
 if (err)
return err;
 }
 return 0;
}
int do_if_print(struct interface *ife, void *cookie)
{
 int *opt_a = (int *) cookie;
 int res;
 res = do_if_fetch(ife); //提取出网卡的信息,置于结构ife中,顺便检查一
下设备的合法性,如是否存在等等……
 if (res >= 0) {
 if ((ife->flags & IFF_UP) || *opt_a)
ife_print(ife); //输出
 }
 return res;
}
int do_if_fetch(struct interface *ife)
{
 if (if_fetch(ife) < 0) {
 char *errmsg;
 if (errno == ENODEV) {
errmsg = _("Device not found");
 } else {
errmsg = strerror(errno);
 }
fprintf(stderr, _("%s: error fetching interface information: %s\n"),
 ife->name, errmsg);
 return -1;
 }
 return 0;
}
int if_fetch(struct interface *ife)
{
 struct ifreq ifr;
 int fd;
 char *ifname = ife->name;
 strcpy(ifr.ifr_name, ifname);
 if (ioctl(skfd, SIOCGIFFLAGS, &ifr) < 0)
 return (-1);
 ife->flags = ifr.ifr_flags;
 strcpy(ifr.ifr_name, ifname);
 if (ioctl(skfd, SIOCGIFHWADDR, &ifr) < 0)
 memset(ife->hwaddr, 0, 32);
 else
 memcpy(ife->hwaddr, ifr.ifr_hwaddr.sa_data, 8);
 ife->type = ifr.ifr_hwaddr.sa_family;
 strcpy(ifr.ifr_name, ifname);
 if (ioctl(skfd, SIOCGIFMETRIC, &ifr) < 0)
 ife->metric = 0;
 else
 ife->metric = ifr.ifr_metric;
 strcpy(ifr.ifr_name, ifname);
 if (ioctl(skfd, SIOCGIFMTU, &ifr) < 0)
 ife->mtu = 0;
 else
 ife->mtu = ifr.ifr_mtu;
#ifdef HAVE_HWSLIP
 if (ife->type == ARPHRD_SLIP || ife->type == ARPHRD_CSLIP ||
 ife->type == ARPHRD_SLIP6 || ife->type == ARPHRD_CSLIP6 ||
 ife->type == ARPHRD_ADAPT) {
#ifdef SIOCGOUTFILL
 strcpy(ifr.ifr_name, ifname);
 if (ioctl(skfd, SIOCGOUTFILL, &ifr) < 0)
ife->outfill = 0;
 else
ife->outfill = (unsigned int) ifr.ifr_data;
#endif
#ifdef SIOCGKEEPALIVE
 strcpy(ifr.ifr_name, ifname);
 if (ioctl(skfd, SIOCGKEEPALIVE, &ifr) < 0)
ife->keepalive = 0;
 else
ife->keepalive = (unsigned int) ifr.ifr_data;
#endif
 }
#endif
 strcpy(ifr.ifr_name, ifname);
 if (ioctl(skfd, SIOCGIFMAP, &ifr) < 0)
 memset(&ife->map, 0, sizeof(struct ifmap));
 else
 memcpy(&ife->map, &ifr.ifr_map, sizeof(struct ifmap));
 strcpy(ifr.ifr_name, ifname);
 if (ioctl(skfd, SIOCGIFMAP, &ifr) < 0)
 memset(&ife->map, 0, sizeof(struct ifmap));
 else
 ife->map = ifr.ifr_map;
#ifdef HAVE_TXQUEUELEN
 strcpy(ifr.ifr_name, ifname);
 if (ioctl(skfd, SIOCGIFTXQLEN, &ifr) < 0)
 ife->tx_queue_len = -1;
 else
 ife->tx_queue_len = ifr.ifr_qlen;
#else
ife->tx_queue_len = -1;
#endif
#if HAVE_AFINET
 fd = get_socket_for_af(AF_INET);
 if (fd >= 0) {
 strcpy(ifr.ifr_name, ifname);
 ifr.ifr_addr.sa_family = AF_INET;
 if (ioctl(fd, SIOCGIFADDR, &ifr) == 0) {
ife->has_ip = 1;
ife->addr = ifr.ifr_addr;
strcpy(ifr.ifr_name, ifname);
if (ioctl(fd, SIOCGIFDSTADDR, &ifr) < 0)
memset(&ife->dstaddr, 0, sizeof(struct sockaddr));
else
ife->dstaddr = ifr.ifr_dstaddr;
strcpy(ifr.ifr_name, ifname);
if (ioctl(fd, SIOCGIFBRDADDR, &ifr) < 0)
memset(&ife->broadaddr, 0, sizeof(struct sockaddr));
else
 ife->broadaddr = ifr.ifr_broadaddr;
strcpy(ifr.ifr_name, ifname);
if (ioctl(fd, SIOCGIFNETMASK, &ifr) < 0)
memset(&ife->netmask, 0, sizeof(struct sockaddr));
else
 ife->netmask = ifr.ifr_netmask;
 } else
memset(&ife->addr, 0, sizeof(struct sockaddr));
 }
#endif
#if HAVE_AFATALK
 fd = get_socket_for_af(AF_APPLETALK);
 if (fd >= 0) {
 strcpy(ifr.ifr_name, ifname);
 if (ioctl(fd, SIOCGIFADDR, &ifr) == 0) {
ife->ddpaddr = ifr.ifr_addr;
ife->has_ddp = 1;
 }
 }
#endif
#if HAVE_AFIPX
 fd = get_socket_for_af(AF_IPX);
 if (fd >= 0) {
 strcpy(ifr.ifr_name, ifname);
 if (!ipx_getaddr(fd, IPX_FRAME_ETHERII, &ifr)) {
ife->has_ipx_bb = 1;
ife->ipxaddr_bb = ifr.ifr_addr;
 }
 strcpy(ifr.ifr_name, ifname);
 if (!ipx_getaddr(fd, IPX_FRAME_SNAP, &ifr)) {
ife->has_ipx_sn = 1;
ife->ipxaddr_sn = ifr.ifr_addr;
 }
 strcpy(ifr.ifr_name, ifname);
 if (!ipx_getaddr(fd, IPX_FRAME_8023, &ifr)) {
ife->has_ipx_e3 = 1;
ife->ipxaddr_e3 = ifr.ifr_addr;
 }
 strcpy(ifr.ifr_name, ifname);
 if (!ipx_getaddr(fd, IPX_FRAME_8022, &ifr)) {
ife->has_ipx_e2 = 1;
ife->ipxaddr_e2 = ifr.ifr_addr;
 }
 }
#endif
#if HAVE_AFECONET
 fd = get_socket_for_af(AF_ECONET);
 if (fd >= 0) {
 strcpy(ifr.ifr_name, ifname);
 if (ioctl(fd, SIOCGIFADDR, &ifr) == 0) {
ife->ecaddr = ifr.ifr_addr;
ife->has_econet = 1;
 }
 }
#endif
posted @   Nilbb  阅读(438)  评论(0编辑  收藏  举报
编辑推荐:
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· C#/.NET/.NET Core技术前沿周刊 | 第 29 期(2025年3.1-3.9)
· 从HTTP原因短语缺失研究HTTP/2和HTTP/3的设计差异
点击右上角即可分享
微信分享提示