00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034 #include "rsync.h"
00035 #include <netinet/in_systm.h>
00036 #include <netinet/ip.h>
00037
00038 extern char *bind_address;
00039 extern int default_af_hint;
00040
00041 #ifdef HAVE_SIGACTION
00042 static struct sigaction sigact;
00043 #endif
00044
00045
00046
00047
00048
00049
00050
00051 static int establish_proxy_connection(int fd, char *host, int port,
00052 char *proxy_user, char *proxy_pass)
00053 {
00054 char *cp, buffer[1024];
00055 char *authhdr, authbuf[1024];
00056 int len;
00057
00058 if (proxy_user && proxy_pass) {
00059 stringjoin(buffer, sizeof buffer,
00060 proxy_user, ":", proxy_pass, NULL);
00061 len = strlen(buffer);
00062
00063 if ((len*8 + 5) / 6 >= (int)sizeof authbuf - 3) {
00064 rprintf(FERROR,
00065 "authentication information is too long\n");
00066 return -1;
00067 }
00068
00069 base64_encode(buffer, len, authbuf, 1);
00070 authhdr = "\r\nProxy-Authorization: Basic ";
00071 } else {
00072 *authbuf = '\0';
00073 authhdr = "";
00074 }
00075
00076 snprintf(buffer, sizeof buffer, "CONNECT %s:%d HTTP/1.0%s%s\r\n\r\n",
00077 host, port, authhdr, authbuf);
00078 len = strlen(buffer);
00079 if (write(fd, buffer, len) != len) {
00080 rsyserr(FERROR, errno, "failed to write to proxy");
00081 return -1;
00082 }
00083
00084 for (cp = buffer; cp < &buffer[sizeof buffer - 1]; cp++) {
00085 if (read(fd, cp, 1) != 1) {
00086 rsyserr(FERROR, errno, "failed to read from proxy");
00087 return -1;
00088 }
00089 if (*cp == '\n')
00090 break;
00091 }
00092
00093 if (*cp != '\n')
00094 cp++;
00095 *cp-- = '\0';
00096 if (*cp == '\r')
00097 *cp = '\0';
00098 if (strncmp(buffer, "HTTP/", 5) != 0) {
00099 rprintf(FERROR, "bad response from proxy -- %s\n",
00100 buffer);
00101 return -1;
00102 }
00103 for (cp = &buffer[5]; isdigit(*(uchar*)cp) || *cp == '.'; cp++) {}
00104 while (*cp == ' ')
00105 cp++;
00106 if (*cp != '2') {
00107 rprintf(FERROR, "bad response from proxy -- %s\n",
00108 buffer);
00109 return -1;
00110 }
00111
00112 while (1) {
00113 for (cp = buffer; cp < &buffer[sizeof buffer - 1]; cp++) {
00114 if (read(fd, cp, 1) != 1) {
00115 rsyserr(FERROR, errno,
00116 "failed to read from proxy");
00117 return -1;
00118 }
00119 if (*cp == '\n')
00120 break;
00121 }
00122 if (cp > buffer && *cp == '\n')
00123 cp--;
00124 if (cp == buffer && (*cp == '\n' || *cp == '\r'))
00125 break;
00126 }
00127 return 0;
00128 }
00129
00130
00131
00132
00133
00134
00135 int try_bind_local(int s, int ai_family, int ai_socktype,
00136 const char *bind_addr)
00137 {
00138 int error;
00139 struct addrinfo bhints, *bres_all, *r;
00140
00141 memset(&bhints, 0, sizeof bhints);
00142 bhints.ai_family = ai_family;
00143 bhints.ai_socktype = ai_socktype;
00144 bhints.ai_flags = AI_PASSIVE;
00145 if ((error = getaddrinfo(bind_addr, NULL, &bhints, &bres_all))) {
00146 rprintf(FERROR, RSYNC_NAME ": getaddrinfo %s: %s\n",
00147 bind_addr, gai_strerror(error));
00148 return -1;
00149 }
00150
00151 for (r = bres_all; r; r = r->ai_next) {
00152 if (bind(s, r->ai_addr, r->ai_addrlen) == -1)
00153 continue;
00154 freeaddrinfo(bres_all);
00155 return s;
00156 }
00157
00158
00159
00160
00161 freeaddrinfo(bres_all);
00162 return -1;
00163 }
00164
00165
00166
00167
00168
00169
00170
00171
00172
00173
00174
00175
00176
00177
00178
00179
00180
00181
00182
00183
00184
00185
00186 int open_socket_out(char *host, int port, const char *bind_addr,
00187 int af_hint)
00188 {
00189 int type = SOCK_STREAM;
00190 int error, s;
00191 struct addrinfo hints, *res0, *res;
00192 char portbuf[10];
00193 char *h, *cp;
00194 int proxied = 0;
00195 char buffer[1024];
00196 char *proxy_user = NULL, *proxy_pass = NULL;
00197
00198
00199
00200 h = getenv("RSYNC_PROXY");
00201 proxied = h != NULL && *h != '\0';
00202
00203 if (proxied) {
00204 strlcpy(buffer, h, sizeof buffer);
00205
00206
00207 if ((cp = strrchr(buffer, '@')) != NULL) {
00208 *cp++ = '\0';
00209
00210 h = cp;
00211
00212 if ((cp = strchr(buffer, ':')) == NULL) {
00213 rprintf(FERROR,
00214 "invalid proxy specification: should be USER:PASS@HOST:PORT\n");
00215 return -1;
00216 }
00217 *cp++ = '\0';
00218
00219 proxy_user = buffer;
00220 proxy_pass = cp;
00221 } else {
00222
00223 h = buffer;
00224 }
00225
00226 if ((cp = strchr(h, ':')) == NULL) {
00227 rprintf(FERROR,
00228 "invalid proxy specification: should be HOST:PORT\n");
00229 return -1;
00230 }
00231 *cp++ = '\0';
00232 strlcpy(portbuf, cp, sizeof portbuf);
00233 if (verbose >= 2) {
00234 rprintf(FINFO, "connection via http proxy %s port %s\n",
00235 h, portbuf);
00236 }
00237 } else {
00238 snprintf(portbuf, sizeof portbuf, "%d", port);
00239 h = host;
00240 }
00241
00242 memset(&hints, 0, sizeof hints);
00243 hints.ai_family = af_hint;
00244 hints.ai_socktype = type;
00245 error = getaddrinfo(h, portbuf, &hints, &res0);
00246 if (error) {
00247 rprintf(FERROR, RSYNC_NAME ": getaddrinfo: %s %s: %s\n",
00248 h, portbuf, gai_strerror(error));
00249 return -1;
00250 }
00251
00252 s = -1;
00253
00254
00255
00256
00257 for (res = res0; res; res = res->ai_next) {
00258 s = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
00259 if (s < 0)
00260 continue;
00261
00262 if (bind_addr
00263 && try_bind_local(s, res->ai_family, type,
00264 bind_addr) == -1) {
00265 close(s);
00266 s = -1;
00267 continue;
00268 }
00269 if (connect(s, res->ai_addr, res->ai_addrlen) < 0) {
00270 close(s);
00271 s = -1;
00272 continue;
00273 }
00274 if (proxied
00275 && establish_proxy_connection(s, host, port,
00276 proxy_user, proxy_pass) != 0) {
00277 close(s);
00278 s = -1;
00279 continue;
00280 }
00281 break;
00282 }
00283 freeaddrinfo(res0);
00284 if (s < 0) {
00285 rsyserr(FERROR, errno, "failed to connect to %s", h);
00286 return -1;
00287 }
00288 return s;
00289 }
00290
00291
00292
00293
00294
00295
00296
00297
00298
00299
00300
00301
00302
00303
00304 int open_socket_out_wrapped(char *host, int port, const char *bind_addr,
00305 int af_hint)
00306 {
00307 char *prog = getenv("RSYNC_CONNECT_PROG");
00308
00309 if (verbose >= 2) {
00310 rprintf(FINFO, "%sopening tcp connection to %s port %d\n",
00311 prog ? "Using RSYNC_CONNECT_PROG instead of " : "",
00312 host, port);
00313 }
00314 if (prog)
00315 return sock_exec(prog);
00316 return open_socket_out(host, port, bind_addr, af_hint);
00317 }
00318
00319
00320
00321
00322
00323
00324
00325
00326
00327
00328
00329
00330
00331
00332
00333
00334 static int *open_socket_in(int type, int port, const char *bind_addr,
00335 int af_hint)
00336 {
00337 int one = 1;
00338 int s, *socks, maxs, i, ecnt;
00339 struct addrinfo hints, *all_ai, *resp;
00340 char portbuf[10], **errmsgs;
00341 int error;
00342
00343 memset(&hints, 0, sizeof hints);
00344 hints.ai_family = af_hint;
00345 hints.ai_socktype = type;
00346 hints.ai_flags = AI_PASSIVE;
00347 snprintf(portbuf, sizeof portbuf, "%d", port);
00348 error = getaddrinfo(bind_addr, portbuf, &hints, &all_ai);
00349 if (error) {
00350 rprintf(FERROR, RSYNC_NAME ": getaddrinfo: bind address %s: %s\n",
00351 bind_addr, gai_strerror(error));
00352 return NULL;
00353 }
00354
00355
00356 for (maxs = 0, resp = all_ai; resp; resp = resp->ai_next, maxs++) {}
00357
00358 socks = new_array(int, maxs + 1);
00359 errmsgs = new_array(char *, maxs);
00360 if (!socks || !errmsgs)
00361 out_of_memory("open_socket_in");
00362
00363
00364
00365
00366 for (resp = all_ai, i = ecnt = 0; resp; resp = resp->ai_next) {
00367 s = socket(resp->ai_family, resp->ai_socktype,
00368 resp->ai_protocol);
00369
00370 if (s == -1) {
00371 int r = asprintf(&errmsgs[ecnt++],
00372 "socket(%d,%d,%d) failed: %s\n",
00373 (int)resp->ai_family, (int)resp->ai_socktype,
00374 (int)resp->ai_protocol, strerror(errno));
00375 if (r < 0)
00376 out_of_memory("open_socket_in");
00377
00378 continue;
00379 }
00380
00381 setsockopt(s, SOL_SOCKET, SO_REUSEADDR,
00382 (char *)&one, sizeof one);
00383
00384 #ifdef IPV6_V6ONLY
00385 if (resp->ai_family == AF_INET6) {
00386 if (setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY,
00387 (char *)&one, sizeof one) < 0
00388 && default_af_hint != AF_INET6) {
00389 close(s);
00390 continue;
00391 }
00392 }
00393 #endif
00394
00395
00396 if (bind(s, resp->ai_addr, resp->ai_addrlen) < 0) {
00397
00398 int r = asprintf(&errmsgs[ecnt++],
00399 "bind() failed: %s (address-family %d)\n",
00400 strerror(errno), (int)resp->ai_family);
00401 if (r < 0)
00402 out_of_memory("open_socket_in");
00403 close(s);
00404 continue;
00405 }
00406
00407 socks[i++] = s;
00408 }
00409 socks[i] = -1;
00410
00411 if (all_ai)
00412 freeaddrinfo(all_ai);
00413
00414
00415
00416 for (s = 0; s < ecnt; s++) {
00417 if (!i || verbose > 1)
00418 rwrite(FLOG, errmsgs[s], strlen(errmsgs[s]));
00419 free(errmsgs[s]);
00420 }
00421 free(errmsgs);
00422
00423 if (!i) {
00424 rprintf(FERROR,
00425 "unable to bind any inbound sockets on port %d\n",
00426 port);
00427 free(socks);
00428 return NULL;
00429 }
00430 return socks;
00431 }
00432
00433
00434
00435
00436
00437 int is_a_socket(int fd)
00438 {
00439 int v;
00440 socklen_t l = sizeof (int);
00441
00442
00443
00444
00445
00446
00447
00448
00449
00450
00451
00452
00453
00454
00455 return getsockopt(fd, SOL_SOCKET, SO_TYPE, (char *)&v, &l) == 0;
00456 }
00457
00458
00459 static RETSIGTYPE sigchld_handler(UNUSED(int val))
00460 {
00461 #ifdef WNOHANG
00462 while (waitpid(-1, NULL, WNOHANG) > 0) {}
00463 #endif
00464 #ifndef HAVE_SIGACTION
00465 signal(SIGCHLD, sigchld_handler);
00466 #endif
00467 }
00468
00469
00470 void start_accept_loop(int port, int (*fn)(int, int))
00471 {
00472 fd_set deffds;
00473 int *sp, maxfd, i;
00474
00475 #ifdef HAVE_SIGACTION
00476 sigact.sa_flags = SA_NOCLDSTOP;
00477 #endif
00478
00479
00480 sp = open_socket_in(SOCK_STREAM, port, bind_address, default_af_hint);
00481 if (sp == NULL)
00482 exit_cleanup(RERR_SOCKETIO);
00483
00484
00485 FD_ZERO(&deffds);
00486 for (i = 0, maxfd = -1; sp[i] >= 0; i++) {
00487 if (listen(sp[i], 5) < 0) {
00488 rsyserr(FERROR, errno, "listen() on socket failed");
00489 #ifdef INET6
00490 if (errno == EADDRINUSE && i > 0) {
00491 rprintf(FINFO,
00492 "Try using --ipv4 or --ipv6 to avoid this listen() error.\n");
00493 }
00494 #endif
00495 exit_cleanup(RERR_SOCKETIO);
00496 }
00497 FD_SET(sp[i], &deffds);
00498 if (maxfd < sp[i])
00499 maxfd = sp[i];
00500 }
00501
00502
00503
00504 while (1) {
00505 fd_set fds;
00506 pid_t pid;
00507 int fd;
00508 struct sockaddr_storage addr;
00509 socklen_t addrlen = sizeof addr;
00510
00511
00512
00513
00514 logfile_close();
00515
00516 #ifdef FD_COPY
00517 FD_COPY(&deffds, &fds);
00518 #else
00519 fds = deffds;
00520 #endif
00521
00522 if (select(maxfd + 1, &fds, NULL, NULL, NULL) != 1)
00523 continue;
00524
00525 for (i = 0, fd = -1; sp[i] >= 0; i++) {
00526 if (FD_ISSET(sp[i], &fds)) {
00527 fd = accept(sp[i], (struct sockaddr *)&addr,
00528 &addrlen);
00529 break;
00530 }
00531 }
00532
00533 if (fd < 0)
00534 continue;
00535
00536 SIGACTION(SIGCHLD, sigchld_handler);
00537
00538 if ((pid = fork()) == 0) {
00539 int ret;
00540 for (i = 0; sp[i] >= 0; i++)
00541 close(sp[i]);
00542
00543
00544 logfile_reopen();
00545 ret = fn(fd, fd);
00546 close_all();
00547 _exit(ret);
00548 } else if (pid < 0) {
00549 rsyserr(FERROR, errno,
00550 "could not create child server process");
00551 close(fd);
00552
00553
00554
00555 sleep(2);
00556 } else {
00557
00558 close(fd);
00559 }
00560 }
00561 }
00562
00563
00564 enum SOCK_OPT_TYPES {OPT_BOOL,OPT_INT,OPT_ON};
00565
00566 struct
00567 {
00568 char *name;
00569 int level;
00570 int option;
00571 int value;
00572 int opttype;
00573 } socket_options[] = {
00574 {"SO_KEEPALIVE", SOL_SOCKET, SO_KEEPALIVE, 0, OPT_BOOL},
00575 {"SO_REUSEADDR", SOL_SOCKET, SO_REUSEADDR, 0, OPT_BOOL},
00576 {"SO_BROADCAST", SOL_SOCKET, SO_BROADCAST, 0, OPT_BOOL},
00577 #ifdef TCP_NODELAY
00578 {"TCP_NODELAY", IPPROTO_TCP, TCP_NODELAY, 0, OPT_BOOL},
00579 #endif
00580 #ifdef IPTOS_LOWDELAY
00581 {"IPTOS_LOWDELAY", IPPROTO_IP, IP_TOS, IPTOS_LOWDELAY, OPT_ON},
00582 #endif
00583 #ifdef IPTOS_THROUGHPUT
00584 {"IPTOS_THROUGHPUT", IPPROTO_IP, IP_TOS, IPTOS_THROUGHPUT, OPT_ON},
00585 #endif
00586 #ifdef SO_SNDBUF
00587 {"SO_SNDBUF", SOL_SOCKET, SO_SNDBUF, 0, OPT_INT},
00588 #endif
00589 #ifdef SO_RCVBUF
00590 {"SO_RCVBUF", SOL_SOCKET, SO_RCVBUF, 0, OPT_INT},
00591 #endif
00592 #ifdef SO_SNDLOWAT
00593 {"SO_SNDLOWAT", SOL_SOCKET, SO_SNDLOWAT, 0, OPT_INT},
00594 #endif
00595 #ifdef SO_RCVLOWAT
00596 {"SO_RCVLOWAT", SOL_SOCKET, SO_RCVLOWAT, 0, OPT_INT},
00597 #endif
00598 #ifdef SO_SNDTIMEO
00599 {"SO_SNDTIMEO", SOL_SOCKET, SO_SNDTIMEO, 0, OPT_INT},
00600 #endif
00601 #ifdef SO_RCVTIMEO
00602 {"SO_RCVTIMEO", SOL_SOCKET, SO_RCVTIMEO, 0, OPT_INT},
00603 #endif
00604 {NULL,0,0,0,0}};
00605
00606
00607
00608
00609
00610
00611 void set_socket_options(int fd, char *options)
00612 {
00613 char *tok;
00614
00615 if (!options || !*options)
00616 return;
00617
00618 options = strdup(options);
00619
00620 if (!options)
00621 out_of_memory("set_socket_options");
00622
00623 for (tok = strtok(options, " \t,"); tok; tok = strtok(NULL," \t,")) {
00624 int ret=0,i;
00625 int value = 1;
00626 char *p;
00627 int got_value = 0;
00628
00629 if ((p = strchr(tok,'='))) {
00630 *p = 0;
00631 value = atoi(p+1);
00632 got_value = 1;
00633 }
00634
00635 for (i = 0; socket_options[i].name; i++) {
00636 if (strcmp(socket_options[i].name,tok)==0)
00637 break;
00638 }
00639
00640 if (!socket_options[i].name) {
00641 rprintf(FERROR,"Unknown socket option %s\n",tok);
00642 continue;
00643 }
00644
00645 switch (socket_options[i].opttype) {
00646 case OPT_BOOL:
00647 case OPT_INT:
00648 ret = setsockopt(fd,socket_options[i].level,
00649 socket_options[i].option,
00650 (char *)&value, sizeof (int));
00651 break;
00652
00653 case OPT_ON:
00654 if (got_value)
00655 rprintf(FERROR,"syntax error -- %s does not take a value\n",tok);
00656
00657 {
00658 int on = socket_options[i].value;
00659 ret = setsockopt(fd,socket_options[i].level,
00660 socket_options[i].option,
00661 (char *)&on, sizeof (int));
00662 }
00663 break;
00664 }
00665
00666 if (ret != 0) {
00667 rsyserr(FERROR, errno,
00668 "failed to set socket option %s", tok);
00669 }
00670 }
00671
00672 free(options);
00673 }
00674
00675
00676
00677
00678 void become_daemon(void)
00679 {
00680 int i;
00681
00682 if (fork()) {
00683 _exit(0);
00684 }
00685
00686
00687 #ifdef HAVE_SETSID
00688 setsid();
00689 #elif defined TIOCNOTTY
00690 i = open("/dev/tty", O_RDWR);
00691 if (i >= 0) {
00692 ioctl(i, (int)TIOCNOTTY, (char *)0);
00693 close(i);
00694 }
00695 #endif
00696
00697
00698 for (i = 0; i < 3; i++) {
00699 close(i);
00700 open("/dev/null", O_RDWR);
00701 }
00702 }
00703
00704
00705
00706
00707
00708
00709
00710
00711
00712
00713
00714 static int socketpair_tcp(int fd[2])
00715 {
00716 int listener;
00717 struct sockaddr_in sock;
00718 struct sockaddr_in sock2;
00719 socklen_t socklen = sizeof sock;
00720 int connect_done = 0;
00721
00722 fd[0] = fd[1] = listener = -1;
00723
00724 memset(&sock, 0, sizeof sock);
00725
00726 if ((listener = socket(PF_INET, SOCK_STREAM, 0)) == -1)
00727 goto failed;
00728
00729 memset(&sock2, 0, sizeof sock2);
00730 #ifdef HAVE_SOCKADDR_IN_LEN
00731 sock2.sin_len = sizeof sock2;
00732 #endif
00733 sock2.sin_family = PF_INET;
00734
00735 bind(listener, (struct sockaddr *)&sock2, sizeof sock2);
00736
00737 if (listen(listener, 1) != 0)
00738 goto failed;
00739
00740 if (getsockname(listener, (struct sockaddr *)&sock, &socklen) != 0)
00741 goto failed;
00742
00743 if ((fd[1] = socket(PF_INET, SOCK_STREAM, 0)) == -1)
00744 goto failed;
00745
00746 set_nonblocking(fd[1]);
00747
00748 sock.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
00749
00750 if (connect(fd[1], (struct sockaddr *)&sock, sizeof sock) == -1) {
00751 if (errno != EINPROGRESS)
00752 goto failed;
00753 } else
00754 connect_done = 1;
00755
00756 if ((fd[0] = accept(listener, (struct sockaddr *)&sock, &socklen)) == -1)
00757 goto failed;
00758
00759 close(listener);
00760 listener = -1;
00761
00762 set_blocking(fd[1]);
00763
00764 if (connect_done == 0) {
00765 if (connect(fd[1], (struct sockaddr *)&sock, sizeof sock) != 0
00766 && errno != EISCONN)
00767 goto failed;
00768 }
00769
00770
00771 return 0;
00772
00773 failed:
00774 if (fd[0] != -1)
00775 close(fd[0]);
00776 if (fd[1] != -1)
00777 close(fd[1]);
00778 if (listener != -1)
00779 close(listener);
00780 return -1;
00781 }
00782
00783
00784
00785
00786
00787
00788
00789
00790
00791
00792
00793
00794 int sock_exec(const char *prog)
00795 {
00796 int fd[2];
00797
00798 if (socketpair_tcp(fd) != 0) {
00799 rsyserr(FERROR, errno, "socketpair_tcp failed");
00800 return -1;
00801 }
00802 if (verbose >= 2)
00803 rprintf(FINFO, "Running socket program: \"%s\"\n", prog);
00804 if (fork() == 0) {
00805 close(fd[0]);
00806 close(0);
00807 close(1);
00808 dup(fd[1]);
00809 dup(fd[1]);
00810 exit(system(prog));
00811 }
00812 close(fd[1]);
00813 return fd[0];
00814 }