1 /* -*- Mode: c; tab-width: 8; indent-tabs-mode: 1; c-basic-offset: 8; -*- */
3 * Copyright (c) 1994, 1995, 1996, 1997, 1998
4 * The Regents of the University of California. All rights reserved.
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
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.
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
40 #include <sys/param.h>
44 #include <sys/ioctl.h>
45 #include <sys/socket.h>
46 #ifdef HAVE_SYS_SOCKIO_H
47 #include <sys/sockio.h>
50 struct mbuf
; /* Squelch compiler warnings on some platforms for */
51 struct rtentry
; /* declarations in <net/if.h> */
53 #include <netinet/in.h>
61 #if !defined(_WIN32) && !defined(__BORLANDC__)
63 #endif /* !_WIN32 && !__BORLANDC__ */
67 #ifdef HAVE_OS_PROTO_H
71 #if !defined(_WIN32) && !defined(MSDOS)
74 * Return the name of a network interface attached to the system, or NULL
75 * if none can be found. The interface must be configured up; the
76 * lowest unit number is preferred; loopback is ignored.
79 pcap_lookupdev(errbuf
)
80 register char *errbuf
;
83 /* for old BSD systems, including bsdi3 */
85 #define IF_NAMESIZE IFNAMSIZ
87 static char device
[IF_NAMESIZE
+ 1];
90 if (pcap_findalldevs(&alldevs
, errbuf
) == -1)
93 if (alldevs
== NULL
|| (alldevs
->flags
& PCAP_IF_LOOPBACK
)) {
95 * There are no devices on the list, or the first device
96 * on the list is a loopback device, which means there
97 * are no non-loopback devices on the list. This means
98 * we can't return any device.
100 * XXX - why not return a loopback device? If we can't
101 * capture on it, it won't be on the list, and if it's
102 * on the list, there aren't any non-loopback devices,
103 * so why not just supply it as the default device?
105 (void)strlcpy(errbuf
, "no suitable device found",
110 * Return the name of the first device on the list.
112 (void)strlcpy(device
, alldevs
->name
, sizeof(device
));
116 pcap_freealldevs(alldevs
);
121 pcap_lookupnet(device
, netp
, maskp
, errbuf
)
122 register const char *device
;
123 register bpf_u_int32
*netp
, *maskp
;
124 register char *errbuf
;
127 register struct sockaddr_in
*sin4
;
131 * The pseudo-device "any" listens on all interfaces and therefore
132 * has the network address and -mask "0.0.0.0" therefore catching
133 * all traffic. Using NULL for the interface is the same as "any".
135 if (!device
|| strcmp(device
, "any") == 0
137 || strstr(device
, "dag") != NULL
139 #ifdef HAVE_SEPTEL_API
140 || strstr(device
, "septel") != NULL
142 #ifdef PCAP_SUPPORT_BT
143 || strstr(device
, "bluetooth") != NULL
145 #ifdef PCAP_SUPPORT_USB
146 || strstr(device
, "usbmon") != NULL
149 || strstr(device
, "snf") != NULL
151 #ifdef PCAP_SUPPORT_NETMAP
152 || strncmp(device
, "netmap:", 7) == 0
153 || strncmp(device
, "vale", 4) == 0
160 fd
= socket(AF_INET
, SOCK_DGRAM
, 0);
162 (void)pcap_snprintf(errbuf
, PCAP_ERRBUF_SIZE
, "socket: %s",
163 pcap_strerror(errno
));
166 memset(&ifr
, 0, sizeof(ifr
));
168 /* XXX Work around Linux kernel bug */
169 ifr
.ifr_addr
.sa_family
= AF_INET
;
171 (void)strlcpy(ifr
.ifr_name
, device
, sizeof(ifr
.ifr_name
));
172 if (ioctl(fd
, SIOCGIFADDR
, (char *)&ifr
) < 0) {
173 if (errno
== EADDRNOTAVAIL
) {
174 (void)pcap_snprintf(errbuf
, PCAP_ERRBUF_SIZE
,
175 "%s: no IPv4 address assigned", device
);
177 (void)pcap_snprintf(errbuf
, PCAP_ERRBUF_SIZE
,
178 "SIOCGIFADDR: %s: %s",
179 device
, pcap_strerror(errno
));
184 sin4
= (struct sockaddr_in
*)&ifr
.ifr_addr
;
185 *netp
= sin4
->sin_addr
.s_addr
;
186 memset(&ifr
, 0, sizeof(ifr
));
188 /* XXX Work around Linux kernel bug */
189 ifr
.ifr_addr
.sa_family
= AF_INET
;
191 (void)strlcpy(ifr
.ifr_name
, device
, sizeof(ifr
.ifr_name
));
192 if (ioctl(fd
, SIOCGIFNETMASK
, (char *)&ifr
) < 0) {
193 (void)pcap_snprintf(errbuf
, PCAP_ERRBUF_SIZE
,
194 "SIOCGIFNETMASK: %s: %s", device
, pcap_strerror(errno
));
199 *maskp
= sin4
->sin_addr
.s_addr
;
201 if (IN_CLASSA(*netp
))
202 *maskp
= IN_CLASSA_NET
;
203 else if (IN_CLASSB(*netp
))
204 *maskp
= IN_CLASSB_NET
;
205 else if (IN_CLASSC(*netp
))
206 *maskp
= IN_CLASSC_NET
;
208 (void)pcap_snprintf(errbuf
, PCAP_ERRBUF_SIZE
,
209 "inet class for 0x%x unknown", *netp
);
217 #elif defined(_WIN32)
220 * Return the name of a network interface attached to the system, or NULL
221 * if none can be found. The interface must be configured up; the
222 * lowest unit number is preferred; loopback is ignored.
224 * In the best of all possible worlds, this would be the same as on
225 * UN*X, but there may be software that expects this to return a
226 * full list of devices after the first device.
228 #define ADAPTERSNAME_LEN 8192
230 pcap_lookupdev(errbuf
)
231 register char *errbuf
;
234 DWORD dwWindowsMajorVersion
;
235 char our_errbuf
[PCAP_ERRBUF_SIZE
+1];
237 #pragma warning (push)
238 #pragma warning (disable: 4996) /* disable MSVC's GetVersion() deprecated warning here */
239 dwVersion
= GetVersion(); /* get the OS version */
240 #pragma warning (pop)
241 dwWindowsMajorVersion
= (DWORD
)(LOBYTE(LOWORD(dwVersion
)));
243 if (dwVersion
>= 0x80000000 && dwWindowsMajorVersion
>= 4) {
245 * Windows 95, 98, ME.
247 ULONG NameLength
= ADAPTERSNAME_LEN
;
248 static char AdaptersName
[ADAPTERSNAME_LEN
];
250 if (PacketGetAdapterNames(AdaptersName
,&NameLength
) )
251 return (AdaptersName
);
256 * Windows NT (NT 4.0 and later).
257 * Convert the names to Unicode for backward compatibility.
259 ULONG NameLength
= ADAPTERSNAME_LEN
;
260 static WCHAR AdaptersName
[ADAPTERSNAME_LEN
];
261 size_t BufferSpaceLeft
;
266 WCHAR
*TAdaptersName
= (WCHAR
*)malloc(ADAPTERSNAME_LEN
* sizeof(WCHAR
));
269 if(TAdaptersName
== NULL
)
271 (void)pcap_snprintf(errbuf
, PCAP_ERRBUF_SIZE
, "memory allocation failure");
275 if ( !PacketGetAdapterNames((PTSTR
)TAdaptersName
,&NameLength
) )
277 pcap_win32_err_to_str(GetLastError(), our_errbuf
);
278 (void)pcap_snprintf(errbuf
, PCAP_ERRBUF_SIZE
,
279 "PacketGetAdapterNames: %s", our_errbuf
);
285 BufferSpaceLeft
= ADAPTERSNAME_LEN
* sizeof(WCHAR
);
286 tAstr
= (char*)TAdaptersName
;
287 Unameptr
= AdaptersName
;
290 * Convert the device names to Unicode into AdapterName.
294 * Length of the name, including the terminating
297 namelen
= strlen(tAstr
) + 1;
300 * Do we have room for the name in the Unicode
303 if (BufferSpaceLeft
< namelen
* sizeof(WCHAR
)) {
309 BufferSpaceLeft
-= namelen
* sizeof(WCHAR
);
312 * Copy the name, converting ASCII to Unicode.
313 * namelen includes the NUL, so we copy it as
316 for (i
= 0; i
< namelen
; i
++)
317 *Unameptr
++ = *tAstr
++;
320 * Count this adapter.
323 } while (namelen
!= 1);
326 * Copy the descriptions, but don't convert them from
329 Adescptr
= (char *)Unameptr
;
334 desclen
= strlen(tAstr
) + 1;
337 * Do we have room for the name in the Unicode
340 if (BufferSpaceLeft
< desclen
) {
348 * Just copy the ASCII string.
349 * namelen includes the NUL, so we copy it as
352 memcpy(Adescptr
, tAstr
, desclen
);
355 BufferSpaceLeft
-= desclen
;
360 return (char *)(AdaptersName
);
366 pcap_lookupnet(device
, netp
, maskp
, errbuf
)
367 register const char *device
;
368 register bpf_u_int32
*netp
, *maskp
;
369 register char *errbuf
;
372 * We need only the first IPv4 address, so we must scan the array returned by PacketGetNetInfo()
373 * in order to skip non IPv4 (i.e. IPv6 addresses)
375 npf_if_addr if_addrs
[MAX_NETWORK_ADDRESSES
];
376 LONG if_addr_size
= MAX_NETWORK_ADDRESSES
;
377 struct sockaddr_in
*t_addr
;
380 if (!PacketGetNetInfoEx((void *)device
, if_addrs
, &if_addr_size
)) {
385 for(i
= 0; i
< if_addr_size
; i
++)
387 if(if_addrs
[i
].IPAddress
.ss_family
== AF_INET
)
389 t_addr
= (struct sockaddr_in
*) &(if_addrs
[i
].IPAddress
);
390 *netp
= t_addr
->sin_addr
.S_un
.S_addr
;
391 t_addr
= (struct sockaddr_in
*) &(if_addrs
[i
].SubnetMask
);
392 *maskp
= t_addr
->sin_addr
.S_un
.S_addr
;
404 #endif /* !_WIN32 && !MSDOS */