[Simh] Hecnet client...

Jason Stevens neozeed at gmail.com
Sun Feb 15 14:39:15 EST 2009


I was looking at the HECnet stuff, and I thought it would be cool if
SIMH could talk directly into a HECnet bridge program.  I've never
setup a DECnet network so I can't really verify that it works 100%,
but what I did do is to modify the HECnet bridge to accept TCP/IP
packets, and then I've included enough UDP code so that I can now
connect into my test HECnet.

As it is right now, the SIMH portion depends on timing working
correctly, so any environment where you can enable the idle timer will
work with this. Additionally the socket programming I'm using is
geared to a *NIX install, so Windows users are out of luck at the
moment, although I suspect it shouldn't be *that* hard to setup some
non blocking UDP stuff in winsock.

 Also due to the nature of HECnet there is no ability to fragment if
the packet is too big... I've been thinking of adding zlib support to
compress the packets... which may not be such a bad idea at any rate.

I think this would be a help to people that don't have full root
access on the machine, or just want to quickly join some network in
the sky.. Much like how the SLiRP stuff helps us TCP/IP folk out.  I
suppose adding the same functionality to Qemu could be done, and even
expanding the bridge to support IPX/SPX...  It would bring a few more
retro emulators onto the net...

Anyways if anyone could test this, I'd be very appreciative!

Jason

-----------------------------------
The following patch adds TCP/IP support to the hecnet bridge program.
-----------------------------------

--- bridge.c    Mon Aug  6 07:50:45 2007
+++ bridge-ip.c Sun Feb 15 12:23:43 2009
@@ -61,6 +61,9 @@
 #define ETHERTYPE_LAT 0x6004
 #define ETHERTYPE_MOPDL 0x6001
 #define ETHERTYPE_MOPRC 0x6002
+#define ETHERTYPE_IP   0x0800
+#define ETHERTYPE_ARP   0x0806
+#define ETHERTYPE_REVARP   0x8035

 #define MAX(a,b) (a>b?a:b)

@@ -71,6 +74,9 @@

 struct bpf_insn insns[] = {
   BPF_STMT(BPF_LD+BPF_H+BPF_ABS, 12),
+  BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, ETHERTYPE_REVARP, 7, 0),
+  BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, ETHERTYPE_ARP, 6, 0),
+  BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, ETHERTYPE_IP, 5, 0),
   BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, ETHERTYPE_MOPRC, 4, 0),
   BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, ETHERTYPE_MOPDL, 3, 0),
   BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, ETHERTYPE_LAT, 2, 0),
@@ -95,8 +101,8 @@
    When data arrives, we filter, process and send it out again.
  */

-typedef enum {DECnet, LAT} pkttyp;
-#define MAXTYP 2
+typedef enum {DECnet, LAT, IP} pkttyp;
+#define MAXTYP 3

 struct BRIDGE {
   char name[40];
@@ -326,6 +332,7 @@
        if(strcmp(buf,"[lat]") == 0) mode = 2;
        if(sscanf(buf,"[source %d.%d]", &area, &node) == 2) mode = 3;
        if(strcmp(buf,"[relay]") == 0) mode = 4;
+        if(strcmp(buf,"[ip]") == 0) mode = 5;
        if(mode < 0) {
          printf("Bad configuration at line %d\n%s\n", line,buf);
          exit(1);
@@ -352,6 +359,10 @@
          break;
        case 4:
          break;
+       case 5:
+         if (!add_service(buf,IP,"IP"))
+           printf("%d: IP bridge %s don't exist.\n", line, buf);
+         break;
        default:
          printf("weird state at line %d\n",line);
          exit(1);
@@ -380,6 +391,14 @@
          is_ethertype(data, ETHERTYPE_MOPRC));
 }

+int is_ip(struct DATA *data)
+{
+  return (is_ethertype(data, ETHERTYPE_IP) ||
+          is_ethertype(data, ETHERTYPE_ARP) ||
+          is_ethertype(data, ETHERTYPE_REVARP));
+}
+
+
 unsigned long timedelta(struct timeval old)
 {
   struct timeval now;
@@ -496,6 +515,8 @@

   if (is_decnet(d)) d->type = DECnet;
   if (is_lat(d)) d->type = LAT;
+  if (is_ip(d)) d->type = IP;
+

   if (bridge[d->source].types[d->type] == 0) return;
   if (d->type == -1) return;




-----------------------------------
replace non implemented section in sim_ether.c (SIMH) to get a hecnet
client built in.  The destination is compiled in at the moment.
-----------------------------------

struct sockaddr_in si_me, si_other;
int s, i, slen;

#define SRV_IP "10.0.1.9"
#define PORT 7771
#define BUFLEN 1518

t_stat eth_open(ETH_DEV* dev, char* name, DEVICE* dptr, uint32 dbit)
{
int32 fl;

slen=sizeof(si_other);
if ((s=socket(PF_INET, SOCK_DGRAM, 0))==-1)
memset((char *) &si_me, 0, sizeof(si_me));
si_me.sin_family = AF_INET;
si_me.sin_port = htons(7771);
si_me.sin_addr.s_addr = INADDR_ANY;
if (bind(s, &si_me, sizeof(si_me))==-1)
        {
        printf("error binding socket\n");
        exit(-1);
        }


fl = fcntl (s, F_GETFL,0);
fcntl (s, F_SETFL, fl | O_NONBLOCK);
return SCPE_OK;
}

t_stat eth_close (ETH_DEV* dev)
{
close(s);
return SCPE_OK;
}

t_stat eth_write (ETH_DEV* dev, ETH_PACK* packet, ETH_PCALLBACK routine)
{
char buf[BUFLEN];

slen=sizeof(si_other);

        if (sendto(s, packet->msg, packet->len, 0, &si_other, slen)==-1)
                {  //error sending packet!
                if(routine)
                        (routine)(1);
                }
        else{
                if(routine)
                (routine)(0);}
return SCPE_OK;
}

t_stat eth_read (ETH_DEV* dev, ETH_PACK* packet, ETH_PCALLBACK routine)
{
char buf[2500];
int rc;

if(!dev) return SCPE_UNATT;
if(!packet) return SCPE_ARG;

dev->read_packet = packet;
packet->len = 0;
dev->read_callback = routine;

slen=sizeof(si_other);

memset(&buf,0x0,sizeof(buf));
rc=recvfrom(s, buf, BUFLEN, 0, &si_other, &slen);
if (rc==-1)
        {} //error?
else {
        dev->read_packet->len=rc;
       memcpy(dev->read_packet->msg,buf,rc);
       eth_add_crc32(dev->read_packet);
       if(dev->read_callback)
        (dev->read_callback)(0);
}

return SCPE_OK;
}

t_stat eth_filter (ETH_DEV* dev, int addr_count,
                   ETH_MAC* addresses,
                   ETH_BOOL all_multicast,
                   ETH_BOOL promiscuous)
{
return SCPE_OK;
}

int eth_devices (int max, ETH_LIST* dev)
{
return SCPE_OK;
}


More information about the Simh mailing list