Chinaunix首页 | 论坛 | 博客
  • 博客访问: 178934
  • 博文数量: 58
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 14
  • 用 户 组: 普通用户
  • 注册时间: 2013-05-29 17:51
文章分类
文章存档

2015年(3)

2014年(8)

2013年(47)

我的朋友

分类: LINUX

2013-06-04 16:00:47

原文地址:linux ppp pppoe 作者:djking1986

PPP:

PPP主要由两类协议组成:链路控制协议族(LCP)和网络控制协议族(NCP)。

LCP用于建立、拆除和监控PPP数据链路,NCP主要用于协商在该数据链路上所传输的数据包的格式与类型。同时,PPP还提供了用于网络安全方面的验证协议族(PAPCHAP)。

ppp是一个分层结构。在底层,它能使用同步媒介(如ISDNH或同步DDN专线),也能使用异步媒介(如基于Modem拨号的PSTN网络)。

在数据链路层,PPP在链路层建立方面提供了丰富的服务,这些服务以LCP协商选项的形式提供。

在上层,PPP通过NCPs提供对多种网络层协议的支持。PPP对于每一种网络层协议都有一种封装格式来区别它们的报文。

 

PPP协商过程分为几个阶段:Dead阶段,Establish阶段,Authenticate阶段,Network阶段和Termintate阶段,在不同的阶段进行不同协议的协商.只有前面的协商出现结果后,才能转到下一个阶段,进行下一个协议的协商.

1)当物理层不可用时,PPP链路处于dead阶段,链路必须从这个阶段开始和结束.当物理层可用时,PPP在建立链路之前首先进行LCP协商,协商内容包括工作方式是SP还是MP,验证方式和最大传输单元等.

2)LCP协商过后就进入Establish阶段,此时LCP状态为Opened,表示链路已经建立.

3)如果培植了验证(远端验证本地或者本地验证远端)就进入Authenticate阶段,开始CHAPPAP验证.

4)如果验证失败进入Terminate阶段,拆除链路,LCP状态转为Down;如果验证成功就进入Network协商阶段(NCP),此时LCP状态仍为Opened,IPCP状态从Initial转到Request.

5)NCP协商支持IPCP协商,IPCP协商主要包括双方的IP地址.通过NCP协商来选择和配置一个网络层协议.当选中的网络层协议配置成功后,该网络层协议就可以通过这条链路发送报文了.

6)PPP链路将一直保持通信,直至有明确的LCPNCP帧关闭这条链路,或发生了某些外部事件.(例如,用户的干预).

PPPoE

Point-to-Point Protocol over Ethernet:即一种在以太网内封装PPP协议报文的协议。基于包交换的以太网没有电路circuit)或链接的概念,因此对IPMAC冲突和安全性都没有保证。使用PPPoE用户之间可以建立虚拟链路,在链路上进行安全的通信。

PPPoE分为两个阶段:

PPPoE discovery:传统的PPP连接是基于点到点的,而在以太网是muti-accesss,即在以太网中的任一节点可以访问其他节点。以太网中的frame包含着目的节点的MAC地址以找到目的节点。   所以在转换PPP frame之前,两个通信节点必须事先知道对方的MAC地址。 PPPeEdiscovery阶段就是让以太网中的节点交换通知其MAC地址,并建立一个Session ID供后续的包交换使用。

PPPoE session:当节点之间知道了相互的MAC地址后,就进入了session阶段。

 

PPP in Linux

PPP框架:

 

1 pppoe程序:首先pppoe完成PPPoE的发现阶段,即相互通知MAC地址。接着这个程序负责发送/接收所有通过ppp网络接口(如ppp0)的数据包。(需要了解类型为0x88630x8864socket是如何工作的,并要了解数据包是如何通过PTY设备在pppoePPP协议栈之间传递的)。

2pppd pppoe配合起来完成拨号上网的协商与维护。

3/dev/ppp:创建了ppp设备后,ppp过程的数据包经过协议栈的分类,会被传送到该接口的队列内。pppd从该接口读取ppp过程的数据包,然后交给相应的协议栈处理。对于响应的数据包同样写入改设备,设备内会将数据包交给协议栈然后转发出去。

4socket pppoe 的会话与发现阶段数据包对应的以太网类型分别为0x88630x8864,因为这两种类型的数据包是由pppoe应用程序通过socket来收发的,所以内核中需要定义这两种类型的socket

5PPP协议栈: 主要负责PPP层的封装、压缩与解压。另外,它还对普通数据包和ppp过程的数据包进行了分流,将普通数据包提交给TCP/IP协议栈,而将PPP过程的数据包交给/dev/ppp设备队列中,等待pppd去收取处理。

