网络ioctl实践1:获取网卡的MAC和IP

网络ioctl实践2:获取网卡的广播地址和子网掩码

网络ioctl实践3:设置网卡的mac、ip、子网掩码、广播地址

前言

如果设备控制没有好的解决办法,那么ioctl就可能是最终答案。如果要说IOCTL能干什么,那就是任何事情,都可以做。

一 ioctl函数原型

它是一个变参函数,第二个是命令类型,第三个是命令对应的参数。函数成功返回0,失败返回-1.

NAMEioctl - control device
SYNOPSIS#include <sys/ioctl.h>int ioctl(int fd, unsigned long request, ...);

参数fd表示文件描述符,如果要获取网卡信息,这个fd就是套接字描述符,就是socket函数的返回值。

NAMEsocket - create an endpoint for communication
SYNOPSIS#include <sys/types.h>          /* See NOTES */#include <sys/socket.h>int socket(int domain, int type, int protocol);

domain参数:我们只关注两个值,AF_UNIX和AF_INET,AF_UNIX用于本地通进程间信,AF_INET既可以用于本机进程间通信新,也可以用于主机间进程通信。

type 参数:我们只关注两个值,SOCK_STREAM和SOCK_DGRAM,SOCK_STREAM用于TCP,SOCK_DGRAM用于UDP。

protocol参数:值为0时,会自动选择type类型对应的默认协议。

获取网络描述符的语句如下所示:

int fd = socket(AF_INET,SOCK_DGRAM,0);

好了,万事具备了。就差给ioctl一个合适的命令和一个合适的参数了。

类别

Request

说明

数据类型

SIOCATMARK

SIOCSPGRP

SIOCGPGRP

是否位于带外标记

设置套接口的进程ID 或进程组ID

获取套接口的进程ID 或进程组ID

int

int

int

FIONBIO

FIOASYNC

FIONREAD

FIOSETOWN

FIOGETOWN

设置/ 清除非阻塞I/O 标志

设置/ 清除信号驱动异步I/O 标志

获取接收缓存区中的字节数

设置文件的进程ID 或进程组ID

获取文件的进程ID 或进程组ID

int

int

int

int

int

SIOCGIFCONF

SIOCSIFADDR

SIOCGIFADDR

SIOCSIFFLAGS

SIOCGIFFLAGS

SIOCSIFDSTADDR

SIOCGIFDSTADDR

SIOCGIFBRDADDR

SIOCSIFBRDADDR

SIOCGIFNETMASK

SIOCSIFNETMASK

SIOCGIFMETRIC

SIOCSIFMETRIC

SIOCGIFMTU

SIOCxxx

获取所有接口的清单

设置接口地址

获取接口地址

设置接口标志

获取接口标志

设置点到点地址

获取点到点地址

获取广播地址

设置广播地址

获取子网掩码

设置子网掩码

获取接口的测度

设置接口的测度

获取接口MTU

(还有很多取决于系统的实现)

struct ifconf

struct ifreq

struct ifreq

struct ifreq

struct ifreq

struct ifreq

struct ifreq

struct ifreq

struct ifreq

struct ifreq

struct ifreq

struct ifreq

struct ifreq

struct ifreq

ARP

SIOCSARP

SIOCGARP

SIOCDARP

创建/ 修改ARP 表项

获取ARP 表项

删除ARP 表项

struct arpreq

struct arpreq

struct arpreq

SIOCADDRT

SIOCDELRT

增加路径

删除路径

struct rtentry

struct rtentry

二 网络相关的IOCTL命令-内核中的宏定义

直接把文件copy过来sockios.h (include\uapi\linux),如果能这些IOCTL挨个试一遍,那么网络控制这块,(⊙o⊙)…就算入魔了吧,这么多啊。下面这个宏定义和上面表格是一样的。

