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