~ubuntu-branches/debian/jessie/italc/jessie

« back to all changes in this revision

Viewing changes to ica/x11/x11vnc/inet.c

  • Committer: Bazaar Package Importer
  • Author(s): Patrick Winnertz
  • Date: 2011-02-11 14:50:22 UTC
  • mto: This revision was merged to the branch mainline in revision 8.
  • Revision ID: james.westby@ubuntu.com-20110211145022-sn173siax6lywjus
Tags: upstream-1.0.13
ImportĀ upstreamĀ versionĀ 1.0.13

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
   Copyright (C) 2002-2010 Karl J. Runge <runge@karlrunge.com> 
 
3
   All rights reserved.
 
4
 
 
5
This file is part of x11vnc.
 
6
 
 
7
x11vnc is free software; you can redistribute it and/or modify
 
8
it under the terms of the GNU General Public License as published by
 
9
the Free Software Foundation; either version 2 of the License, or (at
 
10
your option) any later version.
 
11
 
 
12
x11vnc is distributed in the hope that it will be useful,
 
13
but WITHOUT ANY WARRANTY; without even the implied warranty of
 
14
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
15
GNU General Public License for more details.
 
16
 
 
17
You should have received a copy of the GNU General Public License
 
18
along with x11vnc; if not, write to the Free Software
 
19
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA
 
20
or see <http://www.gnu.org/licenses/>.
 
21
 
 
22
In addition, as a special exception, Karl J. Runge
 
23
gives permission to link the code of its release of x11vnc with the
 
24
OpenSSL project's "OpenSSL" library (or with modified versions of it
 
25
that use the same license as the "OpenSSL" library), and distribute
 
26
the linked executables.  You must obey the GNU General Public License
 
27
in all respects for all of the code used other than "OpenSSL".  If you
 
28
modify this file, you may extend this exception to your version of the
 
29
file, but you are not obligated to do so.  If you do not wish to do
 
30
so, delete this exception statement from your version.
 
31
*/
 
32
 
1
33
/* -- inet.c -- */
2
34
 
3
35
#include "x11vnc.h"
12
44
char *raw2host(char *raw, int len);
13
45
char *raw2ip(char *raw);
14
46
char *ip2host(char *ip);
15
 
int dotted_ip(char *host);
 
47
int ipv6_ip(char *host);
 
48
int dotted_ip(char *host, int partial);
16
49
int get_remote_port(int sock);
17
50
int get_local_port(int sock);
18
51
char *get_remote_host(int sock);
19
52
char *get_local_host(int sock);
20
53
char *ident_username(rfbClientPtr client);
21
54
int find_free_port(int start, int end);
 
55
int find_free_port6(int start, int end);
22
56
int have_ssh_env(void);
 
57
char *ipv6_getnameinfo(struct sockaddr *paddr, int addrlen);
 
58
char *ipv6_getipaddr(struct sockaddr *paddr, int addrlen);
 
59
int listen6(int port);
 
60
int connect_tcp(char *host, int port);
 
61
int listen_tcp(int port, in_addr_t iface, int try6);
23
62
 
24
63
static int get_port(int sock, int remote);
25
64
static char *get_host(int sock, int remote);
39
78
        }
40
79
        memset(&addr, 0, sizeof(addr));
41
80
        addr.sin_family = AF_INET;
42
 
        addr.sin_addr.s_addr =  *(unsigned long *)hp->h_addr_list[0];
 
81
        addr.sin_addr.s_addr =  *(unsigned long *)hp->h_addr;
43
82
        str = strdup(inet_ntoa(addr.sin_addr));
44
83
        return str;
45
84
}
94
133
        return str;
95
134
}
96
135
 
97
 
