You cannot do "export VAR=VALUE" all on one line; the export must be
[rsync.git] / socket.c
1 /* -*- c-file-style: "linux" -*-
2    
3    Copyright (C) 1992-2001 by Andrew Tridgell <tridge@samba.org>
4    Copyright (C) 2001 by Martin Pool <mbp@samba.org>
5    
6    This program is free software; you can redistribute it and/or modify
7    it under the terms of the GNU General Public License as published by
8    the Free Software Foundation; either version 2 of the License, or
9    (at your option) any later version.
10    
11    This program is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14    GNU General Public License for more details.
15    
16    You should have received a copy of the GNU General Public License
17    along with this program; if not, write to the Free Software
18    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 */
20
21 /*
22   socket functions used in rsync 
23
24   */
25
26 #include "rsync.h"
27
28
29 /* Establish a proxy connection on an open socket to a web roxy by
30  * using the CONNECT method. */
31 static int establish_proxy_connection(int fd, char *host, int port)
32 {
33         char buffer[1024];
34         char *cp;
35
36         snprintf(buffer, sizeof(buffer), "CONNECT %s:%d HTTP/1.0\r\n\r\n", host, port);
37         if (write(fd, buffer, strlen(buffer)) != strlen(buffer)) {
38                 rprintf(FERROR, "failed to write to proxy: %s\n",
39                         strerror(errno));
40                 return -1;
41         }
42
43         for (cp = buffer; cp < &buffer[sizeof(buffer) - 1]; cp++) {
44                 if (read(fd, cp, 1) != 1) {
45                         rprintf(FERROR, "failed to read from proxy: %s\n",
46                                 strerror(errno));
47                         return -1;
48                 }
49                 if (*cp == '\n')
50                         break;
51         }
52
53         if (*cp != '\n')
54                 cp++;
55         *cp-- = '\0';
56         if (*cp == '\r')
57                 *cp = '\0';
58         if (strncmp(buffer, "HTTP/", 5) != 0) {
59                 rprintf(FERROR, "bad response from proxy - %s\n",
60                         buffer);
61                 return -1;
62         }
63         for (cp = &buffer[5]; isdigit(*cp) || (*cp == '.'); cp++)
64                 ;
65         while (*cp == ' ')
66                 cp++;
67         if (*cp != '2') {
68                 rprintf(FERROR, "bad response from proxy - %s\n",
69                         buffer);
70                 return -1;
71         }
72         /* throw away the rest of the HTTP header */
73         while (1) {
74                 for (cp = buffer; cp < &buffer[sizeof(buffer) - 1];
75                      cp++) {
76                         if (read(fd, cp, 1) != 1) {
77                                 rprintf(FERROR, "failed to read from proxy: %s\n",
78                                         strerror(errno));
79                                 return -1;
80                         }
81                         if (*cp == '\n')
82                                 break;
83                 }
84                 if ((cp > buffer) && (*cp == '\n'))
85                         cp--;
86                 if ((cp == buffer) && ((*cp == '\n') || (*cp == '\r')))
87                         break;
88         }
89         return 0;
90 }
91
92
93
94 /* open a socket to a tcp remote host with the specified port 
95    based on code from Warren
96    proxy support by Stephen Rothwell */
97 static int open_socket_out (char *host,
98                             int port,
99                             struct in_addr *address)
100 {
101         int type = SOCK_STREAM;
102         struct sockaddr_in sock_out;
103         struct sockaddr_in sock;
104         int res;
105         struct hostent *hp;
106         char *h;
107         unsigned p;
108         int proxied = 0;
109         char buffer[1024];
110         char *cp;
111
112         /* if we have a RSYNC_PROXY env variable then redirect our
113          * connetcion via a web proxy at the given address. The format
114          * is hostname:port */
115         h = getenv("RSYNC_PROXY");
116         proxied = (h != NULL) && (*h != '\0');
117
118         if (proxied) {
119                 strlcpy(buffer, h, sizeof(buffer));
120                 cp = strchr(buffer, ':');
121                 if (cp == NULL) {
122                         rprintf(FERROR,
123                                 "invalid proxy specification: should be HOST:PORT\n");
124                         return -1;
125                 }
126                 *cp++ = '\0';
127                 p = atoi(cp);
128                 h = buffer;
129         } else {
130                 h = host;
131                 p = port;
132         }
133
134         res = socket(PF_INET, type, 0);
135         if (res == -1) {
136                 return -1;
137         }
138
139         hp = gethostbyname(h);
140         if (!hp) {
141                 rprintf(FERROR,"unknown host: \"%s\"\n", h);
142                 close(res);
143                 return -1;
144         }
145
146         memcpy(&sock_out.sin_addr, hp->h_addr, hp->h_length);
147         sock_out.sin_port = htons(p);
148         sock_out.sin_family = PF_INET;
149
150         if (address) {
151                 sock.sin_addr = *address;
152                 sock.sin_port = 0;
153                 sock.sin_family = hp->h_addrtype;
154                 bind(res, (struct sockaddr * ) &sock,sizeof(sock));
155         }
156
157         if (connect(res,(struct sockaddr *)&sock_out,sizeof(sock_out))) {
158                 rprintf (FERROR, RSYNC_NAME ": failed to connect to host %s: %s\n",
159                          h, strerror(errno));
160                 close(res);
161                 return -1;
162         }
163
164         if (proxied && establish_proxy_connection(res, host, port) != 0) {
165                 close(res);
166                 return -1;
167         }
168
169         return res;
170 }
171
172
173 /**
174  * Open an outgoing socket, but allow for it to be intercepted by
175  * $RSYNC_CONNECT_PROG, which will execute a program across a TCP
176  * socketpair rather than really opening a socket.
177  *
178  * We use this primarily in testing to detect TCP flow bugs, but not
179  * cause security problems by really opening remote connections.
180  *
181  * This is based on the Samba LIBSMB_PROG feature.
182  **/
183 int open_socket_out_wrapped (char *host,
184                              int port,
185                              struct in_addr *address)
186 {
187         char *prog;
188
189         if ((prog = getenv ("RSYNC_CONNECT_PROG")) != NULL) 
190                 return sock_exec (prog);
191         else 
192                 return open_socket_out (host, port, address);
193 }
194
195
196
197 /****************************************************************************
198 open a socket of the specified type, port and address for incoming data
199 ****************************************************************************/
200 static int open_socket_in(int type, int port, struct in_addr *address)
201 {
202         struct sockaddr_in sock;
203         int res;
204         int one=1;
205
206         memset((char *)&sock,0,sizeof(sock));
207         sock.sin_port = htons(port);
208         sock.sin_family = AF_INET;
209         if (address) {
210                 sock.sin_addr = *address;
211         } else {
212                 sock.sin_addr.s_addr = INADDR_ANY;
213         }
214         res = socket(AF_INET, type, 0);
215         if (res == -1) { 
216                 rprintf(FERROR, RSYNC_NAME ": socket failed: %s\n",
217                         strerror(errno)); 
218                 return -1; 
219         }
220
221         setsockopt(res,SOL_SOCKET,SO_REUSEADDR,(char *)&one,sizeof(one));
222
223         /* now we've got a socket - we need to bind it */
224         if (bind(res, (struct sockaddr * ) &sock,sizeof(sock)) == -1) { 
225                 rprintf(FERROR,"bind failed on port %d: %s\n", port,
226                         strerror(errno));
227                 if (errno == EACCES && port < 1024) {
228                         rprintf(FERROR, "Note: you must be root to bind "
229                                 "to low-numbered ports");
230                 }
231                 close(res); 
232                 return -1;
233         }
234
235         return res;
236 }
237
238
239 /*
240  * Determine if a file descriptor is in fact a socket
241  */
242 int is_a_socket(int fd)
243 {
244         int v;
245         socklen_t l;
246         l = sizeof(int);
247
248         /* Parameters to getsockopt, setsockopt etc are very
249          * unstandardized across platforms, so don't be surprised if
250          * there are compiler warnings on e.g. SCO OpenSwerver or AIX.
251          * It seems they all eventually get the right idea.
252          *
253          * Debian says: ``The fifth argument of getsockopt and
254          * setsockopt is in reality an int [*] (and this is what BSD
255          * 4.* and libc4 and libc5 have).  Some POSIX confusion
256          * resulted in the present socklen_t.  The draft standard has
257          * not been adopted yet, but glibc2 already follows it and
258          * also has socklen_t [*]. See also accept(2).''
259          *
260          * We now return to your regularly scheduled programming.  */
261         return(getsockopt(fd, SOL_SOCKET, SO_TYPE, (char *)&v, &l) == 0);
262 }
263
264
265 void start_accept_loop(int port, int (*fn)(int ))
266 {
267         int s;
268         extern struct in_addr socket_address;
269
270         /* open an incoming socket */
271         s = open_socket_in(SOCK_STREAM, port, &socket_address);
272         if (s == -1)
273                 exit_cleanup(RERR_SOCKETIO);
274
275         /* ready to listen */
276         if (listen(s, 5) == -1) {
277                 close(s);
278                 exit_cleanup(RERR_SOCKETIO);
279         }
280
281
282         /* now accept incoming connections - forking a new process
283            for each incoming connection */
284         while (1) {
285                 fd_set fds;
286                 int fd;
287                 struct sockaddr addr;
288                 socklen_t in_addrlen = sizeof(addr);
289
290                 /* close log file before the potentially very long select so
291                    file can be trimmed by another process instead of growing
292                    forever */
293                 log_close();
294
295                 FD_ZERO(&fds);
296                 FD_SET(s, &fds);
297
298                 if (select(s+1, &fds, NULL, NULL, NULL) != 1) {
299                         continue;
300                 }
301
302                 if(!FD_ISSET(s, &fds)) continue;
303
304                 /* See note above prototypes. */
305                 fd = accept(s,&addr, &in_addrlen);
306
307                 if (fd == -1) continue;
308
309                 signal(SIGCHLD, SIG_IGN);
310
311                 /* we shouldn't have any children left hanging around
312                    but I have had reports that on Digital Unix zombies
313                    are produced, so this ensures that they are reaped */
314 #ifdef WNOHANG
315                 while (waitpid(-1, NULL, WNOHANG) > 0);
316 #endif
317
318                 if (fork()==0) {
319                         close(s);
320
321                         /* open log file in child before possibly giving
322                            up privileges  */
323                         log_open();
324
325                         _exit(fn(fd));
326                 }
327
328                 close(fd);
329         }
330 }
331
332
333 enum SOCK_OPT_TYPES {OPT_BOOL,OPT_INT,OPT_ON};
334
335 struct
336 {
337   char *name;
338   int level;
339   int option;
340   int value;
341   int opttype;
342 } socket_options[] = {
343   {"SO_KEEPALIVE",      SOL_SOCKET,    SO_KEEPALIVE,    0,                 OPT_BOOL},
344   {"SO_REUSEADDR",      SOL_SOCKET,    SO_REUSEADDR,    0,                 OPT_BOOL},
345   {"SO_BROADCAST",      SOL_SOCKET,    SO_BROADCAST,    0,                 OPT_BOOL},
346 #ifdef TCP_NODELAY
347   {"TCP_NODELAY",       IPPROTO_TCP,   TCP_NODELAY,     0,                 OPT_BOOL},
348 #endif
349 #ifdef IPTOS_LOWDELAY
350   {"IPTOS_LOWDELAY",    IPPROTO_IP,    IP_TOS,          IPTOS_LOWDELAY,    OPT_ON},
351 #endif
352 #ifdef IPTOS_THROUGHPUT
353   {"IPTOS_THROUGHPUT",  IPPROTO_IP,    IP_TOS,          IPTOS_THROUGHPUT,  OPT_ON},
354 #endif
355 #ifdef SO_SNDBUF
356   {"SO_SNDBUF",         SOL_SOCKET,    SO_SNDBUF,       0,                 OPT_INT},
357 #endif
358 #ifdef SO_RCVBUF
359   {"SO_RCVBUF",         SOL_SOCKET,    SO_RCVBUF,       0,                 OPT_INT},
360 #endif
361 #ifdef SO_SNDLOWAT
362   {"SO_SNDLOWAT",       SOL_SOCKET,    SO_SNDLOWAT,     0,                 OPT_INT},
363 #endif
364 #ifdef SO_RCVLOWAT
365   {"SO_RCVLOWAT",       SOL_SOCKET,    SO_RCVLOWAT,     0,                 OPT_INT},
366 #endif
367 #ifdef SO_SNDTIMEO
368   {"SO_SNDTIMEO",       SOL_SOCKET,    SO_SNDTIMEO,     0,                 OPT_INT},
369 #endif
370 #ifdef SO_RCVTIMEO
371   {"SO_RCVTIMEO",       SOL_SOCKET,    SO_RCVTIMEO,     0,                 OPT_INT},
372 #endif
373   {NULL,0,0,0,0}};
374
375         
376
377 /****************************************************************************
378 set user socket options
379 ****************************************************************************/
380 void set_socket_options(int fd, char *options)
381 {
382         char *tok;
383         if (!options || !*options) return;
384
385         options = strdup(options);
386         
387         if (!options) out_of_memory("set_socket_options");
388
389         for (tok=strtok(options, " \t,"); tok; tok=strtok(NULL," \t,")) {
390                 int ret=0,i;
391                 int value = 1;
392                 char *p;
393                 int got_value = 0;
394
395                 if ((p = strchr(tok,'='))) {
396                         *p = 0;
397                         value = atoi(p+1);
398                         got_value = 1;
399                 }
400
401                 for (i=0;socket_options[i].name;i++)
402                         if (strcmp(socket_options[i].name,tok)==0)
403                                 break;
404
405                 if (!socket_options[i].name) {
406                         rprintf(FERROR,"Unknown socket option %s\n",tok);
407                         continue;
408                 }
409
410                 switch (socket_options[i].opttype) {
411                 case OPT_BOOL:
412                 case OPT_INT:
413                         ret = setsockopt(fd,socket_options[i].level,
414                                          socket_options[i].option,(char *)&value,sizeof(int));
415                         break;
416                         
417                 case OPT_ON:
418                         if (got_value)
419                                 rprintf(FERROR,"syntax error - %s does not take a value\n",tok);
420
421                         {
422                                 int on = socket_options[i].value;
423                                 ret = setsockopt(fd,socket_options[i].level,
424                                                  socket_options[i].option,(char *)&on,sizeof(int));
425                         }
426                         break;    
427                 }
428                 
429                 if (ret != 0)
430                         rprintf(FERROR, "failed to set socket option %s: %s\n", tok,
431                                 strerror(errno));
432         }
433
434         free(options);
435 }
436
437 /****************************************************************************
438 become a daemon, discarding the controlling terminal
439 ****************************************************************************/
440 void become_daemon(void)
441 {
442         int i;
443
444         if (fork()) {
445                 _exit(0);
446         }
447
448         /* detach from the terminal */
449 #ifdef HAVE_SETSID
450         setsid();
451 #else
452 #ifdef TIOCNOTTY
453         i = open("/dev/tty", O_RDWR);
454         if (i >= 0) {
455                 ioctl(i, (int) TIOCNOTTY, (char *)0);      
456                 close(i);
457         }
458 #endif /* TIOCNOTTY */
459 #endif
460         /* make sure that stdin, stdout an stderr don't stuff things
461            up (library functions, for example) */
462         for (i=0;i<3;i++) {
463                 close(i); 
464                 open("/dev/null", O_RDWR);
465         }
466 }
467
468 /*******************************************************************
469  return the IP addr of the client as a string 
470  ******************************************************************/
471 char *client_addr(int fd)
472 {
473         struct sockaddr sa;
474         struct sockaddr_in *sockin = (struct sockaddr_in *) (&sa);
475         socklen_t length = sizeof(sa);
476         static char addr_buf[100];
477         static int initialised;
478
479         if (initialised) return addr_buf;
480
481         initialised = 1;
482
483         if (getpeername(fd, &sa, &length)) {
484                 exit_cleanup(RERR_SOCKETIO);
485         }
486         
487         strlcpy(addr_buf,(char *)inet_ntoa(sockin->sin_addr), sizeof(addr_buf));
488         return addr_buf;
489 }
490
491
492 /*******************************************************************
493  return the DNS name of the client 
494  ******************************************************************/
495 char *client_name(int fd)
496 {
497         struct sockaddr sa;
498         struct sockaddr_in *sockin = (struct sockaddr_in *) (&sa);
499         socklen_t length = sizeof(sa);
500         static char name_buf[100];
501         struct hostent *hp;
502         char **p;
503         char *def = "UNKNOWN";
504         static int initialised;
505
506         if (initialised) return name_buf;
507
508         initialised = 1;
509
510         strcpy(name_buf,def);
511
512         if (getpeername(fd, &sa, &length)) {
513                 exit_cleanup(RERR_SOCKETIO);
514         }
515
516         /* Look up the remote host name. */
517         if ((hp = gethostbyaddr((char *) &sockin->sin_addr,
518                                 sizeof(sockin->sin_addr),
519                                 AF_INET))) {
520                 strlcpy(name_buf,(char *)hp->h_name,sizeof(name_buf));
521         }
522
523
524         /* do a forward lookup as well to prevent spoofing */
525         hp = gethostbyname(name_buf);
526         if (!hp) {
527                 strcpy (name_buf,def);
528                 rprintf (FERROR, "reverse name lookup for \"%s\" failed\n",
529                         name_buf);
530         } else {
531                 for (p=hp->h_addr_list;*p;p++) {
532                         if (memcmp(*p, &sockin->sin_addr, hp->h_length) == 0) {
533                                 break;
534                         }
535                 }
536                 if (!*p) {
537                         strcpy(name_buf,def);
538                         rprintf(FERROR,"reverse name lookup mismatch - spoofed address?\n");
539                 } 
540         }
541
542         return name_buf;
543 }
544
545 /**
546    Convert a string to an IP address. The string can be a name or
547    dotted decimal number.
548
549    Returns a pointer to a static in_addr struct -- if you call this
550    more than once then you should copy it.
551 */
552 struct in_addr *ip_address(const char *str)
553 {
554         static struct in_addr ret;
555         struct hostent *hp;
556
557         if (!str) {
558                 rprintf (FERROR, "ip_address received NULL name\n");
559                 return NULL;
560         }
561
562         /* try as an IP address */
563         if (inet_aton(str, &ret) != 0) {
564                 return &ret;
565         }
566
567         /* otherwise assume it's a network name of some sort and use 
568            gethostbyname */
569         if ((hp = gethostbyname (str)) == 0) {
570                 rprintf(FERROR, "gethostbyname failed for \"%s\": unknown host?\n",str);
571                 return NULL;
572         }
573
574         if (hp->h_addr == NULL) {
575                 rprintf(FERROR, "gethostbyname: host address is invalid for host \"%s\"\n",str);
576                 return NULL;
577         }
578
579         if (hp->h_length > sizeof ret) {
580                 rprintf(FERROR, "gethostbyname: host address for \"%s\" is too large\n",
581                         str);
582                 return NULL;
583         }
584
585         if (hp->h_addrtype != AF_INET) {
586                 rprintf (FERROR, "gethostname: host address for \"%s\" is not IPv4\n",
587                          str);
588                 return NULL;
589         }
590
591         /* This is kind of difficult.  The only field in ret is
592            s_addr, which is the IP address as a 32-bit int.  On
593            UNICOS, s_addr is in fact a *bitfield* for reasons best
594            know to Cray.  This means we can't memcpy in to it.  On the
595            other hand, h_addr is a char*, so we can't just assign.
596
597            Since there's meant to be only one field inside the in_addr
598            structure we will try just copying over the top and see how
599            that goes. */
600         memcpy (&ret, hp->h_addr, hp->h_length);
601
602         return &ret;
603 }
604
605
606
607 /*******************************************************************
608 this is like socketpair but uses tcp. It is used by the Samba
609 regression test code
610 The function guarantees that nobody else can attach to the socket,
611 or if they do that this function fails and the socket gets closed
612 returns 0 on success, -1 on failure
613 the resulting file descriptors are symmetrical
614  ******************************************************************/
615 static int socketpair_tcp(int fd[2])
616 {
617         int listener;
618         struct sockaddr_in sock;
619         struct sockaddr_in sock2;
620         socklen_t socklen = sizeof(sock);
621         int connect_done = 0;
622         
623         fd[0] = fd[1] = listener = -1;
624
625         memset(&sock, 0, sizeof(sock));
626         
627         if ((listener = socket(PF_INET, SOCK_STREAM, 0)) == -1) goto failed;
628
629         memset(&sock2, 0, sizeof(sock2));
630 #ifdef HAVE_SOCK_SIN_LEN
631         sock2.sin_len = sizeof(sock2);
632 #endif
633         sock2.sin_family = PF_INET;
634
635         bind(listener, (struct sockaddr *)&sock2, sizeof(sock2));
636
637         if (listen(listener, 1) != 0) goto failed;
638
639         if (getsockname(listener, (struct sockaddr *)&sock, &socklen) != 0) goto failed;
640
641         if ((fd[1] = socket(PF_INET, SOCK_STREAM, 0)) == -1) goto failed;
642
643         set_nonblocking(fd[1]);
644
645         sock.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
646
647         if (connect(fd[1],(struct sockaddr *)&sock,sizeof(sock)) == -1) {
648                 if (errno != EINPROGRESS) goto failed;
649         } else {
650                 connect_done = 1;
651         }
652
653         if ((fd[0] = accept(listener, (struct sockaddr *)&sock, &socklen)) == -1) goto failed;
654
655         close(listener);
656         if (connect_done == 0) {
657                 if (connect(fd[1],(struct sockaddr *)&sock,sizeof(sock)) != 0
658                     && errno != EISCONN) goto failed;
659         }
660
661         set_blocking (fd[1]);
662
663         /* all OK! */
664         return 0;
665
666  failed:
667         if (fd[0] != -1) close(fd[0]);
668         if (fd[1] != -1) close(fd[1]);
669         if (listener != -1) close(listener);
670         return -1;
671 }
672
673
674 /*******************************************************************
675 run a program on a local tcp socket, this is used to launch smbd
676 when regression testing
677 the return value is a socket which is attached to a subprocess
678 running "prog". stdin and stdout are attached. stderr is left
679 attached to the original stderr
680  ******************************************************************/
681 int sock_exec(const char *prog)
682 {
683         int fd[2];
684         if (socketpair_tcp(fd) != 0) {
685                 rprintf (FERROR, RSYNC_NAME
686                          ": socketpair_tcp failed (%s)\n",
687                          strerror(errno));
688                 return -1;
689         }
690         if (fork() == 0) {
691                 close(fd[0]);
692                 close(0);
693                 close(1);
694                 dup(fd[1]);
695                 dup(fd[1]);
696                 if (verbose > 3)
697                         fprintf (stderr,
698                                  RSYNC_NAME ": execute socket program \"%s\"\n",
699                                  prog);
700                 exit (system (prog));
701         }
702         close (fd[1]);
703         return fd[0];
704 }
705
706
707