xref: /minix/external/bsd/libpcap/dist/fad-win32.c (revision bb9622b5)
1 /*	$NetBSD: fad-win32.c,v 1.3 2015/03/31 21:39:42 christos Exp $	*/
2 
3 /*
4  * Copyright (c) 2002 - 2005 NetGroup, Politecnico di Torino (Italy)
5  * Copyright (c) 2005 - 2006 CACE Technologies, Davis (California)
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  *
12  * 1. Redistributions of source code must retain the above copyright
13  * notice, this list of conditions and the following disclaimer.
14  * 2. Redistributions in binary form must reproduce the above copyright
15  * notice, this list of conditions and the following disclaimer in the
16  * documentation and/or other materials provided with the distribution.
17  * 3. Neither the name of the Politecnico di Torino, CACE Technologies
18  * nor the names of its contributors may be used to endorse or promote
19  * products derived from this software without specific prior written
20  * permission.
21  *
22  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
23  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
24  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
25  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
26  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
27  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
28  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
29  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
30  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
31  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
32  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33  *
34  */
35 
36 #include <sys/cdefs.h>
37 __RCSID("$NetBSD: fad-win32.c,v 1.3 2015/03/31 21:39:42 christos Exp $");
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 static int
50 pcap_add_if_win32(pcap_if_t **devlist, char *name, const char *desc,
51     char *errbuf)
52 {
53 	pcap_if_t *curdev;
54 	npf_if_addr if_addrs[MAX_NETWORK_ADDRESSES];
55 	LONG if_addr_size;
56 	int res = 0;
57 
58 	if_addr_size = MAX_NETWORK_ADDRESSES;
59 
60 	/*
61 	 * Add an entry for this interface, with no addresses.
62 	 */
63 	if (add_or_find_if(&curdev, devlist, name, 0, desc, errbuf) == -1) {
64 		/*
65 		 * Failure.
66 		 */
67 		return (-1);
68 	}
69 
70 	/*
71 	 * Get the list of addresses for the interface.
72 	 */
73 	if (!PacketGetNetInfoEx((void *)name, if_addrs, &if_addr_size)) {
74 		/*
75 		 * Failure.
76 		 *
77 		 * We don't return an error, because this can happen with
78 		 * NdisWan interfaces, and we want to supply them even
79 		 * if we can't supply their addresses.
80 		 *
81 		 * We return an entry with an empty address list.
82 		 */
83 		return (0);
84 	}
85 
86 	/*
87 	 * Now add the addresses.
88 	 */
89 	while (if_addr_size-- > 0) {
90 		/*
91 		 * "curdev" is an entry for this interface; add an entry for
92 		 * this address to its list of addresses.
93 		 */
94 		if(curdev == NULL)
95 			break;
96 		res = add_addr_to_dev(curdev,
97 		    (struct sockaddr *)&if_addrs[if_addr_size].IPAddress,
98 		    sizeof (struct sockaddr_storage),
99 		    (struct sockaddr *)&if_addrs[if_addr_size].SubnetMask,
100 		    sizeof (struct sockaddr_storage),
101 		    (struct sockaddr *)&if_addrs[if_addr_size].Broadcast,
102 		    sizeof (struct sockaddr_storage),
103 		    NULL,
104 		    0,
105 		    errbuf);
106 		if (res == -1) {
107 			/*
108 			 * Failure.
109 			 */
110 			break;
111 		}
112 	}
113 
114 	return (res);
115 }
116 
117 
118 /*
119  * Get a list of all interfaces that are up and that we can open.
120  * Returns -1 on error, 0 otherwise.
121  * The list, as returned through "alldevsp", may be null if no interfaces
122  * were up and could be opened.
123  *
124  * Win32 implementation, based on WinPcap
125  */
126 int
127 pcap_findalldevs_interfaces(pcap_if_t **alldevsp, char *errbuf)
128 {
129 	pcap_if_t *devlist = NULL;
130 	int ret = 0;
131 	const char *desc;
132 	char *AdaptersName;
133 	ULONG NameLength;
134 	char *name;
135 
136 	/*
137 	 * Find out how big a buffer we need.
138 	 *
139 	 * This call should always return FALSE; if the error is
140 	 * ERROR_INSUFFICIENT_BUFFER, NameLength will be set to
141 	 * the size of the buffer we need, otherwise there's a
142 	 * problem, and NameLength should be set to 0.
143 	 *
144 	 * It shouldn't require NameLength to be set, but,
145 	 * at least as of WinPcap 4.1.3, it checks whether
146 	 * NameLength is big enough before it checks for a
147 	 * NULL buffer argument, so, while it'll still do
148 	 * the right thing if NameLength is uninitialized and
149 	 * whatever junk happens to be there is big enough
150 	 * (because the pointer argument will be null), it's
151 	 * still reading an uninitialized variable.
152 	 */
153 	NameLength = 0;
154 	if (!PacketGetAdapterNames(NULL, &NameLength))
155 	{
156 		DWORD last_error = GetLastError();
157 
158 		if (last_error != ERROR_INSUFFICIENT_BUFFER)
159 		{
160 			snprintf(errbuf, PCAP_ERRBUF_SIZE,
161 				"PacketGetAdapterNames: %s",
162 				pcap_win32strerror());
163 			return (-1);
164 		}
165 	}
166 
167 	if (NameLength > 0)
168 		AdaptersName = (char*) malloc(NameLength);
169 	else
170 	{
171 		*alldevsp = NULL;
172 		return 0;
173 	}
174 	if (AdaptersName == NULL)
175 	{
176 		snprintf(errbuf, PCAP_ERRBUF_SIZE, "Cannot allocate enough memory to list the adapters.");
177 		return (-1);
178 	}
179 
180 	if (!PacketGetAdapterNames(AdaptersName, &NameLength)) {
181 		snprintf(errbuf, PCAP_ERRBUF_SIZE,
182 			"PacketGetAdapterNames: %s",
183 			pcap_win32strerror());
184 		free(AdaptersName);
185 		return (-1);
186 	}
187 
188 	/*
189 	 * "PacketGetAdapterNames()" returned a list of
190 	 * null-terminated ASCII interface name strings,
191 	 * terminated by a null string, followed by a list
192 	 * of null-terminated ASCII interface description
193 	 * strings, terminated by a null string.
194 	 * This means there are two ASCII nulls at the end
195 	 * of the first list.
196 	 *
197 	 * Find the end of the first list; that's the
198 	 * beginning of the second list.
199 	 */
200 	desc = &AdaptersName[0];
201 	while (*desc != '\0' || *(desc + 1) != '\0')
202 		desc++;
203 
204 	/*
205  	 * Found it - "desc" points to the first of the two
206 	 * nulls at the end of the list of names, so the
207 	 * first byte of the list of descriptions is two bytes
208 	 * after it.
209 	 */
210 	desc += 2;
211 
212 	/*
213 	 * Loop over the elements in the first list.
214 	 */
215 	name = &AdaptersName[0];
216 	while (*name != '\0') {
217 		/*
218 		 * Add an entry for this interface.
219 		 */
220 		if (pcap_add_if_win32(&devlist, name, desc, errbuf) == -1) {
221 			/*
222 			 * Failure.
223 			 */
224 			ret = -1;
225 			break;
226 		}
227 		name += strlen(name) + 1;
228 		desc += strlen(desc) + 1;
229 	}
230 
231 	if (ret != -1) {
232 		/*
233 		 * We haven't had any errors yet; do any platform-specific
234 		 * operations to add devices.
235 		 */
236 		if (pcap_platform_finddevs(&devlist, errbuf) < 0)
237 			ret = -1;
238 	}
239 
240 	if (ret == -1) {
241 		/*
242 		 * We had an error; free the list we've been constructing.
243 		 */
244 		if (devlist != NULL) {
245 			pcap_freealldevs(devlist);
246 			devlist = NULL;
247 		}
248 	}
249 
250 	*alldevsp = devlist;
251 	free(AdaptersName);
252 	return (ret);
253 }
254