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

Remove SIOCGIFCONF in favour of getifaddrs(3) or pcap_findalldevs(3).

Use the result from those functions in preference to looking it up again.
Looking up of ethernet addresses remains unportable.
This commit is contained in:
Olaf Seibert
2015-12-18 14:06:28 +01:00
parent 79658f9bf8
commit 34559748e5
6 changed files with 294 additions and 514 deletions

View File

@@ -52,6 +52,7 @@ LINKER = $(CC)
LDFLAGS =
LDOUTF = -o
LIBS =
NETLIBS = -lpcap
# Variables specific to this makefile setup
# SRC and MAKE_CENV are normally overridden.
@@ -230,13 +231,13 @@ DINTFLAGS = \
##
kn10-ks: $(OFILES_KS)
$(LINKER) $(LDFLAGS) $(LDOUTF) kn10-ks $(OFILES_KS) $(LIBS)
$(LINKER) $(LDFLAGS) $(LDOUTF) kn10-ks $(OFILES_KS) $(NETLIBS) $(LIBS)
kn10-ks-its: $(OFILES_KS)
$(LINKER) $(LDFLAGS) $(LDOUTF) kn10-ks-its $(OFILES_KS) $(LIBS)
$(LINKER) $(LDFLAGS) $(LDOUTF) kn10-ks-its $(OFILES_KS) $(NETLIBS) $(LIBS)
kn10-kl: $(OFILES_KL)
$(LINKER) $(LDFLAGS) $(LDOUTF) kn10-kl $(OFILES_KL) $(LIBS)
$(LINKER) $(LDFLAGS) $(LDOUTF) kn10-kl $(OFILES_KL) $(NETLIBS) $(LIBS)
####################################################################
@@ -299,6 +300,7 @@ base-ks-its:
"CFLAGS = $(CFLAGS) $(CFLAGS_AUX)" \
"LDFLAGS = $(LDFLAGS)" \
"LIBS = $(LIBS)" \
"NETLIBS = $(NETLIBS)" \
"CENVFLAGS = $(CENVFLAGS)" \
"CONFFLAGS = \
-DKLH10_CPU_KS=1 \
@@ -326,6 +328,7 @@ base-ks:
"CFLAGS = $(CFLAGS) $(CFLAGS_AUX)" \
"LDFLAGS = $(LDFLAGS)" \
"LIBS = $(LIBS)" \
"NETLIBS = $(NETLIBS)" \
"CENVFLAGS = $(CENVFLAGS)" \
"CONFFLAGS = \
-DKLH10_CPU_KS=1 \
@@ -349,6 +352,7 @@ base-kl:
"CFLAGS = $(CFLAGS) $(CFLAGS_AUX)" \
"LDFLAGS = $(LDFLAGS)" \
"LIBS = $(LIBS)" \
"NETLIBS = $(NETLIBS)" \
"CENVFLAGS = $(CENVFLAGS)" \
"CONFFLAGS = \
-DKLH10_CPU_KLX=1 \
@@ -399,6 +403,7 @@ lint-ks-its:
"CFLAGS = $(CFLAGS) $(CFLAGS_AUX) $(CFLAGS_LINT)" \
"LDFLAGS = $(LDFLAGS)" \
"LIBS = $(LIBS)" \
"NETLIBS = $(NETLIBS)" \
"CENVFLAGS = $(CENVFLAGS)" \
"CONFFLAGS = $(CONFFLAGS) $(CONFFLAGS_AUX)"
@@ -409,6 +414,7 @@ lint-ks:
"CFLAGS = $(CFLAGS) $(CFLAGS_AUX) $(CFLAGS_LINT)" \
"LDFLAGS = $(LDFLAGS)" \
"LIBS = $(LIBS)" \
"NETLIBS = $(NETLIBS)" \
"CENVFLAGS = $(CENVFLAGS)" \
"CONFFLAGS = $(CONFFLAGS) $(CONFFLAGS_AUX)"
@@ -419,6 +425,7 @@ lint-kl:
"CFLAGS = $(CFLAGS) $(CFLAGS_AUX) $(CFLAGS_LINT)" \
"LDFLAGS = $(LDFLAGS)" \
"LIBS = $(LIBS)" \
"NETLIBS = $(NETLIBS)" \
"CENVFLAGS = $(CENVFLAGS)" \
"CONFFLAGS = $(CONFFLAGS) $(CONFFLAGS_AUX)"
@@ -439,6 +446,7 @@ port-ks:
"CFLAGS = $(CFLAGS) $(CFLAGS_AUX)" \
"LDFLAGS = $(LDFLAGS)" \
"LIBS = $(LIBS)" \
"NETLIBS = $(NETLIBS)" \
"CENVFLAGS = $(CENVFLAGS)" \
"CONFFLAGS = \
-DKLH10_CPU_KS=1 \
@@ -463,6 +471,7 @@ kl0i-sync:
"CFLAGS = $(CFLAGS) $(CFLAGS_AUX)" \
"LDFLAGS = $(LDFLAGS)" \
"LIBS = $(LIBS)" \
"NETLIBS = $(NETLIBS)" \
"CENVFLAGS = $(CENVFLAGS)" \
"CONFFLAGS = \
-DKLH10_CPU_KL0=1 \
@@ -486,6 +495,7 @@ kl0i-rtmopt:
"CFLAGS = $(CFLAGS) $(CFLAGS_AUX)" \
"LDFLAGS = $(LDFLAGS)" \
"LIBS = $(LIBS)" \
"NETLIBS = $(NETLIBS)" \
"CENVFLAGS = $(CENVFLAGS)" \
"CONFFLAGS = \
-DKLH10_CPU_KL0=1 \
@@ -535,7 +545,7 @@ dpni20.o: $(SRC)/dpni20.c $(SRC)/dpni20.h $(SRC)/dpsup.h
$(BUILDMOD) $(SRC)/dpni20.c
dpni20: dpni20.o dpsup.o
$(LINKER) $(LDFLAGS) $(LDOUTF) dpni20 dpni20.o dpsup.o $(LIBS)
$(LINKER) $(LDFLAGS) $(LDOUTF) dpni20 dpni20.o dpsup.o $(NETLIBS) $(LIBS)
# --------- IMP subprocess (ITS KS only; counterpart for dvlhdh)
@@ -544,7 +554,7 @@ dpimp.o: $(SRC)/dpimp.c $(SRC)/dpimp.h $(SRC)/dpsup.h
$(BUILDMOD) $(SRC)/dpimp.c
dpimp: dpimp.o dpsup.o
$(LINKER) $(LDFLAGS) $(LDOUTF) dpimp dpimp.o dpsup.o $(LIBS)
$(LINKER) $(LDFLAGS) $(LDOUTF) dpimp dpimp.o dpsup.o $(NETLIBS) $(LIBS)
####################################################################
@@ -615,7 +625,7 @@ enaddr.o: $(SRC)/enaddr.c $(SRC)/osdnet.h $(SRC)/osdnet.c
$(CC) $(CFLAGS) $(CENVFLAGS) $(CONFFLAGS) $(SRC)/enaddr.c
enaddr: enaddr.o
$(LINKER) $(LDFLAGS) $(LDOUTF) enaddr enaddr.o $(LIBS)
$(LINKER) $(LDFLAGS) $(LDOUTF) enaddr enaddr.o $(NETLIBS) $(LIBS)
####################################################################

