DHCP源码分析--主流程

DHCP 服务器,客户端代码都采用了统一的事件轮询(event loop),包含了任务处理消息,定时器消息,socke收发消息等等。

 1 static struct {
 2     isc_appmethods_t methods;
 3 
 4     /*%
 5      * The following are defined just for avoiding unused static functions.
 6      */
 7 #ifndef BIND9
 8     void *run, *shutdown, *start, *onrun, *reload, *finish,
 9         *block, *unblock;
10 #endif
11 } appmethods = {
12     {
13         isc__appctx_destroy,
14         isc__app_ctxstart,
15         isc__app_ctxrun,
16         isc__app_ctxsuspend,
17         isc__app_ctxshutdown,
18         isc__app_ctxfinish,
19         isc__appctx_settaskmgr,
20         isc__appctx_setsocketmgr,
21         isc__appctx_settimermgr
22     }
23 #ifndef BIND9
24     ,
25     (void *)isc__app_run, (void *)isc__app_shutdown,
26     (void *)isc__app_start, (void *)isc__app_onrun, (void *)isc__app_reload,
27     (void *)isc__app_finish, (void *)isc__app_block,
28     (void *)isc__app_unblock
29 #endif
30 };
31         (void)isc__taskmgr_dispatch(ctx->taskmgr);
32 
33     result = evloop(ctx);
34     if (result != ISC_R_SUCCESS)
35         return (result);

网卡接口对象的收包处理函数注册:

 1 for (tmp = interfaces; tmp; tmp = tmp -> next) {
 2         /* not if it's been registered before */
 3         if (tmp -> flags & INTERFACE_RUNNING)
 4             continue;
 5         if (tmp -> rfdesc == -1)
 6             continue;
 7         switch (local_family) {
 8 #ifdef DHCPv6 
 9         case AF_INET6:
10             status = omapi_register_io_object((omapi_object_t *)tmp,
11                               if_readsocket, 
12                               0, got_one_v6, 0, 0);
13             break;
14 #endif /* DHCPv6 */
15         case AF_INET:
16         default:
17             status = omapi_register_io_object((omapi_object_t *)tmp,
18                               if_readsocket, 
19                               0, got_one, 0, 0);
20             break;
21         }
22 
23         if (status != ISC_R_SUCCESS)
24             log_fatal ("Can't register I/O handle for %s: %s",
25                    tmp -> name, isc_result_totext (status));
26 
27 #if defined(DHCPv6)
28         /* Only register the first interface for V6, since they all
29          * use the same socket.  XXX: This has some messy side
30          * effects if we start dynamically adding and removing
31          * interfaces, but we're well beyond that point in terms of
32          * mess.
33          */
34         if (local_family == AF_INET6)
35             break;
36 #endif
37     } /* for (tmp = interfaces; ... */

 

omapi_register_io_object函数将收包处理函数got_one与对应的接口对象指针关联:

 1 status = omapi_object_reference (&obj -> inner, h, MDL);
 2     if (status != ISC_R_SUCCESS) {
 3         omapi_io_dereference (&obj, MDL);
 4         return status;
 5     }
 6 
 7     status = omapi_object_reference (&h -> outer,
 8                      (omapi_object_t *)obj, MDL);
 9     if (status != ISC_R_SUCCESS) {
10         omapi_io_dereference (&obj, MDL);
11         return status;
12     }
13 
14         ...
15         obj -> reader = reader;

 

reader 就是指向 got_one 函数的函数指针参数,这样就可以从主流程main函数入口进入到收包处理流程了。

 1 isc_result_t got_one (h)
 2     omapi_object_t *h; {
 3     ....
 4     if (bootp_packet_handler) {
 5         ifrom.len = 4;
 6         memcpy (ifrom.iabuf, &from.sin_addr, ifrom.len);
 7 
 8         (*bootp_packet_handler) (ip, &u.packet, (unsigned)result,
 9                      from.sin_port, ifrom, &hfrom);
10     }
11     ....
12 }

 

bootp_packet_handler 即是 main函数设置的包处理函数:

1 /* Set up various hooks. */
2     dhcp_interface_setup_hook = dhcpd_interface_setup_hook;
3     bootp_packet_handler = do_packet;
4 #ifdef DHCPv6
5     dhcpv6_packet_handler = do_packet6;
6 #endif /* DHCPv6 */

 

posted @ 2016-08-23 15:20  丹西  阅读(2903)  评论(0编辑  收藏  举报