Main Page   Modules   Data Structures   File List   Data Fields   Globals   Related Pages  

inet.c

Go to the documentation of this file.
00001 /* -*- Mode: c; tab-width: 8; indent-tabs-mode: 1; c-basic-offset: 8; -*- */
00002 /*
00003  * Copyright (c) 1994, 1995, 1996, 1997, 1998
00004  *  The Regents of the University of California.  All rights reserved.
00005  *
00006  * Redistribution and use in source and binary forms, with or without
00007  * modification, are permitted provided that the following conditions
00008  * are met:
00009  * 1. Redistributions of source code must retain the above copyright
00010  *    notice, this list of conditions and the following disclaimer.
00011  * 2. Redistributions in binary form must reproduce the above copyright
00012  *    notice, this list of conditions and the following disclaimer in the
00013  *    documentation and/or other materials provided with the distribution.
00014  * 3. All advertising materials mentioning features or use of this software
00015  *    must display the following acknowledgement:
00016  *  This product includes software developed by the Computer Systems
00017  *  Engineering Group at Lawrence Berkeley Laboratory.
00018  * 4. Neither the name of the University nor of the Laboratory may be used
00019  *    to endorse or promote products derived from this software without
00020  *    specific prior written permission.
00021  *
00022  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
00023  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00024  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00025  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
00026  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
00027  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
00028  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
00029  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00030  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
00031  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
00032  * SUCH DAMAGE.
00033  */
00034 
00035 #ifndef lint
00036 static const char rcsid[] =
00037     "@(#) $Header: /tcpdump/master/libpcap/inet.c,v 1.54 2002/12/22 02:36:48 guy Exp $ (LBL)";
00038 #endif
00039 
00040 #ifdef HAVE_CONFIG_H
00041 #include "config.h"
00042 #endif
00043 
00044 #ifdef WIN32
00045 #include <pcap-stdinc.h>
00046 #else /* WIN32 */
00047 
00048 #include <sys/param.h>
00049 #include <sys/file.h>
00050 #include <sys/ioctl.h>
00051 #include <sys/socket.h>
00052 #ifdef HAVE_SYS_SOCKIO_H
00053 #include <sys/sockio.h>
00054 #endif
00055 #include <sys/time.h>               /* concession to AIX */
00056 
00057 struct mbuf;        /* Squelch compiler warnings on some platforms for */
00058 struct rtentry;     /* declarations in <net/if.h> */
00059 #include <net/if.h>
00060 #include <netinet/in.h>
00061 #endif /* WIN32 */
00062 
00063 #include <ctype.h>
00064 #include <errno.h>
00065 #include <memory.h>
00066 #include <stdio.h>
00067 #include <stdlib.h>
00068 #include <string.h>
00069 #ifndef WIN32
00070 #include <unistd.h>
00071 #endif /* WIN32 */
00072 #ifdef HAVE_LIMITS_H
00073 #include <limits.h>
00074 #else
00075 #define INT_MAX     2147483647
00076 #endif
00077 #ifdef HAVE_IFADDRS_H
00078 #include <ifaddrs.h>
00079 #endif
00080 
00081 #include "pcap-int.h"
00082 
00083 #ifdef HAVE_OS_PROTO_H
00084 #include "os-proto.h"
00085 #endif
00086 
00087 /* Not all systems have IFF_LOOPBACK */
00088 #ifdef IFF_LOOPBACK
00089 #define ISLOOPBACK(name, flags) ((flags) & IFF_LOOPBACK)
00090 #else
00091 #define ISLOOPBACK(name, flags) ((name)[0] == 'l' && (name)[1] == 'o' && \
00092     (isdigit((unsigned char)((name)[2])) || (name)[2] == '\0'))
00093 #endif
00094 
00095 struct sockaddr *
00096 dup_sockaddr(struct sockaddr *sa, size_t sa_length)
00097 {
00098     struct sockaddr *newsa;
00099 
00100     if ((newsa = malloc(sa_length)) == NULL)
00101         return (NULL);
00102     return (memcpy(newsa, sa, sa_length));
00103 }
00104 
00105 static int
00106 get_instance(const char *name)
00107 {
00108     const char *cp, *endcp;
00109     int n;
00110 
00111     if (strcmp(name, "any") == 0) {
00112         /*
00113          * Give the "any" device an artificially high instance
00114          * number, so it shows up after all other non-loopback
00115          * interfaces.
00116          */
00117         return INT_MAX;
00118     }
00119 
00120     endcp = name + strlen(name);
00121     for (cp = name; cp < endcp && !isdigit((unsigned char)*cp); ++cp)
00122         continue;
00123 
00124     if (isdigit((unsigned char)*cp))
00125         n = atoi(cp);
00126     else
00127         n = 0;
00128     return (n);
00129 }
00130 
00131 int
00132 add_or_find_if(pcap_if_t **curdev_ret, pcap_if_t **alldevs, const char *name,
00133     u_int flags, const char *description, char *errbuf)
00134 {
00135     pcap_t *p;
00136     pcap_if_t *curdev, *prevdev, *nextdev;
00137     int this_instance;
00138 
00139     /*
00140      * Can we open this interface for live capture?
00141      */
00142     p = pcap_open_live(name, 68, 0, 0, errbuf);
00143     if (p == NULL) {
00144         /*
00145          * No.  Don't bother including it.
00146          * Don't treat this as an error, though.
00147          */
00148         *curdev_ret = NULL;
00149         return (0);
00150     }
00151     pcap_close(p);
00152 
00153     /*
00154      * Is there already an entry in the list for this interface?
00155      */
00156     for (curdev = *alldevs; curdev != NULL; curdev = curdev->next) {
00157         if (strcmp(name, curdev->name) == 0)
00158             break;  /* yes, we found it */
00159     }
00160     if (curdev == NULL) {
00161         /*
00162          * No, we didn't find it.
00163          * Allocate a new entry.
00164          */
00165         curdev = malloc(sizeof(pcap_if_t));
00166         if (curdev == NULL) {
00167             (void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
00168                 "malloc: %s", pcap_strerror(errno));
00169             return (-1);
00170         }
00171 
00172         /*
00173          * Fill in the entry.
00174          */
00175         curdev->next = NULL;
00176         curdev->name = malloc(strlen(name) + 1);
00177         strcpy(curdev->name, name);
00178         if (description != NULL) {
00179             /*
00180              * We have a description for this interface.
00181              */
00182             curdev->description = malloc(strlen(description) + 1);
00183             strcpy(curdev->description, description);
00184         } else {
00185             /*
00186              * We don't.
00187              */
00188             curdev->description = NULL;
00189         }
00190         curdev->addresses = NULL;   /* list starts out as empty */
00191         curdev->flags = 0;
00192         if (ISLOOPBACK(name, flags))
00193             curdev->flags |= PCAP_IF_LOOPBACK;
00194 
00195         /*
00196          * Add it to the list, in the appropriate location.
00197          * First, get the instance number of this interface.
00198          */
00199         this_instance = get_instance(name);
00200 
00201         /*
00202          * Now look for the last interface with an instance number
00203          * less than or equal to the new interface's instance
00204          * number - except that non-loopback interfaces are
00205          * arbitrarily treated as having interface numbers less
00206          * than those of loopback interfaces, so the loopback
00207          * interfaces are put at the end of the list.
00208          *
00209          * We start with "prevdev" being NULL, meaning we're before
00210          * the first element in the list.
00211          */
00212         prevdev = NULL;
00213         for (;;) {
00214             /*
00215              * Get the interface after this one.
00216              */
00217             if (prevdev == NULL) {
00218                 /*
00219                  * The next element is the first element.
00220                  */
00221                 nextdev = *alldevs;
00222             } else
00223                 nextdev = prevdev->next;
00224 
00225             /*
00226              * Are we at the end of the list?
00227              */
00228             if (nextdev == NULL) {
00229                 /*
00230                  * Yes - we have to put the new entry
00231                  * after "prevdev".
00232                  */
00233                 break;
00234             }
00235 
00236             /*
00237              * Is the new interface a non-loopback interface
00238              * and the next interface a loopback interface?
00239              */
00240             if (!(curdev->flags & PCAP_IF_LOOPBACK) &&
00241                 (nextdev->flags & PCAP_IF_LOOPBACK)) {
00242                 /*
00243                  * Yes, we should put the new entry
00244                  * before "nextdev", i.e. after "prevdev".
00245                  */
00246                 break;
00247             }
00248 
00249             /*
00250              * Is the new interface's instance number less
00251              * than the next interface's instance number,
00252              * and is it the case that the new interface is a
00253              * non-loopback interface or the next interface is
00254              * a loopback interface?
00255              *
00256              * (The goal of both loopback tests is to make
00257              * sure that we never put a loopback interface
00258              * before any non-loopback interface and that we
00259              * always put a non-loopback interface before all
00260              * loopback interfaces.)
00261              */
00262             if (this_instance < get_instance(nextdev->name) &&
00263                 (!(curdev->flags & PCAP_IF_LOOPBACK) ||
00264                    (nextdev->flags & PCAP_IF_LOOPBACK))) {
00265                 /*
00266                  * Yes - we should put the new entry
00267                  * before "nextdev", i.e. after "prevdev".
00268                  */
00269                 break;
00270             }
00271 
00272             prevdev = nextdev;
00273         }
00274 
00275         /*
00276          * Insert before "nextdev".
00277          */
00278         curdev->next = nextdev;
00279 
00280         /*
00281          * Insert after "prevdev" - unless "prevdev" is null,
00282          * in which case this is the first interface.
00283          */
00284         if (prevdev == NULL) {
00285             /*
00286              * This is the first interface.  Pass back a
00287              * pointer to it, and put "curdev" before
00288              * "nextdev".
00289              */
00290             *alldevs = curdev;
00291         } else
00292             prevdev->next = curdev;
00293     }
00294 
00295     *curdev_ret = curdev;
00296     return (0);
00297 }
00298 
00299 int
00300 add_addr_to_iflist(pcap_if_t **alldevs, char *name, u_int flags,
00301     struct sockaddr *addr, size_t addr_size,
00302     struct sockaddr *netmask, size_t netmask_size,
00303     struct sockaddr *broadaddr, size_t broadaddr_size,
00304     struct sockaddr *dstaddr, size_t dstaddr_size,
00305     char *errbuf)
00306 {
00307     pcap_if_t *curdev;
00308     pcap_addr_t *curaddr, *prevaddr, *nextaddr;
00309 
00310     if (add_or_find_if(&curdev, alldevs, name, flags, NULL, errbuf) == -1) {
00311         /*
00312          * Error - give up.
00313          */
00314         return (-1);
00315     }
00316     if (curdev == NULL) {
00317         /*
00318          * Device wasn't added because it can't be opened.
00319          * Not a fatal error.
00320          */
00321         return (0);
00322     }
00323 
00324     /*
00325      * "curdev" is an entry for this interface; add an entry for this
00326      * address to its list of addresses.
00327      *
00328      * Allocate the new entry and fill it in.
00329      */
00330     curaddr = malloc(sizeof(pcap_addr_t));
00331     if (curaddr == NULL) {
00332         (void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
00333             "malloc: %s", pcap_strerror(errno));
00334         return (-1);
00335     }
00336 
00337     curaddr->next = NULL;
00338     if (addr != NULL) {
00339         curaddr->addr = dup_sockaddr(addr, addr_size);
00340         if (curaddr->addr == NULL) {
00341             (void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
00342                 "malloc: %s", pcap_strerror(errno));
00343             free(curaddr);
00344             return (-1);
00345         }
00346     } else
00347         curaddr->addr = NULL;
00348 
00349     if (netmask != NULL) {
00350         curaddr->netmask = dup_sockaddr(netmask, netmask_size);
00351         if (curaddr->netmask == NULL) {
00352             (void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
00353                 "malloc: %s", pcap_strerror(errno));
00354             free(curaddr);
00355             return (-1);
00356         }
00357     } else
00358         curaddr->netmask = NULL;
00359 
00360     if (broadaddr != NULL) {
00361         curaddr->broadaddr = dup_sockaddr(broadaddr, broadaddr_size);
00362         if (curaddr->broadaddr == NULL) {
00363             (void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
00364                 "malloc: %s", pcap_strerror(errno));
00365             free(curaddr);
00366             return (-1);
00367         }
00368     } else
00369         curaddr->broadaddr = NULL;
00370 
00371     if (dstaddr != NULL) {
00372         curaddr->dstaddr = dup_sockaddr(dstaddr, dstaddr_size);
00373         if (curaddr->dstaddr == NULL) {
00374             (void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
00375                 "malloc: %s", pcap_strerror(errno));
00376             free(curaddr);
00377             return (-1);
00378         }
00379     } else
00380         curaddr->dstaddr = NULL;
00381 
00382     /*
00383      * Find the end of the list of addresses.
00384      */
00385     for (prevaddr = curdev->addresses; prevaddr != NULL; prevaddr = nextaddr) {
00386         nextaddr = prevaddr->next;
00387         if (nextaddr == NULL) {
00388             /*
00389              * This is the end of the list.
00390              */
00391             break;
00392         }
00393     }
00394 
00395     if (prevaddr == NULL) {
00396         /*
00397          * The list was empty; this is the first member.
00398          */
00399         curdev->addresses = curaddr;
00400     } else {
00401         /*
00402          * "prevaddr" is the last member of the list; append
00403          * this member to it.
00404          */
00405         prevaddr->next = curaddr;
00406     }
00407 
00408     return (0);
00409 }
00410 
00411 int
00412 pcap_add_if(pcap_if_t **devlist, char *name, u_int flags,
00413     const char *description, char *errbuf)
00414 {
00415     pcap_if_t *curdev;
00416 
00417     return (add_or_find_if(&curdev, devlist, name, flags, description,
00418         errbuf));
00419 }
00420 
00421 
00422 /*
00423  * Free a list of interfaces.
00424  */
00425 void
00426 pcap_freealldevs(pcap_if_t *alldevs)
00427 {
00428     pcap_if_t *curdev, *nextdev;
00429     pcap_addr_t *curaddr, *nextaddr;
00430 
00431     for (curdev = alldevs; curdev != NULL; curdev = nextdev) {
00432         nextdev = curdev->next;
00433 
00434         /*
00435          * Free all addresses.
00436          */
00437         for (curaddr = curdev->addresses; curaddr != NULL; curaddr = nextaddr) {
00438             nextaddr = curaddr->next;
00439             if (curaddr->addr)
00440                 free(curaddr->addr);
00441             if (curaddr->netmask)
00442                 free(curaddr->netmask);
00443             if (curaddr->broadaddr)
00444                 free(curaddr->broadaddr);
00445             if (curaddr->dstaddr)
00446                 free(curaddr->dstaddr);
00447             free(curaddr);
00448         }
00449 
00450         /*
00451          * Free the name string.
00452          */
00453         free(curdev->name);
00454 
00455         /*
00456          * Free the description string, if any.
00457          */
00458         if (curdev->description != NULL)
00459             free(curdev->description);
00460 
00461         /*
00462          * Free the interface.
00463          */
00464         free(curdev);
00465     }
00466 }
00467 
00468 #ifndef WIN32
00469 
00470 /*
00471  * Return the name of a network interface attached to the system, or NULL
00472  * if none can be found.  The interface must be configured up; the
00473  * lowest unit number is preferred; loopback is ignored.
00474  */
00475 char *
00476 pcap_lookupdev(errbuf)
00477     register char *errbuf;
00478 {
00479     pcap_if_t *alldevs;
00480 /* for old BSD systems, including bsdi3 */
00481 #ifndef IF_NAMESIZE
00482 #define IF_NAMESIZE IFNAMSIZ
00483 #endif
00484     static char device[IF_NAMESIZE + 1];
00485     char *ret;
00486 
00487     if (pcap_findalldevs(&alldevs, errbuf) == -1)
00488         return (NULL);
00489 
00490     if (alldevs == NULL || (alldevs->flags & PCAP_IF_LOOPBACK)) {
00491         /*
00492          * There are no devices on the list, or the first device
00493          * on the list is a loopback device, which means there
00494          * are no non-loopback devices on the list.  This means
00495          * we can't return any device.
00496          *
00497          * XXX - why not return a loopback device?  If we can't
00498          * capture on it, it won't be on the list, and if it's
00499          * on the list, there aren't any non-loopback devices,
00500          * so why not just supply it as the default device?
00501          */
00502         (void)strlcpy(errbuf, "no suitable device found",
00503             PCAP_ERRBUF_SIZE);
00504         ret = NULL;
00505     } else {
00506         /*
00507          * Return the name of the first device on the list.
00508          */
00509         (void)strlcpy(device, alldevs->name, sizeof(device));
00510         ret = device;
00511     }
00512 
00513     pcap_freealldevs(alldevs);
00514     return (ret);
00515 }
00516 
00517 int
00518 pcap_lookupnet(device, netp, maskp, errbuf)
00519     register const char *device;
00520     register bpf_u_int32 *netp, *maskp;
00521     register char *errbuf;
00522 {
00523     register int fd;
00524     register struct sockaddr_in *sin;
00525     struct ifreq ifr;
00526 
00527     /*
00528      * The pseudo-device "any" listens on all interfaces and therefore
00529      * has the network address and -mask "0.0.0.0" therefore catching
00530      * all traffic. Using NULL for the interface is the same as "any".
00531      */
00532     if (!device || strcmp(device, "any") == 0) {
00533         *netp = *maskp = 0;
00534         return 0;
00535     }
00536 
00537     fd = socket(AF_INET, SOCK_DGRAM, 0);
00538     if (fd < 0) {
00539         (void)snprintf(errbuf, PCAP_ERRBUF_SIZE, "socket: %s",
00540             pcap_strerror(errno));
00541         return (-1);
00542     }
00543     memset(&ifr, 0, sizeof(ifr));
00544 #ifdef linux
00545     /* XXX Work around Linux kernel bug */
00546     ifr.ifr_addr.sa_family = AF_INET;
00547 #endif
00548     (void)strncpy(ifr.ifr_name, device, sizeof(ifr.ifr_name));
00549     if (ioctl(fd, SIOCGIFADDR, (char *)&ifr) < 0) {
00550         if (errno == EADDRNOTAVAIL) {
00551             (void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
00552                 "%s: no IPv4 address assigned", device);
00553         } else {
00554             (void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
00555                 "SIOCGIFADDR: %s: %s",
00556                 device, pcap_strerror(errno));
00557         }
00558         (void)close(fd);
00559         return (-1);
00560     }
00561     sin = (struct sockaddr_in *)&ifr.ifr_addr;
00562     *netp = sin->sin_addr.s_addr;
00563     if (ioctl(fd, SIOCGIFNETMASK, (char *)&ifr) < 0) {
00564         (void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
00565             "SIOCGIFNETMASK: %s: %s", device, pcap_strerror(errno));
00566         (void)close(fd);
00567         return (-1);
00568     }
00569     (void)close(fd);
00570     *maskp = sin->sin_addr.s_addr;
00571     if (*maskp == 0) {
00572         if (IN_CLASSA(*netp))
00573             *maskp = IN_CLASSA_NET;
00574         else if (IN_CLASSB(*netp))
00575             *maskp = IN_CLASSB_NET;
00576         else if (IN_CLASSC(*netp))
00577             *maskp = IN_CLASSC_NET;
00578         else {
00579             (void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
00580                 "inet class for 0x%x unknown", *netp);
00581             return (-1);
00582         }
00583     }
00584     *netp &= *maskp;
00585     return (0);
00586 }
00587 
00588 #else /* WIN32 */
00589 
00590 /*
00591  * Return the name of a network interface attached to the system, or NULL
00592  * if none can be found.  The interface must be configured up; the
00593  * lowest unit number is preferred; loopback is ignored.
00594  */
00595 char *
00596 pcap_lookupdev(errbuf)
00597     register char *errbuf;
00598 {
00599     DWORD dwVersion;
00600     DWORD dwWindowsMajorVersion;
00601     dwVersion = GetVersion();   /* get the OS version */
00602     dwWindowsMajorVersion = (DWORD)(LOBYTE(LOWORD(dwVersion)));
00603     
00604     if (dwVersion >= 0x80000000 && dwWindowsMajorVersion >= 4) {
00605         /*
00606          * Windows 95, 98, ME.
00607          */
00608         ULONG NameLength = 8192;
00609         static char AdaptersName[8192];
00610         
00611         PacketGetAdapterNames(AdaptersName,&NameLength);
00612         
00613         return (AdaptersName);
00614     } else {
00615         /*
00616          * Windows NT (NT 4.0, W2K, WXP).
00617          */
00618         ULONG NameLength = 8192;
00619         static WCHAR AdaptersName[8192];
00620         
00621         PacketGetAdapterNames((PTSTR)AdaptersName,&NameLength);
00622         
00623         return (char *)(AdaptersName);
00624     }   
00625 }
00626 
00627 
00628 int
00629 pcap_lookupnet(device, netp, maskp, errbuf)
00630     register const char *device;
00631     register bpf_u_int32 *netp, *maskp;
00632     register char *errbuf;
00633 {
00634     /* 
00635      * We need only the first address, so we allocate a single
00636      * npf_if_addr structure and we set if_addr_size to 1.
00637      */
00638     npf_if_addr if_addrs;
00639     LONG if_addr_size = 1;
00640     struct sockaddr_in *t_addr;
00641 
00642     if (!PacketGetNetInfoEx((void *)device, &if_addrs, &if_addr_size)) {
00643         *netp = *maskp = 0;
00644         return (0);
00645     }
00646 
00647     t_addr = (struct sockaddr_in *) &(if_addrs.IPAddress);
00648     *netp = t_addr->sin_addr.S_un.S_addr;
00649     t_addr = (struct sockaddr_in *) &(if_addrs.SubnetMask);
00650     *maskp = t_addr->sin_addr.S_un.S_addr;
00651 
00652     /*
00653      * XXX - will we ever get back a 0 netmask?
00654      * If so, we should presumably make the "if (*maskp == 0)" code
00655      * above common, rather than non-Win32-specific.
00656      */
00657 
00658     *netp &= *maskp;
00659     return (0);
00660 }
00661 
00662 #endif /* WIN32 */

documentation. Copyright (c) 2002-2003 Politecnico di Torino. All rights reserved.