isc-dhcp监听网口的实现步骤
2014-03-26 14:42
281 查看
在启动dhcpd进程的日志记录开始部分,我们都会看到类似如下的打印:
我将dhcpd监听网口的步骤理解为两大步:发现网口,监听网口。在common/discover.c中我们能找到函数void discover_interfaces(int state)。所有被发现的网口都会存放到全局变量interfaces链表中,然后调用判断网口信息是否合法,与地址池是否匹配等等,最后完成网口接收和发送报文的初始化。
一、发现网口
在这一步主要使用了三个函数(begin_iface_scan/next_iface/end_iface_scan)组成。但对于不同的系统它们的实现也有所不同。在这里支持三个类型的系统Solaris、Linux、BSD,他们都是类UNIX系统,之间有很多相似之处,也有很多不同。为什么要做这样的区分呢?
Solaris:ioctl()支持SIOCGLIFCONF参数扩展来获取网口配置信息。
Linux:通过/proc/net/dev文件来读取本机所有网口名,同样也通过ioctl()来获取ip/flag等信息。
BSD:提供getifaddrs() 函数来获取所有网口。
在进行上述三个函数来发现所有网口时,同时过滤掉不可用的网口(loopback或者没有ip的网口),并调用dhcp_interface_setup_hook找出每个可用的网口所在的网段(subnet)。
二、监听网口
这一步只需要关注两个函数(if_register_receive/if_register_send)。这两个函数只是针对dhcpv4来说,dhcpv6则需要使用if_register6。
与第一步类似,对于不同的系统也有所区分。主要有以下几种:
1. LPF
全称Linux Packet Filter,主要适用一般linux系统。接收/发送报文使用raw socket,并在接收报文时通过setsockopt()过滤指定端口的报文。dhcpv4使用67端口,v6则使用547。
2. Socket
主要适用BSD系统,使用udp socket。
3. UPF
全称 Ultrix Packet Filter。然后打一个upf设备,通过ioctl()来关联对应的网口进行收发报文。
4. BPF
与UPF类似,只是打开的设备文件不同。
5. NIT
全称Network Interface Tap。与UPF也类似,区别在于打开的设备文件。
6. DLPI
全称Data Link Provider Interface。打开一个dlpi设备,同样将这个打开的设备文件与网口绑定。
在根据上面各种不同情况,初始化了接收/发送报文的文件描述符,然后调用omapi_register_io_object()来注册回调函数,接收报文,并调用处理报文函数。
over
本文出自 “cizyzhang” 博客,请务必保留此出处http://cizyzhang.blog.51cto.com/1529108/1384513
create for interface for eth5 dhcp_interface_setup_hook eth5, for addr 10.40.124.205 create for interface for base0 dhcp_interface_setup_hook base0, for addr 169.254.1.1 add to interface for base0 dhcp_interface_setup_hook base0, for addr 169.254.100.100 add to interface for VIF2 dhcp_interface_setup_hook VIF2, for addr 192.168.1.10 Listening on LPF/VIF2/b8:c8:55:ac:03:81/network-VIF2 Sending on LPF/VIF2/b8:c8:55:ac:03:81/network-VIF2 Sending on Socket/fallback/fallback-net如果你再使用ifconfig查看一下系统的网口信息就会发现,eth5/base0/VIF2都是有ip地址,其他的网口是没有地址的(当然lo除外),并且它们与上面的前8行对应。
我将dhcpd监听网口的步骤理解为两大步:发现网口,监听网口。在common/discover.c中我们能找到函数void discover_interfaces(int state)。所有被发现的网口都会存放到全局变量interfaces链表中,然后调用判断网口信息是否合法,与地址池是否匹配等等,最后完成网口接收和发送报文的初始化。
一、发现网口
在这一步主要使用了三个函数(begin_iface_scan/next_iface/end_iface_scan)组成。但对于不同的系统它们的实现也有所不同。在这里支持三个类型的系统Solaris、Linux、BSD,他们都是类UNIX系统,之间有很多相似之处,也有很多不同。为什么要做这样的区分呢?
Solaris:ioctl()支持SIOCGLIFCONF参数扩展来获取网口配置信息。
Linux:通过/proc/net/dev文件来读取本机所有网口名,同样也通过ioctl()来获取ip/flag等信息。
BSD:提供getifaddrs() 函数来获取所有网口。
在进行上述三个函数来发现所有网口时,同时过滤掉不可用的网口(loopback或者没有ip的网口),并调用dhcp_interface_setup_hook找出每个可用的网口所在的网段(subnet)。
二、监听网口
这一步只需要关注两个函数(if_register_receive/if_register_send)。这两个函数只是针对dhcpv4来说,dhcpv6则需要使用if_register6。
与第一步类似,对于不同的系统也有所区分。主要有以下几种:
1. LPF
全称Linux Packet Filter,主要适用一般linux系统。接收/发送报文使用raw socket,并在接收报文时通过setsockopt()过滤指定端口的报文。dhcpv4使用67端口,v6则使用547。
2. Socket
主要适用BSD系统,使用udp socket。
3. UPF
全称 Ultrix Packet Filter。然后打一个upf设备,通过ioctl()来关联对应的网口进行收发报文。
4. BPF
与UPF类似,只是打开的设备文件不同。
5. NIT
全称Network Interface Tap。与UPF也类似,区别在于打开的设备文件。
6. DLPI
全称Data Link Provider Interface。打开一个dlpi设备,同样将这个打开的设备文件与网口绑定。
在根据上面各种不同情况,初始化了接收/发送报文的文件描述符,然后调用omapi_register_io_object()来注册回调函数,接收报文,并调用处理报文函数。
over
本文出自 “cizyzhang” 博客,请务必保留此出处http://cizyzhang.blog.51cto.com/1529108/1384513
相关文章推荐
- Android网络状态监听
- 获取android手机当前ip地址
- js 与或运算符 || && 妙用
- JavaScript的一些基础
- hevc
- Java Callable接口应用举例
- SOCI、LiteSQL、POCO数据库访问类库对比
- 记不起引用类型和值类型,在项目中让我犯糊涂,我真是菜鸟。
- 曲苑杂坛--数据库更新探秘
- java获取map中的最小KEY,最小VALUE
- 伊顿250万美元建中国客户体验中心
- Android判断屏幕是横屏还是竖屏
- .NTE 基础 之对象
- mysql 强大的trim() 函数
- iOS申请真机调试证书-图文详解
- C# Assembly.GetManifestResourceStream总返回 null问题
- 8 个很棒的免费的 C++ GUI 库
- Oracle的REDO和UNDO
- 学习-机器视觉(3D采集重建)
- 开始使用VIM