]> The Tcpdump Group git mirrors - libpcap/blob - fad-win32.c
Added a pcap_pkthdr field to the pcap structure. It is needed by pcap_next_ex().
[libpcap] / fad-win32.c
1 /*
2 * Copyright (c) 1999, 2002
3 * Politecnico di Torino. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that: (1) source code distributions
7 * retain the above copyright notice and this paragraph in its entirety, (2)
8 * distributions including binary code include the above copyright notice and
9 * this paragraph in its entirety in the documentation or other materials
10 * provided with the distribution, and (3) all advertising materials mentioning
11 * features or use of this software display the following acknowledgement:
12 * ``This product includes software developed by the Politecnico
13 * di Torino, and its contributors.'' Neither the name of
14 * the University nor the names of its contributors may be used to endorse
15 * or promote products derived from this software without specific prior
16 * written permission.
17 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
18 * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
19 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
20 */
21
22 #ifndef lint
23 static const char rcsid[] =
24 "@(#) $Header: /tcpdump/master/libpcap/fad-win32.c,v 1.5 2003-03-12 13:28:54 risso Exp $ (LBL)";
25 #endif
26
27 #ifdef HAVE_CONFIG_H
28 #include "config.h"
29 #endif
30
31 #include <pcap.h>
32 #include <pcap-int.h>
33 #include <packet32.h>
34
35 #include <errno.h>
36
37 #ifndef SA_LEN
38 #ifdef HAVE_SOCKADDR_SA_LEN
39 #define SA_LEN(addr) ((addr)->sa_len)
40 #else /* HAVE_SOCKADDR_SA_LEN */
41 #define SA_LEN(addr) (sizeof (struct sockaddr))
42 #endif /* HAVE_SOCKADDR_SA_LEN */
43 #endif /* SA_LEN */
44
45 /*
46 * Add an entry to the list of addresses for an interface.
47 * "curdev" is the entry for that interface.
48 */
49 static int
50 add_addr_to_list(pcap_if_t *curdev, struct sockaddr *addr,
51 struct sockaddr *netmask, struct sockaddr *broadaddr,
52 struct sockaddr *dstaddr, char *errbuf)
53 {
54 pcap_addr_t *curaddr, *prevaddr, *nextaddr;
55
56 /*
57 * Allocate the new entry and fill it in.
58 */
59 curaddr = (pcap_addr_t*)malloc(sizeof(pcap_addr_t));
60 if (curaddr == NULL) {
61 (void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
62 "malloc: %s", pcap_strerror(errno));
63 return (-1);
64 }
65
66 curaddr->next = NULL;
67 if (addr != NULL) {
68 curaddr->addr = (struct sockaddr*)dup_sockaddr(addr, SA_LEN(addr));
69 if (curaddr->addr == NULL) {
70 (void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
71 "malloc: %s", pcap_strerror(errno));
72 free(curaddr);
73 return (-1);
74 }
75 } else
76 curaddr->addr = NULL;
77
78 if (netmask != NULL) {
79 curaddr->netmask = (struct sockaddr*)dup_sockaddr(netmask, SA_LEN(netmask));
80 if (curaddr->netmask == NULL) {
81 (void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
82 "malloc: %s", pcap_strerror(errno));
83 free(curaddr);
84 return (-1);
85 }
86 } else
87 curaddr->netmask = NULL;
88
89 if (broadaddr != NULL) {
90 curaddr->broadaddr = (struct sockaddr*)dup_sockaddr(broadaddr, SA_LEN(broadaddr));
91 if (curaddr->broadaddr == NULL) {
92 (void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
93 "malloc: %s", pcap_strerror(errno));
94 free(curaddr);
95 return (-1);
96 }
97 } else
98 curaddr->broadaddr = NULL;
99
100 if (dstaddr != NULL) {
101 curaddr->dstaddr = (struct sockaddr*)dup_sockaddr(dstaddr, SA_LEN(dstaddr));
102 if (curaddr->dstaddr == NULL) {
103 (void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
104 "malloc: %s", pcap_strerror(errno));
105 free(curaddr);
106 return (-1);
107 }
108 } else
109 curaddr->dstaddr = NULL;
110
111 /*
112 * Find the end of the list of addresses.
113 */
114 for (prevaddr = curdev->addresses; prevaddr != NULL; prevaddr = nextaddr) {
115 nextaddr = prevaddr->next;
116 if (nextaddr == NULL) {
117 /*
118 * This is the end of the list.
119 */
120 break;
121 }
122 }
123
124 if (prevaddr == NULL) {
125 /*
126 * The list was empty; this is the first member.
127 */
128 curdev->addresses = curaddr;
129 } else {
130 /*
131 * "prevaddr" is the last member of the list; append
132 * this member to it.
133 */
134 prevaddr->next = curaddr;
135 }
136
137 return (0);
138 }
139
140
141 static int
142 pcap_add_if_win32(pcap_if_t **devlist, char *name, const char *desc,
143 char *errbuf)
144 {
145 pcap_if_t *curdev;
146 npf_if_addr if_addrs[16];
147 LONG if_addr_size;
148 int res = 0;
149
150 if_addr_size = 16;
151
152 /*
153 * Add an entry for this interface, with no addresses.
154 */
155 if (add_or_find_if(&curdev, devlist, (char *)name, 0, (char *)desc,
156 errbuf) == -1) {
157 /*
158 * Failure.
159 */
160 return (-1);
161 }
162
163 /*
164 * Get the list of addresses for the interface.
165 *
166 * XXX - what about IPv6?
167 */
168 if (!PacketGetNetInfoEx((void *)name, if_addrs, &if_addr_size)) {
169 /*
170 * Failure.
171 *
172 * We don't return an error, because this can happen with
173 * NdisWan interfaces, and we want to supply them even
174 * if we can't supply their addresses.
175 *
176 * We return an entry with an empty address list.
177 */
178 return (0);
179 }
180
181 /*
182 * Now add the addresses.
183 */
184 while (if_addr_size-- > 0) {
185 /*
186 * "curdev" is an entry for this interface; add an entry for
187 * this address to its list of addresses.
188 */
189 if(curdev == NULL)
190 break;
191 res = add_addr_to_list(curdev,
192 (struct sockaddr *)&if_addrs[if_addr_size].IPAddress,
193 (struct sockaddr *)&if_addrs[if_addr_size].SubnetMask,
194 (struct sockaddr *)&if_addrs[if_addr_size].Broadcast,
195 NULL,
196 errbuf);
197 if (res == -1) {
198 /*
199 * Failure.
200 */
201 break;
202 }
203 }
204
205 return (res);
206 }
207
208
209 /*
210 * Get a list of all interfaces that are up and that we can open.
211 * Returns -1 on error, 0 otherwise.
212 * The list, as returned through "alldevsp", may be null if no interfaces
213 * were up and could be opened.
214 *
215 * Win32 implementation, based on WinPcap
216 */
217 int
218 pcap_findalldevs(pcap_if_t **alldevsp, char *errbuf)
219 {
220 pcap_if_t *devlist = NULL;
221 DWORD dwVersion;
222 DWORD dwWindowsMajorVersion;
223 int ret = 0;
224 const char *desc;
225
226 dwVersion = GetVersion(); /* get the OS version */
227 dwWindowsMajorVersion = (DWORD)(LOBYTE(LOWORD(dwVersion)));
228 if (dwVersion >= 0x80000000 && dwWindowsMajorVersion >= 4) {
229 /*
230 * Windows 95, 98, ME.
231 */
232 char AdaptersName[8192];
233 ULONG NameLength = 8192;
234 char *name;
235
236 if (!PacketGetAdapterNames(AdaptersName, &NameLength)) {
237 snprintf(errbuf, PCAP_ERRBUF_SIZE,
238 "PacketGetAdapterNames: %s",
239 pcap_win32strerror());
240 return (-1);
241 }
242
243 /*
244 * "PacketGetAdapterNames()" returned a list of
245 * null-terminated ASCII interface name strings,
246 * terminated by a null string, followed by a list
247 * of null-terminated ASCII interface description
248 * strings, terminated by a null string.
249 * This means there are two ASCII nulls at the end
250 * of the first list.
251 *
252 * Find the end of the first list; that's the
253 * beginning of the second list.
254 */
255 desc = &AdaptersName[0];
256 while (*desc != '\0' || *(desc + 1) != '\0')
257 desc++;
258
259 /*
260 * Found it - "desc" points to the first of the two
261 * nulls at the end of the list of names, so the
262 * first byte of the list of descriptions is two bytes
263 * after it.
264 */
265 desc += 2;
266
267 /*
268 * Loop over the elements in the first list.
269 */
270 name = &AdaptersName[0];
271 while (*name != '\0') {
272 /*
273 * Add an entry for this interface.
274 */
275 if (pcap_add_if_win32(&devlist, name, desc,
276 errbuf) == -1) {
277 /*
278 * Failure.
279 */
280 ret = -1;
281 break;
282 }
283 name += strlen(name) + 1;
284 desc += strlen(desc) + 1;
285 }
286 } else {
287 /*
288 * Windows NT (NT 4.0, W2K, WXP).
289 */
290 WCHAR AdaptersName[8192];
291 ULONG NameLength = 8192;
292 const WCHAR *t;
293 WCHAR *uc_name;
294 char ascii_name[8192];
295 char ascii_desc[8192];
296 char *p;
297
298 if (!PacketGetAdapterNames((PTSTR)AdaptersName, &NameLength)) {
299 snprintf(errbuf, PCAP_ERRBUF_SIZE,
300 "PacketGetAdapterNames: %s",
301 pcap_win32strerror());
302 return (-1);
303 }
304
305 /*
306 * "PacketGetAdapterNames()" returned a list of
307 * null-terminated Unicode interface name strings,
308 * terminated by a null string, followed by a list
309 * of null-terminated ASCII interface description
310 * strings, terminated by a null string.
311 * This means there are two Unicode nulls at the end
312 * of the first list.
313 *
314 * Find the end of the first list; that's the
315 * beginning of the second list.
316 */
317 t = &AdaptersName[0];
318 while (*t != '\0' || *(t + 1) != '\0')
319 t++;
320
321 /*
322 * Found it - "t" points to the first of the two
323 * nulls at the end of the list of names, so the
324 * first byte of the list of descriptions is two wide
325 * characters after it.
326 */
327 t += 2;
328 desc = (const char *)t;
329
330 /*
331 * Loop over the elements in the first list.
332 *
333 * We assume all characters in the name string are valid
334 * ASCII characters.
335 */
336 uc_name = &AdaptersName[0];
337 while (*uc_name != '\0') {
338 p = ascii_name;
339 while ((*p++ = (char)*uc_name++) != '\0')
340 ;
341 p = ascii_desc;
342 while ((*p++ = *desc++) != '\0')
343 ;
344
345 /*
346 * Add an entry for this interface.
347 */
348 if (pcap_add_if_win32(&devlist, ascii_name,
349 ascii_desc, errbuf) == -1) {
350 /*
351 * Failure.
352 */
353 ret = -1;
354 break;
355 }
356 }
357 }
358
359 if (ret == -1) {
360 /*
361 * We had an error; free the list we've been constructing.
362 */
363 if (devlist != NULL) {
364 pcap_freealldevs(devlist);
365 devlist = NULL;
366 }
367 }
368
369 *alldevsp = devlist;
370 return (ret);
371 }