分类: LINUX
2015-03-05 22:21:25
原文地址:Linux PPP详细介绍 作者:xlzxlz2
什么是PPP
PPP是一种网络中最为基础的协议。PPP协议(Point-to-Point Protocol)是一种数据链路层协议,它是为在同等单元之间传输数据包这样的简单链路而设计的。这种链路提供全双工操作,并按照顺序传递数据包。PPP为基于各种主机、网桥和路由器的简单连接提供一种共通的解决方案。
PPP协议包括以下三个部分:
1. 数据帧封装方法。
2. 链路控制协议LCP(Link Control Protocol):它用于对封装格式选项的自动协商,建立和终止连接,探测链路错误和配置错误。
3. 针对不同网络层协议的一族网络控制协议NCP(Network Control Protocol): PPP协议规定了针对每一种网络层协议都有相应的网络控制协议,并用它们来管理各个协议不同的需求。
PPP认证方式
1. 口令验证协议(PAP)
PAP 是一种简单的明文验证方式。NAS(网络接入服务器,Network Access Server)要求用户提供用户名和口令,PAP以明文方式返回用户信息。
2. 挑战-握手验证协议(CHAP)
CHAP是一种加密的验证方式,能够避免建立连接时传送用户的真实密码。NAS向远程用户发送一个挑战口令(challenge),其中包括会话ID和 一个任意生成的挑战字串(arbitrary challenge string)。远程客户必须使用MD5单向哈希算法(one-way hashing algorithm)返回用户名和加密的挑战口令,会话ID以及用户口令,称为Secret Password,其中用户名以非哈希方式发送。
PPP 协议之下是以太网和串口等物理层,之上是IP协议等网络层。这里,对于下层,我们只讨论串口的情况,对于上层,我们只讨论TCP/IP的情况。发送 时,TCP/IP数据包经过PPP打包之后经过串口发送。接收时,从串口上来的数据经PPP解包之后上报给TCP/IP协议层。linux下ppp框架结构如下图:
????
PPP 是一个分层结构。在底层,它能使用同步媒介(如 ISDN 或同步 DDN 专线),也能适用异步媒介(如基于 Modem 拨号的 PSTN 网络)。在数据链路层,PPP 在链路建立方面提供了丰富的服务,这些服务以
LCP 协商选项的形式提供。在上层,PPP 通过 NCPs 提供对多种网络层协议的支持。PPP 对于每一种网络层协议都有一种封装格式来区别它们的报文。
什么是pppd
pppd是一个用户空间的后台服务进程(daemon。pppd实现了所有鉴权、压缩/解压和加密/解密等扩展功能的控制协议。pppd只是一个普通的用户进程,pppd与内核中的PPP协议处理模块之间通过设备文件(/dev/ppp)进行通信。pppd有一个辅助工具chat,用来与GSM模组建立会话。它向串口发送AT命令,建立与GSM模组的会话,以便让PPP协议可以在串口上传输数据包。
/dev/ppp
设备文件/dev/ppp。通过read系统调用,pppd可以读取PPP协议处理模块的数据包,当然,PPP协议处理模块只会把应该由pppd处理的数据包发给pppd。通过write系统调用,pppd可以把要发送的数据包传递给PPP协议处理模块。通过ioctrl系统调用,pppd可以设置PPP协议的参数,可以建立/关闭连接。在pppd里,每种协议实现都在独立的C文件中,它们通常要实现protent接口,该接口主要用于处理数据包,和fsm_callbacks接口,该接口主要用于状态机的状态切换。数据包的接收是由main.c: get_input统一处理的,然后根据协议类型分发到具体的协议实现上。而数据包的发送则是协议实现者根据需要调用output函数完成的。
发送数据
应用程序通过socket 接口发送TCP/IP数据包,这些TCP/IP数据包如何流经PPP协议处理模块,然后通过串口发送出去呢?pppd在make_ppp_unit函数调用ioctrl(PPPIOCNEWUNIT)创建一个网络接口(如ppp0),内核中的PPP协议模块在处理PPPIOCNEWUNIT时,调用register_netdev向内核注册ppp的网络接口,该网络接口的传输函数指向ppp_start_xmit。当应用程序发送数据时,内核根据IP地址和路由表,找到ppp网络接口,然后调用ppp_start_xmit函数,此时控制就转移到PPP协议处理模块了。ppp_start_xmit调用函数ppp_xmit_process去发送队列中的所有数据包,ppp_xmit_process又调用ppp_send_frame去发送单个数据包, ppp_send_frame根据设置,调用压缩等扩展处理之后,又经ppp_push调用pch->chan->ops->start_xmit发送数据包。pch->chan->ops->start_xmit是什么?它就是具体的传输方式了,比如说对于串口发送方式,则是ppp_async.c: ppp_asynctty_open中注册的ppp_async_send函数,ppp_async_send经ppp_async_push函数调用tty->driver->write把数据发送串口。
接收数据
接收数据的情形又是如何的?ppp_async.c在初始化(ppp_async_init),调用tty_register_ldisc向tty注册了行规程处理接口,也就是一组回调函数,当串口tty收到数据时,它就会回调ppp_ldisc的 ppp_asynctty_receive函数接收数据。ppp_asynctty_receive调用ppp_async_input把数据buffer转换成sk_buff,并放入接收队列ap->rqueue中。ppp_async另外有一个tasklet(ppp_async_process)专门处理接收队列ap->rqueue中的数据包,ppp_async_process一直挂在接收队列ap->rqueue上,一旦被唤醒,它就调用ppp_input函数让PPP协议处理模块处理该数据包。
在ppp_input函数中,数据被分成两路,一路是控制协议数据包,放入pch->file.rqb队列,交给pppd处理。另外一路是用户数据包,经ppp_do_recv/ppp_receive_frame进行PPP处理之后,再由netif_rx提交给上层协议处理,最后经 socket传递到应用程序。