--------------------------------------------------------------
| Ethernet Header | IPv6 Header | UDP Header | Payload/Data |
--------------------------------------------------------------
^ ^ ^ ^
| | | |
skb->data skb->network_head skb->transport_head skb->tail
假设我们有一个上述 skb
数据包结构:
skb->data
:指向数据包数据区域的指针,即数据包的起始地址。skb->network_head
:指向网络头部的指针,如 IPv6 头部。skb->transport_head
:指向传输层头部的指针,如 UDP 头部。skb->tail
:指向数据包数据区域的末尾,即数据包的结束地址。
1 skb_pull()
// 假设 eth_hdr_len 和 ipv6_hdr_len 分别表示以太网头部和 IPv6 头部的长度
skb_pull(skb, eth_hdr_len + ipv6_hdr_len);
执行"skb_pull()"后,'skb' 指针将被移动到UDP头部的位置,数据包的指针"skb->data"现在指向UDP头部的起始位置,以太网头部和Ipv6头部的数据被消耗掉,已经不再存在于数据包中。
2 skb_push()
// 假设 custom_hdr_len 表示自定义协议头部的长度
unsigned char *custom_hdr = skb_push(skb, custom_hdr_len);
// 设置 custom_hdr 的字段值
// ...
执行"skb_push()"后,数据包中的所有数据都将向后移动,为新添加的自定义协议头部留出空间。"skb->data"指针指向新添加的自定义协议头部的起始位置。
3 skb_append()
当需要向数据包中追加一些额外的数据,使用"skb_append()"
// 假设 payload_len 表示要追加的有效载荷长度
unsigned char *payload = skb_append(skb, payload_len);
// 填充 payload 数据
// ...
执行'skb_append()'后,数据包的长度将增加,'skb_data'指针仍然指向原有的数据末尾,而'payload'指针指向追加的有效载荷的起始位置。
在网络编程的过程中,这几个函数是基础,不能把报文的解析搞错否则后果很严重。