Removed various signed comparision warnings
[olsrd.git] / src / linux / net.c
index 28cac59..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.15 2005/02/14 16:55:37 kattemat Exp $
+ * $Id: net.c,v 1.24 2005/03/04 21:30:16 kattemat Exp $
  */
 
 
 #include "../net_os.h"
 #include "../parser.h"
 
+
+/*
+ *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
  *
@@ -64,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);
 
 }
@@ -122,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
        {
@@ -259,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')
@@ -443,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
@@ -518,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
  *
@@ -544,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);
@@ -597,3 +681,186 @@ olsr_recvfrom(int  s,
                  from, 
                  fromlen);
 }
+
+/**
+ * Wrapper for select(2)
+ */
+
+int
+olsr_select(int nfds,
+            fd_set *readfds,
+            fd_set *writefds,
+            fd_set *exceptfds,
+            struct timeval *timeout)
+{
+  return select(nfds,
+                readfds,
+                writefds,
+                exceptfds,
+                timeout);
+}
+
+int
+check_wireless_interface(char *ifname)
+{
+  struct ifreq ifr;
+
+  memset(&ifr, 0, sizeof(ifr));
+  strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
+
+  return (ioctl(ioctl_s, SIOCGIWNAME, &ifr) >= 0) ? 1 : 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
+
+int
+calculate_if_metric(char *ifname)
+{
+  if(check_wireless_interface(ifname))
+    {
+      struct ifreq ifr;
+      strncpy(ifr.ifr_name, ifname, IFNAMSIZ);
+      
+      /* Get bit rate */
+      if(ioctl(ioctl_s, SIOCGIWRATE, &ifr) < 0)
+       {
+         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
+    {
+      /* 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;
+      }
+
+      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;
+
+
+      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(mii->val_out & MII_BMCR_100MBIT)
+       return WEIGHT_ETHERNET_100MB;
+      else
+       return WEIGHT_ETHERNET_10MB;
+      //WEIGHT_ETHERNET_1GB,      /* Ethernet 1Gb   */
+
+    }
+}
+
+
+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;
+
+      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
+