/** INET     An implementation of the TCP/IP protocol suite for the LINUX*       operating system.  INET is implemented using the  BSD Socket*       interface as the means of communication with the user level.**      Definitions of the socket-level I/O control calls.** Version:   @(#)sockios.h  1.0.2   03/09/93** Authors: Ross Biro*      Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>**       This program is free software; you can redistribute it and/or*      modify it under the terms of the GNU General Public License*        as published by the Free Software Foundation; either version*       2 of the License, or (at your option) any later version.*/
#ifndef _LINUX_SOCKIOS_H
#define _LINUX_SOCKIOS_H#include <asm/sockios.h>/* Linux-specific socket ioctls */
#define SIOCINQ     FIONREAD
#define SIOCOUTQ    TIOCOUTQ        /* output queue size (not sent + not acked) *//* Routing table calls. */
#define SIOCADDRT   0x890B      /* add routing table entry  */
#define SIOCDELRT   0x890C      /* delete routing table entry   */
#define SIOCRTMSG   0x890D      /* call to routing system   *//* Socket configuration controls. */
#define SIOCGIFNAME 0x8910      /* get iface name       */
#define SIOCSIFLINK 0x8911      /* set iface channel        */
#define SIOCGIFCONF 0x8912      /* get iface list       */
#define SIOCGIFFLAGS    0x8913      /* get flags            */
#define SIOCSIFFLAGS    0x8914      /* set flags            */
#define SIOCGIFADDR 0x8915      /* get PA address       */
#define SIOCSIFADDR 0x8916      /* set PA address       */
#define SIOCGIFDSTADDR  0x8917      /* get remote PA address    */
#define SIOCSIFDSTADDR  0x8918      /* set remote PA address    */
#define SIOCGIFBRDADDR  0x8919      /* get broadcast PA address */
#define SIOCSIFBRDADDR  0x891a      /* set broadcast PA address */
#define SIOCGIFNETMASK  0x891b      /* get network PA mask      */
#define SIOCSIFNETMASK  0x891c      /* set network PA mask      */
#define SIOCGIFMETRIC   0x891d      /* get metric           */
#define SIOCSIFMETRIC   0x891e      /* set metric           */
#define SIOCGIFMEM  0x891f      /* get memory address (BSD) */
#define SIOCSIFMEM  0x8920      /* set memory address (BSD) */
#define SIOCGIFMTU  0x8921      /* get MTU size         */
#define SIOCSIFMTU  0x8922      /* set MTU size         */
#define SIOCSIFNAME 0x8923      /* set interface name */
#define SIOCSIFHWADDR   0x8924      /* set hardware address     */
#define SIOCGIFENCAP    0x8925      /* get/set encapsulations       */
#define SIOCSIFENCAP    0x8926
#define SIOCGIFHWADDR   0x8927      /* Get hardware address     */
#define SIOCGIFSLAVE    0x8929      /* Driver slaving support   */
#define SIOCSIFSLAVE    0x8930
#define SIOCADDMULTI    0x8931      /* Multicast address lists  */
#define SIOCDELMULTI    0x8932
#define SIOCGIFINDEX    0x8933      /* name -> if_index mapping  */
#define SIOGIFINDEX SIOCGIFINDEX    /* misprint compatibility :-)   */
#define SIOCSIFPFLAGS   0x8934      /* set/get extended flags set   */
#define SIOCGIFPFLAGS   0x8935
#define SIOCDIFADDR 0x8936      /* delete PA address        */
#define SIOCSIFHWBROADCAST  0x8937  /* set hardware broadcast addr  */
#define SIOCGIFCOUNT    0x8938      /* get number of devices */#define SIOCGIFBR    0x8940      /* Bridging support     */
#define SIOCSIFBR   0x8941      /* Set bridging options     */#define SIOCGIFTXQLEN 0x8942      /* Get the tx queue length  */
#define SIOCSIFTXQLEN   0x8943      /* Set the tx queue length  *//* SIOCGIFDIVERT was: 0x8944      Frame diversion support */
/* SIOCSIFDIVERT was:   0x8945      Set frame diversion options */#define SIOCETHTOOL   0x8946      /* Ethtool interface        */#define SIOCGMIIPHY   0x8947      /* Get address of MII PHY in use. */
#define SIOCGMIIREG 0x8948      /* Read MII PHY register.   */
#define SIOCSMIIREG 0x8949      /* Write MII PHY register.  */#define SIOCWANDEV    0x894A      /* get/set netdev parameters    */#define SIOCOUTQNSD   0x894B      /* output queue size (not sent only) *//* ARP cache control calls. *//*  0x8950 - 0x8952  * obsolete calls, don't re-use */
#define SIOCDARP    0x8953      /* delete ARP table entry   */
#define SIOCGARP    0x8954      /* get ARP table entry      */
#define SIOCSARP    0x8955      /* set ARP table entry      *//* RARP cache control calls. */
#define SIOCDRARP   0x8960      /* delete RARP table entry  */
#define SIOCGRARP   0x8961      /* get RARP table entry     */
#define SIOCSRARP   0x8962      /* set RARP table entry     *//* Driver configuration calls */#define SIOCGIFMAP    0x8970      /* Get device parameters    */
#define SIOCSIFMAP  0x8971      /* Set device parameters    *//* DLCI configuration calls */#define SIOCADDDLCI 0x8980      /* Create new DLCI device   */
#define SIOCDELDLCI 0x8981      /* Delete DLCI device       */#define SIOCGIFVLAN   0x8982      /* 802.1Q VLAN support      */
#define SIOCSIFVLAN 0x8983      /* Set 802.1Q VLAN options  *//* bonding calls */#define SIOCBONDENSLAVE    0x8990      /* enslave a device to the bond */
#define SIOCBONDRELEASE 0x8991      /* release a slave from the bond*/
#define SIOCBONDSETHWADDR      0x8992   /* set the hw addr of the bond  */
#define SIOCBONDSLAVEINFOQUERY 0x8993   /* rtn info about slave state   */
#define SIOCBONDINFOQUERY      0x8994   /* rtn info about bond state    */
#define SIOCBONDCHANGEACTIVE   0x8995   /* update to a new active slave *//* bridge calls */
#define SIOCBRADDBR     0x89a0      /* create new bridge device     */
#define SIOCBRDELBR     0x89a1      /* remove bridge device         */
#define SIOCBRADDIF 0x89a2      /* add interface to bridge      */
#define SIOCBRDELIF 0x89a3      /* remove interface from bridge *//* hardware time stamping: parameters in linux/net_tstamp.h */
#define SIOCSHWTSTAMP   0x89b0      /* set and get config       */
#define SIOCGHWTSTAMP   0x89b1      /* get config           *//* Device private ioctl calls *//**   These 16 ioctls are available to devices via the do_ioctl() device* vector. Each device should include this file and redefine these names*  as their own. Because these are device dependent it is a good idea* _NOT_ to issue them to random objects and hope.**   THESE IOCTLS ARE _DEPRECATED_ AND WILL DISAPPEAR IN 2.5.X -DaveM*/#define SIOCDEVPRIVATE    0x89F0  /* to 89FF *//**    These 16 ioctl calls are protocol private*/#define SIOCPROTOPRIVATE 0x89E0 /* to 89EF */
#endif  /* _LINUX_SOCKIOS_H */

