Linux内核源代码解析——IP切碎了又粘好
本文原创为freas_1990,转载请标明出处:http://blog.csdn.net/freas_1990/article/details/23795587
IP分片定义如下:
/* Describe an IP fragment. */ struct ipfrag { int offset; /* offset of fragment in IP datagram */ int end; /* last byte of data in datagram */ int len; /* length of this fragment */ struct sk_buff *skb; /* complete received fragment */ unsigned char *ptr; /* pointer into real fragment data */ struct ipfrag *next; /* linked list pointers */ struct ipfrag *prev; };
IP datagram定义如下:
/* Describe an entry in the "incomplete datagrams" queue. */ struct ipq { unsigned char *mac; /* pointer to MAC header */ struct iphdr *iph; /* pointer to IP header */ int len; /* total length of original datagram */ short ihlen; /* length of the IP header */ short maclen; /* length of the MAC header */ struct timer_list timer; /* when will this queue expire? */ struct ipfrag *fragments; /* linked list of received fragments */ struct ipq *next; /* linked list pointers */ struct ipq *prev; struct device *dev; /* Device - for icmp replies */ };
IP分片构建如下:
/* Create a new fragment entry. */ static struct ipfrag *ip_frag_create(int offset, int end, struct sk_buff *skb, unsigned char *ptr) { struct ipfrag *fp; fp = (struct ipfrag *) kmalloc(sizeof(struct ipfrag), GFP_ATOMIC); if (fp == NULL) { printk("IP: frag_create: no memory left !\n"); return(NULL); } memset(fp, 0, sizeof(struct ipfrag)); /* Fill in the structure. */ fp->offset = offset; fp->end = end; fp->len = end - offset; fp->skb = skb; fp->ptr = ptr; return(fp); }
IP分片完整性检查如下:
/* See if a fragment queue is complete. */ static int ip_done(struct ipq *qp) { struct ipfrag *fp; int offset; /* Only possible if we received the final fragment. */ if (qp->len == 0) return(0); /* Check all fragment offsets to see if they connect. */ fp = qp->fragments; offset = 0; while (fp != NULL) { if (fp->offset > offset) return(0); /* fragment(s) missing */ offset = fp->end; fp = fp->next; } /* All fragments are present. */ return(1); }
从所有的fragments构建出一个IP datagram的代码如下:
/* Build a new IP datagram from all its fragments. */ static struct sk_buff *ip_glue(struct ipq *qp) { struct sk_buff *skb; struct iphdr *iph; struct ipfrag *fp; unsigned char *ptr; int count, len; /* Allocate a new buffer for the datagram. */ len = sizeof(struct sk_buff)+qp->maclen + qp->ihlen + qp->len; if ((skb = alloc_skb(len,GFP_ATOMIC)) == NULL) { printk("IP: queue_glue: no memory for glueing queue 0x%X\n", (int) qp); ip_free(qp); return(NULL); } /* Fill in the basic details. */ skb->len = (len - qp->maclen); skb->h.raw = skb->data; skb->free = 1; /* Copy the original MAC and IP headers into the new buffer. */ ptr = (unsigned char *) skb->h.raw; memcpy(ptr, ((unsigned char *) qp->mac), qp->maclen); /* printk("Copied %d bytes of mac header.\n",qp->maclen);*/ ptr += qp->maclen; memcpy(ptr, ((unsigned char *) qp->iph), qp->ihlen); /* printk("Copied %d byte of ip header.\n",qp->ihlen);*/ ptr += qp->ihlen; skb->h.raw += qp->maclen; /* printk("Protocol = %d\n",skb->h.iph->protocol);*/ count = 0; /* Copy the data portions of all fragments into the new buffer. */ fp = qp->fragments; while(fp != NULL) { if(count+fp->len>skb->len) { printk("Invalid fragment list: Fragment over size.\n"); ip_free(qp); kfree_skb(skb,FREE_WRITE); return NULL; } /* printk("Fragment %d size %d\n",fp->offset,fp->len);*/ memcpy((ptr + fp->offset), fp->ptr, fp->len); count += fp->len; fp = fp->next; } /* We glued together all fragments, so remove the queue entry. */ ip_free(qp); /* Done with all fragments. Fixup the new IP header. */ iph = skb->h.iph; iph->frag_off = 0; iph->tot_len = htons((iph->ihl * sizeof(unsigned long)) + count); skb->ip_hdr = iph; return(skb); }
24岁生日之后写的第一篇技术文章。
年龄越大,人越懒,除了源代码什么都不想说了。
原谅我一生不羁放纵爱自由。。。
郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。