From 9264555cddb7cac93e41f08c70a8932bceffcfaa Mon Sep 17 00:00:00 2001
From: Stefan Reither <stefan.reither@kit.edu>
Date: Thu, 9 Jul 2020 17:00:13 +0200
Subject: [PATCH] adds raw_socket

---
 etc/raw_socket/Makefile     |  18 ++++++
 etc/raw_socket/raw_socket.c | 115 ++++++++++++++++++++++++++++++++++++
 2 files changed, 133 insertions(+)
 create mode 100644 etc/raw_socket/Makefile
 create mode 100644 etc/raw_socket/raw_socket.c

diff --git a/etc/raw_socket/Makefile b/etc/raw_socket/Makefile
new file mode 100644
index 000000000..af261855d
--- /dev/null
+++ b/etc/raw_socket/Makefile
@@ -0,0 +1,18 @@
+# raw_socket
+
+PREFIX = /usr/local
+BDIR = $(DESTDIR)/$(PREFIX)
+
+.PHONY: all clean install
+
+all: raw_socket
+
+raw_socket: raw_socket.c
+	$(CC) -o $@ raw_socket.c
+
+install: raw_socket
+	install -D raw_socket $(BDIR)/bin/raw_socket
+	setcap cap_net_raw,cap_ipc_lock,cap_sys_nice+ep $(BDIR)/bin/raw_socket
+
+clean:
+	rm -f raw_socket
diff --git a/etc/raw_socket/raw_socket.c b/etc/raw_socket/raw_socket.c
new file mode 100644
index 000000000..32322d9be
--- /dev/null
+++ b/etc/raw_socket/raw_socket.c
@@ -0,0 +1,115 @@
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+#include <sysexits.h>
+#include <unistd.h>
+
+#include <arpa/inet.h>
+#include <net/ethernet.h>
+#include <net/if.h>
+#include <linux/if_packet.h>
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+
+#define ETH_P_ECAT 0x88A4
+
+extern char **environ;
+
+int main(int argc, char *argv[])
+{
+   fprintf(stderr, "raw_socket was build: %s\n", __TIMESTAMP__);
+   int i, ret, ifindex, psock;
+   struct ifreq ifr;
+   struct sockaddr_ll sll;
+   struct timeval timeout;
+   int argssize = argc + 1;
+   char *args[argssize];
+   char sock[5];
+
+	if (argc < 3) {
+		fprintf(stderr, "usage: %s [ifname] [binary] <args>\n", argv[0]);
+		return EX_USAGE;
+	}
+
+	/* we use RAW packet socket, with packet type ETH_P_ECAT */
+	psock = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ECAT));
+	if (psock < 0) {
+		perror("socket");
+      		fprintf(stderr, "raw_socket error: socket SOCK_RAW\n");
+		return EX_OSERR;
+	}
+
+   timeout.tv_sec =  0;
+   timeout.tv_usec = 1;
+   fprintf(stderr, "raw_socket: setsockopt SO_RCVTIMEO\n");
+   ret = setsockopt(psock, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(timeout));
+   if (ret != 0) {
+      perror("setsockopt");
+      fprintf(stderr, "raw_socket error: setsockopt SO_RCVTIMEO\n");
+      return EX_OSERR;
+   }
+
+   fprintf(stderr, "raw_socket: setsockopt SO_SNDTIMEO\n");
+   ret = setsockopt(psock, SOL_SOCKET, SO_SNDTIMEO, &timeout, sizeof(timeout));
+   if (ret != 0) {
+      perror("setsockopt");
+      fprintf(stderr, "raw_socket error: setsockopt SO_SNDTIMEO\n");
+      return EX_OSERR;
+   }
+
+   i = 1;
+   fprintf(stderr, "raw_socket: setsockopt SO_DONTROUTE\n");
+   ret = setsockopt(psock, SOL_SOCKET, SO_DONTROUTE, &i, sizeof(i));
+   if (ret != 0) {
+      perror("setsockopt");
+      fprintf(stderr, "raw_socket error: setsockopt SO_DONTROUTE\n");
+      return EX_OSERR;
+   }
+   /* connect socket to NIC by name */
+   strcpy(ifr.ifr_name, argv[1]);
+   ret = ioctl(psock, SIOCGIFINDEX, &ifr);
+   ifindex = ifr.ifr_ifindex;
+   strcpy(ifr.ifr_name, argv[1]);
+   ifr.ifr_flags = 0;
+   /* reset flags of NIC interface */
+   ret = ioctl(psock, SIOCGIFFLAGS, &ifr);
+   /* set flags of NIC interface, here promiscuous and broadcast */
+   ifr.ifr_flags = ifr.ifr_flags | IFF_PROMISC | IFF_BROADCAST;
+   ret = ioctl(psock, SIOCGIFFLAGS, &ifr);
+   /* bind socket to protocol, in this case RAW EtherCAT */
+   sll.sll_family = AF_PACKET;
+   sll.sll_ifindex = ifindex;
+   sll.sll_protocol = htons(ETH_P_ECAT);
+   ret = bind(psock, (struct sockaddr *)&sll, sizeof(sll));
+   /* setup ethernet headers in tx buffers so we don't have to repeat it */
+
+   fprintf(stderr, "raw_socket: setenv ARMARX_LD_LIBRARY_PATH\n");
+   ret = setenv("LD_LIBRARY_PATH", getenv("ARMARX_LD_LIBRARY_PATH"), 1);
+   if (ret != 0) {
+      perror("setenv");
+      fprintf(stderr, "raw_socket error: setenv ARMARX_LD_LIBRARY_PATH\n");
+      return EX_OSERR;
+   }
+
+   i=0;
+   fprintf(stderr, "ARGUMENT %d/%d: %s\n", i+1, argssize, strrchr(argv[2], '/'));
+   args[i++] = strrchr(argv[2], '/');
+
+   snprintf(sock, 5, "%d", psock);
+
+   fprintf(stderr, "ARGUMENT %d/%d: %s\n", i+1, argssize, sock);
+   args[i++] = sock;
+   for (i = 2; argv[i] != NULL; i++) {
+      fprintf(stderr, "ARGUMENT %d/%d: %s\n", i+1, argssize, argv[i]);	
+      args[i] = argv[i];
+   }
+   fprintf(stderr, "ARGUMENT %d/%d: NULL\n", i+1, argssize);
+   args[i] = NULL;
+   fprintf(stderr, "executing %s\n", argv[2]);
+   execve(argv[2], args, environ);
+   fprintf(stderr, "executing %s...done!\n", argv[2]);
+   perror("execv");
+
+	return EX_OSERR;
+}
-- 
GitLab