Commit 3713346f authored by Salvador Fandino's avatar Salvador Fandino Committed by Mike Gabriel

Provide support for channel endpoints being UNIX file sockets in addition to being TCP/IP sockets.

parent b326eda7
/**************************************************************************/
/* */
/* Copyright (c) 2015 Qindel Formacion y Servicios SL. */
/* */
/* This program is free software; you can redistribute it and/or modify */
/* it under the terms of the GNU General Public License Version 2, as */
/* published by the Free Software Foundation. */
/* */
/* This program is distributed in the hope that it will be useful, but */
/* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTA- */
/* BILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General */
/* Public License for more details. */
/* */
/* You should have received a copy of the GNU General Public License */
/* along with this program; if not, you can request a copy to Qindel */
/* or write to the Free Software Foundation, Inc., 59 Temple Place, Suite */
/* 330, Boston, MA 02111-1307 USA */
/* */
/* All rights reserved. */
/* */
/**************************************************************************/
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include "ChannelEndPoint.h"
#include "NXalert.h"
ChannelEndPoint::ChannelEndPoint(const char *spec)
: defaultTCPPort_(0), defaultTCPInterface_(0),
defaultUnixPath_(NULL) {
spec_ = (spec ? strdup(spec) : NULL);
}
void
ChannelEndPoint::setSpec(const char *spec) {
if (spec_) free(spec_);
if (spec && strlen(spec))
spec_ = strdup(spec);
else
spec_ = NULL;
}
void
ChannelEndPoint::setSpec(int port) {
if (port >= 0) {
char tmp[20];
sprintf(tmp, "%d", port);
setSpec(tmp);
}
else setSpec((char*)NULL);
}
void
ChannelEndPoint::setDefaultTCPPort(long port) {
defaultTCPPort_ = port;
}
void
ChannelEndPoint::setDefaultTCPInterface(int publicInterface) {
defaultTCPInterface_ = publicInterface;
}
void
ChannelEndPoint::setDefaultUnixPath(char *path) {
if (defaultUnixPath_) free(defaultUnixPath_);
if (path && strlen(path))
defaultUnixPath_ = strdup(path);
else
defaultUnixPath_ = NULL;
}
void
ChannelEndPoint::disable() { setSpec("0"); }
bool
ChannelEndPoint::specIsPort(long *port) const {
if (port) *port = 0;
long p = -1;
if (spec_) {
char *end;
p = strtol(spec_, &end, 10);
if ((end == spec_) || (*end != '\0'))
return false;
}
if (port) *port = p;
return true;
}
bool
ChannelEndPoint::getUnixPath(char **unixPath) const {
if (unixPath) *unixPath = 0;
long p;
char *path = NULL;
if (specIsPort(&p)) {
if (p != 1) return false;
}
else if (spec_ && (strncmp("unix:", spec_, 5) == 0)) {
path = spec_ + 5;
}
else
return false;
if (!path || (*path == '\0')) {
path = defaultUnixPath_;
if (!path)
return false;
}
if (unixPath)
*unixPath = strdup(path);
return true;
}
// FIXME!!!
static const char *
getComputerName() {
//
// Strangely enough, under some Windows OSes SMB
// service doesn't bind to localhost. Fall back
// to localhost if can't find computer name in
// the environment. In future we should try to
// bind to localhost and then try the other IPs.
//
const char *hostname = NULL;
#ifdef __CYGWIN32__
hostname = getenv("COMPUTERNAME");
#endif
if (hostname == NULL)
{
hostname = "localhost";
}
return hostname;
}
bool
ChannelEndPoint::getTCPHostAndPort(char **host, long *port) const {
long p;
char *h = NULL;
ssize_t h_len;
if (host) *host = NULL;
if (port) *port = 0;
if (specIsPort(&p)) {
h_len = 0;
}
else if (spec_ && (strncmp("tcp:", spec_, 4) == 0)) {
h = spec_ + 4;
char *colon = strrchr(h, ':');
if (colon) {
char *end;
h_len = colon++ - h;
p = strtol(colon, &end, 10);
if ((end == colon) || (*end != '\0'))
return false;
}
else {
h_len = strlen(h);
p = 1;
}
}
else
return false;
if (p == 1) p = defaultTCPPort_;
if (p < 1) return false;
if (port)
*port = p;
if (host)
*host = ( h_len
? strndup(h, h_len)
: strdup(defaultTCPInterface_ ? getComputerName() : "localhost"));
return true;
}
bool
ChannelEndPoint::enabled() const {
return (getUnixPath() || getTCPHostAndPort());
}
long ChannelEndPoint::getTCPPort() const {
long port;
if (getTCPHostAndPort(NULL, &port)) return port;
return -1;
}
bool
ChannelEndPoint::validateSpec() {
return (specIsPort() || getUnixPath() || getTCPHostAndPort());
}
ChannelEndPoint &ChannelEndPoint::operator=(const ChannelEndPoint &other) {
char *old;
defaultTCPPort_ = other.defaultTCPPort_;
defaultTCPInterface_ = other.defaultTCPInterface_;
old = defaultUnixPath_;
defaultUnixPath_ = (other.defaultUnixPath_ ? strdup(other.defaultUnixPath_) : NULL);
free(old);
old = spec_;
spec_ = (other.spec_ ? strdup(other.spec_) : NULL);
free(old);
return *this;
}
std::ostream& operator<<(std::ostream& os, const ChannelEndPoint& endPoint) {
if (endPoint.enabled()) {
char *unixPath, *host;
long port;
if (endPoint.getUnixPath(&unixPath)) {
os << "unix:" << unixPath;
free(unixPath);
}
else if (endPoint.getTCPHostAndPort(&host, &port)) {
os << "tcp:" << host << ":" << port;
free(host);
}
else {
os << "(invalid)";
}
}
else {
os << "(disabled)";
}
return os;
}
/**************************************************************************/
/* */
/* Copyright (c) 2015 Qindel Formacion y Servicios SL. */
/* */
/* This program is free software; you can redistribute it and/or modify */
/* it under the terms of the GNU General Public License Version 2, as */
/* published by the Free Software Foundation. */
/* */
/* This program is distributed in the hope that it will be useful, but */
/* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTA- */
/* BILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General */
/* Public License for more details. */
/* */
/* You should have received a copy of the GNU General Public License */
/* along with this program; if not, you can request a copy to Qindel */
/* or write to the Free Software Foundation, Inc., 59 Temple Place, Suite */
/* 330, Boston, MA 02111-1307 USA */
/* */
/* All rights reserved. */
/* */
/**************************************************************************/
#ifndef ChannelEndPoint_H
#define ChannelEndPoint_H
#include <iostream>
#include <sys/un.h>
class ChannelEndPoint
{
private:
long defaultTCPPort_;
int defaultTCPInterface_; // 0=localhost, otherwise IP of public interface.
char *defaultUnixPath_;
char *spec_;
bool specIsPort(long *port = NULL) const;
public:
ChannelEndPoint(const char *spec = NULL);
ChannelEndPoint &operator=(const ChannelEndPoint &other);
bool enabled() const;
bool disabled() { return !enabled(); }
void disable();
void setSpec(const char *spec);
void setSpec(int port);
void setDefaultTCPPort(long port);
void setDefaultTCPInterface(int publicInterface);
void setDefaultUnixPath(char *path);
bool getUnixPath(char **path = NULL) const;
bool getTCPHostAndPort(char **hostname = NULL, long *port = NULL) const;
long getTCPPort() const;
bool validateSpec();
};
std::ostream& operator<<(std::ostream& os, const ChannelEndPoint& endPoint);
#endif
......@@ -68,8 +68,11 @@ void ClientProxy::handleDisplayConfiguration(const char *xServerDisplay, int xSe
#endif
}
void ClientProxy::handlePortConfiguration(int cupsServerPort, int smbServerPort, int mediaServerPort,
int httpServerPort, const char *fontServerPort)
void ClientProxy::handlePortConfiguration(ChannelEndPoint &cupsServerPort,
ChannelEndPoint &smbServerPort,
ChannelEndPoint &mediaServerPort,
ChannelEndPoint &httpServerPort,
const char *fontServerPort)
{
delete [] fontServerPort_;
......@@ -141,8 +144,8 @@ int ClientProxy::handleNewConnectionFromProxy(T_channel_type type, int channelId
// Connect on the TCP port number.
//
return handleNewGenericConnectionFromProxy(channelId, channel_font, "localhost",
port, "font");
return handleNewGenericConnectionFromProxyTCP(channelId, channel_font, "localhost",
port, "font");
}
else
{
......@@ -150,7 +153,7 @@ int ClientProxy::handleNewConnectionFromProxy(T_channel_type type, int channelId
// Connect to the Unix path.
//
return handleNewGenericConnectionFromProxy(channelId, channel_font, "localhost",
return handleNewGenericConnectionFromProxyUnix(channelId, channel_font,
fontServerPort_, "font");
}
}
......
......@@ -38,8 +38,11 @@ class ClientProxy : public Proxy
virtual void handleDisplayConfiguration(const char *xServerDisplay, int xServerAddrFamily,
sockaddr *xServerAddr, unsigned int xServerAddrLength);
virtual void handlePortConfiguration(int cupsServerPort, int smbServerPort, int mediaServerPort,
int httpServerPort, const char *fontServerPort);
virtual void handlePortConfiguration(ChannelEndPoint &cupsServerPort,
ChannelEndPoint &smbServerPort,
ChannelEndPoint &mediaServerPort,
ChannelEndPoint &httpServerPort,
const char *fontServerPort);
protected:
......
......@@ -36,7 +36,7 @@
#include <sys/wait.h>
#include <sys/resource.h>
#include <sys/utsname.h>
#include <sys/un.h>
#include <netdb.h>
#include <netinet/in.h>
#include <arpa/inet.h>
......@@ -89,6 +89,7 @@ typedef int socklen_t;
#include "ServerProxy.h"
#include "Message.h"
#include "ChannelEndPoint.h"
//
// System specific defines.
......@@ -437,7 +438,10 @@ static int SetupDisplaySocket(int &xServerAddrFamily, sockaddr *&xServerAddr,
// a new connection.
//
static int ListenConnection(int port, const char *label);
static int ListenConnection(ChannelEndPoint &endPoint, const char *label);
static int ListenConnectionTCP(const char *host, long port, const char *label);
static int ListenConnectionUnix(const char *unixPath, const char *label);
static int ListenConnectionAny(sockaddr *addr, socklen_t addrlen, const char *label);
static int AcceptConnection(int fd, int domain, const char *label);
//
......@@ -475,6 +479,8 @@ static const char *GetArg(int &argi, int argc, const char **argv);
static int CheckArg(const char *type, const char *name, const char *value);
static int ParseArg(const char *type, const char *name, const char *value);
static int ValidateArg(const char *type, const char *name, const char *value);
static void SetAndValidateChannelEndPointArg(const char *type, const char *name, const char *value,
ChannelEndPoint &endPoint);
static int LowercaseArg(const char *type, const char *name, char *value);
static int CheckSignal(int signal);
......@@ -978,12 +984,12 @@ static int connectPort = -1;
// Helper channels are disabled by default.
//
static int cupsPort = -1;
static int auxPort = -1;
static int smbPort = -1;
static int mediaPort = -1;
static int httpPort = -1;
static int slavePort = -1;
static ChannelEndPoint cupsPort;
static ChannelEndPoint auxPort;
static ChannelEndPoint smbPort;
static ChannelEndPoint mediaPort;
static ChannelEndPoint httpPort;
static ChannelEndPoint slavePort;
//
// Can be either a port number or a Unix
......@@ -4474,7 +4480,7 @@ int SetupServiceSockets()
// Since ProtoStep7 (#issue 108)
int port = atoi(fontPort);
if ((fontFD = ListenConnection(port, "font")) < 0)
if ((fontFD = ListenConnectionTCP("localhost", port, "font")) < 0)
{
useFontSocket = 0;
}
......@@ -4504,56 +4510,41 @@ int SetupServiceSockets()
return 1;
}
int ListenConnection(int port, const char *label)
int ListenConnectionAny(sockaddr *addr, socklen_t addrlen, const char *label)
{
sockaddr_in tcpAddr;
unsigned int portTCP = port;
int newFD = socket(AF_INET, SOCK_STREAM, PF_UNSPEC);
int newFD = socket(addr->sa_family, SOCK_STREAM, PF_UNSPEC);
if (newFD == -1)
{
#ifdef PANIC
*logofs << "Loop: PANIC! Call to socket failed for " << label
<< " TCP socket. Error is " << EGET() << " '"
<< " socket. Error is " << EGET() << " '"
<< ESTR() << "'.\n" << logofs_flush;
#endif
cerr << "Error" << ": Call to socket failed for " << label
<< " TCP socket. Error is " << EGET() << " '"
<< " socket. Error is " << EGET() << " '"
<< ESTR() << "'.\n";
goto SetupSocketError;
}
else if (SetReuseAddress(newFD) < 0)
if (SetReuseAddress(newFD) < 0)
{
// SetReuseAddress already warns with an error
goto SetupSocketError;
}
tcpAddr.sin_family = AF_INET;
tcpAddr.sin_port = htons(portTCP);
if ( loopbackBind )
{
tcpAddr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
}
else
{
tcpAddr.sin_addr.s_addr = htonl(INADDR_ANY);
}
if (bind(newFD, (sockaddr *) &tcpAddr, sizeof(tcpAddr)) == -1)
if (bind(newFD, addr, addrlen) == -1)
{
#ifdef PANIC
*logofs << "Loop: PANIC! Call to bind failed for " << label
<< " TCP port " << port << ". Error is " << EGET()
<< ". Error is " << EGET()
<< " '" << ESTR() << "'.\n" << logofs_flush;
#endif
cerr << "Error" << ": Call to bind failed for " << label
<< " TCP port " << port << ". Error is " << EGET()
<< ". Error is " << EGET()
<< " '" << ESTR() << "'.\n";
goto SetupSocketError;
}
......@@ -4561,12 +4552,12 @@ int ListenConnection(int port, const char *label)
{
#ifdef PANIC
*logofs << "Loop: PANIC! Call to bind failed for " << label
<< " TCP port " << port << ". Error is " << EGET()
<< ". Error is " << EGET()
<< " '" << ESTR() << "'.\n" << logofs_flush;
#endif
cerr << "Error" << ": Call to bind failed for " << label
<< " TCP port " << port << ". Error is " << EGET()
<< ". Error is " << EGET()
<< " '" << ESTR() << "'.\n";
goto SetupSocketError;
......@@ -4590,6 +4581,82 @@ SetupSocketError:
//
HandleCleanup();
return -1;
}
int ListenConnectionUnix(const char *path, const char *label)
{
sockaddr_un unixAddr;
unixAddr.sun_family = AF_UNIX;
#ifdef UNIX_PATH_MAX
if (strlen(path) >= UNIX_PATH_MAX)
#else
if (strlen(path) >= sizeof(unixAddr.sun_path))
#endif
{
#ifdef PANIC
*logofs << "Loop: PANIC! Socket path \"" << path << "\" for "
<< label << " is too long.\n" << logofs_flush;
#endif
cerr << "Error" << ": Socket path \"" << path << "\" for "
<< label << " is too long.\n";
HandleCleanup();
return -1;
}
strcpy(unixAddr.sun_path, path);
return ListenConnectionAny((sockaddr *)&unixAddr, sizeof(unixAddr), label);
}
int ListenConnectionTCP(const char *host, long port, const char *label)
{
sockaddr_in tcpAddr;
tcpAddr.sin_family = AF_INET;
tcpAddr.sin_port = htons(port);
if (loopbackBind ||
!host ||
!strcmp(host, "") ||
!strcmp(host, "localhost")) {
tcpAddr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
}
else if(strcmp(host, "*") == 0) {
tcpAddr.sin_addr.s_addr = htonl(INADDR_ANY);
}
else {
int ip = tcpAddr.sin_addr.s_addr = GetHostAddress(host);
if (ip == 0)
{
#ifdef PANIC
*logofs << "Loop: PANIC! Unknown " << label << " host '" << host
<< "'.\n" << logofs_flush;
#endif
cerr << "Error" << ": Unknown " << label << " host '" << host
<< "'.\n";
HandleCleanup();
return -1;
}
}
return ListenConnectionAny((sockaddr *)&tcpAddr, sizeof(tcpAddr), label);
}
int ListenConnection(ChannelEndPoint &endpoint, const char *label)
{
char *unixPath, *host;
long port;
if (endpoint.getUnixPath(&unixPath)) {
return ListenConnectionUnix(unixPath, label);
}
else if (endpoint.getTCPHostAndPort(&host, &port)) {
return ListenConnectionTCP(host, port, label);
}
return -1;
}
static int AcceptConnection(int fd, int domain, const char *label)
......@@ -5521,12 +5588,12 @@ void CleanupLocal()
listenPort = -1;
connectPort = -1;
cupsPort = -1;
auxPort = -1;
smbPort = -1;
mediaPort = -1;
httpPort = -1;
slavePort = -1;
cupsPort.disable();
auxPort.disable();
smbPort.disable();
mediaPort.disable();
httpPort.disable();
slavePort.disable();
*fontPort = '\0';
......@@ -8070,6 +8137,35 @@ int ReadRemoteData(int fd, char *buffer, int size, char stop)
return -1;
}
static int
hexval(char c) {
if ((c >= '0') && (c <= '9'))
return c - '0';
if ((c >= 'a') && (c <= 'f'))
return c - 'a' + 10;
if ((c >= 'A') && (c <= 'F'))
return c - 'A' + 10;
return -1;
}
static void
URLDecodeInPlace(char *str) {
if (str) {
char *to = str;
while (str[0]) {
if ((str[0] == '%') &&
(hexval(str[1]) >= 0) &&
(hexval(str[2]) >= 0)) {
*(to++) = hexval(str[1]) * 16 + hexval(str[2]);
str += 3;
}
else
*(to++) = *(str++);
}
*to = '\0';
}
}
int WriteLocalData(int fd, const char *buffer, int size)
{
int position = 0;
......@@ -8357,6 +8453,7 @@ int ParseEnvironmentOptions(const char *env, int force)
while (name)
{
value = strtok(NULL, ",");
URLDecodeInPlace(value);
if (CheckArg("environment", name, value) < 0)
{
......@@ -8750,7 +8847,7 @@ int ParseEnvironmentOptions(const char *env, int force)
}
else if (strcasecmp(name, "cups") == 0)
{
cupsPort = ValidateArg("local", name, value);
SetAndValidateChannelEndPointArg("local", name, value, cupsPort);
}
else if (strcasecmp(name, "sync") == 0)
{
......@@ -8762,25 +8859,25 @@ int ParseEnvironmentOptions(const char *env, int force)
cerr << "Warning" << ": No 'sync' channel in current version. "
<< "Assuming 'cups' channel.\n";
cupsPort = ValidateArg("local", name, value);
SetAndValidateChannelEndPointArg("local", name, value, cupsPort);
}
else if (strcasecmp(name, "keybd") == 0 ||
strcasecmp(name, "aux") == 0)
{
auxPort = ValidateArg("local", name, value);
SetAndValidateChannelEndPointArg("local", name, value, auxPort);
}
else if (strcasecmp(name, "samba") == 0 ||
strcasecmp(name, "smb") == 0)
{
smbPort = ValidateArg("local", name, value);
SetAndValidateChannelEndPointArg("local", name, value, smbPort);
}
else if (strcasecmp(name, "media") == 0)
{
mediaPort = ValidateArg("local", name, value);
SetAndValidateChannelEndPointArg("local", name, value, mediaPort);
}
else if (strcasecmp(name, "http") == 0)
{
httpPort = ValidateArg("local", name, value);
SetAndValidateChannelEndPointArg("local", name, value, httpPort);
}
else if (strcasecmp(name, "font") == 0)
{
......@@ -8788,7 +8885,7 @@ int ParseEnvironmentOptions(const char *env, int force)
}
else if (strcasecmp(name, "slave") == 0)
{
slavePort = ValidateArg("local", name, value);
SetAndValidateChannelEndPointArg("local", name, value, slavePort);
}
else if (strcasecmp(name, "mask") == 0)
{
......@@ -11515,237 +11612,105 @@ int SetPorts()
// ing, causing a loop.
//
if (cupsPort <= 0)
{
#ifdef TEST
*logofs << "Loop: Disabling cups connections.\n"
<< logofs_flush;
#endif
cupsPort = 0;
useCupsSocket = 0;
}
else
{
if (control -> ProxyMode == proxy_client)
{
if (cupsPort == 1)
{
cupsPort = DEFAULT_NX_CUPS_PORT_OFFSET + proxyPort;
}
useCupsSocket = 0;
if (cupsPort.enabled()) {
if (control -> ProxyMode == proxy_client) {
cupsPort.setDefaultTCPPort(DEFAULT_NX_CUPS_PORT_OFFSET + proxyPort);
useCupsSocket = 1;
}
else
{
if (cupsPort == 1)
{
//
// Use the well-known 631/tcp port of the
// Internet Printing Protocol.
//
cupsPort = 631;
}
useCupsSocket = 0;
}
#ifdef TEST
*logofs << "Loop: Using cups port '" << cupsPort
<< "'.\n" << logofs_flush;
#endif
cupsPort.setDefaultTCPPort(631);
}
if (auxPort <= 0)
{
#ifdef TEST
*logofs << "Loop: Disabling auxiliary X11 connections.\n"
#ifdef TEST
*logofs << "Loop: cups port: " << cupsPort->getDebugSpec() << "\n"
<< logofs_flush;
#endif
auxPort = 0;
useAuxSocket = 0;
}
else
{
if (control -> ProxyMode == proxy_client)
{
if (auxPort == 1)
{
auxPort = DEFAULT_NX_AUX_PORT_OFFSET + proxyPort;
}
#endif
useAuxSocket = 0;
if (auxPort.enabled()) {
if (control -> ProxyMode == proxy_client) {
auxPort.setDefaultTCPPort(DEFAULT_NX_AUX_PORT_OFFSET + proxyPort);
useAuxSocket = 1;
}
else
{
//
// Auxiliary X connections are always forwarded
// to the display where the session is running.
// The only value accepted is 1.
//
else {
auxPort.setDefaultTCPPort(1);
if (auxPort != 1)
{
#ifdef WARNING
if (auxPort.getTCPPort() != 1) {
#ifdef WARNING
*logofs << "Loop: WARNING! Overriding auxiliary X11 "
<< "port with new value '" << 1 << "'.\n"
<< logofs_flush;
#endif
#endif
cerr << "Warning" << ": Overriding auxiliary X11 "
<< "port with new value '" << 1 << "'.\n";
auxPort = 1;
auxPort.setSpec("1");
}
useAuxSocket = 0;
}
#ifdef TEST
*logofs << "Loop: Using auxiliary X11 port '" << auxPort
<< "'.\n" << logofs_flush;
#endif
}
if (smbPort <= 0)
{
#ifdef TEST
*logofs << "Loop: Disabling SMB connections.\n"
<< logofs_flush;
#endif
smbPort = 0;
useSmbSocket = 0;
}
else
{
if (control -> ProxyMode == proxy_client)
{
if (smbPort == 1)
{
smbPort = DEFAULT_NX_SMB_PORT_OFFSET + proxyPort;
}
#ifdef TEST
*logofs << "Loop: aux port: " << auxPort->getDebugSpec() << "\n"
<< logofs_flush;
#endif
useSmbSocket = 1;
useSmbSocket = 0;
if (smbPort.enabled()) {
if (control -> ProxyMode == proxy_client) {
auxPort.setDefaultTCPPort(DEFAULT_NX_SMB_PORT_OFFSET + proxyPort);
useAuxSocket = 1;
}
else
{
if (smbPort == 1)
{
//
// Assume the 139/tcp port used for SMB
// over NetBIOS over TCP.
//
smbPort = 139;
}
useSmbSocket = 0;
}
#ifdef TEST
*logofs << "Loop: Using SMB port '" << smbPort
<< "'.\n" << logofs_flush;
#endif
auxPort.setDefaultTCPPort(139);
}
if (mediaPort <= 0)
{
#ifdef TEST
*logofs << "Loop: Disabling multimedia connections.\n"
<< logofs_flush;
#endif
mediaPort = 0;
useMediaSocket = 0;
}
else
{
if (control -> ProxyMode == proxy_client)
{
if (mediaPort == 1)
{
mediaPort = DEFAULT_NX_MEDIA_PORT_OFFSET + proxyPort;
}
#ifdef TEST
*logofs << "Loop: smb port: " << smbPort->getDebugSpec() << "\n"
<< logofs_flush;
#endif
useMediaSocket = 0;
if (mediaPort.enabled()) {
if (control -> ProxyMode == proxy_client) {
mediaPort.setDefaultTCPPort(DEFAULT_NX_MEDIA_PORT_OFFSET + proxyPort);
useMediaSocket = 1;
}
else
{
if (mediaPort == 1)
{
//
// We don't have a well-known port to
// be used for media connections.
//
#ifdef PANIC
*logofs << "Loop: PANIC! No port specified for multimedia connections.\n"
<< logofs_flush;
#endif
else if (mediaPort.getTCPPort() == 1) {
#ifdef PANIC
*logofs << "Loop: PANIC! No port specified for multimedia connections.\n"
<< logofs_flush;
#endif
cerr << "Error" << ": No port specified for multimedia connections.\n";
cerr << "Error" << ": No port specified for multimedia connections.\n";
HandleCleanup();
}
useMediaSocket = 0;
HandleCleanup();
}
#ifdef TEST
*logofs << "Loop: Using multimedia port '" << mediaPort
<< "'.\n" << logofs_flush;
#endif
}
if (httpPort <= 0)
{
#ifdef TEST
*logofs << "Loop: Disabling HTTP connections.\n"
<< logofs_flush;
#endif
httpPort = 0;
useHttpSocket = 0;
}
else
{
if (control -> ProxyMode == proxy_client)
{
if (httpPort == 1)
{
httpPort = DEFAULT_NX_HTTP_PORT_OFFSET + proxyPort;
}
#ifdef TEST
*logofs << "Loop: Using multimedia port '" << mediaPort->getDebugSpec()
<< "'.\n" << logofs_flush;
#endif
useHttpSocket = 0;
if (httpPort.enabled()) {
if (control -> ProxyMode == proxy_client) {
httpPort.setDefaultTCPPort(DEFAULT_NX_HTTP_PORT_OFFSET + proxyPort);
useHttpSocket = 1;
}
else
{
if (httpPort == 1)
{
//
// Use the well-known 80/tcp port.
//
httpPort = 80;
}
useHttpSocket = 0;
}
#ifdef TEST
*logofs << "Loop: Using HTTP port '" << httpPort
<< "'.\n" << logofs_flush;
#endif
httpPort.setDefaultTCPPort(80);
}
#ifdef TEST
*logofs << "Loop: Using HTTP port '" << httpPort->getDebugSpec()
<< "'.\n" << logofs_flush;
#endif
if (ParseFontPath(fontPort) <= 0)
{
#ifdef TEST
......@@ -11781,44 +11746,20 @@ int SetPorts()
#endif
}
if (slavePort <= 0)
{
#ifdef TEST
*logofs << "Loop: Disabling slave connections.\n"
<< logofs_flush;
#endif
slavePort = 0;
useSlaveSocket = 0;
}
else
{
//
// File transfer connections can
// be originated by both sides.
//
if (slavePort == 1)
{
if (control -> ProxyMode == proxy_client)
{
slavePort = DEFAULT_NX_SLAVE_PORT_CLIENT_OFFSET + proxyPort;
}
else
{
slavePort = DEFAULT_NX_SLAVE_PORT_SERVER_OFFSET + proxyPort;
}
}
useSlaveSocket = 0;
if (slavePort.enabled()) {
useSlaveSocket = 1;
#ifdef TEST
*logofs << "Loop: Using slave port '" << slavePort
<< "'.\n" << logofs_flush;
#endif
if (control -> ProxyMode == proxy_client)
slavePort.setDefaultTCPPort(DEFAULT_NX_SLAVE_PORT_CLIENT_OFFSET + proxyPort);
else
slavePort.setDefaultTCPPort(DEFAULT_NX_SLAVE_PORT_SERVER_OFFSET + proxyPort);
}
#ifdef TEST
*logofs << "Loop: Using slave port '" << slavePort->getDebugSpec()
<< "'.\n" << logofs_flush;
#endif
return 1;
}
......@@ -14109,65 +14050,65 @@ void PrintConnectionInfo()
}
if (control -> ProxyMode == proxy_client &&
useCupsSocket > 0 && cupsPort > 0)
useCupsSocket > 0 && cupsPort.enabled())
{
cerr << "Info" << ": Listening to CUPS connections "
<< "on port '" << cupsPort << "'.\n";
}
else if (control -> ProxyMode == proxy_server &&
cupsPort > 0)
cupsPort.enabled())
{
cerr << "Info" << ": Forwarding CUPS connections "
<< "to port '" << cupsPort << "'.\n";
}
if (control -> ProxyMode == proxy_client &&
useAuxSocket > 0 && auxPort > 0)
useAuxSocket > 0 && auxPort.enabled())
{
cerr << "Info" << ": Listening to auxiliary X11 connections "
<< "on port '" << auxPort << "'.\n";
}
else if (control -> ProxyMode == proxy_server &&
auxPort > 0)
auxPort.enabled())
{
cerr << "Info" << ": Forwarding auxiliary X11 connections "
<< "to display '" << displayHost << "'.\n";
}
if (control -> ProxyMode == proxy_client &&
useSmbSocket > 0 && smbPort > 0)
useSmbSocket > 0 && smbPort.enabled())
{
cerr << "Info" << ": Listening to SMB connections "
<< "on port '" << smbPort << "'.\n";
}
else if (control -> ProxyMode == proxy_server &&
smbPort > 0)
smbPort.enabled())
{
cerr << "Info" << ": Forwarding SMB connections "
<< "to port '" << smbPort << "'.\n";
}
if (control -> ProxyMode == proxy_client &&
useMediaSocket > 0 && mediaPort > 0)
useMediaSocket > 0 && mediaPort.enabled())
{
cerr << "Info" << ": Listening to multimedia connections "
<< "on port '" << mediaPort << "'.\n";
}
else if (control -> ProxyMode == proxy_server &&
mediaPort > 0)
mediaPort.enabled())
{
cerr << "Info" << ": Forwarding multimedia connections "
<< "to port '" << mediaPort << "'.\n";
}
if (control -> ProxyMode == proxy_client &&
useHttpSocket > 0 && httpPort > 0)
useHttpSocket > 0 && httpPort.enabled())
{
cerr << "Info" << ": Listening to HTTP connections "
<< "on port '" << httpPort << "'.\n";
}
else if (control -> ProxyMode == proxy_server &&
httpPort > 0)
httpPort.enabled())
{
cerr << "Info" << ": Forwarding HTTP connections "
<< "to port '" << httpPort << "'.\n";
......@@ -14186,7 +14127,7 @@ void PrintConnectionInfo()
<< "to port '" << fontPort << "'.\n";
}
if (useSlaveSocket > 0 && slavePort > 0)
if (useSlaveSocket > 0 && slavePort.enabled())
{
cerr << "Info" << ": Listening to slave connections "
<< "on port '" << slavePort << "'.\n";
......@@ -14443,6 +14384,25 @@ int ParseArg(const char *type, const char *name, const char *value)
return (int) result;
}
void SetAndValidateChannelEndPointArg(const char *type, const char *name, const char *value,
ChannelEndPoint &endPoint) {
endPoint.setSpec(value);
if (!endPoint.validateSpec()) {
#ifdef PANIC
*logofs << "Loop: PANIC! Invalid " << type
<< " option '" << name << "' with value '"
<< value << "'.\n" << logofs_flush;
#endif
cerr << "Error" << ": Invalid " << type
<< " option '" << name << "' with value '"
<< value << "'.\n";
HandleCleanup();
}
}
int ValidateArg(const char *type, const char *name, const char *value)
{
int number = atoi(value);
......
......@@ -149,6 +149,7 @@ CXXSRC = Loop.cpp \
ClientChannel.cpp \
ServerChannel.cpp \
GenericChannel.cpp \
ChannelEndPoint.cpp \
ReadBuffer.cpp \
ProxyReadBuffer.cpp \
ClientReadBuffer.cpp \
......
......@@ -65,6 +65,7 @@ struct sockaddr_un
#include "ClientChannel.h"
#include "ServerChannel.h"
#include "GenericChannel.h"
#include "ChannelEndPoint.h"
//
// We need to adjust some values related
......@@ -6053,8 +6054,36 @@ int Proxy::handleNewSlaveConnection(int clientFd)
return handleNewGenericConnection(clientFd, channel_slave, "slave");
}
int Proxy::handleNewGenericConnectionFromProxy(int channelId, T_channel_type type,
const char *hostname, int port, const char *label)
ChannelEndPoint &endPoint, const char *label)
{
char *unixPath, *host;
long port;
if (endPoint.getUnixPath(&unixPath)) {
return handleNewGenericConnectionFromProxyUnix(channelId, type, unixPath, label);
}
if (endPoint.getTCPHostAndPort(&host, &port)) {
return handleNewGenericConnectionFromProxyTCP(channelId, type, host, port, label);
}
#ifdef WARNING
*logofs << "Proxy: WARNING! Refusing attempted connection "
<< "to " << label << " server.\n" << logofs_flush;
#endif
cerr << "Warning" << ": Refusing attempted connection "
<< "to " << label << " server.\n";
return -1;
}
int Proxy::handleNewGenericConnectionFromProxyTCP(int channelId, T_channel_type type,
const char *hostname, long port, const char *label)
{
if (port <= 0)
{
......@@ -6173,8 +6202,8 @@ int Proxy::handleNewGenericConnectionFromProxy(int channelId, T_channel_type typ
return 1;
}
int Proxy::handleNewGenericConnectionFromProxy(int channelId, T_channel_type type,
const char *hostname, const char *path, const char *label)
int Proxy::handleNewGenericConnectionFromProxyUnix(int channelId, T_channel_type type,
const char *path, const char *label)
{
if (path == NULL || *path == '\0' )
{
......
......@@ -32,6 +32,7 @@
#include "Transport.h"
#include "EncodeBuffer.h"
#include "ProxyReadBuffer.h"
#include "ChannelEndPoint.h"
//
// Forward declaration as we
......@@ -258,8 +259,11 @@ class Proxy
virtual void handleDisplayConfiguration(const char *xServerDisplay, int xServerAddrFamily,
sockaddr * xServerAddr, unsigned int xServerAddrLength) = 0;
virtual void handlePortConfiguration(int cupsServerPort, int smbServerPort, int mediaServerPort,
int httpServerPort, const char *fontServerPort) = 0;
virtual void handlePortConfiguration(ChannelEndPoint &cupsServerPort,
ChannelEndPoint &smbServerPort,
ChannelEndPoint &mediaServerPort,
ChannelEndPoint &httpServerPort,
const char *fontServerPort) = 0;
//
// Create new tunneled channels.
......@@ -278,10 +282,13 @@ class Proxy
int handleNewGenericConnection(int clientFd, T_channel_type type, const char *label);
int handleNewGenericConnectionFromProxy(int channelId, T_channel_type type,
const char *hostname, int port, const char *label);
ChannelEndPoint &endpoint, const char *label);
int handleNewGenericConnectionFromProxy(int channelId, T_channel_type type,
const char *hostname, const char *path, const char *label);
int handleNewGenericConnectionFromProxyUnix(int channelId, T_channel_type type,
const char *path, const char *label);
int handleNewGenericConnectionFromProxyTCP(int channelId, T_channel_type type,
const char *hostname, long port, const char *label);
int handleNewSlaveConnection(int clientFd);
......
/**************************************************************************/
/* */
/* Copyright (c) 2001, 2011 NoMachine, http://www.nomachine.com/. */
/* Copyright (c) 2015 Qindel Formacion y Servicios S.L. */
/* */
/* NXCOMP, NX protocol compression and NX extensions to this software */
/* are copyright of NoMachine. Redistribution and use of the present */
......@@ -51,10 +52,10 @@ ServerProxy::ServerProxy(int proxyFd) : Proxy(proxyFd)
xServerAddr_ = NULL;
xServerDisplay_ = NULL;
cupsServerPort_ = -1;
smbServerPort_ = -1;
mediaServerPort_ = -1;
httpServerPort_ = -1;
cupsServerPort_ = NULL;
smbServerPort_ = NULL;
mediaServerPort_ = NULL;
httpServerPort_ = NULL;
fontServerPort_ = NULL;
......@@ -101,8 +102,11 @@ void ServerProxy::handleDisplayConfiguration(const char *xServerDisplay, int xSe
#endif
}
void ServerProxy::handlePortConfiguration(int cupsServerPort, int smbServerPort, int mediaServerPort,
int httpServerPort, const char *fontServerPort)
void ServerProxy::handlePortConfiguration(ChannelEndPoint &cupsServerPort,
ChannelEndPoint &smbServerPort,
ChannelEndPoint &mediaServerPort,
ChannelEndPoint &httpServerPort,
const char *fontServerPort)
{
cupsServerPort_ = cupsServerPort;
smbServerPort_ = smbServerPort;
......@@ -161,22 +165,23 @@ int ServerProxy::handleNewConnectionFromProxy(T_channel_type type, int channelId
}
case channel_cups:
{
return handleNewGenericConnectionFromProxy(channelId, channel_cups, "localhost",
return handleNewGenericConnectionFromProxy(channelId, channel_cups,
cupsServerPort_, "CUPS");
}
case channel_smb:
{
return handleNewGenericConnectionFromProxy(channelId, channel_smb, getComputerName(),
smbServerPort_.setDefaultTCPInterface(1);
return handleNewGenericConnectionFromProxy(channelId, channel_smb,
smbServerPort_, "SMB");
}
case channel_media:
{
return handleNewGenericConnectionFromProxy(channelId, channel_media, "localhost",
return handleNewGenericConnectionFromProxy(channelId, channel_media,
mediaServerPort_, "media");
}
case channel_http:
{
return handleNewGenericConnectionFromProxy(channelId, channel_http, getComputerName(),
return handleNewGenericConnectionFromProxy(channelId, channel_http,
httpServerPort_, "HTTP");
}
case channel_slave:
......
......@@ -24,6 +24,7 @@
#include "Proxy.h"
#include "Misc.h"
#include "ChannelEndPoint.h"
//
// Set the verbosity level.
......@@ -43,8 +44,11 @@ class ServerProxy : public Proxy
virtual void handleDisplayConfiguration(const char *xServerDisplay, int xServerAddrFamily,
sockaddr *xServerAddr, unsigned int xServerAddrLength);
virtual void handlePortConfiguration(int cupsServerPort, int smbServerPort, int mediaServerPort,
int httpServerPort, const char *fontServerPort);
virtual void handlePortConfiguration(ChannelEndPoint &cupsServerPort,
ChannelEndPoint &smbServerPort,
ChannelEndPoint &mediaServerPort,
ChannelEndPoint &httpServerPort,
const char *fontServerPort);
protected:
......@@ -108,6 +112,7 @@ class ServerProxy : public Proxy
private:
// FIXME: Use a ChannelEndPoint object also for the X server!
int xServerAddrFamily_;
sockaddr *xServerAddr_;
unsigned int xServerAddrLength_;
......@@ -124,10 +129,10 @@ class ServerProxy : public Proxy
// TCP connections.
//
int cupsServerPort_;
int smbServerPort_;
int mediaServerPort_;
int httpServerPort_;
ChannelEndPoint cupsServerPort_;
ChannelEndPoint smbServerPort_;
ChannelEndPoint mediaServerPort_;
ChannelEndPoint httpServerPort_;
//
// It will have to be passed to the channel
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment