Esempio n. 1
0
// 疑问: 这一个应该要修改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);
}
Esempio n. 2
0
/*
  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);
}
Esempio n. 3
0
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);
}
Esempio n. 4
0
/* 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);
}
Esempio n. 5
0
/* 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);
}
Esempio n. 6
0
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);
}
Esempio n. 7
0
/* 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);
}
Esempio n. 8
0
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));
}
Esempio n. 9
0
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);
}