Removed various signed comparision warnings
[olsrd.git] / src / linux / net.c
index 4b204d3..710ba32 100644 (file)
@@ -36,7 +36,7 @@
  * to the project. For more information see the website or contact
  * the copyright holders.
  *
- * $Id: net.c,v 1.14 2005/02/13 11:00:51 kattemat Exp $
+ * $Id: net.c,v 1.24 2005/03/04 21:30:16 kattemat Exp $
  */
 
 
 #include "../parser.h"
 
 
-extern struct olsr_netbuf *netbufs[];
-static char inbuf[MAXMESSAGESIZE+1];
-
+/*
+ *Wireless definitions for ioctl calls
+ *(from linux/wireless.h)
+ */
+#define SIOCGIWNAME    0x8B01          /* get name == wireless protocol */
+#define SIOCGIWRATE    0x8B21          /* get default bit rate (bps) */
 
 /**
  *Bind a socket to a device
@@ -69,7 +72,7 @@ bind_socket_to_device(int sock, char *dev_name)
   /*
    *Bind to device using the SO_BINDTODEVICE flag
    */
-  olsr_printf(3, "Binding socket %d to device %s\n", sock, dev_name);
+  OLSR_PRINTF(3, "Binding socket %d to device %s\n", sock, dev_name)
   return setsockopt(sock, SOL_SOCKET, SO_BINDTODEVICE, dev_name, strlen(dev_name)+1);
 
 }
@@ -127,7 +130,7 @@ enable_ip_forwarding(int version)
       fclose(proc_fwd);
       if(orig_fwd_state == '1')
        {
-         olsr_printf(3, "\nIP forwarding is enabled on this system\n");
+         OLSR_PRINTF(3, "\nIP forwarding is enabled on this system\n")
        }
       else
        {
@@ -264,7 +267,7 @@ restore_settings(int version)
   char procfile[FILENAME_MAX];
   struct interface *ifs;
 
-  olsr_printf(1, "Restoring network state\n");
+  OLSR_PRINTF(1, "Restoring network state\n")
 
   /* Restore IP forwarding to "off" */
   if(orig_fwd_state == '0')
@@ -448,6 +451,13 @@ getsocket6(struct sockaddr_in6 *sin, int bufspace, char *int_name)
       return (-1);
     }
 
+#ifdef IPV6_V6ONLY
+  if (setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY, &on, sizeof(on)) < 0) 
+    {
+      perror("setsockopt(IPV6_V6ONLY)");
+      syslog(LOG_ERR, "setsockopt(IPV6_V6ONLY): %m");
+    }
+#endif
 
 
   //#ifdef SO_BROADCAST
@@ -523,6 +533,75 @@ getsocket6(struct sockaddr_in6 *sin, int bufspace, char *int_name)
 }
 
 