三 打印网卡MAC地址:SIOCGIFHWADDR命令

它对应的结构体是struct ifreq ifr;很多人搞不懂这个命令主要是不了解这个结构体,如果看到这个结构体的定义,如下所示,那就理解起来,(⊙o⊙)…,也不轻松。

#define  IFNAMSIZ    16
struct ifreq {
#define IFHWADDRLEN 6union{char ifrn_name[IFNAMSIZ];        /* if name, e.g. "en0" */} ifr_ifrn;union {struct sockaddr ifru_addr;struct   sockaddr ifru_dstaddr;struct    sockaddr ifru_broadaddr;struct  sockaddr ifru_netmask;struct  sockaddr ifru_hwaddr;short    ifru_flags;int  ifru_ivalue;int ifru_mtu;struct  ifmap ifru_map;char    ifru_slave[IFNAMSIZ];   /* Just fits the size */char    ifru_newname[IFNAMSIZ];void __user *    ifru_data;struct    if_settings ifru_settings;} ifr_ifru;
}

根据名字,ifru_hwaddr应该是用来表示硬件MAC地址的。看下struct sockaddr的结构体定义:

/**  1003.1g requires sa_family_t and that sa_data is char.*/
typedef unsigned short __kernel_sa_family_t;
typedef __kernel_sa_family_t    sa_family_t;
struct sockaddr {sa_family_t    sa_family;  /* address family, AF_xxx   */char      sa_data[14];    /* 14 bytes of protocol address */
};

