⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ip_fragment.c

📁 libnids w32 libnids w32 libnids w32 libnids w32 libnids w32
💻 C
📖 第 1 页 / 共 2 页
字号:
static voidip_evictor(void){  // fprintf(stderr, "ip_evict:numpack=%i\n", numpack);  while (this_host->ip_frag_mem > IPFRAG_LOW_THRESH) {    if (!this_host->ipqueue)      panic("ip_evictor: memcount");    ip_free(this_host->ipqueue);  }}/*  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){  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"));    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);  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);  }  memcpy(qp->iph, iph, ihlen + 8);  qp->len = 0;  qp->ihlen = ihlen;  qp->fragments = NULL;  qp->hf = this_host;  /* 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;  qp->next = this_host->ipqueue;  if (qp->next != NULL)    qp->next->prev = qp;  this_host->ipqueue = qp;    return (qp);}/* See if a fragment queue is complete. */static intip_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);}/*  Build a new IP datagram from all its fragments.   FIXME: We copy here because we lack an effective way of handling  lists of bits on input. Until the new skb data handling is in I'm  not going to touch this with a bargepole.*/static char *ip_glue(struct ipq * qp){  char *skb;  struct ip *iph;  struct ipfrag *fp;  unsigned char *ptr;  int count, len;  /* Allocate a new buffer for the datagram. */  len = qp->ihlen + qp->len;    if (len > 65535) {    // NETDEBUG(printk("Oversized IP packet from %s.\n", int_ntoa(qp->iph->ip_src.s_addr)));    nids_params.syslog(NIDS_WARN_IP, NIDS_WARN_IP_OVERSIZED, qp->iph, 0);    ip_free(qp);    return NULL;  }  if ((skb = (char *) malloc(len)) == NULL) {    // NETDEBUG(printk("IP: queue_glue: no memory for gluing queue %p\n", qp));    nids_params.no_mem("ip_glue");    ip_free(qp);    return (NULL);  }  /* Fill in the basic details. */  ptr = skb;  memcpy(ptr, ((unsigned char *) qp->iph), qp->ihlen);  ptr += qp->ihlen;  count = 0;  /* Copy the data portions of all fragments into the new buffer. */  fp = qp->fragments;  while (fp != NULL) {    if (fp->len < 0 || fp->offset + qp->ihlen + fp->len > len) {      //NETDEBUG(printk("Invalid fragment list: Fragment over size.\n"));      nids_params.syslog(NIDS_WARN_IP, NIDS_WARN_IP_INVLIST, qp->iph, 0);      ip_free(qp);      //kfree_skb(skb, FREE_WRITE);      //ip_statistics.IpReasmFails++;      free(skb);      return NULL;    }    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 = (struct ip *) skb;  iph->ip_off = 0;  iph->ip_len = htons((iph->ip_hl * 4) + count);  // skb->ip_hdr = iph;  return (skb);}/* Process an incoming IP datagram fragment. */static char *ip_defrag(struct ip *iph, struct sk_buff *skb){  struct ipfrag *prev, *next, *tmp;  struct ipfrag *tfp;  struct ipq *qp;  char *skb2;  unsigned char *ptr;  int flags, offset;  int i, ihl, end;  if (!hostfrag_find(iph) && skb)    hostfrag_create(iph);  /* Start by cleaning up the memory. */  if (this_host)    if (this_host->ip_frag_mem > IPFRAG_HIGH_THRESH)      ip_evictor();    /* Find the entry of this IP datagram in the "incomplete datagrams" queue. */  if (this_host)    qp = ip_find(iph);  else    qp = 0;  /* Is this a non-fragmented datagram? */  offset = ntohs(iph->ip_off);  flags = offset & ~IP_OFFSET;  offset &= IP_OFFSET;  if (((flags & IP_MF) == 0) && (offset == 0)) {    if (qp != NULL)      ip_free(qp);		/* Fragmented frame replaced by full				   unfragmented copy */    return 0;  }  offset <<= 3;			/* offset is in 8-byte chunks */  ihl = iph->ip_hl * 4;  /*    If the queue already existed, keep restarting its timer as long as    we still are receiving fragments.  Otherwise, create a fresh queue    entry.  */  if (qp != NULL) {    /* ANK. If the first fragment is received, we should remember the correct       IP header (with options) */    if (offset == 0) {      qp->ihlen = ihl;      memcpy(qp->iph, iph, ihl + 8);    }    del_timer(&qp->timer);    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);  }  else {    /* If we failed to create it, then discard the frame. */    if ((qp = ip_create(iph)) == NULL) {      kfree_skb(skb, FREE_READ);      return NULL;    }  }  /* Attempt to construct an oversize packet. */  if (ntohs(iph->ip_len) + (int) offset > 65535) {    // NETDEBUG(printk("Oversized packet received from %s\n", int_ntoa(iph->ip_src.s_addr)));    nids_params.syslog(NIDS_WARN_IP, NIDS_WARN_IP_OVERSIZED, iph, 0);    kfree_skb(skb, FREE_READ);    return NULL;  }  /* Determine the position of this fragment. */  end = offset + ntohs(iph->ip_len) - ihl;  /* Point into the IP datagram 'data' part. */  ptr = skb->data + ihl;  /* Is this the final fragment? */  if ((flags & IP_MF) == 0)    qp->len = end;  /*    Find out which fragments are in front and at the back of us in the    chain of fragments so far.  We must know where to put this    fragment, right?  */  prev = NULL;  for (next = qp->fragments; next != NULL; next = next->next) {    if (next->offset >= offset)      break;			/* bingo! */    prev = next;  }  /*    We found where to put this one.  Check for overlap with preceding    fragment, and, if needed, align things so that any overlaps are    eliminated.  */  if (prev != NULL && offset < prev->end) {    nids_params.syslog(NIDS_WARN_IP, NIDS_WARN_IP_OVERLAP, iph, 0);    i = prev->end - offset;    offset += i;		/* ptr into datagram */    ptr += i;			/* ptr into fragment data */  }  /*    Look for overlap with succeeding segments.    If we can merge fragments, do it.  */  for (tmp = next; tmp != NULL; tmp = tfp) {    tfp = tmp->next;    if (tmp->offset >= end)      break;			/* no overlaps at all */    nids_params.syslog(NIDS_WARN_IP, NIDS_WARN_IP_OVERLAP, iph, 0);        i = end - next->offset;	/* overlap is 'i' bytes */    tmp->len -= i;		/* so reduce size of    */    tmp->offset += i;		/* next fragment        */    tmp->ptr += i;    /*      If we get a frag size of <= 0, remove it and the packet that it      goes with. We never throw the new frag away, so the frag being      dumped has always been charged for.    */    if (tmp->len <= 0) {      if (tmp->prev != NULL)	tmp->prev->next = tmp->next;      else	qp->fragments = tmp->next;            if (tmp->next != NULL)	tmp->next->prev = tmp->prev;            next = tfp;		/* We have killed the original next frame */      frag_kfree_skb(tmp->skb, FREE_READ);      frag_kfree_s(tmp, sizeof(struct ipfrag));    }  }  /* Insert this fragment in the chain of fragments. */  tfp = NULL;  tfp = ip_frag_create(offset, end, skb, ptr);    /*    No memory to save the fragment - so throw the lot. If we failed    the frag_create we haven't charged the queue.  */  if (!tfp) {    nids_params.no_mem("ip_defrag");    kfree_skb(skb, FREE_READ);    return NULL;  }  /* From now on our buffer is charged to the queues. */  tfp->prev = prev;  tfp->next = next;  if (prev != NULL)    prev->next = tfp;  else    qp->fragments = tfp;  if (next != NULL)    next->prev = tfp;  /*    OK, so we inserted this new fragment into the chain.  Check if we    now have a full IP datagram which we can bump up to the IP    layer...  */  if (ip_done(qp)) {    skb2 = ip_glue(qp);		/* glue together the fragments */    return (skb2);  }  return (NULL);}intip_defrag_stub(struct ip *iph, struct ip **defrag){  int offset, flags, tot_len;  struct sk_buff *skb;  numpack++;  timenow = 0;  while (timer_head && timer_head->expires < jiffies()) {    this_host = ((struct ipq *) (timer_head->data))->hf;    timer_head->function(timer_head->data);  }  offset = ntohs(iph->ip_off);  flags = offset & ~IP_OFFSET;  offset &= IP_OFFSET;  if (((flags & IP_MF) == 0) && (offset == 0)) {    ip_defrag(iph, 0);    return IPF_NOTF;  }  tot_len = ntohs(iph->ip_len);  skb = (struct sk_buff *) malloc(tot_len + sizeof(struct sk_buff));  skb->data = (char *) (skb + 1);  memcpy(skb->data, iph, tot_len);  skb->truesize = tot_len + 16 + nids_params.dev_addon;  skb->truesize = (skb->truesize + 15) & ~15;  skb->truesize += nids_params.sk_buff_size;  if ((*defrag = (struct ip *)ip_defrag((struct ip *) (skb->data), skb)))    return IPF_NEW;  return IPF_ISF;}intip_frag_init(int n){  struct timeval tv;    gettimeofday(&tv, 0);  time0 = tv.tv_sec;  fragtable = (struct hostfrags **) malloc(n * sizeof(struct hostfrags *));  if (!fragtable)    nids_params.no_mem("ip_frag_init");  memset(fragtable, 0, n * sizeof(struct hostfrags *));  hash_size = n;  return 0;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -