1100784Sfenner/* 2100784Sfenner * Copyright (c) 1997, 1998, 1999, 2000 3100784Sfenner * The Regents of the University of California. All rights reserved. 4100784Sfenner * 5100784Sfenner * Redistribution and use in source and binary forms, with or without 6100784Sfenner * modification, are permitted provided that the following conditions 7100784Sfenner * are met: 8100784Sfenner * 1. Redistributions of source code must retain the above copyright 9100784Sfenner * notice, this list of conditions and the following disclaimer. 10100784Sfenner * 2. Redistributions in binary form must reproduce the above copyright 11100784Sfenner * notice, this list of conditions and the following disclaimer in the 12100784Sfenner * documentation and/or other materials provided with the distribution. 13100784Sfenner * 3. All advertising materials mentioning features or use of this software 14100784Sfenner * must display the following acknowledgement: 15100784Sfenner * This product includes software developed by the Computer Systems 16100784Sfenner * Engineering Group at Lawrence Berkeley Laboratory. 17100784Sfenner * 4. Neither the name of the University nor of the Laboratory may be used 18100784Sfenner * to endorse or promote products derived from this software without 19100784Sfenner * specific prior written permission. 20100784Sfenner * 21100784Sfenner * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 22100784Sfenner * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23100784Sfenner * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24100784Sfenner * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 25100784Sfenner * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26100784Sfenner * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27100784Sfenner * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28100784Sfenner * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29100784Sfenner * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30100784Sfenner * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31100784Sfenner * SUCH DAMAGE. 32100784Sfenner */ 33100784Sfenner 34100784Sfenner#ifndef lint 35100784Sfennerstatic const char rcsid[] = 36100784Sfenner "@(#) $Id: ifaddrlist.c,v 1.9 2000/11/23 20:01:55 leres Exp $ (LBL)"; 37100784Sfenner#endif 38100784Sfenner 39100784Sfenner#include <sys/param.h> 40100784Sfenner#include <sys/file.h> 41100784Sfenner#include <sys/ioctl.h> 42100784Sfenner#include <sys/socket.h> 43100784Sfenner#ifdef HAVE_SYS_SOCKIO_H 44100784Sfenner#include <sys/sockio.h> 45100784Sfenner#endif 46100784Sfenner#include <sys/time.h> /* concession to AIX */ 47100784Sfenner 48100784Sfenner#if __STDC__ 49100784Sfennerstruct mbuf; 50100784Sfennerstruct rtentry; 51100784Sfenner#endif 52100784Sfenner 53100784Sfenner#include <net/if.h> 54100784Sfenner#include <netinet/in.h> 55100784Sfenner 56100784Sfenner#include <ctype.h> 57100784Sfenner#include <errno.h> 58100784Sfenner#include <memory.h> 59100784Sfenner#include <stdio.h> 60100784Sfenner#include <stdlib.h> 61100784Sfenner#include <string.h> 62100784Sfenner#include <unistd.h> 63100784Sfenner 64100784Sfenner#include "ifaddrlist.h" 65100784Sfenner 66100784Sfenner/* 67100784Sfenner * Return the interface list 68100784Sfenner */ 69100784Sfennerint 70100784Sfennerifaddrlist(register struct ifaddrlist **ipaddrp, register char *errbuf) 71100784Sfenner{ 72100784Sfenner register int fd, nipaddr; 73100784Sfenner#ifdef HAVE_SOCKADDR_SA_LEN 74216184Suqs size_t n; 75100784Sfenner#endif 76100784Sfenner register struct ifreq *ifrp, *ifend, *ifnext, *mp; 77100784Sfenner register struct sockaddr_in *sin; 78100784Sfenner register struct ifaddrlist *al; 79100784Sfenner struct ifconf ifc; 80100784Sfenner struct ifreq ibuf[(32 * 1024) / sizeof(struct ifreq)], ifr; 81216184Suqs#define MAX_IPADDR ((int)(sizeof(ibuf) / sizeof(ibuf[0]))) 82100784Sfenner static struct ifaddrlist ifaddrlist[MAX_IPADDR]; 83100784Sfenner char device[sizeof(ifr.ifr_name) + 1]; 84100784Sfenner 85100784Sfenner fd = socket(AF_INET, SOCK_DGRAM, 0); 86100784Sfenner if (fd < 0) { 87100784Sfenner (void)sprintf(errbuf, "socket: %s", strerror(errno)); 88100784Sfenner return (-1); 89100784Sfenner } 90100784Sfenner ifc.ifc_len = sizeof(ibuf); 91100784Sfenner ifc.ifc_buf = (caddr_t)ibuf; 92100784Sfenner 93100784Sfenner if (ioctl(fd, SIOCGIFCONF, (char *)&ifc) < 0 || 94216184Suqs ifc.ifc_len < (int)sizeof(struct ifreq)) { 95100784Sfenner if (errno == EINVAL) 96100784Sfenner (void)sprintf(errbuf, 97216184Suqs "SIOCGIFCONF: ifreq struct too small (%zu bytes)", 98100784Sfenner sizeof(ibuf)); 99100784Sfenner else 100100784Sfenner (void)sprintf(errbuf, "SIOCGIFCONF: %s", 101100784Sfenner strerror(errno)); 102100784Sfenner (void)close(fd); 103100784Sfenner return (-1); 104100784Sfenner } 105100784Sfenner ifrp = ibuf; 106100784Sfenner ifend = (struct ifreq *)((char *)ibuf + ifc.ifc_len); 107100784Sfenner 108100784Sfenner al = ifaddrlist; 109100784Sfenner mp = NULL; 110100784Sfenner nipaddr = 0; 111100784Sfenner for (; ifrp < ifend; ifrp = ifnext) { 112100784Sfenner#ifdef HAVE_SOCKADDR_SA_LEN 113100784Sfenner n = ifrp->ifr_addr.sa_len + sizeof(ifrp->ifr_name); 114100784Sfenner if (n < sizeof(*ifrp)) 115100784Sfenner ifnext = ifrp + 1; 116100784Sfenner else 117100784Sfenner ifnext = (struct ifreq *)((char *)ifrp + n); 118100784Sfenner if (ifrp->ifr_addr.sa_family != AF_INET) 119100784Sfenner continue; 120100784Sfenner#else 121100784Sfenner ifnext = ifrp + 1; 122100784Sfenner#endif 123100784Sfenner /* 124100784Sfenner * Need a template to preserve address info that is 125100784Sfenner * used below to locate the next entry. (Otherwise, 126100784Sfenner * SIOCGIFFLAGS stomps over it because the requests 127100784Sfenner * are returned in a union.) 128100784Sfenner */ 129100784Sfenner strncpy(ifr.ifr_name, ifrp->ifr_name, sizeof(ifr.ifr_name)); 130100784Sfenner if (ioctl(fd, SIOCGIFFLAGS, (char *)&ifr) < 0) { 131100784Sfenner if (errno == ENXIO) 132100784Sfenner continue; 133100784Sfenner (void)sprintf(errbuf, "SIOCGIFFLAGS: %.*s: %s", 134100784Sfenner (int)sizeof(ifr.ifr_name), ifr.ifr_name, 135100784Sfenner strerror(errno)); 136100784Sfenner (void)close(fd); 137100784Sfenner return (-1); 138100784Sfenner } 139100784Sfenner 140100784Sfenner /* Must be up */ 141100784Sfenner if ((ifr.ifr_flags & IFF_UP) == 0) 142100784Sfenner continue; 143100784Sfenner 144100784Sfenner 145100784Sfenner (void)strncpy(device, ifr.ifr_name, sizeof(ifr.ifr_name)); 146100784Sfenner device[sizeof(device) - 1] = '\0'; 147100784Sfenner#ifdef sun 148100784Sfenner /* Ignore sun virtual interfaces */ 149100784Sfenner if (strchr(device, ':') != NULL) 150100784Sfenner continue; 151100784Sfenner#endif 152100784Sfenner if (ioctl(fd, SIOCGIFADDR, (char *)&ifr) < 0) { 153100784Sfenner (void)sprintf(errbuf, "SIOCGIFADDR: %s: %s", 154100784Sfenner device, strerror(errno)); 155100784Sfenner (void)close(fd); 156100784Sfenner return (-1); 157100784Sfenner } 158100784Sfenner 159100784Sfenner if (nipaddr >= MAX_IPADDR) { 160100784Sfenner (void)sprintf(errbuf, "Too many interfaces (%d)", 161100784Sfenner MAX_IPADDR); 162100784Sfenner (void)close(fd); 163100784Sfenner return (-1); 164100784Sfenner } 165100784Sfenner sin = (struct sockaddr_in *)&ifr.ifr_addr; 166100784Sfenner al->addr = sin->sin_addr.s_addr; 167100784Sfenner al->device = strdup(device); 168100784Sfenner ++al; 169100784Sfenner ++nipaddr; 170100784Sfenner } 171100784Sfenner (void)close(fd); 172100784Sfenner 173100784Sfenner *ipaddrp = ifaddrlist; 174100784Sfenner return (nipaddr); 175100784Sfenner} 176