int dotted_ip(char *host) {
 
136
int ipv6_ip(char *host_in) {
 
137
        char *p, *host, a[2];
 
138
        int ncol = 0, nhex = 0;
 
139
 
 
140
        if (host_in[0] == '[')  {
 
141
                host = host_in + 1;
 
142
        } else {
 
143
                host = host_in;
 
144
        }
 
145
 
 
146
        if (strstr(host, "::ffff:") == host || strstr(host, "::FFFF:") == host) {
 
147
                return dotted_ip(host + strlen("::ffff:"), 0);
 
148
        }
 
149
 
 
150
        a[1] = '\0';
 
151
 
 
152
        p = host;
 
153
        while (*p != '\0' && *p != '%' && *p != ']') {
 
154
                if (*p == ':') {
 
155
                        ncol++;
 
156
                } else {
 
157
                        nhex++;
 
158
                }
 
159
                a[0] = *p;
 
160
                if (strpbrk(a, ":abcdef0123456789") == a) {
 
161
                        p++;
 
162
                        continue;
 
163
                }
 
164
                return 0;
 
165
        }
 
166
        if (ncol < 2 || ncol > 8 || nhex == 0) {
 
167
                return 0;
 
168
        } else {
 
169
                return 1;
 
170
        }
 
171
}
 
172
 
 
173
int dotted_ip(char *host, int partial) {
 
174
        int len, dots = 0;
98
175
        char *p = host;
 
176
 
 
177
        if (!host) {
 
178
                return 0;
 
179
        }
 
180
 
 
181
        if (!isdigit((unsigned char) host[0])) {
 
182
                return 0;
 
183
        }
 
184
 
 
185
        len = strlen(host);
 
186
        if (!partial && !isdigit((unsigned char) host[len-1])) {
 
187
                return 0;
 
188
        }
 
189
 
99
190
        while (*p != '\0') {
 
191
                if (*p == '.') dots++;
100
192
                if (*p == '.' || isdigit((unsigned char) (*p))) {
101
193
                        p++;
102
194
                        continue;
103
195
                }
104
196
                return 0;
105
197
        }
 
198
        if (!partial && dots != 3) {
 
199
                return 0;       
 
200
        }
106
201
        return 1;
107
202
}
108
203
 
177
272
                user = cd->username;
178
273
        }
