PPPOE(PPP over Ethernet)
pppoe在标准PPP报文的前面加上以太网的报头。
1.PPPOE帧格式
DESTINATION_ADDR SOURCE_ADDR ETHER_TYPE PAYLOAD CHECKSUM
6 6 2 1
PAYLOAD:
VER TYPE CODE SESSION_ID LENGTH PLAYLOAD1
0001 0001 8BIT 2 2
PLAYLOAD1:
TAG_TYPE TAG_LENGTH TAG_VALUE .....
ETHER_TYPE:
0X8863 Discovery Stage
0x8864 PPP Session Stage
CODE:
0x00 PPP Session Stage
0x09 PPPOE Active Discovery Initiation(PADI) packet
0x07 PPPOE Active Discovery Offer(PADO) packet
0x19 PPPOE Active Discovery Request(PADR) packet
0x65 PPPOE Active Discovery Session-confirmation(PADS) PACKET
0xa7 PPPOE Active Discovery Terminate(PADT) packet
TAG_TYPES:
0x0000 End_Of_List
0x0101 Service-Name
0x0102 AC-Name
0x0103 Host_Uniq
0x0104 AC-Cookie
0x0105 Vendor-Specific
0x0110 Relau-Session-Id
0x0201 Service-Name-Error
0x0202 AC-System-Error
0x0203 Generic-Error
PPPoE协议工作原理
两个阶段:发现阶段,会话阶段。
发现阶段分为4个步骤,主要目的是建立唯一的PPPoE的SessionID.
1.客户端广播发分组(PADI):目的:客户端寻找服务器。实现:客户端发送CODE:0x09,SESSION-ID=0x0000,标签类型字段值为0x0101,地址0xffffffffffff;
2.服务器收(PADI)发(PAD0): 目的:服务器反馈客户端。实现:服务端发送CODE:0x07,SESSION-ID=0x0000,标签类型字段值为0x0102(以及一个或多个服务器),地址客户端;
3.客户端选服务器发(PADR):目的;多服务器优先选择。实现:客户端发送CODE:0x19,SESSION-ID=0x0000,客户端未收到PAD0,就重发PAD1,并加长等待时间。地址客户端;
4.服务端发会话确认(PADS): 目的:准备开始PPP会话。 实现:服务端发送CODE:0x65,SESSION-ID=唯一.客户端收到PADS确认后吗,开始会话阶段。
用户终端 ADSL局端
发 ---------PADI-------->
现 <--------PAD0---------
阶 ---------PADR-------->
段 <--------PADS---------
<------PPP Data------> 会话阶段
<--------PADT--------> 会话释放
会话阶段:
PPDT可以在会话建立后任何时刻发送,终止PPPoE会话。CODE:0xa7,SESSION-ID.
代码分析:
typedef struct PPPoEConnectionStruct {
int discoveryState; /* Where we are in discovery */
int discoverySocket; /* Raw socket for discovery frames */
int sessionSocket; /* Raw socket for session frames */
unsigned char myEth[ETH_ALEN]; /* My MAC address */
unsigned char peerEth[ETH_ALEN]; /* Peer's MAC address */
UINT16_t session; /* Session ID */
char *ifName; /* Interface name */
char *serviceName; /* Desired service name, if any */
char *acName; /* Desired AC name, if any */
int synchronous; /* Use synchronous PPP */
int useHostUniq; /* Use Host-Uniq tag */
int printACNames; /* Just print AC names */
int skipDiscovery; /* Skip discovery */
int noDiscoverySocket; /* Don't even open discovery socket */
int killSession; /* Kill session and exit */
FILE *debugFile; /* Debug file for dumping packets */
int numPADOs; /* Number of PADO packets received */
PPPoETag cookie; /* We have to send this if we get it */
PPPoETag relayId; /* Ditto */
int PADSHadError; /* If PADS had an error tag */
int discoveryTimeout; /* Timeout for discovery packets */
} PPPoEConnection;