From 07e17387454bca5b5b37a19507ac15f482c9a200 Mon Sep 17 00:00:00 2001 From: Mark Pizzolato Date: Fri, 11 Nov 2011 07:03:25 -0800 Subject: [PATCH 1/8] Cleaned up makefile to only build network support for simulators which can use it. --- makefile | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/makefile b/makefile index ebe7379a..d22df57f 100644 --- a/makefile +++ b/makefile @@ -37,8 +37,8 @@ ifeq ($(WIN32),) OS_LDFLAGS += -lm endif ifeq (SunOS,$(shell uname)) - OS_CCDEFS += -I/opt/sfw/include -DSIM_ASYNCH_IO -DUSE_READER_THREAD - OS_LDFLAGS += -lsocket -lnsl -lrt -lm -lpthread -L/opt/sfw/lib -R/opt/sfw/lib + OS_CCDEFS += -I/opt/sfw/include + OS_LDFLAGS += -lsocket -lnsl -L/opt/sfw/lib -R/opt/sfw/lib endif ifeq (cygwin,$(findstring cygwin,$(OSTYPE))) OS_CCDEFS += -O2 @@ -90,6 +90,7 @@ ifeq ($(WIN32),) ifneq (binexists,$(shell if $(TEST) -e BIN; then echo binexists; fi)) MKDIRBIN = if $(TEST) ! -e BIN; then mkdir BIN; fi endif + NETWORK_OPT = $(NETWORK_CCDEFS) ifneq ($(USE_NETWORK),) # Assume built from tcpdump.org sources with default install target NETWORK_OPT = -DUSE_NETWORK -isystem /usr/local/include /usr/local/lib/libpcap.a @@ -137,7 +138,7 @@ else endif -CC = $(GCC) -std=c99 -U__STRICT_ANSI__ -g -I . $(NETWORK_CCDEFS) $(OS_CCDEFS) $(ROMS_OPT) +CC = $(GCC) -std=c99 -U__STRICT_ANSI__ -g -I . $(OS_CCDEFS) $(ROMS_OPT) LDFLAGS = $(OS_LDFLAGS) $(NETWORK_LDFLAGS) # From 22b130be23bad9f881e2d1ae45b6c8e76ed087b9 Mon Sep 17 00:00:00 2001 From: Mark Pizzolato Date: Tue, 15 Nov 2011 14:42:44 -0800 Subject: [PATCH 2/8] Generalized makefile approach to find libraries and include files allowing different platforms to simply describe where to check for required components. It now explicitly reports which libraries are being referenced. --- makefile | 123 +++++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 87 insertions(+), 36 deletions(-) diff --git a/makefile b/makefile index d22df57f..09933916 100644 --- a/makefile +++ b/makefile @@ -11,6 +11,15 @@ # # CC Command (and platform available options). (Poor man's autoconf) # +# In general, the logic below will detect and build with the available +# features which the host build environment provides. +# +# Readline support can be disabled if GNU make is invoked with +# DONT_USE_READLINE=1 on the command line. +# +# Internal ROM support can be disabled if GNU make is invoked with +# DONT_USE_ROMS=1 on the command line. +# ifeq ($(WIN32),) #*nix Environments (&& cygwin) GCC = gcc @@ -19,81 +28,123 @@ ifeq ($(WIN32),) else TEST = test endif + INCPATH=/usr/include + LIBPATH=/usr/lib + OS_CCDEFS = -D_GNU_SOURCE ifeq (Darwin,$(shell uname)) LIBEXT = dylib else ifeq (Linux,$(shell uname)) LIBEXT = so + ifeq (usrlib64,$(shell if $(TEST) -d /usr/lib64; then echo usrlib64; fi)) + LIBPATH += /usr/lib64 + endif + ifeq (lib32,$(shell if $(TEST) -d /usr/lib32; then echo lib32; fi)) + LIBPATH += /usr/lib32 + endif else ifeq (SunOS,$(shell uname)) LIBEXT = so + OS_LDFLAGS += -lsocket -lnsl + ifeq (incsfw,$(shell if $(TEST) -d /opt/sfw/include; then echo incsfw; fi)) + INCPATH += /opt/sfw/include + OS_CCDEFS += -I/opt/sfw/include + endif + ifeq (libsfw,$(shell if $(TEST) -d /opt/sfw/lib; then echo libsfw; fi)) + LIBPATH += /opt/sfw/lib + OS_LDFLAGS += -L/opt/sfw/lib -R/opt/sfw/lib + endif else + ifeq (usrpkglib,$(shell if $(TEST) -d /usr/pkg/lib; then echo usrpkglib; fi)) + LIBPATH += /usr/pkg/lib + OS_LDFLAGS += -L/usr/pkg/lib -R/usr/pkg/lib + endif LIBEXT = a endif endif endif - OS_CCDEFS = -D_GNU_SOURCE - ifeq (libm,$(shell if $(TEST) -e /usr/lib/libm.$(LIBEXT) -o -e /usr/lib64/libm.$(LIBEXT); then echo libm; fi)) - OS_LDFLAGS += -lm - endif - ifeq (SunOS,$(shell uname)) - OS_CCDEFS += -I/opt/sfw/include - OS_LDFLAGS += -lsocket -lnsl -L/opt/sfw/lib -R/opt/sfw/lib - endif ifeq (cygwin,$(findstring cygwin,$(OSTYPE))) OS_CCDEFS += -O2 endif - ifeq (librt,$(shell if $(TEST) -e /usr/lib/librt.$(LIBEXT) -o -e /usr/lib64/librt.$(LIBEXT); then echo librt; fi)) + find_lib = $(strip $(firstword $(foreach dir,$(strip $(LIBPATH)),$(wildcard $(dir)/lib$(1).$(LIBEXT))))) + find_include = $(strip $(firstword $(foreach dir,$(strip $(INCPATH)),$(wildcard $(dir)/$(1).h)))) + ifneq (,$(call find_lib,m)) + OS_LDFLAGS += -lm + $(info using libm: $(call find_lib,m)) + endif + ifneq (,$(call find_lib,rt)) OS_LDFLAGS += -lrt + $(info using librt: $(call find_lib,rt)) endif - ifeq (libpthread,$(shell if $(TEST) -e /usr/lib/libpthread.$(LIBEXT) -o -e /usr/lib64/libpthread.$(LIBEXT); then echo libpthread; fi)) - OS_CCDEFS += -DSIM_ASYNCH_IO -DUSE_READER_THREAD - OS_LDFLAGS += -lpthread + ifneq (,$(call find_lib,pthread)) + ifneq (,$(call find_include,pthread)) + OS_CCDEFS += -DSIM_ASYNCH_IO -DUSE_READER_THREAD + OS_LDFLAGS += -lpthread + $(info using libpthread: $(call find_lib,pthread) $(call find_include,pthread)) + endif endif - ifeq (readline,$(shell if $(TEST) -e /usr/lib/libreadline.$(LIBEXT) -o -e /usr/lib64/libreadline.$(LIBEXT) -o -e /opt/sfw/lib/libreadline.a; then echo readline; fi)) - ifeq (readline_h,$(shell if $(TEST) -e /usr/include/readline/readline.h -o -e /usr/include/readline.h -o -e /opt/sfw/include/readline/readline.h; then echo readline_h; fi)) - # Use Locally installed and available readline support - ifeq (ncurses,$(shell if $(TEST) -e /usr/lib/libncurses.$(LIBEXT) -o -e /opt/sfw/lib/libncurses.a; then echo ncurses; fi)) - OS_CCDEFS += -DHAVE_READLINE - OS_LDFLAGS += -lreadline -lncurses - else - ifeq (curses,$(shell if $(TEST) -e /usr/lib/libcurses.$(LIBEXT); then echo curses; fi)) + ifeq ($(DONT_USE_READLINE),) + ifneq (,$(call find_include,readline/readline)) + ifneq (,$(call find_lib,readline)) + # Use Locally installed and available readline support + ifneq (,$(call find_lib,ncurses)) OS_CCDEFS += -DHAVE_READLINE - OS_LDFLAGS += -lreadline -lcurses + OS_LDFLAGS += -lreadline -lncurses + $(info using libreadline and libncurses: $(call find_lib,readline) $(call find_lib,ncurses) $(call find_include,readline/readline)) else - ifeq (solaris_readline,$(shell if $(TEST) ! -e /opt/sfw/lib/libreadline.a; then echo solaris_readline; fi)) + ifneq (,$(call find_lib,curses)) OS_CCDEFS += -DHAVE_READLINE - OS_LDFLAGS += -lreadline + OS_LDFLAGS += -lreadline -lcurses + $(info using libreadline and libcurses: $(call find_lib,readline) $(call find_lib,curses) $(call find_include,readline/readline)) endif endif endif endif endif - ifeq (pcap,$(shell if $(TEST) -e /usr/include/pcap.h -o -e /opt/sfw/include/pcap.h; then echo pcap; fi)) - # Use Locally installed and available pcap support - NETWORK_CCDEFS = -DUSE_NETWORK - NETWORK_LDFLAGS = -lpcap + ifneq (,$(call find_lib,pcap)) + ifneq (,$(call find_include,pcap)) + NETWORK_CCDEFS = -DUSE_NETWORK + NETWORK_LDFLAGS = -lpcap + $(info using libpcap: $(call find_lib,pcap) $(call find_include,pcap)) + endif endif - ifeq (vde,$(shell if $(TEST) -e /usr/include/libvdeplug.h -a \( -e /usr/lib/libvdeplug.$(LIBEXT) -o -e /usr/lib64/libvdeplug.$(LIBEXT) \); then echo vde; fi)) - # Provide support for vde networking - NETWORK_CCDEFS += -DUSE_VDE_NETWORK - NETWORK_LDFLAGS += -lvdeplug + ifneq (,$(call find_lib,vdeplug)) + ifneq (,$(call find_include,libvdeplug)) + # Provide support for vde networking + NETWORK_CCDEFS += -DUSE_VDE_NETWORK + NETWORK_LDFLAGS += -lvdeplug + $(info using libvdeplug: $(call find_lib,vdeplug) $(call find_include,libvdeplug)) + endif endif - ifeq (tuntap,$(shell if $(TEST) -e /usr/include/linux/if_tun.h; then echo tuntap; fi)) + ifneq (,$(call find_include,linux/if_tun)) # Provide support for Tap networking on Linux NETWORK_CCDEFS += -DUSE_TAP_NETWORK endif 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 + # Provide support for Tap networking on BSD platforms (including OS X) NETWORK_CCDEFS += -DUSE_TAP_NETWORK -DUSE_BSDTUNTAP endif ifneq (binexists,$(shell if $(TEST) -e BIN; then echo binexists; fi)) MKDIRBIN = if $(TEST) ! -e BIN; then mkdir BIN; fi endif NETWORK_OPT = $(NETWORK_CCDEFS) - ifneq ($(USE_NETWORK),) - # Assume built from tcpdump.org sources with default install target - NETWORK_OPT = -DUSE_NETWORK -isystem /usr/local/include /usr/local/lib/libpcap.a + ifneq ($(USE_NETWORK),) # Network support specified on the GNU make command line + ifneq (USE_NETWORK,$(findstring USE_NETWORK,$(NETWORK_CCDEFS))) + # Look for package built from tcpdump.org sources with default install target + LIBPATH += /usr/local/lib + INCPATH += /usr/local/include + LIBEXT = a + ifneq (,$(call find_lib,pcap)) + ifneq (,$(call find_include,pcap)) + NETWORK_OPT = -DUSE_NETWORK -isystem /usr/local/include /usr/local/lib/libpcap.a + $(info using libpcap: $(call find_lib,pcap) $(call find_include,pcap)) + else + $(error using libpcap: $(call find_lib,pcap) missing pcap.h) + endif + else + $(error missing libpcap) + endif + endif endif else #Win32 Environments (via MinGW32) From 2d4d248ae3ff2f43d45b615128107451e091cd6c Mon Sep 17 00:00:00 2001 From: Mark Pizzolato Date: Wed, 16 Nov 2011 13:45:37 -0800 Subject: [PATCH 3/8] Added Android targeted build support to the makefile --- makefile | 75 +++++++++++++++++++++++++++++++++----------------------- 1 file changed, 44 insertions(+), 31 deletions(-) diff --git a/makefile b/makefile index 09933916..15d8375f 100644 --- a/makefile +++ b/makefile @@ -7,9 +7,10 @@ # NetBSD # FreeBSD # Windows (MinGW & cygwin) -# +# Linux x86 targeting Android (using agcc script) # -# CC Command (and platform available options). (Poor man's autoconf) +# Android targeted builds should invoke GNU make with GCC=agcc on +# the command line. # # In general, the logic below will detect and build with the available # features which the host build environment provides. @@ -20,46 +21,54 @@ # Internal ROM support can be disabled if GNU make is invoked with # DONT_USE_ROMS=1 on the command line. # -ifeq ($(WIN32),) - #*nix Environments (&& cygwin) - GCC = gcc +# CC Command (and platform available options). (Poor man's autoconf) +# +ifeq ($(WIN32),) #*nix Environments (&& cygwin) + ifeq ($(GCC),) + GCC = gcc + endif ifeq (SunOS,$(shell uname)) TEST = /bin/test else TEST = test endif - INCPATH=/usr/include - LIBPATH=/usr/lib - OS_CCDEFS = -D_GNU_SOURCE - ifeq (Darwin,$(shell uname)) - LIBEXT = dylib - else - ifeq (Linux,$(shell uname)) - LIBEXT = so - ifeq (usrlib64,$(shell if $(TEST) -d /usr/lib64; then echo usrlib64; fi)) - LIBPATH += /usr/lib64 - endif - ifeq (lib32,$(shell if $(TEST) -d /usr/lib32; then echo lib32; fi)) - LIBPATH += /usr/lib32 - endif + ifeq (agcc,$(findstring agcc,$(GCC))) # Android target build? + OS_CCDEFS = -D_GNU_SOURCE -DSIM_ASYNCH_IO + OS_LDFLAGS = -lm + else # Non-Android Builds + INCPATH=/usr/include + LIBPATH=/usr/lib + OS_CCDEFS = -D_GNU_SOURCE + ifeq (Darwin,$(shell uname)) + LIBEXT = dylib else - ifeq (SunOS,$(shell uname)) + ifeq (Linux,$(shell uname)) LIBEXT = so - OS_LDFLAGS += -lsocket -lnsl - ifeq (incsfw,$(shell if $(TEST) -d /opt/sfw/include; then echo incsfw; fi)) - INCPATH += /opt/sfw/include - OS_CCDEFS += -I/opt/sfw/include + ifeq (usrlib64,$(shell if $(TEST) -d /usr/lib64; then echo usrlib64; fi)) + LIBPATH += /usr/lib64 endif - ifeq (libsfw,$(shell if $(TEST) -d /opt/sfw/lib; then echo libsfw; fi)) - LIBPATH += /opt/sfw/lib - OS_LDFLAGS += -L/opt/sfw/lib -R/opt/sfw/lib + ifeq (lib32,$(shell if $(TEST) -d /usr/lib32; then echo lib32; fi)) + LIBPATH += /usr/lib32 endif else - ifeq (usrpkglib,$(shell if $(TEST) -d /usr/pkg/lib; then echo usrpkglib; fi)) - LIBPATH += /usr/pkg/lib - OS_LDFLAGS += -L/usr/pkg/lib -R/usr/pkg/lib + ifeq (SunOS,$(shell uname)) + LIBEXT = so + OS_LDFLAGS += -lsocket -lnsl + ifeq (incsfw,$(shell if $(TEST) -d /opt/sfw/include; then echo incsfw; fi)) + INCPATH += /opt/sfw/include + OS_CCDEFS += -I/opt/sfw/include + endif + ifeq (libsfw,$(shell if $(TEST) -d /opt/sfw/lib; then echo libsfw; fi)) + LIBPATH += /opt/sfw/lib + OS_LDFLAGS += -L/opt/sfw/lib -R/opt/sfw/lib + endif + else + ifeq (usrpkglib,$(shell if $(TEST) -d /usr/pkg/lib; then echo usrpkglib; fi)) + LIBPATH += /usr/pkg/lib + OS_LDFLAGS += -L/usr/pkg/lib -R/usr/pkg/lib + endif + LIBEXT = a endif - LIBEXT = a endif endif endif @@ -441,7 +450,11 @@ endif ${BIN}BuildROMs${EXE} : ${MKDIRBIN} +ifeq (agcc,$(findstring agcc,$(firstword $(CC)))) + gcc $(wordlist 2,1000,${CC}) sim_BuildROMs.c -o $@ +else ${CC} sim_BuildROMs.c -o $@ +endif ifeq ($(WIN32),) $@ ${RM} $@ From 8b01b900086f83c7f59aa128fbda0b390a0178ed Mon Sep 17 00:00:00 2001 From: Mark Pizzolato Date: Thu, 17 Nov 2011 08:46:15 -0800 Subject: [PATCH 4/8] Generalized readline support to dynamically load the readline library and avoid the symbol conflicts which happen on some platforms and some simulators with a global PC variable. --- makefile | 33 ++++++++++++++------------------- scp.c | 47 +++++++++++++++++++++++++++++++++++------------ 2 files changed, 49 insertions(+), 31 deletions(-) diff --git a/makefile b/makefile index 15d8375f..b7499af5 100644 --- a/makefile +++ b/makefile @@ -15,9 +15,6 @@ # In general, the logic below will detect and build with the available # features which the host build environment provides. # -# Readline support can be disabled if GNU make is invoked with -# DONT_USE_READLINE=1 on the command line. -# # Internal ROM support can be disabled if GNU make is invoked with # DONT_USE_ROMS=1 on the command line. # @@ -67,7 +64,11 @@ ifeq ($(WIN32),) #*nix Environments (&& cygwin) LIBPATH += /usr/pkg/lib OS_LDFLAGS += -L/usr/pkg/lib -R/usr/pkg/lib endif - LIBEXT = a + ifneq (,$(findstring NetBSD,$(shell uname))$(findstring FreeBSD,$(shell uname))) + LIBEXT = so + else + LIBEXT = a + endif endif endif endif @@ -92,21 +93,15 @@ ifeq ($(WIN32),) #*nix Environments (&& cygwin) $(info using libpthread: $(call find_lib,pthread) $(call find_include,pthread)) endif endif - ifeq ($(DONT_USE_READLINE),) - ifneq (,$(call find_include,readline/readline)) - ifneq (,$(call find_lib,readline)) - # Use Locally installed and available readline support - ifneq (,$(call find_lib,ncurses)) - OS_CCDEFS += -DHAVE_READLINE - OS_LDFLAGS += -lreadline -lncurses - $(info using libreadline and libncurses: $(call find_lib,readline) $(call find_lib,ncurses) $(call find_include,readline/readline)) - else - ifneq (,$(call find_lib,curses)) - OS_CCDEFS += -DHAVE_READLINE - OS_LDFLAGS += -lreadline -lcurses - $(info using libreadline and libcurses: $(call find_lib,readline) $(call find_lib,curses) $(call find_include,readline/readline)) - endif - endif + ifneq (,$(call find_include,dlfcn)) + ifneq (,$(call find_lib,dl)) + OS_CCDEFS += -DHAVE_DLOPEN=$(LIBEXT) + OS_LDFLAGS += -ldl + $(info using libdl: $(call find_lib,dl) $(call find_include,dlfcn)) + else + ifeq (BSD,$(findstring BSD,$(shell uname))) + OS_CCDEFS += -DHAVE_DLOPEN=so + $(info using libdl: $(call find_include,dlfcn)) endif endif endif diff --git a/scp.c b/scp.c index 9473b947..3920db7d 100644 --- a/scp.c +++ b/scp.c @@ -213,9 +213,8 @@ #include #include -#if defined(HAVE_READLINE) -#include -#include +#if defined(HAVE_DLOPEN) /* Dynamic Readline support */ +#include #endif #define EX_D 0 /* deposit */ @@ -3841,15 +3840,39 @@ return read_line_p (NULL, cptr, size, stream); char *read_line_p (char *prompt, char *cptr, int32 size, FILE *stream) { char *tptr; +#if defined(HAVE_DLOPEN) +static int initialized = 0; +static char *(*p_readline)(const char *) = NULL; +static void (*p_add_history)(const char *) = NULL; -#if defined(HAVE_READLINE) +if (!initialized) { + initialized = 1; + void *handle; + +#define __STR_QUOTE(tok) #tok +#define __STR(tok) __STR_QUOTE(tok) + handle = dlopen("libncurses." __STR(HAVE_DLOPEN), RTLD_NOW|RTLD_GLOBAL); + handle = dlopen("libreadline." __STR(HAVE_DLOPEN), RTLD_NOW|RTLD_GLOBAL); + if (handle) { + p_readline = dlsym(handle, "readline"); + p_add_history = dlsym(handle, "add_history"); + } + } if (prompt) { /* interactive? */ - char *tmpc = readline (prompt); /* get cmd line */ - if (tmpc == NULL) /* bad result? */ - cptr = NULL; + char *tmpc; + + if (p_readline) { + char *tmpc = p_readline (prompt); /* get cmd line */ + if (tmpc == NULL) /* bad result? */ + cptr = NULL; + else { + strncpy (cptr, tmpc, size); /* copy result */ + free (tmpc) ; /* free temp */ + } + } else { - strncpy (cptr, tmpc, size); /* copy result */ - free (tmpc) ; /* free temp */ + printf ("%s", prompt); /* display prompt */ + cptr = fgets (cptr, size, stream); /* get cmd line */ } } else cptr = fgets (cptr, size, stream); /* get cmd line */ @@ -3875,9 +3898,9 @@ while (isspace (*cptr)) /* trim leading spc */ if (*cptr == ';') /* ignore comment */ *cptr = 0; -#if defined (HAVE_READLINE) -if (prompt) - add_history (cptr); +#if defined (HAVE_DLOPEN) +if (prompt && p_add_history && *cptr) /* Save non blank lines in history */ + p_add_history (cptr); #endif return cptr; From 3b7492d6bee69bfa23c0a91cf895e2528f210dc0 Mon Sep 17 00:00:00 2001 From: Mark Pizzolato Date: Thu, 17 Nov 2011 09:51:58 -0800 Subject: [PATCH 5/8] Added dynamic loading of libpcap on *nix platforms. --- 0readme_ethernet.txt | 1 + makefile | 22 +++++-- sim_ether.c | 134 ++++++++++++++++++++++++++++++------------- sim_ether.h | 10 ++++ 4 files changed, 122 insertions(+), 45 deletions(-) diff --git a/0readme_ethernet.txt b/0readme_ethernet.txt index eb1c66f0..225f5be0 100644 --- a/0readme_ethernet.txt +++ b/0readme_ethernet.txt @@ -378,6 +378,7 @@ Dave Change Log =============================================================================== + 17-Nov-11 MP Added dynamic loading of libpcap on *nix platforms 30-Oct-11 MP Added support for vde (Virtual Distributed Ethernet) networking 29-Oct-11 MP Added support for integrated Tap networking interfaces on OSX 17-Aug-11 RMS Fix from Sergey Oboguev relating to XU and XQ Auto Config and diff --git a/makefile b/makefile index b7499af5..6d4c357f 100644 --- a/makefile +++ b/makefile @@ -14,6 +14,10 @@ # # In general, the logic below will detect and build with the available # features which the host build environment provides. +# +# Dynamic loading of libpcap is the default behavior if pcap.h is +# available at build time. Direct calls to libpcap can be enabled +# if GNU make is invoked with USE_NETWORK on the command line. # # Internal ROM support can be disabled if GNU make is invoked with # DONT_USE_ROMS=1 on the command line. @@ -105,11 +109,19 @@ ifeq ($(WIN32),) #*nix Environments (&& cygwin) endif endif endif - ifneq (,$(call find_lib,pcap)) - ifneq (,$(call find_include,pcap)) - NETWORK_CCDEFS = -DUSE_NETWORK - NETWORK_LDFLAGS = -lpcap - $(info using libpcap: $(call find_lib,pcap) $(call find_include,pcap)) + ifneq (,$(call find_include,pcap)) + ifneq (,$(call find_lib,pcap)) + ifneq ($(USE_NETWORK),) # Network support specified on the GNU make command line + NETWORK_CCDEFS = -DUSE_NETWORK + NETWORK_LDFLAGS = -lpcap + $(info using libpcap: $(call find_lib,pcap) $(call find_include,pcap)) + else # default build uses dynamic libpcap + NETWORK_CCDEFS = -DUSE_SHARED + $(info using libpcap: $$(call find_include,pcap)) + endif + else + NETWORK_CCDEFS = -DUSE_SHARED + $(info using libpcap: $$(call find_include,pcap)) endif endif ifneq (,$(call find_lib,vdeplug)) diff --git a/sim_ether.c b/sim_ether.c index 3ca7eefa..08abbad9 100644 --- a/sim_ether.c +++ b/sim_ether.c @@ -50,7 +50,7 @@ Define one of the two macros below to enable networking: USE_NETWORK - Create statically linked network code - USE_SHARED - Create dynamically linked network code (_WIN32 only) + USE_SHARED - Create dynamically linked network code ------------------------------------------------------------------------------ @@ -160,6 +160,7 @@ Modification history: + 17-Nov-11 MP Added dynamic loading of libpcap on *nix platforms 30-Oct-11 MP Added support for vde (Virtual Distributed Ethernet) networking 29-Oct-11 MP Added support for integrated Tap networking interfaces on OSX 12-Aug-11 MP Cleaned up payload length determination @@ -752,7 +753,7 @@ void ethq_insert(ETH_QUE* que, int32 type, ETH_PACK* pack, int32 status) /* Non-implemented versions */ /*============================================================================*/ -#if !defined (USE_NETWORK) && (!defined (_WIN32) || !defined (USE_SHARED)) +#if !defined (USE_NETWORK) && !defined (USE_SHARED) t_stat eth_open(ETH_DEV* dev, char* name, DEVICE* dptr, uint32 dbit) {return SCPE_NOFNC;} t_stat eth_close (ETH_DEV* dev) @@ -816,14 +817,35 @@ void eth_show_dev (FILE* st, ETH_DEV* dev) #include #endif -#if defined(_WIN32) && defined(USE_SHARED) +#if defined(USE_SHARED) && (defined(_WIN32) || defined(HAVE_DLOPEN)) /* Dynamic DLL loading technique and modified source comes from Etherial/WireShark capture_pcap.c */ +#ifdef HAVE_DLOPEN +#include +#endif + /* Dynamic DLL load variables */ -static HINSTANCE hDll = 0; /* handle to DLL */ -static int dll_loaded = 0; /* 0=not loaded, 1=loaded, 2=DLL load failed, 3=Func load failed */ -static char* no_wpcap = "wpcap load failure"; +#ifdef _WIN32 +static HINSTANCE hLib = 0; /* handle to DLL */ +#else +static void *hLib = 0; /* handle to Library */ +#endif +static int lib_loaded = 0; /* 0=not loaded, 1=loaded, 2=library load failed, 3=Func load failed */ +static char* lib_name = +#ifdef _WIN32 + "wpcap.dll"; +#else +#define __STR_QUOTE(tok) #tok +#define __STR(tok) __STR_QUOTE(tok) + "libpcap." __STR(HAVE_DLOPEN); +#endif +static char* no_pcap = +#ifdef _WIN32 + "wpcap load failure"; +#else + "libpcap load failure"; +#endif /* define pointers to pcap functions needed */ static void (*p_pcap_close) (pcap_t *); @@ -836,46 +858,63 @@ static void (*p_pcap_freecode) (struct bpf_program *); static char* (*p_pcap_geterr) (pcap_t *); static int (*p_pcap_lookupnet) (const char *, bpf_u_int32 *, bpf_u_int32 *, char *); static pcap_t* (*p_pcap_open_live) (const char *, int, int, int, char *); +#ifdef _WIN32 static int (*p_pcap_setmintocopy) (pcap_t* handle, int); static HANDLE (*p_pcap_getevent) (pcap_t *); +#else +static int (*p_pcap_get_selectable_fd) (pcap_t *); +#endif static int (*p_pcap_sendpacket) (pcap_t* handle, const u_char* msg, int len); static int (*p_pcap_setfilter) (pcap_t *, struct bpf_program *); static char* (*p_pcap_lib_version) (void); /* load function pointer from DLL */ void load_function(char* function, void** func_ptr) { - *func_ptr = GetProcAddress(hDll, function); - if (*func_ptr == 0) { - char* msg = "Eth: Failed to find function '%s' in wpcap.dll\r\n"; +#ifdef _WIN32 + *func_ptr = GetProcAddress(hLib, function); +#else + *func_ptr = dlsym(hLib, function); +#endif + if (*func_ptr == 0) { + char* msg = "Eth: Failed to find function '%s' in %s\r\n"; - printf (msg, function); - if (sim_log) fprintf (sim_log, msg, function); - dll_loaded = 3; + printf (msg, function, lib_name); + if (sim_log) fprintf (sim_log, msg, function, lib_name); + lib_loaded = 3; } } /* load wpcap.dll as required */ -int load_wpcap(void) { - switch(dll_loaded) { +int load_pcap(void) { + switch(lib_loaded) { case 0: /* not loaded */ /* attempt to load DLL */ - hDll = LoadLibrary(TEXT("wpcap.dll")); - if (hDll == 0) { +#ifdef _WIN32 + hLib = LoadLibraryA(lib_name); +#else + hLib = dlopen(lib_name, RTLD_NOW); +#endif + if (hLib == 0) { /* failed to load DLL */ - char* msg = "Eth: Failed to load wpcap.dll\r\n"; - char* msg2 = "Eth: You must install WinPcap 4.x to use networking\r\n"; + char* msg = "Eth: Failed to load %s\r\n"; + char* msg2 = +#ifdef _WIN32 + "Eth: You must install WinPcap 4.x to use networking\r\n"; +#else + "Eth: You must install libpcap to use networking\r\n"; +#endif - printf (msg); + printf (msg, lib_name); printf (msg2); if (sim_log) { - fprintf (sim_log, msg); + fprintf (sim_log, msg, lib_name); fprintf (sim_log, msg2); } - dll_loaded = 2; + lib_loaded = 2; break; } else { - /* DLL loaded OK */ - dll_loaded = 1; + /* library loaded OK */ + lib_loaded = 1; } /* load required functions; sets dll_load=3 on error */ @@ -889,13 +928,17 @@ int load_wpcap(void) { load_function("pcap_geterr", (void**) &p_pcap_geterr); load_function("pcap_lookupnet", (void**) &p_pcap_lookupnet); load_function("pcap_open_live", (void**) &p_pcap_open_live); +#ifdef _WIN32 load_function("pcap_setmintocopy", (void**) &p_pcap_setmintocopy); load_function("pcap_getevent", (void**) &p_pcap_getevent); +#else + load_function("pcap_get_selectable_fd", (void**) &p_pcap_get_selectable_fd); +#endif load_function("pcap_sendpacket", (void**) &p_pcap_sendpacket); load_function("pcap_setfilter", (void**) &p_pcap_setfilter); load_function("pcap_lib_version", (void**) &p_pcap_lib_version); - if (dll_loaded == 1) { + if (lib_loaded == 1) { /* log successful load */ char* version = p_pcap_lib_version(); printf("%s\n", version); @@ -906,18 +949,18 @@ int load_wpcap(void) { default: /* loaded or failed */ break; } - return (dll_loaded == 1) ? 1 : 0; + return (lib_loaded == 1) ? 1 : 0; } /* define functions with dynamic revectoring */ void pcap_close(pcap_t* a) { - if (load_wpcap() != 0) { + if (load_pcap() != 0) { p_pcap_close(a); } } int pcap_compile(pcap_t* a, struct bpf_program* b, char* c, int d, bpf_u_int32 e) { - if (load_wpcap() != 0) { + if (load_pcap() != 0) { return p_pcap_compile(a, b, c, d, e); } else { return 0; @@ -925,7 +968,7 @@ int pcap_compile(pcap_t* a, struct bpf_program* b, char* c, int d, bpf_u_int32 e } int pcap_datalink(pcap_t* a) { - if (load_wpcap() != 0) { + if (load_pcap() != 0) { return p_pcap_datalink(a); } else { return 0; @@ -933,7 +976,7 @@ int pcap_datalink(pcap_t* a) { } int pcap_dispatch(pcap_t* a, int b, pcap_handler c, u_char* d) { - if (load_wpcap() != 0) { + if (load_pcap() != 0) { return p_pcap_dispatch(a, b, c, d); } else { return 0; @@ -941,29 +984,29 @@ int pcap_dispatch(pcap_t* a, int b, pcap_handler c, u_char* d) { } int pcap_findalldevs(pcap_if_t** a, char* b) { - if (load_wpcap() != 0) { + if (load_pcap() != 0) { return p_pcap_findalldevs(a, b); } else { *a = 0; - strcpy(b, no_wpcap); + strcpy(b, no_pcap); return -1; } } void pcap_freealldevs(pcap_if_t* a) { - if (load_wpcap() != 0) { + if (load_pcap() != 0) { p_pcap_freealldevs(a); } } void pcap_freecode(struct bpf_program* a) { - if (load_wpcap() != 0) { + if (load_pcap() != 0) { p_pcap_freecode(a); } } char* pcap_geterr(pcap_t* a) { - if (load_wpcap() != 0) { + if (load_pcap() != 0) { return p_pcap_geterr(a); } else { return (char*) 0; @@ -971,7 +1014,7 @@ char* pcap_geterr(pcap_t* a) { } int pcap_lookupnet(const char* a, bpf_u_int32* b, bpf_u_int32* c, char* d) { - if (load_wpcap() != 0) { + if (load_pcap() != 0) { return p_pcap_lookupnet(a, b, c, d); } else { return 0; @@ -979,15 +1022,16 @@ int pcap_lookupnet(const char* a, bpf_u_int32* b, bpf_u_int32* c, char* d) { } pcap_t* pcap_open_live(const char* a, int b, int c, int d, char* e) { - if (load_wpcap() != 0) { + if (load_pcap() != 0) { return p_pcap_open_live(a, b, c, d, e); } else { return (pcap_t*) 0; } } +#ifdef _WIN32 int pcap_setmintocopy(pcap_t* a, int b) { - if (load_wpcap() != 0) { + if (load_pcap() != 0) { return p_pcap_setmintocopy(a, b); } else { return 0; @@ -995,15 +1039,25 @@ int pcap_setmintocopy(pcap_t* a, int b) { } HANDLE pcap_getevent(pcap_t* a) { - if (load_wpcap() != 0) { + if (load_pcap() != 0) { return p_pcap_getevent(a); } else { return (HANDLE) 0; } } +#else +int pcap_get_selectable_fd(pcap_t* a) { + if (load_pcap() != 0) { + return p_pcap_get_selectable_fd(a); + } else { + return 0; + } +} +#endif + int pcap_sendpacket(pcap_t* a, const u_char* b, int c) { - if (load_wpcap() != 0) { + if (load_pcap() != 0) { return p_pcap_sendpacket(a, b, c); } else { return 0; @@ -1011,7 +1065,7 @@ int pcap_sendpacket(pcap_t* a, const u_char* b, int c) { } int pcap_setfilter(pcap_t* a, struct bpf_program* b) { - if (load_wpcap() != 0) { + if (load_pcap() != 0) { return p_pcap_setfilter(a, b); } else { return 0; diff --git a/sim_ether.h b/sim_ether.h index 1478c40c..2314e835 100644 --- a/sim_ether.h +++ b/sim_ether.h @@ -28,6 +28,7 @@ Modification history: + 17-Nov-11 MP Added dynamic loading of libpcap on *nix platforms 30-Oct-11 MP Added support for vde (Virtual Distributed Ethernet) networking 18-Apr-11 MP Fixed race condition with self loopback packets in multithreaded environments @@ -98,6 +99,15 @@ #endif #endif /* USE_READER_THREAD */ +/* give priority to USE_NETWORK over USE_SHARED */ +#if defined(USE_NETWORK) && defined(USE_SHARED) +#undef USE_SHARED +#endif +/* USE_SHARED only works on Windows or if HAVE_DLOPEN */ +#if defined(USE_SHARED) && !defined(_WIN32) && !defined(HAVE_DLOPEN) +#undef USE_SHARED +#endif + /* 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 From 2793d49bf9460ac602aad12ab3c2b8ae5e798235 Mon Sep 17 00:00:00 2001 From: Mark Pizzolato Date: Thu, 17 Nov 2011 11:29:13 -0800 Subject: [PATCH 6/8] Cleanup function prototypes for consistency with newer versions of WinPcap and libpcap. --- Visual Studio Projects/0ReadMe_Projects.txt | 27 +++++++++++++++++---- sim_ether.c | 16 ++++++------ 2 files changed, 30 insertions(+), 13 deletions(-) diff --git a/Visual Studio Projects/0ReadMe_Projects.txt b/Visual Studio Projects/0ReadMe_Projects.txt index fa304799..19baa7c6 100644 --- a/Visual Studio Projects/0ReadMe_Projects.txt +++ b/Visual Studio Projects/0ReadMe_Projects.txt @@ -1,4 +1,11 @@ -This dirctory contains a set of Visual Studio 2008 build projects for the current simh code base. When used (with Visual Studio Express 2008 or Visual Studio Express 2010) it populates a directory tree under the BIN directory of the Simh distribution for temporary build files and produces resulting executables in the BIN/NT/Win32-Debug or BIN/NT/Win32-Release directories (depending on whether you target a Debug or Release build). It expects that a winpcap developer pack zip file is expanded in a directory parallel to the simh directory. +This dirctory contains a set of Visual Studio 2008 build projects for the +current simh code base. When used (with Visual Studio Express 2008 or +Visual Studio Express 2010) it populates a directory tree under the BIN +directory of the Simh distribution for temporary build files and produces +resulting executables in the BIN/NT/Win32-Debug or BIN/NT/Win32-Release +directories (depending on whether you target a Debug or Release build). +It expects that a winpcap developer pack zip file is expanded in a directory +parallel to the simh directory. For Example, the directory structure should look like: @@ -13,8 +20,10 @@ For Example, the directory structure should look like: The winpcap developer pack can be found at: http://www.winpcap.org/devel.htm +The latest version of the WinPcap developer's pack is Version 4.1.2 -Some features can be enabled if the pthreads API is available and contained also in a parallel place in the directory structure. +Some features can be enabled if the pthreads API is available and contained +also in a parallel place in the directory structure. .../simh/pthreads/Pre-built.2/include/include/pthreads.h @@ -24,10 +33,18 @@ To install pthreads API, create the directory: .../simh/pthreads/ -download the file: ftp://sourceware.org/pub/pthreads-win32/pthreads-w32-2-8-0-release.exe +download the file: + ftp://sourceware.org/pub/pthreads-win32/pthreads-w32-2-8-0-release.exe to that directory and execute it. Click on the Extract button. -Once installed, When running a simulator with pthreads support enabled, you will need a copy of the DLL file (simh\pthreads\Pre-built.2\lib\pthreadVC2.dll) to exist in either the %windir%\System32 directory or your working directory while running a simh simulator. The default working directory for included project files is the "Visual Studio Projects" directory. +Once installed, When running a simulator with pthreads support enabled, you +will need a copy of the DLL file (simh\pthreads\Pre-built.2\lib\pthreadVC2.dll) +to exist in either the %windir%\System32 directory (or %windir%\SysWOW64 on +x64 Windows environments) or your working directory while running a simh +simulator. The default working directory for included project files is the +"Visual Studio Projects" directory. -Only network devices are capable of using pthreads to enhance their performance. Build the desire simulator with USE_READER_THREAD defined. The relevant simulators which have network support are VAX, VAX780, PDP11 and PDP10. +Only network devices are capable of using pthreads to enhance their +performance. Build the desire simulator with USE_READER_THREAD defined. The +relevant simulators which have network support are VAX, VAX780 and PDP11. diff --git a/sim_ether.c b/sim_ether.c index 08abbad9..741bb917 100644 --- a/sim_ether.c +++ b/sim_ether.c @@ -849,7 +849,7 @@ static char* no_pcap = /* define pointers to pcap functions needed */ static void (*p_pcap_close) (pcap_t *); -static int (*p_pcap_compile) (pcap_t *, struct bpf_program *, char *, int, bpf_u_int32); +static int (*p_pcap_compile) (pcap_t *, struct bpf_program *, const char *, int, bpf_u_int32); static int (*p_pcap_datalink) (pcap_t *); static int (*p_pcap_dispatch) (pcap_t *, int, pcap_handler, u_char *); static int (*p_pcap_findalldevs) (pcap_if_t **, char *); @@ -861,8 +861,8 @@ static pcap_t* (*p_pcap_open_live) (const char *, int, int, int, char *); #ifdef _WIN32 static int (*p_pcap_setmintocopy) (pcap_t* handle, int); static HANDLE (*p_pcap_getevent) (pcap_t *); -#else -static int (*p_pcap_get_selectable_fd) (pcap_t *); +#else +static int (*p_pcap_get_selectable_fd) (pcap_t *); #endif static int (*p_pcap_sendpacket) (pcap_t* handle, const u_char* msg, int len); static int (*p_pcap_setfilter) (pcap_t *, struct bpf_program *); @@ -905,10 +905,10 @@ int load_pcap(void) { #endif printf (msg, lib_name); - printf (msg2); + printf ("%s", msg2); if (sim_log) { fprintf (sim_log, msg, lib_name); - fprintf (sim_log, msg2); + fprintf (sim_log, "%s", msg2); } lib_loaded = 2; break; @@ -959,7 +959,7 @@ void pcap_close(pcap_t* a) { } } -int pcap_compile(pcap_t* a, struct bpf_program* b, char* c, int d, bpf_u_int32 e) { +int pcap_compile(pcap_t* a, struct bpf_program* b, const char* c, int d, bpf_u_int32 e) { if (load_pcap() != 0) { return p_pcap_compile(a, b, c, d, e); } else { @@ -1047,13 +1047,13 @@ HANDLE pcap_getevent(pcap_t* a) { } #else -int pcap_get_selectable_fd(pcap_t* a) { +int pcap_get_selectable_fd(pcap_t* a) { if (load_pcap() != 0) { return p_pcap_get_selectable_fd(a); } else { return 0; } -} +} #endif int pcap_sendpacket(pcap_t* a, const u_char* b, int c) { From 934836483b2cebd4547e9fe19a5098d8d8e95525 Mon Sep 17 00:00:00 2001 From: Mark Pizzolato Date: Thu, 17 Nov 2011 11:59:50 -0800 Subject: [PATCH 7/8] Added pcap_fileno to the dynamically loaded libpcap entry points since it is needed by OS X. --- makefile | 2 +- sim_ether.c | 10 ++++++++++ 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/makefile b/makefile index 6d4c357f..cd2d0194 100644 --- a/makefile +++ b/makefile @@ -117,7 +117,7 @@ ifeq ($(WIN32),) #*nix Environments (&& cygwin) $(info using libpcap: $(call find_lib,pcap) $(call find_include,pcap)) else # default build uses dynamic libpcap NETWORK_CCDEFS = -DUSE_SHARED - $(info using libpcap: $$(call find_include,pcap)) + $(info using libpcap: $(call find_include,pcap)) endif else NETWORK_CCDEFS = -DUSE_SHARED diff --git a/sim_ether.c b/sim_ether.c index 741bb917..ebcaa0bb 100644 --- a/sim_ether.c +++ b/sim_ether.c @@ -863,6 +863,7 @@ static int (*p_pcap_setmintocopy) (pcap_t* handle, int); static HANDLE (*p_pcap_getevent) (pcap_t *); #else static int (*p_pcap_get_selectable_fd) (pcap_t *); +static int (*p_pcap_fileno) (pcap_t *); #endif static int (*p_pcap_sendpacket) (pcap_t* handle, const u_char* msg, int len); static int (*p_pcap_setfilter) (pcap_t *, struct bpf_program *); @@ -933,6 +934,7 @@ int load_pcap(void) { load_function("pcap_getevent", (void**) &p_pcap_getevent); #else load_function("pcap_get_selectable_fd", (void**) &p_pcap_get_selectable_fd); + load_function("pcap_fileno", (void**) &p_pcap_fileno); #endif load_function("pcap_sendpacket", (void**) &p_pcap_sendpacket); load_function("pcap_setfilter", (void**) &p_pcap_setfilter); @@ -1054,6 +1056,14 @@ int pcap_get_selectable_fd(pcap_t* a) { return 0; } } + +int pcap_fileno(pcap_t * a) { + if (load_pcap() != 0) { + return p_pcap_fileno(a); + } else { + return 0; + } +} #endif int pcap_sendpacket(pcap_t* a, const u_char* b, int c) { From db7e04e0dfb9cebbf4ea1afa6b5aa93f2d8d0d3b Mon Sep 17 00:00:00 2001 From: Mark Pizzolato Date: Thu, 17 Nov 2011 13:06:36 -0800 Subject: [PATCH 8/8] Cleanup of readline and static libpcap support after multi-platform testing. --- makefile | 6 ++++-- scp.c | 1 + 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/makefile b/makefile index cd2d0194..34f0246d 100644 --- a/makefile +++ b/makefile @@ -121,7 +121,7 @@ ifeq ($(WIN32),) #*nix Environments (&& cygwin) endif else NETWORK_CCDEFS = -DUSE_SHARED - $(info using libpcap: $$(call find_include,pcap)) + $(info using libpcap: $(call find_include,pcap)) endif endif ifneq (,$(call find_lib,vdeplug)) @@ -149,14 +149,16 @@ ifeq ($(WIN32),) #*nix Environments (&& cygwin) # Look for package built from tcpdump.org sources with default install target LIBPATH += /usr/local/lib INCPATH += /usr/local/include + LIBEXTSAVE = $(LIBEXT) LIBEXT = a ifneq (,$(call find_lib,pcap)) ifneq (,$(call find_include,pcap)) - NETWORK_OPT = -DUSE_NETWORK -isystem /usr/local/include /usr/local/lib/libpcap.a + NETWORK_OPT := -DUSE_NETWORK -isystem $(dir $(call find_include,pcap)) $(call find_lib,pcap) $(info using libpcap: $(call find_lib,pcap) $(call find_include,pcap)) else $(error using libpcap: $(call find_lib,pcap) missing pcap.h) endif + LIBEXT = $(LIBEXTSAVE) else $(error missing libpcap) endif diff --git a/scp.c b/scp.c index 3920db7d..b70905be 100644 --- a/scp.c +++ b/scp.c @@ -3852,6 +3852,7 @@ if (!initialized) { #define __STR_QUOTE(tok) #tok #define __STR(tok) __STR_QUOTE(tok) handle = dlopen("libncurses." __STR(HAVE_DLOPEN), RTLD_NOW|RTLD_GLOBAL); + handle = dlopen("libcurses." __STR(HAVE_DLOPEN), RTLD_NOW|RTLD_GLOBAL); handle = dlopen("libreadline." __STR(HAVE_DLOPEN), RTLD_NOW|RTLD_GLOBAL); if (handle) { p_readline = dlsym(handle, "readline");