]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/libpcap/inet.c
MFV r330102: ntp 4.2.8p11
[FreeBSD/FreeBSD.git] / contrib / libpcap / inet.c
1 /* -*- Mode: c; tab-width: 8; indent-tabs-mode: 1; c-basic-offset: 8; -*- */
2 /*
3  * Copyright (c) 1994, 1995, 1996, 1997, 1998
4  *      The Regents of the University of California.  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  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  * 3. All advertising materials mentioning features or use of this software
15  *    must display the following acknowledgement:
16  *      This product includes software developed by the Computer Systems
17  *      Engineering Group at Lawrence Berkeley Laboratory.
18  * 4. Neither the name of the University nor of the Laboratory may be used
19  *    to endorse or promote products derived from this software without
20  *    specific prior written permission.
21  *
22  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32  * SUCH DAMAGE.
33  */
34
35 #ifdef HAVE_CONFIG_H
36 #include "config.h"
37 #endif
38
39 #ifdef _WIN32
40 #include <pcap-stdinc.h>
41 #else /* _WIN32 */
42
43 #include <sys/param.h>
44 #ifndef MSDOS
45 #include <sys/file.h>
46 #endif
47 #include <sys/ioctl.h>
48 #include <sys/socket.h>
49 #ifdef HAVE_SYS_SOCKIO_H
50 #include <sys/sockio.h>
51 #endif
52
53 struct mbuf;            /* Squelch compiler warnings on some platforms for */
54 struct rtentry;         /* declarations in <net/if.h> */
55 #include <net/if.h>
56 #include <netinet/in.h>
57 #endif /* _WIN32 */
58
59 #include <errno.h>
60 #include <memory.h>
61 #include <stdio.h>
62 #include <stdlib.h>
63 #include <string.h>
64 #if !defined(_WIN32) && !defined(__BORLANDC__)
65 #include <unistd.h>
66 #endif /* !_WIN32 && !__BORLANDC__ */
67
68 #include "pcap-int.h"
69
70 #ifdef HAVE_OS_PROTO_H
71 #include "os-proto.h"
72 #endif
73
74 #if !defined(_WIN32) && !defined(MSDOS)
75
76 /*
77  * Return the name of a network interface attached to the system, or NULL
78  * if none can be found.  The interface must be configured up; the
79  * lowest unit number is preferred; loopback is ignored.
80  */
81 char *
82 pcap_lookupdev(errbuf)
83         register char *errbuf;
84 {
85         pcap_if_t *alldevs;
86 /* for old BSD systems, including bsdi3 */
87 #ifndef IF_NAMESIZE
88 #define IF_NAMESIZE IFNAMSIZ
89 #endif
90         static char device[IF_NAMESIZE + 1];
91         char *ret;
92
93         if (pcap_findalldevs(&alldevs, errbuf) == -1)
94                 return (NULL);
95
96         if (alldevs == NULL || (alldevs->flags & PCAP_IF_LOOPBACK)) {
97                 /*
98                  * There are no devices on the list, or the first device
99                  * on the list is a loopback device, which means there
100                  * are no non-loopback devices on the list.  This means
101                  * we can't return any device.
102                  *
103                  * XXX - why not return a loopback device?  If we can't
104                  * capture on it, it won't be on the list, and if it's
105                  * on the list, there aren't any non-loopback devices,
106                  * so why not just supply it as the default device?
107                  */
108                 (void)strlcpy(errbuf, "no suitable device found",
109                     PCAP_ERRBUF_SIZE);
110                 ret = NULL;
111         } else {
112                 /*
113                  * Return the name of the first device on the list.
114                  */
115                 (void)strlcpy(device, alldevs->name, sizeof(device));
116                 ret = device;
117         }
118
119         pcap_freealldevs(alldevs);
120         return (ret);
121 }
122
123 int
124 pcap_lookupnet(device, netp, maskp, errbuf)
125         register const char *device;
126         register bpf_u_int32 *netp, *maskp;
127         register char *errbuf;
128 {
129         register int fd;
130         register struct sockaddr_in *sin4;
131         struct ifreq ifr;
132
133         /*
134          * The pseudo-device "any" listens on all interfaces and therefore
135          * has the network address and -mask "0.0.0.0" therefore catching
136          * all traffic. Using NULL for the interface is the same as "any".
137          */
138         if (!device || strcmp(device, "any") == 0
139 #ifdef HAVE_DAG_API
140             || strstr(device, "dag") != NULL
141 #endif
142 #ifdef HAVE_SEPTEL_API
143             || strstr(device, "septel") != NULL
144 #endif
145 #ifdef PCAP_SUPPORT_BT
146             || strstr(device, "bluetooth") != NULL
147 #endif
148 #ifdef PCAP_SUPPORT_USB
149             || strstr(device, "usbmon") != NULL
150 #endif
151 #ifdef PCAP_SUPPORT_NETMAP
152             || !strncmp(device, "netmap:", 7)
153             || !strncmp(device, "vale", 4)
154 #endif
155 #ifdef HAVE_SNF_API
156             || strstr(device, "snf") != NULL
157 #endif
158             ) {
159                 *netp = *maskp = 0;
160                 return 0;
161         }
162
163         fd = socket(AF_INET, SOCK_DGRAM, 0);
164         if (fd < 0) {
165                 (void)pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "socket: %s",
166                     pcap_strerror(errno));
167                 return (-1);
168         }
169         memset(&ifr, 0, sizeof(ifr));
170 #ifdef linux
171         /* XXX Work around Linux kernel bug */
172         ifr.ifr_addr.sa_family = AF_INET;
173 #endif
174         (void)strlcpy(ifr.ifr_name, device, sizeof(ifr.ifr_name));
175         if (ioctl(fd, SIOCGIFADDR, (char *)&ifr) < 0) {
176                 if (errno == EADDRNOTAVAIL) {
177                         (void)pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
178                             "%s: no IPv4 address assigned", device);
179                 } else {
180                         (void)pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
181                             "SIOCGIFADDR: %s: %s",
182                             device, pcap_strerror(errno));
183                 }
184                 (void)close(fd);
185                 return (-1);
186         }
187         sin4 = (struct sockaddr_in *)&ifr.ifr_addr;
188         *netp = sin4->sin_addr.s_addr;
189         memset(&ifr, 0, sizeof(ifr));
190 #ifdef linux
191         /* XXX Work around Linux kernel bug */
192         ifr.ifr_addr.sa_family = AF_INET;
193 #endif
194         (void)strlcpy(ifr.ifr_name, device, sizeof(ifr.ifr_name));
195         if (ioctl(fd, SIOCGIFNETMASK, (char *)&ifr) < 0) {
196                 (void)pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
197                     "SIOCGIFNETMASK: %s: %s", device, pcap_strerror(errno));
198                 (void)close(fd);
199                 return (-1);
200         }
201         (void)close(fd);
202         *maskp = sin4->sin_addr.s_addr;
203         if (*maskp == 0) {
204                 if (IN_CLASSA(*netp))
205                         *maskp = IN_CLASSA_NET;
206                 else if (IN_CLASSB(*netp))
207                         *maskp = IN_CLASSB_NET;
208                 else if (IN_CLASSC(*netp))
209                         *maskp = IN_CLASSC_NET;
210                 else {
211                         (void)pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
212                             "inet class for 0x%x unknown", *netp);
213                         return (-1);
214                 }
215         }
216         *netp &= *maskp;
217         return (0);
218 }
219
220 #elif defined(_WIN32)
221
222 /*
223  * Return the name of a network interface attached to the system, or NULL
224  * if none can be found.  The interface must be configured up; the
225  * lowest unit number is preferred; loopback is ignored.
226  *
227  * In the best of all possible worlds, this would be the same as on
228  * UN*X, but there may be software that expects this to return a
229  * full list of devices after the first device.
230  */
231 #define ADAPTERSNAME_LEN        8192
232 char *
233 pcap_lookupdev(errbuf)
234         register char *errbuf;
235 {
236         DWORD dwVersion;
237         DWORD dwWindowsMajorVersion;
238         char our_errbuf[PCAP_ERRBUF_SIZE+1];
239
240 #pragma warning (push)
241 #pragma warning (disable: 4996) /* disable MSVC's GetVersion() deprecated warning here */
242         dwVersion = GetVersion();       /* get the OS version */
243 #pragma warning (pop)
244         dwWindowsMajorVersion = (DWORD)(LOBYTE(LOWORD(dwVersion)));
245
246         if (dwVersion >= 0x80000000 && dwWindowsMajorVersion >= 4) {
247                 /*
248                  * Windows 95, 98, ME.
249                  */
250                 ULONG NameLength = ADAPTERSNAME_LEN;
251                 static char AdaptersName[ADAPTERSNAME_LEN];
252
253                 if (PacketGetAdapterNames(AdaptersName,&NameLength) )
254                         return (AdaptersName);
255                 else
256                         return NULL;
257         } else {
258                 /*
259                  * Windows NT (NT 4.0 and later).
260                  * Convert the names to Unicode for backward compatibility.
261                  */
262                 ULONG NameLength = ADAPTERSNAME_LEN;
263                 static WCHAR AdaptersName[ADAPTERSNAME_LEN];
264                 size_t BufferSpaceLeft;
265                 char *tAstr;
266                 WCHAR *Unameptr;
267                 char *Adescptr;
268                 size_t namelen, i;
269                 WCHAR *TAdaptersName = (WCHAR*)malloc(ADAPTERSNAME_LEN * sizeof(WCHAR));
270                 int NAdapts = 0;
271
272                 if(TAdaptersName == NULL)
273                 {
274                         (void)pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "memory allocation failure");
275                         return NULL;
276                 }
277
278                 if ( !PacketGetAdapterNames((PTSTR)TAdaptersName,&NameLength) )
279                 {
280                         pcap_win32_err_to_str(GetLastError(), our_errbuf);
281                         (void)pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
282                                 "PacketGetAdapterNames: %s", our_errbuf);
283                         free(TAdaptersName);
284                         return NULL;
285                 }
286
287
288                 BufferSpaceLeft = ADAPTERSNAME_LEN * sizeof(WCHAR);
289                 tAstr = (char*)TAdaptersName;
290                 Unameptr = AdaptersName;
291
292                 /*
293                  * Convert the device names to Unicode into AdapterName.
294                  */
295                 do {
296                         /*
297                          * Length of the name, including the terminating
298                          * NUL.
299                          */
300                         namelen = strlen(tAstr) + 1;
301
302                         /*
303                          * Do we have room for the name in the Unicode
304                          * buffer?
305                          */
306                         if (BufferSpaceLeft < namelen * sizeof(WCHAR)) {
307                                 /*
308                                  * No.
309                                  */
310                                 goto quit;
311                         }
312                         BufferSpaceLeft -= namelen * sizeof(WCHAR);
313
314                         /*
315                          * Copy the name, converting ASCII to Unicode.
316                          * namelen includes the NUL, so we copy it as
317                          * well.
318                          */
319                         for (i = 0; i < namelen; i++)
320                                 *Unameptr++ = *tAstr++;
321
322                         /*
323                          * Count this adapter.
324                          */
325                         NAdapts++;
326                 } while (namelen != 1);
327
328                 /*
329                  * Copy the descriptions, but don't convert them from
330                  * ASCII to Unicode.
331                  */
332                 Adescptr = (char *)Unameptr;
333                 while(NAdapts--)
334                 {
335                         size_t desclen;
336
337                         desclen = strlen(tAstr) + 1;
338
339                         /*
340                          * Do we have room for the name in the Unicode
341                          * buffer?
342                          */
343                         if (BufferSpaceLeft < desclen) {
344                                 /*
345                                  * No.
346                                  */
347                                 goto quit;
348                         }
349
350                         /*
351                          * Just copy the ASCII string.
352                          * namelen includes the NUL, so we copy it as
353                          * well.
354                          */
355                         memcpy(Adescptr, tAstr, desclen);
356                         Adescptr += desclen;
357                         tAstr += desclen;
358                         BufferSpaceLeft -= desclen;
359                 }
360
361         quit:
362                 free(TAdaptersName);
363                 return (char *)(AdaptersName);
364         }
365 }
366
367
368 int
369 pcap_lookupnet(device, netp, maskp, errbuf)
370         register const char *device;
371         register bpf_u_int32 *netp, *maskp;
372         register char *errbuf;
373 {
374         /*
375          * We need only the first IPv4 address, so we must scan the array returned by PacketGetNetInfo()
376          * in order to skip non IPv4 (i.e. IPv6 addresses)
377          */
378         npf_if_addr if_addrs[MAX_NETWORK_ADDRESSES];
379         LONG if_addr_size = 1;
380         struct sockaddr_in *t_addr;
381         unsigned int i;
382
383         if (!PacketGetNetInfoEx((void *)device, if_addrs, &if_addr_size)) {
384                 *netp = *maskp = 0;
385                 return (0);
386         }
387
388         for(i=0; i<MAX_NETWORK_ADDRESSES; i++)
389         {
390                 if(if_addrs[i].IPAddress.ss_family == AF_INET)
391                 {
392                         t_addr = (struct sockaddr_in *) &(if_addrs[i].IPAddress);
393                         *netp = t_addr->sin_addr.S_un.S_addr;
394                         t_addr = (struct sockaddr_in *) &(if_addrs[i].SubnetMask);
395                         *maskp = t_addr->sin_addr.S_un.S_addr;
396
397                         *netp &= *maskp;
398                         return (0);
399                 }
400
401         }
402
403         *netp = *maskp = 0;
404         return (0);
405 }
406
407 #endif /* !_WIN32 && !MSDOS */