如何在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)

}

}

第一种方法

# echo 1 >/proc/sys/net/ipv6/bindv6only

# echo "net.ipv6.bindv6only = 1" >>/etc/sysctl.conf

第二种方法

让系统不加载ipv6相关模块,这需要修改modprobe相关设定文件,为了管理方便,我们新建设定文件/etc/modprobe.d/ipv6off.conf,内容如下,三种方式,总有一款适合你:

aliasnet-pf-10 off

options ipv6 disable=1

或者 installipv6/bin/true

或者 installipv6/sbin/modprobe-n -i ipv6

注意,如果你使用了网卡绑定(bond)技术,而且不希望用ipv6,那么你使用第一种,否则系统启动时,bonding模块可能会加载失败。


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

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

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

发表评论

登录后才能评论

评论列表(0条)

保存