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:
4
.gitignore
vendored
4
.gitignore
vendored
@@ -19,3 +19,7 @@ new
|
||||
src/tags
|
||||
src/config.h.in
|
||||
tmp*/*
|
||||
#*#
|
||||
*/#*#
|
||||
*.~*
|
||||
*/*.~*
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
1578
src/dpchaos.c
Normal file
File diff suppressed because it is too large
Load Diff
133
src/dpchaos.h
Normal file
133
src/dpchaos.h
Normal 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 */
|
||||
912
src/dpchudp.c
912
src/dpchudp.c
@@ -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
|
||||
108
src/dpchudp.h
108
src/dpchudp.h
@@ -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 */
|
||||
444
src/dvch11.c
444
src/dvch11.c
@@ -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! */
|
||||
}
|
||||
|
||||
@@ -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) */
|
||||
|
||||
|
||||
122
src/dvch11.txt
122
src/dvch11.txt
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user