Back to index

courier  0.68.2
rfc1035ifconf.c
Go to the documentation of this file.
00001 /*
00002 ** Copyright 2002 Double Precision, Inc.
00003 ** See COPYING for distribution information.
00004 */
00005 
00006 #include "rfc1035.h"
00007 
00008 #include <stdio.h>
00009 #include <stdlib.h>
00010 #include <string.h>
00011 
00012 #if HAVE_UNISTD_H
00013 #include <unistd.h>
00014 #endif
00015 
00016 
00017 #if HAVE_SIOCGIFCONF
00018 
00019 #if HAVE_SYS_TYPES_H
00020 #include <sys/types.h>
00021 #endif
00022 
00023 #include <sys/ioctl.h>
00024 #include <net/if.h>
00025 
00026 static int getifconf(int fd, struct rfc1035_ifconf **ifconf_ptr)
00027 {
00028        struct ifreq ifreq_buf[64];
00029        struct ifconf ifc;
00030        int i;
00031        const struct sockaddr_in *sin;
00032        RFC1035_ADDR addr;
00033        char ipaddr[RFC1035_NTOABUFSIZE];
00034        struct rfc1035_ifconf *ifcptr;
00035        struct rfc1035_ifconf **ifconf;
00036 
00037        ifc.ifc_len=sizeof(ifreq_buf);
00038        ifc.ifc_req=ifreq_buf;
00039 
00040        if (ioctl(fd, SIOCGIFCONF, &ifc) < 0)
00041               return (0);
00042 
00043        for (i=0; i * sizeof(struct ifreq) < ifc.ifc_len; i++)
00044        {
00045               sin=(const struct sockaddr_in *)&ifreq_buf[i].ifr_addr;
00046 
00047 #if RFC1035_IPV6
00048               if (sin->sin_family == AF_INET6)
00049               {
00050                      struct sockaddr_in6 sin6;
00051 
00052                      memcpy(&sin6, sin, sizeof(sin6));
00053                      addr=sin6.sin6_addr;
00054               }
00055               else if (sin->sin_family == AF_INET)
00056                      rfc1035_ipv4to6(&addr, &sin->sin_addr);
00057               else
00058                      continue;
00059 #else
00060               if (sin->sin_family == AF_INET)
00061                      addr=sin->sin_addr;
00062               else
00063                      continue;
00064 #endif
00065 
00066               rfc1035_ntoa(&addr, ipaddr);
00067 
00068               /*
00069               ** Eliminate any dupes.
00070               */
00071 
00072               ifconf=ifconf_ptr;
00073 
00074               while ( *ifconf )
00075               {
00076                      char ipaddr2[RFC1035_NTOABUFSIZE];
00077 
00078                      rfc1035_ntoa(&(*ifconf)->ifaddr, ipaddr2);
00079 
00080                      if (strcmp(ipaddr, ipaddr2) == 0)
00081                             break;
00082 
00083                      ifconf= &(*ifconf)->next;
00084               }
00085 
00086               if ( *ifconf )
00087                      continue;     /* Already have this IP addr */
00088 
00089               if ( (ifcptr=malloc(sizeof(struct rfc1035_ifconf))) == NULL ||
00090                    (ifcptr->ifname=strdup(ifreq_buf[i].ifr_name)) == NULL)
00091               {
00092                      if (ifcptr)
00093                             free(ifcptr);
00094                      return (-1);
00095               }
00096 
00097               ifcptr->ifaddr=addr;
00098               ifcptr->next=NULL;
00099 
00100               *ifconf= ifcptr;
00101        }
00102        return (0);
00103 }
00104 
00105 /*
00106 ** On systems that support IPv6, issue an SIOCGIFCONF on both an IPv4 and
00107 ** an IPv6 socket, for good measure.
00108 */
00109 
00110 static int doifconf(struct rfc1035_ifconf **ifconf_list)
00111 {
00112        int fd;
00113 
00114        fd=socket(PF_INET, SOCK_STREAM, 0);
00115 
00116        if (fd >= 0)
00117        {
00118               if (getifconf(fd, ifconf_list))
00119               {
00120                      close(fd);
00121                      return (-1);
00122               }
00123               close(fd);
00124        }
00125 
00126 #if RFC1035_IPV6
00127 
00128        fd=socket(PF_INET6, SOCK_STREAM, 0);
00129 
00130        if (fd >= 0)
00131        {
00132               if (getifconf(fd, ifconf_list))
00133               {
00134                      close(fd);
00135                      return (-1);
00136               }
00137               close(fd);
00138        }
00139 #endif
00140        return (0);
00141 }
00142 
00143 struct rfc1035_ifconf *rfc1035_ifconf(int *errflag)
00144 {
00145        struct rfc1035_ifconf *ifconf_list=NULL;
00146        int dummy;
00147 
00148        if (!errflag)
00149               errflag= &dummy;
00150 
00151        *errflag= -1;
00152        if (doifconf(&ifconf_list))
00153        {
00154               rfc1035_ifconf_free(ifconf_list);
00155               return (NULL);
00156        }
00157 
00158        *errflag=0;
00159        return ifconf_list;
00160 }
00161 
00162 #else
00163 
00164 struct rfc1035_ifconf *rfc1035_ifconf(int *errflag)
00165 {
00166        if (errflag)
00167               *errflag=0;
00168        return NULL;
00169 }
00170 #endif
00171 
00172 void rfc1035_ifconf_free(struct rfc1035_ifconf *ifconf_list)
00173 {
00174        while (ifconf_list)
00175        {
00176               struct rfc1035_ifconf *p=ifconf_list->next;
00177 
00178               free(ifconf_list->ifname);
00179               free(ifconf_list);
00180               ifconf_list=p;
00181        }
00182 }
00183