ARM crosscompiler fixes
[olsrd.git] / src / net.c
index 5d0fe7b..0e6c129 100644 (file)
--- a/src/net.c
+++ b/src/net.c
  * 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: net.c,v 1.17 2004/10/20 19:43:04 kattemat Exp $
  *
  */
 
-/* $Id: net.c,v 1.8 2004/09/21 18:24:39 kattemat Exp $ */
-
-
 #include "net.h"
 #include "olsr.h"
 #include <stdlib.h>
@@ -34,75 +34,99 @@ void
 WinSockPError(char *);
 #endif
 
+#warning Interface configuration is now responsible for setting up outputbuffers!!
 
-
-static char out_buffer[MAXMESSAGESIZE+1];
-static char fwd_buffer[MAXMESSAGESIZE+1];
-
-static union olsr_packet *outmsg = (union olsr_packet *)out_buffer;
-static union olsr_packet *fwdmsg = (union olsr_packet *)fwd_buffer;
-
-int outputsize = 0;         /* current size of the output buffer */
-int fwdsize = 0;         /* current size of the forward buffer */
+struct olsr_netbuf
+{
+  char *buff;     /* Pointer to the allocated buffer */
+  int if_index;
+  int bufsize;    /* Size of the buffer */
+  int maxsize;    /* Max bytes of payload that can be added to the buffer */
+  int pending;    /* How much data is currently pending in the buffer */
+  int reserved;   /* Plugins can reserve space in buffers */
+};
 
 
-/* Max OLSR packet size */
+static struct olsr_netbuf *netbufs[MAX_IFS];
 
-static int maxmessagesize = MAXMESSAGESIZE - OLSR_HEADERSIZE;
 
 
 void
 init_net()
 {
   ptf_list = NULL;
-  maxmessagesize = MAXMESSAGESIZE - OLSR_HEADERSIZE;
 
   return;
 }
 
 int
-net_set_maxmsgsize(olsr_u16_t new_size)
+net_add_buffer(struct interface *ifp)
 {
+  struct olsr_netbuf *new_buf;
 
-  if(new_size > (MAXMESSAGESIZE - OLSR_HEADERSIZE))
+  /* If a buffer already exists for this interface back off */
+  if(netbufs[ifp->if_nr])
     return -1;
 
-  else
-    maxmessagesize = new_size;
+  new_buf = olsr_malloc(sizeof(struct olsr_netbuf), "add_netbuff1");
+  new_buf->buff = olsr_malloc(ifp->int_mtu, "add_netbuff2");
 
-  return maxmessagesize;
-}
+  /* Fill struct */
+  new_buf->bufsize = ifp->int_mtu;
+  new_buf->if_index = ifp->if_nr;
+  new_buf->maxsize = ifp->int_mtu - OLSR_HEADERSIZE;
+  new_buf->pending = 0;
+  new_buf->reserved = 0;
 
+  netbufs[ifp->if_nr] = new_buf;
 
-inline olsr_u16_t
-net_get_maxmsgsize()
-{
-  return maxmessagesize;
+  return 0;
 }
 
 
-inline olsr_u16_t
-net_fwd_pending()
+int
+net_remove_buffer(struct interface *ifp)
 {
-  return fwdsize;
+
+  /* If a buffer already exists for this interface back off */
+  if(!netbufs[ifp->if_nr])
+    return -1;
+  
+  /* Flush pending data */
+  if(netbufs[ifp->if_nr]->pending)
+    net_output(ifp);
+
+  free(netbufs[ifp->if_nr]->buff);
+  free(netbufs[ifp->if_nr]);
+  netbufs[ifp->if_nr] = NULL;
+
+  return 0;
 }
 
-/**
- * Add data to the buffer that is to be transmitted
- *
- * @return 0 if there was not enough room in buffer
- */
+
+
 int
