isc-dhcp監聽網口的實現步驟

   在啓動dhcpd進程的日誌記錄開始部分,我們都會看到類似如下的打印:

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



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章