]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/libpcap/fad-win32.c
MFV r324198: 8081 Compiler warnings in zdb
[FreeBSD/FreeBSD.git] / contrib / libpcap / fad-win32.c
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
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
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 }