|
|
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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.