• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.11.2.3 2006/02/22 17:09:32 gianluca 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(pcap_if_t ** alldevsp,char * errbuf)219 pcap_findalldevs(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 	if (!PacketGetAdapterNames(NULL, &NameLength))
229 	{
230 		DWORD last_error = GetLastError();
231 
232 		if (last_error != ERROR_INSUFFICIENT_BUFFER)
233 		{
234 			snprintf(errbuf, PCAP_ERRBUF_SIZE,
235 				"PacketGetAdapterNames: %s",
236 				pcap_win32strerror());
237 			return (-1);
238 		}
239 	}
240 
241 	if (NameLength > 0)
242 		AdaptersName = (char*) malloc(NameLength);
243 	else
244 	{
245 		*alldevsp = NULL;
246 		return 0;
247 	}
248 	if (AdaptersName == NULL)
249 	{
250 		snprintf(errbuf, PCAP_ERRBUF_SIZE, "Cannot allocate enough memory to list the adapters.");
251 		return (-1);
252 	}
253 
254 	if (!PacketGetAdapterNames(AdaptersName, &NameLength)) {
255 		snprintf(errbuf, PCAP_ERRBUF_SIZE,
256 			"PacketGetAdapterNames: %s",
257 			pcap_win32strerror());
258 		free(AdaptersName);
259 		return (-1);
260 	}
261 
262 	/*
263 	 * "PacketGetAdapterNames()" returned a list of
264 	 * null-terminated ASCII interface name strings,
265 	 * terminated by a null string, followed by a list
266 	 * of null-terminated ASCII interface description
267 	 * strings, terminated by a null string.
268 	 * This means there are two ASCII nulls at the end
269 	 * of the first list.
270 	 *
271 	 * Find the end of the first list; that's the
272 	 * beginning of the second list.
273 	 */
274 	desc = &AdaptersName[0];
275 	while (*desc != '\0' || *(desc + 1) != '\0')
276 		desc++;
277 
278 	/*
279  	 * Found it - "desc" points to the first of the two
280 	 * nulls at the end of the list of names, so the
281 	 * first byte of the list of descriptions is two bytes
282 	 * after it.
283 	 */
284 	desc += 2;
285 
286 	/*
287 	 * Loop over the elements in the first list.
288 	 */
289 	name = &AdaptersName[0];
290 	while (*name != '\0') {
291 		/*
292 		 * Add an entry for this interface.
293 		 */
294 		if (pcap_add_if_win32(&devlist, name, desc, errbuf) == -1) {
295 			/*
296 			 * Failure.
297 			 */
298 			ret = -1;
299 			break;
300 		}
301 		name += strlen(name) + 1;
302 		desc += strlen(desc) + 1;
303 	}
304 
305 	if (ret == -1) {
306 		/*
307 		 * We had an error; free the list we've been constructing.
308 		 */
309 		if (devlist != NULL) {
310 			pcap_freealldevs(devlist);
311 			devlist = NULL;
312 		}
313 	}
314 
315 	*alldevsp = devlist;
316 	free(AdaptersName);
317 	return (ret);
318 }
319