2005-12-06 00:07:13 +00:00
|
|
|
/* capture-pcap-util.c
|
2004-07-18 00:24:25 +00:00
|
|
|
* Utility routines for packet capture
|
|
|
|
*
|
2006-05-21 05:12:17 +00:00
|
|
|
* Wireshark - Network traffic analyzer
|
|
|
|
* By Gerald Combs <gerald@wireshark.org>
|
2004-07-18 00:24:25 +00:00
|
|
|
* Copyright 1998 Gerald Combs
|
|
|
|
*
|
2018-04-30 07:47:58 +00:00
|
|
|
* SPDX-License-Identifier: GPL-2.0-or-later
|
|
|
|
*/
|
2004-07-18 00:24:25 +00:00
|
|
|
|
2012-09-20 01:29:52 +00:00
|
|
|
#include "config.h"
|
2004-07-18 00:24:25 +00:00
|
|
|
|
|
|
|
#ifdef HAVE_LIBPCAP
|
|
|
|
|
|
|
|
#include <glib.h>
|
|
|
|
|
|
|
|
#include <stdlib.h>
|
2007-11-30 22:01:05 +00:00
|
|
|
#include <stdio.h>
|
2004-07-18 00:24:25 +00:00
|
|
|
#include <limits.h>
|
|
|
|
#include <string.h>
|
|
|
|
|
2018-05-16 19:51:45 +00:00
|
|
|
#include <sys/types.h>
|
2004-07-18 00:24:25 +00:00
|
|
|
|
|
|
|
#ifdef HAVE_SYS_SOCKET_H
|
|
|
|
#include <sys/socket.h>
|
|
|
|
#endif
|
|
|
|
|
2017-09-05 16:18:00 +00:00
|
|
|
#include "ws_attributes.h"
|
|
|
|
|
2016-01-05 21:54:02 +00:00
|
|
|
/*
|
|
|
|
* Linux bonding devices mishandle unknown ioctls; they fail
|
|
|
|
* with ENODEV rather than ENOTSUP, EOPNOTSUPP, or ENOTTY,
|
|
|
|
* so pcap_can_set_rfmon() returns a "no such device" indication
|
|
|
|
* if we try to do SIOCGIWMODE on them.
|
|
|
|
*
|
|
|
|
* So, on Linux, we check for bonding devices, if we can, before
|
|
|
|
* trying pcap_can_set_rfmon(), as pcap_can_set_rfmon() will
|
|
|
|
* end up trying SIOCGIWMODE on the device if that ioctl exists.
|
|
|
|
*/
|
|
|
|
#if defined(HAVE_PCAP_CREATE) && defined(__linux__)
|
|
|
|
|
|
|
|
#include <sys/ioctl.h>
|
|
|
|
|
|
|
|
/*
|
|
|
|
* If we're building for a Linux version that supports bonding,
|
|
|
|
* HAVE_BONDING will be defined.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#ifdef HAVE_LINUX_SOCKIOS_H
|
|
|
|
#include <linux/sockios.h>
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifdef HAVE_LINUX_IF_BONDING_H
|
|
|
|
#include <linux/if_bonding.h>
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if defined(BOND_INFO_QUERY_OLD) || defined(SIOCBONDINFOQUERY)
|
|
|
|
#define HAVE_BONDING
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#endif /* defined(HAVE_PCAP_CREATE) && defined(__linux__) */
|
|
|
|
|
2014-07-04 07:24:02 +00:00
|
|
|
#include "caputils/capture_ifinfo.h"
|
|
|
|
#include "caputils/capture-pcap-util.h"
|
|
|
|
#include "caputils/capture-pcap-util-int.h"
|
2004-07-18 00:24:25 +00:00
|
|
|
|
2016-01-05 21:54:02 +00:00
|
|
|
#include "log.h"
|
|
|
|
|
2016-01-05 22:20:57 +00:00
|
|
|
#include <wsutil/file_util.h>
|
2019-03-24 04:02:47 +00:00
|
|
|
#include <wsutil/please_report_bug.h>
|
2013-05-22 01:46:12 +00:00
|
|
|
|
2004-09-11 23:03:36 +00:00
|
|
|
#ifndef _WIN32
|
2004-07-18 00:24:25 +00:00
|
|
|
#include <netinet/in.h>
|
|
|
|
#endif
|
|
|
|
|
From Mike Garratt:
Friendly Names for interfaces on Windows
Notes on the changes the patch covers:
* if_info_t struct: addition of friendly_name
* Dumpcap Interface list format changes:
+ Win32: "dumpcap -D" shows friendly_name in place of descript if known
+ All: machine interface "dumpcap -D -Z none" includes friendly_name in the
list in addition to the existing parameters
* interface_options struct: addition of console_display_name
+ When an interface name is displayed in a console, it will typically be the
console_display_name (instead of name).
+ console_display_name is used as the basis of the autogenerated temp
filenames
+ console_display_name is typically set to the friendly_name if known,
otherwise it is set to the interface name
* Enhancements to capture_opts_add_iface_opt() (the function which process -i
options).
+ Can now specify the interface using its name and friendly_name
+ Interface name matching is case insenstive
+ Name matching first attempts exact matching, then falls back to prefix
matching
(e.g. dumpcap -i local)
+ Validates interface names, instead of blindly sending them off to
winpcap/libpcap
+ Interface specification by number is still supported.
* capture_opts_trim_iface() has been refactored:
+ Instead of repeating a decent chunk of the cost in
capture_opts_add_iface_opt(), it calls capture_opts_trim_iface() to specify the
interface.
* introduction of capture_win_ifnames.[ch] (windows only code)
+ Implements static function GetInterfaceFriendlyNameFromDeviceGuid() - a
windows version independant function to convert an interface guid into its
friendly name. Uses published api functions on windows vista and higher, but
falls back to unpublished API functions on older windows releases.
+ void get_windows_interface_friendlyname(/* IN */ char
*interface_devicename, /* OUT */char **interface_friendlyname); - extracts the
GUID from the interface_devicename, then uses
GetInterfaceFriendlyNameFromDeviceGuid() to do the resolution
* Auto temp filename generation:
+ Now uses wireshark_pcapng_* or wireshark_pcap_* depending on file format
+ Basis temp filename format on console_display_name
+ Win32: if console_display_name is a windows interface guid, extracts
numbers from GUID here (instead of in interface option processing)
GUI CHANGES:
* Dialog that displays when you click the "Manage Interfaces" button (within
Capture Options dialog) has been renamed from "Add new interfaces" to
"Interface Management"
* ui/gtk/capture_dlg.c: new_interfaces_w variable renamed to
interface_management_w
* Win32: Local Interfaces tab on Interface Management dialog, shows includes
friendly name as far left column
* Interface Management dialog defaults to larger size on win32 - so it fits
without resizing local interfaces tab
* Interface Management dialog now saves preferences when you click the apply
button (local hidden interfaces was not persisting across restarts)
* Tweaks: "Interface Details" dialog (Interface list->Capture Interfaces ->
Details):
+ "Friendly Name" renamed to "NDIS Friendly Name"
+ Added "OS Friendly Name" to the top of the list
* Win32: The "Capture Interfaces" dialog now shows the friendly name instead of
device guid
* Welcome screen:
+ The height of the interface list scrollbox dynamically adjusts & updates to
the number visible interfaces.
Up to 10 interfaces can be listed without a scroll bar, the minimum height
is for 2 interfaces.
+ Win32: now shows just the Friendly Name if known - in place of
"Interfacename_Guid:(Description)"
svn path=/trunk/; revision=46083
2012-11-19 20:07:27 +00:00
|
|
|
#ifdef _WIN32
|
2014-07-04 07:24:02 +00:00
|
|
|
#include "caputils/capture_win_ifnames.h" /* windows friendly interface names */
|
2013-05-22 01:19:18 +00:00
|
|
|
#endif
|
|
|
|
|
2018-08-21 19:08:41 +00:00
|
|
|
#if defined(__FreeBSD__) || defined(__OpenBSD__)
|
|
|
|
/*
|
|
|
|
* Needed for the code to get a device description.
|
|
|
|
*/
|
|
|
|
#include <errno.h>
|
|
|
|
#include <net/if.h>
|
|
|
|
#include <sys/sockio.h>
|
|
|
|
#endif
|
|
|
|
|
2013-05-22 01:19:18 +00:00
|
|
|
/*
|
|
|
|
* Given an interface name, find the "friendly name" and interface
|
|
|
|
* type for the interface.
|
|
|
|
*/
|
|
|
|
|
2017-10-15 11:16:46 +00:00
|
|
|
#if defined(HAVE_MACOS_FRAMEWORKS)
|
2013-05-22 01:19:18 +00:00
|
|
|
|
|
|
|
#include <CoreFoundation/CoreFoundation.h>
|
|
|
|
#include <SystemConfiguration/SystemConfiguration.h>
|
|
|
|
|
2014-06-21 18:01:19 +00:00
|
|
|
#include <wsutil/cfutils.h>
|
2013-05-22 01:19:18 +00:00
|
|
|
|
|
|
|
/*
|
2017-04-05 19:15:27 +00:00
|
|
|
* On macOS, we get the "friendly name" and interface type for the interface
|
2013-05-22 01:19:18 +00:00
|
|
|
* from the System Configuration framework.
|
|
|
|
*
|
|
|
|
* To find the System Configuration framework information for the
|
|
|
|
* interface, we get all the interfaces that the System Configuration
|
|
|
|
* framework knows about and look for the one with a "BSD name" matching
|
|
|
|
* the interface name.
|
|
|
|
*
|
|
|
|
* If we find it, we use its "localized display name", if it has one, as
|
|
|
|
* the "friendly name".
|
|
|
|
*
|
|
|
|
* As for the interface type:
|
|
|
|
*
|
|
|
|
* Yes, fetching all the network addresses for an interface gets you an
|
|
|
|
* AF_LINK address, of type "struct sockaddr_dl", and, yes, that includes
|
|
|
|
* an SNMP MIB-II ifType value.
|
|
|
|
*
|
|
|
|
* However, it's IFT_ETHER, i.e. Ethernet, for AirPort interfaces,
|
2017-04-05 19:15:27 +00:00
|
|
|
* not IFT_IEEE80211 (which isn't defined in macOS in any case).
|
2013-05-22 01:19:18 +00:00
|
|
|
*
|
|
|
|
* Perhaps some other BSD-flavored OSes won't make this mistake;
|
|
|
|
* however, FreeBSD 7.0 and OpenBSD 4.2, at least, appear to have
|
|
|
|
* made the same mistake, at least for my Belkin ZyDAS stick.
|
|
|
|
*
|
|
|
|
* SCNetworkInterfaceGetInterfaceType() will get the interface
|
|
|
|
* type. The interface type is a CFString, and:
|
|
|
|
*
|
|
|
|
* kSCNetworkInterfaceTypeIEEE80211 means IF_WIRELESS;
|
|
|
|
* kSCNetworkInterfaceTypeBluetooth means IF_BLUETOOTH;
|
|
|
|
* kSCNetworkInterfaceTypeModem or
|
|
|
|
* kSCNetworkInterfaceTypePPP or
|
|
|
|
* maybe kSCNetworkInterfaceTypeWWAN means IF_DIALUP
|
|
|
|
*/
|
|
|
|
static void
|
|
|
|
add_unix_interface_ifinfo(if_info_t *if_info, const char *name,
|
2015-02-13 18:43:32 +00:00
|
|
|
const char *description _U_)
|
2013-05-22 01:19:18 +00:00
|
|
|
{
|
|
|
|
CFStringRef name_CFString;
|
|
|
|
CFArrayRef interfaces;
|
|
|
|
CFIndex num_interfaces;
|
|
|
|
CFIndex i;
|
|
|
|
SCNetworkInterfaceRef interface;
|
|
|
|
CFStringRef bsdname_CFString;
|
|
|
|
CFStringRef friendly_name_CFString;
|
|
|
|
CFStringRef interface_type_CFString;
|
|
|
|
|
|
|
|
interfaces = SCNetworkInterfaceCopyAll();
|
|
|
|
if (interfaces == NULL) {
|
|
|
|
/*
|
|
|
|
* Couldn't get a list of interfaces.
|
|
|
|
*/
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
name_CFString = CFStringCreateWithCString(kCFAllocatorDefault,
|
|
|
|
name, kCFStringEncodingUTF8);
|
|
|
|
if (name_CFString == NULL) {
|
|
|
|
/*
|
|
|
|
* Couldn't convert the interface name to a CFString.
|
|
|
|
*/
|
|
|
|
CFRelease(interfaces);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
num_interfaces = CFArrayGetCount(interfaces);
|
|
|
|
for (i = 0; i < num_interfaces; i++) {
|
|
|
|
interface = (SCNetworkInterfaceRef)CFArrayGetValueAtIndex(interfaces, i);
|
|
|
|
bsdname_CFString = SCNetworkInterfaceGetBSDName(interface);
|
|
|
|
if (bsdname_CFString == NULL) {
|
|
|
|
/*
|
|
|
|
* This interface has no BSD name, so it's not
|
|
|
|
* a regular network interface.
|
|
|
|
*/
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
if (CFStringCompare(name_CFString, bsdname_CFString, 0) == 0) {
|
|
|
|
/*
|
|
|
|
* This is the interface.
|
|
|
|
* First, get the friendly name.
|
|
|
|
*/
|
|
|
|
friendly_name_CFString = SCNetworkInterfaceGetLocalizedDisplayName(interface);
|
|
|
|
if (friendly_name_CFString != NULL)
|
|
|
|
if_info->friendly_name = CFString_to_C_string(friendly_name_CFString);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Now get the interface type.
|
|
|
|
*/
|
|
|
|
interface_type_CFString = SCNetworkInterfaceGetInterfaceType(interface);
|
|
|
|
if (CFStringCompare(interface_type_CFString,
|
|
|
|
kSCNetworkInterfaceTypeIEEE80211, 0) == kCFCompareEqualTo)
|
|
|
|
if_info->type = IF_WIRELESS;
|
|
|
|
else if (CFStringCompare(interface_type_CFString,
|
|
|
|
kSCNetworkInterfaceTypeBluetooth, 0) == kCFCompareEqualTo)
|
|
|
|
if_info->type = IF_BLUETOOTH;
|
|
|
|
else if (CFStringCompare(interface_type_CFString,
|
|
|
|
kSCNetworkInterfaceTypeModem, 0) == kCFCompareEqualTo)
|
|
|
|
if_info->type = IF_DIALUP;
|
|
|
|
else if (CFStringCompare(interface_type_CFString,
|
|
|
|
kSCNetworkInterfaceTypePPP, 0) == kCFCompareEqualTo)
|
|
|
|
if_info->type = IF_DIALUP;
|
|
|
|
else if (CFStringCompare(interface_type_CFString,
|
|
|
|
kSCNetworkInterfaceTypeWWAN, 0) == kCFCompareEqualTo)
|
|
|
|
if_info->type = IF_DIALUP;
|
|
|
|
else
|
|
|
|
if_info->type = IF_WIRED;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
CFRelease(interfaces);
|
2013-06-17 07:20:23 +00:00
|
|
|
CFRelease(name_CFString);
|
2013-05-22 01:19:18 +00:00
|
|
|
}
|
|
|
|
#elif defined(__linux__)
|
|
|
|
/*
|
|
|
|
* Linux doesn't offer any form of "friendly name", but you can
|
|
|
|
* determine an interface type to some degree.
|
|
|
|
*/
|
|
|
|
static void
|
|
|
|
add_unix_interface_ifinfo(if_info_t *if_info, const char *name,
|
2015-02-13 18:43:32 +00:00
|
|
|
const char *description _U_)
|
2013-05-22 01:19:18 +00:00
|
|
|
{
|
|
|
|
char *wireless_path;
|
|
|
|
ws_statb64 statb;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Look for /sys/class/net/{device}/wireless. If it exists,
|
|
|
|
* it's a wireless interface.
|
|
|
|
*/
|
|
|
|
wireless_path = g_strdup_printf("/sys/class/net/%s/wireless", name);
|
|
|
|
if (wireless_path != NULL) {
|
|
|
|
if (ws_stat64(wireless_path, &statb) == 0)
|
|
|
|
if_info->type = IF_WIRELESS;
|
|
|
|
g_free(wireless_path);
|
|
|
|
}
|
|
|
|
if (if_info->type == IF_WIRED) {
|
|
|
|
/*
|
|
|
|
* We still don't know what it is. Check for
|
|
|
|
* Bluetooth and USB devices.
|
|
|
|
*/
|
|
|
|
if (strstr(name, "bluetooth") != NULL) {
|
|
|
|
/*
|
|
|
|
* XXX - this is for raw Bluetooth capture; what
|
|
|
|
* about IP-over-Bluetooth devices?
|
|
|
|
*/
|
|
|
|
if_info->type = IF_BLUETOOTH;
|
|
|
|
} else if (strstr(name, "usbmon") != NULL)
|
|
|
|
if_info->type = IF_USB;
|
|
|
|
}
|
|
|
|
}
|
2012-11-22 06:02:49 +00:00
|
|
|
#else
|
2013-05-22 01:19:18 +00:00
|
|
|
/*
|
|
|
|
* On other UN*Xes, if there is a description, it's a friendly
|
|
|
|
* name, and there is no vendor description. ("Other UN*Xes"
|
|
|
|
* currently means "FreeBSD and OpenBSD".)
|
|
|
|
*/
|
2018-02-17 23:17:40 +00:00
|
|
|
static void
|
2013-05-22 01:19:18 +00:00
|
|
|
add_unix_interface_ifinfo(if_info_t *if_info, const char *name _U_,
|
2015-02-13 18:43:32 +00:00
|
|
|
const char *description)
|
2013-05-22 01:19:18 +00:00
|
|
|
{
|
|
|
|
if_info->friendly_name = g_strdup(description);
|
|
|
|
}
|
From Mike Garratt:
Friendly Names for interfaces on Windows
Notes on the changes the patch covers:
* if_info_t struct: addition of friendly_name
* Dumpcap Interface list format changes:
+ Win32: "dumpcap -D" shows friendly_name in place of descript if known
+ All: machine interface "dumpcap -D -Z none" includes friendly_name in the
list in addition to the existing parameters
* interface_options struct: addition of console_display_name
+ When an interface name is displayed in a console, it will typically be the
console_display_name (instead of name).
+ console_display_name is used as the basis of the autogenerated temp
filenames
+ console_display_name is typically set to the friendly_name if known,
otherwise it is set to the interface name
* Enhancements to capture_opts_add_iface_opt() (the function which process -i
options).
+ Can now specify the interface using its name and friendly_name
+ Interface name matching is case insenstive
+ Name matching first attempts exact matching, then falls back to prefix
matching
(e.g. dumpcap -i local)
+ Validates interface names, instead of blindly sending them off to
winpcap/libpcap
+ Interface specification by number is still supported.
* capture_opts_trim_iface() has been refactored:
+ Instead of repeating a decent chunk of the cost in
capture_opts_add_iface_opt(), it calls capture_opts_trim_iface() to specify the
interface.
* introduction of capture_win_ifnames.[ch] (windows only code)
+ Implements static function GetInterfaceFriendlyNameFromDeviceGuid() - a
windows version independant function to convert an interface guid into its
friendly name. Uses published api functions on windows vista and higher, but
falls back to unpublished API functions on older windows releases.
+ void get_windows_interface_friendlyname(/* IN */ char
*interface_devicename, /* OUT */char **interface_friendlyname); - extracts the
GUID from the interface_devicename, then uses
GetInterfaceFriendlyNameFromDeviceGuid() to do the resolution
* Auto temp filename generation:
+ Now uses wireshark_pcapng_* or wireshark_pcap_* depending on file format
+ Basis temp filename format on console_display_name
+ Win32: if console_display_name is a windows interface guid, extracts
numbers from GUID here (instead of in interface option processing)
GUI CHANGES:
* Dialog that displays when you click the "Manage Interfaces" button (within
Capture Options dialog) has been renamed from "Add new interfaces" to
"Interface Management"
* ui/gtk/capture_dlg.c: new_interfaces_w variable renamed to
interface_management_w
* Win32: Local Interfaces tab on Interface Management dialog, shows includes
friendly name as far left column
* Interface Management dialog defaults to larger size on win32 - so it fits
without resizing local interfaces tab
* Interface Management dialog now saves preferences when you click the apply
button (local hidden interfaces was not persisting across restarts)
* Tweaks: "Interface Details" dialog (Interface list->Capture Interfaces ->
Details):
+ "Friendly Name" renamed to "NDIS Friendly Name"
+ Added "OS Friendly Name" to the top of the list
* Win32: The "Capture Interfaces" dialog now shows the friendly name instead of
device guid
* Welcome screen:
+ The height of the interface list scrollbox dynamically adjusts & updates to
the number visible interfaces.
Up to 10 interfaces can be listed without a scroll bar, the minimum height
is for 2 interfaces.
+ Win32: now shows just the Friendly Name if known - in place of
"Interfacename_Guid:(Description)"
svn path=/trunk/; revision=46083
2012-11-19 20:07:27 +00:00
|
|
|
#endif
|
|
|
|
|
2018-08-13 03:32:01 +00:00
|
|
|
if_info_t *
|
|
|
|
if_info_get(const char *name)
|
|
|
|
{
|
|
|
|
char *description = NULL;
|
|
|
|
if_info_t *if_info;
|
|
|
|
#ifdef SIOCGIFDESCR
|
|
|
|
/*
|
|
|
|
* Try to fetch the description of this interface.
|
|
|
|
* XXX - this is only here because libpcap has no API to
|
|
|
|
* get the description of a *single* interface; it really
|
|
|
|
* needs both an API to get pcapng-IDB-style attributes
|
|
|
|
* for a single interface and to get a list of interfaces
|
|
|
|
* with pcapng-IDB-style attributes for each interface.
|
|
|
|
*/
|
|
|
|
int s;
|
|
|
|
struct ifreq ifrdesc;
|
|
|
|
#ifndef IFDESCRSIZE
|
|
|
|
size_t descrlen = 64;
|
|
|
|
#else
|
|
|
|
size_t descrlen = IFDESCRSIZE;
|
|
|
|
#endif /* IFDESCRSIZE */
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Get the description for the interface.
|
|
|
|
*/
|
|
|
|
memset(&ifrdesc, 0, sizeof ifrdesc);
|
|
|
|
g_strlcpy(ifrdesc.ifr_name, name, sizeof ifrdesc.ifr_name);
|
|
|
|
s = socket(AF_INET, SOCK_DGRAM, 0);
|
|
|
|
if (s >= 0) {
|
|
|
|
#ifdef __FreeBSD__
|
|
|
|
/*
|
|
|
|
* On FreeBSD, if the buffer isn't big enough for the
|
|
|
|
* description, the ioctl succeeds, but the description
|
|
|
|
* isn't copied, ifr_buffer.length is set to the description
|
|
|
|
* length, and ifr_buffer.buffer is set to NULL.
|
|
|
|
*/
|
|
|
|
for (;;) {
|
|
|
|
g_free(description);
|
|
|
|
if ((description = g_malloc(descrlen)) != NULL) {
|
|
|
|
ifrdesc.ifr_buffer.buffer = description;
|
|
|
|
ifrdesc.ifr_buffer.length = descrlen;
|
|
|
|
if (ioctl(s, SIOCGIFDESCR, &ifrdesc) == 0) {
|
|
|
|
if (ifrdesc.ifr_buffer.buffer ==
|
|
|
|
description)
|
|
|
|
break;
|
|
|
|
else
|
|
|
|
descrlen = ifrdesc.ifr_buffer.length;
|
|
|
|
} else {
|
|
|
|
/*
|
|
|
|
* Failed to get interface description.
|
|
|
|
*/
|
|
|
|
g_free(description);
|
|
|
|
description = NULL;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
} else
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
#else /* __FreeBSD__ */
|
|
|
|
/*
|
|
|
|
* The only other OS that currently supports
|
|
|
|
* SIOCGIFDESCR is OpenBSD, and it has no way
|
|
|
|
* to get the description length - it's clamped
|
|
|
|
* to a maximum of IFDESCRSIZE.
|
|
|
|
*/
|
|
|
|
if ((description = g_malloc(descrlen)) != NULL) {
|
|
|
|
ifrdesc.ifr_data = (caddr_t)description;
|
|
|
|
if (ioctl(s, SIOCGIFDESCR, &ifrdesc) != 0) {
|
|
|
|
/*
|
|
|
|
* Failed to get interface description.
|
|
|
|
*/
|
|
|
|
g_free(description);
|
|
|
|
description = NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif /* __FreeBSD__ */
|
|
|
|
close(s);
|
|
|
|
if (description != NULL && strlen(description) == 0) {
|
|
|
|
/*
|
|
|
|
* Description is empty, so discard it.
|
|
|
|
*/
|
|
|
|
g_free(description);
|
|
|
|
description = NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#ifdef __FreeBSD__
|
|
|
|
/*
|
|
|
|
* For FreeBSD, if we didn't get a description, and this is
|
|
|
|
* a device with a name of the form usbusN, label it as a USB
|
|
|
|
* bus.
|
|
|
|
*/
|
|
|
|
if (description == NULL) {
|
|
|
|
if (strncmp(name, "usbus", 5) == 0) {
|
|
|
|
/*
|
|
|
|
* OK, it begins with "usbus".
|
|
|
|
*/
|
|
|
|
long busnum;
|
|
|
|
char *p;
|
|
|
|
|
|
|
|
errno = 0;
|
|
|
|
busnum = strtol(name + 5, &p, 10);
|
|
|
|
if (errno == 0 && p != name + 5 && *p == '\0' &&
|
|
|
|
busnum >= 0 && busnum <= INT_MAX) {
|
|
|
|
/*
|
|
|
|
* OK, it's a valid number that's not
|
|
|
|
* bigger than INT_MAX. Construct
|
|
|
|
* a description from it.
|
|
|
|
*/
|
|
|
|
static const char descr_prefix[] = "USB bus number ";
|
|
|
|
size_t descr_size;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Allow enough room for a 32-bit bus number.
|
|
|
|
* sizeof (descr_prefix) includes the
|
|
|
|
* terminating NUL.
|
|
|
|
*/
|
|
|
|
descr_size = sizeof (descr_prefix) + 10;
|
|
|
|
description = g_malloc(descr_size);
|
|
|
|
if (description != NULL) {
|
2018-08-21 19:00:17 +00:00
|
|
|
g_snprintf(description, descr_size,
|
2018-08-13 03:32:01 +00:00
|
|
|
"%s%ld", descr_prefix, busnum);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif /* __FreeBSD__ */
|
|
|
|
#endif /* SIOCGIFDESCR */
|
|
|
|
if_info = if_info_new(name, description, FALSE);
|
|
|
|
g_free(description);
|
|
|
|
return if_info;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
if_info_free(if_info_t *if_info)
|
|
|
|
{
|
|
|
|
g_free(if_info->name);
|
|
|
|
g_free(if_info->friendly_name);
|
|
|
|
g_free(if_info->vendor_description);
|
|
|
|
g_free(if_info->extcap);
|
|
|
|
g_slist_free_full(if_info->addrs, g_free);
|
|
|
|
g_free(if_info);
|
|
|
|
}
|
|
|
|
|
2004-07-18 00:24:25 +00:00
|
|
|
if_info_t *
|
2012-11-23 22:28:06 +00:00
|
|
|
if_info_new(const char *name, const char *description, gboolean loopback)
|
2004-07-18 00:24:25 +00:00
|
|
|
{
|
|
|
|
if_info_t *if_info;
|
2012-11-24 18:55:06 +00:00
|
|
|
#ifdef _WIN32
|
|
|
|
const char *guid_text;
|
|
|
|
GUID guid;
|
|
|
|
#endif
|
2004-07-18 00:24:25 +00:00
|
|
|
|
2010-03-04 09:37:05 +00:00
|
|
|
if_info = (if_info_t *)g_malloc(sizeof (if_info_t));
|
2004-07-18 00:24:25 +00:00
|
|
|
if_info->name = g_strdup(name);
|
2013-05-22 01:19:18 +00:00
|
|
|
if_info->friendly_name = NULL; /* default - unknown */
|
|
|
|
if_info->vendor_description = NULL;
|
|
|
|
if_info->type = IF_WIRED; /* default */
|
2014-02-25 13:05:11 +00:00
|
|
|
if_info->extcap = g_strdup("");
|
2012-11-23 22:28:06 +00:00
|
|
|
#ifdef _WIN32
|
2013-05-22 01:19:18 +00:00
|
|
|
/*
|
|
|
|
* Get the interface type.
|
|
|
|
*
|
|
|
|
* Much digging failed to reveal any obvious way to get something
|
|
|
|
* such as the SNMP MIB-II ifType value for an interface:
|
|
|
|
*
|
|
|
|
* http://www.iana.org/assignments/ianaiftype-mib
|
|
|
|
*
|
|
|
|
* by making some NDIS request. And even if there were such
|
|
|
|
* a way, there's no guarantee that the ifType reflects an
|
|
|
|
* interface type that a user would view as correct (for
|
|
|
|
* example, some systems report Wi-Fi interfaces as
|
|
|
|
* Ethernet interfaces).
|
|
|
|
*
|
|
|
|
* So we look for keywords in the vendor's interface
|
|
|
|
* description.
|
|
|
|
*/
|
|
|
|
if (description && (strstr(description, "generic dialup") != NULL ||
|
|
|
|
strstr(description, "PPP/SLIP") != NULL)) {
|
|
|
|
if_info->type = IF_DIALUP;
|
|
|
|
} else if (description && (strstr(description, "Wireless") != NULL ||
|
|
|
|
strstr(description,"802.11") != NULL)) {
|
|
|
|
if_info->type = IF_WIRELESS;
|
|
|
|
} else if (description && strstr(description, "AirPcap") != NULL ||
|
|
|
|
strstr(name, "airpcap") != NULL) {
|
|
|
|
if_info->type = IF_AIRPCAP;
|
|
|
|
} else if (description && strstr(description, "Bluetooth") != NULL ) {
|
|
|
|
if_info->type = IF_BLUETOOTH;
|
|
|
|
} else if (description && strstr(description, "VMware") != NULL) {
|
|
|
|
/*
|
|
|
|
* Bridge, NAT, or host-only interface on a VMware host.
|
|
|
|
*
|
|
|
|
* XXX - what about guest interfaces?
|
|
|
|
*/
|
|
|
|
if_info->type = IF_VIRTUAL;
|
|
|
|
}
|
|
|
|
|
2012-11-23 22:28:06 +00:00
|
|
|
/*
|
|
|
|
* On Windows, the "description" is a vendor description,
|
2019-02-08 19:08:01 +00:00
|
|
|
* and the friendly name isn't returned by Npcap/WinPcap.
|
2012-11-23 22:28:06 +00:00
|
|
|
* Fetch it ourselves.
|
|
|
|
*/
|
2012-11-24 18:55:06 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Skip over the "\Device\NPF_" prefix in the device name,
|
|
|
|
* if present.
|
|
|
|
*/
|
|
|
|
if (strncmp("\\Device\\NPF_", name, 12) == 0)
|
|
|
|
guid_text = name + 12;
|
|
|
|
else
|
|
|
|
guid_text = name;
|
|
|
|
|
|
|
|
/* Now try to parse what remains as a GUID. */
|
|
|
|
if (parse_as_guid(guid_text, &guid)) {
|
|
|
|
/*
|
|
|
|
* Success. Try to get a friendly name using the GUID.
|
|
|
|
* As this is a regular interface, the description is a
|
|
|
|
* vendor description.
|
|
|
|
*/
|
|
|
|
if_info->friendly_name = get_interface_friendly_name_from_device_guid(&guid);
|
|
|
|
if_info->vendor_description = g_strdup(description);
|
|
|
|
} else {
|
|
|
|
/*
|
|
|
|
* This is probably not a regular interface; we only
|
|
|
|
* support NT 5 (W2K) and later, so all regular interfaces
|
|
|
|
* should have GUIDs at the end of the name. Therefore,
|
|
|
|
* the description, if supplied, is a friendly name
|
|
|
|
* provided by WinPcap, and there is no vendor
|
|
|
|
* description.
|
|
|
|
*/
|
|
|
|
if_info->friendly_name = g_strdup(description);
|
2012-11-24 19:08:28 +00:00
|
|
|
if_info->vendor_description = NULL;
|
2012-11-24 18:55:06 +00:00
|
|
|
}
|
2012-11-23 22:28:06 +00:00
|
|
|
#else
|
|
|
|
/*
|
|
|
|
* On UN*X, if there is a description, it's a friendly
|
|
|
|
* name, and there is no vendor description.
|
2013-05-22 01:19:18 +00:00
|
|
|
*
|
|
|
|
* Try the platform's way of getting a friendly name and
|
|
|
|
* interface type first.
|
|
|
|
*
|
|
|
|
* If that fails, then, for a loopback interface, give it the
|
|
|
|
* friendly name "Loopback" and, for VMware interfaces,
|
|
|
|
* give them the type IF_VIRTUAL.
|
2012-11-23 22:28:06 +00:00
|
|
|
*/
|
2013-05-22 01:19:18 +00:00
|
|
|
add_unix_interface_ifinfo(if_info, name, description);
|
|
|
|
if (if_info->type == IF_WIRED) {
|
|
|
|
/*
|
|
|
|
* This is the default interface type.
|
|
|
|
*
|
|
|
|
* Bridge, NAT, or host-only interfaces on VMWare hosts
|
|
|
|
* have the name vmnet[0-9]+. Guests might use a native
|
|
|
|
* (LANCE or E1000) driver or the vmxnet driver. Check
|
|
|
|
* the name.
|
|
|
|
*/
|
|
|
|
if (g_ascii_strncasecmp(name, "vmnet", 5) == 0)
|
|
|
|
if_info->type = IF_VIRTUAL;
|
|
|
|
else if (g_ascii_strncasecmp(name, "vmxnet", 6) == 0)
|
|
|
|
if_info->type = IF_VIRTUAL;
|
|
|
|
}
|
2012-11-23 22:28:06 +00:00
|
|
|
if (if_info->friendly_name == NULL) {
|
2013-05-22 01:19:18 +00:00
|
|
|
/*
|
|
|
|
* We couldn't get interface information using platform-
|
|
|
|
* dependent calls.
|
|
|
|
*
|
|
|
|
* If this is a loopback interface, give it a
|
|
|
|
* "friendly name" of "Loopback".
|
|
|
|
*/
|
|
|
|
if (loopback)
|
|
|
|
if_info->friendly_name = g_strdup("Loopback");
|
2012-11-23 22:28:06 +00:00
|
|
|
}
|
|
|
|
if_info->vendor_description = NULL;
|
|
|
|
#endif
|
2012-11-22 06:02:49 +00:00
|
|
|
if_info->loopback = loopback;
|
2010-03-04 01:12:04 +00:00
|
|
|
if_info->addrs = NULL;
|
2004-07-18 00:24:25 +00:00
|
|
|
return if_info;
|
|
|
|
}
|
|
|
|
|
2004-07-18 02:34:45 +00:00
|
|
|
void
|
|
|
|
if_info_add_address(if_info_t *if_info, struct sockaddr *addr)
|
2004-07-18 00:24:25 +00:00
|
|
|
{
|
2010-03-04 01:12:04 +00:00
|
|
|
if_addr_t *if_addr;
|
2004-07-18 23:07:04 +00:00
|
|
|
struct sockaddr_in *ai;
|
2004-07-19 01:06:06 +00:00
|
|
|
struct sockaddr_in6 *ai6;
|
2004-07-18 00:24:25 +00:00
|
|
|
|
2004-07-18 02:34:45 +00:00
|
|
|
switch (addr->sa_family) {
|
|
|
|
|
|
|
|
case AF_INET:
|
2011-04-26 02:47:52 +00:00
|
|
|
ai = (struct sockaddr_in *)(void *)addr;
|
2010-03-04 09:37:05 +00:00
|
|
|
if_addr = (if_addr_t *)g_malloc(sizeof(*if_addr));
|
2010-03-04 01:12:04 +00:00
|
|
|
if_addr->ifat_type = IF_AT_IPv4;
|
|
|
|
if_addr->addr.ip4_addr =
|
2004-07-18 23:07:04 +00:00
|
|
|
*((guint32 *)&(ai->sin_addr.s_addr));
|
2016-09-28 11:31:14 +00:00
|
|
|
if_info->addrs = g_slist_prepend(if_info->addrs, if_addr);
|
2004-07-18 18:47:44 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case AF_INET6:
|
2011-04-26 02:47:52 +00:00
|
|
|
ai6 = (struct sockaddr_in6 *)(void *)addr;
|
2010-03-04 09:37:05 +00:00
|
|
|
if_addr = (if_addr_t *)g_malloc(sizeof(*if_addr));
|
2010-03-04 01:12:04 +00:00
|
|
|
if_addr->ifat_type = IF_AT_IPv6;
|
|
|
|
memcpy((void *)&if_addr->addr.ip6_addr,
|
2004-07-19 01:06:06 +00:00
|
|
|
(void *)&ai6->sin6_addr.s6_addr,
|
2010-03-04 01:12:04 +00:00
|
|
|
sizeof if_addr->addr.ip6_addr);
|
2016-09-28 11:31:14 +00:00
|
|
|
if_info->addrs = g_slist_prepend(if_info->addrs, if_addr);
|
2004-07-18 02:34:45 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2004-07-18 00:24:25 +00:00
|
|
|
|
|
|
|
#ifdef HAVE_PCAP_FINDALLDEVS
|
2004-07-18 02:34:45 +00:00
|
|
|
/*
|
2012-11-22 06:02:49 +00:00
|
|
|
* Get all IP address information for the given interface.
|
2004-07-18 02:34:45 +00:00
|
|
|
*/
|
|
|
|
static void
|
|
|
|
if_info_ip(if_info_t *if_info, pcap_if_t *d)
|
|
|
|
{
|
|
|
|
pcap_addr_t *a;
|
|
|
|
|
|
|
|
/* All addresses */
|
|
|
|
for (a = d->addresses; a != NULL; a = a->next) {
|
|
|
|
if (a->addr != NULL)
|
|
|
|
if_info_add_address(if_info, a->addr);
|
|
|
|
}
|
2016-09-28 11:31:14 +00:00
|
|
|
|
|
|
|
if(if_info->addrs){
|
|
|
|
if_info->addrs = g_slist_reverse(if_info->addrs);
|
|
|
|
}
|
2004-07-18 02:34:45 +00:00
|
|
|
}
|
|
|
|
|
2007-12-04 11:19:29 +00:00
|
|
|
#ifdef HAVE_PCAP_REMOTE
|
|
|
|
GList *
|
|
|
|
get_interface_list_findalldevs_ex(const char *source,
|
2015-02-13 18:43:32 +00:00
|
|
|
struct pcap_rmtauth *auth,
|
|
|
|
int *err, char **err_str)
|
2008-11-03 20:04:01 +00:00
|
|
|
{
|
|
|
|
GList *il = NULL;
|
|
|
|
pcap_if_t *alldevs, *dev;
|
|
|
|
if_info_t *if_info;
|
2014-08-27 20:55:12 +00:00
|
|
|
/*
|
|
|
|
* WinPcap can overflow PCAP_ERRBUF_SIZE if the host is unreachable.
|
|
|
|
* Fudge a larger size.
|
|
|
|
*/
|
|
|
|
char errbuf[PCAP_ERRBUF_SIZE*4];
|
2008-11-03 20:04:01 +00:00
|
|
|
|
2014-08-27 20:55:12 +00:00
|
|
|
if (pcap_findalldevs_ex((char *)source, auth, &alldevs, errbuf) == -1) {
|
2008-11-03 20:04:01 +00:00
|
|
|
*err = CANT_GET_INTERFACE_LIST;
|
|
|
|
if (err_str != NULL)
|
|
|
|
*err_str = cant_get_if_list_error_message(errbuf);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (alldevs == NULL) {
|
|
|
|
/*
|
|
|
|
* No interfaces found.
|
|
|
|
*/
|
2014-07-22 23:53:18 +00:00
|
|
|
*err = 0;
|
2008-11-03 20:04:01 +00:00
|
|
|
if (err_str != NULL)
|
|
|
|
*err_str = NULL;
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (dev = alldevs; dev != NULL; dev = dev->next) {
|
2012-11-23 22:28:06 +00:00
|
|
|
if_info = if_info_new(dev->name, dev->description,
|
|
|
|
(dev->flags & PCAP_IF_LOOPBACK) ? TRUE : FALSE);
|
2008-11-03 20:04:01 +00:00
|
|
|
il = g_list_append(il, if_info);
|
|
|
|
if_info_ip(if_info, dev);
|
|
|
|
}
|
|
|
|
pcap_freealldevs(alldevs);
|
|
|
|
|
|
|
|
return il;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2004-07-18 00:24:25 +00:00
|
|
|
GList *
|
2007-01-21 23:45:36 +00:00
|
|
|
get_interface_list_findalldevs(int *err, char **err_str)
|
2004-07-18 00:24:25 +00:00
|
|
|
{
|
|
|
|
GList *il = NULL;
|
|
|
|
pcap_if_t *alldevs, *dev;
|
|
|
|
if_info_t *if_info;
|
2007-01-21 23:45:36 +00:00
|
|
|
char errbuf[PCAP_ERRBUF_SIZE];
|
2004-07-18 00:24:25 +00:00
|
|
|
|
2007-01-21 23:45:36 +00:00
|
|
|
if (pcap_findalldevs(&alldevs, errbuf) == -1) {
|
2004-07-18 00:24:25 +00:00
|
|
|
*err = CANT_GET_INTERFACE_LIST;
|
2007-01-21 23:45:36 +00:00
|
|
|
if (err_str != NULL)
|
|
|
|
*err_str = cant_get_if_list_error_message(errbuf);
|
2004-07-18 00:24:25 +00:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (alldevs == NULL) {
|
|
|
|
/*
|
|
|
|
* No interfaces found.
|
|
|
|
*/
|
2014-07-22 23:53:18 +00:00
|
|
|
*err = 0;
|
2007-01-21 23:45:36 +00:00
|
|
|
if (err_str != NULL)
|
|
|
|
*err_str = NULL;
|
2004-07-18 00:24:25 +00:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (dev = alldevs; dev != NULL; dev = dev->next) {
|
2012-11-23 22:28:06 +00:00
|
|
|
if_info = if_info_new(dev->name, dev->description,
|
|
|
|
(dev->flags & PCAP_IF_LOOPBACK) ? TRUE : FALSE);
|
2004-07-18 00:24:25 +00:00
|
|
|
il = g_list_append(il, if_info);
|
|
|
|
if_info_ip(if_info, dev);
|
|
|
|
}
|
|
|
|
pcap_freealldevs(alldevs);
|
|
|
|
|
|
|
|
return il;
|
|
|
|
}
|
|
|
|
#endif /* HAVE_PCAP_FINDALLDEVS */
|
|
|
|
|
|
|
|
static void
|
|
|
|
free_if_cb(gpointer data, gpointer user_data _U_)
|
|
|
|
{
|
2018-08-13 03:32:01 +00:00
|
|
|
if_info_free((if_info_t *)data);
|
2004-07-18 00:24:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
free_interface_list(GList *if_list)
|
|
|
|
{
|
|
|
|
g_list_foreach(if_list, free_if_cb, NULL);
|
|
|
|
g_list_free(if_list);
|
|
|
|
}
|
|
|
|
|
2008-12-21 23:22:12 +00:00
|
|
|
#if !defined(HAVE_PCAP_DATALINK_NAME_TO_VAL) || !defined(HAVE_PCAP_DATALINK_VAL_TO_NAME) || !defined(HAVE_PCAP_DATALINK_VAL_TO_DESCRIPTION)
|
|
|
|
struct dlt_choice {
|
|
|
|
const char *name;
|
|
|
|
const char *description;
|
|
|
|
int dlt;
|
|
|
|
};
|
|
|
|
|
|
|
|
#define DLT_CHOICE(code, description) { #code, description, code }
|
|
|
|
#define DLT_CHOICE_SENTINEL { NULL, NULL, 0 }
|
|
|
|
|
|
|
|
static struct dlt_choice dlt_choices[] = {
|
2015-02-13 18:43:32 +00:00
|
|
|
DLT_CHOICE(DLT_NULL, "BSD loopback"),
|
|
|
|
DLT_CHOICE(DLT_EN10MB, "Ethernet"),
|
|
|
|
DLT_CHOICE(DLT_IEEE802, "Token ring"),
|
|
|
|
DLT_CHOICE(DLT_ARCNET, "ARCNET"),
|
|
|
|
DLT_CHOICE(DLT_SLIP, "SLIP"),
|
|
|
|
DLT_CHOICE(DLT_PPP, "PPP"),
|
|
|
|
DLT_CHOICE(DLT_FDDI, "FDDI"),
|
|
|
|
DLT_CHOICE(DLT_ATM_RFC1483, "RFC 1483 IP-over-ATM"),
|
|
|
|
DLT_CHOICE(DLT_RAW, "Raw IP"),
|
|
|
|
DLT_CHOICE(DLT_SLIP_BSDOS, "BSD/OS SLIP"),
|
|
|
|
DLT_CHOICE(DLT_PPP_BSDOS, "BSD/OS PPP"),
|
|
|
|
DLT_CHOICE(DLT_ATM_CLIP, "Linux Classical IP-over-ATM"),
|
|
|
|
DLT_CHOICE(DLT_PPP_SERIAL, "PPP over serial"),
|
|
|
|
DLT_CHOICE(DLT_PPP_ETHER, "PPPoE"),
|
|
|
|
DLT_CHOICE(DLT_C_HDLC, "Cisco HDLC"),
|
|
|
|
DLT_CHOICE(DLT_IEEE802_11, "802.11"),
|
|
|
|
DLT_CHOICE(DLT_FRELAY, "Frame Relay"),
|
|
|
|
DLT_CHOICE(DLT_LOOP, "OpenBSD loopback"),
|
|
|
|
DLT_CHOICE(DLT_ENC, "OpenBSD encapsulated IP"),
|
|
|
|
DLT_CHOICE(DLT_LINUX_SLL, "Linux cooked"),
|
|
|
|
DLT_CHOICE(DLT_LTALK, "Localtalk"),
|
|
|
|
DLT_CHOICE(DLT_PFLOG, "OpenBSD pflog file"),
|
|
|
|
DLT_CHOICE(DLT_PRISM_HEADER, "802.11 plus Prism header"),
|
|
|
|
DLT_CHOICE(DLT_IP_OVER_FC, "RFC 2625 IP-over-Fibre Channel"),
|
|
|
|
DLT_CHOICE(DLT_SUNATM, "Sun raw ATM"),
|
|
|
|
DLT_CHOICE(DLT_IEEE802_11_RADIO, "802.11 plus BSD radio information header"),
|
2008-12-21 23:22:12 +00:00
|
|
|
DLT_CHOICE(DLT_APPLE_IP_OVER_IEEE1394, "Apple IP-over-IEEE 1394"),
|
2015-02-13 18:43:32 +00:00
|
|
|
DLT_CHOICE(DLT_ARCNET_LINUX, "Linux ARCNET"),
|
|
|
|
DLT_CHOICE(DLT_LINUX_IRDA, "Linux IrDA"),
|
|
|
|
DLT_CHOICE(DLT_IEEE802_11_RADIO_AVS, "802.11 plus AVS radio information header"),
|
2008-12-21 23:22:12 +00:00
|
|
|
DLT_CHOICE_SENTINEL
|
|
|
|
};
|
|
|
|
|
|
|
|
#if !defined(HAVE_PCAP_DATALINK_NAME_TO_VAL)
|
|
|
|
static int
|
|
|
|
pcap_datalink_name_to_val(const char *name)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
|
|
|
|
for (i = 0; dlt_choices[i].name != NULL; i++) {
|
|
|
|
if (g_ascii_strcasecmp(dlt_choices[i].name + sizeof("DLT_") - 1,
|
|
|
|
name) == 0)
|
|
|
|
return (dlt_choices[i].dlt);
|
|
|
|
}
|
|
|
|
return (-1);
|
|
|
|
}
|
|
|
|
#endif /* defined(HAVE_PCAP_DATALINK_NAME_TO_VAL) */
|
|
|
|
|
|
|
|
#if !defined(HAVE_PCAP_DATALINK_VAL_TO_NAME)
|
|
|
|
static const char *
|
|
|
|
pcap_datalink_val_to_name(int dlt)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
|
|
|
|
for (i = 0; dlt_choices[i].name != NULL; i++) {
|
|
|
|
if (dlt_choices[i].dlt == dlt)
|
|
|
|
return (dlt_choices[i].name + sizeof("DLT_") - 1);
|
|
|
|
}
|
|
|
|
return (NULL);
|
|
|
|
}
|
|
|
|
#endif /* defined(HAVE_PCAP_DATALINK_VAL_TO_NAME) */
|
|
|
|
|
|
|
|
#if !defined(HAVE_PCAP_DATALINK_VAL_TO_DESCRIPTION)
|
|
|
|
const char *
|
|
|
|
pcap_datalink_val_to_description(int dlt)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
|
|
|
|
for (i = 0; dlt_choices[i].name != NULL; i++) {
|
|
|
|
if (dlt_choices[i].dlt == dlt)
|
|
|
|
return (dlt_choices[i].description);
|
|
|
|
}
|
|
|
|
return (NULL);
|
|
|
|
}
|
|
|
|
#endif /* defined(HAVE_PCAP_DATALINK_VAL_TO_DESCRIPTION) */
|
|
|
|
|
|
|
|
#endif /* !defined(HAVE_PCAP_DATALINK_VAL_TO_NAME) || !defined(HAVE_PCAP_DATALINK_VAL_TO_DESCRIPTION) */
|
|
|
|
|
2004-07-18 00:24:25 +00:00
|
|
|
static void
|
|
|
|
free_linktype_cb(gpointer data, gpointer user_data _U_)
|
|
|
|
{
|
2010-03-04 09:37:05 +00:00
|
|
|
data_link_info_t *linktype_info = (data_link_info_t *)data;
|
2004-07-18 00:24:25 +00:00
|
|
|
|
|
|
|
g_free(linktype_info->name);
|
2009-03-15 18:08:46 +00:00
|
|
|
g_free(linktype_info->description);
|
2015-10-04 09:31:19 +00:00
|
|
|
g_free(linktype_info);
|
2004-07-18 00:24:25 +00:00
|
|
|
}
|
|
|
|
|
2017-08-07 14:38:52 +00:00
|
|
|
static void
|
|
|
|
free_timestamp_cb(gpointer data, gpointer user_data _U_)
|
|
|
|
{
|
2017-08-25 12:05:42 +00:00
|
|
|
timestamp_info_t *timestamp_info = (timestamp_info_t *)data;
|
|
|
|
|
|
|
|
g_free(timestamp_info->name);
|
|
|
|
g_free(timestamp_info->description);
|
2017-08-07 14:38:52 +00:00
|
|
|
g_free(data);
|
|
|
|
}
|
|
|
|
|
2004-07-18 00:24:25 +00:00
|
|
|
void
|
2010-05-14 00:49:28 +00:00
|
|
|
free_if_capabilities(if_capabilities_t *caps)
|
2004-07-18 00:24:25 +00:00
|
|
|
{
|
2010-05-13 17:37:39 +00:00
|
|
|
g_list_foreach(caps->data_link_types, free_linktype_cb, NULL);
|
|
|
|
g_list_free(caps->data_link_types);
|
2017-08-07 14:38:52 +00:00
|
|
|
|
|
|
|
g_list_foreach(caps->timestamp_types, free_timestamp_cb, NULL);
|
|
|
|
g_list_free(caps->timestamp_types);
|
|
|
|
|
2010-05-13 17:37:39 +00:00
|
|
|
g_free(caps);
|
2004-07-18 00:24:25 +00:00
|
|
|
}
|
|
|
|
|
2006-02-17 02:18:48 +00:00
|
|
|
const char *
|
|
|
|
linktype_val_to_name(int dlt)
|
|
|
|
{
|
2015-02-13 18:43:32 +00:00
|
|
|
return pcap_datalink_val_to_name(dlt);
|
2006-02-17 02:18:48 +00:00
|
|
|
}
|
|
|
|
|
2016-01-05 21:54:02 +00:00
|
|
|
int
|
|
|
|
linktype_name_to_val(const char *linktype)
|
2006-02-17 02:18:48 +00:00
|
|
|
{
|
2015-02-13 18:43:32 +00:00
|
|
|
return pcap_datalink_name_to_val(linktype);
|
2006-02-17 02:18:48 +00:00
|
|
|
}
|
|
|
|
|
2016-01-05 21:54:02 +00:00
|
|
|
/*
|
|
|
|
* Get the data-link type for a libpcap device.
|
|
|
|
* This works around AIX 5.x's non-standard and incompatible-with-the-
|
|
|
|
* rest-of-the-universe libpcap.
|
|
|
|
*/
|
|
|
|
int
|
|
|
|
get_pcap_datalink(pcap_t *pch, const char *devicename
|
|
|
|
#ifndef _AIX
|
|
|
|
_U_)
|
|
|
|
#else
|
|
|
|
)
|
|
|
|
#endif
|
|
|
|
{
|
|
|
|
int datalink;
|
|
|
|
#ifdef _AIX
|
|
|
|
const char *ifacename;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
datalink = pcap_datalink(pch);
|
|
|
|
#ifdef _AIX
|
|
|
|
|
|
|
|
/*
|
|
|
|
* The libpcap that comes with AIX 5.x uses RFC 1573 ifType values
|
|
|
|
* rather than DLT_ values for link-layer types; the ifType values
|
|
|
|
* for LAN devices are:
|
|
|
|
*
|
|
|
|
* Ethernet 6
|
|
|
|
* 802.3 7
|
|
|
|
* Token Ring 9
|
|
|
|
* FDDI 15
|
|
|
|
*
|
|
|
|
* and the ifType value for a loopback device is 24.
|
|
|
|
*
|
|
|
|
* The AIX names for LAN devices begin with:
|
|
|
|
*
|
|
|
|
* Ethernet en
|
|
|
|
* 802.3 et
|
|
|
|
* Token Ring tr
|
|
|
|
* FDDI fi
|
|
|
|
*
|
|
|
|
* and the AIX names for loopback devices begin with "lo".
|
|
|
|
*
|
|
|
|
* (The difference between "Ethernet" and "802.3" is presumably
|
|
|
|
* whether packets have an Ethernet header, with a packet type,
|
|
|
|
* or an 802.3 header, with a packet length, followed by an 802.2
|
|
|
|
* header and possibly a SNAP header.)
|
|
|
|
*
|
|
|
|
* If the device name matches "datalink" interpreted as an ifType
|
|
|
|
* value, rather than as a DLT_ value, we will assume this is AIX's
|
|
|
|
* non-standard, incompatible libpcap, rather than a standard libpcap,
|
|
|
|
* and will map the link-layer type to the standard DLT_ value for
|
|
|
|
* that link-layer type, as that's what the rest of Wireshark expects.
|
|
|
|
*
|
|
|
|
* (This means the capture files won't be readable by a tcpdump
|
|
|
|
* linked with AIX's non-standard libpcap, but so it goes. They
|
|
|
|
* *will* be readable by standard versions of tcpdump, Wireshark,
|
|
|
|
* and so on.)
|
|
|
|
*
|
|
|
|
* XXX - if we conclude we're using AIX libpcap, should we also
|
|
|
|
* set a flag to cause us to assume the time stamps are in
|
|
|
|
* seconds-and-nanoseconds form, and to convert them to
|
|
|
|
* seconds-and-microseconds form before processing them and
|
|
|
|
* writing them out?
|
|
|
|
*/
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Find the last component of the device name, which is the
|
|
|
|
* interface name.
|
|
|
|
*/
|
|
|
|
ifacename = strchr(devicename, '/');
|
|
|
|
if (ifacename == NULL)
|
|
|
|
ifacename = devicename;
|
|
|
|
|
|
|
|
/* See if it matches any of the LAN device names. */
|
|
|
|
if (strncmp(ifacename, "en", 2) == 0) {
|
|
|
|
if (datalink == 6) {
|
|
|
|
/*
|
|
|
|
* That's the RFC 1573 value for Ethernet;
|
|
|
|
* map it to DLT_EN10MB.
|
|
|
|
*/
|
|
|
|
datalink = 1;
|
|
|
|
}
|
|
|
|
} else if (strncmp(ifacename, "et", 2) == 0) {
|
|
|
|
if (datalink == 7) {
|
|
|
|
/*
|
|
|
|
* That's the RFC 1573 value for 802.3;
|
|
|
|
* map it to DLT_EN10MB.
|
|
|
|
*
|
|
|
|
* (libpcap, tcpdump, Wireshark, etc. don't
|
|
|
|
* care if it's Ethernet or 802.3.)
|
|
|
|
*/
|
|
|
|
datalink = 1;
|
|
|
|
}
|
|
|
|
} else if (strncmp(ifacename, "tr", 2) == 0) {
|
|
|
|
if (datalink == 9) {
|
|
|
|
/*
|
|
|
|
* That's the RFC 1573 value for 802.5 (Token Ring);
|
|
|
|
* map it to DLT_IEEE802, which is what's used for
|
|
|
|
* Token Ring.
|
|
|
|
*/
|
|
|
|
datalink = 6;
|
|
|
|
}
|
|
|
|
} else if (strncmp(ifacename, "fi", 2) == 0) {
|
|
|
|
if (datalink == 15) {
|
|
|
|
/*
|
|
|
|
* That's the RFC 1573 value for FDDI;
|
|
|
|
* map it to DLT_FDDI.
|
|
|
|
*/
|
|
|
|
datalink = 10;
|
|
|
|
}
|
|
|
|
} else if (strncmp(ifacename, "lo", 2) == 0) {
|
|
|
|
if (datalink == 24) {
|
|
|
|
/*
|
|
|
|
* That's the RFC 1573 value for "software loopback"
|
|
|
|
* devices; map it to DLT_NULL, which is what's used
|
|
|
|
* for loopback devices on BSD.
|
|
|
|
*/
|
|
|
|
datalink = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
return datalink;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Set the data link type on a pcap. */
|
|
|
|
gboolean
|
|
|
|
set_pcap_datalink(pcap_t *pcap_h, int datalink, char *name,
|
|
|
|
char *errmsg, size_t errmsg_len,
|
|
|
|
char *secondary_errmsg, size_t secondary_errmsg_len)
|
|
|
|
{
|
|
|
|
char *set_datalink_err_str;
|
|
|
|
|
|
|
|
if (datalink == -1)
|
|
|
|
return TRUE; /* just use the default */
|
|
|
|
#ifdef HAVE_PCAP_SET_DATALINK
|
|
|
|
if (pcap_set_datalink(pcap_h, datalink) == 0)
|
|
|
|
return TRUE; /* no error */
|
|
|
|
set_datalink_err_str = pcap_geterr(pcap_h);
|
|
|
|
#else
|
|
|
|
/* Let them set it to the type it is; reject any other request. */
|
|
|
|
if (get_pcap_datalink(pcap_h, name) == datalink)
|
|
|
|
return TRUE; /* no error */
|
|
|
|
set_datalink_err_str =
|
|
|
|
"That DLT isn't one of the DLTs supported by this device";
|
|
|
|
#endif
|
|
|
|
g_snprintf(errmsg, (gulong) errmsg_len, "Unable to set data link type on interface '%s' (%s).",
|
|
|
|
name, set_datalink_err_str);
|
|
|
|
/*
|
|
|
|
* If the error isn't "XXX is not one of the DLTs supported by this device",
|
|
|
|
* tell the user to tell the Wireshark developers about it.
|
|
|
|
*/
|
|
|
|
if (strstr(set_datalink_err_str, "is not one of the DLTs supported by this device") == NULL)
|
2019-03-24 04:02:47 +00:00
|
|
|
g_snprintf(secondary_errmsg, (gulong) secondary_errmsg_len,
|
|
|
|
"%s", please_report_bug());
|
2016-01-05 21:54:02 +00:00
|
|
|
else
|
|
|
|
secondary_errmsg[0] = '\0';
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static data_link_info_t *
|
|
|
|
create_data_link_info(int dlt)
|
|
|
|
{
|
|
|
|
data_link_info_t *data_link_info;
|
|
|
|
const char *text;
|
|
|
|
|
|
|
|
data_link_info = (data_link_info_t *)g_malloc(sizeof (data_link_info_t));
|
|
|
|
data_link_info->dlt = dlt;
|
|
|
|
text = pcap_datalink_val_to_name(dlt);
|
|
|
|
if (text != NULL)
|
|
|
|
data_link_info->name = g_strdup(text);
|
|
|
|
else
|
|
|
|
data_link_info->name = g_strdup_printf("DLT %d", dlt);
|
|
|
|
text = pcap_datalink_val_to_description(dlt);
|
2017-08-07 14:38:52 +00:00
|
|
|
data_link_info->description = g_strdup(text);
|
2016-01-05 21:54:02 +00:00
|
|
|
return data_link_info;
|
|
|
|
}
|
|
|
|
|
|
|
|
static GList *
|
|
|
|
get_data_link_types(pcap_t *pch, interface_options *interface_opts,
|
2018-06-10 06:39:12 +00:00
|
|
|
cap_device_open_err *err, char **err_str)
|
2016-01-05 21:54:02 +00:00
|
|
|
{
|
|
|
|
GList *data_link_types;
|
|
|
|
int deflt;
|
|
|
|
#ifdef HAVE_PCAP_LIST_DATALINKS
|
|
|
|
int *linktypes;
|
|
|
|
int i, nlt;
|
|
|
|
#endif
|
|
|
|
data_link_info_t *data_link_info;
|
|
|
|
|
|
|
|
deflt = get_pcap_datalink(pch, interface_opts->name);
|
|
|
|
#ifdef HAVE_PCAP_LIST_DATALINKS
|
|
|
|
nlt = pcap_list_datalinks(pch, &linktypes);
|
2016-01-07 06:07:14 +00:00
|
|
|
if (nlt < 0) {
|
|
|
|
/*
|
2017-03-07 22:08:53 +00:00
|
|
|
* A negative return is an error.
|
2016-01-07 06:07:14 +00:00
|
|
|
*/
|
2017-03-07 22:08:53 +00:00
|
|
|
#ifdef HAVE_PCAP_CREATE
|
2018-06-10 06:39:12 +00:00
|
|
|
/*
|
|
|
|
* If we have pcap_create(), we have
|
|
|
|
* pcap_statustostr(), and we can get back errors
|
|
|
|
* other than PCAP_ERROR (-1), such as
|
|
|
|
* PCAP_ERROR_NOT_ACTIVATED. and we should report
|
|
|
|
* them properly.
|
|
|
|
*/
|
|
|
|
if (nlt == PCAP_ERROR) {
|
|
|
|
*err = CAP_DEVICE_OPEN_ERR_GENERIC;
|
2017-03-07 22:08:53 +00:00
|
|
|
*err_str = g_strdup_printf("pcap_list_datalinks() failed: %s",
|
|
|
|
pcap_geterr(pch));
|
2018-06-10 06:39:12 +00:00
|
|
|
} else {
|
|
|
|
if (nlt == PCAP_ERROR_PERM_DENIED)
|
|
|
|
*err = CAP_DEVICE_OPEN_ERR_PERMISSIONS;
|
|
|
|
else
|
|
|
|
*err = CAP_DEVICE_OPEN_ERR_NOT_PERMISSIONS;
|
|
|
|
*err_str = g_strdup(pcap_statustostr(nlt));
|
2016-01-07 06:07:14 +00:00
|
|
|
}
|
2018-06-10 06:39:12 +00:00
|
|
|
#else /* HAVE_PCAP_CREATE */
|
|
|
|
*err = CAP_DEVICE_OPEN_ERR_GENERIC;
|
|
|
|
*err_str = g_strdup_printf("pcap_list_datalinks() failed: %s",
|
|
|
|
pcap_geterr(pch));
|
|
|
|
#endif /* HAVE_PCAP_CREATE */
|
2016-01-05 21:54:02 +00:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
data_link_types = NULL;
|
|
|
|
for (i = 0; i < nlt; i++) {
|
|
|
|
data_link_info = create_data_link_info(linktypes[i]);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* XXX - for 802.11, make the most detailed 802.11
|
|
|
|
* version the default, rather than the one the
|
|
|
|
* device has as the default?
|
|
|
|
*/
|
|
|
|
if (linktypes[i] == deflt)
|
|
|
|
data_link_types = g_list_prepend(data_link_types,
|
|
|
|
data_link_info);
|
|
|
|
else
|
|
|
|
data_link_types = g_list_append(data_link_types,
|
|
|
|
data_link_info);
|
|
|
|
}
|
|
|
|
#ifdef HAVE_PCAP_FREE_DATALINKS
|
|
|
|
pcap_free_datalinks(linktypes);
|
|
|
|
#else
|
|
|
|
/*
|
|
|
|
* In Windows, there's no guarantee that if you have a library
|
|
|
|
* built with one version of the MSVC++ run-time library, and
|
|
|
|
* it returns a pointer to allocated data, you can free that
|
|
|
|
* data from a program linked with another version of the
|
|
|
|
* MSVC++ run-time library.
|
|
|
|
*
|
|
|
|
* This is not an issue on UN*X.
|
|
|
|
*
|
|
|
|
* See the mail threads starting at
|
|
|
|
*
|
|
|
|
* https://www.winpcap.org/pipermail/winpcap-users/2006-September/001421.html
|
|
|
|
*
|
|
|
|
* and
|
|
|
|
*
|
|
|
|
* https://www.winpcap.org/pipermail/winpcap-users/2008-May/002498.html
|
|
|
|
*/
|
|
|
|
#ifndef _WIN32
|
|
|
|
#define xx_free free /* hack so checkAPIs doesn't complain */
|
|
|
|
xx_free(linktypes);
|
|
|
|
#endif /* _WIN32 */
|
|
|
|
#endif /* HAVE_PCAP_FREE_DATALINKS */
|
|
|
|
#else /* HAVE_PCAP_LIST_DATALINKS */
|
|
|
|
|
|
|
|
data_link_info = create_data_link_info(deflt);
|
|
|
|
data_link_types = g_list_append(data_link_types, data_link_info);
|
|
|
|
#endif /* HAVE_PCAP_LIST_DATALINKS */
|
|
|
|
|
2018-06-10 06:39:12 +00:00
|
|
|
*err_str = NULL;
|
2016-01-07 06:07:14 +00:00
|
|
|
return data_link_types;
|
2016-01-05 21:54:02 +00:00
|
|
|
}
|
|
|
|
|
2017-08-07 14:38:52 +00:00
|
|
|
/* Get supported timestamp types for a libpcap device. */
|
|
|
|
static GList*
|
|
|
|
get_pcap_timestamp_types(pcap_t *pch _U_, char **err_str _U_)
|
|
|
|
{
|
|
|
|
GList *list = NULL;
|
|
|
|
#ifdef HAVE_PCAP_SET_TSTAMP_TYPE
|
|
|
|
int *types;
|
|
|
|
int ntypes = pcap_list_tstamp_types(pch, &types);
|
|
|
|
|
|
|
|
if (err_str)
|
|
|
|
*err_str = ntypes < 0 ? pcap_geterr(pch) : NULL;
|
|
|
|
|
|
|
|
if (ntypes <= 0)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
while (ntypes--) {
|
|
|
|
timestamp_info_t *info = (timestamp_info_t *)g_malloc(sizeof *info);
|
2017-08-25 12:05:42 +00:00
|
|
|
info->name = g_strdup(pcap_tstamp_type_val_to_name(types[ntypes]));
|
|
|
|
info->description = g_strdup(pcap_tstamp_type_val_to_description(types[ntypes]));
|
2017-08-07 14:38:52 +00:00
|
|
|
list = g_list_prepend(list, info);
|
|
|
|
}
|
|
|
|
|
|
|
|
pcap_free_tstamp_types(types);
|
|
|
|
#endif
|
|
|
|
return list;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-01-07 05:56:45 +00:00
|
|
|
#ifdef HAVE_PCAP_CREATE
|
|
|
|
#ifdef HAVE_BONDING
|
|
|
|
static gboolean
|
|
|
|
is_linux_bonding_device(const char *ifname)
|
|
|
|
{
|
|
|
|
int fd;
|
|
|
|
struct ifreq ifr;
|
|
|
|
ifbond ifb;
|
|
|
|
|
|
|
|
fd = socket(PF_INET, SOCK_DGRAM, 0);
|
|
|
|
if (fd == -1)
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
memset(&ifr, 0, sizeof ifr);
|
|
|
|
g_strlcpy(ifr.ifr_name, ifname, sizeof ifr.ifr_name);
|
|
|
|
memset(&ifb, 0, sizeof ifb);
|
|
|
|
ifr.ifr_data = (caddr_t)&ifb;
|
|
|
|
#if defined(SIOCBONDINFOQUERY)
|
|
|
|
if (ioctl(fd, SIOCBONDINFOQUERY, &ifr) == 0) {
|
|
|
|
close(fd);
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
#else
|
|
|
|
if (ioctl(fd, BOND_INFO_QUERY_OLD, &ifr) == 0) {
|
|
|
|
close(fd);
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
close(fd);
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
#else
|
|
|
|
static gboolean
|
|
|
|
is_linux_bonding_device(const char *ifname _U_)
|
|
|
|
{
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2016-01-05 21:54:02 +00:00
|
|
|
if_capabilities_t *
|
|
|
|
get_if_capabilities_pcap_create(interface_options *interface_opts,
|
2018-06-10 06:39:12 +00:00
|
|
|
cap_device_open_err *err, char **err_str)
|
2016-01-05 21:54:02 +00:00
|
|
|
{
|
|
|
|
if_capabilities_t *caps;
|
|
|
|
char errbuf[PCAP_ERRBUF_SIZE];
|
|
|
|
pcap_t *pch;
|
|
|
|
int status;
|
|
|
|
|
|
|
|
pch = pcap_create(interface_opts->name, errbuf);
|
|
|
|
if (pch == NULL) {
|
2018-06-10 06:39:12 +00:00
|
|
|
*err = CAP_DEVICE_OPEN_ERR_NOT_PERMISSIONS;
|
|
|
|
*err_str = g_strdup(errbuf);
|
2016-01-05 21:54:02 +00:00
|
|
|
return NULL;
|
|
|
|
}
|
2017-02-22 04:05:29 +00:00
|
|
|
|
2016-01-05 21:54:02 +00:00
|
|
|
if (is_linux_bonding_device(interface_opts->name)) {
|
|
|
|
/*
|
|
|
|
* Linux bonding device; not Wi-Fi, so no monitor mode, and
|
|
|
|
* calling pcap_can_set_rfmon() might get a "no such device"
|
|
|
|
* error.
|
|
|
|
*/
|
|
|
|
status = 0;
|
|
|
|
} else {
|
|
|
|
/*
|
|
|
|
* Not a Linux bonding device, so go ahead.
|
|
|
|
*/
|
|
|
|
status = pcap_can_set_rfmon(pch);
|
|
|
|
}
|
|
|
|
if (status < 0) {
|
|
|
|
/* Error. */
|
2018-06-10 06:39:12 +00:00
|
|
|
if (status == PCAP_ERROR) {
|
|
|
|
*err = CAP_DEVICE_OPEN_ERR_GENERIC;
|
2016-01-05 21:54:02 +00:00
|
|
|
*err_str = g_strdup_printf("pcap_can_set_rfmon() failed: %s",
|
|
|
|
pcap_geterr(pch));
|
2018-06-10 06:39:12 +00:00
|
|
|
} else {
|
|
|
|
if (status == PCAP_ERROR_PERM_DENIED)
|
|
|
|
*err = CAP_DEVICE_OPEN_ERR_PERMISSIONS;
|
|
|
|
else
|
|
|
|
*err = CAP_DEVICE_OPEN_ERR_NOT_PERMISSIONS;
|
2016-01-05 21:54:02 +00:00
|
|
|
*err_str = g_strdup(pcap_statustostr(status));
|
2018-06-10 06:39:12 +00:00
|
|
|
}
|
2016-01-05 21:54:02 +00:00
|
|
|
pcap_close(pch);
|
|
|
|
return NULL;
|
|
|
|
}
|
2017-02-22 04:05:29 +00:00
|
|
|
caps = (if_capabilities_t *)g_malloc(sizeof *caps);
|
2016-01-05 21:54:02 +00:00
|
|
|
if (status == 0)
|
|
|
|
caps->can_set_rfmon = FALSE;
|
|
|
|
else if (status == 1) {
|
|
|
|
caps->can_set_rfmon = TRUE;
|
|
|
|
if (interface_opts->monitor_mode)
|
|
|
|
pcap_set_rfmon(pch, 1);
|
|
|
|
} else {
|
2018-06-10 06:39:12 +00:00
|
|
|
*err = CAP_DEVICE_OPEN_ERR_NOT_PERMISSIONS;
|
|
|
|
*err_str = g_strdup_printf("pcap_can_set_rfmon() returned %d",
|
|
|
|
status);
|
2016-01-05 21:54:02 +00:00
|
|
|
pcap_close(pch);
|
|
|
|
g_free(caps);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
status = pcap_activate(pch);
|
|
|
|
if (status < 0) {
|
|
|
|
/* Error. We ignore warnings (status > 0). */
|
2018-06-10 06:39:12 +00:00
|
|
|
if (status == PCAP_ERROR) {
|
|
|
|
*err = CAP_DEVICE_OPEN_ERR_GENERIC;
|
|
|
|
*err_str = g_strdup_printf("pcap_activate() failed: %s",
|
|
|
|
pcap_geterr(pch));
|
|
|
|
} else {
|
|
|
|
if (status == PCAP_ERROR_PERM_DENIED)
|
|
|
|
*err = CAP_DEVICE_OPEN_ERR_PERMISSIONS;
|
2016-01-05 21:54:02 +00:00
|
|
|
else
|
2018-06-10 06:39:12 +00:00
|
|
|
*err = CAP_DEVICE_OPEN_ERR_NOT_PERMISSIONS;
|
|
|
|
*err_str = g_strdup(pcap_statustostr(status));
|
2016-01-05 21:54:02 +00:00
|
|
|
}
|
|
|
|
pcap_close(pch);
|
|
|
|
g_free(caps);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
caps->data_link_types = get_data_link_types(pch, interface_opts,
|
2018-06-10 06:39:12 +00:00
|
|
|
err, err_str);
|
2016-01-05 21:54:02 +00:00
|
|
|
if (caps->data_link_types == NULL) {
|
|
|
|
pcap_close(pch);
|
|
|
|
g_free(caps);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2017-08-07 14:38:52 +00:00
|
|
|
caps->timestamp_types = get_pcap_timestamp_types(pch, NULL);
|
|
|
|
|
2016-01-05 21:54:02 +00:00
|
|
|
pcap_close(pch);
|
|
|
|
|
|
|
|
if (err_str != NULL)
|
|
|
|
*err_str = NULL;
|
|
|
|
return caps;
|
|
|
|
}
|
|
|
|
|
|
|
|
pcap_t *
|
|
|
|
open_capture_device_pcap_create(capture_options *capture_opts
|
2017-08-07 14:38:52 +00:00
|
|
|
#if defined(HAVE_PCAP_SET_TSTAMP_PRECISION) || defined (HAVE_PCAP_SET_TSTAMP_TYPE)
|
2016-01-05 21:54:02 +00:00
|
|
|
,
|
|
|
|
#else
|
|
|
|
_U_,
|
|
|
|
#endif
|
|
|
|
interface_options *interface_opts, int timeout,
|
2018-06-10 06:39:12 +00:00
|
|
|
cap_device_open_err *open_err,
|
2016-01-05 21:54:02 +00:00
|
|
|
char (*open_err_str)[PCAP_ERRBUF_SIZE])
|
|
|
|
{
|
|
|
|
pcap_t *pcap_h;
|
2018-06-10 06:39:12 +00:00
|
|
|
int status;
|
2016-01-05 21:54:02 +00:00
|
|
|
|
|
|
|
g_log(LOG_DOMAIN_CAPTURE_CHILD, G_LOG_LEVEL_DEBUG,
|
|
|
|
"Calling pcap_create() using %s.", interface_opts->name);
|
|
|
|
pcap_h = pcap_create(interface_opts->name, *open_err_str);
|
|
|
|
g_log(LOG_DOMAIN_CAPTURE_CHILD, G_LOG_LEVEL_DEBUG,
|
|
|
|
"pcap_create() returned %p.", (void *)pcap_h);
|
2018-06-10 06:39:12 +00:00
|
|
|
if (pcap_h == NULL) {
|
|
|
|
*open_err = CAP_DEVICE_OPEN_ERR_NOT_PERMISSIONS;
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
if (interface_opts->has_snaplen) {
|
2016-01-05 21:54:02 +00:00
|
|
|
g_log(LOG_DOMAIN_CAPTURE_CHILD, G_LOG_LEVEL_DEBUG,
|
2018-06-10 06:39:12 +00:00
|
|
|
"Calling pcap_set_snaplen() with snaplen %d.",
|
|
|
|
interface_opts->snaplen);
|
|
|
|
pcap_set_snaplen(pcap_h, interface_opts->snaplen);
|
|
|
|
}
|
|
|
|
g_log(LOG_DOMAIN_CAPTURE_CHILD, G_LOG_LEVEL_DEBUG,
|
|
|
|
"Calling pcap_set_promisc() with promisc_mode %d.",
|
|
|
|
interface_opts->promisc_mode);
|
|
|
|
pcap_set_promisc(pcap_h, interface_opts->promisc_mode);
|
|
|
|
pcap_set_timeout(pcap_h, timeout);
|
2016-01-05 21:54:02 +00:00
|
|
|
|
|
|
|
#ifdef HAVE_PCAP_SET_TSTAMP_PRECISION
|
2018-06-10 06:39:12 +00:00
|
|
|
/*
|
|
|
|
* If we're writing pcapng files, try to enable
|
|
|
|
* nanosecond-resolution capture; any code that
|
|
|
|
* can read pcapng files must be able to handle
|
|
|
|
* nanosecond-resolution time stamps. We don't
|
|
|
|
* care whether it succeeds or fails - if it fails,
|
|
|
|
* we just use the microsecond-precision time stamps
|
|
|
|
* we get.
|
|
|
|
*
|
|
|
|
* If we're writing pcap files, don't try to enable
|
|
|
|
* nanosecond-resolution capture, as not all code
|
|
|
|
* that reads pcap files recognizes the nanosecond-
|
|
|
|
* resolution pcap file magic number.
|
|
|
|
* We don't care whether this succeeds or fails; if it
|
|
|
|
* fails (because we don't have pcap_set_tstamp_precision(),
|
|
|
|
* or because we do but the OS or device doesn't support
|
|
|
|
* nanosecond resolution timing), we just use microsecond-
|
|
|
|
* resolution time stamps.
|
|
|
|
*/
|
|
|
|
if (capture_opts->use_pcapng)
|
|
|
|
request_high_resolution_timestamp(pcap_h);
|
2016-01-05 21:54:02 +00:00
|
|
|
#endif /* HAVE_PCAP_SET_TSTAMP_PRECISION */
|
|
|
|
|
2017-08-07 14:38:52 +00:00
|
|
|
#ifdef HAVE_PCAP_SET_TSTAMP_TYPE
|
2018-06-10 06:39:12 +00:00
|
|
|
if (interface_opts->timestamp_type) {
|
|
|
|
status = pcap_set_tstamp_type(pcap_h, interface_opts->timestamp_type_id);
|
|
|
|
/*
|
|
|
|
* XXX - what if it fails because that time stamp type
|
|
|
|
* isn't supported?
|
|
|
|
*/
|
|
|
|
if (status == PCAP_ERROR) {
|
|
|
|
*open_err = CAP_DEVICE_OPEN_ERR_NOT_PERMISSIONS;
|
|
|
|
g_strlcpy(*open_err_str, pcap_geterr(pcap_h),
|
|
|
|
sizeof *open_err_str);
|
|
|
|
pcap_close(pcap_h);
|
|
|
|
return NULL;
|
2017-08-07 14:38:52 +00:00
|
|
|
}
|
2018-06-10 06:39:12 +00:00
|
|
|
}
|
2017-08-07 14:38:52 +00:00
|
|
|
#endif /* HAVE_PCAP_SET_TSTAMP_PRECISION */
|
|
|
|
|
2018-06-10 06:39:12 +00:00
|
|
|
g_log(LOG_DOMAIN_CAPTURE_CHILD, G_LOG_LEVEL_DEBUG,
|
|
|
|
"buffersize %d.", interface_opts->buffer_size);
|
|
|
|
if (interface_opts->buffer_size != 0)
|
|
|
|
pcap_set_buffer_size(pcap_h,
|
|
|
|
interface_opts->buffer_size * 1024 * 1024);
|
|
|
|
g_log(LOG_DOMAIN_CAPTURE_CHILD, G_LOG_LEVEL_DEBUG,
|
|
|
|
"monitor_mode %d.", interface_opts->monitor_mode);
|
|
|
|
if (interface_opts->monitor_mode)
|
|
|
|
pcap_set_rfmon(pcap_h, 1);
|
|
|
|
status = pcap_activate(pcap_h);
|
|
|
|
g_log(LOG_DOMAIN_CAPTURE_CHILD, G_LOG_LEVEL_DEBUG,
|
|
|
|
"pcap_activate() returned %d.", status);
|
|
|
|
if (status < 0) {
|
|
|
|
/* Failed to activate, set to NULL */
|
|
|
|
if (status == PCAP_ERROR) {
|
|
|
|
*open_err = CAP_DEVICE_OPEN_ERR_GENERIC;
|
|
|
|
g_strlcpy(*open_err_str, pcap_geterr(pcap_h),
|
|
|
|
sizeof *open_err_str);
|
|
|
|
} else {
|
|
|
|
if (status == PCAP_ERROR_PERM_DENIED)
|
|
|
|
*open_err = CAP_DEVICE_OPEN_ERR_PERMISSIONS;
|
2016-01-05 21:54:02 +00:00
|
|
|
else
|
2018-06-10 06:39:12 +00:00
|
|
|
*open_err = CAP_DEVICE_OPEN_ERR_NOT_PERMISSIONS;
|
|
|
|
g_strlcpy(*open_err_str, pcap_statustostr(status),
|
|
|
|
sizeof *open_err_str);
|
2016-01-05 21:54:02 +00:00
|
|
|
}
|
2018-06-10 06:39:12 +00:00
|
|
|
pcap_close(pcap_h);
|
|
|
|
return NULL;
|
2016-01-05 21:54:02 +00:00
|
|
|
}
|
|
|
|
return pcap_h;
|
|
|
|
}
|
|
|
|
#endif /* HAVE_PCAP_CREATE */
|
|
|
|
|
|
|
|
if_capabilities_t *
|
|
|
|
get_if_capabilities_pcap_open_live(interface_options *interface_opts,
|
2018-06-10 06:39:12 +00:00
|
|
|
cap_device_open_err *err, char **err_str)
|
2016-01-05 21:54:02 +00:00
|
|
|
{
|
|
|
|
if_capabilities_t *caps;
|
|
|
|
char errbuf[PCAP_ERRBUF_SIZE];
|
|
|
|
pcap_t *pch;
|
|
|
|
|
|
|
|
pch = pcap_open_live(interface_opts->name, MIN_PACKET_SIZE, 0, 0,
|
|
|
|
errbuf);
|
|
|
|
if (pch == NULL) {
|
2018-06-10 06:39:12 +00:00
|
|
|
*err = CAP_DEVICE_OPEN_ERR_GENERIC;
|
|
|
|
*err_str = g_strdup(errbuf[0] == '\0' ? "Unknown error (pcap bug; actual error cause not reported)" : errbuf);
|
2016-01-05 21:54:02 +00:00
|
|
|
return NULL;
|
|
|
|
}
|
2017-02-22 04:05:29 +00:00
|
|
|
|
|
|
|
caps = (if_capabilities_t *)g_malloc(sizeof *caps);
|
|
|
|
caps->can_set_rfmon = FALSE;
|
2016-01-05 21:54:02 +00:00
|
|
|
caps->data_link_types = get_data_link_types(pch, interface_opts,
|
2018-06-10 06:39:12 +00:00
|
|
|
err, err_str);
|
2016-01-05 21:54:02 +00:00
|
|
|
if (caps->data_link_types == NULL) {
|
|
|
|
pcap_close(pch);
|
|
|
|
g_free(caps);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2017-08-07 14:38:52 +00:00
|
|
|
caps->timestamp_types = get_pcap_timestamp_types(pch, NULL);
|
|
|
|
|
2016-01-05 21:54:02 +00:00
|
|
|
pcap_close(pch);
|
|
|
|
|
2018-06-10 06:39:12 +00:00
|
|
|
*err_str = NULL;
|
2016-01-05 21:54:02 +00:00
|
|
|
return caps;
|
|
|
|
}
|
|
|
|
|
|
|
|
pcap_t *
|
|
|
|
open_capture_device_pcap_open_live(interface_options *interface_opts,
|
2018-06-10 06:39:12 +00:00
|
|
|
int timeout, cap_device_open_err *open_err,
|
|
|
|
char (*open_err_str)[PCAP_ERRBUF_SIZE])
|
2016-01-05 21:54:02 +00:00
|
|
|
{
|
|
|
|
pcap_t *pcap_h;
|
2017-06-03 17:14:39 +00:00
|
|
|
int snaplen;
|
2016-01-05 21:54:02 +00:00
|
|
|
|
2017-06-03 17:32:44 +00:00
|
|
|
if (interface_opts->has_snaplen)
|
2017-06-03 17:14:39 +00:00
|
|
|
snaplen = interface_opts->snaplen;
|
|
|
|
else {
|
|
|
|
/*
|
Allow bigger snapshot lengths for D-Bus captures.
Use WTAP_MAX_PACKET_SIZE_STANDARD, set to 256KB, for everything except
for D-Bus captures. Use WTAP_MAX_PACKET_SIZE_DBUS, set to 128MB, for
them, because that's the largest possible D-Bus message size. See
https://bugs.freedesktop.org/show_bug.cgi?id=100220
for an example of the problems caused by limiting the snapshot length to
256KB for D-Bus.
Have a snapshot length of 0 in a capture_file structure mean "there is
no snapshot length for the file"; we don't need the has_snap field in
that case, a value of 0 mean "no, we don't have a snapshot length".
In dumpcap, start out with a pipe buffer size of 2KB, and grow it as
necessary. When checking for a too-big packet from a pipe, check
against the appropriate maximum - 128MB for DLT_DBUS, 256KB for
everything else.
Change-Id: Ib2ce7a0cf37b971fbc0318024fd011e18add8b20
Reviewed-on: https://code.wireshark.org/review/21952
Petri-Dish: Guy Harris <guy@alum.mit.edu>
Tested-by: Petri Dish Buildbot <buildbot-no-reply@wireshark.org>
Reviewed-by: Guy Harris <guy@alum.mit.edu>
2017-06-05 01:58:40 +00:00
|
|
|
* Default - use the non-D-Bus maximum snapshot length of
|
|
|
|
* 256KB, which should be big enough (libpcap didn't get
|
|
|
|
* D-Bus support until after it goet pcap_create() and
|
|
|
|
* pcap_activate(), so we don't have D-Bus support and
|
|
|
|
* don't have to worry about really huge packets).
|
2017-06-03 17:14:39 +00:00
|
|
|
*/
|
Allow bigger snapshot lengths for D-Bus captures.
Use WTAP_MAX_PACKET_SIZE_STANDARD, set to 256KB, for everything except
for D-Bus captures. Use WTAP_MAX_PACKET_SIZE_DBUS, set to 128MB, for
them, because that's the largest possible D-Bus message size. See
https://bugs.freedesktop.org/show_bug.cgi?id=100220
for an example of the problems caused by limiting the snapshot length to
256KB for D-Bus.
Have a snapshot length of 0 in a capture_file structure mean "there is
no snapshot length for the file"; we don't need the has_snap field in
that case, a value of 0 mean "no, we don't have a snapshot length".
In dumpcap, start out with a pipe buffer size of 2KB, and grow it as
necessary. When checking for a too-big packet from a pipe, check
against the appropriate maximum - 128MB for DLT_DBUS, 256KB for
everything else.
Change-Id: Ib2ce7a0cf37b971fbc0318024fd011e18add8b20
Reviewed-on: https://code.wireshark.org/review/21952
Petri-Dish: Guy Harris <guy@alum.mit.edu>
Tested-by: Petri Dish Buildbot <buildbot-no-reply@wireshark.org>
Reviewed-by: Guy Harris <guy@alum.mit.edu>
2017-06-05 01:58:40 +00:00
|
|
|
snaplen = 256*1024;
|
2017-06-03 17:14:39 +00:00
|
|
|
}
|
2016-01-05 21:54:02 +00:00
|
|
|
g_log(LOG_DOMAIN_CAPTURE_CHILD, G_LOG_LEVEL_DEBUG,
|
|
|
|
"pcap_open_live() calling using name %s, snaplen %d, promisc_mode %d.",
|
2017-06-03 17:14:39 +00:00
|
|
|
interface_opts->name, snaplen, interface_opts->promisc_mode);
|
|
|
|
pcap_h = pcap_open_live(interface_opts->name, snaplen,
|
2016-01-05 21:54:02 +00:00
|
|
|
interface_opts->promisc_mode, timeout, *open_err_str);
|
|
|
|
g_log(LOG_DOMAIN_CAPTURE_CHILD, G_LOG_LEVEL_DEBUG,
|
|
|
|
"pcap_open_live() returned %p.", (void *)pcap_h);
|
2018-06-10 06:39:12 +00:00
|
|
|
if (pcap_h == NULL) {
|
|
|
|
*open_err = CAP_DEVICE_OPEN_ERR_GENERIC;
|
|
|
|
return NULL;
|
|
|
|
}
|
2016-01-05 21:54:02 +00:00
|
|
|
|
|
|
|
#ifdef _WIN32
|
2018-06-10 06:39:12 +00:00
|
|
|
/* Try to set the capture buffer size. */
|
|
|
|
if (interface_opts->buffer_size > 1) {
|
2016-01-05 21:54:02 +00:00
|
|
|
/*
|
|
|
|
* We have no mechanism to report a warning if this
|
|
|
|
* fails; we just keep capturing with the smaller buffer,
|
|
|
|
* as is the case on systems with BPF and pcap_create()
|
|
|
|
* and pcap_set_buffer_size(), where pcap_activate() just
|
|
|
|
* silently clamps the buffer size to the maximum.
|
|
|
|
*/
|
|
|
|
pcap_setbuff(pcap_h, interface_opts->buffer_size * 1024 * 1024);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
return pcap_h;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Get the capabilities of a network device.
|
|
|
|
*/
|
|
|
|
if_capabilities_t *
|
2018-06-10 06:39:12 +00:00
|
|
|
get_if_capabilities(interface_options *interface_opts,
|
|
|
|
cap_device_open_err *err, char **err_str)
|
2016-01-05 21:54:02 +00:00
|
|
|
{
|
|
|
|
#if defined(HAVE_PCAP_OPEN) && defined(HAVE_PCAP_REMOTE)
|
|
|
|
if_capabilities_t *caps;
|
|
|
|
char errbuf[PCAP_ERRBUF_SIZE];
|
|
|
|
pcap_t *pch;
|
|
|
|
int deflt;
|
|
|
|
data_link_info_t *data_link_info;
|
|
|
|
|
|
|
|
if (strncmp (interface_opts->name, "rpcap://", 8) == 0) {
|
|
|
|
struct pcap_rmtauth auth;
|
|
|
|
|
|
|
|
auth.type = interface_opts->auth_type == CAPTURE_AUTH_PWD ?
|
|
|
|
RPCAP_RMTAUTH_PWD : RPCAP_RMTAUTH_NULL;
|
|
|
|
auth.username = interface_opts->auth_username;
|
|
|
|
auth.password = interface_opts->auth_password;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* WinPcap 4.1.2, and possibly earlier versions, have a bug
|
|
|
|
* wherein, when an open with an rpcap: URL fails, the error
|
|
|
|
* message for the error is not copied to errbuf and whatever
|
|
|
|
* on-the-stack junk is in errbuf is treated as the error
|
|
|
|
* message.
|
|
|
|
*
|
|
|
|
* To work around that (and any other bugs of that sort), we
|
|
|
|
* initialize errbuf to an empty string. If we get an error
|
|
|
|
* and the string is empty, we report it as an unknown error.
|
|
|
|
* (If we *don't* get an error, and the string is *non*-empty,
|
|
|
|
* that could be a warning returned, such as "can't turn
|
|
|
|
* promiscuous mode on"; we currently don't do so.)
|
|
|
|
*/
|
|
|
|
errbuf[0] = '\0';
|
|
|
|
pch = pcap_open(interface_opts->name, MIN_PACKET_SIZE, 0, 0, &auth,
|
|
|
|
errbuf);
|
|
|
|
if (pch == NULL) {
|
2018-06-10 06:39:12 +00:00
|
|
|
/*
|
|
|
|
* We don't know whether it's a permission error or not.
|
|
|
|
* (If it is, maybe we can give ourselves permission or
|
|
|
|
* maybe we just have to ask politely for permission.)
|
|
|
|
*/
|
|
|
|
*err = CAP_DEVICE_OPEN_ERR_GENERIC;
|
|
|
|
*err_str = g_strdup(errbuf[0] == '\0' ? "Unknown error (pcap bug; actual error cause not reported)" : errbuf);
|
2016-01-05 21:54:02 +00:00
|
|
|
return NULL;
|
|
|
|
}
|
2017-02-22 04:05:29 +00:00
|
|
|
|
|
|
|
caps = (if_capabilities_t *)g_malloc(sizeof *caps);
|
|
|
|
caps->can_set_rfmon = FALSE;
|
|
|
|
caps->data_link_types = NULL;
|
2016-01-05 21:54:02 +00:00
|
|
|
deflt = get_pcap_datalink(pch, interface_opts->name);
|
|
|
|
data_link_info = create_data_link_info(deflt);
|
2017-08-07 14:38:52 +00:00
|
|
|
caps->data_link_types = g_list_append(caps->data_link_types, data_link_info);
|
|
|
|
caps->timestamp_types = get_pcap_timestamp_types(pch, NULL);
|
2016-01-05 21:54:02 +00:00
|
|
|
pcap_close(pch);
|
|
|
|
|
2018-06-10 06:39:12 +00:00
|
|
|
*err_str = NULL;
|
2016-01-05 21:54:02 +00:00
|
|
|
return caps;
|
|
|
|
}
|
|
|
|
#endif /* defined(HAVE_PCAP_OPEN) && defined(HAVE_PCAP_REMOTE) */
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Local interface.
|
|
|
|
*/
|
2018-06-10 06:39:12 +00:00
|
|
|
return get_if_capabilities_local(interface_opts, err, err_str);
|
2016-01-05 21:54:02 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
pcap_t *
|
|
|
|
open_capture_device(capture_options *capture_opts,
|
|
|
|
interface_options *interface_opts, int timeout,
|
2018-06-10 06:39:12 +00:00
|
|
|
cap_device_open_err *open_err,
|
2016-01-05 21:54:02 +00:00
|
|
|
char (*open_err_str)[PCAP_ERRBUF_SIZE])
|
|
|
|
{
|
|
|
|
pcap_t *pcap_h;
|
|
|
|
#if defined(HAVE_PCAP_OPEN) && defined(HAVE_PCAP_REMOTE)
|
|
|
|
struct pcap_rmtauth auth;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
/* Open the network interface to capture from it.
|
|
|
|
Some versions of libpcap may put warnings into the error buffer
|
|
|
|
if they succeed; to tell if that's happened, we have to clear
|
|
|
|
the error buffer, and check if it's still a null string. */
|
|
|
|
g_log(LOG_DOMAIN_CAPTURE_CHILD, G_LOG_LEVEL_DEBUG, "Entering open_capture_device().");
|
2018-06-10 06:39:12 +00:00
|
|
|
*open_err = CAP_DEVICE_OPEN_NO_ERR;
|
2016-01-05 21:54:02 +00:00
|
|
|
(*open_err_str)[0] = '\0';
|
|
|
|
#if defined(HAVE_PCAP_OPEN) && defined(HAVE_PCAP_REMOTE)
|
|
|
|
/*
|
|
|
|
* If we're opening a remote device, use pcap_open(); that's currently
|
|
|
|
* the only open routine that supports remote devices.
|
|
|
|
*/
|
|
|
|
if (strncmp (interface_opts->name, "rpcap://", 8) == 0) {
|
2017-06-03 17:14:39 +00:00
|
|
|
int snaplen;
|
|
|
|
|
2016-01-05 21:54:02 +00:00
|
|
|
auth.type = interface_opts->auth_type == CAPTURE_AUTH_PWD ?
|
|
|
|
RPCAP_RMTAUTH_PWD : RPCAP_RMTAUTH_NULL;
|
|
|
|
auth.username = interface_opts->auth_username;
|
|
|
|
auth.password = interface_opts->auth_password;
|
|
|
|
|
2017-06-03 21:13:17 +00:00
|
|
|
if (interface_opts->has_snaplen)
|
2017-06-03 17:14:39 +00:00
|
|
|
snaplen = interface_opts->snaplen;
|
|
|
|
else {
|
|
|
|
/*
|
Allow bigger snapshot lengths for D-Bus captures.
Use WTAP_MAX_PACKET_SIZE_STANDARD, set to 256KB, for everything except
for D-Bus captures. Use WTAP_MAX_PACKET_SIZE_DBUS, set to 128MB, for
them, because that's the largest possible D-Bus message size. See
https://bugs.freedesktop.org/show_bug.cgi?id=100220
for an example of the problems caused by limiting the snapshot length to
256KB for D-Bus.
Have a snapshot length of 0 in a capture_file structure mean "there is
no snapshot length for the file"; we don't need the has_snap field in
that case, a value of 0 mean "no, we don't have a snapshot length".
In dumpcap, start out with a pipe buffer size of 2KB, and grow it as
necessary. When checking for a too-big packet from a pipe, check
against the appropriate maximum - 128MB for DLT_DBUS, 256KB for
everything else.
Change-Id: Ib2ce7a0cf37b971fbc0318024fd011e18add8b20
Reviewed-on: https://code.wireshark.org/review/21952
Petri-Dish: Guy Harris <guy@alum.mit.edu>
Tested-by: Petri Dish Buildbot <buildbot-no-reply@wireshark.org>
Reviewed-by: Guy Harris <guy@alum.mit.edu>
2017-06-05 01:58:40 +00:00
|
|
|
* Default - use the non-D-Bus maximum snapshot length,
|
2017-06-03 17:14:39 +00:00
|
|
|
* which should be big enough, except for D-Bus.
|
|
|
|
*/
|
Allow bigger snapshot lengths for D-Bus captures.
Use WTAP_MAX_PACKET_SIZE_STANDARD, set to 256KB, for everything except
for D-Bus captures. Use WTAP_MAX_PACKET_SIZE_DBUS, set to 128MB, for
them, because that's the largest possible D-Bus message size. See
https://bugs.freedesktop.org/show_bug.cgi?id=100220
for an example of the problems caused by limiting the snapshot length to
256KB for D-Bus.
Have a snapshot length of 0 in a capture_file structure mean "there is
no snapshot length for the file"; we don't need the has_snap field in
that case, a value of 0 mean "no, we don't have a snapshot length".
In dumpcap, start out with a pipe buffer size of 2KB, and grow it as
necessary. When checking for a too-big packet from a pipe, check
against the appropriate maximum - 128MB for DLT_DBUS, 256KB for
everything else.
Change-Id: Ib2ce7a0cf37b971fbc0318024fd011e18add8b20
Reviewed-on: https://code.wireshark.org/review/21952
Petri-Dish: Guy Harris <guy@alum.mit.edu>
Tested-by: Petri Dish Buildbot <buildbot-no-reply@wireshark.org>
Reviewed-by: Guy Harris <guy@alum.mit.edu>
2017-06-05 01:58:40 +00:00
|
|
|
snaplen = 256*1024;
|
2017-06-03 17:14:39 +00:00
|
|
|
}
|
2016-01-05 21:54:02 +00:00
|
|
|
g_log(LOG_DOMAIN_CAPTURE_CHILD, G_LOG_LEVEL_DEBUG,
|
|
|
|
"Calling pcap_open() using name %s, snaplen %d, promisc_mode %d, datatx_udp %d, nocap_rpcap %d.",
|
2017-06-03 17:14:39 +00:00
|
|
|
interface_opts->name, snaplen,
|
2016-01-05 21:54:02 +00:00
|
|
|
interface_opts->promisc_mode, interface_opts->datatx_udp,
|
|
|
|
interface_opts->nocap_rpcap);
|
2017-06-03 17:14:39 +00:00
|
|
|
pcap_h = pcap_open(interface_opts->name, snaplen,
|
2016-01-05 21:54:02 +00:00
|
|
|
/* flags */
|
|
|
|
(interface_opts->promisc_mode ? PCAP_OPENFLAG_PROMISCUOUS : 0) |
|
|
|
|
(interface_opts->datatx_udp ? PCAP_OPENFLAG_DATATX_UDP : 0) |
|
|
|
|
(interface_opts->nocap_rpcap ? PCAP_OPENFLAG_NOCAPTURE_RPCAP : 0),
|
|
|
|
timeout, &auth, *open_err_str);
|
|
|
|
if (pcap_h == NULL) {
|
2018-06-10 06:39:12 +00:00
|
|
|
/*
|
|
|
|
* Error.
|
|
|
|
*
|
|
|
|
* We don't know whether it's a permission error
|
|
|
|
* or not.
|
|
|
|
* (If it is, maybe we can give ourselves permission
|
|
|
|
* or maybe we just have to ask politely for
|
|
|
|
* permission.)
|
|
|
|
*/
|
|
|
|
*open_err = CAP_DEVICE_OPEN_ERR_GENERIC;
|
|
|
|
/* Did pcap actually supply an error message? */
|
2016-01-05 21:54:02 +00:00
|
|
|
if ((*open_err_str)[0] == '\0') {
|
|
|
|
/*
|
|
|
|
* Work around known WinPcap bug wherein
|
|
|
|
* no error message is filled in on a
|
|
|
|
* failure to open an rpcap: URL.
|
|
|
|
*/
|
|
|
|
g_strlcpy(*open_err_str,
|
|
|
|
"Unknown error (pcap bug; actual error cause not reported)",
|
|
|
|
sizeof *open_err_str);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
g_log(LOG_DOMAIN_CAPTURE_CHILD, G_LOG_LEVEL_DEBUG,
|
|
|
|
"pcap_open() returned %p.", (void *)pcap_h);
|
|
|
|
g_log(LOG_DOMAIN_CAPTURE_CHILD, G_LOG_LEVEL_DEBUG, "open_capture_device %s : %s", pcap_h ? "SUCCESS" : "FAILURE", interface_opts->name);
|
|
|
|
return pcap_h;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
pcap_h = open_capture_device_local(capture_opts, interface_opts,
|
2018-06-10 06:39:12 +00:00
|
|
|
timeout, open_err, open_err_str);
|
2016-01-05 21:54:02 +00:00
|
|
|
g_log(LOG_DOMAIN_CAPTURE_CHILD, G_LOG_LEVEL_DEBUG, "open_capture_device %s : %s", pcap_h ? "SUCCESS" : "FAILURE", interface_opts->name);
|
|
|
|
return pcap_h;
|
|
|
|
}
|
|
|
|
|
2004-07-18 00:24:25 +00:00
|
|
|
#endif /* HAVE_LIBPCAP */
|
2015-02-13 18:43:32 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Editor modelines - http://www.wireshark.org/tools/modelines.html
|
|
|
|
*
|
|
|
|
* Local variables:
|
|
|
|
* c-basic-offset: 8
|
|
|
|
* tab-width: 8
|
|
|
|
* indent-tabs-mode: t
|
|
|
|
* End:
|
|
|
|
*
|
|
|
|
* vi: set shiftwidth=8 tabstop=8 noexpandtab:
|
|
|
|
* :indentSize=8:tabSize=8:noTabs=false:
|
|
|
|
*/
|