1
0
mirror of https://github.com/PDP-10/klh10.git synced 2026-04-03 12:22:55 +00:00

Add tap/bridge support,

and some other small build support things for my environment.
This commit is contained in:
Olaf Seibert
2015-04-27 23:33:58 +02:00
parent f5ed23867f
commit 0a03946833
11 changed files with 374 additions and 36 deletions

View File

@@ -1,2 +1,5 @@
#!/bin/sh
make base-kl CONFFLAGS_AUX=-DKLH10_I_CIRC=1
# or
# make base-ks CONFFLAGS_AUX=-DKLH10_I_CIRC=1
# make base-ks-its CONFFLAGS_AUX=-DKLH10_I_CIRC=1

View File

@@ -1,2 +1,4 @@
#!/bin/sh
export KL10HOME=/scratch/tops20/emulators/panda-dist/i386
make base-kl CONFFLAGS_AUX=-DKLH10_I_CIRC=1
#make base-ks-its CONFFLAGS_AUX=-DKLH10_I_CIRC=1

View File

@@ -175,6 +175,16 @@ config file if they don't already exist (correct as of FreeBSD 4.2):
pseudo-device bpf 1 # Need at least one for NI20 or IMP
pseudo-device tun 1 # Need at least one for IMP
NetBSD
------
See The NetBSD Guide, chapter 17.9 "Kernel Tuning" for information on
how to recompile a kernel. You need at least these options (as of 3.0):
options SYSVSHM # System V-like memory sharing
options SHMMAXPGS=10240 # 2048 pages is the default, >8192 for KLH10
pseudo-device tap # cloning device for NI20
pseudo-device bridge # cloning device for NI20
Linux
-----
@@ -1116,6 +1126,36 @@ mistakenly "fixed" to disallow it (FreeBSD).
other host before telnetting back into the KN10. A better solution
would be to fix those OSes that are open-source, and push to have
these fixes incorporated in the standard releases.
For NetBSD (it may work on FreeBSD too) there exists a better
solution. A special configuration is created with a virtual ethernet
segment that has its host-side in the form of the interface tap0 (as in
the example below). The tap0 interface is bridged to the real network
interface. The NI20 is at the "other end" of the virtual ethernet.
(This differs from the other connectivity methods where the named
interface is the one that is basically used as the NI20). The NI20 is
therefore a dedicated interface:
devdef ni0 564 ni20 ipaddr=10.0.0.51 ifc=tap0 dedic=true
If the named tap interface already exists, no further changes to its
configuration are made. You can use this for alternative connectivity,
such as routed on the 10.0.1.0/24 subnet (instead of bridged):
# To the shell, suppose your real network is 10.0.0.0/24,
# create a 10.0.1.0/24 network for KLH:
ifconfig tap0 create inet 10.0.1.1 netmask 255.255.255.0 up
; in .ini file:
devdef ni0 564 ni20 ipaddr=10.0.1.51 ifc=tap0 dedic=true
! in SYSTEM:INTERNET.ADDRESS on TOPS-20 v7.0
IPNI#0,10 0 1 51,PACKET-SIZE:1500,DEFAULT,PREFERRED
! in SYSTEM:INTERNET.ADDRESS on TOPS-20 v7.1
IPNI#0,10.0.1.51,PACKET-SIZE:1500,LOGICAL-HOST-MASK:255.255.255.0,DEFAULT,PREFERRED
! in SYSTEM:INTERNET.GATEWAYS on TOPS-20 v7.x
PRIME 10.0.1.1
(If TOPS-20 v7.0 can't do subnetting it might be better to use a
192.168.2.0/24 network)
LHDH (IMP): (KS-ITS only)

View File

@@ -12,7 +12,12 @@ devdef mta0 rh1.0 tm03 type=tu45
; Need KLNI to avoid LAPRBF BUGCHKs - use valid address if known
;
devdef ni0 564 ni20 ipaddr=10.0.0.51
; devdef ni0 564 ni20 ipaddr=10.0.0.51
; The (NetBSD/FreeBSD) version with tap(4) and bridge(4) creates the named
; tap device dynamically and bridges it to the default interface.
; If you want it differently (for instance routed instead of bridged),
; you can create the tap yourself and it will be used as it is.
devdef ni0 564 ni20 ipaddr=10.0.0.51 ifc=tap0 dedic=true
; Load disk bootstrap directly
load boot.sav