sa_family_t 成员本质上是unsigned short,取值就是socket的第一个参数。

如果是取MAC地址,data中保存的就是mac地址值:原理如下:

int i = 0;
struct ifreq ifr;
ioctl(fd,SIOCGIFHWADDR,&ifr);for(i = 0;i < IFHWADDRLEN;i++)
{if(i == IFHWADDRLEN - 1){printf("0x%02x",ifr.ifr_hwaddr.sa_data[i]);}else{printf("0x%02x:",ifr.ifr_hwaddr.sa_data[i]);}
}

获取网卡实例1:ioctl.c

#include <sys/ioctl.h>
#include <unistd.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <stdlib.h>
#include <net/if.h>
int main(int argc,char *argv[])
{int fd;int i;struct ifreq ifr;fd =  socket(AF_INET,SOCK_DGRAM,0);if(fd < 0){perror("socket");exit(-1);}if(i = ioctl(fd,SIOCGIFHWADDR,&ifr)){perror("ioctl");close(fd);exit(-2);}for(i = 0;i < 6;i++){if(i == 55555){printf("0x%02x",ifr.ifr_hwaddr.sa_data[i]);}else{printf("0x%02x:",ifr.ifr_hwaddr.sa_data[i]);}}close(fd);return 0;
}

编译gcc ioctl.c -o ioctl,运行./ioctl,结果如下所示:

csdn@ubuntu:~$ ./a.out
ioctl: No such device
csdn@ubuntu:~$

提示没有设备,这是因为它需要我们让内核知道,我们需要哪一个网卡的mac地址,假设现在你知道网卡的名字是ens33,根据结构体的struct ifreq 定义可知,成员ifrn_name用于保存网卡名字,且名字最大长度是16;如下所示:

sprintf(ifr.ifr_ifrn.ifrn_name,"%s","ens33");

修改后的代码:ioctl.c

#include <sys/ioctl.h>
#include <unistd.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <stdlib.h>
#include <net/if.h>
#include <stdint.h>
int get_mac_by_name(int fd,char *name)
{int i = 0;struct ifreq ifr;sprintf(ifr.ifr_ifrn.ifrn_name,"%s",name);if(i = ioctl(fd,SIOCGIFHWADDR,&ifr)){perror("ioctl");close(fd);exit(-2);}for(i = 0;i < 6;i++){if(i == 5){printf("0x%02x\n",(uint8_t)ifr.ifr_ifru.ifru_hwaddr.sa_data[i]);}else{printf("0x%02x:",(uint8_t)ifr.ifr_ifru.ifru_hwaddr.sa_data[i]);}}return 0;
}
int main(int argc,char *argv[])
{int fd;int i;fd =  socket(AF_INET,SOCK_DGRAM,0);if(fd < 0){perror("socket");exit(-1);}get_mac_by_name(fd,"ens33");close(fd);return 0;
}

编译gcc ioctl.c -o app,运行./app,运行结果:与ifconfig结果相比,准确无误。

csdn@ubuntu:~$ ./app
0x00:0x0c:0x29:0x8c:0x05:0x15
csdn@ubuntu:~$ ifconfig | sed -n '/ens33/,+1p'
ens33     Link encap:以太网  硬件地址 00:0c:29:8c:05:15inet 地址:192.168.0.11  广播:192.168.0.255  掩码:255.255.255.0
csdn@ubuntu:~$

