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

Implement dedicated interface (for Linux)

The new stuff in osdnet seems to have made it impossible(?) to use
dedicated interfaces, since the only options are tun/tap/pcap but no
"raw access". This branch takes code from the Panda KLH10_NET_LNX case
which makes that easily possible again.
This commit is contained in:
Björn Victor 2018-02-18 15:25:02 +01:00 committed by Lars Brinkhoff
parent fcf812e4d7
commit 20b3f73717
3 changed files with 119 additions and 0 deletions

View File

@ -54,6 +54,22 @@ case "${enable_lights}" in
*) AC_MSG_ERROR([bad value ${enable_lights} for --enable-lights]) ;;
esac
# -------------------------------------------------------------------------
# Check whether we want LNX support
# -------------------------------------------------------------------------
AC_ARG_ENABLE(lnx,
AS_HELP_STRING([--enable-lnx],[enable lnx networking (default on) when it cannot be found]))
case "${with_lnx}" in
yes | "")
AC_DEFINE(KLH10_NET_LNX, 1, [Set to 0 to enable LNX networking])
AC_MSG_NOTICE([Compiling with LNX support]) ;;
no) AC_DEFINE(KLH10_NET_LNX, 0, [Set to 0 to disable LNX networking])
AC_MSG_NOTICE([Compiling without LNX support]) ;;
*) AC_MSG_ERROR([bad value ${enable_lnx} for --enable-lnx]) ;;
esac
# -------------------------------------------------------------------------
# Check whether we want VDE support
# -------------------------------------------------------------------------

View File

@ -52,6 +52,9 @@
struct ifent *osn_iflookup(char *ifnam);
static struct ifent *osn_iftab_addaddress(char *name, struct sockaddr *addr, struct sockaddr *mask);
#if KLH10_NET_LNX
static void osn_pfinit_lnx(struct pfdata *pfdata, struct osnpf *osnpf, void *pfarg);
#endif /* KLH10_NET_LNX */
#if KLH10_NET_PCAP
static void osn_pfinit_pcap(struct pfdata *pfdata, struct osnpf *osnpf, void *pfarg);
static ssize_t osn_pfread_pcap(struct pfdata *pfdata, void *buf, size_t nbytes);
@ -101,6 +104,9 @@ char osn_networking[] =
#endif
#if KLH10_NET_VDE
" vde"
#endif
#if KLH10_NET_LNX
" lnx"
#endif
;
@ -1412,6 +1418,12 @@ osn_pfinit(struct pfdata *pfdata, struct osnpf *osnpf, void *pfarg)
return osn_pfinit_vde(pfdata, osnpf, pfarg);
}
#endif /* KLH10_NET_VDE */
#if KLH10_NET_LNX
if (!method[0] || !strcmp(method, "lnx")) {
pfdata->pf_meth = PF_METH_LNX;
return osn_pfinit_lnx(pfdata, osnpf, pfarg);
}
#endif /* KLH10_NET_LNX */
esfatal(1, "Interface method \"%s\" not supported (only%s)",
method, osn_networking);
@ -1436,6 +1448,96 @@ osn_pfdeinit(struct pfdata *pfdata, struct osnpf *osnpf)
pfdata->pf_deinit(pfdata, osnpf);
}
#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.
*/
void
osn_pfinit_lnx(struct pfdata *pfdata, struct osnpf *osnpf, void *pfarg)
{
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");
if (!osnpf->osnpf_dedic) {
esfatal(1,"LNX ifmethod only works for dedicated interfaces");
}
/* 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]);
pfdata->pf_meth = PF_METH_LNX;
pfdata->pf_read = osn_pfread_fd;
pfdata->pf_write = osn_pfwrite_fd;
pfdata->pf_deinit = NULL;
pfdata->pf_handle = NULL;
pfdata->pf_can_filter = 0;
pfdata->pf_fd=fd;
return;
}
#endif /* KLH10_NET_LNX */
#if KLH10_NET_PCAP
static
void

View File

@ -309,6 +309,7 @@ struct pfdata {
#define PF_METH_TUN 2
#define PF_METH_TAP 3
#define PF_METH_VDE 4
#define PF_METH_LNX 5
int osn_iftab_init(void);
int osn_nifents(void); /* # of entries cached by osn_iftab_init */