Exemplo n.º 1
0
void cxtbuffer_free(connection *c)
{
   if ( c == NULL )
      return;

   if ( c->s_ip )
      ip_free(c->s_ip);

   if ( c->d_ip )
      ip_free(c->d_ip);

   free(c);
   c = NULL;
   //cxt_free++;
}
Exemplo n.º 2
0
/* Memory limiting on fragments.  Evictor trashes the oldest 
 * fragment queue until we are back under the low threshold.
 */
static void ip_evictor(void)
{
	int i, progress;

restart:
	progress = 0;
	/* FIXME: Make LRU queue of frag heads. -DaveM */
	for (i = 0; i < IPQ_HASHSZ; i++) {
		struct ipq *qp;
		if (atomic_read(&ip_frag_mem) <= sysctl_ipfrag_low_thresh)
			return;
		/* We are in a BH context, so these queue
		 * accesses are safe.  -DaveM
		 */
		qp = ipq_hash[i];
		if (qp) {
			/* find the oldest queue for this hash bucket */
			while (qp->next)
				qp = qp->next;
			ip_free(qp);
			progress = 1;
		}
	}
	if (progress)
		goto restart;
	panic("ip_evictor: memcount");
}
Exemplo n.º 3
0
static void ip_evictor(void)
{
	while(ip_frag_mem>IPFRAG_LOW_THRESH)
	{
		if(!ipqueue)
			panic("ip_evictor: memcount");
		ip_free(ipqueue);
	}
}
Exemplo n.º 4
0
/* Oops- a fragment queue timed out.  Kill it and send an ICMP reply. */
static void
ip_expire(unsigned long arg)
{
  struct ipq *qp;

  qp = (struct ipq *) arg;

  /* Nuke the fragment queue. */
  ip_free(qp);
}
Exemplo n.º 5
0
/*
  Memory limiting on fragments. Evictor trashes the oldest fragment
  queue until we are back under the low threshold.
*/
static void
ip_evictor(void)
{
  // fprintf(stderr, "ip_evict:numpack=%i\n", numpack);
  while (this_host && this_host->ip_frag_mem > IPFRAG_LOW_THRESH) {
    if (!this_host->ipqueue)
      panic("ip_evictor: memcount");
    ip_free(this_host->ipqueue);
  }
}
Exemplo n.º 6
0
/* Oops- a fragment queue timed out.  Kill it and send an ICMP reply. */
static void
ip_expire(unsigned long arg, IP_THREAD_LOCAL_P ip_thread_local_p)
{
	struct ipq *qp;

	qp = (struct ipq *) arg;

	/* Nuke the fragment queue. */
//!   ip_free(qp);
	ip_free(qp,ip_thread_local_p);
}
Exemplo n.º 7
0
Arquivo: ipobj.c Projeto: sdnnfv/snort
void test_ip4_parsing(void)
{
    unsigned host, mask, not_flag;
    PORTSET  portset;
    char **curip;
    int ret;
    IPADDRESS *adp;
    char *ips[] = {
        "138.26.1.24:25",
        "1.1.1.1/255.255.255.0:444",
        "1.1.1.1/16:25-28",
        "1.1.1.1/255.255.255.255:25 27-29",
        "z/24",
        "0/0",
        "0.0.0.0/0.0.0.0:25-26 28-29 31",
        "0.0.0.0/0.0.2.0",
        NULL
    };

    for(curip = ips; curip[0] != NULL; curip++)
    {

        portset_init(&portset);

        /* network byte order stuff */
        if((ret = ip4_parse(curip[0], 1, &not_flag, &host, &mask, &portset)) != 0)
        {
            fprintf(stderr, "Unable to parse %s with ret %d\n", curip[0], ret);
        }
        else
        {
            printf("%c", not_flag ? '!' : ' ');
            printf("%s/", inet_ntoa(*(struct in_addr *) &host));
            printf("%s", inet_ntoa(*(struct in_addr *) &mask));
            printf(" parsed successfully!\n");
        }

        /* host byte order stuff */
        if((ret = ip4_parse(curip[0], 0, &not_flag, &host, &mask, &portset)) != 0)
        {
            fprintf(stderr, "Unable to parse %s with ret %d\n", curip[0], ret);
        }
        else
        {
            adp = ip_new(IPV4_FAMILY);
            ip_set(adp, &host, IPV4_FAMILY);
            ip_fprint(stdout, adp);
            fprintf(stdout, "*****************\n");
            ip_free(adp);
        }
    }

    return;
}
Exemplo n.º 8
0
void del_node(struct ip_node *node)
{
	struct ip_node *foo, *bar;

	foo = node->children;
	while (foo){
		bar = foo;
		foo = foo->next;
		del_node(bar);
	}

	ip_free(node);
}
Exemplo n.º 9
0
/*
  Memory limiting on fragments. Evictor trashes the oldest fragment
  queue until we are back under the low threshold.
*/
static void
//! ip_evictor(void)
ip_evictor(IP_THREAD_LOCAL_P  ip_thread_local_p)
{
//!   // fprintf(stderr, "ip_evict:numpack=%i\n", numpack);
	// fprintf(stderr, "ip_evict:ip_thread_local_p->numpack=%i\n", ip_thread_local_p->numpack);
//!   while (this_host->ip_frag_mem > IPFRAG_LOW_THRESH) {
	while (ip_thread_local_p->this_host->ip_frag_mem > IPFRAG_LOW_THRESH) {
//!     if (!this_host->ipqueue)
		if (!ip_thread_local_p->this_host->ipqueue)
			panic("ip_evictor: memcount");
//!     ip_free(this_host->ipqueue);
		ip_free(ip_thread_local_p->this_host->ipqueue,ip_thread_local_p);
	}
}
Exemplo n.º 10
0
static void
ip_evictor(void)
{
	// fprintf(stderr, "ip_evict:numpack=%i\n", numpack);

	// 如果当前host存在,并且当前host的内存大于了下限
	while (this_host && this_host->ip_frag_mem > IPFRAG_LOW_THRESH)
	{
		// 如果对应的ip队列不为空
		if (!this_host->ipqueue)
			// 报错(好像会exit)
			panic("ip_evictor: memcount");
		// 释放当前的ipqueue, 一直到当前host的内存小于下限
		ip_free(this_host->ipqueue);
	}
}
Exemplo n.º 11
0
/*
 * Oops, a fragment queue timed out.  Kill it and send an ICMP reply.
 */
