netlink
http://blog.csdn.net/zirconsdu/article/details/8569193
http://www.xuebuyuan.com/1725837.html
netlink 编程介绍
Linux
从 2.2开始支持PF_NETLINK
域的通讯方式,这个方式主要的用途是在Linux的内核空间和用户空间进行通讯。目前在网络上面关于netlink编程的中文资料很少,为了促进对
netlink编程的理解我编写了这篇文章,由于我对netlink的了解不是很透彻,特别是对于内核部分不是很熟悉,所以文章中肯定有很多错误的地方还
请大家指正。文章分下面几个部分进行讲述
netlink
基础知识 nlmsghdr 结构介绍 解析nlmsghdr数据 sockaddr_nl 结构介绍 NETLINK_ROUTE 协议介绍
NETLINK_SKIP 协议介绍 NETLINK_USERSOCK协议介绍 NETLINK_FIREWALL 协议介绍
NETLINK_TCPDIAG 协议介绍 NETLINK_NFLOG
协议介绍 NETLINK_ARPD 协议介绍 NETLINK_ROUTE6 协议介绍 NETLINK_IP6_FW 协议介绍
NETLINK_DNRTMSG 协议介绍 NETLINK_TAPBASE 协议介绍 参考资料 版权说明 修改记录
netlink基础知识
我们在使用socket(2)的man手册时候可以找到man手册中有下面一行说明
PF_NETLINK Kernel
user interface device netlink(7)
在我们通过PF_NETLINK创建一个SOCKET以后表示我们期望同内核进行消息通讯。使用netlink(7)的手册可以看到关于PF_NETLINK的详细说明。
#include
#include
#include
netlink_socket = socket(PF_NETLINK, socket_type, netlink_family);
按照netlink的手册,socket_type可以取SOCK_RAW和SOCK_DGRAM,不过内核不区分这两个字段。netlink_family字段指定了我们期望的通讯协议,主要有:
NETLINK_ROUTE
用来获取,创建和修改设备的各种信息,详细参见
rtnetlink(7) NETLINK_SKIP
Enskip 的保留选项 NETLINK_USERSOCK
为今后用户程序空间协议用保留选项 NETLINK_FIREWALL
接收 IPv4 防火墙编码发送的数据包 NETLINK_TCPDIAG
TCP套接字监控 NETLINK_NFLOG
netfilter的用户空间日志 NETLINK_ARPD
用以维护用户地址空间里的 arp 表 NETLINK_ROUTE6
接收和发送 IPv6 路由表更新消息 NETLINK_IP6_FW
接收未通过 IPv6 防火墙检查的数据包(尚未实现) NETLINK_TAPBASE
是 ethertap 设备实例
后面我们会对每一个协议进行解释和说明.
nlmsghdr结构介绍
每一个发送给内核或者从内核介绍的报文都有一个相同的报文头,这个报文头的结构如下定义:
struct nlmsghdr
{
__u32 nlmsg_len; /* 包括报头在内的消息长度*/
__u16 nlmsg_type; /* 消息正文 */
__u16 nlmsg_flags; /* 附加标志*/
__u32 nlmsg_seq; /* 序列号*/
__u32 nlmsg_pid; /* 发送进程号 PID */
};
所有发送给内核或者内核的报文的第一部分都必须使用这个机构,后面跟随相应的内容。nlmsg_type为后面消息的内容个数,对于前面我们提到的不同通讯协议有着不同的消息类型。下面是三个通用的消息类型
NLMSG_NOOP 这个消息类型表示消息内容为空,应用可以忽略该报文 NLMSG_ERROR 这个消息类型表示后面的消息是一个错误信息,错误信息的机构为nlmsgerr
struct nlmsgerr
{
int error; /* 负数表示的出错号 errno 或为 0 要求确认 acks*/
struct nlmsghdr msg; /* 造成出错的消息报头*/
};NLMSG_DONE 在我们接收或者发送消息给内核的时候,我们有可能一次发送多个报文,这个消息类型表示是报文的最后一个,类似于在链表中我们将最后一个成员的next指针设置为NULL。
附加的标志用于控制或者表示消息的其它信息,一些比较通用的标志是
NLM_F_REQUEST
表示这个消息是一个请求消息,这个消息可以同以下一个标志组合 NLM_F_ROOT 返回树的根 NLM_F_MATCH
返回所有匹配的 NLM_F_ATOMIC
返回对象表的单一快照 NLM_F_DUMP 被定义为NLM_F_ROOT|NLM_F_MATCH NLM_F_REPLACE
表示替换现有的规则 NLM_F_EXCL 如果现有规则存在则不修改 NLM_F_CREAT
创建一个规则 NLM_F_APPEND
追加一个规则 NLM_F_MULTI 表示这个消息是多个报文中的一个,报文的结尾通过NLMSG_DONE来表示 NLM_F_ACK 表示这个消息是一个应答消息 NLM_F_ECHO 表示这个消息是一个要求返回请求信息的消息
解析nlmsghdr数据
为了获取netlink报文中数据的方便,netlink提供了下面几个宏进行数据的获取和解包操作
#include
#include
int NLMSG_ALIGN(size_t len);
int NLMSG_LENGTH(size_t len);
int NLMSG_SPACE(size_t len);
void *NLMSG_DATA(struct nlmsghdr *nlh);
struct nlmsghdr *NLMSG_NEXT(struct nlmsghdr *nlh, int len);
int NLMSG_OK(struct nlmsghdr *nlh, int len);
int NLMSG_PAYLOAD(struct nlmsghdr *nlh, int len);
NLMSG_ALIGN:进行数据长度的对齐操作
NLMSG_DATA:获取通讯报文中的数据
NLMSG_NEXT:获取下一个报文
NLMSG_OK:判断是否数据可以继续获取
NLMSG_PAYLOAD:获取数据的长度
在我们后面的实例中会介绍如何使用这几个宏。
sockaddr_nl结构介绍
在socket程序中,如果我们要求接收报文则要求调用bind,表示我们期望接收什么样的报文。对于netlink也一样,我们要求指定我们期望接收的地址信息,不过同传统的sockaddr不同,这个地方是一个sockaddr_nl的结构:
struct sockaddr_nl
{
sa_family_t nl_family; /* AF_NETLINK */
unsigned short nl_pad; /* 用来填充的字段,赋值为0 */
pid_t nl_pid; /* 进程标识号pid */
__u32 nl_groups; /* 多址广播组掩码*/
};
每
一个 netlink 数据类都有一个32位广播分组,当对套接字调用 bind(2) 时, sockaddr_nl 中的 nl_groups
字段设置成所要侦听的广播组的位掩码。其默认值为 0,表示不接收任何广播,我们会在后面中看到如何使用这个广播组的例子。
· 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; /* 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 */
};
struct rtattr
{
unsigned short rta_len; /* Length of option */
unsigned short rta_type; /* Type of option */
/* Data follows */
};
ifi_type:这个字段包含了硬件的类型,可以参考比较常见的是 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
#include
#include
#include
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);
· · NETLINK_ARPD 协议介绍
TODO:还没有找到资料
· NETLINK_ROUTE6 协议介绍
TODO:还没有找到资料
· NETLINK_IP6_FW 协议介绍
TODO:还没有找到资料
· NETLINK_DNRTMSG 协议介绍
TODO:还没有找到资料
· NETLINK_TAPBASE 协议介绍
TODO:还没有找到资料
· 参考资料
Linux
系统内核空间与用户空间通信的实现与分析 这篇文章是陈鑫在IBM中国开发网站上的一篇文章,讨论了在LINUX下如何进行内核空间和用户空间通讯。
Netlink Sockets Tour 这是一篇英文的介绍Linux内核中是如何实现netlink通讯的文章。 Netlink Sockets
- Overview 这是一篇介绍netlink编程入门的英文资料,介绍了一些基础性的东西。
Understanding And Programming With Netlink Sockets
一篇介绍netlink程序的英文文章,介绍的非常详细。 Linux Netlink as an IP Services Protocol
这个可能是最详细介绍netlink之间通讯协议报文的一篇RFC文档,详细的描述了每一个协议的通讯报文格式。 NETLINK中文MAN手册
CMPP已经将netlink(7)的man手册翻译成中文了,不过现在找不到这个的html版,只找到了一个doc版。 IPROUTE 路由工具
IPROUTE路由工具的源代码中有大量的关于netlink的ROUTE代码可以参考,同时也提供了一个libnetlink库用来进行操作。
IPTABLES
IPTABLES是一个Linux下强有力的防火墙工具。在IPTABLES的源代码中有大量的关于netlink编程的FIREWALL代码可以
参考,同时也提供了一个libipq库来进行操作。 ULOG 用户层日志
ULOG通过使用netlink的NFLOG功能,在用户层进行了通讯报文的日志记录功能,您可以参考ULOG的源代码来了解NFLOG的使用
netlink的更多相关文章
- netlink优势
netlink相对其他应用进程和内核之间通信的方式(ioctrl或者系统文件等方式),全双工,可由内核发起,应用进程可用epoll监听,而其他方式只能由应用进程发起. 顺便记下隧道,隧道可以通过在ip ...
- linux 内核与用户空间通信之netlink使用方法
转自:http://blog.csdn.net/haomcu/article/details/7371835 Linux中的进程间通信机制源自于Unix平台上的进程通信机制.Unix的两大分支AT&a ...
- C# 怎么才能取到网卡的型号信息呢? 如: 博通 NetLink BCM57781 Gigabit Ethernet
C# 怎么才能取到网卡的型号信息呢? 如: 博通 NetLink BCM57781 Gigabit Ethernet
- NetLink Communication Mechanism And Netlink Sourcecode Analysis
catalog . Netlink简介 . Netlink Function API Howto . Generic Netlink HOWTO kernel API . RFC Linux Netl ...
- Generic Netlink详解
netlink socket是一种用于用户态进程和内核态进程之间的通信机制.它通过为内核模块提供一组特殊的API,并为用户程序提供了一组标准的socket接口的方式,实现了全双工的通讯连接. Netl ...
- Linux netlink机制
netlink 是一种特殊的 socket,它是 Linux 所特有的,类似于 BSD 中的AF_ROUTE 但又远比它的功能强大,目前在最新的 Linux 内核(2.6.14)中使用netlink ...
- netlink机制
一.netlink机制简介 netlink是一种基于网络的机制,允许在内核内部以及内核与用户之间进行通信.正式定义见RFC3549.手册见netlink(3)和netlink(7).netlink(3 ...
- 1、netlink 连接器 通信机制
使用netlink之前,先参考一下资料:http://www.ibm.com/developerworks/cn/linux/l-connector/ netlink通信机制介绍:资料来源 linux ...
- linux netlink套接字学习资料
理论: http://blog.csdn.net/unbutun/article/details/3394061 进一步深入: http://edsionte.com/techblog/archive ...
随机推荐
- EF,ADO.NET Entity Data Model简要的笔记
1. 新建一个项目,添加一个ADO.NET Entity Data Model的文件,此文件会生成所有的数据对象模型,如果是用vs2012生的话,在.Designer.cs里会出现“// Defaul ...
- 关键字 new 的作用
①做运算符 用于创建对象和调用构造函数,小栗子a如下: Class1 obj = new Class1(); 创建匿名类型的实例,小栗子b如下: var query = from cust in cu ...
- eclipse打开出错 Error: opening registry key 'Software\JavaSoft\Java Runtime Environment'
eclipse出现注册错误:①在“打开”输入框中输入“regedit”命令,删除注册表的HKEY_LOCAL_MACHINE\SOFTWARE\JavaSoft\ 的INSTALLDIR删除. 或者 ...
- ionic localstorage
angular.module('locals',[]) .factory('ls', ['$window', function($window) { return { set: function(ke ...
- ERDAS 2013与ArcGIS10.1安装时的兼容性问题
在Regedit中HKEY_LOCAL_MACHINE->SOFTWARE->FLEXlm License Manager下新建一个“ERDAS License Manager”,然后按照 ...
- gulp sass使用
var gulp = require("gulp");var sass = require("gulp-sass-china");var dgbl = requ ...
- Android IOS WebRTC 音视频开发总结(二四)-- p2p调用堆栈
本文主要分析webrtc音视频点对点部分的代码结构,文章来自博客园RTC.Blacker,转载请说明出处. 前段时间在查一个偶尔断线的问题(这种问题最蛋疼,不好重现,只能凭经验去搞),所以理了下web ...
- 十一、Struts2封装请求参数的方式
十一.Struts2封装请求参数的方式 方式一.Action 本身作为model对象,通过成员setter封装(一个名字为params的拦截器干的) 注意:表单中的名称要和动作类中的名称一致(这是必须 ...
- Tomcat启动过程(二):EndPoint解析
EndPoint提供基础的网络IO服务,用来实现网络连接和控制,它是服务器对外I/O操作的接入点.主要任务是管理对外的socket连接,同时将建立好的socket连接交到合适的工作线程中去.里面两个主 ...
- RocketMQ学习记录
RocketMQ是一款分布式.队列模型的消息中间件,具有以下特点: 1.能够保证严格的消息顺序 2.提供丰富的消息拉取模式 3.高效的订阅者水平扩展能力 4.实时的消息订阅机制 5.亿级消息堆积能力 ...