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 #ifdef HAVE_CONFIG_H
35 #include "config.h"
36 #endif
37 
38 #include <pcap.h>
39 #include <pcap-int.h>
40 #include <Packet32.h>
41 
42 #include <errno.h>
43 
44 static int
pcap_add_if_win32(pcap_if_t ** devlist,char * name,const char * desc,char * errbuf)45 pcap_add_if_win32(pcap_if_t **devlist, char *name, const char *desc,
46     char *errbuf)
47 {
48 	pcap_if_t *curdev;
49 	npf_if_addr if_addrs[MAX_NETWORK_ADDRESSES];
50 	LONG if_addr_size;
51 	int res = 0;
52 
53 	if_addr_size = MAX_NETWORK_ADDRESSES;
54 
55 	/*
56 	 * Add an entry for this interface, with no addresses.
57 	 */
58 	if (add_or_find_if(&curdev, devlist, name, 0, desc, errbuf) == -1) {
59 		/*
60 		 * Failure.
61 		 */
62 		return (-1);
63 	}
64 
65 	/*
66 	 * Get the list of addresses for the interface.
67 	 */
68 	if (!PacketGetNetInfoEx((void *)name, if_addrs, &if_addr_size)) {
69 		/*
70 		 * Failure.
71 		 *
72 		 * We don't return an error, because this can happen with
73 		 * NdisWan interfaces, and we want to supply them even
74 		 * if we can't supply their addresses.
75 		 *
76 		 * We return an entry with an empty address list.
77 		 */
78 		return (0);
79 	}
80 
81 	/*
82 	 * Now add the addresses.
83 	 */
84 	while (if_addr_size-- > 0) {
85 		/*
86 		 * "curdev" is an entry for this interface; add an entry for
87 		 * this address to its list of addresses.
88 		 */
89 		if(curdev == NULL)
90 			break;
91 		res = add_addr_to_dev(curdev,
92 		    (struct sockaddr *)&if_addrs[if_addr_size].IPAddress,
93 		    sizeof (struct sockaddr_storage),
94 		    (struct sockaddr *)&if_addrs[if_addr_size].SubnetMask,
95 		    sizeof (struct sockaddr_storage),
96 		    (struct sockaddr *)&if_addrs[if_addr_size].Broadcast,
97 		    sizeof (struct sockaddr_storage),
98 		    NULL,
99 		    0,
100 		    errbuf);
101 		if (res == -1) {
102 			/*
103 			 * Failure.
104 			 */
105 			break;
106 		}
107 	}
108 
109 	return (res);
110 }
111 
112 
113 /*
114  * Get a list of all interfaces that are up and that we can open.
115  * Returns -1 on error, 0 otherwise.
116  * The list, as returned through "alldevsp", may be null if no interfaces
117  * were up and could be opened.
118  *
119  * Win32 implementation, based on WinPcap
120  */
121 int
pcap_findalldevs_interfaces(pcap_if_t ** alldevsp,char * errbuf)122 pcap_findalldevs_interfaces(pcap_if_t **alldevsp, char *errbuf)
123 {
124 	pcap_if_t *devlist = NULL;
125 	int ret = 0;
126 	const char *desc;
127 	char *AdaptersName;
128 	ULONG NameLength;
129 	char *name;
130 
131 	/*
132 	 * Find out how big a buffer we need.
133 	 *
134 	 * This call should always return FALSE; if the error is
135 	 * ERROR_INSUFFICIENT_BUFFER, NameLength will be set to
136 	 * the size of the buffer we need, otherwise there's a
137 	 * problem, and NameLength should be set to 0.
138 	 *
139 	 * It shouldn't require NameLength to be set, but,
140 	 * at least as of WinPcap 4.1.3, it checks whether
141 	 * NameLength is big enough before it checks for a
142 	 * NULL buffer argument, so, while it'll still do
143 	 * the right thing if NameLength is uninitialized and
144 	 * whatever junk happens to be there is big enough
145 	 * (because the pointer argument will be null), it's
146 	 * still reading an uninitialized variable.
147 	 */
148 	NameLength = 0;
149 	if (!PacketGetAdapterNames(NULL, &NameLength))
150 	{
151 		DWORD last_error = GetLastError();
152 
153 		if (last_error != ERROR_INSUFFICIENT_BUFFER)
154 		{
155 			snprintf(errbuf, PCAP_ERRBUF_SIZE,
156 				"PacketGetAdapterNames: %s",
157 				pcap_win32strerror());
158 			return (-1);
159 		}
160 	}
161 
162 	if (NameLength > 0)
163 		AdaptersName = (char*) malloc(NameLength);
164 	else
165 	{
166 		*alldevsp = NULL;
167 		return 0;
168 	}
169 	if (AdaptersName == NULL)
170 	{
171 		snprintf(errbuf, PCAP_ERRBUF_SIZE, "Cannot allocate enough memory to list the adapters.");
172 		return (-1);
173 	}
174 
175 	if (!PacketGetAdapterNames(AdaptersName, &NameLength)) {
176 		snprintf(errbuf, PCAP_ERRBUF_SIZE,
177 			"PacketGetAdapterNames: %s",
178 			pcap_win32strerror());
179 		free(AdaptersName);
180 		return (-1);
181 	}
182 
183 	/*
184 	 * "PacketGetAdapterNames()" returned a list of
185 	 * null-terminated ASCII interface name strings,
186 	 * terminated by a null string, followed by a list
187 	 * of null-terminated ASCII interface description
188 	 * strings, terminated by a null string.
189 	 * This means there are two ASCII nulls at the end
190 	 * of the first list.
191 	 *
192 	 * Find the end of the first list; that's the
193 	 * beginning of the second list.
194 	 */
195 	desc = &AdaptersName[0];
196 	while (*desc != '\0' || *(desc + 1) != '\0')
197 		desc++;
198 
199 	/*
200  	 * Found it - "desc" points to the first of the two
201 	 * nulls at the end of the list of names, so the
202 	 * first byte of the list of descriptions is two bytes
203 	 * after it.
204 	 */
205 	desc += 2;
206 
207 	/*
208 	 * Loop over the elements in the first list.
209 	 */
210 	name = &AdaptersName[0];
211 	while (*name != '\0') {
212 		/*
213 		 * Add an entry for this interface.
214 		 */
215 		if (pcap_add_if_win32(&devlist, name, desc, errbuf) == -1) {
216 			/*
217 			 * Failure.
218 			 */
219 			ret = -1;
220 			break;
221 		}
222 		name += strlen(name) + 1;
223 		desc += strlen(desc) + 1;
224 	}
225 
226 	if (ret != -1) {
227 		/*
228 		 * We haven't had any errors yet; do any platform-specific
229 		 * operations to add devices.
230 		 */
231 		if (pcap_platform_finddevs(&devlist, errbuf) < 0)
232 			ret = -1;
233 	}
234 
235 	if (ret == -1) {
236 		/*
237 		 * We had an error; free the list we've been constructing.
238 		 */
239 		if (devlist != NULL) {
240 			pcap_freealldevs(devlist);
241 			devlist = NULL;
242 		}
243 	}
244 
245 	*alldevsp = devlist;
246 	free(AdaptersName);
247 	return (ret);
248 }
249