From 8e76a8d0818bf72c665cfc000e79b4b4f6ce0a44 Mon Sep 17 00:00:00 2001 From: Mark Pizzolato Date: Fri, 2 Mar 2012 13:27:20 -0800 Subject: [PATCH] Fixed cygwin build and execution issue, mostly from Tony Nicholson Fixed OS/X build issues from Tony Nickolson Fixed OS/X tap networking startup Added cygwin host NIC hardware address determination Made *nix host NIC hardware address determination more robust --- 0readme_ethernet.txt | 43 ++++++++---- makefile | 144 +++++++++++++++++++++++-------------- sim_ether.c | 164 ++++++++++++++++++++++++++++++------------- sim_ether.h | 16 ++++- 4 files changed, 249 insertions(+), 118 deletions(-) diff --git a/0readme_ethernet.txt b/0readme_ethernet.txt index 6916cfac..841079e2 100644 --- a/0readme_ethernet.txt +++ b/0readme_ethernet.txt @@ -129,17 +129,17 @@ OSX (Snow Leopard) based internal network so a host and guest can communicate directly. Download the install package from: - http://sourceforge.net/projects/tuntaposx/files/tuntap/20090913/tuntap_20090913.tar.gz + http://sourceforge.net/projects/tuntaposx/files/tuntap/20111101/tuntap_20111101.tar.gz Expand the tarball to a directory. - Invoke the package installer tuntap_20090913.pkg + Invoke the package installer tuntap_20111101.pkg Click through the various prompts accepting things and eventually installing the package. # Build and Run simulator and: sim> attach xq tap:tap0 sim> ! ifconfig tap0 192.168.6.1 netmask 255.255.255.0 - Simulated system uses IP address 192.168.6.2 and host uses 192.167.6.1 + Simulated system uses IP address 192.168.6.2 and host uses 192.168.6.1 and things work. You must run as root for this to work. @@ -180,7 +180,8 @@ Windows notes: and the user must be an Administrator on the machine to do so. If you need to run as an unprivileged user, you must set the "npf" driver to autostart. Current WinPcap installers provide an option to configure this at - installation time. + installation time, so if that choice is made, then there is no need for + administrator privileged to run simulators with network support. Building on Windows: @@ -189,10 +190,10 @@ Building on Windows: Express 2008 or 2010 interactive development environments, read the file ".\Visual Studio Projects\0ReadMe_Projects.txt" for details about the required dependencies. Alternatively, you can build simh with networking - support using the MinGW GCC compiler environment. Both the Visual C++ - and MinGW build environments require WinPcap and Posix packages being - available. These should be located in a directory structure parallel to - the current simulator source directory. + support using the MinGW GCC compiler environment or the cygwin environment. + Each of these Visual C++, MinGW and cygwin build environments require + WinPcap and Posix packages being available. These should be located in a + directory structure parallel to the current simulator source directory. For Example, the directory structure should look like: @@ -243,7 +244,9 @@ for details. packets through the driver. a) For Windows systems this means having administrator privileges to start the "npf" driver. The current WinPcap installer offers an - option to autostart the "npf" driver when the system boots. + option to autostart the "npf" driver when the system boots. + Starting the "npf" driver at boot time means that simulators do + not need to run with administrator privileges. b) For more recent Linux systems, The concepts leveraging "Filesystem Capabilities" can be used to specifically grant the simh binary the needed privileges to access the network. The article at: @@ -264,7 +267,7 @@ for details. (possibly at system boot time), using the TAP devices can be done without root privileges. -Building on Linux, {Free|Net|Open}BSD, OS/X, Un*x: +Building on Linux, {Free|Net|Open}BSD, OS/X, Solaris, other *nix: 1. Get/make/install the libpcap-dev package for your operating system. Sources: All : http://www.tcpdump.org/ @@ -290,10 +293,16 @@ Building on Linux, {Free|Net|Open}BSD, OS/X, Un*x: 2. If you install the vendor supplied libpcap-dev package then the simh makefile will automatically use the vendor supplied library without any additional arguments. If you have downloaded and built libpcap from - www.tcpdump.org, then you can force its use during a build by typing - 'make USE_NETWORK=1' + www.tcpdump.org, then the existing makefile will detect that this is + the case and try to use that. - 3. Build it! + 3. The makefile defaults to building simulators with network support which + dynamically load the libpcap library. This means that the same simulator + binaries will run on any system whether or not libpcap is installed. If + you want to force direct libpcap linking during a build you do so by + typing 'make USE_NETWORK=1' + + 4. Build it! ------------------------------------------------------------------------------- @@ -404,6 +413,14 @@ Dave Change Log =============================================================================== + 01-Mar-12 AGN Added support for building using Cygwin on Windows + 01-Mar-12 MP Made host NIC address detection more robust on *nix platforms + and mad it work when compiling under Cygwin + 29-Feb-12 MP Fixed MAC Address Conflict detection support + 28-Feb-12 MP Fixed overrun bug in eth_devices which caused SEGFAULTs + 28-Feb-12 MP Fixed internal loopback processing to only respond to loopback + packets addressed to the physical MAC or appropriate Multicast + or Broadcast addresses. 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 diff --git a/makefile b/makefile index a211e432..4ac68fbb 100644 --- a/makefile +++ b/makefile @@ -1,5 +1,5 @@ # -# This GMU make makefile has been tested on: +# This GNU make makefile has been tested on: # Linux (x86 & Sparc) # OS X # Solaris (x86 & Sparc) @@ -12,9 +12,9 @@ # 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. -# +# 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=1 on the command line. @@ -29,15 +29,21 @@ ifeq ($(WIN32),) #*nix Environments (&& cygwin) GCC = gcc endif OSTYPE = $(shell uname) + # OSNAME is used in messages to indicate the source of libpcap components OSNAME = $(OSTYPE) ifeq (SunOS,$(OSTYPE)) TEST = /bin/test else TEST = test endif + ifeq (CYGWIN,$(findstring CYGWIN,$(OSTYPE))) # uname returns CYGWIN_NT-n.n-ver + OSTYPE = cygwin + OSNAME = windows-build + endif + PCAPLIB = pcap ifeq (agcc,$(findstring agcc,$(GCC))) # Android target build? OS_CCDEFS = -D_GNU_SOURCE -DSIM_ASYNCH_IO - OS_LDFLAGS = -lm + OS_LDFLAGS = -lm else # Non-Android Builds INCPATH:=/usr/include LIBPATH:=/usr/lib @@ -64,26 +70,36 @@ ifeq ($(WIN32),) #*nix Environments (&& cygwin) OS_LDFLAGS += -L/opt/sfw/lib -R/opt/sfw/lib endif else - LDSEARCH :=$(shell ldconfig -r | grep 'search directories' | awk '{print $$3}' | sed 's/:/ /g') - ifneq (,$(LDSEARCH)) - LIBPATH := $(LDSEARCH) - endif - 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 - ifneq (,$(findstring NetBSD,$(OSTYPE))$(findstring FreeBSD,$(OSTYPE))) - LIBEXT = so - else + ifeq (cygwin,$(OSTYPE)) + # use 0readme_ethernet.txt documented Windows pcap build components + INCPATH += ../windows-build/winpcap/WpdPack/include + LIBPATH += ../windows-build/winpcap/WpdPack/lib + PCAPLIB = wpcap LIBEXT = a + else + LDSEARCH :=$(shell ldconfig -r | grep 'search directories' | awk '{print $$3}' | sed 's/:/ /g') + ifneq (,$(LDSEARCH)) + LIBPATH := $(LDSEARCH) + endif + 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 + ifneq (,$(findstring NetBSD,$(OSTYPE))$(findstring FreeBSD,$(OSTYPE))) + LIBEXT = so + else + LIBEXT = a + endif endif endif endif endif endif $(info lib paths are: $(LIBPATH)) - ifeq (cygwin,$(findstring cygwin,$(OSTYPE))) - OS_CCDEFS += -O2 + ifeq (cygwin,$(OSTYPE)) + # gcc optimization seems to be broken in Cygwin's gcc 4.5.3 + # (vax780 won't boot VMS 4.7 unless -O2 removed) + #OS_CCDEFS += -O2 endif 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)))) @@ -92,13 +108,13 @@ ifeq ($(WIN32),) #*nix Environments (&& cygwin) $(info using libm: $(call find_lib,m)) endif ifneq (,$(call find_lib,rt)) - OS_LDFLAGS += -lrt + OS_LDFLAGS += -lrt $(info using librt: $(call find_lib,rt)) endif ifneq (,$(call find_lib,pthread)) ifneq (,$(call find_include,pthread)) - OS_CCDEFS += -DSIM_ASYNCH_IO -DUSE_READER_THREAD - OS_LDFLAGS += -lpthread + OS_CCDEFS += -DSIM_ASYNCH_IO -DUSE_READER_THREAD + OS_LDFLAGS += -lpthread $(info using libpthread: $(call find_lib,pthread) $(call find_include,pthread)) endif endif @@ -131,43 +147,61 @@ ifeq ($(WIN32),) #*nix Environments (&& cygwin) endif ifneq (,$(NETWORK_USEFUL)) ifneq (,$(call find_include,pcap)) - ifneq (,$(call find_lib,pcap)) + ifneq (,$(call find_lib,$(PCAPLIB))) 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)) + NETWORK_CCDEFS = -DUSE_NETWORK -I$(dir $(call find_include,pcap)) + ifeq (cygwin,$(OSTYPE)) + # cygwin has no ldconfig so explicitly specify pcap object library + NETWORK_LDFLAGS = -L$(dir $(call find_lib,$(PCAPLIB))) -Wl,-R,$(dir $(call find_lib,$(PCAPLIB))) -l$(PCAPLIB) + else + NETWORK_LDFLAGS = -l$(PCAPLIB) + endif + $(info using libpcap: $(call find_lib,$(PCAPLIB)) $(call find_include,pcap)) else # default build uses dynamic libpcap - NETWORK_CCDEFS = -DUSE_SHARED + NETWORK_CCDEFS = -DUSE_SHARED -I$(dir $(call find_include,pcap)) $(info using libpcap: $(call find_include,pcap)) endif + $(info ***) $(info *** $(BUILD_SINGLE)Simulator$(BUILD_MULTIPLE) being built with networking support using) - $(info *** $(OSTYPE) provided libpcap components) + $(info *** $(OSNAME) provided libpcap components) + $(info ***) else - NETWORK_CCDEFS = -DUSE_SHARED + NETWORK_CCDEFS = -DUSE_SHARED -I$(dir $(call find_include,pcap)) $(info using libpcap: $(call find_include,pcap)) + $(info ***) $(info *** $(BUILD_SINGLE)Simulator$(BUILD_MULTIPLE) being built with networking support using) - $(info *** $(OSTYPE) provided libpcap components) + $(info *** $(OSNAME) provided libpcap components) + $(info ***) endif else - # Look for package built from tcpdump.org sources with default install target + # Look for package built from tcpdump.org sources with default install target (or cygwin winpcap) LIBPATH += /usr/local/lib INCPATH += /usr/local/include LIBEXTSAVE := $(LIBEXT) LIBEXT = a - ifneq (,$(call find_lib,pcap)) + ifneq (,$(call find_lib,$(PCAPLIB))) ifneq (,$(call find_include,pcap)) - NETWORK_CCDEFS := -DUSE_NETWORK -isystem $(dir $(call find_include,pcap)) $(call find_lib,pcap) - $(info using libpcap: $(call find_lib,pcap) $(call find_include,pcap)) - $(info *** Warning ***) - $(info *** Warning *** $(BUILD_SINGLE)Simulator$(BUILD_MULTIPLE) being built with networking support using) - $(info *** Warning *** libpcap components from www.tcpdump.org.) - $(info *** Warning *** Some users have had problems using the www.tcpdump.org libpcap) - $(info *** Warning *** components for simh networking. For best results, with) - $(info *** Warning *** simh networking, it is recommended that you install the) - $(info *** Warning *** libpcap-dev package from your $(OSTYPE) distribution) - $(info *** Warning ***) + $(info using libpcap: $(call find_lib,$(PCAPLIB)) $(call find_include,pcap)) + ifeq (cygwin,$(OSTYPE)) + NETWORK_CCDEFS = -DUSE_NETWORK -I$(dir $(call find_include,pcap)) + NETWORK_LDFLAGS = -L$(dir $(call find_lib,$(PCAPLIB))) -Wl,-R,$(dir $(call find_lib,$(PCAPLIB))) -l$(PCAPLIB) + $(info ***) + $(info *** $(BUILD_SINGLE)Simulator$(BUILD_MULTIPLE) being built with networking support using) + $(info *** libpcap components located in the cygwin directories.) + $(info ***) + else + NETWORK_CCDEFS := -DUSE_NETWORK -isystem $(dir $(call find_include,pcap)) $(call find_lib,$(PCAPLIB)) + $(info *** Warning ***) + $(info *** Warning *** $(BUILD_SINGLE)Simulator$(BUILD_MULTIPLE) being built with networking support using) + $(info *** Warning *** libpcap components from www.tcpdump.org.) + $(info *** Warning *** Some users have had problems using the www.tcpdump.org libpcap) + $(info *** Warning *** components for simh networking. For best results, with) + $(info *** Warning *** simh networking, it is recommended that you install the) + $(info *** Warning *** libpcap-dev package from your $(OSTYPE) distribution) + $(info *** Warning ***) + endif else - $(error using libpcap: $(call find_lib,pcap) missing pcap.h) + $(error using libpcap: $(call find_lib,$(PCAPLIB)) missing pcap.h) endif LIBEXT = $(LIBEXTSAVE) endif @@ -197,8 +231,9 @@ ifeq ($(WIN32),) #*nix Environments (&& cygwin) $(info *** Warning ***) $(info *** Warning *** $(BUILD_SINGLE)Simulator$(BUILD_MULTIPLE) are being built WITHOUT networking support) $(info *** Warning ***) - $(info *** Warning *** To build simulator(s) with networking support you should install) - $(info *** Warning *** the libpcap-dev package from your $(OSTYPE) distribution) + $(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 *** needed libpcap components for your $(OSTYPE) platform) $(info *** Warning ***) endif NETWORK_OPT = $(NETWORK_CCDEFS) @@ -223,16 +258,16 @@ else endif ifeq (pcap,$(shell if exist ..\windows-build\winpcap\Wpdpack\include\pcap.h echo pcap)) PCAP_CCDEFS = -I../windows-build/winpcap/Wpdpack/include -I$(GCC_Path)..\include\ddk -DUSE_SHARED - NETWORK_LDFLAGS = + NETWORK_LDFLAGS = NETWORK_OPT = -DUSE_SHARED else ifeq (pcap,$(shell if exist $(dir $(GCC_Path))..\include\pcap.h echo pcap)) - PCAP_CCDEFS = -DUSE_SHARED -I$(GCC_Path)..\include\ddk - NETWORK_LDFLAGS = + PCAP_CCDEFS = -DUSE_SHARED -I$(GCC_Path)..\include\ddk + NETWORK_LDFLAGS = NETWORK_OPT = -DUSE_SHARED endif endif - OS_CCDEFS = -fms-extensions -O2 $(PTHREADS_CCDEFS) $(PCAP_CCDEFS) + OS_CCDEFS = -fms-extensions -O2 $(PTHREADS_CCDEFS) $(PCAP_CCDEFS) OS_LDFLAGS = -lm -lwsock32 -lwinmm $(PTHREADS_LDFLAGS) EXE = .exe ifneq (binexists,$(shell if exist BIN echo binexists)) @@ -247,10 +282,12 @@ ifneq ($(DONT_USE_ROMS),) else BUILD_ROMS = ${BIN}BuildROMs${EXE} endif - +ifneq ($(DONT_USE_READER_THREAD),) + NETWORK_OPT += -DDONT_USE_READER_THREAD +endif CC = $(GCC) -std=c99 -U__STRICT_ANSI__ -g -I . $(OS_CCDEFS) $(ROMS_OPT) -LDFLAGS = $(OS_LDFLAGS) $(NETWORK_LDFLAGS) +LDFLAGS = $(OS_LDFLAGS) $(NETWORK_LDFLAGS) # # Common Libraries @@ -499,7 +536,7 @@ else if exist BIN rmdir BIN endif -${BIN}BuildROMs${EXE} : +${BIN}BuildROMs${EXE} : ${MKDIRBIN} ifeq (agcc,$(findstring agcc,$(firstword $(CC)))) gcc $(wordlist 2,1000,${CC}) sim_BuildROMs.c -o $@ @@ -509,6 +546,9 @@ endif ifeq ($(WIN32),) $@ ${RM} $@ + ifeq (Darwin,$(OSTYPE)) # remove Xcode's debugging symbols folder too + ${RM} -rf $@.dSYM + endif else $(@D)\$(@F) del $(@D)\$(@F) @@ -639,7 +679,7 @@ ${BIN}altair${EXE} : ${ALTAIR} ${SIM} altairz80 : ${BIN}altairz80${EXE} -${BIN}altairz80${EXE} : ${ALTAIRZ80} ${SIM} +${BIN}altairz80${EXE} : ${ALTAIRZ80} ${SIM} ${MKDIRBIN} ${CC} ${ALTAIRZ80} ${SIM} ${ALTAIRZ80_OPT} -o $@ ${LDFLAGS} diff --git a/sim_ether.c b/sim_ether.c index 3cc40ace..78cf7fc4 100644 --- a/sim_ether.c +++ b/sim_ether.c @@ -129,7 +129,7 @@ likely run faster (given that modern host CPUs are multi-core and have someplace to do this work in parallel). MUST_DO_SELECT - Specifies that, when USE_READER_THREAD is active, - select() should be used to determin when available + select() should be used to determine when available packets are ready for reading. Otherwise, we depend on the libpcap/kernel packet timeout specified on pcap_open_live. If USE_READER_THREAD is not set, then @@ -163,6 +163,12 @@ Modification history: + 01-Mar-12 MP Made host NIC address determination on *nix platforms more + robust. + 01-Mar-12 MP Added host NIC address determination work when building + under Cygwin + 01-Mar-12 AGN Add conditionals for Cygwin dynamic loading of wpcap.dll + 01-Mar-12 AGN Specify the full /usr/lib for dlopen under Apple Mac OS X. 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 @@ -193,11 +199,11 @@ network traffic from the host and/or from hosts on the LAN. These new TOE features are: LSO (Large Send Offload) and Jumbo packet fragmentation support. These features allow a simulated network - device to suuport traffic when a host leverages a NIC's Large + device to support traffic when a host leverages a NIC's Large Send Offload capabilities to fregment and/or segment outgoing network traffic. Additionally a simulated network device can reasonably exist on a LAN which is configured to use Jumbo frames. - 21-May-10 MP Added functionslity to fixup IP header checksums to accomodate + 21-May-10 MP Added functionality to fixup IP header checksums to accomodate packets from a host with a NIC which has TOE (TCP Offload Engine) enabled which is expected to implement the checksum computations in hardware. Since we catch packets before they arrive at the @@ -817,14 +823,14 @@ void eth_show_dev (FILE* st, ETH_DEV* dev) #include #endif -#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 +#if defined(USE_SHARED) && (defined(_WIN32) || defined(HAVE_DLOPEN)) +/* Dynamic DLL loading technique and modified source comes from + Etherial/WireShark capture_pcap.c */ + /* Dynamic DLL load variables */ #ifdef _WIN32 static HINSTANCE hLib = 0; /* handle to DLL */ @@ -833,15 +839,17 @@ 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 +#if defined(_WIN32) || defined(__CYGWIN__) "wpcap.dll"; +#elif defined(__APPLE__) + "/usr/lib/libpcap.A.dylib"; #else #define __STR_QUOTE(tok) #tok #define __STR(tok) __STR_QUOTE(tok) "libpcap." __STR(HAVE_DLOPEN); #endif static char* no_pcap = -#ifdef _WIN32 +#if defined(_WIN32) || defined(__CYGWIN__) "wpcap load failure"; #else "libpcap load failure"; @@ -862,7 +870,9 @@ static pcap_t* (*p_pcap_open_live) (const char *, int, int, int, char *); static int (*p_pcap_setmintocopy) (pcap_t* handle, int); static HANDLE (*p_pcap_getevent) (pcap_t *); #else +#ifdef MUST_DO_SELECT static int (*p_pcap_get_selectable_fd) (pcap_t *); +#endif static int (*p_pcap_fileno) (pcap_t *); #endif static int (*p_pcap_sendpacket) (pcap_t* handle, const u_char* msg, int len); @@ -933,7 +943,9 @@ int load_pcap(void) { load_function("pcap_setmintocopy", (void**) &p_pcap_setmintocopy); load_function("pcap_getevent", (void**) &p_pcap_getevent); #else +#ifdef MUST_DO_SELECT load_function("pcap_get_selectable_fd", (void**) &p_pcap_get_selectable_fd); +#endif load_function("pcap_fileno", (void**) &p_pcap_fileno); #endif load_function("pcap_sendpacket", (void**) &p_pcap_sendpacket); @@ -1054,6 +1066,7 @@ HANDLE pcap_getevent(pcap_t* a) { } #else +#ifdef MUST_DO_SELECT int pcap_get_selectable_fd(pcap_t* a) { if (load_pcap() != 0) { return p_pcap_get_selectable_fd(a); @@ -1061,6 +1074,7 @@ int pcap_get_selectable_fd(pcap_t* a) { return 0; } } +#endif int pcap_fileno(pcap_t * a) { if (load_pcap() != 0) { @@ -1112,32 +1126,57 @@ int pcap_sendpacket(pcap_t* handle, const u_char* msg, int len) } #endif /* !HAS_PCAP_SENDPACKET */ -#ifdef _WIN32 -#include -#include +#if defined(_WIN32) || defined(__CYGWIN__) +/* extracted from WinPcap's Packet32.h */ +struct _PACKET_OID_DATA { + uint32 Oid; ///< OID code. See the Microsoft DDK documentation or the file ntddndis.h + ///< for a complete list of valid codes. + uint32 Length; ///< Length of the data field + uint8 Data[1]; ///< variable-lenght field that contains the information passed to or received + ///< from the adapter. +}; +typedef struct _PACKET_OID_DATA PACKET_OID_DATA, *PPACKET_OID_DATA; +typedef void **LPADAPTER; +#define OID_802_3_CURRENT_ADDRESS 0x01010102 /* Extracted from ntddmdis.h */ -static int pcap_mac_if_win32(char *AdapterName, UCHAR MACAddress[6]) +static int pcap_mac_if_win32(char *AdapterName, unsigned char MACAddress[6]) { LPADAPTER lpAdapter; PPACKET_OID_DATA OidData; - BOOLEAN Status; + int Status; int ReturnValue; +#ifdef _WIN32 HINSTANCE hDll; /* handle to DLL */ - LPADAPTER (*p_PacketOpenAdapter)(PCHAR AdapterName); - VOID (*p_PacketCloseAdapter)(LPADAPTER lpAdapter); - BOOLEAN (*p_PacketRequest)(LPADAPTER AdapterObject,BOOLEAN Set,PPACKET_OID_DATA OidData); +#else + static void *hDll = NULL; /* handle to Library */ + typedef int BOOLEAN; +#endif + LPADAPTER (*p_PacketOpenAdapter)(char *AdapterName); + void (*p_PacketCloseAdapter)(LPADAPTER lpAdapter); + int (*p_PacketRequest)(LPADAPTER AdapterObject,BOOLEAN Set,PPACKET_OID_DATA OidData); - hDll = LoadLibrary(TEXT("packet.dll")); +#ifdef _WIN32 + hDll = LoadLibraryA("packet.dll"); p_PacketOpenAdapter = (void *)GetProcAddress(hDll, "PacketOpenAdapter"); p_PacketCloseAdapter = (void *)GetProcAddress(hDll, "PacketCloseAdapter"); p_PacketRequest = (void *)GetProcAddress(hDll, "PacketRequest"); +#else + hDll = dlopen("packet.dll", RTLD_NOW); + p_PacketOpenAdapter = (void *)dlsym(hDll, "PacketOpenAdapter"); + p_PacketCloseAdapter = (void *)dlsym(hDll, "PacketCloseAdapter"); + p_PacketRequest = (void *)dlsym(hDll, "PacketRequest"); +#endif /* Open the selected adapter */ lpAdapter = p_PacketOpenAdapter(AdapterName); - if (!lpAdapter || (lpAdapter->hFile == INVALID_HANDLE_VALUE)) { - FreeLibrary(hDll); + if (!lpAdapter || (*lpAdapter == (void *)-1)) { +#ifdef _WIN32 + FreeLibrary(hDll); +#else + dlclose(hDll); +#endif return -1; } @@ -1146,7 +1185,11 @@ static int pcap_mac_if_win32(char *AdapterName, UCHAR MACAddress[6]) OidData = malloc(6 + sizeof(PACKET_OID_DATA)); if (OidData == NULL) { p_PacketCloseAdapter(lpAdapter); +#ifdef _WIN32 FreeLibrary(hDll); +#else + dlclose(hDll); +#endif return -1; } @@ -1166,7 +1209,11 @@ static int pcap_mac_if_win32(char *AdapterName, UCHAR MACAddress[6]) free(OidData); p_PacketCloseAdapter(lpAdapter); +#ifdef _WIN32 FreeLibrary(hDll); +#else + dlclose(hDll); +#endif return ReturnValue; } #endif @@ -1175,44 +1222,55 @@ static void eth_get_nic_hw_addr(ETH_DEV* dev, char *devname) { memset(&dev->host_nic_phy_hw_addr, 0, sizeof(dev->host_nic_phy_hw_addr)); dev->have_host_nic_phy_addr = 0; -#ifdef _WIN32 - if (!pcap_mac_if_win32(devname, (UCHAR *)&dev->host_nic_phy_hw_addr)) +#if defined(_WIN32) || defined(__CYGWIN__) + if (!pcap_mac_if_win32(devname, dev->host_nic_phy_hw_addr)) dev->have_host_nic_phy_addr = 1; -#elif !defined (__VMS) +#elif !defined (__VMS) && !defined(__CYGWIN__) if (1) { char command[1024]; FILE *f; + int i; + char *patterns[] = { + "grep [0-9a-fA-F][0-9a-fA-F]:[0-9a-fA-F][0-9a-fA-F]:[0-9a-fA-F][0-9a-fA-F]:[0-9a-fA-F][0-9a-fA-F]:[0-9a-fA-F][0-9a-fA-F]:[0-9a-fA-F][0-9a-fA-F]", + "egrep [0-9a-fA-F]?[0-9a-fA-F]:[0-9a-fA-F]?[0-9a-fA-F]:[0-9a-fA-F]?[0-9a-fA-F]:[0-9a-fA-F]?[0-9a-fA-F]:[0-9a-fA-F]?[0-9a-fA-F]:[0-9a-fA-F]?[0-9a-fA-F]", + NULL}; if (0 == strncmp("vde:", devname, 4)) return; memset(command, 0, sizeof(command)); - snprintf(command, sizeof(command)-1, "ifconfig %s | grep [0-9a-fA-F][0-9a-fA-F]:[0-9a-fA-F][0-9a-fA-F]:[0-9a-fA-F][0-9a-fA-F]:[0-9a-fA-F][0-9a-fA-F]:[0-9a-fA-F][0-9a-fA-F]:[0-9a-fA-F][0-9a-fA-F] >NIC.hwaddr", devname); - system(command); - if (f = fopen("NIC.hwaddr", "r")) { - if (fgets(command, sizeof(command)-1, f)) { - char *p1, *p2; - - p1 = strchr(command, ':'); - while (p1) { - p2 = strchr(p1+1, ':'); - if (p2 == p1+3) { - int mac_bytes[6]; - if (6 == sscanf(p1-2, "%02x:%02x:%02x:%02x:%02x:%02x", &mac_bytes[0], &mac_bytes[1], &mac_bytes[2], &mac_bytes[3], &mac_bytes[4], &mac_bytes[5])) { - dev->host_nic_phy_hw_addr[0] = mac_bytes[0]; - dev->host_nic_phy_hw_addr[1] = mac_bytes[1]; - dev->host_nic_phy_hw_addr[2] = mac_bytes[2]; - dev->host_nic_phy_hw_addr[3] = mac_bytes[3]; - dev->host_nic_phy_hw_addr[4] = mac_bytes[4]; - dev->host_nic_phy_hw_addr[5] = mac_bytes[5]; - dev->have_host_nic_phy_addr = 1; + for (i=0; patterns[i] && (0 == dev->have_host_nic_phy_addr); ++i) { + snprintf(command, sizeof(command)-1, "ifconfig %s | %s >NIC.hwaddr", devname, patterns[i]); + system(command); + if (f = fopen("NIC.hwaddr", "r")) { + while (0 == dev->have_host_nic_phy_addr) { + if (fgets(command, sizeof(command)-1, f)) { + char *p1, *p2; + + p1 = strchr(command, ':'); + while (p1) { + p2 = strchr(p1+1, ':'); + if (p2 <= p1+3) { + int mac_bytes[6]; + if (6 == sscanf(p1-2, "%02x:%02x:%02x:%02x:%02x:%02x", &mac_bytes[0], &mac_bytes[1], &mac_bytes[2], &mac_bytes[3], &mac_bytes[4], &mac_bytes[5])) { + dev->host_nic_phy_hw_addr[0] = mac_bytes[0]; + dev->host_nic_phy_hw_addr[1] = mac_bytes[1]; + dev->host_nic_phy_hw_addr[2] = mac_bytes[2]; + dev->host_nic_phy_hw_addr[3] = mac_bytes[3]; + dev->host_nic_phy_hw_addr[4] = mac_bytes[4]; + dev->host_nic_phy_hw_addr[5] = mac_bytes[5]; + dev->have_host_nic_phy_addr = 1; + } + break; + } + p1 = p2; } - break; } - p1 = p2; + else + break; } + fclose(f); + remove("NIC.hwaddr"); } - fclose(f); - remove("NIC.hwaddr"); } } #endif @@ -1523,11 +1581,14 @@ if (0 == strncmp("tap:", savname, 4)) { memset (&ifr, 0, sizeof(ifr)); ifr.ifr_addr.sa_family = AF_INET; - strncpy(ifr.ifr_name, savname+4, sizeof(ifr.ifr_name)); + strncpy(ifr.ifr_name, savname, sizeof(ifr.ifr_name)); if ((s = socket(AF_INET, SOCK_DGRAM, 0)) >= 0) { if (ioctl(s, SIOCGIFFLAGS, (caddr_t)&ifr) >= 0) { ifr.ifr_flags |= IFF_UP; - ioctl(s, SIOCSIFFLAGS, (caddr_t)&ifr); + if (ioctl(s, SIOCSIFFLAGS, (caddr_t)&ifr)) { + strncpy(errbuf, strerror(errno), sizeof(errbuf)-1); + close(tun); + } } close(s); } @@ -1798,9 +1859,12 @@ eth_filter(dev, 1, (ETH_MAC *)mac, 0, 0); status = _eth_write (dev, &send, NULL); if (status != SCPE_OK) { char *msg; - msg = "Eth: Error Transmitting packet: %s\r\n" + msg = (dev->eth_api == ETH_API_PCAP) ? + "Eth: Error Transmitting packet: %s\r\n" "You may need to run as root, or install a libpcap version\r\n" - "which is at least 0.9 from your OS vendor or www.tcpdump.org\r\n"; + "which is at least 0.9 from your OS vendor or www.tcpdump.org\r\n" : + "Eth: Error Transmitting packet: %s\r\n" + "You may need to run as root.\r\n"; printf(msg, strerror(errno)); if (sim_log) fprintf (sim_log, msg, strerror(errno)); return status; diff --git a/sim_ether.h b/sim_ether.h index 29c9e7a8..571b75a8 100644 --- a/sim_ether.h +++ b/sim_ether.h @@ -28,6 +28,7 @@ Modification history: + 01-Mar-12 AGN Cygwin doesn't have non-blocking pcap I/O pcap (it uses WinPcap) 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 @@ -72,16 +73,25 @@ #if defined(__NetBSD__) || defined (__OpenBSD__) || defined (__FreeBSD__) #define xBSD 1 #endif -#if !defined(__FreeBSD__) && !defined(_WIN32) && !defined(VMS) +#if !defined(__FreeBSD__) && !defined(_WIN32) && !defined(VMS) && !defined(__CYGWIN__) && !defined(__APPLE__) #define USE_SETNONBLOCK 1 #endif +/* cygwin dowsn't have the right features to use the threaded network I/O */ +#if defined(__CYGWIN__) +#define DONT_USE_READER_THREAD +#endif + #if (((defined(__sun__) && defined(__i386__)) || defined(__linux)) && !defined(DONT_USE_READER_THREAD)) #define USE_READER_THREAD 1 #endif +#if defined(DONT_USE_READER_THREAD) +#undef USE_READER_THREAD +#endif + /* make common winpcap code a bit easier to read in this file */ -#if defined(_WIN32) || defined(VMS) +#if defined(_WIN32) || defined(VMS) || defined(__CYGWIN__) #define PCAP_READ_TIMEOUT -1 #else #define PCAP_READ_TIMEOUT 1 @@ -94,7 +104,7 @@ #endif /* USE_SETNONBLOCK */ #undef PCAP_READ_TIMEOUT #define PCAP_READ_TIMEOUT 15 -#if (!defined (xBSD) && !defined(_WIN32) && !defined(VMS)) || defined (USE_TAP_NETWORK) || defined (USE_VDE_NETWORK) +#if (!defined (xBSD) && !defined(_WIN32) && !defined(VMS) && !defined(__CYGWIN__)) || defined (USE_TAP_NETWORK) || defined (USE_VDE_NETWORK) #define MUST_DO_SELECT 1 #endif #endif /* USE_READER_THREAD */