ppp 完全理解(一)

ppp 协议简介、功能及组成分析

 

作者:李圳均

日期:2013/11/27

简介

正式介绍前,分析两个名词:ppp、pppd,在调试中,这两个名字经常出现,ppp(Point to PointProtocol)点对点协议,pppd(Point to Point Protocol daemon)点对点协议守护进程。ppp 在内核中, 是ppp协议处理模块,pppd 是一个在应用层中的守护进程,其功能为实现ppp策略性的内容,包括所有鉴权、压缩/解压和加密/解密等扩展功能的控制协议。

这个文档先介绍ppp的原理及组成,后续文档再详细分析ppp协议处理模块和pppd部分。

 

点对点协议(PPP)为在点对点连接上传输多协议数据包提供了一个标准方法。ppp 位于数据链路层,是一种为同等单元之间传输数据包这样的简单链路设计的链路层协议。这种链路提供全双工操作,并按照顺序传递数据包。

PPP 最初设计是为两个对等节点之间的 IP 流量传输提供一种封装协议。在 TCP-IP 协议集中它是一种用来同步调制连接的数据链路层协议(OSI 模式中的第二层),替代了原来非标准的第二层协议,即 SLIP。除了 IP 以外 PPP 还可以携带其它协议,包括 DECnet 和 Novell 的Internet 网包交换(IPX)。。设计目的主要是用来通 过拨号或专线方式建立点对点连接发送数据,使其成为各种主机、网桥和路由器之间简单连接的一种共通的解决方案。

 

功能及组成:

PPP(Point-to-Point)提供了一种标准的方法在点对点的连接上传输多种协议数据包,pppd、chat、tty、socket、ccp、chap、pap、eap、ecp、ipcp和很多其它概念在一起使用, PPP协议提供两个实体之间的数据链路连接的建立、维持和释放,负责流量和差错控制等等功能。

PPP协议之下是以太网和串口等物理层,之上是IP协议等网络层。发送时,TCP/IP数据包经过PPP打包之后经过串口发送。接收时,从串口上来的数据经PPP解包之后上报给TCP/IP协议层。网络协议是分层实现的,上层一般只需要知道其直接下层,只有在极少数据情况才使用间接下层的接口。比如,彩信、浏览器和邮件等应用程序使用socket接口编程,它们只需要知道TCP/IP协议,而无需要知道PPP协议的存在。这种分层设计简化了协议的实现和应用程序的开发。PPP协议不只是提供了简单的数据链路层功能,它还提供了诸如鉴权(如PAP/CHAP),数据压缩/解压(如CCP)和数据加密/解密(如ECP)等扩展功能。应用程序要求使用透明化,不关心这些扩展功能的存在,而反过来,PPP协议处理模块本身又无法处理这些策略性的东西,因为它不知道用户名/密码,不知道是否要进行压缩,不知道是否要进行加密。 怎么办?如何在对应用程序透明的情况下使用扩展功能呢?于是pppd就出现了。

pppd是一个后台服务进程(daemon),是一个用户空间的进程,所以把策略性的内容从内核的PPP协议处理模块移到pppd中是很自然的事了。pppd实现了所有鉴权、压缩/解压和加密/解密等扩展功能的控制协议。pppd只是一个普通的用户进程,它如何扩展PPP协议呢?这就是pppd与内核中的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函数完成的。chat是pppd所带一个辅助工具。它和xchat不是一个类型的,xchat用来与人聊天,而chat用来与GSM模组建立会话。它的实现比较简单,它向串口发送AT命令,建立与GSM模组的会话,以便让PPP协议可以在串口上传输数据包。

 

对于pppd的操作,直接调试代码的需求并不高,标准的pppd提供了丰富的参数来设置相应的操作,下面用一个pppd启动参数的例子说简单的介绍一下pppd的参数.

下面这一行是在我们的3G平板上使用的pppd启动参数,其内容出自/system/etc/ppp/call-ppd 脚本。

/system/bin/pppd $1 debug defaultroutenoauth nodetach nocrtscts $2 noipdefault usepeerdns user "$3"password "$4" connect "$5" disconnect "$6"

下面是对上面参数在我们3G平板上的具体解释,上面一行就可以看到有6个传入参数,下面这行给出每个参数的具体值,这些值是可变的。这6个参数取出来分别为:/dev/ttyUSB244(串口),-pap(鉴权模式),"test"(用户名),"test"(密码),"/system/bin/chat -v  -f/data/connect"(connect 脚本),"/system/bin/chat -v -f /data/disconnect"(disconnect 脚本,目前为空)。