179
274
        if (!user || *user == '\0') {
180
 
                char msg[128];
181
275
                int n, sock, ok = 0;
182
276
                int block = 0;
 
277
                int refused = 0;
183
278
 
184
279
                /*
185
280
                 * need to check to see if the operation will block for
189
284
            {   pid_t pid, pidw;
190
285
                int rc;
191
286
                if ((pid = fork()) > 0) {
192
 
                        usleep(100 * 1000);     /* 0.1 sec */
 
287
                        usleep(100 * 1000);     /* 0.1 sec for quick success or refusal */
193
288
                        pidw = waitpid(pid, &rc, WNOHANG);
194
289
                        if (pidw <= 0) {
195
 
                                usleep(1000 * 1000);    /* 1.0 sec */
 
290
                                usleep(1500 * 1000);    /* 1.5 sec */
196
291
                                pidw = waitpid(pid, &rc, WNOHANG);
197
292
                                if (pidw <= 0) {
 
293
                                        int rc2;
 
294
                                        rfbLog("ident_username: set block=1 (hung)\n");
198
295
                                        block = 1;
199
296
                                        kill(pid, SIGTERM);
 
297
                                        usleep(100 * 1000);
 
298
                                        waitpid(pid, &rc2, WNOHANG);
 
299
                                }
 
300
                        }
 
301
                        if (pidw > 0 && !block) {
 
302
                                if (WIFEXITED(rc) && WEXITSTATUS(rc) == 1) {
 
303
                                        rfbLog("ident_username: set refused=1 (exit)\n");
 
304
                                        refused = 1;
200
305
                                }
201
306
                        }
202
307
                } else if (pid == -1) {
208
313
                        signal(SIGQUIT, SIG_DFL);
209
314
                        signal(SIGTERM, SIG_DFL);
210
315
 
211
 
                        if ((sock = rfbConnectToTcpAddr(client->host, 113)) < 0) {
 
316
                        if ((sock = connect_tcp(client->host, 113)) < 0) {
212
317
                                exit(1);
213
318
                        } else {
214
319
                                close(sock);
217
322
                }
218
323
            }
219
324
#endif
220
 
                if (block) {
 
325
                if (block || refused) {
221
326
                        ;
222
 
                } else if ((sock = rfbConnectToTcpAddr(client->host, 113)) < 0) {
223
 
                        rfbLog("could not connect to ident: %s:%d\n",
 
327
                } else if ((sock = connect_tcp(client->host, 113)) < 0) {
 
328
                        rfbLog("ident_username: could not connect to ident: %s:%d\n",
224
329
                            client->host, 113);
225
330
                } else {
 
331
                        char msg[128];
226
332
                        int ret;
227
333
                        fd_set rfds;
228
334
                        struct timeval tv;
234
340
 
235
341
                        FD_ZERO(&rfds);
236
342
                        FD_SET(sock, &rfds);
237
 
                        tv.tv_sec  = 4;
 
343
                        tv.tv_sec  = 3;
238
344
                        tv.tv_usec = 0;
239
345
                        ret = select(sock+1, &rfds, NULL, NULL, &tv); 
240
346
 
241
347
                        if (ret > 0) {
242
348
                                int i;
243
349
                                char *q, *p;
244
 
                                for (i=0; i<128; i++) {
 
350
                                for (i=0; i < (int) sizeof(msg); i++) {
245
351
                                        msg[i] = '\0';
246
352
                                }
247
353
                                usleep(250*1000);
313
419
                end = 65530;
314
420
        }
315
421
        for (port = start; port <= end; port++)  {
316
 
                int sock = rfbListenOnTCPPort(port, htonl(INADDR_ANY));
 
422
                int sock = listen_tcp(port, htonl(INADDR_ANY), 0);
 
423
                if (sock >= 0) {
 
424
                        close(sock);
 
425
                        return port;
 
426
                }
 
427
        }
 
428
        return 0;
 
429
}
 
430
 
 
431
int find_free_port6(int start, int end) {
 
432
        int port;
 
433
        if (start <= 0) {
 
434
                start = 1024;
 
435
        }
 
436
        if (end <= 0) {
 
437
                end = 65530;
 
438
        }
 
439
        for (port = start; port <= end; port++)  {
 
440
                int sock = listen6(port);
317
441
                if (sock >= 0) {
318
442
                        close(sock);
319
443
                        return port;
385
509
        return 0;
386
510
}
387
511
 
 
512
char *ipv6_getnameinfo(struct sockaddr *paddr, int addrlen) {
 
513
#if X11VNC_IPV6
 
514
        char name[200];
 
515
        if (noipv6) {
 
516
                return strdup("unknown");
 
517
        }
 
518
        if (getnameinfo(paddr, addrlen, name, sizeof(name), NULL, 0, 0) == 0) {
 
519
                return strdup(name);
 
520
        }
 
521
#endif
 
522
        return strdup("unknown");
 
523
}
 
524
 
 
525
char *ipv6_getipaddr(struct sockaddr *paddr, int addrlen) {
 
526
#if X11VNC_IPV6 && defined(NI_NUMERICHOST)
 
527
        char name[200];
 
528
        if (noipv6) {
 
529
                return strdup("unknown");
 
530
        }
 
531
        if (getnameinfo(paddr, addrlen, name, sizeof(name), NULL, 0, NI_NUMERICHOST) == 0) {
 
532
                return strdup(name);
 
533
        }
 
534
#endif
 
535
        return strdup("unknown");
 
536
}
 
537
 
 
538
int listen6(int port) {
 
539
#if X11VNC_IPV6
 
540
        struct sockaddr_in6 sin;
 
541
        int fd = -1, one = 1;
 
542
 
 
543
        if (noipv6) {
 
544
                return -1;
 
545
        }
 
546
        if (port <= 0 || 65535 < port) {
 
547
                /* for us, invalid port means do not listen. */
 
548
                return -1;
 
549
        }
 
550
 
 
551
        fd = socket(AF_INET6, SOCK_STREAM, 0);
 
552
        if (fd < 0) {
 
553
                rfbLogPerror("listen6: socket");
 
554
                rfbLog("(Ignore the above error if this system is IPv4-only.)\n");
 
555
                return -1;
 
556
        }
 
557
 
 
558
        if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char *)&one, sizeof(one)) < 0) {
 
559
                rfbLogPerror("listen6: setsockopt SO_REUSEADDR"); 
 
560
                close(fd);
 
561
                return -1;
 
562
        }
 
563
 
 
564
#if defined(SOL_IPV6) && defined(IPV6_V6ONLY)
 
565
        if (setsockopt(fd, SOL_IPV6, IPV6_V6ONLY, (char *)&one, sizeof(one)) < 0) {
 
566
                rfbLogPerror("listen6: setsockopt IPV6_V6ONLY"); 
 
567
                close(fd);
 
568
                return -1;
 
569
        }
 
570
#endif
 
571
 
 
572
        memset((char *)&sin, 0, sizeof(sin));
 
573
        sin.sin6_family = AF_INET6;
 
574
        sin.sin6_port   = htons(port);
 
575
        sin.sin6_addr   = in6addr_any;
 
576
 
 
577
        if (listen_str6) {
 
578
                if (!strcmp(listen_str6, "localhost") || !strcmp(listen_str6, "::1")) {
 
579
                        sin.sin6_addr = in6addr_loopback;
 
580
                } else {
 
581
                        int err;
 
582
                        struct addrinfo *ai;
 
583
                        struct addrinfo hints;
 
584
                        char service[32];
 
585
 
 
586
                        memset(&hints, 0, sizeof(hints));
 
587
                        sprintf(service, "%d", port);
 
588
 
 
589
                        hints.ai_family = AF_INET6;
 
590
                        hints.ai_socktype = SOCK_STREAM;
 
591
#ifdef AI_ADDRCONFIG
 
592
                        hints.ai_flags |= AI_ADDRCONFIG;
 
593
#endif
 
594
#ifdef AI_NUMERICHOST
 
595
                        if(ipv6_ip(listen_str6)) {
 
596
                                hints.ai_flags |= AI_NUMERICHOST;
 
597
                        }
 
598
#endif
 
599
#ifdef AI_NUMERICSERV
 
600
                        hints.ai_flags |= AI_NUMERICSERV;
 
601
#endif
 
602
                        err = getaddrinfo(listen_str6, service, &hints, &ai);
 
603
                        if (err == 0) {
 
604
                                struct addrinfo *ap = ai;
 
605
                                err = 1;
 
606
                                while (ap != NULL) {
 
607
                                        char *s = ipv6_getipaddr(ap->ai_addr, ap->ai_addrlen);
 
608
                                        if (!s) s = strdup("unknown");
 
609
 
 
610
                                        rfbLog("listen6: checking: %s family: %d\n", s, ap->ai_family); 
 
611
                                        if (ap->ai_family == AF_INET6) {
 
612
                                                memcpy((char *)&sin, ap->ai_addr, sizeof(sin));
 
613
                                                rfbLog("listen6: using:    %s scope_id: %d\n", s, sin.sin6_scope_id); 
 
614
                                                err = 0;
 
615
                                                free(s);
 
616
                                                break;
 
617
                                        }
 
618
                                        free(s);
 
619
                                        ap = ap->ai_next;
 
620
                                }
 
621
                                freeaddrinfo(ai);
 
622
                        }
 
623
 
 
624
                        if (err != 0) {
 
625
                                rfbLog("Invalid or Unsupported -listen6 string: %s\n", listen_str6);
 
626
                                close(fd);
 
627
                                return -1;
 
628
                        }
 
629
                }
 
630
        } else if (allow_list && !strcmp(allow_list, "127.0.0.1")) {
 
631
                sin.sin6_addr = in6addr_loopback;
 
632
        } else if (listen_str) {
 
633
                if (!strcmp(listen_str, "localhost")) {
 
634
                        sin.sin6_addr = in6addr_loopback;
 
635
                }
 
636
        }
 
637
 
 
638
        if (bind(fd, (struct sockaddr *) &sin, sizeof(sin)) < 0) {
 
639
                rfbLogPerror("listen6: bind"); 
 
640
                close(fd);
 
641
                return -1;
 
642
        }
 
643
        if (listen(fd, 32) < 0) {
 
644
                rfbLogPerror("listen6: listen");
 
645
                close(fd);
 
646
                return -1;
 
647
        }
 
648
        return fd;
 
649
#else
 
650
        if (port) {}
 
651
        return -1;
 
652
#endif
 
653
}
 
654
 
 
655
int connect_tcp(char *host, int port) {
 
656
        double t0 = dnow();
 
657
        int fd = -1;
 
658
        int fail4 = noipv4;
 
659
        if (getenv("IPV4_FAILS")) {
 
660
                fail4 = 2;
 
661
        }
 
662
 
 
663
        rfbLog("connect_tcp: trying:   %s %d\n", host, port);
 
664
 
 
665
        if (fail4) {
 
666
                if (fail4 > 1) {
 
667
                        rfbLog("TESTING: IPV4_FAILS for connect_tcp.\n");
 
668
                }
 
669
        } else {
 
670
                fd = rfbConnectToTcpAddr(host, port);
 
671
        }
 
672
 
 
673
        if (fd >= 0) {
 
674
                return fd;
 
675
        }
 
676
        rfbLogPerror("connect_tcp: connection failed");
 
677
 
 
678
        if (dnow() - t0 < 4.0) {
 
679
                rfbLog("connect_tcp: re-trying %s %d\n", host, port);
 
680
                usleep (100 * 1000);
 
681
                if (!fail4) {
 
682
                        fd = rfbConnectToTcpAddr(host, port);
 
683
                }
 
684
                if (fd < 0) {
 
685
                        rfbLogPerror("connect_tcp: connection failed");
 
686
                }
 
687
        }
 
688
 
 
689
        if (fd < 0 && !noipv6) {
 
690
#if X11VNC_IPV6
 
691
                int err;
 
692
                struct addrinfo *ai;
 
693
                struct addrinfo hints;
 
694
                char service[32], *host2, *q;
 
695
 
 
696
                rfbLog("connect_tcp: trying IPv6 %s %d\n", host, port);
 
697
 
 
698
                memset(&hints, 0, sizeof(hints));
 
699
                sprintf(service, "%d", port);
 
700
 
 
701
                hints.ai_family = AF_UNSPEC;
 
702
                hints.ai_socktype = SOCK_STREAM;
 
703
#ifdef AI_ADDRCONFIG
 
704
                hints.ai_flags |= AI_ADDRCONFIG;
 
705
#endif
 
706
                if(ipv6_ip(host)) {
 
707
#ifdef AI_NUMERICHOST
 
708
                        rfbLog("connect_tcp[ipv6]: setting AI_NUMERICHOST for %s\n", host);
 
709
                        hints.ai_flags |= AI_NUMERICHOST;
 
710
#endif
 
711
                }
 
712
#ifdef AI_NUMERICSERV
 
713
                hints.ai_flags |= AI_NUMERICSERV;
 
714
#endif
 
715
 
 
716
                if (!strcmp(host, "127.0.0.1")) {
 
717
                        host2 = strdup("::1");
 
718
                } else if (host[0] == '[') {
 
719
                        host2 = strdup(host+1);
 
720
                } else {
 
721
                        host2 = strdup(host);
 
722
                }
 
723
                q = strrchr(host2, ']');
 
724
                if (q) {
 
725
                        *q = '\0';
 
726
                }
 
727
 
 
728
                err = getaddrinfo(host2, service, &hints, &ai);
 
729
                if (err != 0) {
 
730
                        rfbLog("connect_tcp[ipv6]: getaddrinfo[%d]: %s\n", err, gai_strerror(err));
 
731
                        usleep(100 * 1000);
 
732
                        err = getaddrinfo(host2, service, &hints, &ai);
 
733
                }
 
734
                free(host2);
 
735
 
 
736
                if (err != 0) {
 
737
                        rfbLog("connect_tcp[ipv6]: getaddrinfo[%d]: %s\n", err, gai_strerror(err));
 
738
                } else {
 
739
                        struct addrinfo *ap = ai;
 
740
                        while (ap != NULL) {
 
741
                                int sock;
 
742
 
 
743
                                if (fail4) {
 
744
                                        struct sockaddr_in6 *s6ptr;
 
745
                                        if (ap->ai_family != AF_INET6) {
 
746
                                                rfbLog("connect_tcp[ipv6]: skipping AF_INET address under -noipv4\n");
 
747
                                                ap = ap->ai_next;
 
748
                                                continue;
 
749
                                        }
 
750
#ifdef IN6_IS_ADDR_V4MAPPED
 
751
                                        s6ptr = (struct sockaddr_in6 *) ap->ai_addr;
 
752
                                        if (IN6_IS_ADDR_V4MAPPED(&(s6ptr->sin6_addr))) {
 
753
                                                rfbLog("connect_tcp[ipv6]: skipping V4MAPPED address under -noipv4\n");
 
754
                                                ap = ap->ai_next;
 
755
                                                continue;
 
756
                                        }
 
757
#endif
 
758
                                }
 
759
 
 
760
                                sock = socket(ap->ai_family, ap->ai_socktype, ap->ai_protocol);
 
761
 
 
762
                                if (sock == -1) {
 
763
                                        rfbLogPerror("connect_tcp[ipv6]: socket");
 
764
                                        if (0) rfbLog("(Ignore the above error if this system is IPv4-only.)\n");
 
765
                                } else {
 
766
                                        int res = -1, dmsg = 0;
 
767
                                        char *s = ipv6_getipaddr(ap->ai_addr, ap->ai_addrlen);
 
768
                                        if (!s) s = strdup("unknown");
 
769
 
 
770
                                        rfbLog("connect_tcp[ipv6]: trying sock=%d fam=%d proto=%d using %s\n",
 
771
                                            sock, ap->ai_family, ap->ai_protocol, s);
 
772
                                        res = connect(sock, ap->ai_addr, ap->ai_addrlen);
 
773
#if defined(SOL_IPV6) && defined(IPV6_V6ONLY)
 
774
                                        if (res != 0) {
 
775
                                                int zero = 0;
 
776
                                                rfbLogPerror("connect_tcp[ipv6]: connect");
 
777
                                                dmsg = 1;
 
778
                                                if (setsockopt(sock, SOL_IPV6, IPV6_V6ONLY, (char *)&zero, sizeof(zero)) == 0) {
 
779
                                                        rfbLog("connect_tcp[ipv6]: trying again with IPV6_V6ONLY=0\n");
 
780
                                                        res = connect(sock, ap->ai_addr, ap->ai_addrlen);
 
781
                                                        dmsg = 0;
 
782
                                                } else {
 
783
                                                        rfbLogPerror("connect_tcp[ipv6]: setsockopt IPV6_V6ONLY");
 
784
                                                }
 
785
                                        }
 
786
#endif
 
787
                                        if (res == 0) {
 
788
                                                rfbLog("connect_tcp[ipv6]: connect OK\n");
 
789
                                                fd = sock;
 
790
                                                if (!ipv6_client_ip_str) {
 
791
                                                        ipv6_client_ip_str = strdup(s);
 
792
                                                }
 
793
                                                free(s);
 
794
                                                break;
 
795
                                        } else {
 
796
                                                if (!dmsg) rfbLogPerror("connect_tcp[ipv6]: connect");
 
797
                                                close(sock);
 
798
                                        }
 
799
                                        free(s);
 
800
                                }
 
801
                                ap = ap->ai_next;
 
802
                        }
 
803
                        freeaddrinfo(ai);
 
804
                }
 
805
#endif
 
806
        }
 
807
        if (fd < 0 && !fail4) {
 
808
                /* this is a kludge for IPv4-only machines getting v4mapped string. */
 
809
                char *q, *host2;
 
810
                if (host[0] == '[') {
 
811
                        host2 = strdup(host+1);
 
812
                } else {
 
813
                        host2 = strdup(host);
 
814
                }
 
815
                q = strrchr(host2, ']');
 
816
                if (q) {
 
817
                        *q = '\0';
 
818
                }
 
819
                if (strstr(host2, "::ffff:") == host2 || strstr(host2, "::FFFF:") == host2) {
 
820
                        char *host3 = host2 + strlen("::ffff:");
 
821
                        if (dotted_ip(host3, 0)) {
 
822
                                rfbLog("connect_tcp[ipv4]: trying fallback to IPv4 for %s\n", host2);
 
823
                                fd = rfbConnectToTcpAddr(host3, port);
 
824
                                if (fd < 0) {
 
825
                                        rfbLogPerror("connect_tcp[ipv4]: connection failed");
 
826
                                }
 
827
                        }
 
828
                }
 
829
                free(host2);
 
830
        }
 
831
        return fd;
 
832
}
 
833
 
 
834
int listen_tcp(int port, in_addr_t iface, int try6) {
 
835
        int fd = -1;
 
836
        int fail4 = noipv4;
 
837
        if (getenv("IPV4_FAILS")) {
 
838
                fail4 = 2;
 
839
        }
 
840
 
 
841
        if (port <= 0 || 65535 < port) {
 
842
                /* for us, invalid port means do not listen. */
 
843
                return -1;
 
844
        }
 
845
 
 
846
        if (fail4) {
 
847
                if (fail4 > 1) {
 
848
                        rfbLog("TESTING: IPV4_FAILS for listen_tcp: port=%d try6=%d\n", port, try6);
 
849
                }
 
850
        } else {
 
851
                fd = rfbListenOnTCPPort(port, iface);
 
852
        }
 
853
 
 
854
        if (fd >= 0) {
 
855
                return fd;
 
856
        }
 
857
        if (fail4 > 1) {
 
858
                rfbLogPerror("listen_tcp: listen failed");
 
859
        }
 
860
 
 
861
        if (fd < 0 && try6 && ipv6_listen && !noipv6) {
 
862
#if X11VNC_IPV6
 
863
                char *save = listen_str6;
 
864
                if (iface == htonl(INADDR_LOOPBACK)) {
 
865
                        listen_str6 = "localhost";
 
866
                        rfbLog("listen_tcp: retrying on IPv6 in6addr_loopback ...\n");
 
867
                        fd = listen6(port);
 
868
                } else if (iface == htonl(INADDR_ANY)) {
 
869
                        listen_str6 = NULL;
 
870
                        rfbLog("listen_tcp: retrying on IPv6 in6addr_any ...\n");
 
871
                        fd = listen6(port);
 
872
                }
 
873
                listen_str6 = save;
 
874
#endif
 
875
        }
 
876
        return fd;
 
877
}
 
878