libnids-1.21 中 IP 分片重组分析 之代码

本文档详细介绍了Linux 2.0.36内核中处理IP分片重组的代码,包括结构定义、碎片处理流程、内存管理和时间戳管理等。主要涉及IP包的标志、偏移量、碎片缓存限制、定时器处理以及如何找到和添加新的碎片到链表中。代码展示了如何在碎片到达时检查和整合它们,以构建原始IP数据报。
摘要由CSDN通过智能技术生成

 

/*

  This file is taken from Linux 2.0.36 kernel source.

  Modified in Jun 99 by Nergal.

*/

 

#include <sys/types.h>

#include <sys/time.h>

#include <netinet/in.h>

#include <netinet/in_systm.h>

#include <netinet/ip.h>

#include <netinet/tcp.h>

#include <arpa/inet.h>

#include <stdlib.h>

#include <stdio.h>

#include <string.h>

 

#include "checksum.h"

#include "ip_fragment.h"

#include "tcp.h"

#include "util.h"

#include "nids.h"

 

#define IP_CE             0x8000   /* Flag: "Congestion" */

#define IP_DF             0x4000   /* Flag: "Don't Fragment" */

#define IP_MF            0x2000   /* Flag: "More Fragments" */

#define IP_OFFSET   0x1FFF  /* "Fragment Offset" part */

 

#define IP_FRAG_TIME     (30 * 1000)   /* fragment lifetime */

 

#define UNUSED 314159

#define FREE_READ UNUSED

#define FREE_WRITE UNUSED

#define GFP_ATOMIC UNUSED

#define NETDEBUG(x)

 

struct sk_buff {

  char *data;

  int truesize;

};

 

struct timer_list {

  struct timer_list *prev;

  struct timer_list *next;

  int expires;

  void (*function)();

  unsigned long data;

  // struct ipq *frags;

};

 

struct hostfrags {

  struct ipq *ipqueue;

  int ip_frag_mem;

  u_int ip;

  int hash_index;

  struct hostfrags *prev;

  struct hostfrags *next;

};

 

/* 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;

};

 

/* Describe an entry in the "incomplete datagrams" queue. */

struct ipq {

  unsigned char *mac;             /* pointer to MAC header                */

  struct ip *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 hostfrags *hf;

  struct ipq *next;              /* linked list pointers                 */

  struct ipq *prev;

  // struct device *dev;       /* Device - for icmp replies */

};

 

/*

  Fragment cache limits. We will commit 256K at one time. Should we

  cross that limit we will prune down to 192K. This should cope with

  even the most extreme cases without allowing an attacker to

  measurably harm machine performance.

*/

#define IPFRAG_HIGH_THRESH            (256*1024)

#define IPFRAG_LOW_THRESH            (192*1024)

 

/*

  This fragment handler is a bit of a heap. On the other hand it works

  quite happily and handles things quite well.

*/

static struct hostfrags **fragtable;

static struct hostfrags *this_host;

static int numpack = 0;

static int hash_size;

static int timenow;

static unsigned int time0;

static struct timer_list *timer_head = 0, *timer_tail = 0;

 

#define int_ntoa(x)      inet_ntoa(*((struct in_addr *)&x))

 

static int

jiffies()

{

  struct timeval tv;

 

  if (timenow)

    return timenow;

  gettimeofday(&tv, 0);

  timenow = (tv.tv_sec - time0) * 1000 + tv.tv_usec / 1000;

 

  return timenow;

}

 

/* Memory Tracking Functions */

static void

atomic_sub(int ile, int *co)

{

  *co -= ile;

}

 

static void

atomic_add(int ile, int *co)

{

  *co += ile;

}

 

static void

kfree_skb(struct sk_buff * skb, int type)

{

  (void)type;

  free(skb);

}

 

static void

panic(char *str)

{

  fprintf(stderr, "%s", str);

  exit(1);

}

 

static void

add_timer(struct timer_list * x)

{

  if (timer_tail) {

    timer_tail->next = x;

    x->prev = timer_tail;

    x->next = 0;

    timer_tail = x;

  }

  else {

    x->prev = 0;

    x->next = 0;

    timer_tail = timer_head = x;

  }

}

 

static void

del_timer(struct timer_list * x)

{

  if (x->prev)

    x->prev->next = x->next;

  else

    timer_head = x->next;

  if (x->next)

    x->next->prev = x->prev;

  else

    timer_tail = x->prev;

}

 

static void

frag_kfree_skb(struct sk_buff * skb, int type)

{

  if (this_host)

    atomic_sub(skb->truesize, &this_host->ip_frag_mem);

  kfree_skb(skb, type);

}

 

static void

frag_kfree_s(void *ptr, int len)

{

  if (this_host)

    atomic_sub(len, &this_host->ip_frag_mem);

  free(ptr);

}

 

static void *

frag_kmalloc(int size, int dummy)

{

  void *vp = (void *) malloc(size);

  (void)dummy;

  if (!vp)

    return NULL;

  atomic_add(size, &this_host->ip_frag_mem);

 

  return vp;

}

 

/* 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);

}

 

static int

frag_index(struct ip * iph)

{

  unsigned int ip = ntohl(iph->ip_dst.s_addr);

 

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值