在linux中我们获取wan lan 的ip地址等信息通常是通过 ifconfig 命令来获取的,然而ifconfig命令实际上是通过ioctl接口与内核通信,ifconfig命令首先会打开一个socket,然后调用ioctl将request传递到内核,从而获取request请求数据
ioctl的关于网络相关的请求可以划分为6类
套接口操作
文件操作
接口操作
ARP高速缓存操作
路由表操作
流系统
获取ipaddress 归属于接口操作,在ioctl中第二个参数决定了你将通过内核获取到的数据
而其中能获取到ip地址是离不开 struct ifreq 的
结构体定义:
ifreq结构定义在/usr/include/net/if.h,用来配置ip地址,激活接口,配置MTU等接口信息的。
其中包含了一个接口的名字和具体内容—(是个共用体,有可能是IP地址,广播地址,子网掩码,MAC号,MTU或其他内容)。
ifreq包含 在ifconf结构中。而ifconf结构通常是用来保存所有接口的信息的。
结构体struct ifreq:
struct ifreq
{
#define IFHWADDRLEN 6
union
{
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;
};
#define ifr_name ifr_ifrn.ifrn_name /* interface name */
#define ifr_hwaddr ifr_ifru.ifru_hwaddr /* MAC address */
#define ifr_addr ifr_ifru.ifru_addr /* address */
#define ifr_dstaddr ifr_ifru.ifru_dstaddr /* other end of p-p lnk */
#define ifr_broadaddr ifr_ifru.ifru_broadaddr /* broadcast address */
#define ifr_netmask ifr_ifru.ifru_netmask /* interface net mask */
#define ifr_flags ifr_ifru.ifru_flags /* flags */
#define ifr_metric ifr_ifru.ifru_ivalue /* metric */
#define ifr_mtu ifr_ifru.ifru_mtu /* mtu */
#define ifr_map ifr_ifru.ifru_map /* device map */
#define ifr_slave ifr_ifru.ifru_slave /* slave device */
#define ifr_data ifr_ifru.ifru_data /* for use by interface */
#define ifr_ifindex ifr_ifru.ifru_ivalue /* interface index */
#define ifr_bandwidth ifr_ifru.ifru_ivalue /* link bandwidth */
#define ifr_qlen ifr_ifru.ifru_ivalue /* Queue length */
#define ifr_newname ifr_ifru.ifru_newname /* New name */
#define ifr_settings ifr_ifru.ifru_settings /* Device/proto settings*/
结构体 struct ifconf:
struct ifconf{
lint ifc_len;
union{
caddr_t ifcu_buf
Struct ifreq *ifcu_req;
}ifc_ifcu
}
#define ifc_buf ifc_ifcu.ifcu_buf
#define ifc_req ifc_ifcu.ifcu_req
示例:获取lan ipadress:
/* get lan interface ipaddr */
int getLanAddr(const char *ifname, char *addr, int len)
{
struct ifreq ifr;
int sockfd, ret = 0;
if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
return -1;
bzero(ifr.ifr_name, sizeof(ifr.ifr_name));
memcpy(ifr.ifr_name, ifname, strlen(ifname));
if (ioctl(sockfd, SIOCGIFADDR, &ifr))
ret = -1;
else
{
char *temp = inet_ntoa(((struct sockaddr_in *)&(ifr.ifr_addr))->sin_addr);
memcpy(addr, temp, len);
}
close(sockfd);
return ret;
}
通过ifconfig得:
因此要获得lan地址
- 建立 socket
- 将 “br-lan” 放入ifr.ifr_name
- 因为获取的是lan地址,所以ioctl第二个参数选择 SIOCGIFADDR
- 从ifr.ifr_addr获取 ip地址
- 关闭 socket