/system/bin/pppd /dev/ttyUSB244 debugdefaultroute noauth nodetach nocrtscts -pap noipdefault usepeerdns user "test"password "test" connect "/system/bin/chat -v  -f /data/connect" disconnect " "

 

脚本/data/connect的内容如下:

TIMEOUT 5

ABORT 'BUSY'

ABORT 'NO CARRIER'

ABORT 'NO ANSWER'

ABORT 'ERROR'

ABORT '+CME ERROR: 100'

"" AT

OK   AT+CGDCONT=1,"IP","3gnet"

OK        ATD*99#

CONNECT

 

下面这组pppd启动参数来自华为MU509的RIL代码:

/system/bin/pppd  %s 115200 mru 1280 nodetach debug dump %s defaultroute usepeerdns novj  user \"%s\" password\"%s\"  novjccomp noipdefaultipcp-accept-local ipcp-accept-remote connect-delay 5000 ipcp-max-failure 60ipcp-max-configure 60 -am

从这一段参数可以看出,有4个参数要传入,分别为串口,鉴权模式,用户,密码

        

-------------------------------------分割线------------------------------------

    对于我们的平板在巴西遇到的专有APN连接数据业务有问题的情况,经过分析,问题来自鉴权模式,在使用有公网连接数据业务时,一般是不需要鉴权的,移动数据业务的鉴权是在SIM卡鉴权后就完成了,简单的说,就是卡上有钱,就可以上网,不需要在连接数据业务时再进行鉴权。但专有网络在这部分有别于公网,其在连接数据业务的过程中,会根据具体专有网络有的拥有者的需求设置为需要鉴权或不用,通常都是需要鉴权的,鉴权协议多数据为PAP鉴权。

    因早期没有鉴权需求,RK的RIL代码中是没有发送鉴权设置的,当网络端有鉴权请求时,pppd会默认发送chap-MD5的鉴权响应,而另一方面,运营商对条件符合,但鉴权协议不对的鉴权,不会执行具体的鉴权,直接响应鉴权成功,以便一些设置了用户名和密码的公网用户可以正常访问网络。所以,默认的chap-MD5鉴权可以鉴权成功(这部分干扰了我们的早期的判断),但AUC(核心网中的鉴权中心)实际上认定该用户没有进行鉴权,不能连接数据业务。

    后期的调试集中在pppd上面,因RK的赵工和我在这之前都没有深入调试过pppd,工作习惯让我们直接进入pppd的代码加调试LOG来找问题,事实证明,这个方法的效果很小,出现了一些很奇怪的问题,打印传入参数时,会出现一部分的传入参数打印不出来,打印结果随机性很高,无法确认问题点。

    在仔细看过pppd的参数 后,我发现dump参数可以打印出pppd的传入参数,在启动参数行中加入参数dump后,所有pppd的启动参数都可以正常打印出来,发现传入参数没有问题,查看LCP过程,鉴权还是用的chap-MD5,在启动参数中加入-chap +pap后会出现需要一个pap-sercet脚本的需求,但后华为袭工进行多轮沟通并多次测试后,发现要使用PAP鉴权,只能一个一个的减去在其之前优先支持的鉴权,参数如下:-chap -mschap-v2 -mschap refuse-eap

综合起来,我们最终使用的pppd参数为:

/system/bin/pppd /dev/ttyUSB244 debugdefaultroute dump nodetach nocrtscts-chap -mschap-v2 -mschap refuse-eapnoipdefault usepeerdns user "test" password "test" connect"/system/bin/chat -v  -f/data/connect" disconnect " "

 

在RIL代码中我们加入段处理鉴权模式的代码,处理APN设置的鉴权模式,把APN的鉴权需求转换成相应的pppd启动参数传入pppd,通过pppd完成相应的鉴权过程。

 

    从调试过程来看,这个问题的解决过程中,最主要的问题是沟通,花了大量的时间进行无效沟通,有效的沟通是从11月12晚上开始的,但当晚因为是在家里和巴西的工程师联系上的,没有有效的调试环境,调试上没有实际的进展,但沟通渠道OK,为后续有效调试奠定了基础,后面几天来看,13号和14晚上的沟通和调试查明了问题,从15号到18号,巴西那边休息3天,调试没有进行,之后两天巴西那边不能进入警局测试,20号晚上,我们已确认问题原因并基本解决,19号在巴西圣保罗的警局测试通过,可以正常连接数据业务。整个专有APN不能连接数据业务的问题解决。

 

具体的ppp协议,LCP协议,CHAP和PAP鉴权协议,IPCP协议,pppd代码分析和ppp协议处理模块代码分析在文档二和文档三中介绍。