aboutsummaryrefslogtreecommitdiffstats
path: root/roms/skiboot/external/mambo/mambo-socket-proxy.c
diff options
context:
space:
mode:
authorAngelos Mouzakitis <a.mouzakitis@virtualopensystems.com>2023-10-10 14:33:42 +0000
committerAngelos Mouzakitis <a.mouzakitis@virtualopensystems.com>2023-10-10 14:33:42 +0000
commitaf1a266670d040d2f4083ff309d732d648afba2a (patch)
tree2fc46203448ddcc6f81546d379abfaeb323575e9 /roms/skiboot/external/mambo/mambo-socket-proxy.c
parente02cda008591317b1625707ff8e115a4841aa889 (diff)
Add submodule dependency filesHEADmaster
Change-Id: Iaf8d18082d3991dec7c0ebbea540f092188eb4ec
Diffstat (limited to 'roms/skiboot/external/mambo/mambo-socket-proxy.c')
-rw-r--r--roms/skiboot/external/mambo/mambo-socket-proxy.c347
1 files changed, 347 insertions, 0 deletions
diff --git a/roms/skiboot/external/mambo/mambo-socket-proxy.c b/roms/skiboot/external/mambo/mambo-socket-proxy.c
new file mode 100644
index 000000000..64b677045
--- /dev/null
+++ b/roms/skiboot/external/mambo/mambo-socket-proxy.c
@@ -0,0 +1,347 @@
+// SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
+/*
+ * Compile with:
+ * gcc -static -O2 mambo-socket-proxy.c -o mambo-socket-proxy -pthread
+ * Run inside the simulator:
+ * - to forward host ssh connections to sim ssh server
+ * ./mambo-socket-proxy -h 10022 -s 22
+ * Then connect to port 10022 on your host
+ * ssh -p 10022 localhost
+ * - to allow http proxy access from inside the sim to local http proxy
+ * ./mambo-socket-proxy -b proxy.mynetwork -h 3128 -s 3128
+ *
+ * Copyright (C) 2017 Michael Neuling <mikey@neuling.org>, IBM
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <pthread.h>
+#include <getopt.h>
+
+#define CALL_TCL 86
+#define BOGUS_SOCKET_CONN_PROBE_CODE 224
+#define BOGUS_SOCKET_CONN_SEND_CODE 225
+#define BOGUS_SOCKET_CONN_RECV_CODE 226
+
+static inline int callthru2(int command, unsigned long arg1, unsigned long arg2)
+{
+ register int c asm("r3") = command;
+ register unsigned long a1 asm("r4") = arg1;
+ register unsigned long a2 asm("r5") = arg2;
+ asm volatile (".long 0x000eaeb0":"=r" (c):"r"(c), "r"(a1), "r"(a2));
+ return (c);
+}
+
+static inline int callthru3(int command, unsigned long arg1, unsigned long arg2,
+ unsigned long arg3)
+{
+ register int c asm("r3") = command;
+ register unsigned long a1 asm("r4") = arg1;
+ register unsigned long a2 asm("r5") = arg2;
+ register unsigned long a3 asm("r6") = arg3;
+ asm volatile (".long 0x000eaeb0":"=r" (c):"r"(c), "r"(a1), "r"(a2),
+ "r"(a3));
+ return (c);
+}
+
+static inline int callthru4(int command, unsigned long arg1, unsigned long arg2,
+ unsigned long arg3, unsigned long arg4)
+{
+ register int c asm("r3") = command;
+ register unsigned long a1 asm("r4") = arg1;
+ register unsigned long a2 asm("r5") = arg2;
+ register unsigned long a3 asm("r6") = arg3;
+ register unsigned long a4 asm("r7") = arg4;
+ asm volatile (".long 0x000eaeb0":"=r" (c):"r"(c), "r"(a1), "r"(a2),
+ "r"(a3), "r"(a4));
+ return (c);
+}
+
+static inline int callthru5(int command, unsigned long arg1, unsigned long arg2,
+ unsigned long arg3, unsigned long arg4, unsigned long arg5)
+{
+ register int c asm("r3") = command;
+ register unsigned long a1 asm("r4") = arg1;
+ register unsigned long a2 asm("r5") = arg2;
+ register unsigned long a3 asm("r6") = arg3;
+ register unsigned long a4 asm("r7") = arg4;
+ register unsigned long a5 asm("r8") = arg5;
+ asm volatile (".long 0x000eaeb0":"=r" (c):"r"(c), "r"(a1), "r"(a2),
+ "r"(a3), "r"(a4), "r"(a5));
+ return (c);
+}
+
+unsigned long callthru_tcl(const char *str, int strlen)
+{
+ return callthru2(CALL_TCL, (unsigned long)str,
+ (unsigned long)strlen);
+}
+
+unsigned long bogus_socket_conn_probe(int dev, void *addr, int conn)
+{
+ return callthru3(BOGUS_SOCKET_CONN_PROBE_CODE,
+ (unsigned long)dev,
+ (unsigned long)addr,
+ (unsigned long)conn);
+}
+
+unsigned long bogus_socket_conn_recv(int dev, void *addr, int maxlen, int conn)
+{
+ return callthru4(BOGUS_SOCKET_CONN_RECV_CODE,
+ (unsigned long)dev,
+ (unsigned long)addr,
+ (unsigned long)maxlen,
+ (unsigned long)conn);
+}
+
+unsigned long bogus_socket_conn_send(int dev, void *addr, int maxlen, int conn)
+{
+ return callthru5(BOGUS_SOCKET_CONN_SEND_CODE,
+ (unsigned long)dev,
+ (unsigned long)addr,
+ (unsigned long)maxlen,
+ 0,
+ (unsigned long)conn);
+}
+
+#define BUF_MAX 1024
+
+struct sock_info {
+ char *host;
+ int sock;
+ int dev;
+ int open;
+ int conn;
+};
+
+void *recv_thread(void *ptr)
+{
+ struct timeval timeout;
+ struct sock_info *si = ptr;
+ char buf[BUF_MAX];
+ int len;
+ fd_set set;
+
+ /* 1 sec */
+
+
+ while(1) {
+ FD_ZERO(&set);
+ FD_SET(si->sock, &set);
+ timeout.tv_sec = 1;
+ timeout.tv_usec = 0;
+ /* Set timeout to 1 second */
+ len = select(si->sock+1, &set, NULL, NULL, &timeout);
+ if (len <= 0) /* timeout */
+ len = -1;
+ else /* Receive from mambo tcp server */
+ len = recv(si->sock, &buf, BUF_MAX, 0);
+ if (len == 0) {
+ si->open = 0;
+ return NULL; /* closed */
+ }
+ if (len != -1) {
+ bogus_socket_conn_send(si->dev, &buf, len, si->conn);
+ }
+ if (!si->open)
+ return NULL;
+ }
+}
+
+#define POLL_MAX_NS 10000000
+
+void *send_thread(void *ptr)
+{
+ struct sock_info *si = ptr;
+ char buf[BUF_MAX];
+ int len;
+ struct timespec t;
+ int fault_retry = 16;
+
+ t.tv_sec = 0;
+ t.tv_nsec = POLL_MAX_NS;
+
+ while(1) {
+ /* Send to mambo tcp server */
+ len = bogus_socket_conn_recv(si->dev, &buf, BUF_MAX, si->conn);
+ if (len == -3 && fault_retry--) {
+ /* Page fault. Touch the buf and try again */
+ memset(buf, 0, BUF_MAX);
+ continue;
+ }
+ fault_retry = 16;
+
+ if (len == -1) /* EAGAIN */
+ nanosleep(&t , NULL);
+ else if (len > 0)
+ send(si->sock, &buf, len, 0);
+ else {
+ si->open = 0;
+ return NULL; /* closed */
+ }
+ if (!si->open)
+ return NULL;
+ }
+
+}
+
+void *connect_sockets(void *ptr)
+{
+ struct sock_info *si = ptr;
+ pthread_t recv, send;
+ unsigned long rc = 0;
+
+ if (pthread_create(&recv, NULL, recv_thread, si) ||
+ pthread_create(&send, NULL, send_thread, si)) {
+ rc = -1;
+ goto out;
+ }
+
+ if (pthread_join(recv, NULL) || pthread_join(send, NULL)) {
+ rc = -1;
+ goto out;
+ }
+
+out:
+ /* FIXME: Do shutdown better */
+ shutdown(si->sock, SHUT_WR);
+ si->open = 0;
+ free(si);
+ return (void *)rc;
+}
+
+void print_usage() {
+ printf("Usage:\n");
+ printf(" mambo-socket-proxy [-b <host>] -h <host port> -s <sim port>\n");
+ printf("\n");
+ printf(" -h <host port> : Port on the host to forward\n");
+ printf(" -s <host port> : Port in the sim to forward\n");
+ printf(" -b <host machine> : Connect sim port to host network\n");
+ printf("\n");
+}
+
+int main (int argc, char *argv[])
+{
+ char cmd[128];
+ struct sockaddr_in ser, client;
+ pthread_t sockets_thread;
+ struct sock_info *si;
+ int sock, conn, rc = 0, option = 0, one_shot = 0, c, sock_desc = 0;
+ char *host = NULL;
+ int host_port = -1, sim_port = -1;
+ int dev = 1; /* backwards starts at 1 so forwards can use 0 */
+
+ while ((option = getopt(argc, argv,"rb:h:s:")) != -1) {
+ switch (option) {
+ case 'b' :
+ host = optarg;
+ break;
+ case 'h' :
+ host_port = atoi(optarg);
+ break;
+ case 's' :
+ sim_port = atoi(optarg);
+ break;
+ default:
+ print_usage();
+ exit(1);
+ }
+ }
+
+ if (host_port == -1 || sim_port ==-1) {
+ print_usage();
+ exit(EXIT_FAILURE);
+ }
+
+ /*
+ * A host/backwards connection will use dev=0 and conn >= 0.
+ * The forwards connection will use dev >= 1 and conn=0
+ */
+ if (host) {
+ sock_desc = socket(PF_INET, SOCK_STREAM, 0);
+ ser.sin_family = AF_INET;
+ ser.sin_addr.s_addr = INADDR_ANY;
+ ser.sin_port = htons(sim_port);
+
+ if (bind(sock_desc, (struct sockaddr *) &ser, sizeof(ser)) < 0) {
+ perror("Can't connect to sim port");
+ rc = -1;
+ goto out;
+ }
+
+ listen(sock_desc, 3);
+ } else {
+ /*
+ * Cleaning up old bogus socket.
+ */
+ sprintf(cmd, "mysim bogus socket cleanup");
+ callthru_tcl(cmd, strlen(cmd));
+ sleep(1); /* Cleanup takes a while */
+ sprintf(cmd, "mysim bogus socket init 0 server "
+ "127.0.0.1 %i poll 0 nonblock", host_port);
+ callthru_tcl(cmd, strlen(cmd));
+ }
+
+ while (1) {
+
+ if (host) {
+ sock = accept(sock_desc, (struct sockaddr *)&client, (socklen_t*)&c);
+ if (sock < 0) {
+ perror("accept failed");
+ rc = -1;
+ goto out;
+ }
+
+ sprintf(cmd, "mysim bogus socket init %i client %s %i poll 0",
+ dev, host, host_port);
+ callthru_tcl(cmd, strlen(cmd));
+ while (bogus_socket_conn_probe(dev, NULL, 0) == -1)
+ sleep(1);
+ } else {
+ struct timespec t;
+ t.tv_sec = 0;
+ t.tv_nsec = 10000000;
+ do {
+ conn = bogus_socket_conn_probe(0, NULL, -1);
+ nanosleep(&t , NULL);
+ } while (conn == -1);
+
+ sock = socket(PF_INET, SOCK_STREAM, 0);
+ ser.sin_family = AF_INET;
+ ser.sin_port = htons(sim_port);
+ ser.sin_addr.s_addr = inet_addr("127.0.0.1");
+ memset(ser.sin_zero, '\0', sizeof ser.sin_zero);
+
+ if (connect(sock, (struct sockaddr *) &ser, sizeof(ser))) {
+ perror("Can't connect to sim port");
+ rc = -1;
+ goto out;
+ }
+ }
+
+ si = malloc(sizeof(struct sock_info));
+ si->host = host;
+ si->sock = sock;
+ si->dev = host?dev:0;
+ si->open = 1;
+ si->conn = host?0:conn;
+
+ if (pthread_create(&sockets_thread, NULL, connect_sockets, si)) {
+ rc = -1;
+ goto out;
+ }
+
+ if (one_shot)
+ break;
+ ++dev; // FIXME: do a real allocator
+ }
+out:
+ exit(rc);
+}