三 遍历网卡的名字:SIOCGIFCONF命令

SIOCGIFCONF全名大概是Socket IO Control InterFace CONFigure。或者是 Socket IO Control Internet Family CONFigure。也可能是Socket IO Control Internet inteface Family CONFigure。这都不重要,咱又不考研,知道它是获取信息的就够了。

给它的ioctl的参数是struct ifconf结构体指针。

/** Structure used in SIOCGIFCONF request.* Used to retrieve interface configuration* for machine (useful for programs which* must know all networks accessible).*/struct ifconf  {int   ifc_len;            /* size of buffer   */union {char __user *ifcu_buf;struct ifreq __user *ifcu_req;} ifc_ifcu;
}

由定义可知,ifcu_req成员可以作为一个数组来看待,ifc_len返回的就是这个数组的长度。

遍历名字,就是下面这样的,如果不知道struct ifconf结构体的定义,这个代码是看不明白的。

struct ifconf ifconf;
ioctl(fd,SIOCGIFCONF,&ifconf);
for(i = 0;i < iconf.ifc_len;i++){printf("%s",ifconf.ifc_ifcu.ifcu_req[i].ifr_ifrn.ifrn_name);
}

实例验证:ioctl.c,所需头文件和前例相同。

int main(int argc,char *argv[])
{int fd;int i;struct ifconf ifconf;fd =  socket(AF_INET,SOCK_DGRAM,0);if(fd < 0){perror("socket");exit(-1);}if(i = ioctl(fd,SIOCGIFCONF,&ifconf)){perror("ioctl");printf("ret = %d\n",i);close(fd);exit(-1);}printf("ifconf.ifc_len = %d\n",ifconf.ifc_len);for(i = 0;i < ifconf.ifc_len;i++){printf("%d:%s\n",i,ifconf.ifc_ifcu.ifcu_req[i].ifr_ifrn.ifrn_name);}close(fd);return 0;
}

编译gcc ioctl.c -o app,运行./app,结果如下所示:

csdn@ubuntu:~$ ./app
ioctl: Bad address
ret = -1
csdn@ubuntu:~$

报错,这是为什么呢?上面的分析有误,ifc_len 表示的是 size of buffer    ,char __user *ifcu_buf;

ifcu_buf成员需要指向用户空间等待缓存,所以要提前给它分配空间。我们暂且给他分配1024字节。并给这个内存清零,这样最多可以获取的接口数就是:1024/sizeof(struct ifreq)。为了简单,我们直接计算返回的网卡名字的长度,如果长度为0,说明已经获取信息完毕。

    ifconf.ifc_len = 1024;ifconf.ifc_ifcu.ifcu_buf = malloc(1024);memset(ifconf.ifc_ifcu.ifcu_buf,0,1024);if(i = ioctl(fd,SIOCGIFCONF,&ifconf)){perror("ioctl");printf("ret = %d\n",i);close(fd);exit(-1);}for(i = 0;i < ifconf.ifc_len/sizeof(struct ifreq);i++){if(strlen(ifconf.ifc_ifcu.ifcu_req[i].ifr_ifrn.ifrn_name) == 0)break;printf("%d:%s\n",i,ifconf.ifc_ifcu.ifcu_req[i].ifr_ifrn.ifrn_name);}

完整的实例代码:ioctl.c

int main(int argc,char *argv[])
{int fd;int i;struct ifconf ifconf;fd =  socket(AF_INET,SOCK_DGRAM,0);if(fd < 0){perror("socket");exit(-1);}ifconf.ifc_len = 1024;ifconf.ifc_ifcu.ifcu_buf = malloc(1024);memset(ifconf.ifc_ifcu.ifcu_buf,0,1024);if(i = ioctl(fd,SIOCGIFCONF,&ifconf)){perror("ioctl");printf("ret = %d\n",i);close(fd);exit(-1);}for(i = 0;i < ifconf.ifc_len/sizeof(struct ifreq);i++){if(strlen(ifconf.ifc_ifcu.ifcu_req[i].ifr_ifrn.ifrn_name) == 0)break;printf("%d:%s\n",i,ifconf.ifc_ifcu.ifcu_req[i].ifr_ifrn.ifrn_name);}free(ifconf.ifc_ifcu.ifcu_buf);close(fd);return 0;
}

