[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