NETLINK_ROUTE協定介紹 - netlink目前使用最廣泛的是通過這個選項來擷取網絡裝置或者網址的一些資訊。在使用這個協定時候支援的類型有:
- RTM_NEWLINK, RTM_DELLINK, RTM_GETLINK 建立,删除或者擷取網絡裝置的資訊
- RTM_NEWADDR, RTM_DELADDR, RTM_GETADDR 建立,删除或者擷取網絡裝置的IP資訊
- RTM_NEWROUTE, RTM_DELROUTE, RTM_GETROUTE 建立,删除或者擷取網絡裝置的路由資訊
- RTM_NEWNEIGH, RTM_DELNEIGH, RTM_GETNEIGH 建立,删除或者擷取網絡裝置的相鄰資訊
- RTM_NEWRULE, RTM_DELRULE, RTM_GETRULE 建立,删除或者擷取路由規則資訊
- RTM_NEWQDISC, RTM_DELQDISC, RTM_GETQDISC 建立,删除或者擷取隊列的原則
- RTM_NEWTCLASS, RTM_DELTCLASS, RTM_GETTCLASS 建立,删除或者擷取流量的類别
- RTM_NEWTFILTER, RTM_DELTFILTER, RTM_GETTFILTER 建立,删除或者擷取流量的過慮
由于NETLINK_ROUTE支援的類型實在太多了,我們這個地方隻重點介紹一下RTM_GETLINK這個類型,然後通過一個例子介紹如何同核心進行通訊。關于其它類型的用法大家可以參考rtnetlink(7)的man手冊。
按照rtnetlink的說法,在擷取裝置資訊的時候我們要求首先發送一個封包給核心表示我們的請求,這個封包的格式是1個nlmsghdr頭部機構+1個ifinfomsg接口結構+多個rtattr屬性機構。其中後面兩個結構的定義是:
struct ifinfomsg
{
unsigned char ifi_family;
unsigned short ifi_type;
int ifi_index;
unsigned int ifi_flags;
unsigned int ifi_change;
};
struct rtattr
{
unsigned short rta_len;
unsigned short rta_type;
};
ifi_type:這個字段包含了硬體的類型,可以參考<linux/if_arp.h>比較常見的是 ARPHRD_ETHER 10M以太網
ARPHRD_PPP PPP撥号
ARPHRD_LOOPBACK 環路裝置
ifi_flags:這個字段包含了裝置的一些标志,相應的值為: 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 接口關閉時丢棄位址.
rta_type:這個字段指定屬性的類型,相應的值為: 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型的裝置資訊
在我們接收和發送資料的時候為了我們擷取屬性的友善,rtnetlink提供了一個宏供我們取擷取其中的結構,這些宏的定義為: #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);