ETHER: Added capability to build working networking support without pcap packet transport (i.e. only using one of the other available packet transports: VDE, TAP, UDP, etc.)

This commit is contained in:
Mark Pizzolato 2013-12-19 09:45:51 -08:00
parent e34babdc7e
commit 7b3e508627
5 changed files with 192 additions and 124 deletions

View file

@ -235,7 +235,7 @@ PCAP_EXECLET = $(PCAP_VCI)
PCAP_INC = ,$(PCAP_DIR) PCAP_INC = ,$(PCAP_DIR)
PCAP_LIBD = $(PCAP_LIB) PCAP_LIBD = $(PCAP_LIB)
PCAP_LIBR = ,$(PCAP_LIB)/LIB/SYSEXE PCAP_LIBR = ,$(PCAP_LIB)/LIB/SYSEXE
PCAP_DEFS = ,"USE_NETWORK=1" PCAP_DEFS = ,"USE_NETWORK=1,HAVE_PCAP_NETWORK=1"
PCAP_SIMH_INC = /INCL=($(PCAP_DIR)) PCAP_SIMH_INC = /INCL=($(PCAP_DIR))
.ENDIF .ENDIF
.ENDIF .ENDIF

View file

@ -313,6 +313,7 @@ ifeq ($(WIN32),) #*nix Environments (&& cygwin)
OS_CCDEFS += -DHAVE_FNMATCH OS_CCDEFS += -DHAVE_FNMATCH
endif endif
endif endif
ifneq (,$(VIDEO_USEFUL))
ifneq (,$(call find_include,SDL2/SDL)) ifneq (,$(call find_include,SDL2/SDL))
ifneq (,$(call find_lib,SDL2)) ifneq (,$(call find_lib,SDL2))
OS_CCDEFS += -DHAVE_LIBSDL -I$(dir $(call find_include,SDL2/SDL)) OS_CCDEFS += -DHAVE_LIBSDL -I$(dir $(call find_include,SDL2/SDL))
@ -336,7 +337,6 @@ ifeq ($(WIN32),) #*nix Environments (&& cygwin)
endif endif
endif endif
endif endif
ifneq (,$(VIDEO_USEFUL))
ifeq (,$(findstring HAVE_LIBSDL,$(OS_CCDEFS))) ifeq (,$(findstring HAVE_LIBSDL,$(OS_CCDEFS)))
$(info *** Warning ***) $(info *** Warning ***)
$(info *** Warning *** The simulator$(BUILD_MULTIPLE) you are building could provide more) $(info *** Warning *** The simulator$(BUILD_MULTIPLE) you are building could provide more)
@ -349,9 +349,11 @@ ifeq ($(WIN32),) #*nix Environments (&& cygwin)
endif endif
ifneq (,$(NETWORK_USEFUL)) ifneq (,$(NETWORK_USEFUL))
ifneq (,$(call find_include,pcap)) ifneq (,$(call find_include,pcap))
NETWORK_CCDEFS += -DHAVE_PCAP_NETWORK -I$(dir $(call find_include,pcap))
NETWORK_LAN_FEATURES += PCAP
ifneq (,$(call find_lib,$(PCAPLIB))) ifneq (,$(call find_lib,$(PCAPLIB)))
ifneq ($(USE_NETWORK),) # Network support specified on the GNU make command line ifneq ($(USE_NETWORK),) # Network support specified on the GNU make command line
NETWORK_CCDEFS = -DUSE_NETWORK -I$(dir $(call find_include,pcap)) NETWORK_CCDEFS += -DUSE_NETWORK
$(info *** Warning ***) $(info *** Warning ***)
$(info *** Warning *** Statically linking against libpcap is provides no measurable) $(info *** Warning *** Statically linking against libpcap is provides no measurable)
$(info *** Warning *** benefits over dynamically linking libpcap.) $(info *** Warning *** benefits over dynamically linking libpcap.)
@ -368,27 +370,21 @@ ifeq ($(WIN32),) #*nix Environments (&& cygwin)
$(info using libpcap: $(call find_lib,$(PCAPLIB)) $(call find_include,pcap)) $(info using libpcap: $(call find_lib,$(PCAPLIB)) $(call find_include,pcap))
NETWORK_FEATURES = - static networking support using $(OSNAME) provided libpcap components NETWORK_FEATURES = - static networking support using $(OSNAME) provided libpcap components
else # default build uses dynamic libpcap else # default build uses dynamic libpcap
NETWORK_CCDEFS = -DUSE_SHARED -I$(dir $(call find_include,pcap)) NETWORK_CCDEFS += -DUSE_SHARED
$(info using libpcap: $(call find_include,pcap)) $(info using libpcap: $(call find_include,pcap))
NETWORK_FEATURES = - dynamic networking support using $(OSNAME) provided libpcap components NETWORK_FEATURES = - dynamic networking support using $(OSNAME) provided libpcap components
endif endif
else
ifneq (,$(call find_lib,$(PCAPLIB)))
NETWORK_CCDEFS = -DUSE_SHARED -I$(dir $(call find_include,pcap))
NETWORK_FEATURES = - dynamic networking support using $(OSNAME) provided libpcap components
$(info using libpcap: $(call find_include,pcap))
else else
LIBEXTSAVE := $(LIBEXT) LIBEXTSAVE := $(LIBEXT)
LIBEXT = a LIBEXT = a
ifneq (,$(call find_lib,$(PCAPLIB))) ifneq (,$(call find_lib,$(PCAPLIB)))
NETWORK_CCDEFS = -DUSE_NETWORK -I$(dir $(call find_include,pcap)) NETWORK_CCDEFS += -DUSE_NETWORK
NETWORK_LDFLAGS := -L$(dir $(call find_lib,$(PCAPLIB))) -l$(PCAPLIB) NETWORK_LDFLAGS := -L$(dir $(call find_lib,$(PCAPLIB))) -l$(PCAPLIB)
NETWORK_FEATURES = - static networking support using $(OSNAME) provided libpcap components NETWORK_FEATURES = - static networking support using $(OSNAME) provided libpcap components
$(info using libpcap: $(call find_lib,$(PCAPLIB)) $(call find_include,pcap)) $(info using libpcap: $(call find_lib,$(PCAPLIB)) $(call find_include,pcap))
endif endif
LIBEXT = $(LIBEXTSAVE) LIBEXT = $(LIBEXTSAVE)
endif endif
endif
else else
# Look for package built from tcpdump.org sources with default install target (or cygwin winpcap) # Look for package built from tcpdump.org sources with default install target (or cygwin winpcap)
INCPATH += /usr/local/include INCPATH += /usr/local/include
@ -405,11 +401,11 @@ ifeq ($(WIN32),) #*nix Environments (&& cygwin)
ifneq (,$(call find_lib,$(PCAPLIB))) ifneq (,$(call find_lib,$(PCAPLIB)))
$(info using libpcap: $(call find_lib,$(PCAPLIB)) $(call find_include,pcap)) $(info using libpcap: $(call find_lib,$(PCAPLIB)) $(call find_include,pcap))
ifeq (cygwin,$(OSTYPE)) ifeq (cygwin,$(OSTYPE))
NETWORK_CCDEFS = -DUSE_NETWORK -I$(dir $(call find_include,pcap)) NETWORK_CCDEFS = -DUSE_NETWORK -DHAVE_PCAP_NETWORK -I$(dir $(call find_include,pcap))
NETWORK_LDFLAGS = -L$(dir $(call find_lib,$(PCAPLIB))) -Wl,-R,$(dir $(call find_lib,$(PCAPLIB))) -l$(PCAPLIB) NETWORK_LDFLAGS = -L$(dir $(call find_lib,$(PCAPLIB))) -Wl,-R,$(dir $(call find_lib,$(PCAPLIB))) -l$(PCAPLIB)
NETWORK_FEATURES = - static networking support using libpcap components located in the cygwin directories NETWORK_FEATURES = - static networking support using libpcap components located in the cygwin directories
else else
NETWORK_CCDEFS := -DUSE_NETWORK -isystem -I$(dir $(call find_include,pcap)) $(call find_lib,$(PCAPLIB)) NETWORK_CCDEFS := -DUSE_NETWORK -DHAVE_PCAP_NETWORK -isystem -I$(dir $(call find_include,pcap)) $(call find_lib,$(PCAPLIB))
NETWORK_FEATURES = - networking support using libpcap components from www.tcpdump.org NETWORK_FEATURES = - networking support using libpcap components from www.tcpdump.org
$(info *** Warning ***) $(info *** Warning ***)
$(info *** Warning *** $(BUILD_SINGLE)Simulator$(BUILD_MULTIPLE) being built with networking support using) $(info *** Warning *** $(BUILD_SINGLE)Simulator$(BUILD_MULTIPLE) being built with networking support using)
@ -426,18 +422,32 @@ ifeq ($(WIN32),) #*nix Environments (&& cygwin)
else else
$(error using libpcap: $(call find_include,pcap) missing $(PCAPLIB).$(LIBEXT)) $(error using libpcap: $(call find_include,pcap) missing $(PCAPLIB).$(LIBEXT))
endif endif
NETWORK_LAN_FEATURES += PCAP
endif endif
LIBEXT = $(LIBEXTSAVE) LIBEXT = $(LIBEXTSAVE)
else
$(info *** Warning ***)
$(info *** Warning *** $(BUILD_SINGLE)Simulator$(BUILD_MULTIPLE) are being built WITHOUT)
$(info *** Warning *** libpcap networking support)
$(info *** Warning ***)
$(info *** Warning *** To build simulator(s) with libpcap networking support you)
$(info *** Warning *** should read 0readme_ethernet.txt and follow the instructions)
$(info *** Warning *** regarding the needed libpcap development components for your)
$(info *** Warning *** $(OSTYPE) platform)
$(info *** Warning ***)
endif endif
endif endif
ifneq (,$(findstring USE_NETWORK,$(NETWORK_CCDEFS))$(findstring USE_SHARED,$(NETWORK_CCDEFS))) # Consider other network connections
# Given we have libpcap components, consider other network connections as well
ifneq (,$(call find_lib,vdeplug)) ifneq (,$(call find_lib,vdeplug))
# libvdeplug requires the use of the OS provided libpcap # libvdeplug requires the use of the OS provided libpcap
ifeq (,$(findstring usr/local,$(NETWORK_CCDEFS))) ifeq (,$(findstring usr/local,$(NETWORK_CCDEFS)))
ifneq (,$(call find_include,libvdeplug)) ifneq (,$(call find_include,libvdeplug))
# Provide support for vde networking # Provide support for vde networking
NETWORK_CCDEFS += -DUSE_VDE_NETWORK NETWORK_CCDEFS += -DHAVE_VDE_NETWORK
NETWORK_LAN_FEATURES += VDE
ifeq (,$(findstring USE_NETWORK,$(NETWORK_CCDEFS))$(findstring USE_SHARED,$(NETWORK_CCDEFS)))
NETWORK_CCDEFS += -DUSE_NETWORK
endif
ifeq (Darwin,$(OSTYPE)) ifeq (Darwin,$(OSTYPE))
NETWORK_LDFLAGS += -lvdeplug -L$(dir $(call find_lib,vdeplug)) NETWORK_LDFLAGS += -lvdeplug -L$(dir $(call find_lib,vdeplug))
else else
@ -447,7 +457,7 @@ ifeq ($(WIN32),) #*nix Environments (&& cygwin)
endif endif
endif endif
endif endif
ifeq (,$(findstring USE_VDE_NETWORK,$(NETWORK_CCDEFS))) ifeq (,$(findstring HAVE_VDE_NETWORK,$(NETWORK_CCDEFS)))
# Support is available on Linux for libvdeplug. Advise on its usage # Support is available on Linux for libvdeplug. Advise on its usage
ifneq (,$(findstring Linux,$(OSTYPE))) ifneq (,$(findstring Linux,$(OSTYPE)))
$(info *** Warning ***) $(info *** Warning ***)
@ -466,16 +476,25 @@ ifeq ($(WIN32),) #*nix Environments (&& cygwin)
endif endif
ifneq (,$(call find_include,linux/if_tun)) ifneq (,$(call find_include,linux/if_tun))
# Provide support for Tap networking on Linux # Provide support for Tap networking on Linux
NETWORK_CCDEFS += -DUSE_TAP_NETWORK NETWORK_CCDEFS += -DHAVE_TAP_NETWORK
NETWORK_LAN_FEATURES += TAP
ifeq (,$(findstring USE_NETWORK,$(NETWORK_CCDEFS))$(findstring USE_SHARED,$(NETWORK_CCDEFS)))
NETWORK_CCDEFS += -DUSE_NETWORK
endif
endif endif
ifeq (bsdtuntap,$(shell if $(TEST) -e /usr/include/net/if_tun.h -o -e /Library/Extensions/tap.kext; then echo bsdtuntap; fi)) ifeq (bsdtuntap,$(shell if $(TEST) -e /usr/include/net/if_tun.h -o -e /Library/Extensions/tap.kext; then echo bsdtuntap; fi))
# Provide support for Tap networking on BSD platforms (including OS X) # Provide support for Tap networking on BSD platforms (including OS X)
NETWORK_CCDEFS += -DUSE_TAP_NETWORK -DUSE_BSDTUNTAP NETWORK_CCDEFS += -DHAVE_TAP_NETWORK -DHAVE_BSDTUNTAP
NETWORK_LAN_FEATURES += TAP
ifeq (,$(findstring USE_NETWORK,$(NETWORK_CCDEFS))$(findstring USE_SHARED,$(NETWORK_CCDEFS)))
NETWORK_CCDEFS += -DUSE_NETWORK
endif endif
else endif
NETWORK_FEATURES = - WITHOUT networking support ifeq (,$(findstring USE_NETWORK,$(NETWORK_CCDEFS))$(findstring USE_SHARED,$(NETWORK_CCDEFS)))
NETWORK_CCDEFS += -DUSE_NETWORK
NETWORK_FEATURES = - WITHOUT Local LAN networking support
$(info *** Warning ***) $(info *** Warning ***)
$(info *** Warning *** $(BUILD_SINGLE)Simulator$(BUILD_MULTIPLE) are being built WITHOUT networking support) $(info *** Warning *** $(BUILD_SINGLE)Simulator$(BUILD_MULTIPLE) are being built WITHOUT LAN networking support)
$(info *** Warning ***) $(info *** Warning ***)
$(info *** Warning *** To build simulator(s) with networking support you should read) $(info *** Warning *** To build simulator(s) with networking support you should read)
$(info *** Warning *** 0readme_ethernet.txt and follow the instructions regarding the) $(info *** Warning *** 0readme_ethernet.txt and follow the instructions regarding the)
@ -641,6 +660,9 @@ ifneq (clean,$(MAKECMDGOALS))
ifneq (,$(NETWORK_FEATURES)) ifneq (,$(NETWORK_FEATURES))
$(info *** $(NETWORK_FEATURES).) $(info *** $(NETWORK_FEATURES).)
endif endif
ifneq (,$(NETWORK_LAN_FEATURES))
$(info *** - Local LAN packet transports: $(NETWORK_LAN_FEATURES))
endif
ifneq (,$(VIDEO_FEATURES)) ifneq (,$(VIDEO_FEATURES))
$(info *** $(VIDEO_FEATURES).) $(info *** $(VIDEO_FEATURES).)
endif endif

