Gabe Black has uploaded this change for review. ( https://gem5-review.googlesource.com/c/public/gem5/+/69167?usp=email )

Change subject: util: Make m5term able to connect to unix domain sockets.
......................................................................

util: Make m5term able to connect to unix domain sockets.

To connect to a unix domain socket, it must start with a non-digit
character to avoid being confused with a TCP port. If it starts with an
"@" character, then it is treated as an abstract socket.

Change-Id: I3a71eb8ef80018546f3bbf9d781770bd37ecec09
---
M util/term/term.c
1 file changed, 117 insertions(+), 29 deletions(-)



diff --git a/util/term/term.c b/util/term/term.c
index 529712c..8cbd202 100644
--- a/util/term/term.c
+++ b/util/term/term.c
@@ -27,26 +27,30 @@
  */

 #include <arpa/telnet.h>
-#include <netinet/in.h>
-#include <sys/socket.h>
-#include <sys/termios.h>
-#include <sys/time.h>
-#include <sys/types.h>
-#include <sys/un.h>
+#include <ctype.h>
 #include <err.h>
 #include <errno.h>
 #include <fcntl.h>
+#include <libgen.h>
+#include <linux/limits.h>
 #include <netdb.h>
+#include <netinet/in.h>
 #include <poll.h>
 #include <stdarg.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
+#include <sys/socket.h>
+#include <sys/termios.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <sys/un.h>
 #include <unistd.h>

 ssize_t atomicio(ssize_t (*)(), int, void *, size_t);
 void    readwrite(int);
-int     remote_connect(char *, char *, struct addrinfo);
+int     remote_connect_inet(char *, char *);
+int     remote_connect_unix(char *);

 struct  termios saved_ios;
 void    raw_term();
@@ -60,7 +64,6 @@
 {
     int ch, s, ret;
     char *host, *port, *endp;
-    struct addrinfo hints;
     socklen_t len;

     ret = 1;
@@ -87,33 +90,40 @@

     raw_term();

+    if (isdigit(port[0])) {
+        s = remote_connect_inet(host, port);
+    } else {
+        if (argc != 2)
+            errx(1, "host specified with local socket");
+        s = remote_connect_unix(port);
+    }
+
+    if (s != -1) {
+        readwrite(s);
+        close(s);
+    }
+
+    exit(0);
+}
+
+/*
+ * remote_connect_inet()
+ * Return's a socket connected to a remote host. Properly bind's to a local
+ * port or source address if needed. Return's -1 on failure.
+ */
+int
+remote_connect_inet(char *host, char *port)
+{
+    struct addrinfo hints;
+    struct addrinfo *res, *res0;
+    int s, error;
+
     /* Initialize addrinfo structure */
     memset(&hints, 0, sizeof(struct addrinfo));
     hints.ai_family = AF_UNSPEC;
     hints.ai_socktype = SOCK_STREAM;
     hints.ai_protocol = IPPROTO_TCP;

-    s = remote_connect(host, port, hints);
-    ret = 0;
-    readwrite(s);
-
-    if (s)
-        close(s);
-
-    exit(ret);
-}
-
-/*
- * remote_connect()
- * Return's a socket connected to a remote host. Properly bind's to a local
- * port or source address if needed. Return's -1 on failure.
- */
-int
-remote_connect(char *host, char *port, struct addrinfo hints)
-{
-    struct addrinfo *res, *res0;
-    int s, error;
-
     if ((error = getaddrinfo(host, port, &hints, &res)))
         errx(1, "getaddrinfo: %s", gai_strerror(error));

@@ -136,6 +146,84 @@
 }

 /*
+ * remote_connect_inet()
+ * Return's a socket connected to a remote host. Properly bind's to a local
+ * port or source address if needed. Return's -1 on failure.
+ */
+int
+remote_connect_unix(char *path)
+{
+    struct sockaddr_un addr;
+
+    // Create a copy of path so we can safely modify it in place.
+    char *pathc = strdup(path);
+    path = pathc;
+
+    // Create a unix domain socket.
+    int s = socket(AF_UNIX, SOCK_STREAM, 0);
+    if (s == -1)
+        return s;
+
+    // Prepare the scokaddr_un.
+    memset(&addr, 0, sizeof(addr));
+    addr.sun_family = AF_UNIX;
+
+ // Keep track of where we're filling in the path, and the remaining space.
+    int path_size = sizeof(addr.sun_path);
+    char *sun_path = &addr.sun_path[0];
+
+    // Keep track of the current directory in case we change it to maximize
+    // what we can fit in the limited space in sun_path.
+    char *cwd = NULL;
+
+    if (path[0] == '@') {
+        // If this is an abstract socket, prefix it with a null byte.
+        *sun_path++ = '\0';
+        path++;
+        path_size--;
+ // Keep track of how much of sun_path is actual data since everything
+        // we include will be part of the lookup.
+        int len = strlen(path);
+        if (len < path_size)
+            path_size = len;
+    } else {
+        // Switch to the parent directory of the socket.
+        cwd = (char *)malloc(PATH_MAX);
+        getcwd(cwd, PATH_MAX);
+        char *dirc = strdup(path);
+        char *dname = dirname(dirc);
+        chdir(dname);
+        free(dirc);
+
+        // Replace the path with just the filename part. We still have a
+        // pointer to our copy of "path" so we can clean it up later.
+        path = basename(path);
+    }
+
+    // Copy the path into sun_path.
+    strncpy(sun_path, path, path_size);
+
+    // Figure out how much actual data we have in sockaddr_un.
+    int struct_len = (char *)sun_path + path_size - (char *)&addr;
+
+    // Actually connect to the socket.
+    if (connect(s, (struct sockaddr *)&addr, struct_len) == -1) {
+        // If that didn't work, switch our dir back and error out.
+        if (cwd)
+            chdir(cwd);
+        errx(1, "Failed to connect");
+    }
+
+    // We're connected, clean up memory and switch the current dir back.
+    free(pathc);
+    if (cwd)
+        chdir(cwd);
+
+    // Return the FD of our new connection.
+    return s;
+}
+
+/*
  * readwrite()
  * Loop that selects on the network file descriptor and stdin.
  * Changed from poll() by Ali Saidi to make work on Mac OS X >= 10.4

--
To view, visit https://gem5-review.googlesource.com/c/public/gem5/+/69167?usp=email To unsubscribe, or for help writing mail filters, visit https://gem5-review.googlesource.com/settings

Gerrit-Project: public/gem5
Gerrit-Branch: develop
Gerrit-Change-Id: I3a71eb8ef80018546f3bbf9d781770bd37ecec09
Gerrit-Change-Number: 69167
Gerrit-PatchSet: 1
Gerrit-Owner: Gabe Black <gabe.bl...@gmail.com>
Gerrit-CC: Gabe Black <gabebl...@google.com>
Gerrit-MessageType: newchange
_______________________________________________
gem5-dev mailing list -- gem5-dev@gem5.org
To unsubscribe send an email to gem5-dev-le...@gem5.org

Reply via email to