[Simh] [PATCH] tun/tap networking support

Pär Moberg gw at ghost-wolf.com
Thu Apr 29 04:37:58 EDT 2010


I am looking forward to this, cheering from the user bench.
//Pär

ucsavl at gmail.com wrote:
> 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;
> +}
> +
> _______________________________________________
> Simh mailing list
> Simh at trailing-edge.com
> http://mailman.trailing-edge.com/mailman/listinfo/simh



More information about the Simh mailing list