小知识: 柔性数组 : 柔性数组既数组大小待定的数组, C语言中结构体的最后一个元素可以是大小未知的数组,也就是所谓的0长度,所以我们可以用结构体来创建柔性数组。 https://www.cnblogs.com/veis/p/7073076.html
封装一个结构体是在不确定某一个成员大小时可以使用如果上图的柔性数组 ,扩展这个结构体的内存大小, 因为是连续的所以仅限于数组
设计流程: 无论什么协议都先宏观的了解其动态结构(交互过程) ,再微观的了解静态结构(交互的实现和其组成的字段)
1.协议实现的动态结构: 了解协议的交互过程
PPOE分成两个阶段 1.发现阶段: 发现和确定对端的存在 2.会话阶段: 认证并建立好对端的连接并开始数据传输
第一阶段 :PADI -> 广播查找对端服务器 PADO -> 回应并告知自己的信息 PADR -> 请求会话号 PADS -> 分配并告知会话号
第二阶段 :LCP协商: 协商双方使用什么方式认证(明文认证密文认证等) ,
认证 :认证成功后获得了授权 ,
IPCP协商 :IP DNS WINS等 的协商 , 完成认证并授权后开始数据传输
2.协议实现的静态结构: 了解协议字段的组成
链路层协议的组成: 源(6字节) , 目的(6字节) ,L/T(协议长度(14字节)和类型(决定了data协议类型) 2字节) , data(协议)
//消息包的类型 #define PADI_CODE 0x09 #define PADO_CODE 0x07 #define PADR_CODE 0x19 #define PADS_CODE 0x65 #define PADT_CODE 0xa7
struct pppoe_tag {
unsigned short tag_type;
unsigned short tag_len;
char tag_data[0];
};
//网络字节序是大端序 ,Linux和Windows都是小端序 //实现一个协议结构 PPOE协议 Discovery阶段的所有消息包都是使用下列结构 struct ppoe_discovery { unsigned char type; // 协议类型 unsigned char version; // 版本 unsigned char code; // 消息类型 unsigned short session; // 用作PPOE后续认证授权的session ,由服务端发送 unsigned short size; // 整个包的大小 struct pppoe_tag tag[0]; // tag里可以存放的本机或对端的标识码等 ,常见的TAG都符合TLV结构 } // host-uniq(标识客户端) , // AC-Cookie(标识与客户端的链接,用于恢复会话的, 比如浏览器历史记录的恢复网页的访问)),tag[0]作为一个索引使用. // AC-Name 标识服务端 // Service-Name 一般不需要 ,用于设备绑定 服务端提供的服务名必须和客户端的一样 ,
PADI(I = Initiation)包 :广播(在同一个局域网)查找网络中的服务器 ,因为是广播所以目标地址=ff:ff:ff:ff:ff:ff tags : host-uniq 标识客户端
PADO(O = Offer)包 :服务器端响应,将自己的一些信息告知客户端; tags : host-uniq ,AC-Name 标识服务端 ,AC-Cookie 返回标识当次会话的链接
PADR(R = Request)包 :客户端向此服务器发送,请求Session号; tags : host-uniq ,AC-Cookie 使用Cookie号继续本次会话
PADS(S = Session-confirmation)包 :服务器端响应,将分配的Session号返回。至此,PPPoE会话建立。后续可以进行PPP的协商了。
tags : host-uniq ,AC-Cookie ,Session
上述的是 discover阶段的 静态结构和动态结构 , 现在开始session阶段
#define MTU 1500 #define PPPOE_HEADER_LEN 6 #define LCP 0xc021 #define PAP 0xc023 #define CHAP 0xc223 #define IPCP 0x8021 struct ppp_frame_for_pppoe { unsigned short int Protocol_Field; //session阶段的协议类型 char Information[MTU-PPPOE_HEADER_LEN-2]; }; struct LCP_packet { unsigned char Code; unsigned char Identifier; unsigned short int Length; //indicates the length of the LCP packet, including the Code, Identifier, Length and Data fields char Data[MTU-PPPOE_HEADER_LEN-2-1-1-2]; }; struct magic_number { unsigned char Type; unsigned char Length; unsigned int Data; }; struct MRU { unsigned char Type; unsigned char Length; unsigned short int Data; };
PPPoE会话阶段有三个过程:
1.LCP协商,完成二层的建链和参数协商。
LCP = Link Control Protocol,链路控制协议
此阶段主要是协商链路的一些参数,如最大接收单元MRU、Magic Number,以及后续认证时使用的协议等;
2.认证,主要使用PAP\CHAP\MSCHAP
此阶段服务器端将验证客户端的合法性。最常见的两种就是PAP和CHAP;
PAP认证:发送的认证信息是明文,可以通过抓包工具看到用户名、密码;
CHAP认证:发送的认证信息是密文,抓包工具无法解析出来真正的用户名、密码。
3.NCP协商,使用IPCP协议,完成三层的配置。
此阶段进行IP、DNS、WINS等的协商;
4.数据传输: 上述任一阶段失败都会导致协议终止。如果都成功,则可以开始进行IP层的通信了;