View File

@@ -21,7 +21,7 @@
# Build definitions
SRC = ../../src
CFLAGS = -c -g3 -O3
CFLAGS = -c -g3 -O3 -ggdb
CFLAGS_LINT = -ansi -pedantic -Wall -Wshadow \
-Wstrict-prototypes -Wmissing-prototypes \
-Wmissing-declarations -Wredundant-decls

View File

@@ -228,6 +228,10 @@ default for every OS that implements /dev/tun.
#include <sys/resource.h> /* For setpriority() */
#include <sys/mman.h> /* For mlockall() */
#if CENV_SYS_NETBSD
#include <poll.h>
#endif
#include "dpimp.h" /* DPIMP specific defs, grabs DPSUP if needed */
#ifdef RCSID

View File

@@ -169,6 +169,7 @@ The following general situations are possible:
RCSID(dpni20_c,"$Id: dpni20.c,v 2.7 2003/02/23 18:07:50 klh Exp $")
#endif
/* Globals */
int chpid; /* PID of child, handles input (net-to-10). */
@@ -432,6 +433,8 @@ main(int argc, char **argv)
progname = progname_w; /* Reset progname to indicate identity */
tentoeth(dpni); /* Parent process handles output to net */
osn_pfdeinit();
return 1; /* Never returns, but placate compiler */
}
@@ -498,6 +501,7 @@ void net_init(register struct dpni20_s *dpni)
ea_set(&ihost_ea, &npf.osnpf_ea); /* Copy actual ea */
}
/* Now set any return info values in shared struct.
*/
memcpy(dpni->dpni_eth, (char *)&ihost_ea, 6); /* Copy ether addr */
@@ -996,7 +1000,7 @@ pfshow(struct OSN_PFSTRUCT *pf)
/* LNX packetfilter initialization */
#if KLH10_NET_LNX
#if KLH10_NET_LNX || KLH10_NET_TAP_BRIDGE
/*
The Linux PF_PACKET interface is described to some extent
@@ -1092,6 +1096,10 @@ int lnx_filter(register struct dpni20_s *dpni,
*/
void eth_adrset(register struct dpni20_s *dpni)
{
#if OSN_USE_IPONLY
dbprintln("\"%s\" multicast table ignored - IP-only interface",
dpni->dpni_ifnam);
#else
unsigned char rdea[ETHER_ADRSIZ];
char old[OSN_EASTRSIZ];
char new[OSN_EASTRSIZ];
@@ -1157,6 +1165,7 @@ void eth_adrset(register struct dpni20_s *dpni)
}
}
#endif
/* Assume succeeded since call succeeded, and clobber our address! */
memcpy(dpni->dpni_eth, dpni->dpni_rqeth, ETHER_ADRSIZ);
}
@@ -1175,6 +1184,10 @@ void eth_adrset(register struct dpni20_s *dpni)
void eth_mcatset(register struct dpni20_s *dpni)
{
#if OSN_USE_IPONLY
dbprintln("\"%s\" multicast table ignored - IP-only interface",
dpni->dpni_ifnam);
#else
ossock_t s;
int i, n, j;
char ethstr[OSN_EASTRSIZ];
@@ -1249,6 +1262,7 @@ void eth_mcatset(register struct dpni20_s *dpni)
nmcats = n;
memcpy(ethmcat[0], dpni->dpni_mcat[0], (n * 6));
#endif
}
/* ARP Hackery */
@@ -1361,7 +1375,9 @@ int arp_myreply(register unsigned char *buf, register int cnt)
/* Now send it! Ignore any errors. */
if (swstatus) {
char ipstr[OSN_IPSTRSIZ];
dbprintln("ARP MyReply %s", ip_adrsprint(ipstr, ife->ife_ipchr));
char ethstr[OSN_EASTRSIZ];
dbprintln("ARP MyReply %s %s", ip_adrsprint(ipstr, ife->ife_ipchr),
eth_adrsprint(ethstr, ife->ife_ea));
}
#if KLH10_NET_DLPI
@@ -1372,6 +1388,9 @@ int arp_myreply(register unsigned char *buf, register int cnt)
(void) putmsg(pffd, NULL, &data, 0);
}
#else
/* XXX
* Why is this sent to the packet filter (= host) and not to the -10?????
*/
(void)write(pffd, pktbuf, sizeof(pktbuf));
#endif
return TRUE;
@@ -1441,7 +1460,7 @@ void ethtoten(register struct dpni20_s *dpni)
cnt = data.len;
/* Else cnt must be -1 as call failed */
}
#elif KLH10_NET_NIT || KLH10_NET_PFLT || KLH10_NET_LNX
#elif KLH10_NET_NIT || KLH10_NET_PFLT || KLH10_NET_LNX || KLH10_NET_TAP_BRIDGE
cnt = read(pffd, buff, max);
#elif KLH10_NET_BPF
cnt = read(pffd, tbuff, tmax);
@@ -1499,17 +1518,20 @@ void ethtoten(register struct dpni20_s *dpni)
else
dbprint("Read=%d", cnt);
}
#if KLH10_NET_LNX
#if KLH10_NET_LNX || KLH10_NET_TAP_BRIDGE
/* Linux has no packet filtering, thus must apply manual check to
each and every packet read, unless dedicated. Ugh!
*/
if (!dpni->dpni_dedic) {
if (KLH10_NET_TAP_BRIDGE || !dpni->dpni_dedic) {
/* Sharing interface. Check for IP, DECNET, 802.3 */
if (!lnx_filter(dpni, buff, cnt))
if (!lnx_filter(dpni, buff, cnt)) {
if (DBGFLG)
dbprint("Dropped");
continue; /* Drop packet, continue reading */
}
}
#endif /* KLH10_NET_LNX */
#if KLH10_NET_NIT || KLH10_NET_DLPI || KLH10_NET_PFLT || KLH10_NET_LNX
#if KLH10_NET_NIT || KLH10_NET_DLPI || KLH10_NET_PFLT || KLH10_NET_LNX || KLH10_NET_TAP_BRIDGE
#if 0
if (DBGFLG)
if (((struct ether_header *)buff)->ether_type == htons(ETHERTYPE_ARP))
@@ -1521,7 +1543,7 @@ void ethtoten(register struct dpni20_s *dpni)
if (DBGFLG)
dbprint("sent RPKT");
#endif /* KLH10_NET_NIT || KLH10_NET_DLPI || KLH10_NET_PFLT || KLH10_NET_LNX */
#endif /* KLH10_NET_NIT || KLH10_NET_DLPI || KLH10_NET_PFLT || KLH10_NET_LNX || NET_TAP_BRIDGE */
#if KLH10_NET_BPF
/* Screwy BPF algorithm requires more overhead because there's
@@ -1594,7 +1616,11 @@ void tentoeth(register struct dpni20_s *dpni)
/* Must check for outbound ARP requests if asked to and have
** at least one entry in our table of host's IP interfaces.
*/
#if KLH10_NET_TAP_BRIDGE
doarpchk = 0;
#else
doarpchk = (dpni->dpni_doarp & DPNI_ARPF_OCHK) && (osn_nifents() > 0);
#endif
dpx = dp_dpxto(&dp); /* Get ptr to "To-DP" xfer stuff */
buff = dp_xrbuff(dpx, &max);
@@ -1640,7 +1666,7 @@ void tentoeth(register struct dpni20_s *dpni)
}
#else
cnt = write(pffd, buff, rcnt);
#endif
#endif /* else KLH10_NET_DLPI */
if (cnt != rcnt) {
if ((cnt < 0) && (errno == EINTR)) {
continue; /* Start over, may have new cmd */
@@ -1701,6 +1727,9 @@ void dumppkt(unsigned char *ucp, int cnt)
fprintf(stderr, "\r\n");
}
}
/* Add OSDNET shared code here */

