PPP程序基本流程.docx
- 文档编号:6658079
- 上传时间:2023-01-08
- 格式:DOCX
- 页数:13
- 大小:454.09KB
PPP程序基本流程.docx
《PPP程序基本流程.docx》由会员分享,可在线阅读,更多相关《PPP程序基本流程.docx(13页珍藏版)》请在冰豆网上搜索。
PPP程序基本流程
PPP程序基本流程图
PPPD程序用到的几个重要的结构体:
typedefstructfsm{
intunit;/*Interfaceunitnumber*/
intprotocol;/*DataLinkLayerProtocolfieldvalue*/
intstate;/*State*/
intflags;/*Containsoptionbits*/
u_charid;/*Currentid*/
u_charreqid;/*Currentrequestid*/
u_charseen_ack;/*HavereceivedvalidAck/Nak/RejtoReq*/
inttimeouttime;/*Timeouttimeinmilliseconds*/
intmaxconfreqtransmits;/*MaximumConfigure-Requesttransmissions*/
intretransmits;/*Numberofretransmissionsleft*/
intmaxtermtransmits;/*MaximumTerminate-Requesttransmissions*/
intnakloops;/*Numberofnakloopssincelastack*/
intrnakloops;/*Numberofnaksreceived*/
intmaxnakloops;/*Maximumnumberofnakloopstolerated*/
structfsm_callbacks*callbacks;/*Callbackroutines*/
char*term_reason;/*Reasonforclosingprotocol*/
intterm_reason_len;/*Lengthofterm_reason*/
}fsm;
typedefstructfsm_callbacks{
void(*resetci)/*ResetourConfigurationInformation*/
__P((fsm*));
int(*cilen)/*LengthofourConfigurationInformation*/
__P((fsm*));
void(*addci)/*AddourConfigurationInformation*/
__P((fsm*,u_char*,int*));
int(*ackci)/*ACKourConfigurationInformation*/
__P((fsm*,u_char*,int));
int(*nakci)/*NAKourConfigurationInformation*/
__P((fsm*,u_char*,int,int));
int(*rejci)/*RejectourConfigurationInformation*/
__P((fsm*,u_char*,int));
int(*reqci)/*Requestpeer'sConfigurationInformation*/
__P((fsm*,u_char*,int*,int));
void(*up)/*CalledwhenfsmreachesOPENEDstate*/
__P((fsm*));
void(*down)/*CalledwhenfsmleavesOPENEDstate*/
__P((fsm*));
void(*starting)/*Calledwhenwewantthelowerlayer*/
__P((fsm*));
void(*finished)/*Calledwhenwedon'twantthelowerlayer*/
__P((fsm*));
void(*protreject)/*CalledwhenProtocol-Rejectreceived*/
__P((int));
void(*retransmit)/*Retransmissionisnecessary*/
__P((fsm*));
int(*extcode)/*Calledwhenunknowncodereceived*/
__P((fsm*,int,int,u_char*,int));
char*proto_name;/*Stringnameforprotocol(formessages)*/
}fsm_callbacks;
typedefstruct{
char*name;/*nameoftheoption*/
enumopt_typetype;
void*addr;
char*description;
unsignedintflags;
void*addr2;
intupper_limit;
intlower_limit;
constchar*source;
shortintpriority;
shortintwinner;
}option_t;
structprotent{
u_shortprotocol;/*PPPprotocolnumber*/
/*Initializationprocedure*/
void(*init)__P((intunit));
/*Processareceivedpacket*/
void(*input)__P((intunit,u_char*pkt,intlen));
/*Processareceivedprotocol-reject*/
void(*protrej)__P((intunit));
/*Lowerlayerhascomeup*/
void(*lowerup)__P((intunit));
/*Lowerlayerhasgonedown*/
void(*lowerdown)__P((intunit));
/*Opentheprotocol*/
void(*open)__P((intunit));
/*Closetheprotocol*/
void(*close)__P((intunit,char*reason));
/*Printapacketinreadableform*/
int(*printpkt)__P((u_char*pkt,intlen,
void(*printer)__P((void*,char*,...)),
void*arg));
/*Processareceiveddatapacket*/
void(*datainput)__P((intunit,u_char*pkt,intlen));
boolenabled_flag;/*0iffprotocolisdisabled*/
char*name;/*Textnameofprotocol*/
char*data_name;/*Textnameofcorrespondingdataprotocol*/
option_t*options;/*Listofcommand-lineoptions*/
/*Checkrequestedoptions,assigndefaults*/
void(*check_options)__P((void));
/*Configureinterfacefordemand-dial*/
int(*demand_conf)__P((intunit));
/*Saywhethertobringuplinkforthispkt*/
int(*active_pkt)__P((u_char*pkt,intlen));
};
structchannel{
/*setofoptionsforthischannel*/
option_t*options;
/*findandprocessaper-channeloptionsfile*/
void(*process_extra_options)__P((void));
/*checkalltheoptionsthathavebeengiven*/
void(*check_options)__P((void));
/*getthechannelreadytodoPPP,returnafiledescriptor*/
int(*connect)__P((void));
/*we'refinishedwiththechannel*/
void(*disconnect)__P((void));
/*putthechannelintoPPP`mode'*/
int(*establish_ppp)__P((int));
/*takethechanneloutofPPP`mode',restoreloopbackifdemand*/
void(*disestablish_ppp)__P((int));
/*setthetransmit-sidePPPparametersofthechannel*/
void(*send_config)__P((int,u_int32_t,int,int));
/*setthereceive-sidePPPparametersofthechannel*/
void(*recv_config)__P((int,u_int32_t,int,int));
/*cleanuponerrorornormalexit*/
void(*cleanup)__P((void));
/*closethedevice,calledinchildrenafterfork*/
void(*close)__P((void));
};
PPP的状态转换图:
对程序流程的基本框架的说明
因为程序是利用protent结构指针指向当前所在协议层的方法来实现的因此,每一层都要经历几个阶段,直到本层达到OPENED状态时才可进入下一阶段来实现下一阶段的协议。
所以对每一层的协议都有相同的函数指针,只是函数指针指向的协议不同而已。
整个程序的主体实现是从主函数的LCP_OPEN()开始的,在这个函数里,调用了有限状态机FSM_OPEN(),而在FSM_OPEN()中,callback指针指向了starting,于是就到了LCP_STARTING()函数来实现一个OPEN事件从而使得PPP状态准备从DEAD到ESTABLISHED的转变。
接下来,回到主函数,下面一步是调用START_LINK(),在此函数中会把一个串口设备作为PPP的接口,并把状态转变为ESTABLISHED,然后调用lcp_lowerup()来告诉上层底层已经UP,lcp_lowerup()中调用FSM_LOWERUP()来发送一个configure-request请求,再把当前状态设置为REQSENT状态,至此,第一个LCP协商的报文已经发送出去。
while(phase!
=PHASE_DEAD){
handle_events();
get_input();
if(kill_link)
lcp_close(0,"Userrequest");
if(asked_to_quit){
bundle_terminating=1;
if(phase==PHASE_MASTER)
mp_bundle_terminated();
}
if(open_ccp_flag){
if(phase==PHASE_NETWORK||phase==PHASE_RUNNING){
ccp_fsm[0].flags=OPT_RESTART;/*clearsOPT_SILENT*/
(*ccp_protent.open)(0);
}
}
}
接下来的流程实现主要就是在这个while循环中实现了。
之前说过了我们已经发送了第一个配置协商报文,所以handle_events()主要就是做等待接收数据包的时间处理了,在handle_events()里主要调用了两个函数一个是wait_input(),他的任务是等待并判断是否超时。
还有一个是calltimeout()他主要是做超时的处理。
当等待并未超时而且有数据包过来,则调用整个PPPD中最重要的函数get_input()函数。
他主要接收过来的数据包并做出相应的动作。
接下来就get_input()函数进行详细的说明。
首先对包进行判断,丢弃所有不在LCP阶段和没有OPENED状态的包,然后protop指针指向当前协议的input函数。
于是就进入了LCP_INPUT(),同理LCP_INPUT()调用了FSM_INPUT()对收到的包进行代码域的判断,判断收到的是什么包。
假设比较顺利,我们收到的是CONFACK的包,于是调用fsm_rconack()函数,在此函数中根据当前自身的状态来决定下一步的状态如何改变,这里我们假设也很顺利,已经发送完了configure-ack,因此我们把FSM当前状态变成了OPENED状态,并把callback指针指向UP.所以我们马上就调用LCP_UP()在那里我们又调用了LINK_ESTABLISHED()函数来进入认证的协商,或者如果没有认证则直接进入网络层协议。
当然这里我们还是要认证的所有在LINK_ESTABLISHED()里我们选择是利用何种认证方式是PAP,还是EAP,还是CHAP.假设我们这里采用CHAP而且是选择CHAPWITHPEER,意思是等待对端先发送CHALLENGE挑战报文。
于是我们又调用了chap_with_peer()函数,并等待接收挑战报文。
于是从新又来到handle_events()等待接收。
再利用get_input()来接收包,在get_input()里这次调用chap_input(),再调用FSM_INPUT(),在那里我们再对包的代码域进行判断,这次判断出是CHAP_CHALLENGE包,则我们要调用chap_respons()函数来回应对端,继续等待对方的报文,再次利用CHAP_INPUT(),FSM_INPUT()来判断,如果是SUCCESS,则调用handle_status(),在这个函数里调用success_chap_with_peer函数(),从而进入网络层阶段,调用network_phase()函数。
网络层的互动是从start_networks()开始的,如果在网络层阶段同时有CCP协议(压缩控制协议)则进行压缩控制协议的协商,然后再进入正式的IPCP的协商,而IPCP的协商主要也是通过protop指针指向IPCP_OPEN()开始的。
而IPCP_OPEN()则是调用了FSM_OPEN(),在这里,首先发送一个configure-request包,然后和之前一样等待接收。
经过几个交互后最后调用NP_UP()完成网络层的协商,至此PPP链路可以承载网络层的数据包了。
选项的协商
以LCP为例,它使用了lcp_options结构,并定义了该结构的四个变量lcp_wantoptions,lcp_gotoptions,lcp_allowoptions,lcp_hisoptions,分别用来表示我们想要请求的选项,对方ack的选项,我们允许对方请求的选项,我们ack对方的选项。
lcp_options结构中每个域的含义见附录。
pppd根据lcp_wantoptions生成发送的选项请求,根据lcp_allowoptions决定接受还是拒绝接收到的选项请求。
pppd在lcp_init函数中对lcp_wantoptions和lcp_allowoptions进行赋值。
在状态机的发送函数中,在当前状态不为REQSENT,ACKRCVD,ACKSENT的情况下,调用状态机的reset函数把lcp_wantoptions赋值给lcp_gotoptions来组装选项。
选项的组装是靠状态机的回调函数指针addci完成的,对于LCP就是lcp_addci,组装好选项后发送数据是通过调用fsm_sdata实现的。
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- PPP 程序 基本 流程