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

 (

6 is the latest approved patch-set.
No files were changed between the latest approved patch-set and the submitted one.
 )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
Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/69167
Reviewed-by: Jui-min Lee <f...@google.com>
Maintainer: Gabe Black <gabebl...@google.com>
Tested-by: kokoro <noreply+kok...@google.com>
---
M util/term/term.c
1 file changed, 139 insertions(+), 31 deletions(-)

Approvals:
  Gabe Black: Looks good to me, approved
  Jui-min Lee: Looks good to me, approved
  kokoro: Regressions pass




diff --git a/util/term/term.c b/util/term/term.c
index 529712c..cf3fdda 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(const 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,38 @@

     raw_term();

+    if (strcmp(host, "--unix") == 0) {
+        s = remote_connect_unix(port);
+    } else {
+        s = remote_connect_inet(host, 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 +144,104 @@
 }

 /*
+ * 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(const char *cpath)
+{
+    struct sockaddr_un addr;
+
+    // Create a copy of path so we can safely modify it in place.
+    char *path = strdup(cpath);
+    char *const path_buf = path;
+
+    // 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) {
+            fprintf(stderr,
+ "warning: Truncated abstract socket from %d to %d bytes.\n",
+                len, path_size);
+            path_size = len;
+        }
+    } else {
+        // Switch to the parent directory of the socket.
+        cwd = (char *)malloc(PATH_MAX);
+        if (!cwd)
+            errx(1, "Failed to allocate %d byte buffer.", PATH_MAX);
+        if (!getcwd(cwd, PATH_MAX)) {
+            perror("getcwd failed");
+            exit(1);
+        }
+        char *dirc = strdup(path);
+        if (!dirc) {
+            perror("strdup failed");
+            exit(1);
+        }
+        char *dname = dirname(dirc);
+        if (chdir(dname) != 0) {
+            perror("chdir to socket dir failed");
+            exit(1);
+        }
+        free(dirc);
+
+        // Replace the path with just the filename part. We still have a
+        // pointer to the cpath argument, 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(path_buf);
+    if (cwd) {
+        if (chdir(cwd) != 0) {
+            perror("chdir back failed:");
+            exit(1);
+        }
+    }
+
+    // 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
@@ -165,7 +271,8 @@
         n = select(max_fd, &read_fds, NULL, NULL, &timeout);
         if (n < 0) {
             close(nfd);
-            perror("Select Error:");
+            perror("Select Error");
+            exit(1);
         }

         if (n == 0) {
@@ -221,7 +328,8 @@
 void
 usage(int ret)
 {
-    fprintf(stderr, "usage: %s hostname port\n", progname);
+    fprintf(stderr, "usage: %s [hostname] port\n", progname);
+    fprintf(stderr, "usage: %s --unix socket\n", progname);
     if (ret)
         exit(1);
 }

--
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: 8
Gerrit-Owner: Gabe Black <gabe.bl...@gmail.com>
Gerrit-Reviewer: Gabe Black <gabe.bl...@gmail.com>
Gerrit-Reviewer: Gabe Black <gabebl...@google.com>
Gerrit-Reviewer: Jui-min Lee <f...@google.com>
Gerrit-Reviewer: kokoro <noreply+kok...@google.com>
Gerrit-MessageType: merged
_______________________________________________
gem5-dev mailing list -- gem5-dev@gem5.org
To unsubscribe send an email to gem5-dev-le...@gem5.org

Reply via email to