linux下底层函数实现MAC、IP地址以及网关地址

l1.Linux系统中获取网卡信息
获取网卡信息有两种方法。一种是读取系统文件。一种是通过系统API进行获取。

通过系统API进行获取:
主要是使用两个结构体struct ifconf 和struct ifreq。Ifconf结构主要有两个成员,一个是用来表示长度的,还有一个是指向struct ifreq的指针。通过ifc_buf和ifc_req来分贝访问。
具体步骤是:首先创建socket套接字(SOCK_DGRAME类型),然后再通过ioctl(sockfd, SIOCGCONF, &ifconf);这样就可以获得网卡所有信息了,然后再通过操作irconf,把ifc_req指向的ifreq数组中的网卡信息取出来就可以了。

struct ifreq
{
#define IFHWADDRLEN 6 //6个字节的硬件地址,即MAC
union{
char ifrn_name[IFNAMESIZ];//网络接口名称
}ifr_ifrn;
union{
struct sockaddr ifru_addr;//本地IP地址
struct sockaddr ifru_dstaddr;//目标IP地址
struct sockaddr ifru_broadaddr;//广播IP地址
struct sockaddr ifru_netmask;//本地子网掩码地址
struct sockaddr ifru_hwaddr;//本地MAC地址
short ifru_flags;//网络接口标记
int ifru_ivalue;//不同的请求含义不同
struct ifmap ifru_map;//网卡地址映射
int ifru_mtu;//最大传输单元
char ifru_slave[IFNAMSIZ];//占位符
char ifru_newname[IFNAMSIZE];//新名称
void __user* ifru_data;//用户数据
struct if_settings ifru_settings;//设备协议设置
}ifr_ifru;
}
#define ifr_name ifr_ifrn.ifrn_name;//接口名称
#define ifr_hwaddr ifr_ifru.ifru_hwaddr;//MAC
#define ifr_addr ifr_ifru.ifru_addr;//本地IP
#define ifr_dstaddr ifr_ifru.dstaddr;//目标IP
#define ifr_broadaddr ifr_ifru.broadaddr;//广播IP
#define ifr_netmask ifr_ifru.ifru_netmask;//子网掩码
#define ifr_flags ifr_ifru.ifru_flags;//标志
#define ifr_metric ifr_ifru.ifru_ivalue;//接口侧度
#define ifr_mtu ifr_ifru.ifru_mtu;//最大传输单元
#define ifr_map ifr_ifru.ifru_map;//设备地址映射
#define ifr_slave ifr_ifru.ifru_slave;//副设备
#define ifr_data ifr_ifru.ifru_data;//接口使用
#define ifr_ifrindex ifr_ifru.ifru_ivalue;//网络接口序号
#define ifr_bandwidth ifr_ifru.ifru_ivalue;//连接带宽
#define ifr_qlen ifr_ifru.ifru_ivalue;//传输单元长度
#define ifr_newname ifr_ifru.ifru_newname;//新名称
#define ifr_seeting ifr_ifru.ifru_settings;//设备协议设置
struct ifmap
{//网卡设备的映射属性
unsigned long mem_start;//开始地址
unsigned long mem_end;//结束地址
unsigned short base_addr;//基地址
unsigned char irq; //中断号
unsigned char dma; //DMA
unsigned char port; //端口
} ;

struct ifconf
{//网络配置结构体是一种缓冲区
int ifc_len;//缓冲区ifr_buf的大小
Union
{
char__user *ifcu_buf;//绘冲区指针
struct ifreq__user* ifcu_req;//指向ifreq指针
}ifc_ifcu;
};

函数ioctl()函数详解:
Ioctl是设备驱动程序中对设备的I/O通道进行管理的函数,所谓的I/O通道管理,就是对设备的一些特性进行控制。

函数原型:
Int ioctl(int fd, int cmd, …);
其中fd是用户程序打开设备时使用open函数返回的文件标识符,cmd是用户程序对设备的控制命令,至于后面的省略号,是一些补充参数,一般最多一个,这个参数的有无核cmd的意义相关。
备注:要记住,用户程序所作的只是通过命令码(cmd)告诉驱动程序它想要做什么,至于怎么解释这些命令和怎么实现这些命令,这都是驱动程序要做的事情。

使用API接口获得指定网卡的IP地址:
void GetEthIP(uint8 * eth_name,uint8 *ip_addr)
{
struct ifreq eth_if;
int sock_fd;
strncpy(eth_if.ifr_name,(char *)eth_name,sizeof(eth_if.ifr_name));
sock_fd=socket(AF_INET,SOCK_DGRAM,0);
ioctl(sock_fd,SIOCGIFADDR,&eth_if);
int i;
for(i=2;i<6;i++)
{
ip_addr[i-2]=eth_if.ifr_addr.sa_data[i];
}
}

使用API接口获取指定网卡的物理地址:

void GetEthMAC(uint8 * eth_name , uint8 *mac)
{
struct ifreq eth_if;
int sock_fd;
strncpy(eth_if.ifr_name,(char *)eth_name,sizeof(eth_if.ifr_name));
sock_fd=socket(AF_INET,SOCK_DGRAM,0);
ioctl(sock_fd,SIOCGIFHWADDR,&eth_if);
int i;
for(i=0;i<6;i++)
{
mac[i]=eth_if.ifr_hwaddr.sa_data[i];
}
}

获取网关的地址:
通过读取系统文件可以获取网卡信息,难点在于对文件的处理。通过/proc/net/route文件即可以获取网关的地址。

Proc方法获取网关的地址:
Void GetGateWayIP(uint8 *ip_addr)
{
Char inf[100];
FILE *file_fd;
Uint8 high=0,low=0,value;
Int i;
File_fd = fopen(“/proc/net/route”,”r”);
If(file_fd == NULL)
{
Printf(“can not open /proc/net/route\n”);
}
Else
{
While(!feof(file_fd))
{
Memset(inf,0,sizeof(inf));
Fgets(inf,100,file_fd);
if(inf[5]==’0’&&inf[6]==’0’&&inf[7]==’0’&&inf[8]==’0’&&inf[9]==’0’&&inf[10]==’0’&&inf[11]==’0’&&inf[12]==’0’)
{
for(i=20;i>=14;i-=2)
{
if(inf[i]>=65)
high = inf[i]-55;
else
high = inf[i]-48;
if(inf[i+1]>=65)
low = inf[i+1]-55;
else
low = inf[i+1]-48;
value = high*16+low;
ip_addr[10-i/2] = value;
}
break;
}}
}
}

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值