Show helper program with -v when opening connection.
[rsync/rsync.git] / socket.c
CommitLineData
7c1b4daa
MP
1/* -*- c-file-style: "linux" -*-
2
d54765c4
MP
3 rsync -- fast file replication program
4
eecd22ff 5 Copyright (C) 1992-2001 by Andrew Tridgell <tridge@samba.org>
362099a5 6 Copyright (C) 2001, 2002 by Martin Pool <mbp@samba.org>
bc2e93eb
AT
7
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2 of the License, or
11 (at your option) any later version.
12
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21*/
22
d5d4b282
MP
23/**
24 * @file socket.c
25 *
26 * Socket functions used in rsync.
362099a5
MP
27 *
28 * This file is now converted to use the new-style getaddrinfo()
29 * interface, which supports IPv6 but is also supported on recent
30 * IPv4-only machines. On systems that don't have that interface, we
31 * emulate it using the KAME implementation.
d5d4b282 32 **/
bc2e93eb 33
f0fca04e
AT
34#include "rsync.h"
35
885448d7
MP
36static const char default_name[] = "UNKNOWN";
37
9a5a8673
MP
38static int lookup_name(const struct sockaddr_storage *ss,
39 socklen_t ss_len,
40 char *name_buf, size_t name_buf_len,
41 char *port_buf, size_t port_buf_len);
42
43static int check_name(const struct sockaddr_storage *ss,
44 socklen_t ss_len,
0f955520 45 char *name_buf,
9a5a8673
MP
46 const char *port_buf);
47
660c6fbd
MP
48/* Establish a proxy connection on an open socket to a web roxy by
49 * using the CONNECT method. */
4c3b4b25
AT
50static int establish_proxy_connection(int fd, char *host, int port)
51{
52 char buffer[1024];
53 char *cp;
54
8950ac03 55 snprintf(buffer, sizeof(buffer), "CONNECT %s:%d HTTP/1.0\r\n\r\n", host, port);
4c3b4b25 56 if (write(fd, buffer, strlen(buffer)) != strlen(buffer)) {
660c6fbd 57 rprintf(FERROR, "failed to write to proxy: %s\n",
4c3b4b25
AT
58 strerror(errno));
59 return -1;
60 }
61
62 for (cp = buffer; cp < &buffer[sizeof(buffer) - 1]; cp++) {
63 if (read(fd, cp, 1) != 1) {
660c6fbd
MP
64 rprintf(FERROR, "failed to read from proxy: %s\n",
65 strerror(errno));
4c3b4b25
AT
66 return -1;
67 }
68 if (*cp == '\n')
69 break;
70 }
71
72 if (*cp != '\n')
73 cp++;
74 *cp-- = '\0';
75 if (*cp == '\r')
76 *cp = '\0';
77 if (strncmp(buffer, "HTTP/", 5) != 0) {
78 rprintf(FERROR, "bad response from proxy - %s\n",
79 buffer);
80 return -1;
81 }
82 for (cp = &buffer[5]; isdigit(*cp) || (*cp == '.'); cp++)
83 ;
84 while (*cp == ' ')
85 cp++;
86 if (*cp != '2') {
87 rprintf(FERROR, "bad response from proxy - %s\n",
88 buffer);
89 return -1;
90 }
91 /* throw away the rest of the HTTP header */
92 while (1) {
93 for (cp = buffer; cp < &buffer[sizeof(buffer) - 1];
94 cp++) {
95 if (read(fd, cp, 1) != 1) {
660c6fbd
MP
96 rprintf(FERROR, "failed to read from proxy: %s\n",
97 strerror(errno));
4c3b4b25
AT
98 return -1;
99 }
100 if (*cp == '\n')
101 break;
102 }
103 if ((cp > buffer) && (*cp == '\n'))
104 cp--;
105 if ((cp == buffer) && ((*cp == '\n') || (*cp == '\r')))
106 break;
107 }
108 return 0;
109}
110
111
f8be7d42
MP
112/**
113 * Try to set the local address for a newly-created socket. Return -1
114 * if this fails.
115 **/
116int try_bind_local(int s,
117 int ai_family, int ai_socktype,
118 const char *bind_address)
119{
120 int error;
121 struct addrinfo bhints, *bres_all, *r;
122
123 memset(&bhints, 0, sizeof(bhints));
124 bhints.ai_family = ai_family;
125 bhints.ai_socktype = ai_socktype;
126 bhints.ai_flags = AI_PASSIVE;
98355b80 127 if ((error = getaddrinfo(bind_address, NULL, &bhints, &bres_all))) {
f8be7d42
MP
128 rprintf(FERROR, RSYNC_NAME ": getaddrinfo %s: %s\n",
129 bind_address, gai_strerror(error));
130 return -1;
131 }
132
133 for (r = bres_all; r; r = r->ai_next) {
9ec75284 134 if (bind(s, r->ai_addr, r->ai_addrlen) == -1)
f8be7d42
MP
135 continue;
136 return s;
137 }
138
139 /* no error message; there might be some problem that allows
140 * creation of the socket but not binding, perhaps if the
141 * machine has no ipv6 address of this name. */
142 return -1;
143}
144
eecd22ff 145
d5d4b282
MP
146/**
147 * Open a socket to a tcp remote host with the specified port .
06963d0f 148 *
d5d4b282
MP
149 * Based on code from Warren. Proxy support by Stephen Rothwell.
150 * getaddrinfo() rewrite contributed by KAME.net.
06963d0f 151 *
d5d4b282
MP
152 * Now that we support IPv6 we need to look up the remote machine's
153 * address first, using @p af_hint to set a preference for the type
154 * of address. Then depending on whether it has v4 or v6 addresses we
155 * try to open a connection.
06963d0f 156 *
d5d4b282
MP
157 * The loop allows for machines with some addresses which may not be
158 * reachable, perhaps because we can't e.g. route ipv6 to that network
159 * but we can get ip4 packets through.
160 *
161 * @param bind_address Local address to use. Normally NULL to bind
162 * the wildcard address.
163 *
164 * @param af_hint Address family, e.g. AF_INET or AF_INET6.
06963d0f 165 **/
d5d4b282
MP
166int open_socket_out(char *host, int port, const char *bind_address,
167 int af_hint)
bc2e93eb 168{
f0fca04e 169 int type = SOCK_STREAM;
06963d0f
MP
170 int error;
171 int s;
06963d0f
MP
172 struct addrinfo hints, *res0, *res;
173 char portbuf[10];
4c3b4b25 174 char *h;
4c3b4b25
AT
175 int proxied = 0;
176 char buffer[1024];
177 char *cp;
178
660c6fbd
MP
179 /* if we have a RSYNC_PROXY env variable then redirect our
180 * connetcion via a web proxy at the given address. The format
181 * is hostname:port */
4c3b4b25
AT
182 h = getenv("RSYNC_PROXY");
183 proxied = (h != NULL) && (*h != '\0');
184
185 if (proxied) {
186 strlcpy(buffer, h, sizeof(buffer));
187 cp = strchr(buffer, ':');
188 if (cp == NULL) {
660c6fbd
MP
189 rprintf(FERROR,
190 "invalid proxy specification: should be HOST:PORT\n");
4c3b4b25
AT
191 return -1;
192 }
193 *cp++ = '\0';
06963d0f 194 strcpy(portbuf, cp);
4c3b4b25
AT
195 h = buffer;
196 } else {
06963d0f 197 snprintf(portbuf, sizeof(portbuf), "%d", port);
4c3b4b25 198 h = host;
4c3b4b25 199 }
f0fca04e 200
06963d0f 201 memset(&hints, 0, sizeof(hints));
d5d4b282 202 hints.ai_family = af_hint;
06963d0f
MP
203 hints.ai_socktype = type;
204 error = getaddrinfo(h, portbuf, &hints, &res0);
205 if (error) {
d5d4b282
MP
206 rprintf(FERROR, RSYNC_NAME ": getaddrinfo: %s %s: %s\n",
207 h, portbuf, gai_strerror(error));
f0fca04e
AT
208 return -1;
209 }
210
06963d0f 211 s = -1;
2d6dbe29
MP
212 /* Try to connect to all addresses for this machine until we get
213 * through. It might e.g. be multi-homed, or have both IPv4 and IPv6
214 * addresses. We need to create a socket for each record, since the
215 * address record tells us what protocol to use to try to connect. */
06963d0f
MP
216 for (res = res0; res; res = res->ai_next) {
217 s = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
218 if (s < 0)
219 continue;
f0fca04e 220
f8be7d42
MP
221 if (bind_address)
222 if (try_bind_local(s, res->ai_family, type,
223 bind_address) == -1) {
224 close(s);
225 s = -1;
06963d0f
MP
226 continue;
227 }
e30f0657 228
06963d0f
MP
229 if (connect(s, res->ai_addr, res->ai_addrlen) < 0) {
230 close(s);
231 s = -1;
232 continue;
233 }
234 if (proxied &&
235 establish_proxy_connection(s, host, port) != 0) {
236 close(s);
237 s = -1;
238 continue;
239 } else
240 break;
4c3b4b25 241 }
06963d0f
MP
242 freeaddrinfo(res0);
243 if (s < 0) {
7ef6aa64
MP
244 rprintf(FERROR, RSYNC_NAME ": failed to connect to %s: %s\n",
245 h, strerror(errno));
f0fca04e
AT
246 return -1;
247 }
06963d0f 248 return s;
f0fca04e
AT
249}
250
251
eecd22ff
MP
252/**
253 * Open an outgoing socket, but allow for it to be intercepted by
254 * $RSYNC_CONNECT_PROG, which will execute a program across a TCP
255 * socketpair rather than really opening a socket.
256 *
257 * We use this primarily in testing to detect TCP flow bugs, but not
258 * cause security problems by really opening remote connections.
259 *
260 * This is based on the Samba LIBSMB_PROG feature.
06963d0f
MP
261 *
262 * @param bind_address Local address to use. Normally NULL to get the stack default.
eecd22ff
MP
263 **/
264int open_socket_out_wrapped (char *host,
265 int port,
d5d4b282
MP
266 const char *bind_address,
267 int af_hint)
eecd22ff
MP
268{
269 char *prog;
270
271 if ((prog = getenv ("RSYNC_CONNECT_PROG")) != NULL)
272 return sock_exec (prog);
273 else
d5d4b282
MP
274 return open_socket_out (host, port, bind_address,
275 af_hint);
eecd22ff
MP
276}
277
278
279
06963d0f
MP
280/**
281 * Open a socket of the specified type, port and address for incoming data
282 *
b8771f96
MP
283 * Try to be better about handling the results of getaddrinfo(): when
284 * opening an inbound socket, we might get several address results,
285 * e.g. for the machine's ipv4 and ipv6 name.
286 *
287 * If binding a wildcard, then any one of them should do. If an address
288 * was specified but it's insufficiently specific then that's not our
289 * fault.
290 *
291 * However, some of the advertized addresses may not work because e.g. we
292 * don't have IPv6 support in the kernel. In that case go on and try all
293 * addresses until one succeeds.
294 *
06963d0f
MP
295 * @param bind_address Local address to bind, or NULL to allow it to
296 * default.
297 **/
d5d4b282
MP
298static int open_socket_in(int type, int port, const char *bind_address,
299 int af_hint)
f0fca04e 300{
f0fca04e 301 int one=1;
06963d0f 302 int s;
13e29995 303 struct addrinfo hints, *all_ai, *resp;
06963d0f
MP
304 char portbuf[10];
305 int error;
306
307 memset(&hints, 0, sizeof(hints));
d5d4b282 308 hints.ai_family = af_hint;
06963d0f
MP
309 hints.ai_socktype = type;
310 hints.ai_flags = AI_PASSIVE;
311 snprintf(portbuf, sizeof(portbuf), "%d", port);
13e29995 312 error = getaddrinfo(bind_address, portbuf, &hints, &all_ai);
06963d0f 313 if (error) {
7ef6aa64
MP
314 rprintf(FERROR, RSYNC_NAME ": getaddrinfo: bind address %s: %s\n",
315 bind_address, gai_strerror(error));
06963d0f
MP
316 return -1;
317 }
06963d0f 318
13e29995
MP
319 /* We may not be able to create the socket, if for example the
320 * machine knows about IPv6 in the C library, but not in the
321 * kernel. */
322 for (resp = all_ai; resp; resp = resp->ai_next) {
323 s = socket(resp->ai_family, resp->ai_socktype,
324 resp->ai_protocol);
325
326 if (s == -1)
327 /* See if there's another address that will work... */
328 continue;
329
330 setsockopt(s, SOL_SOCKET, SO_REUSEADDR,
331 (char *)&one, sizeof one);
332
333 /* now we've got a socket - we need to bind it */
334 if (bind(s, all_ai->ai_addr, all_ai->ai_addrlen) < 0) {
335 /* Nope, try another */
336 close(s);
337 continue;
b8771f96
MP
338 }
339
13e29995 340 return s;
f0fca04e
AT
341 }
342
13e29995
MP
343 rprintf(FERROR, RSYNC_NAME ": open inbound socket on port %d failed: "
344 "%s\n",
345 port,
346 strerror(errno));
b8771f96 347
13e29995 348 freeaddrinfo(all_ai);
b8771f96 349 return -1;
f0fca04e
AT
350}
351
352
7c1b4daa
MP
353/*
354 * Determine if a file descriptor is in fact a socket
355 */
f0fca04e
AT
356int is_a_socket(int fd)
357{
ac2a1a44
MP
358 int v;
359 socklen_t l;
3eb38818 360 l = sizeof(int);
7c1b4daa
MP
361
362 /* Parameters to getsockopt, setsockopt etc are very
363 * unstandardized across platforms, so don't be surprised if
ac2a1a44
MP
364 * there are compiler warnings on e.g. SCO OpenSwerver or AIX.
365 * It seems they all eventually get the right idea.
7c1b4daa
MP
366 *
367 * Debian says: ``The fifth argument of getsockopt and
368 * setsockopt is in reality an int [*] (and this is what BSD
369 * 4.* and libc4 and libc5 have). Some POSIX confusion
370 * resulted in the present socklen_t. The draft standard has
371 * not been adopted yet, but glibc2 already follows it and
372 * also has socklen_t [*]. See also accept(2).''
373 *
374 * We now return to your regularly scheduled programming. */
3eb38818 375 return(getsockopt(fd, SOL_SOCKET, SO_TYPE, (char *)&v, &l) == 0);
f0fca04e
AT
376}
377
378
8ef4ffd6 379void start_accept_loop(int port, int (*fn)(int ))
f0fca04e
AT
380{
381 int s;
06963d0f 382 extern char *bind_address;
13e29995 383 extern int default_af_hint;
f0fca04e 384
f0fca04e 385 /* open an incoming socket */
13e29995 386 s = open_socket_in(SOCK_STREAM, port, bind_address, default_af_hint);
f0fca04e 387 if (s == -1)
65417579 388 exit_cleanup(RERR_SOCKETIO);
f0fca04e
AT
389
390 /* ready to listen */
391 if (listen(s, 5) == -1) {
392 close(s);
65417579 393 exit_cleanup(RERR_SOCKETIO);
f0fca04e
AT
394 }
395
396
397 /* now accept incoming connections - forking a new process
398 for each incoming connection */
399 while (1) {
400 fd_set fds;
401 int fd;
2d6dbe29 402 struct sockaddr_storage addr;
d54765c4 403 socklen_t addrlen = sizeof addr;
f0fca04e 404
15b84e14
DD
405 /* close log file before the potentially very long select so
406 file can be trimmed by another process instead of growing
407 forever */
408 log_close();
45a83540 409
f0fca04e
AT
410 FD_ZERO(&fds);
411 FD_SET(s, &fds);
412
413 if (select(s+1, &fds, NULL, NULL, NULL) != 1) {
414 continue;
415 }
416
417 if(!FD_ISSET(s, &fds)) continue;
418
2d6dbe29 419 fd = accept(s,(struct sockaddr *)&addr,&addrlen);
f0fca04e
AT
420
421 if (fd == -1) continue;
422
31f440e6
AT
423 signal(SIGCHLD, SIG_IGN);
424
425 /* we shouldn't have any children left hanging around
426 but I have had reports that on Digital Unix zombies
427 are produced, so this ensures that they are reaped */
428#ifdef WNOHANG
0503f060 429 while (waitpid(-1, NULL, WNOHANG) > 0);
31f440e6
AT
430#endif
431
f0fca04e
AT
432 if (fork()==0) {
433 close(s);
15b84e14
DD
434 /* open log file in child before possibly giving
435 up privileges */
436 log_open();
f0fca04e
AT
437 _exit(fn(fd));
438 }
439
440 close(fd);
441 }
f0fca04e
AT
442}
443
444
445enum SOCK_OPT_TYPES {OPT_BOOL,OPT_INT,OPT_ON};
446
447struct
448{
449 char *name;
450 int level;
451 int option;
452 int value;
453 int opttype;
454} socket_options[] = {
455 {"SO_KEEPALIVE", SOL_SOCKET, SO_KEEPALIVE, 0, OPT_BOOL},
456 {"SO_REUSEADDR", SOL_SOCKET, SO_REUSEADDR, 0, OPT_BOOL},
457 {"SO_BROADCAST", SOL_SOCKET, SO_BROADCAST, 0, OPT_BOOL},
458#ifdef TCP_NODELAY
459 {"TCP_NODELAY", IPPROTO_TCP, TCP_NODELAY, 0, OPT_BOOL},
460#endif
461#ifdef IPTOS_LOWDELAY
462 {"IPTOS_LOWDELAY", IPPROTO_IP, IP_TOS, IPTOS_LOWDELAY, OPT_ON},
463#endif
464#ifdef IPTOS_THROUGHPUT
465 {"IPTOS_THROUGHPUT", IPPROTO_IP, IP_TOS, IPTOS_THROUGHPUT, OPT_ON},
466#endif
467#ifdef SO_SNDBUF
468 {"SO_SNDBUF", SOL_SOCKET, SO_SNDBUF, 0, OPT_INT},
469#endif
470#ifdef SO_RCVBUF
471 {"SO_RCVBUF", SOL_SOCKET, SO_RCVBUF, 0, OPT_INT},
472#endif
473#ifdef SO_SNDLOWAT
474 {"SO_SNDLOWAT", SOL_SOCKET, SO_SNDLOWAT, 0, OPT_INT},
475#endif
476#ifdef SO_RCVLOWAT
477 {"SO_RCVLOWAT", SOL_SOCKET, SO_RCVLOWAT, 0, OPT_INT},
478#endif
479#ifdef SO_SNDTIMEO
480 {"SO_SNDTIMEO", SOL_SOCKET, SO_SNDTIMEO, 0, OPT_INT},
481#endif
482#ifdef SO_RCVTIMEO
483 {"SO_RCVTIMEO", SOL_SOCKET, SO_RCVTIMEO, 0, OPT_INT},
484#endif
485 {NULL,0,0,0,0}};
486
487
488
489/****************************************************************************
490set user socket options
491****************************************************************************/
492void set_socket_options(int fd, char *options)
493{
494 char *tok;
a6801c39
AT
495 if (!options || !*options) return;
496
f0fca04e
AT
497 options = strdup(options);
498
499 if (!options) out_of_memory("set_socket_options");
500
501 for (tok=strtok(options, " \t,"); tok; tok=strtok(NULL," \t,")) {
502 int ret=0,i;
503 int value = 1;
504 char *p;
505 int got_value = 0;
506
507 if ((p = strchr(tok,'='))) {
508 *p = 0;
509 value = atoi(p+1);
510 got_value = 1;
511 }
512
513 for (i=0;socket_options[i].name;i++)
514 if (strcmp(socket_options[i].name,tok)==0)
515 break;
516
517 if (!socket_options[i].name) {
518 rprintf(FERROR,"Unknown socket option %s\n",tok);
519 continue;
520 }
521
522 switch (socket_options[i].opttype) {
523 case OPT_BOOL:
524 case OPT_INT:
525 ret = setsockopt(fd,socket_options[i].level,
526 socket_options[i].option,(char *)&value,sizeof(int));
527 break;
528
529 case OPT_ON:
530 if (got_value)
531 rprintf(FERROR,"syntax error - %s does not take a value\n",tok);
532
533 {
534 int on = socket_options[i].value;
535 ret = setsockopt(fd,socket_options[i].level,
536 socket_options[i].option,(char *)&on,sizeof(int));
537 }
538 break;
539 }
540
541 if (ret != 0)
660c6fbd
MP
542 rprintf(FERROR, "failed to set socket option %s: %s\n", tok,
543 strerror(errno));
f0fca04e
AT
544 }
545
546 free(options);
547}
548
549/****************************************************************************
550become a daemon, discarding the controlling terminal
551****************************************************************************/
552void become_daemon(void)
553{
b11ed3b1
AT
554 int i;
555
c46ded46 556 if (fork()) {
f0fca04e 557 _exit(0);
c46ded46 558 }
f0fca04e
AT
559
560 /* detach from the terminal */
561#ifdef HAVE_SETSID
562 setsid();
563#else
564#ifdef TIOCNOTTY
c46ded46
AT
565 i = open("/dev/tty", O_RDWR);
566 if (i >= 0) {
567 ioctl(i, (int) TIOCNOTTY, (char *)0);
568 close(i);
f0fca04e
AT
569 }
570#endif /* TIOCNOTTY */
571#endif
b11ed3b1
AT
572 /* make sure that stdin, stdout an stderr don't stuff things
573 up (library functions, for example) */
574 for (i=0;i<3;i++) {
575 close(i);
576 open("/dev/null", O_RDWR);
577 }
bc2e93eb 578}
ff8b29b8 579
1f0fa931
MP
580/**
581 * Return the IP addr of the client as a string
582 **/
ff8b29b8
AT
583char *client_addr(int fd)
584{
2d6dbe29 585 struct sockaddr_storage ss;
d54765c4 586 socklen_t length = sizeof ss;
ff8b29b8 587 static char addr_buf[100];
11a5a3c7
AT
588 static int initialised;
589
590 if (initialised) return addr_buf;
591
592 initialised = 1;
ff8b29b8 593
2d6dbe29 594 if (getpeername(fd, (struct sockaddr *)&ss, &length)) {
65417579 595 exit_cleanup(RERR_SOCKETIO);
ff8b29b8 596 }
06963d0f 597
2d6dbe29 598 getnameinfo((struct sockaddr *)&ss, length,
06963d0f 599 addr_buf, sizeof(addr_buf), NULL, 0, NI_NUMERICHOST);
ff8b29b8
AT
600 return addr_buf;
601}
602
603
51f289d1 604static int get_sockaddr_family(const struct sockaddr_storage *ss)
d91c8c50
MP
605{
606 return ((struct sockaddr *) ss)->sa_family;
607}
608
609
1f0fa931 610/**
d1d15050
MP
611 * Return the DNS name of the client.
612 *
613 * The name is statically cached so that repeated lookups are quick,
614 * so there is a limit of one lookup per customer.
885448d7
MP
615 *
616 * If anything goes wrong, including the name->addr->name check, then
617 * we just use "UNKNOWN", so you can use that value in hosts allow
618 * lines.
1f0fa931 619 **/
ff8b29b8
AT
620char *client_name(int fd)
621{
2d6dbe29 622 struct sockaddr_storage ss;
9a5a8673 623 socklen_t ss_len = sizeof ss;
ff8b29b8 624 static char name_buf[100];
06963d0f 625 static char port_buf[100];
11a5a3c7
AT
626 static int initialised;
627
628 if (initialised) return name_buf;
629
885448d7 630 strcpy(name_buf, default_name);
11a5a3c7 631 initialised = 1;
ff8b29b8 632
9a5a8673 633 if (getpeername(fd, (struct sockaddr *)&ss, &ss_len)) {
d5d4b282
MP
634 /* FIXME: Can we really not continue? */
635 rprintf(FERROR, RSYNC_NAME ": getpeername on fd%d failed: %s\n",
c11b8806 636 fd, strerror(errno));
65417579 637 exit_cleanup(RERR_SOCKETIO);
ff8b29b8
AT
638 }
639
9a5a8673
MP
640 if (!lookup_name(&ss, ss_len, name_buf, sizeof name_buf, port_buf, sizeof port_buf))
641 check_name(&ss, ss_len, name_buf, port_buf);
642
643 return name_buf;
644}
645
646
647/**
648 * Look up a name from @p ss into @p name_buf.
649 **/
650static int lookup_name(const struct sockaddr_storage *ss,
651 socklen_t ss_len,
652 char *name_buf, size_t name_buf_len,
653 char *port_buf, size_t port_buf_len)
654{
655 int name_err;
9a5a8673 656
06963d0f 657#ifdef INET6
9a5a8673
MP
658 if (get_sockaddr_family(ss) == AF_INET6 &&
659 IN6_IS_ADDR_V4MAPPED(&((struct sockaddr_in6 *)ss)->sin6_addr)) {
362099a5
MP
660 /* OK, so ss is in the IPv6 family, but it is really
661 * an IPv4 address: something like
662 * "::ffff:10.130.1.2". If we use it as-is, then the
663 * reverse lookup might fail or perhaps something else
664 * bad might happen. So instead we convert it to an
665 * equivalent address in the IPv4 address family. */
06963d0f
MP
666 struct sockaddr_in6 sin6;
667 struct sockaddr_in *sin;
668
9a5a8673
MP
669 memcpy(&sin6, ss, sizeof(sin6));
670 sin = (struct sockaddr_in *)ss;
06963d0f
MP
671 memset(sin, 0, sizeof(*sin));
672 sin->sin_family = AF_INET;
9a5a8673 673 ss_len = sizeof(struct sockaddr_in);
06963d0f 674#ifdef HAVE_SOCKADDR_LEN
9a5a8673 675 sin->sin_len = ss_len;
06963d0f
MP
676#endif
677 sin->sin_port = sin6.sin6_port;
362099a5
MP
678 /* FIXME: Isn't there a macro we can use here rather
679 * than grovelling through the struct? It might be
680 * wrong on some systems. */
06963d0f
MP
681 memcpy(&sin->sin_addr, &sin6.sin6_addr.s6_addr[12],
682 sizeof(sin->sin_addr));
683 }
684#endif
685
686 /* reverse lookup */
b14545b3
MP
687 name_err = getnameinfo((struct sockaddr *) ss, ss_len,
688 name_buf, name_buf_len,
689 port_buf, port_buf_len,
690 NI_NAMEREQD | NI_NUMERICSERV);
691 if (name_err != 0) {
885448d7 692 strcpy(name_buf, default_name);
b14545b3 693 rprintf(FERROR, RSYNC_NAME ": name lookup failed: %s\n",
9a5a8673
MP
694 gai_strerror(name_err));
695 return name_err;
ff8b29b8
AT
696 }
697
9a5a8673
MP
698 return 0;
699}
700
701
702
703/* Do a forward lookup on name_buf and make sure it corresponds to ss
704 * -- otherwise we may be being spoofed. If we suspect we are, then
705 * we don't abort the connection but just emit a warning. */
706static int check_name(const struct sockaddr_storage *ss,
707 socklen_t ss_len,
0f955520 708 char *name_buf,
9a5a8673
MP
709 const char *port_buf)
710{
711 struct addrinfo hints, *res, *res0;
712 int error;
713
06963d0f
MP
714 memset(&hints, 0, sizeof(hints));
715 hints.ai_family = PF_UNSPEC;
716 hints.ai_flags = AI_CANONNAME;
717 hints.ai_socktype = SOCK_STREAM;
718 error = getaddrinfo(name_buf, port_buf, &hints, &res0);
719 if (error) {
885448d7 720 strcpy(name_buf, default_name);
7ef6aa64 721 rprintf(FERROR,
9a5a8673
MP
722 RSYNC_NAME ": forward name lookup for %s:%s failed: %s\n",
723 name_buf, port_buf,
7ef6aa64 724 gai_strerror(error));
9a5a8673 725 return error;
06963d0f 726 }
de5fb374 727
9a5a8673
MP
728
729 /* We expect that one of the results will be the same as ss. */
06963d0f 730 for (res = res0; res; res = res->ai_next) {
9a5a8673 731 if (res->ai_family != get_sockaddr_family(ss))
06963d0f 732 continue;
9a5a8673 733 if (res->ai_addrlen != ss_len)
06963d0f 734 continue;
9a5a8673 735 if (memcmp(res->ai_addr, ss, res->ai_addrlen) == 0)
06963d0f
MP
736 break;
737 }
738
06963d0f 739 if (res == NULL) {
885448d7 740 strcpy(name_buf, default_name);
9a5a8673
MP
741 /* We hit the end of the list without finding an
742 * address that was the same as ss. */
743 rprintf(FERROR, RSYNC_NAME
744 ": no address record for \"%s\" corresponds to peer name: spoofed address?\n",
745 name_buf);
de5fb374
AT
746 }
747
06963d0f 748 freeaddrinfo(res0);
9a5a8673 749 return 0;
ff8b29b8 750}
5c9730a4 751
eecd22ff
MP
752
753/*******************************************************************
754this is like socketpair but uses tcp. It is used by the Samba
755regression test code
756The function guarantees that nobody else can attach to the socket,
757or if they do that this function fails and the socket gets closed
758returns 0 on success, -1 on failure
759the resulting file descriptors are symmetrical
760 ******************************************************************/
761static int socketpair_tcp(int fd[2])
762{
763 int listener;
764 struct sockaddr_in sock;
765 struct sockaddr_in sock2;
766 socklen_t socklen = sizeof(sock);
767 int connect_done = 0;
768
769 fd[0] = fd[1] = listener = -1;
770
771 memset(&sock, 0, sizeof(sock));
772
773 if ((listener = socket(PF_INET, SOCK_STREAM, 0)) == -1) goto failed;
774
775 memset(&sock2, 0, sizeof(sock2));
776#ifdef HAVE_SOCK_SIN_LEN
777 sock2.sin_len = sizeof(sock2);
778#endif
779 sock2.sin_family = PF_INET;
780
781 bind(listener, (struct sockaddr *)&sock2, sizeof(sock2));
782
783 if (listen(listener, 1) != 0) goto failed;
784
785 if (getsockname(listener, (struct sockaddr *)&sock, &socklen) != 0) goto failed;
786
787 if ((fd[1] = socket(PF_INET, SOCK_STREAM, 0)) == -1) goto failed;
788
789 set_nonblocking(fd[1]);
790
791 sock.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
792
793 if (connect(fd[1],(struct sockaddr *)&sock,sizeof(sock)) == -1) {
794 if (errno != EINPROGRESS) goto failed;
795 } else {
796 connect_done = 1;
797 }
798
799 if ((fd[0] = accept(listener, (struct sockaddr *)&sock, &socklen)) == -1) goto failed;
800
801 close(listener);
802 if (connect_done == 0) {
803 if (connect(fd[1],(struct sockaddr *)&sock,sizeof(sock)) != 0
804 && errno != EISCONN) goto failed;
805 }
806
807 set_blocking (fd[1]);
808
809 /* all OK! */
810 return 0;
811
812 failed:
813 if (fd[0] != -1) close(fd[0]);
814 if (fd[1] != -1) close(fd[1]);
815 if (listener != -1) close(listener);
816 return -1;
817}
818
819
d02984bb
MP
820
821/**
822 * Run a program on a local tcp socket, so that we can talk to it's
823 * stdin and stdout. This is used to launch ssh and similar
824 * connection helper programs for rsync.
825 *
826 * @return a socket which is attached to a subprocess running
827 * "prog". stdin and stdout are attached. stderr is left attached to
828 * the original stderr
829 **/
eecd22ff
MP
830int sock_exec(const char *prog)
831{
832 int fd[2];
5d264037
MP
833
834 if (verbose > 0) {
835 rprintf(FINFO, RSYNC_NAME
836 ": open connection using \"%s\"\n",
837 prog);
838 }
839
eecd22ff
MP
840 if (socketpair_tcp(fd) != 0) {
841 rprintf (FERROR, RSYNC_NAME
842 ": socketpair_tcp failed (%s)\n",
843 strerror(errno));
844 return -1;
845 }
846 if (fork() == 0) {
847 close(fd[0]);
848 close(0);
849 close(1);
850 dup(fd[1]);
851 dup(fd[1]);
5d264037
MP
852 if (verbose > 3) {
853 /* Can't use rprintf because we've forked. */
eecd22ff
MP
854 fprintf (stderr,
855 RSYNC_NAME ": execute socket program \"%s\"\n",
856 prog);
5d264037 857 }
eecd22ff
MP
858 exit (system (prog));
859 }
860 close (fd[1]);
861 return fd[0];
862}
863
864
865