⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 netlink.htm

📁 netlink编程
💻 HTM
📖 第 1 页 / 共 5 页
字号:
                  /* Data follows */
              };
</pre>
ifi_type:这个字段包含了硬件的类型,可以参考&lt;linux/if_arp.h&gt;比较常见的是
<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 &lt;asm/types.h&gt;
       #include &lt;linux/netlink.h&gt;
       #include &lt;linux/rtnetlink.h&gt;
       #include &lt;sys/socket.h&gt;

       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>&lt;stdio.h&gt;</b></font>
<font color="#8080ff"><b>#include </b></font><font color="#ff40ff"><b>&lt;string.h&gt;</b></font>
<font color="#8080ff"><b>#include </b></font><font color="#ff40ff"><b>&lt;errno.h&gt;</b></font>
<font color="#8080ff"><b>#include </b></font><font color="#ff40ff"><b>&lt;sys/socket.h&gt;</b></font>
<font color="#8080ff"><b>#include </b></font><font color="#ff40ff"><b>&lt;sys/types.h&gt;</b></font>
<font color="#8080ff"><b>#include </b></font><font color="#ff40ff"><b>&lt;unistd.h&gt;</b></font>
<font color="#8080ff"><b>#include </b></font><font color="#ff40ff"><b>&lt;asm/types.h&gt;</b></font>
<font color="#8080ff"><b>#include </b></font><font color="#ff40ff"><b>&lt;linux/netlink.h&gt;</b></font>
<font color="#8080ff"><b>#include </b></font><font color="#ff40ff"><b>&lt;linux/rtnetlink.h&gt;</b></font>
<font color="#8080ff"><b>#include </b></font><font color="#ff40ff"><b>&lt;linux/netdevice.h&gt;</b></font>
<font color="#8080ff"><b>#include </b></font><font color="#ff40ff"><b>&lt;net/if_arp.h&gt;</b></font>
<font color="#8080ff"><b>#include </b></font><font color="#ff40ff"><b>&lt;netinet/if_ether.h&gt;</b></font>
<font color="#8080ff"><b>#include </b></font><font color="#ff40ff"><b>&lt;netinet/ether.h&gt;</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 &lt; <font color="#ff40ff"><b>0</b></font>)
    {
        fprintf(<font color="#ff40ff"><b>stderr</b></font>, <font color="#ff40ff"><b>&quot;创建SOCKET错误:</b></font><font color="#ff6060"><b>%s</b></font><font color="#ff6060"><b>\n</b></font><font color="#ff40ff"><b>&quot;</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(&amp;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 *)&amp;struAddr, <font color="#ffff00"><b>sizeof</b></font>(struAddr)) &lt; <font color="#ff40ff"><b>0</b></font>)
    {
        fprintf(<font color="#ff40ff"><b>stderr</b></font>, <font color="#ff40ff"><b>&quot;绑定SOCKET错误:</b></font><font color="#ff6060"><b>%s</b></font><font color="#ff6060"><b>\n</b></font><font color="#ff40ff"><b>&quot;</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(&amp;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(&amp;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, &amp;struReq, struReq.nh.nlmsg_len, <font color="#ff40ff"><b>0</b></font>,
        (<font color="#00ff00"><b>struct</b></font> sockaddr *)&amp;struAddr, <font color="#ffff00"><b>sizeof</b></font>(struAddr)) &lt; <font color="#ff40ff"><b>0</b></font>)
    {
        fprintf(<font color="#ff40ff"><b>stderr</b></font>, <font color="#ff40ff"><b>&quot;发送数据错误:</b></font><font color="#ff6060"><b>%s</b></font><font color="#ff6060"><b>\n</b></font><font color="#ff40ff"><b>&quot;</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 -&gt; nlmsg_type == NLMSG_DONE)
                <font color="#ffff00"><b>break</b></font>;
            <font color="#ffff00"><b>if</b></font>(pstruNL -&gt; 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>&quot;发生错误[</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>&quot;</b></font>,
                    strerror(-pstruError -&gt; error));
                <font color="#ffff00"><b>break</b></font>;
            }

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -