socket.c

Socket functions used in rsync. [詳細]

ソースコードを見る。


列挙型

enum  SOCK_OPT_TYPES { OPT_BOOL, OPT_INT, OPT_ON }

関数

static int establish_proxy_connection (int fd, char *host, int port, char *proxy_user, char *proxy_pass)
 Establish a proxy connection on an open socket to a web proxy by using the CONNECT method.
int try_bind_local (int s, int ai_family, int ai_socktype, const char *bind_addr)
 Try to set the local address for a newly-created socket.
int open_socket_out (char *host, int port, const char *bind_addr, int af_hint)
 Open a socket to a tcp remote host with the specified port .
int open_socket_out_wrapped (char *host, int port, const char *bind_addr, int af_hint)
 Open an outgoing socket, but allow for it to be intercepted by $RSYNC_CONNECT_PROG, which will execute a program across a TCP socketpair rather than really opening a socket.
static int * open_socket_in (int type, int port, const char *bind_addr, int af_hint)
 Open one or more sockets for incoming data using the specified type, port, and address.
int is_a_socket (int fd)
static RETSIGTYPE sigchld_handler (UNUSED(int val))
void start_accept_loop (int port, int(*fn)(int, int))
void set_socket_options (int fd, char *options)
 Set user socket options
void become_daemon (void)
 Become a daemon, discarding the controlling terminal
static int socketpair_tcp (int fd[2])
 This is like socketpair but uses tcp.
int sock_exec (const char *prog)
 Run a program on a local tcp socket, so that we can talk to it's stdin and stdout.

変数

char * bind_address
 Local address to bind.
int default_af_hint
 Network address family.
static struct sigaction sigact
struct {
   char *   name
   int   level
   int   option
   int   value
   int   opttype
socket_options []

説明

Socket functions used in rsync.

This file is now converted to use the new-style getaddrinfo() interface, which supports IPv6 but is also supported on recent IPv4-only machines. On systems that don't have that interface, we emulate it using the KAME implementation.

socket.c で定義されています。


列挙型

enum SOCK_OPT_TYPES

列挙型の値:
OPT_BOOL 
OPT_INT 
OPT_ON 

socket.c564 行で定義されています。


関数

static int establish_proxy_connection ( int  fd,
char *  host,
int  port,
char *  proxy_user,
char *  proxy_pass 
) [static]

Establish a proxy connection on an open socket to a web proxy by using the CONNECT method.

If proxy_user and proxy_pass are not NULL, they are used to authenticate to the proxy using the "Basic" proxy-authorization protocol

socket.c51 行で定義されています。

参照先 base64_encode()errnoFERRORrprintf()rsyserr()snprintf()stringjoin().

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         /* throw away the rest of the HTTP header */
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 }

int try_bind_local ( int  s,
int  ai_family,
int  ai_socktype,
const char *  bind_addr 
)

Try to set the local address for a newly-created socket.

Return -1 if this fails.

socket.c135 行で定義されています。

参照先 addrinfo::ai_addraddrinfo::ai_addrlenaddrinfo::ai_nextFERRORfreeaddrinfo()gai_strerror()getaddrinfo()rprintf().

参照元 open_socket_out().

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         /* no error message; there might be some problem that allows
00159          * creation of the socket but not binding, perhaps if the
00160          * machine has no ipv6 address of this name. */
00161         freeaddrinfo(bres_all);
00162         return -1;
00163 }

int open_socket_out ( char *  host,
int  port,
const char *  bind_addr,
int  af_hint 
)

Open a socket to a tcp remote host with the specified port .

Based on code from Warren. Proxy support by Stephen Rothwell. getaddrinfo() rewrite contributed by KAME.net.

Now that we support IPv6 we need to look up the remote machine's address first, using af_hint to set a preference for the type of address. Then depending on whether it has v4 or v6 addresses we try to open a connection.

The loop allows for machines with some addresses which may not be reachable, perhaps because we can't e.g. route ipv6 to that network but we can get ip4 packets through.

引数:
bind_addr Local address to use. Normally NULL to bind the wildcard address.
af_hint Address family, e.g. AF_INET or AF_INET6.

socket.c186 行で定義されています。

