1. 发现阶段
发现阶段是无状态的,目的是获得PPPoE终结端(在局端的ADSL设备上)的以太网MAC地址,并建立一个惟一的PPPoE SESSION-ID。
host ———–PADI—————–> server
host <———–PADO—————– server
host ———–PADR—————–> server
host <———–PADS—————– server
1.1 PADI,active discovery initiation
1.主机广播发起分组,分组的目的地址为以太网的广播地址 0xffffffffffff
/* Set destination to Ethernet broadcast address */
memset(packet.ethHdr.h_dest, 0xFF, ETH_ALEN);
Ethernet II, Src: Dell_49:3f:5f (24:b6:fd:49:3f:5f), Dst: Broadcast (ff:ff:ff:ff:ff:ff)
Destination: Broadcast (ff:ff:ff:ff:ff:ff)
Source: Dell_49:3f:5f (24:b6:fd:49:3f:5f)
Type: PPPoE Discovery (0x8863)
2.CODE(代码)字段值为0×09(PADI Code),SESSION-ID(会话ID)字段值为0x0000。
packet.ethHdr.h_proto = htons(Eth_PPPOE_Discovery);
//#define ETH_PPPOE_DISCOVERY 0x8863
packet.vertype = PPPOE_VER_TYPE(1, 1);
//#define PPPOE_VER_TYPE(v, t) (((v) << 4) | (t))
packet.code = CODE_PADI;
//#define CODE_PADI 0x09
packet.session = 0;
生成hostUniq
/* If we're using Host-Uniq, copy it over */
if (conn->hostUniq) {
PPPoETag hostUniq;
int len = (int) strlen(conn->hostUniq);
hostUniq.type = htons(TAG_HOST_UNIQ);
hostUniq.length = htons(len);
memcpy(hostUniq.payload, conn->hostUniq, len);
CHECK_ROOM(cursor, packet.payload, len + TAG_HDR_SIZE);
memcpy(cursor, &hostUniq, len + TAG_HDR_SIZE);
cursor += len + TAG_HDR_SIZE;
plen += len + TAG_HDR_SIZE;
}
PPP-over-Ethernet Discovery
0001 .... = Version: 1
.... 0001 = Type: 1
Code: Active Discovery Initiation (PADI) (0x09)
Session ID: 0x0000
Payload Length: 20
PPPoE Tags
Host-Uniq: 010000000000000001000000
3.PADI分组必须至少包含一个服务名称类型的标签(Service Name Tag,字段值为0x0101),向接入集中器提出所要求提供的服务。
if (!omit_service_name) {
plen = TAG_HDR_SIZE + namelen;
CHECK_ROOM(cursor, packet.payload, plen);
svc->type = TAG_SERVICE_NAME;
svc->length = htons(namelen);
if (conn->serviceName) {
memcpy(svc->payload, conn->serviceName, strlen(conn->serviceName));
}
cursor += namelen + TAG_HDR_SIZE;
}
else{
plen = 0;
}
1.2 PADO, active discovery offer
1.接入集中器收到在服务范围内的PADI分组,发送PPPoE有效发现提供包分组,以响应请求。
- 服务器:pppoe-server.c processPADI
可接受的tag:
PPPoETag acname;
PPPoETag servname;