1
0
mirror of https://github.com/PDP-10/klh10.git synced 2026-02-06 00:15:26 +00:00

Intermediate state.

Tested with ITS and ifmeth=pcap, tun, and tap+bridge.
This commit is contained in:
Olaf Seibert
2016-01-06 00:52:37 +01:00
parent 6f1f3b4758
commit ff6747d034
5 changed files with 193 additions and 178 deletions

View File

@@ -276,7 +276,7 @@ int othlockid;
int swstatus = TRUE;
struct pfdata pfdata; /* Packet-Filter state */
struct in_addr ehost_ip; /* Emulated host IP addr, net order */
struct in_addr ehost_ip; /* Emulated guest IP addr, net order */
struct in_addr ihost_ip; /* IMP/Native host IP addr, net order */
struct in_addr ihost_nm; /* IMP/Native host subnet netmask, net order */
struct in_addr ihost_net; /* IMP/Native host net #, net order */
@@ -522,59 +522,59 @@ main(int argc, char **argv)
/* Initialize various network info */
net_init(dpimp);
if (!pfdata.pf_ip4_only) {
/* TUN may not have an ethernet address associated with it;
not sure what to do if DPIMP turns out to need one.
*/
#if !KLH10_NET_TUN
/* TUN may not have an ethernet address associated with it;
not sure what to do if DPIMP turns out to need one.
*/
/* See if ether address needs to be set */
if (memcmp((void *)&ihost_ea, "\0\0\0\0\0\0", 6) != 0)
eaflags |= EAF_IHOST;
/* See if ether address needs to be set */
if (memcmp((void *)&ihost_ea, "\0\0\0\0\0\0", 6) != 0)
eaflags |= EAF_IHOST;
switch (eaflags & (EAF_IHOST|EAF_EHOST)) {
case 0:
efatal(1, "no ethernet address");
case EAF_IHOST:
break; /* OK, don't need anything special */
case EAF_EHOST:
error("couldn't get native ether addr, using specified");
ea_set(&ihost_ea, &ehost_ea);
break;
case EAF_IHOST|EAF_EHOST:
if (memcmp((void *)&ihost_ea, (void *)&ehost_ea, 6) == 0)
break; /* OK, addresses are same */
/* Ugh, specified an EA address different from one actually
** in use by interface! For now, don't allow clobberage.
*/
efatal(1, "changing ethernet addr is disallowed");
break;
switch (eaflags & (EAF_IHOST|EAF_EHOST)) {
case 0:
efatal(1, "no ethernet address");
case EAF_IHOST:
break; /* OK, don't need anything special */
case EAF_EHOST:
error("couldn't get native ether addr, using specified");
ea_set(&ihost_ea, &ehost_ea);
break;
case EAF_IHOST|EAF_EHOST:
if (memcmp((void *)&ihost_ea, (void *)&ehost_ea, 6) == 0)
break; /* OK, addresses are same */
/* Ugh, specified an EA address different from one actually
** in use by interface! For now, don't allow clobberage.
*/
efatal(1, "changing ethernet addr is disallowed");
break;
}
}
#endif /* !KLH10_NET_TUN */
/* Make this a status (rather than debug) printout? */
if (swstatus) {
char ipbuf[OSN_IPSTRSIZ];
char eabuf[OSN_EASTRSIZ];
#if !KLH10_NET_TUN
dbprintln("ifc \"%s\" => ether %s",
dpimp->dpimp_ifnam,
eth_adrsprint(eabuf, (unsigned char *)&ihost_ea));
dbprintln(" inet %s",
ip_adrsprint(ipbuf, (unsigned char *)&ihost_ip));
dbprintln(" netmask %s",
ip_adrsprint(ipbuf, (unsigned char *)&ihost_nm));
dbprintln(" net %s",
ip_adrsprint(ipbuf, (unsigned char *)&ihost_net));
dbprintln(" gwdef %s",
ip_adrsprint(ipbuf, (unsigned char *)&gwdef_ip));
#else
dbprintln("ifc \"%s\"",
dpimp->dpimp_ifnam);
dbprintln(" tun %s",
ip_adrsprint(ipbuf, (unsigned char *)&tun_ip));
#endif
dbprintln(" HOST %s",
if (pfdata.pf_ip4_only) {
dbprintln("ifc \"%s\"",
dpimp->dpimp_ifnam);
dbprintln(" tun %s",
ip_adrsprint(ipbuf, (unsigned char *)&tun_ip));
} else {
dbprintln("ifc \"%s\" => ether %s",
dpimp->dpimp_ifnam,
eth_adrsprint(eabuf, (unsigned char *)&ihost_ea));
dbprintln(" inet %s",
ip_adrsprint(ipbuf, (unsigned char *)&ihost_ip));
dbprintln(" netmask %s",
ip_adrsprint(ipbuf, (unsigned char *)&ihost_nm));
dbprintln(" net %s",
ip_adrsprint(ipbuf, (unsigned char *)&ihost_net));
dbprintln(" gwdef %s",
ip_adrsprint(ipbuf, (unsigned char *)&gwdef_ip));
}
dbprintln(" GUEST %s",
ip_adrsprint(ipbuf, (unsigned char *)&ehost_ip));
}
@@ -582,13 +582,13 @@ main(int argc, char **argv)
** Set up ARP entry so hardware host knows about our IP address and
** can respond to ARP requests for it.
*/
#if !KLH10_NET_TUN /* If TUN, already done by osn_pfinit */
arp_init(dpimp);
if (!osn_arp_stuff(dpimp->dpimp_ifnam,
(unsigned char *)&ehost_ip,
(unsigned char *)&ihost_ea, TRUE)) /* Set us up */
esfatal(1, "OSN_ARP_STUFF failed");
#endif
if (!pfdata.pf_ip4_only) {
arp_init(dpimp);
if (!osn_arp_stuff(dpimp->dpimp_ifnam,
(unsigned char *)&ehost_ip,
(unsigned char *)&ihost_ea, TRUE)) /* Set us up */
esfatal(1, "OSN_ARP_STUFF failed");
}
/* Now start up a child process to handle input */
if (DBGFLG)
@@ -630,89 +630,104 @@ void
net_init(struct dpimp_s *dpimp)
{
struct ifreq ifr;
char *ifnam_for_ipaddr; /* which interface to ask IP addr/netmask */
#if !KLH10_NET_TUN
if (osn_iftab_init() <= 0)
esfatal(0, "Couldn't find interface information");
#if 1 /* This code is identical to dpni20 - merge in osdnet? */
if (strcmp(dpimp->dpimp_ifmeth, "pcap") != 0) {
/*
* TUN or TAP or TAP+BRIDGE method.
* It is horrible to look at ifmeth; we would really like to
* look at something that tells us if the given interface name
* is one that the host uses for external communications.
*/
struct ifent *ife = osn_ipdefault();
if (!ife)
esfatal(0, "Couldn't find default interface");
ifnam_for_ipaddr = ife->ife_name;
} else {
/* PCAP method */
#if 1 /* This code is identical to dpni20 - merge in osdnet? */
/* Ensure network device name, if specified, isn't too long */
if (dpimp->dpimp_ifnam[0] && (strlen(dpimp->dpimp_ifnam)
>= sizeof(ifr.ifr_name))) {
esfatal(0, "interface name \"%s\" too long - max %d",
dpimp->dpimp_ifnam, (int)sizeof(ifr.ifr_name));
}
/* Determine network device to use, if none was specified (this only
** works for shared devices, as dedicated ones will be "down" and
** cannot be found by iftab_init).
** Also grab native IP and ethernet addresses, if ARP might need them.
*/
if ((!dpimp->dpimp_ifnam[0] && !dpimp->dpimp_dedic)
|| (dpimp->dpimp_doarp & DPIMP_ARPF_OCHK)) {
if (osn_iftab_init() <= 0)
esfatal(0, "Couldn't find interface information");
/* Found at least one! Pick first one, if a default is needed. */
if (!dpimp->dpimp_ifnam[0]) {
struct ifent *ife = osn_ipdefault();
if (!ife)
esfatal(0, "Couldn't find default interface");
if (strlen(ife->ife_name) >= sizeof(dpimp->dpimp_ifnam))
esfatal(0, "Default interface name \"%s\" too long, max %d",
ife->ife_name, (int)sizeof(dpimp->dpimp_ifnam));
strcpy(dpimp->dpimp_ifnam, ife->ife_name);
if (swstatus)
dbprintln("Using default interface \"%s\"", dpimp->dpimp_ifnam);
/* Ensure network device name, if specified, isn't too long */
if (dpimp->dpimp_ifnam[0] && (strlen(dpimp->dpimp_ifnam)
>= sizeof(ifr.ifr_name))) {
esfatal(0, "interface name \"%s\" too long - max %d",
dpimp->dpimp_ifnam, (int)sizeof(ifr.ifr_name));
}
/* Determine network device to use, if none was specified (this only
** works for shared devices, as dedicated ones will be "down" and
** cannot be found by iftab_init).
** Also grab native IP and ethernet addresses, if ARP might need them.
*/
if ((!dpimp->dpimp_ifnam[0] && !dpimp->dpimp_dedic)
|| (dpimp->dpimp_doarp & DPIMP_ARPF_OCHK)) {
/* Found at least one! Pick first one, if a default is needed. */
if (!dpimp->dpimp_ifnam[0]) {
struct ifent *ife = osn_ipdefault();
if (!ife)
esfatal(0, "Couldn't find default interface");
if (strlen(ife->ife_name) >= sizeof(dpimp->dpimp_ifnam))
esfatal(0, "Default interface name \"%s\" too long, max %d",
ife->ife_name, (int)sizeof(dpimp->dpimp_ifnam));
strcpy(dpimp->dpimp_ifnam, ife->ife_name);
if (swstatus)
dbprintln("Using default interface \"%s\"", dpimp->dpimp_ifnam);
}
ifnam_for_ipaddr = dpimp->dpimp_ifnam;
}
#endif /* 1 */
}
#endif
/* Now set remaining stuff */
/* Find IMP host's IP address for this interface */
if (!osn_ifipget(-1, dpimp->dpimp_ifnam, (unsigned char *)&ihost_ip)) {
efatal(1,"osn_ifipget failed for \"%s\"", dpimp->dpimp_ifnam);
}
/* Ditto for its network mask */
if (!osn_ifnmget(-1, dpimp->dpimp_ifnam, (unsigned char *)&ihost_nm)) {
efatal(1,"osn_ifnmget failed for \"%s\"", dpimp->dpimp_ifnam);
}
/* Now set remaining stuff */
ihost_net.s_addr = ihost_nm.s_addr & ihost_ip.s_addr; /* Local net */
/* Either move this check up much earlier, or find a way to
** query OS for a default gateway.
*/
if (gwdef_ip.s_addr == -1 || gwdef_ip.s_addr == 0)
efatal(1, "No default prime gateway specified");
#endif /* !KLH10_NET_TUN */
/* Set up appropriate net fd and packet filter.
** Should also determine interface's ethernet addr, if possible,
** and set ihost_ea.
*/
{
struct osnpf npf;
{
struct osnpf npf; /* Configuration data */
npf.osnpf_ifnam = dpimp->dpimp_ifnam;
npf.osnpf_ifmeth = dpimp->dpimp_ifmeth;
npf.osnpf_dedic = FALSE; /* Force filtering always! */
npf.osnpf_rdtmo = dpimp->dpimp_rdtmo;
npf.osnpf_backlog = dpimp->dpimp_backlog;
npf.osnpf_ip.ia_addr = ehost_ip;
npf.osnpf_tun.ia_addr = tun_ip;
/* Ether addr is both a potential arg and a returned value;
the packetfilter open may use and/or change it.
*/
ea_set(&npf.osnpf_ea, dpimp->dpimp_eth); /* Set requested ea if any */
osn_pfinit(&pfdata, &npf, (void *)dpimp); /* Will abort if fails */
ea_set(&ihost_ea, &npf.osnpf_ea); /* Copy actual ea if one */
tun_ip = npf.osnpf_tun.ia_addr; /* Copy actual tun if any */
}
npf.osnpf_ifnam = dpimp->dpimp_ifnam;
npf.osnpf_ifmeth = dpimp->dpimp_ifmeth;
npf.osnpf_dedic = FALSE; /* Force filtering always! */
npf.osnpf_rdtmo = dpimp->dpimp_rdtmo;
npf.osnpf_backlog = dpimp->dpimp_backlog;
npf.osnpf_ip.ia_addr = ehost_ip;
npf.osnpf_tun.ia_addr = tun_ip;
/* Ether addr is both a potential arg and a returned value;
the packetfilter open may use and/or change it.
*/
ea_set(&npf.osnpf_ea, dpimp->dpimp_eth);/* Set requested ea if any */
osn_pfinit(&pfdata, &npf, (void *)dpimp);/* Will abort if fails */
ea_set(&ihost_ea, &npf.osnpf_ea); /* Copy actual ea if one */
tun_ip = npf.osnpf_tun.ia_addr; /* Copy actual tun if any */
}
if (!pfdata.pf_ip4_only) {
/* Now set remaining stuff */
/* Find IMP host's IP address for this interface */
if (!osn_ifipget(-1, ifnam_for_ipaddr, (unsigned char *)&ihost_ip)) {
efatal(1,"osn_ifipget failed for \"%s\"", dpimp->dpimp_ifnam);
}
/* Ditto for its network mask */
if (!osn_ifnmget(-1, ifnam_for_ipaddr, (unsigned char *)&ihost_nm)) {
efatal(1,"osn_ifnmget failed for \"%s\"", dpimp->dpimp_ifnam);
}
/* Now set remaining stuff */
ihost_net.s_addr = ihost_nm.s_addr & ihost_ip.s_addr; /* Local net */
/* Either move this check up much earlier, or find a way to
** query OS for a default gateway.
*/
if (gwdef_ip.s_addr == -1 || gwdef_ip.s_addr == 0)
efatal(1, "No default prime gateway specified");
}
}
/* The DPIMP packet filter must implement the following test:
@@ -1452,8 +1467,11 @@ imptohost(struct dpimp_s *dpimp)
* manual check to each and every packet read, even if dedicated.
*/
if (!pfdata.pf_can_filter) {
if (!lnx_filter(dpimp, buffp, cnt))
if (!lnx_filter(dpimp, buffp, cnt)) {
if (DBGFLG)
dbprint("Dropped");
continue; /* Drop packet, continue reading */
}
}
if (!pfdata.pf_ip4_only) {
@@ -1652,22 +1670,27 @@ hosttoimp(struct dpimp_s *dpimp)
buff[SIH_HSIZ+SIL_LNK]);
continue;
}
#if KLH10_NET_TUN
if (DBGFLG)
dbprintln("net out = %d", rcnt - (SIH_HSIZ+SI_LDRSIZ));
if (osn_pfwrite(&pfdata, &buff[SIH_HSIZ+SI_LDRSIZ],
rcnt - (SIH_HSIZ+SI_LDRSIZ)) < 0)
syserr(errno, "tun write() failed");
else {
#else
if (hi_iproute(&ipdest, &buff[SIH_HSIZ], rcnt - SIH_HSIZ)) {
ip_write(&ipdest, &buff[SIH_HSIZ+SI_LDRSIZ],
rcnt - (SIH_HSIZ+SI_LDRSIZ));
#endif
int res = -1; /* Assume error */
if (pfdata.pf_ip4_only) {
if (DBGFLG)
dbprintln("net out = %d", rcnt - (SIH_HSIZ+SI_LDRSIZ));
if (osn_pfwrite(&pfdata, &buff[SIH_HSIZ+SI_LDRSIZ],
rcnt - (SIH_HSIZ+SI_LDRSIZ)) < 0) {
syserr(errno, "tun write() failed");
} else {
res = 0;
}
} else {
if (hi_iproute(&ipdest, &buff[SIH_HSIZ], rcnt - SIH_HSIZ)) {
ip_write(&ipdest, &buff[SIH_HSIZ+SI_LDRSIZ],
rcnt - (SIH_HSIZ+SI_LDRSIZ));
res = 0;
}
}
#if !SICONF_SIMP
# error "Too hard to implement non-Simple IMP model!"
# if 0
{ int res;
if (res == 0) {
/* IP packet sent out to net, now send RFNM to host */
buff[SIH_HSIZ+SIL_TYP] = SIMT_RFNM;
buff[2] = 0; /* High byte of count */
@@ -1680,7 +1703,6 @@ hosttoimp(struct dpimp_s *dpimp)
}
# endif
#endif
}
break;
case SIMT_LERR: /* Error in leader: err in previous IMP-to-Host ldr */
@@ -1798,7 +1820,6 @@ ether_write(struct eth_header *hp,
unsigned char *pp,
int cnt)
{
#if KLH10_NET_PCAP || KLH10_NET_TAP_BRIDGE
char *buf = (char *)(pp - ETHER_HDRSIZ);
if (DP_DBGFLG)
@@ -1810,12 +1831,6 @@ ether_write(struct eth_header *hp,
/* What to do here? For debugging, complain but return. */
error("write failed - %s", dp_strerror(errno));
}
#elif KLH10_NET_TUN
/* No code needed here -- routine never used */
#else
# error "No implementation for ether_write()"
#endif
}

View File

@@ -497,7 +497,6 @@ void net_init(struct dpni20_s *dpni)
/* Set up packet filter. This also returns in "ihost_ea"
the ethernet address for the selected interface.
*/
{
npf.osnpf_ifnam = dpni->dpni_ifnam;
npf.osnpf_ifmeth = dpni->dpni_ifmeth;
@@ -513,7 +512,6 @@ void net_init(struct dpni20_s *dpni)
osn_pfinit(&pfdata, &npf, (void *)dpni); /* Will abort if fails */
ea_set(&ihost_ea, &npf.osnpf_ea); /* Copy actual ea */
tun_ip = npf.osnpf_tun.ia_addr; /* Get actual tunnel addr */
}
/* Now set any return info values in shared struct.

View File

@@ -25,10 +25,6 @@
#ifndef DPNI20_INCLUDED
#define DPNI20_INCLUDED 1
#ifdef RCSID
RCSID(dpni20_h,"$Id: dpni20.h,v 2.3 2001/11/10 21:28:59 klh Exp $")
#endif
#ifndef DPSUP_INCLUDED
# include "dpsup.h"
#endif
@@ -39,7 +35,7 @@
/* Version of DPNI20-specific shared memory structure */
#define DPNI20_VERSION DPC_VERSION(1,1,2) /* 1.1.2 */
#define IFNAM_LEN 16 /* at least IFNAMSIZ! */
/* DPNI20-specific stuff */
/* C = controlling parent sets, D = Device proc sets */
@@ -49,7 +45,7 @@ struct dpni20_s {
int dpni_attrs; /* C Attribute flags */
# define DPNI20F_LSAP 0x0100 /* Set if LSAP value specified */
int dpni_lsap; /* C Dest/Source LSAP value if needed */
char dpni_ifnam[16]; /* CD Interface name if any */
char dpni_ifnam[IFNAM_LEN]; /* CD Interface name if any */
char dpni_ifmeth[16]; /* C Interface access method */
unsigned char dpni_eth[6]; /* CD Ethernet address of interface */
unsigned char dpni_ip[4]; /* C 10's IP address to filter on, if shared */

View File

@@ -1445,6 +1445,17 @@ struct tuntap_context {
*/
static struct tuntap_context tt_ctx;
static void
basenamecpy(char *dest, char *src, int len)
{
char *slash = strchr(src, '/');
if (slash) {
strncpy(dest, slash + 1, len);
} else {
strncpy(dest, src, len);
}
}
#define BASENAMESIZE 32
static int
@@ -1488,6 +1499,7 @@ pfopen(char *basename, struct tuntap_context *tt_ctx, struct osnpf *osnpf)
}
tt_ctx->my_tap = TRUE;
basenamecpy(osnpf->osnpf_ifnam, pfname, IFNAM_LEN);
return fd; /* Success! */
}
@@ -1496,6 +1508,15 @@ pfopen(char *basename, struct tuntap_context *tt_ctx, struct osnpf *osnpf)
#if KLH10_NET_TUN || KLH10_NET_TAP
# if CENV_SYS_LINUX
# define TUN_BASE "/dev/net/tun"
# define TAP_BASE "/dev/net/tun"
# else
# define TUN_BASE "/dev/tun"
# define TAP_BASE "/dev/tap"
# endif /* CENV_SYS_LINUX */
/*
In order to use the TUN interface we have to do the equivalent of
(1) "ifconfig tun0 <localaddr> <destaddr> up"
@@ -1556,7 +1577,7 @@ osn_pfinit_tuntap(struct pfdata *pfdata, struct osnpf *osnpf, void *arg)
int allowextern = TRUE; /* For now, always try for external access */
int fd;
struct ifreq ifr;
char ifnam[IFNAMSIZ];
char *ifnam = osnpf->osnpf_ifnam; /* alias for the persisting copy */
char ipb1[OSN_IPSTRSIZ];
char ipb2[OSN_IPSTRSIZ];
struct ifent *ife = NULL; /* Native host's default IP interface if one */
@@ -1571,7 +1592,7 @@ osn_pfinit_tuntap(struct pfdata *pfdata, struct osnpf *osnpf, void *arg)
if (DP_DBGFLG)
dbprint("Opening %s device",
pfdata->pf_ip4_only ? "TUN" : "TAP");
pfdata->pf_meth == PF_METH_TUN ? "TUN" : "TAP");
/* Local address can be set explicitly if we plan to do full IP
masquerading. */
@@ -1600,19 +1621,11 @@ osn_pfinit_tuntap(struct pfdata *pfdata, struct osnpf *osnpf, void *arg)
switch (pfdata->pf_meth) {
case PF_METH_TUN:
pfdata->pf_ip4_only = TRUE;
#if CENV_SYS_LINUX
basename = "/dev/net/tun";
#else
basename = "/dev/tun";
#endif /* CENV_SYS_LINUX */
basename = TUN_BASE;
break;
case PF_METH_TAP:
pfdata->pf_ip4_only = FALSE;
#if CENV_SYS_LINUX
basename = "/dev/net/tun";
#else
basename = "/dev/tap";
#endif /* CENV_SYS_LINUX */
basename = TAP_BASE;
break;
default:
esfatal(0, "pf_meth value %d invalid", pfdata->pf_meth);
@@ -1663,13 +1676,12 @@ osn_pfinit_tuntap(struct pfdata *pfdata, struct osnpf *osnpf, void *arg)
}
#endif
if (DP_DBGFLG)
if (DP_DBGFLG) {
dbprintln("Opened %s, configuring for local (host) %s, remote (guest) %s",
ifnam,
ip_adrsprint(ipb1, (unsigned char *)&iplocal),
ip_adrsprint(ipb2, (unsigned char *)&ipremote));
strncpy(osnpf->osnpf_ifnam, ifnam, IFNAM_LEN);
}
/* Activate TUN device.
First address is "local" -- doesn't matter if all we care about is
@@ -1815,12 +1827,6 @@ osn_pfinit_tuntap(struct pfdata *pfdata, struct osnpf *osnpf, void *arg)
publish an ARP entry mapping the virtual host to the same
ether addr.
*/
#if OSN_USE_IPONLY
/* dpni20 does this already; dpimp doesn't. */
if (!pfdata->pf_ip4_only) {
(void) osn_arp_stuff(ifnam, (unsigned char *)&ipremote, &emhost_ea, TRUE);
}
#endif
/* Return that as our ether address */
//ea_set((char *)&osnpf->osnpf_ea, ife->ife_ea); // no, use emhost_ea as set up above
@@ -1842,7 +1848,7 @@ osn_pfinit_tuntap(struct pfdata *pfdata, struct osnpf *osnpf, void *arg)
pfdata->pf_fd = fd;
pfdata->pf_handle = &tt_ctx;
pfdata->pf_can_filter = FALSE;
pfdata->pf_can_filter = pfdata->pf_ip4_only;
pfdata->pf_read = osn_pfread_fd;
pfdata->pf_write = osn_pfwrite_fd;
pfdata->pf_deinit = osn_pfdeinit_tuntap;
@@ -1855,7 +1861,7 @@ osn_pfinit_tuntap(struct pfdata *pfdata, struct osnpf *osnpf, void *arg)
#endif /* KLH10_NET_BRIDGE */
if (DP_DBGFLG)
dbprintln("osn_pfinit tun completed");
dbprintln("osn_pfinit_tuntap completed");
}

View File

@@ -276,7 +276,7 @@
#endif
#if !HAVE_LIBPCAP && !HAVE_GETIFADDRS
#error "Sorry, can't lookup ethernet interfaces without libpcap or getifaddrs(3)"
#error "Sorry, can't lookup ethernet interfaces without getifaddrs(3) or libpcap"
#endif
/* Interface table entry.