static void ip_expire(unsigned long arg)
{
	struct ipq *qp = (struct ipq *) arg;

  	if(!qp->fragments)
        {	
#ifdef IP_EXPIRE_DEBUG
	  	printk("warning: possible ip-expire attack\n");
#endif
		goto out;
  	}
  
	/* Send an ICMP "Fragment Reassembly Timeout" message. */
	ip_statistics.IpReasmTimeout++;
	ip_statistics.IpReasmFails++;   
	icmp_send(qp->fragments->skb, ICMP_TIME_EXCEEDED, ICMP_EXC_FRAGTIME, 0);

out:
	/* Nuke the fragment queue. */
	ip_free(qp);
}
Exemplo n.º 12
0
static void ip_expire(unsigned long arg)
{
	struct ipq *qp;

	qp = (struct ipq *)arg;

	/*
	 *	Send an ICMP "Fragment Reassembly Timeout" message.
	 */

	ip_statistics.IpReasmTimeout++;
	ip_statistics.IpReasmFails++;   
	/* This if is always true... shrug */
	if(qp->fragments!=NULL)
		icmp_send(qp->fragments->skb,ICMP_TIME_EXCEEDED,
				ICMP_EXC_FRAGTIME, 0, qp->dev);

	/*
	 *	Nuke the fragment queue.
	 */
	ip_free(qp);
}
Exemplo n.º 13
0
void got_packet (u_char *useless,const struct pcap_pkthdr *pheader, const u_char *packet) {
   if ( intr_flag != 0 ) { check_interupt(); }
   inpacket = 1;

   tstamp = pheader->ts;

   /* are we dumping */
   if (mode & MODE_DUMP) {
      time_t now = time(NULL);

      /* check if we should roll on time */
      if( ( roll_time != 0 ) &&
          ( now >= (roll_time_last + roll_time) ) )
      {
         roll_time_last = now;
         printf("Rolling on time.\n");
         dump_file_roll();
      }

      dump_file_offset = (uint64_t)ftell((FILE *)dump_handle);

      /* check if we should roll on size */
      if ( (roll_size > 0) &&
           (dump_file_offset >= roll_size) )
      {
         printf("Rolling on size.\n");
         dump_file_roll();
      }

      /* write the packet */
      pcap_dump((u_char *)dump_handle, pheader, packet);

      if ( dump_with_flush )
         pcap_dump_flush(dump_handle);
   }
   else if ( mode & MODE_FILE ) {
      read_file_offset = (uint64_t)ftell(pcap_file(handle)) - pheader->caplen - 16;
   }

   /* printf("[*] Got network packet...\n"); */
   ether_header *eth_hdr;
   eth_hdr = (ether_header *) (packet);
   u_short eth_type;
   eth_type = ntohs(eth_hdr->eth_ip_type);
   int eth_header_len;
   eth_header_len = ETHERNET_HEADER_LEN;
   vlanid = 0;

   if ( eth_type == ETHERNET_TYPE_8021Q ) {
      /* printf("[*] ETHERNET TYPE 8021Q\n"); */
      eth_type = ntohs(eth_hdr->eth_8_ip_type);
      eth_header_len +=4;
      vlanid = ntohs(eth_hdr->eth_8_vid);
   }

   else if ( eth_type == (ETHERNET_TYPE_802Q1MT|ETHERNET_TYPE_802Q1MT2|ETHERNET_TYPE_802Q1MT3|ETHERNET_TYPE_8021AD) ) {
      /* printf("[*] ETHERNET TYPE 802Q1MT\n"); */
      eth_type = ntohs(eth_hdr->eth_82_ip_type);
      eth_header_len +=8;
      vlanid = ntohs(eth_hdr->eth_82_vid);
   }

   /* zero-ise our structure, simplifies our hashing later on */
   int ip_tracked = 0;
   ip_t *ip_src = calloc(1, sizeof(ip_t));
   ip_t *ip_dst = calloc(1, sizeof(ip_t));

   if ( eth_type == ETHERNET_TYPE_IP ) {
      /* printf("[*] Got IPv4 Packet...\n"); */
      ip4_header *ip4;
      ip4 = (ip4_header *) (packet + eth_header_len);

      ip_set(&ip_config, ip_src, &ip4->ip_src, AF_INET);
      ip_set(&ip_config, ip_dst, &ip4->ip_dst, AF_INET);

      if ( ip4->ip_p == IP_PROTO_TCP ) {
         tcp_header *tcph;
         tcph = (tcp_header *) (packet + eth_header_len + (IP_HL(ip4)*4));
         /* printf("[*] IPv4 PROTOCOL TYPE TCP:\n"); */
         ip_tracked = cx_track(ip_src, tcph->src_port, ip_dst, tcph->dst_port, ip4->ip_p, pheader->len, tcph->t_flags, tstamp, AF_INET);
      }
      else if (ip4->ip_p == IP_PROTO_UDP) {
         udp_header *udph;
         udph = (udp_header *) (packet + eth_header_len + (IP_HL(ip4)*4));
         /* printf("[*] IPv4 PROTOCOL TYPE UDP:\n"); */
         ip_tracked = cx_track(ip_src, udph->src_port, ip_dst, udph->dst_port, ip4->ip_p, pheader->len, 0, tstamp, AF_INET);
      }
      else if (ip4->ip_p == IP_PROTO_ICMP) {
         icmp_header *icmph;
         icmph = (icmp_header *) (packet + eth_header_len + (IP_HL(ip4)*4));
         /* printf("[*] IP PROTOCOL TYPE ICMP\n"); */
         ip_tracked = cx_track(ip_src, icmph->s_icmp_id, ip_dst, icmph->s_icmp_id, ip4->ip_p, pheader->len, 0, tstamp, AF_INET);
      }
      else {
         /* printf("[*] IPv4 PROTOCOL TYPE OTHER: %d\n",ip4->ip_p); */
         ip_tracked = cx_track(ip_src, ip4->ip_p, ip_dst, ip4->ip_p, ip4->ip_p, pheader->len, 0, tstamp, AF_INET);
      }
   }

   else if ( eth_type == ETHERNET_TYPE_IPV6) {
      /* printf("[*] Got IPv6 Packet...\n"); */
      ip6_header *ip6;
      ip6 = (ip6_header *) (packet + eth_header_len);

      ip_set(&ip_config, ip_src, &ip6->ip_src, AF_INET6);
      ip_set(&ip_config, ip_dst, &ip6->ip_dst, AF_INET6);

      if ( ip6->next == IP_PROTO_TCP ) {
         tcp_header *tcph;
         tcph = (tcp_header *) (packet + eth_header_len + IP6_HEADER_LEN);
         /* printf("[*] IPv6 PROTOCOL TYPE TCP:\n"); */
         ip_tracked = cx_track(ip_src, tcph->src_port, ip_dst, tcph->dst_port, ip6->next, pheader->len, tcph->t_flags, tstamp, AF_INET6);
      }
      else if (ip6->next == IP_PROTO_UDP) {
         udp_header *udph;
         udph = (udp_header *) (packet + eth_header_len + IP6_HEADER_LEN);
         /* printf("[*] IPv6 PROTOCOL TYPE UDP:\n"); */
         ip_tracked = cx_track(ip_src, udph->src_port, ip_dst, udph->dst_port, ip6->next, pheader->len, 0, tstamp, AF_INET6);
      }
      else if (ip6->next == IP6_PROTO_ICMP) {
         //icmp6_header *icmph;
         //icmph = (icmp6_header *) (packet + eth_header_len + IP6_HEADER_LEN);

         /* printf("[*] IPv6 PROTOCOL TYPE ICMP\n"); */
         ip_tracked = cx_track(ip_src, ip6->hop_lmt, ip_dst, ip6->hop_lmt, ip6->next, pheader->len, 0, tstamp, AF_INET6);
      }
      else {
         /* printf("[*] IPv6 PROTOCOL TYPE OTHER: %d\n",ip6->next); */
         ip_tracked = cx_track(ip_src, ip6->next, ip_dst, ip6->next, ip6->next, pheader->len, 0, tstamp, AF_INET6);
      }
   }

   if ( ip_tracked == 0 )
   {
      if (ip_src != NULL) ip_free(ip_src);
      if (ip_dst != NULL) ip_free(ip_dst);
   }

   inpacket = 0;
   return;
   (void) useless;
   /* else { */
   /*   printf("[*] ETHERNET TYPE : %x\n", eth_hdr->eth_ip_type); */
   /*   return; */
   /* } */
}
Exemplo n.º 14
0
/*
  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)
ip_glue(struct ipq * qp,IP_THREAD_LOCAL_P  ip_thread_local_p)
{
	char *skb;
	struct ip *iph;
	struct ipfrag *fp;
	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);
		ip_free(qp,ip_thread_local_p);
		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);
		ip_free(qp,ip_thread_local_p);
		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);
			ip_free(qp,ip_thread_local_p);
			//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);
	ip_free(qp,ip_thread_local_p);

	/* 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);
}
Exemplo n.º 15
0
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 = qp->ihlen + qp->len;
	
	if(len>65535)
	{
		NETDEBUG(printk("Oversized IP packet from %s.\n", in_ntoa(qp->iph->saddr)));
		ip_statistics.IpReasmFails++;
		ip_free(qp);
		return NULL;
	}
	
	if ((skb = dev_alloc_skb(len)) == NULL)
	{
		ip_statistics.IpReasmFails++;
		NETDEBUG(printk("IP: queue_glue: no memory for gluing queue %p\n", qp));
		ip_free(qp);
		return(NULL);
	}

	/* Fill in the basic details. */
	skb_put(skb,len);
	skb->h.raw = skb->data;
	skb->free = 1;

	/* Copy the original IP headers into the new buffer. */
	ptr = (unsigned char *) skb->h.raw;
	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 > skb->len)
		{
			NETDEBUG(printk("Invalid fragment list: Fragment over size.\n"));
			ip_free(qp);
			kfree_skb(skb,FREE_WRITE);
			ip_statistics.IpReasmFails++;
			return NULL;
		}
		memcpy((ptr + fp->offset), fp->ptr, fp->len);
		count += fp->len;
		fp = fp->next;
	}

	skb->pkt_type = qp->fragments->skb->pkt_type;
	skb->protocol = qp->fragments->skb->protocol;
	/* 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 * 4) + count);
	skb->ip_hdr = iph;

	ip_statistics.IpReasmOKs++;
	return(skb);
}
Exemplo n.º 16
0
/* 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;
  }

  /* ip_evictor() could have removed all queues for the current host */
  if (!this_host)
    hostfrag_create(iph);

  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 = (unsigned char *)(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 */
    fprintf(stderr,"this is ipfragment.sd");
	return (skb2);
  }
  return (NULL);
}
Exemplo n.º 17
0
void GreensFunction3DRadInf::makeRnTable(RealVector& RnTable,
                                          Real r, Real t) const
{
    RnTable.clear();

    const Real sigma(getSigma());
    const Real D(getD());
    const Real kf(getkf());

    {  
        // First, estimate the size of p_corr, and if it's small enough,
        // we don't need to calculate it in the first place.
        const Real pirr(p_irr(r, t, r0, kf, D, sigma));
        const Real ipfree_max(ip_free(M_PI, r, t) * 2 * M_PI * r * r);
        
        if(fabs((pirr - ipfree_max) / ipfree_max) < 1e-8)
        {
            return;
        }
    }


    const Real pfreemax(p_free_max(r, r0, t, D));

    gsl_integration_workspace* 
        workspace(gsl_integration_workspace_alloc(2000));
    
    Real Rn_prev(0.0);
    const Real RnFactor(1.0 / (4.0 * M_PI * sqrt(r * r0)));

    const Real integrationTolerance(pfreemax / RnFactor * THETA_TOLERANCE);
    const Real truncationTolerance(pfreemax * THETA_TOLERANCE * 1e-1);
    
    unsigned int n(0);
    for (;;) 
    {
        const Real Rn(this->Rn(n, r, t, workspace, 
                                 integrationTolerance));
        
        RnTable.push_back(Rn);
        
        // truncate when converged enough.
        const Real absRn(fabs(Rn));
        if(absRn * RnFactor < truncationTolerance &&
            absRn < Rn_prev)
        {
            break;
        }

        if(n >= this->MAX_ORDER)
        {
            log_.info("GreensFunction3DRadInf: Rn didn't converge");
            break;
        }
        
        Rn_prev = fabs(Rn);
        
        ++n;
    }

    gsl_integration_workspace_free(workspace);
}
Exemplo n.º 18
0
/* Process an incoming IP datagram fragment. */
struct sk_buff *ip_defrag(struct sk_buff *skb)
{
	struct iphdr *iph = skb->nh.iph;
	struct ipfrag *prev, *next, *tmp, *tfp;
	struct ipq *qp;
	unsigned char *ptr;
	int flags, offset;
	int i, ihl, end;
	
