inet.c revision 17683
117683Spst/* 217683Spst * Copyright (c) 1994, 1995, 1996 317683Spst * The Regents of the University of California. All rights reserved. 417683Spst * 517683Spst * Redistribution and use in source and binary forms, with or without 617683Spst * modification, are permitted provided that the following conditions 717683Spst * are met: 817683Spst * 1. Redistributions of source code must retain the above copyright 917683Spst * notice, this list of conditions and the following disclaimer. 1017683Spst * 2. Redistributions in binary form must reproduce the above copyright 1117683Spst * notice, this list of conditions and the following disclaimer in the 1217683Spst * documentation and/or other materials provided with the distribution. 1317683Spst * 3. All advertising materials mentioning features or use of this software 1417683Spst * must display the following acknowledgement: 1517683Spst * This product includes software developed by the Computer Systems 1617683Spst * Engineering Group at Lawrence Berkeley Laboratory. 1717683Spst * 4. Neither the name of the University nor of the Laboratory may be used 1817683Spst * to endorse or promote products derived from this software without 1917683Spst * specific prior written permission. 2017683Spst * 2117683Spst * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 2217683Spst * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2317683Spst * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2417683Spst * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 2517683Spst * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2617683Spst * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2717683Spst * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2817683Spst * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2917683Spst * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 3017683Spst * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 3117683Spst * SUCH DAMAGE. 3217683Spst */ 3317683Spst 3417683Spst#ifndef lint 3517683Spststatic char rcsid[] = 3617683Spst "@(#) $Header: inet.c,v 1.18 96/07/15 00:48:49 leres Exp $ (LBL)"; 3717683Spst#endif 3817683Spst 3917683Spst#include <sys/param.h> 4017683Spst#include <sys/file.h> 4117683Spst#include <sys/ioctl.h> 4217683Spst#include <sys/socket.h> 4317683Spst#ifdef HAVE_SYS_SOCKIO_H 4417683Spst#include <sys/sockio.h> 4517683Spst#endif 4617683Spst#include <sys/time.h> /* concession to AIX */ 4717683Spst 4817683Spst#if __STDC__ 4917683Spststruct mbuf; 5017683Spststruct rtentry; 5117683Spst#endif 5217683Spst 5317683Spst#include <net/if.h> 5417683Spst#include <netinet/in.h> 5517683Spst 5617683Spst#include <ctype.h> 5717683Spst#include <errno.h> 5817683Spst#include <memory.h> 5917683Spst#include <stdio.h> 6017683Spst#include <stdlib.h> 6117683Spst#include <string.h> 6217683Spst#include <unistd.h> 6317683Spst 6417683Spst#include "pcap-int.h" 6517683Spst 6617683Spst#include "gnuc.h" 6717683Spst#ifdef HAVE_OS_PROTO_H 6817683Spst#include "os-proto.h" 6917683Spst#endif 7017683Spst 7117683Spst/* Not all systems have IFF_LOOPBACK */ 7217683Spst#ifdef IFF_LOOPBACK 7317683Spst#define ISLOOPBACK(p) ((p)->ifr_flags & IFF_LOOPBACK) 7417683Spst#else 7517683Spst#define ISLOOPBACK(p) (strcmp((p)->ifr_name, "lo0") == 0) 7617683Spst#endif 7717683Spst 7817683Spst/* 7917683Spst * Return the name of a network interface attached to the system, or NULL 8017683Spst * if none can be found. The interface must be configured up; the 8117683Spst * lowest unit number is preferred; loopback is ignored. 8217683Spst */ 8317683Spstchar * 8417683Spstpcap_lookupdev(errbuf) 8517683Spst register char *errbuf; 8617683Spst{ 8717683Spst register int fd, minunit, n; 8817683Spst register char *cp; 8917683Spst register struct ifreq *ifrp, *ifend, *ifnext, *mp; 9017683Spst struct ifconf ifc; 9117683Spst struct ifreq ibuf[16], ifr; 9217683Spst static char device[sizeof(ifrp->ifr_name) + 1]; 9317683Spst 9417683Spst fd = socket(AF_INET, SOCK_DGRAM, 0); 9517683Spst if (fd < 0) { 9617683Spst (void)sprintf(errbuf, "socket: %s", pcap_strerror(errno)); 9717683Spst return (NULL); 9817683Spst } 9917683Spst ifc.ifc_len = sizeof ibuf; 10017683Spst ifc.ifc_buf = (caddr_t)ibuf; 10117683Spst 10217683Spst if (ioctl(fd, SIOCGIFCONF, (char *)&ifc) < 0 || 10317683Spst ifc.ifc_len < sizeof(struct ifreq)) { 10417683Spst (void)sprintf(errbuf, "SIOCGIFCONF: %s", pcap_strerror(errno)); 10517683Spst (void)close(fd); 10617683Spst return (NULL); 10717683Spst } 10817683Spst ifrp = ibuf; 10917683Spst ifend = (struct ifreq *)((char *)ibuf + ifc.ifc_len); 11017683Spst 11117683Spst mp = NULL; 11217683Spst minunit = 666; 11317683Spst for (; ifrp < ifend; ifrp = ifnext) { 11417683Spst#ifdef HAVE_SOCKADDR_SA_LEN 11517683Spst n = ifrp->ifr_addr.sa_len + sizeof(ifrp->ifr_name); 11617683Spst if (n < sizeof(*ifrp)) 11717683Spst ifnext = ifrp + 1; 11817683Spst else 11917683Spst ifnext = (struct ifreq *)((char *)ifrp + n); 12017683Spst if (ifrp->ifr_addr.sa_family != AF_INET) 12117683Spst continue; 12217683Spst#else 12317683Spst ifnext = ifrp + 1; 12417683Spst#endif 12517683Spst /* 12617683Spst * Need a template to preserve address info that is 12717683Spst * used below to locate the next entry. (Otherwise, 12817683Spst * SIOCGIFFLAGS stomps over it because the requests 12917683Spst * are returned in a union.) 13017683Spst */ 13117683Spst strncpy(ifr.ifr_name, ifrp->ifr_name, sizeof(ifr.ifr_name)); 13217683Spst if (ioctl(fd, SIOCGIFFLAGS, (char *)&ifr) < 0) { 13317683Spst (void)sprintf(errbuf, "SIOCGIFFLAGS: %s", 13417683Spst pcap_strerror(errno)); 13517683Spst (void)close(fd); 13617683Spst return (NULL); 13717683Spst } 13817683Spst 13917683Spst /* Must be up and not the loopback */ 14017683Spst if ((ifr.ifr_flags & IFF_UP) == 0 || ISLOOPBACK(&ifr)) 14117683Spst continue; 14217683Spst 14317683Spst for (cp = ifrp->ifr_name; !isdigit(*cp); ++cp) 14417683Spst continue; 14517683Spst n = atoi(cp); 14617683Spst if (n < minunit) { 14717683Spst minunit = n; 14817683Spst mp = ifrp; 14917683Spst } 15017683Spst } 15117683Spst (void)close(fd); 15217683Spst if (mp == NULL) { 15317683Spst (void)strcpy(errbuf, "no suitable device found"); 15417683Spst return (NULL); 15517683Spst } 15617683Spst 15717683Spst (void)strncpy(device, mp->ifr_name, sizeof(device) - 1); 15817683Spst device[sizeof(device) - 1] = '\0'; 15917683Spst return (device); 16017683Spst} 16117683Spst 16217683Spstint 16317683Spstpcap_lookupnet(device, netp, maskp, errbuf) 16417683Spst register char *device; 16517683Spst register bpf_u_int32 *netp, *maskp; 16617683Spst register char *errbuf; 16717683Spst{ 16817683Spst register int fd; 16917683Spst register struct sockaddr_in *sin; 17017683Spst struct ifreq ifr; 17117683Spst 17217683Spst fd = socket(AF_INET, SOCK_DGRAM, 0); 17317683Spst if (fd < 0) { 17417683Spst (void)sprintf(errbuf, "socket: %s", pcap_strerror(errno)); 17517683Spst return (-1); 17617683Spst } 17717683Spst memset(&ifr, 0, sizeof(ifr)); 17817683Spst#ifdef linux 17917683Spst /* XXX Work around Linux kernel bug */ 18017683Spst ifr.ifr_addr.sa_family = AF_INET; 18117683Spst#endif 18217683Spst (void)strncpy(ifr.ifr_name, device, sizeof(ifr.ifr_name)); 18317683Spst if (ioctl(fd, SIOCGIFADDR, (char *)&ifr) < 0) { 18417683Spst (void)sprintf(errbuf, "SIOCGIFADDR: %s: %s", 18517683Spst device, pcap_strerror(errno)); 18617683Spst (void)close(fd); 18717683Spst return (-1); 18817683Spst } 18917683Spst sin = (struct sockaddr_in *)&ifr.ifr_addr; 19017683Spst *netp = sin->sin_addr.s_addr; 19117683Spst if (ioctl(fd, SIOCGIFNETMASK, (char *)&ifr) < 0) { 19217683Spst (void)sprintf(errbuf, "SIOCGIFNETMASK: %s: %s", 19317683Spst device, pcap_strerror(errno)); 19417683Spst (void)close(fd); 19517683Spst return (-1); 19617683Spst } 19717683Spst (void)close(fd); 19817683Spst *maskp = sin->sin_addr.s_addr; 19917683Spst if (*maskp == 0) { 20017683Spst if (IN_CLASSA(*netp)) 20117683Spst *maskp = IN_CLASSA_NET; 20217683Spst else if (IN_CLASSB(*netp)) 20317683Spst *maskp = IN_CLASSB_NET; 20417683Spst else if (IN_CLASSC(*netp)) 20517683Spst *maskp = IN_CLASSC_NET; 20617683Spst else { 20717683Spst (void)sprintf(errbuf, "inet class for 0x%x unknown", 20817683Spst *netp); 20917683Spst return (-1); 21017683Spst } 21117683Spst } 21217683Spst *netp &= *maskp; 21317683Spst return (0); 21417683Spst} 215