-net_outbuffer_push(olsr_u8_t *data, olsr_u16_t size)
+net_reserve_bufspace(struct interface *ifp, int size)
 {
 
-  if((outputsize + size) > maxmessagesize)
-    return 0;
 
-  memcpy(&out_buffer[outputsize + OLSR_HEADERSIZE], data, size);
-  outputsize += size;
+  if((!netbufs[ifp->if_nr]) || (size > netbufs[ifp->if_nr]->maxsize))
+    return -1;
+  
+  netbufs[ifp->if_nr]->reserved = size;
+  netbufs[ifp->if_nr]->maxsize -= size;
+  
+  return 0;
+}
 
-  return 1;
+
+inline olsr_u16_t
+net_output_pending(struct interface *ifp)
+{
+  if(!netbufs[ifp->if_nr])
+    return -1;
+
+  return netbufs[ifp->if_nr]->pending;
 }
 
 
@@ -112,32 +136,58 @@ net_outbuffer_push(olsr_u8_t *data, olsr_u16_t size)
  *
  * @return 0 if there was not enough room in buffer
  */
-inline int
-net_outbuffer_bytes_left()
+int
+net_outbuffer_push(struct interface *ifp, olsr_u8_t *data, olsr_u16_t size)
 {
-  return (maxmessagesize - outputsize);
+
+  if(!netbufs[ifp->if_nr])
+    return -1;
+
+  if((netbufs[ifp->if_nr]->pending + size) > netbufs[ifp->if_nr]->maxsize)
+    return 0;
+
+  memcpy(&netbufs[ifp->if_nr]->buff[netbufs[ifp->if_nr]->pending + OLSR_HEADERSIZE], data, size);
+  netbufs[ifp->if_nr]->pending += size;
+
+  return size;
 }
 
 
 /**
- * Add data to the buffer that is to be forwarded
+ * Adddata to the reserved part of the buffer that is to be transmitted
  *
  * @return 0 if there was not enough room in buffer
  */
 int
-net_fwdbuffer_push(olsr_u8_t *data, olsr_u16_t size)
+net_outbuffer_push_reserved(struct interface *ifp, olsr_u8_t *data, olsr_u16_t size)
 {
 
-  if((fwdsize + size) > maxmessagesize)
+  if(!netbufs[ifp->if_nr])
+    return -1;
+
+  if((netbufs[ifp->if_nr]->pending + size) > (netbufs[ifp->if_nr]->maxsize + netbufs[ifp->if_nr]->reserved))
     return 0;
 
-  memcpy(&fwd_buffer[fwdsize + OLSR_HEADERSIZE], data, size);
-  fwdsize += size;
+  memcpy(&netbufs[ifp->if_nr]->buff[netbufs[ifp->if_nr]->pending + OLSR_HEADERSIZE], data, size);
+  netbufs[ifp->if_nr]->pending += size;
 
-  return 1;
+  return size;
+}
+
+
+inline int
+net_outbuffer_bytes_left(struct interface *ifp)
+{
+
+  if(!netbufs[ifp->if_nr])
+    return -1;
+
+  return (netbufs[ifp->if_nr]->maxsize - netbufs[ifp->if_nr]->pending);
 }
 
 
+
+
 /**
  *Sends a packet on a given interface.
  *
@@ -154,21 +204,26 @@ net_output(struct interface *ifp)
   struct sockaddr_in6 dst6;
   struct ptf *tmp_ptf_list;
   int i, x;
+  union olsr_packet *outmsg;
 
   sin = NULL;
   sin6 = NULL;
 
-  if(outputsize <= 0)
+  if(!netbufs[ifp->if_nr])
     return -1;
 
-  outputsize += OLSR_HEADERSIZE;
+  if(!netbufs[ifp->if_nr]->pending)
+    return 0;
+
+  netbufs[ifp->if_nr]->pending += OLSR_HEADERSIZE;
+
+  outmsg = (union olsr_packet *)netbufs[ifp->if_nr]->buff;
   /* Add the Packet seqno */
   outmsg->v4.olsr_seqno = htons(ifp->olsr_seqnum++);
   /* Set the packetlength */
-#warning 0.4.8 net_output now sets packetsize itself
-  outmsg->v4.olsr_packlen = htons(outputsize);
+  outmsg->v4.olsr_packlen = htons(netbufs[ifp->if_nr]->pending);
 