	ip_statistics.IpReasmReqds++;

	/* Start by cleaning up the memory. */
	if (atomic_read(&ip_frag_mem) > sysctl_ipfrag_high_thresh)
		ip_evictor();

	/*
	 * Look for the entry for this IP datagram in the
	 * "incomplete datagrams" queue. If found, the
	 * timer is removed.
	 */
	qp = ip_find(iph, skb->dst);

	/* Is this a non-fragmented datagram? */
	offset = ntohs(iph->frag_off);
	flags = offset & ~IP_OFFSET;
	offset &= IP_OFFSET;

	offset <<= 3;		/* offset is in 8-byte chunks */
	ihl = iph->ihl * 4;

	/*
	 * Check whether to create a fresh queue entry. If the
	 * queue already exists, its timer will be restarted as
	 * long as we continue to receive fragments.
	 */
	if (qp) {
		/* ANK. If the first fragment is received,
		 * we should remember the correct IP header (with options)
		 */
	        if (offset == 0) {
			/* Fragmented frame replaced by unfragmented copy? */
			if ((flags & IP_MF) == 0)
				goto out_freequeue;
			qp->ihlen = ihl;
			memcpy(qp->iph, iph, (ihl + 8));
		}
	} else {
		/* Fragmented frame replaced by unfragmented copy? */
		if ((offset == 0) && ((flags & IP_MF) == 0))
			goto out_skb;

		/* If we failed to create it, then discard the frame. */
		qp = ip_create(skb, iph);
		if (!qp)
			goto out_freeskb;
	}
	
