Annotation of tme/host/bsd/bsd-if.c, revision 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.