6PTY设备:串行设备,PPP内核协议栈与pppoe应用程序的中转站。因为ppp协议早多运行在串行链路上,所以在Linux内核中PPP协议栈与串行设备结合紧密。

 

PPPoE拨号建立的过程

==PPPoEDiscovery过程

==PPP过程

==》设置上网主机

 

pppd的实现:

网络协议是分层实现的,上层一般只需要知道其直接下层,只有在极少数的情况下才使用间接下层的接口。如普通的socket编程,它们只需要知道TCP/IP协议,而不需要知道PPP协议的存在。这种分层的设计简化了协议的实现和应用程序的开发。

但是PPP协议并不只提供简单的数据链路层功能,还提供了一些扩展功能(如鉴权PAP/CHAP,加密解密ECP)。应用程序要求使用透明化,不关心这些扩展功能的存在,而反过来。ppp协议处理模块本身又无法处理这些策略性的东西,因为它不知道用户名/密码,不知道是否要进行压缩,不知道是否要进行加密。

pppd的出现解决了这个问题。pppd是一个后台服务进程(daemon),是一个用户空间的进程,所以把那些策略性的内容从内核的PPP协议处理模块移到pppd中是很自然地事情。(pppd实现了所有鉴权、压缩、加密解密等扩展功能的控制协议)

pppd是用户空间的程序,它与内核态通过 设备文件(/dev/ppp  进行通信。通过read系统调用,pppd可以读取PPP协议处理模块的数据包(PPP协议处理模块只会把应该由pppd处理的数据包发给pppd);通过write系统调用,pppd可以把要发送的数据包传递给PPP协议处理模块。通过ioctrl系统调用,pppd可以设置PPP协议的参数,可以建立/关闭连接。

pppd里,每种协议实现都在独立的c文件中,它们通常要实现protent接口(该接口主要用于处理数据包)和fsm_callbacks接口(该接口主要用于状态机的状态切换)。数据包的接收是由main.cget_input统一处理的,然后根据协议类型分法到具体的协议实现上。而数据包的发送则是协议实现者根据需要调用output函数完成的。

=======  流程  =======

应用程序通过socket接口发送TCP/IP数据包,这些TCP/IP数据包要如何经过PPP协议处理模块然后通过串口发送出去?

pppdmake_ppp_unit函数中调用ioctrlPPPIOCNEWUNIT)创建一个网络接口(如ppp0),内核中的PPP协议模块在处理PPPIOCNEWUNIT时,调用register_netdev向内核注册ppp的网络接口(ppp0),该网络接口的传输函数指向ppp_start_xmit

当应用程序发送数据时,内核根据IP地址和路由表,找到ppp网络接口(ppp0),然后条用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发送数据包。

 

PPPoE (用户态):

PPPoE pppoe客户端版本:rp-pppoe-3.5-32.1 官网:

PPPOE主文件为PPPOE.c 入口函数是main() main函数中主要做了两件事情:

PPPOE协议中的DISCOVERY阶段:处理函数为discovery(),此函数建立一个RAW SOCKET,然后发送报文,接着等待回应,等待处理,最后成功后设置状态进入SESSION阶段。

PPOE协议中的SESSION阶段,处理函数为session(),此函数首先建立一个RAW SOCKET,然后从PPPD中读入数据,在加上PPPOE发送出去,再将接收到的数据发送给PPPD程序,让PPPD处理,处理完后就建立了PPPOE连接,ppp0端口也建立了,并且从SERVER端分配到了IP

 

PPPOE建立连接后数据报文的流程:

 

如果从eth收到PPPOE数据:   —— 首先数据被PPPOERAW SOCKET数据接收, PPPOE解开数据包的PPPOE报头, 然后将数据包传输到伪终端主设备->伪终端的从设备,然后通过内核到达ppp0解开,ppp0设备通过驱动将数据包处理后向上层传输。

 

数据包发送: —— 首先根据路由知道数据要发送的端口在ppp0设备端口,数据达到ppp0设备后,ppp0将数据传输到伪终端从设备->伪终端主设备,然后到达PPPOEPPPOE给数据包加上PPPOE报头,然后通过RAW SOCKETeth接口发送出去。

 

【问题】:

数据包的处理——至上而下:PPP封转->PPPOE封装->以太网报头,但是PPPOE用户态(PPPOE内核态的实现是这个理想的流程)的实现流程并不是这样,用户态实现用在PPPPPPOE中添加了一个伪终端,是为了不破坏LINUX内核中原有的终端实现的接口,因为linux内核中是将串行设备作为终端设备来驱动的。

阅读(1214) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~