1127664Sbms/*
2172677Smlaier * Copyright (c) 2002 - 2005 NetGroup, Politecnico di Torino (Italy)
3172677Smlaier * Copyright (c) 2005 - 2006 CACE Technologies, Davis (California)
4127664Sbms * All rights reserved.
5127664Sbms *
6127664Sbms * Redistribution and use in source and binary forms, with or without
7127664Sbms * modification, are permitted provided that the following conditions
8127664Sbms * are met:
9127664Sbms *
10127664Sbms * 1. Redistributions of source code must retain the above copyright
11127664Sbms * notice, this list of conditions and the following disclaimer.
12127664Sbms * 2. Redistributions in binary form must reproduce the above copyright
13127664Sbms * notice, this list of conditions and the following disclaimer in the
14127664Sbms * documentation and/or other materials provided with the distribution.
15172677Smlaier * 3. Neither the name of the Politecnico di Torino, CACE Technologies
16172677Smlaier * nor the names of its contributors may be used to endorse or promote
17172677Smlaier * products derived from this software without specific prior written
18172677Smlaier * permission.
19127664Sbms *
20127664Sbms * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21127664Sbms * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22127664Sbms * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23127664Sbms * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24127664Sbms * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25127664Sbms * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26127664Sbms * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27127664Sbms * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28127664Sbms * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29127664Sbms * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30127664Sbms * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31127664Sbms *
32127664Sbms */
33127664Sbms
34127664Sbms#ifndef lint
35127664Sbmsstatic const char rcsid[] _U_ =
36214518Srpaulo    "@(#) $Header: /tcpdump/master/libpcap/fad-win32.c,v 1.15 2007-09-25 20:34:36 guy Exp $ (LBL)";
37127664Sbms#endif
38127664Sbms
39127664Sbms#ifdef HAVE_CONFIG_H
40127664Sbms#include "config.h"
41127664Sbms#endif
42127664Sbms
43127664Sbms#include <pcap.h>
44127664Sbms#include <pcap-int.h>
45172677Smlaier#include <Packet32.h>
46127664Sbms
47127664Sbms#include <errno.h>
48127664Sbms
49127664Sbms/*
50127664Sbms * Add an entry to the list of addresses for an interface.
51127664Sbms * "curdev" is the entry for that interface.
52127664Sbms */
53127664Sbmsstatic int
54127664Sbmsadd_addr_to_list(pcap_if_t *curdev, struct sockaddr *addr,
55127664Sbms    struct sockaddr *netmask, struct sockaddr *broadaddr,
56127664Sbms    struct sockaddr *dstaddr, char *errbuf)
57127664Sbms{
58127664Sbms	pcap_addr_t *curaddr, *prevaddr, *nextaddr;
59127664Sbms
60127664Sbms	/*
61127664Sbms	 * Allocate the new entry and fill it in.
62127664Sbms	 */
63127664Sbms	curaddr = (pcap_addr_t*)malloc(sizeof(pcap_addr_t));
64127664Sbms	if (curaddr == NULL) {
65127664Sbms		(void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
66127664Sbms		    "malloc: %s", pcap_strerror(errno));
67127664Sbms		return (-1);
68127664Sbms	}
69127664Sbms
70127664Sbms	curaddr->next = NULL;
71127664Sbms	if (addr != NULL) {
72127664Sbms		curaddr->addr = (struct sockaddr*)dup_sockaddr(addr, sizeof(struct sockaddr_storage));
73127664Sbms		if (curaddr->addr == NULL) {
74127664Sbms			(void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
75127664Sbms			    "malloc: %s", pcap_strerror(errno));
76127664Sbms			free(curaddr);
77127664Sbms			return (-1);
78127664Sbms		}
79127664Sbms	} else
80127664Sbms		curaddr->addr = NULL;
81127664Sbms
82127664Sbms	if (netmask != NULL) {
83127664Sbms		curaddr->netmask = (struct sockaddr*)dup_sockaddr(netmask, sizeof(struct sockaddr_storage));
84127664Sbms		if (curaddr->netmask == NULL) {
85127664Sbms			(void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
86127664Sbms			    "malloc: %s", pcap_strerror(errno));
87127664Sbms			free(curaddr);
88127664Sbms			return (-1);
89127664Sbms		}
90127664Sbms	} else
91127664Sbms		curaddr->netmask = NULL;
92127664Sbms
93127664Sbms	if (broadaddr != NULL) {
94127664Sbms		curaddr->broadaddr = (struct sockaddr*)dup_sockaddr(broadaddr, sizeof(struct sockaddr_storage));
95127664Sbms		if (curaddr->broadaddr == NULL) {
96127664Sbms			(void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
97127664Sbms			    "malloc: %s", pcap_strerror(errno));
98127664Sbms			free(curaddr);
99127664Sbms			return (-1);
100127664Sbms		}
101127664Sbms	} else
102127664Sbms		curaddr->broadaddr = NULL;
103127664Sbms
104127664Sbms	if (dstaddr != NULL) {
105127664Sbms		curaddr->dstaddr = (struct sockaddr*)dup_sockaddr(dstaddr, sizeof(struct sockaddr_storage));
106127664Sbms		if (curaddr->dstaddr == NULL) {
107127664Sbms			(void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
108127664Sbms			    "malloc: %s", pcap_strerror(errno));
109127664Sbms			free(curaddr);
110127664Sbms			return (-1);
111127664Sbms		}
112127664Sbms	} else
113127664Sbms		curaddr->dstaddr = NULL;
114127664Sbms
115127664Sbms	/*
116127664Sbms	 * Find the end of the list of addresses.
117127664Sbms	 */
118127664Sbms	for (prevaddr = curdev->addresses; prevaddr != NULL; prevaddr = nextaddr) {
119127664Sbms		nextaddr = prevaddr->next;
120127664Sbms		if (nextaddr == NULL) {
121127664Sbms			/*
122127664Sbms			 * This is the end of the list.
123127664Sbms			 */
124127664Sbms			break;
125127664Sbms		}
126127664Sbms	}
127127664Sbms
128127664Sbms	if (prevaddr == NULL) {
129127664Sbms		/*
130127664Sbms		 * The list was empty; this is the first member.
131127664Sbms		 */
132127664Sbms		curdev->addresses = curaddr;
133127664Sbms	} else {
134127664Sbms		/*
135127664Sbms		 * "prevaddr" is the last member of the list; append
136127664Sbms		 * this member to it.
137127664Sbms		 */
138127664Sbms		prevaddr->next = curaddr;
139127664Sbms	}
140127664Sbms
141127664Sbms	return (0);
142127664Sbms}
143127664Sbms
144127664Sbms
145127664Sbmsstatic int
146127664Sbmspcap_add_if_win32(pcap_if_t **devlist, char *name, const char *desc,
147127664Sbms    char *errbuf)
148127664Sbms{
149127664Sbms	pcap_if_t *curdev;
150127664Sbms	npf_if_addr if_addrs[MAX_NETWORK_ADDRESSES];
151127664Sbms	LONG if_addr_size;
152127664Sbms	int res = 0;
153127664Sbms
154127664Sbms	if_addr_size = MAX_NETWORK_ADDRESSES;
155127664Sbms
156127664Sbms	/*
157127664Sbms	 * Add an entry for this interface, with no addresses.
158127664Sbms	 */
159146768Ssam	if (add_or_find_if(&curdev, devlist, name, 0, desc, errbuf) == -1) {
160127664Sbms		/*
161127664Sbms		 * Failure.
162127664Sbms		 */
163127664Sbms		return (-1);
164127664Sbms	}
165127664Sbms
166127664Sbms	/*
167127664Sbms	 * Get the list of addresses for the interface.
168127664Sbms	 */
169127664Sbms	if (!PacketGetNetInfoEx((void *)name, if_addrs, &if_addr_size)) {
170127664Sbms		/*
171127664Sbms		 * Failure.
172127664Sbms		 *
173127664Sbms		 * We don't return an error, because this can happen with
174127664Sbms		 * NdisWan interfaces, and we want to supply them even
175127664Sbms		 * if we can't supply their addresses.
176127664Sbms		 *
177127664Sbms		 * We return an entry with an empty address list.
178127664Sbms		 */
179127664Sbms		return (0);
180127664Sbms	}
181127664Sbms
182127664Sbms	/*
183127664Sbms	 * Now add the addresses.
184127664Sbms	 */
185127664Sbms	while (if_addr_size-- > 0) {
186127664Sbms		/*
187127664Sbms		 * "curdev" is an entry for this interface; add an entry for
188127664Sbms		 * this address to its list of addresses.
189127664Sbms		 */
190127664Sbms		if(curdev == NULL)
191127664Sbms			break;
192127664Sbms		res = add_addr_to_list(curdev,
193127664Sbms		    (struct sockaddr *)&if_addrs[if_addr_size].IPAddress,
194127664Sbms		    (struct sockaddr *)&if_addrs[if_addr_size].SubnetMask,
195127664Sbms		    (struct sockaddr *)&if_addrs[if_addr_size].Broadcast,
196127664Sbms		    NULL,
197127664Sbms			errbuf);
198127664Sbms		if (res == -1) {
199127664Sbms			/*
200127664Sbms			 * Failure.
201127664Sbms			 */
202127664Sbms			break;
203127664Sbms		}
204127664Sbms	}
205127664Sbms
206127664Sbms	return (res);
207127664Sbms}
208127664Sbms
209127664Sbms
210127664Sbms/*
211127664Sbms * Get a list of all interfaces that are up and that we can open.
212127664Sbms * Returns -1 on error, 0 otherwise.
213127664Sbms * The list, as returned through "alldevsp", may be null if no interfaces
214127664Sbms * were up and could be opened.
215127664Sbms *
216127664Sbms * Win32 implementation, based on WinPcap
217127664Sbms */
218127664Sbmsint
219127664Sbmspcap_findalldevs(pcap_if_t **alldevsp, char *errbuf)
220127664Sbms{
221127664Sbms	pcap_if_t *devlist = NULL;
222127664Sbms	int ret = 0;
223127664Sbms	const char *desc;
224146768Ssam	char *AdaptersName;
225146768Ssam	ULONG NameLength;
226127664Sbms	char *name;
227127664Sbms
228172677Smlaier	if (!PacketGetAdapterNames(NULL, &NameLength))
229162012Ssam	{
230172677Smlaier		DWORD last_error = GetLastError();
231172677Smlaier
232172677Smlaier		if (last_error != ERROR_INSUFFICIENT_BUFFER)
233172677Smlaier		{
234172677Smlaier			snprintf(errbuf, PCAP_ERRBUF_SIZE,
235172677Smlaier				"PacketGetAdapterNames: %s",
236172677Smlaier				pcap_win32strerror());
237172677Smlaier			return (-1);
238172677Smlaier		}
239162012Ssam	}
240146768Ssam
241146768Ssam	if (NameLength > 0)
242146768Ssam		AdaptersName = (char*) malloc(NameLength);
243146768Ssam	else
244146768Ssam	{
245146768Ssam		*alldevsp = NULL;
246146768Ssam		return 0;
247146768Ssam	}
248146768Ssam	if (AdaptersName == NULL)
249146768Ssam	{
250146768Ssam		snprintf(errbuf, PCAP_ERRBUF_SIZE, "Cannot allocate enough memory to list the adapters.");
251146768Ssam		return (-1);
252146768Ssam	}
253146768Ssam
254127664Sbms	if (!PacketGetAdapterNames(AdaptersName, &NameLength)) {
255127664Sbms		snprintf(errbuf, PCAP_ERRBUF_SIZE,
256127664Sbms			"PacketGetAdapterNames: %s",
257127664Sbms			pcap_win32strerror());
258146768Ssam		free(AdaptersName);
259127664Sbms		return (-1);
260127664Sbms	}
261127664Sbms
262127664Sbms	/*
263127664Sbms	 * "PacketGetAdapterNames()" returned a list of
264127664Sbms	 * null-terminated ASCII interface name strings,
265127664Sbms	 * terminated by a null string, followed by a list
266127664Sbms	 * of null-terminated ASCII interface description
267127664Sbms	 * strings, terminated by a null string.
268127664Sbms	 * This means there are two ASCII nulls at the end
269127664Sbms	 * of the first list.
270127664Sbms	 *
271127664Sbms	 * Find the end of the first list; that's the
272127664Sbms	 * beginning of the second list.
273127664Sbms	 */
274127664Sbms	desc = &AdaptersName[0];
275127664Sbms	while (*desc != '\0' || *(desc + 1) != '\0')
276127664Sbms		desc++;
277127664Sbms
278127664Sbms	/*
279127664Sbms 	 * Found it - "desc" points to the first of the two
280127664Sbms	 * nulls at the end of the list of names, so the
281127664Sbms	 * first byte of the list of descriptions is two bytes
282127664Sbms	 * after it.
283127664Sbms	 */
284127664Sbms	desc += 2;
285127664Sbms
286127664Sbms	/*
287127664Sbms	 * Loop over the elements in the first list.
288127664Sbms	 */
289127664Sbms	name = &AdaptersName[0];
290127664Sbms	while (*name != '\0') {
291146768Ssam		/*
292146768Ssam		 * Add an entry for this interface.
293146768Ssam		 */
294146768Ssam		if (pcap_add_if_win32(&devlist, name, desc, errbuf) == -1) {
295127664Sbms			/*
296146768Ssam			 * Failure.
297146768Ssam			 */
298127664Sbms			ret = -1;
299127664Sbms			break;
300127664Sbms		}
301127664Sbms		name += strlen(name) + 1;
302127664Sbms		desc += strlen(desc) + 1;
303127664Sbms	}
304190225Srpaulo
305190225Srpaulo	if (ret != -1) {
306190225Srpaulo		/*
307190225Srpaulo		 * We haven't had any errors yet; do any platform-specific
308190225Srpaulo		 * operations to add devices.
309190225Srpaulo		 */
310190225Srpaulo		if (pcap_platform_finddevs(&devlist, errbuf) < 0)
311190225Srpaulo			ret = -1;
312190225Srpaulo	}
313127664Sbms
314127664Sbms	if (ret == -1) {
315146768Ssam		/*
316146768Ssam		 * We had an error; free the list we've been constructing.
317146768Ssam		 */
318146768Ssam		if (devlist != NULL) {
319127664Sbms			pcap_freealldevs(devlist);
320127664Sbms			devlist = NULL;
321127664Sbms		}
322127664Sbms	}
323127664Sbms
324127664Sbms	*alldevsp = devlist;
325146768Ssam	free(AdaptersName);
326127664Sbms	return (ret);
327127664Sbms}
328