Annotation of tme/host/bsd/bsd-if.c, revision 1.1.1.1

1.1       root        1: /* $Id: bsd-if.c,v 1.2 2003/05/18 00:06:06 fredette Exp $ */
                      2: 
                      3: /* host/bsd/bsd-if.c - BSD interface support: */
                      4: 
                      5: /*
                      6:  * Copyright (c) 2001, 2003 Matt Fredette
                      7:  * All rights reserved.
                      8:  *
                      9:  * Redistribution and use in source and binary forms, with or without
                     10:  * modification, are permitted provided that the following conditions
                     11:  * are met:
                     12:  * 1. Redistributions of source code must retain the above copyright
                     13:  *    notice, this list of conditions and the following disclaimer.
                     14:  * 2. Redistributions in binary form must reproduce the above copyright
                     15:  *    notice, this list of conditions and the following disclaimer in the
                     16:  *    documentation and/or other materials provided with the distribution.
                     17:  * 3. All advertising materials mentioning features or use of this software
                     18:  *    must display the following acknowledgement:
                     19:  *      This product includes software developed by Matt Fredette.
                     20:  * 4. The name of the author may not be used to endorse or promote products
                     21:  *    derived from this software without specific prior written permission.
                     22:  *
                     23:  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
                     24:  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
                     25:  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
                     26:  * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
                     27:  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
                     28:  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
                     29:  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     30:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
                     31:  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
                     32:  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
                     33:  * POSSIBILITY OF SUCH DAMAGE.
                     34:  */
                     35: 
                     36: #include <tme/common.h>
                     37: _TME_RCSID("$Id: bsd-if.c,v 1.2 2003/05/18 00:06:06 fredette Exp $");
                     38: 
                     39: /* includes: */
                     40: #include "bsd-impl.h"
                     41: #include <string.h>
                     42: #include <errno.h>
                     43: #include <fcntl.h>
                     44: #include <netdb.h>
                     45: #include <sys/param.h>
                     46: #include <sys/socket.h>
                     47: #include <sys/stat.h>
                     48: #include <net/if.h>
                     49: #include <netinet/in_systm.h>
                     50: #include <netinet/in.h>
                     51: #if defined(HAVE_SYS_SOCKIO_H)
                     52: #include <sys/sockio.h>
                     53: #elif defined(HAVE_SYS_SOCKETIO_H)
                     54: #include <sys/socketio.h> 
                     55: #endif /* HAVE_SYS_SOCKETIO_H */
                     56: #include <sys/ioctl.h>
                     57: #ifdef HAVE_IOCTLS_H
                     58: #include <ioctls.h>
                     59: #endif /* HAVE_IOCTLS_H */
                     60: #ifdef HAVE_NET_IF_ETHER_H
                     61: #include <net/if_ether.h>
                     62: #endif /* HAVE_NET_IF_ETHER_H */
                     63: #ifdef HAVE_NET_ETHERNET_H
                     64: #include <net/ethernet.h>
                     65: #endif /* HAVE_NET_ETHERNET_H */
                     66: #include <netinet/ip.h>
                     67: #ifdef HAVE_NET_IF_DL_H
                     68: #include <net/if_dl.h>
                     69: #endif /* HAVE_NET_IF_DL_H */
                     70: #include <arpa/inet.h>
                     71: 
                     72: /* this macro helps us size a struct ifreq: */
                     73: #ifdef HAVE_SOCKADDR_SA_LEN
                     74: #define SIZEOF_IFREQ(ifr) (sizeof(ifr->ifr_name) + ifr->ifr_addr.sa_len)
                     75: #else  /* !HAVE_SOCKADDR_SA_LEN */
                     76: #define SIZEOF_IFREQ(ifr) (sizeof(ifr->ifr_name) + sizeof(struct sockaddr))
                     77: #endif /* !HAVE_SOCKADDR_SA_LEN */
                     78: 
                     79: /* this finds a network interface: */
                     80: int
                     81: tme_bsd_if_find(const char *ifr_name_user, struct ifreq **_ifreq, tme_uint8_t **_if_addr, unsigned int *_if_addr_size)
                     82: {
                     83:   int saved_errno;
                     84:   int dummy_fd;
                     85:   char ifreq_buffer[16384];    /* FIXME - magic constant. */
                     86:   struct ifconf ifc;
                     87:   struct ifreq *ifr;
                     88:   struct ifreq *ifr_user;
                     89:   size_t ifr_offset;
                     90:   struct sockaddr_in saved_ip_address;
                     91:   short saved_flags;
                     92: #ifdef HAVE_AF_LINK
                     93:   struct ifreq *link_ifreqs[20];       /* FIXME - magic constant. */
                     94:   size_t link_ifreqs_count;
                     95:   size_t link_ifreqs_i;
                     96:   struct sockaddr_dl *sadl;
                     97: #endif                         /* HAVE_AF_LINK */
                     98: 
                     99:   /* make a dummy socket so we can read the interface list: */
                    100:   if ((dummy_fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
                    101:     return (NULL);
                    102:   }
                    103: 
                    104:   /* read the interface list: */
                    105:   ifc.ifc_len = sizeof(ifreq_buffer);
                    106:   ifc.ifc_buf = ifreq_buffer;
                    107:   if (ioctl(dummy_fd, SIOCGIFCONF, &ifc) < 0) {
                    108:     saved_errno = errno;
                    109:     close(dummy_fd);
                    110:     errno = saved_errno;
                    111:     return (-1);
                    112:   }
                    113: 
                    114: #ifdef HAVE_AF_LINK
                    115:   /* start our list of link address ifreqs: */
                    116:   link_ifreqs_count = 0;
                    117: #endif /* HAVE_AF_LINK */
                    118: 
                    119:   /* walk the interface list: */
                    120:   ifr_user = NULL;
                    121:   for (ifr_offset = 0;; ifr_offset += SIZEOF_IFREQ(ifr)) {
                    122: 
                    123:     /* stop walking if we have run out of space in the buffer.  note
                    124:        that before we can use SIZEOF_IFREQ, we have to make sure that
                    125:        there is a minimum number of bytes in the buffer to use it
                    126:        (namely, that there's a whole struct sockaddr available): */
                    127:     ifr = (struct ifreq *) (ifreq_buffer + ifr_offset);
                    128:     if (((ifr_offset
                    129:         + sizeof(ifr->ifr_name)
                    130:         + sizeof(struct sockaddr))
                    131:         > ifc.ifc_len)
                    132:        || ((ifr_offset
                    133:             + SIZEOF_IFREQ(ifr))
                    134:            > ifc.ifc_len)) {
                    135:       errno = ENOENT;
                    136:       break;
                    137:     }
                    138: 
                    139: #ifdef HAVE_AF_LINK
                    140:     /* if this is a hardware address, save it: */
                    141:     if (ifr->ifr_addr.sa_family == AF_LINK) {
                    142:       if (link_ifreqs_count < TME_ARRAY_ELS(link_ifreqs)) {
                    143:        link_ifreqs[link_ifreqs_count++] = ifr;
                    144:       }
                    145:       continue;
                    146:     }
                    147: #endif /* HAVE_AF_LINK */
                    148: 
                    149:     /* ignore this interface if it doesn't do IP: */
                    150:     /* XXX is this actually important? */
                    151:     if (ifr->ifr_addr.sa_family != AF_INET) {
                    152:       continue;
                    153:     }
                    154: 
                    155:     /* get the interface flags, preserving the IP address in the
                    156:        struct ifreq across the call: */
                    157:     saved_ip_address = *((struct sockaddr_in *) & ifr->ifr_addr);
                    158:     if (ioctl(dummy_fd, SIOCGIFFLAGS, ifr) < 0) {
                    159:       ifr = NULL;
                    160:       break;
                    161:     }
                    162:     saved_flags = ifr->ifr_flags;
                    163:     *((struct sockaddr_in *) & ifr->ifr_addr) = saved_ip_address;
                    164: 
                    165:     /* ignore this interface if it isn't up and running: */
                    166:     if ((saved_flags & (IFF_UP | IFF_RUNNING))
                    167:        != (IFF_UP | IFF_RUNNING)) {
                    168:       continue;
                    169:     }
                    170: 
                    171:     /* if we don't have an interface yet, take this one depending on
                    172:        whether the user asked for an interface by name or not.  if he
                    173:        did, and this is it, take this one.  if he didn't, and this
                    174:        isn't a loopback interface, take this one: */
                    175:     if (ifr_user == NULL
                    176:        && (ifr_name_user != NULL
                    177:            ? !strncmp(ifr->ifr_name, ifr_name_user, sizeof(ifr->ifr_name))
                    178:            : !(ifr->ifr_flags & IFF_LOOPBACK))) {
                    179:       ifr_user = ifr;
                    180:     }
                    181:   }
                    182: 
                    183:   /* close the dummy socket: */
                    184:   saved_errno = errno;
                    185:   close(dummy_fd);
                    186:   errno = saved_errno;
                    187: 
                    188:   /* if we don't have an interface to return: */
                    189:   if (ifr_user == NULL) {
                    190:     return (errno);
                    191:   }
                    192: 
                    193:   /* return this interface: */
                    194:   *_ifreq = (struct ifreq *) tme_memdup(ifr_user, SIZEOF_IFREQ(ifr_user));
                    195: 
                    196:   /* assume that we can't find this interface's hardware address: */
                    197:   if (_if_addr != NULL) {
                    198:     *_if_addr = NULL;
                    199:   }
                    200:   if (_if_addr_size != NULL) {
                    201:     *_if_addr_size = 0;
                    202:   }
                    203: 
                    204: #ifdef HAVE_AF_LINK
                    205: 
                    206:   /* try to find an AF_LINK ifreq that gives us the interface's
                    207:      hardware address: */
                    208:   ifr = NULL;
                    209:   for (link_ifreqs_i = 0;
                    210:        link_ifreqs_i < link_ifreqs_count;
                    211:        link_ifreqs_i++) {
                    212:     if (!strncmp(link_ifreqs[link_ifreqs_i]->ifr_name,
                    213:                 ifr_user->ifr_name,
                    214:                 sizeof(ifr_user->ifr_name))) {
                    215:       ifr = link_ifreqs[link_ifreqs_i];
                    216:       break;
                    217:     }
                    218:   }
                    219: 
                    220:   /* if we found one, return the hardware address: */
                    221:   if (ifr != NULL) {
                    222:     sadl = (struct sockaddr_dl *) &ifr->ifr_addr;
                    223:     if (_if_addr_size != NULL) {
                    224:       *_if_addr_size = sadl->sdl_alen;
                    225:     }
                    226:     if (_if_addr != NULL) {
                    227:       *_if_addr = tme_new(tme_uint8_t, sadl->sdl_alen);
                    228:       memcpy(*_if_addr, LLADDR(sadl), sadl->sdl_alen);
                    229:     }
                    230:   }
                    231: 
                    232: #endif /* HAVE_AF_LINK */
                    233: 
                    234:   /* done: */
                    235:   return (TME_OK);
                    236: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.