netlink(2)- rtnetlink

  • Post author:
  • Post category:其他




netlink(2)- rtnetlink:



rtnetlink 介绍:

当创建socket时, 协议类型参数选择的是NETLINK_ROUTE, 得到的socket是rtnetlink_socket, 需要使用到rtnetlink.

​ 所有rtnetlink 消息都包含一个netlink消息头和附加属性,rtnetlink 中定义的一组宏就是用于操作这些属性所用。

​ rtnetlink 除了标准的netlink消息外还包含其它消息类型(如RTM_NEWLINK), 不同的消息对应的附加属性会有差异,后面会具体说明。



rtnetlink 包含的宏:

#include <linux/rtnetlink.h>
 	#define RTA_ALIGNTO 4

	#define RTA_ALIGN(len) (((len)+RTA_ALIGNTO-1)& ~(RTA_ALIGNTO-1))
	/*RTA_ALIGN(len) 得到不小于len 且是RTA_ALIGNTO 对齐(即整数倍)的最小数*/

	#define RTA_OK(rta,len) ((len) >= (int)sizeof(srtuct rtattr)&&\
							(rta)->rta_len >= sizeof(struct rtattr)&&\
							(rta->rta_len) <= (len))
	/* 确认len长度的数据中至少包含一个rta ,且rta 正常。 如果rta指向有效路由属性,attrlen 是属性的运行长度。 !此宏返回指针的有效性!*/

	#define RTA_NETX(rta,attrlen)  ((attrlen) - =RTA_ALIGN((rta)->rta_len),\
									(struct rtattr*)(((char*)(rta))+RTA_ALIGN(rta)->rta_len))
	/*返回下一个RTA的首地址,并且attrlen减去当前rta长度。 !此宏返回rta的下一个属性!*/

	#define RTA_LENGTH(len) (RTA_ALIGN(sizeof(struct rtattr))+(len))
	/*返回len字节数据+标题 对应的长度*/

	#define RTA_SPACE(len) RTA_ALIGN(RTA_LENGTH(len))
	/*在需要len字节数据的消息中,需要返回的空间量 (len+sizeof(rtattr))*/

	#define RTA_DATA(rta)	((void*)(((char*)(rta))+RTA_LENGTH(0)))
	/*!该宏返回一个指向该属性开始的指针数据!*/

	#define RTA_PAYLOAD(rta) ((int)((rta)->rta_len)-RTA_LENGTH(0))
	/* !返回此属性数据的长度 ! */



rtnetlink 包含的消息类型及对应数据结构:



rtattr 结构

rtattr 是可选的属性,在initital 头后面,结构如下:

struct rtattr{
    unsigned short rta_len;		/*option 的长度*/
    unsigned short rta_type;	/*option 的类型*/
    /*属性数据跟在这个结构之后*/
};



1. RTM_NEWLINK, RTM_DELINK, RTM_GETLINK 消息:

上述消息是创建,删除,获取有关特定网络接口的信息;

这些消息中包含一个ifinfomsg 结构且后面紧跟一系列rtattr结构。



ifinfomsg 结构

struct ifinfomsg{
    unsigned char 	ifi_family; /*地址族,设置为AF_UNSPEC*/
    unsigned short 	ifi_type;	/* Device type */
    int				ifi_index;	/* Interface index*/
    unsigned int	ifi_flags;	/* Device flags*/
	unsigned int	ifi_change; /* change mask*/
};


参数说明


ifi_family:

为AF_UNSPEC


ifi_type

: 为


ifi_flags:

包含device flags, 参考https://www.man7.org/linux/man-pages/man7/netdevice.7.html

如:ifi_flags =IFF_LOWER_UP Driver signals L1 up


ifi_index:

网络接口独一无二的index值,当RTM_NEWLINK 消息发生时填的值。


ifi_change:

保留值,将来使用。



对应的rta_type 说明:

rta_type 路由属性的值类型 说明
IFLA_UNSPEC

IFLA_ADDRESS


硬件地址



接口L2地址(如wlan0 的MAC 地址)

IFLA_BROADCAST 硬件地址 L2 广播地址

IFLA_IFNAME


asciiz string



设备名称(如wlan0)

