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[] _U_ = 00037 "@(#) $Header: /tcpdump/master/libpcap/inet.c,v 1.58.2.2 2004/04/30 09:07:21 risso 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_if_t *curdev, *prevdev, *nextdev; 00136 int this_instance; 00137 00138 /* 00139 * Is there already an entry in the list for this interface? 00140 */ 00141 for (curdev = *alldevs; curdev != NULL; curdev = curdev->next) { 00142 if (strcmp(name, curdev->name) == 0) 00143 break; /* yes, we found it */ 00144 } 00145 if (curdev == NULL) { 00146 /* 00147 * No, we didn't find it. 00148 * Allocate a new entry. 00149 */ 00150 curdev = malloc(sizeof(pcap_if_t)); 00151 if (curdev == NULL) { 00152 (void)snprintf(errbuf, PCAP_ERRBUF_SIZE, 00153 "malloc: %s", pcap_strerror(errno)); 00154 return (-1); 00155 } 00156 00157 /* 00158 * Fill in the entry. 00159 */ 00160 curdev->next = NULL; 00161 curdev->name = malloc(strlen(name) + 1); 00162 strcpy(curdev->name, name); 00163 if (description != NULL) { 00164 /* 00165 * We have a description for this interface. 00166 */ 00167 curdev->description = malloc(strlen(description) + 1); 00168 strcpy(curdev->description, description); 00169 } else { 00170 /* 00171 * We don't. 00172 */ 00173 curdev->description = NULL; 00174 } 00175 curdev->addresses = NULL; /* list starts out as empty */ 00176 curdev->flags = 0; 00177 if (ISLOOPBACK(name, flags)) 00178 curdev->flags |= PCAP_IF_LOOPBACK; 00179 00180 /* 00181 * Add it to the list, in the appropriate location. 00182 * First, get the instance number of this interface. 00183 */ 00184 this_instance = get_instance(name); 00185 00186 /* 00187 * Now look for the last interface with an instance number 00188 * less than or equal to the new interface's instance 00189 * number - except that non-loopback interfaces are 00190 * arbitrarily treated as having interface numbers less 00191 * than those of loopback interfaces, so the loopback 00192 * interfaces are put at the end of the list. 00193 * 00194 * We start with "prevdev" being NULL, meaning we're before 00195 * the first element in the list. 00196 */ 00197 prevdev = NULL; 00198 for (;;) { 00199 /* 00200 * Get the interface after this one. 00201 */ 00202 if (prevdev == NULL) { 00203 /* 00204 * The next element is the first element. 00205 */ 00206 nextdev = *alldevs; 00207 } else 00208 nextdev = prevdev->next; 00209 00210 /* 00211 * Are we at the end of the list? 00212 */ 00213 if (nextdev == NULL) { 00214 /* 00215 * Yes - we have to put the new entry 00216 * after "prevdev". 00217 */ 00218 break; 00219 } 00220 00221 /* 00222 * Is the new interface a non-loopback interface 00223 * and the next interface a loopback interface? 00224 */ 00225 if (!(curdev->flags & PCAP_IF_LOOPBACK) && 00226 (nextdev->flags & PCAP_IF_LOOPBACK)) { 00227 /* 00228 * Yes, we should put the new entry 00229 * before "nextdev", i.e. after "prevdev". 00230 */ 00231 break; 00232 } 00233 00234 /* 00235 * Is the new interface's instance number less 00236 * than the next interface's instance number, 00237 * and is it the case that the new interface is a 00238 * non-loopback interface or the next interface is 00239 * a loopback interface? 00240 * 00241 * (The goal of both loopback tests is to make 00242 * sure that we never put a loopback interface 00243 * before any non-loopback interface and that we 00244 * always put a non-loopback interface before all 00245 * loopback interfaces.) 00246 */ 00247 if (this_instance < get_instance(nextdev->name) && 00248 (!(curdev->flags & PCAP_IF_LOOPBACK) || 00249 (nextdev->flags & PCAP_IF_LOOPBACK))) { 00250 /* 00251 * Yes - we should put the new entry 00252 * before "nextdev", i.e. after "prevdev". 00253 */ 00254 break; 00255 } 00256 00257 prevdev = nextdev; 00258 } 00259 00260 /* 00261 * Insert before "nextdev". 00262 */ 00263 curdev->next = nextdev; 00264 00265 /* 00266 * Insert after "prevdev" - unless "prevdev" is null, 00267 * in which case this is the first interface. 00268 */ 00269 if (prevdev == NULL) { 00270 /* 00271 * This is the first interface. Pass back a 00272 * pointer to it, and put "curdev" before 00273 * "nextdev". 00274 */ 00275 *alldevs = curdev; 00276 } else 00277 prevdev->next = curdev; 00278 } 00279 00280 *curdev_ret = curdev; 00281 return (0); 00282 } 00283 00284 int 00285 add_addr_to_iflist(pcap_if_t **alldevs, char *name, u_int flags, 00286 struct sockaddr *addr, size_t addr_size, 00287 struct sockaddr *netmask, size_t netmask_size, 00288 struct sockaddr *broadaddr, size_t broadaddr_size, 00289 struct sockaddr *dstaddr, size_t dstaddr_size, 00290 char *errbuf) 00291 { 00292 pcap_if_t *curdev; 00293 pcap_addr_t *curaddr, *prevaddr, *nextaddr; 00294 00295 if (add_or_find_if(&curdev, alldevs, name, flags, NULL, errbuf) == -1) { 00296 /* 00297 * Error - give up. 00298 */ 00299 return (-1); 00300 } 00301 if (curdev == NULL) { 00302 /* 00303 * Device wasn't added because it can't be opened. 00304 * Not a fatal error. 00305 */ 00306 return (0); 00307 } 00308 00309 /* 00310 * "curdev" is an entry for this interface; add an entry for this 00311 * address to its list of addresses. 00312 * 00313 * Allocate the new entry and fill it in. 00314 */ 00315 curaddr = malloc(sizeof(pcap_addr_t)); 00316 if (curaddr == NULL) { 00317 (void)snprintf(errbuf, PCAP_ERRBUF_SIZE, 00318 "malloc: %s", pcap_strerror(errno)); 00319 return (-1); 00320 } 00321 00322 curaddr->next = NULL; 00323 if (addr != NULL) { 00324 curaddr->addr = dup_sockaddr(addr, addr_size); 00325 if (curaddr->addr == NULL) { 00326 (void)snprintf(errbuf, PCAP_ERRBUF_SIZE, 00327 "malloc: %s", pcap_strerror(errno)); 00328 free(curaddr); 00329 return (-1); 00330 } 00331 } else 00332 curaddr->addr = NULL; 00333 00334 if (netmask != NULL) { 00335 curaddr->netmask = dup_sockaddr(netmask, netmask_size); 00336 if (curaddr->netmask == NULL) { 00337 (void)snprintf(errbuf, PCAP_ERRBUF_SIZE, 00338 "malloc: %s", pcap_strerror(errno)); 00339 free(curaddr); 00340 return (-1); 00341 } 00342 } else 00343 curaddr->netmask = NULL; 00344 00345 if (broadaddr != NULL) { 00346 curaddr->broadaddr = dup_sockaddr(broadaddr, broadaddr_size); 00347 if (curaddr->broadaddr == NULL) { 00348 (void)snprintf(errbuf, PCAP_ERRBUF_SIZE, 00349 "malloc: %s", pcap_strerror(errno)); 00350 free(curaddr); 00351 return (-1); 00352 } 00353 } else 00354 curaddr->broadaddr = NULL; 00355 00356 if (dstaddr != NULL) { 00357 curaddr->dstaddr = dup_sockaddr(dstaddr, dstaddr_size); 00358 if (curaddr->dstaddr == NULL) { 00359 (void)snprintf(errbuf, PCAP_ERRBUF_SIZE, 00360 "malloc: %s", pcap_strerror(errno)); 00361 free(curaddr); 00362 return (-1); 00363 } 00364 } else 00365 curaddr->dstaddr = NULL; 00366 00367 /* 00368 * Find the end of the list of addresses. 00369 */ 00370 for (prevaddr = curdev->addresses; prevaddr != NULL; prevaddr = nextaddr) { 00371 nextaddr = prevaddr->next; 00372 if (nextaddr == NULL) { 00373 /* 00374 * This is the end of the list. 00375 */ 00376 break; 00377 } 00378 } 00379 00380 if (prevaddr == NULL) { 00381 /* 00382 * The list was empty; this is the first member. 00383 */ 00384 curdev->addresses = curaddr; 00385 } else { 00386 /* 00387 * "prevaddr" is the last member of the list; append 00388 * this member to it. 00389 */ 00390 prevaddr->next = curaddr; 00391 } 00392 00393 return (0); 00394 } 00395 00396 int 00397 pcap_add_if(pcap_if_t **devlist, char *name, u_int flags, 00398 const char *description, char *errbuf) 00399 { 00400 pcap_if_t *curdev; 00401 00402 return (add_or_find_if(&curdev, devlist, name, flags, description, 00403 errbuf)); 00404 } 00405 00406 00407 /* 00408 * Free a list of interfaces. 00409 */ 00410 void 00411 pcap_freealldevs(pcap_if_t *alldevs) 00412 { 00413 pcap_if_t *curdev, *nextdev; 00414 pcap_addr_t *curaddr, *nextaddr; 00415 00416 for (curdev = alldevs; curdev != NULL; curdev = nextdev) { 00417 nextdev = curdev->next; 00418 00419 /* 00420 * Free all addresses. 00421 */ 00422 for (curaddr = curdev->addresses; curaddr != NULL; curaddr = nextaddr) { 00423 nextaddr = curaddr->next; 00424 if (curaddr->addr) 00425 free(curaddr->addr); 00426 if (curaddr->netmask) 00427 free(curaddr->netmask); 00428 if (curaddr->broadaddr) 00429 free(curaddr->broadaddr); 00430 if (curaddr->dstaddr) 00431 free(curaddr->dstaddr); 00432 free(curaddr); 00433 } 00434 00435 /* 00436 * Free the name string. 00437 */ 00438 free(curdev->name); 00439 00440 /* 00441 * Free the description string, if any. 00442 */ 00443 if (curdev->description != NULL) 00444 free(curdev->description); 00445 00446 /* 00447 * Free the interface. 00448 */ 00449 free(curdev); 00450 } 00451 } 00452 00453 #ifndef WIN32 00454 00455 /* 00456 * Return the name of a network interface attached to the system, or NULL 00457 * if none can be found. The interface must be configured up; the 00458 * lowest unit number is preferred; loopback is ignored. 00459 */ 00460 char * 00461 pcap_lookupdev(errbuf) 00462 register char *errbuf; 00463 { 00464 pcap_if_t *alldevs; 00465 /* for old BSD systems, including bsdi3 */ 00466 #ifndef IF_NAMESIZE 00467 #define IF_NAMESIZE IFNAMSIZ 00468 #endif 00469 static char device[IF_NAMESIZE + 1]; 00470 char *ret; 00471 00472 if (pcap_findalldevs(&alldevs, errbuf) == -1) 00473 return (NULL); 00474 00475 if (alldevs == NULL || (alldevs->flags & PCAP_IF_LOOPBACK)) { 00476 /* 00477 * There are no devices on the list, or the first device 00478 * on the list is a loopback device, which means there 00479 * are no non-loopback devices on the list. This means 00480 * we can't return any device. 00481 * 00482 * XXX - why not return a loopback device? If we can't 00483 * capture on it, it won't be on the list, and if it's 00484 * on the list, there aren't any non-loopback devices, 00485 * so why not just supply it as the default device? 00486 */ 00487 (void)strlcpy(errbuf, "no suitable device found", 00488 PCAP_ERRBUF_SIZE); 00489 ret = NULL; 00490 } else { 00491 /* 00492 * Return the name of the first device on the list. 00493 */ 00494 (void)strlcpy(device, alldevs->name, sizeof(device)); 00495 ret = device; 00496 } 00497 00498 pcap_freealldevs(alldevs); 00499 return (ret); 00500 } 00501 00502 int 00503 pcap_lookupnet(device, netp, maskp, errbuf) 00504 register const char *device; 00505 register bpf_u_int32 *netp, *maskp; 00506 register char *errbuf; 00507 { 00508 register int fd; 00509 register struct sockaddr_in *sin; 00510 struct ifreq ifr; 00511 00512 /* 00513 * The pseudo-device "any" listens on all interfaces and therefore 00514 * has the network address and -mask "0.0.0.0" therefore catching 00515 * all traffic. Using NULL for the interface is the same as "any". 00516 */ 00517 if (!device || strcmp(device, "any") == 0 00518 #ifdef HAVE_DAG_API 00519 || strstr(device, "dag") != NULL 00520 #endif 00521 ) { 00522 *netp = *maskp = 0; 00523 return 0; 00524 } 00525 00526 fd = socket(AF_INET, SOCK_DGRAM, 0); 00527 if (fd < 0) { 00528 (void)snprintf(errbuf, PCAP_ERRBUF_SIZE, "socket: %s", 00529 pcap_strerror(errno)); 00530 return (-1); 00531 } 00532 memset(&ifr, 0, sizeof(ifr)); 00533 #ifdef linux 00534 /* XXX Work around Linux kernel bug */ 00535 ifr.ifr_addr.sa_family = AF_INET; 00536 #endif 00537 (void)strncpy(ifr.ifr_name, device, sizeof(ifr.ifr_name)); 00538 if (ioctl(fd, SIOCGIFADDR, (char *)&ifr) < 0) { 00539 if (errno == EADDRNOTAVAIL) { 00540 (void)snprintf(errbuf, PCAP_ERRBUF_SIZE, 00541 "%s: no IPv4 address assigned", device); 00542 } else { 00543 (void)snprintf(errbuf, PCAP_ERRBUF_SIZE, 00544 "SIOCGIFADDR: %s: %s", 00545 device, pcap_strerror(errno)); 00546 } 00547 (void)close(fd); 00548 return (-1); 00549 } 00550 sin = (struct sockaddr_in *)&ifr.ifr_addr; 00551 *netp = sin->sin_addr.s_addr; 00552 if (ioctl(fd, SIOCGIFNETMASK, (char *)&ifr) < 0) { 00553 (void)snprintf(errbuf, PCAP_ERRBUF_SIZE, 00554 "SIOCGIFNETMASK: %s: %s", device, pcap_strerror(errno)); 00555 (void)close(fd); 00556 return (-1); 00557 } 00558 (void)close(fd); 00559 *maskp = sin->sin_addr.s_addr; 00560 if (*maskp == 0) { 00561 if (IN_CLASSA(*netp)) 00562 *maskp = IN_CLASSA_NET; 00563 else if (IN_CLASSB(*netp)) 00564 *maskp = IN_CLASSB_NET; 00565 else if (IN_CLASSC(*netp)) 00566 *maskp = IN_CLASSC_NET; 00567 else { 00568 (void)snprintf(errbuf, PCAP_ERRBUF_SIZE, 00569 "inet class for 0x%x unknown", *netp); 00570 return (-1); 00571 } 00572 } 00573 *netp &= *maskp; 00574 return (0); 00575 } 00576 00577 #else /* WIN32 */ 00578 00579 /* 00580 * Return the name of a network interface attached to the system, or NULL 00581 * if none can be found. The interface must be configured up; the 00582 * lowest unit number is preferred; loopback is ignored. 00583 */ 00584 char * 00585 pcap_lookupdev(errbuf) 00586 register char *errbuf; 00587 { 00588 DWORD dwVersion; 00589 DWORD dwWindowsMajorVersion; 00590 dwVersion = GetVersion(); /* get the OS version */ 00591 dwWindowsMajorVersion = (DWORD)(LOBYTE(LOWORD(dwVersion))); 00592 00593 if (dwVersion >= 0x80000000 && dwWindowsMajorVersion >= 4) { 00594 /* 00595 * Windows 95, 98, ME. 00596 */ 00597 ULONG NameLength = 8192; 00598 static char AdaptersName[8192]; 00599 00600 if (PacketGetAdapterNames(AdaptersName,&NameLength) ) 00601 return (AdaptersName); 00602 else 00603 return NULL; 00604 } else { 00605 /* 00606 * Windows NT (NT 4.0, W2K, WXP). Convert the names to UNICODE for backward compatibility 00607 */ 00608 ULONG NameLength = 8192; 00609 static WCHAR AdaptersName[8192]; 00610 char *tAstr; 00611 WCHAR *tUstr; 00612 WCHAR *TAdaptersName = (WCHAR*)malloc(8192 * sizeof(WCHAR)); 00613 int NAdapts = 0; 00614 00615 if(TAdaptersName == NULL) 00616 { 00617 (void)snprintf(errbuf, PCAP_ERRBUF_SIZE, "memory allocation failure"); 00618 return NULL; 00619 } 00620 00621 if ( !PacketGetAdapterNames((PTSTR)TAdaptersName,&NameLength) ) 00622 { 00623 (void)snprintf(errbuf, PCAP_ERRBUF_SIZE, 00624 "PacketGetAdapterNames: %s", 00625 pcap_win32strerror()); 00626 free(TAdaptersName); 00627 return NULL; 00628 } 00629 00630 00631 tAstr = (char*)TAdaptersName; 00632 tUstr = (WCHAR*)AdaptersName; 00633 00634 /* 00635 * Convert and copy the device names 00636 */ 00637 while(sscanf(tAstr, "%S", tUstr) > 0) 00638 { 00639 tAstr += strlen(tAstr) + 1; 00640 tUstr += wcslen(tUstr) + 1; 00641 NAdapts ++; 00642 } 00643 00644 tAstr++; 00645 *tUstr = 0; 00646 tUstr++; 00647 00648 /* 00649 * Copy the descriptions 00650 */ 00651 while(NAdapts--) 00652 { 00653 strcpy((char*)tUstr, tAstr); 00654 (char*)tUstr += strlen(tAstr) + 1;; 00655 tAstr += strlen(tAstr) + 1; 00656 } 00657 00658 free(TAdaptersName); 00659 return (char *)(AdaptersName); 00660 } 00661 } 00662 00663 00664 int 00665 pcap_lookupnet(device, netp, maskp, errbuf) 00666 const register char *device; 00667 register bpf_u_int32 *netp, *maskp; 00668 register char *errbuf; 00669 { 00670 /* 00671 * We need only the first IPv4 address, so we must scan the array returned by PacketGetNetInfo() 00672 * in order to skip non IPv4 (i.e. IPv6 addresses) 00673 */ 00674 npf_if_addr if_addrs[MAX_NETWORK_ADDRESSES]; 00675 LONG if_addr_size = 1; 00676 struct sockaddr_in *t_addr; 00677 unsigned int i; 00678 00679 if (!PacketGetNetInfoEx((void *)device, if_addrs, &if_addr_size)) { 00680 *netp = *maskp = 0; 00681 return (0); 00682 } 00683 00684 for(i=0; i<MAX_NETWORK_ADDRESSES; i++) 00685 { 00686 if(if_addrs[i].IPAddress.ss_family == AF_INET) 00687 { 00688 t_addr = (struct sockaddr_in *) &(if_addrs[i].IPAddress); 00689 *netp = t_addr->sin_addr.S_un.S_addr; 00690 t_addr = (struct sockaddr_in *) &(if_addrs[i].SubnetMask); 00691 *maskp = t_addr->sin_addr.S_un.S_addr; 00692 00693 *netp &= *maskp; 00694 return (0); 00695 } 00696 00697 } 00698 00699 *netp = *maskp = 0; 00700 return (0); 00701 } 00702 00703 #endif /* WIN32 */

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