PPP
Posted dongzhuangdian
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了PPP相关的知识,希望对你有一定的参考价值。
名称
chat–调制解调器的自动对话脚本
命令格式
chat [options] script
描述
Chat程序定义了一个计算机和调制解调器之间对话交流,其主要目的是用来在本地PPPD和远端PPPD程序之间建立连接。
选项
-f <chat file>
从chat file文件读取chat脚本。这个选项的使用与chat的脚本参数互斥(mutually exclusive)。
使用者必须具有该文件的读取权限。在文件中允许多线(multiple lines)设定。应该以空格或tab键来分隔字符串。
-l <lock file>
依所指示的锁定文件执行UUCP式的锁定。
如果无法建立该文件那么chat程序将会失败。只有在chat程序因为任何原因而执行失败的情况下该锁定文件才会被删除。
如果该脚本执行成功则锁定文件将会留在磁盘上。当pppd程序不再希望使用串行设备时该锁定文件将会被删除。
不应该同时使用chat以及pppd的锁定选项来使用锁定文件。他们是互斥的选项而且如果你两个都使用将会引起其中一个或者另一个程序无法获得所需的锁定而失败。
-t <timeout>
对于要接收的预期字符串(expected string)设定的超时限制。如果在该时间限制内没有接收到该字符串的话就不发送回复字符串(reply string)。可以发送一个变通(alternate)的回复或者如果没有变通的回复字符串则该脚本运行失败。
一个失败的脚本会导致chat程序以一个非零错误代码结束。你也可以使用TIMEOUT字符串来指定超时限制。
-r <report file>
设置报告字符串输出文件。如果你使用REPORT关键字,由此产生的字符串将写入该文件中。
如果没有使用该选项而且你仍使用了REPORT关键字,输出字符串将用标准错误文件记录。
-e
打开echo选项。Echoing使用ECHO关键字在chat脚本的指定位置打开或者关闭。
当echoing被使能,所有调制解调器的输出内容将记录到标准错误文件中。
-E
使能环境变量替换chat脚本中的使用标准的$xxx语法的变量。
-v
要求chat脚本以冗长(verbose)模式执行。
chat程序将记录chat脚本的执行状态,包括所有从调制解调器中接收到的文字以及发送给调制解调器的字符串。
默认记录到SYSLOG去;记录方法可能会通过-S或者-s标志改变。
-V
要求chat脚本使用标准错误的详细模式下执行。
chat程序将记录所有从调制解调器中接收到的文本和发送给调制解调器的字符串到标准错误设备中。
该设备通常是运行chat或pppd程序的本地控制台。
-s
使用标准错误。所有由“-v”产生的日志信息和所有的错误信息将发送到标准错误。
-S
不使用SYSLOG。默认情况下,错误信息被发送到SYSLOG。-S的使用将阻止由’-v’产生的日志信息和错误信息发送到SYSLOG。
-T <phone number>
传递一个任意字符串,通常为一个电话号码,将用于替换发送字符串中的/T替换元字符。
-U <phone number 2>
传递第二个字符串,通常是一个电话号码,将用于替换发送字符串中的/U替换元字符。
当对ISDN终端适配器进行拨号时是非常有用的,它需要两个号码。
script
如果脚本没有以-f选项指定在文件里那么该脚本会如参数般被包含在chat程序里。
CHAT脚本
chat脚本定义通信过程。
一个脚本包含一个或多个“期待对方送出(expect-send)”的配对字符串(pairs of string),以空格隔开,还有一个选择性的“期待对方送出的候补(subexpect-subsend)”配对字符串,以短线(dash)隔开。像下面这个例子:
ogin:-BREAK-ogin: ppp ssword: hello2u2
这一行指示chat程序应该期待“ogin:”这个字符串。如果在所分配的时间间隔内接收登录提示失败的话,那它就送出一个中断程序(break sequence)给远端然后期待“ogin:”这个字符串。
如果第一个“ogin:”被接收到那么中断程序就不会产生。
一旦它接收到该登录提示则chat程序将送出ppp这个字符串然后期待“ssword:”这个提示。
当他接收到到密码提示后,他将会送出密码hello2u2。
一般在回复字符串后面会跟着送出一个回车(carriage return)。
在“期待”字符串里除非以/r字符指令(character sequence)指定为必须否则不会期待它的出现。
期待系列(expect sequence)应该只包含辨识字符串所需要的信息。
因为它一般是存放在磁盘文件里,它不应该包含可变信息。
通常不会以时间字符串(time strings),网络识别字符串(network identification strings),或者其他变化的数据做期待字符串。
为了修正在初始化过程中(initial sequence)可能会传送错误的字符,所以寻找字符串“ogin:”而不是“login:”。
开头的“l”字符可能接收错误而你永远找不到该字符串,即使它已经被系统发送。
同样的原因,脚本寻找“ogin:”而不是“login:”以及“ssword:”而不是“password:”。
一个非常简单的脚本看起来可能像这样:
ogin: ppp ssword: hello2u2
换句话说,期待 …ogin:,发送 ppp,期待 …ssword:,再送出hello2u2。
在实际使用上,简单的脚本是罕见的,至少在原先的字符串没有被接收时应该把候补期待(subexpect sequences)包括进来。
例如,考虑下面这个例子:
ogin:--ogin: ppp ssword: hello2u2
这会是个比前面所用的简单脚本跟好的脚本。它会寻找相同的login:提示,然而,如果没有接收到的话,会发送出一个单独的返回序列(return sequence)并且再次寻找login:。
如果线路干扰掩盖掉第一个login提示那么接着送出空线路(empty line)经常将会再次产生登录提示。
注释
注释可以嵌入在chat脚本中。注释是一个第一列以“#”字符开头的行。注释行仅仅被chat程序忽略。
如果一个“#”出现在期待指令的第一个字母中,你应该引用该字符串。如果你想等待一个以“#”字符开头的提示符,你必须像这样写:
# 现在等待注销的提示和发送字符串
‘# ‘ logout
从文件中发送数据(SENDING DATA FROM A FILE)
如果发送字符串以“@”符号开头,那么该字符串的其余部分被视为一个文件名称用以获取发送字符串。
如果读取文件的最后一个字符是换行字符,它被删除。该文件可以是一个命名管道(或者FIFO)而不是一个普通文件。
这就提供chat和其他程序通信的一个方法,例如,一个程序提供提示用户和接收用户的密码输入。
ABORT字符串
许多调制解调器以字符串来回报呼叫的状态。这个字符串可能是CONNECTED或者是NO CARRIER或者是BUSY。
通常要是调制解调器连接远端失败的话应该会希望结束脚本。困难的是脚本不会确切地知道它可能接收到那个调制解调器字符串。
在初次尝试时,它可能接收到BUSY然而下次它可能接收到NO CARRIER。
这个“失败”字符串可以用ABORT指令指定到脚本中。像下面这个例子一样写到脚本里:
ABORT BUSY ABORT ‘NO CARRIER‘ ‘‘ ATZ OK ATDT5551212 CONNECT
这个指令不会期待什么;而且接着发送ATZ这个字符串。对此期待的回应是OK这个字符串。
当它接收到OK时,字符串ADTD5551212就进行拨号。期待字符串是CONNECT。
如果接收到字串CONNECT那么就会执行脚本其余部分。
然而,要是调制解调器发现电话忙线,他将会发送出BUSY这个字符串。
这会使得该字符串符合失败字符命令(abort character)。
这个脚本将会因为它发现一个失败字符串(abort string)而失败(fail)。
如果他接收到的是NO CARRIER字符串,它也会因为同样的原因而失败。
不是可以接收到字符串就是字符串将终结chat脚本。
CLR_ABORT字符串
这个指令允许清除以前的ABORT字符串设置。ABORT字符串被保存在一个预定大小的数组内(在编译时);
CLR_ABORT将清除条目的空间回收,以便新的字符串可以使用这些空间。
SAY字符串
SAY指令允许脚本在终端上通过标准错误发送字符串给用户。
如果chat正在被pppd运行,而pppd是作为一个守护进程(同它的控制终端分离)运行,标准错误通常被重定向到文件/etc/ppp/connect-errors中。
SAY字符串必须使用单引号或者双引号。如果字符串中需要输出回车和换行,你必须明确地将它们添加到您的字符串。
SAY字符串可以用来提供那些你使用了“ECHO OFF”但是仍想让用户知道发生什么的脚本段落的进度信息。一个例子是:
ABORT BUSY
ECHO OFF
SAY "Dialling your ISP.../n"
‘‘ ATDT5551212
TIMEOUT 120
SAY "Waiting up to 2 minutes for connection ... "
CONNECT ‘‘
SAY "Connected, now logging in ...0
ogin: account
ssword: pass
$ SAY "Logged in OK ...0 etc ...
这段脚本将目前唯一的SAY字符串发送给用户,所有脚本的详细信息将保持隐藏。例如,如果上面这段脚本运行,用户将看到:
Dialling your ISP...
Waiting up to 2 minutes for connection ... Connected, now logging in ...
Logged in OK ...
REPORT字符串
报告字符串类似于ABORT字符串。所不同的是,字符串和所有字符到下一个控制字符如回车,都被写入报告文件。
报告字符串可以用来分离调制解调器的连接字符串中的发送速率和返回该值给chat用户。
报告字符串的分析产生逻辑结合其他字符串过程像寻找期待字符串。
同样的字符串在报告指令和中止指令中的作用可能不是非常有用,但是,他是可能的。
报告字符串并没有改变程序的完成代码。
这些“报告”字符串被脚本中的REPORT指令所指定。方法如以下示例脚本:
REPORT CONNECT ABORT BUSY ‘‘ ATDT5551212 CONNECT ‘‘ ogin: account
该脚本不期望什么;接着发送字符串ATDT5551212拨打电话期望的字符串是CONNECT。
如果接收到字符串CONNECT脚本的其余部分将被执行。此外程序将字符串“CONNECT”和跟随它之后的任何字符如连接速率写入预期文件。
CLR_REPORT字符串
这个指令允许清除以前的REPORT字符串设置。REPORT字符串被保存在一个预定大小的数组内(在编译时);
CLR_REPORT将清除条目的空间回收,以便新的字符串可以使用这些空间。
ECHO
Echo选项控制是否将调制解调器的输出ECHO到标准错误。该选项可以通过-e选项设置,但它同样可以被ECHO关键字控制。
“期待-发送”对使用ECHO ON使能ECHO,使用ECHO OFF关闭ECHO。使用这个关键字你可以选择哪部分对话应该是可见的。
如下面脚本:
ABORT ‘BUSY‘
ABORT ‘NO CARRIER‘
OK/r/n ATD1234567
/r/n /c
ECHO ON
CONNECT /c
ogin: account
所有调制解调器的输出结果、配置和拨号是不可见的,但是从CONNECT(或者BUSY)消息之后所有都被echo。
HANGUP
挂断(HANGUP)选项控制调制解调器挂断是否被视作错误。这个选项对拨号系统脚本是非常有用的,挂断并给你系统回电。
HANGUP选项可以是ON或者OFF。
当HANGUP设置为OFF并且调制解调器挂断(例如,登录一个回电系统的第一阶段之后),chat将继续运行脚本(例如,等待一个来电和第二阶段登录提示)。
只要来电被连接,你应该使用HANGUP ON指令重新安装正常挂断信号行为。这里是一个简单的脚本例子:
ABORT ‘BUSY‘
OK/r/n ATD1234567
/r/n /c
CONNECT /c
‘Callback login:‘ call_back_ID
HANGUP OFF
ABORT "Bad Login"
‘Callback Password:‘ Call_back_password
TIMEOUT 120
CONNECT /c
HANGUP ON
ABORT "NO CARRIER"
ogin:--BREAK--ogin: real_account
etc ...
TIMEOUT
初始超时值是45秒。这可以用-t参数来修改。你也可以指定“TIMEOUT 0”。
要对下一个期待字符串改变超时值的话,可以使用下面这个例子:
ATZ OK ATDT5551212 CONNECT TIMEOUT 10 ogin:--ogin: TIMEOUT 5 assword: hello2u2
这将会在在期待“login:”提示的时候把超时限制改成10秒。超时限制接着在它寻找密码提示时被改成5秒。
超时限制一旦改变就会持续作用直到它再度被改变。
传送EOT
EOT这个特别的回复字符串指示chat程序应该发送一个EOT字符到远端去。这是一般的文件结束(End-of-file)字符命令。
在EOT后面并不会跟着发送出去一个返回字符(return character)。这个EOT指令可以用^D指令嵌入到发送的字符串里。
产生中断(GENERATING BREAK)
BREAK这个特殊的回复字符串将会使得一个中断情况被送出。这个中断是发送端的一个特殊信号。
接收端一般对此的处理时改变传输率。它可以用来循环测试远端可能的传输率直到你能够接到有效的登录提示。
这个中断命令可以用/K命令嵌入到发送字符串里。
转义指令(ESCAPE SEQUENCES)
期待以及回复字符串可以包含转义指令。所有这种指令在回复字符串中都是合法的。有许多在期待字符串中是合法的。
那些在期待指令中无效的会被指出。
‘‘ 期待或送出一个空字串(null string)。如果你送出一个空字符串那么它还会送出一个返回字符(/r)。
这个指令可以是一对省略符号(apostrophe)或者也可以是引用字符。
/b 代表一个退位(backspace)字符。
/c 抑制在回复字符串结尾的新列(newline)字符。这是送出结尾没有返回字符的字符串的唯一方法。
它必须在发送字符串的结尾。例如,这个指令hello/c将会简单地送出字符h,e,l,l,o。(在期待字符串中无效。)
/d 延迟一秒钟。该程序使用最长延迟为一秒的sleep(1)。(在期待字符串中无效。)
/K 插入一个中断(在期待字串中无效。)
/n 发送一个新列(newline)或换行(linefeed)字元。
/N 送出一个空字符(null character)。同样的指令可以用/0代替。(在期待字符串中无效。)
/p 暂停一小段时间。延迟1/10秒。(在期待字符串中无效。)
/q 抑制字符串写往SYSLOG文件。该??????字串被记录到自己的空间。(在期待字符串中无效。)
/r 传送或期待一个回车字符
/s 代替字符串中的空格。这个可以用在不愿引用包含空格的字符串时。HI TIM和HI/sTIM是相同的。
/t 传送或期待一个定位(tab)字符。
/T 发送-T选项指定的电话号码字符串(在期待中无效)
/U 发送-U选项指定的电话号码字符串2(在期待中无效)
// 传送或期待一个反斜线(backslash)字符。
/ddd 将八进制数字(ddd)转换(collapse)成单一的ASCII字符并将其送出。(某些字符在期待字符串中无效。)
^C 替换含有以C代表之控制字符的指令。例如,字符DC1(17)是以^Q表示。(某些字符在期待字符串中无效。)
环境变量(ENVIRONMENT VARIABLES)
环境变量在chat脚本中是可用的,如果-E选项在命令行被指定。“$”字符用来引用用来替换的环境变量的。
如果替换失败,那是因为要求的环境变量没有设置,变量不被替换。
结束码(TERMINATION CODES)
chat随着下面的结束码终止运行。
0 程序正常终止。这表明脚本没有错误得到正常执行。
1 一个或者多个参数是无效字符串或者期待字符串大于内部缓存。这表明该程序没有正确执行。
2 一个错误发生在程序执行期间。这可能是由于读或写由于某个原因失败或者chat接收到类似SIGINT的信号量。
3 没有被选发送字符串的情况下发生了一个超时事件。这意味着你没有编写正确脚本执行条件或者发生某些突发事件而致期待字符串不能出现。
4 第一个字符串标记为ABORT条件发生。
5 第二个字符串标记为ABORT条件发生。
6 第三个字符串标记为ABORT条件发生。
7 第四个字符串标记为ABORT条件发生。
... 其他结束码也被认为是一个ABORT条件明显字符串。
使用结束码,有可能确定哪些事件终止了脚本。可以决定是否选择字符串“BUSY”而不是“NO DIAL TONE”。
虽然第一个事件可能会重试,第二个事件在重试过程中成功的机会不大。
参阅(SEE ALSO)
关于chat脚本的其他资料可以在UUCP文件里找到。chat脚本的概念由uucico程序所使用的脚本来的。
uucico(1), uucp(1)
版权(COPYRIGHT)
chat程序是个公益程序(public domain)。这并非是GNU public license。如果它毁掉了你可以保留每块碎片。
一、 协议相关介绍
- 链路控制协议 LCP(Link Control Protocol);
- 网络控制协议 NCP(Network Control Protocol);
- 认证协议:口 令验证协议PAP(Password Authentication Protocol)和挑战握手验证协议CHAP(Challenge-Handshake Authentication Protocol)。
- LCP协商,协商内容包 括除RFC1661中所定义的选项之外,还要考虑PPPOA和PPPOE协议中规定的内容。
- LCP协商过 后就到了Establish阶段,开始PAP或CHAP认证。PAP为两次握手认证,口令为明文。PAP认证过程如下:发送用户名同口令到认证方,认证方 查看是否有此用户,口令是否正确,然后发送相应的响应。CHAP为三次握手认证,口令为密文(密钥)CHAP认证由认证方发送一些随机产生的报文,交给被 认证,被认证方用自己的口令字用MD5算法进行加密,传回密文,认证方用自己保存的口令字及随机报文用MD5算法加密,比较二者的密文,根据比较结果返回 响应的响应。
- 认证成功即进 行Network阶段协商(NCP),在IP接入中主要是IPCP协商(如IP地址和DNS地址的协商等)。任何阶段的协商失败都将导致链路的拆除。
- 协商成功,则 链路建立成功,可以开始传输网络层数据报文。
二、应用关系
pppd是一个普通的用户进程,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所带一个辅助工具。 chat用来与GSM模组建立会话。它的实现比较简单,它向串口发送AT命令,建立与GSM模组的会话,以便让PPP协议可以在串口上传输数据包。
三、数据收发流程
应用程序通过socket接 口发送TCP/IP数据包,这些TCP/IP数据包如何流经PPP协议处理模块,然后通过串口发送出去呢?pppd在make_ppp_unit函数中调 用ioctrl(PPPIOCNEWUNIT)创建一个网络接口(如ppp0),内核中的PPP协议模块在处理PPPIOCNEWUNIT时,调用 register_netdev向内核注册ppp的网络接口,该网络接口的传输函数指向ppp_start_xmit。
当应用程序发送数据时,内核根据IP地址和路由表,找到ppp网络接口,然后调用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发送数据包。
pch->chan->ops->start_xmit 是什么?它就是具体的传输方式了,比如说对于串口发送方式,则是ppp_async.c: ppp_asynctty_open中注册的ppp_async_send函数,ppp_async_send经ppp_async_push函数调用 tty->driver->write把数据发送串口。
1.用 户数据发送过程如下所示:
应用程序 pppd
| |
| |
socket /dev/ppp
| |
| |
PPP协议模块
|
|
tty
|
|
GSM模组
2.pppd的控制协议数据发送过程:
pppd --Pap/chap/eap(etc)--> /dev/ppp --> PPP协议模块 --> tty --> GSM模组
3.接收数据流程:
ppp_async.c在初始化时(ppp_async_init),调用tty_register_ldisc向tty注册了行规程处理接口,也就是一组回调函数,当串口tty收到数据时,它就会回调ppp_ldisc的ppp_asynctty_receive函数接收数据。ppp_asynctty_receive调用ppp_async_input把 数据buffer转换成sk_buff,并放入接收队列ap->rqueue中。
ppp_async另外有一个tasklet(ppp_async_process)专门处理接收队列ap->rqueue中的数据包,ppp_async_process一直挂在接收队列ap->rqueue上,一旦被唤醒,它就调用ppp_input函数让PPP协议处理模块处理该数据包。
在ppp_input函数中,数据被分成两路,一路是控制协议数据包,放入pch->file.rqb队列,交给pppd处 理。另外一路是用户数据包,经ppp_do_recv/ppp_receive_frame进行PPP处理之后,再由netif_rx提交给上层协议处理,最后经socket传递到应用程序。
应用程序 pppd
| |
| |
socket /dev/ppp
| |
| |
PPP协议模块
|
|
tty
|
|
GSM模组
搭建 PPPOE 拨号上网
DevinGeng
发表于云+技术订阅
234
腾讯云服务器 年付3折起
首次购买云服务器 最低3折起 超高性价比
限时抢购
PPPoE是point-to-point protocol over ethernet的简称,可以使以太网的主机通过一个简单的桥接设备连到一个远端的接入集中器上。通过pppoe协议,远端接入设备能够实现对每个接入用户的控制和计费。rp-PPP0E是一个集成了拨号客户端和服务端的解决方案。
下载地址:http://www.roaringpenguin.com/products/pppoe
编译、安装的步骤:
rp-pppoe-3.10.tar.gz 在 /opt 目录下。
tar -zxvf rp-pppoe-3.10.tar.gz
cd rp-pppoe-3.10/src
./configure
make
make install
修改配置文件:
cd /etc/ppp
vim pppoe.conf
修改下面几个值,其他的不要动
ETH=eth0
USER=rp-pppoe
LINUX_PLUGIN=/etc/ppp/plugins/rp-pppoe.so
vim pppoe-server-options
下面是全部内容
require-pap
require-chap
login
lcp-echo-interval 10
lcp-echo-failure 2
logfile /var/log/pppoe.log
ms-dns 218.108.248.200
ms-dns 8.8.4.4
defaultroute
vim chap-secrets
rp-pppoe * rp-pppoe *
以上表示用户名和密码都是rp-pppoe
vim options
local
运行程序:
(用户模式)
/usr/sbin/pppoe-server -I eth0 -L 10.0.0.1 -R 10.0.0.2 -N 64
-I 指定局域网网卡
-L 指定pppoeserver的IP地址
-R 为客户分配的起始IP地址
-N 指定分配给客服端IP地址的个数
-k 使用内核模式
现在就可以用pppoe客户端来连接我们已经运行的pppoeserver了,用户名和密码为上面设置的
rp-pppoe和rp-pppoe,认证方式为CHAP
但是客户端连接上去后不能上网,因为服务器那边没有进行数据包的转发。
虚拟机添加了2块网卡,eth0和eth1,eth0是静态IP,eth1为DHCP方式获取IP。
需要修改下配置脚本
cd/etc/sysconfig/network-scripts
vim ifcfg-eth0
#Advanced Micro Devices [AMD] 79c970 [PCnet32 LANCE]
DEVICE=lan
IPADDR=192.168.61.120
NETMASK=255.255.255.0
GATEWAY=192.168.61.1
DNS1=61.139.2.69
DNS2=192.168.61.1
HWADDR=00:0c:29:6b:71:d6
ONBOOT=yes
BOOTPROTO=static
USERCTL=no
IPV6INIT=yes
NM_CONTROLLED=yes
TYPE=Ethernet
vimifcfg-eth1
TYPE="Ethernet"
HWADDR=00:0C:29:6B:71:E0
BOOTPROTO=dhcp
DEVICE=wan
ONBOOT=yes
开启数据包转发
echo"1">>/proc/sys/net/ipv4/ip_forward
iptables -t nat -A POSTROUTING -o eth1 -j MASQUERADE
好了,现在客户端这边就可以上网了。
下面是 etherPeek 抓包的截图,pppoe发现阶段已经省去,只是TCP3次握手和4次挥手的抓包。
10.0.0.10是pppoe客户端的IP,192.168.61.206是linux下eth1的IP,每次局域网网关收到eth0上的数据,然后把源IP改成eth1的IP,目的IP不变,
广域网网卡收到远端服务器返回的数据,就把目的IP修改成内网主机pppoe的IP。
TCP3次握手
4次挥手
PPPoE 的验证过程
PPPoE 的验证过程包括 2 个阶段,Discovery 阶段和 PPP Session 阶段。
Discovery 阶段,包含 4 个步骤:
Step 1: PADI
PPPoE 客户端发送主动发现初始包(PPPoE Active Discovery Initiation,PADI),以太头中的目的地址是以太广播地址 FF:FF:FF:FF:FF:FF,PPPOE 头中的 CODE 为 0x09,SESSION_ID 值必须为 0,负载部分必须只包含一个 Service-Name 类型的 TAG 表示请求的服务类型,另外可以包含其他 TAG,整个 PPPOE 包不能超过 1484 字节;
Step 2: PADO
服务器端 PPPoE 进程在网络接口侦听到 PADI 包后,发送主动发现提议包(PPPoEActive Discovery Offer, PADO),用来回应客户机的 PADI 包,以太头中的目的地址是客户机的MAC 地址,PPPOE 头中的 CODE 为 0x07, SESSION_ID 值必须为 0,负载部分必须包含一个 AC-Name 类型的 TAG,用来指示本 AC 的名称,一个在 PADI 包中指定的Service- Name 的 TAG,另外可以包含其他 Service-Name 的 TAG。如果 AC 不对该客户机提供服务,AC 就不回应 PADO 包。
Step 3: PADR
PPPoE 客户端收到 PADO 包后,在 PADO 包中选择一个(可能有多个 PPPoE 服务器,通常选取最快的一个)发送主动发现请求包(PPPoEActive Discovery Request,PADR),以太头中的目的地址是所选取的 PADO 包的源以太头地址(即 PPPoE 服务器的 MAC 地址),PPPOE 头中的 CODE 为 0x19,SESSION_ID 值必须为 0,负载部分必须只包含一个 Service-Name 类型的 TAG 表示请求的服务类型,另外可以包含其他 TAG。
Step 4: PADS
MAC 地址匹配的 PPPoE 服务器收到 PADR 包后,发送主动发现会话确认包(PPPoE Active Discovery Session-confirmation, PADS),将产生一个SEESSION_ID 值用来标志本次 PPP 会话,以 PADR 包方式发送给客户机。以太头中的目的地址是客户机的 MAC 地址,PPPOE 头中的 CODE 为 0x65,SESSION_ID 值必须为所生成的那个SESSION_ID,负载部分必须只包含一个 Service-Name 类型的 TAG,表示该服务类型被 PPPoE 服务器接受,另外可以包含其他 TAG。如果 PPPoE 服务器不接受 PADR 中的
Server-Name,PADS 中则包含一个 Service-Name -Error 类型的 TAG,这时 SESSION_ID 设置为 0。
PPP Session 阶段:
当客户端与服务器端远成发现阶段之后,即进入会话阶段,在 PPP 会话阶段,PPP 包被封装在 PPPOE 以太帧中,以太包目的地址都是单一的,以太协议为 0x8864,PPPOE 头的CODE必须为0,SESSION_ID必须一直为发现阶段协商出的SEESION_ID值,PPPOE的负载是整个 PPP 包,PPP 包前是两字节的 PPP 协议 ID 值。
在 Session 阶段,主机或服务器任何一方都可发 PADT(PPPoE Active Discovery Terminate)报文通知对方结束 Session。
PPPoE 的身份验证发生在会话(PPP Session)阶段。可以这样更解,rp-pppoe 包负责Discovery 及会话终止 PADT,ppp 包负责会话阶段的数据传输。
以上是关于PPP的主要内容,如果未能解决你的问题,请参考以下文章
*++*++ppp,*++pp[1],*++(*(1+ppp)有啥具体的区别吗?(C/C++指针问题)
计算机网络(谢希仁 第七版) 第三章(数据链路层)-- 3.2 点对点协议PPP(PPP协议的特点 & PPP协议的帧格式 & PPP协议的工作状态)