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.