Now sends ICMP time-exceeded if the TTL is decremented to zero
diff --git a/contiki/uip/uip-fw.c b/contiki/uip/uip-fw.c
index adf6635..1ef2207 100644
--- a/contiki/uip/uip-fw.c
+++ b/contiki/uip/uip-fw.c
@@ -9,6 +9,7 @@
  */
 
 #include "uip.h"
+#include "uip_arch.h"
 #include "uip-fw.h"
 
 /**
@@ -49,6 +50,37 @@
   u8_t optdata[4];
 };
 
+struct icmpip_hdr {
+  /* IP header. */
+  u8_t vhl,
+    tos,          
+    len[2],       
+    ipid[2],        
+    ipoffset[2],  
+    ttl,          
+    proto;     
+  u16_t ipchksum;
+  u16_t srcipaddr[2], 
+    destipaddr[2];
+  /* ICMP (echo) header. */
+  u8_t type, icode;
+  u16_t icmpchksum;
+  u16_t id, seqno;
+  u8_t payload[1];
+};
+
+/**
+ * \internal
+ * ICMP ECHO type definition.
+ */
+#define ICMP_ECHO 8 
+
+/**
+ * \internal
+ * ICMP TIME-EXCEEDED type definition.
+ */
+#define ICMP_TE 11 
+
 /**
  * \internal
  * Pointer to the TCP/IP headers of the packet in the uip_buf buffer.
@@ -57,6 +89,12 @@
 
 /**
  * \internal
+ * Pointer to the ICMP/IP headers of the packet in the uip_buf buffer.
+ */
+#define ICMPBUF ((struct icmpip_hdr *)&uip_buf[UIP_LLH_LEN])
+
+/**
+ * \internal
  * Certain fields of an IP packet that are used for identifying
  * duplicate packets.
  */
@@ -114,6 +152,63 @@
 /*------------------------------------------------------------------------------*/
 /**
  * \internal
+ * Send out an ICMP TIME-EXCEEDED message.
+ *
+ * This function replaces the packet in the uip_buf buffer with the
+ * ICMP packet.
+ */
+/*------------------------------------------------------------------------------*/
+static void
+time_exceeded(void)
+{
+  u16_t tmp16;
+  
+  /* Copy fields from packet header into payload of this ICMP packet. */
+  memcpy(&(ICMPBUF->payload[0]), ICMPBUF, 28);
+
+  /* Set the ICMP type and code. */
+  ICMPBUF->type = ICMP_TE;
+  ICMPBUF->icode = 0;
+
+  /* Calculate the ICMP checksum. */
+  ICMPBUF->icmpchksum = 0;
+  ICMPBUF->icmpchksum = ~uip_chksum((u16_t *)&(ICMPBUF->type), 36);
+
+  /* Set the IP destination address to be the source address of the
+     original packet. */
+  tmp16= BUF->destipaddr[0];
+  BUF->destipaddr[0] = BUF->srcipaddr[0];
+  BUF->srcipaddr[0] = tmp16;
+  tmp16 = BUF->destipaddr[1];
+  BUF->destipaddr[1] = BUF->srcipaddr[1];
+  BUF->srcipaddr[1] = tmp16;
+
+  /* Set our IP address as the source address. */
+  BUF->srcipaddr[0] = uip_hostaddr[0];
+  BUF->srcipaddr[1] = uip_hostaddr[1];
+
+  /* The size of the ICMP time exceeded packet is 36 + the size of the
+     IP header (20) = 56. */
+  uip_len = 56;
+  ICMPBUF->len[0] = 0;
+  ICMPBUF->len[1] = uip_len;
+
+  /* Fill in the other fields in the IP header. */
+  ICMPBUF->vhl = 0x45;
+  ICMPBUF->tos = 0;
+  ICMPBUF->ipoffset[0] = ICMPBUF->ipoffset[1] = 0;
+  ICMPBUF->ttl  = UIP_TTL;
+  ICMPBUF->proto = UIP_PROTO_ICMP;
+  
+  /* Calculate IP checksum. */
+  ICMPBUF->ipchksum = 0;
+  ICMPBUF->ipchksum = ~(uip_ipchksum());
+
+
+}
+/*------------------------------------------------------------------------------*/
+/**
+ * \internal
  * Register a packet in the forwarding cache so that it won't be
  * forwarded again.
  */