-  if(ipversion == AF_INET)
+  if(olsr_cnf->ip_version == AF_INET)
     {
       /* IP version 4 */
       sin = (struct sockaddr_in *)&ifp->int_broadaddr;
@@ -177,10 +232,6 @@ net_output(struct interface *ifp)
       dst = *sin;
       sin = &dst;
 
-      /* Set user defined broadcastaddr */
-      if(bcast_set)
-       memcpy(&dst.sin_addr.s_addr, &bcastaddr.sin_addr, sizeof(olsr_u32_t));
-
       if (sin->sin_port == 0)
        sin->sin_port = olsr_udp_port;
     }
@@ -193,52 +244,13 @@ net_output(struct interface *ifp)
       sin6 = &dst6;
     }
 
-  /*
-   *if the '-disp- option was given
-   *we print her decimal contetnt of the packets
-   */
-  /*
-  if(disp_pack_out)
-    {
-      switch(out_buffer[4])
-       {
-       case(HELLO_MESSAGE):printf("\n\tHELLO ");break;
-       case(TC_MESSAGE):printf("\n\tTC ");break;
-       case(MID_MESSAGE):printf("\n\tMID ");break;
-       case(HNA_MESSAGE):printf("\n\tHNA ");break;
-       }
-      if(ipversion == AF_INET)
-       printf("to %s size: %d\n\t", ip_to_string(&sin->sin_addr.s_addr), outputsize);
-      else
-       printf("to %s size: %d\n\t", ip6_to_string(&sin6->sin6_addr), outputsize);
-
-      x = 0;
-
-      for(i = 0; i < outputsize;i++)
-       {
-         if(x == 4)
-           {
-             x = 0;
-             printf("\n\t");
-           }
-         x++;
-         if(ipversion == AF_INET)
-           printf(" %3i", (u_char) out_buffer[i]);
-         else
-           printf(" %2x", (u_char) out_buffer[i]);
-       }
-      
-      printf("\n");
-    }
-  */
-
   /*
    *Call possible packet transform functions registered by plugins  
    */
   tmp_ptf_list = ptf_list;
   while(tmp_ptf_list != NULL)
     {
-      tmp_ptf_list->function(out_buffer, &outputsize);
+      tmp_ptf_list->function(netbufs[ifp->if_nr]->buff, &netbufs[ifp->if_nr]->pending);
       tmp_ptf_list = tmp_ptf_list->next;
     }
 
