mirror of
https://github.com/PDP-10/klh10.git
synced 2026-02-06 00:15:26 +00:00
Add ch11 files and apply patch from http://victor.se/bjorn/its/ch11.tar.gz
This commit is contained in:
@@ -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
|
||||
DPROCS_KSITS = dprpxx dptm03 dpimp dpchudp
|
||||
|
||||
|
||||
# Base utility programs, independent of KN10
|
||||
@@ -290,6 +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 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
|
||||
@@ -297,6 +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 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
|
||||
@@ -546,6 +549,14 @@ kl0i-rtmopt:
|
||||
$(CONFFLAGS_AUX) \
|
||||
$(CONFFLAGS_USR) "
|
||||
|
||||
# --------- CHUDP subprocess (ITS KS only; counterpart for dvch11)
|
||||
#
|
||||
dpchudp.o: $(SRC)/dpchudp.c $(SRC)/dpchudp.h $(SRC)/dpsup.h
|
||||
$(BUILDMOD) $(SRC)/dpchudp.c
|
||||
|
||||
dpchudp: dpchudp.o dpsup.o
|
||||
$(LINKER) $(LDFLAGS) $(LDOUTF) dpchudp dpchudp.o dpsup.o $(LIBS)
|
||||
|
||||
|
||||
####################################################################
|
||||
## Device Process (DP) programs
|
||||
|
||||
910
src/dpchudp.c
Normal file
910
src/dpchudp.c
Normal file
@@ -0,0 +1,910 @@
|
||||
/* 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 "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));
|
||||
memset(&iplen, 0, sizeof(iplen));
|
||||
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];
|
||||
unsigned char *ip = (unsigned char *)&ip_sender.sin_addr.s_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 %d.%d.%d.%d port %d., %d. bytes (datalen %d)",
|
||||
chafrom,
|
||||
ip[0],ip[1],ip[2],ip[3], 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/%d.%d.%d.%d:%d",
|
||||
i, chafrom, ip[0],ip[1],ip[2],ip[3], port);
|
||||
dpchudp->dpchudp_chip_tbl[i].dpchudp_chip_ipport = port;
|
||||
memcpy(&dpchudp->dpchudp_chip_tbl[i].dpchudp_chip_ipaddr, ip, 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/%d.%d.%d.%d:%d",
|
||||
i, chafrom, ip[0],ip[1],ip[2],ip[3], 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, 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
Normal file
108
src/dpchudp.h
Normal file
@@ -0,0 +1,108 @@
|
||||
/* 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 */
|
||||
1328
src/dvch11.c
1328
src/dvch11.c
File diff suppressed because it is too large
Load Diff
@@ -107,4 +107,9 @@ extern struct device *dvch11_init(FILE *, char *);
|
||||
|
||||
#define UB_CH11END (UB_CHXMT+2) /* First addr not used by CH11 regs */
|
||||
|
||||
|
||||
#define CHAOS_HW_TRAILERSIZE (6) /* "hw" trailer bytes */
|
||||
#define CHAOS_HEADERSIZE (4*4) /* chaos packet header size */
|
||||
#define CHAOS_MAXDATA 488 /* Max data bytes per packet #### incl header? */
|
||||
|
||||
#endif /* ifndef DVCH11_INCLUDED */
|
||||
|
||||
111
src/dvch11.txt
Normal file
111
src/dvch11.txt
Normal file
@@ -0,0 +1,111 @@
|
||||
================================
|
||||
CHAOS is restored!
|
||||
or
|
||||
CH11 support for ITS in KLH10
|
||||
================================
|
||||
|
||||
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.
|
||||
|
||||
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!
|
||||
|
||||
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.
|
||||
|
||||
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.
|
||||
|
||||
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).
|
||||
|
||||
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).
|
||||
|
||||
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.)
|
||||
|
||||
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...
|
||||
|
||||
*BEWARE*:
|
||||
If you have both CHAOSP and IMPP, you run into a bug which results in
|
||||
all non-local IP packets being routed via Chaosnet... (unfortunately
|
||||
noone is listenting at Chaos address 3040).
|
||||
The bug is caused by the IPMASK macro defined and used in
|
||||
SYSTEM;CONFIG, which results in the netmask NM%CHA being zero, which
|
||||
matches anything. The easy fix is to change the line
|
||||
IFN CHAOSP,DEFOPT NM%CHA==<IPMASK IMPUS4> ; Set default netmask for it
|
||||
to
|
||||
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???
|
||||
|
||||
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
|
||||
|
||||
@@ -293,7 +293,7 @@ extern struct device *dvlhdh_create(FILE *f, char *s);
|
||||
extern struct device *dvdz11_init(FILE *f, char *s);
|
||||
#endif
|
||||
#if KLH10_DEV_CH11
|
||||
extern struct device *dvch11_init(FILE *f, char *s);
|
||||
extern struct device *dvch11_create(FILE *f, char *s);
|
||||
#endif
|
||||
|
||||
/* Table binding static device driver modules with their names
|
||||
@@ -329,7 +329,7 @@ static struct dvdrv_s dvdrvtab[KLH10_DEVMAX+1] = {
|
||||
{ "dz11", dvdz11_init, NULL, NULL, "DZ11 dummy (Unibus)" },
|
||||
#endif
|
||||
#if KLH10_DEV_CH11
|
||||
{ "ch11", dvch11_init, NULL, NULL, "Chaosnet dummy (Unibus)" },
|
||||
{ "ch11", dvch11_create, NULL, NULL, "Chaosnet interface (Unibus)" },
|
||||
#endif
|
||||
{ NULL, NULL, NULL }
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user