@@ -122,7 +217,7 @@
 fwcache_register(void)
 {
   struct fwcache_entry *fw;
-    
+
   /* Register packet in forwarding cache. */
   fw = &fwcache[0];
   fw->len = BUF->len;
@@ -137,6 +232,29 @@
 }
 /*------------------------------------------------------------------------------*/
 /**
+ * \internal
+ * Find a network interface for the IP packet in uip_buf.
+ */
+/*------------------------------------------------------------------------------*/
+static struct uip_fw_netif *
+find_netif(void)
+{
+  struct uip_fw_netif *netif;
+  
+  /* Walk through every network interface to check for a match. */
+  for(netif = netifs; netif != NULL; netif = netif->next) {
+    if(ipaddr_maskcmp(BUF->destipaddr, netif->ipaddr,
+		      netif->netmask)) {
+      /* If there was a match, we break the loop. */
+      return netif;
+    }
+  }
+  
+  /* If no matching netif was found, we use default netif. */
+  return defaultnetif;  
+}    
+/*------------------------------------------------------------------------------*/
+/**
  * Output an IP packet on the correct network interface.
  *
  * The IP packet should be present in the uip_buf buffer and its
@@ -148,20 +266,8 @@
 {
   struct uip_fw_netif *netif;
   
-  /* Walk through every network interface to check for a match. */
-  for(netif = netifs; netif != NULL; netif = netif->next) {
-    if(ipaddr_maskcmp(BUF->destipaddr, netif->ipaddr,
-		      netif->netmask)) {
-      /* If there was a match, we break the loop. */
-      break;
-    }
-  }
+  netif = find_netif();
   
-  /* If no matching netif was found, we use default netif. */
-  if(netif == NULL) {
-    netif = defaultnetif;
-  }
-
   /* If we now have found a suitable network interface, we call its
      output function to send out the packet. */
   if(netif != NULL && uip_len > 0) {
@@ -184,7 +290,7 @@
 {
   struct uip_fw_netif *netif;
   struct fwcache_entry *fw;
-  
+
   /* First check if the packet is destined for ourselves and return 0
      to indicate that the packet should be processed locally. */
   if(BUF->destipaddr[0] == uip_hostaddr[0] &&
@@ -192,6 +298,16 @@
     return 0;
   }
 
+  /* If we use ping IP address configuration, and our IP address is
+     not yet configured, we should intercept all ICMP echo packets. */
+#if UIP_PINGADDRCONF
+  if((uip_hostaddr[0] | uip_hostaddr[1]) == 0 &&
+     BUF->proto == UIP_PROTO_ICMP &&
+     ICMPBUF->type == ICMP_ECHO) {
+    return 0;
+  }
+#endif /* UIP_PINGADDRCONF */
+
   /* Check if the packet is in the forwarding cache already, and if so
      we drop it. */
   /*  for(fw = fwcache; fw <= &fwcache[FWCACHE_SIZE]; ++fw) {*/
@@ -212,37 +328,26 @@
   }
 
   
-  /* Walk through every network interface to check for a match. */
-  for(netif = netifs; netif != NULL; netif = netif->next) {
-    if(ipaddr_maskcmp(BUF->destipaddr, netif->ipaddr,
-		      netif->netmask)) {
-      /* If there was a match, we break the loop. */
-      break;
-    }
-  }
-  
-  /* If no matching netif was found, we use default netif. */
-  if(netif == NULL) {
-    netif = defaultnetif;
-  }
+  netif = find_netif();
 
   /* Decrement the TTL (time-to-live) value in the IP header */
-  BUF->ttl = htons(htons(BUF->ttl) - 1);
+  BUF->ttl = BUF->ttl - 1;
   
-  /* We should really send an ICMP message if TTL == 0, but we skip it
-     for now... Instead, we just drop the packet (and pretend that it
-     was forwarded by returning 1). */
-  if(BUF->ttl == 0) {
-    return 1;
-  }
-
-  /* Incrementally update the IP checksum. */
+  /* Update the IP checksum. */
   if(BUF->ipchksum >= htons(0xffff - 0x0100)) {
     BUF->ipchksum = BUF->ipchksum + HTONS(0x0100) + 1;
   } else {
     BUF->ipchksum = BUF->ipchksum + HTONS(0x0100);
   }
   
+  /* If the TTL reaches zero we procude an ICMP time exceeded message
+     in the uip_buf buffer and forward that packet back to the sender
+     of the packet. */
+  if(BUF->ttl == 0) {    
+    time_exceeded();
+    netif = find_netif();
+  }
+  
   /* If we now have found a suitable network interface, we call its
      output function to send out the packet. */
   if(netif != NULL && uip_len > 0) {