+int
+join_mcast(struct interface *ifs, int sock)
+{
+  /* See linux/in6.h */
+
+  struct ipv6_mreq mcastreq;
+
+  COPY_IP(&mcastreq.ipv6mr_multiaddr, &ifs->int6_multaddr.sin6_addr);
+  mcastreq.ipv6mr_interface = ifs->if_index;
+
+#if !defined __FreeBSD__ && !defined __MacOSX__ && !defined __NetBSD__
+  OLSR_PRINTF(3, "Interface %s joining multicast %s...",       ifs->int_name, olsr_ip_to_string((union olsr_ip_addr *)&ifs->int6_multaddr.sin6_addr))
+  /* Send multicast */
+  if(setsockopt(sock, 
+               IPPROTO_IPV6, 
+               IPV6_ADD_MEMBERSHIP, 
+               (char *)&mcastreq, 
+               sizeof(struct ipv6_mreq)) 
+     < 0)
+    {
+      perror("Join multicast");
+      return -1;
+    }
+#else
+#warning implement IPV6_ADD_MEMBERSHIP
+#endif
+
+  /* Old libc fix */
+#ifdef IPV6_JOIN_GROUP
+  /* Join reciever group */
+  if(setsockopt(sock, 
+               IPPROTO_IPV6, 
+               IPV6_JOIN_GROUP, 
+               (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;
+    }
+
+  
+  if(setsockopt(sock, 
+               IPPROTO_IPV6, 
+               IPV6_MULTICAST_IF, 
+               (char *)&mcastreq.ipv6mr_interface, 
+               sizeof(mcastreq.ipv6mr_interface)) 
+     < 0)
+    {
+      perror("Set multicast if");
+      return -1;
+    }
+
+
+  OLSR_PRINTF(3, "OK\n")
+  return 0;
+}
+
+
+
 /*
  *From net-tools lib/interface.c
  *
@@ -549,11 +628,11 @@ get_ipv6_address(char *ifname, struct sockaddr_in6 *saddr6, int scope_in)
              sprintf(addr6, "%s:%s:%s:%s:%s:%s:%s:%s",
                      addr6p[0], addr6p[1], addr6p[2], addr6p[3],
                      addr6p[4], addr6p[5], addr6p[6], addr6p[7]);
-             olsr_printf(5, "\tinet6 addr: %s\n", addr6);
-             olsr_printf(5, "\tScope: %d", scope);
+             OLSR_PRINTF(5, "\tinet6 addr: %s\n", addr6)
+             OLSR_PRINTF(5, "\tScope: %d", scope)
              if(scope == scope_in)
                {
-                 olsr_printf(4, "IPv6 addr:\n");
+                 OLSR_PRINTF(4, "IPv6 addr:\n")
                  inet_pton(AF_INET6,addr6,&tmp_sockaddr6);
                  memcpy(&saddr6->sin6_addr, &tmp_sockaddr6, sizeof(struct in6_addr));    
                  fclose(f);
@@ -567,239 +646,221 @@ get_ipv6_address(char *ifname, struct sockaddr_in6 *saddr6, int scope_in)
   return 0;
 }
 
+
 /**
- *Sends a packet on a given interface.
- *
- *@param ifp the interface to send on.
- *
- *@return negative on error
+ * Wrapper for sendto(2)
  */
-int
-net_output(struct interface *ifp)
-{
-  struct sockaddr_in *sin;  
-  struct sockaddr_in dst;
-  struct sockaddr_in6 *sin6;  
-  struct sockaddr_in6 dst6;
-  struct ptf *tmp_ptf_list;
-  int i, x;
-  union olsr_packet *outmsg;
-
-  sin = NULL;
-  sin6 = NULL;
-
-  if(!netbufs[ifp->if_nr])
-    return -1;
 
-  if(!netbufs[ifp->if_nr]->pending)
-    return 0;
+ssize_t
+olsr_sendto(int s, 
+           const void *buf, 
+           size_t len, 
+           int flags, 
+           const struct sockaddr *to, 
+           socklen_t tolen)
+{
+  return sendto(s, buf, len, flags, to, tolen);
+}
 
-  netbufs[ifp->if_nr]->pending += OLSR_HEADERSIZE;
+/**
+ * Wrapper for recvfrom(2)
+ */
 
-  outmsg = (union olsr_packet *)netbufs[ifp->if_nr]->buff;
-  /* Add the Packet seqno */
-  outmsg->v4.olsr_seqno = htons(ifp->olsr_seqnum++);
-  /* Set the packetlength */
-  outmsg->v4.olsr_packlen = htons(netbufs[ifp->if_nr]->pending);
+ssize_t  
+olsr_recvfrom(int  s, 
+             void *buf, 
+             size_t len, 
+             int flags, 
+             struct sockaddr *from,
+             socklen_t *fromlen)
+{
+  return recvfrom(s, 
+                 buf, 
+                 len, 
+                 0, 
+                 from, 
+                 fromlen);
+}
 
-  if(olsr_cnf->ip_version == AF_INET)
-    {
-      /* IP version 4 */
-      sin = (struct sockaddr_in *)&ifp->int_broadaddr;
+/**
+ * Wrapper for select(2)
+ */
 
-      /* Copy sin */
-      dst = *sin;
-      sin = &dst;
+int
+olsr_select(int nfds,
+            fd_set *readfds,
+            fd_set *writefds,
+            fd_set *exceptfds,
+            struct timeval *timeout)
+{
+  return select(nfds,
+                readfds,
+                writefds,
+                exceptfds,
+                timeout);
+}
 
-      if (sin->sin_port == 0)
-       sin->sin_port = olsr_udp_port;
-    }
-  else
-    {
-      /* IP version 6 */
-      sin6 = (struct sockaddr_in6 *)&ifp->int6_multaddr;
-      /* Copy sin */
-      dst6 = *sin6;
-      sin6 = &dst6;
-    }
+int
+check_wireless_interface(char *ifname)
+{
+  struct ifreq ifr;
 
-  /*
-   *Call possible packet transform functions registered by plugins  
-   */
-  tmp_ptf_list = ptf_list;
-  while(tmp_ptf_list != NULL)
-    {
-      tmp_ptf_list->function(netbufs[ifp->if_nr]->buff, &netbufs[ifp->if_nr]->pending);
-      tmp_ptf_list = tmp_ptf_list->next;
-    }
+  memset(&ifr, 0, sizeof(ifr));
+  strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
 
-  /*
-   *if the -dispout option was given
-   *we print the contetnt of the packets
-   */
-  if(disp_pack_out)
-    {
-      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 ", netbufs[ifp->if_nr]->buff[4]); break;
-       }
-      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), netbufs[ifp->if_nr]->pending);
+  return (ioctl(ioctl_s, SIOCGIWNAME, &ifr) >= 0) ? 1 : 0;
+}
 
-      x = 0;
+#if 0
+
+#include <linux/sockios.h>
+#include <linux/types.h>
+
+/* This data structure is used for all the MII ioctl's */
+struct mii_data {
+    __u16      phy_id;
+    __u16      reg_num;
+    __u16      val_in;
+    __u16      val_out;
+};
+
+
+/* Basic Mode Control Register */
+#define MII_BMCR               0x00
+#define  MII_BMCR_RESET                0x8000
+#define  MII_BMCR_LOOPBACK     0x4000
+#define  MII_BMCR_100MBIT      0x2000
+#define  MII_BMCR_AN_ENA       0x1000
+#define  MII_BMCR_ISOLATE      0x0400
+#define  MII_BMCR_RESTART      0x0200
+#define  MII_BMCR_DUPLEX       0x0100
+#define  MII_BMCR_COLTEST      0x0080
+
+/* Basic Mode Status Register */
+#define MII_BMSR               0x01
+#define  MII_BMSR_CAP_MASK     0xf800
+#define  MII_BMSR_100BASET4    0x8000
+#define  MII_BMSR_100BASETX_FD 0x4000
+#define  MII_BMSR_100BASETX_HD 0x2000
+#define  MII_BMSR_10BASET_FD   0x1000
+#define  MII_BMSR_10BASET_HD   0x0800
+#define  MII_BMSR_NO_PREAMBLE  0x0040
+#define  MII_BMSR_AN_COMPLETE  0x0020
+#define  MII_BMSR_REMOTE_FAULT 0x0010
+#define  MII_BMSR_AN_ABLE      0x0008
+#define  MII_BMSR_LINK_VALID   0x0004
+#define  MII_BMSR_JABBER       0x0002
+#define  MII_BMSR_EXT_CAP      0x0001
 
-      for(i = 0; i < netbufs[ifp->if_nr]->pending;i++)
-       {
-         if(x == 4)
-           {
-             x = 0;
-             printf("\n\t");
-           }
-         x++;
-         if(olsr_cnf->ip_version == AF_INET)
-           printf(" %3i", (u_char) netbufs[ifp->if_nr]->buff[i]);
-         else
-           printf(" %2x", (u_char) netbufs[ifp->if_nr]->buff[i]);
-       }
+int
+calculate_if_metric(char *ifname)
+{
+  if(check_wireless_interface(ifname))
+    {
+      struct ifreq ifr;
+      strncpy(ifr.ifr_name, ifname, IFNAMSIZ);
       
-      printf("\n");
-    }
-  
-  if(olsr_cnf->ip_version == AF_INET)
-    {
-      /* IP version 4 */
-      if(sendto(ifp->olsr_socket, 
-               netbufs[ifp->if_nr]->buff, 
-               netbufs[ifp->if_nr]->pending, 
-               MSG_DONTROUTE, 
-               (struct sockaddr *)sin, 
-               sizeof (*sin)) 
-        < 0)
+      /* Get bit rate */
+      if(ioctl(ioctl_s, SIOCGIWRATE, &ifr) < 0)
        {
-         perror("sendto(v4)");
-         olsr_syslog(OLSR_LOG_ERR, "OLSR: sendto IPv4 %m");
-         netbufs[ifp->if_nr]->pending = 0;
-         return -1;
+         OLSR_PRINTF(1, "Not able to find rate for WLAN interface %s\n", ifname)
+         return WEIGHT_WLAN_11MB;
        }
+      
+      OLSR_PRINTF(1, "Bitrate %d\n", ifr.ifr_ifru.ifru_ivalue)
+
+      //WEIGHT_WLAN_LOW,          /* <11Mb WLAN     */
+      //WEIGHT_WLAN_11MB,         /* 11Mb 802.11b   */
+      //WEIGHT_WLAN_54MB,         /* 54Mb 802.11g   */
+      return WEIGHT_WLAN_LOW;
     }
   else
     {
-      /* IP version 6 */
-      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), (int)sizeof(*sin6));
-         fprintf(stderr, "Outputsize: %d\n", netbufs[ifp->if_nr]->pending);
-         netbufs[ifp->if_nr]->pending = 0;
-         return -1;
-       }
-    }
-  
-  netbufs[ifp->if_nr]->pending = 0;
-
-  return 1;
-}
-
-/**
- *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;
-
+      /* Ethernet */
+      /* Mii wizardry */
+      struct ifreq ifr;
+      struct mii_data *mii = (struct mii_data *)&ifr.ifr_data;
+      int bmcr;
+      memset(&ifr, 0, sizeof(ifr));
+      strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
+
+      if (ioctl(ioctl_s, SIOCGMIIPHY, &ifr) < 0) {
+       if (errno != ENODEV)
+         OLSR_PRINTF(1, "SIOCGMIIPHY on '%s' failed: %s\n",
+                     ifr.ifr_name, strerror(errno))
+       return WEIGHT_ETHERNET_DEFAULT;
+      }
 