View File

@@ -659,7 +659,7 @@ net_init(register struct dpimp_s *dpimp)
*/
if ((!dpimp->dpimp_ifnam[0] && !dpimp->dpimp_dedic)
|| (dpimp->dpimp_doarp & DPIMP_ARPF_OCHK)) {
if (osn_iftab_init(IFTAB_IPS) <= 0)
if (osn_iftab_init() <= 0)
esfatal(0, "Couldn't find interface information");
/* Found at least one! Pick first one, if a default is needed. */
@@ -699,7 +699,7 @@ net_init(register struct dpimp_s *dpimp)
if (gwdef_ip.s_addr == -1 || gwdef_ip.s_addr == 0)
efatal(1, "No default prime gateway specified");
#endif
#endif /* !KLH10_NET_TUN */
/* Set up appropriate net fd and packet filter.
** Should also determine interface's ethernet addr, if possible,
@@ -1635,7 +1635,7 @@ imptohost(register struct dpimp_s *dpimp)
/* Small enough to constitute one IMP message, so pass it on! */
ihl_hhsend(dpimp, cnt, buffp + ETHER_HDRSIZ);
}
#else
#else /* !KLH10_NET_TUN */
if (cnt > SI_MAXMSG)
ihl_frag(cnt, buffp);
else

View File