View File

@@ -337,6 +337,7 @@ CMDDEF(cd_lights, fc_lights, CMRF_TLIN, "<hexaddr>",
KEYSBEGIN(fectbkeys)
KEYDEF("?", cd_ques)
KEYDEF("help", cd_help)
KEYDEF("exit", cd_quit)
KEYDEF("quit", cd_quit)
KEYDEF("load", cd_load)
KEYDEF("dump", cd_dump)
@@ -2765,6 +2766,7 @@ fc_dump(struct cmd_s *cm)
static void
fc_lights(struct cmd_s *cm)
{
#if KLH10_DEV_LITES /* Moby conditional for entire file */
unsigned long port = 0;
int c;
char *sloc = cm->cmd_arglin;
@@ -2783,6 +2785,7 @@ fc_lights(struct cmd_s *cm)
}
}
printf("?Bad address\n");
#endif /* KLH10_DEV_LITES */
}
/* Instruction printing routines */

View File

@@ -759,7 +759,7 @@ dw10_t op10ashc(register dw10_t d,
** must be done to the argument prior to the call!
*/
static dw10_t
x_ashc(register dw10_t d,
x_ashc(/*register*/ dw10_t d,
register int i)
{
#endif /* IFFLAGS */
@@ -3238,7 +3238,7 @@ static int qdivstep(qw10_t *aq,
register dw10_t d,
register int nmagbits)
{
register qw10_t qw;
/*register*/ qw10_t qw;
dw10_t quot;
register int qbit;

View File

@@ -68,7 +68,7 @@ int
osn_ifsock(char *ifnam, ossock_t *as)
{
#if (KLH10_NET_NIT || KLH10_NET_DLPI || KLH10_NET_BPF || KLH10_NET_PFLT || \
KLH10_NET_TUN || KLH10_NET_LNX)
KLH10_NET_TUN || KLH10_NET_LNX || KLH10_NET_TAP_BRIDGE)
return ((*as = socket(AF_INET, SOCK_DGRAM, 0)) >= 0);
#else
# error OSD implementation needed for osn_ifsock
@@ -79,7 +79,7 @@ int
osn_ifclose(ossock_t s)
{
#if (KLH10_NET_NIT || KLH10_NET_DLPI || KLH10_NET_BPF || KLH10_NET_PFLT || \
KLH10_NET_TUN || KLH10_NET_LNX)
KLH10_NET_TUN || KLH10_NET_LNX || KLH10_NET_TAP_BRIDGE)
return (close(s) >= 0);
#else
# error OSD implementation needed for osn_ifclose
@@ -161,6 +161,12 @@ or alternatively:
? (sizeof(struct ifreq) - sizeof(struct sockaddr) + (ifr).ifr_addr.sa_len) \
: sizeof(struct ifreq))
This has been made trickier by NetBSD 5.0, which doesn't put a sockaddr
but a (union with as largest member a) sockaddr_storage in the ifreq.
Now the size is always the same again, but not sizeof(struct sockaddr).
This can (probably) be recognised by the existence of
#define ifr_space ifr_ifru.ifru_space / * sockaddr_storage * /
*/
/*
Note that searching for AF_INET or IP addresses only finds interfaces that
@@ -288,7 +294,7 @@ osn_iftab_pass(int opts, int npass, int s, struct ifconf *ifc)
uses a variable-size "ifreq" entry! Choke...
*/
ifnext = ifp + 1; /* Assume normal entry at first */
#if NETIF_HAS_SALEN
#if NETIF_HAS_SALEN && !defined(ifr_space)
if (ifp->ifr_addr.sa_len > sizeof(struct sockaddr)) {
offset = ifp->ifr_addr.sa_len - sizeof(struct sockaddr);
ifnext = (struct ifreq *)((char *)ifnext + offset);
@@ -382,6 +388,8 @@ osn_iftab_pass(int opts, int npass, int s, struct ifconf *ifc)
}
}
#include <stddef.h>
void
osn_ifctab_show(FILE *f, struct ifconf *ifc)
{
@@ -393,7 +401,14 @@ osn_ifctab_show(FILE *f, struct ifconf *ifc)
int nents = 0;
int nvary = 0;
fprintf(f, "Interface table: %ld bytes (%d entries if std addr len %d)\n",
fprintf(f, "sizeof struct ifreq = %d\r\n", (int) sizeof(struct ifreq));
fprintf(f, "IFNAMSIZ = %d\r\n", (int) IFNAMSIZ);
fprintf(f, "offset of struct sockaddr_storage = %d\r\n", (int) offsetof(struct ifreq, ifr_space));
fprintf(f, "sizeof struct sockaddr = %d\r\n", (int) sizeof(struct sockaddr));
fprintf(f, "sizeof struct sockaddr_storage = %d\r\n", (int) sizeof(struct sockaddr_storage));
fprintf(f, "sizeof union ifr_ifru = %d\r\n", (int) sizeof(ifr->ifr_ifru));
fprintf(f, "Interface table: %ld bytes (%d entries if std addr len %d)\r\n",
(long)ifc->ifc_len, ifc->ifc_len/sizeof(struct ifreq),
(int)sizeof(struct sockaddr));
@@ -408,18 +423,19 @@ osn_ifctab_show(FILE *f, struct ifconf *ifc)
len = sizeof(struct sockaddr);
#endif
fprintf(f, "offset: %d\r\n", (int)((char *)ifr - (char *)ifc->ifc_req));
/* Output entry data */
fprintf(f, "%2d: \"%.*s\" fam %d, len %d",
fprintf(f, "%2d: \"%.*s\" sockaddr.sa_family %d, .sa_len %d",
i, (int)sizeof(ifr->ifr_name), ifr->ifr_name,
ifr->ifr_addr.sa_family, len);
if (len) {
cp = (unsigned char *) ifr->ifr_addr.sa_data;
fprintf(f, " = %x", *cp);
fprintf(f, " = (sockaddr.sa_data) %x", *cp);
for (--len; len > 0; --len) {
fprintf(f, ":%x", *++cp);
}
}
fprintf(f, "\n");
fprintf(f, "\r\n");
cp = (unsigned char *) ifr->ifr_addr.sa_data;
switch (ifr->ifr_addr.sa_family) {
@@ -429,7 +445,7 @@ osn_ifctab_show(FILE *f, struct ifconf *ifc)
struct in_addr *in = &skin->sin_addr;
unsigned char *ucp = (unsigned char *) &in->s_addr;
fprintf(f, " AF_INET = port %d, IP %d.%d.%d.%d\n",
fprintf(f, " AF_INET = port %d, IP %d.%d.%d.%d\r\n",
(int)skin->sin_port,
ucp[0], ucp[1], ucp[2], ucp[3]);
}
@@ -439,7 +455,7 @@ osn_ifctab_show(FILE *f, struct ifconf *ifc)
case AF_LINK:
{
struct sockaddr_dl *dla = (struct sockaddr_dl *) &ifr->ifr_addr;
fprintf(f, " AF_LINK = type %d, alen %d",
fprintf(f, " AF_LINK = type %d, sdl_alen %d",
dla->sdl_type, dla->sdl_alen);
if (len = dla->sdl_alen) {
cp = (unsigned char *) LLADDR(dla);
@@ -448,18 +464,23 @@ osn_ifctab_show(FILE *f, struct ifconf *ifc)
fprintf(f, ":%x", *++cp);
}
}
fprintf(f, "\n");
fprintf(f, "\r\n");
}
break;
#endif
#if defined(AF_INET6)
case AF_INET6:
fprintf(f, " AF_INET6 (No handler for this)\r\n");
break;
#endif
default:
fprintf(f, " No handler for this family\n");
fprintf(f, " No handler for this family\r\n");
}
/* Move onto next entry */
#if NETIF_HAS_SALEN
#if NETIF_HAS_SALEN && !defined(ifr_space)
if (ifr->ifr_addr.sa_len > sizeof(struct sockaddr)) {
++nvary;
ifr = (struct ifreq *)((char *)(ifr + 1) +
@@ -469,10 +490,10 @@ osn_ifctab_show(FILE *f, struct ifconf *ifc)
ifr++;
}
if (nvary)
fprintf(f, "Interface summary: %d entries of varying length\n",
fprintf(f, "Interface summary: %d entries of varying length\r\n",
nents);
else
fprintf(f, "Interface summary: %d entries of std length %d\n",
fprintf(f, "Interface summary: %d entries of std length %d\r\n",
nents, (int)sizeof(struct ifreq));
}
@@ -483,7 +504,7 @@ osn_iftab_show(FILE *f, struct ifent *ifents, int nents)
register struct ifent *ife;
int i;
fprintf(f, "Filtered IFE table: %d entries\n", nents);
fprintf(f, "Filtered IFE table: %d entries\r\n", nents);
for (i = 0, ife = ifents; i < nents; ++i, ++ife) {
fprintf(f, "%2d: \"%s\"", i, ife->ife_name);
@@ -502,7 +523,7 @@ osn_iftab_show(FILE *f, struct ifent *ifents, int nents)
fprintf(f, " (Other: fam %d)",
ife->ife_pother->ifr_addr.sa_family);
}
fprintf(f, "\n");
fprintf(f, "\r\n");
}
}
@@ -897,6 +918,9 @@ osn_ifeaget(int s, /* Socket for (AF_INET, SOCK_DGRAM, 0) */
return TRUE;
}
static struct eth_addr emhost_ea = /* Emulated host ether addr for tap */
{ 0xf2, 0x0b, 0xa4, 0xff, 0xff, 0xff };
/* OSN_PFEAGET - get physical ethernet address for an open packetfilter FD.
*
* Also not well documented, but generally easier to perform.
@@ -945,8 +969,20 @@ osn_pfeaget(int pfs, /* Packetfilter socket or FD */
}
ea_set(eap, endp.end_addr);
#elif KLH10_NET_BPF && !CENV_SYS_NETBSD && !CENV_SYS_FREEBSD
/* NetBSD no longer seems to support this */
#elif KLH10_NET_TAP_BRIDGE
/* If we do tap(4) + bridge(4), the ether address of the tap is wholly
* irrelevant, it is on the other side of the "wire".
* Our own address is something we can make up completely.
*/
if (emhost_ea.ea_octets[5] == 0xFF) {
time_t t = time(NULL);
emhost_ea.ea_octets[5] = t & 0xFE;
emhost_ea.ea_octets[4] = (t >> 8) & 0xFF;
emhost_ea.ea_octets[3] = (t >> 16) & 0xFF;
}
ea_set(eap, &emhost_ea); /* Return the ether address */
#elif (KLH10_NET_BPF && !CENV_SYS_NETBSD && !CENV_SYS_FREEBSD)
/* NetBSD no longer seems to support this (on bpf) */
struct ifreq ifr;
strncpy(ifr.ifr_name, ifnam, sizeof(ifr.ifr_name));
@@ -1131,7 +1167,7 @@ osn_ifeaset(int s, /* Socket for (AF_INET, SOCK_DGRAM, 0) */
char *ifnam, /* Interface name */
unsigned char *newpa) /* New ether address */
{
#if CENV_SYS_DECOSF || KLH10_NET_LNX \
#if CENV_SYS_DECOSF || KLH10_NET_LNX || KLH10_NET_TAP_BRIDGE \
|| (CENV_SYS_FREEBSD && defined(SIOCSIFLLADDR))
/* Common preamble code */
@@ -1190,6 +1226,8 @@ osn_ifeaset(int s, /* Socket for (AF_INET, SOCK_DGRAM, 0) */
if (ownsock) close(s);
return FALSE;
}
# elif KLH10_NET_TAP_BRIDGE
ea_set(&emhost_ea, newpa);
# else
# error "Unimplemented OS routine osn_ifeaset()"
# endif
@@ -1338,6 +1376,7 @@ pfopen(void)
}
#endif /* KLH10_NET_PFLT || KLH10_NET_BPF */
#if KLH10_NET_PFLT
@@ -1916,6 +1955,212 @@ osn_pfinit(struct osnpf *osnpf, void *arg)
}
#endif /* KLH10_NET_NIT */
/*
* Too bad that this is never called...
*/
osn_pfdeinit()
{
#if KLH10_NET_TAP_BRIDGE
void tap_bridge_close();
tap_bridge_close();
#endif
}
#if KLH10_NET_TAP_BRIDGE
osn_pfinit(register struct osnpf *osnpf, void *arg)
{
int fd;
char *ifnam = osnpf->osnpf_ifnam;
/* No "default interface" concept here */
if (!ifnam || !ifnam[0])
esfatal(1, "Packetfilter interface must be specified");
fd = tap_bridge_open(ifnam);
/* Now get our fresh new virtual interface's ethernet address.
*/
(void) osn_pfeaget(fd, ifnam, (unsigned char *)&(osnpf->osnpf_ea));
return fd;
}
#include <net/if_tap.h>
#include <net/if_bridgevar.h>
#include <stdint.h>
static struct ifreq br_ifr;
static struct ifreq tap_ifr;
static int my_tap;
/*
* A TAP is a virtual ethernet interface, much like TUN is a virtual IP
* interface. We can use it to inject packets into the Unix input stream,
* provided it is UP and the host side has a matching IP address and
* netmask (also much like TUN), or that it is bridged to another interface.
*
* Here we try to create the user-given interface and then bridge it to
* the "default" interface. This is probably the most common configuration.
* If something else is desired, the user can set up the tap herself,
* and we'll just use it as it is. This is useful for a routed approach,
* for instance.
*/
int
tap_bridge_open(char *ifnam)
{
int tapfd;
int res;
union ipaddr netmask;
char cmdbuff[128];
struct ifent *ife;
int s;
int i;
struct ifbreq br_req;
struct ifdrv br_ifd;
if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
esfatal(1, "tap_bridge_open: socket() failed");
}
/* try to create tapN as specified by the user */
memset(&tap_ifr, 0, sizeof(tap_ifr));
strcpy(tap_ifr.ifr_name, ifnam);
res = ioctl(s, SIOCIFCREATE, &tap_ifr);
if (res == 0) {
my_tap = 1;
dbprintln("Created host-side tap \"%s\"", ifnam);
} else {
if (errno != EEXIST)
esfatal(1, "tap_bridge_open: can't create tap \"%s\"?", ifnam);
my_tap = 0;
dbprintln("Host-side tap \"%s\" alread exists; use it as-is", ifnam);
}
sprintf(cmdbuff, "/dev/%s", ifnam);
tapfd = open(cmdbuff, O_RDWR, 0);
if (tapfd < 0) {
/* Note possible error meanings:
ENOENT - no such filename
ENXIO - not configured in kernel
*/
esfatal(1, "Couldn't find or open 10-side tap \"%s\"", cmdbuff);
}
dbprintln("Opened 10-side tap \"%s\"", cmdbuff);
/* Finally, turn on IFF_UP just in case the above didn't do it.
Note interface name is still there from the SIOCIFCREATE.
*/
if (ioctl(s, SIOCGIFFLAGS, &tap_ifr) < 0) {
esfatal(1, "tap_bridge_open tap SIOCGIFFLAGS failed");
}
if (!(tap_ifr.ifr_flags & IFF_UP)) {
tap_ifr.ifr_flags |= IFF_UP;
if (ioctl(s, SIOCSIFFLAGS, &tap_ifr) < 0) {
esfatal(1, "tap_bridge_open tap SIOCSIFFLAGS failed");
}
if (DP_DBGFLG)
dbprint("tap_bridge_open tap did SIOCSIFFLAGS");
}
if (my_tap) {
for (i = 0; i < 1000; i++) {
/* try to create bridge%d */
memset(&br_ifr, 0, sizeof(br_ifr));
sprintf(br_ifr.ifr_name, "bridge%d", i);
res = ioctl(s, SIOCIFCREATE, &br_ifr);
if (res == 0)
break;
if (errno != EEXIST)
esfatal(1, "tap_bridge_open: can't create bridge \"%s\"?", br_ifr.ifr_name);
}
dbprintln("Created bridge \"%s\"", br_ifr.ifr_name);
/*
* Find default IP interface to bridge with.
* It might find the wrong one if there is more than one.
*/
ife = osn_ipdefault();
if (!ife)
esfatal(0, "Couldn't find default interface");
if (swstatus)
dbprintln("Bridging with default interface \"%s\"", ife->ife_name);
if (1) {
sprintf(cmdbuff, "/sbin/brconfig %s add %s add %s up",
br_ifr.ifr_name, ife->ife_name, ifnam);
res = system(cmdbuff);
dbprintln("%s => %d", cmdbuff, res);
} else {
/* do whatever brconfig bridge0 add intf0 does... */
memset(&br_ifd, 0, sizeof(br_ifd));
memset(&br_req, 0, sizeof(br_req));
/* set name of the bridge */
strcpy(br_ifd.ifd_name, br_ifr.ifr_name);
br_ifd.ifd_cmd = BRDGADD;
br_ifd.ifd_len = sizeof(br_req);
br_ifd.ifd_data = &br_req;
/* brconfig bridge0 add tap0 (the virtual interface) */
strcpy(br_req.ifbr_ifsname, ifnam);
res = ioctl(s, SIOCSDRVSPEC, &br_ifd);
if (res == -1)
esfatal(1, "tap_bridge_open: can't add virtual intf to bridge?");
/* brconfig bridge0 add vr0 (the hardware interface) */
strcpy(br_req.ifbr_ifsname, ife->ife_name);
res = ioctl(s, SIOCSDRVSPEC, &br_ifd);
if (res == -1)
esfatal(1, "tap_bridge_open: can't add real intf to bridge?");
/* Finally, turn on IFF_UP just in case the above didn't do it.
* Note interface name is still there.
*/
if (ioctl(s, SIOCGIFFLAGS, &br_ifr) < 0) {
esfatal(1, "tap_bridge_open bridge SIOCGIFFLAGS failed");
}
if (!(br_ifr.ifr_flags & IFF_UP)) {
br_ifr.ifr_flags |= IFF_UP;
if (ioctl(s, SIOCSIFFLAGS, &br_ifr) < 0) {
esfatal(1, "tap_bridge_open bridge SIOCSIFFLAGS failed");
}
if (DP_DBGFLG)
dbprint("tap_bridge_open bridge did SIOCSIFFLAGS");
}
}
}
close(s);
return tapfd; /* Success! */
}
void
tap_bridge_close()
{
if (my_tap) {
int s, res;
struct ifreq tap_ifr;
if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
esfatal(1, "tap_bridge_close: socket() failed");
}
/* Destroy bridge */
res = ioctl(s, SIOCIFDESTROY, &br_ifr);
res = ioctl(s, SIOCIFDESTROY, &tap_ifr);
close(s);
}
}
#endif /* KLH10_NET_TAP_BRIDGE */
#if KLH10_NET_DLPI
/* DLPI packetfilter initialization */

