Main Page   Modules   Data Structures   File List   Data Fields   Globals  

fad-win32.c

Go to the documentation of this file.
00001 /*
00002  * Copyright (c) 1999, 2002
00003  *  Politecnico di Torino.  All rights reserved.
00004  *
00005  * Redistribution and use in source and binary forms, with or without
00006  * modification, are permitted provided that: (1) source code distributions
00007  * retain the above copyright notice and this paragraph in its entirety, (2)
00008  * distributions including binary code include the above copyright notice and
00009  * this paragraph in its entirety in the documentation or other materials
00010  * provided with the distribution, and (3) all advertising materials mentioning
00011  * features or use of this software display the following acknowledgement:
00012  * ``This product includes software developed by the Politecnico
00013  * di Torino, and its contributors.'' Neither the name of
00014  * the University nor the names of its contributors may be used to endorse
00015  * or promote products derived from this software without specific prior
00016  * written permission.
00017  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
00018  * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
00019  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
00020  */
00021 
00022 #ifdef HAVE_CONFIG_H
00023 #include "config.h"
00024 #endif
00025 
00026 #include <pcap.h>
00027 #include <packet32.h>
00028 
00029 #include <errno.h>
00030 
00031 #ifndef SA_LEN
00032 #ifdef HAVE_SOCKADDR_SA_LEN
00033 #define SA_LEN(addr)    ((addr)->sa_len)
00034 #else /* HAVE_SOCKADDR_SA_LEN */
00035 #define SA_LEN(addr)    (sizeof (struct sockaddr))
00036 #endif /* HAVE_SOCKADDR_SA_LEN */
00037 #endif /* SA_LEN */
00038 
00039 /*
00040  * Add an entry to the list of addresses for an interface.
00041  * "curdev" is the entry for that interface.
00042  */
00043 static int
00044 add_addr_to_list(pcap_if_t *curdev, struct sockaddr *addr,
00045     struct sockaddr *netmask, struct sockaddr *broadaddr,
00046     struct sockaddr *dstaddr, char *errbuf)
00047 {
00048     pcap_addr_t *curaddr, *prevaddr, *nextaddr;
00049 
00050     /*
00051      * Allocate the new entry and fill it in.
00052      */
00053     curaddr = (pcap_addr_t*)malloc(sizeof(pcap_addr_t));
00054     if (curaddr == NULL) {
00055         (void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
00056             "malloc: %s", pcap_strerror(errno));
00057         return (-1);
00058     }
00059 
00060     curaddr->next = NULL;
00061     if (addr != NULL) {
00062         curaddr->addr = (struct sockaddr*)dup_sockaddr(addr, SA_LEN(addr));
00063         if (curaddr->addr == NULL) {
00064             (void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
00065                 "malloc: %s", pcap_strerror(errno));
00066             free(curaddr);
00067             return (-1);
00068         }
00069     } else
00070         curaddr->addr = NULL;
00071 
00072     if (netmask != NULL) {
00073         curaddr->netmask = (struct sockaddr*)dup_sockaddr(netmask, SA_LEN(netmask));
00074         if (curaddr->netmask == NULL) {
00075             (void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
00076                 "malloc: %s", pcap_strerror(errno));
00077             free(curaddr);
00078             return (-1);
00079         }
00080     } else
00081         curaddr->netmask = NULL;
00082         
00083     if (broadaddr != NULL) {
00084         curaddr->broadaddr = (struct sockaddr*)dup_sockaddr(broadaddr, SA_LEN(broadaddr));
00085         if (curaddr->broadaddr == NULL) {
00086             (void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
00087                 "malloc: %s", pcap_strerror(errno));
00088             free(curaddr);
00089             return (-1);
00090         }
00091     } else
00092         curaddr->broadaddr = NULL;
00093         
00094     if (dstaddr != NULL) {
00095         curaddr->dstaddr = (struct sockaddr*)dup_sockaddr(dstaddr, SA_LEN(dstaddr));
00096         if (curaddr->dstaddr == NULL) {
00097             (void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
00098                 "malloc: %s", pcap_strerror(errno));
00099             free(curaddr);
00100             return (-1);
00101         }
00102     } else
00103         curaddr->dstaddr = NULL;
00104         
00105     /*
00106      * Find the end of the list of addresses.
00107      */
00108     for (prevaddr = curdev->addresses; prevaddr != NULL; prevaddr = nextaddr) {
00109         nextaddr = prevaddr->next;
00110         if (nextaddr == NULL) {
00111             /*
00112              * This is the end of the list.
00113              */
00114             break;
00115         }
00116     }
00117 
00118     if (prevaddr == NULL) {
00119         /*
00120          * The list was empty; this is the first member.
00121          */
00122         curdev->addresses = curaddr;
00123     } else {
00124         /*
00125          * "prevaddr" is the last member of the list; append
00126          * this member to it.
00127          */
00128         prevaddr->next = curaddr;
00129     }
00130 
00131     return (0);
00132 }
00133 
00134 
00135 static int
00136 pcap_add_if_win32(pcap_if_t **devlist, char *name, const char *desc,
00137     char *errbuf)
00138 {
00139     pcap_if_t *curdev;
00140     npf_if_addr if_addrs[16];
00141     LONG if_addr_size;
00142     int res = 0;
00143     struct sockaddr_in *addr, *netmask;
00144 
00145     if_addr_size = 16;
00146 
00147     /*
00148      * Add an entry for this interface, with no addresses.
00149      */
00150     if (add_or_find_if(&curdev, devlist, (char *)name, 0, (char *)desc,
00151         errbuf) == -1) {
00152         /*
00153          * Failure.
00154          */
00155         return (-1);
00156     }
00157 
00158     /*
00159      * Get the list of addresses for the interface.
00160      *
00161      * XXX - what about IPv6?
00162      */
00163     if (!PacketGetNetInfoEx((void *)name, if_addrs, &if_addr_size)) {
00164         /*
00165          * Failure. Return A succesful code, but don't add any address to the list
00166          */
00167 
00168         return 0;
00169     }
00170 
00171     /*
00172      * Now add the addresses.
00173      */
00174     while (if_addr_size-- > 0) {
00175         /*
00176          * "curdev" is an entry for this interface; add an entry for
00177          * this address to its list of addresses.
00178          */
00179         if(curdev == NULL)
00180             break;
00181         res = add_addr_to_list(curdev,
00182             (struct sockaddr *)&if_addrs[if_addr_size].IPAddress,
00183             (struct sockaddr *)&if_addrs[if_addr_size].SubnetMask,
00184             (struct sockaddr *)&if_addrs[if_addr_size].Broadcast,
00185             NULL,
00186             errbuf);
00187         if (res == -1) {
00188             /*
00189              * Failure.
00190              */
00191             break;
00192         }
00193     }
00194 
00195     return (res);
00196 }
00197 
00198 
00199 /*
00200  * Get a list of all interfaces that are up and that we can open.
00201  * Returns -1 on error, 0 otherwise.
00202  * The list, as returned through "alldevsp", may be null if no interfaces
00203  * were up and could be opened.
00204  *
00205  * Win32 implementation, based on WinPcap
00206  */
00207 int
00208 pcap_findalldevs(pcap_if_t **alldevsp, char *errbuf)
00209 {
00210     pcap_if_t *devlist = NULL;
00211     DWORD dwVersion;
00212     DWORD dwWindowsMajorVersion;
00213     int ret = 0;
00214     const char *desc;
00215 
00216     dwVersion = GetVersion();   /* get the OS version */
00217     dwWindowsMajorVersion =  (DWORD)(LOBYTE(LOWORD(dwVersion)));
00218     if (dwVersion >= 0x80000000 && dwWindowsMajorVersion >= 4) {
00219         /*
00220          * Windows 95, 98, ME.
00221          */
00222         char AdaptersName[8192];
00223         ULONG NameLength = 8192;
00224         char *name;
00225 
00226         if (!PacketGetAdapterNames(AdaptersName, &NameLength)) {
00227             snprintf(errbuf, PCAP_ERRBUF_SIZE,
00228                 "PacketGetAdapterNames: %s",
00229                 pcap_win32strerror());
00230             return (-1);
00231         }
00232 
00233         /*
00234          * "PacketGetAdapterNames()" returned a list of
00235          * null-terminated ASCII interface name strings,
00236          * terminated by a null string, followed by a list
00237          * of null-terminated ASCII interface description
00238          * strings, terminated by a null string.
00239          * This means there are two ASCII nulls at the end
00240          * of the first list.
00241          *
00242          * Find the end of the first list; that's the
00243          * beginning of the second list.
00244          */
00245         desc = &AdaptersName[0];
00246         while (*desc != '\0' || *(desc + 1) != '\0')
00247             desc++;
00248 
00249         /*
00250          * Found it - "desc" points to the first of the two
00251          * nulls at the end of the list of names, so the
00252          * first byte of the list of descriptions is two bytes
00253          * after it.
00254          */
00255         desc += 2;
00256 
00257         /*
00258          * Loop over the elements in the first list.
00259          */
00260         name = &AdaptersName[0];
00261         while (*name != '\0') {
00262             /*
00263              * Add an entry for this interface.
00264              */
00265             if (pcap_add_if_win32(&devlist, name, desc,
00266                 errbuf) == -1) {
00267                 /*
00268                  * Failure.
00269                  */
00270                 ret = -1;
00271                 break;
00272             }
00273             name += strlen(name) + 1;
00274             desc += strlen(desc) + 1;
00275         }
00276     } else {
00277         /*
00278          * Windows NT (NT 4.0, W2K, WXP).
00279          */
00280         WCHAR AdaptersName[8192];
00281         ULONG NameLength = 8192;
00282         const WCHAR *t;
00283         WCHAR *uc_name;
00284         char ascii_name[8192];
00285         char ascii_desc[8192];
00286         char *p;
00287 
00288         if (!PacketGetAdapterNames((PTSTR)AdaptersName, &NameLength)) {
00289             snprintf(errbuf, PCAP_ERRBUF_SIZE,
00290                 "PacketGetAdapterNames: %s",
00291                 pcap_win32strerror());
00292             return (-1);
00293         }
00294 
00295         /*
00296          * "PacketGetAdapterNames()" returned a list of
00297          * null-terminated Unicode interface name strings,
00298          * terminated by a null string, followed by a list
00299          * of null-terminated ASCII interface description
00300          * strings, terminated by a null string.
00301          * This means there are two Unicode nulls at the end
00302          * of the first list.
00303          *
00304          * Find the end of the first list; that's the
00305          * beginning of the second list.
00306          */
00307         t = &AdaptersName[0];
00308         while (*t != '\0' || *(t + 1) != '\0')
00309             t++;
00310 
00311         /*
00312          * Found it - "t" points to the first of the two
00313          * nulls at the end of the list of names, so the
00314          * first byte of the list of descriptions is two wide
00315          * characters after it.
00316          */
00317         t += 2;
00318         desc = (const char *)t;
00319 
00320         /*
00321          * Loop over the elements in the first list.
00322          *
00323          * We assume all characters in the name string are valid
00324          * ASCII characters.
00325          */
00326         uc_name = &AdaptersName[0];
00327         while (*uc_name != '\0') {
00328             p = ascii_name;
00329             while ((*p++ = (char)*uc_name++) != '\0')
00330                 ;
00331             p = ascii_desc;
00332             while ((*p++ = *desc++) != '\0')
00333                 ;
00334 
00335             /*
00336              * Add an entry for this interface.
00337              */
00338             if (pcap_add_if_win32(&devlist, ascii_name,
00339                 ascii_desc, errbuf) == -1) {
00340                 /*
00341                  * Failure.
00342                  */
00343                 ret = -1;
00344                 break;
00345             }
00346         }
00347     }
00348 
00349     if (ret == -1) {
00350         /*
00351          * We had an error; free the list we've been constructing.
00352          */
00353         if (devlist != NULL) {
00354             pcap_freealldevs(devlist);
00355             devlist = NULL;
00356         }
00357     }
00358 
00359     *alldevsp = devlist;
00360     return (ret);
00361 }

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