1
0
mirror of https://github.com/PDP-10/klh10.git synced 2026-01-11 23:52:54 +00:00

Add libpcap for receiving and sending ethernet frames.

The goal is to retire KLH10_NET_BPF, _PFLT, _DLPI and _LNX as much as possible.
However where ethernet addresses are manipulated, such operating system dependent methods still need to be used, since libpcap does not handle that.

Code for the other packet filters is still included but most likely does not work.
To use the new code, add -DKLH10_NET_PCAP to the Makefile(s).
This commit is contained in:
Olaf Seibert 2015-12-20 17:56:51 +01:00
parent 6bc3ecd739
commit 89be604190
7 changed files with 500 additions and 134 deletions

View File

@ -191,7 +191,7 @@ fail because the arp_look() call can't find it.
Algorithm to use:
- See if IMP ifc is same as default IP ifc.
- If yes - shared, not dedicated.
Get ether addr from PFFD as usual and copy into arptab cache.
Get ether addr from pfdata.pf_FD as usual and copy into arptab cache.
- If no - dedicated, not shared.
See if native IP address can be found in OS ARP table.
If yes - save in cache, done.
@ -277,7 +277,7 @@ int chpid; /* PID of child (R proc) */
int mylockid; /* Locker IDs: 1 for W, 0 for R */
int othlockid;
int swstatus = TRUE;
int pffd; /* Packet-Filter FD (bidirectional) */
struct pfdata pfdata; /* Packet-Filter state */
struct in_addr ehost_ip; /* Emulated host IP addr, net order */
struct in_addr ihost_ip; /* IMP/Native host IP addr, net order */
@ -595,7 +595,8 @@ main(int argc, char **argv)
*/
#if !KLH10_NET_TUN /* If TUN, already done by osn_pfinit */
arp_init(dpimp);
if (!osn_arp_stuff((unsigned char *)&ehost_ip,
if (!osn_arp_stuff(dpimp->dpimp_ifnam,
(unsigned char *)&ehost_ip,
(unsigned char *)&ihost_ea, TRUE)) /* Set us up */
esfatal(1, "OSN_ARP_STUFF failed");
#endif
@ -720,7 +721,7 @@ net_init(register struct dpimp_s *dpimp)
the packetfilter open may use and/or change it.
*/
ea_set(&npf.osnpf_ea, dpimp->dpimp_eth); /* Set requested ea if any */
pffd = osn_pfinit(&npf, (void *)dpimp); /* Will abort if fails */
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 */
@ -808,7 +809,7 @@ pfshow(struct OSN_PFSTRUCT *pf)
#endif /* KLH10_NET_PFLT || KLH10_NET_NIT || KLH10_NET_DLPI */
#if KLH10_NET_BPF
#if KLH10_NET_BPF || KLH10_NET_PCAP
/*
** BPF filter program stuff.
@ -908,9 +909,10 @@ pfbuild(void *arg, struct in_addr *ipa)
/* Want to pass ARP replies as well, so we can see responses to any
** ARPs we send out?
** NOTE!!! ARP *requests* are not passed! The assumption is that
** ARP *requests* are also passed! The hope is that
** osn_arp_stuff() will have ensured that the host platform
** proxy-answers requests for our IP address.
** proxy-answers requests for our IP address, but that doesn't
** always work.
*/
*p++ = BPFI_LDH(PKBOFF_ETYPE); /* Load ethernet type field */
*p++ = BPFI_CAMN(ETHERTYPE_ARP); /* Skip unless ARP packet */
@ -959,7 +961,7 @@ pfshow(struct OSN_PFSTRUCT *pf)
pf->PF_FILT[i].k);
fprintf(stderr, "]\r\n");
}
#endif /* KLH10_NET_BPF */
#endif /* KLH10_NET_BPF || KLH10_NET_PCAP */
#if KLH10_NET_LNX
@ -986,11 +988,11 @@ int lnx_filter(register struct dpimp_s *dpimp,
*/
etyp = ntohs(sp[PKSWOFF_ETYPE]);
switch (etyp) {
#if 1 /* Must pass on ARP processing (Linux doesn't proxy ARP for us!!) */
/* Must pass on ARP processing (Linux doesn't proxy ARP for us!!)
*/
case ETHERTYPE_ARP:
return TRUE;
#endif
case ETHERTYPE_IP:
/* For IP packet, return TRUE if IP destination matches ours */
return (memcmp(dpimp->dpimp_ip, bp + PKBOFF_IPDEST, 4) == 0);
@ -1293,6 +1295,10 @@ arp_look(struct in_addr ip,
return NULL;
}
struct offset_ether_arp {
unsigned char offset[DPIMP_DATAOFFSET];
struct ether_arp arp;
};
/* ARP_REQ - Generates and sends ARP request.
Must remember the fact in our cache, so can process reply ourself
@ -1303,7 +1309,7 @@ arp_req(struct in_addr *ipa)
{
static int ethbuild = 0, arpbuild = 0;
static struct eth_header eh;
static struct ether_arp arp;
static struct offset_ether_arp arp;
register struct arpent *at;
struct ether_addr ea;
@ -1322,20 +1328,20 @@ arp_req(struct in_addr *ipa)
/* Now put together the ARP packet */
if (!arpbuild) {
arp.arp_hrd = htons(ARPHRD_ETHER); /* Set hdw addr format */
arp.arp_pro = htons(ETHERTYPE_IP); /* Set ptcl addr fmt */
arp.arp_hln = sizeof(arp.arp_sha); /* Hdw address len */
arp.arp_pln = sizeof(arp.arp_spa); /* Ptcl address len */
arp.arp_op = htons(ARPOP_REQUEST); /* Type REQUEST */
ea_set(arp.arp_sha, &ihost_ea); /* Sender hdw addr */
memcpy((char *)arp.arp_spa, /* Sender IP addr */
(char *)&ihost_ip, sizeof(arp.arp_sha));
arp.arp.arp_hrd = htons(ARPHRD_ETHER); /* Set hdw addr format */
arp.arp.arp_pro = htons(ETHERTYPE_IP); /* Set ptcl addr fmt */
arp.arp.arp_hln = sizeof(arp.arp.arp_sha); /* Hdw address len */
arp.arp.arp_pln = sizeof(arp.arp.arp_spa); /* Ptcl address len */
arp.arp.arp_op = htons(ARPOP_REQUEST); /* Type REQUEST */
ea_set(arp.arp.arp_sha, &ihost_ea); /* Sender hdw addr */
memcpy((char *)arp.arp.arp_spa, /* Sender IP addr */
(char *)&ihost_ip, sizeof(arp.arp.arp_sha));
arpbuild = TRUE;
}
/* Now do only thing that varies -- set IP addr we're looking up. */
memcpy((char *)arp.arp_tpa, /* Target IP addr */
(char *)ipa, sizeof(arp.arp_tpa));
memcpy((char *)arp.arp.arp_tpa, /* Target IP addr */
(char *)ipa, sizeof(arp.arp.arp_tpa));
/* Now send it! */
if (swstatus) {
@ -1343,15 +1349,15 @@ arp_req(struct in_addr *ipa)
dbprintln("ARP req %s", ip_adrsprint(ipbuf, (unsigned char *)ipa));
}
ether_write(&eh, (unsigned char *)&arp, sizeof(arp));
ether_write(&eh, (unsigned char *)&arp.arp, sizeof(arp.arp));
}
/* ARP_GOTREP - Process an ARP Reply
/* ARP_GOTREP - Process an ARP Request or Reply.
If it matches a request we already sent out, remember its
information. Next time we try sending a packet to that IP address
we'll find the entry.
Should we respond to ARP requests (proxy ARP)???
We should respond to ARP requests for our own IPv4 address.
*/
#define ARP_PKTSIZ (sizeof(struct ether_header) + sizeof(struct ether_arp))
@ -1365,6 +1371,7 @@ arp_gotrep(unsigned char *buf, int cnt)
if (DP_DBGFLG) {
char eabuf[OSN_EASTRSIZ];
dbprintln("Got ARP from %s", eth_adrsprint(eabuf, eh_sptr(buf)));
}
@ -1411,8 +1418,11 @@ arp_gotrep(unsigned char *buf, int cnt)
}
if (DP_DBGFLG) {
char ipbuf[OSN_IPSTRSIZ];
dbprintln("Dropped ARP req for %s",
ip_adrsprint(ipbuf, (unsigned char *)&ent.at_iaddr));
char eabuf[OSN_EASTRSIZ];
dbprintln("Dropped ARP req for %s from %s",
ip_adrsprint(ipbuf, (unsigned char *)&ent.at_iaddr),
eth_adrsprint(eabuf, (unsigned char *)&aa->arp_sha));
}
return;
}
@ -1460,7 +1470,7 @@ arp_reply(unsigned char *eap, /* Requestor ether addr */
unsigned char *iap) /* Requestor IP addr */
{
struct eth_header eh;
struct ether_arp arp;
struct offset_ether_arp arp;
/* Build ethernet header */
eh_dset(&eh, eap); /* Set dest addr */
@ -1468,31 +1478,38 @@ arp_reply(unsigned char *eap, /* Requestor ether addr */
eh_tset(&eh, ETHERTYPE_ARP);
/* Now put together the ARP packet */
arp.arp_hrd = htons(ARPHRD_ETHER); /* Set hdw addr format */
arp.arp_pro = htons(ETHERTYPE_IP); /* Set ptcl addr fmt */
arp.arp_hln = sizeof(arp.arp_sha); /* Hdw address len */
arp.arp_pln = sizeof(arp.arp_spa); /* Ptcl address len */
arp.arp_op = htons(ARPOP_REPLY); /* Type REPLY */
arp.arp.arp_hrd = htons(ARPHRD_ETHER); /* Set hdw addr format */
arp.arp.arp_pro = htons(ETHERTYPE_IP); /* Set ptcl addr fmt */
arp.arp.arp_hln = sizeof(arp.arp.arp_sha); /* Hdw address len */
arp.arp.arp_pln = sizeof(arp.arp.arp_spa); /* Ptcl address len */
arp.arp.arp_op = htons(ARPOP_REPLY); /* Type REPLY */
memcpy((char *)arp.arp_spa, /* Sender IP addr */
(char *)&ihost_ip, sizeof(arp.arp_sha));
memcpy((char *)arp.arp.arp_spa, /* Sender IP addr */
(char *)&ihost_ip, sizeof(arp.arp.arp_sha));
/* Sender hdw addr and IP addr (that's us - the resolved info) */
ea_set(arp.arp_sha, &ihost_ea); /* Sender hdw addr */
memcpy((char *)arp.arp_spa, (char *)&ehost_ip, IP_ADRSIZ);
ea_set(arp.arp.arp_sha, &ihost_ea); /* Sender hdw addr */
memcpy((char *)arp.arp.arp_spa, (char *)&ehost_ip, IP_ADRSIZ);
/* Target hdw addr and IP addr (for politeness?) */
ea_set(arp.arp_tha, eap); /* Target hdw addr */
memcpy((char *)arp.arp_tpa, iap, IP_ADRSIZ);
ea_set(arp.arp.arp_tha, eap); /* Target hdw addr */
memcpy((char *)arp.arp.arp_tpa, iap, IP_ADRSIZ);
/* Now send it! */
if (swstatus) {
char ipbuf[OSN_IPSTRSIZ];
dbprintln("ARP reply sent to %s",
ip_adrsprint(ipbuf, iap));
char eabuf[OSN_EASTRSIZ];
char ipbuf2[OSN_IPSTRSIZ];
char eabuf2[OSN_EASTRSIZ];
dbprintln("ARP reply sent to %s %s (%s %s)",
ip_adrsprint(ipbuf, iap),
eth_adrsprint(eabuf2, (unsigned char *)&arp.arp.arp_tha),
ip_adrsprint(ipbuf2, (unsigned char *)&arp.arp.arp_spa),
eth_adrsprint(eabuf, (unsigned char *)&arp.arp.arp_sha));
}
ether_write(&eh, (unsigned char *)&arp, sizeof(arp));
ether_write(&eh, (unsigned char *)&arp.arp, sizeof(arp.arp));
}
#endif /* !KLH10_NET_TUN */
@ -1527,7 +1544,7 @@ imptohost(register struct dpimp_s *dpimp)
if (DBGFLG)
fprintf(stderr, "[dpimp-R: sent INIT]\r\n");
#if (KLH10_NET_NIT || KLH10_NET_DLPI || KLH10_NET_PFLT || \
#if (KLH10_NET_PCAP || KLH10_NET_NIT || KLH10_NET_DLPI || KLH10_NET_PFLT || \
KLH10_NET_TUN || KLH10_NET_LNX)
for (;;) {
/* Make sure that buffer is free before clobbering it */
@ -1545,7 +1562,11 @@ imptohost(register struct dpimp_s *dpimp)
#endif
/* OK, now do a blocking read on packetfilter input! */
cnt = read(pffd, buffp, MAXETHERLEN);
#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
@ -1567,17 +1588,17 @@ imptohost(register struct dpimp_s *dpimp)
if (errno == EINTR) /* Ignore spurious signals */
continue;
#if CENV_SYS_NETBSD
#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 == EWOULDBLOCK) {
if (errno == EAGAIN || errno == EWOULDBLOCK) {
int ptimeout = (dpimp->dpimp_rdtmo ? dpimp->dpimp_rdtmo : 1);
struct pollfd myfd;
myfd.fd = pffd;
myfd.fd = pfdata.pf_fd;
myfd.events = POLLIN;
(void) poll(&myfd, 1, ptimeout*1000);
continue;
@ -1608,7 +1629,6 @@ imptohost(register struct dpimp_s *dpimp)
#endif /* KLH10_NET_LNX */
#if !KLH10_NET_TUN
#if 1
/* Verify that pf filtering is doing its job */
switch (eh_tget((struct eth_header *)buffp)) {
case ETHERTYPE_IP:
@ -1621,7 +1641,6 @@ imptohost(register struct dpimp_s *dpimp)
eh_tget((struct eth_header *)buffp));
continue;
}
#endif
#endif /* !KLH10_NET_TUN */
/* OK, it claims to be an IP packet, see if so long that we
@ -1655,7 +1674,7 @@ imptohost(register struct dpimp_s *dpimp)
buffp = inibuf + DPIMP_DATAOFFSET;
if ((cnt = read(pffd, buffp, OSN_BPF_MTU)) < 0) {
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");
@ -1879,7 +1898,7 @@ hosttoimp(register struct dpimp_s *dpimp)
#if KLH10_NET_TUN
if (DBGFLG)
dbprintln("net out = %d", rcnt - (SIH_HSIZ+SI_LDRSIZ));
if (write(pffd, &buff[SIH_HSIZ+SI_LDRSIZ],
if (osn_pfwrite(&pfdata, &buff[SIH_HSIZ+SI_LDRSIZ],
rcnt - (SIH_HSIZ+SI_LDRSIZ)) < 0)
syserr(errno, "tun write() failed");
else {
@ -2012,13 +2031,32 @@ ip_write(struct in_addr *ipa, unsigned char *buf, int len)
ether_write(&eh, buf, len);
}
/*
* Write an ethernet frame, consisting of the header and the
* data. They are supplied separately but sent together.
*
* It is assumed there is space before the payload data to put
* a copy of the header!
*/
void
ether_write(register struct eth_header *hp,
register unsigned char *pp,
register int cnt)
{
#if KLH10_NET_NIT
#if KLH10_NET_PCAP || KLH10_NET_TAP_BRIDGE
char *buf = (char *)(pp - ETHER_HDRSIZ);
if (DP_DBGFLG)
dbprintln("net out = %d", cnt);
memcpy(buf, (char *)hp, ETHER_HDRSIZ);
if (osn_pfwrite(&pfdata, 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_NIT
struct strbuf ctl, dat;
struct sockaddr sa;
@ -2047,7 +2085,7 @@ ether_write(register struct eth_header *hp,
if (DP_DBGFLG)
dbprintln("net out = %d", cnt);
if (putmsg(pffd, &ctl, &dat, 0) < 0) {
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));
}
@ -2069,7 +2107,7 @@ ether_write(register struct eth_header *hp,
if (DP_DBGFLG)
dbprintln("net out = %d", cnt);
if (putmsg(pffd, NULL, &dat, 0) < 0) {
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));
}
@ -2090,7 +2128,7 @@ ether_write(register struct eth_header *hp,
if (DP_DBGFLG)
dbprintln("net out = %d", cnt);
if (write(pffd, buf, (size_t)(cnt + ETHER_HDRSIZ)) < 0) {
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));
}
@ -2106,7 +2144,7 @@ ether_write(register struct eth_header *hp,
if (DP_DBGFLG)
dbprintln("net out = %d", cnt);
if (writev(pffd, iov, sizeof(iov)/sizeof(*iov)) < 0) {
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));
}

