Main Page   Alphabetical List   Data Structures   File List   Data Fields   Globals   Related Pages  

socket.c File Reference

Socket functions used in rsync. More...

Go to the source code of this file.

Enumerations

enum  SOCK_OPT_TYPES { OPT_BOOL, OPT_INT, OPT_ON }

Functions

int establish_proxy_connection (int fd, char *host, int port)
 Establish a proxy connection on an open socket to a web proxy by using the HTTP CONNECT method. More...

int try_bind_local (int s, int ai_family, int ai_socktype, const char *bind_address)
 Try to set the local address for a newly-created socket. More...

int open_socket_out (char *host, int port, const char *bind_address, int af_hint)
 Open a socket to a tcp remote host with the specified port . More...

int open_socket_out_wrapped (char *host, int port, const char *bind_address, 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. More...

int open_socket_in (int type, int port, const char *bind_address, int af_hint)
 Open a socket of the specified type, port and address for incoming data. More...

int is_a_socket (int fd)
void start_accept_loop (int port, int(*fn)(int))
void set_socket_options (int fd, char *options)
 Set user socket options. More...

void become_daemon (void)
 Become a daemon, discarding the controlling terminal. More...

int socketpair_tcp (int fd[2])
 This is like socketpair but uses tcp. More...

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. More...


Variables

struct {
   char *   name
   int   level
   int   option
   int   value
   int   opttype
socket_options []


Detailed Description

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.

Definition in file socket.c.


Enumeration Type Documentation

enum SOCK_OPT_TYPES
 

Enumeration values:
OPT_BOOL 
OPT_INT 
OPT_ON 

Definition at line 455 of file socket.c.


Function Documentation

int establish_proxy_connection int    fd,
char *    host,
int    port
[static]
 

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

Definition at line 41 of file socket.c.

References FERROR, host, rprintf(), and snprintf().

Referenced by open_socket_out().

00042 {
00043         char buffer[1024];
00044         char *cp;
00045 
00046         snprintf(buffer, sizeof(buffer), "CONNECT %s:%d HTTP/1.0\r\n\r\n", host, port);
00047         if (write(fd, buffer, strlen(buffer)) != (int) strlen(buffer)) {
00048                 rprintf(FERROR, "failed to write to proxy: %s\n",
00049                         strerror(errno));
00050                 return -1;
00051         }
00052 
00053         for (cp = buffer; cp < &buffer[sizeof(buffer) - 1]; cp++) {
00054                 if (read(fd, cp, 1) != 1) {
00055                         rprintf(FERROR, "failed to read from proxy: %s\n",
00056                                 strerror(errno));
00057                         return -1;
00058                 }
00059                 if (*cp == '\n')
00060                         break;
00061         }
00062 
00063         if (*cp != '\n')
00064                 cp++;
00065         *cp-- = '\0';
00066         if (*cp == '\r')
00067                 *cp = '\0';
00068         if (strncmp(buffer, "HTTP/", 5) != 0) {
00069                 rprintf(FERROR, "bad response from proxy - %s\n",
00070                         buffer);
00071                 return -1;
00072         }
00073         for (cp = &buffer[5]; isdigit(* (unsigned char *) cp) || (*cp == '.'); cp++)
00074                 ;
00075         while (*cp == ' ')
00076                 cp++;
00077         if (*cp != '2') {
00078                 rprintf(FERROR, "bad response from proxy - %s\n",
00079                         buffer);
00080                 return -1;
00081         }
00082         /* throw away the rest of the HTTP header */
00083         while (1) {
00084                 for (cp = buffer; cp < &buffer[sizeof(buffer) - 1];
00085                      cp++) {
00086                         if (read(fd, cp, 1) != 1) {
00087                                 rprintf(FERROR, "failed to read from proxy: %s\n",
00088                                         strerror(errno));
00089                                 return -1;
00090                         }
00091                         if (*cp == '\n')
00092                                 break;
00093                 }
00094                 if ((cp > buffer) && (*cp == '\n'))
00095                         cp--;
00096                 if ((cp == buffer) && ((*cp == '\n') || (*cp == '\r')))
00097                         break;
00098         }
00099         return 0;
00100 }

int try_bind_local int    s,
int    ai_family,
int    ai_socktype,
const char *    bind_address
 

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

Return -1 if this fails.

Definition at line 107 of file socket.c.

References addrinfo::ai_addr, addrinfo::ai_addrlen, addrinfo::ai_family, addrinfo::ai_flags, addrinfo::ai_next, addrinfo::ai_socktype, bind_address, FERROR, gai_strerror(), and rprintf().

Referenced by open_socket_out().

00110 {
00111         int error;
00112         struct addrinfo bhints, *bres_all, *r;
00113 
00114         memset(&bhints, 0, sizeof(bhints));
00115         bhints.ai_family = ai_family;
00116         bhints.ai_socktype = ai_socktype;
00117         bhints.ai_flags = AI_PASSIVE;
00118         if ((error = getaddrinfo(bind_address, NULL, &bhints, &bres_all))) {
00119                 rprintf(FERROR, RSYNC_NAME ": getaddrinfo %s: %s\n",
00120                         bind_address, gai_strerror(error));
00121                 return -1;
00122         }
00123 
00124         for (r = bres_all; r; r = r->ai_next) {
00125                 if (bind(s, r->ai_addr, r->ai_addrlen) == -1)
00126                         continue;
00127                 freeaddrinfo(bres_all);
00128                 return s;
00129         }
00130 
00131         /* no error message; there might be some problem that allows
00132          * creation of the socket but not binding, perhaps if the
00133          * machine has no ipv6 address of this name. */
00134         freeaddrinfo(bres_all);
00135         return -1;
00136 }

int open_socket_out char *    host,
int    port,
const char *    bind_address,
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.

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

Definition at line 159 of file socket.c.

References addrinfo::ai_addr, addrinfo::ai_addrlen, addrinfo::ai_family, addrinfo::ai_next, addrinfo::ai_protocol, addrinfo::ai_socktype, bind_address, establish_proxy_connection(), FERROR, FINFO, gai_strerror(), getenv(), host, rprintf(), snprintf(), strlcpy(), and try_bind_local().

Referenced by open_socket_out_wrapped().

00161 {
00162         int type = SOCK_STREAM;
00163         int error;
00164         int s;
00165         struct addrinfo hints, *res0, *res;
00166         char portbuf[10];
00167         char *h;
00168         int proxied = 0;
00169         char buffer[1024];
00170         char *cp;
00171 
00172         /* if we have a RSYNC_PROXY env variable then redirect our
00173          * connetcion via a web proxy at the given address. The format
00174          * is hostname:port */
00175         h = getenv("RSYNC_PROXY");
00176         proxied = (h != NULL) && (*h != '\0');
00177 
00178         if (proxied) {
00179                 strlcpy(buffer, h, sizeof(buffer));
00180                 cp = strchr(buffer, ':');
00181                 if (cp == NULL) {
00182                         rprintf(FERROR,
00183                                 "invalid proxy specification: should be HOST:PORT\n");
00184                         return -1;
00185                 }
00186                 *cp++ = '\0';
00187                 strcpy(portbuf, cp);
00188                 h = buffer;
00189                 if (verbose >= 2) {
00190                         rprintf(FINFO, "connection via http proxy %s port %s\n",
00191                                 h, portbuf);
00192                 }
00193         } else {
00194                 snprintf(portbuf, sizeof(portbuf), "%d", port);
00195                 h = host;
00196         }
00197 
00198         memset(&hints, 0, sizeof(hints));
00199         hints.ai_family = af_hint;
00200         hints.ai_socktype = type;
00201         error = getaddrinfo(h, portbuf, &hints, &res0);
00202         if (error) {
00203                 rprintf(FERROR, RSYNC_NAME ": getaddrinfo: %s %s: %s\n",
00204                         h, portbuf, gai_strerror(error));
00205                 return -1;
00206         }
00207 
00208         s = -1;
00209         /* Try to connect to all addresses for this machine until we get
00210          * through.  It might e.g. be multi-homed, or have both IPv4 and IPv6
00211          * addresses.  We need to create a socket for each record, since the
00212          * address record tells us what protocol to use to try to connect. */
00213         for (res = res0; res; res = res->ai_next) {
00214                 s = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
00215                 if (s < 0)
00216                         continue;
00217 
00218                 if (bind_address)
00219                         if (try_bind_local(s, res->ai_family, type,
00220                                            bind_address) == -1) {
00221                                 close(s);
00222                                 s = -1;
00223                                 continue;
00224                         }
00225 
00226                 if (connect(s, res->ai_addr, res->ai_addrlen) < 0) {
00227                         close(s);
00228                         s = -1;
00229                         continue;
00230                 }
00231                 if (proxied &&
00232                     establish_proxy_connection(s, host, port) != 0) {
00233                         close(s);
00234                         s = -1;
00235                         continue;
00236                 } else
00237                         break;
00238         }
00239         freeaddrinfo(res0);
00240         if (s < 0) {
00241                 rprintf(FERROR, RSYNC_NAME ": failed to connect to %s: %s\n",
00242                         h, strerror(errno));
00243                 return -1;
00244         }
00245         return s;
00246 }

int open_socket_out_wrapped char *    host,
int    port,
const char *    bind_address,
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.

Parameters:
bind_address  Local address to use. Normally NULL to get the stack default.

Definition at line 261 of file socket.c.

References bind_address, getenv(), host, open_socket_out(), and sock_exec().

Referenced by start_socket_client().

00265 {
00266         char *prog;
00267 
00268         if ((prog = getenv ("RSYNC_CONNECT_PROG")) != NULL) 
00269                 return sock_exec (prog);
00270         else 
00271                 return open_socket_out (host, port, bind_address,
00272                                         af_hint);
00273 }

int open_socket_in int    type,
int    port,
const char *    bind_address,
int    af_hint
[static]
 

Open a socket of the specified type, port and address for incoming data.

Try to be better about handling the results of getaddrinfo(): when opening an inbound socket, we might get several address results, e.g. for the machine's ipv4 and ipv6 name.

If binding a wildcard, then any one of them should do. If an address was specified but it's insufficiently specific then that's not our fault.

However, some of the advertized addresses may not work because e.g. we don't have IPv6 support in the kernel. In that case go on and try all addresses until one succeeds.

Parameters:
bind_address  Local address to bind, or NULL to allow it to default.

Definition at line 295 of file socket.c.

References addrinfo::ai_addr, addrinfo::ai_addrlen, addrinfo::ai_family, addrinfo::ai_flags, addrinfo::ai_next, addrinfo::ai_protocol, addrinfo::ai_socktype, bind_address, FERROR, gai_strerror(), rprintf(), and snprintf().

Referenced by start_accept_loop().

00297 {
00298         int one=1;
00299         int s;
00300         struct addrinfo hints, *all_ai, *resp;
00301         char portbuf[10];
00302         int error;
00303 
00304         memset(&hints, 0, sizeof(hints));
00305         hints.ai_family = af_hint;
00306         hints.ai_socktype = type;
00307         hints.ai_flags = AI_PASSIVE;
00308         snprintf(portbuf, sizeof(portbuf), "%d", port);
00309         error = getaddrinfo(bind_address, portbuf, &hints, &all_ai);
00310         if (error) {
00311                 rprintf(FERROR, RSYNC_NAME ": getaddrinfo: bind address %s: %s\n",
00312                         bind_address, gai_strerror(error));
00313                 return -1;
00314         }
00315 
00316         /* We may not be able to create the socket, if for example the
00317          * machine knows about IPv6 in the C library, but not in the
00318          * kernel. */
00319         for (resp = all_ai; resp; resp = resp->ai_next) {
00320                 s = socket(resp->ai_family, resp->ai_socktype,
00321                            resp->ai_protocol);
00322 
00323                 if (s == -1) 
00324                         /* See if there's another address that will work... */
00325                         continue;
00326                 
00327                 setsockopt(s, SOL_SOCKET, SO_REUSEADDR,
00328                            (char *)&one, sizeof one);
00329                 
00330                 /* now we've got a socket - we need to bind it */
00331                 if (bind(s, all_ai->ai_addr, all_ai->ai_addrlen) < 0) {
00332                         /* Nope, try another */
00333                         close(s);
00334                         continue;
00335                 }
00336 
00337                 freeaddrinfo(all_ai);
00338                 return s;
00339         }
00340 
00341         rprintf(FERROR, RSYNC_NAME ": open inbound socket on port %d failed: "
00342                 "%s\n",
00343                 port, 
00344                 strerror(errno));
00345 
00346         freeaddrinfo(all_ai);
00347         return -1; 
00348 }

int is_a_socket int    fd
 

Definition at line 354 of file socket.c.

Referenced by daemon_main().

00355 {
00356         int v;
00357         socklen_t l;
00358         l = sizeof(int);
00359 
00360         /* Parameters to getsockopt, setsockopt etc are very
00361          * unstandardized across platforms, so don't be surprised if
00362          * there are compiler warnings on e.g. SCO OpenSwerver or AIX.
00363          * It seems they all eventually get the right idea.
00364          *
00365          * Debian says: ``The fifth argument of getsockopt and
00366          * setsockopt is in reality an int [*] (and this is what BSD
00367          * 4.* and libc4 and libc5 have).  Some POSIX confusion
00368          * resulted in the present socklen_t.  The draft standard has
00369          * not been adopted yet, but glibc2 already follows it and
00370          * also has socklen_t [*]. See also accept(2).''
00371          *
00372          * We now return to your regularly scheduled programming.  */
00373         return(getsockopt(fd, SOL_SOCKET, SO_TYPE, (char *)&v, &l) == 0);
00374 }

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

Definition at line 377 of file socket.c.

References bind_address, default_af_hint, FERROR, log_close(), log_open(), open_socket_in(), rprintf(), and waitpid().

Referenced by daemon_main().

00378 {
00379         int s;
00380         extern char *bind_address;
00381         extern int default_af_hint;
00382 
00383         /* open an incoming socket */
00384         s = open_socket_in(SOCK_STREAM, port, bind_address, default_af_hint);
00385         if (s == -1)
00386                 exit_cleanup(RERR_SOCKETIO);
00387 
00388         /* ready to listen */
00389         if (listen(s, 5) == -1) {
00390                 close(s);
00391                 exit_cleanup(RERR_SOCKETIO);
00392         }
00393 
00394 
00395         /* now accept incoming connections - forking a new process
00396            for each incoming connection */
00397         while (1) {
00398                 fd_set fds;
00399                 pid_t pid;
00400                 int fd;
00401                 struct sockaddr_storage addr;
00402                 socklen_t addrlen = sizeof addr;
00403 
00404                 /* close log file before the potentially very long select so
00405                    file can be trimmed by another process instead of growing
00406                    forever */
00407                 log_close();
00408 
00409                 FD_ZERO(&fds);
00410                 FD_SET(s, &fds);
00411 
00412                 if (select(s+1, &fds, NULL, NULL, NULL) != 1) {
00413                         continue;
00414                 }
00415 
00416                 if(!FD_ISSET(s, &fds)) continue;
00417 
00418                 fd = accept(s,(struct sockaddr *)&addr,&addrlen);
00419 
00420                 if (fd == -1) continue;
00421 
00422                 signal(SIGCHLD, SIG_IGN);
00423 
00424                 /* we shouldn't have any children left hanging around
00425                    but I have had reports that on Digital Unix zombies
00426                    are produced, so this ensures that they are reaped */
00427 #ifdef WNOHANG
00428                 while (waitpid(-1, NULL, WNOHANG) > 0);
00429 #endif
00430 
00431                 if ((pid = fork()) == 0) {
00432                         close(s);
00433                         /* open log file in child before possibly giving
00434                            up privileges  */
00435                         log_open();
00436                         _exit(fn(fd));
00437                 } else if (pid < 0) {
00438                         rprintf(FERROR,
00439                                 RSYNC_NAME
00440                                 ": could not create child server process: %s\n",
00441                                 strerror(errno));
00442                         close(fd);
00443                         /* This might have happened because we're
00444                          * overloaded.  Sleep briefly before trying to
00445                          * accept again. */
00446                         sleep(2);
00447                 } else {
00448                         /* Parent doesn't need this fd anymore. */
00449                         close(fd);
00450                 }
00451         }
00452 }

void set_socket_options int    fd,
char *    options
 

Set user socket options.

Definition at line 502 of file socket.c.

References FERROR, level, name, OPT_BOOL, OPT_INT, OPT_ON, option, out_of_memory(), rprintf(), socket_options, strdup(), and value.

Referenced by start_daemon().

00503 {
00504         char *tok;
00505         if (!options || !*options) return;
00506 
00507         options = strdup(options);
00508         
00509         if (!options) out_of_memory("set_socket_options");
00510 
00511         for (tok=strtok(options, " \t,"); tok; tok=strtok(NULL," \t,")) {
00512                 int ret=0,i;
00513                 int value = 1;
00514                 char *p;
00515                 int got_value = 0;
00516 
00517                 if ((p = strchr(tok,'='))) {
00518                         *p = 0;
00519                         value = atoi(p+1);
00520                         got_value = 1;
00521                 }
00522 
00523                 for (i=0;socket_options[i].name;i++)
00524                         if (strcmp(socket_options[i].name,tok)==0)
00525                                 break;
00526 
00527                 if (!socket_options[i].name) {
00528                         rprintf(FERROR,"Unknown socket option %s\n",tok);
00529                         continue;
00530                 }
00531 
00532                 switch (socket_options[i].opttype) {
00533                 case OPT_BOOL:
00534                 case OPT_INT:
00535                         ret = setsockopt(fd,socket_options[i].level,
00536                                          socket_options[i].option,(char *)&value,sizeof(int));
00537                         break;
00538                         
00539                 case OPT_ON:
00540                         if (got_value)
00541                                 rprintf(FERROR,"syntax error - %s does not take a value\n",tok);
00542 
00543                         {
00544                                 int on = socket_options[i].value;
00545                                 ret = setsockopt(fd,socket_options[i].level,
00546                                                  socket_options[i].option,(char *)&on,sizeof(int));
00547                         }
00548                         break;    
00549                 }
00550                 
00551                 if (ret != 0)
00552                         rprintf(FERROR, "failed to set socket option %s: %s\n", tok,
00553                                 strerror(errno));
00554         }
00555 
00556         free(options);
00557 }

void become_daemon void   
 

Become a daemon, discarding the controlling terminal.

Definition at line 562 of file socket.c.

Referenced by daemon_main().

00563 {
00564         int i;
00565 
00566         if (fork()) {
00567                 _exit(0);
00568         }
00569 
00570         /* detach from the terminal */
00571 #ifdef HAVE_SETSID
00572         setsid();
00573 #else
00574 #ifdef TIOCNOTTY
00575         i = open("/dev/tty", O_RDWR);
00576         if (i >= 0) {
00577                 ioctl(i, (int) TIOCNOTTY, (char *)0);      
00578                 close(i);
00579         }
00580 #endif /* TIOCNOTTY */
00581 #endif
00582         /* make sure that stdin, stdout an stderr don't stuff things
00583            up (library functions, for example) */
00584         for (i=0;i<3;i++) {
00585                 close(i); 
00586                 open("/dev/null", O_RDWR);
00587         }
00588 }

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.

Definition at line 600 of file socket.c.

References set_blocking(), and set_nonblocking().

Referenced by sock_exec().

00601 {
00602         int listener;
00603         struct sockaddr_in sock;
00604         struct sockaddr_in sock2;
00605         socklen_t socklen = sizeof(sock);
00606         int connect_done = 0;
00607         
00608         fd[0] = fd[1] = listener = -1;
00609 
00610         memset(&sock, 0, sizeof(sock));
00611         
00612         if ((listener = socket(PF_INET, SOCK_STREAM, 0)) == -1) goto failed;
00613 
00614         memset(&sock2, 0, sizeof(sock2));
00615 #ifdef HAVE_SOCKADDR_LEN
00616         sock2.sin_len = sizeof(sock2);
00617 #endif
00618         sock2.sin_family = PF_INET;
00619 
00620         bind(listener, (struct sockaddr *)&sock2, sizeof(sock2));
00621 
00622         if (listen(listener, 1) != 0) goto failed;
00623 
00624         if (getsockname(listener, (struct sockaddr *)&sock, &socklen) != 0) goto failed;
00625 
00626         if ((fd[1] = socket(PF_INET, SOCK_STREAM, 0)) == -1) goto failed;
00627 
00628         set_nonblocking(fd[1]);
00629 
00630         sock.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
00631 
00632         if (connect(fd[1],(struct sockaddr *)&sock,sizeof(sock)) == -1) {
00633                 if (errno != EINPROGRESS) goto failed;
00634         } else {
00635                 connect_done = 1;
00636         }
00637 
00638         if ((fd[0] = accept(listener, (struct sockaddr *)&sock, &socklen)) == -1) goto failed;
00639 
00640         close(listener);
00641         if (connect_done == 0) {
00642                 if (connect(fd[1],(struct sockaddr *)&sock,sizeof(sock)) != 0
00643                     && errno != EISCONN) goto failed;
00644         }
00645 
00646         set_blocking (fd[1]);
00647 
00648         /* all OK! */
00649         return 0;
00650 
00651  failed:
00652         if (fd[0] != -1) close(fd[0]);
00653         if (fd[1] != -1) close(fd[1]);
00654         if (listener != -1) close(listener);
00655         return -1;
00656 }

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.

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

Definition at line 669 of file socket.c.

References FERROR, rprintf(), and socketpair_tcp().

Referenced by open_socket_out_wrapped().

00670 {
00671         int fd[2];
00672         
00673         if (socketpair_tcp(fd) != 0) {
00674                 rprintf (FERROR, RSYNC_NAME
00675                          ": socketpair_tcp failed (%s)\n",
00676                          strerror(errno));
00677                 return -1;
00678         }
00679         if (fork() == 0) {
00680                 close(fd[0]);
00681                 close(0);
00682                 close(1);
00683                 dup(fd[1]);
00684                 dup(fd[1]);
00685                 if (verbose > 3) {
00686                         /* Can't use rprintf because we've forked. */
00687                         fprintf (stderr,
00688                                  RSYNC_NAME ": execute socket program \"%s\"\n",
00689                                  prog);
00690                 }
00691                 exit (system (prog));
00692         }
00693         close (fd[1]);
00694         return fd[0];
00695 }


Variable Documentation

char* name
 

Definition at line 459 of file socket.c.

Referenced by set_socket_options().

int level
 

Definition at line 460 of file socket.c.

Referenced by set_socket_options().

int option
 

Definition at line 461 of file socket.c.

Referenced by set_socket_options().

int value
 

Definition at line 462 of file socket.c.

Referenced by abs_val(), dopr(), fmtint(), fmtstr(), ROUND(), and set_socket_options().

int opttype
 

Definition at line 463 of file socket.c.

struct { ... } socket_options[]
 

Referenced by set_socket_options().


Generated on Tue Apr 16 12:37:39 2002 for rsync by doxygen1.2.15