@@ -248,22 +260,22 @@ net_output(struct interface *ifp)
    */
   if(disp_pack_out)
     {
-      switch(out_buffer[4])
+      switch(netbufs[ifp->if_nr]->buff[4])
        {
        case(HELLO_MESSAGE):printf("\n\tHELLO ");break;
        case(TC_MESSAGE):printf("\n\tTC ");break;
        case(MID_MESSAGE):printf("\n\tMID ");break;
        case(HNA_MESSAGE):printf("\n\tHNA ");break;
-       default:printf("\n\tTYPE: %d ", out_buffer[4]); break;
+       default:printf("\n\tTYPE: %d ", netbufs[ifp->if_nr]->buff[4]); break;
        }
-      if(ipversion == AF_INET)
-       printf("to %s size: %d\n\t", ip_to_string((olsr_u32_t *)&sin->sin_addr.s_addr), outputsize);
+      if(olsr_cnf->ip_version == AF_INET)
+       printf("to %s size: %d\n\t", ip_to_string((olsr_u32_t *)&sin->sin_addr.s_addr), netbufs[ifp->if_nr]->pending);
       else
-       printf("to %s size: %d\n\t", ip6_to_string(&sin6->sin6_addr), outputsize);
+       printf("to %s size: %d\n\t", ip6_to_string(&sin6->sin6_addr), netbufs[ifp->if_nr]->pending);
 
       x = 0;
 
-      for(i = 0; i < outputsize;i++)
+      for(i = 0; i < netbufs[ifp->if_nr]->pending;i++)
        {
          if(x == 4)
            {
@@ -271,10 +283,10 @@ net_output(struct interface *ifp)
              printf("\n\t");
            }
          x++;
-         if(ipversion == AF_INET)
-           printf(" %3i", (u_char) out_buffer[i]);
+         if(olsr_cnf->ip_version == AF_INET)
+           printf(" %3i", (u_char) netbufs[ifp->if_nr]->buff[i]);
          else
-           printf(" %2x", (u_char) out_buffer[i]);
+           printf(" %2x", (u_char) netbufs[ifp->if_nr]->buff[i]);
        }
       
       printf("\n");
@@ -285,33 +297,45 @@ net_output(struct interface *ifp)
    *used when building packets.
    */
   
-  if(ipversion == AF_INET)
+  if(olsr_cnf->ip_version == AF_INET)
     {
       /* IP version 4 */
-      if(sendto(ifp->olsr_socket, out_buffer, outputsize, MSG_DONTROUTE, (struct sockaddr *)sin, sizeof (*sin)) < 0)
+      if(sendto(ifp->olsr_socket, 
+               netbufs[ifp->if_nr]->buff, 
+               netbufs[ifp->if_nr]->pending, 
+               MSG_DONTROUTE, 
+               (struct sockaddr *)sin, 
+               sizeof (*sin)) 
+        < 0)
        {
          perror("sendto(v4)");
          olsr_syslog(OLSR_LOG_ERR, "OLSR: sendto IPv4 %m");
-         outputsize = 0;
+         netbufs[ifp->if_nr]->pending = 0;
          return -1;
        }
     }
   else
     {
       /* IP version 6 */
-      if(sendto(ifp->olsr_socket, out_buffer, outputsize, MSG_DONTROUTE, (struct sockaddr *)sin6, sizeof (*sin6)) < 0)
+      if(sendto(ifp->olsr_socket, 
+               netbufs[ifp->if_nr]->buff,
+               netbufs[ifp->if_nr]->pending, 
+               MSG_DONTROUTE, 
+               (struct sockaddr *)sin6, 
+               sizeof (*sin6)) 
+        < 0)
        {
          perror("sendto(v6)");
          olsr_syslog(OLSR_LOG_ERR, "OLSR: sendto IPv6 %m");
          fprintf(stderr, "Socket: %d interface: %d\n", ifp->olsr_socket, ifp->if_nr);
          fprintf(stderr, "To: %s (size: %d)\n", ip6_to_string(&sin6->sin6_addr), sizeof(*sin6));
-         fprintf(stderr, "Outputsize: %d\n", outputsize);
-         outputsize = 0;
+         fprintf(stderr, "Outputsize: %d\n", netbufs[ifp->if_nr]->pending);
+         netbufs[ifp->if_nr]->pending = 0;
          return -1;
        }
     }
   
-  outputsize = 0;
+  netbufs[ifp->if_nr]->pending = 0;
 
   return 1;
 }
@@ -321,130 +345,6 @@ net_output(struct interface *ifp)
 
 
 
