PPP程序基本流程.docx

上传人:b****6 文档编号:7011029 上传时间:2023-01-16 格式:DOCX 页数:12 大小:451.69KB
下载 相关 举报
PPP程序基本流程.docx_第1页
第1页 / 共12页
PPP程序基本流程.docx_第2页
第2页 / 共12页
PPP程序基本流程.docx_第3页
第3页 / 共12页
PPP程序基本流程.docx_第4页
第4页 / 共12页
PPP程序基本流程.docx_第5页
第5页 / 共12页
点击查看更多>>
下载资源
资源描述

PPP程序基本流程.docx

《PPP程序基本流程.docx》由会员分享,可在线阅读,更多相关《PPP程序基本流程.docx(12页珍藏版)》请在冰豆网上搜索。

PPP程序基本流程.docx

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实现的。

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 总结汇报

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1