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.