|
|
1.1.1.2 ! root 1: /* $Id: bsd-if.c,v 1.3 2003/10/16 02:48:23 fredette Exp $ */ 1.1 root 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> 1.1.1.2 ! root 37: _TME_RCSID("$Id: bsd-if.c,v 1.3 2003/10/16 02:48:23 fredette Exp $"); 1.1 root 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) { 1.1.1.2 ! root 101: return (-1); 1.1 root 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)) 1.1.1.2 ! root 131: > (size_t) ifc.ifc_len) 1.1 root 132: || ((ifr_offset 133: + SIZEOF_IFREQ(ifr)) 1.1.1.2 ! root 134: > (size_t) ifc.ifc_len)) { 1.1 root 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.