PPPoE(以太网上的点对点协议)
协议概述
PPPoE分为两个阶段,即Discovery(地址发现)阶段和PPP会话阶段。当某个主机希望发起一个PPPoE会话时,它必须首先执行Discovery来确定对方的以太网MAC地址并建立起一个PPPoE会话标识符SESSION_ID(Access Concentrator生成)。虽然PPP定义的是端到端的对等关系,Discovery却是天生的一种客户端-服务器关系。在Discovery的过程中,主机(作为客户端)发现某个访问集中器(Access Concentrator,作为服务器),根据网络的拓扑结构,可能主机能够跟不止一个的访问集中器通信 。Discovery阶段允许主机发现所有的访问集中器并从中选择一个。当Discovery阶段成功完成之后,主机和访问集中器两者都具备了用于在以太网上建立点到点连接所需的所有信息。
Discovery阶段保持无状态(stateless)直到建立起一个PPP会话。一旦PPP会话建立,主机和访问集中器两者都必须为一个PPP虚拟接口分配资源。
报文格式
以太网帧格式(更多介绍请查看RFC894/tcp/ip协议详解:卷1 第2章)
ETHER_TYPE设置为0x8863(Discovery阶段)或者0x8864(PPP会话阶段)
payload头
payload内容
包含0个或多个tag,每个tag是一个tlv(type-length-value)三元组
发现阶段(discovery stage)
发现阶段分为四步:PADI、PADO、PADR、PADS。
当HOST收到PADS后,那么HOST与AC(access concentrator)间的点对点关系就已建立,进入了会话阶段(session stage)。
PPPoE Active Discovery Initiation数据包(PADI)
主机发送DESTINATION_ADDR 为广播地址的PADI数据包,CODE域设置为0x09,SESSION_ID域必须设置为0x0000。
PADI数据包必须包含且仅包含一个TAG_TYPE为Service-Name的TAG,以表明主机请求的服务,以及任意数目的其它类型的TAG。整个PADI数据包(包括PPPoE头部)不允许超过1484个字节,以留足空间让中继代理(向数据包中)增加类型为Relay-Session-Id的TAG。
The PPPoE Active Discovery Offer 数据包(PADO)
如果访问集中器能够为收到的PADI请求提供服务,它将通过发送一个PADO数据包来做出应答。DESTINATION_ADDR为发送PADI的主机的单播地址,CODE域为0x07,SESSION_ID域必须设置为0x0000。
PADO数据包必须包含一个类型为AC-Name的TAG(包含了访问集中器的名字),与PADI中相同的Service-Name,以及任意数目的类型为Service-Name的TAG表明访问集中器提供的其它服务。如果访问集中器不能为PADI提供服务,则不允许用PADO作响应。
The PPPoE Active Discovery Request 数据包(PADR)
由于PADI是广播的,主机可能收到不止一个PADO,它将审查接收到的所有PADO并从中选择一个。可以根据其中的AC-Name或PADO所提供的服务来作出选择。然后主机向选中的访问集中器发送一个PADR数据包。其中,DESTINATION_ADDR域设置为发送PADO的访问集中器的单播地址,CODE域设置为0x19,SESSION_ID必须设置为0x0000。
PADR必须包含且仅包含一个TAG_TYPE为Service-Name的TAG,表明主机请求的服务,以及任意数目其他类型的TAG。
The PPPoE Active Discovery Session-confirmation 数据包(PADS)
当访问集中器收到一个PADR数据包,它就准备开始一个PPP会话。它为PPPoE会话创建一个唯一的SESSION_ID并用一个PADS数据包来给主机作出响应。DESTINATION_ADDR域为发送PADR数据包的主机的单播以太网地址,CODE域设置为0x65,SESSION_ID必须设置为所创建好的PPPoE会话标识符。
PADS数据包包含且仅包含一个TAG_TYPE为Service-Name的TAG,表明访问集中器已经接受的该PPPoE会话的服务类型,以及任意数目的其他类型的TAG。
如果访问集中器不喜欢PADR中的Service-Name,那么它必须用一个带有类型为Service-Name-Error的TAG(以及任意数目的其它TAG类型)的PADS来作出应答。这种情况下,SESSION_ID必须设置为0x0000。
The PPPoE Active Discovery Terminate数据包(PADT)
这种数据包可以在会话建立以后的任意时刻发送,表明PPPoE会话已经终止。它可以由主机或访问集中器发送,DESTINATION_ADDR域为单播以太网地址,CODE域设置为0xa7,SESSION_ID必须表明终止的会话,这种数据包不需要任何TAG。
当收到PADT以后,就不允许再使用该会话发送PPP流量了。在发送或接收到PADT后,即使是常规的PPP结束数据包也不允许发送。PPP通信双方应该使用PPP协议自身来结束PPPoE会话,但在无法使用PPP时可以使用PADT。
会话阶段(session stage)
一旦PPPoE会话开始,PPP数据就像其它PPP封装一样发送。所有的以太网数据包都是单播的。ETHER_TYPE域设置为0x8864。PPPoE的CODE必须设置为0x00。PPPoE会话的SESSION_ID不允许发生改变,必须是Discovery阶段所指定的值。PPPoE的payload包含一个PPP帧,帧始于PPP Protocol-ID。
TAG_TYPE和TAG_VALUE
0x0000 End-Of-List
该TAG表明表中没有其它TAG了。该TAG的TAG_LENGTH必须总是0。不要求使用该标签,存在是为了向后兼容。
0x0101 Service-Name
该TAG表明后面紧跟的是服务的名称。TAG_VALUE是不以NULL结束的UTF-8字符串。当TAG_LENGTH为0时,该TAG用于表明接受任何服务。使用Service-Name标签的例子是表明ISP(Internet服务提供商)或者一类服务或者服务的质量。
0x0102 AC-Name
该TAG表明后面紧跟的字符串唯一地表示了某个特定的访问集中器。它可以是商标、型号以及序列号等信息的集合,或者该访问集中器MAC地址的一个简单的UTF-8表示。它不以NULL来结束。
0x0103 Host-Uniq
该TAG由主机用于把访问集中器的响应(PADO或者PADS)与主机的某个唯一特定的请求联系起来。TAG_VALUE是主机选择的长度和值为任意的二进制数据。它不能由访问集中器解释。主机可以在PADI或者PADR中包含一个Host-Uniq标签。如果访问集中器收到了该标签,它必须在对应的PADO或者PADS中不加改变的包含该标签。
0x0104 AC-Cookie
该TAG由访问集中器用于防止拒绝服务攻击(见“安全方面的考虑”)。访问集中器可以在PADO数据包中包含该TAG。如果主机收到了该标签,它必须在接下来的PADR中不加改变的包含该标签。TAG_VALUE I是长度和值任意的二进制数据,不能由主机解释。
0x0105 Vendor-Specific
该TAG用来传送厂商自定义的信息。TAG_VALUE的头4个字节包含了厂商的识别码 ,其余字节尚未定义。厂商识别码的高字节为0,低3个字节为网络字节序的厂商的SMI网络管理专用企业码,如“定义值RFC”(参考文献[4])中定义的那样。
不推荐使用该TAG。为了确保互操作性,实现可以悄悄的忽略Vendor-Specific TAG。
0x0110 Relay-Session-Id
该TAG可由中继流量的中间代理加入到Discovery数据包中。TAG_VALUE对主机和访问集中器都是晦涩难懂的(paque)。如果主机或访问集中器收到该TAG,则它们必须在所有的Discovery数据包中包含该TAG以作为响应。所有的PADI数据包必须保证足够空间来加入TAG_VALUE长度为12字节的Relay-Session-Id标签。
如果Discovery数据包中已经包含一个Relay-Session-Id标签,则不允许再加入该标签。这种情况下,中间代理应该使用该现有的Relay-Session-Id标签。如果它不能使用现有的标签,或者没有足够空间来增加一个Relay- Session-Id标签,那么它应该向发送者返回一个Generic-Error标签。
0x0201 Service-Name-Error
该TAG(典型的有一个长度为零的数据部分)表明了由于某种原因,没有理睬所请求的Service-Name。如果有数据部分,并且数据部分的头一个字节非0,那么它必须是一个 可打印的UTF-8字符串,解释请求被拒绝的原因。该字符串可以不以NULL结束。
0x0202 AC-System-Error
该TAG表明了访问集中器在处理主机请求时出现了某个错误。(例如没有足够资源来创建一个虚拟电路。PADS数据包中可以包含该标签。
如果有数据,并且数据的第一个字节不为0,那么(数据)必须是一个可打印的UTF-8 字符串,该字符串解释了错误的性质。该字符串可以不以NULL结束。
0x0203 Generic-Error
该TAG表明发生了一个错误。当发生一个不可恢复的错误并且没有其它合适的TAG时,它可被加到PADO, PADR或PADS数据包中。如果出现数据部分,那么数据必须是一个UTF-8字符串,解释错误的性质。该字符串不允许以NULL结束。