1 /* capture-pcap-util-unix.c
2 * UN*X-specific utility routines for packet capture
6 * Wireshark - Network traffic analyzer
7 * By Gerald Combs <gerald@wireshark.org>
8 * Copyright 1998 Gerald Combs
10 * This program is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU General Public License
12 * as published by the Free Software Foundation; either version 2
13 * of the License, or (at your option) any later version.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
31 #ifndef HAVE_PCAP_FINDALLDEVS
42 #ifdef HAVE_SYS_SOCKET_H
43 #include <sys/socket.h>
46 #ifdef HAVE_SYS_IOCTL_H
47 #include <sys/ioctl.h>
51 * Keep Digital UNIX happy when including <net/if.h>.
57 #ifdef HAVE_SYS_SOCKIO_H
58 # include <sys/sockio.h>
61 #include "capture-pcap-util.h"
67 #endif /* HAVE_PCAP_FINDALLDEVS */
69 #include "capture_ifinfo.h"
70 #include "capture-pcap-util-int.h"
72 #ifndef HAVE_PCAP_FINDALLDEVS
73 struct search_user_data
{
79 search_for_if_cb(gpointer data
, gpointer user_data
);
82 #ifdef HAVE_PCAP_REMOTE
84 get_remote_interface_list(const char *hostname
, const char *port
,
85 int auth_type
, const char *username
,
86 const char *passwd
, int *err
, char **err_str
)
88 struct pcap_rmtauth auth
;
89 char source
[PCAP_BUF_SIZE
];
90 char errbuf
[PCAP_ERRBUF_SIZE
];
93 if (pcap_createsrcstr(source
, PCAP_SRC_IFREMOTE
, hostname
, port
,
94 NULL
, errbuf
) == -1) {
95 *err
= CANT_GET_INTERFACE_LIST
;
97 *err_str
= cant_get_if_list_error_message(errbuf
);
101 auth
.type
= auth_type
;
102 auth
.username
= g_strdup(username
);
103 auth
.password
= g_strdup(passwd
);
105 result
= get_interface_list_findalldevs_ex(source
, &auth
, err
, err_str
);
106 g_free(auth
.username
);
107 g_free(auth
.password
);
114 get_interface_list(int *err
, char **err_str
)
116 #ifdef HAVE_PCAP_FINDALLDEVS
117 return get_interface_list_findalldevs(err
, err_str
);
120 gint nonloopback_pos
= 0;
121 struct ifreq
*ifr
, *last
;
123 struct ifreq ifrflags
;
124 int sock
= socket(AF_INET
, SOCK_DGRAM
, 0);
125 struct search_user_data user_data
;
130 char errbuf
[PCAP_ERRBUF_SIZE
];
134 *err
= CANT_GET_INTERFACE_LIST
;
135 if (err_str
!= NULL
) {
136 *err_str
= g_strdup_printf(
137 "Can't get list of interfaces: error opening socket: %s",
144 * This code came from: W. Richard Stevens: "UNIX Network Programming",
145 * Networking APIs: Sockets and XTI, Vol 1, page 434.
148 len
= 100 * sizeof(struct ifreq
);
153 memset (buf
, 0, len
);
154 if (ioctl(sock
, SIOCGIFCONF
, &ifc
) < 0) {
155 if (errno
!= EINVAL
|| lastlen
!= 0) {
156 if (err_str
!= NULL
) {
157 *err_str
= g_strdup_printf(
158 "Can't get list of interfaces: SIOCGIFCONF ioctl error: %s",
164 if ((unsigned int) ifc
.ifc_len
< sizeof(struct ifreq
)) {
165 if (err_str
!= NULL
) {
167 "Can't get list of interfaces: SIOCGIFCONF ioctl gave too small return buffer");
171 if (ifc
.ifc_len
== lastlen
)
172 break; /* success, len has not changed */
173 lastlen
= ifc
.ifc_len
;
175 len
+= 10 * sizeof(struct ifreq
); /* increment */
178 ifr
= (struct ifreq
*) ifc
.ifc_req
;
179 last
= (struct ifreq
*) ((char *) ifr
+ ifc
.ifc_len
);
182 * Skip entries that begin with "dummy", or that include
183 * a ":" (the latter are Solaris virtuals).
185 if (strncmp(ifr
->ifr_name
, "dummy", 5) == 0 ||
186 strchr(ifr
->ifr_name
, ':') != NULL
)
190 * If we already have this interface name on the list,
191 * don't add it, but, if we don't already have an IP
192 * address for it, add that address (SIOCGIFCONF returns,
193 * at least on BSD-flavored systems, one entry per
194 * interface *address*; if an interface has multiple
195 * addresses, we get multiple entries for it).
197 user_data
.name
= ifr
->ifr_name
;
198 user_data
.if_info
= NULL
;
199 g_list_foreach(il
, search_for_if_cb
, &user_data
);
200 if (user_data
.if_info
!= NULL
) {
201 if_info_add_address(user_data
.if_info
, &ifr
->ifr_addr
);
206 * Get the interface flags.
208 memset(&ifrflags
, 0, sizeof ifrflags
);
209 g_strlcpy(ifrflags
.ifr_name
, ifr
->ifr_name
,
210 sizeof ifrflags
.ifr_name
);
211 if (ioctl(sock
, SIOCGIFFLAGS
, (char *)&ifrflags
) < 0) {
214 if (err_str
!= NULL
) {
215 *err_str
= g_strdup_printf(
216 "Can't get list of interfaces: SIOCGIFFLAGS error getting flags for interface %s: %s",
217 ifr
->ifr_name
, g_strerror(errno
));
223 * Skip interfaces that aren't up.
225 if (!(ifrflags
.ifr_flags
& IFF_UP
))
229 * Skip interfaces that we can't open with "libpcap".
230 * Open with the minimum packet size - it appears that the
231 * IRIX SIOCSNOOPLEN "ioctl" may fail if the capture length
232 * supplied is too large, rather than just truncating it.
234 pch
= pcap_open_live(ifr
->ifr_name
, MIN_PACKET_SIZE
, 0, 0,
241 * If it's a loopback interface, add it at the end of the
242 * list, otherwise add it after the last non-loopback
243 * interface, so all loopback interfaces go at the end - we
244 * don't want a loopback interface to be the default capture
245 * device unless there are no non-loopback devices.
247 loopback
= ((ifrflags
.ifr_flags
& IFF_LOOPBACK
) ||
248 strncmp(ifr
->ifr_name
, "lo", 2) == 0);
249 if_info
= if_info_new(ifr
->ifr_name
, NULL
, loopback
);
250 if_info_add_address(if_info
, &ifr
->ifr_addr
);
252 il
= g_list_append(il
, if_info
);
254 il
= g_list_insert(il
, if_info
, nonloopback_pos
);
256 * Insert the next non-loopback interface after this
264 ifr
= (struct ifreq
*) ((char *) ifr
+
265 (ifr
->ifr_addr
.sa_len
> sizeof(ifr
->ifr_addr
) ?
266 ifr
->ifr_addr
.sa_len
: sizeof(ifr
->ifr_addr
)) +
269 ifr
= (struct ifreq
*) ((char *) ifr
+ sizeof(struct ifreq
));
275 * OK, maybe we have support for the "any" device, to do a cooked
276 * capture on all interfaces at once.
277 * Try opening it and, if that succeeds, add it to the end of
278 * the list of interfaces.
280 pch
= pcap_open_live("any", MIN_PACKET_SIZE
, 0, 0, errbuf
);
283 * It worked; we can use the "any" device.
285 if_info
= if_info_new("any",
286 "Pseudo-device that captures on all interfaces", FALSE
);
287 il
= g_list_insert(il
, if_info
, -1);
297 * No interfaces found.
299 *err
= NO_INTERFACES_FOUND
;
307 free_interface_list(il
);
310 *err
= CANT_GET_INTERFACE_LIST
;
312 #endif /* HAVE_PCAP_FINDALLDEVS */
315 #ifndef HAVE_PCAP_FINDALLDEVS
317 search_for_if_cb(gpointer data
, gpointer user_data
)
319 struct search_user_data
*search_user_data
= user_data
;
320 if_info_t
*if_info
= data
;
322 if (strcmp(if_info
->name
, search_user_data
->name
) == 0)
323 search_user_data
->if_info
= if_info
;
325 #endif /* HAVE_PCAP_FINDALLDEVS */
328 * Get an error message string for a CANT_GET_INTERFACE_LIST error from
329 * "get_interface_list()".
332 cant_get_if_list_error_message(const char *err_str
)
334 return g_strdup_printf("Can't get list of interfaces: %s", err_str
);
338 * Append the version of libpcap with which we were compiled to a GString.
341 get_compiled_pcap_version(GString
*str
)
344 * NOTE: in *some* flavors of UN*X, the data from a shared
345 * library might be linked into executable images that are
346 * linked with that shared library, in which case you could
347 * look at pcap_version[] to get the version with which
348 * the program was compiled.
350 * In other flavors of UN*X, that doesn't happen, so
351 * pcap_version[] gives you the version the program is
352 * running with, not the version it was built with, and,
353 * in at least some of them, if the length of a data item
354 * referred to by the executable - such as the pcap_version[]
355 * string - isn't the same in the version of the library
356 * with which the program was built and the version with
357 * which it was run, the run-time linker will complain,
360 * So, for now, we just give up on reporting the version
361 * of libpcap with which we were compiled.
363 g_string_append(str
, "with libpcap");
367 * Append the version of libpcap with which we we're running to a GString.
370 get_runtime_pcap_version(GString
*str
)
372 g_string_append_printf(str
, "with ");
373 #ifdef HAVE_PCAP_LIB_VERSION
374 g_string_append(str
, pcap_lib_version());
376 g_string_append(str
, "libpcap (version unknown)");
380 #else /* HAVE_LIBPCAP */
383 * Append an indication that we were not compiled with libpcap
387 get_compiled_pcap_version(GString
*str
)
389 g_string_append(str
, "without libpcap");
393 * Don't append anything, as we weren't even compiled to use WinPcap.
396 get_runtime_pcap_version(GString
*str _U_
)
400 #endif /* HAVE_LIBPCAP */