From 33bb72daa8f6c0890387257dcf3494830a6a8028 Mon Sep 17 00:00:00 2001 From: Floris Bos Date: Sun, 12 Dec 2021 15:47:54 +0100 Subject: [PATCH 1/2] Fix systemd socket activation support Fix systemd socket activation with passing listening sockets. (Seems only inetd style accept=yes systemd socket activation was actually working previously) Can be used with systemd units among the lines of: x11vnc.service == [Unit] Description=VNC server Requires=x11vnc.socket [Service] Type=simple ExecStart=/usr/bin/x11vnc -no6 -xkb -repeat -auth guess -display WAIT:0 -forever -shared == x11vnc.socket == [Unit] Description=VNC server socket [Socket] ListenStream=5900 [Install] WantedBy=sockets.target == systemctl enable x11vnc.socket Signed-off-by: Floris Bos --- libvncserver/sockets.c | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/libvncserver/sockets.c b/libvncserver/sockets.c index 2c87376b8..1a0f06cd6 100644 --- a/libvncserver/sockets.c +++ b/libvncserver/sockets.c @@ -183,8 +183,27 @@ rfbInitSockets(rfbScreenInfoPtr rfbScreen) rfbSocket sock = SD_LISTEN_FDS_START + 0; if (sd_is_socket(sock, AF_UNSPEC, 0, 0)) rfbNewConnectionFromSock(rfbScreen, sock); - else if (sd_is_socket(sock, AF_UNSPEC, 0, 1)) + else if (sd_is_socket(sock, AF_UNSPEC, 0, 1)) { + struct sockaddr_storage sa; + int sa_len = sizeof(sa); + char hoststr[NI_MAXHOST]; + char portstr[NI_MAXSERV]; + + if (getsockname(sock, (struct sockaddr *) &sa, &sa_len) == 0 + && getnameinfo((struct sockaddr *)&sa, sa_len, hoststr, sizeof(hoststr), + portstr, sizeof(portstr), NI_NUMERICHOST | NI_NUMERICSERV) == 0) { + rfbLog("Socket activation through systemd. Listening for VNC connections on %s:%s\n", hoststr, portstr); + rfbScreen->port = atoi(portstr); + } else { + rfbLogPerror("Error retrieving nameinfo of socket received from systemd\n"); + } + + FD_ZERO(&(rfbScreen->allFds)); + rfbScreen->listenSock = sock; + FD_SET(rfbScreen->listenSock, &(rfbScreen->allFds)); + rfbScreen->maxFd = rfbScreen->listenSock; rfbProcessNewConnection(rfbScreen); + } return; } else From 1c244968bac962d393d2c248d252614705c4112c Mon Sep 17 00:00:00 2001 From: Floris Bos Date: Sun, 12 Dec 2021 16:27:07 +0100 Subject: [PATCH 2/2] Add support for httpd systemd socket activation If a second socket is passed through systemd, assume it is meant for httpd use. Using it requires systemd units among the lines of: /lib/systemd/system/x11vnc.service == [Unit] Description=VNC server Requires=x11vnc.socket [Service] Type=simple ExecStart=/usr/bin/x11vnc -httpdir /usr/share/novnc -no6 -xkb -repeat -auth guess -display WAIT:0 -forever -shared == /lib/systemd/system/x11vnc.socket == [Unit] Description=VNC server socket [Socket] ListenStream=5900 ListenStream=80 [Install] WantedBy=sockets.target == systemctl enable --now x11vnc.socket Signed-off-by: Floris Bos --- libvncserver/httpd.c | 30 ++++++++++++++++++++++++++++++ libvncserver/sockets.c | 3 +-- 2 files changed, 31 insertions(+), 2 deletions(-) diff --git a/libvncserver/httpd.c b/libvncserver/httpd.c index e2de6c707..43566086b 100644 --- a/libvncserver/httpd.c +++ b/libvncserver/httpd.c @@ -63,6 +63,10 @@ #include #endif +#ifdef LIBVNCSERVER_WITH_SYSTEMD +#include +#endif + #define NOT_FOUND_STR "HTTP/1.0 404 Not found\r\nConnection: close\r\n\r\n" \ "File Not Found\n" \ @@ -100,6 +104,32 @@ rfbHttpInitSockets(rfbScreenInfoPtr rfbScreen) if (!rfbScreen->httpDir) return; +#ifdef LIBVNCSERVER_WITH_SYSTEMD + if (sd_listen_fds(0) == 2) { + rfbSocket sock = SD_LISTEN_FDS_START + 1; + if (sd_is_socket(sock, AF_UNSPEC, 0, 0)) { + rfbErr("Systemd socket activation passed 'accept=yes' inetd style socket. Only passing listening sockets is supported for http socket\n"); + } else if (sd_is_socket(sock, AF_UNSPEC, 0, 1)) { + struct sockaddr_storage sa; + int sa_len = sizeof(sa); + char hoststr[NI_MAXHOST]; + char portstr[NI_MAXSERV]; + + if (getsockname(sock, (struct sockaddr *) &sa, &sa_len) == 0 + && getnameinfo((struct sockaddr *)&sa, sa_len, hoststr, sizeof(hoststr), + portstr, sizeof(portstr), NI_NUMERICHOST | NI_NUMERICSERV) == 0) { + rfbLog("Socket activation through systemd. Listening for HTTP connections on %s:%s\n", hoststr, portstr); + } else { + rfbLogPerror("Error retrieving nameinfo of socket received from systemd\n"); + } + + rfbScreen->httpListenSock = sock; + } + + return; + } +#endif + if (rfbScreen->httpPort == 0) { rfbScreen->httpPort = rfbScreen->port-100; } diff --git a/libvncserver/sockets.c b/libvncserver/sockets.c index 1a0f06cd6..55345e39a 100644 --- a/libvncserver/sockets.c +++ b/libvncserver/sockets.c @@ -178,7 +178,7 @@ rfbInitSockets(rfbScreenInfoPtr rfbScreen) rfbScreen->socketState = RFB_SOCKET_READY; #ifdef LIBVNCSERVER_WITH_SYSTEMD - if (sd_listen_fds(0) == 1) + if (sd_listen_fds(0) == 1 || sd_listen_fds(0) == 2) { rfbSocket sock = SD_LISTEN_FDS_START + 0; if (sd_is_socket(sock, AF_UNSPEC, 0, 0)) @@ -202,7 +202,6 @@ rfbInitSockets(rfbScreenInfoPtr rfbScreen) rfbScreen->listenSock = sock; FD_SET(rfbScreen->listenSock, &(rfbScreen->allFds)); rfbScreen->maxFd = rfbScreen->listenSock; - rfbProcessNewConnection(rfbScreen); } return; }