* applied patches from the most recent FreiFunkFirmware (and fixed compile errors...
[olsrd.git] / src / parser.c
index e89428e..f6fe3d6 100644 (file)
@@ -1,26 +1,42 @@
 /*
- * OLSR ad-hoc routing table management protocol
- * Copyright (C) 2004 Andreas T√łnnesen (andreto@ifi.uio.no)
+ * The olsr.org Optimized Link-State Routing daemon(olsrd)
+ * Copyright (c) 2004, Andreas T√łnnesen(andreto@olsr.org)
+ * All rights reserved.
  *
- * This file is part of the olsr.org OLSR daemon.
+ * Redistribution and use in source and binary forms, with or without 
+ * modification, are permitted provided that the following conditions 
+ * are met:
  *
- * olsr.org is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
+ * * Redistributions of source code must retain the above copyright 
+ *   notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright 
+ *   notice, this list of conditions and the following disclaimer in 
+ *   the documentation and/or other materials provided with the 
+ *   distribution.
+ * * Neither the name of olsr.org, olsrd nor the names of its 
+ *   contributors may be used to endorse or promote products derived 
+ *   from this software without specific prior written permission.
  *
- * olsr.org is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
+ * POSSIBILITY OF SUCH DAMAGE.
  *
- * You should have received a copy of the GNU General Public License
- * along with olsr.org; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- * 
- * 
- * $Id: parser.c,v 1.7 2004/09/21 19:08:57 kattemat Exp $
+ * Visit http://www.olsr.org for more information.
  *
+ * If you find this software useful feel free to make a donation
+ * to the project. For more information see the website or contact
+ * the copyright holders.
+ *
+ * $Id: parser.c,v 1.32 2007/01/31 12:36:50 bernd67 Exp $
  */
 
 #include "parser.h"
 #include "mid_set.h"
 #include "olsr.h"
 #include "rebuild_packet.h"
+#include "net_os.h"
+#include "log.h"
+#include "print_packet.h"
 
-//union olsr_ip_addr tmp_addr;
 #ifdef WIN32
 #undef EWOULDBLOCK
 #define EWOULDBLOCK WSAEWOULDBLOCK
 #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. 
@@ -52,9 +89,7 @@
 void
 olsr_init_parser()
 {
-  olsr_printf(3, "Initializing parser...\n");
-
-  parse_functions = NULL;
+  OLSR_PRINTF(3, "Initializing parser...\n")
 
   /* Initialize the packet functions */
   olsr_init_package_process();
@@ -62,11 +97,11 @@ olsr_init_parser()
 }
 
 void
-olsr_parser_add_function(void (*function)(union olsr_message *, struct interface *, union olsr_ip_addr *), int type, int forwarding)
+olsr_parser_add_function(void (*function)(union olsr_message *, struct interface *, union olsr_ip_addr *), olsr_u32_t type, int forwarding)
 {
   struct parse_function_entry *new_entry;
 
-  olsr_printf(3, "Parser: registering event for type %d\n", type);
+  OLSR_PRINTF(3, "Parser: registering event for type %d\n", type)
  
 
   new_entry = olsr_malloc(sizeof(struct parse_function_entry), "Register parse function");
@@ -79,14 +114,14 @@ olsr_parser_add_function(void (*function)(union olsr_message *, struct interface
   new_entry->next = parse_functions;
   parse_functions = new_entry;
 
-  olsr_printf(3, "Register parse function: Added function for type %d\n", type);
+  OLSR_PRINTF(3, "Register parse function: Added function for type %d\n", type)
 
 }
 
 
 
 int
-olsr_parser_remove_function(void (*function)(union olsr_message *, struct interface *, union olsr_ip_addr *), int type, int forwarding)
+olsr_parser_remove_function(void (*function)(union olsr_message *, struct interface *, union olsr_ip_addr *), olsr_u32_t type, int forwarding)
 {
   struct parse_function_entry *entry, *prev;
 
@@ -119,103 +154,6 @@ olsr_parser_remove_function(void (*function)(union olsr_message *, struct interf
 }
 
 
-
-/**
- *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(int fd)
-{
-  /* sockaddr_in6 is bigger than sockaddr !!!! */
-  struct sockaddr_storage from;
-  size_t fromlen;
-  int cc;
-  struct interface *olsr_in_if;
-  union olsr_ip_addr from_addr;
-  union
-  {
-    char       buf[MAXMESSAGESIZE+1];
-    struct     olsr olsr;
-  } inbuf;
-
-
-  for (;;) 
-    {
-      fromlen = sizeof(struct sockaddr_storage);
-
-      cc = recvfrom(fd, 
-                   (char *)&inbuf, 
-                   sizeof (inbuf), 
-                   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");
-           }
-         break;
-       }
-
-      if(ipversion == AF_INET)
-       {
-         /* IPv4 sender address */
-         COPY_IP(&from_addr, &((struct sockaddr_in *)&from)->sin_addr.s_addr);
-       }
-      else
-       {
-         /* 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 ((ipversion == AF_INET) && (fromlen != sizeof (struct sockaddr_in)))
-       break;
-      else if ((ipversion == AF_INET6) && (fromlen != sizeof (struct sockaddr_in6)))
-       break;
-
-      //printf("Recieved data on socket %d\n", socknr);
-
-
-      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(&inbuf.olsr, cc, olsr_in_if, &from_addr);
-    
-    }
-}
-
-
-
-
 /**
  *Process a newly received OLSR packet. Checks the type
  *and to the neccessary convertions and call the
@@ -235,19 +173,15 @@ parse_packet(struct olsr *olsr, int size, struct interface *in_if, union olsr_ip
   int msgsize;
   int processed;
   struct parse_function_entry *entry;
-  char *packet = (char*)olsr;
-  int i;
-  int x = 0;
 
   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)
     {
-      olsr_printf(1, "Size error detected in received packet.\nRecieved %d, in packet %d\n", size, ntohs(olsr->olsr_packlen));
+      OLSR_PRINTF(1, "Size error detected in received packet.\nRecieved %d, in packet %d\n", size, ntohs(olsr->olsr_packlen))
            
       olsr_syslog(OLSR_LOG_ERR, " packet length error in  packet received from %s!",
             olsr_ip_to_string(from_addr));
@@ -258,27 +192,9 @@ parse_packet(struct olsr *olsr, int size, struct interface *in_if, union olsr_ip
       
   /* Display packet */
   if(disp_pack_in)
-    {
-      printf("\n\tfrom: %s\n\tsize: %d\n\tcontent(decimal):\n\t", olsr_ip_to_string(from_addr), size);
-       
-      for(i = 0; i < size;i++)
-       {
-         if(x == 4)
-           {
-             x = 0;
-             printf("\n\t");
-           }
-         x++;
-         if(ipversion == AF_INET)
-           printf(" %03i", (u_char) packet[i]);
-         else
-           printf(" %02x", (u_char) packet[i]);
-       }
-           
-      printf("\n");
-    }
+    print_olsr_serialized_packet(stdout, (union olsr_packet *)olsr, size, from_addr);
 
-  if(ipversion == AF_INET)
+  if(olsr_cnf->ip_version == AF_INET)
     msgsize = ntohs(m->v4.olsr_msgsize);
   else
     msgsize = ntohs(m->v6.olsr_msgsize);
@@ -287,33 +203,38 @@ parse_packet(struct olsr *olsr, int size, struct interface *in_if, union olsr_ip
   /*
    * Hysteresis update - for every OLSR package
    */
-  if(use_hysteresis)
+  if(olsr_cnf->use_hysteresis)
     {
-      if(ipversion == AF_INET)
+      if(olsr_cnf->ip_version == AF_INET)
        {
          /* 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,
+                              ntohs(olsr->olsr_seqno));
+    }
   
   for ( ; count > 0; m = (union olsr_message *)((char *)m + (msgsize)))
     {
 
       processed = 0;      
-      if (count < minsize)
+      if (count < MIN_PACKET_SIZE(olsr_cnf->ip_version))
        break;
       
-      if(ipversion == AF_INET)
+      if(olsr_cnf->ip_version == AF_INET)
        msgsize = ntohs(m->v4.olsr_msgsize);
       else
        msgsize = ntohs(m->v6.olsr_msgsize);
@@ -323,8 +244,8 @@ parse_packet(struct olsr *olsr, int size, struct interface *in_if, union olsr_ip
       /* Check size of message */
       if(count < 0)
        {
-         olsr_printf(1, "packet length error in  packet received from %s!",
-                     olsr_ip_to_string(from_addr));
+         OLSR_PRINTF(1, "packet length error in  packet received from %s!",
+                     olsr_ip_to_string(from_addr))
 
          olsr_syslog(OLSR_LOG_ERR, " packet length error in  packet received from %s!",
                 olsr_ip_to_string(from_addr));
@@ -333,25 +254,25 @@ parse_packet(struct olsr *olsr, int size, struct interface *in_if, union olsr_ip
 
 
       /* Treat TTL hopcnt */
-      if(ipversion == AF_INET)
+      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(1, "Dropping packet type %d from neigh %s with TTL 0\n", 
+             OLSR_PRINTF(2, "Dropping packet type %d from neigh %s with TTL 0\n", 
                          m->v4.olsr_msgtype,
-                         olsr_ip_to_string(from_addr))
+                         olsr_ip_to_string(from_addr))
              continue;
            }
        }
       else
        {
          /* IPv6 */
-         if (m->v6.ttl <= 0) 
+         if (m->v6.ttl <= 0 && olsr_cnf->lq_fish == 0
            {
-             olsr_printf(1, "Dropping packet type %d from %s with TTL 0\n", 
+             OLSR_PRINTF(2, "Dropping packet type %d from %s with TTL 0\n", 
                          m->v4.olsr_msgtype,
-                         olsr_ip_to_string(from_addr))
+                         olsr_ip_to_string(from_addr))
              continue;
            }
        }
@@ -365,10 +286,10 @@ 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");
+         OLSR_PRINTF(3, "Not processing message originating from us!\n")
 #endif
          continue;
        }
@@ -399,13 +320,13 @@ parse_packet(struct olsr *olsr, int size, struct interface *in_if, union olsr_ip
        {
          unk_chgestruct(&unkpacket, m);
          
-         olsr_printf(1, "Unknown type: %d, size %d, from %s\n",
+         OLSR_PRINTF(3, "Unknown type: %d, size %d, from %s\n",
                      m->v4.olsr_msgtype,
                      size,
-                     olsr_ip_to_string(&unkpacket.originator));
+                     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, 
@@ -425,3 +346,192 @@ parse_packet(struct olsr *olsr, int size, struct interface *in_if, union olsr_ip
 
 
 
+/**
+ *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(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;
+  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, 
+                        inbuf, 
+                        sizeof (inbuf), 
+                        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");
+           }
+         break;
+       }
+
+      if(olsr_cnf->ip_version == AF_INET)
+       {
+         /* IPv4 sender address */
+         COPY_IP(&from_addr, &((struct sockaddr_in *)&from)->sin_addr.s_addr);
+       }
+      else
+       {
+         /* IPv6 sender address */
+         COPY_IP(&from_addr, &((struct sockaddr_in6 *)&from)->sin6_addr);
+       }
+      
+      
+#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
+       
+       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",
+                     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);
+    
+    }
+}
+
+
+
+
+/**
+ *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);
+  
+}
+
+