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

getifaddrs.c

/* Distributed Checksum Clearinghouse
 *
 * kludge replacement for getifaddrs(3) for systems that lack it
 *
 * Copyright (c) 2005 by Rhyolite Software
 *
 * Permission to use, copy, modify, and distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND RHYOLITE SOFTWARE DISCLAIMS ALL
 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL RHYOLITE SOFTWARE
 * BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES
 * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
 * WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
 * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
 * SOFTWARE.
 *
 * Rhyolite Software DCC 1.2.74-1.13 $Revision$
 */


/* let the configure script decide if this might work */
#ifndef TEST_DCC_GETIFADDRS
#include "dcc_config.h"
#endif

#ifndef USE_DCC_GETIFADDRS
/* global to suppress "defined but not used" warning */
char dcc_getifaddrs_unneeded[] = "dcc_getifaddrs() unneeded";

#else

#include <sys/types.h>
#define BSD_COMP              /* for SunOS */
#define _IO_TERMIOS_H               /* kludge for OpenUNIX */
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <net/if.h>
#include <unistd.h>
#include "dcc_defs.h"
#include "dcc_heap_debug.h"
#include "dcc_ifaddrs.h"

#include <errno.h>
#include <stdlib.h>
#include <string.h>

int
dcc_getifaddrs(struct ifaddrs **pif)
{
      struct ifconf ifc;
      int buf_size;
      char *buf;
      struct ifreq *ifrp, *ifrp_next, ifr_f;
      struct ifaddrs_all *result0, *result, *rp;
      int i, serrno, s;

      if ((s = socket(AF_INET, SOCK_STREAM, 0)) < 0)
            return -1;

      /* get the list of interface names and addresses */
      buf_size = 1024;
      for (;;) {
            buf = dcc_malloc(buf_size);
            if (!buf) {
                  serrno = errno;
                  close(s);
                  errno = serrno;
                  return -1;
            }
            ifc.ifc_buf = buf;
            ifc.ifc_len = buf_size;
            memset(buf, 0, buf_size);
            if (0 > ioctl(s, SIOCGIFCONF, (char *)&ifc)
                && errno != EINVAL) {
                  serrno = errno;
                  close(s);
                  errno = serrno;
                  *pif = 0;
                  return -1;
            }
            if (ifc.ifc_len < buf_size && ifc.ifc_len != 0)
                  break;
            dcc_free(buf);
            buf_size *= 2;
      }

      i = (ifc.ifc_len/sizeof(struct ifreq)) * sizeof(*result);
      result = (struct ifaddrs_all *)dcc_malloc(i);
      if (!result) {
            serrno = errno;
            dcc_free(buf);
            close(s);
            errno = serrno;
            *pif = 0;
            return -1;
      }
      memset(result, 0, i);
      result0 = result;
      *pif = &result->ifa;

      for (ifrp = ifc.ifc_req;
           (void *)ifrp < (void *)&ifc.ifc_buf[ifc.ifc_len];
           ifrp = ifrp_next) {
#ifdef DCC_HAVE_SA_LEN
            i = ifrp->ifr_addr.sa_len + sizeof(ifrp->ifr_name);
            if (i < (int)sizeof(*ifrp))
                  ifrp_next = ifrp + 1;
            else
                  ifrp_next = (struct ifreq *)((char *)ifrp + i);
#else
            ifrp_next = ifrp + 1;
#endif

            if (ifrp->ifr_addr.sa_family != AF_INET
#ifdef AF_INET6
            && ifrp->ifr_addr.sa_family != AF_INET6
#endif
                )
                  continue;

            strncpy(ifr_f.ifr_name, ifrp->ifr_name, sizeof(ifr_f.ifr_name));
            if (0 > ioctl(s, SIOCGIFFLAGS, (char *)&ifr_f)) {
                  if (errno == ENXIO)
                        continue;
                  serrno = errno;
                  close(s);
                  dcc_free(buf);
                  dcc_free(*pif);
                  *pif = 0;
                  errno = serrno;
                  return -1;
            }

            /* save the name only for debugging */
            strncpy(result->name, ifrp->ifr_name, sizeof(result->name));
            result->ifa.ifa_name = result->name;

            result->addr.sa = ifrp->ifr_addr;
            result->ifa.ifa_addr = &result->addr.sa;
            result->ifa.ifa_flags = ifr_f.ifr_flags;
            result->ifa.ifa_next = &(result+1)->ifa;

            /* skip duplicate addresses */
            rp = result0;
            for (;;) {
                  if (rp >= result) {
                        ++result;
                        break;
                  }
                  if (DCC_SU_SA_EQ(&rp->addr, &result->addr))
                        break;
                  ++rp;
            }
      }

      if (&result->ifa == *pif) {
            *pif = 0;
      } else {
            (result-1)->ifa.ifa_next = 0;
      }
      dcc_free(buf);
      close(s);

      return 0;
}
#endif /* USE_DCC_GETIFADDRS */

Generated by  Doxygen 1.6.0   Back to index