IFLA_MTU unsigned int 设备的MTU
IFLA_LINK int 链接类型
IFLA_QDISC asciiz string 队列规则
IFLA_STATS struct rtnl_link_status 网络接口的状态



特别说明:

如RTM_NEWLINK 消息到来时: 设备可能是在newlink 状态,也可能在device down 状态,也可能在Device up 状态,也可能在dellink 状态, 收到该信息进行处理时,依赖ifi_flags 的标志,对设备状态进行修改。 如下:

/*----------NEWLINK Message-----------*/
switch(dev_type)
{
	case DEV_NONE:
	case DEV_DELLINK:
		dev_type=DEV_NEWLINK;
		...
		notify(...);
		if(ifi_flags==IFF_LOWER_UP)
		{
		dev_type=DEV_UP;
		....
		notify(...);
		}
		break;
	case DEV_NEWLINK:
	case DEV_DOWN:
		if(ifi_flags==IFF_LOWER_UP)
		{
		dev_type=DEV_UP;
		....
		notify(...);
		}
		break;
	case DEV_up:
		if(ifi_flags==IFI_LOWER_DOWN)
		{
		dev_type=DEV_DOWN;
		...
		notify(...);
		}
		break;
	default:
		break;
		
}
/*-------------Del Message----------*/
switch(dev_type)
{
	case DEV_NEWLINK:
	case DEV_UP:
	case DEV_DOWN:
		dev_type = DEV_DELLINK;
		...
		notify(...);
		break;
	default:
		break;
}



2. RTM_NEWADDR, RTM_DELADDR, RTM_GETADDR


消息作用

:增加,删除,获取某个网络几口关联的IP地址信息。//一个网络接口可以携带多个IP地址,IPV4/IPV6.


结构顺序

:包含一个ifaddrmsg 后可选若干rtattr 路由属性。



ifaddrmsg 结构:

struct ifaddrmsg {
                  unsigned char ifa_family;    /* Address type */
                  unsigned char ifa_prefixlen; /* Prefixlength of address */
                  unsigned char ifa_flags;     /* Address flags */
                  unsigned char ifa_scope;     /* Address scope */
                  unsigned int  ifa_index;     /* Interface index */
              };
  • ifa_family: 地址族,为AF_INET 或AF_INET6
  • ifa_prefixlen: address mask 的长度 (地址掩码长度)
  • ifa_scope: 地址范围
  • ifa_index:地址关联的网络接口索引值
  • ifa_flags:IFA_F_SECONDARY 用于辅助地址,IFA_F_PERMANENT 用于用户设置的永久地址。



对应的rta_type 说明:

type 类型 数据类型 描述
IFA_UNSPEC

IFA_ADDRESS


原始协议地址类型



接口地址(接口本地IP地址)

IFA_LOCAL 原始协议地址类型 本地地址

IFA_LABEL


string 类型