View File

@@ -59,6 +59,9 @@
#ifndef KLH10_NET_DLPI /* Solaris Data Link Provider Interface */
# define KLH10_NET_DLPI 0
#endif
#ifndef KLH10_NET_TAP_BRIDGE /* BSD Ethernet Tunnel device + a bridge */
# define KLH10_NET_TAP_BRIDGE 0
#endif
#ifndef KLH10_NET_TUN /* BSD IP Tunnel device */
# define KLH10_NET_TUN 0
#endif
@@ -67,14 +70,18 @@
#endif
#if !(KLH10_NET_NIT || KLH10_NET_DLPI || KLH10_NET_BPF || KLH10_NET_PFLT || \
KLH10_NET_TUN || KLH10_NET_LNX)
KLH10_NET_TUN || KLH10_NET_LNX || KLH10_NET_TAP_BRIDGE)
/* None explicitly specified, pick a reasonable default */
# if (CENV_SYS_FREEBSD && OSN_USE_IPONLY)
# if ((CENV_SYS_NETBSD || CENV_SYS_FREEBSD) && OSN_USE_IPONLY)
# undef KLH10_NET_TUN
# define KLH10_NET_TUN 1
# elif (CENV_SYS_NETBSD || CENV_SYS_FREEBSD)
# undef KLH10_NET_BPF
# define KLH10_NET_BPF 1
/*
* # undef KLH10_NET_BPF
* # define KLH10_NET_BPF 1
*/
# undef KLH10_NET_TAP_BRIDGE
# define KLH10_NET_TAP_BRIDGE 1
# elif CENV_SYS_DECOSF
# undef KLH10_NET_PFLT
# define KLH10_NET_PFLT 1