-  for (;;) 
-    {
-      fromlen = sizeof(struct sockaddr_storage);
+      mii->reg_num = MII_BMCR;
+      if (ioctl(ioctl_s, SIOCGMIIREG, &ifr) < 0) {
+       OLSR_PRINTF(1, "SIOCGMIIREG on %s failed: %s\n", ifr.ifr_name,
+                   strerror(errno))
+       return WEIGHT_ETHERNET_DEFAULT;
+      }
+      bmcr = mii->val_out;
 
-      cc = 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;
-       }
+      OLSR_PRINTF(1, "%s: ", ifr.ifr_name)
+      OLSR_PRINTF(1, "%s Mbit, %s duplex\n",
+                 (bmcr & MII_BMCR_100MBIT) ? "100" : "10",
+                 (bmcr & MII_BMCR_DUPLEX) ? "full" : "half")
+    
+      is_if_link_up(ifname);
 
-      if(olsr_cnf->ip_version == AF_INET)
-       {
-         /* IPv4 sender address */
-         COPY_IP(&from_addr, &((struct sockaddr_in *)&from)->sin_addr.s_addr);
-       }
+      if(mii->val_out & MII_BMCR_100MBIT)
+       return WEIGHT_ETHERNET_100MB;
       else
-       {
-         /* IPv6 sender address */
-         COPY_IP(&from_addr, &((struct sockaddr_in6 *)&from)->sin6_addr);
-       }
+       return WEIGHT_ETHERNET_10MB;
+      //WEIGHT_ETHERNET_1GB,      /* Ethernet 1Gb   */
 