编译gcc ioctl.c -o app,运行./app,结果如下所示:

csdn@ubuntu:~$ ./app
0:lo
1:ens33
2:ens38
csdn@ubuntu:~$

使用ifconfig获取网卡名字:和我们./app执行结果比较,完全正确是吧。

csdn@ubuntu:~$ ifconfig | sed -n '/Link encap/p'
ens33     Link encap:以太网  硬件地址 00:0c:29:8c:05:15
ens38     Link encap:以太网  硬件地址 00:0c:29:8c:05:1f
lo        Link encap:本地环回
csdn@ubuntu:~$

四 获取IP地址:SIOCGIFADDR命令

理论上SIOCGIFCONF也可以获取IP地址,但是ifr_ifru这个共用体,我还不知道它里面哪个才是有效,至少还缺少理论知识支撑。和获取MAC地址思路相同,需要提供名字,从struct ifreq结构题定义可知,ifru_addr就是返回的IP地址信息。需要将它转换struct sockaddr_in 结构体。

struct sockaddr_in {__kernel_sa_family_t sin_family; /* Address family       */__be16        sin_port;   /* Port number          */struct in_addr    sin_addr;   /* Internet address     *//* Pad to size of `struct sockaddr'. */unsigned char        __pad[__SOCK_SIZE__ - sizeof(short int) -sizeof(unsigned short int) - sizeof(struct in_addr)];
};

在这里端口信息无效,所以只关系struct in_addr    sin_addr,根据内存的布局特点,sin_addr成员对应ifru_addr.sa_data[2-5],好了,代码大概如下所示:

实例代码:ioctl.c

int get_ip_by_name(int fd,char *name)
{int i = 0;struct ifreq ifr;sprintf(ifr.ifr_ifrn.ifrn_name,"%s",name);if(i = ioctl(fd,SIOCGIFADDR,&ifr)){perror("ioctl");close(fd);exit(-2);}for(i = 0;i < 4;i++){if(i == 3){printf("%d\n",(uint8_t)ifr.ifr_ifru.ifru_addr.sa_data[2 + i]);}else{printf("%d:",(uint8_t)ifr.ifr_ifru.ifru_addr.sa_data[2 + i]);}}return 0;
}
int main(int argc,char *argv[])
{int fd;int i;fd =  socket(AF_INET,SOCK_DGRAM,0);if(fd < 0){perror("socket");exit(-1);}get_ip_by_name(fd,"ens33");close(fd);return 0;
}

编译gcc ioctl.c -o app,运行./app,结果如下所示:

csdn@ubuntu:~$ ./app
192:168:0:11
csdn@ubuntu:~$

使用ifconfig验证结果:sed -n '/ens33/,+1p'表示匹配ens33所在的行,并多显示一行。

csdn@ubuntu:~$ ifconfig | sed -n '/ens33/,+1p'
ens33     Link encap:以太网  硬件地址 00:0c:29:8c:05:15inet 地址:192.168.0.11  广播:192.168.0.255  掩码:255.255.255.0
csdn@ubuntu:~$

五 综合:遍历MAC+IP实例

借助本章学到的三个命令,写一个遍历网口名字、MAC地址和IP地址的小代码:ioctl.c

