// 疑问: 这一个应该要修改this_host的 ip_frag_mem变量吧???? // 输入: // ip头 // 返回: // ip队列,这个ip队列已经被挂载到host上了 static struct ipq * ip_create(struct ip * iph) { struct ipq *qp; int ihlen; // 调用malloc,申请一个空间 qp = (struct ipq *) frag_kmalloc(sizeof(struct ipq), GFP_ATOMIC); if (qp == NULL) { // NETDEBUG(printk("IP: create: no memory left !\n")); nids_params.no_mem("ip_create"); return (NULL); } // 填充为0 memset(qp, 0, sizeof(struct ipq)); /* Allocate memory for the IP header (plus 8 octets for ICMP). */ // 多分配8字节,需要保存ip头以及头后面8字节,因为icmp的内容就是ip头+8字节 ihlen = iph->ip_hl * 4; qp->iph = (struct ip *) frag_kmalloc(64 + 8, GFP_ATOMIC); if (qp->iph == NULL) { //NETDEBUG(printk("IP: create: no memory left !\n")); nids_params.no_mem("ip_create"); frag_kfree_s(qp, sizeof(struct ipq)); return (NULL); } // 将ip头+8字节的内容保存在iph变量中。 // 到时候iph变量就能够直接作为icmp的内容,如果有必要发送icmp的话 memcpy(qp->iph, iph, ihlen + 8); // 队列长度=0, 头长度,碎片队列 qp->len = 0; qp->ihlen = ihlen; qp->fragments = NULL; // 挂载到当前host上 qp->hf = this_host; /* Start a timer for this entry. */ // jiffies函数返回当前时间,毫秒为单位 qp->timer.expires = jiffies() + IP_FRAG_TIME; /* about 30 seconds */ // 设置关联 qp->timer.data = (unsigned long) qp; /* pointer to queue */ // 注册一个超时函数,当超时的时候,会回调这个函数 qp->timer.function = ip_expire; /* expire function */ // 将这个timer挂载到queue上 add_timer(&qp->timer); /* Add this entry to the queue. */ // 将这个队列挂载到当前host上 qp->prev = NULL; qp->next = this_host->ipqueue; if (qp->next != NULL) qp->next->prev = qp; this_host->ipqueue = qp; return (qp); }
/* Add an entry to the 'ipq' queue for a newly received IP datagram. We will (hopefully :-) receive all other fragments of this datagram in time, so we just create a queue for this datagram, in which we will insert the received fragments at their respective positions. */ static struct ipq * //! ip_create(struct ip * iph) ip_create(struct ip * iph,IP_THREAD_LOCAL_P ip_thread_local_p) { struct ipq *qp; int ihlen; //! qp = (struct ipq *) frag_kmalloc(sizeof(struct ipq), GFP_ATOMIC); qp = (struct ipq *) frag_kmalloc(sizeof(struct ipq), GFP_ATOMIC,ip_thread_local_p); if (qp == NULL) { // NETDEBUG(printk("IP: create: no memory left !\n")); nids_params.no_mem("ip_create"); return (NULL); } memset(qp, 0, sizeof(struct ipq)); /* Allocate memory for the IP header (plus 8 octets for ICMP). */ ihlen = iph->ip_hl * 4; qp->iph = (struct ip *) frag_kmalloc(64 + 8, GFP_ATOMIC, ip_thread_local_p); if (qp->iph == NULL) { //NETDEBUG(printk("IP: create: no memory left !\n")); nids_params.no_mem("ip_create"); //! frag_kfree_s(qp, sizeof(struct ipq)); frag_kfree_s(qp, sizeof(struct ipq),ip_thread_local_p); return (NULL); } memcpy(qp->iph, iph, ihlen + 8); qp->len = 0; qp->ihlen = ihlen; qp->fragments = NULL; //! qp->hf = this_host; qp->hf = ip_thread_local_p->this_host; /* Start a timer for this entry. */ //! qp->timer.expires = jiffies() + IP_FRAG_TIME; /* about 30 seconds */ qp->timer.expires = jiffies(ip_thread_local_p) + IP_FRAG_TIME; /* about 30 seconds */ qp->timer.data = (unsigned long) qp; /* pointer to queue */ qp->timer.function = ip_expire; /* expire function */ //! add_timer(&qp->timer); add_timer(&qp->timer,ip_thread_local_p); /* Add this entry to the queue. */ qp->prev = NULL; //! qp->next = this_host->ipqueue; qp->next = ip_thread_local_p->this_host->ipqueue; if (qp->next != NULL) qp->next->prev = qp; //! this_host->ipqueue = qp; ip_thread_local_p->this_host->ipqueue = qp; return (qp); }
static struct ipq *ip_create(struct sk_buff *skb, struct iphdr *iph, struct device *dev) { struct ipq *qp; int ihlen; qp = (struct ipq *) frag_kmalloc(sizeof(struct ipq), GFP_ATOMIC); if (qp == NULL) { NETDEBUG(printk("IP: create: no memory left !\n")); return(NULL); } memset(qp, 0, sizeof(struct ipq)); /* * Allocate memory for the IP header (plus 8 octets for ICMP). */ ihlen = iph->ihl * 4; qp->iph = (struct iphdr *) frag_kmalloc(64 + 8, GFP_ATOMIC); if (qp->iph == NULL) { NETDEBUG(printk("IP: create: no memory left !\n")); frag_kfree_s(qp, sizeof(struct ipq)); return(NULL); } memcpy(qp->iph, iph, ihlen + 8); qp->len = 0; qp->ihlen = ihlen; qp->fragments = NULL; qp->dev = dev; /* Start a timer for this entry. */ qp->timer.expires = jiffies + IP_FRAG_TIME; /* about 30 seconds */ qp->timer.data = (unsigned long) qp; /* pointer to queue */ qp->timer.function = ip_expire; /* expire function */ add_timer(&qp->timer); /* Add this entry to the queue. */ qp->prev = NULL; cli(); qp->next = ipqueue; if (qp->next != NULL) qp->next->prev = qp; ipqueue = qp; sti(); return(qp); }
/* 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 *) frag_kmalloc(sizeof(struct ipfrag), GFP_ATOMIC); if (fp == NULL) { // NETDEBUG(printk("IP: frag_create: no memory left !\n")); nids_params.no_mem("ip_frag_create"); 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; /* Charge for the SKB as well. */ this_host->ip_frag_mem += skb->truesize; return (fp); }
/* 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 *) frag_kmalloc(sizeof(struct ipfrag), GFP_ATOMIC); if (fp == NULL) goto out_nomem; /* Fill in the structure. */ fp->offset = offset; fp->end = end; fp->len = end - offset; fp->skb = skb; fp->ptr = ptr; fp->next = fp->prev = NULL; /* Charge for the SKB as well. */ atomic_add(skb->truesize, &ip_frag_mem); return(fp); out_nomem: NETDEBUG(printk(KERN_ERR "IP: frag_create: no memory left !\n")); return(NULL); }
static struct ipfrag *ip_frag_create(int offset, int end, struct sk_buff *skb, unsigned char *ptr) { struct ipfrag *fp; unsigned long flags; fp = (struct ipfrag *) frag_kmalloc(sizeof(struct ipfrag), GFP_ATOMIC); if (fp == NULL) { NETDEBUG(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; /* * Charge for the SKB as well. */ save_flags(flags); cli(); ip_frag_mem+=skb->truesize; restore_flags(flags); return(fp); }
/* Add an entry to the 'ipq' queue for a newly received IP datagram. * We will (hopefully :-) receive all other fragments of this datagram * in time, so we just create a queue for this datagram, in which we * will insert the received fragments at their respective positions. */ static struct ipq *ip_create(struct sk_buff *skb, struct iphdr *iph) { struct ipq *qp; unsigned int hash; int ihlen; qp = (struct ipq *) frag_kmalloc(sizeof(struct ipq), GFP_ATOMIC); if (qp == NULL) goto out_nomem; /* Allocate memory for the IP header (plus 8 octets for ICMP). */ ihlen = iph->ihl * 4; qp->iph = (struct iphdr *) frag_kmalloc(64 + 8, GFP_ATOMIC); if (qp->iph == NULL) goto out_free; memcpy(qp->iph, iph, ihlen + 8); qp->len = 0; qp->ihlen = ihlen; qp->fragments = NULL; qp->dev = skb->dev; /* Initialize a timer for this entry. */ init_timer(&qp->timer); qp->timer.expires = 0; /* (to be set later) */ qp->timer.data = (unsigned long) qp; /* pointer to queue */ qp->timer.function = ip_expire; /* expire function */ /* Add this entry to the queue. */ hash = ipqhashfn(iph->id, iph->saddr, iph->daddr, iph->protocol); /* We are in a BH context, no locking necessary. -DaveM */ if((qp->next = ipq_hash[hash]) != NULL) qp->next->pprev = &qp->next; ipq_hash[hash] = qp; qp->pprev = &ipq_hash[hash]; return qp; out_free: frag_kfree_s(qp, sizeof(struct ipq)); out_nomem: NETDEBUG(printk(KERN_ERR "IP: create: no memory left !\n")); return(NULL); }
static void create_frag_entry(struct sk_buff *skb, __u8 *nhptr, struct frag_hdr *fhdr) { struct frag_queue *fq; struct ipv6hdr *hdr; fq = (struct frag_queue *) frag_kmalloc(sizeof(struct frag_queue), GFP_ATOMIC); if (fq == NULL) { ipv6_statistics.Ip6ReasmFails++; kfree_skb(skb); return; } memset(fq, 0, sizeof(struct frag_queue)); fq->id = fhdr->identification; hdr = skb->nh.ipv6h; ipv6_addr_copy(&fq->saddr, &hdr->saddr); ipv6_addr_copy(&fq->daddr, &hdr->daddr); /* init_timer has been done by the memset */ fq->timer.function = frag_expire; fq->timer.data = (long) fq; fq->timer.expires = jiffies + sysctl_ip6frag_time; reasm_queue(fq, skb, fhdr, nhptr); if (fq->fragments) { fq->prev = ipv6_frag_queue.prev; fq->next = &ipv6_frag_queue; fq->prev->next = fq; ipv6_frag_queue.prev = fq; add_timer(&fq->timer); } else frag_kfree_s(fq, sizeof(*fq)); }
static void reasm_queue(struct frag_queue *fq, struct sk_buff *skb, struct frag_hdr *fhdr, u8 *nhptr) { struct ipv6_frag *nfp, *fp, **bptr; nfp = (struct ipv6_frag *) frag_kmalloc(sizeof(struct ipv6_frag), GFP_ATOMIC); if (nfp == NULL) { kfree_skb(skb); return; } nfp->offset = ntohs(fhdr->frag_off) & ~0x7; nfp->len = (ntohs(skb->nh.ipv6h->payload_len) - ((u8 *) (fhdr + 1) - (u8 *) (skb->nh.ipv6h + 1))); if ((u32)nfp->offset + (u32)nfp->len >= 65536) { icmpv6_param_prob(skb,ICMPV6_HDR_FIELD, (u8*)&fhdr->frag_off); goto err; } if (fhdr->frag_off & __constant_htons(0x0001)) { /* Check if the fragment is rounded to 8 bytes. * Required by the RFC. * ... and would break our defragmentation algorithm 8) */ if (nfp->len & 0x7) { printk(KERN_DEBUG "fragment not rounded to 8bytes\n"); /* It is not in specs, but I see no reasons to send an error in this case. --ANK */ if (nfp->offset == 0) icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, &skb->nh.ipv6h->payload_len); goto err; } } nfp->skb = skb; nfp->fhdr = fhdr; nfp->next = NULL; bptr = &fq->fragments; for (fp = fq->fragments; fp; fp=fp->next) { if (nfp->offset <= fp->offset) break; bptr = &fp->next; } if (fp && fp->offset == nfp->offset) { if (nfp->len != fp->len) { printk(KERN_DEBUG "reasm_queue: dup with wrong len\n"); } /* duplicate. discard it. */ goto err; } atomic_add(skb->truesize, &ip6_frag_mem); /* All the checks are done, fragment is acepted. Only now we are allowed to update reassembly data! (fixed --ANK (980728)) */ /* iif always set to one of the last arrived segment */ fq->dev = skb->dev; fq->iif = skb->dev->ifindex; /* Last fragment */ if ((fhdr->frag_off & __constant_htons(0x0001)) == 0) fq->last_in |= LAST_IN; /* First fragment. nexthdr and nhptr are get from the first fragment. Moreover, nexthdr is UNDEFINED for all the fragments but the first one. (fixed --ANK (980728)) */ if (nfp->offset == 0) { fq->nexthdr = fhdr->nexthdr; fq->last_in |= FIRST_IN; fq->nhoffset = nhptr - skb->nh.raw; } *bptr = nfp; nfp->next = fp; return; err: frag_kfree_s(nfp, sizeof(*nfp)); kfree_skb(skb); }