-      /* 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_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 ;
-       }
+olsr_bool
+is_if_link_up(char *ifname)
+{
+  if(check_wireless_interface(ifname))
+    {
+      /* No link checking on wireless devices */
+      return OLSR_TRUE;
+    }
+  else
+    {
+      /* Mii wizardry */
+      struct ifreq ifr;
+      struct mii_data *mii = (struct mii_data *)&ifr.ifr_data;
+      int bmsr;
+      memset(&ifr, 0, sizeof(ifr));
+      strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
+
+      if (ioctl(ioctl_s, SIOCGMIIPHY, &ifr) < 0) {
+       if (errno != ENODEV)
+         OLSR_PRINTF(1, "SIOCGMIIPHY on '%s' failed: %s\n",
+                     ifr.ifr_name, strerror(errno))
+       return WEIGHT_ETHERNET_DEFAULT;
+      }
+      mii->reg_num = MII_BMSR;
+      if (ioctl(ioctl_s, SIOCGMIIREG, &ifr) < 0) {
+       OLSR_PRINTF(1, "SIOCGMIIREG on %s failed: %s\n", ifr.ifr_name,
+                   strerror(errno))
+       return WEIGHT_ETHERNET_DEFAULT;
+      }
+      bmsr = mii->val_out;
 
-      /*
-       * &from - sender
-       * &inbuf.olsr 
-       * cc - bytes read
-       */
-      parse_packet((struct olsr *)inbuf, cc, olsr_in_if, &from_addr);
+      OLSR_PRINTF(1, "%s: ", ifr.ifr_name)
+      OLSR_PRINTF(1, "%s\n", (bmsr & MII_BMSR_LINK_VALID) ? "link ok " : "no link ")
     
+      return (bmsr & MII_BMSR_LINK_VALID);
+
     }
 }
 
-
+#else
+int
+calculate_if_metric(char *ifname)
+{
+  return check_wireless_interface(ifname);
+}
+#endif
+