detach(); //默认放在后台以daemon执行,也可配置/etc/ppp/option中的nodetach参数放在前台执行
……
"pppd %s started by %s, uid %d"uid); //熟悉的log,现在准备执行了
getpid());
setup_signals(); //设置信号处理函数
create_linkpidfile(getpid()); //创建PID文件
/*
* If we're doing dial-on-demand, set up the interface now.
*/
if(demand){ //以按需拨号方式运行,可配置
/*
* Open the loopback channel and set it up to be the ppp interface.
*/
fd_loop=open_ppp_loopback(); //详见下面分析
//设置IFNAME环境变量为接口名称如ppp0
/*
* Configure the interface and mark it up, etc.
*/
demand_conf();
}
(第二阶段)……
PPP协议里包括各种控制协议如LCP,PAP,CHAP,IPCP等,这些控制协议都有很多共同的地方,因此PPPD将每个控制协议都用结构protent表示,并放在控制协议数组protocols[]中,一般常用的是LCP,PAP,CHAP,IPCP这四个协议。
/*
* PPP Data Link Layer "protocol" table.
* One entry per supported protocol.
* The last entry must be NULL.
*/
&lcp_protent, //LCP协议
&pap_protent, //PAP协议
&chap_protent, //CHAP协议
#ifdef CBCP_SUPPORT
#endif
&ipcp_protent, //IPCP协议,IPv4
#ifdef INET6
//IPCP协议,IPv6
#endif
&ccp_protent,
&ecp_protent,
#ifdef IPX_CHANGE
#endif
#ifdef AT_CHANGE
#endif
&eap_protent,
NULL
};
每个控制协议由protent结构来表示,此结构包含每个协议处理用到的函数指针:
/*
* The following struct gives the addresses of procedures to call
* for a particular protocol.
*/
struct protent{
/* Initialization procedure */
unit)); //初始化指针,在main()中被调用
/* Process a received packet */
unit//接收报文处理
/* Process a received protocol-reject */
unit)); //协议错误处理
/* Lower layer has come up */
unit)); //当下层协议UP起来后的处理
/* Lower layer has gone down */
unit)); //当下层协议DOWN后的处理
/* Open the protocol */
unit)); //打开协议
/* Close the protocol */
unit//关闭协议
/* Print a packet in readable form */
len,
void