Logo Search packages:      
Sourcecode: radvd version File versions  Download package

device-bsd44.c

/*
 *   $Id: device-bsd44.c,v 1.22 2006/10/08 19:25:29 psavola Exp $
 *
 *   Authors:
 *    Craig Metz        <cmetz@inner.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 */

static uint8_t ll_prefix[] = { 0xfe, 0x80 };

/*
 * 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 ifconf ifconf;
      struct ifreq ifr;
      unsigned int nlen;
      uint8_t *p, *end;
      struct AdvPrefix *prefix;
      char zero[sizeof(iface->if_addr)];

      /* just allocate 8192 bytes, should be more than enough.. */
      if (!(ifconf.ifc_buf = malloc(ifconf.ifc_len = (32 << 8))))
      {
            flog(LOG_CRIT, "malloc failed: %s", strerror(errno));
            goto ret;
      }

      if (ioctl(sock, SIOCGIFCONF, &ifconf) < 0)
      {
            flog(LOG_ERR, "ioctl(SIOCGIFCONF) failed: %s(%d)", strerror(errno), errno);
            goto ret;
      }

      memset(&ifr, 0, sizeof(ifr));
      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));
            goto ret;
      }     

      dlog(LOG_DEBUG, 3, "mtu for %s is %d", iface->Name, ifr.ifr_mtu);
      iface->if_maxmtu = ifr.ifr_mtu;

      p = (uint8_t *)ifconf.ifc_buf;
      end = p + ifconf.ifc_len;
      nlen = strlen(iface->Name);

      while(p < end)
      {
            p += IFNAMSIZ;
            
            if ((p + 2) >= end)
                  break;
                  
            if ((p + *p) >= end)
                  break;
                  
            if ((*(p + 1) == AF_LINK) &&
                (((struct sockaddr_dl *)p)->sdl_nlen == nlen) &&
                (!memcmp(iface->Name, ((struct sockaddr_dl *)p)->sdl_data, nlen)))
            {
            
                  if (((struct sockaddr_dl *)p)->sdl_alen > sizeof(iface->if_addr))
                  {
                        flog(LOG_ERR, "address length %d too big for",
                              ((struct sockaddr_dl *)p)->sdl_alen,
                              iface->Name);
                        goto ret;
                  }
            
                  memcpy(iface->if_hwaddr, LLADDR((struct sockaddr_dl *)p), ((struct sockaddr_dl *)p)->sdl_alen);
                  iface->if_hwaddr_len = ((struct sockaddr_dl *)p)->sdl_alen << 3;

                  switch(((struct sockaddr_dl *)p)->sdl_type) {
                        case IFT_ETHER:
                        case IFT_ISO88023:
                              iface->if_prefix_len = 64;
                              break;
                        case IFT_FDDI:
                              iface->if_prefix_len = 64;
                              break;
                        default:
                              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_prefix_len != -1) {
                        memset(zero, 0, ((struct sockaddr_dl *)p)->sdl_alen);
                        if (!memcmp(iface->if_hwaddr, zero, ((struct sockaddr_dl *)p)->sdl_alen))
                              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;
                  }
                  
                  free(ifconf.ifc_buf);
                  return 0;
            }
        
            p += *p;    
      }

ret:
      iface->if_maxmtu = -1;
      iface->if_hwaddr_len = -1;
      iface->if_prefix_len = -1;
      free(ifconf.ifc_buf);
      return -1;
}

int setup_linklocal_addr(int sock, struct Interface *iface)
{
      struct ifconf ifconf;
      unsigned int nlen;
      uint8_t *p, *end;
      int index = 0;

      /* just allocate 8192 bytes, should be more than enough.. */
      if (!(ifconf.ifc_buf = malloc(ifconf.ifc_len = (32 << 8))))
      {
            flog(LOG_CRIT, "malloc failed: %s", strerror(errno));
            goto ret;
      }

      if (ioctl(sock, SIOCGIFCONF, &ifconf) < 0)
      {
            flog(LOG_ERR, "ioctl(SIOCGIFCONF) failed: %s(%d)", strerror(errno), errno);
            goto ret;
      }

      p = (uint8_t *)ifconf.ifc_buf;
      end = p + ifconf.ifc_len;
      nlen = strlen(iface->Name);

      while(p < end)
      {
            p += IFNAMSIZ;
      
            if ((p + 2) >= end)
                  break;
                  
            if ((p + *p) >= end)
                  break;
                  
            if ((*(p + 1) == AF_LINK) &&
                (((struct sockaddr_dl *)p)->sdl_nlen == nlen) &&
                (!memcmp(iface->Name, ((struct sockaddr_dl *)p)->sdl_data, nlen)))
            {
                  index = ((struct sockaddr_dl *)p)->sdl_index;
            }
            
            if (index && (*(p + 1) == AF_INET6))
              if (!memcmp(&((struct sockaddr_in6 *)p)->sin6_addr, ll_prefix, sizeof(ll_prefix)))
              {
                  memcpy(&iface->if_addr, &((struct sockaddr_in6 *)p)->sin6_addr, sizeof(struct in6_addr));
                  iface->if_index = index;

                  free(ifconf.ifc_buf);
                  return 0;
                    }
              
            p += *p;

      }

ret:
      flog(LOG_ERR, "no linklocal address configured for %s", iface->Name);
      free(ifconf.ifc_buf);
      return -1;
}

int setup_allrouters_membership(int sock, struct Interface *iface)
{
      return (0);
}

int check_allrouters_membership(int sock, struct Interface *iface)
{
      return (0);
}

int
set_interface_linkmtu(const char *iface, uint32_t mtu)
{
      dlog(LOG_DEBUG, 4, "setting LinkMTU (%u) for %s is not supported",
           mtu, iface);
      return -1;
}

int
set_interface_curhlim(const char *iface, uint8_t hlim)
{
      dlog(LOG_DEBUG, 4, "setting CurHopLimit (%u) for %s is not supported",
           hlim, iface);
      return -1;
}

int
set_interface_reachtime(const char *iface, uint32_t rtime)
{
      dlog(LOG_DEBUG, 4, "setting BaseReachableTime (%u) for %s is not supported",
           rtime, iface);
      return -1;
}

int
set_interface_retranstimer(const char *iface, uint32_t rettimer)
{
      dlog(LOG_DEBUG, 4, "setting RetransTimer (%u) for %s is not supported",
           rettimer, iface);
      return -1;
}


Generated by  Doxygen 1.6.0   Back to index