接口名称 (接口名称如wlan0


IFA_BROADCAST 原始协议地址类型 广播地址
IFA_ANYCAST 原始协议地址类型 任意播地址
IFA_CACHEINFO struct ifa_cacheinfo 类型 地址信息



3. RTM_NEWROUTIE, RTM_DELROUTE, RTM_GETROUTE

**消息作用:**创建,删除或者获取某个网络路由的信息。


结构顺序

:该message 包含一个rtmsg 后面跟随多个rtattr 结构(rtattr 可选)



rtmsg 结构:

struct rtmsg {
                  unsigned char rtm_family;   /* Address family of route */
                  unsigned char rtm_dst_len;  /* Length of destination */
                  unsigned char rtm_src_len;  /* Length of source */
                  unsigned char rtm_tos;      /* TOS filter */
                  unsigned char rtm_table;    /* Routing table ID;
                                                 see RTA_TABLE below */
                  unsigned char rtm_protocol; /* Routing protocol; see below */
                  unsigned char rtm_scope;    /* See below */
                  unsigned char rtm_type;     /* See below */

                  unsigned int  rtm_flags;
              };
  • rtm_table

    rtm_table 路由表类型
    RT_TABLE_UNSPEC 未指定的路由表
    RT_TABLE_DEFAULT 默认路由表
    RT_TABLE_MAIN main table
    RT_TABLE_LOCAL 本地table

    注:用户使用在RT_TABLE_UNSPEC 与RT_TABLE_DEFAULT

  • rtm_protocol:

    路由协议
    RTPROT_UNSPEC
    RTPROT_REDIRECT 通过ICMP 重定向(当前未使用)
    RTPROT_KERNEL by kernel
    RTPROT_BOOT during boot
    RTPROT_STATIC 管理员

    大于PTRPOT_STATIC 的值不被内核解释,仅仅用于用户信息。 可标记路由信息的来源或区分多个路由守护进程。

  • rtm_socpe:

    // 获取到目的地的距离

    RT_SCOPE_UNIVERSE global route
    RT_SCOPE_SITE interior route in the local autonomous system
    RT_SCOPE_LINK route on this link
    RT_SCOPE_HOST route on the local host
    RT_SCOPE_NOWHERE destination doesn’t exist

    注:RT_SCOP_UNIVERSE -RT_SCOPE_SITE 给用户使用。

  • rtm_type:

    rtm_type 路由类型
    RTN_UNSPEC
    RTN_UNICAST 网关或直接路由
    RTN_LOCAL 本地接口路由
    RTN_BROADCAST 本地广播路由(作为广播发送)
    RTN_ANYCAST 本地广播路由(作为单播发送)
    RTN_MULTICAST 多播路由
    RTN_BLACKHOLE 丢包路由
    RTN_UNREACHABLE 不可达目的地
    RTN_PROHIBIT 包拒绝路由
    RTN_THROW 继续在另一个表中进行路由查询
    RTN_NAT 网络地址转换规则
    RTN_XRESOLVE 外部解析器
  • rtm_flags:

RTM_F_NOTIFY 路由改变时通知用户
RTM_F_CLONED 路由被其它路由克隆
RTM_F_EQUALIZE 暂未使用



对应的rta_type 说明

rta_type 值类型 描述
RTA_UNSPEC
RTA_DST 协议地址 路由目标地址
RTA_SRC 协议地址 路由源地址
RTA_IIF int 输入的接口index
RTA_OIF int 输出的接口index
RTA_GATEWAY 协议地址 路由的网关
RTA_PRIORITY int 路由的优先级
RTA_PREFSRC 协议地址 首选的源地址
RTA_METRICS int 路由度量
RTA_MULTIPATH
RTA_PROTOINFO
RTA_FLOW int 路由领域
RTA_CACHEINFO
RTA_TABLE 路由表ID



4. RTM_NEWNEIGH, RTM_DELNEIGH, RTM_GETNEIGH


消息作用

: 增加,删除,或获取邻里表项信息,如ARP entry.


数据结构

: 信息包括一个mdmsg 结构



ndmsg 结构:

   struct ndmsg {
                  unsigned char ndm_family;
                  int           ndm_ifindex;  /* Interface index */
                  __u16         ndm_state;    /* State */
                  __u8          ndm_flags;    /* Flags */
                  __u8          ndm_type;
              };
  • ndm_state:

    ndm_state 解释
    NUD_INCOMPLETE 当前解决缓存条目
    NUD_REACHABLE 确认的工作缓存条目
    NUD_STALE 过期的缓存条目
    NUD_DELAY 等待计时器的条目
    NUD_PROBE 缓存条目当前重探测
    NUD_FAILED 无效缓存条目
    NUD_NOARP 设备没有目标缓存
    NUD_PERMANENT 静态项
  • ndm_flags:

    ndm_flags 说明
    NTF_PROXY 代理ARP 表项
    NTF_ROUTER IPv6 路由器



rta_type:

rta_type 说明
NDA_UNSPEC


NDA_DST



邻居缓存N/W 层目的地址 (对端IP地址)



NDA_LLADDR



邻居缓存链路层地址(对端MAC地址)

NDA_CACHEINFO 缓存统计

如果rta_type 是NDA_CACHEINFO , 则紧跟一个nda_cacheinfo 头。



nda_cacheinfo

 struct nda_cacheinfo {
                  __u32         ndm_confirmed;
                  __u32         ndm_used;
                  __u32         ndm_updated;
                  __u32         ndm_refcnt;
              };
  • 参考网址:

    https://www.man7.org/linux/man-pages/man7/netdevice.7.html

    https://www.man7.org/linux/man-pages/man7/rtnetlink.7.html



版权声明:本文为gege_hxg原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。