@@ -475,10 +475,11 @@ void net_init(register struct dpni20_s *dpni)
** cannot be found by iftab_init).
** Also grab native IP and ethernet addresses, if ARP might need them.
*/
if (osn_iftab_init() <= 0)
esfatal(0, "Couldn't find interface information");
if ((!dpni->dpni_ifnam[0] && !dpni->dpni_dedic)
|| (dpni->dpni_doarp & DPNI_ARPF_OCHK)) {
if (osn_iftab_init(IFTAB_IPS) <= 0)
esfatal(0, "Couldn't find interface information");
/* Found at least one! Pick first one, if a default is needed. */
if (!dpni->dpni_ifnam[0]) {
@@ -1338,8 +1339,7 @@ int arp_myreply(register unsigned char *buf, register int cnt)
/* Found it! ife now points to matching entry */
if (!ife->ife_gotea) {
if (!osn_ifeaget(-1, ife->ife_name, ife->ife_ea,
(unsigned char *)NULL)) {
if (!osn_ifeaget2(ife->ife_name, ife->ife_ea)) {
error("ARP MyReply failed, no E/N addr for %s", ife->ife_name);
return FALSE;
}

View File

@@ -115,22 +115,10 @@ Usage: enaddr [-v] [<ifc> [default | <ifaddr>] [+<addmcast>] [-<delmcast>]]\n\
Set up for eventual extraction into a separate module
*/
#if 1 /* ENADDR */
# define LOG_EOL "\n"
# undef LOG_DP
# define LOG_PROGNAME "enaddr"
# define DP_DBGFLG debugf
#else
# define LOG_EOL "\r\n"
# define LOG_DP dp
# if KLH10_SIMP
# define LOG_PROGNAME "simp"
# elif KLH10_DEV_DPIMP
# define LOG_PROGNAME "dpimp"
# elif KLH10_DEV_DPNI20
# define LOG_PROGNAME "dpni20"
# endif
#endif
#define LOG_EOL "\n"
#undef LOG_DP
#define LOG_PROGNAME "enaddr"
#define DP_DBGFLG debugf
#if 1 /* Error and diagnostic stuff */
@@ -142,7 +130,7 @@ Usage: enaddr [-v] [<ifc> [default | <ifaddr>] [+<addmcast>] [-<delmcast>]]\n\
static const char *log_progname = LOG_PROGNAME;
char *log_strerror(err)
char *log_strerror(int err)
{
if (err == -1 && errno != err)
return log_strerror(errno);
@@ -265,6 +253,7 @@ static void logfatal_ser(int num, char *fmt, ...)
#endif /* Error and Diagnostic stuff */
int
main(int argc, char **argv)
{
int i;
@@ -324,9 +313,7 @@ main(int argc, char **argv)
}
/* First, show interface info if desired */
if (debugf) {
osn_iftab_init(IFTAB_ALL);
}
osn_iftab_init();
/* Now mung interface if one given */
if (ifc) {
@@ -337,7 +324,8 @@ main(int argc, char **argv)
}
/* Read the default and current MAC address */
(void) osn_ifeaget(s, ifc, pa_cur, pa_def);
(void) osn_ifealookup(ifc, pa_cur); /* pa_def not looked up */
/* Print the MAC addresses */
penetaddr(ifc, pa_cur, pa_def);
@@ -350,7 +338,8 @@ main(int argc, char **argv)
(void) osn_ifeaset(s, ifc, (endef ? pa_def : pa_new));
/* Read back to confirm */
(void) osn_ifeaget(s, ifc, pa_cur, pa_def);
osn_iftab_init();
(void) osn_ifealookup(ifc, pa_cur); /* pa_def not looked up */
penetaddr(ifc, pa_cur, pa_def);
}

View File

@@ -1,6 +1,6 @@
/* OSDNET.C - OS Dependent Network facilities
*/
/* $Id: osdnet.c,v 2.8 2003/02/23 18:22:08 klh Exp $
/* From: $Id: osdnet.c,v 2.8 2003/02/23 18:22:08 klh Exp $
*/
/* Copyright © 1999, 2001 Kenneth L. Harrenstien
** All Rights Reserved
@@ -15,21 +15,6 @@
** This notice (including the copyright and warranty disclaimer)
** must be included in all copies or derivations of this software.
*/
/*
* $Log: osdnet.c,v $
* Revision 2.8 2003/02/23 18:22:08 klh
* Fix various problems for NetBSD/Alpha 1.6.
*
* Revision 2.7 2002/03/18 04:25:03 klh
* Add support for promiscuous mode, fix minor ARP error output
*
* Revision 2.6 2001/11/19 10:32:34 klh
* Solaris port fixups.
*
* Revision 2.5 2001/11/10 21:28:59 klh
* Final 2.0 distribution checkin
*
*/
/* This file, like DPSUP.C, is intended to be included directly
into source code rather than compiled separately and then linked
@@ -39,6 +24,7 @@
*/
#include <unistd.h> /* For basic Unix syscalls */
#include <stdlib.h>
/* The possible configuration macro definitions, with defaults:
*/
@@ -50,14 +36,10 @@
# include "osdnet.h" /* Insurance to make sure our defs are there */
#endif
#ifdef RCSID
RCSID(osdnet_c,"$Id: osdnet.c,v 2.8 2003/02/23 18:22:08 klh Exp $")
#endif
/* Local predeclarations */
struct ifent *osn_iflookup(char *ifnam);
int osn_ifealookup(char *ifnam, unsigned char *eap);
/* Get a socket descriptor suitable for general net interface
examination and manipulation; this is not necessarily suitable for
@@ -107,66 +89,12 @@ ip_adrsprint(char *cp, unsigned char *ia)
/* Interface Table initialization
** Gets info about all net interfaces known to the native system.
** Used for several purposes, hence fairly general.
** This table is used as much as possible, instead of using
** system specific lookup
** A sticky point remains the ethernet addresses. They may or may
** not be reported, and if they are it is in a system specific way.
** Therefore we need to keep the system-specific functions for that.
**
*/
/*
SIOCGIFCONF documentation is virtually non-existent. The following
info comes from looking at source code.
struct ifconf ifconf;
s = socket(AF_INET, SOCK_DGRAM, 0);
ioctl(s, SIOCGIFCONF, &ifconf);
ifconf has only two elements:
<sys/if.h>: struct ifconf
caddr_t ifcu_buf; Buffer to use
int ifc_len; Buffer size in bytes (or # bytes used)
On return, the buffer holds a series of "struct ifreq" entries, each of
which holds an interface name and address. On older systems, each
such entry was a fixed size, but this was later changed in order to
accomodate longer addresses and consequently,
=====>> EACH ENTRY MAY BE OF VARYING SIZE!!!! <<======
This, by the way, is why SIOCGIFCONF appeared to be broken on OSF/1 when
used with a single ifreq's worth of buffer -- since it needed a larger
"ifreq" than the buffer had room for, it returned nothing.
Although the second element of "struct ifreq" is a union, SIOCGIFCONF always
uses it to return a sockaddr:
<sys/if.h>: struct ifreq
char ifr_name[16] interface name, eg "de0"
struct sockaddr ifr_addr interface address
<sys/socket.h>: struct sockaddr
unsigned char sa_len # bytes in this sockaddr
unsigned char sa_family address type, AF_xxx
char sa_data[14] actually up to 253 bytes!
Note that the sa_len field is new; older versions of sockaddr had
just sa_family and sa_data.
To repeat, the actual size of an ifreq depends on the size of the
sockaddr it contains. This is ALWAYS at least sizeof(struct sockaddr),
so trickiness is only needed when sa_len is greater than this default
size.
#define _SIZEOF_ADDR_IFREQ(p) \
((p)->ifr_addr.sa_len <= sizeof(struct sockaddr) \
? sizeof(struct ifreq) \
: (sizeof(struct ifreq)-sizeof(struct sockaddr)+(p)->ifr_addr.sa_len))
or alternatively:
#define _SIZEOF_ADDR_IFREQ(ifr) \
((ifr).ifr_addr.sa_len > sizeof(struct sockaddr) \
? (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
@@ -180,86 +108,107 @@ or alternatively:
interface; there is none.
*/
/* Complete table as returned from system by SIOCGIFCONF
* Currently static for debugging, could be dynamic.
*/
static struct ifconf ifctab;
static char ifcbuf[sizeof(struct ifreq) * NETIFC_MAX];
/* Our own internal table of interface entries, filtered
to keep only the ones we're interested in.
/* Our own internal table of interface entries.
*/
static int iftab_initf = 0;
static int iftab_nifs = 0;
static struct ifent iftab[NETIFC_MAX];
static void osn_iftab_pass(int opts, int npass, int s, struct ifconf *ifc);
static struct ifent *
osn_iftab_addaddress(char *name, struct sockaddr *addr);
/* Get table of all interfaces, using our own generic entry format.
* Routine works as follows:
*
* First, grabs a IFCONF table of all interfaces from the kernel.
* Each IFR entry contains a name and an address.
* This uses either getifaddrs(3) (available on at least BSD, linux,
* OS X) or otherwise pcap_findalldevs(3).
*
* Second, scan this IFCONF table (pass 1) to build our own table of IFE
* entries, made of all IFR entries that pass the following filter
* flags:
* IFTAB_IPS - if set, accepts AF_INET interfaces (with IP address)
* IFTAB_ETHS - if set, accepts LINK interfaces with Ether-like addrs.
* IFTAB_OTH - if set, accepts all others (with unknown addr)
* getifaddrs(3) will provide link-level (ethernet) addresses on at
* least NetBSD 1.5+, FreeBSD 4.1+, MacOS X 10.6+, Linux.
*
* Third, make another scan of IFCONF (pass 2) that grabs *all* information
* about any interface present in our IFE table, regardless of what caused
* it to be inserted.
* pcap_findalldevs(3) may omit interfaces that are not IFF_UP.
* It will provide ethernet addresses on at least NetBSD, FreeBSD, Linux.
*/
int
osn_iftab_init(int opts)
osn_iftab_init(void)
{
int s;
struct ifconf *ifc = &ifctab;
register struct ifent *ifet;
struct ifent *ife;
/* Start out with empty table */
memset(&iftab[0], sizeof(iftab), 0);
iftab_nifs = 0;
ifet = &iftab[0];
/* Open socket with AF_INET family to get at IP stuff.
*/
#if HAVE_GETIFADDRS
struct ifaddrs *ifp;
getifaddrs(&ifp);
while (ifp) {
if (!ifp->ifa_name)
continue;
ife = osn_iftab_addaddress(ifp->ifa_name, ifp->ifa_addr);
if (ife) {
ife->ife_flags = ifp->ifa_flags;
}
ifp = ifp->ifa_next;
}
freeifaddrs(ifp);
#elif HAVE_LIBPCAP
char errbuf[PCAP_ERRBUF_SIZE];
pcap_if_t *alldevs;
struct ifreq ifr;
int s;
if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
esfatal(1, "osn_iftab_init socket()");
syserr(errno, "Can't get socket for SIOCGIFFLAGS");
return FALSE;
}
/* Gobble table of config info about all interfaces, including name
and IP address.
/*
* This may only find interfaces that are IFF_UP.
*/
ifc->ifc_len = sizeof(ifcbuf);
ifc->ifc_buf = (caddr_t)ifcbuf;
if (ioctl(s, SIOCGIFCONF, (char *)ifc) < 0) {
close(s);
esfatal(1, "osn_iftab_init SIOCGIFCONF");
if (pcap_findalldevs(&alldevs, errbuf) == -1) {
error("pcap_findalldevs: %s", errbuf);
return;
}
if (ifc->ifc_len < sizeof(struct ifreq)) {
if (DP_DBGFLG)
dbprintln("SIOCGIFCONF only got %d bytes (need %d)",
(int)ifc->ifc_len, (int)sizeof(struct ifreq));
close(s);
return 0; /* Assume no interfaces */
while (alldevs) {
pcap_addr_t *addr;
if (!alldevs->name)
continue;
/* These ioctls should work for all interfaces */
strncpy(ifr.ifr_name, alldevs->name, sizeof(ifr.ifr_name));
if (ioctl(s, SIOCGIFFLAGS, (char *)&ifr) < 0) {
syserr(errno, "SIOCGIFFLAGS for \"%s\"", alldevs->name);
continue;
}
addr = alldevs->addresses;
while (addr) {
ife = osn_iftab_addaddress(alldevs->name, addr->addr);
addr = addr->next;
}
if (ife) {
ife->ife_flags = ifr.ifr_flags;
}
alldevs = alldevs->next;
}
if (DP_DBGFLG)
dbprintln("SIOCGIFCONF returned %d bytes (%d ifcs?)",
(int)ifc->ifc_len, (int)(ifc->ifc_len/sizeof(struct ifreq)));
if (DP_DBGFLG)
osn_ifctab_show(stdout, ifc);
/* Grabbed everything from OS, now grovel through it */
osn_iftab_pass(opts, 1, s, ifc); /* Do pass 1 scan */
osn_iftab_pass(opts, 2, s, ifc); /* Do pass 2 scan */
iftab_initf = opts; /* Inited! */
pcap_freealldevs(alldevs);
close(s);
#endif
if (DP_DBGFLG)
osn_iftab_show(stdout, &iftab[0], iftab_nifs);
return iftab_nifs;
}
@@ -269,239 +218,80 @@ osn_nifents(void)
return iftab_nifs;
}
static void
osn_iftab_pass(int opts, int npass, int s, struct ifconf *ifc)
/*
* Remember a specific address for an interface.
*
* If multiple addresses are found, they overwrite each other.
*
* For AF_LINK addresses, in NetBSD at least it seems that the first one
* is the default hardware address, and later ones were set with
* "ifconfig re0 link <addr>" or removed with "ifconfig re0 link <addr>
* -alias". The default hardware address can't be removed this way.
* The net effect is that the last address set up (which is presumably
* the one in use) is remembered.
*
* Maybe we should simply remember an array of addresses of each type.
*/
static struct ifent *
osn_iftab_addaddress(char *name, struct sockaddr *addr)
{
register int i;
int offset;
struct ifreq ifr;
register struct ifreq *ifp, *ifend, *ifnext;
register struct ifent *ife, *ifet;
/* Start out with empty table */
if (npass == 1)
iftab_nifs = 0;
ifet = &iftab[0];
ifp = ifc->ifc_req;
ifend = (struct ifreq *)((char *)ifp + ifc->ifc_len);
for (; ifp < ifend; ifp = ifnext) {
/* Find next pointer now, to simplify structure of code.
This is complicated by the fact that the returned table format
has changed under different OS versions. The "new regime"
uses a variable-size "ifreq" entry! Choke...
*/
ifnext = ifp + 1; /* Assume normal entry at first */
#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);
}
#endif
/* See whether this entry is already in table.
*/
for (i = 0; i < iftab_nifs; ++i) {
if (strncmp(ifp->ifr_name, ifet[i].ife_name, sizeof(ifp->ifr_name))
== 0) {
/* Found existing entry! Use its pointer */
ife = &ifet[i];
break;
}
}
if (i >= iftab_nifs) {
if (npass == 2)
continue;
/* Pass1, decide now whether to create entry or not */
/* See if it's something we're interested in. */
if ((opts & IFTAB_IPS) && (ifp->ifr_addr.sa_family == AF_INET)) {
/* yes */
#if NETIF_HAS_ETHLINK
} else if ((opts & IFTAB_ETHS)
&& (ifp->ifr_addr.sa_family == AF_LINK)
&& (((struct sockaddr_dl *)&ifp->ifr_addr)->sdl_alen
== ETHER_ADRSIZ)){
/* yes */
#endif
} else if (opts & IFTAB_OTH) {
/* yes */
} else {
/* Nope, ignore this one */
continue;
}
/* Yes, create this entry */
if (iftab_nifs >= NETIFC_MAX-1) {
error("ifc table overflow, max %d", NETIFC_MAX);
return; /* Stop now */
}
ife = &ifet[iftab_nifs++]; /* New table entry to fill out */
/* Copy interface name and ensure null-terminated
even if sizes someday get out of synch.
*/
strncpy(ife->ife_name, ifp->ifr_name,
(sizeof(ife->ife_name) < sizeof(ifp->ifr_name))
? sizeof(ife->ife_name) : sizeof(ifp->ifr_name));
ife->ife_name[sizeof(ife->ife_name)-1] = '\0';
/* These ioctls should work for all interfaces */
strncpy(ifr.ifr_name, ifp->ifr_name, sizeof(ifr.ifr_name));
if (ioctl(s, SIOCGIFFLAGS, (char *)&ifr) < 0) {
syserr(errno, "SIOCGIFFLAGS for \"%s\"", ife->ife_name);
continue; /* Discard entry */
}
ife->ife_flags = ifr.ifr_flags;
/* SIOCGIFMTU: ifr_mtu */
/* SIOCGIFMETRIC: ifr_metric */
continue;
}
if (npass == 1)
continue;
/* Pass 2 and dealing with an existing entry. Flesh it out! */
switch (ifp->ifr_addr.sa_family) {
case AF_INET:
ife->ife_gotip4 = TRUE;
ife->ife_ipint = ((struct sockaddr_in *)
&ifp->ifr_addr)->sin_addr.s_addr;
break;
#if NETIF_HAS_ETHLINK
case AF_LINK:
if (((struct sockaddr_dl *)&ifp->ifr_addr)->sdl_alen
== ETHER_ADRSIZ) {
/* Looks like Ethernet physical link, save addr */
struct sockaddr_dl *dla = (struct sockaddr_dl *)&ifp->ifr_addr;
memcpy(ife->ife_ea, LLADDR(dla), dla->sdl_alen);
ife->ife_gotea = TRUE;
break;
}
#endif
/* Else drop through to "other" case */
default:
break;
}
}
}
#include <stddef.h>
void
osn_ifctab_show(FILE *f, struct ifconf *ifc)
{
register struct ifreq *ifr;
struct ifreq *ifrend;
int len;
struct ifent *ife, *ifet;
int i;
unsigned char *cp;
int nents = 0;
int nvary = 0;
int idx;
fprintf(f, "sizeof struct ifreq = %d\r\n", (int) sizeof(struct ifreq));
fprintf(f, "IFNAMSIZ = %d\r\n", (int) IFNAMSIZ);
#if CENV_SYS_NETBSD
fprintf(f, "offset of struct sockaddr_storage = %d\r\n", (int) offsetof(struct ifreq, ifr_space));
#endif
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));
/* First see if the name is already known */
fprintf(f, "Interface table: %ld bytes (%d entries if std addr len %d)\r\n",
(long)ifc->ifc_len, (int)(ifc->ifc_len/sizeof(struct ifreq)),
(int)sizeof(struct sockaddr));
ifr = ifc->ifc_req;
ifrend = (struct ifreq *)((char *)(ifc->ifc_req) + ifc->ifc_len);
for (i = 0; ifr < ifrend; ++i) {
++nents;
#if NETIF_HAS_SALEN
len = ifr->ifr_addr.sa_len;
#else
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\" 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, " = (sockaddr.sa_data) %x", *cp);
for (--len; len > 0; --len) {
fprintf(f, ":%x", *++cp);
}
idx = -1;
for (i = iftab_nifs - 1; i >= 0; i--) {
if (strcmp(iftab[i].ife_name, name) == 0) {
idx = i;
break;
}
fprintf(f, "\r\n");
cp = (unsigned char *) ifr->ifr_addr.sa_data;
switch (ifr->ifr_addr.sa_family) {
case AF_INET:
{
struct sockaddr_in *skin = (struct sockaddr_in *) &ifr->ifr_addr;
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\r\n",
(int)skin->sin_port,
ucp[0], ucp[1], ucp[2], ucp[3]);
}
break;
#if NETIF_HAS_ETHLINK
case AF_LINK:
{
struct sockaddr_dl *dla = (struct sockaddr_dl *) &ifr->ifr_addr;
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);
fprintf(f, " = %x", *cp);
for (--len; len > 0; --len) {
fprintf(f, ":%x", *++cp);
}
}
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\r\n");
}
/* Move onto next entry */
#if NETIF_HAS_SALEN && !defined(ifr_space)
if (ifr->ifr_addr.sa_len > sizeof(struct sockaddr)) {
++nvary;
ifr = (struct ifreq *)((char *)(ifr + 1) +
(ifr->ifr_addr.sa_len - sizeof(struct sockaddr)));
} else
#endif
ifr++;
}
if (nvary)
fprintf(f, "Interface summary: %d entries of varying length\r\n",
nents);
else
fprintf(f, "Interface summary: %d entries of std length %d\r\n",
nents, (int)sizeof(struct ifreq));
}
if (idx < 0) {
idx = iftab_nifs++;
if (idx >= NETIFC_MAX)
return NULL; /* doesn't fit */
strncpy(iftab[idx].ife_name, name, IFNAMSIZ);
iftab[idx].ife_name[IFNAMSIZ] = '\0';
}
ifet = &iftab[idx];
switch (addr->sa_family) {
case AF_INET: {
struct sockaddr_in *sin = (struct sockaddr_in *)addr;
ifet->ife_ipia = sin->sin_addr;
ifet->ife_gotip4 = TRUE;
break;
}
#if defined(AF_LINK)
case AF_LINK: {
struct sockaddr_dl *sdl = (struct sockaddr_dl *)addr;
if (sdl->sdl_type == IFT_ETHER && sdl->sdl_alen == ETHER_ADRSIZ) {
ea_set(ifet->ife_ea, LLADDR(sdl));
ifet->ife_gotea = TRUE;
}
}
#endif /* AF_LINK*/
#if defined(AF_PACKET)
case AF_PACKET: {
struct sockaddr_ll *sll = (struct sockaddr_ll *)addr;
if (sll->sll_hatype == ARPHRD_ETHER && sll->sll_halen == ETHER_ADRSIZ) {
ea_set(ifet->ife_ea, &sll->sll_addr);
ifet->ife_gotea = TRUE;
}
}
#endif /* AF_PACKET*/
}
}
void
osn_iftab_show(FILE *f, struct ifent *ifents, int nents)
{
register struct ifent *ife;
struct ifent *ife;
int i;
fprintf(f, "Filtered IFE table: %d entries\r\n", nents);
@@ -528,8 +318,8 @@ osn_iftab_show(FILE *f, struct ifent *ifents, int nents)
struct ifent *
osn_iftab_arp(struct in_addr ia)
{
register int i = 0;
register struct ifent *ife = iftab;
int i = 0;
struct ifent *ife = iftab;
for (; i < iftab_nifs; ++i, ++ife)
if (ife->ife_ipia.s_addr == ia.s_addr)
@@ -542,7 +332,7 @@ osn_iftab_arp(struct in_addr ia)
int
osn_iftab_arpget(struct in_addr ia, unsigned char *eap)
{
register struct ifent *ife;
struct ifent *ife;
if ((ife = osn_iftab_arp(ia)) && ife->ife_gotea) {
ea_set(eap, ife->ife_ea);
@@ -558,8 +348,8 @@ osn_iftab_arpget(struct in_addr ia, unsigned char *eap)
struct ifent *
osn_ipdefault(void)
{
register int i = 0;
register struct ifent *ife = iftab;
int i = 0;
struct ifent *ife = iftab;
for (; i < iftab_nifs; ++i, ++ife)
if ((ife->ife_flags & IFF_UP) && !(ife->ife_flags & IFF_LOOPBACK))
@@ -572,8 +362,8 @@ osn_ipdefault(void)
struct ifent *
osn_iflookup(char *ifnam)
{
register int i = 0;
register struct ifent *ife = iftab;
int i = 0;
struct ifent *ife = iftab;
for (; i < iftab_nifs; ++i, ++ife)
if (strcmp(ifnam, ife->ife_name) == 0)
@@ -588,18 +378,18 @@ int
osn_ifealookup(char *ifnam, /* Interface name */
unsigned char *eap) /* Where to write ether address */
{
#if NETIF_HAS_ETHLINK
register struct ifent *ife;
struct ifent *ife;
if ((ife = osn_iflookup(ifnam))
&& ife->ife_gotea) {
if (ife = osn_iflookup(ifnam)) {
if (!ife->ife_gotea) {
ife->ife_gotea = osn_ifeaget2(ifnam, ife->ife_ea);
}
if (ife->ife_gotea) {
ea_set(eap, ife->ife_ea);
return TRUE;
}
}
return FALSE;
#else
return osn_ifeaget(-1, ifnam, eap, (unsigned char *)NULL);
#endif
}
/* OSN_ARP_STUFF - stuff emulated-host ARP entry into kernel.
@@ -782,11 +572,17 @@ osn_ifnmget(int s, /* Socket for (AF_INET, SOCK_DGRAM, 0) */
}
/* OSN_IFEAGET - get physical ethernet address for a given interface name.
/* OSN_IFEAGET2 - get physical ethernet address for a given interface name.
*
* This is fairly tricky as the OSD mechanism for this tends to
* be *very* poorly documented.
*
* Usually this information was already found by the information from
* either getifaddrs(3) or pcap_findalldevs(3).
*
* In the cases where it wasn't, we have fallbacks for DECOSF
* and via ARP.
*
* Apparently only DEC OSF/1 and Linux can find this directly.
* However, other systems seem to be divided into either of two
* camps:
@@ -797,117 +593,50 @@ osn_ifnmget(int s, /* Socket for (AF_INET, SOCK_DGRAM, 0) */
* AF_LINK family address in the ifconf table.
*/
int
osn_ifeaget(int s, /* Socket for (AF_INET, SOCK_DGRAM, 0) */
char *ifnam, /* Interface name */
unsigned char *eap, /* Current ether address */
unsigned char *def) /* Default (hardware) ether address */
osn_ifeaget2(char *ifnam, /* Interface name */
unsigned char *eap) /* Current ether address */
{
char eastr[OSN_EASTRSIZ];
#if CENV_SYS_DECOSF /* Direct approach */
{
int ownsock = FALSE;
struct ifdevea ifdev;
{
int ownsock = FALSE;
struct ifdevea ifdev;
if (s == -1) {
if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
syserr(errno, "Can't get EN addr for \"%s\": socket()", ifnam);
return FALSE;
}
ownsock = TRUE;
}
strncpy(ifdev.ifr_name, ifnam, sizeof(ifdev.ifr_name));
if (ioctl(s, SIOCRPHYSADDR, &ifdev) < 0) {
syserr(errno, "Can't get EN addr for \"%s\": SIOCRPHYSADDR", ifnam);
if (ownsock) close(s);
return FALSE;
}
if (ownsock)
close(s);
ea_set(eap, ifdev.current_pa);
if (def)
ea_set(def, ifdev.default_pa);
}
#elif CENV_SYS_LINUX
{
int ownsock = FALSE;
struct ifreq ifr;
if (s == -1) {
if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
syserr(errno, "Can't get EN addr for \"%s\": socket()", ifnam);
strncpy(ifdev.ifr_name, ifnam, sizeof(ifdev.ifr_name));
if (ioctl(s, SIOCRPHYSADDR, &ifdev) < 0) {
syserr(errno, "Can't get EN addr for \"%s\": SIOCRPHYSADDR", ifnam);
if (ownsock) close(s);
return FALSE;
}
ownsock = TRUE;
}
memset(&ifr, 0, sizeof(ifr));
strncpy(ifr.ifr_name, ifnam, sizeof(ifr.ifr_name));
if (ioctl(s, SIOCGIFHWADDR, &ifr) < 0 ) {
syserr(errno, "SIOCGIFHWADDR of %s failed", ifnam);
if (ownsock) close(s);
return FALSE;
}
if (ifr.ifr_hwaddr.sa_family != ARPHRD_ETHER) {
error("%s is not an ethernet - ARPHRD type %d",
ifnam, ifr.ifr_hwaddr.sa_family);
if (ownsock) close(s);
return FALSE;
}
if (ownsock)
close(s);
ea_set(eap, &ifr.ifr_addr.sa_data[0]); /* Return the ether address */
if (def)
memset(def, 0, ETHER_ADRSIZ);
}
#elif NETIF_HAS_ARPIOCTL
{
/* Much more general hack */
unsigned char ipchr[IP_ADRSIZ];
char ipstr[OSN_IPSTRSIZ];
/* Get IP address for this interface, as an argument for ARP lookup */
if (!osn_ifipget(s, ifnam, ipchr)) {
error("Can't get EN addr for \"%s\": osn_ifipget failed", ifnam);
return FALSE;
ea_set(eap, ifdev.current_pa);
}
/* Have IP address, now do ARP lookup hackery */
if (!osn_arp_look((struct in_addr *)ipchr, eap)) {
syserr(errno,"Can't find EN addr for \"%s\" %s using ARP",
ifnam, ip_adrsprint(ipstr, ipchr));
return FALSE;
}
if (def)
memset(def, 0, ETHER_ADRSIZ);
}
#elif NETIF_HAS_ETHLINK
/* Should never happen unless osn_ifeaget() is called directly
without going through osn_ifealookup(). If so, attempt
to do right thing anyway.
*/
{
register struct ifent *ife;
if (iftab_initf == 0) {
/* Try to initialize iftab, ignore errors */
(void) osn_iftab_init(IFTAB_ETHS);
}
if (!(ife = osn_iflookup(ifnam))
|| !(ife->ife_gotea)) {
error("No EN addr in iftab for \"%s\"", ifnam);
return FALSE;
}
ea_set(eap, ife->ife_ea);
if (def)
memset(def, 0, ETHER_ADRSIZ);
}
#else
# error "Unimplemented OS routine osn_ifeaget()"
{
/* Much more general hack */
unsigned char ipchr[IP_ADRSIZ];
char ipstr[OSN_IPSTRSIZ];
/* Get IP address for this interface, as an argument for ARP lookup */
if (!osn_ifipget(-1, ifnam, ipchr)) {
error("Can't get EN addr for \"%s\": osn_ifipget failed", ifnam);
return FALSE;
}
/* Have IP address, now do ARP lookup hackery */
if (!osn_arp_look((struct in_addr *)ipchr, eap)) {
syserr(errno,"Can't find EN addr for \"%s\" %s using ARP",
ifnam, ip_adrsprint(ipstr, ipchr));
return FALSE;
}
}
#endif
dbprintln("EN addr for \"%s\" = %s",
ifnam, eth_adrsprint(eastr, eap));
@@ -999,7 +728,7 @@ osn_pfeaget(int pfs, /* Packetfilter socket or FD */
return FALSE;
}
#else
if (!osn_ifeaget(pfs, ifnam, eap, (unsigned char *)NULL))
if (!osn_ifealookup(ifnam, eap))
return FALSE;
#endif
@@ -1485,7 +1214,7 @@ osn_pfinit(struct osnpf *osnpf, void *pfarg)
#if KLH10_NET_BPF
int
osn_pfinit(register struct osnpf *osnpf, void *arg)
osn_pfinit(struct osnpf *osnpf, void *arg)
{
int fd;
struct bpf_version bv;
@@ -1523,6 +1252,25 @@ osn_pfinit(register struct osnpf *osnpf, void *arg)
if (ioctl(fd, BIOCIMMEDIATE, (char *) &i) < 0)
esfatal(1, "BIOCIMMEDIATE failed");
/* BIOCSFEEDBACK causes packets that we send via bpf to be
* seen as incoming by the host OS.
* Without this, there is no working communication between
* the host and the guest OS (just in one direction).
*/
#if !defined(BIOCSFEEDBACK) && defined(BIOCFEEDBACK)
# define BIOCSFEEDBACK BIOCSFEEDBACK
#endif
//#if defined(__NetBSD_Version__) && __NetBSD_Version__ < 799002500
//# undef BIOCSFEEDBACK /* buggy before NetBSD 7.99.24 or 7.1 */
//#endif
#if defined(BIOCSFEEDBACK)
error("trying BIOCSFEEDBACK");
errno = 0;
i = 1;
if (ioctl(fd, BIOCSFEEDBACK, (char *) &i) < 0)
syserr(errno, "BIOCSFEEDBACK failed");
#endif
/* Set the read() buffer size.
Must be set before interface is attached!
*/
@@ -1647,7 +1395,7 @@ The ifra_mask field is ignored (left as-is or zeroed if new) unless
*/
int
osn_pfinit(register struct osnpf *osnpf, void *arg)
osn_pfinit(struct osnpf *osnpf, void *arg)
{
int allowextern = TRUE; /* For now, always try for external access */
int fd;
@@ -1678,7 +1426,7 @@ osn_pfinit(register struct osnpf *osnpf, void *arg)
exist, if there is no hardware interface)
*/
if (allowextern) {
if (osn_iftab_init(IFTAB_IPS) && (ife = osn_ipdefault())) {
if (osn_iftab_init() && (ife = osn_ipdefault())) {
iplocal = ife->ife_ipia;
} else {
error("Cannot find default IP interface for host");
@@ -1707,13 +1455,13 @@ osn_pfinit(register struct osnpf *osnpf, void *arg)
if (ioctl(fd, TUNSETIFF, (void *) &ifr) < 0) /* turn it on */
esfatal(0, "Couldn't set tun device");
strcpy(ifnam, ifr.ifr_name); /* get device name (typically "tun0") */
#else
#else /* not CENV_SYS_LINUX */
do {
#if OSN_USE_IPONLY
sprintf(tunname, "/dev/tun%d", ++i);
#else
sprintf(tunname, "/dev/tap%d", ++i);
#endif
#endif /* not CENV_SYS_LINUX */
} while ((fd = open(tunname, O_RDWR)) < 0 && errno == EBUSY);
if (fd < 0)
@@ -2012,7 +1760,8 @@ osn_pfinit(struct osnpf *osnpf, void *arg)
/*
* Too bad that this is never called...
*/
osn_pfdeinit()
void
osn_pfdeinit(void)
{
#if KLH10_NET_TAP_BRIDGE
void tap_bridge_close();
@@ -2022,7 +1771,7 @@ osn_pfdeinit()
#if KLH10_NET_TAP_BRIDGE
osn_pfinit(register struct osnpf *osnpf, void *arg)
osn_pfinit(struct osnpf *osnpf, void *arg)
{
int fd;
char *ifnam = osnpf->osnpf_ifnam;

View File

@@ -201,12 +201,14 @@
/* Determine whether:
* (1) sockaddr contains sa_len (NETIF_HAS_SALEN)
* (2) ifconf provides physical link addrs (NETIF_HAS_ETHLINK)
* (2) ifconf provides physical link addrs (NETIF_HAS_AF_LINK or
* NETIF_HAS_AF_PACKET)
* (3) ARP ioctls exist (NETIF_HAS_ARPIOCTL)
*
* 4.4BSD DECOSF SunOS Solaris Linux
* NETIF_HAS_SALEN yes yes no no no
* NETIF_HAS_ETHLINK yes yes no no no
* NETIF_HAS_AF_LINK yes yes no no no
* NETIF_HAS_AF_PACKET no ? ? ? yes
* NETIF_HAS_ARPIOCTL no yes yes yes yes
*/
#ifndef NETIF_HAS_SALEN /* If not explicitly told, see if known OS */
@@ -224,17 +226,31 @@
# endif
#endif
#if !defined(NETIF_HAS_AF_PACKET)
#if CENV_SYS_LINUX || defined(AF_PACKET)
#define NETIF_HAS_AF_PACKET 1
#else
#define NETIF_HAS_AF_PACKET 0
#endif
#endif /* !defined(NETIF_HAS_AF_PACKET) */
#if NETIF_HAS_AF_PACKET
#include <linux/if_packet.h> /* For struct sockaddr_ll */
#endif /* NETIF_HAS_AF_PACKET */
#if NETIF_HAS_SALEN
# ifdef AF_LINK
# include <net/if_dl.h> /* For sockaddr_dl */
# include <net/if_types.h> /* For IFT_ETHER */
# endif
# ifdef LLADDR /* Double-check, make sure this is defined */
# define NETIF_HAS_ETHLINK 1
# define NETIF_HAS_AF_LINK 1
# else
# define NETIF_HAS_ETHLINK 0
# define NETIF_HAS_AF_LINK 0
# endif
#else
# define NETIF_HAS_ETHLINK 0
# define NETIF_HAS_AF_LINK 0
#endif
#ifdef SIOCGARP
@@ -243,6 +259,19 @@
# define NETIF_HAS_ARPIOCTL 0
#endif
#define HAVE_GETIFADDRS 1 /* assume this for now */
#define HAVE_LIBPCAP 1 /* assume this for now */
#if HAVE_LIBPCAP
#include <pcap/pcap.h>
#endif
#if HAVE_GETIFADDRS
#include <ifaddrs.h>
#endif
#if !HAVE_LIBPCAP && !HAVE_GETIFADDRS
#error "Sorry, can't lookup ethernet interfaces without libpcap or getifaddrs(3)"
#endif
/* Interface table entry.
This is needed to provide a more generic format that can
@@ -351,7 +380,7 @@ union ipaddr {
struct in_addr ia_addr;
};
int osn_iftab_init(int);
int osn_iftab_init(void);
int osn_nifents(void); /* # of entries cached by osn_iftab_init */
int osn_ifsock(char *ifnam, ossock_t *);
@@ -361,7 +390,7 @@ void osn_ifctab_show(FILE *f, struct ifconf *ifc);
int osn_ifipget(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_ifeaget(int s, char *ifnam, unsigned char *eap, unsigned char *def);
int osn_ifeaget2(char *ifnam, unsigned char *eap);
#if !OSN_USE_IPONLY
int osn_ifeaset(int s, char *ifnam, unsigned char *newpa);
int osn_ifmcset(int s, char *ifc, int delf, unsigned char *pa);
@@ -371,6 +400,8 @@ struct ifent *osn_ipdefault(void);
struct ifent *osn_iftab_arp(struct in_addr ia);
int osn_iftab_arpget(struct in_addr ia, unsigned char *eap);
int osn_ifealookup(char *ifnam, unsigned char *eap);
#define OSN_EASTRSIZ sizeof("xx:xx:xx:xx:xx:xxZZ")
char *eth_adrsprint(char *cp, unsigned char *ea);
@@ -390,5 +421,6 @@ struct osnpf { /* Arg struct for common initialization params */
struct ether_addr osnpf_ea; /* OUT: ether address of ifc */
};
int osn_pfinit(struct osnpf *, void *);
void osn_pfdeinit(void);
#endif /* ifndef OSDNET_INCLUDED */