#include <sys/ioctl.h>
#include <string.h>
#include <unistd.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <stdlib.h>
#include <net/if.h>
#include <stdint.h>int get_mac_by_name(int fd,char *name)
{int i = 0;struct ifreq ifr;sprintf(ifr.ifr_ifrn.ifrn_name,"%s",name);if(i = ioctl(fd,SIOCGIFHWADDR,&ifr)){perror("ioctl");close(fd);exit(-2);}for(i = 0;i < 6;i++){if(i == 5){printf("0x%02x\n",(uint8_t)ifr.ifr_ifru.ifru_hwaddr.sa_data[i]);}else{printf("0x%02x:",(uint8_t)ifr.ifr_ifru.ifru_hwaddr.sa_data[i]);}}return 0;
}
int get_ip_by_name(int fd,char *name);
int show_all_net_interface_name(int fd)
{int i = 0;struct ifconf ifconf;ifconf.ifc_len = 1024;ifconf.ifc_ifcu.ifcu_buf = malloc(1024);memset(ifconf.ifc_ifcu.ifcu_buf,0,1024);if(i = ioctl(fd,SIOCGIFCONF,&ifconf)){perror("ioctl");printf("ret = %d\n",i);close(fd);exit(-1);}for(i = 0;i < ifconf.ifc_len/sizeof(struct ifreq);i++){if(strlen(ifconf.ifc_ifcu.ifcu_req[i].ifr_ifrn.ifrn_name) == 0)break;printf("%d:%s\n",i,ifconf.ifc_ifcu.ifcu_req[i].ifr_ifrn.ifrn_name);printf("ip:");get_ip_by_name(fd,ifconf.ifc_ifcu.ifcu_req[i].ifr_ifrn.ifrn_name);printf("mac:");get_mac_by_name(fd,ifconf.ifc_ifcu.ifcu_req[i].ifr_ifrn.ifrn_name);printf("\n");}free(ifconf.ifc_ifcu.ifcu_buf);return 0;
}
int get_ip_by_name(int fd,char *name)
{int i = 0;struct ifreq ifr;sprintf(ifr.ifr_ifrn.ifrn_name,"%s",name);if(i = ioctl(fd,SIOCGIFADDR,&ifr)){perror("ioctl");close(fd);exit(-2);}for(i = 0;i < 4;i++){if(i == 3){printf("%d\n",(uint8_t)ifr.ifr_ifru.ifru_addr.sa_data[2 + i]);}else{printf("%d:",(uint8_t)ifr.ifr_ifru.ifru_addr.sa_data[2 + i]);}}return 0;
}
int main(int argc,char *argv[])
{int fd;int i;fd =  socket(AF_INET,SOCK_DGRAM,0);if(fd < 0){perror("socket");exit(-1);}show_all_net_interface_name(fd);close(fd);return 0;
}

编译gcc ioctl.c -o app,运行./app,结果如下所示:

csdn@ubuntu:~$ ./app
0:lo
ip:127:0:0:1
mac:0x00:0x00:0x00:0x00:0x00:0x001:ens33
ip:192:168:0:11
mac:0x00:0x0c:0x29:0x8c:0x05:0x152:ens38
ip:192:168:31:148
mac:0x00:0x0c:0x29:0x8c:0x05:0x1fcsdn@ubuntu:~$

使用ifconfig验证结果:ifconfig | sed -n '/Link encap/,+1p'

csdn@ubuntu:~$ ifconfig | sed -n '/Link encap/,+1p'
ens33     Link encap:以太网  硬件地址 00:0c:29:8c:05:15inet 地址:192.168.0.11  广播:192.168.0.255  掩码:255.255.255.0
ens38     Link encap:以太网  硬件地址 00:0c:29:8c:05:1finet 地址:192.168.31.148  广播:192.168.31.255  掩码:255.255.255.0
lo        Link encap:本地环回inet 地址:127.0.0.1  掩码:255.0.0.0
csdn@ubuntu:~$

小结

第二篇:网络ioctl实践2:获取网卡的广播地址和子网掩码