11
scp.c
View file

@ -512,11 +512,6 @@ static const char *sim_sa64 = "64b addresses";
#else #else
static const char *sim_sa64 = "32b addresses"; static const char *sim_sa64 = "32b addresses";
#endif #endif
#if defined (USE_NETWORK) || defined (USE_SHARED)
static const char *sim_snet = "Ethernet support";
#else
static const char *sim_snet = "no Ethernet";
#endif
/* Tables and strings */ /* Tables and strings */
@ -2825,7 +2820,7 @@ if (flag) {
fprintf (st, "\n\tSimulator Framework Capabilities:"); fprintf (st, "\n\tSimulator Framework Capabilities:");
fprintf (st, "\n\t\t%s", sim_si64); fprintf (st, "\n\t\t%s", sim_si64);
fprintf (st, "\n\t\t%s", sim_sa64); fprintf (st, "\n\t\t%s", sim_sa64);
fprintf (st, "\n\t\t%s", sim_snet); fprintf (st, "\n\t\t%s", eth_capabilities());
idle_capable = sim_timer_idle_capable (&os_tick_size); idle_capable = sim_timer_idle_capable (&os_tick_size);
fprintf (st, "\n\t\tIdle/Throttling support is %savailable", ((idle_capable == 0) ? "NOT " : "")); fprintf (st, "\n\t\tIdle/Throttling support is %savailable", ((idle_capable == 0) ? "NOT " : ""));
if (sim_disk_vhd_support()) if (sim_disk_vhd_support())
@ -4068,7 +4063,7 @@ REG *rptr;
fprintf (sfile, "%s\n%s\n%s\n%s\n%s\n%.0f\n", fprintf (sfile, "%s\n%s\n%s\n%s\n%s\n%.0f\n",
save_vercur, /* [V2.5] save format */ save_vercur, /* [V2.5] save format */
sim_name, /* sim name */ sim_name, /* sim name */
sim_si64, sim_sa64, sim_snet, /* [V3.5] options */ sim_si64, sim_sa64, eth_capabilities(), /* [V3.5] options */
sim_time); /* [V3.2] sim time */ sim_time); /* [V3.2] sim time */
WRITE_I (sim_rtime); /* [V2.6] sim rel time */ WRITE_I (sim_rtime); /* [V2.6] sim rel time */
@ -6291,7 +6286,7 @@ UPDATE_SIM_TIME; /* update sim time */
if (sim_clock_queue == QUEUE_LIST_END) { /* queue empty? */ if (sim_clock_queue == QUEUE_LIST_END) { /* queue empty? */
sim_interval = noqueue_time = NOQUEUE_WAIT; /* flag queue empty */ sim_interval = noqueue_time = NOQUEUE_WAIT; /* flag queue empty */
sim_debug (SIM_DBG_EVENT, sim_dflt_dev, "Queue Emptry New Interval = %d\n", sim_interval); sim_debug (SIM_DBG_EVENT, sim_dflt_dev, "Queue Empty New Interval = %d\n", sim_interval);
return SCPE_OK; return SCPE_OK;
} }
do { do {

View file

@ -134,14 +134,14 @@
on the libpcap/kernel packet timeout specified on on the libpcap/kernel packet timeout specified on
pcap_open_live. If USE_READER_THREAD is not set, then pcap_open_live. If USE_READER_THREAD is not set, then
MUST_DO_SELECT is irrelevant MUST_DO_SELECT is irrelevant
USE_TAP_NETWORK - Specifies that support for tap networking should be HAVE_TAP_NETWORK - Specifies that support for tap networking should be
included. This can be leveraged, along with OS bridging included. This can be leveraged, along with OS bridging
capabilities to share a single LAN interface. This capabilities to share a single LAN interface. This
allows device names of the form tap:tap0 to be specified allows device names of the form tap:tap0 to be specified
at open time. This functionality is only useful/needed at open time. This functionality is only useful/needed
on *nix platforms since native sharing of Windows NIC on *nix platforms since native sharing of Windows NIC
devices works with no external magic. devices works with no external magic.
USE_VDE_NETWORK - Specifies that support for vde networking should be HAVE_VDE_NETWORK - Specifies that support for vde networking should be
included. This can be leveraged, along with OS bridging included. This can be leveraged, along with OS bridging
capabilities to share a single LAN interface. It also capabilities to share a single LAN interface. It also
can allow a simulator to have useful networking can allow a simulator to have useful networking
@ -667,7 +667,6 @@ void eth_zero(ETH_DEV* dev)
static ETH_DEV **eth_open_devices = NULL; static ETH_DEV **eth_open_devices = NULL;
static int eth_open_device_count = 0; static int eth_open_device_count = 0;
#if defined (USE_NETWORK) || defined (USE_SHARED)
static void _eth_add_to_open_list (ETH_DEV* dev) static void _eth_add_to_open_list (ETH_DEV* dev)
{ {
eth_open_devices = (ETH_DEV**)realloc(eth_open_devices, (eth_open_device_count+1)*sizeof(*eth_open_devices)); eth_open_devices = (ETH_DEV**)realloc(eth_open_devices, (eth_open_device_count+1)*sizeof(*eth_open_devices));
@ -686,7 +685,6 @@ for (i=0; i<eth_open_device_count; ++i)
break; break;
} }
} }
#endif
t_stat eth_show (FILE* st, UNIT* uptr, int32 val, void* desc) t_stat eth_show (FILE* st, UNIT* uptr, int32 val, void* desc)
{ {
@ -842,6 +840,8 @@ ethq_insert_data(que, type, pack->oversize ? pack->oversize : pack->msg, pack->u
/*============================================================================*/ /*============================================================================*/
#if !defined (USE_NETWORK) && !defined (USE_SHARED) #if !defined (USE_NETWORK) && !defined (USE_SHARED)
const char *eth_capabilities(void)
{return "no Ethernet";}
t_stat eth_open(ETH_DEV* dev, char* name, DEVICE* dptr, uint32 dbit) t_stat eth_open(ETH_DEV* dev, char* name, DEVICE* dptr, uint32 dbit)
{return SCPE_NOFNC;} {return SCPE_NOFNC;}
t_stat eth_close (ETH_DEV* dev) t_stat eth_close (ETH_DEV* dev)
@ -875,6 +875,22 @@ void eth_show_dev (FILE* st, ETH_DEV* dev)
{} {}
#else /* endif unimplemented */ #else /* endif unimplemented */
const char *eth_capabilities(void)
{
return "Ethernet Packet transport"
#if defined (HAVE_PCAP_NETWORK)
":PCAP"
#endif
#if defined (HAVE_TAP_NETWORK)
":TAP"
#endif
#if defined (HAVE_VDE_NETWORK)
":VDE"
#endif
":UDP";
}
#if defined (HAVE_PCAP_NETWORK)
/*============================================================================*/ /*============================================================================*/
/* WIN32, Linux, and xBSD routines use WinPcap and libpcap packages */ /* WIN32, Linux, and xBSD routines use WinPcap and libpcap packages */
/* OpenVMS Alpha uses a WinPcap port and an associated execlet */ /* OpenVMS Alpha uses a WinPcap port and an associated execlet */
@ -887,24 +903,33 @@ void eth_show_dev (FILE* st, ETH_DEV* dev)
#include <pcap.h> #include <pcap.h>
#include <string.h> #include <string.h>
#else
struct pcap_pkthdr {
uint32 caplen; /* length of portion present */
uint32 len; /* length this packet (off wire) */
};
#define PCAP_ERRBUF_SIZE 256
typedef void * pcap_t; /* Pseudo Type to avoid compiler errors */
#define DLT_EN10MB 1 /* Dummy Value to avoid compiler errors */
#endif /* HAVE_PCAP_NETWORK */
#ifdef USE_TAP_NETWORK #ifdef HAVE_TAP_NETWORK
#if defined(__linux) || defined(__linux__) #if defined(__linux) || defined(__linux__)
#include <sys/ioctl.h> #include <sys/ioctl.h>
#include <net/if.h> #include <net/if.h>
#include <linux/if_tun.h> #include <linux/if_tun.h>
#elif defined(USE_BSDTUNTAP) #elif defined(HAVE_BSDTUNTAP)
#include <sys/types.h> #include <sys/types.h>
#include <net/if_types.h> #include <net/if_types.h>
#include <net/if.h> #include <net/if.h>
#else /* We don't know how to do this on the current platform */ #else /* We don't know how to do this on the current platform */
#undef USE_TAP_NETWORK #undef HAVE_TAP_NETWORK
#endif #endif
#endif /* USE_TAP_NETWORK */ #endif /* HAVE_TAP_NETWORK */
#ifdef USE_VDE_NETWORK #ifdef HAVE_VDE_NETWORK
#include <libvdeplug.h> #include <libvdeplug.h>
#endif /* USE_VDE_NETWORK */ #endif /* HAVE_VDE_NETWORK */
/* Allows windows to look up user-defined adapter names */ /* Allows windows to look up user-defined adapter names */
#if defined(_WIN32) #if defined(_WIN32)
@ -1404,7 +1429,7 @@ static int pcap_mac_if_vms(char *AdapterName, unsigned char MACAddress[6])
return -1; return -1;
return 0; return 0;
} }
#endif #endif /* defined (__VMS) && !defined(__VAX) */
static void eth_get_nic_hw_addr(ETH_DEV* dev, char *devname) static void eth_get_nic_hw_addr(ETH_DEV* dev, char *devname)
{ {
@ -1493,9 +1518,11 @@ HANDLE hWait = (dev->eth_api == ETH_API_PCAP) ? pcap_getevent ((pcap_t*)dev->han
switch (dev->eth_api) { switch (dev->eth_api) {
case ETH_API_PCAP: case ETH_API_PCAP:
#if defined (HAVE_PCAP_NETWORK)
#if defined (MUST_DO_SELECT) #if defined (MUST_DO_SELECT)
do_select = 1; do_select = 1;
select_fd = pcap_get_selectable_fd((pcap_t *)dev->handle); select_fd = pcap_get_selectable_fd((pcap_t *)dev->handle);
#endif
#endif #endif
break; break;
case ETH_API_TAP: case ETH_API_TAP:
@ -1543,10 +1570,12 @@ while (dev->handle) {
break; break;
/* dispatch read request queue available packets */ /* dispatch read request queue available packets */
switch (dev->eth_api) { switch (dev->eth_api) {
#ifdef HAVE_PCAP_NETWORK
case ETH_API_PCAP: case ETH_API_PCAP:
status = pcap_dispatch ((pcap_t*)dev->handle, -1, &_eth_callback, (u_char*)dev); status = pcap_dispatch ((pcap_t*)dev->handle, -1, &_eth_callback, (u_char*)dev);
break; break;
#ifdef USE_TAP_NETWORK #endif
#ifdef HAVE_TAP_NETWORK
case ETH_API_TAP: case ETH_API_TAP:
if (1) { if (1) {
struct pcap_pkthdr header; struct pcap_pkthdr header;
@ -1564,8 +1593,8 @@ while (dev->handle) {
status = 0; status = 0;
} }
break; break;
#endif /* USE_TAP_NETWORK */ #endif /* HAVE_TAP_NETWORK */
#ifdef USE_VDE_NETWORK #ifdef HAVE_VDE_NETWORK
case ETH_API_VDE: case ETH_API_VDE:
if (1) { if (1) {
struct pcap_pkthdr header; struct pcap_pkthdr header;
@ -1583,7 +1612,7 @@ while (dev->handle) {
status = 0; status = 0;
} }
break; break;
#endif /* USE_VDE_NETWORK */ #endif /* HAVE_VDE_NETWORK */
case ETH_API_UDP: case ETH_API_UDP:
if (1) { if (1) {
struct pcap_pkthdr header; struct pcap_pkthdr header;
@ -1740,7 +1769,7 @@ if (0 == strncmp("tap:", savname, 4)) {
int tun = -1; /* TUN/TAP Socket */ int tun = -1; /* TUN/TAP Socket */
int on = 1; int on = 1;
#if defined(USE_TAP_NETWORK) #if defined(HAVE_TAP_NETWORK)
if (!strcmp(savname, "tap:tapN")) { if (!strcmp(savname, "tap:tapN")) {
msg = "Eth: Must specify actual tap device name (i.e. tap:tap0)\r\n"; msg = "Eth: Must specify actual tap device name (i.e. tap:tap0)\r\n";
printf (msg, errbuf); printf (msg, errbuf);
@ -1748,7 +1777,7 @@ if (0 == strncmp("tap:", savname, 4)) {
return SCPE_OPENERR; return SCPE_OPENERR;
} }
#endif #endif
#if (defined(__linux) || defined(__linux__)) && defined(USE_TAP_NETWORK) #if (defined(__linux) || defined(__linux__)) && defined(HAVE_TAP_NETWORK)
if ((tun = open("/dev/net/tun", O_RDWR)) >= 0) { if ((tun = open("/dev/net/tun", O_RDWR)) >= 0) {
struct ifreq ifr; /* Interface Requests */ struct ifreq ifr; /* Interface Requests */
@ -1773,7 +1802,7 @@ if (0 == strncmp("tap:", savname, 4)) {
} }
else else
strncpy(errbuf, strerror(errno), sizeof(errbuf)-1); strncpy(errbuf, strerror(errno), sizeof(errbuf)-1);
#elif defined(USE_BSDTUNTAP) && defined(USE_TAP_NETWORK) #elif defined(HAVE_BSDTUNTAP) && defined(HAVE_TAP_NETWORK)
if (1) { if (1) {
char dev_name[64] = ""; char dev_name[64] = "";
@ -1815,7 +1844,7 @@ if (0 == strncmp("tap:", savname, 4)) {
} }
#else #else
strncpy(errbuf, "No support for tap: devices", sizeof(errbuf)-1); strncpy(errbuf, "No support for tap: devices", sizeof(errbuf)-1);
#endif /* !defined(__linux) && !defined(USE_BSDTUNTAP) */ #endif /* !defined(__linux) && !defined(HAVE_BSDTUNTAP) */
if (0 == errbuf[0]) { if (0 == errbuf[0]) {
dev->eth_api = ETH_API_TAP; dev->eth_api = ETH_API_TAP;
dev->handle = (void *)1; /* Flag used to indicated open */ dev->handle = (void *)1; /* Flag used to indicated open */
@ -1823,7 +1852,7 @@ if (0 == strncmp("tap:", savname, 4)) {
} }
else else
if (0 == strncmp("vde:", savname, 4)) { if (0 == strncmp("vde:", savname, 4)) {
#if defined(USE_VDE_NETWORK) #if defined(HAVE_VDE_NETWORK)
struct vde_open_args voa; struct vde_open_args voa;
memset(&voa, 0, sizeof(voa)); memset(&voa, 0, sizeof(voa));
@ -1841,7 +1870,7 @@ else
} }
#else #else
strncpy(errbuf, "No support for vde: network devices", sizeof(errbuf)-1); strncpy(errbuf, "No support for vde: network devices", sizeof(errbuf)-1);
#endif /* defined(USE_VDE_NETWORK) */ #endif /* defined(HAVE_VDE_NETWORK) */
} }
else { else {
if (0 == strncmp("udp:", savname, 4)) { if (0 == strncmp("udp:", savname, 4)) {
@ -1875,6 +1904,7 @@ else
dev->handle = (void *)1; /* Flag used to indicated open */ dev->handle = (void *)1; /* Flag used to indicated open */
} }
else { else {
#if defined(HAVE_PCAP_NETWORK)
dev->handle = (void*) pcap_open_live(savname, bufsz, ETH_PROMISC, PCAP_READ_TIMEOUT, errbuf); dev->handle = (void*) pcap_open_live(savname, bufsz, ETH_PROMISC, PCAP_READ_TIMEOUT, errbuf);
if (!dev->handle) { /* can't open device */ if (!dev->handle) { /* can't open device */
msg = "Eth: pcap_open_live error - %s\r\n"; msg = "Eth: pcap_open_live error - %s\r\n";
@ -1883,6 +1913,9 @@ else
return SCPE_OPENERR; return SCPE_OPENERR;
} }
dev->eth_api = ETH_API_PCAP; dev->eth_api = ETH_API_PCAP;
#else
strncpy (errbuf, "Unknown or unsupported network device", sizeof(errbuf)-1);
#endif
} }
} }
if (errbuf[0]) { if (errbuf[0]) {
@ -1906,7 +1939,7 @@ strcpy(dev->name, savname);
dev->dptr = dptr; dev->dptr = dptr;
dev->dbit = dbit; dev->dbit = dbit;
#if !defined(HAS_PCAP_SENDPACKET) && defined (xBSD) && !defined (__APPLE__) #if !defined(HAS_PCAP_SENDPACKET) && defined (xBSD) && !defined (__APPLE__) && defined (HAVE_PCAP_NETWORK)
/* Tell the kernel that the header is fully-formed when it gets it. /* Tell the kernel that the header is fully-formed when it gets it.
This is required in order to fake the src address. */ This is required in order to fake the src address. */
if (dev->eth_api == ETH_API_PCAP) { if (dev->eth_api == ETH_API_PCAP) {
@ -2008,15 +2041,17 @@ ethq_destroy (&dev->read_queue); /* release FIFO queue */
#endif #endif
switch (dev->eth_api) { switch (dev->eth_api) {
#ifdef HAVE_PCAP_NETWORK
case ETH_API_PCAP: case ETH_API_PCAP:
pcap_close(pcap); pcap_close(pcap);
break; break;
#ifdef USE_TAP_NETWORK #endif
#ifdef HAVE_TAP_NETWORK
case ETH_API_TAP: case ETH_API_TAP:
close(pcap_fd); close(pcap_fd);
break; break;
#endif #endif
#ifdef USE_VDE_NETWORK #ifdef HAVE_VDE_NETWORK
case ETH_API_VDE: case ETH_API_VDE:
vde_close((VDECONN*)pcap); vde_close((VDECONN*)pcap);
break; break;
@ -2221,15 +2256,17 @@ if ((packet->len >= ETH_MIN_PACKET) && (packet->len <= ETH_MAX_PACKET)) {
/* dispatch write request (synchronous; no need to save write info to dev) */ /* dispatch write request (synchronous; no need to save write info to dev) */
switch (dev->eth_api) { switch (dev->eth_api) {
#ifdef HAVE_PCAP_NETWORK
case ETH_API_PCAP: case ETH_API_PCAP:
status = pcap_sendpacket((pcap_t*)dev->handle, (u_char*)packet->msg, packet->len); status = pcap_sendpacket((pcap_t*)dev->handle, (u_char*)packet->msg, packet->len);
break; break;
#ifdef USE_TAP_NETWORK #endif
#ifdef HAVE_TAP_NETWORK
case ETH_API_TAP: case ETH_API_TAP:
status = (((int)packet->len == write(dev->fd_handle, (void *)packet->msg, packet->len)) ? 0 : -1); status = (((int)packet->len == write(dev->fd_handle, (void *)packet->msg, packet->len)) ? 0 : -1);
break; break;
#endif #endif
#ifdef USE_VDE_NETWORK #ifdef HAVE_VDE_NETWORK
case ETH_API_VDE: case ETH_API_VDE:
status = vde_send((VDECONN*)dev->handle, (void *)packet->msg, packet->len, 0); status = vde_send((VDECONN*)dev->handle, (void *)packet->msg, packet->len, 0);
if ((status == (int)packet->len) || (status == 0)) if ((status == (int)packet->len) || (status == 0))
@ -2931,7 +2968,7 @@ do {
case ETH_API_PCAP: case ETH_API_PCAP:
status = pcap_dispatch((pcap_t*)dev->handle, 1, &_eth_callback, (u_char*)dev); status = pcap_dispatch((pcap_t*)dev->handle, 1, &_eth_callback, (u_char*)dev);
break; break;
#ifdef USE_TAP_NETWORK #ifdef HAVE_TAP_NETWORK
case ETH_API_TAP: case ETH_API_TAP:
if (1) { if (1) {
struct pcap_pkthdr header; struct pcap_pkthdr header;
@ -2949,8 +2986,8 @@ do {
status = 0; status = 0;
} }
break; break;
#endif /* USE_TAP_NETWORK */ #endif /* HAVE_TAP_NETWORK */
#ifdef USE_VDE_NETWORK #ifdef HAVE_VDE_NETWORK
case ETH_API_VDE: case ETH_API_VDE:
if (1) { if (1) {
struct pcap_pkthdr header; struct pcap_pkthdr header;
@ -2968,7 +3005,7 @@ do {
status = 0; status = 0;
} }
break; break;
#endif /* USE_VDE_NETWORK */ #endif /* HAVE_VDE_NETWORK */
case ETH_API_UDP: case ETH_API_UDP:
if (1) { if (1) {
struct pcap_pkthdr header; struct pcap_pkthdr header;
@ -3022,7 +3059,6 @@ t_stat eth_filter_hash(ETH_DEV* dev, int addr_count, ETH_MAC* const addresses,
ETH_MULTIHASH* const hash) ETH_MULTIHASH* const hash)
{ {
int i; int i;
bpf_u_int32 bpf_subnet, bpf_netmask;
char buf[114+66*ETH_FILTER_MAX]; char buf[114+66*ETH_FILTER_MAX];
char errbuf[PCAP_ERRBUF_SIZE]; char errbuf[PCAP_ERRBUF_SIZE];
char mac[20]; char mac[20];
@ -3167,11 +3203,13 @@ sim_debug(dev->dbit, dev->dptr, "BPF string is: |%s|\n", buf);
/* get netmask, which is a required argument for compiling. The value, /* get netmask, which is a required argument for compiling. The value,
in our case isn't actually interesting since the filters we generate in our case isn't actually interesting since the filters we generate
aren't referencing IP fields, networks or values */ aren't referencing IP fields, networks or values */
if ((dev->eth_api == ETH_API_PCAP) && (pcap_lookupnet(dev->name, &bpf_subnet, &bpf_netmask, errbuf)<0))
bpf_netmask = 0;
#ifdef USE_BPF #ifdef USE_BPF
if (dev->eth_api == ETH_API_PCAP) { if (dev->eth_api == ETH_API_PCAP) {
bpf_u_int32 bpf_subnet, bpf_netmask;
if (pcap_lookupnet(dev->name, &bpf_subnet, &bpf_netmask, errbuf)<0)
bpf_netmask = 0;
/* compile filter string */ /* compile filter string */
if ((status = pcap_compile(dev->handle, &bpf, buf, 1, bpf_netmask)) < 0) { if ((status = pcap_compile(dev->handle, &bpf, buf, 1, bpf_netmask)) < 0) {
sprintf(errbuf, "%s", pcap_geterr(dev->handle)); sprintf(errbuf, "%s", pcap_geterr(dev->handle));
@ -3233,14 +3271,17 @@ return SCPE_OK;
*/ */
int eth_host_devices(int used, int max, ETH_LIST* list) int eth_host_devices(int used, int max, ETH_LIST* list)
{ {
pcap_t* conn; pcap_t* conn = NULL;
int i, j, datalink; int i, j, datalink = 0;
char errbuf[PCAP_ERRBUF_SIZE]; char errbuf[PCAP_ERRBUF_SIZE];
for (i=0; i<used; ++i) { for (i=0; i<used; ++i) {
/* Cull any non-ethernet interface types */ /* Cull any non-ethernet interface types */
#if defined(HAVE_PCAP_NETWORK)
conn = pcap_open_live(list[i].name, ETH_MAX_PACKET, ETH_PROMISC, PCAP_READ_TIMEOUT, errbuf); conn = pcap_open_live(list[i].name, ETH_MAX_PACKET, ETH_PROMISC, PCAP_READ_TIMEOUT, errbuf);
if (NULL != conn) datalink = pcap_datalink(conn), pcap_close(conn); if (NULL != conn)
datalink = pcap_datalink(conn), pcap_close(conn);
#endif
if ((NULL == conn) || (datalink != DLT_EN10MB)) { if ((NULL == conn) || (datalink != DLT_EN10MB)) {
for (j=i; j<used-1; ++j) for (j=i; j<used-1; ++j)
list[j] = list[j+1]; list[j] = list[j+1];
@ -3290,7 +3331,7 @@ for (i=0; i<used; i++) {
} /* for */ } /* for */
#endif #endif
#ifdef USE_TAP_NETWORK #ifdef HAVE_TAP_NETWORK
if (used < max) { if (used < max) {
#if defined(__OpenBSD__) #if defined(__OpenBSD__)
sprintf(list[used].name, "%s", "tap:tunN"); sprintf(list[used].name, "%s", "tap:tunN");
@ -3301,7 +3342,7 @@ if (used < max) {
++used; ++used;
} }
#endif #endif
#ifdef USE_VDE_NETWORK #ifdef HAVE_VDE_NETWORK
if (used < max) { if (used < max) {
sprintf(list[used].name, "%s", "vde:device"); sprintf(list[used].name, "%s", "vde:device");
sprintf(list[used].desc, "%s", "Integrated VDE support"); sprintf(list[used].desc, "%s", "Integrated VDE support");
@ -3329,10 +3370,10 @@ return used;
int eth_devices(int max, ETH_LIST* list) int eth_devices(int max, ETH_LIST* list)
{ {
int i = 0; int i = 0;
char errbuf[PCAP_ERRBUF_SIZE];
#ifndef DONT_USE_PCAP_FINDALLDEVS #ifndef DONT_USE_PCAP_FINDALLDEVS
pcap_if_t* alldevs; pcap_if_t* alldevs;
pcap_if_t* dev; pcap_if_t* dev;
char errbuf[PCAP_ERRBUF_SIZE];
memset(list, 0, max*sizeof(*list)); memset(list, 0, max*sizeof(*list));
errbuf[0] = '\0'; errbuf[0] = '\0';

View file

@ -105,7 +105,7 @@
#endif /* USE_SETNONBLOCK */ #endif /* USE_SETNONBLOCK */
#undef PCAP_READ_TIMEOUT #undef PCAP_READ_TIMEOUT
#define PCAP_READ_TIMEOUT 15 #define PCAP_READ_TIMEOUT 15
#if (!defined (xBSD) && !defined(_WIN32) && !defined(VMS) && !defined(__CYGWIN__)) || defined (USE_TAP_NETWORK) || defined (USE_VDE_NETWORK) #if (!defined (xBSD) && !defined(_WIN32) && !defined(VMS) && !defined(__CYGWIN__)) || defined (HAVE_TAP_NETWORK) || defined (HAVE_VDE_NETWORK)
#define MUST_DO_SELECT 1 #define MUST_DO_SELECT 1
#endif #endif
#endif /* USE_READER_THREAD */ #endif /* USE_READER_THREAD */
@ -119,13 +119,22 @@
#undef USE_SHARED #undef USE_SHARED
#endif #endif
/* USE_SHARED implies shared pcap, so force HAVE_PCAP_NETWORK */
#if defined(USE_SHARED) && !defined(HAVE_PCAP_NETWORK)
#define HAVE_PCAP_NETWORK 1
#endif
/* /*
USE_BPF is defined to let this code leverage the libpcap/OS kernel provided USE_BPF is defined to let this code leverage the libpcap/OS kernel provided
BPF packet filtering. This generally will enhance performance. It may not BPF packet filtering. This generally will enhance performance. It may not
be available in some environments and/or it may not work correctly, so be available in some environments and/or it may not work correctly, so
undefining this will still provide working code here. undefining this will still provide working code here.
*/ */
#if defined(HAVE_PCAP_NETWORK)
#define USE_BPF 1 #define USE_BPF 1
#else
#define DONT_USE_PCAP_FINDALLDEVS 1
#endif
#if defined (USE_READER_THREAD) #if defined (USE_READER_THREAD)
#include <pthread.h> #include <pthread.h>
@ -314,5 +323,6 @@ void ethq_insert_data(ETH_QUE* que, int32 type, /* insert item into FIFO
size_t crc_len, const uint8 *crc_data, int32 status); size_t crc_len, const uint8 *crc_data, int32 status);
t_stat ethq_destroy(ETH_QUE* que); /* release FIFO queue */ t_stat ethq_destroy(ETH_QUE* que); /* release FIFO queue */
const char *eth_capabilities(void);
#endif /* _SIM_ETHER_H */ #endif /* _SIM_ETHER_H */