[Simh] [PATCH] tun/tap networking support
ucsavl at gmail.com
ucsavl at gmail.com
Wed Apr 28 20:05:02 EDT 2010
This patch lets simh read/write the ethernet frames from/into
a file descriptor, instead of injecting them with pcap into an interface.
That file descriptor could be obtained by opening a tun/tap device
(ex. 'att xq tap:tap0' on linux does the necessary magic of opening
/dev/net/tun, attaching it to 'tap0' and setting ethernet mode),
opening some other path in the filesystem, or it could be opened by a
helper program and passed down to simh via an environment variable.
The main advantage of this is being able to run simh with networking
as a regular user.
to build it:
$ make USE_TAP_NETWORK=1
to use it, run as root:
# tunctl -u regular_user -t tap0
then configure the host as if tap0 were a real interface and simh a real
machine connected to it (ex. enable forwarding+NAT, run dhcp on tap0, etc).
finally, running as regular_user:
$ vax
...
sim> att xq tap:tap0
diff -Nrup simhv38-1-orig/makefile simhv38-1/makefile
--- simhv38-1-orig/makefile 2008-11-19 21:53:48.000000000 +0200
+++ simhv38-1/makefile 2010-04-28 04:53:02.000000000 +0300
@@ -13,8 +13,9 @@ ifeq ($(WIN32),)
endif
endif
CC = gcc -std=c99 -U__STRICT_ANSI__ -g $(OS_CCDEFS) -I .
- ifeq ($(USE_NETWORK),)
- else
+ ifneq ($(USE_TAP_NETWORK),)
+ NETWORK_OPT = -DUSE_NETWORK -DUSE_TAP_NETWORK sim_ether_tap.c opentap.c
+ else ifneq ($(USE_NETWORK),)
NETWORK_OPT = -DUSE_NETWORK -isystem /usr/local/include /usr/local/lib/libpcap.a
endif
else
@@ -35,7 +36,6 @@ BIN = BIN/
SIM = scp.c sim_console.c sim_fio.c sim_timer.c sim_sock.c \
sim_tmxr.c sim_ether.c sim_tape.c
-
#
# Emulator source files and compile time options
#
diff -Nrup simhv38-1-orig/opentap.c simhv38-1/opentap.c
--- simhv38-1-orig/opentap.c 1970-01-01 02:00:00.000000000 +0200
+++ simhv38-1/opentap.c 2010-04-28 04:42:21.000000000 +0300
@@ -0,0 +1,34 @@
+#ifdef __linux
+#include <sys/types.h>
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+#include <linux/if.h>
+#include <linux/if_tun.h>
+#include <errno.h>
+#include <stdio.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+int opentap(char *fn){
+ int fd;
+ struct ifreq ifr;
+ if(snprintf(ifr.ifr_name, sizeof ifr.ifr_name, "%s", fn)
+ >= sizeof ifr.ifr_name){
+ errno = ENAMETOOLONG;
+ return -1;
+ }
+ if((fd = open("/dev/net/tun", O_RDWR)) == -1)
+ return -1;
+ ifr.ifr_flags = IFF_TAP|IFF_NO_PI;
+ if(ioctl(fd, TUNSETIFF, &ifr) == -1){
+ close(fd);
+ return -1;
+ }
+ return fd;
+}
+
+#else
+int opentap(char *fn){
+ return -1;
+}
+#endif
diff -Nrup simhv38-1-orig/sim_ether.c simhv38-1/sim_ether.c
--- simhv38-1-orig/sim_ether.c 2008-04-24 17:11:42.000000000 +0300
+++ simhv38-1/sim_ether.c 2009-02-20 22:55:54.000000000 +0200
@@ -606,10 +606,17 @@ void ethq_insert(ETH_QUE* que, int32 typ
}
/*============================================================================*/
+/* Simple tap network */
+/*============================================================================*/
+#if defined (USE_TAP_NETWORK)
+
+/* use sim_ether_tap.c */
+
+/*============================================================================*/
/* Non-implemented versions */
/*============================================================================*/
-#if !defined (USE_NETWORK) && !defined(USE_SHARED)
+#elif !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)
diff -Nrup simhv38-1-orig/sim_ether_tap.c simhv38-1/sim_ether_tap.c
--- simhv38-1-orig/sim_ether_tap.c 1970-01-01 02:00:00.000000000 +0200
+++ simhv38-1/sim_ether_tap.c 2010-04-28 05:46:42.000000000 +0300
@@ -0,0 +1,139 @@
+#include <sys/types.h>
+#include <sys/ioctl.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include "sim_ether.h"
+
+extern FILE *sim_log;
+void eth_add_crc32(ETH_PACK* packet);
+int opentap(char*);
+
+static void
+errf(char *fmt, ...)
+{
+ va_list va;
+ va_start(va, fmt);
+ vprintf(fmt, va);
+ if(sim_log) vfprintf(sim_log, fmt, va);
+ va_end(va);
+}
+
+t_stat
+eth_open(ETH_DEV *dev, char *fn, DEVICE *dptr, uint32 dbit)
+{
+ int fd, t;
+ if(!dev || !fn)
+ return SCPE_ARG;
+ if(!strncmp(fn, "fd:", 3)){
+ char *v;
+ if(fn[3] == '$'){
+ if(!(v = getenv(fn + 4))){
+ errf("no such environment variable '%s'\n",
+ fn + 4);
+ return SCPE_OPENERR;
+ }
+ }else
+ v = fn + 3;
+ if(v[0] < '0' || v[0] > '9'){
+ errf("fd should be a number, not '%s'\n", v);
+ return SCPE_OPENERR;
+ }
+ if((fd = dup(atoi(v))) < 0){
+ errf("dup(%s): %s\n", v, strerror(errno));
+ return SCPE_OPENERR;
+ }
+ }else if(!strncmp(fn, "tap:", 4)){
+ if((fd = opentap(fn + 4)) < 0){
+ errf("opentap(%s): %s\n", fn + 4, strerror(errno));
+ return SCPE_OPENERR;
+ }
+ }else{
+ if((fd = open(fn, O_RDWR)) < 0){
+ errf("open(%s): %s\n", fn, strerror(errno));
+ return SCPE_OPENERR;
+ }
+ }
+ t = 1;
+ if(ioctl(fd, FIONBIO, &t)){
+ errf("ioctl(FIONBIO, 1): %s\n", strerror(errno));
+ close(fd);
+ return SCPE_OPENERR;
+ }
+ if(!(dev->name = strdup(fn))){
+ close(fd);
+ return SCPE_MEM;
+ }
+ dev->handle = (void*)fd;
+ dev->need_crc = 0;
+ return SCPE_OK;
+}
+
+t_stat
+eth_close(ETH_DEV *dev)
+{
+ if(!dev) return SCPE_UNATT;
+ close((int)dev->handle);
+ free(dev->name);
+ return SCPE_OK;
+}
+
+t_stat
+eth_write(ETH_DEV *dev, ETH_PACK *packet, ETH_PCALLBACK routine)
+{
+ int fd;
+ if(!dev) return SCPE_UNATT;
+ if(!packet) return SCPE_ARG;
+ fd = (int)dev->handle;
+ if(write(fd, packet->msg, packet->len) < 0)
+ return SCPE_IOERR;
+ if(routine)
+ routine(0);
+ return SCPE_OK;
+}
+
+t_stat
+eth_read(ETH_DEV *dev, ETH_PACK *packet, ETH_PCALLBACK routine)
+{
+ int fd;
+ ssize_t r;
+ if(!dev) return SCPE_UNATT;
+ if(!packet) return SCPE_ARG;
+ fd = (int)dev->handle;
+ r = read(fd, packet->msg, sizeof packet->msg);
+ if(r < 0)
+ return SCPE_IOERR;
+ packet->len = r;
+ if (dev->need_crc)
+ eth_add_crc32(packet);
+ if(routine)
+ routine(0);
+ return SCPE_OK;
+}
+
+t_stat
+eth_filter(ETH_DEV *dev, int addr_count, ETH_MAC *addresses,
+ ETH_BOOL all_multicast, ETH_BOOL promiscuous)
+{
+ if(!dev) return SCPE_UNATT;
+ return SCPE_OK;
+}
+
+static ETH_LIST dlist[] = {
+ { 0, "fd:d", "file descriptor 'd'" },
+ { 0, "fd:$d", "file descriptor from environment variable 'd'" },
+ { 0, "tap:if", "tun/tap interface 'if'" },
+ { 0, "/path/to/file", "file path" },
+};
+
+int
+eth_devices(int max, ETH_LIST *list)
+{
+ int i;
+ for(i = 0; i < max && i < sizeof dlist/sizeof*dlist; i++)
+ list[i] = dlist[i];
+ return i;
+}
+
More information about the Simh
mailing list