1 /*
2  * Copyright (c) 2002 - 2005 NetGroup, Politecnico di Torino (Italy)
3  * Copyright (c) 2005 - 2006 CACE Technologies, Davis (California)
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  *
10  * 1. Redistributions of source code must retain the above copyright
11  * notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  * notice, this list of conditions and the following disclaimer in the
14  * documentation and/or other materials provided with the distribution.
15  * 3. Neither the name of the Politecnico di Torino, CACE Technologies
16  * nor the names of its contributors may be used to endorse or promote
17  * products derived from this software without specific prior written
18  * permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31  *
32  */
33 
34 #ifndef lint
35 static const char rcsid[] _U_ =
36     "@(#) $Header: /tcpdump/master/libpcap/fad-win32.c,v 1.15 2007-09-25 20:34:36 guy Exp $ (LBL)";
37 #endif
38 
39 #ifdef HAVE_CONFIG_H
40 #include "config.h"
41 #endif
42 
43 #include <pcap.h>
44 #include <pcap-int.h>
45 #include <Packet32.h>
46 
47 #include <errno.h>
48 
49 /*
50  * Add an entry to the list of addresses for an interface.
51  * "curdev" is the entry for that interface.
52  */
53 static int
add_addr_to_list(pcap_if_t * curdev,struct sockaddr * addr,struct sockaddr * netmask,struct sockaddr * broadaddr,struct sockaddr * dstaddr,char * errbuf)54 add_addr_to_list(pcap_if_t *curdev, struct sockaddr *addr,
55     struct sockaddr *netmask, struct sockaddr *broadaddr,
56     struct sockaddr *dstaddr, char *errbuf)
57 {
58 	pcap_addr_t *curaddr, *prevaddr, *nextaddr;
59 
60 	/*
61 	 * Allocate the new entry and fill it in.
62 	 */
63 	curaddr = (pcap_addr_t*)malloc(sizeof(pcap_addr_t));
64 	if (curaddr == NULL) {
65 		(void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
66 		    "malloc: %s", pcap_strerror(errno));
67 		return (-1);
68 	}
69 
70 	curaddr->next = NULL;
71 	if (addr != NULL) {
72 		curaddr->addr = (struct sockaddr*)dup_sockaddr(addr, sizeof(struct sockaddr_storage));
73 		if (curaddr->addr == NULL) {
74 			(void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
75 			    "malloc: %s", pcap_strerror(errno));
76 			free(curaddr);
77 			return (-1);
78 		}
79 	} else
80 		curaddr->addr = NULL;
81 
82 	if (netmask != NULL) {
83 		curaddr->netmask = (struct sockaddr*)dup_sockaddr(netmask, sizeof(struct sockaddr_storage));
84 		if (curaddr->netmask == NULL) {
85 			(void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
86 			    "malloc: %s", pcap_strerror(errno));
87 			free(curaddr);
88 			return (-1);
89 		}
90 	} else
91 		curaddr->netmask = NULL;
92 
93 	if (broadaddr != NULL) {
94 		curaddr->broadaddr = (struct sockaddr*)dup_sockaddr(broadaddr, sizeof(struct sockaddr_storage));
95 		if (curaddr->broadaddr == NULL) {
96 			(void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
97 			    "malloc: %s", pcap_strerror(errno));
98 			free(curaddr);
99 			return (-1);
100 		}
101 	} else
102 		curaddr->broadaddr = NULL;
103 
104 	if (dstaddr != NULL) {
105 		curaddr->dstaddr = (struct sockaddr*)dup_sockaddr(dstaddr, sizeof(struct sockaddr_storage));
106 		if (curaddr->dstaddr == NULL) {
107 			(void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
108 			    "malloc: %s", pcap_strerror(errno));
109 			free(curaddr);
110 			return (-1);
111 		}
112 	} else
113 		curaddr->dstaddr = NULL;
114 
115 	/*
116 	 * Find the end of the list of addresses.
117 	 */
118 	for (prevaddr = curdev->addresses; prevaddr != NULL; prevaddr = nextaddr) {
119 		nextaddr = prevaddr->next;
120 		if (nextaddr == NULL) {
121 			/*
122 			 * This is the end of the list.
123 			 */
124 			break;
125 		}
126 	}
127 
128 	if (prevaddr == NULL) {
129 		/*
130 		 * The list was empty; this is the first member.
131 		 */
132 		curdev->addresses = curaddr;
133 	} else {
134 		/*
135 		 * "prevaddr" is the last member of the list; append
136 		 * this member to it.
137 		 */
138 		prevaddr->next = curaddr;
139 	}
140 
141 	return (0);
142 }
143 
144 
145 static int
pcap_add_if_win32(pcap_if_t ** devlist,char * name,const char * desc,char * errbuf)146 pcap_add_if_win32(pcap_if_t **devlist, char *name, const char *desc,
147     char *errbuf)
148 {
149 	pcap_if_t *curdev;
150 	npf_if_addr if_addrs[MAX_NETWORK_ADDRESSES];
151 	LONG if_addr_size;
152 	int res = 0;
153 
154 	if_addr_size = MAX_NETWORK_ADDRESSES;
155 
156 	/*
157 	 * Add an entry for this interface, with no addresses.
158 	 */
159 	if (add_or_find_if(&curdev, devlist, name, 0, desc, errbuf) == -1) {
160 		/*
161 		 * Failure.
162 		 */
163 		return (-1);
164 	}
165 
166 	/*
167 	 * Get the list of addresses for the interface.
168 	 */
169 	if (!PacketGetNetInfoEx((void *)name, if_addrs, &if_addr_size)) {
170 		/*
171 		 * Failure.
172 		 *
173 		 * We don't return an error, because this can happen with
174 		 * NdisWan interfaces, and we want to supply them even
175 		 * if we can't supply their addresses.
176 		 *
177 		 * We return an entry with an empty address list.
178 		 */
179 		return (0);
180 	}
181 
182 	/*
183 	 * Now add the addresses.
184 	 */
185 	while (if_addr_size-- > 0) {
186 		/*
187 		 * "curdev" is an entry for this interface; add an entry for
188 		 * this address to its list of addresses.
189 		 */
190 		if(curdev == NULL)
191 			break;
192 		res = add_addr_to_list(curdev,
193 		    (struct sockaddr *)&if_addrs[if_addr_size].IPAddress,
194 		    (struct sockaddr *)&if_addrs[if_addr_size].SubnetMask,
195 		    (struct sockaddr *)&if_addrs[if_addr_size].Broadcast,
196 		    NULL,
197 			errbuf);
198 		if (res == -1) {
199 			/*
200 			 * Failure.
201 			 */
202 			break;
203 		}
204 	}
205 
206 	return (res);
207 }
208 
209 
210 /*
211  * Get a list of all interfaces that are up and that we can open.
212  * Returns -1 on error, 0 otherwise.
213  * The list, as returned through "alldevsp", may be null if no interfaces
214  * were up and could be opened.
215  *
216  * Win32 implementation, based on WinPcap
217  */
218 int
pcap_findalldevs_interfaces(pcap_if_t ** alldevsp,char * errbuf)219 pcap_findalldevs_interfaces(pcap_if_t **alldevsp, char *errbuf)
220 {
221 	pcap_if_t *devlist = NULL;
222 	int ret = 0;
223 	const char *desc;
224 	char *AdaptersName;
225 	ULONG NameLength;
226 	char *name;
227 
228 	/*
229 	 * Find out how big a buffer we need.
230 	 *
231 	 * This call should always return FALSE; if the error is
232 	 * ERROR_INSUFFICIENT_BUFFER, NameLength will be set to
233 	 * the size of the buffer we need, otherwise there's a
234 	 * problem, and NameLength should be set to 0.
235 	 *
236 	 * It shouldn't require NameLength to be set, but,
237 	 * at least as of WinPcap 4.1.3, it checks whether
238 	 * NameLength is big enough before it checks for a
239 	 * NULL buffer argument, so, while it'll still do
240 	 * the right thing if NameLength is uninitialized and
241 	 * whatever junk happens to be there is big enough
242 	 * (because the pointer argument will be null), it's
243 	 * still reading an uninitialized variable.
244 	 */
245 	NameLength = 0;
246 	if (!PacketGetAdapterNames(NULL, &NameLength))
247 	{
248 		DWORD last_error = GetLastError();
249 
250 		if (last_error != ERROR_INSUFFICIENT_BUFFER)
251 		{
252 			snprintf(errbuf, PCAP_ERRBUF_SIZE,
253 				"PacketGetAdapterNames: %s",
254 				pcap_win32strerror());
255 			return (-1);
256 		}
257 	}
258 
259 	if (NameLength > 0)
260 		AdaptersName = (char*) malloc(NameLength);
261 	else
262 	{
263 		*alldevsp = NULL;
264 		return 0;
265 	}
266 	if (AdaptersName == NULL)
267 	{
268 		snprintf(errbuf, PCAP_ERRBUF_SIZE, "Cannot allocate enough memory to list the adapters.");
269 		return (-1);
270 	}
271 
272 	if (!PacketGetAdapterNames(AdaptersName, &NameLength)) {
273 		snprintf(errbuf, PCAP_ERRBUF_SIZE,
274 			"PacketGetAdapterNames: %s",
275 			pcap_win32strerror());
276 		free(AdaptersName);
277 		return (-1);
278 	}
279 
280 	/*
281 	 * "PacketGetAdapterNames()" returned a list of
282 	 * null-terminated ASCII interface name strings,
283 	 * terminated by a null string, followed by a list
284 	 * of null-terminated ASCII interface description
285 	 * strings, terminated by a null string.
286 	 * This means there are two ASCII nulls at the end
287 	 * of the first list.
288 	 *
289 	 * Find the end of the first list; that's the
290 	 * beginning of the second list.
291 	 */
292 	desc = &AdaptersName[0];
293 	while (*desc != '\0' || *(desc + 1) != '\0')
294 		desc++;
295 
296 	/*
297  	 * Found it - "desc" points to the first of the two
298 	 * nulls at the end of the list of names, so the
299 	 * first byte of the list of descriptions is two bytes
300 	 * after it.
301 	 */
302 	desc += 2;
303 
304 	/*
305 	 * Loop over the elements in the first list.
306 	 */
307 	name = &AdaptersName[0];
308 	while (*name != '\0') {
309 		/*
310 		 * Add an entry for this interface.
311 		 */
312 		if (pcap_add_if_win32(&devlist, name, desc, errbuf) == -1) {
313 			/*
314 			 * Failure.
315 			 */
316 			ret = -1;
317 			break;
318 		}
319 		name += strlen(name) + 1;
320 		desc += strlen(desc) + 1;
321 	}
322 
323 	if (ret != -1) {
324 		/*
325 		 * We haven't had any errors yet; do any platform-specific
326 		 * operations to add devices.
327 		 */
328 		if (pcap_platform_finddevs(&devlist, errbuf) < 0)
329 			ret = -1;
330 	}
331 
332 	if (ret == -1) {
333 		/*
334 		 * We had an error; free the list we've been constructing.
335 		 */
336 		if (devlist != NULL) {
337 			pcap_freealldevs(devlist);
338 			devlist = NULL;
339 		}
340 	}
341 
342 	*alldevsp = devlist;
343 	free(AdaptersName);
344 	return (ret);
345 }
346