精华内容
下载资源
问答
  • 分片重组
    更多相关内容
  • IP分片重组

    2017-12-24 11:43:11
    亲自写的,很有用,希望能对大家有帮助,里面主要介绍了IP分片重组的概念、方法以及在Linux下进行操作所需要的代码
  • c#文件分片重组源码

    2016-07-21 09:56:36
    FileCut.csproj Form1.Designer.cs
  • tcp/ip协议中ip分片重组以及tcp分段重组具体实现原理
  • 基于FPGA的IP分片重组的实现.pdf
  • IPv4与IPv6业务-IP虚拟分片重组技术介绍.pdf
  • 将经过分片的IP包重组成原来的数据包,并以16进制输出内容(考虑到长度限制,可以只输出数据包交界部分的内容,以验证重组的正确性)
  • 针对如何克服当前SQL注入渗透测试存在的盲目性,以生成优化的SQL注入攻击模式、增强渗透测试攻击生成阶段的有效性,提高对SQL注入渗透测试的准确度问题,提出一种基于二阶分片重组的SQL盲注漏洞渗透测试方法。...
  • IPv4之分片重组(三)

    2020-02-27 00:02:33
    这篇笔记来看看分片重组功能额外的一些细节实现,包括: IP分片队列的回收; 哈希表的重新散列; IP分片队列的回收 首先,最正常的情况就是收到了所有的IP分片,然后将其组装成一个完整的IP报文,然后递交给上层。...

    这篇笔记来看看分片重组功能额外的一些实现细节,包括:

    1. IP分片队列的回收;
    2. 哈希表的重新散列;

    IP分片队列的回收

    首先,最正常的情况就是收到了所有的IP分片,然后将其组装成一个完整的IP报文,然后递交给上层。情况最差的,就是在规定的时间内没有收到全部的分片,这时需要有老化机制,使得之前缓存的片段能够被释放,否则对系统是一种负担。

    重组完成后的IP分片队列回收

    在ip_frag_reasm()中,并没有看到有对IP分片队列的明确回收操作,相关的两个动作如下:

    /* Build a new IP datagram from all its fragments. */
    static int ip_frag_reasm(struct ipq *qp, struct sk_buff *prev, struct net_device *dev)
    {
    ...
    	// 实现见下文
    	ipq_kill(qp);
    	// 分片队列后面的skb全部移除
    	qp->q.fragments = NULL;
    ...
    }
    

    ipq_kill()

    void inet_frag_kill(struct inet_frag_queue *fq, struct inet_frags *f)
    {
    	// 停止定时器,如果停止成功则递减引用计数,因为在安装定时器时增加了引用计数
    	// 这里需要对应操作
    	if (del_timer(&fq->timer))
    		atomic_dec(&fq->refcnt);
    	// 对于没有设置COMPLETE标记的IP分片队列,将其从哈希表和LRU表中移除,并且递减其引用计数,然后设置CPMPLETE,
    	// 如果不设置该标记,后续无法进行释放。重组场景调用ipq_kill()时还并没有设置COMPLETE标记
    	if (!(fq->last_in & COMPLETE)) {
    		fq_unlink(fq, f);
    		atomic_dec(&fq->refcnt);
    		fq->last_in |= COMPLETE;
    	}
    }
    EXPORT_SYMBOL(inet_frag_kill);
    
    /* Kill ipq entry. It is not destroyed immediately,
     * because caller (and someone more) holds reference count.
     */
    static void ipq_kill(struct ipq *ipq)
    {
    	inet_frag_kill(&ipq->q, &ip4_frags);
    }
    

    如上代码所示,对于正常重组后的IP分片队列,这里仅仅是递减了其引用计数,并没有执行直接的释放动作,所以需要回忆其从创建到重组过程中引用计数的变化:

    创建时

    static struct inet_frag_queue *inet_frag_alloc(struct netns_frags *nf, struct inet_frags *f, void *arg)
    {
    	struct inet_frag_queue *q;
    ...
    	// 初始化引用计数为1
    	atomic_set(&q->refcnt, 1);
    ...
    }
    

    启动定时器/插入哈希表时
    创建IP分片队列后,会立即启动其组装超时定时器,此时也会增加引用计数,因为定时器超时函数也会引用该IP分片队列。

    在将IP分片队列放入全局的哈希表和LRU表后,也会增加引用计数。

    static struct inet_frag_queue *inet_frag_intern(struct netns_frags *nf,
    		struct inet_frag_queue *qp_in, struct inet_frags *f, unsigned int hash, void *arg)
    {
    	struct inet_frag_queue *qp;
    ...
    	// 启动该IP分片队列的定时器,超时时间来自系统参数(见网络命名空间中的frags)
    	if (!mod_timer(&qp->timer, jiffies + nf->timeout))
    		atomic_inc(&qp->refcnt);
    	// 将新的IP分片队列加入哈希表中,并累加计数器
    	atomic_inc(&qp->refcnt);
    	hlist_add_head(&qp->list, &f->hash[hash]);
    	// 将qp加入LRU链表
    	list_add_tail(&qp->lru_list, &nf->lru_list);
    ...
    }
    

    查找时
    在每次执行ip_find()后,都会增加一次引用计数,这是为了保证在引用期间IP分片队列不会被释放,引用结束后会做对应的递减操作。

    struct inet_frag_queue *inet_frag_find(struct netns_frags *nf, struct inet_frags *f, void *key, unsigned int hash)
    {
    	struct inet_frag_queue *q;
    ...
    	hlist_for_each_entry(q, n, &f->hash[hash], list) {
    		if (q->net == nf && f->match(q, key)) {
    			// 已经存在的场景下,匹配后增加引用计数
    			atomic_inc(&q->refcnt);
    			read_unlock(&f->lock);
    			return q;
    		}
    	}
    	// 新建场景,并不会额外增加引用计数,因为在创建时已经初始化为1了
    	return inet_frag_create(nf, f, key, hash);
    }
    

    如上分析,对于所有分片重组成功的场景,一共增加了3次引用计数,在重组完成后,同样进行了3次递减(删除定时器、从哈希表中删除、查找结束后),关键的释放动作在查找结束后对ipq_put()的调用,该调用后,IP分片队列的引用计数会递减为0,进而执行内存回收动作。

    ipq_put()

    void inet_frag_destroy(struct inet_frag_queue *q, struct inet_frags *f, int *work)
    {
    	struct sk_buff *fp;
    	struct netns_frags *nf;
    	// 必须设置了COMPLETE标记,否则视为异常
    	BUG_TRAP(q->last_in & COMPLETE);
    	// 分片队列的重组超时定时器必须已经停止
    	BUG_TRAP(del_timer(&q->timer) == 0);
    
    	// 释放已经收到的所有IP分片
    	fp = q->fragments;
    	nf = q->net;
    	while (fp) {
    		struct sk_buff *xp = fp->next;
    		frag_kfree_skb(nf, f, fp, work);
    		fp = xp;
    	}
    
    	if (work)
    		*work -= f->qsize;
    	// 在内存记账信息中递减IP分片队列本身占用的内存大小
    	atomic_sub(f->qsize, &nf->mem);
    	// 如果协议相关的IP分片队列指定了析构回调则调用它,然后释放分片队列自身占用内存,
    	// IP分片队列提供了析构函数ip4_frag_free(),其中释放了和IP端点管理有关的信息
    	if (f->destructor)
    		f->destructor(q);
    	kfree(q);
    }
    
    static inline void inet_frag_put(struct inet_frag_queue *q, struct inet_frags *f)
    {
    	// 递减引用计数,如果计数变为了0,则执行销毁动作
    	if (atomic_dec_and_test(&q->refcnt))
    		inet_frag_destroy(q, f, NULL);
    }
    
    static __inline__ void ipq_put(struct ipq *ipq)
    {
    	// 全局变量ip4_frags索引了IPv4的所有IP分片队列
    	inet_frag_put(&ipq->q, &ip4_frags);
    }
    

    重组超时后的IP分片队列回收

    在IP分片队列被创建后,会启动IP分片队列的定时器(struct inet_frag_queue的timer成员),超时时间nf->timeout来自系统参数/proc/sys/net/ipv4/ipfrag_time,默认30s,超时函数frag_expire实际指向ip_expire()。

    在inet_frag_intern()中,定时器启动成功后,增加了IP分片队列的引用计数,这时因为在定时器回调中会使用该数据结构,所以在定时器超时前,要保证该结构不会被释放。

    static struct inet_frag_queue *inet_frag_intern(struct netns_frags *nf,
    		struct inet_frag_queue *qp_in, struct inet_frags *f, unsigned int hash, void *arg)
    {
    	struct inet_frag_queue *qp;
    ...
    	qp = qp_in;
    	// 启动该IP分片队列的定时器,超时时间来自系统参数(见网络命名空间中的frags)
    	if (!mod_timer(&qp->timer, jiffies + nf->timeout))
    		atomic_inc(&qp->refcnt);
    ...
    }
    
    static struct inet_frag_queue *inet_frag_alloc(struct netns_frags *nf, struct inet_frags *f, void *arg)
    {
    	struct inet_frag_queue *q;
    ...
    	// 建立定时器,但是并不启动,启动是在inet_frag_intern()中完成的
    	setup_timer(&q->timer, f->frag_expire, (unsigned long)q);
    ...
    }
    

    重组超时函数: ip_expire()

    上面的分片超时函数对于IPv4来说是ip_expire()。

    /*
     * Oops, a fragment queue timed out.  Kill it and send an ICMP reply.
     */
    static void ip_expire(unsigned long arg)
    {
    	struct ipq *qp;
    
    	qp = container_of((struct inet_frag_queue *) arg, struct ipq, q);
    	spin_lock(&qp->q.lock);
    	// 对于设置了COMPLETE标记的
    	if (qp->q.last_in & COMPLETE)
    		goto out;
    	// 见上面的分析
    	ipq_kill(qp);
    
    	IP_INC_STATS_BH(IPSTATS_MIB_REASMTIMEOUT);
    	IP_INC_STATS_BH(IPSTATS_MIB_REASMFAILS);
    	// 如果收到了第一个分片,那么向远端发送ICMP消息,之所以要收到第一个分片,是因为ICMP消息
    	// 中必须携带产生该ICMP报文的一些信息,第一个分片包含了源报文的头部信息
    	if ((qp->q.last_in&FIRST_IN) && qp->q.fragments != NULL) {
    		struct sk_buff *head = qp->q.fragments;
    		/* Send an ICMP "Fragment Reassembly Timeout" message. */
    		if ((head->dev = dev_get_by_index(&init_net, qp->iif)) != NULL) {
    			icmp_send(head, ICMP_TIME_EXCEEDED, ICMP_EXC_FRAGTIME, 0);
    			dev_put(head->dev);
    		}
    	}
    out:
    	spin_unlock(&qp->q.lock);
    	// 将会销毁IP分片队列
    	ipq_put(qp);
    }
    

    哈希表的重新散列

    在刚开始,哈希表中各个分片队列的分布是比较均匀的,但是经过一段时间,不断的有分片队列从哈希表中删除或者添加,那么哈希表将变得不再均匀,这样会影响处理性能,因此内核设计了一种机制,定期对哈希表重新进行散列,使其尽量保持均匀。

    在初始化时安装了一个定时器,如下:

    void inet_frags_init(struct inet_frags *f)
    {
    ...
    	// 生成随机数,并直接启动定时器,定时间隔指定为10分钟,定时器函数是inet_frag_secret_rebuild()
    	f->rnd = (u32) ((num_physpages ^ (num_physpages>>7)) ^ (jiffies ^ (jiffies >> 6)));
    	setup_timer(&f->secret_timer, inet_frag_secret_rebuild, (unsigned long)f);
    	f->secret_timer.expires = jiffies + f->secret_interval;
    	add_timer(&f->secret_timer);
    }
    

    inet_frag_secret_rebuild()

    static void inet_frag_secret_rebuild(unsigned long dummy)
    {
    	struct inet_frags *f = (struct inet_frags *)dummy;
    	unsigned long now = jiffies;
    	int i;
    
    	write_lock(&f->lock);
    	// 重新生成随机数,该随机数是哈希算法的一个参数
    	get_random_bytes(&f->rnd, sizeof(u32));
    	// 遍历所有的哈希桶
    	for (i = 0; i < INETFRAGS_HASHSZ; i++) {
    		struct inet_frag_queue *q;
    		struct hlist_node *p, *n;
    		// 对于冲突链中的每个分片队列,重新计算其哈希值,如果索引不是当前冲突链,
    		// 将其从当前冲突链删除,并加入新的冲突链中
    		hlist_for_each_entry_safe(q, p, n, &f->hash[i], list) {
    			unsigned int hval = f->hashfn(q);
    			if (hval != i) {
    				hlist_del(&q->list);
    				/* Relink to new hash chain. */
    				hlist_add_head(&q->list, &f->hash[hval]);
    			}
    		}
    	}
    	write_unlock(&f->lock);
    	// 重新启动定时器
    	mod_timer(&f->secret_timer, now + f->secret_interval);
    }
    
    展开全文
  • educoder -- ip分片重组

    2022-04-18 14:56:17
    将收到ip分片重组为完整的ip包。 struct IpPkt* CombinIp(struct IpPktList *ip_list) 注意:参数中给出的分片顺序可能是乱序的,与前一关任务中返回的链表会存在不同。 #include"network_protocol.h" #include ...

    任务说明

    将收到ip分片重组为完整的ip包。

    struct IpPkt* CombinIp(struct IpPktList *ip_list)  
    

    注意:参数中给出的分片顺序可能是乱序的,与前一关任务中返回的链表会存在不同。

     #include"network_protocol.h"
     #include <malloc.h>
    //ip分片重组
    struct IpPkt* CombinIp(struct IpPktList *ip_list){
    	struct IpPkt *ip=NULL;
        /********* Begin 1 **********/
        //如果只有一个分片,直接复制ip
        if(ip_list->next == NULL){
            return ip_list->ip;
        }
        //找到最后分片,确定ip的长度,其标志为000,片偏移不为0
        struct IpPktList *t = (struct IpPktList*)malloc(sizeof(struct IpPktList));
        t = ip_list;
        struct IpPkt *tempip;
        short len = t->ip->ip_len;
        while(t!=NULL){
            tempip = t->ip;
            short fragoff = ntohs(tempip->ip_fragoff);
            if((fragoff & 0xe000) == 0 && (fragoff & 0x1fff) > 0){
                // printf("%d\n", fragoff);
                len = (fragoff << 3) + ntohs(tempip->ip_len) - 20;
                break;
            }
            t = t->next;
        }
        // printf("%d\n", len);
        //按片偏移进行重组,注意最后的ip长度,偏移标志字段,校验要重新计算
        ip = (struct IpPkt*)malloc(20 + len);
        *ip = *(t->ip);
        ip->ip_len = htons(len + 20);
        ip->ip_cksum = 0;
        ip->ip_fragoff = 0;
        ip->ip_cksum = htons(ipcksum(ip));
        t = ip_list;
        while(t != NULL){
            tempip = t->ip;
            short fragoff = ntohs(tempip->ip_fragoff);
            short offset = fragoff << 3;
            len = ntohs(tempip->ip_len) - 20;
            for(int i = 0; i < len; i++){
                ip->ip_data[offset + 1] = tempip->ip_data[i];
            }
            t = t->next;
        }
        /********* End 1  **********/
        return ip;
    }
     
    
    展开全文
  • IPv4之分片重组(一)

    千次阅读 2019-12-29 23:14:51
    这篇笔记先来看看IP分片重组功能涉及的一些数据结构以及核心函数,下一篇笔记则将这些过程串起来,看看整个分片重组过程是如何进行的。 数据结构 IP分片重组控制信息 在网络命名空间中,为IPv4分片重组定义了...

    这篇笔记先来看看IP分片重组功能涉及的一些数据结构以及核心函数,下一篇笔记则将这些过程串起来,看看整个分片重组过程是如何进行的。

    数据结构

    IP分片重组控制信息

    在网络命名空间中,为IPv4分片重组定义了frags变量,用于保存分片重组功能需要的一些全局控制信息。

    struct net {
    ...
    	struct netns_ipv4	ipv4;
    }
    struct netns_ipv4 {
    ...
    	struct netns_frags	frags;
    }
    struct netns_frags {
    	// 当前待重组的IP报文个数,是哈希表中IP分片队列的个数,并非IP分片的个数
    	int	nqueues;
    	// 当前保存的所有待重组分片占用的全部内存,不仅仅是分片本身的大小,还有为了管理而增加的额外开销,
    	// 该值不允许超过下面的上限值high_thresh,超过后,后续的IP片段将会由于没有内存而被丢弃
    	atomic_t mem;
    	// 所有IP片段组成一个LRU列表,便于在内存紧张时进行片段回收
    	struct list_head	lru_list;
    
    	// 配置参数/proc/sys/net/ipv4/ipfrag_time,默认30s
    	int	timeout;
    	// 配置参数/proc/sys/net/ipv4/ipfrag_high_thresh
    	int	high_thresh;
    	// 配置参数/proc/sys/net/ipv4/ipfrag_low_thresh
    	int	low_thresh;
    };
    

    IPv4分片哈希表

    在代码实现上,内核将片段重组功能进行了抽象剥离,非协议相关的部分在net/ipv4/inet_fragment.c(不知道为什么还在ipv4目录下)中实现,IPv4相关的在net/ipv4/ip_fragment.c中实现。在相关函数的命令上也很好区分,以ip_xxx开头的是IPv4相关的,以inet_xxx相关的,是非协议相关的。

    在实现重组功能时,IP层显然需要先缓存所有收到的IP片段,等同一个IP报文的所有片段都到达后把它们重组到一起再递交给L4协议。所以,IPv4协议定义了哈希表用于保存当前已收到的所有分片。

    #define INETFRAGS_HASHSZ		64
    struct inet_frags {
    	// 所有待重组的分段组织在该哈希表中
    	struct hlist_head hash[INETFRAGS_HASHSZ];
    	// 保护哈希表的读写锁
    	rwlock_t lock;
    	// 参与哈希值计算的一个随机数
    	u32	rnd;
    	// 哈希表中保存的元素的大小,用于队列元素的创建过程。对于IPv4,是sizeof(struct ipq)
    	int	qsize;
    	// 配置参数/proc/sys/net/ipv4/ipfrag_secret_interval,内核初始化为10分钟
    	int	secret_interval;
    	struct timer_list	secret_timer;
    	// 一组回调函数,在分片重组过程中被回调
    	unsigned int (*hashfn)(struct inet_frag_queue *);
    	// 当分配一个新的IP分片队列时回调,用于初始化该新建的IP分片队列
    	void (*constructor)(struct inet_frag_queue *q, void *arg);
    	void (*destructor)(struct inet_frag_queue *);
    	void (*skb_free)(struct sk_buff *);
    	// 用于判断arg指定的IP分片是否属于一个IP分片队列q(见ip_find())
    	int	(*match)(struct inet_frag_queue *q, void *arg);
    	// 分片队列超时清理回调函数
    	void (*frag_expire)(unsigned long data);
    };
    // IPv4协议用于分片重组的哈希表信息
    static struct inet_frags ip4_frags;
    

    IP分片队列: struct ipq

    IPv4在哈希表中保存的结构实际上是struct ipq,该结构保存了属于同一个IP报文的所有IP片段。

    struct inet_frag_queue {
    	// 将IP分片队列接入全局的哈希表ip4_frag.hash中
    	struct hlist_node list;
    	// 指向网络命名空间中的net->ipv4.frags
    	struct netns_frags *net;
    	// 将IP分片以LRU链表组织(inet.ipv4.frags.lru_list),方便内存紧张时的回收处理
    	struct list_head lru_list;   /* lru list member */
    	spinlock_t lock;
    	// 引用计数,每个IP片段都会持有一个该队列的引用计数
    	atomic_t refcnt;
    	// 一个IP报文,如果在指定时间内(/proc/sys/net/ipv4/ipfrag_time)内不能完成重组,则所有片段都会丢弃
    	struct timer_list timer;      /* when will this queue expire? */
    	// IP分片列表,已经按照offset顺序排好了
    	struct sk_buff *fragments; /* list of received fragments */
    	// 上一次收到IP分片的时间戳
    	ktime_t	stamp;
    	// 当前收到的该IP报文的最大偏移量,随着片段的接收,该值会不断更新,实际一个IP报文
    	// 有多少字节只能在收到最后一个片段后才能知道
    	int	len;        /* total length of orig datagram */
    	// 当前已经收到的IP分片的数据量总和
    	int	meat;
    	// 可取下面三个标记,分别表示第一个分片、最后一个分片、以及是否全部分片接收完成
    	__u8 last_in;    /* first/last segment arrived? */
    
    #define COMPLETE		4
    #define FIRST_IN		2
    #define LAST_IN			1
    };
    
    /* Describe an entry in the "incomplete datagrams" queue. */
    struct ipq {
    	// 通用的IP分片队列
    	struct inet_frag_queue q;
    	// user是用来标识分片重组是由谁发起的,因为正常理解来看,重组应该由IP层在数据传递过程中发起,
    	// 但是一些防火墙功能,必须要处理完整的IP报文,所以也存在提前进行组装的可能
    	u32	user;
    	// 来自IP报头的几个字段
    	__be32 saddr;
    	__be32 daddr;
    	__be16 id;
    	u8 protocol;
    	// 记录IP分片的输入网卡索引
    	int iif;
    	unsigned int    rid;
    	// 和IP层的IP地址管理有关,先忽略
    	struct inet_peer *peer;
    };
    

    关于user,内核定义了如下可能的值,我们这里只关注IP_DEFRAG_LOCAL_DELIVER这一种最常规的场景:

    enum ip_defrag_users
    {
    	IP_DEFRAG_LOCAL_DELIVER,
    	IP_DEFRAG_CALL_RA_CHAIN,
    	IP_DEFRAG_CONNTRACK_IN,
    	IP_DEFRAG_CONNTRACK_OUT,
    	IP_DEFRAG_VS_IN,
    	IP_DEFRAG_VS_OUT,
    	IP_DEFRAG_VS_FWD
    };
    

    上面这些数据结构之间的组织关键件下图:
    在这里插入图片描述

    初始化

    在IPv4初始化过程中,会调用ipfrag_init()对IP分片子模块进行初始化,不过这部分初始化只和IP片段的重组有关系,发送过程中的IP分段并不涉及。

    ip_frag_init()

    void __init ipfrag_init(void)
    {
    	// 初始化网络命名空间中的IPv4分片重组控制信息
    	register_pernet_subsys(&ip4_frags_ops);
    	// 初始化全局哈希表ip4_frags
    	ip4_frags.hashfn = ip4_hashfn;
    	ip4_frags.constructor = ip4_frag_init;
    	ip4_frags.destructor = ip4_frag_free;
    	ip4_frags.skb_free = NULL;
    	ip4_frags.qsize = sizeof(struct ipq);
    	ip4_frags.match = ip4_frag_match;
    	ip4_frags.frag_expire = ip_expire;
    	// 超时时间为10分钟
    	ip4_frags.secret_interval = 10 * 60 * HZ;
    	inet_frags_init(&ip4_frags);
    }
    
    void inet_frags_init(struct inet_frags *f)
    {
    	int i;
    
    	for (i = 0; i < INETFRAGS_HASHSZ; i++)
    		INIT_HLIST_HEAD(&f->hash[i]);
    	rwlock_init(&f->lock);
    	// 生成随机数,并直接启动定时器,定时间隔由secret_interval指定,定时器函数是inet_frag_secret_rebuild()
    	f->rnd = (u32) ((num_physpages ^ (num_physpages>>7)) ^ (jiffies ^ (jiffies >> 6)));
    	setup_timer(&f->secret_timer, inet_frag_secret_rebuild, (unsigned long)f);
    	f->secret_timer.expires = jiffies + f->secret_interval;
    	add_timer(&f->secret_timer);
    }
    

    网络命名空间相关初始化

    void inet_frags_init_net(struct netns_frags *nf)
    {
    	nf->nqueues = 0;
    	atomic_set(&nf->mem, 0);
    	INIT_LIST_HEAD(&nf->lru_list);
    }
    
    static int ipv4_frags_init_net(struct net *net)
    {
    	/*
    	 * Fragment cache limits. We will commit 256K at one time. Should we
    	 * cross that limit we will prune down to 192K. This should cope with
    	 * even the most extreme cases without allowing an attacker to
    	 * measurably harm machine performance.
    	 */
    	net->ipv4.frags.high_thresh = 256 * 1024;
    	net->ipv4.frags.low_thresh = 192 * 1024;
    	/*
    	 * Important NOTE! Fragment queue must be destroyed before MSL expires.
    	 * RFC791 is wrong proposing to prolongate timer each fragment arrival
    	 * by TTL.
    	 */
    	net->ipv4.frags.timeout = IP_FRAG_TIME;
    	// 初始化frags中的其它几个字段
    	inet_frags_init_net(&net->ipv4.frags);
    	// 在/proc/sys/net/ipv4/目录下创建控制参数文件
    	return ip4_frags_ctl_register(net);
    }
    
    static struct pernet_operations ip4_frags_ops = {
    	.init = ipv4_frags_init_net,
    	.exit = ipv4_frags_exit_net,
    };
    

    IPv4关键函数实现

    如上,全局的ip4_frags中有一组回调函数,这组回调函数影响了IP层分片重组功能的实现。

    ip4_frag_match()

    该函数用于判断一个IP片段是否属于一个IP分片队列,调用场景见ip_find()。

    static int ip4_frag_match(struct inet_frag_queue *q, void *a)
    {
    	struct ipq *qp;
    	struct ip4_create_arg *arg = a;
    	// 对于IPv4,实际的IP分片队列结构是ipq
    	qp = container_of(q, struct ipq, q);
    	// 很好理解
    	return (qp->id == arg->iph->id &&
    			qp->saddr == arg->iph->saddr &&
    			qp->daddr == arg->iph->daddr &&
    			qp->protocol == arg->iph->protocol &&
    			qp->user == arg->user);
    }
    

    ip4_frag_init()

    每当新建一个IP分片队列后,则回调该函数,见inet_frag_alloc()。

    static void ip4_frag_init(struct inet_frag_queue *q, void *a)
    {
    	struct ipq *qp = container_of(q, struct ipq, q);
    	struct ip4_create_arg *arg = a;
    
    	qp->protocol = arg->iph->protocol;
    	qp->id = arg->iph->id;
    	qp->saddr = arg->iph->saddr;
    	qp->daddr = arg->iph->daddr;
    	qp->user = arg->user;
    	qp->peer = sysctl_ipfrag_max_dist ? inet_getpeer(arg->iph->saddr, 1) : NULL;
    }
    
    展开全文
  • 最近研究学习IP分片重组,也拜读了不少dx的阅读理解。可还是有疑问,请教xdm。源代码:linux-2.4.26\linux-2.4.26\net\ipv4\ip_fragment.cIP分片的重组大概经过以下几个函数:0/ ip_defrag1/ ip_find-->ip_frag_...
  • 1 IP分片重组控制信息数据结构 1.1网络命名空间 struct netns_ipv4 1.2 IPv4分片哈希表struct inet_frags 1.3 IP分片队列struct ipq [ inet_frag_queue] 1.4 IPv4分片关系图 2 IPv4分片初始化ipfrag_init 2.1 ...
  • 个人公众号“代码就是生产力”,发布更多有用的...可以看到,一个数据被分成了8个数据分片,但是他们的ID是一样的,然后有不同的offset,那么我们就可以根据这两个特性,把每组的分片重组起来。 仅仅使用 dpkt 工具即可
  • 对比ZigBee技术,分析了全IP传感器网络的实现方式,在IEEE 802.15.4和IPv6...接着分析了IPv6和IEEE 802.15.4之间数据格式的差别,由此给出了对原始IPv6数据包进行分片重组的方案。最后,通过程序验证了方案的可行性。
  • 分片重组

    2019-05-23 19:57:00
    0,是一个分片,需要重组,再根据首部“标示”字段值,可判断此分片属于哪一个数据报,片偏移用来判断此分片在原始数据报中的位置。 转载于:https://www.cnblogs.com/caijinwen/p/10914143.html...
  • 我们看一下分片重组的过程。我们看一下分片重组中用到的数据结构。ipq结构体是代表一个完整的传输层包,他被ip层分成了多个分片。ipfrag结构体是代表一个ip分片。他是传输层包的一个部分。 我们开始分析组片之前,...
  • 为了保持IP数据报抽象与链路层细节的一致和分离,IP引人了分片重组 IP分片原理: 当IP层接收到一个要发送的IP数据报时,它会判断该数据报应该从哪个本地接口发送(通过查找一个转发表,见前面Internet文章)以及...
  • This document provides software architecture information, development environment information and optimization guidelines.For programming examples and for instructions on compiling and running each ...
  • IPv4之分片重组(二)

    2020-01-05 13:34:37
    继上一篇IPv4之接收过程中的分片重组(一),这篇笔记从整体上看linux是如何进行IP片段重组的。 在接收路径上的ip_local_deliver()函数中,此时已经确认数据包是给本机的,会首先调用ip_defrag()判断是否是一个完整的...
  • TCP分段重组和IP分片重组

    千次阅读 2020-09-30 11:39:10
    TCP分段重组过程 ​ TCP分段,数据传输到传输层的时候,受MSS(为MTP-IP首部长度)限制,将对数据进行分段。每一段分别添加TCP首部,数据1的长度=MSS-TCP首部长度。 ​ TCP重组时,先依次解每一层的头部,到达传输层...
  • 虚拟分片重组

    2018-10-30 16:00:35
    IP包的分片重组,第一个分片有完整的TCP/UDP协议头信息,即端口信息,而其它分片则没有,而当这些分片经过防火墙的时候,防火墙就犯难了,对于第一个分片,如果是合规的,合规就是公司安全策略允许得流量,则允许...
  • 在之前的一篇博文Linux内核网络协议栈TCP/IP分析之三:网络层分析了IP网络层协议,下面基于Linux 2.4.9内核代码着重分析IP分片重组。 二 IP分片 2.1 标志  与分片有关的是’标志’字段,标志字段占3bit。目前只有前...
  • IP分片重组算法_RFC815_的实现及其改进.docx
  • 基于二阶分片重组盲注的渗透测试方法.pdf
  • ip分片重组攻击

    2019-05-17 13:51:00
    插入攻击 插入攻击分别向IDS和目标设备发送数据表,这些数据包将被...当第二个片段进入网络后,IDS将丢弃该片段,因为第一个片段的时限参数已经触发IDS进行分组丢弃,而当第二个片段到达目标设备时,由于目标设...
  • IPv4与IPv6业务-IP虚拟分片重组技术介绍-D.docx
  • dpdk ipv4分片重组

    千次阅读 2018-08-25 21:49:18
    报文在以太网中传输时,中间会经过各种交换设备,由于物理链路的MTU值大小的限制,当要发送报文数据长度超过MTU,若DF 标记位未设置时,则会进行分片,相应对于最终 目的IP设备会进行重组。(其实,对于传输过程中的...
  • 基于fpga的ip分片重组的实现,文中详细介绍了相关内容

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 15,616
精华内容 6,246
关键字:

分片重组