	/* Attempt to construct an oversize packet. */
	if((ntohs(iph->tot_len) + ((int) offset)) > 65535)
		goto out_oversize;

	/* Determine the position of this fragment. */
	end = offset + ntohs(iph->tot_len) - 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;
	}

	/* Point into the IP datagram 'data' part. */
	ptr = skb->data + ihl;

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

		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.
		 */
		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;
			
			/* We have killed the original next frame. */
			next = tfp;

			frag_kfree_skb(tmp->skb);
			frag_kfree_s(tmp, sizeof(struct ipfrag));
		}
	}

	/*
	 * Create a fragment to hold this skb.
	 * No memory to save the fragment? throw the lot ...
	 */
	tfp = ip_frag_create(offset, end, skb, ptr);
	if (!tfp)
		goto out_freeskb;

	/* Insert this fragment in the chain of fragments. */
	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)) {
		/* Glue together the fragments. */
 		skb = ip_glue(qp);
		/* Free the queue entry. */
out_freequeue:
		ip_free(qp);
out_skb:
		return skb;
	}

	/*
	 * The queue is still active ... reset its timer.
	 */
out_timer:
	mod_timer(&qp->timer, jiffies + sysctl_ipfrag_time); /* ~ 30 seconds */
out:
	return NULL;

	/*
	 * Error exits ... we need to reset the timer if there's a queue.
	 */
