1/* 2 * Copyright (c) 2009 Apple Inc. All rights reserved. 3 * 4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ 5 * 6 * This file contains Original Code and/or Modifications of Original Code 7 * as defined in and that are subject to the Apple Public Source License 8 * Version 2.0 (the 'License'). You may not use this file except in 9 * compliance with the License. The rights granted to you under the License 10 * may not be used to create, or enable the creation or redistribution of, 11 * unlawful or unlicensed copies of an Apple operating system, or to 12 * circumvent, violate, or enable the circumvention or violation of, any 13 * terms of an Apple operating system software license agreement. 14 * 15 * Please obtain a copy of the License at 16 * http://www.opensource.apple.com/apsl/ and read it before using this file. 17 * 18 * The Original Code and all software distributed under the License are 19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 23 * Please see the License for the specific language governing rights and 24 * limitations under the License. 25 * 26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ 27 */ 28 29/* 30 * Copyright (c) 1997, 1998, 1999, 2000 31 * The Regents of the University of California. All rights reserved. 32 * 33 * Redistribution and use in source and binary forms, with or without 34 * modification, are permitted provided that the following conditions 35 * are met: 36 * 1. Redistributions of source code must retain the above copyright 37 * notice, this list of conditions and the following disclaimer. 38 * 2. Redistributions in binary form must reproduce the above copyright 39 * notice, this list of conditions and the following disclaimer in the 40 * documentation and/or other materials provided with the distribution. 41 * 3. All advertising materials mentioning features or use of this software 42 * must display the following acknowledgement: 43 * This product includes software developed by the Computer Systems 44 * Engineering Group at Lawrence Berkeley Laboratory. 45 * 4. Neither the name of the University nor of the Laboratory may be used 46 * to endorse or promote products derived from this software without 47 * specific prior written permission. 48 * 49 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 50 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 51 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 52 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 53 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 54 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 55 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 56 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 57 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 58 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 59 * SUCH DAMAGE. 60 */ 61 62#ifndef lint 63static const char rcsid[] = 64 "@(#) $Id: ifaddrlist.c,v 1.3 2006/02/07 06:22:57 lindak Exp $ (LBL)"; 65#endif 66 67#include <sys/param.h> 68#include <sys/file.h> 69#include <sys/ioctl.h> 70#include <sys/socket.h> 71#ifdef HAVE_SYS_SOCKIO_H 72#include <sys/sockio.h> 73#endif 74#include <sys/time.h> /* concession to AIX */ 75 76#if __STDC__ 77struct mbuf; 78struct rtentry; 79#endif 80 81#include <net/if.h> 82#include <netinet/in.h> 83 84#include <ctype.h> 85#include <errno.h> 86#include <memory.h> 87#include <stdio.h> 88#include <stdlib.h> 89#include <string.h> 90#include <unistd.h> 91 92#include "gnuc.h" 93#ifdef HAVE_OS_PROTO_H 94#include "os-proto.h" 95#endif 96 97#include "ifaddrlist.h" 98 99/* 100 * Return the interface list 101 */ 102int 103ifaddrlist(register struct ifaddrlist **ipaddrp, register char *errbuf, size_t errbuflen) 104{ 105 register int fd, nipaddr; 106#ifdef HAVE_SOCKADDR_SA_LEN 107 register int n; 108#endif 109 register struct ifreq *ifrp, *ifend, *ifnext, *mp; 110 register struct sockaddr_in *sin; 111 register struct ifaddrlist *al; 112 struct ifconf ifc; 113 struct ifreq ibuf[(32 * 1024) / sizeof(struct ifreq)], ifr; 114#define MAX_IPADDR (sizeof(ibuf) / sizeof(ibuf[0])) 115 static struct ifaddrlist ifaddrlist[MAX_IPADDR]; 116 char device[sizeof(ifr.ifr_name) + 1]; 117 118 fd = socket(AF_INET, SOCK_DGRAM, 0); 119 if (fd < 0) { 120 (void)snprintf(errbuf, errbuflen, "socket: %s", strerror(errno)); 121 return (-1); 122 } 123 ifc.ifc_len = sizeof(ibuf); 124 ifc.ifc_buf = (caddr_t)ibuf; 125 126 if (ioctl(fd, SIOCGIFCONF, (char *)&ifc) < 0 || 127 ifc.ifc_len < sizeof(struct ifreq)) { 128 if (errno == EINVAL) 129 (void)snprintf(errbuf, sizeof(errbuf), 130 "SIOCGIFCONF: ifreq struct too small (%d bytes)", 131 (int)sizeof(ibuf)); 132 else 133 (void)snprintf(errbuf, errbuflen, "SIOCGIFCONF: %s", 134 strerror(errno)); 135 (void)close(fd); 136 return (-1); 137 } 138 ifrp = ibuf; 139 ifend = (struct ifreq *)((char *)ibuf + ifc.ifc_len); 140 141 al = ifaddrlist; 142 mp = NULL; 143 nipaddr = 0; 144 for (; ifrp < ifend; ifrp = ifnext) { 145#ifdef HAVE_SOCKADDR_SA_LEN 146 n = ifrp->ifr_addr.sa_len + sizeof(ifrp->ifr_name); 147 if (n < sizeof(*ifrp)) 148 ifnext = ifrp + 1; 149 else 150 ifnext = (struct ifreq *)((char *)ifrp + n); 151 if (ifrp->ifr_addr.sa_family != AF_INET) 152 continue; 153#else 154 ifnext = ifrp + 1; 155#endif 156 /* 157 * Need a template to preserve address info that is 158 * used below to locate the next entry. (Otherwise, 159 * SIOCGIFFLAGS stomps over it because the requests 160 * are returned in a union.) 161 */ 162 strncpy(ifr.ifr_name, ifrp->ifr_name, sizeof(ifr.ifr_name)); 163 if (ioctl(fd, SIOCGIFFLAGS, (char *)&ifr) < 0) { 164 if (errno == ENXIO) 165 continue; 166 (void)snprintf(errbuf, errbuflen, "SIOCGIFFLAGS: %.*s: %s", 167 (int)sizeof(ifr.ifr_name), ifr.ifr_name, 168 strerror(errno)); 169 (void)close(fd); 170 return (-1); 171 } 172 173 /* Must be up */ 174 if ((ifr.ifr_flags & IFF_UP) == 0) 175 continue; 176 177 178 (void)strncpy(device, ifr.ifr_name, sizeof(ifr.ifr_name)); 179 device[sizeof(device) - 1] = '\0'; 180#ifdef sun 181 /* Ignore sun virtual interfaces */ 182 if (strchr(device, ':') != NULL) 183 continue; 184#endif 185 if (ioctl(fd, SIOCGIFADDR, (char *)&ifr) < 0) { 186 (void)snprintf(errbuf, errbuflen, "SIOCGIFADDR: %s: %s", 187 device, strerror(errno)); 188 (void)close(fd); 189 return (-1); 190 } 191 192 if (nipaddr >= MAX_IPADDR) { 193 (void)snprintf(errbuf, errbuflen, "Too many interfaces (%d)", 194 (int)MAX_IPADDR); 195 (void)close(fd); 196 return (-1); 197 } 198 sin = (struct sockaddr_in *)&ifr.ifr_addr; 199 al->addr = sin->sin_addr.s_addr; 200 al->device = strdup(device); 201 ++al; 202 ++nipaddr; 203 } 204 (void)close(fd); 205 206 *ipaddrp = ifaddrlist; 207 return (nipaddr); 208} 209