]> oss.titaniummirror.com Git - tinyos-2.x.git/commitdiff
missing
authorsdhsdh <sdhsdh>
Tue, 20 Jan 2009 00:32:00 +0000 (00:32 +0000)
committersdhsdh <sdhsdh>
Tue, 20 Jan 2009 00:32:00 +0000 (00:32 +0000)
support/sdk/c/blip/driver/radvd-1.0/device.c [new file with mode: 0644]

diff --git a/support/sdk/c/blip/driver/radvd-1.0/device.c b/support/sdk/c/blip/driver/radvd-1.0/device.c
new file mode 100644 (file)
index 0000000..f160c15
--- /dev/null
@@ -0,0 +1,298 @@
+/*
+ *   $Id$
+ *
+ *   Authors:
+ *    Lars Fenneberg           <lf@elemental.net>       
+ *
+ *   This software is Copyright 1996,1997 by the above mentioned author(s), 
+ *   All Rights Reserved.
+ *
+ *   The license which is distributed with this software in the file COPYRIGHT
+ *   applies to this software. If your distribution is missing this file, you
+ *   may request it from <pekkas@netcore.fi>.
+ *
+ */
+
+#include <config.h>
+#include <includes.h>
+#include <radvd.h>
+#include <defaults.h>
+#include <pathnames.h>         /* for PATH_PROC_NET_IF_INET6 */
+
+#ifndef IPV6_ADDR_LINKLOCAL
+#define IPV6_ADDR_LINKLOCAL   0x0020U
+#endif
+
+/*
+ * this function gets the hardware type and address of an interface,
+ * determines the link layer token length and checks it against
+ * the defined prefixes
+ */
+int
+setup_deviceinfo(int sock, struct Interface *iface)
+{
+       struct ifreq    ifr;
+       struct AdvPrefix *prefix;
+       char zero[sizeof(iface->if_addr)];
+       
+       strncpy(ifr.ifr_name, iface->Name, IFNAMSIZ-1);
+       ifr.ifr_name[IFNAMSIZ-1] = '\0';
+
+       if (ioctl(sock, SIOCGIFMTU, &ifr) < 0) {
+               flog(LOG_ERR, "ioctl(SIOCGIFMTU) failed for %s: %s",
+                       iface->Name, strerror(errno));
+               return (-1);
+       }
+
+       dlog(LOG_DEBUG, 3, "mtu for %s is %d", iface->Name, ifr.ifr_mtu);
+       iface->if_maxmtu = ifr.ifr_mtu;
+
+       if (ioctl(sock, SIOCGIFHWADDR, &ifr) < 0)
+       {
+               flog(LOG_ERR, "ioctl(SIOCGIFHWADDR) failed for %s: %s",
+                       iface->Name, strerror(errno));
+               return (-1);
+       }
+
+       dlog(LOG_DEBUG, 3, "hardware type for %s is %d", iface->Name,
+               ifr.ifr_hwaddr.sa_family); 
+
+       switch(ifr.ifr_hwaddr.sa_family)
+        {
+       case ARPHRD_ETHER:
+               iface->if_hwaddr_len = 48;
+               iface->if_prefix_len = 64;
+               break;
+#ifdef ARPHRD_FDDI
+       case ARPHRD_FDDI:
+               iface->if_hwaddr_len = 48;
+               iface->if_prefix_len = 64;
+               break;
+#endif /* ARPHDR_FDDI */
+#ifdef ARPHRD_ARCNET
+       case ARPHRD_ARCNET:
+               iface->if_hwaddr_len = 8;
+               iface->if_prefix_len = -1;
+               iface->if_maxmtu = -1;
+               break;
+#endif /* ARPHDR_ARCNET */
+       default:
+               iface->if_hwaddr_len = -1;
+               iface->if_prefix_len = -1;
+               iface->if_maxmtu = -1;
+               break;
+       }
+
+       dlog(LOG_DEBUG, 3, "link layer token length for %s is %d", iface->Name,
+               iface->if_hwaddr_len);
+
+       dlog(LOG_DEBUG, 3, "prefix length for %s is %d", iface->Name,
+               iface->if_prefix_len);
+
+       if (iface->if_hwaddr_len != -1) {
+               unsigned int if_hwaddr_len_bytes = (iface->if_hwaddr_len + 7) >> 3;
+               
+               if (if_hwaddr_len_bytes > sizeof(iface->if_hwaddr)) {
+                       flog(LOG_ERR, "address length %d too big for %s", if_hwaddr_len_bytes, iface->Name);
+                       return(-2);
+               }
+               memcpy(iface->if_hwaddr, ifr.ifr_hwaddr.sa_data, if_hwaddr_len_bytes);
+
+               memset(zero, 0, sizeof(zero));
+               if (!memcmp(iface->if_hwaddr, zero, if_hwaddr_len_bytes))
+                       flog(LOG_WARNING, "WARNING, MAC address on %s is all zero!",
+                               iface->Name);
+       }
+
+       prefix = iface->AdvPrefixList;
+       while (prefix)
+       {
+               if ((iface->if_prefix_len != -1) &&
+                  (iface->if_prefix_len != prefix->PrefixLen))
+               {
+                       flog(LOG_WARNING, "prefix length should be %d for %s",
+                               iface->if_prefix_len, iface->Name);
+               }
+                       
+               prefix = prefix->next;
+       }
+                
+       return (0);
+}
+
+/*
+ * this function extracts the link local address and interface index
+ * from PATH_PROC_NET_IF_INET6.  Note: 'sock' unused in Linux.
+ */
+int setup_linklocal_addr(int sock, struct Interface *iface)
+{
+       FILE *fp;
+       char str_addr[40];
+       unsigned int plen, scope, dad_status, if_idx;
+       char devname[IFNAMSIZ];
+
+       if ((fp = fopen(PATH_PROC_NET_IF_INET6, "r")) == NULL)
+       {
+               flog(LOG_ERR, "can't open %s: %s", PATH_PROC_NET_IF_INET6,
+                       strerror(errno));
+               return (-1);    
+       }
+       
+       while (fscanf(fp, "%32s %x %02x %02x %02x %15s\n",
+                     str_addr, &if_idx, &plen, &scope, &dad_status,
+                     devname) != EOF)
+       {
+               if (scope == IPV6_ADDR_LINKLOCAL &&
+                   strcmp(devname, iface->Name) == 0)
+               {
+                       struct in6_addr addr;
+                       unsigned int ap;
+                       int i;
+                       
+                       for (i=0; i<16; i++)
+                       {
+                               sscanf(str_addr + i * 2, "%02x", &ap);
+                               addr.s6_addr[i] = (unsigned char)ap;
+                       }
+                       memcpy(&iface->if_addr, &addr, sizeof(iface->if_addr));
+
+                       iface->if_index = if_idx;
+                       fclose(fp);
+                       return 0;
+               }
+       }
+
+       flog(LOG_ERR, "no linklocal address configured for %s", iface->Name);
+       fclose(fp);
+       return (-1);
+}
+
+int setup_allrouters_membership(int sock, struct Interface *iface)
+{
+       struct ipv6_mreq mreq;                  
+       
+       memset(&mreq, 0, sizeof(mreq));                  
+       mreq.ipv6mr_interface = iface->if_index;
+       
+       /* ipv6-allrouters: ff02::2 */
+       mreq.ipv6mr_multiaddr.s6_addr32[0] = htonl(0xFF020000);                                          
+       mreq.ipv6mr_multiaddr.s6_addr32[3] = htonl(0x2);     
+
+       if (setsockopt(sock, SOL_IPV6, IPV6_ADD_MEMBERSHIP, &mreq, sizeof(mreq)) < 0)
+       {
+               /* linux-2.6.12-bk4 returns error with HUP signal but keep listening */
+               if (errno != EADDRINUSE)
+               {
+                       flog(LOG_ERR, "can't join ipv6-allrouters on %s", iface->Name);
+                       return (-1);
+               }
+       }
+
+       return (0);
+}
+
+int check_allrouters_membership(int sock, struct Interface *iface)
+{
+       #define ALL_ROUTERS_MCAST "ff020000000000000000000000000002"
+       
+       FILE *fp;
+       unsigned int if_idx, allrouters_ok=0;
+       char addr[32+1];
+       int ret=0;
+
+       if ((fp = fopen(PATH_PROC_NET_IGMP6, "r")) == NULL)
+       {
+               flog(LOG_ERR, "can't open %s: %s", PATH_PROC_NET_IGMP6,
+                       strerror(errno));
+               return (-1);    
+       }
+       
+       while ( (ret=fscanf(fp, "%u %*s %32[0-9A-Fa-f] %*x %*x %*x\n", &if_idx, addr)) != EOF) {
+               if (ret == 2) {
+                       if (iface->if_index == if_idx) {
+                               if (strncmp(addr, ALL_ROUTERS_MCAST, sizeof(addr)) == 0)
+                                       allrouters_ok = 1;
+                       }
+               }
+       }
+
+       fclose(fp);
+
+       if (!allrouters_ok) {
+               flog(LOG_WARNING, "resetting ipv6-allrouters membership on %s", iface->Name);
+               setup_allrouters_membership(sock, iface);
+       }       
+
+       return(0);
+}              
+
+static int
+set_interface_var(const char *iface,
+                 const char *var, const char *name,
+                 uint32_t val)
+{
+       FILE *fp;
+       char spath[64+IFNAMSIZ];        /* XXX: magic constant */
+       snprintf(spath, sizeof(spath), var, iface);
+
+       fp = fopen(spath, "w");
+       if (!fp) {
+               if (name)
+                       flog(LOG_ERR, "failed to set %s (%u) for %s",
+                            name, val, iface);
+               return -1;
+       }
+       fprintf(fp, "%u", val);
+       fclose(fp);
+
+       return 0;
+}
+
+int
+set_interface_linkmtu(const char *iface, uint32_t mtu)
+{
+       return set_interface_var(iface,
+                                PROC_SYS_IP6_LINKMTU, "LinkMTU",
+                                mtu);
+}
+
+int
+set_interface_curhlim(const char *iface, uint8_t hlim)
+{
+       return set_interface_var(iface,
+                                PROC_SYS_IP6_CURHLIM, "CurHopLimit",
+                                hlim);
+}
+
+int
+set_interface_reachtime(const char *iface, uint32_t rtime)
+{
+       int ret;
+       ret = set_interface_var(iface,
+                               PROC_SYS_IP6_BASEREACHTIME_MS,
+                               NULL,
+                               rtime);
+       if (ret)
+               ret = set_interface_var(iface,
+                                       PROC_SYS_IP6_BASEREACHTIME,
+                                       "BaseReachableTimer",
+                                       rtime / 1000);
+       return ret;
+}
+
+int
+set_interface_retranstimer(const char *iface, uint32_t rettimer)
+{
+       int ret;
+       ret = set_interface_var(iface,
+                               PROC_SYS_IP6_RETRANSTIMER_MS,
+                               NULL,
+                               rettimer);
+       if (ret)
+               ret = set_interface_var(iface,
+                                       PROC_SYS_IP6_RETRANSTIMER,
+                                       "RetransTimer",
+                                       rettimer / 1000);
+       return ret;
+}
+