diff options
author | Angelos Mouzakitis <a.mouzakitis@virtualopensystems.com> | 2023-10-10 14:33:42 +0000 |
---|---|---|
committer | Angelos Mouzakitis <a.mouzakitis@virtualopensystems.com> | 2023-10-10 14:33:42 +0000 |
commit | af1a266670d040d2f4083ff309d732d648afba2a (patch) | |
tree | 2fc46203448ddcc6f81546d379abfaeb323575e9 /roms/skiboot/external/mambo/mambo-socket-proxy.c | |
parent | e02cda008591317b1625707ff8e115a4841aa889 (diff) |
Change-Id: Iaf8d18082d3991dec7c0ebbea540f092188eb4ec
Diffstat (limited to 'roms/skiboot/external/mambo/mambo-socket-proxy.c')
-rw-r--r-- | roms/skiboot/external/mambo/mambo-socket-proxy.c | 347 |
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); +} |