* applied patches from the most recent FreiFunkFirmware (and fixed compile errors...
[olsrd.git] / src / parser.c
index 9772cbc..f6fe3d6 100644 (file)
@@ -36,7 +36,7 @@
  * to the project. For more information see the website or contact
  * the copyright holders.
  *
- * $Id: parser.c,v 1.23 2005/05/26 09:55:11 kattemat Exp $
+ * $Id: parser.c,v 1.32 2007/01/31 12:36:50 bernd67 Exp $
  */
 
 #include "parser.h"
 #define strerror(x) StrError(x)
 #endif
 
+/* Sven-Ola: On very slow devices used in huge networks
+ * the amount of lq_tc messages is so high, that the 
+ * recv() loop never ends. This is a small hack to end
+ * the loop in this cases
+ */
+unsigned int cpu_overload_exit = 0;
+
+struct parse_function_entry *parse_functions;
+
 static char inbuf[MAXMESSAGESIZE+1];
 
+static olsr_bool disp_pack_in = OLSR_FALSE;
+
+void
+parser_set_disp_pack_in(olsr_bool val)
+{
+  disp_pack_in = val;
+}
+
 /**
  *Initialize the parser. 
  *
@@ -158,7 +176,7 @@ parse_packet(struct olsr *olsr, int size, struct interface *in_if, union olsr_ip
 
   count = size - ((char *)m - (char *)olsr);
 
-  if (count < minsize)
+  if (count < MIN_PACKET_SIZE(olsr_cnf->ip_version))
     return;
 
   if (ntohs(olsr->olsr_packlen) != size)
@@ -191,21 +209,21 @@ parse_packet(struct olsr *olsr, int size, struct interface *in_if, union olsr_ip
        {
          /* IPv4 */
          update_hysteresis_incoming(from_addr, 
-                                    &in_if->ip_addr,
+                                    in_if,
                                     ntohs(olsr->olsr_seqno));
        }
       else
        {
          /* IPv6 */
          update_hysteresis_incoming(from_addr, 
-                                    &in_if->ip_addr
+                                    in_if
                                     ntohs(olsr->olsr_seqno));
        }
     }
 
   if (olsr_cnf->lq_level > 0)
     {
-      olsr_update_packet_loss(from_addr, &in_if->ip_addr,
+      olsr_update_packet_loss(from_addr, in_if,
                               ntohs(olsr->olsr_seqno));
     }
   
@@ -213,7 +231,7 @@ parse_packet(struct olsr *olsr, int size, struct interface *in_if, union olsr_ip
     {
 
       processed = 0;      
-      if (count < minsize)
+      if (count < MIN_PACKET_SIZE(olsr_cnf->ip_version))
        break;
       
       if(olsr_cnf->ip_version == AF_INET)
@@ -239,7 +257,7 @@ parse_packet(struct olsr *olsr, int size, struct interface *in_if, union olsr_ip
       if(olsr_cnf->ip_version == AF_INET)
        {
          /* IPv4 */
-         if (m->v4.ttl <= 0)
+         if (m->v4.ttl <= 0 && olsr_cnf->lq_fish == 0)
            {
              OLSR_PRINTF(2, "Dropping packet type %d from neigh %s with TTL 0\n", 
                          m->v4.olsr_msgtype,
@@ -250,7 +268,7 @@ parse_packet(struct olsr *olsr, int size, struct interface *in_if, union olsr_ip
       else
        {
          /* IPv6 */
-         if (m->v6.ttl <= 0) 
+         if (m->v6.ttl <= 0 && olsr_cnf->lq_fish == 0
            {
              OLSR_PRINTF(2, "Dropping packet type %d from %s with TTL 0\n", 
                          m->v4.olsr_msgtype,
@@ -268,7 +286,7 @@ parse_packet(struct olsr *olsr, int size, struct interface *in_if, union olsr_ip
        */
 
       /* Should be the same for IPv4 and IPv6 */
-      if(COMP_IP(&m->v4.originator, &main_addr))
+      if(COMP_IP(&m->v4.originator, &olsr_cnf->main_addr))
        {
 #ifdef DEBUG
          OLSR_PRINTF(3, "Not processing message originating from us!\n")
@@ -308,7 +326,7 @@ parse_packet(struct olsr *olsr, int size, struct interface *in_if, union olsr_ip
                      olsr_ip_to_string(&unkpacket.originator))
 
          /* Forward message */
-         if(!COMP_IP(&unkpacket.originator, &main_addr))
+         if(!COMP_IP(&unkpacket.originator, &olsr_cnf->main_addr))
            {         
              /* Forward */
              olsr_forward_message(m, 
@@ -341,14 +359,20 @@ olsr_input(int fd)
 {
   /* sockaddr_in6 is bigger than sockaddr !!!! */
   struct sockaddr_storage from;
-  size_t fromlen;
+  socklen_t fromlen;
   int cc;
   struct interface *olsr_in_if;
   union olsr_ip_addr from_addr;
-
-
+  cpu_overload_exit = 0;
+  
   for (;;) 
     {
+      if (32 < ++cpu_overload_exit)
+      {
+        OLSR_PRINTF(1, "CPU overload detected, ending olsr_input() loop\n")
+       break;
+      }
+      
       fromlen = sizeof(struct sockaddr_storage);
 
       cc = olsr_recvfrom(fd, 
@@ -378,23 +402,21 @@ olsr_input(int fd)
          /* IPv6 sender address */
          COPY_IP(&from_addr, &((struct sockaddr_in6 *)&from)->sin6_addr);
        }
-
-      /* are we talking to ourselves? */
-      if(if_ifwithaddr(&from_addr) != NULL)
-       return;
-
+      
+      
 #ifdef DEBUG
       OLSR_PRINTF(5, "Recieved a packet from %s\n", olsr_ip_to_string((union olsr_ip_addr *)&((struct sockaddr_in *)&from)->sin_addr.s_addr))
 #endif
-      //printf("\nCC: %d FROMLEN: %d\n\n", cc, fromlen);
-      if ((olsr_cnf->ip_version == AF_INET) && (fromlen != sizeof (struct sockaddr_in)))
-       break;
-      else if ((olsr_cnf->ip_version == AF_INET6) && (fromlen != sizeof (struct sockaddr_in6)))
-       break;
-
-      //printf("Recieved data on socket %d\n", socknr);
-
-
+       
+       if ((olsr_cnf->ip_version == AF_INET) && (fromlen != sizeof (struct sockaddr_in)))
+         break;
+       else if ((olsr_cnf->ip_version == AF_INET6) && (fromlen != sizeof (struct sockaddr_in6)))
+         break;
+      
+      /* are we talking to ourselves? */
+      if(if_ifwithaddr(&from_addr) != NULL)
+       return;
+      
       if((olsr_in_if = if_ifwithsock(fd)) == NULL)
        {
          OLSR_PRINTF(1, "Could not find input interface for message from %s size %d\n",
@@ -417,3 +439,99 @@ olsr_input(int fd)
 }
 
 
+
+
+/**
+ *Processing OLSR data from socket. Reading data, setting 
+ *wich interface recieved the message, Sends IPC(if used) 
+ *and passes the packet on to parse_packet().
+ *
+ *@param fd the filedescriptor that data should be read from.
+ *@return nada
+ */
+void
+olsr_input_hostemu(int fd)
+{
+  /* sockaddr_in6 is bigger than sockaddr !!!! */
+  struct sockaddr_storage from;
+  socklen_t fromlen;
+  int cc;
+  struct interface *olsr_in_if;
+  union olsr_ip_addr from_addr;
+  olsr_u16_t pcklen;
+
+  /* Host emulator receives IP address first to emulate
+     direct link */
+
+  if((cc = recv(fd, from_addr.v6.s6_addr, olsr_cnf->ipsize, 0)) != (int)olsr_cnf->ipsize)
+    {
+      fprintf(stderr, "Error receiving host-client IP hook(%d) %s!\n", cc, strerror(errno));
+      COPY_IP(&from_addr, &((struct olsr *)inbuf)->olsr_msg->originator);
+    }
+
+  /* are we talking to ourselves? */
+  if(if_ifwithaddr(&from_addr) != NULL)
+    return;
+      
+  /* Extract size */
+  if((cc = recv(fd, &pcklen, 2, MSG_PEEK)) != 2)
+    {
+      if(cc <= 0)
+       {
+         fprintf(stderr, "Lost olsr_switch connection - exit!\n");
+         olsr_exit(__func__, EXIT_FAILURE);
+       }
+      fprintf(stderr, "[hust-emu] error extracting size(%d) %s!\n", cc, strerror(errno));
+      return;
+    }
+  else
+    {
+      pcklen = ntohs(pcklen);
+    }
+
+  fromlen = sizeof(struct sockaddr_storage);
+  
+  cc = olsr_recvfrom(fd, 
+                    inbuf, 
+                    pcklen, 
+                    0, 
+                    (struct sockaddr *)&from, 
+                    &fromlen);
+
+  if (cc <= 0) 
+    {
+      if (cc < 0 && errno != EWOULDBLOCK)
+       {
+         OLSR_PRINTF(1, "error recvfrom: %s", strerror(errno))
+           olsr_syslog(OLSR_LOG_ERR, "error recvfrom: %m");
+       }
+      return;
+    }
+  
+  if(cc != pcklen)
+    {
+      printf("Could not read whole packet(size %d, read %d)\n", pcklen, cc);
+      return;
+    }
+
+  if((olsr_in_if = if_ifwithsock(fd)) == NULL)
+    {
+      OLSR_PRINTF(1, "Could not find input interface for message from %s size %d\n",
+                 olsr_ip_to_string(&from_addr),
+                 cc)
+       olsr_syslog(OLSR_LOG_ERR, "Could not find input interface for message from %s size %d\n",
+                   olsr_ip_to_string(&from_addr),
+                   cc);
+      return;
+    }
+  
+  /*
+   * &from - sender
+   * &inbuf.olsr 
+   * cc - bytes read
+   */
+  parse_packet((struct olsr *)inbuf, cc, olsr_in_if, &from_addr);
+  
+}
+
+