1a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat/*
2a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat   Copyright (C) 2002-2010 Karl J. Runge <runge@karlrunge.com>
3a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat   All rights reserved.
4a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
5a430b2b5ca4f0967836f5820e8f03adc17fc0a24San MehatThis file is part of x11vnc.
6a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
7a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehatx11vnc is free software; you can redistribute it and/or modify
8a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehatit under the terms of the GNU General Public License as published by
9a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehatthe Free Software Foundation; either version 2 of the License, or (at
10a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehatyour option) any later version.
11a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
12a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehatx11vnc is distributed in the hope that it will be useful,
13a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehatbut WITHOUT ANY WARRANTY; without even the implied warranty of
14a430b2b5ca4f0967836f5820e8f03adc17fc0a24San MehatMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15a430b2b5ca4f0967836f5820e8f03adc17fc0a24San MehatGNU General Public License for more details.
16a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
17a430b2b5ca4f0967836f5820e8f03adc17fc0a24San MehatYou should have received a copy of the GNU General Public License
18a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehatalong with x11vnc; if not, write to the Free Software
19a430b2b5ca4f0967836f5820e8f03adc17fc0a24San MehatFoundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA
20a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehator see <http://www.gnu.org/licenses/>.
21a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
22a430b2b5ca4f0967836f5820e8f03adc17fc0a24San MehatIn addition, as a special exception, Karl J. Runge
23a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehatgives permission to link the code of its release of x11vnc with the
24a430b2b5ca4f0967836f5820e8f03adc17fc0a24San MehatOpenSSL project's "OpenSSL" library (or with modified versions of it
25a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehatthat use the same license as the "OpenSSL" library), and distribute
26a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehatthe linked executables.  You must obey the GNU General Public License
27a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehatin all respects for all of the code used other than "OpenSSL".  If you
28a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehatmodify this file, you may extend this exception to your version of the
29a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehatfile, but you are not obligated to do so.  If you do not wish to do
30a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehatso, delete this exception statement from your version.
31a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat*/
32a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
33a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat/* -- inet.c -- */
34a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
35a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#include "x11vnc.h"
36a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#include "unixpw.h"
37a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#include "sslhelper.h"
38a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
39a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat/*
40a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat * Simple utility to map host name to dotted IP address.  Ignores aliases.
41a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat * Up to caller to free returned string.
42a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat */
43a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehatchar *host2ip(char *host);
44a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehatchar *raw2host(char *raw, int len);
45a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehatchar *raw2ip(char *raw);
46a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehatchar *ip2host(char *ip);
47a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehatint ipv6_ip(char *host);
48a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehatint dotted_ip(char *host, int partial);
49a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehatint get_remote_port(int sock);
50a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehatint get_local_port(int sock);
51a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehatchar *get_remote_host(int sock);
52a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehatchar *get_local_host(int sock);
53a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehatchar *ident_username(rfbClientPtr client);
54a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehatint find_free_port(int start, int end);
55a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehatint find_free_port6(int start, int end);
56a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehatint have_ssh_env(void);
57a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehatchar *ipv6_getnameinfo(struct sockaddr *paddr, int addrlen);
58a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehatchar *ipv6_getipaddr(struct sockaddr *paddr, int addrlen);
59a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehatint listen6(int port);
60a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehatint listen_unix(char *file);
61a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehatint accept_unix(int s);
62a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehatint connect_tcp(char *host, int port);
63a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehatint listen_tcp(int port, in_addr_t iface, int try6);
64a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
65a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehatstatic int get_port(int sock, int remote);
66a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehatstatic char *get_host(int sock, int remote);
67a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
68a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehatchar *host2ip(char *host) {
69a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	struct hostent *hp;
70a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	struct sockaddr_in addr;
71a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	char *str;
72a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
73a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	if (! host_lookup) {
74a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		return NULL;
75a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	}
76a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
77a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	hp = gethostbyname(host);
78a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	if (!hp) {
79a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		return NULL;
80a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	}
81a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	memset(&addr, 0, sizeof(addr));
82a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	addr.sin_family = AF_INET;
83a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	addr.sin_addr.s_addr =  *(unsigned long *)hp->h_addr;
84a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	str = strdup(inet_ntoa(addr.sin_addr));
85a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	return str;
86a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat}
87a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
88a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehatchar *raw2host(char *raw, int len) {
89a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	char *str;
90a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#if LIBVNCSERVER_HAVE_NETDB_H && LIBVNCSERVER_HAVE_NETINET_IN_H
91a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	struct hostent *hp;
92a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
93a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	if (! host_lookup) {
94a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		return strdup("unknown");
95a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	}
96a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
97a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	hp = gethostbyaddr(raw, len, AF_INET);
98a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	if (!hp) {
99a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		return strdup(inet_ntoa(*((struct in_addr *)raw)));
100a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	}
101a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	str = strdup(hp->h_name);
102a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#else
103a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	str = strdup("unknown");
104a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#endif
105a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	return str;
106a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat}
107a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
108a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehatchar *raw2ip(char *raw) {
109a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	return strdup(inet_ntoa(*((struct in_addr *)raw)));
110a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat}
111a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
112a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehatchar *ip2host(char *ip) {
113a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	char *str;
114a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#if LIBVNCSERVER_HAVE_NETDB_H && LIBVNCSERVER_HAVE_NETINET_IN_H
115a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	struct hostent *hp;
116a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	in_addr_t iaddr;
117a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
118a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	if (! host_lookup) {
119a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		return strdup("unknown");
120a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	}
121a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
122a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	iaddr = inet_addr(ip);
123a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	if (iaddr == htonl(INADDR_NONE)) {
124a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		return strdup("unknown");
125a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	}
126a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
127a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	hp = gethostbyaddr((char *)&iaddr, sizeof(in_addr_t), AF_INET);
128a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	if (!hp) {
129a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		return strdup("unknown");
130a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	}
131a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	str = strdup(hp->h_name);
132a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#else
133a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	str = strdup("unknown");
134a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#endif
135a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	return str;
136a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat}
137a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
138a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehatint ipv6_ip(char *host_in) {
139a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	char *p, *host, a[2];
140a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	int ncol = 0, nhex = 0;
141a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
142a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	if (host_in[0] == '[')  {
143a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		host = host_in + 1;
144a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	} else {
145a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		host = host_in;
146a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	}
147a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
148a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	if (strstr(host, "::ffff:") == host || strstr(host, "::FFFF:") == host) {
149a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		return dotted_ip(host + strlen("::ffff:"), 0);
150a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	}
151a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
152a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	a[1] = '\0';
153a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
154a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	p = host;
155a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	while (*p != '\0' && *p != '%' && *p != ']') {
156a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		if (*p == ':') {
157a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat			ncol++;
158a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		} else {
159a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat			nhex++;
160a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		}
161a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		a[0] = *p;
162a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		if (strpbrk(a, ":abcdef0123456789") == a) {
163a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat			p++;
164a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat			continue;
165a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		}
166a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		return 0;
167a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	}
168a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	if (ncol < 2 || ncol > 8 || nhex == 0) {
169a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		return 0;
170a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	} else {
171a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		return 1;
172a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	}
173a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat}
174a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
175a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehatint dotted_ip(char *host, int partial) {
176a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	int len, dots = 0;
177a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	char *p = host;
178a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
179a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	if (!host) {
180a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		return 0;
181a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	}
182a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
183a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	if (!isdigit((unsigned char) host[0])) {
184a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		return 0;
185a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	}
186a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
187a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	len = strlen(host);
188a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	if (!partial && !isdigit((unsigned char) host[len-1])) {
189a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		return 0;
190a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	}
191a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
192a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	while (*p != '\0') {
193a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		if (*p == '.') dots++;
194a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		if (*p == '.' || isdigit((unsigned char) (*p))) {
195a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat			p++;
196a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat			continue;
197a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		}
198a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		return 0;
199a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	}
200a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	if (!partial && dots != 3) {
201a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		return 0;
202a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	}
203a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	return 1;
204a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat}
205a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
206a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehatstatic int get_port(int sock, int remote) {
207a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	struct sockaddr_in saddr;
208a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	unsigned int saddr_len;
209a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	int saddr_port;
210a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
211a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	saddr_len = sizeof(saddr);
212a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	memset(&saddr, 0, sizeof(saddr));
213a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	saddr_port = -1;
214a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	if (remote) {
215a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		if (!getpeername(sock, (struct sockaddr *)&saddr, &saddr_len)) {
216a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat			saddr_port = ntohs(saddr.sin_port);
217a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		}
218a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	} else {
219a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		if (!getsockname(sock, (struct sockaddr *)&saddr, &saddr_len)) {
220a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat			saddr_port = ntohs(saddr.sin_port);
221a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		}
222a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	}
223a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	return saddr_port;
224a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat}
225a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
226a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehatint get_remote_port(int sock) {
227a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	return get_port(sock, 1);
228a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat}
229a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
230a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehatint get_local_port(int sock) {
231a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	return get_port(sock, 0);
232a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat}
233a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
234a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehatstatic char *get_host(int sock, int remote) {
235a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	struct sockaddr_in saddr;
236a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	unsigned int saddr_len;
237a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	int saddr_port;
238a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	char *saddr_ip_str = NULL;
239a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
240a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	saddr_len = sizeof(saddr);
241a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	memset(&saddr, 0, sizeof(saddr));
242a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	saddr_port = -1;
243a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#if LIBVNCSERVER_HAVE_NETINET_IN_H
244a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	if (remote) {
245a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		if (!getpeername(sock, (struct sockaddr *)&saddr, &saddr_len)) {
246a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat			saddr_ip_str = inet_ntoa(saddr.sin_addr);
247a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		}
248a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	} else {
249a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		if (!getsockname(sock, (struct sockaddr *)&saddr, &saddr_len)) {
250a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat			saddr_ip_str = inet_ntoa(saddr.sin_addr);
251a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		}
252a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	}
253a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#endif
254a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	if (! saddr_ip_str) {
255a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		saddr_ip_str = "unknown";
256a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	}
257a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	return strdup(saddr_ip_str);
258a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat}
259a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
260a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehatchar *get_remote_host(int sock) {
261a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	return get_host(sock, 1);
262a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat}
263a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
264a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehatchar *get_local_host(int sock) {
265a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	return get_host(sock, 0);
266a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat}
267a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
268a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehatchar *ident_username(rfbClientPtr client) {
269a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	ClientData *cd = (ClientData *) client->clientData;
270a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	char *str, *newhost, *user = NULL, *newuser = NULL;
271a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	int len;
272a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
273a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	if (cd) {
274a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		user = cd->username;
275a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	}
276a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	if (!user || *user == '\0') {
277a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		int n, sock, ok = 0;
278a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		int block = 0;
279a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		int refused = 0;
280a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
281a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		/*
282a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		 * need to check to see if the operation will block for
283a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		 * a long time: a firewall may just ignore our packets.
284a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		 */
285a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#if LIBVNCSERVER_HAVE_FORK
286a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	    {	pid_t pid, pidw;
287a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		int rc;
288a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		if ((pid = fork()) > 0) {
289a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat			usleep(100 * 1000);	/* 0.1 sec for quick success or refusal */
290a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat			pidw = waitpid(pid, &rc, WNOHANG);
291a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat			if (pidw <= 0) {
292a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat				usleep(1500 * 1000);	/* 1.5 sec */
293a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat				pidw = waitpid(pid, &rc, WNOHANG);
294a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat				if (pidw <= 0) {
295a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat					int rc2;
296a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat					rfbLog("ident_username: set block=1 (hung)\n");
297a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat					block = 1;
298a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat					kill(pid, SIGTERM);
299a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat					usleep(100 * 1000);
300a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat					waitpid(pid, &rc2, WNOHANG);
301a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat				}
302a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat			}
303a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat			if (pidw > 0 && !block) {
304a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat				if (WIFEXITED(rc) && WEXITSTATUS(rc) == 1) {
305a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat					rfbLog("ident_username: set refused=1 (exit)\n");
306a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat					refused = 1;
307a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat				}
308a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat			}
309a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		} else if (pid == -1) {
310a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat			;
311a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		} else {
312a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat			/* child */
313a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat			signal(SIGHUP,  SIG_DFL);
314a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat			signal(SIGINT,  SIG_DFL);
315a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat			signal(SIGQUIT, SIG_DFL);
316a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat			signal(SIGTERM, SIG_DFL);
317a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
318a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat			if ((sock = connect_tcp(client->host, 113)) < 0) {
319a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat				exit(1);
320a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat			} else {
321a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat				close(sock);
322a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat				exit(0);
323a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat			}
324a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		}
325a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	    }
326a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#endif
327a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		if (block || refused) {
328a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat			;
329a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		} else if ((sock = connect_tcp(client->host, 113)) < 0) {
330a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat			rfbLog("ident_username: could not connect to ident: %s:%d\n",
331a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat			    client->host, 113);
332a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		} else {
333a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat			char msg[128];
334a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat			int ret;
335a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat			fd_set rfds;
336a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat			struct timeval tv;
337a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat			int rport = get_remote_port(client->sock);
338a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat			int lport = get_local_port(client->sock);
339a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
340a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat			sprintf(msg, "%d, %d\r\n", rport, lport);
341a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat			n = write(sock, msg, strlen(msg));
342a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
343a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat			FD_ZERO(&rfds);
344a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat			FD_SET(sock, &rfds);
345a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat			tv.tv_sec  = 3;
346a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat			tv.tv_usec = 0;
347a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat			ret = select(sock+1, &rfds, NULL, NULL, &tv);
348a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
349a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat			if (ret > 0) {
350a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat				int i;
351a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat				char *q, *p;
352a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat				for (i=0; i < (int) sizeof(msg); i++) {
353a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat					msg[i] = '\0';
354a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat				}
355a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat				usleep(250*1000);
356a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat				n = read(sock, msg, 127);
357a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat				close(sock);
358a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat				if (n <= 0) goto badreply;
359a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
360a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat				/* 32782 , 6000 : USERID : UNIX :runge */
361a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat				q = strstr(msg, "USERID");
362a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat				if (!q) goto badreply;
363a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat				q = strstr(q, ":");
364a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat				if (!q) goto badreply;
365a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat				q++;
366a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat				q = strstr(q, ":");
367a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat				if (!q) goto badreply;
368a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat				q++;
369a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat				q = lblanks(q);
370a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat				p = q;
371a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat				while (*p) {
372a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat					if (*p == '\r' || *p == '\n') {
373a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat						*p = '\0';
374a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat					}
375a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat					p++;
376a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat				}
377a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat				ok = 1;
378a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat				if (strlen(q) > 24) {
379a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat					*(q+24) = '\0';
380a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat				}
381a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat				newuser = strdup(q);
382a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
383a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat				badreply:
384a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat				n = 0;	/* avoid syntax error */
385a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat			} else {
386a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat				close(sock);
387a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat			}
388a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		}
389a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		if (! ok || !newuser) {
390a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat			newuser = strdup("unknown-user");
391a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		}
392a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		if (cd) {
393a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat			if (cd->username) {
394a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat				free(cd->username);
395a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat			}
396a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat			cd->username = newuser;
397a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		}
398a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		user = newuser;
399a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	}
400a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	if (!strcmp(user, "unknown-user") && cd && cd->unixname[0] != '\0') {
401a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		user = cd->unixname;
402a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	}
403a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	if (unixpw && openssl_last_ip && strstr("UNIX:", user) != user) {
404a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		newhost = ip2host(openssl_last_ip);
405a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	} else {
406a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		newhost = ip2host(client->host);
407a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	}
408a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	len = strlen(user) + 1 + strlen(newhost) + 1;
409a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	str = (char *) malloc(len);
410a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	sprintf(str, "%s@%s", user, newhost);
411a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	free(newhost);
412a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	return str;
413a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat}
414a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
415a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehatint find_free_port(int start, int end) {
416a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	int port;
417a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	if (start <= 0) {
418a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		start = 1024;
419a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	}
420a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	if (end <= 0) {
421a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		end = 65530;
422a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	}
423a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	for (port = start; port <= end; port++)  {
424a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		int sock = listen_tcp(port, htonl(INADDR_ANY), 0);
425a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		if (sock >= 0) {
426a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat			close(sock);
427a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat			return port;
428a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		}
429a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	}
430a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	return 0;
431a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat}
432a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
433a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehatint find_free_port6(int start, int end) {
434a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	int port;
435a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	if (start <= 0) {
436a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		start = 1024;
437a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	}
438a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	if (end <= 0) {
439a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		end = 65530;
440a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	}
441a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	for (port = start; port <= end; port++)  {
442a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		int sock = listen6(port);
443a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		if (sock >= 0) {
444a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat			close(sock);
445a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat			return port;
446a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		}
447a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	}
448a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	return 0;
449a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat}
450a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
451a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehatint have_ssh_env(void) {
452a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	char *str, *p = getenv("SSH_CONNECTION");
453a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	char *rhost, *rport, *lhost, *lport;
454a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
455a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	if (! p) {
456a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		char *q = getenv("SSH_CLIENT");
457a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		if (! q) {
458a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat			return 0;
459a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		}
460a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		if (strstr(q, "127.0.0.1") != NULL) {
461a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat			return 0;
462a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		}
463a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		return 1;
464a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	}
465a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
466a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	if (strstr(p, "127.0.0.1") != NULL) {
467a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		return 0;
468a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	}
469a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
470a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	str = strdup(p);
471a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
472a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	p = strtok(str, " ");
473a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	rhost = p;
474a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
475a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	p = strtok(NULL, " ");
476a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	if (! p) goto fail;
477a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
478a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	rport = p;
479a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
480a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	p = strtok(NULL, " ");
481a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	if (! p) goto fail;
482a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
483a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	lhost = p;
484a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
485a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	p = strtok(NULL, " ");
486a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	if (! p) goto fail;
487a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
488a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	lport = p;
489a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
490a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehatif (0) fprintf(stderr, "%d/%d - '%s' '%s'\n", atoi(rport), atoi(lport), rhost, lhost);
491a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
492a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	if (atoi(rport) <= 16 || atoi(rport) > 65535) {
493a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		goto fail;
494a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	}
495a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	if (atoi(lport) <= 16 || atoi(lport) > 65535) {
496a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		goto fail;
497a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	}
498a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
499a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	if (!strcmp(rhost, lhost)) {
500a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		goto fail;
501a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	}
502a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
503a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	free(str);
504a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
505a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	return 1;
506a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
507a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	fail:
508a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
509a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	free(str);
510a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
511a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	return 0;
512a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat}
513a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
514a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehatchar *ipv6_getnameinfo(struct sockaddr *paddr, int addrlen) {
515a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#if X11VNC_IPV6
516a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	char name[200];
517a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	if (noipv6) {
518a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		return strdup("unknown");
519a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	}
520a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	if (getnameinfo(paddr, addrlen, name, sizeof(name), NULL, 0, 0) == 0) {
521a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		return strdup(name);
522a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	}
523a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#endif
524a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	return strdup("unknown");
525a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat}
526a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
527a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehatchar *ipv6_getipaddr(struct sockaddr *paddr, int addrlen) {
528a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#if X11VNC_IPV6 && defined(NI_NUMERICHOST)
529a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	char name[200];
530a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	if (noipv6) {
531a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		return strdup("unknown");
532a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	}
533a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	if (getnameinfo(paddr, addrlen, name, sizeof(name), NULL, 0, NI_NUMERICHOST) == 0) {
534a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		return strdup(name);
535a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	}
536a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#endif
537a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	return strdup("unknown");
538a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat}
539a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
540a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehatint listen6(int port) {
541a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#if X11VNC_IPV6
542a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	struct sockaddr_in6 sin;
543a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	int fd = -1, one = 1;
544a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
545a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	if (noipv6) {
546a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		return -1;
547a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	}
548a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	if (port <= 0 || 65535 < port) {
549a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		/* for us, invalid port means do not listen. */
550a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		return -1;
551a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	}
552a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
553a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	fd = socket(AF_INET6, SOCK_STREAM, 0);
554a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	if (fd < 0) {
555a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		rfbLogPerror("listen6: socket");
556a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		rfbLog("(Ignore the above error if this system is IPv4-only.)\n");
557a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		return -1;
558a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	}
559a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
560a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char *)&one, sizeof(one)) < 0) {
561a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		rfbLogPerror("listen6: setsockopt SO_REUSEADDR");
562a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		close(fd);
563a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		return -1;
564a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	}
565a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
566a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#if defined(SOL_IPV6) && defined(IPV6_V6ONLY)
567a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	if (setsockopt(fd, SOL_IPV6, IPV6_V6ONLY, (char *)&one, sizeof(one)) < 0) {
568a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		rfbLogPerror("listen6: setsockopt IPV6_V6ONLY");
569a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		close(fd);
570a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		return -1;
571a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	}
572a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#endif
573a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
574a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	memset((char *)&sin, 0, sizeof(sin));
575a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	sin.sin6_family = AF_INET6;
576a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	sin.sin6_port   = htons(port);
577a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	sin.sin6_addr   = in6addr_any;
578a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
579a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	if (listen_str6) {
580a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		if (!strcmp(listen_str6, "localhost") || !strcmp(listen_str6, "::1")) {
581a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat			sin.sin6_addr = in6addr_loopback;
582a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		} else {
583a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat			int err;
584a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat			struct addrinfo *ai;
585a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat			struct addrinfo hints;
586a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat			char service[32];
587a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
588a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat			memset(&hints, 0, sizeof(hints));
589a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat			sprintf(service, "%d", port);
590a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
591a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat			hints.ai_family = AF_INET6;
592a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat			hints.ai_socktype = SOCK_STREAM;
593a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#ifdef AI_ADDRCONFIG
594a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat			hints.ai_flags |= AI_ADDRCONFIG;
595a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#endif
596a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#ifdef AI_NUMERICHOST
597a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat			if(ipv6_ip(listen_str6)) {
598a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat				hints.ai_flags |= AI_NUMERICHOST;
599a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat			}
600a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#endif
601a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#ifdef AI_NUMERICSERV
602a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat			hints.ai_flags |= AI_NUMERICSERV;
603a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#endif
604a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat			err = getaddrinfo(listen_str6, service, &hints, &ai);
605a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat			if (err == 0) {
606a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat				struct addrinfo *ap = ai;
607a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat				err = 1;
608a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat				while (ap != NULL) {
609a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat					char *s = ipv6_getipaddr(ap->ai_addr, ap->ai_addrlen);
610a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat					if (!s) s = strdup("unknown");
611a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
612a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat					rfbLog("listen6: checking: %s family: %d\n", s, ap->ai_family);
613a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat					if (ap->ai_family == AF_INET6) {
614a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat						memcpy((char *)&sin, ap->ai_addr, sizeof(sin));
615a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat						rfbLog("listen6: using:    %s scope_id: %d\n", s, sin.sin6_scope_id);
616a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat						err = 0;
617a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat						free(s);
618a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat						break;
619a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat					}
620a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat					free(s);
621a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat					ap = ap->ai_next;
622a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat				}
623a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat				freeaddrinfo(ai);
624a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat			}
625a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
626a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat			if (err != 0) {
627a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat				rfbLog("Invalid or Unsupported -listen6 string: %s\n", listen_str6);
628a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat				close(fd);
629a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat				return -1;
630a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat			}
631a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		}
632a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	} else if (allow_list && !strcmp(allow_list, "127.0.0.1")) {
633a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		sin.sin6_addr = in6addr_loopback;
634a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	} else if (listen_str) {
635a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		if (!strcmp(listen_str, "localhost")) {
636a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat			sin.sin6_addr = in6addr_loopback;
637a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		}
638a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	}
639a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
640a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	if (bind(fd, (struct sockaddr *) &sin, sizeof(sin)) < 0) {
641a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		rfbLogPerror("listen6: bind");
642a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		close(fd);
643a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		return -1;
644a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	}
645a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	if (listen(fd, 32) < 0) {
646a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		rfbLogPerror("listen6: listen");
647a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		close(fd);
648a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		return -1;
649a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	}
650a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	return fd;
651a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#else
652a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	if (port) {}
653a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	return -1;
654a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#endif
655a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat}
656a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
657a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#ifdef LIBVNCSERVER_HAVE_SYS_SOCKET_H
658a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#include <sys/un.h>
659a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#endif
660a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
661a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehatint listen_unix(char *file) {
662a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#if !defined(AF_UNIX) || !defined(LIBVNCSERVER_HAVE_SYS_SOCKET_H)
663a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	if (sock) {}
664a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	return -1;
665a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#else
666a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	int s, len;
667a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	struct sockaddr_un saun;
668a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
669a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	s = socket(AF_UNIX, SOCK_STREAM, 0);
670a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	if (s < 0) {
671a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		rfbLogPerror("listen_unix: socket");
672a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		return -1;
673a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	}
674a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	saun.sun_family = AF_UNIX;
675a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	strcpy(saun.sun_path, file);
676a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	unlink(file);
677a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
678a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	len = sizeof(saun.sun_family) + strlen(saun.sun_path);
679a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
680a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	if (bind(s, (struct sockaddr *)&saun, len) < 0) {
681a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		rfbLogPerror("listen_unix: bind");
682a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		close(s);
683a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		return -1;
684a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	}
685a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
686a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	if (listen(s, 32) < 0) {
687a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		rfbLogPerror("listen_unix: listen");
688a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		close(s);
689a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		return -1;
690a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	}
691a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	rfbLog("listening on unix socket: %s fd=%d\n", file, s);
692a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	return s;
693a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#endif
694a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat}
695a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
696a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehatint accept_unix(int s) {
697a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#if !defined(AF_UNIX) || !defined(LIBVNCSERVER_HAVE_SYS_SOCKET_H)
698a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	if (s) {}
699a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	return -1;
700a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#else
701a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	int fd, fromlen;
702a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	struct sockaddr_un fsaun;
703a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
704a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	fd = accept(s, (struct sockaddr *)&fsaun, &fromlen);
705a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	if (fd < 0) {
706a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		rfbLogPerror("accept_unix: accept");
707a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		return -1;
708a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	}
709a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	return fd;
710a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#endif
711a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat}
712a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
713a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehatint connect_tcp(char *host, int port) {
714a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	double t0 = dnow();
715a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	int fd = -1;
716a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	int fail4 = noipv4;
717a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	if (getenv("IPV4_FAILS")) {
718a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		fail4 = 2;
719a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	}
720a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
721a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	rfbLog("connect_tcp: trying:   %s %d\n", host, port);
722a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
723a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	if (fail4) {
724a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		if (fail4 > 1) {
725a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat			rfbLog("TESTING: IPV4_FAILS for connect_tcp.\n");
726a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		}
727a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	} else {
728a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		fd = rfbConnectToTcpAddr(host, port);
729a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	}
730a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
731a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	if (fd >= 0) {
732a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		return fd;
733a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	}
734a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	rfbLogPerror("connect_tcp: connection failed");
735a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
736a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	if (dnow() - t0 < 4.0) {
737a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		rfbLog("connect_tcp: re-trying %s %d\n", host, port);
738a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		usleep (100 * 1000);
739a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		if (!fail4) {
740a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat			fd = rfbConnectToTcpAddr(host, port);
741a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		}
742a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		if (fd < 0) {
743a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat			rfbLogPerror("connect_tcp: connection failed");
744a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		}
745a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	}
746a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
747a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	if (fd < 0 && !noipv6) {
748a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#if X11VNC_IPV6
749a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		int err;
750a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		struct addrinfo *ai;
751a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		struct addrinfo hints;
752a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		char service[32], *host2, *q;
753a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
754a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		rfbLog("connect_tcp: trying IPv6 %s %d\n", host, port);
755a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
756a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		memset(&hints, 0, sizeof(hints));
757a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		sprintf(service, "%d", port);
758a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
759a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		hints.ai_family = AF_UNSPEC;
760a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		hints.ai_socktype = SOCK_STREAM;
761a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#ifdef AI_ADDRCONFIG
762a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		hints.ai_flags |= AI_ADDRCONFIG;
763a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#endif
764a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		if(ipv6_ip(host)) {
765a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#ifdef AI_NUMERICHOST
766a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat			rfbLog("connect_tcp[ipv6]: setting AI_NUMERICHOST for %s\n", host);
767a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat			hints.ai_flags |= AI_NUMERICHOST;
768a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#endif
769a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		}
770a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#ifdef AI_NUMERICSERV
771a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		hints.ai_flags |= AI_NUMERICSERV;
772a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#endif
773a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
774a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		if (!strcmp(host, "127.0.0.1")) {
775a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat			host2 = strdup("::1");
776a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		} else if (host[0] == '[') {
777a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat			host2 = strdup(host+1);
778a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		} else {
779a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat			host2 = strdup(host);
780a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		}
781a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		q = strrchr(host2, ']');
782a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		if (q) {
783a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat			*q = '\0';
784a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		}
785a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
786a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		err = getaddrinfo(host2, service, &hints, &ai);
787a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		if (err != 0) {
788a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat			rfbLog("connect_tcp[ipv6]: getaddrinfo[%d]: %s\n", err, gai_strerror(err));
789a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat			usleep(100 * 1000);
790a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat			err = getaddrinfo(host2, service, &hints, &ai);
791a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		}
792a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		free(host2);
793a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
794a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		if (err != 0) {
795a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat			rfbLog("connect_tcp[ipv6]: getaddrinfo[%d]: %s\n", err, gai_strerror(err));
796a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		} else {
797a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat			struct addrinfo *ap = ai;
798a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat			while (ap != NULL) {
799a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat				int sock;
800a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
801a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat				if (fail4) {
802a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat					struct sockaddr_in6 *s6ptr;
803a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat					if (ap->ai_family != AF_INET6) {
804a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat						rfbLog("connect_tcp[ipv6]: skipping AF_INET address under -noipv4\n");
805a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat						ap = ap->ai_next;
806a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat						continue;
807a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat					}
808a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#ifdef IN6_IS_ADDR_V4MAPPED
809a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat					s6ptr = (struct sockaddr_in6 *) ap->ai_addr;
810a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat					if (IN6_IS_ADDR_V4MAPPED(&(s6ptr->sin6_addr))) {
811a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat						rfbLog("connect_tcp[ipv6]: skipping V4MAPPED address under -noipv4\n");
812a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat						ap = ap->ai_next;
813a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat						continue;
814a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat					}
815a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#endif
816a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat				}
817a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
818a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat				sock = socket(ap->ai_family, ap->ai_socktype, ap->ai_protocol);
819a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
820a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat				if (sock == -1) {
821a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat					rfbLogPerror("connect_tcp[ipv6]: socket");
822a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat					if (0) rfbLog("(Ignore the above error if this system is IPv4-only.)\n");
823a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat				} else {
824a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat					int res = -1, dmsg = 0;
825a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat					char *s = ipv6_getipaddr(ap->ai_addr, ap->ai_addrlen);
826a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat					if (!s) s = strdup("unknown");
827a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
828a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat					rfbLog("connect_tcp[ipv6]: trying sock=%d fam=%d proto=%d using %s\n",
829a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat					    sock, ap->ai_family, ap->ai_protocol, s);
830a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat					res = connect(sock, ap->ai_addr, ap->ai_addrlen);
831a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#if defined(SOL_IPV6) && defined(IPV6_V6ONLY)
832a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat					if (res != 0) {
833a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat						int zero = 0;
834a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat						rfbLogPerror("connect_tcp[ipv6]: connect");
835a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat						dmsg = 1;
836a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat						if (setsockopt(sock, SOL_IPV6, IPV6_V6ONLY, (char *)&zero, sizeof(zero)) == 0) {
837a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat							rfbLog("connect_tcp[ipv6]: trying again with IPV6_V6ONLY=0\n");
838a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat							res = connect(sock, ap->ai_addr, ap->ai_addrlen);
839a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat							dmsg = 0;
840a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat						} else {
841a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat							rfbLogPerror("connect_tcp[ipv6]: setsockopt IPV6_V6ONLY");
842a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat						}
843a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat					}
844a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#endif
845a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat					if (res == 0) {
846a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat						rfbLog("connect_tcp[ipv6]: connect OK\n");
847a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat						fd = sock;
848a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat						if (!ipv6_client_ip_str) {
849a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat							ipv6_client_ip_str = strdup(s);
850a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat						}
851a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat						free(s);
852a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat						break;
853a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat					} else {
854a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat						if (!dmsg) rfbLogPerror("connect_tcp[ipv6]: connect");
855a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat						close(sock);
856a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat					}
857a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat					free(s);
858a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat				}
859a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat				ap = ap->ai_next;
860a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat			}
861a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat			freeaddrinfo(ai);
862a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		}
863a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#endif
864a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	}
865a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	if (fd < 0 && !fail4) {
866a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		/* this is a kludge for IPv4-only machines getting v4mapped string. */
867a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		char *q, *host2;
868a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		if (host[0] == '[') {
869a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat			host2 = strdup(host+1);
870a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		} else {
871a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat			host2 = strdup(host);
872a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		}
873a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		q = strrchr(host2, ']');
874a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		if (q) {
875a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat			*q = '\0';
876a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		}
877a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		if (strstr(host2, "::ffff:") == host2 || strstr(host2, "::FFFF:") == host2) {
878a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat			char *host3 = host2 + strlen("::ffff:");
879a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat			if (dotted_ip(host3, 0)) {
880a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat				rfbLog("connect_tcp[ipv4]: trying fallback to IPv4 for %s\n", host2);
881a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat				fd = rfbConnectToTcpAddr(host3, port);
882a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat				if (fd < 0) {
883a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat					rfbLogPerror("connect_tcp[ipv4]: connection failed");
884a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat				}
885a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat			}
886a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		}
887a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		free(host2);
888a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	}
889a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	return fd;
890a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat}
891a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
892a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehatint listen_tcp(int port, in_addr_t iface, int try6) {
893a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	int fd = -1;
894a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	int fail4 = noipv4;
895a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	if (getenv("IPV4_FAILS")) {
896a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		fail4 = 2;
897a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	}
898a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
899a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	if (port <= 0 || 65535 < port) {
900a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		/* for us, invalid port means do not listen. */
901a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		return -1;
902a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	}
903a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
904a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	if (fail4) {
905a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		if (fail4 > 1) {
906a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat			rfbLog("TESTING: IPV4_FAILS for listen_tcp: port=%d try6=%d\n", port, try6);
907a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		}
908a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	} else {
909a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		fd = rfbListenOnTCPPort(port, iface);
910a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	}
911a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
912a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	if (fd >= 0) {
913a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		return fd;
914a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	}
915a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	if (fail4 > 1) {
916a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		rfbLogPerror("listen_tcp: listen failed");
917a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	}
918a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
919a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	if (fd < 0 && try6 && ipv6_listen && !noipv6) {
920a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#if X11VNC_IPV6
921a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		char *save = listen_str6;
922a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		if (iface == htonl(INADDR_LOOPBACK)) {
923a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat			listen_str6 = "localhost";
924a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat			rfbLog("listen_tcp: retrying on IPv6 in6addr_loopback ...\n");
925a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat			fd = listen6(port);
926a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		} else if (iface == htonl(INADDR_ANY)) {
927a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat			listen_str6 = NULL;
928a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat			rfbLog("listen_tcp: retrying on IPv6 in6addr_any ...\n");
929a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat			fd = listen6(port);
930a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		}
931a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		listen_str6 = save;
932a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#endif
933a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	}
934a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	return fd;
935a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat}
936a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
937