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:
509
src/dpimp.c
509
src/dpimp.c
@@ -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
|
||||
|
||||
473
src/dpni20.c
473
src/dpni20.c
@@ -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 */
|
||||
|
||||
754
src/osdnet.c
754
src/osdnet.c
@@ -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 *)𝔦
|
||||
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 */
|
||||
|
||||
@@ -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() */
|
||||
|
||||
Reference in New Issue
Block a user