out_oversize:
	if (net_ratelimit())
		printk(KERN_INFO "Oversized packet received from %d.%d.%d.%d\n",
			NIPQUAD(iph->saddr));
	/* the skb isn't in a fragment, so fall through to free it */
out_freeskb:
	kfree_skb(skb);
	ip_statistics.IpReasmFails++;
	if (qp)
		goto out_timer;
	goto out;
}
Exemplo n.º 19
0
//
//  输入:
//        一个给定的ip队列,这个队列应该是完整的
//  返回:
//        一个ip报文
static char *
ip_glue(struct ipq * qp)
{
	char *skb;
	// 指向一个ip,到时候用来给新生成的ip字段赋值
	struct ip *iph;
	// 指向一个ip碎片
	struct ipfrag *fp;
	// 执向一个字节
	unsigned char *ptr;
	// 计数器、长度
	int count, len;

	/* Allocate a new buffer for the datagram. */
	// 长度 = 头长度 + 队列长度, 队列是所有ip碎片,不包括头长度
	len = qp->ihlen + qp->len;

	// 如果大于65535B 太大了,返回
	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;
	}

	// 如果使用malloc失败,返回
	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. */
	// 首先将指针,指向skb,一个最新分配的空间
	ptr = (unsigned char *)skb;
	// 将头拷贝过来
	memcpy(ptr, ((unsigned char *) qp->iph), qp->ihlen);
	ptr += qp->ihlen;
	// count应该是用来记录偏移量的
	count = 0;


	/* Copy the data portions of all fragments into the new buffer. */
	// 遍历队列中的所有碎片
	fp = qp->fragments;
	while (fp != NULL)
	{
		// 如果碎片大小为0,  或者,   碎片的偏移量过大, 则出错,释放空间,返回
		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);
		// 长度增加(通常这个会是fp->end - fp->offset -1)
		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. */
	// 将最新生成的ip结构保存下来
	iph = (struct ip *) skb;
	// 偏移量初始化为0
	iph->ip_off = 0;
	// 计算长度
	iph->ip_len = htons((iph->ip_hl * 4) + count);
	// skb->ip_hdr = iph;

	// 返回生成的ip
	return (skb);
}
Exemplo n.º 20
0
// 每重组一个ip碎片,就会更新对应ipq的timer
//
//
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;

	// 如果成功更新全局变量this_host, 并且skb是有内容的
	if (!hostfrag_find(iph) && skb)
		// 生成一个碎片
		hostfrag_create(iph);

	/* Start by cleaning up the memory. */
	// 如果当前host不为空
	if (this_host)
		// 如果大于上限
		if (this_host->ip_frag_mem > IPFRAG_HIGH_THRESH)
			// 裁剪掉一些ip碎片,直到 ip_frag_mem < IPFRAG_LOW_THRESH
			ip_evictor();

	/* Find the entry of this IP datagram in the "incomplete datagrams" queue. */
	// 如果host存在
	if (this_host)
		// 找到与这个ip头相关的ip队列
		qp = ip_find(iph);
	else
		// 否则设置队列为空
		qp = 0;
	

	/* Is this a non-fragmented datagram? */
	// ip_off是一个16位的字段,高3位用来保存标志信息,低12位用来保存当前碎片的偏移
	offset = ntohs(iph->ip_off);  /* 先把ip_offset这个字段取出来 */
	// 把高3位取出来
	flags = offset & ~IP_OFFSET;
	// 把低13位取出来
	offset &= IP_OFFSET;
	// IP_MF==0表示当前收到是碎片后面没有碎片了,并且当前收到碎片是第一个碎片,
	// 显然当前碎片虽在的ip报文仅仅有一个碎片
	// 那么当前碎片(刚刚收到的碎片)并不需要重组,因此可以返回了
	if (((flags & IP_MF) == 0) && (offset == 0))
	{
		// 如果队列不为空就释放掉
		if (qp != NULL)
			ip_free(qp);		/* Fragmented frame replaced by full unfragmented copy */
		return 0;
	}

	/* ip_evictor() could have removed all queues for the current host */
	// 如果host全部被移出了,那么重新创建一个,针对当前ip头的host
	// 但是,这个host并不会包括任何东西,它是一个空的,没有ip队列
	if (!this_host)
		hostfrag_create(iph);
	// 计算offset和头长度
	// 这个offset是刚刚收到的这个碎片的offset
	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) */
		// 如果偏移量为0,可能是该pi报文中的第一个碎片,因此要把前8字节保存下来
		if (offset == 0)
		{
			// 保存头长度
			qp->ihlen = ihl;
			// 拷贝头信息+8字节
			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. */
	// 刚刚收到的碎片分组 + 刚刚收到的碎片ip包大小 - 刚刚收到的碎片ip包头大小
	// = 刚刚收到的分组的结尾
	end = offset + ntohs(iph->ip_len) - ihl;

	/* Point into the IP datagram 'data' part. */
	// 将指针,指向刚刚收到的碎片ip包的数据开头部分
	// prt 指向肉
	ptr = (unsigned char *)(skb->data + ihl);

	/* Is this the final fragment? */
	// 如果这是最后一个碎片,那么,整个队列的长度,就是当前的end
	// 否则qp->len会在后面更改,因为会有重叠部分
	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;
	// 给定一个offset,在所有的fragments中找到第一个
	// 拥有不小于给定offset的offset的碎片,然后终止循环
	// 由此可以猜测,这一个函数,其实是将某一个新来的碎片插入到
	// 队列合适的位置,保证offset升序排列
	// next 指向的是第一个不小于当前offset的碎片
	// pre指向的是前一个碎片
	for (next = qp->fragments; next != NULL; next = next->next)
	{
		if (next->offset >= offset)
			break;			/* bingo! */
		prev = next;
	}
	/*--------------------------------------------------------------
	注意: 
		next 指向的是第一个排在当前碎片后面的 碎片;
		pre  指向的是第一个排在当前碎片前面的 碎片。
		next 有可能offset与当前碎片的offset一样
	----------------------------------------------------------------*/
	
	
	/*
	  We found where to put this one.  Check for overlap with preceding
	  fragment, and, if needed, align things so that any overlaps are
	  eliminated.
	*/
	// 如果有排在当前碎片前面的分组,并且, 该分组的结束比当前分组的offset大
	// 说明有重叠,应噶修正当前offset,以先来的为准
	if (prev != NULL && offset < prev->end)
	{
		nids_params.syslog(NIDS_WARN_IP, NIDS_WARN_IP_OVERLAP, iph, 0);
		i = prev->end - offset;
		// 将当前收到的碎片的offset增加i
		offset += i;		/* ptr into datagram */
		// 将当前收到的碎片的指正向后移动i
		ptr += i;			/* ptr into fragment data */
	}
	
	/*
	  Look for overlap with succeeding segments.
	  If we can merge fragments, do it.
	*/
	// 现在往后查看是否有重叠的
	// 从next开始
	for (tmp = next; tmp != NULL; tmp = tfp)
	{
		// temp总是等于next
		tfp = tmp->next;
		// 如果next的 offset >= 当前分组的end,那就没有问题
		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 */
		// 将next碎片的长度减少i
		tmp->len -= i;		/* so reduce size of    */
		// 将next碎片的开始增加i
		tmp->offset += i;		/* next fragment        */
		// 将指针也要向后移动i
		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.
		*/
		// 如果此时next碎片的长度小于0, 那么摘掉next节点
		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;

			// tfp原来就等于next->next,所以原来的next节点被摘掉了
			next = tfp;		/* We have killed the original "next" frame */

			// 释放掉frag节点对应的内存
			frag_kfree_skb(tmp->skb, FREE_READ);
			// 释放掉frag节点
			frag_kfree_s(tmp, sizeof(struct ipfrag));
		}
	}

	
	/* Insert this fragment in the chain of fragments. */
	tfp = NULL;
	// offset是刚刚接收到的碎片偏移,按字节
	// end   是刚刚接收到的碎片的结束字节
	// skb   是传进来的一个内存空间,应该事先分配好
	// prt   是指向这个碎片第一个数据的指针
	tfp = ip_frag_create(offset, end, skb, ptr);
	/*---------------------------------------------------
	注意:  
		ip_frag_create函数只是创建一个ip_frag,还没有吧
		它挂载到队列中
	-----------------------------------------------------*/

	/*
	  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. */
	// 将刚刚创建的ip_frag挂载到队列中去了
	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);
}
Exemplo n.º 21
0
Arquivo: fbbi.c Projeto: catseye/FBBI
int main(int argc, char **argv)
{
    int k, ec=0;
    FILE *f=NULL;
    bfspace *p=NULL;
    ip *i=NULL;
    cell w,h;
    int ssize  = DEFAULT_STACK_SIZE;
    int sssize = DEFAULT_STACKSTACK_SIZE;

    global_argv = argv;
    global_argc = argc;

    if (argc < 2)
        usage();

    fungeprog_arg = -1;
    for(k=1; k<argc; k++)
    {
#ifndef FBBI_MINIMAL
        if((!strcmp(argv[k], "-F")) || (!strcmp(argv[k], "-not-fast")) || (!strcmp(argv[k], "--not-fast"))) fast=0;
        if((!strcmp(argv[k], "-f")) || (!strcmp(argv[k], "-fast")) || (!strcmp(argv[k], "--fast"))) fast=1;
        if((!strcmp(argv[k], "-w")) || (!strcmp(argv[k], "-warn")) || (!strcmp(argv[k], "--warn"))) warn=1;
        if((!strcmp(argv[k], "-t")) || (!strcmp(argv[k], "-trace")) || (!strcmp(argv[k], "--trace"))) trace=1;
        if((!strcmp(argv[k], "-s")) || (!strcmp(argv[k], "-script")) || (!strcmp(argv[k], "--script"))) script = 1;
        if((!strcmp(argv[k], "-u")) || (!strcmp(argv[k], "-unefunge")) || (!strcmp(argv[k], "--unefunge"))) une = 1;
        if((!strcmp(argv[k], "-93")) || (!strcmp(argv[k], "-befunge93")) || (!strcmp(argv[k], "--befunge-93")) || (!strcmp(argv[k], "--befunge93"))) b93 = 1;
        if((!strcmp(argv[k], "-mc")) || (!strcmp(argv[k], "-maxcells")) || (!strcmp(argv[k], "--max-cells")) || (!strcmp(argv[k], "--maxcells")))
        {
            ssize = atoi(argv[++k]);
        } else if((!strcmp(argv[k], "-ms")) || (!strcmp(argv[k], "-maxstacks")) || (!strcmp(argv[k], "--max-stacks"))  || (!strcmp(argv[k], "--maxstacks")))
        {
            sssize = atoi(argv[++k]);
        } else
#endif
            if(argv[k][0] != '-') {
                fungeprog_arg = k;
                break;
            }
    }
    if (fungeprog_arg == -1)
        usage();

    /* initialize */

    srand(time(0));

    DEBUG("Allocating Funge-Space");
    if ((p = bfspace_alloc(NULL)) != NULL)
    {
        DEBUG("Allocating IP");
        if ((i = ip_alloc(p, ssize, sssize)) != NULL)
        {
            DEBUG("Opening Source File");
            if ((f=fopen(argv[fungeprog_arg],"r")) != NULL)
            {
#ifdef FBBI_MSDOS
#ifndef FBBI_ANSI
                setmode(fileno(f), O_BINARY);
#endif
#endif
                DEBUG("Reading Source File");
                if (bfspace_fread(i->bs, f, 0, 0, &w, &h, 0))
                {
                    fclose(f);
#ifndef FBBI_MINIMAL
                    if ((w > 79) || (h > 24))
                    {
                        if(b93 && warn)
                            fprintf(stderr, "fbbi warning: "
                                    "source too large for Befunge-93-Space (%ld x %ld)\n", w+1, h+1);
                    }
                    if (h >= 1)
                    {
                        if(une && warn)
                            fprintf(stderr, "fbbi warning: "
                                    "source too large for Unefunge-98-Space (%ld x %ld)\n", w+1, h+1);
                    }
                    if (script)
                    {
                        while (bfspace_fetch(i->bs, 0, i->y)
                                == ((long)0 | (long)'#'))
                            i->y++;
                    }
#endif
                    DEBUG("* Begin Interpret *");
                    while (!i->hm)
                    {
                        DEBUG("Moving IP");
                        ip_move(i);
#ifndef FBBI_MINIMAL
                        if(bpt && i->x == bx && i->y == by) trace=1;
#endif
                        DEBUG("Getting Instruction");
                        i->ir = bfspace_fetch(i->bs, i->x, i->y);
#ifndef FBBI_MINIMAL
                        if (b93 && ((i->x < 0) || (i->y < 0) || (i->x > 79) || (i->y > 24)) )
                        {
                            if(warn)
                                fprintf(stderr, "fbbi warning: "
                                        "beyond Befunge-93-Space at (%ld,%ld)\n", i->x, i->y);
                        }
                        if (trace)
                        {
                            perform_trace(i);
                            if (i->hm) break;
                        }
#endif
                        DEBUG("Executing Instruction");
                        if (i->sm && ((char)i->ir != '"'))
                        {
                            ip_push(i, i->ir);
                        } else
                        {
                            if ((i->ir < 32) || (i->ir > 126))
                            {
                                fi_unimp(i);
                            } else
                            {
#ifndef FBBI_MINIMAL
                                if(b93) b93instable[(char)i->ir-32](i);
                                else
#endif
                                    instable[(char)i->ir-32](i);
                            }
                        }
                    }
                    DEBUG("* End Interpret *");

                    ec = (int)i->ec;
                    DEBUG("Freeing IP");
                    ip_free(i);
                    DEBUG("Freeing Funge-Space");
                    bfspace_free(p);

                } else
                {
                    DEBUG("Freeing IP");
                    ip_free(i);
                    DEBUG("Freeing Funge-Space");
                    bfspace_free(p);
                    fclose(f);
#ifndef FBBI_MINIMAL
                    fprintf(stderr, "fbbi error: can't load file\n");
#endif
                    exit(1);
                }
            } else
            {
                DEBUG("Freeing IP");
                ip_free(i);
                DEBUG("Freeing Funge-Space");
                bfspace_free(p);
#ifndef FBBI_MINIMAL
                fprintf(stderr, "fbbi error: can't open file\n");
#endif
                exit(1);
            }
        } else
        {
            DEBUG("Freeing Funge-Space");
            bfspace_free(p);
#ifndef FBBI_MINIMAL
            fprintf(stderr, "fbbi error: can't allocate ip\n");
#endif
            exit(1);
        }
    } else
    {
#ifndef FBBI_MINIMAL
        fprintf(stderr, "fbbi error: can't allocate befunge-space\n");
#endif
        exit(1);
    }
    return ec;
}