-/**
- *Forward a message on all interfaces
- *
- *@return negative on error
- */
-int
-net_forward()
-{
-  struct sockaddr_in *sin;  
-  struct sockaddr_in dst;
-  struct sockaddr_in6 *sin6;  
-  struct sockaddr_in6 dst6;
-  struct interface *ifn;
-  struct ptf *tmp_ptf_list;
-  int i, x;
-  
-  sin = NULL;
-  sin6 = NULL;
-  
-  for (ifn = ifnet; ifn; ifn = ifn->int_next) 
-    {
-      
-      fwdsize += OLSR_HEADERSIZE;      
-      /* Add the Packet seqno */
-      fwdmsg->v4.olsr_seqno = htons(ifn->olsr_seqnum++);
-      /* Set the packetlength */
-#warning 0.4.8 net_forward now sets packetsize itself
-      fwdmsg->v4.olsr_packlen = htons(fwdsize);
-
-      if(ipversion == AF_INET)
-       {
-         /* IP version 4 */
-         sin = (struct sockaddr_in *)&ifn->int_broadaddr;
-         
-         /* Copy sin */
-         dst = *sin;
-         sin = &dst;
-
-         /* Set user defined broadcastaddr */
-         if(bcast_set)
-           memcpy(&dst.sin_addr.s_addr, &bcastaddr.sin_addr, sizeof(olsr_u32_t));
-         
-         if (sin->sin_port == 0)
-           sin->sin_port = olsr_udp_port;
-       }
-      else
-       {
-         /* IP version 6 */
-         sin6 = (struct sockaddr_in6 *)&ifn->int6_multaddr;
-         /* Copy sin */
-         dst6 = *sin6;
-         sin6 = &dst6;
-       }
-
-      /*
-       *if the '-disp- option was given
-       *we print her decimal contetnt of the packets
-       */
-      if(disp_pack_out)
-       {
-         if(ipversion == AF_INET)
-           printf("FORWARDING to %s size: %d\n\t", ip_to_string((olsr_u32_t *)&sin->sin_addr.s_addr), fwdsize);
-         else
-           printf("FORWARDING to %s size: %d\n\t", ip6_to_string(&sin6->sin6_addr), fwdsize);
-         
-         x = 0;
-         
-         for(i = 0; i < fwdsize;i++)
-           {
-             if(x == 4)
-               {
-                 x = 0;
-                 printf("\n\t");
-               }
-             x++;
-             if(ipversion == AF_INET)
-               printf(" %3i", (u_char) fwd_buffer[i]);
-             else
-               printf(" %2x", (u_char) fwd_buffer[i]);
-           }
-         
-         printf("\n");
-       }
-  
-      
-      /*
-       *Call possible packet transform functions registered by plugins  
-       */
-      tmp_ptf_list = ptf_list;
-      while(tmp_ptf_list != NULL)
-       {
-         tmp_ptf_list->function(fwd_buffer, &fwdsize);
-         tmp_ptf_list = tmp_ptf_list->next;
-       }
-
-
-      if(ipversion == AF_INET)
-       {
-         /* IP version 4 */
-         if(sendto(ifn->olsr_socket, fwd_buffer, fwdsize, MSG_DONTROUTE, (struct sockaddr *)sin, sizeof (*sin)) < 0)
-           {
-             perror("sendto(v4)");
-             olsr_syslog(OLSR_LOG_ERR, "OLSR: forward sendto IPv4 %m");
-             return -1;
-           }
-       }
-      else
-       {
-         /* IP version 6 */
-         if(sendto(ifn->olsr_socket, fwd_buffer, fwdsize, MSG_DONTROUTE, (struct sockaddr *)sin6, sizeof (*sin6)) < 0)
-           {
-             perror("sendto(v6)");
-             olsr_syslog(OLSR_LOG_ERR, "OLSR: forward sendto IPv6 %m");
-             fprintf(stderr, "Socket: %d interface: %d\n", ifn->olsr_socket, ifn->if_nr);
-             fprintf(stderr, "To: %s (size: %d)\n", ip6_to_string(&sin6->sin6_addr), sizeof(*sin6));
-             fprintf(stderr, "Outputsize: %d\n", fwdsize);
-             return -1;
-           }
-       }
-
-    }      
-  return 1;
-}
-
 /*
  * Add a packet transform function
  */
@@ -523,7 +423,8 @@ join_mcast(struct interface *ifs, int sock)
       return -1;
     }
 
-
+  /* Old libc fix */
+#ifdef IPV6_JOIN_GROUP
   /* Join reciever group */
   if(setsockopt(sock, 
                IPPROTO_IPV6, 
@@ -531,6 +432,15 @@ join_mcast(struct interface *ifs, int sock)
                (char *)&mcastreq, 
                sizeof(struct ipv6_mreq)) 
      < 0)
+#else
+  /* Join reciever group */
+  if(setsockopt(sock, 
+               IPPROTO_IPV6, 
+               IPV6_ADD_MEMBERSHIP, 
+               (char *)&mcastreq, 
+               sizeof(struct ipv6_mreq)) 
+     < 0)
+#endif 
     {
       perror("Join multicast send");
       return -1;
@@ -691,7 +601,7 @@ olsr_ip_to_string(union olsr_ip_addr *addr)
   char *ret;
   struct in_addr in;
   
-  if(ipversion == AF_INET)
+  if(olsr_cnf->ip_version == AF_INET)
     {
       in.s_addr=addr->v4;
       ret = inet_ntoa(in);