如何在Linux内核中为IPv6添加一种新的扩展头

如何在Linux内核中为IPv6添加一种新的扩展头,第1张

IPv6头部的设计是一个简洁的基本头部后面根据需要加上多种不同类型的扩展头部,这种设计可以将不常用的功能通过选择性的添加不同的扩展头部实现,从而在保证了基本头部的简洁和处理的快速性。以Linux2.6.28版本内核为例,IPv6扩展首部的定义在Linux-2.6.28/include/linux/in6.h和linux-2.6.28/include/net/ipv6.h两个目录下,我们以添加一种IPPROTO_MY类型的扩展头为例:

1、在头文件中添加新类型扩展头的定义,在linux-2.6.28/include/linux/in6.h中

/*

* NextHeader field of IPv6 header

*/

#define NEXTHDR_HOP 0 /* Hop-by-hop option header. */

#define NEXTHDR_TCP 6 /* TCP segment. */

#define NEXTHDR_UDP 17 /* UDP message. */

#define NEXTHDR_IPV6 41 /* IPv6 in IPv6 */

#define NEXTHDR_ROUTING 43 /* Routing header. */

#define NEXTHDR_FRAGMENT 44 /* Fragmentation/reassembly header. */

#define NEXTHDR_ESP 50 /* Encapsulating security payload. */

#define NEXTHDR_AUTH 51 /* Authentication header. */

#define NEXTHDR_ICMP 58 /* ICMP for IPv6. */

#define NEXTHDR_NONE 59 /* No next header */

#define NEXTHDR_DEST 60 /* Destination options header. */

#define NEXTHDR_MOBILITY 135 /* Mobility header. */

#define IPPROTO_MY 200/*自己定义的头部类型 */

2、在linux-2.6.28/include/net/ipv6.h中定义结构体

/*

* IPV6 extension headers

*/

#define IPPROTO_HOPOPTS 0 /* IPv6 hop-by-hop options */

#define IPPROTO_ROUTING 43 /* IPv6 routing header */

#define IPPROTO_FRAGMENT 44 /* IPv6 fragmentation header */

#define IPPROTO_ICMPV6 58 /* ICMPv6 */

#define IPPROTO_NONE 59 /* IPv6 no next header */

#define IPPROTO_DSTOPTS 60 /* IPv6 destination options */

#define IPPROTO_MH 135 /* IPv6 mobility header */

自己定义新的扩展头类型如:

#define NEXTHDR_INDEX200/*IPv6 next header */

自己定义新的扩展头类型:

struct index_hdr{ /*index扩展头结构*/

__u8nexthdr

__u8hdrlen

__u16 reserved

__u32 skb_index

}

3、在需要添加头部和删除头部的源文件中添加添加和删除函数,届时直接调用这两个函数即可

static void ip6_index_add(struct sk_buff *skb,unsigned char *data,unsigned int len)

{

struct ipv6hdr *tmp_hdr

struct ipv6hdr *old_hdr

struct index_hdr *ih

u8 prevhdr

unsigned int hlen

unsigned int ilen

ilen=sizeof(struct index_hdr)

hlen=sizeof(struct ipv6hdr)

old_hdr=skb_network_header(skb)

prevhdr=old_hdr->nexthdr

if(prevhdr!=200){

old_hdr->nexthdr=NEXTHDR_INDEX

tmp_hdr = kmemdup(skb_network_header(skb), hlen, GFP_ATOMIC)

__skb_pull(skb, hlen) /*使data指针下移hlen长度,将ipv6头部去掉*/

ih = (struct index_hdr*)__skb_push(skb, ilen) /*上移data指针,将index头部添加进去*/

__skb_push(skb, hlen) /*继续上移data指针,将原来的ipv6头部加进去*/

skb_reset_network_header(skb)

memcpy(skb_network_header(skb), tmp_hdr, hlen)

/*为index扩展头赋值*/

ih->nexthdr = prevhdr

ih->hdrlen = 8

ih->reserved = 0

ih->skb_index = htonl(skb->xfrm_index)

skb->truesize += ilen

ipv6_hdr(skb)->payload_len += ilen

data = skb->data

len = skb->len

kfree(tmp_hdr)

}

}

static void ip6_index_del(struct sk_buff *skb,unsigned char *data,unsigned int len)

{

struct ipv6hdr *tmp_hdr

struct ipv6hdr *old_hdr

struct index_hdr *ih

u8 prevhdr

unsigned int hlen

unsigned int ilen

ilen=sizeof(struct index_hdr)

hlen=sizeof(struct ipv6hdr)

if(ipv6_hdr(skb)->nexthdr == 200){

tmp_hdr = kmemdup(skb_network_header(skb), hlen, GFP_ATOMIC)/*保存ipv6头*/

__skb_pull(skb, hlen) /*下移data指针,去掉ipv6头*/

skb_reset_network_header(skb)

ih=(struct index_hdr *)skb_network_header(skb)

prevhdr = ih->nexthdr

tmp_hdr->nexthdr = prevhdr

__skb_pull(skb, ilen) /*下移data指针,去掉index扩展头*/

__skb_push(skb, hlen)/*上移data指针,将原来的ipv6头添加回去*/

skb_reset_network_header(skb)

memcpy(skb_network_header(skb), tmp_hdr, hlen)

skb_reset_network_header(skb)

skb->truesize -= ilen

ipv6_hdr(skb)->payload_len -= ilen

kfree(tmp_hdr)

}

}

首先确认所使用的网络支持ipv6,装载的Linux系统支持ipv6

网络设置里设置ipv6为“自动-DHCP”模式

根据得到的ipv6地址(2001::打头的是公用,fe80::是本机私有)

ping6 ipv6.google.com

ping通,就可以访问ipv6网站了。不然使用如下步骤

[plain] view plain copy

sudo dhclient -6 -r //释放ipv6地址

sudo dhclient -6 //重新获取ipv6地址

sudo service networking restart//重启网络服务

[plain] view plain copy

不知道为什么在另外一台机器上,上述命令不行,不过可以先设置Ipv6的地址获取方式为忽略,然后sudo dhclient -6手动获取ipv6地址,这样也可以使用了


欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/yw/7523486.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-04-06
下一篇 2023-04-06

发表评论

登录后才能评论

评论列表(0条)

保存