fad-win32.c revision 146768
1127664Sbms/*
2127664Sbms * Copyright (c) 2002 - 2003
3127664Sbms * NetGroup, Politecnico di Torino (Italy)
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.
15127664Sbms * 3. Neither the name of the Politecnico di Torino nor the names of its
16127664Sbms * contributors may be used to endorse or promote products derived from
17127664Sbms * this software without specific prior written permission.
18127664Sbms *
19127664Sbms * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20127664Sbms * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21127664Sbms * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22127664Sbms * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23127664Sbms * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24127664Sbms * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25127664Sbms * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26127664Sbms * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27127664Sbms * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28127664Sbms * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29127664Sbms * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30127664Sbms *
31127664Sbms */
32127664Sbms
33127664Sbms#ifndef lint
34127664Sbmsstatic const char rcsid[] _U_ =
35146768Ssam    "@(#) $Header: /tcpdump/master/libpcap/fad-win32.c,v 1.11 2005/01/29 00:52:22 guy Exp $ (LBL)";
36127664Sbms#endif
37127664Sbms
38127664Sbms#ifdef HAVE_CONFIG_H
39127664Sbms#include "config.h"
40127664Sbms#endif
41127664Sbms
42127664Sbms#include <pcap.h>
43127664Sbms#include <pcap-int.h>
44127664Sbms#include <packet32.h>
45127664Sbms
46127664Sbms#include <errno.h>
47127664Sbms
48127664Sbms/*
49127664Sbms * Add an entry to the list of addresses for an interface.
50127664Sbms * "curdev" is the entry for that interface.
51127664Sbms */
52127664Sbmsstatic int
53127664Sbmsadd_addr_to_list(pcap_if_t *curdev, struct sockaddr *addr,
54127664Sbms    struct sockaddr *netmask, struct sockaddr *broadaddr,
55127664Sbms    struct sockaddr *dstaddr, char *errbuf)
56127664Sbms{
57127664Sbms	pcap_addr_t *curaddr, *prevaddr, *nextaddr;
58127664Sbms
59127664Sbms	/*
60127664Sbms	 * Allocate the new entry and fill it in.
61127664Sbms	 */
62127664Sbms	curaddr = (pcap_addr_t*)malloc(sizeof(pcap_addr_t));
63127664Sbms	if (curaddr == NULL) {
64127664Sbms		(void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
65127664Sbms		    "malloc: %s", pcap_strerror(errno));
66127664Sbms		return (-1);
67127664Sbms	}
68127664Sbms
69127664Sbms	curaddr->next = NULL;
70127664Sbms	if (addr != NULL) {
71127664Sbms		curaddr->addr = (struct sockaddr*)dup_sockaddr(addr, sizeof(struct sockaddr_storage));
72127664Sbms		if (curaddr->addr == NULL) {
73127664Sbms			(void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
74127664Sbms			    "malloc: %s", pcap_strerror(errno));
75127664Sbms			free(curaddr);
76127664Sbms			return (-1);
77127664Sbms		}
78127664Sbms	} else
79127664Sbms		curaddr->addr = NULL;
80127664Sbms
81127664Sbms	if (netmask != NULL) {
82127664Sbms		curaddr->netmask = (struct sockaddr*)dup_sockaddr(netmask, sizeof(struct sockaddr_storage));
83127664Sbms		if (curaddr->netmask == NULL) {
84127664Sbms			(void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
85127664Sbms			    "malloc: %s", pcap_strerror(errno));
86127664Sbms			free(curaddr);
87127664Sbms			return (-1);
88127664Sbms		}
89127664Sbms	} else
90127664Sbms		curaddr->netmask = NULL;
91127664Sbms
92127664Sbms	if (broadaddr != NULL) {
93127664Sbms		curaddr->broadaddr = (struct sockaddr*)dup_sockaddr(broadaddr, sizeof(struct sockaddr_storage));
94127664Sbms		if (curaddr->broadaddr == NULL) {
95127664Sbms			(void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
96127664Sbms			    "malloc: %s", pcap_strerror(errno));
97127664Sbms			free(curaddr);
98127664Sbms			return (-1);
99127664Sbms		}
100127664Sbms	} else
101127664Sbms		curaddr->broadaddr = NULL;
102127664Sbms
103127664Sbms	if (dstaddr != NULL) {
104127664Sbms		curaddr->dstaddr = (struct sockaddr*)dup_sockaddr(dstaddr, sizeof(struct sockaddr_storage));
105127664Sbms		if (curaddr->dstaddr == NULL) {
106127664Sbms			(void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
107127664Sbms			    "malloc: %s", pcap_strerror(errno));
108127664Sbms			free(curaddr);
109127664Sbms			return (-1);
110127664Sbms		}
111127664Sbms	} else
112127664Sbms		curaddr->dstaddr = NULL;
113127664Sbms
114127664Sbms	/*
115127664Sbms	 * Find the end of the list of addresses.
116127664Sbms	 */
117127664Sbms	for (prevaddr = curdev->addresses; prevaddr != NULL; prevaddr = nextaddr) {
118127664Sbms		nextaddr = prevaddr->next;
119127664Sbms		if (nextaddr == NULL) {
120127664Sbms			/*
121127664Sbms			 * This is the end of the list.
122127664Sbms			 */
123127664Sbms			break;
124127664Sbms		}
125127664Sbms	}
126127664Sbms
127127664Sbms	if (prevaddr == NULL) {
128127664Sbms		/*
129127664Sbms		 * The list was empty; this is the first member.
130127664Sbms		 */
131127664Sbms		curdev->addresses = curaddr;
132127664Sbms	} else {
133127664Sbms		/*
134127664Sbms		 * "prevaddr" is the last member of the list; append
135127664Sbms		 * this member to it.
136127664Sbms		 */
137127664Sbms		prevaddr->next = curaddr;
138127664Sbms	}
139127664Sbms
140127664Sbms	return (0);
141127664Sbms}
142127664Sbms
143127664Sbms
144127664Sbmsstatic int
145127664Sbmspcap_add_if_win32(pcap_if_t **devlist, char *name, const char *desc,
146127664Sbms    char *errbuf)
147127664Sbms{
148127664Sbms	pcap_if_t *curdev;
149127664Sbms	npf_if_addr if_addrs[MAX_NETWORK_ADDRESSES];
150127664Sbms	LONG if_addr_size;
151127664Sbms	int res = 0;
152127664Sbms
153127664Sbms	if_addr_size = MAX_NETWORK_ADDRESSES;
154127664Sbms
155127664Sbms	/*
156127664Sbms	 * Add an entry for this interface, with no addresses.
157127664Sbms	 */
158146768Ssam	if (add_or_find_if(&curdev, devlist, name, 0, desc, errbuf) == -1) {
159127664Sbms		/*
160127664Sbms		 * Failure.
161127664Sbms		 */
162127664Sbms		return (-1);
163127664Sbms	}
164127664Sbms
165127664Sbms	/*
166127664Sbms	 * Get the list of addresses for the interface.
167127664Sbms	 */
168127664Sbms	if (!PacketGetNetInfoEx((void *)name, if_addrs, &if_addr_size)) {
169127664Sbms		/*
170127664Sbms		 * Failure.
171127664Sbms		 *
172127664Sbms		 * We don't return an error, because this can happen with
173127664Sbms		 * NdisWan interfaces, and we want to supply them even
174127664Sbms		 * if we can't supply their addresses.
175127664Sbms		 *
176127664Sbms		 * We return an entry with an empty address list.
177127664Sbms		 */
178127664Sbms		return (0);
179127664Sbms	}
180127664Sbms
181127664Sbms	/*
182127664Sbms	 * Now add the addresses.
183127664Sbms	 */
184127664Sbms	while (if_addr_size-- > 0) {
185127664Sbms		/*
186127664Sbms		 * "curdev" is an entry for this interface; add an entry for
187127664Sbms		 * this address to its list of addresses.
188127664Sbms		 */
189127664Sbms		if(curdev == NULL)
190127664Sbms			break;
191127664Sbms		res = add_addr_to_list(curdev,
192127664Sbms		    (struct sockaddr *)&if_addrs[if_addr_size].IPAddress,
193127664Sbms		    (struct sockaddr *)&if_addrs[if_addr_size].SubnetMask,
194127664Sbms		    (struct sockaddr *)&if_addrs[if_addr_size].Broadcast,
195127664Sbms		    NULL,
196127664Sbms			errbuf);
197127664Sbms		if (res == -1) {
198127664Sbms			/*
199127664Sbms			 * Failure.
200127664Sbms			 */
201127664Sbms			break;
202127664Sbms		}
203127664Sbms	}
204127664Sbms
205127664Sbms	return (res);
206127664Sbms}
207127664Sbms
208127664Sbms
209127664Sbms/*
210127664Sbms * Get a list of all interfaces that are up and that we can open.
211127664Sbms * Returns -1 on error, 0 otherwise.
212127664Sbms * The list, as returned through "alldevsp", may be null if no interfaces
213127664Sbms * were up and could be opened.
214127664Sbms *
215127664Sbms * Win32 implementation, based on WinPcap
216127664Sbms */
217127664Sbmsint
218127664Sbmspcap_findalldevs(pcap_if_t **alldevsp, char *errbuf)
219127664Sbms{
220127664Sbms	pcap_if_t *devlist = NULL;
221127664Sbms	int ret = 0;
222127664Sbms	const char *desc;
223146768Ssam	char *AdaptersName;
224146768Ssam	ULONG NameLength;
225127664Sbms	char *name;
226127664Sbms
227146768Ssam	PacketGetAdapterNames(NULL, &NameLength);
228146768Ssam
229146768Ssam	if (NameLength > 0)
230146768Ssam		AdaptersName = (char*) malloc(NameLength);
231146768Ssam	else
232146768Ssam	{
233146768Ssam		*alldevsp = NULL;
234146768Ssam		return 0;
235146768Ssam	}
236146768Ssam	if (AdaptersName == NULL)
237146768Ssam	{
238146768Ssam		snprintf(errbuf, PCAP_ERRBUF_SIZE, "Cannot allocate enough memory to list the adapters.");
239146768Ssam		return (-1);
240146768Ssam	}
241146768Ssam
242127664Sbms	if (!PacketGetAdapterNames(AdaptersName, &NameLength)) {
243127664Sbms		snprintf(errbuf, PCAP_ERRBUF_SIZE,
244127664Sbms			"PacketGetAdapterNames: %s",
245127664Sbms			pcap_win32strerror());
246146768Ssam		free(AdaptersName);
247127664Sbms		return (-1);
248127664Sbms	}
249127664Sbms
250127664Sbms	/*
251127664Sbms	 * "PacketGetAdapterNames()" returned a list of
252127664Sbms	 * null-terminated ASCII interface name strings,
253127664Sbms	 * terminated by a null string, followed by a list
254127664Sbms	 * of null-terminated ASCII interface description
255127664Sbms	 * strings, terminated by a null string.
256127664Sbms	 * This means there are two ASCII nulls at the end
257127664Sbms	 * of the first list.
258127664Sbms	 *
259127664Sbms	 * Find the end of the first list; that's the
260127664Sbms	 * beginning of the second list.
261127664Sbms	 */
262127664Sbms	desc = &AdaptersName[0];
263127664Sbms	while (*desc != '\0' || *(desc + 1) != '\0')
264127664Sbms		desc++;
265127664Sbms
266127664Sbms	/*
267127664Sbms 	 * Found it - "desc" points to the first of the two
268127664Sbms	 * nulls at the end of the list of names, so the
269127664Sbms	 * first byte of the list of descriptions is two bytes
270127664Sbms	 * after it.
271127664Sbms	 */
272127664Sbms	desc += 2;
273127664Sbms
274127664Sbms	/*
275127664Sbms	 * Loop over the elements in the first list.
276127664Sbms	 */
277127664Sbms	name = &AdaptersName[0];
278127664Sbms	while (*name != '\0') {
279146768Ssam		/*
280146768Ssam		 * Add an entry for this interface.
281146768Ssam		 */
282146768Ssam		if (pcap_add_if_win32(&devlist, name, desc, errbuf) == -1) {
283127664Sbms			/*
284146768Ssam			 * Failure.
285146768Ssam			 */
286127664Sbms			ret = -1;
287127664Sbms			break;
288127664Sbms		}
289127664Sbms		name += strlen(name) + 1;
290127664Sbms		desc += strlen(desc) + 1;
291127664Sbms	}
292127664Sbms
293127664Sbms	if (ret == -1) {
294146768Ssam		/*
295146768Ssam		 * We had an error; free the list we've been constructing.
296146768Ssam		 */
297146768Ssam		if (devlist != NULL) {
298127664Sbms			pcap_freealldevs(devlist);
299127664Sbms			devlist = NULL;
300127664Sbms		}
301127664Sbms	}
302127664Sbms
303127664Sbms	*alldevsp = devlist;
304146768Ssam	free(AdaptersName);
305127664Sbms	return (ret);
306127664Sbms}
307