1
0
mirror of https://github.com/PDP-10/klh10.git synced 2026-04-25 19:51:18 +00:00

Remove lots of now-unneeded code.

This commit is contained in:
Olaf Seibert
2015-12-22 18:06:27 +01:00
parent 89be604190
commit 77aa001e3f
4 changed files with 206 additions and 1536 deletions

View File

@@ -36,12 +36,9 @@ that looks like a simplified IMP. It uses the host system's
packet-filtering mechanism to access the ethernet, and assumes that
only IP packets will be transferred in and out. This mechanism might
be one of:
NIT - SunOS Network Interface Tap.
DLPI - Solaris Data-Link-Provider Interface (the ugliest).
BPF - BSD packetfilter.
PFLT - OSF/1 packetfilter.
TUN - FreeBSD tunnel device (the simplest).
LNX - Linux "PF_PACKET" interface (the dumbest).
PCAP - The portable packet capture library
TAP - Ethernet tunnel device
TUN - IP tunnel device (the simplest).
In what follows, "NET" is understood to be one of the above.
@@ -283,11 +280,8 @@ struct in_addr ehost_ip; /* Emulated host 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 */
#if KLH10_NET_TUN
struct in_addr tun_ip; /* IP addr of tunnel */
#else
struct in_addr tun_ip; /* IP addr of host side of tunnel */
struct in_addr gwdef_ip; /* IP addr of default prime gateway */
#endif
struct ether_addr ehost_ea; /* Emulated host ethernet addr */
struct ether_addr ihost_ea; /* IMP/Native host ethernet addr */
@@ -421,7 +415,7 @@ int initdebug = 0;
int
main(int argc, char **argv)
{
register struct dpimp_s *dpimp; /* Ptr to shared memory area */
struct dpimp_s *dpimp; /* Ptr to shared memory area */
/* Search for a "-debug" command-line argument so that we can start
debug output ASAP if necessary.
@@ -505,11 +499,8 @@ main(int argc, char **argv)
shared DP area.
*/
memcpy((void *)&ehost_ip, dpimp->dpimp_ip, 4); /* Host IP addr */
#if KLH10_NET_TUN
memcpy((void *)&tun_ip, dpimp->dpimp_tun, 4); /* Tunnel addr */
#else
memcpy((void *)&gwdef_ip, dpimp->dpimp_gw, 4); /* Default GW addr */
#endif
memcpy((void *)&ehost_ea, dpimp->dpimp_eth, 6); /* Host Ether addr */
/* IMP must always have IP address specified! */
@@ -638,7 +629,7 @@ main(int argc, char **argv)
** given network interface we'll use.
*/
void
net_init(register struct dpimp_s *dpimp)
net_init(struct dpimp_s *dpimp)
{
struct ifreq ifr;
@@ -714,18 +705,14 @@ net_init(register struct dpimp_s *dpimp)
npf.osnpf_rdtmo = dpimp->dpimp_rdtmo;
npf.osnpf_backlog = dpimp->dpimp_backlog;
npf.osnpf_ip.ia_addr = ehost_ip;
#if KLH10_NET_TUN
npf.osnpf_tun.ia_addr = tun_ip;
#endif
/* 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 */
#if KLH10_NET_TUN
tun_ip = npf.osnpf_tun.ia_addr; /* Copy actual tun if any */
#endif
}
}
@@ -738,78 +725,8 @@ net_init(register struct dpimp_s *dpimp)
** native host. We do this even before checking whether the packet contains
** IP data; if it's too short, it's rejected anyway.
*/
/* Common packetfilter definitions - for all but BPF */
#if KLH10_NET_PFLT || KLH10_NET_NIT || KLH10_NET_DLPI
#if KLH10_NET_PFLT
# define OSN_PFSTRUCT enfilter
# define PF_PRIO enf_Priority
# define PF_FLEN enf_FilterLen
# define PF_FILT enf_Filter
#elif (KLH10_NET_DLPI || KLH10_NET_NIT)
# define OSN_PFSTRUCT packetfilt
# define PF_PRIO Pf_Priority
# define PF_FLEN Pf_FilterLen
# define PF_FILT Pf_Filter
#endif
struct OSN_PFSTRUCT pfilter;
static void pfshow(struct OSN_PFSTRUCT *);
/* Build packet filter to pass on only IP packets for given IP addr */
struct OSN_PFSTRUCT *
pfbuild(void *arg, struct in_addr *ipa)
{
register struct dpimp_s *dpimp = (struct dpimp_s *)arg;
register unsigned short *p;
register union ipaddr *uipa = (union ipaddr *)ipa;
register struct OSN_PFSTRUCT *pfp = &pfilter;
p = pfp->PF_FILT; /* Get addr of filter (length ENMAXFILTERS) */
*p++ = ENF_PUSHWORD + PKSWOFF_IPDEST+1;
*p++ = ENF_PUSHLIT | ENF_CAND; /* Compare low wds of IP addrs */
*p++ = htons((uipa->ia_octet[2]<<8) | (uipa->ia_octet[3]));
*p++ = ENF_PUSHWORD + PKSWOFF_IPDEST;
*p++ = ENF_PUSHLIT | ENF_CAND; /* Compare high wds of IP addrs */
*p++ = htons((uipa->ia_octet[0]<<8) | (uipa->ia_octet[1]));
*p++ = ENF_PUSHWORD + PKSWOFF_ETYPE; /* Verify IP packet */
*p++ = ENF_PUSHLIT | ENF_EQ;
*p++ = htons(ETHERTYPE_IP);
pfp->PF_FLEN = p - pfp->PF_FILT; /* Set # of items on list */
pfp->PF_PRIO = 128; /* Pick middle of 0-255 range */
/* "Ignored", but RARPD recommends > 2 */
if (DBGFLG) /* If debugging, print out resulting filter */
pfshow(pfp);
return pfp;
}
/* Debug auxiliary to print out packetfilter we composed.
*/
static void
pfshow(struct OSN_PFSTRUCT *pf)
{
int i;
fprintf(stderr,"[%s: kernel packetfilter pri %d, len %d:", progname,
pf->PF_PRIO, pf->PF_FLEN);
for (i = 0; i < pf->PF_FLEN; ++i)
fprintf(stderr, " %04X", pf->PF_FILT[i]);
fprintf(stderr, "]\r\n");
}
#endif /* KLH10_NET_PFLT || KLH10_NET_NIT || KLH10_NET_DLPI */
#if KLH10_NET_BPF || KLH10_NET_PCAP
#if KLH10_NET_PCAP
/*
** BPF filter program stuff.
@@ -893,10 +810,10 @@ static void pfshow(struct OSN_PFSTRUCT *);
struct OSN_PFSTRUCT *
pfbuild(void *arg, struct in_addr *ipa)
{
register struct dpimp_s *dpimp = (struct dpimp_s *)arg;
register unsigned char *ucp = (unsigned char *)ipa;
register struct OSN_PFSTRUCT *pfp = &bpf_pfilter;
register struct bpf_insn *p;
struct dpimp_s *dpimp = (struct dpimp_s *)arg;
unsigned char *ucp = (unsigned char *)ipa;
struct OSN_PFSTRUCT *pfp = &bpf_pfilter;
struct bpf_insn *p;
p = pfp->PF_FILT; /* Point to 1st instruction in BPF program */
@@ -961,9 +878,8 @@ pfshow(struct OSN_PFSTRUCT *pf)
pf->PF_FILT[i].k);
fprintf(stderr, "]\r\n");
}
#endif /* KLH10_NET_BPF || KLH10_NET_PCAP */
#endif /* KLH10_NET_PCAP */
#if KLH10_NET_LNX
/* Because until very recently LNX had no kernel packet filtering, must do it
manually. Ugh!
@@ -974,13 +890,13 @@ pfshow(struct OSN_PFSTRUCT *pf)
Returns TRUE if packet OK, FALSE if it should be dropped.
Note that the code parallels that for pfbuild().
*/
int lnx_filter(register struct dpimp_s *dpimp,
int lnx_filter(struct dpimp_s *dpimp,
unsigned char *bp,
int cnt)
{
/* Code assumes buffer is at least shortword-aligned. */
register unsigned short *sp = (unsigned short *)bp;
register unsigned short etyp;
unsigned short *sp = (unsigned short *)bp;
unsigned short etyp;
/* Get ethernet protocol type.
Could also test packet length, but for now assume higher level
@@ -997,45 +913,12 @@ int lnx_filter(register struct dpimp_s *dpimp,
/* For IP packet, return TRUE if IP destination matches ours */
return (memcmp(dpimp->dpimp_ip, bp + PKBOFF_IPDEST, 4) == 0);
#if 0 /* No other types allowed through IMP */
/* Check for DECNET protocol types if requested.
** The following are the known types:
** 6001 DNA/MOP
** 6002 RmtCon
** 6003 DECnet
** 6004 LAT
** 6016 ANF-10 (T10 only; not DECNET)
** 9000 Loopback (?)
*/
case 0x6001: /* DNA/MOP */
case 0x6002: /* RmtCon */
case 0x6003: /* DECnet */
case 0x6004: /* LAT */
case 0x6016: /* ANF-10 (T10 only; not DECNET) */
case 0x9000: /* Loopback (?) */
return (dpni->dpni_decnet); /* TRUE if wanted Decnet stuff */
default:
/* Test for an IEEE 802.3 packet with a specific dst/src LSAP.
Packet is 802.3 if type field is actually packet length -- in which
case it will be 1 <= len <= 1500 (note 1514 is max, of which header
uses 6+6+2=14).
Dst/src LSAPs are in the 1st shortwd after packet length.
*/
if (etyp <= 1500
&& (dpni->dpni_attrs & DPNI20F_LSAP)
&& (dpni->dpni_lsap == sp[PKSWOFF_SAPS]))
return TRUE;
break;
#endif /* 0 */
}
/* No other types allowed through IMP */
return FALSE;
}
#endif /* KLH10_NET_LNX */
#if !KLH10_NET_TUN
@@ -1061,7 +944,6 @@ used.
*/
#if 1 /* New stuff */
/* Set up by init for easier reference */
static struct dpimpsh_s *arpp;
@@ -1070,27 +952,6 @@ static struct arpent *arptab_lim;
#define ARPTAB_HASH(max,a) \
((unsigned long)(a) % (max))
#else /* Old stuff - temporarily saved */
#define ARPTAB_BSIZ 6 /* bucket size */
#define ARPTAB_NB 31 /* number of buckets (prime) */
#define ARPTAB_SIZE (ARPTAB_BSIZ * ARPTAB_NB)
struct arpent arptab[ARPTAB_SIZE];
#define ARPTAB_HASH(a) \
((unsigned long)(a) % ARPTAB_NB)
#define ARPTAB_LOOK(at,addr) { \
register int n; \
at = &arptab[ARPTAB_HASH(addr.s_addr) * ARPTAB_BSIZ]; \
for (n = 0 ; n < ARPTAB_BSIZ ; n++,at++) \
if (at->at_iaddr.s_addr == addr.s_addr) \
break; \
if (n >= ARPTAB_BSIZ) \
at = 0; \
}
#endif /* 0 */
/* ARP_INIT
** Set up our own ARP cache, and ensure that native host is in
@@ -1099,7 +960,7 @@ struct arpent arptab[ARPTAB_SIZE];
void
arp_init(struct dpimp_s *dpimp)
{
register struct dpimpsh_s *dsh = DPIMPSH(dpimp);
struct dpimpsh_s *dsh = DPIMPSH(dpimp);
struct ether_addr ea;
struct arpent *at;
@@ -1140,10 +1001,10 @@ arp_init(struct dpimp_s *dpimp)
int
arp_refreset(void)
{
register struct dpimpsh_s *dsh = arpp;
register struct arpent *at = &dsh->dpimpsh_arptab[0];
register int max = dsh->dpimpsh_arpsiz;
register int i;
struct dpimpsh_s *dsh = arpp;
struct arpent *at = &dsh->dpimpsh_arptab[0];
int max = dsh->dpimpsh_arpsiz;
int i;
for (i = 0; i < max; i++, at++) {
at->at_lastref = 0;
@@ -1155,10 +1016,10 @@ arp_refreset(void)
struct arpent *
arptab_look(struct in_addr addr)
{
register struct dpimpsh_s *dsh = arpp;
register int i;
register int max = dsh->dpimpsh_arpsiz;
register struct arpent *at =
struct dpimpsh_s *dsh = arpp;
int i;
int max = dsh->dpimpsh_arpsiz;
struct arpent *at =
&dsh->dpimpsh_arptab[ARPTAB_HASH(max, addr.s_addr)];
for (i = 0; i < max; i++, at++) {
@@ -1186,14 +1047,14 @@ arp_tnew(struct in_addr addr,
struct ether_addr *eap,
int flags)
{
register struct dpimpsh_s *dsh = arpp;
register int i;
register int max = dsh->dpimpsh_arpsiz;
register struct arpent *at =
struct dpimpsh_s *dsh = arpp;
int i;
int max = dsh->dpimpsh_arpsiz;
struct arpent *at =
&dsh->dpimpsh_arptab[ARPTAB_HASH(max, addr.s_addr)];
int oldest = dsh->dpimpsh_arprefs;
register struct arpent *ato = NULL;
struct arpent *ato = NULL;
for (i = 0; i < max; i++, at++) {
if (at >= arptab_lim)
@@ -1226,12 +1087,12 @@ arp_tnew(struct in_addr addr,
* the update access control, even though it's quite simple.
*/
void
arp_set(register struct arpent *at,
arp_set(struct arpent *at,
struct in_addr addr,
struct ether_addr *eap,
int flags)
{
register struct dpimpsh_s *dsh = arpp;
struct dpimpsh_s *dsh = arpp;
/* Get write lock */
dsh->dpimpsh_lock[mylockid] = TRUE;
@@ -1263,11 +1124,11 @@ struct arpent *
arp_look(struct in_addr ip,
struct ether_addr *eap)
{
register struct arpent *at;
struct arpent *at;
at = arptab_look(ip); /* Look up IP addr */
if (at && (at->at_flags & ARPF_COM)) {
register int i;
int i;
/* Exists and complete */
ea_set(eap, &(at->at_eaddr)); /* Return ether addr */
@@ -1310,7 +1171,7 @@ arp_req(struct in_addr *ipa)
static int ethbuild = 0, arpbuild = 0;
static struct eth_header eh;
static struct offset_ether_arp arp;
register struct arpent *at;
struct arpent *at;
struct ether_addr ea;
/* Store request in cache */
@@ -1365,8 +1226,8 @@ arp_req(struct in_addr *ipa)
void
arp_gotrep(unsigned char *buf, int cnt)
{
register struct ether_arp *aa;
register struct arpent *at;
struct ether_arp *aa;
struct arpent *at;
struct arpent ent;
if (DP_DBGFLG) {
@@ -1385,13 +1246,13 @@ arp_gotrep(unsigned char *buf, int cnt)
if (aa->arp_hrd != htons(ARPHRD_ETHER)) { /* Check hdw addr format */
if (DP_DBGFLG)
dbprintln("Dropped ARP, hrd %0x != %0x",
aa->arp_hrd, htons(ARPHRD_ETHER));
aa->arp_hrd, ARPHRD_ETHER);
return;
}
if (aa->arp_pro != htons(ETHERTYPE_IP)) { /* Check ptcl addr fmt */
if (DP_DBGFLG)
dbprintln("Dropped ARP, pro %0x != %0x",
aa->arp_pro, htons(ETHERTYPE_IP));
aa->arp_pro, ETHERTYPE_IP);
return;
}
if (aa->arp_hln != sizeof(aa->arp_sha)) { /* Check Hdw address len */
@@ -1517,19 +1378,15 @@ arp_reply(unsigned char *eap, /* Requestor ether addr */
** Reads packets from net, fragments if necessary, and feeds
** IMP packets to DP superior process.
*/
#if KLH10_NET_BPF
# define MAXETHERLEN OSN_BPF_MTU
#else
# define MAXETHERLEN 1600 /* Actually 1519 but be generous */
#endif
#define NINBUFSIZ (DPIMP_DATAOFFSET+MAXETHERLEN)
void
imptohost(register struct dpimp_s *dpimp)
imptohost(struct dpimp_s *dpimp)
{
register struct dpx_s *dpx = dp_dpxfr(&dp);
register int cnt;
struct dpx_s *dpx = dp_dpxfr(&dp);
int cnt;
unsigned char *inibuf;
unsigned char *buffp;
size_t max;
@@ -1544,8 +1401,12 @@ imptohost(register struct dpimp_s *dpimp)
if (DBGFLG)
fprintf(stderr, "[dpimp-R: sent INIT]\r\n");
#if (KLH10_NET_PCAP || KLH10_NET_NIT || KLH10_NET_DLPI || KLH10_NET_PFLT || \
KLH10_NET_TUN || KLH10_NET_LNX)
#if KLH10_NET_TUN
# define ETHER_HDR_OFFSET 0 /* No ether headers on TUN */
#else
# define ETHER_HDR_OFFSET ETHER_HDRSIZ
#endif
for (;;) {
/* Make sure that buffer is free before clobbering it */
dp_xswait(dpx); /* Wait until buff free */
@@ -1554,24 +1415,12 @@ imptohost(register struct dpimp_s *dpimp)
fprintf(stderr, "[dpimp-R: InWait]\r\n");
/* Set up buffer and initialize offsets */
#if KLH10_NET_TUN
/* XXX clean up TUN condits by using "0" ETHER_HDRSIZ substitute */
buffp = inibuf + DPIMP_DATAOFFSET;
#else
buffp = inibuf + (DPIMP_DATAOFFSET - ETHER_HDRSIZ);
#endif
buffp = inibuf + DPIMP_DATAOFFSET - ETHER_HDR_OFFSET;
/* OK, now do a blocking read on packetfilter input! */
#if KLH10_NET_PCAP || KLH10_NET_TUN || KLH10_NET_TAP_BRIDGE
cnt = osn_pfread(&pfdata, buffp, MAXETHERLEN);
#else
cnt = read(pfdata.pf_fd, buffp, MAXETHERLEN);
#endif
#if KLH10_NET_TUN
if (cnt <= 0) { /* No ether headers on TUN */
#else
if (cnt <= ETHER_HDRSIZ) {
#endif
if (cnt <= ETHER_HDR_OFFSET) {
/* If call times out due to E/BIOCSRTIMEOUT, will return 0 */
if (cnt == 0 && dpimp->dpimp_rdtmo)
continue; /* Just try again */
@@ -1588,22 +1437,6 @@ imptohost(register struct dpimp_s *dpimp)
if (errno == EINTR) /* Ignore spurious signals */
continue;
#if 0 && CENV_SYS_NETBSD
/* NetBSD bpf is broken.
See osdnet.c:osn_pfinit() comments re BIOCIMMEDIATE to
understand why this crock is necessary.
Always block for at least 1 sec, will wake up sooner if
input arrives.
*/
if (errno == EAGAIN || errno == EWOULDBLOCK) {
int ptimeout = (dpimp->dpimp_rdtmo ? dpimp->dpimp_rdtmo : 1);
struct pollfd myfd;
myfd.fd = pfdata.pf_fd;
myfd.events = POLLIN;
(void) poll(&myfd, 1, ptimeout*1000);
continue;
}
#endif
syserr(errno, "Eread = %d, errno %d", cnt, errno);
if (--stoploop <= 0)
efatal(1, "Too many retries, aborting");
@@ -1620,112 +1453,46 @@ imptohost(register struct dpimp_s *dpimp)
}
/* Have packet, now dispatch it to host */
#if KLH10_NET_LNX
/* Linux has no packet filtering, thus must apply manual check to
each and every packet read, even if dedicated.
*/
if (!lnx_filter(dpimp, buffp, cnt))
continue; /* Drop packet, continue reading */
#endif /* KLH10_NET_LNX */
#if !KLH10_NET_TUN
/* Verify that pf filtering is doing its job */
switch (eh_tget((struct eth_header *)buffp)) {
case ETHERTYPE_IP:
break;
case ETHERTYPE_ARP: /* If ARP, */
arp_gotrep(buffp, cnt); /* attempt to process replies */
continue; /* and always drop packet */
default:
error("Non-IP ether packet: %0X",
eh_tget((struct eth_header *)buffp));
continue;
/* If there hasn't been any packet filtering yet, then must apply
* manual check to each and every packet read, even if dedicated.
*/
if (!pfdata.pf_can_filter) {
if (!lnx_filter(dpimp, buffp, cnt))
continue; /* Drop packet, continue reading */
}
#endif /* !KLH10_NET_TUN */
#if !KLH10_NET_TUN
/* if (!pfdata.pf_ip4_only) */ {
/* Verify that pf filtering is doing its job */
switch (eh_tget((struct eth_header *)buffp)) {
case ETHERTYPE_IP:
break;
case ETHERTYPE_ARP: /* If ARP, */
arp_gotrep(buffp, cnt); /* attempt to process replies */
continue; /* and always drop packet */
default:
error("Non-IP ether packet: %0X",
eh_tget((struct eth_header *)buffp));
continue;
}
}
#endif
/* OK, it claims to be an IP packet, see if so long that we
** need to fragment it. Yech!
*/
#if !KLH10_NET_TUN
cnt -= ETHER_HDRSIZ;
cnt -= ETHER_HDR_OFFSET;
buffp += ETHER_HDR_OFFSET;
if (cnt > SI_MAXMSG) {
ihl_frag(cnt, buffp + ETHER_HDRSIZ);
ihl_frag(cnt, buffp);
} else {
/* Small enough to constitute one IMP message, so pass it on! */
ihl_hhsend(dpimp, cnt, buffp + ETHER_HDRSIZ);
}
#else /* !KLH10_NET_TUN */
if (cnt > SI_MAXMSG)
ihl_frag(cnt, buffp);
else
ihl_hhsend(dpimp, cnt, buffp);
#endif /* KLH10_NET_TUN */
}
}
#endif /* NIT || DLPI || PFLT || TUN || LNX */
#if KLH10_NET_BPF
for (;;) {
char *bp, *ep, *pp;
size_t caplen, hdrlen;
/* Make sure that buffer is free before clobbering it */
dp_xswait(dpx); /* Wait until buff free */
buffp = inibuf + DPIMP_DATAOFFSET;
if ((cnt = read(pfdata.pf_fd, buffp, OSN_BPF_MTU)) < 0) {
fprintf(stderr, "dpimp: BPF read = %d, ", cnt);
if (--stoploop <= 0)
efatal(1, "Too many retries, aborting");
fprintf(stderr, "errno %d = %s]\r\n", errno, dp_strerror(errno));
}
/* If call times out, will return 0 */
/* XXX fix up like dpni20 */
if (cnt == 0 /* && dpimp->dpimp_rdtmo */)
continue; /* Just try again */
if (DBGFLG)
dbprintln("BPF read = %d", cnt);
/* Grovel through buffer, sending each packet. Note that
** sending can prepend stuff onto data, which trashes the BPF header;
** thus pointer to next header must be derived BEFORE each send.
** The LHDH can also pad-trash the following 3 bytes if the data count
** isn't a multiple of 4 -- hence need to preserve vals from next hdr!
*/
bp = buffp; ep = bp + cnt;
# define bhp(p) ((struct bpf_hdr *)(p))
caplen = bhp(bp)->bh_caplen; /* Pre-fetch first BPF header */
hdrlen = bhp(bp)->bh_hdrlen;
while (bp < ep) {
cnt = caplen - ETHER_HDRSIZ;
pp = bp + hdrlen + ETHER_HDRSIZ;
/* Point to next header now, before current one is trashed */
bp += BPF_WORDALIGN(caplen + hdrlen);
if (bp < ep) {
caplen = bhp(bp)->bh_caplen;
hdrlen = bhp(bp)->bh_hdrlen;
}
# undef bhp
if (DBGFLG)
dbprintln("BPF pkt = %d", cnt);
/* See if so long that we need to fragment it. Yech! */
if (cnt > SI_MAXMSG) {
ihl_frag(cnt, pp);
} else {
/* Small enough for one IMP message, so pass it on! */
ihl_hhsend(dpimp, cnt, pp);
}
/* Wait until send ACKed, assume buff still OK */
dp_xswait(dpx);
}
}
#endif /* KLH10_NET_BPF */
}
void
@@ -1763,12 +1530,12 @@ unsigned char ihobuf[SIH_HSIZ+SI_LDRSIZ] = {
void
ihl_hhsend(register struct dpimp_s *dpimp,
ihl_hhsend(struct dpimp_s *dpimp,
int cnt,
register unsigned char *pp)
unsigned char *pp)
/* "pp" is packet data ptr, has room for header preceding */
{
register int bits = cnt * 8; /* Why not... msg length in bits */
int bits = cnt * 8; /* Why not... msg length in bits */
union ipaddr haddr;
/* Set up IMP leader */
@@ -1801,8 +1568,8 @@ ihl_hhsend(register struct dpimp_s *dpimp,
/* Send up to host! Assume we're already in shared buffer. */
{
register struct dpx_s *dpx = dp_dpxfr(&dp);
register unsigned char *buff;
struct dpx_s *dpx = dp_dpxfr(&dp);
unsigned char *buff;
size_t off, max;
buff = dp_xsbuff(dpx, &max); /* Set up buffer ptr & max count */
@@ -1823,12 +1590,12 @@ ihl_hhsend(register struct dpimp_s *dpimp,
** outputs to NET.
*/
void
hosttoimp(register struct dpimp_s *dpimp)
hosttoimp(struct dpimp_s *dpimp)
{
register struct dpx_s *dpx = dp_dpxto(&dp); /* Get ptr to "To-DP" dpx */
register unsigned char *buff;
struct dpx_s *dpx = dp_dpxto(&dp); /* Get ptr to "To-DP" dpx */
unsigned char *buff;
size_t max;
register int rcnt;
int rcnt;
unsigned char *inibuf;
#if !KLH10_NET_TUN
struct in_addr ipdest;
@@ -2039,9 +1806,9 @@ ip_write(struct in_addr *ipa, unsigned char *buf, int len)
* a copy of the header!
*/
void
ether_write(register struct eth_header *hp,
register unsigned char *pp,
register int cnt)
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);
@@ -2056,98 +1823,6 @@ ether_write(register struct eth_header *hp,
error("write failed - %s", dp_strerror(errno));
}
#elif KLH10_NET_NIT
struct strbuf ctl, dat;
struct sockaddr sa;
/* First set up control message to specify destination, expressed as a
** sockaddr. The interface output driver builds an ethernet header
** from that information.
** If sa_family is AF_UNSPEC, then sa_data is interpreted
** as a ether_header (it just so happens to be the same length,
** 14 bytes - bleah!) and the dest host is taken from ether_dhost,
** plus type from ether_type.
** If sa_family is AF_INET, then sa_data is interpreted as
** the rest of a sockaddr_in, and ARP resolution is done on the sin_addr
** field to find the correct destination ethernet addr. The type is always
** set to ETHERTYPE_IP.
** Unfortunately AF_INET cannot be used on NIT output
** currently; only AF_UNSPEC is allowed.
*/
sa.sa_family = AF_UNSPEC; /* Copy ether header */
memcpy(sa.sa_data, (char *)hp, ETHER_HDRSIZ);
ctl.maxlen = ctl.len = sizeof(struct sockaddr);
ctl.buf = (char *)&sa;
dat.maxlen = dat.len = cnt;
dat.buf = (char *)pp;
if (DP_DBGFLG)
dbprintln("net out = %d", cnt);
if (putmsg(pfdata.pf_fd, &ctl, &dat, 0) < 0) {
/* What to do here? For debugging, complain but return. */
error("putmsg failed - %s", dp_strerror(errno));
}
#elif KLH10_NET_DLPI
struct strbuf ctl, dat;
# if DPIMP_DATAOFFSET /* New code, OK to simply prepend header */
dat.buf = (char *)(pp - ETHER_HDRSIZ);
memcpy(dat.buf, (char *)hp, ETHER_HDRSIZ);
# else /* Old code, does extra buffer copy */
unsigned char buf[MAXETHERLEN];
memcpy(buf, (char *)hp, ETHER_HDRSIZ);
memcpy(buf+ETHER_HDRSIZ, pp, cnt);
dat.buf = (char *)buf;
# endif
dat.maxlen = dat.len = (cnt + ETHER_HDRSIZ);
if (DP_DBGFLG)
dbprintln("net out = %d", cnt);
if (putmsg(pfdata.pf_fd, NULL, &dat, 0) < 0) {
/* What to do here? For debugging, complain but return. */
error("putmsg failed - %s", dp_strerror(errno));
}
#elif KLH10_NET_PFLT
/* The lossage is endless... on DEC OSF/1 packetfilter FDs,
** writev() *WILL NOT WORK*. It appears to succeed, but nothing
** ever shows up on the output!
*/
# if DPIMP_DATAOFFSET /* New code, OK to simply prepend header */
char *buf = (char *)(pp - ETHER_HDRSIZ);
memcpy(buf, (char *)hp, ETHER_HDRSIZ);
# else /* Old code, does extra buffer copy */
unsigned char buf[MAXETHERLEN];
memcpy(buf, (char *)hp, ETHER_HDRSIZ);
memcpy(buf+ETHER_HDRSIZ, pp, cnt);
# endif
if (DP_DBGFLG)
dbprintln("net out = %d", cnt);
if (write(pfdata.pf_fd, buf, (size_t)(cnt + ETHER_HDRSIZ)) < 0) {
/* What to do here? For debugging, complain but return. */
error("write failed - %s", dp_strerror(errno));
}
#elif KLH10_NET_BPF || KLH10_NET_LNX
struct iovec iov[2];
iov[0].iov_base = (char *) hp;
iov[0].iov_len = ETHER_HDRSIZ;
iov[1].iov_base = pp;
iov[1].iov_len = cnt;
if (DP_DBGFLG)
dbprintln("net out = %d", cnt);
if (writev(pfdata.pf_fd, iov, sizeof(iov)/sizeof(*iov)) < 0) {
/* What to do here? For debugging, complain but return. */
error("writev() failed - %s", dp_strerror(errno));
}
#elif KLH10_NET_TUN
/* No code needed here -- routine never used */
#else

View File

@@ -164,10 +164,6 @@ The following general situations are possible:
#include "dpsup.h" /* General DP defs */
#include "dpni20.h" /* NI20 specific defs */
#ifdef RCSID
RCSID(dpni20_c,"$Id: dpni20.c,v 2.7 2003/02/23 18:07:50 klh Exp $")
#endif
/* Globals */
@@ -181,9 +177,7 @@ struct in_addr ehost_ip; /* Emulated host IP addr, net order */
#if 0
struct in_addr ihost_ip; /* Native host's IP addr, net order */
#endif
#if KLH10_NET_TUN
struct in_addr tun_ip; /* Tunnel IP addr, net order */
#endif
struct in_addr tun_ip; /* IP addr of Host side of tunnel, net order */
struct ether_addr ihost_ea; /* Native host ether addr for selected ifc */
/* Debug flag reference. Use DBGFLG within functions that have "dpni";
@@ -298,7 +292,7 @@ int initdebug = 0;
int
main(int argc, char **argv)
{
register struct dpni20_s *dpni;
struct dpni20_s *dpni;
/* Search for a "-debug" command-line argument so that we can start
debug output ASAP if necessary.
@@ -453,17 +447,16 @@ main(int argc, char **argv)
/* NET_INIT - Initialize net-related variables,
** given network interface we'll use.
*/
void net_init(register struct dpni20_s *dpni)
void net_init(struct dpni20_s *dpni)
{
struct ifreq ifr;
/* Get the IP address we need to filter on, if shared */
memcpy((char *)&ehost_ip, (char *)&dpni->dpni_ip, 4);
#if KLH10_NET_TUN
/* Get the IP address for the tunnel, if specified */
memcpy((char *)&tun_ip, (char *)&dpni->dpni_tun, 4);
#else
#if !KLH10_NET_TUN
/* Ensure network device name, if specified, isn't too long */
if (dpni->dpni_ifnam[0] && (strlen(dpni->dpni_ifnam)
>= sizeof(ifr.ifr_name))) {
@@ -511,18 +504,14 @@ void net_init(register struct dpni20_s *dpni)
npf.osnpf_rdtmo = dpni->dpni_rdtmo;
npf.osnpf_backlog = dpni->dpni_backlog;
npf.osnpf_ip.ia_addr = ehost_ip;
#if KLH10_NET_TUN
npf.osnpf_tun.ia_addr = tun_ip;
#endif
/* 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, dpni->dpni_eth); /* Set requested ea if any */
osn_pfinit(&pfdata, &npf, (void *)dpni); /* Will abort if fails */
ea_set(&ihost_ea, &npf.osnpf_ea); /* Copy actual ea */
#if KLH10_NET_TUN
tun_ip = npf.osnpf_tun.ia_addr; /* Get actual tunnel addr */
#endif
}
@@ -551,255 +540,9 @@ void net_init(register struct dpni20_s *dpni)
** IP data; if it's too short, it's rejected anyway.
*/
/* Common packetfilter definitions - for all but BPF */
#if KLH10_NET_PFLT || KLH10_NET_NIT || KLH10_NET_DLPI
#if KLH10_NET_PFLT
# define OSN_PFSTRUCT enfilter
# define PF_PRIO enf_Priority
# define PF_FLEN enf_FilterLen
# define PF_FILT enf_Filter
#elif (KLH10_NET_DLPI || KLH10_NET_NIT)
# define OSN_PFSTRUCT packetfilt
# define PF_PRIO Pf_Priority
# define PF_FLEN Pf_FilterLen
# define PF_FILT Pf_Filter
#endif
struct OSN_PFSTRUCT pfilter;
static void pfshow(struct OSN_PFSTRUCT *);
struct OSN_PFSTRUCT *
pfbuild(void *arg, struct in_addr *ipa)
{
register struct dpni20_s *dpni = (struct dpni20_s *)arg;
register unsigned short *p;
register unsigned char *ucp = (unsigned char *)ipa;
register struct OSN_PFSTRUCT *pfp = &pfilter;
p = pfp->PF_FILT; /* Get addr of filter (length ENMAXFILTERS) */
/* First check for broadcast/multicast bit in dest address */
*p++ = ENF_PUSHWORD + PKSWOFF_EDEST;
#ifdef ENF_PUSHONE /* New feature */
if (htons(0x0100) == 01) {
*p++ = ENF_PUSHONE | ENF_AND; /* Do AND of multicast bit */
*p++ = ENF_PUSHONE | ENF_COR; /* Succeed immediately if AND won */
} else
#endif
{
*p++ = ENF_PUSHLIT | ENF_AND; /* Do AND of multicast bit */
*p++ = htons(0x0100);
*p++ = ENF_PUSHLIT | ENF_COR; /* Succeed immediately if AND won */
*p++ = htons(0x0100);
}
/* Possibly insert check for DECNET protocol types.
** Doing this check is inefficient if most of the traffic is IP.
** Hopefully if the user asked for it, it's used a lot.
** The following are the known types:
** 6001 DNA/MOP
** 6002 RmtCon
** 6003 DECnet
** 6004 LAT
** 6016 ANF-10 (T10 only; not DECNET)
** 9000 Loopback (?)
**
** For the time being, filtering is done by testing for
** (type & ~0x001F) == 0x6000
** which accepts all types in the range 6000-601F inclusive.
** 9000 is ignored.
*/
if (dpni->dpni_decnet) {
#if 0
/* Blunt instrument approach */
*p++ = ENF_PUSHWORD + PKSWOFF_ETYPE; /* Check for DECNET packet */
*p++ = ENF_PUSHLIT | ENF_COR;
*p++ = htons(ETHERTYPE_DECnet); /* Win if 0x6003 */
*p++ = ENF_PUSHWORD + PKSWOFF_ETYPE; /* Check for LAT packet */
*p++ = ENF_PUSHLIT | ENF_COR;
*p++ = htons(ETHERTYPE_LAT); /* Win if 0x6004 */
*p++ = ENF_PUSHWORD + PKSWOFF_ETYPE; /* Check for 0x6016 */
*p++ = ENF_PUSHLIT | ENF_COR;
*p++ = htons(0x6016);
*p++ = ENF_PUSHWORD + PKSWOFF_ETYPE; /* Check for 0x6001 */
*p++ = ENF_PUSHLIT | ENF_COR;
*p++ = htons(0x6001);
*p++ = ENF_PUSHWORD + PKSWOFF_ETYPE; /* Check for 0x6002 */
*p++ = ENF_PUSHLIT | ENF_COR;
*p++ = htons(0x6002);
#else
/* Slightly faster, although sloppier */
*p++ = ENF_PUSHWORD + PKSWOFF_ETYPE; /* Get ethernet type */
*p++ = ENF_PUSHLIT | ENF_AND;
*p++ = htons(0xFFE0); /* Mask out ~0x001F */
*p++ = ENF_PUSHLIT | ENF_COR; /* Succeed if result 6000 */
*p++ = htons(0x6000);
#endif
}
/* Test for an IEEE 802.3 packet with a specific dst/src LSAP.
Packet is 802.3 if type field is actually packet length -- in which
case it will be 1 <= len <= 1500 (note 1514 is max, of which header
uses 6+6+2=14).
There's seemingly no way to tell what order the ENF_LT, etc operands
are used in, so until that's established, use a simple masking
method. 1500 = 0x5dc, so use mask of 0xF800.
Dst/src LSAPs are in next two bytes (1st shortwd after len).
*/
if (dpni->dpni_attrs & DPNI20F_LSAP) {
unsigned short lsaps = dpni->dpni_lsap;
if (lsaps <= 0xFF) { /* If only one byte set, */
lsaps |= (lsaps << 8); /* double it up for both dest & src */
}
*p++ = ENF_PUSHWORD + PKSWOFF_ETYPE; /* Get ethernet type field */
*p++ = ENF_PUSHLIT | ENF_AND;
*p++ = htons(0xF800); /* Unused len bits shd be 0 */
/* Element on stack is now 0 if 802.3. Check LSAPs. */
*p++ = ENF_PUSHWORD + PKSWOFF_SAPS; /* Get DSAP/SSAP word */
*p++ = ENF_PUSHLIT | ENF_NEQ; /* Compare, set 0 if same */
*p++ = htons(lsaps);
/* Now compare result of both checks.
If both succeeded, both will be 0, otherwise some bits will be set.
*/
*p++ = ENF_OR; /* IOR the results together */
*p++ = ENF_PUSHZERO | ENF_COR; /* Succeed if result 0 */
}
/* See if we're interested in IP (and thus ARP) packets.
This is assumed to be the LAST part of the filter, thus
it must either leave the correct result on the stack, or
ensure it is empty (if accepting the packet).
*/
if (memcmp(dpni->dpni_ip, "\0\0\0\0", 4) != 0) {
/* Want to pass ARP replies as well, so 10 can see responses to any
** ARPs it sends out.
** NOTE!!! ARP *requests* are not passed! The assumption is that
** osn_arp_stuff() will have ensured that the host platform
** proxy-answers requests for our IP address.
*/
*p++ = ENF_PUSHWORD + PKSWOFF_ETYPE; /* Check for ARP packet */
*p++ = ENF_PUSHLIT | ENF_COR;
*p++ = htons(ETHERTYPE_ARP); /* Win if 0x0806 */
/* If didn't pass, check for our IP address */
*p++ = ENF_PUSHWORD + PKSWOFF_IPDEST+1;
*p++ = ENF_PUSHLIT | ENF_CAND; /* Comp low wds of IP addrs */
*p++ = htons((ucp[2]<<8) | ucp[3]); /* Make net-order low word */
*p++ = ENF_PUSHWORD + PKSWOFF_IPDEST;
*p++ = ENF_PUSHLIT | ENF_CAND; /* Comp high wds of IP addrs */
*p++ = htons((ucp[0]<<8) | ucp[1]); /* Make net-order high word */
*p++ = ENF_PUSHWORD + PKSWOFF_ETYPE; /* Verify IP packet */
*p++ = ENF_PUSHLIT | ENF_EQ; /* Comp, leave result on stk */
*p++ = htons(ETHERTYPE_IP);
} else {
/* If not doing IP, fail at this point because the packet
doesn't match any of the desired types.
*/
*p++ = ENF_PUSHZERO; /* Fail - must leave 0 result on stk */
}
pfp->PF_FLEN = p - pfp->PF_FILT; /* Set # of items on list */
pfp->PF_PRIO = 128; /* Pick middle of 0-255 range */
/* "Ignored", but NIT RARPD recommends > 2 */
if (DBGFLG) /* If debugging, print out resulting filter */
pfshow(pfp);
return pfp;
}
/* Debug auxiliary to print out packetfilter we composed.
*/
static void
pfshow(struct OSN_PFSTRUCT *pf)
{
int i;
fprintf(stderr,"[%s: kernel packetfilter pri %d, len %d:", progname,
pf->PF_PRIO, pf->PF_FLEN);
for (i = 0; i < pf->PF_FLEN; ++i)
fprintf(stderr, " %04X", pf->PF_FILT[i]);
fprintf(stderr, "]\r\n");
}
#endif /* KLH10_NET_PFLT || KLH10_NET_NIT || KLH10_NET_DLPI */
#if KLH10_NET_DLPI
/* GROSS HACK for Solaris DLPI!!
** Even if the interface is dedicated, there is no way to grab packets
** for all SAPs (ethernet types) without making the interface promiscuous!
** So we have to have a filter on hand that can be used to get only
** the packets that are broadcast/multicast or specifically addressed to
** our ethernet address. Ugh!
*/
struct OSN_PFSTRUCT *
pfeabuild(void *arg, unsigned char *ea)
{
register struct dpni20_s *dpni = (struct dpni20_s *)arg;
register unsigned short *p;
register struct OSN_PFSTRUCT *pfp = &pfilter;
p = pfp->PF_FILT; /* Get addr of filter (length ENMAXFILTERS) */
/* First check for broadcast/multicast bit in dest address */
*p++ = ENF_PUSHWORD + PKSWOFF_EDEST;
#ifdef ENF_PUSHONE /* New feature */
if (htons(0x0100) == 01) {
*p++ = ENF_PUSHONE | ENF_AND; /* Do AND of multicast bit */
*p++ = ENF_PUSHONE | ENF_COR; /* Succeed immediately if AND won */
} else
#endif
{
*p++ = ENF_PUSHLIT | ENF_AND; /* Do AND of multicast bit */
*p++ = htons(0x0100);
*p++ = ENF_PUSHLIT | ENF_COR; /* Succeed immediately if AND won */
*p++ = htons(0x0100);
}
/* Now check for our ethernet address, low bytes first since those
** tend to vary the most.
** Note stack is empty at this point.
*/
*p++ = ENF_PUSHWORD + PKSWOFF_EDEST+2; /* Comp low wds of E/N addrs */
*p++ = ENF_PUSHLIT | ENF_CAND; /* Fail if not same */
*p++ = htons((ea[4]<<8) | ea[5]); /* (net-order low word) */
*p++ = ENF_PUSHWORD + PKSWOFF_EDEST+1; /* Comp mid wds of E/N addrs */
*p++ = ENF_PUSHLIT | ENF_CAND; /* Fail if not same */
*p++ = htons((ea[2]<<8) | ea[3]); /* (net-order mid word) */
*p++ = ENF_PUSHWORD + PKSWOFF_EDEST; /* Comp hi wds of E/N addrs */
*p++ = ENF_PUSHLIT | ENF_CAND; /* Fail if not same */
*p++ = htons((ea[0]<<8) | ea[1]); /* (net-order hi word) */
/* Stack is again empty at this point, which means "accept packet". */
pfp->PF_FLEN = p - pfp->PF_FILT; /* Set # of items on list */
pfp->PF_PRIO = 128; /* Pick middle of 0-255 range */
/* "Ignored", but NIT RARPD recommends > 2 */
if (DBGFLG) /* If debugging, print out resulting filter */
pfshow(pfp);
return pfp;
}
#endif /* KLH10_NET_DLPI */
/* BPF packetfilter initialization */
#if KLH10_NET_PCAP || KLH10_NET_BPF
#if KLH10_NET_PCAP
/*
** BPF filter program stuff.
@@ -881,9 +624,9 @@ static void pfshow(struct OSN_PFSTRUCT *);
struct OSN_PFSTRUCT *
pfbuild(void *arg, struct in_addr *ipa)
{
register struct dpni20_s *dpni = (struct dpni20_s *)arg;
register struct OSN_PFSTRUCT *pfp = &bpf_pfilter;
register struct bpf_insn *p;
struct dpni20_s *dpni = (struct dpni20_s *)arg;
struct OSN_PFSTRUCT *pfp = &bpf_pfilter;
struct bpf_insn *p;
p = pfp->PF_FILT; /* Point to 1st instruction in BPF program */
@@ -1020,7 +763,7 @@ pfshow(struct OSN_PFSTRUCT *pf)
fprintf(stderr, "]\r\n");
}
#endif /* KLH10_NET_BPF */
#endif /* KLH10_NET_PCAP */
/* LNX packetfilter initialization */
@@ -1049,13 +792,13 @@ pfshow(struct OSN_PFSTRUCT *pf)
Returns TRUE if packet OK, FALSE if it should be dropped.
Note that the code parallels that for pfbuild().
*/
int lnx_filter(register struct dpni20_s *dpni,
int lnx_filter(struct dpni20_s *dpni,
unsigned char *bp,
int cnt)
{
/* Code assumes buffer is at least shortword-aligned. */
register unsigned short *sp = (unsigned short *)bp;
register unsigned short etyp;
unsigned short *sp = (unsigned short *)bp;
unsigned short etyp;
/* First check for broadcast/multicast bit in dest address */
if (bp[PKBOFF_EDEST] & 01)
@@ -1115,7 +858,7 @@ int lnx_filter(register struct dpni20_s *dpni,
/* ETH_SETADR - Attempt to set physical ethernet address to dpni_rqeth.
** If successful, reflect this by changing dpni_eth.
*/
void eth_adrset(register struct dpni20_s *dpni)
void eth_adrset(struct dpni20_s *dpni)
{
#if OSN_USE_IPONLY
dbprintln("\"%s\" ethernet address change ignored - IP-only interface",
@@ -1125,16 +868,15 @@ void eth_adrset(register struct dpni20_s *dpni)
char old[OSN_EASTRSIZ];
char new[OSN_EASTRSIZ];
/* Set up for simpler output */
eth_adrsprint(old, dpni->dpni_eth);
eth_adrsprint(new, dpni->dpni_rqeth);
/* Before hitting the barf below, do one last check to make sure
** we're not setting it to the current address.
*/
if (memcmp(dpni->dpni_eth, dpni->dpni_rqeth, ETHER_ADRSIZ) == 0)
if (ea_cmp(dpni->dpni_eth, dpni->dpni_rqeth) == 0)
return; /* Succeed silently */
/* Set up for simpler output */
eth_adrsprint(old, dpni->dpni_eth);
eth_adrsprint(new, dpni->dpni_rqeth);
/* Check to make sure it's OK to set our address.
** Only allow it if interface is dedicated; otherwise, barf so user
@@ -1179,7 +921,7 @@ void eth_adrset(register struct dpni20_s *dpni)
} else {
/* See if same as requested! */
if (memcmp(rdea, dpni->dpni_rqeth, ETHER_ADRSIZ) != 0) {
if (ea_cmp(rdea, dpni->dpni_rqeth) != 0) {
eth_adrsprint(old, rdea);
dbprintln("New \"%s\" e/n addr mismatch! Set=%s Read=%s",
dpni->dpni_ifnam, new, old);
@@ -1188,7 +930,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);
ea_set(dpni->dpni_eth, dpni->dpni_rqeth);
}
@@ -1203,7 +945,7 @@ void eth_adrset(register struct dpni20_s *dpni)
** MCAT loads.
*/
void eth_mcatset(register struct dpni20_s *dpni)
void eth_mcatset(struct dpni20_s *dpni)
{
#if OSN_USE_IPONLY
dbprintln("\"%s\" multicast table ignored - IP-only interface",
@@ -1317,10 +1059,10 @@ void eth_mcatset(register struct dpni20_s *dpni)
#define ARP_PKTSIZ (sizeof(struct ether_header) + sizeof(struct ether_arp))
int arp_myreply(register unsigned char *buf, register int cnt)
int arp_myreply(unsigned char *buf, int cnt)
{
register struct ifent *ife;
register unsigned char *ucp;
struct ifent *ife;
unsigned char *ucp;
struct in_addr ia;
struct ether_arp arp;
unsigned char pktbuf[ARP_PKTSIZ];
@@ -1400,19 +1142,30 @@ int arp_myreply(register unsigned char *buf, register int cnt)
eth_adrsprint(ethstr, ife->ife_ea));
}
#if KLH10_NET_DLPI
{
struct strbuf data;
data.buf = (char *)pktbuf;
data.len = sizeof(pktbuf);
(void) putmsg(pfdata.pf_fd, NULL, &data, 0);
}
#else
#if 0
/* XXX
* Why is this sent to the packet filter (= host) and not to the -10?????
*/
(void)write(pfdata.pf_fd, pktbuf, sizeof(pktbuf));
(void)osn_pfwrite(&pfdata, pktbuf, sizeof(pktbuf));
#else
/* ARP reply packet, pass to 10 via DPC */
struct dpx_s *dpx;
unsigned char *buff;
size_t max;
dpx = dp_dpxfr(&dp); /* Get ptr to from-DP comm rgn */
buff = dp_xsbuff(dpx, &max); /* Set up buffer ptr & max count */
/* Tell KLH10 we're initialized and ready by sending initial packet */
if (sizeof(pktbuf) <= max &&
dp_xswait(dpx)) { /* Wait until buff free, in case */
memcpy(buff, pktbuf, sizeof(pktbuf));
dp_xsend(dpx, DPNI_RPKT, cnt);
if (DP_DBGFLG)
dbprint("sent ARP reply to -10");
}
#endif
return TRUE;
}
@@ -1420,21 +1173,14 @@ int arp_myreply(register unsigned char *buf, register int cnt)
** Reads packets from packetfilter and relays them to 10 using DPC
** mechanism.
*/
/* Screwy BPF algorithm requires more bookkeeping because there's
no way to ensure only one packet is read at a time; the call
may return a buffer of several packets, each of which must
be returned to the 10 separately.
Also, we need to do buffer copying since the 10 side doesn't
understand the BPF header. Later an offset could be provided?
*/
#define MAXETHERLEN 1600 /* Actually 1519 but be generous */
void ethtoten(register struct dpni20_s *dpni)
void ethtoten(struct dpni20_s *dpni)
{
register struct dpx_s *dpx;
register int cnt;
register unsigned char *buff;
struct dpx_s *dpx;
int cnt;
unsigned char *buff;
size_t max;
int cmin = sizeof(struct ether_header);
int stoploop = 50;
@@ -1451,16 +1197,6 @@ void ethtoten(register struct dpni20_s *dpni)
/* Standard algorithm, one packet per read call */
for (;;) {
#if KLH10_NET_BPF
unsigned char *bp, *ep, *pp;
int i;
size_t caplen, hdrlen, datalen;
unsigned char tbuff[OSN_BPF_MTU];
size_t tmax = sizeof(tbuff);
cmin = (int)(sizeof(struct ether_header)+sizeof(struct bpf_hdr));
#endif /* KLH10_NET_BPF */
/* Make sure that buffer is free before clobbering it */
dp_xswait(dpx); /* Wait until buff free */
@@ -1468,25 +1204,8 @@ void ethtoten(register struct dpni20_s *dpni)
dbprintln("InWait");
/* OK, now do a blocking read on packetfilter input! */
#if KLH10_NET_PCAP || KLH10_NET_TUN || KLH10_NET_TAP_BRIDGE
cnt = osn_pfread(&pfdata, buff, max);
#elif KLH10_NET_DLPI
{
struct strbuf data;
int flagsp = 0;
data.buf = (char *)buff;
data.maxlen = max;
data.len = 0;
if ((cnt = getmsg(pfdata.pf_fd, (struct strbuf *)NULL, &data, &flagsp)) == 0)
cnt = data.len;
/* Else cnt must be -1 as call failed */
}
#elif KLH10_NET_BPF
cnt = read(pfdata.pf_fd, tbuff, tmax);
#else
cnt = read(pfdata.pf_fd, buff, max);
#endif /* reading choice */
if (cnt <= cmin) { /* Must get enough for ether header */
/* If call timed out, should return 0 */
@@ -1505,22 +1224,6 @@ void ethtoten(register struct dpni20_s *dpni)
if (errno == EINTR) /* Ignore spurious signals */
continue;
#if 0 && CENV_SYS_NETBSD
/* NetBSD bpf is broken.
See osdnet.c:osn_pfinit() comments re BIOCIMMEDIATE to
understand why this crock is necessary.
Always block for at least 1 sec, will wake up sooner if
input arrives.
*/
if (errno == EAGAIN || errno == EWOULDBLOCK) {
int ptimeout = (dpni->dpni_rdtmo ? dpni->dpni_rdtmo : 1);
struct pollfd myfd;
myfd.fd = pfdata.pf_fd;
myfd.events = POLLIN;
(void) poll(&myfd, 1, ptimeout*1000);
continue;
}
#endif
syserr(errno, "Eread = %d, errno %d", cnt, errno);
if (--stoploop <= 0)
efatal(1, "Too many retries, aborting");
@@ -1530,11 +1233,7 @@ void ethtoten(register struct dpni20_s *dpni)
if (DBGFLG) {
if (DBGFLG & 0x4) {
fprintf(stderr, "\r\n[%s: Read=%d\r\n", progname, cnt);
#if KLH10_NET_BPF
dumppkt(tbuff, cnt);
#else
dumppkt(buff, cnt);
#endif
fprintf(stderr, "]");
}
else
@@ -1553,7 +1252,6 @@ void ethtoten(register struct dpni20_s *dpni)
}
}
#if !KLH10_NET_BPF
#if 0
if (DBGFLG)
if (((struct ether_header *)buff)->ether_type == htons(ETHERTYPE_ARP))
@@ -1564,58 +1262,6 @@ void ethtoten(register struct dpni20_s *dpni)
dp_xsend(dpx, DPNI_RPKT, cnt);
if (DBGFLG)
dbprint("sent RPKT");
#else
/* Screwy BPF algorithm requires more overhead because there's
no way to ensure only one packet is read at a time; the call
may return a buffer of several packets, each of which must
be returned to the 10 separately.
Also, we need to do buffer copying since the 10 side doesn't
understand the BPF header. Later an offset could be provided?
*/
/* Grovel through buffer, sending each packet up to 10.
*/
bp = tbuff;
ep = bp + cnt;
# define bhp(p) ((struct bpf_hdr *)(p))
caplen = bhp(bp)->bh_caplen; /* Pre-fetch first BPF header */
datalen = bhp(bp)->bh_datalen;
hdrlen = bhp(bp)->bh_hdrlen;
for (i = 0; bp < ep; ++i) {
if (caplen != datalen) {
dbprint("BPF#%d trunc %ld => %ld",
i, (long)datalen, (long)caplen);
/* Continue, not much else we can do */
}
cnt = caplen;
pp = bp + hdrlen; /* Pointer to actual packet data */
/* Point to next header now, before current one is trashed */
bp += BPF_WORDALIGN(caplen + hdrlen);
if (bp < ep) {
caplen = bhp(bp)->bh_caplen;
datalen = bhp(bp)->bh_datalen;
hdrlen = bhp(bp)->bh_hdrlen;
}
# undef bhp
if (DBGFLG)
dbprint("BPF pkt %d = %d", i, cnt);
/* Copy packet data into buffer for 10, and send it */
memcpy((char *)buff, (char *)pp, (size_t)cnt);
dp_xsend(dpx, DPNI_RPKT, cnt);
if (DBGFLG)
dbprint("sent RPKT");
/* Wait until send ACKed, assume buff still OK */
dp_xswait(dpx);
}
#endif /* KLH10_NET_BPF */
} /* Infinite loop reading packetfilter input */
}
@@ -1624,14 +1270,14 @@ void ethtoten(register struct dpni20_s *dpni)
** data message, sends to ethernet.
*/
void tentoeth(register struct dpni20_s *dpni)
void tentoeth(struct dpni20_s *dpni)
{
register struct dpx_s *dpx;
register int cnt;
register unsigned char *buff;
struct dpx_s *dpx;
int cnt;
unsigned char *buff;
size_t max;
register int rcnt;
register int doarpchk;
int rcnt;
int doarpchk;
int stoploop = 50;
/* Must check for outbound ARP requests if asked to and have
@@ -1677,19 +1323,8 @@ void tentoeth(register struct dpni20_s *dpni)
&& arp_myreply(buff, rcnt)) { /* and it fits, & is hacked */
break; /* then drop this req pkt */
}
#if KLH10_NET_PCAP || KLH10_NET_TUN || KLH10_NET_TAP_BRIDGE
cnt = osn_pfwrite(&pfdata, buff, rcnt);
#elif KLH10_NET_DLPI
{
struct strbuf data;
data.buf = (char *)buff;
data.len = rcnt;
if ((cnt = putmsg(pfdata.pf_fd, NULL, &data, 0)) == 0)
cnt = rcnt; /* Assume successful */
}
#else
cnt = write(pfdata.pf_fd, buff, rcnt);
#endif /* else KLH10_NET_DLPI */
if (cnt != rcnt) {
if ((cnt < 0) && (errno == EINTR)) {
continue; /* Start over, may have new cmd */

View File

@@ -49,23 +49,13 @@ struct ifent *osn_iflookup(char *ifnam);
int
osn_ifsock(char *ifnam, ossock_t *as)
{
#if (KLH10_NET_NIT || KLH10_NET_DLPI || KLH10_NET_BPF || KLH10_NET_PFLT || \
KLH10_NET_PCAP || 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
#endif
}
int
osn_ifclose(ossock_t s)
{
#if (KLH10_NET_NIT || KLH10_NET_DLPI || KLH10_NET_BPF || KLH10_NET_PFLT || \
KLH10_NET_PCAP || KLH10_NET_TUN || KLH10_NET_LNX || KLH10_NET_TAP_BRIDGE)
return (close(s) >= 0);
#else
# error OSD implementation needed for osn_ifclose
#endif
}
@@ -434,32 +424,50 @@ osn_arp_stuff(char *ifname, unsigned char *ipa, unsigned char *eap, int pubf)
(pubf ? "pub" : ""));
}
#if CENV_SYS_LINUX
#if CENV_SYS_LINUX && OSN_USE_IPONLY
/**
* Linux won't do proxy ARP by default. It needs to be turned on.
* This is needed when we use an Ethernet device, not an IP tunnel.
*
* However, it seems not to help...
*-----
* According to
* http://mailman.ds9a.nl/pipermail/lartc/2003q2/008315.html, this
* is how Linux handles ARP requests:
*
* When an arp request arrives on an interface, if proxy_arp is OFF at
* that interface, then we reply only if it asks who has an IP address
* assigned to that interface. In that case we reply that this IP
* address is at the MAC address of the receiving interface.
*
* If, however, proxy_arp is ON at that interface, then we check the
* routing table (here things get a little fuzzy, since in reality the
* routing can depend on all sorts of things other than the destination
* address, and the arp request isn't specifying any of those) to find
* out, if we were sending a packet to that IP address, which interface
* we would use to send it out. If there is such an interface (we do
* have a route to that address) and it's NOT the same one that the
* request arrived on, then we reply with the MAC address of the
* interface on which the request arrived.
*-----
* So, that helps with a tunnel device, not with a tap device.
* Why then does linux have ATF_PUBL flags in its ARP table?
*/
int fd;
#if 0
char devproc[64];
snprintf(devproc, sizeof(devproc)-1, "/proc/sys/net/ipv4/conf/%s/proxy_arp", ifname);
/*
* or sysctl -w net.ipv4.conf.%s.proxy_arp=1
*/
fd = open(devproc, O_WRONLY|O_TRUNC);
if (fd >= 0) {
(void)write(fd, "1\n", 2);
close(fd);
dbprintln("Enabled net.ipv4.conf.%s.proxy_arp", ifname);
}
fd = open("/proc/sys/net/ipv4/conf/all/proxy_arp", O_WRONLY|O_TRUNC);
if (fd >= 0) {
(void)write(fd, "1\n", 2);
close(fd);
dbprintln("Enabled net.ipv4.conf.all.proxy_arp");
}
#endif
/*
* or sysctl -w net.ipv4.conf.all.proxy_arp=1 (seems not needeede)
*/
/**
* When we use an IP tunnel, this is needed to cause ARP replies to
* be sent by Linux if OSN_USE_IPONLY and if you try to connect to
@@ -474,7 +482,7 @@ osn_arp_stuff(char *ifname, unsigned char *ipa, unsigned char *eap, int pubf)
close(fd);
dbprintln("Enabled net.ipv4.ip_forward");
}
#endif /* CENV_SYS_LINUX */
#endif /* CENV_SYS_LINUX && OSN_USE_IPONLY */
#if NETIF_HAS_ARPIOCTL
struct arpreq arq;
@@ -493,6 +501,13 @@ osn_arp_stuff(char *ifname, unsigned char *ipa, unsigned char *eap, int pubf)
if (pubf)
arq.arp_flags |= ATF_PUBL; /* Publish it for us too! */
#if CENV_SYS_LINUX
/*
* Fill in the name of the interface from which we expect the
* requests.
*/
strncpy(arq.arp_dev, ifname, sizeof (arq.arp_dev));
#endif
if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { /* Get random socket */
syserr(errno, "Cannot set ARP entry for %s %s - socket()",
ip_adrsprint(ipbuf, ipa),
@@ -559,7 +574,7 @@ osn_arp_stuff(char *ifname, unsigned char *ipa, unsigned char *eap, int pubf)
ip_adrsprint(ipbuf, ipa),
eth_adrsprint(eabuf, eap));
return FALSE;
#endif
#endif /* NETIF_HAS_ARPIOCTL, CENV_SYS_XBSD, or else */
}
/* OSN_IFIPGET - get IP address for a given interface name.
@@ -1319,7 +1334,7 @@ osn_pfwrite(struct pfdata *pfdata, const void *buf, size_t nbytes)
}
#endif
#if KLH10_NET_PFLT || KLH10_NET_BPF
#if KLH10_NET_BPF
/* Adapted from DEC's pfopen.c - doing it ourselves here because pfopen(3)
* did not always exist, and this way we can report errors better.
@@ -1328,11 +1343,7 @@ osn_pfwrite(struct pfdata *pfdata, const void *buf, size_t nbytes)
static int
pfopen(void)
{
#if KLH10_NET_PFLT
# define PFDEVPREF "/dev/pf/pfilt"
#elif KLH10_NET_BPF
# define PFDEVPREF "/dev/bpf"
#endif
char pfname[sizeof(PFDEVPREF)+10];
int fd;
int i = 0;
@@ -1354,247 +1365,8 @@ pfopen(void)
return fd; /* Success! */
}
#endif /* KLH10_NET_PFLT || KLH10_NET_BPF */
#if KLH10_NET_PFLT
int
osn_pfinit(struct osnpf *osnpf, void *pfarg)
{
int fd;
int arg;
unsigned short bits;
/* Open PF fd. We'll be doing both R and W. */
fd = pfopen(); /* Open, will abort if fails */
if (osnpf->osnpf_ifnam && osnpf->osnpf_ifnam[0]) { /* Allow default ifc */
/* Bind to specified HW interface */
if (ioctl(fd, EIOCSETIF, osnpf->osnpf_ifnam) < 0)
esfatal(1, "Couldn't open packetfilter for \"%s\" - EIOCSETIF",
osnpf->osnpf_ifnam);
}
/* Set up various mode & flag stuff */
/* Only the super-user can allow promiscuous or copy-all to be set. */
#if 0
/* Allow promiscuous mode if someone wants to use it.
** For shared interface, never true.
*/
arg = 1;
if (ioctl(fd, EIOCALLOWPROMISC, &arg))
esfatal(1, "EIOCALLOWPROMISC failed"); /* Maybe not SU? */
#endif
/* Allow ENCOPYALL bit to be set.
** Always use this for shared interface so the multicast-bit stuff
** we grab can also be seen by kernel and other sniffers.
*/
arg = 1;
if (ioctl(fd, EIOCALLOWCOPYALL, &arg))
esfatal(1, "EIOCALLOWCOPYALL failed"); /* Maybe not SU? */
/* Ensure following bits clear:
** no timestamps, no batching, no held signal
*/
bits = (ENTSTAMP | ENBATCH | ENHOLDSIG);
if (ioctl(fd, EIOCMBIC, &bits))
esfatal(1, "EIOCMBIC failed");
/* Set:
** ??? Put interface into promisc mode (if allowed by SU)
** KLH: No longer -- shouldn't be necessary.
** Pass packet along to other filters
** Copy packets to/from native kernel ptcls - to allow talking with
** native host platform!
*/
bits = (/* ENPROMISC | */ ENNONEXCL | ENCOPYALL);
if (ioctl(fd, EIOCMBIS, &bits))
esfatal(1, "ioctl: EIOCMBIS");
/* Set up packet filter for it - only needed if sharing interface */
if (!osnpf->osnpf_dedic) {
if (ioctl(fd, EIOCSETF, pfbuild(pfarg, &(osnpf->osnpf_ip.ia_addr))) < 0)
esfatal(1, "EIOCSETF failed");
}
/* Now can get our interface's ethernet address.
** In general, this has to wait until after the packetfilter is opened,
** since until then we don't have a handle on the specific interface
** that will be used.
*/
{
struct endevp endp;
if (ioctl(fd, EIOCDEVP, (caddr_t *)&endp) < 0)
esfatal(1, "EIOCDEVP failed");
if (endp.end_dev_type != ENDT_10MB
|| endp.end_addr_len != 6)
esfatal(1, "EIOCDEVP returned non-Ethernet info!");
ea_set(&(osnpf->osnpf_ea), endp.end_addr);
}
/* Miscellaneous stuff */
/* Hack: use timeout mechanism to see if it helps avoid wedging system
** when using OSF/1 V3.0.
*/
if (osnpf->osnpf_rdtmo)
{
struct timeval tv;
tv.tv_sec = osnpf->osnpf_rdtmo;
tv.tv_usec = 0;
if (ioctl(fd, EIOCSRTIMEOUT, &tv) < 0)
esfatal(1, "EIOCSRTIMEOUT failed");
}
/* If backlog param was provided, try to set system's idea of how many
** input packets can be kept on kernel queue while waiting for us to
** read them into user space.
*/
if (osnpf->osnpf_backlog) {
if (ioctl(fd, EIOCSETW, &(osnpf->osnpf_backlog)) < 0)
esfatal(1, "EIOCSETW failed");
}
/* Ready to roll! */
return fd;
}
#endif /* KLH10_NET_PFLT */
#if KLH10_NET_BPF
int
osn_pfinit(struct osnpf *osnpf, void *arg)
{
int fd;
struct bpf_version bv;
struct ifreq ifr;
u_int u;
int i;
char *ifnam = osnpf->osnpf_ifnam;
if (DP_DBGFLG)
dbprint("Opening BPF device");
/* No "default interface" concept here */
if (!ifnam || !ifnam[0])
esfatal(1, "Packetfilter interface must be specified");
/* Open an unused BPF device for R/W */
fd = pfopen(); /* Will abort if fail */
/* Check the filter language version number */
if (ioctl(fd, BIOCVERSION, (char *) &bv) < 0)
esfatal(1, "kernel BPF interpreter out of date");
else if (bv.bv_major != BPF_MAJOR_VERSION ||
bv.bv_minor < BPF_MINOR_VERSION)
efatal(1, "requires BPF language %d.%d or higher; kernel is %d.%d",
BPF_MAJOR_VERSION, BPF_MINOR_VERSION, bv.bv_major, bv.bv_minor);
/* Set immediate mode so that packets are processed as they arrive,
rather than waiting until timeout or buffer full.
WARNING: NetBSD does not implement this correctly! The code
in src/sys/net/bpf.c:bpfread() treats the immediate flag in a way
that causes it to return EWOULDBLOCK if no input is available. But
this flag must still be set in order for bpfpoll() to detect input
as soon as it arrives!
See dpni20 and dpimp read loops for workaround.
*/
i = 1;
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!
*/
u = OSN_BPF_MTU;
if (ioctl(fd, BIOCSBLEN, (char *) &u) < 0)
esfatal(1, "BIOCSBLEN failed");
/* Set up packet filter for it - only needed if sharing interface?
Not sure whether it's needed for a dedicated interface; will need
to experiment.
*/
if (!osnpf->osnpf_dedic) {
struct OSN_PFSTRUCT *pf;
/* Set the kernel packet filter */
pf = pfbuild(arg, &(osnpf->osnpf_ip.ia_addr));
if (ioctl(fd, BIOCSETF, (char *)pf) < 0)
esfatal(1, "BIOCSETF failed");
}
/* Set read timeout.
Safety check in order to avoid infinite hangs if something
wedges up. The periodic re-check overhead is insignificant.
*/
/* Set read timeout.
Safety hack derived from need to use timeout to avoid wedging system
when using OSF/1 V3.0. Probably useful for other systems too.
*/
if (osnpf->osnpf_rdtmo)
{
struct timeval tv;
tv.tv_sec = osnpf->osnpf_rdtmo;
tv.tv_usec = 0;
if (ioctl(fd, BIOCSRTIMEOUT, (char *) &tv) < 0)
esfatal(1, "BIOCSRTIMEOUT failed");
}
/* Attach/bind to desired interface device
*/
strncpy(ifr.ifr_name, ifnam, sizeof(ifr.ifr_name));
if (ioctl(fd, BIOCSETIF, (char *) &ifr) < 0)
esfatal(1, "BIOCSETIF failed for interface \"%s\"", ifnam);
/* This code only works with Ethernet, so check for that.
Note cannot check until after interface is attached.
*/
if (ioctl(fd, BIOCGDLT, (char *) &u) < 0)
esfatal(1, "BIOCGDLT failed for interface \"%s\"", ifnam);
if (u != DLT_EN10MB)
efatal(1, "%s is not an ethernet", ifnam);
/* Now get our interface's ethernet address.
** In general, this has to wait until after the packetfilter is opened,
** since until then we don't have a handle on the specific interface
** that will be used.
*/
(void) osn_pfeaget(fd, ifnam, (unsigned char *)&(osnpf->osnpf_ea));
/* Ready to roll! */
return fd;
}
#endif /* KLH10_NET_BPF */
#if KLH10_NET_TUN
/*
@@ -1706,9 +1478,11 @@ osn_pfinit(struct pfdata *pfdata, struct osnpf *osnpf, void *arg)
memset(&ifr, 0, sizeof(ifr));
# if OSN_USE_IPONLY
ifr.ifr_flags = IFF_TUN | IFF_NO_PI; /* TUN (no Ethernet headers), no pkt info */
/* ip tuntap add mode tun */
# else
ifr.ifr_flags = IFF_TAP | IFF_NO_PI; /* TAP (yes Ethernet headers), no pkt info */
# endif
/* ip tuntap add mode tap */
# endif /* OSN_USE_IPONLY */
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") */
@@ -1718,12 +1492,12 @@ osn_pfinit(struct pfdata *pfdata, struct osnpf *osnpf, void *arg)
sprintf(tunname, "/dev/tun%d", ++i);
# else
sprintf(tunname, "/dev/tap%d", ++i);
# endif /* not CENV_SYS_LINUX */
# endif /* OSN_USE_IPONLY */
} while ((fd = open(tunname, O_RDWR)) < 0 && errno == EBUSY);
if (fd < 0)
esfatal(1, "Couldn't open tunnel device %s", tunname);
#endif
#endif /* CENV_SYS_LINUX */
if (DP_DBGFLG)
dbprintln("Opened %s, configuring for local %s, remote %s",
@@ -1747,6 +1521,8 @@ osn_pfinit(struct pfdata *pfdata, struct osnpf *osnpf, void *arg)
Second address is "remote" -- the one the emulated host is using.
It should probably match the same network as the local address,
especially if planning to connect from other machines.
This is only needed for TUNNEL devices, not TAP devices.
*/
#if 0 /* Hacky method */
{
@@ -1763,6 +1539,7 @@ osn_pfinit(struct pfdata *pfdata, struct osnpf *osnpf, void *arg)
}
#elif CENV_SYS_LINUX /* [BV: Linux tun device] */
/* "Hacky" but simple method */
# if OSN_USE_IPONLY
{
char cmdbuff[128];
int res;
@@ -1778,7 +1555,8 @@ osn_pfinit(struct pfdata *pfdata, struct osnpf *osnpf, void *arg)
esfatal(1, "osn_pfinit: ifconfig failed to initialize tunnel device?");
}
}
#else
# endif /* OSN_USE_IPONLY */
#else /* not CENV_SYS_LINUX */
{
/* Internal method */
int s;
@@ -1799,6 +1577,10 @@ osn_pfinit(struct pfdata *pfdata, struct osnpf *osnpf, void *arg)
syserr(errno, "osn_pfinit tun SIOCDIFADDR failed");
}
# if OSN_USE_IPONLY
/*
* Then set the point-to-point addresses for the tunnel.
*/
memset(&ifra, 0, sizeof(ifra));
strncpy(ifra.ifra_name, ifnam, sizeof(ifra.ifra_name));
((struct sockaddr_in *)(&ifra.ifra_addr))->sin_len = sizeof(struct sockaddr_in);
@@ -1810,6 +1592,8 @@ osn_pfinit(struct pfdata *pfdata, struct osnpf *osnpf, void *arg)
if (ioctl(s, SIOCAIFADDR, &ifra) < 0) {
esfatal(1, "osn_pfinit tun SIOCAIFADDR failed");
}
# endif /* OSN_USE_IPONLY */
/* Finally, turn on IFF_UP just in case the above didn't do it.
Note interface name is still there from the SIOCDIFADDR.
@@ -1826,7 +1610,7 @@ osn_pfinit(struct pfdata *pfdata, struct osnpf *osnpf, void *arg)
dbprint("osn_pfinit tun did SIOCSIFFLAGS");
}
}
#endif
#endif /* CENV_SYS_LINUX */
/* Now optionally determine ethernet address.
This amounts to what if anything we should put in the native
@@ -1883,140 +1667,6 @@ osn_pfinit(struct pfdata *pfdata, struct osnpf *osnpf, void *arg)
#endif /* KLH10_NET_TUN */
#if KLH10_NET_LNX
/*
The Linux PF_PACKET interface is described to some extent
by the packet(7) man page.
Linux provides no kernel packet filtering mechanism other than
possibly a check on the ethernet protocol type, but this is useless
for us since we'll always want to check for more than just one type;
e.g. IP and ARP, plus possibly 802.3 or DECNET packets.
From the man page for packet(7):
By default all packets of the specified protocol type are
passed to a packet socket. To only get packets from a spe-
cific interface use bind(2) specifying an address in a
struct sockaddr_ll to bind the packet socket to an inter-
face. Only the sll_protocol and the sll_ifindex address
fields are used for purposes of binding.
*/
int
osn_pfinit(struct osnpf *osnpf, void *arg)
{
int fd;
char *ifcname = osnpf->osnpf_ifnam;
struct ifreq ifr;
/* Open a socket of the desired type.
*/
struct sockaddr_ll sll;
int ifx;
/* Get raw packets with ethernet headers
*/
fd = socket(PF_PACKET, SOCK_RAW,
#if 0 /*OSN_USE_IPONLY*/ /* If DPIMP or otherwise IP only */
htons(ETH_P_IP) /* for IP only */
#else
htons(ETH_P_ALL) /* for everything */
#endif
);
if (fd < 0)
esfatal(1, "Couldn't open packet socket");
/* Need ifc index in order to do binding, so get it. */
memset(&ifr, 0, sizeof(ifr));
strncpy(ifr.ifr_name, ifcname, sizeof(ifr.ifr_name));
if (ioctl(fd, SIOCGIFINDEX, &ifr) < 0 )
esfatal(1, "SIOCGIFINDEX of %s failed", ifcname);
ifx = ifr.ifr_ifindex;
/* Bind to proper device/interface using ifc index */
memset(&sll, 0, sizeof(sll));
sll.sll_family = AF_PACKET;
sll.sll_protocol = htons(ETH_P_ALL);
sll.sll_ifindex = ifx;
if (bind(fd, (struct sockaddr *)&sll, sizeof(sll)))
esfatal(1, "bind to %s failed", ifcname);
/* This code only works with Ethernet, so check for that */
memset(&ifr, 0, sizeof(ifr));
strncpy(ifr.ifr_name, ifcname, sizeof(ifr.ifr_name));
if (ioctl(fd, SIOCGIFHWADDR, &ifr) < 0 )
esfatal(1, "SIOCGIFHWADDR of %s failed", ifcname);
if (ifr.ifr_hwaddr.sa_family != ARPHRD_ETHER)
efatal(1, "%s is not an ethernet - ARPHRD type %d",
ifcname, ifr.ifr_hwaddr.sa_family);
/* Finally, attempt to determine current ethernet MAC address.
Assume above call returned it in sa_data.
*/
ea_set(&osnpf->osnpf_ea, &ifr.ifr_addr.sa_data[0]);
return fd;
}
#endif /* KLH10_NET_LNX */
#if KLH10_NET_NIT
/* NIT packetfilter initialization */
int
osn_pfinit(struct osnpf *osnpf, void *arg)
{
int fd;
struct strioctl si;
struct ifreq ifr;
/* Open NIT stream. We'll be doing both R and W. */
if ((fd = open("/dev/nit", O_RDWR)) < 0)
esfatal(1, "Couldn't open NIT");
/* Ensure that each read gives us one packet */
if (ioctl(fd, I_SRDOPT, (char *)RMSGD) < 0)
esfatal(1, "I_SRDOPT failed");
/* Set up kernel filtering */
if (ioctl(fd, I_PUSH, "pf") < 0)
esfatal("I_PUSH pf failed");
/* Set up packet filter for it */
if (!osnpf->osnpf_dedic) {
struct OSN_PFSTRUCT *pf;
pf = pfbuild(arg, &osnpf->osnpf_ip.ia_addr);
si.ic_timout = INFTIM; /* Should this be osnpf_rdtmo? */
si.ic_cmd = NIOCSETF; /* Set packet filter */
si.ic_len = sizeof(*pf); /* XXX Unfortunate dependency */
si.ic_dp = (char *)pf;
if (ioctl(fd, I_STR, (char *)&si) < 0)
esfatal(1, "NIOCSETF failed");
}
/* Finally, bind to proper device and flush anything accumulated */
strncpy(ifr.ifr_name, osnpf->osnpf_ifnam, sizeof(ifr.ifr_name));
si.ic_cmd = NIOCBIND;
si.ic_len = sizeof(ifr);
si.ic_dp = (char *)&ifr;
if (ioctl(fd, I_STR, (char *)&si) < 0)
esfatal(1, "NIOCBIND failed");
if (ioctl(fd, I_FLUSH, (char *)FLUSHR) < 0)
esfatal(1, "I_FLUSH failed");
/* Get our ethernet address.
** This can't be done until after the NIT is open and bound.
*/
(void) osn_pfeaget(fd, osnpf->osnpf_ifnam, &(osnpf->osnpf_ea));
/* Ready to roll! */
return fd;
}
#endif /* KLH10_NET_NIT */
/*
* Too bad that this is never called...
*/
@@ -2254,7 +1904,6 @@ 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");
@@ -2313,195 +1962,8 @@ static int dlpromisconreq(struct dlpictx *dc, u_long level);
static int dladdrreq(struct dlpictx *dc, int type);
static int dladdrack(struct dlpictx *dc, unsigned char *addr);
static int dlsetaddrreq(struct dlpictx *dc, unsigned char *addr);
#if 0
static int dlpromiscoff(struct dlpictx *dc);
static int dlinforeq(struct dlpictx *dc);
static int dlinfoack(struct dlpictx *dc);
static int dlenabmulti(struct dlpictx *dc, char *addrp, int len);
static int dldisabmulti(struct dlpictx *dc, char *addrp, int len);
static int dldetachreq(struct dlpictx *dc);
static int dlunbindreq(struct dlpictx *dc);
#endif
int osn_pfinit(struct osnpf *osnpf, void *arg)
{
int fd;
int ppa;
char *cp;
unsigned char curea[ETHER_ADRSIZ];
char devpath[IFNAMSIZ+40];
char eastr[OSN_EASTRSIZ];
unsigned char *ucp;
struct dlpictx dc;
/* Figure out right name of device to use.
** Munch device spec, eg "hmeNN" becomes /dev/hme, unit NN.
** Code formerly allowed full pathname as device spec, but no longer.
*/
if (osnpf->osnpf_ifnam[0] == 0)
efatal(1, "Ethernet DLPI interface must be specified");
strcpy(devpath, "/dev/");
strcat(devpath, osnpf->osnpf_ifnam); /* Buffer always big enough */
ppa = 0; /* Assume unit #0 */
cp = &devpath[strlen(devpath)-1]; /* Point to end of string */
if (isdigit(*cp)) { /* Go to start of unit digits */
while (isdigit(*--cp)); /* (code safe cuz of /dev/ prefix) */
ppa = atoi(++cp);
*cp = '\0'; /* Chop off unit digits */
}
/* Open device. We'll be doing both R and W. */
if ((fd = open(devpath, O_RDWR)) < 0) {
esfatal(1, "Couldn't open DLPI packetfilter for ifc \"%s\" (%s)",
devpath, osnpf->osnpf_ifnam);
}
memset((void *)&dc, 0, sizeof(dc));
dc.dc_fd = fd;
/* Attach to specific unit */
if (dlattachreq(&dc, (long)ppa)
|| dlokack(&dc))
efatal(1, dc.dc_ebuf);
/* Bind */
#if OSN_USE_IPONLY /* Note using IP SAP */
if (dlbindreq(&dc, 0x800, 0, DL_CLDLS, 0)
#else /* Note using fake SAP to avoid Solaris lossage */
if (dlbindreq(&dc, FAKESAP, 0, DL_CLDLS, 0)
#endif
|| dlbindack(&dc))
efatal(1, dc.dc_ebuf);
#if OSN_USE_IPONLY /* Apparently only needed for this */
/* Do stuff for "fastpath" which may be needed to allow header to
be included in data buffer rather than separate control struct.
*/
if (dlfastpathon(&dc, 0) < 0)
efatal(1, dc.dc_ebuf);
#elif 0 /* !OSN_USE_IPONLY */ /* Apparently not needed */
if (dlfastpathon(&dc, FAKESAP) < 0)
efatal(1, dc.dc_ebuf);
#endif
/* Set up various mode & flag stuff */
/* Do input side of DLPI stream */
#if CENV_SYS_SOLARIS
/* Turn on raw receive path, so that ethernet header is included in data.
** This is a special Solaris frob.
*/
if (strioctl(fd, DLIOCRAW, 0, NULL) < 0) {
esfatal(1, "DLIOCRAW ioctl");
}
#endif
#if !OSN_USE_IPONLY
/* Don't need this hackery if only want IP packets */
/* Enable receiving all packets, all SAPs (ethernet header type values) */
# if CENV_SYS_SOLARIS
/* Enable promiscuous mode. On Solaris, this is required in order
** for ALLSAP to work!!! Gross bletcherous misfeatured bug!!!
*/
if ((dlpromisconreq(&dc, DL_PROMISC_PHYS) < 0)
|| dlokack(&dc) < 0)
efatal(1, dc.dc_ebuf);
# endif
/* Evidently must explicitly ask for promiscuous SAPs */
if (dlpromisconreq(&dc, DL_PROMISC_SAP) < 0
|| dlokack(&dc) < 0)
efatal(1, dc.dc_ebuf);
/* And multicast too!? To quote tcpdump,
** "you would have thought promiscuous would be sufficient"
*/
if (dlpromisconreq(&dc, DL_PROMISC_MULTI) < 0
|| dlokack(&dc) < 0)
efatal(1, dc.dc_ebuf);
#endif /* !OSN_USE_IPONLY */
/* Find the physical ethernet address of the interface we got.
** Do it now, because it may be needed in order to set up the
** correct packet filter (sigh).
*/
if (dladdrreq(&dc, DL_CURR_PHYS_ADDR) < 0
|| dladdrack(&dc, (unsigned char *)curea) < 0)
efatal(1, dc.dc_ebuf);
/* HACK HACK -- see if ethernet addr already given, and if so,
** try to set it if different.
*/
if (!ea_isclr(&osnpf->osnpf_ea)
&& (ea_cmp(&osnpf->osnpf_ea, curea) != 0)) {
char old[OSN_EASTRSIZ];
char new[OSN_EASTRSIZ];
/* Attempt to set our EN addr */
eth_adrsprint(old, (unsigned char *)curea);
eth_adrsprint(new, (unsigned char *)&osnpf->osnpf_ea);
if (dlsetaddrreq(&dc, (unsigned char *)&osnpf->osnpf_ea) < 0
|| dlokack(&dc) < 0)
efatal(1, dc.dc_ebuf);
/* Double-check by fetching new addr again and using it */
if (dladdrreq(&dc, DL_CURR_PHYS_ADDR) < 0
|| dladdrack(&dc, (unsigned char *)curea) < 0)
efatal(1, dc.dc_ebuf);
if (ea_cmp(&osnpf->osnpf_ea, curea) == 0) {
dbprintln("\"%s\" E/N addr changed: Old=%s New=%s",
osnpf->osnpf_ifnam, old, new);
} else {
dbprintln("\"%s\" E/N addr change failed, Old=%s New=%s",
osnpf->osnpf_ifnam, old, new);
}
}
ea_set(&osnpf->osnpf_ea, curea);
#if 0
/* Ensure that each read gives us one packet.
** Shouldn't matter since we use getmsg(), but code left here in case.
*/
if (ioctl(fd, I_SRDOPT, (char *)RMSGD) < 0)
esfatal(1, "I_SRDOPT failed");
#endif
/* Set up packet filter for it - should only be needed if
** sharing interface, but on Solaris we may be always in promiscuous
** mode!
*/
#if !CENV_SYS_SOLARIS
if (!osnpf->osnpf_dedic)
#endif
{
struct OSN_PFSTRUCT *pf;
if (ioctl(fd, I_PUSH, "pfmod") < 0)
esfatal(1, "PUSH of pfmod failed");
#if !OSN_USE_IPONLY
if (osnpf->osnpf_dedic)
/* Filter on our ether addr */
pf = pfeabuild(arg, (unsigned char *)&osnpf->osnpf_ea);
else
#endif
/* Filter on our IP addr */
pf = pfbuild(arg, &osnpf->osnpf_ip.ia_addr);
if (strioctl(dc.dc_fd, PFIOCSETF, sizeof(*pf), (char *)pf) < 0)
esfatal(1, "PFIOCSETF failed");
}
/* Needed? Flush read side to ensure clear of anything accumulated */
if (ioctl(fd, I_FLUSH, (char *)FLUSHR) < 0)
esfatal(1, "I_FLUSH failed");
/* Ready to roll! */
return fd;
}
/* Handy auxiliary to pick up EA address given the PF FD, in case
it's needed again after osn_pfinit is done.
*/
@@ -2829,108 +2291,6 @@ dlsetaddrreq(struct dlpictx *dc, unsigned char *addr)
"dlsetaddr");
}
#endif /* KLH10_NET_DLPI */
#if 0 /* KLH10_NET_DLPI */
/* DLPI functions not currently used, but kept around in case
*/
/* Turn off promiscuous mode
*/
static int
dlpromiscoff(struct dlpictx *dc)
{
dl_promiscoff_req_t req;
req.dl_primitive = DL_PROMISCOFF_REQ;
return dl_sendreq(dc, (char *)&req, sizeof(req), "dlpromiscoff");
}
static int
dlinforeq(struct dlpictx *dc)
{
dl_info_req_t req;
req.dl_primitive = DL_INFO_REQ;
return (dl_sendreq(dc, (char *)&req, sizeof(req), "info"));
}
static int
dlinfoack(struct dlpictx *dc)
{
union DL_primitives *dlp;
if (strgetmsg(dc, "dlinfoack", NULL, NULL) < 0)
return -1;
dlp = (union DL_primitives *) dc->dc_ctl.buf;
if (dlp->dl_primitive != DL_INFO_ACK) {
sprintf(dc->dc_ebuf, "dlinfoack unexpected primitive %ld",
(long)dlp->dl_primitive);
return -1;
}
/* Extra stuff like the broadcast address can be returned */
if (dc->dc_ctl.len < DL_INFO_ACK_SIZE) {
sprintf(dc->dc_ebuf, "dlinfoack: incorrect size %ld",
(long)dc->dc_ctl.len);
return -1;
}
return 0;
}
static int
dlenabmulti(struct dlpictx *dc,
char *addrp,
int len)
{
dl_enabmulti_req_t *req;
req = (dl_enabmulti_req_t *) dc->dc_buf;
req->dl_primitive = DL_ENABMULTI_REQ;
req->dl_addr_length = len;
req->dl_addr_offset = sizeof (dl_enabmulti_req_t);
memcpy((dc->dc_buf + sizeof(dl_enabmulti_req_t)), addrp, len);
return (dl_sendreq(dc, (char *)req, sizeof(*req)+len, "dlenabmulti"));
}
static int
dldisabmulti(struct dlpictx *dc,
char *addrp,
int len)
{
dl_disabmulti_req_t *req;
req = (dl_disabmulti_req_t *) dc->dc_buf;
req->dl_primitive = DL_DISABMULTI_REQ;
req->dl_addr_length = len;
req->dl_addr_offset = sizeof (dl_disabmulti_req_t);
memcpy((dc->dc_buf + sizeof(dl_disabmulti_req_t)), addrp, len);
return (dl_sendreq(dc, (char *)req, sizeof(*req)+len, "dldisabmulti"));
}
static int
dldetachreq(struct dlpictx *dc)
{
dl_detach_req_t req;
req.dl_primitive = DL_DETACH_REQ;
return (dl_sendreq(dc, (char *)&req, sizeof(req), "dldetach"));
}
static int
dlunbindreq(struct dlpictx *dc)
{
dl_unbind_req_t req;
req.dl_primitive = DL_UNBIND_REQ;
return (dl_sendreq(dc, (char *)&req, sizeof(req), "dlunbind"));
}
#endif /* KLH10_NET_DLPI */
/* Auxiliary OSDNET.C stuff stops here */

View File

@@ -386,7 +386,7 @@ union ipaddr {
/*
* A structure that aggregates information about the packet filter variant
* which is in use.
* which is in use.
*/
struct pfdata {
int pf_fd; /* most but not all have a file descriptor */
@@ -432,8 +432,8 @@ struct osnpf { /* Arg struct for common initialization params */
int osnpf_dedic; /* TRUE if dedicated ifc, else shared */
int osnpf_rdtmo; /* Read timeout, if any */
int osnpf_backlog; /* Allow # backlogged packets, if any */
union ipaddr osnpf_ip; /* IP address to use */
union ipaddr osnpf_tun; /* INOUT: IP address of tunnel */
union ipaddr osnpf_ip; /* IP address to use */
union ipaddr osnpf_tun; /* INOUT: IP address host side of tunnel */
struct ether_addr osnpf_ea; /* OUT: ether address of ifc */
};
/* the void * is an argument to pass on to pfbuild() */