View File

@ -174,7 +174,7 @@ The following general situations are possible:
int chpid; /* PID of child, handles input (net-to-10). */
int swstatus = TRUE;
int pffd; /* Packet-Filter FD (bidirectional) */
struct pfdata pfdata; /* Packet-Filter state */
struct dp_s dp; /* Device-Process struct for DP ops */
struct in_addr ehost_ip; /* Emulated host IP addr, net order */
@ -413,7 +413,8 @@ main(int argc, char **argv)
** monitor can do it).
*/
if (dpni->dpni_doarp & (DPNI_ARPF_PUBL|DPNI_ARPF_PERM)) {
if (!osn_arp_stuff(&dpni->dpni_ip[0], /* Set up fake IP addr */
if (!osn_arp_stuff(dpni->dpni_ifnam, /* interface name */
&dpni->dpni_ip[0], /* Set up fake IP addr */
&dpni->dpni_eth[0], /* mapped to this ether addr */
(dpni->dpni_doarp & DPNI_ARPF_PUBL))) /* Publicized if nec */
esfatal(1, "ARP_STUFF failed");
@ -517,7 +518,7 @@ void net_init(register struct dpni20_s *dpni)
the packetfilter open may use and/or change it.
*/
ea_set(&npf.osnpf_ea, dpni->dpni_eth); /* Set requested ea if any */
pffd = osn_pfinit(&npf, (void *)dpni); /* Will abort if fails */
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 */
@ -798,7 +799,7 @@ pfeabuild(void *arg, unsigned char *ea)
/* BPF packetfilter initialization */
#if KLH10_NET_BPF
#if KLH10_NET_PCAP || KLH10_NET_BPF
/*
** BPF filter program stuff.
@ -1023,8 +1024,6 @@ pfshow(struct OSN_PFSTRUCT *pf)
/* LNX packetfilter initialization */
#if KLH10_NET_LNX || KLH10_NET_TAP_BRIDGE
/*
The Linux PF_PACKET interface is described to some extent
by the packet(7) man page.
@ -1111,7 +1110,6 @@ int lnx_filter(register struct dpni20_s *dpni,
return FALSE;
}
#endif /* KLH10_NET_LNX */
/* ETH_SETADR - Attempt to set physical ethernet address to dpni_rqeth.
@ -1120,7 +1118,7 @@ int lnx_filter(register struct dpni20_s *dpni,
void eth_adrset(register struct dpni20_s *dpni)
{
#if OSN_USE_IPONLY
dbprintln("\"%s\" multicast table ignored - IP-only interface",
dbprintln("\"%s\" ethernet address change ignored - IP-only interface",
dpni->dpni_ifnam);
#else
unsigned char rdea[ETHER_ADRSIZ];
@ -1175,7 +1173,7 @@ void eth_adrset(register struct dpni20_s *dpni)
/* Apparently won! Try reading it back just to be paranoid,
* using packetfilter FD.
*/
if (!osn_pfeaget(pffd, dpni->dpni_ifnam, rdea)) {
if (!osn_pfeaget(pfdata.pf_fd, dpni->dpni_ifnam, rdea)) {
error("Can't read \"%s\" e/n addr!", dpni->dpni_ifnam);
/* Proceed as if set won, sigh */
} else {
@ -1407,13 +1405,13 @@ int arp_myreply(register unsigned char *buf, register int cnt)
struct strbuf data;
data.buf = (char *)pktbuf;
data.len = sizeof(pktbuf);
(void) putmsg(pffd, NULL, &data, 0);
(void) putmsg(pfdata.pf_fd, NULL, &data, 0);
}
#else
/* XXX
* Why is this sent to the packet filter (= host) and not to the -10?????
*/
(void)write(pffd, pktbuf, sizeof(pktbuf));
(void)write(pfdata.pf_fd, pktbuf, sizeof(pktbuf));
#endif
return TRUE;
}
@ -1470,7 +1468,9 @@ void ethtoten(register struct dpni20_s *dpni)
dbprintln("InWait");
/* OK, now do a blocking read on packetfilter input! */
#if KLH10_NET_DLPI
#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;
@ -1478,15 +1478,15 @@ void ethtoten(register struct dpni20_s *dpni)
data.buf = (char *)buff;
data.maxlen = max;
data.len = 0;
if ((cnt = getmsg(pffd, (struct strbuf *)NULL, &data, &flagsp)) == 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(pffd, tbuff, tmax);
cnt = read(pfdata.pf_fd, tbuff, tmax);
#else
cnt = read(pffd, buff, max);
#endif
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,17 +1505,17 @@ void ethtoten(register struct dpni20_s *dpni)
if (errno == EINTR) /* Ignore spurious signals */
continue;
#if CENV_SYS_NETBSD
#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 == EWOULDBLOCK) {
if (errno == EAGAIN || errno == EWOULDBLOCK) {
int ptimeout = (dpni->dpni_rdtmo ? dpni->dpni_rdtmo : 1);
struct pollfd myfd;
myfd.fd = pffd;
myfd.fd = pfdata.pf_fd;
myfd.events = POLLIN;
(void) poll(&myfd, 1, ptimeout*1000);
continue;
@ -1540,11 +1540,11 @@ void ethtoten(register struct dpni20_s *dpni)
else
dbprint("Read=%d", cnt);
}
#if KLH10_NET_LNX || KLH10_NET_TAP_BRIDGE
/* Linux has no packet filtering, thus must apply manual check to
each and every packet read, unless dedicated. Ugh!
*/
if (KLH10_NET_TAP_BRIDGE || !dpni->dpni_dedic) {
if (!pfdata.pf_can_filter && !dpni->dpni_dedic) {
/* Sharing interface. Check for IP, DECNET, 802.3 */
if (!lnx_filter(dpni, buff, cnt)) {
if (DBGFLG)
@ -1552,7 +1552,7 @@ void ethtoten(register struct dpni20_s *dpni)
continue; /* Drop packet, continue reading */
}
}
#endif /* KLH10_NET_LNX */
#if !KLH10_NET_BPF
#if 0
if (DBGFLG)
@ -1677,16 +1677,18 @@ 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_DLPI
#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(pffd, NULL, &data, 0)) == 0)
if ((cnt = putmsg(pfdata.pf_fd, NULL, &data, 0)) == 0)
cnt = rcnt; /* Assume successful */
}
#else
cnt = write(pffd, buff, rcnt);
cnt = write(pfdata.pf_fd, buff, rcnt);
#endif /* else KLH10_NET_DLPI */
if (cnt != rcnt) {
if ((cnt < 0) && (errno == EINTR)) {

View File

@ -225,7 +225,7 @@ lhdh_conf(FILE *f, char *s, struct lhdh *lh)
lh->lh_backlog = 0;
lh->lh_dedic = FALSE;
lh->lh_doarp = TRUE;
lh->lh_rdtmo = 1; /* Default to 1 sec timeout check */
lh->lh_rdtmo = 60; /* Default to 60 sec timeout check */
lh->lh_dpidly = 0;
lh->lh_dpdbg = FALSE;
#if KLH10_DEV_DPIMP

View File

@ -418,8 +418,8 @@ static int pareth(char *cp, unsigned char *adr)
/* Include OSDNET code, faking out unneeded packetfilter inits
* XXX: clean this up in future OSDNET.
*/
struct fakepf { int foo; };
#define OSN_PFSTRUCT fakepf
#define OSN_PFSTRUCT bpf_program
struct OSN_PFSTRUCT *
pfbuild(void *arg, struct in_addr *ipa)

View File

@ -1346,8 +1346,8 @@ tim_init(void)
os_rtmget(&cpu.tim.osbase);
return FALSE;
}
fread((char *)&cpu.tim.wrbase, sizeof(cpu.tim.wrbase), 1, f);
fread((char *)&cpu.tim.osbase, sizeof(cpu.tim.osbase), 1, f);
(void)fread((char *)&cpu.tim.wrbase, sizeof(cpu.tim.wrbase), 1, f);
(void)fread((char *)&cpu.tim.osbase, sizeof(cpu.tim.osbase), 1, f);
os_rtm_adjust_base(&cpu.tim.osbase, &cpu.tim.osbase, 0);
if (ferror(f)) {
fclose(f);

View File

@ -50,7 +50,7 @@ int
osn_ifsock(char *ifnam, ossock_t *as)
{
#if (KLH10_NET_NIT || KLH10_NET_DLPI || KLH10_NET_BPF || KLH10_NET_PFLT || \
KLH10_NET_TUN || KLH10_NET_LNX || KLH10_NET_TAP_BRIDGE)
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
@ -61,7 +61,7 @@ int
osn_ifclose(ossock_t s)
{
#if (KLH10_NET_NIT || KLH10_NET_DLPI || KLH10_NET_BPF || KLH10_NET_PFLT || \
KLH10_NET_TUN || KLH10_NET_LNX || KLH10_NET_TAP_BRIDGE)
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
@ -236,7 +236,7 @@ osn_nifents(void)
static struct ifent *
osn_iftab_addaddress(char *name, struct sockaddr *addr)
{
struct ifent *ife, *ifet;
struct ifent *ife;
int i;
int idx;
@ -258,21 +258,21 @@ osn_iftab_addaddress(char *name, struct sockaddr *addr)
iftab[idx].ife_name[IFNAMSIZ] = '\0';
}
ifet = &iftab[idx];
ife = &iftab[idx];
switch (addr->sa_family) {
case AF_INET: {
struct sockaddr_in *sin = (struct sockaddr_in *)addr;
ifet->ife_ipia = sin->sin_addr;
ifet->ife_gotip4 = TRUE;
ife->ife_ipia = sin->sin_addr;
ife->ife_gotip4 = TRUE;
break;
}
#if defined(AF_LINK)
case AF_LINK: {
struct sockaddr_dl *sdl = (struct sockaddr_dl *)addr;
if (sdl->sdl_type == IFT_ETHER && sdl->sdl_alen == ETHER_ADRSIZ) {
ea_set(ifet->ife_ea, LLADDR(sdl));
ifet->ife_gotea = TRUE;
ea_set(ife->ife_ea, LLADDR(sdl));
ife->ife_gotea = TRUE;
}
}
#endif /* AF_LINK*/
@ -280,12 +280,14 @@ osn_iftab_addaddress(char *name, struct sockaddr *addr)
case AF_PACKET: {
struct sockaddr_ll *sll = (struct sockaddr_ll *)addr;
if (sll->sll_hatype == ARPHRD_ETHER && sll->sll_halen == ETHER_ADRSIZ) {
ea_set(ifet->ife_ea, &sll->sll_addr);
ifet->ife_gotea = TRUE;
ea_set(ife->ife_ea, &sll->sll_addr);
ife->ife_gotea = TRUE;
}
}
#endif /* AF_PACKET*/
}
return ife;
}
void
@ -309,6 +311,12 @@ osn_iftab_show(FILE *f, struct ifent *ifents, int nents)
"Extracted ",
ucp[0], ucp[1], ucp[2], ucp[3], ucp[4], ucp[5]);
}
if (ife->ife_flags & IFF_UP) {
fprintf(f, " UP");
}
if (ife->ife_flags & IFF_LOOPBACK) {
fprintf(f, " LOOPBACK");
}
fprintf(f, "\r\n");
}
}
@ -371,6 +379,21 @@ osn_iflookup(char *ifnam)
return NULL;
}
/* OSN_IFCREATE - Create or find an interface entry in our table.
*/
struct ifent *
osn_ifcreate(char *ifnam)
{
struct ifent *ife = osn_iflookup(ifnam);
if (!ife && iftab_nifs < NETIFC_MAX) {
ife = &iftab[iftab_nifs];
iftab_nifs++;
}
return ife;
}
/* OSN_IFEALOOKUP - Find ethernet address, barf if neither in our table nor
* available via OS.
*/
@ -399,11 +422,60 @@ osn_ifealookup(char *ifnam, /* Interface name */
** setting rather than (eg) failing.
*/
int
osn_arp_stuff(unsigned char *ipa, unsigned char *eap, int pubf)
osn_arp_stuff(char *ifname, unsigned char *ipa, unsigned char *eap, int pubf)
{
char ipbuf[OSN_IPSTRSIZ];
char eabuf[OSN_EASTRSIZ];
if (DP_DBGFLG) {
dbprintln("Set up ARP: %s %s %s",
ip_adrsprint(ipbuf, ipa),
eth_adrsprint(eabuf, eap),
(pubf ? "pub" : ""));
}
#if CENV_SYS_LINUX
/**
* 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...
*/
int fd;
#if 0
char devproc[64];
snprintf(devproc, sizeof(devproc)-1, "/proc/sys/net/ipv4/conf/%s/proxy_arp", ifname);
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
/**
* 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
* ITS from elsewhere on the network.
* MAYBE also for plain proxy ARP...
*
* Or sysctl -w net.ipv4.ip_forward=1
*/
fd = open("/proc/sys/net/ipv4/ip_forward", O_WRONLY|O_TRUNC);
if (fd >= 0) {
(void)write(fd, "1\n", 2);
close(fd);
dbprintln("Enabled net.ipv4.ip_forward");
}
#endif /* CENV_SYS_LINUX */
#if NETIF_HAS_ARPIOCTL
struct arpreq arq;
int sock;
@ -652,7 +724,7 @@ static struct eth_addr emhost_ea = /* Emulated host ether addr for tap */
*/
int
osn_pfeaget(int pfs, /* Packetfilter socket or FD */
char *ifnam, /* Interface name (sometimes needed) */
char *ifnam, /* Interface name (sometimes needed) */
unsigned char *eap) /* Where to write ether address */
{
@ -1064,6 +1136,188 @@ osn_ifmcset(int s,
* very OSD.
* FD is always opened for both read/write.
*/
#if KLH10_NET_PCAP
void
osn_pfinit(struct pfdata *pfdata, struct osnpf *osnpf, void *pfarg)
{
char errbuf[PCAP_ERRBUF_SIZE];
char *what = "";
pcap_t *pc;
char *ifnam = osnpf->osnpf_ifnam;
if (DP_DBGFLG)
dbprint("Opening PCAP device");
if (!ifnam || !ifnam[0]) { /* Allow default ifc */
struct ifent *ife = osn_ipdefault();
if (!ife)
esfatal(1, "Ethernet interface must be specified");
ifnam = ife->ife_name;
}
pfdata->pf_handle = pc = pcap_create(ifnam, errbuf);
pfdata->pf_ip4_only = FALSE;
if (!pc) {
what = "pcap_create";
goto error;
}
if (pcap_set_snaplen(pc, ETHER_MTU + 100) < 0) { /* fuzz */
what = "pcap_set_snaplen";
goto error;
}
/* 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 [[ note: I see EAGAIN]] 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 read loops in osn_pfread() below for workaround.
*/
if (pcap_set_immediate_mode(pc, 1) < 0) {
what = "pcap_set_immediate_mode";
goto error;
}
/* Set read timeout.
Safety check in order to avoid infinite hangs if something
wedges up. The periodic re-check overhead is insignificant.
*/
if (osnpf->osnpf_rdtmo) {
if (pcap_set_timeout(pc, osnpf->osnpf_rdtmo * 1000) < 0) {
syserr(1, "pcap_set_timeout failed");
}
}
if (pcap_activate(pc) < 0) {
what = "pcap_activate";
goto error;
}
/* 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(pfarg, &(osnpf->osnpf_ip.ia_addr));
if (pcap_setfilter(pc, pf) < 0) {
syserr(1, "pcap_setfilter failed");
}
pfdata->pf_can_filter = TRUE;
} else {
pfdata->pf_can_filter = FALSE;
}
if (pcap_setdirection(pc, PCAP_D_INOUT) < 0) {
what = "pcap_setdirection";
goto error;
}
if (pcap_set_datalink(pc, DLT_EN10MB) < 0) {
what = "pcap_set_datalink";
goto error;
}
pfdata->pf_fd = pcap_get_selectable_fd(pc);
/* 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(pfdata->pf_fd, ifnam, (unsigned char *)&(osnpf->osnpf_ea));
(void) osn_ifealookup(ifnam, (unsigned char *) &osnpf->osnpf_ea);
return;
error:
if (pc) {
syserr(1, "pcap_geterr: %s", pcap_geterr(pc));
pcap_close(pc);
}
esfatal(1, "pcap error for %s, %s: %s", ifnam, what, errbuf);
/* not reached */
}
#if CENV_SYS_NETBSD
#include <poll.h> /* For NetBSD mainly */
#endif
/*
* Like the standard read(2) call:
* Receives a single packet and returns its size.
* Include link-layer headers, but no BPF headers or anything like that.
*/
inline
ssize_t
osn_pfread(struct pfdata *pfdata, void *buf, size_t nbytes)
{
struct pcap_pkthdr pkt_header;
const u_char *pkt_data;
tryagain:
errno = 0;
pkt_data = pcap_next(pfdata->pf_handle, &pkt_header);
if (pkt_data) {
if (pkt_header.caplen < nbytes)
nbytes = pkt_header.caplen;
memcpy(buf, pkt_data, nbytes);
if (DP_DBGFLG)
dbprint("osn_pfread: read %d bytes", nbytes);
return nbytes;
}
#if 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 10 sec, will wake up sooner if
input arrives.
*/
if (errno == EAGAIN || errno == EWOULDBLOCK) {
int ptimeout = 10;
struct pollfd myfd;
int err = errno;
if (DP_DBGFLG)
dbprint("osn_pfread: polling after reading nothing (err=%d)", err);
myfd.fd = pfdata->pf_fd;
myfd.events = POLLIN;
(void) poll(&myfd, 1, ptimeout * 1000);
goto tryagain;
}
#endif
/* From pcap_next_ex(3): "Unfortunately, there is no way to determine
* whether an error occurred or not."
*/
return 0;
}
/*
* Like the standard write(2) call:
* Expect a full ethernet frame including link-layer header.
* returns the number of bytes written.
*/
inline
int
osn_pfwrite(struct pfdata *pfdata, const void *buf, size_t nbytes)
{
//if (DP_DBGFLG)
// dbprint("osn_pfwrite: writing %d bytes", nbytes);
return pcap_inject(pfdata->pf_handle, buf, nbytes);
}
#endif
#if KLH10_NET_PFLT || KLH10_NET_BPF
@ -1223,6 +1477,9 @@ osn_pfinit(struct osnpf *osnpf, void *arg)
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");
@ -1260,15 +1517,15 @@ osn_pfinit(struct osnpf *osnpf, void *arg)
#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(__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");
// error("trying BIOCSFEEDBACK");
// errno = 0;
// i = 1;
// if (ioctl(fd, BIOCSFEEDBACK, (char *) &i) < 0)
// syserr(errno, "BIOCSFEEDBACK failed");
#endif
/* Set the read() buffer size.
@ -1394,19 +1651,19 @@ The ifra_mask field is ignored (left as-is or zeroed if new) unless
*/
int
osn_pfinit(struct osnpf *osnpf, void *arg)
void
osn_pfinit(struct pfdata *pfdata, struct osnpf *osnpf, void *arg)
{
int allowextern = TRUE; /* For now, always try for external access */
int fd;
#if CENV_SYS_LINUX /* [BV: tun support for Linux] */
struct ifreq ifr;
char ifnam[IFNAMSIZ];
#else
#else /* not CENV_SYS_LINUX */
char tunname[sizeof "/dev/tun000"];
char *ifnam = tunname + sizeof("/dev/")-1;
int i = -1;
#endif
#endif /* CENV_SYS_LINUX */
char ipb1[OSN_IPSTRSIZ];
char ipb2[OSN_IPSTRSIZ];
struct ifent *ife = NULL; /* Native host's default IP interface if one */
@ -1418,6 +1675,9 @@ osn_pfinit(struct osnpf *osnpf, void *arg)
ipremote = osnpf->osnpf_ip.ia_addr;
iplocal = osnpf->osnpf_tun.ia_addr;
if (DP_DBGFLG)
dbprint("Opening TUN device");
/* Local address can be set explicitly if we plan to do full IP
masquerading. */
if (memcmp((char *)&iplocal, "\0\0\0\0", IP_ADRSIZ) == 0) {
@ -1440,28 +1700,25 @@ osn_pfinit(struct osnpf *osnpf, void *arg)
osnpf->osnpf_tun.ia_addr = iplocal;
}
if (DP_DBGFLG)
dbprint("Opening TUN device");
#if CENV_SYS_LINUX /* [BV: Linux way] */
if ((fd = open("/dev/net/tun", O_RDWR)) < 0) /* get a fresh device */
esfatal(0, "Couldn't open tunnel device /dev/net/tun");
memset(&ifr, 0, sizeof(ifr));
#if OSN_USE_IPONLY
# if OSN_USE_IPONLY
ifr.ifr_flags = IFF_TUN | IFF_NO_PI; /* TUN (no Ethernet headers), no pkt info */
#else
# else
ifr.ifr_flags = IFF_TAP | IFF_NO_PI; /* TAP (yes Ethernet headers), no pkt info */
#endif
# endif
if (ioctl(fd, TUNSETIFF, (void *) &ifr) < 0) /* turn it on */
esfatal(0, "Couldn't set tun device");
strcpy(ifnam, ifr.ifr_name); /* get device name (typically "tun0") */
#else /* not CENV_SYS_LINUX */
do {
#if OSN_USE_IPONLY
# if OSN_USE_IPONLY
sprintf(tunname, "/dev/tun%d", ++i);
#else
# else
sprintf(tunname, "/dev/tap%d", ++i);
#endif /* not CENV_SYS_LINUX */
# endif /* not CENV_SYS_LINUX */
} while ((fd = open(tunname, O_RDWR)) < 0 && errno == EBUSY);
if (fd < 0)
@ -1595,7 +1852,7 @@ osn_pfinit(struct osnpf *osnpf, void *arg)
publish an ARP entry mapping the virtual host to the same
ether addr.
*/
(void) osn_arp_stuff((unsigned char *)&ipremote, ife->ife_ea, TRUE);
(void) osn_arp_stuff(ifnam, (unsigned char *)&ipremote, ife->ife_ea, TRUE);
/* Return that as our ether address */
ea_set((char *)&osnpf->osnpf_ea, ife->ife_ea);
@ -1615,10 +1872,13 @@ osn_pfinit(struct osnpf *osnpf, void *arg)
#endif
}
pfdata->pf_fd = fd;
pfdata->pf_handle = 0;
pfdata->pf_can_filter = FALSE;
pfdata->pf_ip4_only = OSN_USE_IPONLY;
if (DP_DBGFLG)
dbprintln("osn_pfinit tun completed");
return fd;
}
#endif /* KLH10_NET_TUN */
@ -1771,11 +2031,15 @@ osn_pfdeinit(void)
#if KLH10_NET_TAP_BRIDGE
osn_pfinit(struct osnpf *osnpf, void *arg)
void
osn_pfinit(struct pfdata *pfdata, struct osnpf *osnpf, void *arg)
{
int fd;
char *ifnam = osnpf->osnpf_ifnam;
if (DP_DBGFLG)
dbprint("Opening TAP+BRIDGE device");
/* No "default interface" concept here */
if (!ifnam || !ifnam[0])
esfatal(1, "Packetfilter interface must be specified");
@ -1786,9 +2050,51 @@ osn_pfinit(struct osnpf *osnpf, void *arg)
*/
(void) osn_pfeaget(fd, ifnam, (unsigned char *)&(osnpf->osnpf_ea));
return fd;
struct ifent *ife = osn_ifcreate(ifnam);
if (ife) {
ife->ife_flags = IFF_UP;
ea_set(ife->ife_ea, (unsigned char *)&osnpf->osnpf_ea);
ife->ife_gotea = TRUE;
}
pfdata->pf_fd = fd;
pfdata->pf_handle = 0;
pfdata->pf_ip4_only = FALSE;
pfdata->pf_can_filter = FALSE;
}
#endif /* KLH10_NET_TAP_BRIDGE */
#if KLH10_NET_TAP_BRIDGE || KLH10_NET_TUN
/*
* Like the standard read(2) call:
* Receives a single packet and returns its size.
* Include link-layer headers, but no BPF headers or anything like that.
*/
inline
ssize_t
osn_pfread(struct pfdata *pfdata, void *buf, size_t nbytes)
{
return read(pfdata->pf_fd, buf, nbytes);
}
/*
* Like the standard write(2) call:
* Expect a full ethernet frame including link-layer header.
* returns the number of bytes written.
*/
inline
int
osn_pfwrite(struct pfdata *pfdata, const void *buf, size_t nbytes)
{
return write(pfdata->pf_fd, buf, nbytes);
}
#endif /* KLH10_NET_TAP_BRIDGE || KLH10_NET_TUN */
#if KLH10_NET_TAP_BRIDGE
#include <net/if_tap.h>
#include <net/if_bridgevar.h>
#include <stdint.h>

View File

@ -68,18 +68,20 @@
#ifndef KLH10_NET_LNX /* Linux PF_PACKET interface */
# define KLH10_NET_LNX 0
#endif
#ifndef KLH10_NET_PCAP /* pretty generic libpcap interface */
# define KLH10_NET_PCAP 0
#endif
#if !(KLH10_NET_NIT || KLH10_NET_DLPI || KLH10_NET_BPF || KLH10_NET_PFLT || \
KLH10_NET_TUN || KLH10_NET_LNX || KLH10_NET_TAP_BRIDGE)
KLH10_NET_LNX || KLH10_NET_PCAP || KLH10_NET_TUN || KLH10_NET_TAP_BRIDGE)
/* None explicitly specified, pick a reasonable default */
# if ((CENV_SYS_NETBSD || CENV_SYS_FREEBSD || CENV_SYS_LINUX) && OSN_USE_IPONLY)
# undef KLH10_NET_TUN
# define KLH10_NET_TUN 1
# elif 0
# undef KLH10_NET_PCAP
# define KLH10_NET_PCAP 1
# elif (CENV_SYS_NETBSD || CENV_SYS_FREEBSD)
/*
* # undef KLH10_NET_BPF
* # define KLH10_NET_BPF 1
*/
# undef KLH10_NET_TAP_BRIDGE
# define KLH10_NET_TAP_BRIDGE 1
# elif CENV_SYS_DECOSF
@ -263,10 +265,12 @@
#define HAVE_LIBPCAP 1 /* assume this for now */
#if HAVE_LIBPCAP
#include <pcap/pcap.h>
# define USE_LIBPCAP 1
# include <pcap/pcap.h>
# include <pcap/bpf.h>
#endif
#if HAVE_GETIFADDRS
#include <ifaddrs.h>
# include <ifaddrs.h>
#endif
#if !HAVE_LIBPCAP && !HAVE_GETIFADDRS
@ -379,6 +383,17 @@ union ipaddr {
unsigned char ia_octet[IP_ADRSIZ];
struct in_addr ia_addr;
};
/*
* A structure that aggregates information about the packet filter variant
* which is in use.
*/
struct pfdata {
int pf_fd; /* most but not all have a file descriptor */
void *pf_handle; /* pcap has a handle */
int pf_can_filter; /* has a packet filter built-in and enabled */
int pf_ip4_only; /* set TRUE for IP i/f; FALSE for ethernet i/f */
};
int osn_iftab_init(void);
int osn_nifents(void); /* # of entries cached by osn_iftab_init */
@ -400,6 +415,7 @@ struct ifent *osn_ipdefault(void);
struct ifent *osn_iftab_arp(struct in_addr ia);
int osn_iftab_arpget(struct in_addr ia, unsigned char *eap);
struct ifent *osn_ifcreate(char *ifnam);
int osn_ifealookup(char *ifnam, unsigned char *eap);
#define OSN_EASTRSIZ sizeof("xx:xx:xx:xx:xx:xxZZ")
@ -408,7 +424,7 @@ char *eth_adrsprint(char *cp, unsigned char *ea);
#define OSN_IPSTRSIZ sizeof("ddd.ddd.ddd.dddZZZZ")
char *ip_adrsprint(char *cp, unsigned char *ip);
int osn_arp_stuff(unsigned char *ipa, unsigned char *eap, int pubf);
int osn_arp_stuff(char *ifname, unsigned char *ipa, unsigned char *eap, int pubf);
int osn_arp_look(struct in_addr *ipa, unsigned char *eap);
struct osnpf { /* Arg struct for common initialization params */
@ -420,7 +436,11 @@ struct osnpf { /* Arg struct for common initialization params */
union ipaddr osnpf_tun; /* INOUT: IP address of tunnel */
struct ether_addr osnpf_ea; /* OUT: ether address of ifc */
};
int osn_pfinit(struct osnpf *, void *);
/* the void * is an argument to pass on to pfbuild() */
void osn_pfinit(struct pfdata *, struct osnpf *, void *);
void osn_pfdeinit(void);
ssize_t osn_pfread(struct pfdata *pfdata, void *buf, size_t nbytes);
int osn_pfwrite(struct pfdata *pfdata, const void *buf, size_t nbytes);
#endif /* ifndef OSDNET_INCLUDED */