diff --git a/0readmeAsynchIO.txt b/0readmeAsynchIO.txt index 28a8205b..00f5b7c6 100644 --- a/0readmeAsynchIO.txt +++ b/0readmeAsynchIO.txt @@ -142,8 +142,7 @@ Most *nix platforms have these APIs available and on these platforms simh is typically built with these available since on these platforms, pthreads is required for simh networking support. Windows can also utilize the pthreads APIs if the compile and run time support for the -win32Pthreads package has been installed on the build system and the -run time dll is available in the execution environment. +win32Pthreads package has been installed on the build system. Sample Asynch I/O device implementations. The pdp11_rq.c module has been refactored to leverage the asynch I/O diff --git a/PDP11/pdp11_xq.c b/PDP11/pdp11_xq.c index c4eb46e7..f3b3ce1f 100644 --- a/PDP11/pdp11_xq.c +++ b/PDP11/pdp11_xq.c @@ -1689,6 +1689,16 @@ t_stat xq_process_loopback(CTLR* xq, ETH_PACK* pack) physical_address = &xq->var->setup.macs[0]; else physical_address = &xq->var->mac; + + /* The only packets we should be responding to are ones which + we received due to them being directed to our physical MAC address, + OR the Broadcast address OR to a Multicast address we're listening to + (we may receive others if we're in promiscuous mode, but shouldn't + respond to them) */ + if ((0 == (pack->msg[0]&1)) && /* Multicast or Broadcast */ + (0 != memcmp(physical_address, pack->msg, sizeof(ETH_MAC)))) + return SCPE_NOFNC; + memcpy (&response.msg[0], &response.msg[offset+2], sizeof(ETH_MAC)); memcpy (&response.msg[6], physical_address, sizeof(ETH_MAC)); offset += 8 - 16; /* Account for the Ethernet Header and Offset value in this number */ diff --git a/PDP11/pdp11_xu.c b/PDP11/pdp11_xu.c index 36e97ca0..05bccaed 100644 --- a/PDP11/pdp11_xu.c +++ b/PDP11/pdp11_xu.c @@ -416,6 +416,17 @@ t_stat xu_process_loopback(CTLR* xu, ETH_PACK* pack) /* create forward response packet */ memcpy (&response, pack, sizeof(ETH_PACK)); memcpy (physical_address, xu->var->setup.macs[0], sizeof(ETH_MAC)); + + /* The only packets we should be responding to are ones which + we received due to them being directed to our physical MAC address, + OR the Broadcast address OR to a Multicast address we're listening to + (we may receive others if we're in promiscuous mode, but shouldn't + respond to them) */ + if ((0 == (pack->msg[0]&1)) && /* Multicast or Broadcast */ + (0 != memcmp(physical_address, pack->msg, sizeof(ETH_MAC)))) + return SCPE_NOFNC; + + memcpy (&response.msg[0], &response.msg[offset+2], sizeof(ETH_MAC)); memcpy (&response.msg[6], physical_address, sizeof(ETH_MAC)); offset += 8; diff --git a/VAX/vax780_vmb_exe.h b/VAX/vax780_vmb_exe.h index e15fe616..6b6af820 100644 --- a/VAX/vax780_vmb_exe.h +++ b/VAX/vax780_vmb_exe.h @@ -1,7 +1,9 @@ +#ifndef ROM_vax780_vmb_exe_H +#define ROM_vax780_vmb_exe_H 0 /* - VAX/vax780_vmb_exe.h produced at Tue Sep 20 04:39:17 2011 - from VAX/vmb.exe which was last modified at Tue Sep 20 03:24:44 2011 - file size: 44544 (0xAE00) + VAX/vax780_vmb_exe.h produced at Sun Feb 26 12:32:44 2012 + from VAX/vmb.exe which was last modified at Sat Feb 18 00:01:12 2012 + file size: 44544 (0xAE00) - checksum: 0xFFC014CC */ unsigned char vax780_vmb_exe[] = { 0xD4,0xEF,0x34,0x61,0x00,0x00,0x17,0xEF,0xB8,0x5D,0x00,0x00,0xC1,0xAB,0x38,0xAB, @@ -2788,3 +2790,4 @@ unsigned char vax780_vmb_exe[] = { 0x4C,0x52,0x45,0x41,0x44,0x3A,0x58,0x2D,0x32,0x20,0x20,0x43,0x4F,0x4E,0x49,0x4F, 0x3A,0x58,0x2D,0x33,0x20,0x20,0x2A,0x45,0x6E,0x64,0x20,0x6F,0x66,0x20,0x49,0x64, 0x65,0x6E,0x74,0x20,0x6C,0x69,0x73,0x74,0x73,0x2A,0x00,0x00,0x00,0x00,0x00,0x00,}; +#endif /* ROM_vax780_vmb_exe_H */ diff --git a/VAX/vax_ka655x_bin.h b/VAX/vax_ka655x_bin.h index 7fdea0c6..6cc64347 100644 --- a/VAX/vax_ka655x_bin.h +++ b/VAX/vax_ka655x_bin.h @@ -1,7 +1,9 @@ +#ifndef ROM_vax_ka655x_bin_H +#define ROM_vax_ka655x_bin_H 0 /* - VAX/vax_ka655x_bin.h produced at Tue Sep 20 04:39:07 2011 - from VAX/ka655x.bin which was last modified at Tue Sep 20 03:24:43 2011 - file size: 131072 (0x20000) + VAX/vax_ka655x_bin.h produced at Sun Feb 26 12:32:44 2012 + from VAX/ka655x.bin which was last modified at Sat Feb 18 00:01:12 2012 + file size: 131072 (0x20000) - checksum: 0xFF7673B6 */ unsigned char vax_ka655x_bin[] = { 0x11,0x22,0x11,0xFE,0x02,0x03,0x53,0x01,0x31,0x89,0x03,0x00,0x31,0x8B,0x03,0x00, @@ -8196,3 +8198,4 @@ unsigned char vax_ka655x_bin[] = { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,}; +#endif /* ROM_vax_ka655x_bin_H */ diff --git a/makefile b/makefile index 47f992c0..b470d8df 100644 --- a/makefile +++ b/makefile @@ -28,7 +28,9 @@ ifeq ($(WIN32),) #*nix Environments (&& cygwin) ifeq ($(GCC),) GCC = gcc endif - ifeq (SunOS,$(shell uname)) + OSTYPE = $(shell uname) + OSNAME = $(OSTYPE) + ifeq (SunOS,$(OSTYPE)) TEST = /bin/test else TEST = test @@ -40,14 +42,16 @@ ifeq ($(WIN32),) #*nix Environments (&& cygwin) INCPATH:=/usr/include LIBPATH:=/usr/lib OS_CCDEFS = -D_GNU_SOURCE - ifeq (Darwin,$(shell uname)) + ifeq (Darwin,$(OSTYPE)) + OSNAME = OSX LIBEXT = dylib else - ifeq (Linux,$(shell uname)) + ifeq (Linux,$(OSTYPE)) LIBPATH := $(sort $(foreach lib,$(shell /sbin/ldconfig -p | grep ' => /' | sed 's/^.* => //'),$(dir $(lib)))) LIBEXT = so else - ifeq (SunOS,$(shell uname)) + ifeq (SunOS,$(OSTYPE)) + OSNAME = Solaris LIBPATH := $(shell crle | grep 'Default Library Path' | awk '{ print $$5 }' | sed 's/:/ /g') LIBEXT = so OS_LDFLAGS += -lsocket -lnsl @@ -68,7 +72,7 @@ ifeq ($(WIN32),) #*nix Environments (&& cygwin) LIBPATH += /usr/pkg/lib OS_LDFLAGS += -L/usr/pkg/lib -R/usr/pkg/lib endif - ifneq (,$(findstring NetBSD,$(shell uname))$(findstring FreeBSD,$(shell uname))) + ifneq (,$(findstring NetBSD,$(OSTYPE))$(findstring FreeBSD,$(OSTYPE))) LIBEXT = so else LIBEXT = a @@ -104,49 +108,41 @@ ifeq ($(WIN32),) #*nix Environments (&& cygwin) OS_LDFLAGS += -ldl $(info using libdl: $(call find_lib,dl) $(call find_include,dlfcn)) else - ifeq (BSD,$(findstring BSD,$(shell uname))) + ifeq (BSD,$(findstring BSD,$(OSTYPE))) OS_CCDEFS += -DHAVE_DLOPEN=so $(info using libdl: $(call find_include,dlfcn)) endif endif endif - 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 + # building the pdp11, or any vax simulator could use networking support + ifneq (,$(or $(findstring pdp11,$(MAKECMDGOALS)),$(findstring vax,$(MAKECMDGOALS)),$(findstring all,$(MAKECMDGOALS)))) + NETWORK_USEFUL = true + else + ifeq ($(MAKECMDGOALS),) + # default target is all + NETWORK_USEFUL = true + endif + endif + ifneq (,$(NETWORK_USEFUL)) + 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 + $(info *** Simulator(s) being built with networking support using) + $(info *** $(OSTYPE) provided libpcap components) + else NETWORK_CCDEFS = -DUSE_SHARED $(info using libpcap: $(call find_include,pcap)) + $(info *** Simulator(s) being built with networking support using) + $(info *** $(OSTYPE) provided libpcap components) endif else - NETWORK_CCDEFS = -DUSE_SHARED - $(info using libpcap: $(call find_include,pcap)) - endif - endif - 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 - 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 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),) # 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 @@ -154,16 +150,55 @@ ifeq ($(WIN32),) #*nix Environments (&& cygwin) LIBEXT = a ifneq (,$(call find_lib,pcap)) ifneq (,$(call find_include,pcap)) - NETWORK_OPT := -DUSE_NETWORK -isystem $(dir $(call find_include,pcap)) $(call find_lib,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 *** Simulator(s) 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 ***) else $(error using libpcap: $(call find_lib,pcap) missing pcap.h) endif LIBEXT = $(LIBEXTSAVE) - else - $(error missing libpcap) endif endif + ifneq (,$(findstring USE_NETWORK,$(NETWORK_CCDEFS))$(findstring USE_SHARED,$(NETWORK_CCDEFS))) + # Given we have libpcap components, consider other network connections as well + ifneq (,$(call find_lib,vdeplug)) + # libvdeplug requires the use of the OS provided libpcap + ifeq (,$(findstring usr/local,$(NETWORK_CCDEFS))) + 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 + endif + 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 on BSD platforms (including OS X) + NETWORK_CCDEFS += -DUSE_TAP_NETWORK -DUSE_BSDTUNTAP + endif + else + $(info *** Warning ***) + $(info *** Warning *** Simulator(s) 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 ***) + endif + NETWORK_OPT = $(NETWORK_CCDEFS) + endif + ifneq (binexists,$(shell if $(TEST) -e BIN; then echo binexists; fi)) + MKDIRBIN = if $(TEST) ! -e BIN; then mkdir BIN; fi endif else #Win32 Environments (via MinGW32) diff --git a/scp.c b/scp.c index 3e5dd88b..2d7b5deb 100644 --- a/scp.c +++ b/scp.c @@ -3965,6 +3965,8 @@ if (!initialized) { 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) + handle = dlopen("libreadline." __STR(HAVE_DLOPEN) ".6", RTLD_NOW|RTLD_GLOBAL); if (handle) { p_readline = dlsym(handle, "readline"); p_add_history = dlsym(handle, "add_history"); diff --git a/sim_BuildROMs.c b/sim_BuildROMs.c index d895a4bc..ba573de3 100644 --- a/sim_BuildROMs.c +++ b/sim_BuildROMs.c @@ -53,7 +53,9 @@ #include #endif -int sim_make_ROM_include(const char *rom_filename, +int sim_make_ROM_include(const char *rom_filename, + int expected_size, + int expected_checksum, const char *include_filename, const char *rom_array_name) { @@ -64,24 +66,44 @@ int bytes_written = 0; int c; struct stat statb; unsigned char *ROMData = NULL; +unsigned int checksum = 0; if (NULL == (rFile = fopen (rom_filename, "rb"))) { printf ("Error Opening '%s' for input: %s\n", rom_filename, strerror(errno)); return -1; } if (stat (rom_filename, &statb)) { - printf ("Error Stating '%s': %s\n", rom_filename, strerror(errno)); + printf ("Error stating '%s': %s\n", rom_filename, strerror(errno)); + fclose (rFile); + return -1; + } +if (statb.st_size != expected_size) { + printf ("Error: ROM file '%s' has an unexpected size: %d vs %d\n", rom_filename, (int)statb.st_size, expected_size); + printf ("This can happen if the file was transferred or unpacked incorrectly\n"); + printf ("and in the process tried to convert line endings rather than passing\n"); + printf ("the file's contents unmodified\n"); fclose (rFile); return -1; } ROMData = malloc (statb.st_size); if (statb.st_size != fread (ROMData, sizeof(*ROMData), statb.st_size, rFile)) { - printf ("Error Stating '%s': %s\n", rom_filename, strerror(errno)); + printf ("Error reading '%s': %s\n", rom_filename, strerror(errno)); fclose (rFile); free (ROMData); return -1; } fclose (rFile); +for (c=0; cFooter); + /* align the data portion of the block to the desired alignment */ + /* compute the address of the data portion of the block */ + BlockOffset += BitMapSectors*SectorSize; + /* round up this address to the desired alignment */ + BlockOffset += VHD_DATA_BLOCK_ALIGNMENT-1; + BlockOffset &= ~(VHD_DATA_BLOCK_ALIGNMENT-1); + /* the actual block address is the beginning of the block bitmap */ + BlockOffset -= BitMapSectors*SectorSize; hVHD->BAT[BlockNumber] = NtoHl((uint32)(BlockOffset/SectorSize)); if (WriteFilePosition(hVHD->File, BitMap, diff --git a/sim_ether.c b/sim_ether.c index 82057c3c..3cc40ace 100644 --- a/sim_ether.c +++ b/sim_ether.c @@ -560,7 +560,7 @@ char* eth_getname(int number, char* name) ETH_LIST list[ETH_MAX_DEVICE]; int count = eth_devices(ETH_MAX_DEVICE, list); - if (count <= number) return 0; + if (count <= number) return NULL; strcpy(name, list[number].name); return name; } @@ -587,7 +587,7 @@ char* eth_getname_bydesc(char* desc, char* name) return name; } /* not found */ - return 0; + return NULL; } /* strncasecmp() is not available on all platforms */ @@ -621,16 +621,13 @@ char* eth_getname_byname(char* name, char* temp) found = 0; n = strlen(name); for (i=0; i min) min = len; for (i=0; idbit, dev->dptr, "Determining Address Conflict for MAC address: %s\n", mac_string); +/* The process of checking address conflicts is used in two ways: + 1) to determine the behavior of the currently running packet + delivery facility regarding whether it may receive copies + of every packet sent (and how many). + 2) to verify if a MAC address which this facility is planning + to use as the source address of packets is already in use + by some other node on the local network + Case #1, doesn't require (and explicitly doesn't want) any + interaction or response from other systems on the LAN so + therefore no considerations regarding switch packet forwarding + are important. Meanwhile, Case #2 does require responses from + other components on the LAN to provide useful functionality. + The original designers of this mechanism did this when essentially + all LANs were single collision domains (i.e. ALL nodes which might + be affected by an address conflict were physically present on a single + Ethernet cable which might have been extended by a couple of repeaters). + Since that time, essentially no networks are single collision domains. + Thick and thinwire Ethernet cables don’t exist and very few networks + even have hubs. Today, essentially all LANs are deployed using one + or more layers of network switches. In a switched LAN environment, the + switches on the LAN ‘learn’ which ports on the LAN source traffic from + which MAC addresses and then forward traffic destined for particular + MAC address to the appropriate ports. If a particular MAC address is + already in use somewhere on the LAN, then the switches ‘know’ where + it is. The host based test using the loopback protocol is poorly + designed to detect this condition. This test is performed by the host + first changing the device’s Physical MAC address to the address which + is to be tested, and then sending a loopback packet FROM AND TO this + MAC address with a loopback reply to be sent by a system which may be + currently using the MAC address. If no reply is received, then the + MAC address is presumed to be unused. The sending of this packet will + result in its delivery to the right system since the switch port/MAC + address tables know where to deliver packets destined to this MAC + address, however the response it generates won’t be delivered to the + system performing the test since the switches on the LAN won’t know + about the local port being the right target for packets with this MAC + address. A better test design to detect these conflicts would be for + the testing system to send a loopback packet FROM the current physical + MAC address (BEFORE changing it) TO the MAC address being tested with + the loopback response coming to the current physical MAC address of + the device. If a response is received, then the address is in use and + the attempt to change the device’s MAC address should fail. Since we + can’t change the software running in these simulators to implement this + better conflict detection approach, we can still ‘do the right thing’ + in the sim_ether layer. We’re already handling the loopback test + packets specially since we always had to avoid receiving the packets + which were being sent, but needed to allow for the incoming loopback + packets to be properly dealt with. We can extend this current special + handling to change outgoing ‘loopback to self’ packets to have source + AND loopback destination addresses in the packets to be the host NIC’s + physical address. The switch network will already know the correct + MAC/port relationship for the host NIC’s physical address, so loopback + response packets will be delivered as needed. + + Code in _eth_write and _eth_callback provide the special handling to + perform the described loopback packet adjustments, and code in + eth_filter_hash makes sure that the loopback response packets are received. + + */ + /* build a loopback forward request packet */ memset (&send, 0, sizeof(ETH_PACK)); send.len = ETH_MIN_PACKET; /* minimum packet size */ @@ -1743,7 +1800,7 @@ if (status != SCPE_OK) { char *msg; msg = "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 www.tcpdump.org\r\n"; + "which is at least 0.9 from your OS vendor or www.tcpdump.org\r\n"; printf(msg, strerror(errno)); if (sim_log) fprintf (sim_log, msg, strerror(errno)); return status; @@ -1755,7 +1812,10 @@ sim_os_ms_sleep (300); /* time for a conflicting host to respond */ do { memset (&recv, 0, sizeof(ETH_PACK)); status = eth_read (dev, &recv, NULL); - if (memcmp(send.msg, recv.msg, 14)== 0) + if (((0 == memcmp(send.msg+12, recv.msg+12, 2)) && /* Protocol Match */ + (0 == memcmp(send.msg, recv.msg+6, 6)) && /* Source Match */ + (0 == memcmp(send.msg+6, recv.msg, 6))) || /* Destination Match */ + (0 == memcmp(send.msg, recv.msg, 14))) /* Packet Match (Reflection) */ responses++; } while (recv.len > 0); @@ -1792,12 +1852,16 @@ if (!packet) return SCPE_ARG; /* make sure packet is acceptable length */ if ((packet->len >= ETH_MIN_PACKET) && (packet->len <= ETH_MAX_PACKET)) { - int loopback_self_frame = LOOPBACK_SELF_FRAME(dev->physical_addr, packet->msg); + int loopback_self_frame = LOOPBACK_SELF_FRAME(packet->msg, packet->msg); eth_packet_trace (dev, packet->msg, packet->len, "writing"); /* record sending of loopback packet (done before actual send to avoid race conditions with receiver) */ if (loopback_self_frame) { + if (dev->have_host_nic_phy_addr) { + memcpy(&packet->msg[6], dev->host_nic_phy_hw_addr, sizeof(ETH_MAC)); + memcpy(&packet->msg[18], dev->host_nic_phy_hw_addr, sizeof(ETH_MAC)); + } #ifdef USE_READER_THREAD pthread_mutex_lock (&dev->self_lock); #endif @@ -1806,7 +1870,7 @@ if ((packet->len >= ETH_MIN_PACKET) && (packet->len <= ETH_MAX_PACKET)) { #ifdef USE_READER_THREAD pthread_mutex_unlock (&dev->self_lock); #endif - } + } /* dispatch write request (synchronous; no need to save write info to dev) */ switch (dev->eth_api) { @@ -2346,6 +2410,17 @@ int from_me = 0; int i; int bpf_used; +if ((dev->have_host_nic_phy_addr) && + (LOOPBACK_PHYSICAL_RESPONSE(dev->host_nic_phy_hw_addr, dev->physical_addr, data))) { + u_char *datacopy = malloc(header->len); + + memcpy(datacopy, data, header->len); + memcpy(datacopy, dev->physical_addr, sizeof(ETH_MAC)); + memcpy(datacopy+18, dev->physical_addr, sizeof(ETH_MAC)); + _eth_callback(info, header, datacopy); + free(datacopy); + return; +} switch (dev->eth_api) { case ETH_API_PCAP: #ifdef USE_BPF @@ -2380,7 +2455,9 @@ switch (dev->eth_api) { } /* detect reception of loopback packet to our physical address */ -if (LOOPBACK_SELF_FRAME(dev->physical_addr, data)) { +if ((LOOPBACK_SELF_FRAME(dev->physical_addr, data)) || + (dev->have_host_nic_phy_addr && + LOOPBACK_PHYSICAL_REFLECTION(dev->host_nic_phy_hw_addr, data))) { #ifdef USE_READER_THREAD pthread_mutex_lock (&dev->self_lock); #endif @@ -2397,7 +2474,7 @@ if (LOOPBACK_SELF_FRAME(dev->physical_addr, data)) { #ifdef USE_READER_THREAD pthread_mutex_unlock (&dev->self_lock); #endif - } +} if (bpf_used ? to_me : (to_me && !from_me)) { if (header->len > ETH_MIN_JUMBO_FRAME) { @@ -2689,6 +2766,10 @@ if ((addr_count) && (dev->reflections > 0)) { memcpy(dev->physical_addr, &dev->filter_address[i], sizeof(ETH_MAC)); /* let packets through where dst and src are the same as our physical address */ sprintf (&buf[strlen(buf)], " or ((ether dst %s) and (ether src %s))", mac, mac); + if (dev->have_host_nic_phy_addr) { + eth_mac_fmt(&dev->host_nic_phy_hw_addr, mac); + sprintf(&buf[strlen(buf)], "or ((ether dst %s) and (ether proto 0x9000))", mac); + } break; } } @@ -2697,8 +2778,10 @@ if ((0 == strlen(buf)) && (!dev->promiscuous)) /* Empty filter means match nothi strcpy(buf, "ether host fe:ff:ff:ff:ff:ff"); /* this should be a good match nothing filter */ sim_debug(dev->dbit, dev->dptr, "BPF string is: |%s|\n", buf); -/* get netmask, which is required for compiling */ -if ((dev->eth_api == ETH_API_PCAP) && (pcap_lookupnet(dev->handle, &bpf_subnet, &bpf_netmask, errbuf)<0)) +/* get netmask, which is a required argument for compiling. The value, + in our case isn't actually interesting since the filters we generate + 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 @@ -2823,7 +2906,6 @@ for (i=0; inext) { + for (i=0, dev=alldevs; dev && (i < max); dev=dev->next, ++i) { if ((dev->flags & PCAP_IF_LOOPBACK) || (!strcmp("any", dev->name))) continue; - list[i].num = i; - sprintf(list[i].name, "%s", dev->name); + strncpy(list[i].name, dev->name, sizeof(list[i].name)-1); if (dev->description) - sprintf(list[i].desc, "%s", dev->description); + strncpy(list[i].desc, dev->description, sizeof(list[i].desc)-1); else - sprintf(list[i].desc, "%s", "No description available"); - if (i++ >= max) break; + strncpy(list[i].desc, "No description available", sizeof(list[i].desc)-1); } /* free device list */ diff --git a/sim_ether.h b/sim_ether.h index 2314e835..29c9e7a8 100644 --- a/sim_ether.h +++ b/sim_ether.h @@ -130,19 +130,36 @@ #define ETH_MIN_PACKET 60 /* minimum ethernet packet size */ #define ETH_MAX_PACKET 1514 /* maximum ethernet packet size */ #define ETH_MAX_JUMBO_FRAME 65536 /* maximum ethernet jumbo frame size (or Offload Segment Size) */ -#define ETH_MAX_DEVICE 10 /* maximum ethernet devices */ +#define ETH_MAX_DEVICE 20 /* maximum ethernet devices */ #define ETH_CRC_SIZE 4 /* ethernet CRC size */ #define ETH_FRAME_SIZE (ETH_MAX_PACKET+ETH_CRC_SIZE) /* ethernet maximum frame size */ #define ETH_MIN_JUMBO_FRAME ETH_MAX_PACKET /* Threshold size for Jumbo Frame Processing */ #define LOOPBACK_SELF_FRAME(phy_mac, msg) \ - ((memcmp(phy_mac, msg , 6) == 0) && \ - (memcmp(phy_mac, msg+6, 6) == 0) && \ - ((msg)[12] == 0x90) && ((msg)[13] == 0x00) && \ + (((msg)[12] == 0x90) && ((msg)[13] == 0x00) && \ ((msg)[14] == 0x00) && ((msg)[15] == 0x00) && \ ((msg)[16] == 0x02) && ((msg)[17] == 0x00) && \ - (memcmp(phy_mac, msg+18, 6) == 0) && \ - ((msg)[24] == 0x01) && ((msg)[25] == 0x00)) + ((msg)[24] == 0x01) && ((msg)[25] == 0x00) && \ + (memcmp(phy_mac, (msg), 6) == 0) && \ + (memcmp(phy_mac, (msg)+6, 6) == 0) && \ + (memcmp(phy_mac, (msg)+18, 6) == 0)) + +#define LOOPBACK_PHYSICAL_RESPONSE(host_phy, phy_mac, msg) \ + (((msg)[12] == 0x90) && ((msg)[13] == 0x00) && \ + ((msg)[14] == 0x08) && ((msg)[15] == 0x00) && \ + ((msg)[16] == 0x02) && ((msg)[17] == 0x00) && \ + ((msg)[24] == 0x01) && ((msg)[25] == 0x00) && \ + (memcmp(host_phy, (msg)+18, 6) == 0) && \ + (memcmp(host_phy, (msg), 6) == 0) && \ + (memcmp(phy_mac, (msg)+6, 6) == 0)) + +#define LOOPBACK_PHYSICAL_REFLECTION(host_phy, msg) \ + (((msg)[12] == 0x90) && ((msg)[13] == 0x00) && \ + ((msg)[14] == 0x00) && ((msg)[15] == 0x00) && \ + ((msg)[16] == 0x02) && ((msg)[17] == 0x00) && \ + ((msg)[24] == 0x01) && ((msg)[25] == 0x00) && \ + (memcmp(host_phy, (msg)+6, 6) == 0) && \ + (memcmp(host_phy, (msg)+18, 6) == 0)) struct eth_packet { uint8 msg[ETH_FRAME_SIZE]; /* ethernet frame (message) */ @@ -168,7 +185,6 @@ struct eth_queue { }; struct eth_list { - int num; char name[ETH_DEV_NAME_MAX]; char desc[ETH_DEV_DESC_MAX]; };