1
0
mirror of https://github.com/PDP-10/klh10.git synced 2026-04-04 21:07:36 +00:00

CH11 over Ether (#33)

Working chaos-over-ether implementation (in addition to Chaos-over-UDP). 

Also rename dpchudp => dpchaos, both in code, files and the device process, since it no longer only supports Chaos-over-UDP, but is more generic.

Update doc for CH11.
This commit is contained in:
Björn Victor
2018-04-15 21:33:10 +02:00
committed by GitHub
parent 60d02258cb
commit 678db7c80b
10 changed files with 2097 additions and 1231 deletions

4
.gitignore vendored
View File

@@ -19,3 +19,7 @@ new
src/tags
src/config.h.in
tmp*/*
#*#
*/#*#
*.~*
*/*.~*

View File

@@ -1330,9 +1330,10 @@ DZ11 (TTY MUX): (KS only)
that this device will respond to IO instructions addressed to it,
but no TTY I/O actually happens.
CH11 (CHAOSNET): (KS only)
CH11 (CHAOSNET): (KS only, for ITS only)
This is another dummy device, only for ITS.
This is a Chaosnet device which can use Chaosnet on Ethernet
or tunnelling Chaosnet in UDP. See src/dvch11.txt.
As for the DZ11, the generic Unibus parameters must be provided.
HOST (Native Host): (KL & KS)

View File

@@ -199,7 +199,7 @@ OFILES_KS = klh10.o prmstr.o fecmd.o feload.o wfio.o osdsup.o \
DPROCS_KL = dprpxx dptm03 dpni20
DPROCS_KS = dprpxx dptm03
DPROCS_KSITS = dprpxx dptm03 dpimp dpchudp
DPROCS_KSITS = dprpxx dptm03 dpimp dpchaos
# Base utility programs, independent of KN10
@@ -290,8 +290,8 @@ install:
mv ${KLH10_HOME}/dpni20 ${KLH10_HOME}/flushed; fi
@if [ -x ${KLH10_HOME}/dpimp ]; then \
mv ${KLH10_HOME}/dpimp ${KLH10_HOME}/flushed; fi
@if [ -x ${KLH10_HOME}/dpchudp ]; then \
mv ${KLH10_HOME}/dpchudp ${KLH10_HOME}/flushed; fi
@if [ -x ${KLH10_HOME}/dpchaos ]; then \
mv ${KLH10_HOME}/dpchaos ${KLH10_HOME}/flushed; fi
@if [ -x kn10-ks ]; then cp -p kn10-ks ${KLH10_HOME}/; fi
@if [ -x kn10-ks-its ]; then cp -p kn10-ks-its ${KLH10_HOME}/; fi
@if [ -x kn10-kl ]; then cp -p kn10-kl ${KLH10_HOME}/; fi
@@ -299,7 +299,7 @@ install:
@if [ -x dptm03 ]; then cp -p dptm03 ${KLH10_HOME}/; fi
@if [ -x dpni20 ]; then cp -p dpni20 ${KLH10_HOME}/; fi
@if [ -x dpimp ]; then cp -p dpimp ${KLH10_HOME}/; fi
@if [ -x dpchudp ]; then cp -p dpchudp ${KLH10_HOME}/; fi
@if [ -x dpchaos ]; then cp -p dpchaos ${KLH10_HOME}/; fi
@if [ -x enaddr ]; then cp -p enaddr ${KLH10_HOME}/; fi
@if [ -x tapedd ]; then cp -p tapedd ${KLH10_HOME}/; fi
@if [ -x udlconv ]; then cp -p udlconv ${KLH10_HOME}/; fi
@@ -551,11 +551,11 @@ kl0i-rtmopt:
# --------- CHUDP subprocess (ITS KS only; counterpart for dvch11)
#
dpchudp.o: $(SRC)/dpchudp.c $(SRC)/dpchudp.h $(SRC)/dpsup.h
$(BUILDMOD) $(SRC)/dpchudp.c
dpchaos.o: $(SRC)/dpchaos.c $(SRC)/dpchaos.h $(SRC)/dpsup.h
$(BUILDMOD) $(SRC)/dpchaos.c
dpchudp: dpchudp.o dpsup.o
$(LINKER) $(LDFLAGS) $(LDOUTF) dpchudp dpchudp.o dpsup.o $(LIBS)
dpchaos: dpchaos.o dpsup.o
$(LINKER) $(LDFLAGS) $(LDOUTF) dpchaos dpchaos.o dpsup.o $(LIBS) $(NETLIBS)
####################################################################
@@ -699,7 +699,7 @@ dpsup.o: $(SRC)/dpsup.c $(SRC)/dpsup.h \
$(SRC)/osdsup.h $(SRC)/word10.h $(BLDSRC)/config.h
$(BUILDMOD) $(SRC)/dpsup.c
dvch11.o: $(SRC)/dvch11.c $(SRC)/dvch11.h $(BLDSRC)/config.h
dvch11.o: $(SRC)/dvch11.c $(SRC)/dvch11.h $(SRC)/dpchaos.h $(BLDSRC)/config.h
$(BUILDMOD) $(SRC)/dvch11.c
dvcty.o: $(SRC)/dvcty.c $(SRC)/dvcty.h $(BLDSRC)/config.h

1578
src/dpchaos.c Normal file

File diff suppressed because it is too large Load Diff

133
src/dpchaos.h Normal file
View File

@@ -0,0 +1,133 @@
/* DPCHAOS.H - Definitions for CHAOS process
*/
/* Copyright © 2005 Björn Victor and Kenneth L. Harrenstien
** All Rights Reserved
**
** This file may become part of the KLH10 Distribution. Use, modification, and
** re-distribution is permitted subject to the terms in the file
** named "LICENSE", which contains the full text of the legal notices
** and should always accompany this Distribution.
**
** This software is provided "AS IS" with NO WARRANTY OF ANY KIND.
**
** This notice (including the copyright and warranty disclaimer)
** must be included in all copies or derivations of this software.
*/
#ifndef DPCHAOS_INCLUDED
#define DPCHAOS_INCLUDED 1
#ifndef DPSUP_INCLUDED
# include "dpsup.h"
#endif
#ifndef OSDNET_INCLUDED
# include "osdnet.h"
#endif
/* Version of DPCHAOS-specific shared memory structure */
#define DPCHAOS_VERSION DPC_VERSION(2,0,0) /* 2.0.0 */
#define IFNAM_LEN PATH_MAX /* at least IFNAMSIZ! */
#ifndef DPCHAOS_CHIP_MAX
# define DPCHAOS_CHIP_MAX 10
#endif
/* Chaos ARP list */
// @@@@ implement something to show the table
#define CHARP_MAX 16
#define CHARP_MAX_AGE (60*5) // ARP cache limit
struct charp_ent {
u_char charp_eaddr[ETHER_ADDR_LEN];
u_short charp_chaddr;
time_t charp_age;
};
/* If a dynamically added CHIP entry is older than this (seconds), it can get updated */
#ifndef DPCHAOS_CHIP_DYNAMIC_AGE_LIMIT
# define DPCHAOS_CHIP_DYNAMIC_AGE_LIMIT (60*5)
#endif
/* Chaos/IP mapping entry - see ch_chip */
struct dpchaos_chip {
unsigned int dpchaos_chip_chaddr; /* Chaos address */
struct in_addr dpchaos_chip_ipaddr; /* IP address */
in_port_t dpchaos_chip_ipport; /* IP port */
time_t dpchaos_chip_lastrcvd; /* When last received, if dynamically added */
};
/* DPCHAOS-specific stuff */
/* C = controlling parent sets, D = Device proc sets */
/* If both, 1st letter indicates inital setter */
struct dpchaos_s {
struct dpc_s dpchaos_dpc; /* CD Standard DPC portion */
int dpchaos_ver; /* C Version of shared struct */
int dpchaos_attrs; /* C Attribute flags */
char dpchaos_ifnam[IFNAM_LEN]; /* CD Interface name if any */
char dpchaos_ifmeth[16]; /* C Interface method */
int dpchaos_ifmeth_chudp; /* C Interface method is CHUDP? */
unsigned short dpchaos_myaddr; /* C my Chaos address */
unsigned char dpchaos_eth[6]; /* CD Ethernet address of interface */
/* probably not used */
int dpchaos_inoff; /* C Offset in buffer of input (I->H) data */
int dpchaos_outoff; /* D Offset in buffer of output (H->I) data */
int dpchaos_backlog; /* C Max sys backlog of rcvd packets */
int dpchaos_dedic; /* C TRUE if dedicated ifc, else shared */
in_port_t dpchaos_port; /* C port for CHUDP protocol */
/* Chaos/IP mapping */
int dpchaos_chip_tlen; /* C table length */
struct dpchaos_chip dpchaos_chip_tbl[DPCHAOS_CHIP_MAX];
// ARP table
struct charp_ent charp_list[CHARP_MAX]; /* D arp table */
int charp_len; /* D arp table length */
};
/* Buffer offset:
CHUDP protocol header is 4 bytes; read/write data after those
*/
struct chudp_header {
char chudp_version;
char chudp_function;
char chudp_arg1;
char chudp_arg2;
};
/* CHUDP protocol port - should perhaps be registered? */
#define CHUDP_PORT 42042
/* Protocol version */
#define CHUDP_VERSION 1
/* Protocol function codes */
#define CHUDP_PKT 1 /* Chaosnet packet */
#ifndef ETHERTYPE_CHAOS
# define ETHERTYPE_CHAOS 0x0804
#endif
// old names for new, new names for old?
#ifndef ARPOP_RREQUEST
#define ARPOP_RREQUEST ARPOP_REVREQUEST // 3 /* request protocol address given hardware */
#endif
#ifndef ARPOP_RREPLY
#define ARPOP_RREPLY ARPOP_REVREPLY // 4 /* response giving protocol address */
#endif
#include "dvch11.h"
#define DPCHAOS_CHUDP_DATAOFFSET (sizeof(struct chudp_header)) // 4 bytes
#define DPCHAOS_ETHER_DATAOFFSET (sizeof(struct ether_header)) // 6+6+2=16 bytes
// room for protocol header + Chaos header + max Chaos data + Chaos hw trailer
#define DPCHAOS_MAXLEN (DPCHAOS_ETHER_DATAOFFSET+CHAOS_HEADERSIZE+CHAOS_MAXDATA+CHAOS_HW_TRAILERSIZE+42) /* some slack */
#define DPCHAOS_CH_DESTOFF 4 /* offset to dest addr in chaos pkt */
#define DPCHAOS_CH_FC 2 /* offset to forwarding count */
/* Commands to and from DP and KLH10 CH11 driver */
/* From 10 to DP */
#define DPCHAOS_RESET 0 /* Reset DP */
#define DPCHAOS_SPKT 1 /* Send data packet to ethernet */
/* From DP to 10 */
#define DPCHAOS_INIT 1 /* DP->10 Finished init */
#define DPCHAOS_RPKT 2 /* DP->10 Received data packet from net */
#endif /* ifndef DPCHUDP_INCLUDED */

View File

@@ -1,912 +0,0 @@
/* DPCHUDP.C - Chaos over UDP process
*/
/* Copyright © 2005 Björn Victor and Kenneth L. Harrenstien
** All Rights Reserved
**
** This file may become part of the KLH10 Distribution. Use, modification, and
** re-distribution is permitted subject to the terms in the file
** named "LICENSE", which contains the full text of the legal notices
** and should always accompany this Distribution.
**
** This software is provided "AS IS" with NO WARRANTY OF ANY KIND.
**
** This notice (including the copyright and warranty disclaimer)
** must be included in all copies or derivations of this software.
*/
/* This is based on DPIMP.C, to some extent.
Some things are irrelevant inheritage from dpimp, and could be cleaned up... */
/*
This is a program intended to be run as a child of the KLH10
PDP-10 emulator, in order to provide a Chaos-over-UDP tunnel.
Given a Chaos packet and a mapping between Chaosnet and IP addresses,
it simply sends the packet encapsulated in a UDP datagram.
The protocol is very similar to the original Chaosnet link protocol,
with the addition of a four-byte protocol header:
| V | F | A1 | A2 |
where
V is the CHUDP protocol version (currently 1)
F is the function code (initially only CHUDP_PKT)
A1, A2 are arguments for the function
For F = CHUDP_PKT, A1 and A2 are zero (ignored), followed by the Chaos packet,
and a trailer
| D1 | D2 | S1 | S2 |
| C1 | C2 |
where D1,D2 are the destination Chaos address (subnet, address)
S1,S2 source
C1,C2 are the two bytes of Chaosnet checksum
(for the Chaos packet + trailer)
*note* that this is (currently) the standard Internet
checksum, not the original Chaosnet checksum
"Messages" to and from the IMP are sent over the standard DP
shared memory mechanism; these are composed of 8-bit bytes in exactly
the same order as if a CH11 was sending or receiving them. Packets to
and from the NET are CHUDP packets.
There are actually two processes active, one which pumps data
from the NET to the CH11-output buffer, and another that pumps in the
opposite direction from an input buffer to the NET. Generally they
are completely independent.
*/
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <signal.h>
#include <stdarg.h>
#include <arpa/inet.h>
#include "klh10.h" /* Get config params */
/* This must precede any other OSD includes to ensure that DECOSF gets
the right flavor sockaddr (sigh)
*/
#define OSN_USE_IPONLY 1 /* Only need IP stuff */
#include "osdnet.h" /* OSD net defs, shared with DPNI20 and DPIMP */
#include <sys/resource.h> /* For setpriority() */
#include <sys/mman.h> /* For mlockall() */
#include "dpchudp.h" /* DPCHUDP specific defs, grabs DPSUP if needed */
/* Globals */
struct dp_s dp; /* Device-Process struct for DP ops */
int cpupid; /* PID of superior CPU process */
int chpid; /* PID of child (R proc) */
int swstatus = TRUE;
int sock; /* UDP socket */
int myaddr; /* My chaos address */
struct in_addr ihost_ip; /* My host IP addr, net order */
/* FROM HERE: replace
"dpchudp" for "dpimp",
"chudp" for "imp",
*/
/* Debug flag reference. Use DBGFLG within functions that have "dpchudp";
* all others must use DP_DBGFLG. Both refer to the same location.
* Caching a local copy of the debug flag is a no-no because it lives
* in a shared memory location that may change at any time.
*/
#define DBGFLG (dpchudp->dpchudp_dpc.dpc_debug)
#define DP_DBGFLG (((struct dpchudp_s *)dp.dp_adr)->dpchudp_dpc.dpc_debug)
/* Local predeclarations */
void chudptohost(struct dpchudp_s *);
void hosttochudp(struct dpchudp_s *);
void net_init(struct dpchudp_s *);
void dumppkt(unsigned char *, int);
void ihl_hhsend(register struct dpchudp_s *dpchudp, int cnt, register unsigned char *pp);
void ip_write(struct in_addr *ipa, in_port_t ipport, unsigned char *buf, int len, struct dpchudp_s *dpchudp);
/* Error and diagnostic output */
static const char progname_i[] = "dpchudp";
static const char progname_r[] = "dpchudp-R";
static const char progname_w[] = "dpchudp-W";
static const char *progname = progname_i;
static void efatal(int num, char *fmt, ...)
{
fprintf(stderr, "\r\n[%s: Fatal error: ", progname);
{
va_list ap;
va_start(ap, fmt);
vfprintf(stderr, fmt, ap);
va_end(ap);
}
fputs("]\r\n", stderr);
/* DP automatically kills any child as well. */
dp_exit(&dp, num);
}
static void esfatal(int num, char *fmt, ...)
{
fprintf(stderr, "\r\n[%s: ", progname);
{
va_list ap;
va_start(ap, fmt);
vfprintf(stderr, fmt, ap);
va_end(ap);
}
fprintf(stderr, " - %s]\r\n", dp_strerror(errno));
/* DP automatically kills any child as well. */
dp_exit(&dp, num);
}
static void dbprint(char *fmt, ...)
{
fprintf(stderr, "[%s: ", progname);
{
va_list ap;
va_start(ap, fmt);
vfprintf(stderr, fmt, ap);
va_end(ap);
}
fputs("]", stderr);
}
static void dbprintln(char *fmt, ...)
{
fprintf(stderr, "[%s: ", progname);
{
va_list ap;
va_start(ap, fmt);
vfprintf(stderr, fmt, ap);
va_end(ap);
}
fputs("]\r\n", stderr);
}
static void error(char *fmt, ...)
{
fprintf(stderr, "\r\n[%s: ", progname);
{
va_list ap;
va_start(ap, fmt);
vfprintf(stderr, fmt, ap);
va_end(ap);
}
fputs("]\r\n", stderr);
}
static void syserr(int num, char *fmt, ...)
{
fprintf(stderr, "\r\n[%s: ", progname);
{
va_list ap;
va_start(ap, fmt);
vfprintf(stderr, fmt, ap);
va_end(ap);
}
fprintf(stderr, " - %s]\r\n", dp_strerror(num));
}
int initdebug = 0;
int
main(int argc, char **argv)
{
register struct dpchudp_s *dpchudp; /* Ptr to shared memory area */
/* Search for a "-debug" command-line argument so that we can start
debug output ASAP if necessary.
*/
if (argc > 1) {
int i;
for (i = 1; i < argc; ++i) {
if (strcmp(argv[i], "-debug") == 0) {
initdebug = TRUE;
break;
}
}
}
if (initdebug)
dbprint("Starting");
/* Right off the bat attempt to get the highest scheduling priority
** we can, since a slow response will cause the 10 monitor to declare
** the interface dead.
*/
#if CENV_SYS_SOLARIS || CENV_SYS_DECOSF || CENV_SYS_XBSD || CENV_SYS_LINUX
if (setpriority(PRIO_PROCESS, 0, -20) < 0)
syserr(errno, "Warning - cannot set high priority");
#elif CENV_SYS_UNIX /* Try old generic Unix call */
if (nice(-20) == -1)
syserr(errno, "Warning - cannot set high priority");
#else
error("Warning - cannot set high priority");
#endif
/* Next priority is to quickly close the vulnerability window;
disable TTY cruft to ensure that any TTY hacking done by superior
process doesn't inadvertently kill us off.
*/
signal(SIGINT, SIG_IGN);
signal(SIGQUIT, SIG_IGN);
if (initdebug)
dbprint("Started");
/* General initialization */
if (!dp_main(&dp, argc, argv)) {
efatal(1, "DP init failed!");
}
dpchudp = (struct dpchudp_s *)dp.dp_adr; /* Make for easier refs */
/* Verify that the structure version is compatible */
if (dpchudp->dpchudp_ver != DPCHUDP_VERSION) {
efatal(1, "Wrong version of DPCHUDP: ch11=%0lx dpchudp=%0lx",
(long)dpchudp->dpchudp_ver, (long)DPCHUDP_VERSION);
}
/* Now can access DP args!
From here on we can use DBGFLG, which is actually a shared
memory reference that dpchudp points to. Check here to accomodate the
case where it's not already set but "-debug" was given as a command
arg; leave it alone if already set since the exact bits have
significance.
*/
if (initdebug && !DBGFLG)
DBGFLG = 1;
if (DBGFLG)
dbprint("DP inited");
/* Always attempt to lock memory since the DP processes are fairly
** small, must respond quickly, and SU mode is more or less guaranteed.
** Skip it only if dp_main() already did it for us.
*/
#if CENV_SYS_DECOSF || CENV_SYS_SOLARIS || CENV_SYS_LINUX
if (!(dpchudp->dpchudp_dpc.dpc_flags & DPCF_MEMLOCK)) {
if (mlockall(MCL_CURRENT|MCL_FUTURE) != 0) {
dbprintln("Warning - cannot lock memory");
}
}
#endif
/* Now set up legacy variables based on parameters passed through
shared DP area.
*/
if ((myaddr = dpchudp->dpchudp_myaddr) == 0) /* My chaos address */
efatal(1, "no CHAOS address specified");
/* Initialize various network info */
net_init(dpchudp);
/* Make this a status (rather than debug) printout? */
if (swstatus) {
int i;
char ipbuf[OSN_IPSTRSIZ];
dbprintln("ifc \"%s\" => chaos %lo",
dpchudp->dpchudp_ifnam, (long)myaddr);
for (i = 0; i < dpchudp->dpchudp_chip_tlen; i++)
dbprintln(" chaos %6o => ip %s:%d",
dpchudp->dpchudp_chip_tbl[i].dpchudp_chip_chaddr,
ip_adrsprint(ipbuf,
(unsigned char *)&dpchudp->dpchudp_chip_tbl[i].dpchudp_chip_ipaddr),
dpchudp->dpchudp_chip_tbl[i].dpchudp_chip_ipport);
}
/* Now start up a child process to handle input */
if (DBGFLG)
dbprint("Forking R process");
if ((chpid = fork()) < 0)
esfatal(1, "fork failed");
if (chpid == 0) {
/* Child process.
** Child inherits signal handlers, which is what we want here.
*/
/* Fix up xfer mechanism so ACK of DP input goes to correct proc */
dp.dp_adr->dpc_frdp.dpx_donpid = getpid();
/* And ensure its memory is locked too, since the lockage isn't
** inherited over a fork(). Don't bother warning if it fails.
*/
#if CENV_SYS_DECOSF || CENV_SYS_SOLARIS || CENV_SYS_LINUX
(void) mlockall(MCL_CURRENT|MCL_FUTURE);
#endif
progname = progname_r; /* Reset progname to indicate identity */
chudptohost(dpchudp); /* Child process handles input */
}
progname = progname_w; /* Reset progname to indicate identity */
hosttochudp(dpchudp); /* Parent process handles output */
return 1; /* Never returns, but placate compiler */
}
/* NET_INIT - Initialize net-related variables,
** given network interface we'll use.
*/
void
net_init(register struct dpchudp_s *dpchudp)
{
struct ifreq ifr;
/* Ensure network device name, if specified, isn't too long */
if (dpchudp->dpchudp_ifnam[0] && (strlen(dpchudp->dpchudp_ifnam)
>= sizeof(ifr.ifr_name))) {
esfatal(0, "interface name \"%s\" too long - max %d",
dpchudp->dpchudp_ifnam, (int)sizeof(ifr.ifr_name));
}
#if 0
/* Don't determine network device to use, if none was specified
** (since we simply use all interfaces in that case).
*/
if (dpchudp->dpchudp_ifnam[0]) {
/* Find host's IP address for this interface */
if (!osn_ifipget(-1, dpchudp->dpchudp_ifnam, (unsigned char *)&ihost_ip)) {
efatal(1,"osn_ifipget failed for \"%s\"", dpchudp->dpchudp_ifnam);
}
#endif
/* Set up appropriate net fd.
*/
{
struct sockaddr_in mysin;
if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
efatal(1,"socket failed: %s", dp_strerror(errno));
mysin.sin_family = AF_INET;
mysin.sin_port = htons(dpchudp->dpchudp_port);
mysin.sin_addr.s_addr = INADDR_ANY;
#if 0
if (dpchudp->dpchudp_ifnam[0] && ihost_ip.s_addr != 0)
mysin.sin_addr.s_addr = ihost_ip.s_addr;
#endif
if (bind(sock, (struct sockaddr *)&mysin, sizeof(mysin)) < 0)
efatal(1,"bind failed: %s", dp_strerror(errno));
}
}
/* CHUDPTOHOST - Child-process main loop for pumping packets from CHUDP to HOST.
** Reads packets from net and feeds CHUDP packets to DP superior process.
*/
#define NINBUFSIZ (DPCHUDP_DATAOFFSET+MAXETHERLEN)
/* Duplicated from dvch11.c - should go in dpsup.c */
static unsigned int
ch_checksum(const unsigned char *addr, int count)
{
/* RFC1071 */
/* Compute Internet Checksum for "count" bytes
* beginning at location "addr".
*/
register long sum = 0;
while( count > 1 ) {
/* This is the inner loop */
sum += *(addr)<<8 | *(addr+1);
addr += 2;
count -= 2;
}
/* Add left-over byte, if any */
if( count > 0 )
sum += * (unsigned char *) addr;
/* Fold 32-bit sum to 16 bits */
while (sum>>16)
sum = (sum & 0xffff) + (sum >> 16);
return (~sum) & 0xffff;
}
void
chudptohost(register struct dpchudp_s *dpchudp)
{
register struct dpx_s *dpx = dp_dpxfr(&dp);
register int cnt;
unsigned char *inibuf;
unsigned char *buffp;
size_t max;
int stoploop = 50;
struct sockaddr_in ip_sender;
socklen_t iplen;
inibuf = dp_xsbuff(dpx, &max); /* Get initial buffer ptr */
/* Tell KLH10 we're initialized and ready by sending initial packet */
dp_xswait(dpx); /* Wait until buff free, in case */
dp_xsend(dpx, DPCHUDP_INIT, 0); /* Send INIT */
if (DBGFLG)
fprintf(stderr, "[dpchudp-R: sent INIT]\r\n");
for (;;) {
/* Make sure that buffer is free before clobbering it */
dp_xswait(dpx); /* Wait until buff free */
if (DBGFLG)
fprintf(stderr, "[dpchudp-R: InWait]\r\n");
/* Set up buffer and initialize offsets */
buffp = inibuf;
/* OK, now do a blocking read on UDP socket! */
errno = 0; /* Clear to make sure it's the actual error */
memset(&ip_sender, 0, sizeof(ip_sender));
iplen = sizeof(ip_sender); /* Supply size of ip_sender, and get actual stored length */
cnt = recvfrom(sock, buffp, DPCHUDP_MAXLEN, 0, (struct sockaddr *)&ip_sender, &iplen);
if (cnt <= DPCHUDP_DATAOFFSET) {
if (DBGFLG)
fprintf(stderr, "[dpchudp-R: ERead=%d, Err=%d]\r\n",
cnt, errno);
if (cnt < 0 && (errno == EINTR)) /* Ignore spurious signals */
continue;
/* Error of some kind */
fprintf(stderr, "[dpchudp-R: Eread = %d, ", cnt);
if (cnt < 0) {
if (--stoploop <= 0)
efatal(1, "Too many retries, aborting]");
fprintf(stderr, "errno %d = %s]\r\n",
errno, dp_strerror(errno));
} else if (cnt > 0)
fprintf(stderr, "no chudp data]\r\n");
else fprintf(stderr, "no packet]\r\n");
continue; /* For now... */
}
if (DBGFLG) {
if (DBGFLG & 0x4) {
fprintf(stderr, "\r\n[dpchudp-R: Read=%d\r\n", cnt);
dumppkt(buffp, cnt);
fprintf(stderr, "]");
}
else
fprintf(stderr, "[dpchudp-R: Read=%d]", cnt);
}
/* Have packet, now dispatch it to host */
if (((struct chudp_header *)buffp)->chudp_version != CHUDP_VERSION) {
if (DBGFLG)
error("wrong protocol version %d",
((struct chudp_header *)buffp)->chudp_version);
continue;
}
switch (((struct chudp_header *)buffp)->chudp_function) {
case CHUDP_PKT:
break; /* deliver it */
default:
error("Unknown CHUDP function: %0X",
((struct chudp_header *)buffp)->chudp_function);
continue;
}
/* Check who it's from, update Chaos/IP mapping */
{
/* check that the packet is complete:
4 bytes CHUDP header, Chaos header, add Chaos pkt length, plus 6 bytes trailer */
int chalen = ((buffp[DPCHUDP_DATAOFFSET+2] & 0xf)<<4) | buffp[DPCHUDP_DATAOFFSET+3];
int datalen = (DPCHUDP_DATAOFFSET + CHAOS_HEADERSIZE + chalen);
int chafrom = (buffp[cnt-4]<<8) | buffp[cnt-3];
char *ip = inet_ntoa(ip_sender.sin_addr);
in_port_t port = ntohs(ip_sender.sin_port);
time_t now = time(NULL);
int i, cks;
if ((cks = ch_checksum(buffp+DPCHUDP_DATAOFFSET,cnt-DPCHUDP_DATAOFFSET)) != 0) {
if (1 || DBGFLG)
dbprintln("Bad checksum 0x%x",cks);
/* #### must free buffer first(?) */
/* return; */
}
if (cnt < datalen + CHAOS_HW_TRAILERSIZE) { /* may have a byte of padding */
if (1 || DBGFLG) {
dbprintln("Rcvd bad length: %d. < %d. (expected), chaos data %d bytes, errno %d",
cnt, datalen + CHAOS_HW_TRAILERSIZE, chalen, errno);
dumppkt(buffp, cnt);
}
/* #### must free buffer first(?) */
/* return; */
}
#if 0
if (DBGFLG) {
dbprintln("Rcv from chaos %o = ip %s port %d., %d. bytes (datalen %d)",
chafrom,
ip, port,
cnt, datalen);
dumppkt(buffp,cnt);
}
#endif
/* #### remove cks when buffer freed instead */
if ((cks == 0) && (chafrom != myaddr) && (dpchudp->dpchudp_chip_tlen < DPCHUDP_CHIP_MAX)) {
/* Space available, see if we need to add this */
/* Look for old entries: if one is found which is either
static (from config file) or sufficiently fresh,
keep it and update the freshness (if not static) */
for (i = 0; i < dpchudp->dpchudp_chip_tlen; i++)
if (chafrom == dpchudp->dpchudp_chip_tbl[i].dpchudp_chip_chaddr) {
if (dpchudp->dpchudp_chip_tbl[i].dpchudp_chip_lastrcvd != 0) {
if (now - dpchudp->dpchudp_chip_tbl[i].dpchudp_chip_lastrcvd >
DPCHUDP_CHIP_DYNAMIC_AGE_LIMIT) {
/* Old, update it (in case he moved) */
if (1 || DBGFLG)
dbprintln("Updating CHIP entry %d for %o/%s:%d",
i, chafrom, ip, port);
dpchudp->dpchudp_chip_tbl[i].dpchudp_chip_ipport = port;
memcpy(&dpchudp->dpchudp_chip_tbl[i].dpchudp_chip_ipaddr, &ip_sender.sin_addr, IP_ADRSIZ);
}
/* update timestamp */
dpchudp->dpchudp_chip_tbl[i].dpchudp_chip_lastrcvd = now;
}
chafrom = -1; /* Not it shouldn't be added */
break;
}
if (chafrom > 0) {
/* It's OK to write here, the other fork will see it when tlen is updated */
i = dpchudp->dpchudp_chip_tlen;
if (1 || DBGFLG)
dbprintln("Adding CHIP entry %d for %o/%s:%d",
i, chafrom, ip, port);
dpchudp->dpchudp_chip_tbl[i].dpchudp_chip_chaddr = chafrom;
dpchudp->dpchudp_chip_tbl[i].dpchudp_chip_ipport = port;
dpchudp->dpchudp_chip_tbl[i].dpchudp_chip_lastrcvd = now;
memcpy(&dpchudp->dpchudp_chip_tbl[i].dpchudp_chip_ipaddr, &ip_sender.sin_addr, IP_ADRSIZ);
dpchudp->dpchudp_chip_tlen++;
}
#if 0
else if (0 && DBGFLG) {
dbprintln("Already know chaos %o",chafrom);
}
#endif
}
else if ((dpchudp->dpchudp_chip_tlen >= DPCHUDP_CHIP_MAX) && DBGFLG) {
dbprintln("CHIP table full - cannot add %o", chafrom);
}
}
ihl_hhsend(dpchudp, cnt, buffp);
}
}
/* Send regular message from CHUDP to HOST.
*/
void
ihl_hhsend(register struct dpchudp_s *dpchudp,
int cnt,
register unsigned char *pp)
/* "pp" is packet data ptr, has room for header preceding */
{
/* Send up to host! Assume we're already in shared buffer. */
register struct dpx_s *dpx = dp_dpxfr(&dp);
size_t off = DPCHUDP_DATAOFFSET;
dpchudp->dpchudp_inoff = off; /* Tell host what offset is */
dp_xsend(dpx, DPCHUDP_RPKT, cnt-off);
if (DBGFLG)
fprintf(stderr, "[dpchudp-R: sent RPKT %d+%d]", (int)off, cnt-off);
}
/* HOSTTOCHUDP - Parent main loop for pumping packets from HOST to CHUDP.
** Reads CHUDP message from DP superior
** and interprets it. If a regular message, bundles it up and
** outputs to NET.
*/
void
hosttochudp(register struct dpchudp_s *dpchudp)
{
register struct dpx_s *dpx = dp_dpxto(&dp); /* Get ptr to "To-DP" dpx */
register unsigned char *buff;
size_t max;
register int rcnt;
unsigned char *inibuf;
struct in_addr ipdest;
in_port_t ipport;
struct chudp_header chuhdr = { CHUDP_VERSION, CHUDP_PKT, 0, 0 };
inibuf = dp_xrbuff(dpx, &max); /* Get initial buffer ptr */
if (DBGFLG)
fprintf(stderr, "[dpchudp-W: Starting loop]\r\n");
for (;;) {
if (DBGFLG)
fprintf(stderr, "[dpchudp-W: CmdWait]\r\n");
/* Wait until 10 has a command for us */
dp_xrwait(dpx); /* Wait until something there */
/* Process command from 10! */
switch (dp_xrcmd(dpx)) {
default:
fprintf(stderr, "[dpchudp: Unknown cmd %d]\r\n", dp_xrcmd(dpx));
dp_xrdone(dpx);
continue;
case DPCHUDP_SPKT: /* Send regular packet */
rcnt = dp_xrcnt(dpx);
/* does rcnt include chudp header size? yes. */
buff = inibuf;
memcpy(buff, (void *)&chuhdr, sizeof(chuhdr)); /* put in CHUDP hdr */
if (DBGFLG) {
if (DBGFLG & 0x2) {
fprintf(stderr, "\r\n[dpchudp-W: Sending %d\r\n", rcnt);
dumppkt(buff, rcnt);
fprintf(stderr, "]");
}
else
fprintf(stderr, "[dpchudp-W: SPKT %d]", rcnt);
}
break;
}
/* Come here to handle output packet */
#if 1
{
int chlen = ((buff[DPCHUDP_DATAOFFSET+2] & 0xf) << 4) | buff[DPCHUDP_DATAOFFSET+3];
if ((chlen + CHAOS_HEADERSIZE + DPCHUDP_DATAOFFSET + CHAOS_HW_TRAILERSIZE) > rcnt) {
if (1 || DBGFLG)
dbprintln("NOT sending less than packet: pkt len %d, expected %d (Chaos data len %d)",
rcnt, (chlen + CHAOS_HEADERSIZE + DPCHUDP_DATAOFFSET + CHAOS_HW_TRAILERSIZE),
chlen);
dp_xrdone(dpx); /* ack it to dvch11, but */
return; /* #### don't send it! */
}
}
#endif
/* find IP destination given chaos packet */
if (hi_iproute(&ipdest, &ipport, &buff[DPCHUDP_DATAOFFSET], rcnt - DPCHUDP_DATAOFFSET,dpchudp)) {
ip_write(&ipdest, ipport, buff, rcnt, dpchudp);
}
/* Command done, tell 10 we're done with it */
if (DBGFLG)
fprintf(stderr, "[dpchudp-W: CmdDone]");
dp_xrdone(dpx);
}
}
int
hi_lookup(struct dpchudp_s *dpchudp,
struct in_addr *ipa, /* Dest IP addr to be put here */
in_port_t *ipport, /* dest IP port to be put here */
unsigned int chdest, /* look up this chaos destination */
int sbnmatch) /* just match subnet part */
{
int i;
for (i = 0; i < dpchudp->dpchudp_chip_tlen; i++)
if (
#if DPCHUDP_DO_ROUTING
((!sbnmatch && (chdest == dpchudp->dpchudp_chip_tbl[i].dpchudp_chip_chaddr))
||
/* handle subnet matching */
(sbnmatch && ((chdest >> 8) == (dpchudp->dpchudp_chip_tbl[i].dpchudp_chip_chaddr >> 8))))
#else
(chdest == dpchudp->dpchudp_chip_tbl[i].dpchudp_chip_chaddr)
#endif
&& dpchudp->dpchudp_chip_tbl[i].dpchudp_chip_ipaddr.s_addr != 0) {
memcpy(ipport, &dpchudp->dpchudp_chip_tbl[i].dpchudp_chip_ipport, sizeof(in_port_t));
memcpy((void *)ipa, &dpchudp->dpchudp_chip_tbl[i].dpchudp_chip_ipaddr,
sizeof(struct in_addr));
if (DBGFLG) {
char ipbuf[OSN_IPSTRSIZ];
dbprintln("found Chaos address %o at %s:%d",
chdest, ip_adrsprint(ipbuf, (unsigned char *)ipa), *ipport);
}
return TRUE;
}
if (DBGFLG)
dbprintln("failed looking up Chaos address %o",chdest);
return FALSE;
}
/* HI_IPROUTE - Determine where to actually send Chaos packet.
** Fill in ipa with IP address, based on Chaos header in lp,
** or if DPCHUDP_DO_ROUTING, based on Chaos trailer,
** and also do some basic routing if destination is DEFAULT_CHAOS_ROUTER (3040)
** or just some other subnet we know about.
*/
int
hi_iproute(struct in_addr *ipa, /* Dest IP addr to be put here */
in_port_t *ipport, /* dest IP port to be put here */
unsigned char *lp, /* Ptr to start of Chaos packet */
int cnt, /* Cnt of data including header */
struct dpchudp_s *dpchudp)
{
unsigned int chdest;
#if DPCHUDP_DO_ROUTING
unsigned int hwdest;
#endif
if (cnt < CHAOS_HEADERSIZE) {
error("Chaos packet too short: %d", cnt);
return FALSE;
}
#if !DPCHUDP_DO_ROUTING
/* Derive destination IP address from Chaos header */
chdest = lp[DPCHUDP_CH_DESTOFF]<<8 | lp[DPCHUDP_CH_DESTOFF+1];
#else
/* Use hw trailer instead */
hwdest = lp[cnt-6] << 8 | lp[cnt-5];
if ((hwdest == DEFAULT_CHAOS_ROUTER) || ((hwdest >> 8) != (myaddr >> 8))) {
/* Look up header dest,
if successful, change trailer dest, increase FW count, recompute checksum */
if ((lp[DPCHUDP_CH_FC] >> 4) == 0xf) /* FC about to wrap */
return FALSE; /* drop it */
/* look in header */
chdest = lp[DPCHUDP_CH_DESTOFF]<<8 | lp[DPCHUDP_CH_DESTOFF+1];
} else
/* my subnet */
chdest = hwdest;
if (DBGFLG)
dbprintln("looking for route to chaos %o (hw %o) (FC %d.)", chdest, hwdest,
lp[DPCHUDP_CH_FC] >> 4);
#endif
if (hi_lookup(dpchudp, ipa, ipport, chdest, 0)
#if DPCHUDP_DO_ROUTING
/* try subnet match */
|| ((chdest != hwdest) && hi_lookup(dpchudp, ipa, ipport, chdest, 1))
#endif
) {
#if DPCHUDP_DO_ROUTING
if (chdest != hwdest) {
int cks;
if (DBGFLG)
dbprintln("found route");
/* change hw dest */
lp[cnt-6] = chdest >> 8;
lp[cnt-5] = chdest & 0xff;
/* make sure it's got the right hw source addr */
lp[cnt-4] = myaddr >> 8;
lp[cnt-3] = myaddr & 0xff;
/* increase FW count */
lp[DPCHUDP_CH_FC] = (lp[DPCHUDP_CH_FC] & 0xf) | ((lp[DPCHUDP_CH_FC]>>4)+1)<<4;
/* recompute checksum */
cks = ch_checksum(lp,cnt-2); /* w/o orig checksum */
lp[cnt-2] = cks >> 8;
lp[cnt-1] = cks & 0xff;
}
#endif
return TRUE;
}
return FALSE;
}
/* IP_WRITE - Send IP packet out over UDP
*/
void
ip_write(struct in_addr *ipa, in_port_t ipport, unsigned char *buf, int len, struct dpchudp_s *dpchudp)
{
struct sockaddr_in sin;
if (DBGFLG) {
dbprintln("sending to port %d",ipport);
}
sin.sin_family = AF_INET;
sin.sin_port = htons(ipport);
memcpy((void *)&sin.sin_addr, ipa, sizeof(struct in_addr));
if (sendto(sock, buf, len, 0, (struct sockaddr *) &sin, (socklen_t) (sizeof(sin))) != len) {
error("sendto failed - %s", dp_strerror(errno));
}
}
void
dumppkt_raw(unsigned char *ucp, int cnt)
{
int i;
while (cnt > 0) {
for (i = 8; --i >= 0 && cnt > 0;) {
if (--cnt >= 0)
fprintf(stderr, " %02x", *ucp++);
if (--cnt >= 0)
fprintf(stderr, "%02x", *ucp++);
}
fprintf(stderr, "\r\n");
}
}
static char
*ch_opc[] = { "NIL",
"RFC", "OPN", "CLS", "FWD", "ANS", "SNS", "STS", "RUT",
"LOS", "LSN", "MNT", "EOF", "UNC", "BRD" };
static char *
ch_opcode(int op)
{
char buf[7];
if (op < 017 && op > 0)
return ch_opc[op];
else if (op == 0200)
return "DAT";
else if (op == 0300)
return "DWD";
else
return "bogus";
}
void
dumppkt(unsigned char *ucp, int cnt)
{
int i, row;
fprintf(stderr,"CHUDP version %d, function %d\r\n", ucp[0], ucp[1]);
fprintf(stderr,"Opcode: %o (%s), unused: %o\r\nFC: %o, Nbytes %o\r\n",
ucp[0+DPCHUDP_DATAOFFSET], ch_opcode(ucp[0+DPCHUDP_DATAOFFSET]),
ucp[1+DPCHUDP_DATAOFFSET], ucp[2+DPCHUDP_DATAOFFSET]>>4, ((ucp[2+DPCHUDP_DATAOFFSET]&0xf)<<4) | ucp[3+DPCHUDP_DATAOFFSET]);
fprintf(stderr,"Dest host: %o, index %o\r\nSource host: %o, index %o\r\n",
(ucp[4+DPCHUDP_DATAOFFSET]<<8)|ucp[5+DPCHUDP_DATAOFFSET], (ucp[6+DPCHUDP_DATAOFFSET]<<8)|ucp[7+DPCHUDP_DATAOFFSET],
(ucp[8+DPCHUDP_DATAOFFSET]<<8)|ucp[9+DPCHUDP_DATAOFFSET], (ucp[10+DPCHUDP_DATAOFFSET]<<8)|ucp[11+DPCHUDP_DATAOFFSET]);
fprintf(stderr,"Packet #%o\r\nAck #%o\r\n",
(ucp[12+DPCHUDP_DATAOFFSET]<<8)|ucp[13+DPCHUDP_DATAOFFSET], (ucp[14+DPCHUDP_DATAOFFSET]<<8)|ucp[15+DPCHUDP_DATAOFFSET]);
fprintf(stderr,"Data:\r\n");
/* Skip headers */
ucp += DPCHUDP_DATAOFFSET+CHAOS_HEADERSIZE;
/* Show only data portion */
cnt -= DPCHUDP_DATAOFFSET+CHAOS_HEADERSIZE+CHAOS_HW_TRAILERSIZE;
for (row = 0; row*8 < cnt; row++) {
for (i = 0; (i < 8) && (i+row*8 < cnt); i++) {
fprintf(stderr, " %02x", ucp[i+row*8]);
fprintf(stderr, "%02x", ucp[(++i)+row*8]);
}
fprintf(stderr, " (hex)\r\n");
#if 0
for (i = 0; (i < 8) && (i+row*8 < cnt); i++) {
fprintf(stderr, " %2c", ucp[i+row*8]);
fprintf(stderr, "%2c", ucp[(++i)+row*8]);
}
fprintf(stderr, " (chars)\r\n");
for (i = 0; (i < 8) && (i+row*8 < cnt); i++) {
fprintf(stderr, " %2c", ucp[i+1+row*8]);
fprintf(stderr, "%2c", ucp[(i++)+row*8]);
}
fprintf(stderr, " (11-chars)\r\n");
#endif
}
/* Now show trailer */
fprintf(stderr,"HW trailer:\r\n Dest: %o\r\n Source: %o\r\n Checksum: 0x%x\r\n",
(ucp[cnt]<<8)|ucp[cnt+1],(ucp[cnt+2]<<8)|ucp[cnt+3],(ucp[cnt+4]<<8)|ucp[cnt+5]);
}
/* Add OSDNET shared code here */
/* OSDNET is overkill and assumes a lot of packet filter defs,
which we're not at all interested in providing */
#if 0
# include "osdnet.c"
#else
char *
ip_adrsprint(char *cp, unsigned char *ia)
{
sprintf(cp, "%d.%d.%d.%d", ia[0], ia[1], ia[2], ia[3]);
return cp;
}
#endif

View File

@@ -1,108 +0,0 @@
/* DPCHUDP.H - Definitions for CHUDP process
*/
/* Copyright © 2005 Björn Victor and Kenneth L. Harrenstien
** All Rights Reserved
**
** This file may become part of the KLH10 Distribution. Use, modification, and
** re-distribution is permitted subject to the terms in the file
** named "LICENSE", which contains the full text of the legal notices
** and should always accompany this Distribution.
**
** This software is provided "AS IS" with NO WARRANTY OF ANY KIND.
**
** This notice (including the copyright and warranty disclaimer)
** must be included in all copies or derivations of this software.
*/
#ifndef DPCHUDP_INCLUDED
#define DPCHUDP_INCLUDED 1
#ifndef DPSUP_INCLUDED
# include "dpsup.h"
#endif
#ifndef OSDNET_INCLUDED
# include "osdnet.h"
#endif
/* Version of DPCHUDP-specific shared memory structure */
#define DPCHUDP_VERSION ((1<<10) | (0<<5) | (0)) /* 1.0.0 */
#ifndef DPCHUDP_CHIP_MAX
# define DPCHUDP_CHIP_MAX 10
#endif
/* If a dynamically added CHIP entry is older than this (seconds), it can get updated */
#ifndef DPCHUDP_CHIP_DYNAMIC_AGE_LIMIT
# define DPCHUDP_CHIP_DYNAMIC_AGE_LIMIT (60*5)
#endif
/* Chaos/IP mapping entry - see ch_chip */
struct dpchudp_chip {
unsigned int dpchudp_chip_chaddr; /* Chaos address */
struct in_addr dpchudp_chip_ipaddr; /* IP address */
in_port_t dpchudp_chip_ipport; /* IP port */
time_t dpchudp_chip_lastrcvd; /* When last received, if dynamically added */
};
/* DPCHUDP-specific stuff */
/* C = controlling parent sets, D = Device proc sets */
/* If both, 1st letter indicates inital setter */
struct dpchudp_s {
struct dpc_s dpchudp_dpc; /* CD Standard DPC portion */
int dpchudp_ver; /* C Version of shared struct */
int dpchudp_attrs; /* C Attribute flags */
char dpchudp_ifnam[16]; /* CD Interface name if any */
unsigned int dpchudp_myaddr;
/* probably not used */
int dpchudp_inoff; /* C Offset in buffer of input (I->H) data */
int dpchudp_outoff; /* D Offset in buffer of output (H->I) data */
int dpchudp_backlog; /* C Max sys backlog of rcvd packets */
int dpchudp_dedic; /* C TRUE if dedicated ifc, else shared */
in_port_t dpchudp_port; /* C port for CHUDP protocol */
/* Chaos/IP mapping */
int dpchudp_chip_tlen; /* C table length */
struct dpchudp_chip dpchudp_chip_tbl[DPCHUDP_CHIP_MAX];
};
/* Buffer offset:
CHUDP protocol header is 4 bytes; read/write data after those
*/
struct chudp_header {
char chudp_version;
char chudp_function;
char chudp_arg1;
char chudp_arg2;
};
/* CHUDP protocol port - should perhaps be registered? */
#define CHUDP_PORT 42042
/* Protocol version */
#define CHUDP_VERSION 1
/* Protocol function codes */
#define CHUDP_PKT 1 /* Chaosnet packet */
#include "dvch11.h"
#define DPCHUDP_DATAOFFSET (sizeof(struct chudp_header))
#define DPCHUDP_MAXLEN (CHAOS_MAXDATA+DPCHUDP_DATAOFFSET+42) /* some slack */
#ifndef DPCHUDP_DO_ROUTING
# define DPCHUDP_DO_ROUTING 1
#endif
#define DEFAULT_CHAOS_ROUTER 03040 /* default router (MX-11.LCS.MIT.EDU) */
#define DPCHUDP_CH_DESTOFF 4 /* offset to dest addr in chaos pkt */
#define DPCHUDP_CH_FC 2 /* offset to forwarding count */
/* Commands to and from DP and KLH10 CH11 driver */
/* From 10 to DP */
#define DPCHUDP_RESET 0 /* Reset DP */
#define DPCHUDP_SPKT 1 /* Send data packet to ethernet */
/* From DP to 10 */
#define DPCHUDP_INIT 1 /* DP->10 Finished init */
#define DPCHUDP_RPKT 2 /* DP->10 Received data packet from net */
#endif /* ifndef DPCHUDP_INCLUDED */

View File

@@ -2,7 +2,7 @@
*/
/* $Id: dvch11.c,v 2.3 2001/11/10 21:28:59 klh Exp $
*/
/* Copyright © 2005 Björn Victor and Kenneth L. Harrenstien
/* Copyright © 2005, 2018 Björn Victor and Kenneth L. Harrenstien
** All Rights Reserved
**
** This file may become part of the KLH10 Distribution. Use, modification, and
@@ -31,7 +31,7 @@
** r/w-only definitions of CSR bits is sometimes wrong (e.g. "transmit
** done").
**
** Based on dvlhdh.c, with dpchudp.c based on dpimp.c.
** Based on dvlhdh.c, with dpchaos.c based on dpimp.c.
** (Some things may still be irrelevant inheritage from dvlhdh, and could be cleaned up...)
*/
@@ -55,7 +55,7 @@ static int decosfcclossage;
#include "dvuba.h"
#include "dvch11.h"
#include "dpchudp.h"
#include "dpchaos.h"
#ifndef KLH10_CH11_USE_GETHOSTBYNAME
# define KLH10_CH11_USE_GETHOSTBYNAME 1
@@ -65,7 +65,7 @@ static int decosfcclossage;
# include <netdb.h>
#endif
#define CHUDPBUFSIZ (DPCHUDP_MAXLEN+500) /* Plenty of slop */
#define CHAOSBUFSIZ (DPCHAOS_MAXLEN+500) /* Plenty of slop */
#ifndef CH11_NSUP
@@ -73,16 +73,16 @@ static int decosfcclossage;
#endif
#ifndef CH11_CHIP_MAX
# define CH11_CHIP_MAX 10 /* max Chaos/IP mappings - see DPCHUDP_CHIP_MAX */
# define CH11_CHIP_MAX 10 /* max Chaos/IP mappings - see DPCHAOS_CHIP_MAX */
#endif
#if CH11_CHIP_MAX > DPCHUDP_CHIP_MAX
# error "DPCHUDP_CHIP_MAX must be at least CH11_CHIP_MAX"
#if CH11_CHIP_MAX > DPCHAOS_CHIP_MAX
# error "DPCHAOS_CHIP_MAX must be at least CH11_CHIP_MAX"
#endif
#define REG(u) ((u)->ch_reg)
/* Chaos/IP mapping entry - see dpchudp_chip */
/* Chaos/IP mapping entry - see dpchaos_chip */
struct ch_chip {
unsigned int ch_chip_chaddr; /* Chaos address */
struct in_addr ch_chip_ipaddr; /* IP address */
@@ -108,10 +108,11 @@ struct ch11 {
/* Misc config info not set elsewhere */
char *ch_ifnam; /* Native platform's interface name */
char *ch_ifmeth; /* Native platform's interface access method */
int ch_dedic; /* TRUE if interface dedicated (else shared) */
int ch_backlog; /* Max # input msgs to queue up in kernel */
unsigned int ch_myaddr; /* My Chaos address */
in_port_t ch_chudp_port; /* CHUDP port to use */
in_port_t ch_chudp_port; /* CHUDP port to use */
/* DP stuff */
char *ch_dpname; /* Pointer to dev process pathname */
@@ -153,15 +154,15 @@ static void ch_idone(struct ch11 *ch);
static void ch_odone(struct ch11 *ch);
static void showpkt(FILE *f, char *id, unsigned char *buf, int cnt);
/* Virtual CHUDP low-level stuff */
/* Virtual CHAOS low-level stuff */
/* static */
int chudp_init(struct ch11 *ch, FILE *of);
static int chudp_start(struct ch11 *ch);
static void chudp_stop(struct ch11 *ch);
static void chudp_kill(struct ch11 *ch);
static int chudp_incheck(struct ch11 *ch);
static void chudp_inxfer(struct ch11 *ch);
static int chudp_outxfer(struct ch11 *ch);
int chaos_init(struct ch11 *ch, FILE *of);
static int chaos_start(struct ch11 *ch);
static void chaos_stop(struct ch11 *ch);
static void chaos_kill(struct ch11 *ch);
static int chaos_incheck(struct ch11 *ch);
static void chaos_inxfer(struct ch11 *ch);
static int chaos_outxfer(struct ch11 *ch);
/* Configuration Parameters */
@@ -180,8 +181,9 @@ static int chudp_outxfer(struct ch11 *ch);
\
prmdef(CH11P_MYADDR, "myaddr"),/* My Chaosnet address */\
prmdef(CH11P_CHUPORT, "chudpport"), /* CHUDP port to use */\
prmdef(CH11P_CHIP, "chip") /* Chaos/IP mapping */
prmdef(CH11P_CHIP, "chip"), /* Chaos/IP mapping */\
\
prmdef(CH11P_IFMETH, "ifmeth") /* Interface method (chudp, pcap, etc) */
enum {
# define prmdef(i,s) i
@@ -212,6 +214,7 @@ ch11_conf(FILE *f, char *s, struct ch11 *ch)
struct prmstate_s prm;
char buff[200];
long lval;
int chudp_params_set = 0;
/* First set defaults for all configurable parameters
Unfortunately there's currently no way to access the UBA # that
@@ -224,7 +227,7 @@ ch11_conf(FILE *f, char *s, struct ch11 *ch)
ch->ch_dedic = FALSE;
ch->ch_dpidly = 0;
ch->ch_dpdbg = FALSE;
ch->ch_dpname = "dpchudp"; /* Pathname of device subproc */
ch->ch_dpname = "dpchaos"; /* Pathname of device subproc */
ch->ch_chip_tlen = 0;
ch->ch_chudp_port = CHUDP_PORT;
@@ -286,7 +289,8 @@ ch11_conf(FILE *f, char *s, struct ch11 *ch)
case CH11P_MYADDR: /* Parse as octal number */
if (!prm.prm_val || !s_tonum(prm.prm_val, &lval))
break;
if ((lval < 1) || (lval >= 0xffff)) {
if (((lval & 0xff00) == 0) || ((lval & 0xff) == 0) || (lval >= 0xffff)) {
// subnet part must be nonzero, host part too, also max 16 bit
fprintf(f, "CH11 MYADDR must be a valid Chaosnet address\n");
ret = FALSE;
} else
@@ -294,6 +298,7 @@ ch11_conf(FILE *f, char *s, struct ch11 *ch)
continue;
case CH11P_CHUPORT:
chudp_params_set = 1;
if (!prm.prm_val || !s_todnum(prm.prm_val, &lval))
break;
if ((lval < 1) || (lval >= 0xffff)) {
@@ -304,6 +309,7 @@ ch11_conf(FILE *f, char *s, struct ch11 *ch)
continue;
case CH11P_CHIP:
chudp_params_set = 1;
if (ch->ch_chip_tlen >= CH11_CHIP_MAX) {
fprintf(f,"CH11 Chaos/IP table full\n");
break;
@@ -404,6 +410,12 @@ ch11_conf(FILE *f, char *s, struct ch11 *ch)
ch->ch_dpname = s_dup(prm.prm_val);
continue;
case CH11P_IFMETH: /* Parse as simple string */
if (!prm.prm_val)
break;
ch->ch_ifmeth = s_dup(prm.prm_val);
continue;
}
ret = FALSE;
fprintf(f, "CH11 param \"%s\": ", prm.prm_name);
@@ -429,6 +441,20 @@ ch11_conf(FILE *f, char *s, struct ch11 *ch)
"CH11 param \"myaddr\" must be set\n");
return FALSE;
}
if (ch->ch_ifmeth) {
if ((strcasecmp(ch->ch_ifmeth,"chudp") != 0) &&
(strcasecmp(ch->ch_ifmeth,"pcap") != 0)) {
fprintf(f,"CH11 param \"ifmeth\" only supports \"chudp\" and \"pcap\" for now\n");
return FALSE;
}
} else if (chudp_params_set) {
// backwards compat
fprintf(f, "CH11 assuming \"chudp\" interface method\n");
ch->ch_ifmeth = s_dup("chudp");
} else {
fprintf(f, "CH11 does not know which interface method to use, none specified?\n");
return FALSE;
}
return ret;
}
@@ -491,9 +517,9 @@ dvch11_create(FILE *f, char *s)
static void
ch11_cmd_dpdebug(struct ch11 *ch, FILE *of, int val)
{
struct dpchudp_s *dpc = (struct dpchudp_s *)ch->ch_dp.dp_adr;
fprintf(of,"Old value: %d. New value: %d.\n", dpc->dpchudp_dpc.dpc_debug, val);
dpc->dpchudp_dpc.dpc_debug = val;
struct dpchaos_s *dpc = (struct dpchaos_s *)ch->ch_dp.dp_adr;
fprintf(of,"Old value: %d. New value: %d.\n", dpc->dpchaos_dpc.dpc_debug, val);
dpc->dpchaos_dpc.dpc_debug = val;
}
static void
@@ -504,38 +530,74 @@ ch11_cmd_chiptable(struct ch11 *ch, FILE *of)
char ipa[4*4];
struct tm *ltime;
char last[128];
struct dpchudp_chip *chip;
struct dpchudp_s *dpc = (struct dpchudp_s *)ch->ch_dp.dp_adr;
struct dpchaos_chip *chip;
struct dpchaos_s *dpc = (struct dpchaos_s *)ch->ch_dp.dp_adr;
if (!dpc) {
fprintf(of,"Can't find DP!\n");
return;
}
n = dpc->dpchudp_chip_tlen;
n = dpc->dpchaos_chip_tlen;
fprintf(of,"Currently %d entries in Chaos/IP table\n",n);
if (n > 0) {
fprintf(of,"Chaos IP Port Last received\n");
for (i = 0; i < n; i++) {
chip = &dpc->dpchudp_chip_tbl[i];
ip = (unsigned char *)&chip->dpchudp_chip_ipaddr.s_addr;
chip = &dpc->dpchaos_chip_tbl[i];
ip = (unsigned char *)&chip->dpchaos_chip_ipaddr.s_addr;
sprintf(ipa,"%d.%d.%d.%d", ip[0], ip[1], ip[2], ip[3]);
if (chip->dpchudp_chip_lastrcvd != 0) {
ltime = localtime(&chip->dpchudp_chip_lastrcvd);
if (chip->dpchaos_chip_lastrcvd != 0) {
ltime = localtime(&chip->dpchaos_chip_lastrcvd);
strftime(last, sizeof(last), "%Y-%m-%d %T", ltime);
} else
strcpy(last,"[static]");
fprintf(of,"%6o %-15s %d. %s\n",
chip->dpchudp_chip_chaddr,
chip->dpchaos_chip_chaddr,
ipa,
chip->dpchudp_chip_ipport,
chip->dpchaos_chip_ipport,
last);
}
}
}
void ch11_cmd_print_arp_table(struct ch11 *ch, FILE *of)
{
int i;
time_t age;
struct dpchaos_s *dpc = (struct dpchaos_s *)ch->ch_dp.dp_adr;
if (dpc->charp_len > 0) {
fprintf(of,"Chaos ARP table:\r\n"
"Chaos\tEther\t\t\tAge (s)\r\n");
for (i = 0; i < dpc->charp_len; i++) {
age = (time(NULL) - dpc->charp_list[i].charp_age);
fprintf(of,"%#o\t\%02X:%02X:%02X:%02X:%02X:%02X\t%lu\t%s\r\n",
dpc->charp_list[i].charp_chaddr,
dpc->charp_list[i].charp_eaddr[0],
dpc->charp_list[i].charp_eaddr[1],
dpc->charp_list[i].charp_eaddr[2],
dpc->charp_list[i].charp_eaddr[3],
dpc->charp_list[i].charp_eaddr[4],
dpc->charp_list[i].charp_eaddr[5],
age, age > CHARP_MAX_AGE ? "(old)" : "");
}
} else
fprintf(of,"Chaos ARP table empty\r\n");
}
static void
ch11_cmd_status(struct ch11 *ch, FILE *of)
{
fprintf(of,"My CHAOS address: 0%o, CHUDP port: %d.\n", ch->ch_myaddr, ch->ch_chudp_port);
struct dpchaos_s *dpc = (struct dpchaos_s *)ch->ch_dp.dp_adr;
fprintf(of,"My CHAOS address: 0%o.\n", ch->ch_myaddr);
if (dpc->dpchaos_ifmeth_chudp)
fprintf(of, " CHUDP port: %d.\n", ch->ch_chudp_port);
else {
if (dpc->dpchaos_ifnam)
fprintf(of, " Using ifc=\"%s\"", dpc->dpchaos_ifnam);
fprintf(of, " ether addr %02X:%02X:%02X:%02X:%02X:%02X\n",
dpc->dpchaos_eth[0],dpc->dpchaos_eth[1],dpc->dpchaos_eth[2],
dpc->dpchaos_eth[3],dpc->dpchaos_eth[4],dpc->dpchaos_eth[5]);
}
fprintf(of,"Status register: 0%o\n", REG(ch));
if (REG(ch) & CH_BSY)
fprintf(of, " Transmit busy\n");
@@ -580,12 +642,15 @@ static int
ch11_cmd(register struct device *d, FILE *of, char *cmd)
{
register struct ch11 *ch = (struct ch11 *)d;
struct dpchaos_s *dpc = (struct dpchaos_s *)ch->ch_dp.dp_adr;
if (*cmd)
while (*cmd == ' ')
cmd++;
if (*cmd && (strcmp(cmd,"chiptable") == 0))
ch11_cmd_chiptable(ch, of);
else if (*cmd && ((strcmp(cmd,"arptable") == 0) || (strcmp(cmd,"arp") == 0)))
ch11_cmd_print_arp_table(ch, of);
else if (*cmd && (strcmp(cmd,"status") == 0))
ch11_cmd_status(ch, of);
else if (*cmd && strncmp(cmd,"dpdebug",strlen("dpdebug")) == 0) {
@@ -600,11 +665,15 @@ ch11_cmd(register struct device *d, FILE *of, char *cmd)
}
else if (*cmd) {
fprintf(of,"Unknown command \"%s\"\n", cmd);
fprintf(of,"Commands:\n \"chiptable\" to show the Chaos/IP table\n \"status\" to show device status\n \"dpdebug x\" to set dpchudp debug level to x\n");
} else
/* No command, do both */
fprintf(of,"Commands:\n \"chiptable\" to show the Chaos/IP table\n \"arptable\" to show the Chaos ARP table\n \"status\" to show device status\n \"dpdebug x\" to set dpchaos debug level to x\n");
} else {
/* No command, do all */
ch11_cmd_status(ch, of);
ch11_cmd_chiptable(ch, of);
if (dpc->dpchaos_ifmeth_chudp)
ch11_cmd_chiptable(ch, of);
else
ch11_cmd_print_arp_table(ch, of);
}
return TRUE;
}
@@ -620,7 +689,7 @@ ch11_init(struct device *d, FILE *of)
{
register struct ch11 *ch = (struct ch11 *)d;
if (!chudp_init(ch, of))
if (!chaos_init(ch, of))
return FALSE;
ch_clear(ch);
return TRUE;
@@ -632,7 +701,7 @@ ch11_init(struct device *d, FILE *of)
static void
ch11_powoff(struct device *d)
{
chudp_kill((struct ch11 *)d);
chaos_kill((struct ch11 *)d);
}
@@ -665,9 +734,11 @@ ch_oint_off(register struct ch11 *ch)
static void
ch_iclear(register struct ch11 *ch)
{
struct dpchaos_s *dpc = (struct dpchaos_s *)ch->ch_dp.dp_adr;
ch_iint_off(ch);
if (ch->ch_rbuf)
ch->ch_iptr = ch->ch_rbuf + DPCHUDP_DATAOFFSET;
ch->ch_iptr = ch->ch_rbuf + dpc->dpchaos_inoff; // DPCHUDP_DATAOFFSET;
else
ch->ch_iptr = NULL;
ch->ch_rcnt = -1;
@@ -680,9 +751,11 @@ ch_iclear(register struct ch11 *ch)
static void
ch_oclear(register struct ch11 *ch)
{
struct dpchaos_s *dpc = (struct dpchaos_s *)ch->ch_dp.dp_adr;
ch_oint_off(ch);
if (ch->ch_sbuf)
ch->ch_optr = ch->ch_sbuf + DPCHUDP_DATAOFFSET;
ch->ch_optr = ch->ch_sbuf + dpc->dpchaos_outoff; // DPCHUDP_DATAOFFSET;
else
ch->ch_optr = NULL;
REG(ch) &= ~CH_TAB; /* Not aborted */
@@ -693,7 +766,7 @@ ch_oclear(register struct ch11 *ch)
static void
ch_clear(register struct ch11 *ch)
{
chudp_stop(ch); /* Kill CHUDP process, ready line going down */
chaos_stop(ch); /* Kill CHAOS process, ready line going down */
ch->ch_outactf = TRUE; /* Initialise to true */
@@ -732,13 +805,14 @@ static dvureg_t
ch11_read(struct device *d, register uint18 addr)
{
register struct ch11 *ch = (struct ch11 *)d;
struct dpchaos_s *dpc = (struct dpchaos_s *)ch->ch_dp.dp_adr;
dvureg_t val;
if (DVDEBUG(ch) > 4)
fprintf(DVDBF(ch), "[CH11 Read %#o]\r\n", addr);
if (ch->ch_dp.dp_chpid == 0) /* if DP process is not running, start it */
chudp_start(ch);
chaos_start(ch);
switch (addr) {
/* case UB_CHWBF: /* Write buffer (write only) = CHMYN */
@@ -759,7 +833,7 @@ ch11_read(struct device *d, register uint18 addr)
if (ch->ch_rcnt > 0) {
val = *(ch->ch_iptr++) << 8;
val |= *(ch->ch_iptr++);
if ((ch->ch_iptr - ch->ch_rbuf) >= (ch->ch_rcnt + DPCHUDP_DATAOFFSET)) {
if ((ch->ch_iptr - ch->ch_rbuf) >= (ch->ch_rcnt + dpc->dpchaos_inoff)) { // DPCHUDP_DATAOFFSET
if (DVDEBUG(ch) > 4)
fprintf(DVDBF(ch), "[CH11 reading last word, clearing RDN]\r\n");
ch->ch_rcnt = -1; /* read last word */
@@ -782,16 +856,16 @@ ch11_read(struct device *d, register uint18 addr)
if (ch->ch_optr) { /* #### range check too */
int cks, len;
/* Dest addr already in data, checksum at end */
len = (ch->ch_optr - ch->ch_sbuf)-DPCHUDP_DATAOFFSET+2;
len = (ch->ch_optr - ch->ch_sbuf)-dpc->dpchaos_outoff+2; // DPCHUDP_DATAOFFSET
/* Add source */
*(ch->ch_optr++) = (ch->ch_myaddr>>8);
*(ch->ch_optr++) = (ch->ch_myaddr & 0xff);
/* Make checksum */
cks = ch_checksum(&ch->ch_sbuf[DPCHUDP_DATAOFFSET],len);
cks = ch_checksum(&ch->ch_sbuf[dpc->dpchaos_outoff],len); // DPCHUDP_DATAOFFSET
*(ch->ch_optr++) = cks >> 8;
*(ch->ch_optr++) = cks & 0xff;
chudp_outxfer(ch); /* Send it to DP */
chaos_outxfer(ch); /* Send it to DP */
} else
panic("ch11_read: no output pointer available at CHXMT");
val = (dvureg_t) ch->ch_myaddr;
@@ -816,7 +890,7 @@ ch11_write(struct device *d, uint18 addr, register dvureg_t val)
fprintf(DVDBF(ch), "[CH11 Write %#o <= %#lo]\r\n", addr, (long)val);
if (ch->ch_dp.dp_chpid == 0) /* if DP process is not running, start it */
chudp_start(ch);
chaos_start(ch);
switch (addr) {
/* case UB_CHMYN: /* My chaos address (read only) = CHWBF */
@@ -868,7 +942,7 @@ ch11_write(struct device *d, uint18 addr, register dvureg_t val)
}
if (val & CH_TCL) { /* Clear the transmitter, making it ready */
/* AIM628: stops transmitter and sets TDN */
/* #### do we need to "stop transmitter" (dpchudp)? */
/* #### do we need to "stop transmitter" (dpchaos)? */
val &= ~CH_TCL;
val |= CH_TDN;
/* Done below */
@@ -923,8 +997,10 @@ static void
ch_oint(register struct ch11 *ch)
{
if (REG(ch) & CH_TEN) {
#if 0 // too much noise
if (DVDEBUG(ch))
fprintf(DVDBF(ch), "[CH11: output int]\r\n");
#endif
ch->ch_opireq = TRUE;
(*ch->ch_dv.dv_pifun)(&ch->ch_dv, /* Put up interrupt */
(int)ch->ch_dv.dv_brlev);
@@ -945,20 +1021,20 @@ ch_iint(register struct ch11 *ch)
}
}
/* Activate input side - allow CHUDP input to be received and processed.
/* Activate input side - allow CHAOS input to be received and processed.
*/
static void
ch_igo(register struct ch11 *ch)
{
ch->ch_inactf = TRUE; /* OK to start reading input! */
if (chudp_incheck(ch)) { /* Do initial check for input */
chudp_inxfer(ch); /* Have input! Go snarf it! */
if (chaos_incheck(ch)) { /* Do initial check for input */
chaos_inxfer(ch); /* Have input! Go snarf it! */
ch_idone(ch); /* Finish up CH input done */
}
}
/* CH input done - called to finish up CHUDP input
/* CH input done - called to finish up CHAOS input
*/
static void
ch_idone(register struct ch11 *ch)
@@ -971,11 +1047,13 @@ ch_idone(register struct ch11 *ch)
static int
ch_outcheck(register struct ch11 *ch)
{
struct dpchaos_s *dpc = (struct dpchaos_s *)ch->ch_dp.dp_adr;
/* check if there's some output to send */
return ch->ch_outactf && (((ch->ch_optr - ch->ch_sbuf) - DPCHUDP_DATAOFFSET) > 0);
return ch->ch_outactf && (((ch->ch_optr - ch->ch_sbuf) - dpc->dpchaos_outoff) > 0); // DPCHUDP_DATAOFFSET
}
/* Activate output side - send a message to the CHUDP.
/* Activate output side - send a message to the CHAOS.
** If can't do it because an outbound message is already in progress,
** complain and cause an error.
*/
@@ -983,7 +1061,7 @@ static void
ch_ogo(register struct ch11 *ch)
{
if (ch_outcheck(ch)) {
if (!chudp_outxfer(ch)) {
if (!chaos_outxfer(ch)) {
/* Couldn't output, so abort and done immediately */
REG(ch) |= (CH_TAB|CH_TDN); /* #### */
if (DVDEBUG(ch))
@@ -991,14 +1069,14 @@ ch_ogo(register struct ch11 *ch)
}
ch_oint(ch);
return;
/* DPCHUDP will call ch_evhsdon() when ready for more output. */
/* DPCHAOS will call ch_evhsdon() when ready for more output. */
} else {
ch_oint(ch); /* ITS seems to need this? */
return;
}
}
/* CH output done - called to finish up CHUDP output
/* CH output done - called to finish up CHAOS output
*/
static void
ch_odone(register struct ch11 *ch)
@@ -1008,11 +1086,12 @@ ch_odone(register struct ch11 *ch)
ch_oint(ch); /* Send output interrupt! */
}
/* VIRTUAL CHUDP ROUTINES
/* VIRTUAL CHAOS ROUTINES
*/
/* Utility routine */
#if 0
static void
showpkt(FILE *f, char *id, unsigned char *buf, int cnt)
{
@@ -1035,6 +1114,85 @@ showpkt(FILE *f, char *id, unsigned char *buf, int cnt)
fprintf(f, "%s\r\n", linbuf);
}
}
#else
static char
*ch_opc[] = { "NIL",
"RFC", "OPN", "CLS", "FWD", "ANS", "SNS", "STS", "RUT",
"LOS", "LSN", "MNT", "EOF", "UNC", "BRD" };
static char *
ch_opcode(int op)
{
char buf[7];
if (op < 017 && op > 0)
return ch_opc[op];
else if (op == 0200)
return "DAT";
else if (op == 0300)
return "DWD";
else
return "bogus";
}
char *
ch_char(unsigned char x, char *buf) {
if (x < 32)
sprintf(buf,"^%c", x+64);
else if (x == 127)
sprintf(buf,"^?");
else if (x < 127)
sprintf(buf,"%2c",x);
else
sprintf(buf,"%2x",x);
return buf;
}
static void
showpkt(FILE *f, char *id, unsigned char *ucp, int cnt)
{
int i, row;
char b1[3],b2[3];
fprintf(stderr,"%s pkt dump, len %d\r\n", id, cnt);
fprintf(stderr,"Opcode: %#o (%s), unused: %o\r\nFC: %d., Nbytes %d.\r\n",
ucp[0], ch_opcode(ucp[0]),
ucp[1], ucp[2]>>4, ((ucp[2]&0xf)<<4) | ucp[3]);
fprintf(stderr,"Dest host: %#o, index %#o\r\nSource host: %#o, index %#o\r\n",
(ucp[4]<<8)|ucp[5], (ucp[6]<<8)|ucp[7],
(ucp[8]<<8)|ucp[9], (ucp[10]<<8)|ucp[11]);
fprintf(stderr,"Packet #%o\r\nAck #%o\r\n",
(ucp[12]<<8)|ucp[13], (ucp[14]<<8)|ucp[15]);
fprintf(stderr,"Data:\r\n");
/* Skip headers */
ucp += CHAOS_HEADERSIZE;
/* Show only data portion */
cnt -= CHAOS_HEADERSIZE+CHAOS_HW_TRAILERSIZE;
for (row = 0; row*8 < cnt; row++) {
for (i = 0; (i < 8) && (i+row*8 < cnt); i++) {
fprintf(stderr, " %02x", ucp[i+row*8]);
fprintf(stderr, "%02x", ucp[(++i)+row*8]);
}
fprintf(stderr, " (hex)\r\n");
#if 1
for (i = 0; (i < 8) && (i+row*8 < cnt); i++) {
fprintf(stderr, " %2s", ch_char(ucp[i+row*8], (char *)&b1));
fprintf(stderr, "%2s", ch_char(ucp[(++i)+row*8], (char *)&b2));
}
fprintf(stderr, " (chars)\r\n");
for (i = 0; (i < 8) && (i+row*8 < cnt); i++) {
fprintf(stderr, " %2s", ch_char(ucp[i+1+row*8], (char *)&b1));
fprintf(stderr, "%2s", ch_char(ucp[(i++)+row*8], (char *)&b2));
}
fprintf(stderr, " (11-chars)\r\n");
#endif
}
/* Now show trailer */
fprintf(stderr,"HW trailer:\r\n Dest: %#o\r\n Source: %#o\r\n Checksum: %#x\r\n",
(ucp[cnt]<<8)|ucp[cnt+1],(ucp[cnt+2]<<8)|ucp[cnt+3],(ucp[cnt+4]<<8)|ucp[cnt+5]);
}
#endif
static void ch_evhrwak(struct device *d, struct dvevent_s *evp);
@@ -1042,17 +1200,17 @@ static void ch_evhsdon(struct device *d, struct dvevent_s *evp);
/* static */
int
chudp_init(register struct ch11 *ch, FILE *of)
chaos_init(register struct ch11 *ch, FILE *of)
{
register struct dpchudp_s *dpc;
register struct dpchaos_s *dpc;
struct dvevent_s ev;
size_t junk;
ch->ch_dpstate = FALSE;
if (!dp_init(&ch->ch_dp, sizeof(struct dpchudp_s),
DP_XT_MSIG, SIGUSR1, (size_t)CHUDPBUFSIZ, /* in */
DP_XT_MSIG, SIGUSR1, (size_t)CHUDPBUFSIZ)) { /* out */
if (of) fprintf(of, "CHUDP subproc init failed!\n");
if (!dp_init(&ch->ch_dp, sizeof(struct dpchaos_s),
DP_XT_MSIG, SIGUSR1, (size_t)CHAOSBUFSIZ, /* in */
DP_XT_MSIG, SIGUSR1, (size_t)CHAOSBUFSIZ)) { /* out */
if (of) fprintf(of, "CH11 subproc init failed!\n");
return FALSE;
}
ch->ch_sbuf = dp_xsbuff(&(ch->ch_dp.dp_adr->dpc_todp), &junk);
@@ -1060,35 +1218,50 @@ chudp_init(register struct ch11 *ch, FILE *of)
ch->ch_dv.dv_dpp = &(ch->ch_dp); /* Tell CPU where our DP struct is */
/* Set up DPCHUDP-specific part of shared DP memory */
dpc = (struct dpchudp_s *) ch->ch_dp.dp_adr;
dpc->dpchudp_dpc.dpc_debug = ch->ch_dpdbg; /* Init DP debug flag */
/* Set up DPCHAOS-specific part of shared DP memory */
dpc = (struct dpchaos_s *) ch->ch_dp.dp_adr;
dpc->dpchaos_dpc.dpc_debug = ch->ch_dpdbg; /* Init DP debug flag */
if (cpu.mm_locked) /* Lock DP mem if CPU is */
dpc->dpchudp_dpc.dpc_flags |= DPCF_MEMLOCK;
dpc->dpchaos_dpc.dpc_flags |= DPCF_MEMLOCK;
dpc->dpchudp_ver = DPCHUDP_VERSION;
dpc->dpchudp_attrs = 0;
dpc->dpchaos_ver = DPCHAOS_VERSION;
dpc->dpchaos_attrs = 0;
dpc->dpchudp_backlog = ch->ch_backlog; /* Pass on backlog value */
dpc->dpchudp_dedic = ch->ch_dedic; /* Pass on dedicated flag */
dpc->dpchaos_backlog = ch->ch_backlog; /* Pass on backlog value */
dpc->dpchaos_dedic = ch->ch_dedic; /* Pass on dedicated flag */
if (ch->ch_ifnam) /* Pass on interface name if any */
strncpy(dpc->dpchudp_ifnam, ch->ch_ifnam, sizeof(dpc->dpchudp_ifnam)-1);
strncpy(dpc->dpchaos_ifnam, ch->ch_ifnam, sizeof(dpc->dpchaos_ifnam)-1);
else
dpc->dpchudp_ifnam[0] = '\0'; /* No specific interface */
dpc->dpchaos_ifnam[0] = '\0'; /* No specific interface */
dpc->dpchudp_myaddr = ch->ch_myaddr; /* Set our Chaos address */
dpc->dpchudp_port = ch->ch_chudp_port;
if (ch->ch_ifmeth) { /* Pass on interface access method */
strncpy(dpc->dpchaos_ifmeth, ch->ch_ifmeth, sizeof(dpc->dpchaos_ifmeth)-1);
if (strcasecmp(dpc->dpchaos_ifmeth, "chudp") == 0)
dpc->dpchaos_ifmeth_chudp = 1;
else if (strcasecmp(dpc->dpchaos_ifmeth, "pcap") == 0)
dpc->dpchaos_ifmeth_chudp = 0;
else {
if (of) fprintf(of,"CH11: unsupported ifmeth '%s' (must be chudp or pcap)\n",
dpc->dpchaos_ifmeth);
return FALSE;
}
}
else
dpc->dpchaos_ifmeth[0] = '\0'; /* No specific access method */
dpc->dpchaos_myaddr = ch->ch_myaddr; /* Set our Chaos address */
dpc->dpchaos_port = ch->ch_chudp_port;
/* copy chip table */
for (junk = 0; junk < ch->ch_chip_tlen; junk++) {
memset(&dpc->dpchudp_chip_tbl[junk], 0, sizeof(struct dpchudp_chip));
dpc->dpchudp_chip_tbl[junk].dpchudp_chip_chaddr = ch->ch_chip_tbl[junk].ch_chip_chaddr;
dpc->dpchudp_chip_tbl[junk].dpchudp_chip_ipport = ch->ch_chip_tbl[junk].ch_chip_ipport;
memcpy(&dpc->dpchudp_chip_tbl[junk].dpchudp_chip_ipaddr,
memset(&dpc->dpchaos_chip_tbl[junk], 0, sizeof(struct dpchaos_chip));
dpc->dpchaos_chip_tbl[junk].dpchaos_chip_chaddr = ch->ch_chip_tbl[junk].ch_chip_chaddr;
dpc->dpchaos_chip_tbl[junk].dpchaos_chip_ipport = ch->ch_chip_tbl[junk].ch_chip_ipport;
memcpy(&dpc->dpchaos_chip_tbl[junk].dpchaos_chip_ipaddr,
&ch->ch_chip_tbl[junk].ch_chip_ipaddr, sizeof(struct in_addr));
}
dpc->dpchudp_chip_tlen = ch->ch_chip_tlen;
dpc->dpchaos_chip_tlen = ch->ch_chip_tlen;
/* Register ourselves with main KLH10 loop for DP events */
@@ -1096,7 +1269,7 @@ chudp_init(register struct ch11 *ch, FILE *of)
ev.dvev_arg.eva_int = SIGUSR1;
ev.dvev_arg2.eva_ip = &(ch->ch_dp.dp_adr->dpc_todp.dpx_donflg);
if (!(*ch->ch_dv.dv_evreg)((struct device *)ch, ch_evhsdon, &ev)) {
if (of) fprintf(of, "CHUDP event reg failed!\n");
if (of) fprintf(of, "CH11 event reg failed!\n");
return FALSE;
}
@@ -1104,19 +1277,19 @@ chudp_init(register struct ch11 *ch, FILE *of)
ev.dvev_arg.eva_int = SIGUSR1;
ev.dvev_arg2.eva_ip = &(ch->ch_dp.dp_adr->dpc_frdp.dpx_wakflg);
if (!(*ch->ch_dv.dv_evreg)((struct device *)ch, ch_evhrwak, &ev)) {
if (of) fprintf(of, "CHUDP event reg failed!\n");
if (of) fprintf(of, "CH11 event reg failed!\n");
return FALSE;
}
return TRUE;
}
static int
chudp_start(register struct ch11 *ch)
chaos_start(register struct ch11 *ch)
{
register int res;
if (DVDEBUG(ch))
fprintf(DVDBF(ch), "[chudp_start: starting DP \"%s\"...",
fprintf(DVDBF(ch), "[chaos_start: starting DP \"%s\"...",
ch->ch_dpname);
/* HORRIBLE UGLY HACK: for AXP OSF/1 and perhaps other systems,
@@ -1140,7 +1313,7 @@ chudp_start(register struct ch11 *ch)
if (DVDEBUG(ch))
fprintf(DVDBF(ch), " failed!]\r\n");
else
fprintf(DVDBF(ch), "[chudp_start: Start of DP \"%s\" failed!]\r\n",
fprintf(DVDBF(ch), "[chaos_start: Start of DP \"%s\" failed!]\r\n",
ch->ch_dpname);
return FALSE;
}
@@ -1153,14 +1326,14 @@ chudp_start(register struct ch11 *ch)
return TRUE;
}
/* CHUDP_STOP - Stops CHUDP and drops Host Ready by killing CHUDP subproc,
/* CHAOS_STOP - Stops CHAOS and drops Host Ready by killing CHAOS subproc,
** but allow restarting.
*/
static void
chudp_stop(register struct ch11 *ch)
chaos_stop(register struct ch11 *ch)
{
if (DVDEBUG(ch))
fprintf(DVDBF(ch), "[CHUDP: stopping...");
fprintf(DVDBF(ch), "[CH11: stopping...");
dp_stop(&ch->ch_dp, 1); /* Say to kill and wait 1 sec for synch */
@@ -1170,13 +1343,13 @@ chudp_stop(register struct ch11 *ch)
}
/* CHUDP_KILL - Kill CHUDP process permanently, no restart.
/* CHAOS_KILL - Kill CHAOS process permanently, no restart.
*/
static void
chudp_kill(register struct ch11 *ch)
chaos_kill(register struct ch11 *ch)
{
if (DVDEBUG(ch))
fprintf(DVDBF(ch), "[CHUDP kill]\r\n");
fprintf(DVDBF(ch), "[CH11 kill]\r\n");
ch->ch_dpstate = FALSE;
(*ch->ch_dv.dv_evreg)( /* Flush all event handlers for device */
@@ -1202,16 +1375,16 @@ ch_evhrwak(struct device *d, struct dvevent_s *evp)
fprintf(DVDBF(ch), "[CH11 input wakeup: %d]",
(int)dp_xrtest(dp_dpxfr(&ch->ch_dp)));
/* Always check CHUDP input in order to process any non-data messages
/* Always check CHAOS input in order to process any non-data messages
** regardless of whether CH is actively reading,
** then invoke general CH check to do data transfer if OK.
*/
if (chudp_incheck(ch)) {
if (chaos_incheck(ch)) {
if (!ch->ch_inactf) {
ch->ch_lost++; /* received, but busy */
dp_xrdone(dp_dpxfr(&ch->ch_dp)); /* ack to DP! */
} else {
chudp_inxfer(ch); /* Have input! Go snarf it! */
chaos_inxfer(ch); /* Have input! Go snarf it! */
ch_idone(ch); /* Finish up CH input done */
}
}
@@ -1232,29 +1405,29 @@ ch_evhsdon(struct device *d, struct dvevent_s *evp)
}
/* Start CHUDP output.
/* Start CHAOS output.
*/
static int
chudp_outxfer(register struct ch11 *ch)
chaos_outxfer(register struct ch11 *ch)
{
register int cnt;
register struct dpx_s *dpx = dp_dpxto(&ch->ch_dp);
struct dpchaos_s *dpc = (struct dpchaos_s *)ch->ch_dp.dp_adr;
/* Make sure we can output message and fail if not */
if (!dp_xstest(dpx)) {
if (DVDEBUG(ch))
fprintf(DVDBF(ch), "[CHUDP: DP out blocked]\r\n");
fprintf(DVDBF(ch), "[CH11: DP out blocked]\r\n");
return 0;
}
ch->ch_outactf = FALSE; /* Don't send another just yet */
/* Output xfer requested! */
register struct dpchudp_s *dpc = (struct dpchudp_s *) ch->ch_dp.dp_adr;
#if 1 /* #### Debug */
int chlen = ((ch->ch_sbuf[DPCHUDP_DATAOFFSET+2] & 0xf) << 4) | ch->ch_sbuf[DPCHUDP_DATAOFFSET+3];
int chlen = ((ch->ch_sbuf[dpc->dpchaos_outoff+2] & 0xf) << 4) | ch->ch_sbuf[dpc->dpchaos_outoff+3]; // DPCHUDP_DATAOFFSET
#endif
cnt = (ch->ch_optr - ch->ch_sbuf) - DPCHUDP_DATAOFFSET;
cnt = (ch->ch_optr - ch->ch_sbuf) - dpc->dpchaos_outoff; // DPCHUDP_DATAOFFSET
#if 1 /* #### Debug */
if ((cnt % 2) == 1)
fprintf(stderr,"\r\n[CH11 sending odd number of bytes (%d. data len %d.)]\r\n",
@@ -1264,41 +1437,39 @@ chudp_outxfer(register struct ch11 *ch)
cnt, CHAOS_HEADERSIZE + chlen + CHAOS_HW_TRAILERSIZE, chlen);
#endif
if (DVDEBUG(ch) & DVDBF_DATSHO) /* Show data? */
showpkt(DVDBF(ch), "PKTOUT", ch->ch_sbuf + DPCHUDP_DATAOFFSET, cnt);
dpc->dpchudp_outoff = DPCHUDP_DATAOFFSET;
showpkt(DVDBF(ch), "PKTOUT", ch->ch_sbuf + dpc->dpchaos_outoff, cnt); // DPCHUDP_DATAOFFSET
REG(ch) &= ~(CH_TAB|CH_TDN); /* Not done yet, not aborted */
dp_xsend(dpx, DPCHUDP_SPKT, (size_t)cnt + DPCHUDP_DATAOFFSET);
dp_xsend(dpx, DPCHAOS_SPKT, (size_t)cnt + dpc->dpchaos_outoff); // DPCHUDP_DATAOFFSET
if (DVDEBUG(ch))
fprintf(DVDBF(ch), "[CHUDP: Out %d]\r\n", cnt);
fprintf(DVDBF(ch), "[CH11: Out %d]\r\n", cnt);
return 1;
}
static int
chudp_incheck(register struct ch11 *ch)
chaos_incheck(register struct ch11 *ch)
{
register struct dpx_s *dpx = dp_dpxfr(&ch->ch_dp);
if (dp_xrtest(dpx)) { /* Verify there's a message for us */
switch (dp_xrcmd(dpx)) {
case DPCHUDP_INIT:
case DPCHAOS_INIT:
ch->ch_dpstate = TRUE;
dp_xrdone(dpx); /* ACK it */
return 0; /* No actual input */
case DPCHUDP_RPKT: /* Input packet ready! */
case DPCHAOS_RPKT: /* Input packet ready! */
if (DVDEBUG(ch))
fprintf(DVDBF(ch), "[CHUDP: inbuf %ld]\r\n",
fprintf(DVDBF(ch), "[CH11: inbuf %ld]\r\n",
(long) dp_xrcnt(dpx));
return 1;
default:
if (DVDEBUG(ch))
fprintf(DVDBF(ch), "[CHUDP: R %d flushed]", dp_xrcmd(dpx));
fprintf(DVDBF(ch), "[CH11: R %d flushed]", dp_xrcmd(dpx));
dp_xrdone(dpx); /* just ACK it */
return 0;
}
@@ -1308,30 +1479,30 @@ chudp_incheck(register struct ch11 *ch)
}
/* CHUDP_INXFER - CHUDP Input.
/* CHAOS_INXFER - CHAOS Input.
** For time being, don't worry about partial transfers (sigh),
** which might have left part of a previous message still lying
** around waiting for the next read request.
*/
static void
chudp_inxfer(register struct ch11 *ch)
chaos_inxfer(register struct ch11 *ch)
{
register int err, cnt, cks;
register struct dpx_s *dpx = dp_dpxfr(&ch->ch_dp);
register struct dpchudp_s *dpc = (struct dpchudp_s *) ch->ch_dp.dp_adr;
register struct dpchaos_s *dpc = (struct dpchaos_s *) ch->ch_dp.dp_adr;
register unsigned char *pp;
/* Assume this is ONLY called after verification by chudp_incheck that
/* Assume this is ONLY called after verification by chaos_incheck that
** an input message is actually ready.
*/
cnt = dp_xrcnt(dpx);
/* Adjust for possible offset */
/* cnt -= dpc->dpchudp_inoff; */
pp = ch->ch_rbuf + dpc->dpchudp_inoff;
/* cnt -= dpc->dpchaos_inoff; */
pp = ch->ch_rbuf + dpc->dpchaos_inoff;
if (DVDEBUG(ch))
fprintf(DVDBF(ch), "[CHUDP: In %d]\r\n", cnt);
fprintf(DVDBF(ch), "[CH11: In %d]\r\n", cnt);
if (DVDEBUG(ch) & DVDBF_DATSHO) /* Show data? */
showpkt(DVDBF(ch), "PKTIN ", pp, cnt);
@@ -1344,18 +1515,29 @@ chudp_inxfer(register struct ch11 *ch)
ch->ch_iptr = pp;
/* check hw trailer: dest, checksum */
if ((((pp[cnt-6]<<8) | pp[cnt-5]) != ch->ch_myaddr)) {
// byte order warning...
u_short chlen = ((pp[2] & 0xf) << 4) | pp[3];
u_short trdest = ((pp[cnt-6]<<8) | pp[cnt-5]);
u_short hddest = (pp[4] << 8) | pp[5];
u_short cksm = (pp[cnt-2]<<8) | pp[cnt-1];
if (DVDEBUG(ch) && (CHAOS_HEADERSIZE + chlen + CHAOS_HW_TRAILERSIZE != cnt)) {
fprintf(DVDBF(ch), "[CH11: expected len %d+%d+%d = %d, got %d]\r\n",
CHAOS_HEADERSIZE , chlen , CHAOS_HW_TRAILERSIZE,
CHAOS_HEADERSIZE + chlen + CHAOS_HW_TRAILERSIZE, cnt);
}
// be conservative in what you generate, and liberal in what you accept
if ((trdest != 0) && (trdest != ch->ch_myaddr) && (hddest != 0) && (hddest != ch->ch_myaddr) && !(REG(ch) & CH_SPY)) {
if (DVDEBUG(ch))
fprintf(DVDBF(ch), "[CHUDP: not for my address: destination %o]\r\n",
((pp[cnt-6]<<8) | pp[cnt-5]));
fprintf(DVDBF(ch), "[CH11: not for my address: trailer dest %#o, header dest %#o]\r\n", trdest, hddest);
} else {
cks = ch_checksum(pp,cnt);
if (cks != 0) {
if (DVDEBUG(ch))
fprintf(DVDBF(ch), "[CHUDP: bad checksum 0x%x]\r\n", cks);
#if 1 /* 0 for testing */
REG(ch) |= CH_ERR;
#endif
if (cksm != 0) {
cks = ch_checksum(pp,cnt);
if (cks != 0) {
if (DVDEBUG(ch))
fprintf(DVDBF(ch), "[CH11: bad checksum 0x%x]\r\n", cks);
REG(ch) |= CH_ERR;
}
}
REG(ch) |= CH_RDN; /* Note it's done! */
}

View File

@@ -37,11 +37,11 @@ extern struct device *dvch11_init(FILE *, char *);
/* CH11 addresses & assignments for KS10:
CH11 Address Vector UBA# BR-Level
#1 0764140 0270 3 4 or 5 (dunno which)
#1 0764140 0270 3 4 or 5 (dunno which) [6, according to CHXCHN in ITS]
etc(?) (some) 0230
*/
#define UB_CH11_BR 5
#define UB_CH11_BR 6 /* See CHXCHN in ITS */
#define UB_CH11_VEC 0270 /* CH11 Interrupt Vector */
#define UB_CH11 0764140 /* CH11 Unibus Address (on UBA #3) */

View File

@@ -6,73 +6,75 @@
The ch11 device in KLH10 for ITS, which was originally just a dummy
inteface to keep ITS running, is now a functional Unibus Chaosnet
device, which tunnels Chaosnet packets over UDP. It does not support
SPY (promiscuous) mode, LUP (loopback), or broadcast, but ITS doesn't
seem to use/need these.
device, which supports Chaosnet-on-Ethernet and Chaosnet-over-UDP.
It does not support SPY (promiscuous) mode, LUP (loopback), or
broadcast, but ITS doesn't seem to use/need these.
Latest update: 2005-04-23
Why Chaos when we have the IMP?
* Some ITS services use Chaos but not IP, e.g. the DIR device.
* The IMP needs to run as root on most Unix flavors, but the UDP
tunnel can go over unprivileged ports. (This can also make it avoid
firewalls.)
* It's historically interesting, and makes KLH10 more complete.
* It's FUN!
Latest update: 2018-04-15
Like other KLH10 network devices, ch11 works together with a Device
Process which communicates with the device and reads/writes network
data over UDP. A 4-byte protocol header is added, with only one
defined function code yet (sending a Chaos packet). The "original"
Chaos trailer (destination, source, and checksum) is also added.
data. It can do it in two ways:
Firstly, by implementing Chaosnet over Ethernet (protocol nr 0x0804) and handling
ARP for that protocol (cf RFC 826). This uses one of the packet filtering
implementations (currently only pcap) provided by osdnet. (Only Ethernet II
headers are supported, not 802.3.)
No routing is handled, that's done by ITS - this code uses the
Chaosnet trailer provided by ITS to decide where to send pkts.
(On Ethernet, no Chaosnet trailer is included.)
Secondly, it can do it by using a Chaos-over-UDP tunnel. A 4-byte
protocol header is added, with only one defined function code yet
(sending a Chaos packet). The "original" Chaos trailer (destination,
source, and checksum) is also added.
The protocol, CHUDP, by default uses UDP port 42042, but this can be
configured in case, e.g., that port doesn't pass through your
firewall.
The code is a (very) stripped-down version of dvlhdh.c and dpimp.c,
and includes minimal patches to the makefile and to kn10dev.c.
It can be downloaded via http://victor.se/bjorn/its. I would
appreciate if you send me an email if you do, e.g. so I have an idea
about who to notify about updates.
Configuration parameters:
To configure the CH11 device, as a minimum, use
devdef chaos ub3 ch11 addr=764140 br=6 vec=270 myaddr=3132
where the new parameter is "myaddr", which is the octal Chaosnet
address of the system. ITS seems to think the "br" param should be 6,
not 5 as used in the old dummy device definition (see CHXCHN in ITS).
The basic configuration parameters:
devdef chaos ub3 ch11 addr=764140 br=6 vec=270
It uses the generic Unibus parameters "addr", "br", "vec" etc, plus
additional parameters:
chudpport=50043
changes the UDP port used
chip=3131/10.0.1.42:50011
defines a Chaos/IP mapping for Chaos host 3131, which should
be contacted at IP 10.0.1.42 at UDP port 50011. You can use
hostnames in place of IP addresses, which will use the first
address returned by gethostbyname(), if it is an IPv4 address.
The port suffix is optional and defaults to 42042. You can
define up to 10 such Chaos/IP mappings (without changing the
constants in the code).
ITS seems to think the "br" param should be 6, not 5 as used in the
old dummy device definition (see CHXCHN in ITS).
More parameters:
myaddr=oooo
defines the octal Chaosnet address of the interface.
This needs to match the address configured in ITS (see MYCHAD
in SYSTEM;CONFIG >)
ifmeth=meth
where meth is "chudp" or "pcap", selects the link
implementation to use (Chaos-over-UDP or Chaos-on-Ethernet).
For "chudp":
chudpport=dddddd
sets the local UDP port to use for Chaos-over-UDP. The default is 42042.
chip=oooo/hhhhhhhh
defines a remote Chaos-over-UDP host with the octal Chaos address oooo,
and the IPv4 address or hostname hhhhhhhh. If a hostname is
used, the first IPv4 address returned is used. (Rather than
listing all your friends' ITS hosts directly, I suggest joining the
Global Chaosnet and just list its central router. See
https://aosnet.ch.)
If chudpport or chip parameters are given, the ifmeth defaults to chudp.
If a CHUDP packet is received from an unknown host, a Chaos/IP mapping
is dynamically added to the table, so return traffic can find its
way. This is useful e.g. if you accept connections from other ITSes
without static IP addresses. (There is currently no way to avoid
potentially filling your table this way.)
is dynamically added to the table, so return traffic can find its way.
This is useful e.g. if you accept connections from other ITSes without
static IP addresses. (You can avoid this feature, and potentially
filling your table, by using a firewall.)
To make use of the interface, you need to recompile ITS after defining
CHAOSP, MYCHAD, NINDX, and CH11P in SYSTEM;CONFIG (and following the
instructions in distrib.its, of course). See also BEWARE note below.
Don't forget to compile SYSENG;@CHAOS and install as DEVICE;ATSIGN
CHAOS. Don't forget to keep names of your friends' ITSes in
SYSEN2;MLDEV, SYSENG;@DEV, etc. More notes on the web page.
I would appreciate very much to get feedback and testing, especially
from people who actually *know* how the original interface was
supposed to act. I've discovered many things by reading SYSTEM;CHAOS
and by testing locally, but I can't say I know exactly how it *should*
work...
SYSEN2;MLDEV, SYSENG;@DEV, etc.
*BEWARE*:
If you have both CHAOSP and IMPP, you run into a bug which results in
@@ -87,25 +89,11 @@ IFN CHAOSP,DEFOPT NM%CHA==<IPADDR 255,255,0,0> ; Set default netmask for it
but the real fix would be to the IPMASK macro.
Ideas for future work:
- Better routing support.
- Use DNS to find Chaos addresses - this seems more awkward than helpful.
- Implement loopback (not LUP, but Chaos pkts to self). Currently
they are in practice dropped. I'm not sure ITS handles this very
well anyway.
- Chaos broadcast can easily be implemented by UDP broadcast, but it's
probably not very useful. Another implementation would be to send
(individually) to all known hosts (in the CHIP table) on the same
subnet, but this is probably not very useful either. (Does any ITS
program do broadcast?)
- More CHUDP protocol functions?
- Security?
- Chaosnet library for Linux/Unix???
- Implement Chaos-over-DTLS to get some security, on this modern Internet.
More info:
- see https://aosnet.ch
Cheers,
--
Bjorn Victor Bjorn.Victor@it.uu.se
Dept. of Information Technology tel: +46 18 471 3169
Uppsala University mobile: +46 70 425 0239
Box 337 fax: +46 18 511925
S-751 05 Uppsala, SWEDEN web: http://user.it.uu.se/~victor
Bjorn Victor (bjorn@victor.se)