mirror of
https://github.com/PDP-10/klh10.git
synced 2026-05-03 22:48:17 +00:00
Add initial VDE (libvde2) support.
I have compile-tested this on a virtual FreeBSD 10.2 but not run it.
This commit is contained in:
@@ -43,6 +43,7 @@ AC_CHECK_LIB([pcap], [pcap_findalldevs])
|
|||||||
AC_CHECK_LIB([pcap], [pcap_set_immediate_mode],
|
AC_CHECK_LIB([pcap], [pcap_set_immediate_mode],
|
||||||
[AC_DEFINE(HAVE_PCAP_SET_IMMEDIATE_MODE, 1, [Set to 1 if we have pcap_set_immediate_mode])]
|
[AC_DEFINE(HAVE_PCAP_SET_IMMEDIATE_MODE, 1, [Set to 1 if we have pcap_set_immediate_mode])]
|
||||||
)
|
)
|
||||||
|
AC_CHECK_LIB([vdeplug], [vde_send])
|
||||||
NETLIBS="$LIBS"
|
NETLIBS="$LIBS"
|
||||||
LIBS="$SAVE_LIBS"
|
LIBS="$SAVE_LIBS"
|
||||||
|
|
||||||
@@ -51,7 +52,8 @@ AC_CHECK_HEADERS([arpa/inet.h errno.h fcntl.h limits.h netinet/in.h sgtty.h \
|
|||||||
stddef.h stdlib.h string.h sys/file.h sys/ioctl.h \
|
stddef.h stdlib.h string.h sys/file.h sys/ioctl.h \
|
||||||
sys/socket.h sys/time.h termios.h unistd.h net/if_tun.h \
|
sys/socket.h sys/time.h termios.h unistd.h net/if_tun.h \
|
||||||
linux/if_tun.h linux/if_packet.h net/if_tap.h sys/mtio.h \
|
linux/if_tun.h linux/if_packet.h net/if_tap.h sys/mtio.h \
|
||||||
net/nit.h sys/dlpi.h net/if_dl.h net/if_types.h])
|
net/nit.h sys/dlpi.h net/if_dl.h net/if_types.h \
|
||||||
|
libvdeplug.h])
|
||||||
|
|
||||||
# Checks for typedefs, structures, and compiler characteristics.
|
# Checks for typedefs, structures, and compiler characteristics.
|
||||||
AC_C_INLINE
|
AC_C_INLINE
|
||||||
|
|||||||
@@ -103,6 +103,7 @@ showdefs:
|
|||||||
@echo "MAKER = $(MAKER)"
|
@echo "MAKER = $(MAKER)"
|
||||||
@echo "CFLAGS = $(CFLAGS)"
|
@echo "CFLAGS = $(CFLAGS)"
|
||||||
@echo "CFLAGS_AUX = $(CFLAGS_AUX)"
|
@echo "CFLAGS_AUX = $(CFLAGS_AUX)"
|
||||||
|
@echo "LDFLAGS = $(LDFLAGS)"
|
||||||
@echo "LIBS = $(LIBS)"
|
@echo "LIBS = $(LIBS)"
|
||||||
@echo "NETLIBS = $(NETLIBS)"
|
@echo "NETLIBS = $(NETLIBS)"
|
||||||
@echo "CENVFLAGS = $(CENVFLAGS)"
|
@echo "CENVFLAGS = $(CENVFLAGS)"
|
||||||
|
|||||||
@@ -910,7 +910,7 @@ void eth_adrset(struct dpni20_s *dpni)
|
|||||||
/* Apparently won! Try reading it back just to be paranoid,
|
/* Apparently won! Try reading it back just to be paranoid,
|
||||||
* using packetfilter FD.
|
* using packetfilter FD.
|
||||||
*/
|
*/
|
||||||
if (!osn_pfeaget(pfdata.pf_fd, dpni->dpni_ifnam, rdea)) {
|
if (!osn_pfeaget(&pfdata, dpni->dpni_ifnam, rdea)) {
|
||||||
error("Can't read \"%s\" e/n addr!", dpni->dpni_ifnam);
|
error("Can't read \"%s\" e/n addr!", dpni->dpni_ifnam);
|
||||||
/* Proceed as if set won, sigh */
|
/* Proceed as if set won, sigh */
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
338
src/osdnet.c
338
src/osdnet.c
@@ -42,6 +42,11 @@
|
|||||||
# error "A bridge is useless without a TAP device... configuration error!"
|
# error "A bridge is useless without a TAP device... configuration error!"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if HAVE_LIBVDEPLUG_H && HAVE_LIBVDEPLUG
|
||||||
|
# include <libvdeplug.h>
|
||||||
|
# define KLH10_NET_VDE 1
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Local predeclarations */
|
/* Local predeclarations */
|
||||||
|
|
||||||
struct ifent *osn_iflookup(char *ifnam);
|
struct ifent *osn_iflookup(char *ifnam);
|
||||||
@@ -50,13 +55,13 @@ static struct ifent *osn_iftab_addaddress(char *name, struct sockaddr *addr, str
|
|||||||
#if KLH10_NET_PCAP
|
#if KLH10_NET_PCAP
|
||||||
static void osn_pfinit_pcap(struct pfdata *pfdata, struct osnpf *osnpf, void *pfarg);
|
static void osn_pfinit_pcap(struct pfdata *pfdata, struct osnpf *osnpf, void *pfarg);
|
||||||
static ssize_t osn_pfread_pcap(struct pfdata *pfdata, void *buf, size_t nbytes);
|
static ssize_t osn_pfread_pcap(struct pfdata *pfdata, void *buf, size_t nbytes);
|
||||||
static int osn_pfwrite_pcap(struct pfdata *pfdata, const void *buf, size_t nbytes);
|
static ssize_t osn_pfwrite_pcap(struct pfdata *pfdata, const void *buf, size_t nbytes);
|
||||||
#endif /* KLH10_NET_PCAP */
|
#endif /* KLH10_NET_PCAP */
|
||||||
#if KLH10_NET_TUN || KLH10_NET_TAP
|
#if KLH10_NET_TUN || KLH10_NET_TAP
|
||||||
static void osn_pfinit_tuntap(struct pfdata *pfdata, struct osnpf *osnpf, void *pfarg);
|
static void osn_pfinit_tuntap(struct pfdata *pfdata, struct osnpf *osnpf, void *pfarg);
|
||||||
static void osn_pfdeinit_tuntap(struct pfdata *pfdata, struct osnpf *osnpf);
|
static void osn_pfdeinit_tuntap(struct pfdata *pfdata, struct osnpf *osnpf);
|
||||||
static ssize_t osn_pfread_fd(struct pfdata *pfdata, void *buf, size_t nbytes);
|
static ssize_t osn_pfread_fd(struct pfdata *pfdata, void *buf, size_t nbytes);
|
||||||
static int osn_pfwrite_fd(struct pfdata *pfdata, const void *buf, size_t nbytes);
|
static ssize_t osn_pfwrite_fd(struct pfdata *pfdata, const void *buf, size_t nbytes);
|
||||||
#endif /* TUN || TAP */
|
#endif /* TUN || TAP */
|
||||||
|
|
||||||
struct tuntap_context;
|
struct tuntap_context;
|
||||||
@@ -66,6 +71,15 @@ void tap_bridge_close(struct tuntap_context *tt_ctx);
|
|||||||
#endif /* KLH10_NET_BRIDGE */
|
#endif /* KLH10_NET_BRIDGE */
|
||||||
static void osn_iff_up(int s, char *ifname);
|
static void osn_iff_up(int s, char *ifname);
|
||||||
static int pfopen_create(char *basename, struct tuntap_context *tt_ctx, struct osnpf *osnpf);
|
static int pfopen_create(char *basename, struct tuntap_context *tt_ctx, struct osnpf *osnpf);
|
||||||
|
#if KLH10_NET_VDE
|
||||||
|
static void osn_pfinit_vde(struct pfdata *pfdata, struct osnpf *osnpf, void *pfarg);
|
||||||
|
static void osn_pfdeinit_vde(struct pfdata *pfdata, struct osnpf *osnpf);
|
||||||
|
static ssize_t osn_pfread_vde(struct pfdata *pfdata, void *buf, size_t nbytes);
|
||||||
|
static ssize_t osn_pfwrite_vde(struct pfdata *pfdata, const void *buf, size_t nbytes);
|
||||||
|
#endif /* KLH10_NET_VDE */
|
||||||
|
#if KLH10_NET_TUN || KLH10_NET_TAP || KLH10_NET_VDE
|
||||||
|
static void osn_virt_ether(struct pfdata *pfdata, struct osnpf *osnpf);
|
||||||
|
#endif /* TUN || TAP || VDE */
|
||||||
|
|
||||||
/* Get a socket descriptor suitable for general net interface
|
/* Get a socket descriptor suitable for general net interface
|
||||||
examination and manipulation; this is not necessarily suitable for
|
examination and manipulation; this is not necessarily suitable for
|
||||||
@@ -859,12 +873,31 @@ static struct eth_addr emhost_ea = /* Emulated host ether addr for tap */
|
|||||||
/* OSN_PFEAGET - get physical ethernet address for an open packetfilter FD.
|
/* OSN_PFEAGET - get physical ethernet address for an open packetfilter FD.
|
||||||
*
|
*
|
||||||
* Also not well documented, but generally easier to perform.
|
* Also not well documented, but generally easier to perform.
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
osn_pfeaget(int pfs, /* Packetfilter socket or FD */
|
osn_pfeaget(struct pfdata *pfdata, /* Packetfilter data */
|
||||||
char *ifnam, /* Interface name (sometimes needed) */
|
char *ifnam, /* Interface name (sometimes needed) */
|
||||||
unsigned char *eap) /* Where to write ether address */
|
unsigned char *eap) /* Where to write ether address */
|
||||||
{
|
{
|
||||||
|
int fd = pfdata->pf_fd;
|
||||||
|
|
||||||
|
if (pfdata->pf_meth == PF_METH_TAP ||
|
||||||
|
pfdata->pf_meth == PF_METH_VDE) {
|
||||||
|
|
||||||
|
/* 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 */
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
#if KLH10_NET_NIT
|
#if KLH10_NET_NIT
|
||||||
/* SunOS/Solaris: The EA apparently can't be found until after the PF FD
|
/* SunOS/Solaris: The EA apparently can't be found until after the PF FD
|
||||||
@@ -904,18 +937,6 @@ osn_pfeaget(int pfs, /* Packetfilter socket or FD */
|
|||||||
}
|
}
|
||||||
ea_set(eap, endp.end_addr);
|
ea_set(eap, endp.end_addr);
|
||||||
|
|
||||||
#elif KLH10_NET_TAP
|
|
||||||
/* 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)
|
#elif (KLH10_NET_BPF && !CENV_SYS_NETBSD && !CENV_SYS_FREEBSD)
|
||||||
/* NetBSD no longer seems to support this (on bpf) */
|
/* NetBSD no longer seems to support this (on bpf) */
|
||||||
struct ifreq ifr;
|
struct ifreq ifr;
|
||||||
@@ -1311,7 +1332,14 @@ osn_pfinit(struct pfdata *pfdata, struct osnpf *osnpf, void *pfarg)
|
|||||||
return osn_pfinit_pcap(pfdata, osnpf, pfarg);
|
return osn_pfinit_pcap(pfdata, osnpf, pfarg);
|
||||||
}
|
}
|
||||||
#endif /* KLH10_NET_PCAP */
|
#endif /* KLH10_NET_PCAP */
|
||||||
|
#if KLH10_NET_VDE
|
||||||
|
if (!method[0] || !strcmp(method, "vde")) {
|
||||||
|
pfdata->pf_meth = PF_METH_VDE;
|
||||||
|
return osn_pfinit_vde(pfdata, osnpf, pfarg);
|
||||||
|
}
|
||||||
|
#endif /* KLH10_NET_VDE */
|
||||||
|
|
||||||
|
esfatal(1, "Interface method \"%s\" not supported", method);
|
||||||
}
|
}
|
||||||
|
|
||||||
ssize_t
|
ssize_t
|
||||||
@@ -1524,7 +1552,7 @@ tryagain:
|
|||||||
* Expect a full ethernet frame including link-layer header.
|
* Expect a full ethernet frame including link-layer header.
|
||||||
* returns the number of bytes written.
|
* returns the number of bytes written.
|
||||||
*/
|
*/
|
||||||
int
|
ssize_t
|
||||||
osn_pfwrite_pcap(struct pfdata *pfdata, const void *buf, size_t nbytes)
|
osn_pfwrite_pcap(struct pfdata *pfdata, const void *buf, size_t nbytes)
|
||||||
{
|
{
|
||||||
//if (DP_DBGFLG)
|
//if (DP_DBGFLG)
|
||||||
@@ -1533,6 +1561,7 @@ osn_pfwrite_pcap(struct pfdata *pfdata, const void *buf, size_t nbytes)
|
|||||||
}
|
}
|
||||||
#endif /* KLH10_NET_PCAP */
|
#endif /* KLH10_NET_PCAP */
|
||||||
|
|
||||||
|
|
||||||
#if KLH10_NET_TUN || KLH10_NET_TAP
|
#if KLH10_NET_TUN || KLH10_NET_TAP
|
||||||
|
|
||||||
/* Adapted from DEC's pfopen.c - doing it ourselves here because pfopen(3)
|
/* Adapted from DEC's pfopen.c - doing it ourselves here because pfopen(3)
|
||||||
@@ -1682,51 +1711,22 @@ The ifra_mask field is ignored (left as-is or zeroed if new) unless
|
|||||||
void
|
void
|
||||||
osn_pfinit_tuntap(struct pfdata *pfdata, struct osnpf *osnpf, void *arg)
|
osn_pfinit_tuntap(struct pfdata *pfdata, struct osnpf *osnpf, void *arg)
|
||||||
{
|
{
|
||||||
int allowextern = TRUE; /* For now, always try for external access */
|
|
||||||
int fd;
|
int fd;
|
||||||
struct ifreq ifr;
|
struct ifreq ifr;
|
||||||
char *ifnam = osnpf->osnpf_ifnam; /* alias for the persisting copy */
|
char *ifnam = osnpf->osnpf_ifnam; /* alias for the persisting copy */
|
||||||
char ipb1[OSN_IPSTRSIZ];
|
char ipb1[OSN_IPSTRSIZ];
|
||||||
char ipb2[OSN_IPSTRSIZ];
|
char ipb2[OSN_IPSTRSIZ];
|
||||||
struct ifent *ife = NULL; /* Native host's default IP interface if one */
|
|
||||||
struct in_addr iplocal; /* TUN ifc address at hardware OS end */
|
struct in_addr iplocal; /* TUN ifc address at hardware OS end */
|
||||||
struct in_addr ipremote; /* Address at remote (emulated guest) end */
|
struct in_addr ipremote; /* Address at remote (emulated guest) end */
|
||||||
static unsigned char ipremset[4] = { 192, 168, 0, 44};
|
char *basename = "";
|
||||||
int s;
|
int s;
|
||||||
|
|
||||||
/* Remote address is always that of emulated machine */
|
|
||||||
ipremote = osnpf->osnpf_ip.ia_addr;
|
|
||||||
iplocal = osnpf->osnpf_tun.ia_addr;
|
|
||||||
strncpy(tt_ctx.saved_ifnam, osnpf->osnpf_ifnam, IFNAM_LEN);
|
strncpy(tt_ctx.saved_ifnam, osnpf->osnpf_ifnam, IFNAM_LEN);
|
||||||
|
|
||||||
if (DP_DBGFLG)
|
if (DP_DBGFLG)
|
||||||
dbprint("Opening %s device",
|
dbprint("Opening %s device",
|
||||||
pfdata->pf_meth == PF_METH_TUN ? "TUN" : "TAP");
|
pfdata->pf_meth == PF_METH_TUN ? "TUN" : "TAP");
|
||||||
|
|
||||||
/* Local address can be set explicitly if we plan to do full IP
|
|
||||||
masquerading. */
|
|
||||||
if (memcmp((char *)&iplocal, "\0\0\0\0", IP_ADRSIZ) == 0) {
|
|
||||||
/* Local address is that of hardware machine if we want to permit
|
|
||||||
external access. If not, it doesn't matter (and may not even
|
|
||||||
exist, if there is no hardware interface)
|
|
||||||
*/
|
|
||||||
if (allowextern) {
|
|
||||||
if ((ife = osn_ipdefault())) {
|
|
||||||
iplocal = ife->ife_ipia;
|
|
||||||
} else {
|
|
||||||
error("Cannot find default IP interface for host");
|
|
||||||
allowextern = FALSE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!allowextern) {
|
|
||||||
/* Make up bogus IP address for internal use */
|
|
||||||
memcpy((char *)&iplocal, ipremset, 4);
|
|
||||||
}
|
|
||||||
osnpf->osnpf_tun.ia_addr = iplocal;
|
|
||||||
}
|
|
||||||
|
|
||||||
char *basename = "";
|
|
||||||
|
|
||||||
switch (pfdata->pf_meth) {
|
switch (pfdata->pf_meth) {
|
||||||
case PF_METH_TUN:
|
case PF_METH_TUN:
|
||||||
pfdata->pf_ip4_only = TRUE;
|
pfdata->pf_ip4_only = TRUE;
|
||||||
@@ -1740,6 +1740,12 @@ osn_pfinit_tuntap(struct pfdata *pfdata, struct osnpf *osnpf, void *arg)
|
|||||||
esfatal(0, "pf_meth value %d invalid", pfdata->pf_meth);
|
esfatal(0, "pf_meth value %d invalid", pfdata->pf_meth);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
osn_virt_ether(pfdata, osnpf);
|
||||||
|
|
||||||
|
/* Remote address is always that of emulated machine */
|
||||||
|
ipremote = osnpf->osnpf_ip.ia_addr;
|
||||||
|
iplocal = osnpf->osnpf_tun.ia_addr;
|
||||||
|
|
||||||
fd = pfopen(basename, &tt_ctx, osnpf);
|
fd = pfopen(basename, &tt_ctx, osnpf);
|
||||||
if (fd < 0) {
|
if (fd < 0) {
|
||||||
esfatal(0, "Couldn't open tunnel device %s", basename);
|
esfatal(0, "Couldn't open tunnel device %s", basename);
|
||||||
@@ -1870,79 +1876,6 @@ osn_pfinit_tuntap(struct pfdata *pfdata, struct osnpf *osnpf, void *arg)
|
|||||||
osn_iff_up(s, ifnam);
|
osn_iff_up(s, ifnam);
|
||||||
close(s);
|
close(s);
|
||||||
|
|
||||||
/* Now optionally determine ethernet address.
|
|
||||||
This amounts to what if anything we should put in the native
|
|
||||||
host's ARP tables.
|
|
||||||
- If we only intend to use the net between the virtual host and
|
|
||||||
its hardware host, then no ARP hackery is needed.
|
|
||||||
- However, if the intent is to allow traffic between the virtual
|
|
||||||
host and other machines on the LAN or Internet, then an ARP
|
|
||||||
entry is required. It must advertise the virtual host's IP
|
|
||||||
address, using one of the hardware host's ethernet addresses
|
|
||||||
so any packets on the LAN for the virtual host will at least
|
|
||||||
wind up arriving at the hardware host it's running on.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* Simple method is to get the ifconf table and scan it to find the
|
|
||||||
first interface with both an IP and ethernet address given.
|
|
||||||
Non-4.4BSD systems may not provide the latter datum, but if
|
|
||||||
we're using TUN then we almost certainly also have the good stuff
|
|
||||||
in ifconf.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Now get our fresh new virtual interface's ethernet address.
|
|
||||||
* Basically, we can make it up.
|
|
||||||
*/
|
|
||||||
if (!pfdata->pf_ip4_only) {
|
|
||||||
/* 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(&osnpf->osnpf_ea, &emhost_ea); /* Return the ether address */
|
|
||||||
|
|
||||||
struct ifent *tap_ife = osn_ifcreate(ifnam);
|
|
||||||
if (tap_ife) {
|
|
||||||
tap_ife->ife_flags = IFF_UP;
|
|
||||||
ea_set(tap_ife->ife_ea, (unsigned char *)&osnpf->osnpf_ea);
|
|
||||||
tap_ife->ife_gotea = TRUE;
|
|
||||||
|
|
||||||
if (DP_DBGFLG) {
|
|
||||||
dbprintln("Entered 10-side of TAP into table:");
|
|
||||||
osn_iftab_show(stdout, &iftab[0], iftab_nifs);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (allowextern && ife) {
|
|
||||||
/* Need to determine ether addr of our default interface, then
|
|
||||||
publish an ARP entry mapping the virtual host to the same
|
|
||||||
ether addr.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* Use emhost_ea as set up above */
|
|
||||||
} else {
|
|
||||||
/* ARP hackery will be handled by IP masquerading and packet forwarding. */
|
|
||||||
#if 1 /*OSN_USE_IPONLY*/ /* TOPS-20 does not like NI20 with made up address? */
|
|
||||||
/* Assume no useful ether addr for tun interface. */
|
|
||||||
ea_clr((char *)&osnpf->osnpf_ea);
|
|
||||||
#else
|
|
||||||
/* Assign requested address to tap interface or get kernel assigned one. */
|
|
||||||
if (memcmp((char *)&osnpf->osnpf_ea, "\0\0\0\0\0\0", ETHER_ADRSIZ) == 0) {
|
|
||||||
osn_ifeaget(-1, ifnam, (unsigned char *)&osnpf->osnpf_ea, NULL);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
osn_ifeaset(-1, ifnam, (unsigned char *)&osnpf->osnpf_ea);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
pfdata->pf_fd = fd;
|
pfdata->pf_fd = fd;
|
||||||
pfdata->pf_handle = &tt_ctx;
|
pfdata->pf_handle = &tt_ctx;
|
||||||
pfdata->pf_can_filter = pfdata->pf_ip4_only;
|
pfdata->pf_can_filter = pfdata->pf_ip4_only;
|
||||||
@@ -1994,7 +1927,7 @@ osn_pfread_fd(struct pfdata *pfdata, void *buf, size_t nbytes)
|
|||||||
* returns the number of bytes written.
|
* returns the number of bytes written.
|
||||||
*/
|
*/
|
||||||
static inline
|
static inline
|
||||||
int
|
ssize_t
|
||||||
osn_pfwrite_fd(struct pfdata *pfdata, const void *buf, size_t nbytes)
|
osn_pfwrite_fd(struct pfdata *pfdata, const void *buf, size_t nbytes)
|
||||||
{
|
{
|
||||||
return write(pfdata->pf_fd, buf, nbytes);
|
return write(pfdata->pf_fd, buf, nbytes);
|
||||||
@@ -2078,6 +2011,7 @@ pfopen_create(char *basename, struct tuntap_context *tt_ctx, struct osnpf *osnpf
|
|||||||
#endif /* CENV_SYS_NETBSD */
|
#endif /* CENV_SYS_NETBSD */
|
||||||
#endif /* KLH10_NET_TAP || KLH10_NET_TUN */
|
#endif /* KLH10_NET_TAP || KLH10_NET_TUN */
|
||||||
|
|
||||||
|
|
||||||
#if KLH10_NET_BRIDGE
|
#if KLH10_NET_BRIDGE
|
||||||
#if (CENV_SYS_NETBSD || CENV_SYS_FREEBSD)
|
#if (CENV_SYS_NETBSD || CENV_SYS_FREEBSD)
|
||||||
|
|
||||||
@@ -2260,6 +2194,168 @@ static void osn_iff_up(int s, char *ifname)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#if KLH10_NET_VDE
|
||||||
|
|
||||||
|
static
|
||||||
|
void
|
||||||
|
osn_pfinit_vde(struct pfdata *pfdata, struct osnpf *osnpf, void *pfarg)
|
||||||
|
{
|
||||||
|
struct vde_open_args voa;
|
||||||
|
char *devname = osnpf->osnpf_ifnam;
|
||||||
|
char errbuf[256];
|
||||||
|
|
||||||
|
memset(&voa, 0, sizeof(voa));
|
||||||
|
|
||||||
|
if (!(pfdata->pf_handle = (void*) vde_open(devname, "simh", &voa))) {
|
||||||
|
syserr(errno, "Can't open VDE device \"%s\"", devname);
|
||||||
|
} else {
|
||||||
|
pfdata->pf_fd = vde_datafd((VDECONN*)(pfdata->pf_handle));
|
||||||
|
pfdata->pf_meth = PF_METH_VDE;
|
||||||
|
pfdata->pf_can_filter = FALSE;
|
||||||
|
pfdata->pf_ip4_only = FALSE;
|
||||||
|
pfdata->pf_read = osn_pfread_vde;
|
||||||
|
pfdata->pf_write = osn_pfwrite_vde;
|
||||||
|
pfdata->pf_deinit = osn_pfdeinit_vde;
|
||||||
|
}
|
||||||
|
|
||||||
|
osn_virt_ether(pfdata, osnpf);
|
||||||
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
void
|
||||||
|
osn_pfdeinit_vde(struct pfdata *pfdata, struct osnpf *osnpf)
|
||||||
|
{
|
||||||
|
vde_close(pfdata->pf_handle);
|
||||||
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
ssize_t
|
||||||
|
osn_pfread_vde(struct pfdata *pfdata, void *buf, size_t nbytes)
|
||||||
|
{
|
||||||
|
ssize_t len = vde_recv((VDECONN *)pfdata->pf_handle, buf, nbytes, 0);
|
||||||
|
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
ssize_t
|
||||||
|
osn_pfwrite_vde(struct pfdata *pfdata, const void *buf, size_t nbytes)
|
||||||
|
{
|
||||||
|
ssize_t len = vde_send((VDECONN*)pfdata->pf_handle, buf, nbytes, 0);
|
||||||
|
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
#endif /* KLH10_NET_VDE */
|
||||||
|
|
||||||
|
|
||||||
|
#if KLH10_NET_TUN || KLH10_NET_TAP || KLH10_NET_VDE
|
||||||
|
/*
|
||||||
|
* Some common code for fully virtual ethernet interfaces,
|
||||||
|
* where we have to invent our own ethernet address.
|
||||||
|
*/
|
||||||
|
static
|
||||||
|
void
|
||||||
|
osn_virt_ether(struct pfdata *pfdata, struct osnpf *osnpf)
|
||||||
|
{
|
||||||
|
static unsigned char ipremset[4] = { 192, 168, 0, 44};
|
||||||
|
struct ifent *ife = NULL; /* Native host's default IP interface if one */
|
||||||
|
|
||||||
|
/* Local address can be set explicitly if we plan to do full IP
|
||||||
|
masquerading. */
|
||||||
|
if (memcmp((char *)&osnpf->osnpf_tun.ia_addr, "\0\0\0\0", IP_ADRSIZ) == 0) {
|
||||||
|
int have_addr = TRUE;
|
||||||
|
/* Local address is that of hardware machine if we want to permit
|
||||||
|
external access. If not, it doesn't matter (and may not even
|
||||||
|
exist, if there is no hardware interface)
|
||||||
|
*/
|
||||||
|
if ((ife = osn_ipdefault())) {
|
||||||
|
osnpf->osnpf_tun.ia_addr = ife->ife_ipia;
|
||||||
|
} else {
|
||||||
|
error("Cannot find default IP interface for host");
|
||||||
|
have_addr = FALSE;
|
||||||
|
}
|
||||||
|
if (!have_addr) {
|
||||||
|
/* Make up bogus IP address for internal use */
|
||||||
|
memcpy((char *)&osnpf->osnpf_tun.ia_addr, ipremset, 4);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Now optionally determine ethernet address.
|
||||||
|
This amounts to what if anything we should put in the native
|
||||||
|
host's ARP tables.
|
||||||
|
- If we only intend to use the net between the virtual host and
|
||||||
|
its hardware host, then no ARP hackery is needed.
|
||||||
|
- However, if the intent is to allow traffic between the virtual
|
||||||
|
host and other machines on the LAN or Internet, then an ARP
|
||||||
|
entry is required. It must advertise the virtual host's IP
|
||||||
|
address, using one of the hardware host's ethernet addresses
|
||||||
|
so any packets on the LAN for the virtual host will at least
|
||||||
|
wind up arriving at the hardware host it's running on.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Simple method is to get the ifconf table and scan it to find the
|
||||||
|
first interface with both an IP and ethernet address given.
|
||||||
|
Non-4.4BSD systems may not provide the latter datum, but if
|
||||||
|
we're using TUN then we almost certainly also have the good stuff
|
||||||
|
in ifconf.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Now get our fresh new virtual interface's ethernet address.
|
||||||
|
* Basically, we can make it up.
|
||||||
|
*/
|
||||||
|
if (!pfdata->pf_ip4_only) {
|
||||||
|
/* 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(&osnpf->osnpf_ea, &emhost_ea); /* Return the ether address */
|
||||||
|
|
||||||
|
char *ifnam = osnpf->osnpf_ifnam; /* alias for the persisting copy */
|
||||||
|
struct ifent *tap_ife = osn_ifcreate(ifnam);
|
||||||
|
if (tap_ife) {
|
||||||
|
tap_ife->ife_flags = IFF_UP;
|
||||||
|
ea_set(tap_ife->ife_ea, (unsigned char *)&osnpf->osnpf_ea);
|
||||||
|
tap_ife->ife_gotea = TRUE;
|
||||||
|
|
||||||
|
if (DP_DBGFLG) {
|
||||||
|
dbprintln("Entered 10-side of %s into table:", ifnam);
|
||||||
|
osn_iftab_show(stdout, &iftab[0], iftab_nifs);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ife) {
|
||||||
|
/* Need to determine ether addr of our default interface, then
|
||||||
|
publish an ARP entry mapping the virtual host to the same
|
||||||
|
ether addr.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Use emhost_ea as set up above */
|
||||||
|
} else {
|
||||||
|
/* ARP hackery will be handled by IP masquerading and packet forwarding. */
|
||||||
|
#if 1 /*OSN_USE_IPONLY*/ /* TOPS-20 does not like NI20 with made up address? */
|
||||||
|
/* Assume no useful ether addr for tun interface. */
|
||||||
|
ea_clr((char *)&osnpf->osnpf_ea);
|
||||||
|
#else
|
||||||
|
/* Assign requested address to tap interface or get kernel assigned one. */
|
||||||
|
if (memcmp((char *)&osnpf->osnpf_ea, "\0\0\0\0\0\0", ETHER_ADRSIZ) == 0) {
|
||||||
|
osn_ifeaget(-1, ifnam, (unsigned char *)&osnpf->osnpf_ea, NULL);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
osn_ifeaset(-1, ifnam, (unsigned char *)&osnpf->osnpf_ea);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif /* TUN || TAP || VDE */
|
||||||
|
|
||||||
#if KLH10_NET_DLPI
|
#if KLH10_NET_DLPI
|
||||||
|
|
||||||
|
|||||||
@@ -286,7 +286,7 @@ struct pfdata;
|
|||||||
struct osnpf;
|
struct osnpf;
|
||||||
|
|
||||||
typedef ssize_t (*osn_pfread_f)(struct pfdata *pfdata, void *buf, size_t nbytes);
|
typedef ssize_t (*osn_pfread_f)(struct pfdata *pfdata, void *buf, size_t nbytes);
|
||||||
typedef int (*osn_pfwrite_f)(struct pfdata *pfdata, const void *buf, size_t nbytes);
|
typedef ssize_t (*osn_pfwrite_f)(struct pfdata *pfdata, const void *buf, size_t nbytes);
|
||||||
typedef void (*osn_pfdeinit_f)(struct pfdata *, struct osnpf *);
|
typedef void (*osn_pfdeinit_f)(struct pfdata *, struct osnpf *);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -308,6 +308,7 @@ struct pfdata {
|
|||||||
#define PF_METH_PCAP 1
|
#define PF_METH_PCAP 1
|
||||||
#define PF_METH_TUN 2
|
#define PF_METH_TUN 2
|
||||||
#define PF_METH_TAP 3
|
#define PF_METH_TAP 3
|
||||||
|
#define PF_METH_VDE 4
|
||||||
|
|
||||||
int osn_iftab_init(void);
|
int osn_iftab_init(void);
|
||||||
int osn_nifents(void); /* # of entries cached by osn_iftab_init */
|
int osn_nifents(void); /* # of entries cached by osn_iftab_init */
|
||||||
@@ -318,7 +319,7 @@ void osn_iftab_show(FILE *f, struct ifent *ife, int nents);
|
|||||||
void osn_ifctab_show(FILE *f, struct ifconf *ifc);
|
void osn_ifctab_show(FILE *f, struct ifconf *ifc);
|
||||||
int osn_ifipget(int s, char *ifnam, unsigned char *ipa);
|
int osn_ifipget(int s, char *ifnam, unsigned char *ipa);
|
||||||
int osn_ifnmget(int s, char *ifnam, unsigned char *ipa);
|
int osn_ifnmget(int s, char *ifnam, unsigned char *ipa);
|
||||||
int osn_pfeaget(int s, char *ifnam, unsigned char *eap);
|
int osn_pfeaget(struct pfdata *, char *ifnam, unsigned char *eap);
|
||||||
int osn_ifeaget2(char *ifnam, unsigned char *eap);
|
int osn_ifeaget2(char *ifnam, unsigned char *eap);
|
||||||
#if !OSN_USE_IPONLY
|
#if !OSN_USE_IPONLY
|
||||||
int osn_ifeaset(int s, char *ifnam, unsigned char *newpa);
|
int osn_ifeaset(int s, char *ifnam, unsigned char *newpa);
|
||||||
|
|||||||
Reference in New Issue
Block a user