Linux内核源代码解析——IP切碎了又粘好

来源:互联网 发布:godaddy转阿里云 编辑:程序博客网 时间:2024/05/16 00:25

IP分片定义如下:

/* Describe an IP fragment. */struct ipfrag {  intoffset;/* offset of fragment in IP datagram*/  intend;/* last byte of data in datagram*/  intlen;/* 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*/  intlen;/* total length of original datagram*/  shortihlen;/* 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岁生日之后写的第一篇技术文章。

年龄越大,人越懒,除了源代码什么都不想说了。

原谅我一生不羁放纵爱自由。。。

0 0