网络ioctl实践1:获取网卡的MAC和IP相关推荐

  1. 网络ioctl实践3:设置网卡的mac、ip、子网掩码、广播地址

    前言 网络ioctl实践1:获取网卡的MAC和IP 网络ioctl实践2:获取网卡的广播地址和子网掩码 本文使用的命令是: Request 说明 数据类型 对应的union成员 SIOCSIFADDR ...

  2. Python # 扫描端口功能 # 获取网卡的Mac地址 # 局域网扫描器IP地址和MAC地址,获取网卡名称和其ip地址

    #!/usr/bin/env python # -*- coding: utf-8 -*- # 开发人员: # time: 2021-09-07 20:37 # 开发工具: PyCharm # Ver ...

  3. 结合WMI和DeviceIoControl获取网卡原生MAC地址和当前MAC地址

    虽然Win32_NetworkAdapter包含了属性PermanentAddress,但是在当前的WMI里只是个空值,微软目前还没有实现这个属性值.但是我们仍可以通过结合WMI和DeviceIoCo ...

  4. java获取网卡正真的mac_java获取网卡的mac地址

    为了项目的安全,有时候需要得到电脑的唯一码,比如:网卡的mac地址.和大家分享一下,下面是项目中用到的工具类:/** * 获取Mac地址 * @return */ public String getM ...

  5. Windows上获取网卡的mac地址

    最近,搞了一个Windows工具,需要获取网卡mac, 这个太熟悉了,之前也经常玩,搞起: #include <stdio.h> #include <winsock2.h> # ...

  6. java获取网卡的mac地址

    为了项目的安全,有时候需要得到电脑的唯一码,比如:网卡的mac地址.和大家分享一下,下面是项目中用到的工具类: import java.io.BufferedReader; import java.i ...

  7. iphone开发之获取网卡的MAC地址和IP地址

    这是获取网卡的硬件地址的代码,如果无法编译通过,记得把下面的这几个头文件加上把. #include <sys/socket.h> // Per msqr #include <sys/ ...

  8. Android中获取手机 IMEI Mac地址 IP地址

    一.获取手机IMEI 手机在生产时,每部手机均有一个唯一的标识(ID),国际上采用国际移动设备身份码(IMEI, International Mobile Equipment Identity).IM ...

  9. qt准确获取本机mac和ip地址

    前言 公司服务器有多个mac地址,是用网上的代码获取时总是不准确,只能自己封装一下.qt通过QNetworkInterface类来获取网络接口的各种信息,我是通过解析QNetworkInterface ...

最新文章

  1. redis 代理工具Predixy安装部署
  2. Microbiome:所谓的“富集培养”获得的微生物真的都是被“富集”出来的吗?
  3. 第11章:项目风险管理(2)—章节重点
  4. hadoop基石HDFS
  5. ORA-00020:maximum number of processes (150) exceeded 错误解决方法
  6. vs2005 vc++ 生成非托管的 不需要.net运行环境的exe程序方法
  7. 解决VSCODE因为在此系统上禁止运行脚本报错
  8. 怎么测试本地网页在不同分辨率下电脑显示效果_汇总一波百万高清壁纸站,8K分辨率的都有...
  9. 朝会資料  幕末の歴史の簡単紹介 2010年8月30日
  10. CRM 实施计划和准备的8个步骤!
  11. Android 上千实例源码分析以及开源分析
  12. 项目管理工具与技术---项目风险管理中的工具与技术
  13. Abaqus设置初始地应力场
  14. Centos 7 Opencv安装使用
  15. 狂热分子——码头工人的哲学沉思录
  16. turtle绘制奥运五环
  17. 树莓派4b主板特点_树莓派4B的入手操作
  18. 基于SSM的培训班管理系统
  19. Linux系统更改时区
  20. unicode转中文

热门文章

  1. 基于POA搭建ETH联盟链
  2. pycharm 明明解释器里已经下载了sklearn,但还是显示找不到sklearn解决办法
  3. 全球与中国集成平台即服务(iPaaS)软件市场现状及未来发展趋势
  4. Java数据对象(JDO)快速入门
  5. utest:检验U型和倒U形关系
  6. 计算机系毕业祝福语,搞笑开心的毕业祝福语
  7. 如何搭建 Jenkins 自动化测试平台?
  8. android 中打电话,Android 在 APP 中实现拨打电话的方法
  9. 公众号视频查找接口,支持自定义接口,支持水印
  10. 克莱茵瓶&莫比乌斯带