From 5f976476ede1eb18e8d4ddd367d76c2a83b461a8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Victor?= Date: Sun, 18 Feb 2018 15:25:02 +0100 Subject: [PATCH] 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. --- configure.ac | 20 +++++++++- src/osdnet.c | 102 +++++++++++++++++++++++++++++++++++++++++++++++++++ src/osdnet.h | 1 + 3 files changed, 121 insertions(+), 2 deletions(-) diff --git a/configure.ac b/configure.ac index 0624b9f..f0c0283 100644 --- a/configure.ac +++ b/configure.ac @@ -5,8 +5,8 @@ dnl This configure.ac script was created for Autoconf 2.69, but I dnl tried it with one as old as 2.61, and that seemed to work fine. AC_PREREQ([2.69]) -AC_INIT([klh10], [2.0k-Rhialto], [https://github.com/Rhialto/klh10], - [], [https://github.com/Rhialto/klh10]) +AC_INIT([klh10], [2.0k-Rhialto], [https://github.com/PDP-10/klh10], + [], [https://github.com/PDP-10/klh10]) AC_CONFIG_SRCDIR([src/klh10.h]) AC_CONFIG_HEADERS([src/config.h]) @@ -35,6 +35,22 @@ do done CFLAGS="$NEWCFLAGS -g3 -O3" +# ------------------------------------------------------------------------- +# 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 # ------------------------------------------------------------------------- diff --git a/src/osdnet.c b/src/osdnet.c index a8b27a6..276e001 100644 --- a/src/osdnet.c +++ b/src/osdnet.c @@ -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 ; @@ -1408,6 +1414,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); @@ -1432,6 +1444,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 diff --git a/src/osdnet.h b/src/osdnet.h index d69070e..0070a85 100644 --- a/src/osdnet.h +++ b/src/osdnet.h @@ -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 */