参照先 addrinfo::ai_addraddrinfo::ai_addrlenaddrinfo::ai_familyaddrinfo::ai_nextaddrinfo::ai_protocoladdrinfo::ai_socktypeFERRORFINFOgai_strerror()getaddrinfo()rprintf()snprintf()strlcpy()try_bind_local()verbose.

参照元 open_socket_out_wrapped().

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         /* if we have a RSYNC_PROXY env variable then redirect our
00199          * connetcion via a web proxy at the given address. */
00200         h = getenv("RSYNC_PROXY");
00201         proxied = h != NULL && *h != '\0';
00202 
00203         if (proxied) {
00204                 strlcpy(buffer, h, sizeof buffer);
00205 
00206                 /* Is the USER:PASS@ prefix present? */
00207                 if ((cp = strrchr(buffer, '@')) != NULL) {
00208                         *cp++ = '\0';
00209                         /* The remainder is the HOST:PORT part. */
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                         /* The whole buffer is the HOST:PORT part. */
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         /* Try to connect to all addresses for this machine until we get
00254          * through.  It might e.g. be multi-homed, or have both IPv4 and IPv6
00255          * addresses.  We need to create a socket for each record, since the
00256          * address record tells us what protocol to use to try to connect. */
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 }

int open_socket_out_wrapped ( char *  host,
int  port,
const char *  bind_addr,
int  af_hint 
)

Open an outgoing socket, but allow for it to be intercepted by $RSYNC_CONNECT_PROG, which will execute a program across a TCP socketpair rather than really opening a socket.

We use this primarily in testing to detect TCP flow bugs, but not cause security problems by really opening remote connections.

This is based on the Samba LIBSMB_PROG feature.

引数:
bind_addr Local address to use. Normally NULL to get the stack default.

socket.c304 行で定義されています。

参照先 FINFOopen_socket_out()rprintf()sock_exec()verbose.

参照元 start_socket_client().

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 }

static int* open_socket_in ( int  type,
int  port,
const char *  bind_addr,
int  af_hint 
) [static]

Open one or more sockets for incoming data using the specified type, port, and address.

The getaddrinfo() call may return several address results, e.g. for the machine's IPv4 and IPv6 name.

We return an array of file-descriptors to the sockets, with a trailing -1 value to indicate the end of the list.

引数:
bind_addr Local address to bind, or NULL to allow it to default.

socket.c334 行で定義されています。

参照先 addrinfo::ai_addraddrinfo::ai_addrlenaddrinfo::ai_familyaddrinfo::ai_nextaddrinfo::ai_protocoladdrinfo::ai_socktypeasprintf()default_af_hinterrnoFERRORFLOGfreeaddrinfo()gai_strerror()getaddrinfo()out_of_memory()rprintf()rwrite()snprintf()verbose.

参照元 start_accept_loop().

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         /* Count max number of sockets we might open. */
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         /* We may not be able to create the socket, if for example the
00364          * machine knows about IPv6 in the C library, but not in the
00365          * kernel. */
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                         /* See if there's another address that will work... */
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                 /* Now we've got a socket - we need to bind it. */
00396                 if (bind(s, resp->ai_addr, resp->ai_addrlen) < 0) {
00397                         /* Nope, try another */
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         /* Only output the socket()/bind() messages if we were totally
00415          * unsuccessful, or if the daemon is being run with -vv. */
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 }

int is_a_socket ( int  fd  ) 

socket.c437 行で定義されています。

参照元 close_all()daemon_main().

00438 {
00439         int v;
00440         socklen_t l = sizeof (int);
00441 
00442         /* Parameters to getsockopt, setsockopt etc are very
00443          * unstandardized across platforms, so don't be surprised if
00444          * there are compiler warnings on e.g. SCO OpenSwerver or AIX.
00445          * It seems they all eventually get the right idea.
00446          *
00447          * Debian says: ``The fifth argument of getsockopt and
00448          * setsockopt is in reality an int [*] (and this is what BSD
00449          * 4.* and libc4 and libc5 have).  Some POSIX confusion
00450          * resulted in the present socklen_t.  The draft standard has
00451          * not been adopted yet, but glibc2 already follows it and
00452          * also has socklen_t [*]. See also accept(2).''
00453          *
00454          * We now return to your regularly scheduled programming.  */
00455         return getsockopt(fd, SOL_SOCKET, SO_TYPE, (char *)&v, &l) == 0;
00456 }

