OBS-URL: https://build.opensuse.org/package/show/network:utilities/netcat-openbsd?expand=0&rev=29
158 lines
4.3 KiB
Diff
158 lines
4.3 KiB
Diff
From: Dirk Jagdmann <doj@cubic.org>
|
|
Date: Sun, 6 Mar 2022 21:26:31 -0800
|
|
Subject: Add abstract UNIX domain socket support
|
|
|
|
When using '-U' to connect() or bind() to a UNIX domain socket, if the
|
|
address (path) starts with "@", it is read as an abstract namespace
|
|
socket (the leading "@" is replaced with a NUL byte before binding).
|
|
|
|
This feature is Linux-only.
|
|
|
|
Forwarded: not-needed
|
|
---
|
|
nc.1 | 3 +++
|
|
netcat.c | 75 ++++++++++++++++++++++++++++++++++++++++++++--------------------
|
|
2 files changed, 55 insertions(+), 23 deletions(-)
|
|
|
|
diff --git a/nc.1 b/nc.1
|
|
index d30389a..8285c10 100644
|
|
--- a/nc.1
|
|
+++ b/nc.1
|
|
@@ -235,6 +235,9 @@ Cannot be used together with
|
|
.Fl F
|
|
or
|
|
.Fl x .
|
|
+On Linux, if the name starts with an at symbol (`@') it is read as an abstract
|
|
+namespace socket: the leading `@' is replaced with a \fBNUL\fR byte
|
|
+before binding or connecting. For details, see \fBunix\fR(7).
|
|
.It Fl u
|
|
Use UDP instead of TCP.
|
|
Cannot be used together with
|
|
diff --git a/netcat.c b/netcat.c
|
|
index 061a774..2f8890b 100644
|
|
--- a/netcat.c
|
|
+++ b/netcat.c
|
|
@@ -98,6 +98,7 @@
|
|
#include <netdb.h>
|
|
#include <poll.h>
|
|
#include <signal.h>
|
|
+#include <stddef.h>
|
|
#include <stdarg.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
@@ -208,6 +209,7 @@ int timeout_connect(int, const struct sockaddr *, socklen_t);
|
|
int socks_connect(const char *, const char *, struct addrinfo,
|
|
const char *, const char *, struct addrinfo, int, const char *);
|
|
int udptest(int);
|
|
+int unix_setup_sockaddr(char *, struct sockaddr_un *, int *);
|
|
void connection_info(const char *, const char *, const char *, const char *);
|
|
int unix_bind(char *, int);
|
|
int unix_connect(char *);
|
|
@@ -931,6 +933,46 @@ main(int argc, char *argv[])
|
|
return ret;
|
|
}
|
|
|
|
+int
|
|
+unix_setup_sockaddr(char *path, struct sockaddr_un *s_un, int *addrlen)
|
|
+{
|
|
+ int sun_path_len;
|
|
+
|
|
+ *addrlen = offsetof(struct sockaddr_un, sun_path);
|
|
+ memset(s_un, 0, *addrlen);
|
|
+ s_un->sun_family = AF_UNIX;
|
|
+
|
|
+ if (path[0] == '\0') {
|
|
+ /* Always reject the empty path, aka NUL abstract socket on
|
|
+ * Linux (OTOH the *empty* abstract socket is supported and
|
|
+ * specified as @""). */
|
|
+ errno = EINVAL;
|
|
+ return -1;
|
|
+ }
|
|
+#ifdef __linux__
|
|
+ /* If the unix domain socket path starts with '@',
|
|
+ * treat it as a Linux abstract name. */
|
|
+ else if (path[0] == '@') {
|
|
+ if ((sun_path_len = strlen(path)) <= sizeof(s_un->sun_path)) {
|
|
+ s_un->sun_path[0] = '\0';
|
|
+ strncpy(s_un->sun_path+1, path+1, sun_path_len-1);
|
|
+ *addrlen += sun_path_len;
|
|
+ } else {
|
|
+ errno = ENAMETOOLONG;
|
|
+ return -1;
|
|
+ }
|
|
+ }
|
|
+#endif
|
|
+ else if ((sun_path_len = strlcpy(s_un->sun_path, path, sizeof(s_un->sun_path))) <
|
|
+ sizeof(s_un->sun_path))
|
|
+ *addrlen += sun_path_len + 1; /* account for trailing '\0' */
|
|
+ else {
|
|
+ errno = ENAMETOOLONG;
|
|
+ return -1;
|
|
+ }
|
|
+ return 0;
|
|
+}
|
|
+
|
|
/*
|
|
* unix_bind()
|
|
* Returns a unix socket bound to the given path
|
|
@@ -939,24 +981,17 @@ int
|
|
unix_bind(char *path, int flags)
|
|
{
|
|
struct sockaddr_un s_un;
|
|
- int s, save_errno;
|
|
+ int s, save_errno, addrlen;
|
|
+
|
|
+ if (unix_setup_sockaddr(path, &s_un, &addrlen) == -1)
|
|
+ return -1;
|
|
|
|
/* Create unix domain socket. */
|
|
if ((s = socket(AF_UNIX, flags | (uflag ? SOCK_DGRAM : SOCK_STREAM),
|
|
0)) == -1)
|
|
return -1;
|
|
|
|
- memset(&s_un, 0, sizeof(struct sockaddr_un));
|
|
- s_un.sun_family = AF_UNIX;
|
|
-
|
|
- if (strlcpy(s_un.sun_path, path, sizeof(s_un.sun_path)) >=
|
|
- sizeof(s_un.sun_path)) {
|
|
- close(s);
|
|
- errno = ENAMETOOLONG;
|
|
- return -1;
|
|
- }
|
|
-
|
|
- if (bind(s, (struct sockaddr *)&s_un, sizeof(s_un)) == -1) {
|
|
+ if (bind(s, (struct sockaddr *)&s_un, addrlen) == -1) {
|
|
save_errno = errno;
|
|
close(s);
|
|
errno = save_errno;
|
|
@@ -1066,7 +1101,10 @@ int
|
|
unix_connect(char *path)
|
|
{
|
|
struct sockaddr_un s_un;
|
|
- int s, save_errno;
|
|
+ int s, save_errno, addrlen;
|
|
+
|
|
+ if (unix_setup_sockaddr(path, &s_un, &addrlen) == -1)
|
|
+ return -1;
|
|
|
|
if (uflag) {
|
|
if ((s = unix_bind(unix_dg_tmp_socket, SOCK_CLOEXEC)) == -1)
|
|
@@ -1076,16 +1114,7 @@ unix_connect(char *path)
|
|
return -1;
|
|
}
|
|
|
|
- memset(&s_un, 0, sizeof(struct sockaddr_un));
|
|
- s_un.sun_family = AF_UNIX;
|
|
-
|
|
- if (strlcpy(s_un.sun_path, path, sizeof(s_un.sun_path)) >=
|
|
- sizeof(s_un.sun_path)) {
|
|
- close(s);
|
|
- errno = ENAMETOOLONG;
|
|
- return -1;
|
|
- }
|
|
- if (connect(s, (struct sockaddr *)&s_un, sizeof(s_un)) == -1) {
|
|
+ if (connect(s, (struct sockaddr *)&s_un, addrlen) == -1) {
|
|
save_errno = errno;
|
|
close(s);
|
|
errno = save_errno;
|