红联Linux门户
Linux帮助

Linux下获取网络接口信息

发布时间:2016-08-21 09:47:13来源:linux网站作者:便当君
Linux下的网络接口信息在shell下可以很方便地使用ifconfig查看。同样,使用C/C++也可以很方便地获取接口信息。
netdevice是一个低级别的访问Linux网络设备的方法。此方法通过ioctl来获取网络接口的相关信息。
这里需要借助<net/if.h>头文件中定义的ifreq结构体。此结构体包含了网络接口的名称、IP地址、广播地址、网络地址、掩码等相关信息。在获取上述相关信息的时候需要指明网络接口的名称。
 
struct ifreq {
char ifr_name[IFNAMSIZ]; /* Interface name */
union {
struct sockaddr ifr_addr;
struct sockaddr ifr_dstaddr;
struct sockaddr ifr_broadaddr;
struct sockaddr ifr_netmask;
struct sockaddr ifr_hwaddr;
short           ifr_flags;
int             ifr_ifindex;
int             ifr_metric;
int             ifr_mtu;
struct ifmap    ifr_map;
char            ifr_slave[IFNAMSIZ];
char            ifr_newname[IFNAMSIZ];
char           *ifr_data;
};
};
 
ifreq结构体的定义如上图所示,此结构体中包含了一段联合体,它们共享一段内存空间。
int ioctl(int fd, unsigned long request, ...);
ioctl()函数此处可以用于获取网络接口信息。fd为打开的文件指针,此处可以为任意类型的socket(套接字),一般使用
int sockfd = socket(AF_INET, SOCK_DGRAM, 0)
由于网络接口信息对应变量共享一段内存,所以每次使用ioctl请求得到的网络接口信息只能是一种。对应不同的网络接口
 
信息可以使用不同的请求常量。
//用于请求硬件地址
SIOCGIFHWADDR      
//用于请求IP地址                       
SIOCGIFADDR                                     
//用于请求IP广播地址
SIOCGIFBRDADDR
//用于请求子网掩码
SIOCGIFNETMASK
 
ioctl()的第三个参数需要传入一个ifreq结构体的指针,用做输入输出参数。
在编写程序的时候遇到的小问题:
1)用什么结构体来存取硬件地址信息(mac地址)?硬件地址信息如何转换为可以输出的字符串类型?
2)DNS相关信息如何获取?
3)std::string如何查找和拷贝字符串?
 
1.使用ether_addr来存储硬件地址信息。这个结构体位于<netinet/ether.h>头文件中,使用ioctl获取到硬件地址后可以使用内存拷贝的方法将值拷贝至ether_addr当中。ether_addr可以通过ether_ntoa()函数转换成字符数组的形式。此函数同样位于<netinet/ether.h>头文件中,可以使用命令man ether_ntoa来查看更多相关信息。
 
2.主流Linux桌面发行版使用的Network Manager作为网络管理器,这个网络管理器会在etc目录下生成一个resolv.conf文件,里面包含了当前DNS的相关信息。可以采用读这个文件的方式来获取DNS信息。
 
3.C++ string常用操作可以其它文章,查找字符串通常使用find()函数,给新字符串分配已有字符串的一部分可以使用assign() 函数。
 
附上完整程序:
m_netdevice.h
#ifndef M_NETDEVICE_H
#define M_NETDEVICE_H
#include <st_header.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <netinet/ether.h>
#include <net/if.h>
#include <sys/ioctl.h>
#include <string.h>
#include <iostream>
#include <fstream>
#include <vector>
#include <string>
struct Netdev_int
{
struct deviceInfo {
char int_name[IFNAMSIZ];
sockaddr_in ip_addr;
sockaddr_in bc_addr;
sockaddr_in net_mask;
ether_addr hw_addr;
std::vector<std::string> dns_name;
std::vector<std::string> dns_addr;
} m_dev;
void getIfInfo(char *if_name);
void printDeviceInfo();
void help();
};
#endif // M_NETDEVICE_H
 
m_netdevice.cpp
#include <m_netdevice.h>
void Netdev_int::getIfInfo(char *if_name)
{
struct ifreq ifr;
memcpy(ifr.ifr_ifrn.ifrn_name, if_name, strlen(if_name));
memcpy(m_dev.int_name, if_name, strlen(if_name));
int sockfd = socket(AF_INET, SOCK_STREAM, 0);
if(ioctl(sockfd, SIOCGIFHWADDR, &ifr) == -1)
{
perror("ioctl error");
exit(1);
}
memcpy(&m_dev.hw_addr, (ether_addr*)ifr.ifr_ifru.ifru_hwaddr.sa_data,
sizeof(ether_addr));
if(ioctl(sockfd, SIOCGIFADDR, &ifr) == -1)
{
perror("ioctl error");
exit(1);
}
memcpy(&m_dev.ip_addr, (sockaddr_in*)&ifr.ifr_ifru.ifru_addr,
sizeof(sockaddr_in));
if(ioctl(sockfd, SIOCGIFBRDADDR, &ifr) == -1)
{
perror("ioctl error");
exit(1);
}
memcpy(&m_dev.bc_addr, (sockaddr_in*)&ifr.ifr_ifru.ifru_broadaddr,
sizeof(sockaddr_in));
if(ioctl(sockfd, SIOCGIFNETMASK, &ifr) == -1)
{
perror("ioctl error");
exit(1);
}
memcpy(&m_dev.net_mask, (sockaddr_in*)&ifr.ifr_ifru.ifru_netmask,
sizeof(sockaddr_in));
std::ifstream in;
in.open("/etc/resolv.conf");
std::string str;
while(std::getline(in, str))
{
if(str.at(0) == '#') continue;
int pos = str.find_first_of(' ');
std::string d_name;
std::string d_addr;
d_name.assign(str, 0, pos);
d_addr.assign(str, pos, str.length());
m_dev.dns_name.push_back(d_name);
m_dev.dns_addr.push_back(d_addr);
}
}
void Netdev_int::printDeviceInfo()
{
std::cout << m_dev.int_name << std::endl;
std::cout << "Hardware Address:" << ether_ntoa(&m_dev.hw_addr) << std::endl;
std::cout << "IP Address:" << inet_ntoa(m_dev.ip_addr.sin_addr) << std::endl;
std::cout << "Boardcast Address:" << inet_ntoa(m_dev.bc_addr.sin_addr) << std::endl;
std::cout << "Net Mask:" << inet_ntoa(m_dev.net_mask.sin_addr) << std::endl;
std::vector<std::string>::iterator it2addr = m_dev.dns_addr.begin();
for(std::vector<std::string>::iterator it = m_dev.dns_name.begin();
it != m_dev.dns_name.end(); it++)
{
std::cout << *it << ":" << *it2addr << std::endl;
it2addr++;
}
}
void Netdev_int::help()
{
std::cout << "ifdev if_name" << std::endl;
std::cout << "for example:" << std::endl;
std::cout << "ifdev eth0" << std::endl;
}
 
st_header.h
#ifndef ST_HEADER_H
#define ST_HEADER_H
#include <error.h>
#endif // ST_HEADER_H
 
main.cpp
#include <iostream>
#include <m_netdevice.h>
using namespace std;
int main(int argc, char **argv)
{
Netdev_int *netdev_int = new Netdev_int();
if(argc == 1) {
netdev_int->help();
}
else {
netdev_int->getIfInfo(argv[1]);
netdev_int->printDeviceInfo();
}
}
 
本文永久更新地址:http://www.linuxdiyf.com/linux/23492.html