📄 netlink.htm
字号:
/* Data follows */
};
</pre>
ifi_type:这个字段包含了硬件的类型,可以参考<linux/if_arp.h>比较常见的是
<pre>
ARPHRD_ETHER 10M以太网
ARPHRD_PPP PPP拨号
ARPHRD_LOOPBACK 环路设备
</pre>
ifi_flags:这个字段包含了设备的一些标志,相应的值为:
<pre>
IFF_UP 接口正在运行.
IFF_BROADCAST 有效的广播地址集.
IFF_DEBUG 内部调试标志.
IFF_LOOPBACK 这是自环接口.
IFF_POINTOPOINT 这是点到点的链路接口.
IFF_RUNNING 资源已分配.
IFF_NOARP 无arp协议, 没有设置第二层目的地址.
IFF_PROMISC 接口为杂凑(promiscuous)模式.
IFF_NOTRAILERS 避免使用trailer .
IFF_ALLMULTI 接收所有组播(multicast)报文.
IFF_MASTER 主负载平衡群(bundle).
IFF_SLAVE 从负载平衡群(bundle).
IFF_MULTICAST 支持组播(multicast).
IFF_PORTSEL 可以通过ifmap选择介质(media)类型.
IFF_AUTOMEDIA 自动选择介质.
IFF_DYNAMIC 接口关闭时丢弃地址.
</pre>
rta_type:这个字段指定属性的类型,相应的值为:
<pre>
IFLA_UNSPEC 后面的数据格式未指定
IFLA_ADDRESS 后面的数据是一个硬件地址
IFLA_BROADCAST 后面的数据是一个硬件广播地址
IFLA_IFNAME 后面的数据是一个char型的设备名称
IFLA_MTU unsigned int型的设备MTU值
IFLA_LINK int型的链路类型
IFLA_QDISC 字符串型的队列规则
IFLA_STATS struct net_device_stats型的设备信息
</pre>
在我们接收和发送数据的时候为了我们获取属性的方便,rtnetlink提供了一个宏供我们取获取其中的结构,这些宏的定义为:
<pre>
#include <asm/types.h>
#include <linux/netlink.h>
#include <linux/rtnetlink.h>
#include <sys/socket.h>
int RTA_OK(struct rtattr *rta, int rtabuflen);
void *RTA_DATA(struct rtattr *rta);
unsigned int RTA_PAYLOAD(struct rtattr *rta);
struct rtattr *RTA_NEXT(struct rtattr *rta, unsigned int rtabuflen);
unsigned int RTA_LENGTH(unsigned int length);
unsigned int RTA_SPACE(unsigned int length);
</pre>
下面是一个用来获取所有网卡信息的例子.
<pre style="border:1px blue solid">
<font color="#8080ff"><b>#include </b></font><font color="#ff40ff"><b><stdio.h></b></font>
<font color="#8080ff"><b>#include </b></font><font color="#ff40ff"><b><string.h></b></font>
<font color="#8080ff"><b>#include </b></font><font color="#ff40ff"><b><errno.h></b></font>
<font color="#8080ff"><b>#include </b></font><font color="#ff40ff"><b><sys/socket.h></b></font>
<font color="#8080ff"><b>#include </b></font><font color="#ff40ff"><b><sys/types.h></b></font>
<font color="#8080ff"><b>#include </b></font><font color="#ff40ff"><b><unistd.h></b></font>
<font color="#8080ff"><b>#include </b></font><font color="#ff40ff"><b><asm/types.h></b></font>
<font color="#8080ff"><b>#include </b></font><font color="#ff40ff"><b><linux/netlink.h></b></font>
<font color="#8080ff"><b>#include </b></font><font color="#ff40ff"><b><linux/rtnetlink.h></b></font>
<font color="#8080ff"><b>#include </b></font><font color="#ff40ff"><b><linux/netdevice.h></b></font>
<font color="#8080ff"><b>#include </b></font><font color="#ff40ff"><b><net/if_arp.h></b></font>
<font color="#8080ff"><b>#include </b></font><font color="#ff40ff"><b><netinet/if_ether.h></b></font>
<font color="#8080ff"><b>#include </b></font><font color="#ff40ff"><b><netinet/ether.h></b></font>
<font color="#00ff00"><b>int</b></font> main()
{
<font color="#00ff00"><b>int</b></font> nSocket, nLen, nAttrLen;
<font color="#00ff00"><b>char</b></font> szBuffer[<font color="#ff40ff"><b>4096</b></font>];
<font color="#00ff00"><b>struct</b></font> {
<font color="#00ff00"><b>struct</b></font> nlmsghdr nh;
<font color="#00ff00"><b>struct</b></font> ifinfomsg ifi;
}struReq;
<font color="#00ff00"><b>struct</b></font> sockaddr_nl struAddr;
<font color="#00ff00"><b>struct</b></font> nlmsghdr *pstruNL;
<font color="#00ff00"><b>struct</b></font> ifinfomsg *pstruIF;
<font color="#00ff00"><b>struct</b></font> rtattr *pstruAttr;
<font color="#00ff00"><b>struct</b></font> net_device_stats *pstruInfo;
<font color="#00ff00"><b>struct</b></font> ether_addr *pstruEther;
<font color="#00ffff"><b>/*</b></font>
<font color="#00ffff"><b> * 创建一个PF_NETLINK的SOCKET,使用NETLINK_ROUTE协议</b></font>
<font color="#00ffff"><b> </b></font><font color="#00ffff"><b>*/</b></font>
nSocket = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE);
<font color="#ffff00"><b>if</b></font>(nSocket < <font color="#ff40ff"><b>0</b></font>)
{
fprintf(<font color="#ff40ff"><b>stderr</b></font>, <font color="#ff40ff"><b>"创建SOCKET错误:</b></font><font color="#ff6060"><b>%s</b></font><font color="#ff6060"><b>\n</b></font><font color="#ff40ff"><b>"</b></font>, strerror(errno));
<font color="#ffff00"><b>return</b></font> -<font color="#ff40ff"><b>1</b></font>;
}
<font color="#00ffff"><b>/*</b></font>
<font color="#00ffff"><b> * 绑定地址</b></font>
<font color="#00ffff"><b> </b></font><font color="#00ffff"><b>*/</b></font>
memset(&struAddr, <font color="#ff40ff"><b>0</b></font>, <font color="#ffff00"><b>sizeof</b></font>(struAddr));
struAddr.nl_family = AF_NETLINK;
struAddr.nl_pid = getpid();
struAddr.nl_groups = <font color="#ff40ff"><b>0</b></font>;
<font color="#ffff00"><b>if</b></font>(bind(nSocket, (<font color="#00ff00"><b>struct</b></font> sockaddr *)&struAddr, <font color="#ffff00"><b>sizeof</b></font>(struAddr)) < <font color="#ff40ff"><b>0</b></font>)
{
fprintf(<font color="#ff40ff"><b>stderr</b></font>, <font color="#ff40ff"><b>"绑定SOCKET错误:</b></font><font color="#ff6060"><b>%s</b></font><font color="#ff6060"><b>\n</b></font><font color="#ff40ff"><b>"</b></font>, strerror(errno));
<font color="#ffff00"><b>return</b></font> -<font color="#ff40ff"><b>1</b></font>;
}
<font color="#00ffff"><b>/*</b></font>
<font color="#00ffff"><b> * 发送一个请求</b></font>
<font color="#00ffff"><b> </b></font><font color="#00ffff"><b>*/</b></font>
memset(&struReq, <font color="#ff40ff"><b>0</b></font>, <font color="#ffff00"><b>sizeof</b></font>(struReq));
struReq.nh.nlmsg_len = NLMSG_LENGTH(<font color="#ffff00"><b>sizeof</b></font>(struReq));
struReq.nh.nlmsg_type = RTM_GETLINK;
struReq.nh.nlmsg_flags = NLM_F_REQUEST | NLM_F_DUMP;
struReq.ifi.ifi_family = AF_UNSPEC;
memset(&struAddr, <font color="#ff40ff"><b>0</b></font>, <font color="#ffff00"><b>sizeof</b></font>(struAddr));
struAddr.nl_family = AF_NETLINK;
struAddr.nl_pid = <font color="#ff40ff"><b>0</b></font>;
struAddr.nl_groups = <font color="#ff40ff"><b>0</b></font>;
<font color="#ffff00"><b>if</b></font>(sendto(nSocket, &struReq, struReq.nh.nlmsg_len, <font color="#ff40ff"><b>0</b></font>,
(<font color="#00ff00"><b>struct</b></font> sockaddr *)&struAddr, <font color="#ffff00"><b>sizeof</b></font>(struAddr)) < <font color="#ff40ff"><b>0</b></font>)
{
fprintf(<font color="#ff40ff"><b>stderr</b></font>, <font color="#ff40ff"><b>"发送数据错误:</b></font><font color="#ff6060"><b>%s</b></font><font color="#ff6060"><b>\n</b></font><font color="#ff40ff"><b>"</b></font>, strerror(errno));
<font color="#ffff00"><b>return</b></font> -<font color="#ff40ff"><b>1</b></font>;
}
<font color="#00ffff"><b>/*</b></font>
<font color="#00ffff"><b> * 循环接收数据,直到超时</b></font>
<font color="#00ffff"><b> </b></font><font color="#00ffff"><b>*/</b></font>
alarm(<font color="#ff40ff"><b>30</b></font>);
memset(szBuffer, <font color="#ff40ff"><b>0</b></font>, <font color="#ffff00"><b>sizeof</b></font>(szBuffer));
<font color="#ffff00"><b>while</b></font>((nLen = recv(nSocket, szBuffer, <font color="#ffff00"><b>sizeof</b></font>(szBuffer), <font color="#ff40ff"><b>0</b></font>)))
{
alarm(<font color="#ff40ff"><b>0</b></font>);
pstruNL = (<font color="#00ff00"><b>struct</b></font> nlmsghdr *)szBuffer;
<font color="#00ffff"><b>/*</b></font>
<font color="#00ffff"><b> * 判断是否继续有数据</b></font>
<font color="#00ffff"><b> </b></font><font color="#00ffff"><b>*/</b></font>
<font color="#ffff00"><b>while</b></font>(NLMSG_OK(pstruNL, nLen))
{
<font color="#00ffff"><b>/*</b></font>
<font color="#00ffff"><b> * 数据已经获取完成</b></font>
<font color="#00ffff"><b> </b></font><font color="#00ffff"><b>*/</b></font>
<font color="#ffff00"><b>if</b></font>(pstruNL -> nlmsg_type == NLMSG_DONE)
<font color="#ffff00"><b>break</b></font>;
<font color="#ffff00"><b>if</b></font>(pstruNL -> nlmsg_type == NLMSG_ERROR)
{
<font color="#00ffff"><b>/*</b></font>
<font color="#00ffff"><b> * 发生一个错误</b></font>
<font color="#00ffff"><b> </b></font><font color="#00ffff"><b>*/</b></font>
<font color="#00ff00"><b>struct</b></font> nlmsgerr *pstruError;
pstruError = (<font color="#00ff00"><b>struct</b></font> nlmsgerr *)NLMSG_DATA(pstruNL);
fprintf(<font color="#ff40ff"><b>stderr</b></font>, <font color="#ff40ff"><b>"发生错误[</b></font><font color="#ff6060"><b>%s</b></font><font color="#ff40ff"><b>]</b></font><font color="#ff6060"><b>\n</b></font><font color="#ff40ff"><b>"</b></font>,
strerror(-pstruError -> error));
<font color="#ffff00"><b>break</b></font>;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -