Merge branch 'feature/KASM-4034_unix_sockets' into 'master'
Add support for relaying unix sockets Closes KASM-4034 See merge request kasm-technologies/internal/KasmVNC!90
This commit is contained in:
@@ -29,6 +29,8 @@
|
||||
#include <pwd.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/un.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/utsname.h>
|
||||
|
||||
@@ -51,6 +53,7 @@ extern "C" {
|
||||
void vncSetGlueContext(int screenIndex);
|
||||
|
||||
extern int wakeuppipe[2];
|
||||
extern struct sockaddr_un unixrelayclients[MAX_UNIX_RELAYS];
|
||||
}
|
||||
|
||||
using namespace rfb;
|
||||
@@ -323,6 +326,26 @@ void XserverDesktop::handleSocketEvent(int fd, bool read, bool write)
|
||||
return;
|
||||
}
|
||||
|
||||
unsigned i;
|
||||
for (i = 0; i < MAX_UNIX_RELAYS; i++) {
|
||||
if (unixrelays[i] == -1)
|
||||
break;
|
||||
if (fd == unixrelays[i]) {
|
||||
do {
|
||||
struct sockaddr_un client;
|
||||
socklen_t addrlen = sizeof(struct sockaddr_un);
|
||||
const ssize_t len = recvfrom(unixrelays[i], unixbuf, sizeof(unixbuf),
|
||||
MSG_DONTWAIT,
|
||||
(struct sockaddr *) &client, &addrlen);
|
||||
if (len <= 0)
|
||||
break;
|
||||
memcpy(&unixrelayclients[i], &client, addrlen);
|
||||
server->sendUnixRelayData(unixrelaynames[i], unixbuf, len);
|
||||
} while (1);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (handleListenerEvent(fd, &listeners, server))
|
||||
return;
|
||||
}
|
||||
@@ -557,3 +580,21 @@ bool XserverDesktop::handleTimeout(Timer* t)
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void XserverDesktop::receivedUnixRelayData(const char name[], const unsigned char *buf,
|
||||
const unsigned len)
|
||||
{
|
||||
unsigned i;
|
||||
for (i = 0; i < MAX_UNIX_RELAYS; i++) {
|
||||
if (unixrelays[i] == -1)
|
||||
break;
|
||||
if (strcmp(name, unixrelaynames[i]))
|
||||
continue;
|
||||
|
||||
if (sendto(unixrelays[i], buf, len, 0,
|
||||
(struct sockaddr *) &unixrelayclients[i], sizeof(struct sockaddr_un)) == -1)
|
||||
vlog.error("Error writing unix relay data to %s", name);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -110,6 +110,9 @@ public:
|
||||
const char* userName,
|
||||
char** reason);
|
||||
|
||||
virtual void receivedUnixRelayData(const char name[], const unsigned char *buf,
|
||||
const unsigned len);
|
||||
|
||||
protected:
|
||||
bool handleListenerEvent(int fd,
|
||||
std::list<network::SocketListener*>* sockets,
|
||||
@@ -138,5 +141,7 @@ private:
|
||||
rfb::Point oldCursorPos;
|
||||
|
||||
bool resizing;
|
||||
|
||||
uint8_t unixbuf[1024 * 1024];
|
||||
};
|
||||
#endif
|
||||
|
||||
@@ -89,6 +89,11 @@ Use IPv4 for incoming and outgoing connections. Default is on.
|
||||
Use IPv6 for incoming and outgoing connections. Default is on.
|
||||
.
|
||||
.TP
|
||||
.B \-UnixRelay \fIname:path\fP
|
||||
Create a local named unix socket, for relaying data. May be given multiple times.
|
||||
Example: -UnixRelay audio:/tmp/audiosock
|
||||
.
|
||||
.TP
|
||||
.B \-rfbunixpath \fIpath\fP
|
||||
Specifies the path of a Unix domain socket on which Xvnc listens for
|
||||
connections from viewers, instead of listening on a TCP port.
|
||||
|
||||
@@ -241,6 +241,14 @@ void vncExtensionInit(void)
|
||||
fcntl(wakeuppipe[0], F_SETFL, flags | O_NONBLOCK);
|
||||
vncSetNotifyFd(wakeuppipe[0], 0, true, false);
|
||||
|
||||
unsigned i;
|
||||
for (i = 0; i < MAX_UNIX_RELAYS; i++) {
|
||||
if (unixrelays[i] == -1)
|
||||
break;
|
||||
vncSetNotifyFd(unixrelays[i], 0, true, false);
|
||||
vlog.info("Listening to unix relay socket %s", unixrelaynames[i]);
|
||||
}
|
||||
|
||||
initialised = true;
|
||||
}
|
||||
|
||||
|
||||
@@ -23,6 +23,8 @@
|
||||
#include <stddef.h>
|
||||
#include <sys/select.h>
|
||||
|
||||
#include <rfb/unixRelayLimits.h>
|
||||
|
||||
// Only from C++
|
||||
#ifdef __cplusplus
|
||||
namespace rfb { class StringParameter; };
|
||||
@@ -106,6 +108,9 @@ void vncRefreshScreenLayout(int scrIdx);
|
||||
|
||||
int vncOverrideParam(const char *nameAndValue);
|
||||
|
||||
extern int unixrelays[MAX_UNIX_RELAYS];
|
||||
extern char unixrelaynames[MAX_UNIX_RELAYS][MAX_UNIX_RELAY_NAME_LEN];
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -61,8 +61,11 @@ from the X Consortium.
|
||||
#include "input.h"
|
||||
#include "mipointer.h"
|
||||
#include "micmap.h"
|
||||
#include <sys/socket.h>
|
||||
#include <sys/un.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
#ifndef WIN32
|
||||
#include <sys/param.h>
|
||||
@@ -163,6 +166,73 @@ static char displayNumStr[16];
|
||||
|
||||
static int vncVerbose = DEFAULT_LOG_VERBOSITY;
|
||||
|
||||
int unixrelays[MAX_UNIX_RELAYS];
|
||||
char unixrelaynames[MAX_UNIX_RELAYS][MAX_UNIX_RELAY_NAME_LEN];
|
||||
struct sockaddr_un unixrelayclients[MAX_UNIX_RELAYS];
|
||||
|
||||
static unsigned addrelay(const char * const arg)
|
||||
{
|
||||
const char *ptr = strchr(arg, ':');
|
||||
if (!ptr) {
|
||||
ErrorF("Invalid unixrelay\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
const unsigned namelen = ptr - arg;
|
||||
if (namelen >= MAX_UNIX_RELAY_NAME_LEN) {
|
||||
ErrorF("Unix relay name too long\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
unsigned i;
|
||||
unsigned char found = 0;
|
||||
for (i = 0; i < MAX_UNIX_RELAYS; i++) {
|
||||
if (unixrelays[i] == -1) {
|
||||
found = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!found) {
|
||||
ErrorF("Too many unix relays\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
memcpy(unixrelaynames[i], arg, namelen);
|
||||
unixrelaynames[i][namelen] = '\0';
|
||||
|
||||
unixrelays[i] = socket(AF_UNIX, SOCK_DGRAM, 0);
|
||||
if (unixrelays[i] < 0) {
|
||||
ErrorF("Failed to create unix sock\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
ptr++;
|
||||
struct sockaddr_un sa;
|
||||
if (strlen(ptr) >= sizeof(sa.sun_path)) {
|
||||
ErrorF("Unix relay path too long\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
sa.sun_family = AF_UNIX;
|
||||
strcpy(sa.sun_path, ptr);
|
||||
|
||||
// SO_REUSEADDR doesn't exist for unix sockets, if the socket exists
|
||||
// (from our previous run), we need to delete it first. Check it's a
|
||||
// socket so we don't delete wrong files
|
||||
struct stat st;
|
||||
if (stat(ptr, &st) == 0) {
|
||||
if (S_ISSOCK(st.st_mode))
|
||||
unlink(ptr);
|
||||
}
|
||||
|
||||
if (bind(unixrelays[i], (struct sockaddr *) &sa, sizeof(struct sockaddr_un))) {
|
||||
ErrorF("Failed to bind unix sock\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
char *extra_headers = NULL;
|
||||
unsigned extra_headers_len = 0;
|
||||
|
||||
@@ -374,6 +444,7 @@ void ddxUseMsg(void)
|
||||
ErrorF("-inetd has been launched from inetd\n");
|
||||
ErrorF("-http-header name=val append this header to all HTTP responses\n");
|
||||
ErrorF("-noclipboard disable clipboard settings modification via vncconfig utility\n");
|
||||
ErrorF("-unixrelay name:path create a local named unix relay socket\n");
|
||||
ErrorF("-verbose [n] verbose startup messages\n");
|
||||
ErrorF("-quiet minimal startup messages\n");
|
||||
ErrorF("-version show the server version\n");
|
||||
@@ -426,6 +497,13 @@ ddxProcessArgument(int argc, char *argv[], int i)
|
||||
|
||||
vfbInitializeDefaultScreens();
|
||||
vfbInitializePixmapDepths();
|
||||
|
||||
unsigned r;
|
||||
for (r = 0; r < MAX_UNIX_RELAYS; r++) {
|
||||
unixrelays[r] = -1;
|
||||
unixrelaynames[r][0] = '\0';
|
||||
}
|
||||
|
||||
firstTime = FALSE;
|
||||
vncInitRFB();
|
||||
}
|
||||
@@ -692,6 +770,16 @@ ddxProcessArgument(int argc, char *argv[], int i)
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (strcasecmp(argv[i], "-unixrelay") == 0)
|
||||
{
|
||||
fail_unless_args(argc, i, 1);
|
||||
++i;
|
||||
|
||||
if (addrelay(argv[i]))
|
||||
return 0;
|
||||
return 2;
|
||||
}
|
||||
|
||||
if (!strcmp(argv[i], "-verbose")) {
|
||||
if (++i < argc && argv[i]) {
|
||||
char *end;
|
||||
|
||||
Reference in New Issue
Block a user