static RETSIGTYPE sigchld_handler ( UNUSED(int val)   )  [static]

socket.c459 行で定義されています。

参照先 waitpid().

参照元 start_accept_loop().

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 }

void start_accept_loop ( int  port,
int(*)(int, int)  fn 
)

socket.c470 行で定義されています。

参照先 bind_addressclose_all()default_af_hinterrnoFERRORFINFOlogfile_close()logfile_reopen()open_socket_in()rprintf()rsyserr()sigactsigchld_handler().

参照元 daemon_main().

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         /* open an incoming socket */
00480         sp = open_socket_in(SOCK_STREAM, port, bind_address, default_af_hint);
00481         if (sp == NULL)
00482                 exit_cleanup(RERR_SOCKETIO);
00483 
00484         /* ready to listen */
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         /* now accept incoming connections - forking a new process
00503          * for each incoming connection */
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                 /* close log file before the potentially very long select so
00512                  * file can be trimmed by another process instead of growing
00513                  * forever */
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                         /* Re-open log file in child before possibly giving
00543                          * up privileges (see logfile_close() above). */
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                         /* This might have happened because we're
00553                          * overloaded.  Sleep briefly before trying to
00554                          * accept again. */
00555                         sleep(2);
00556                 } else {
00557                         /* Parent doesn't need this fd anymore. */
00558                         close(fd);
00559                 }
00560         }
00561 }

void set_socket_options ( int  fd,
char *  options 
)

Set user socket options

socket.c611 行で定義されています。

参照先 errnoFERRORlevelnameOPT_BOOLOPT_INToptionopttypeout_of_memory()rprintf()rsyserr()socket_optionsstrdup()value.

参照元 start_daemon()start_socket_client().

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 }

void become_daemon ( void   ) 

Become a daemon, discarding the controlling terminal

socket.c678 行で定義されています。

参照元 daemon_main().

00679 {
00680         int i;
00681 
00682         if (fork()) {
00683                 _exit(0);
00684         }
00685 
00686         /* detach from the terminal */
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         /* make sure that stdin, stdout an stderr don't stuff things
00697          * up (library functions, for example) */
00698         for (i = 0; i < 3; i++) {
00699                 close(i);
00700                 open("/dev/null", O_RDWR);
00701         }
00702 }

static int socketpair_tcp ( int  fd[2]  )  [static]

This is like socketpair but uses tcp.

It is used by the Samba regression test code.

The function guarantees that nobody else can attach to the socket, or if they do that this function fails and the socket gets closed returns 0 on success, -1 on failure the resulting file descriptors are symmetrical.

socket.c714 行で定義されています。

参照先 errnofailed()set_blocking()set_nonblocking().

参照元 sock_exec().

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         /* all OK! */
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 }

int sock_exec ( const char *  prog  ) 

Run a program on a local tcp socket, so that we can talk to it's stdin and stdout.

This is used to fake a connection to a daemon for testing -- not for the normal case of running SSH.

戻り値:
a socket which is attached to a subprocess running "prog". stdin and stdout are attached. stderr is left attached to the original stderr

socket.c794 行で定義されています。

参照先 errnoFERRORFINFOrprintf()rsyserr()socketpair_tcp()verbose.

参照元 open_socket_out_wrapped().

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 }


変数

char* bind_address

Local address to bind.

As a character string because it's interpreted by the IPv6 layer: should be a numeric IP4 or IP6 address, or a hostname.

options.c189 行で定義されています。

int default_af_hint

Network address family.

options.c123 行で定義されています。

struct sigaction sigact [static]

socket.c42 行で定義されています。

char* name

socket.c568 行で定義されています。

int level

socket.c569 行で定義されています。

参照元 set_socket_options().

int option

socket.c570 行で定義されています。

参照元 set_socket_options().

int value

socket.c571 行で定義されています。

参照元 dopr()hpux_acl_call_presence()lp_do_parameter()set_socket_options().

int opttype

socket.c572 行で定義されています。

参照元 set_socket_options().

struct { ... } socket_options[]

参照元 set_socket_options().


rsyncに対してSat Dec 5 19:45:45 2009に生成されました。  doxygen 1.4.7