X-Git-Url: https://mattmccutchen.net/rsync/rsync.git/blobdiff_plain/8950ac03f8fd0fb645c7d2374195ea884d091f72..add7e8fb6ba143bfb3f8aa2ac1e2c01734ab8e81:/socket.c diff --git a/socket.c b/socket.c index 7865e31e..d630fdba 100644 --- a/socket.c +++ b/socket.c @@ -1,6 +1,7 @@ /* -*- c-file-style: "linux" -*- - Copyright (C) 1998-2001 by Andrew Tridgell + Copyright (C) 1998-2001 by Andrew Tridgell + Copyright (C) 2001 by Martin Pool This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -134,7 +135,7 @@ int open_socket_out(char *host, int port, struct in_addr *address) hp = gethostbyname(h); if (!hp) { - rprintf(FERROR,"unknown host: %s\n", h); + rprintf(FERROR,"unknown host: \"%s\"\n", h); close(res); return -1; } @@ -170,34 +171,19 @@ open a socket of the specified type, port and address for incoming data ****************************************************************************/ static int open_socket_in(int type, int port, struct in_addr *address) { - struct hostent *hp; struct sockaddr_in sock; - char host_name[MAXHOSTNAMELEN]; int res; int one=1; - /* get my host name */ - if (gethostname(host_name, sizeof(host_name)) == -1) { - rprintf(FERROR,"gethostname failed\n"); - return -1; - } - - /* get host info */ - if ((hp = gethostbyname(host_name)) == 0) { - rprintf(FERROR,"gethostbyname: Unknown host %s\n",host_name); - return -1; - } - memset((char *)&sock,0,sizeof(sock)); - memcpy((char *)&sock.sin_addr,(char *)hp->h_addr, hp->h_length); sock.sin_port = htons(port); - sock.sin_family = hp->h_addrtype; + sock.sin_family = AF_INET; if (address) { sock.sin_addr = *address; } else { sock.sin_addr.s_addr = INADDR_ANY; } - res = socket(hp->h_addrtype, type, 0); + res = socket(AF_INET, type, 0); if (res == -1) { rprintf(FERROR,"socket failed: %s\n", strerror(errno)); @@ -210,6 +196,10 @@ static int open_socket_in(int type, int port, struct in_addr *address) if (bind(res, (struct sockaddr * ) &sock,sizeof(sock)) == -1) { rprintf(FERROR,"bind failed on port %d: %s\n", port, strerror(errno)); + if (errno == EACCES && port < 1024) { + rprintf(FERROR, "Note: you must be root to bind " + "to low-numbered ports"); + } close(res); return -1; } @@ -223,13 +213,14 @@ static int open_socket_in(int type, int port, struct in_addr *address) */ int is_a_socket(int fd) { - int v, l; + int v; + socklen_t l; l = sizeof(int); /* Parameters to getsockopt, setsockopt etc are very * unstandardized across platforms, so don't be surprised if - * there are compiler warnings on e.g. SCO OpenSwerver. It - * seems they all eventually get the right idea. + * there are compiler warnings on e.g. SCO OpenSwerver or AIX. + * It seems they all eventually get the right idea. * * Debian says: ``The fifth argument of getsockopt and * setsockopt is in reality an int [*] (and this is what BSD @@ -266,7 +257,7 @@ void start_accept_loop(int port, int (*fn)(int )) fd_set fds; int fd; struct sockaddr addr; - int in_addrlen = sizeof(addr); + socklen_t in_addrlen = sizeof(addr); /* close log file before the potentially very long select so file can be trimmed by another process instead of growing @@ -283,7 +274,7 @@ void start_accept_loop(int port, int (*fn)(int )) if(!FD_ISSET(s, &fds)) continue; /* See note above prototypes. */ - fd = accept(s,&addr,&in_addrlen); + fd = accept(s,&addr, &in_addrlen); if (fd == -1) continue; @@ -453,7 +444,7 @@ char *client_addr(int fd) { struct sockaddr sa; struct sockaddr_in *sockin = (struct sockaddr_in *) (&sa); - int length = sizeof(sa); + socklen_t length = sizeof(sa); static char addr_buf[100]; static int initialised; @@ -477,7 +468,7 @@ char *client_name(int fd) { struct sockaddr sa; struct sockaddr_in *sockin = (struct sockaddr_in *) (&sa); - int length = sizeof(sa); + socklen_t length = sizeof(sa); static char name_buf[100]; struct hostent *hp; char **p; @@ -505,8 +496,9 @@ char *client_name(int fd) /* do a forward lookup as well to prevent spoofing */ hp = gethostbyname(name_buf); if (!hp) { - strcpy(name_buf,def); - rprintf(FERROR,"reverse name lookup failed\n"); + strcpy (name_buf,def); + rprintf (FERROR, "reverse name lookup for \"%s\" failed\n", + name_buf); } else { for (p=hp->h_addr_list;*p;p++) { if (memcmp(*p, &sockin->sin_addr, hp->h_length) == 0) { @@ -522,15 +514,23 @@ char *client_name(int fd) return name_buf; } -/******************************************************************* -convert a string to an IP address. The string can be a name or -dotted decimal number - ******************************************************************/ +/** + Convert a string to an IP address. The string can be a name or + dotted decimal number. + + Returns a pointer to a static in_addr struct -- if you call this + more than once then you should copy it. +*/ struct in_addr *ip_address(const char *str) { static struct in_addr ret; struct hostent *hp; + if (!str) { + rprintf (FERROR, "ip_address received NULL name\n"); + return NULL; + } + /* try as an IP address */ if (inet_aton(str, &ret) != 0) { return &ret; @@ -538,22 +538,38 @@ struct in_addr *ip_address(const char *str) /* otherwise assume it's a network name of some sort and use gethostbyname */ - if ((hp = gethostbyname(str)) == 0) { - rprintf(FERROR, "gethostbyname: Unknown host. %s\n",str); + if ((hp = gethostbyname (str)) == 0) { + rprintf(FERROR, "gethostbyname failed for \"%s\": unknown host?\n",str); return NULL; } if (hp->h_addr == NULL) { - rprintf(FERROR, "gethostbyname: host address is invalid for host %s\n",str); + rprintf(FERROR, "gethostbyname: host address is invalid for host \"%s\"\n",str); return NULL; } - if (hp->h_length > sizeof(ret)) { - rprintf(FERROR, "gethostbyname: host address is too large\n"); + if (hp->h_length > sizeof ret) { + rprintf(FERROR, "gethostbyname: host address for \"%s\" is too large\n", + str); return NULL; } - memcpy(&ret.s_addr, hp->h_addr, hp->h_length); + if (hp->h_addrtype != AF_INET) { + rprintf (FERROR, "gethostname: host address for \"%s\" is not IPv4\n", + str); + return NULL; + } + + /* This is kind of difficult. The only field in ret is + s_addr, which is the IP address as a 32-bit int. On + UNICOS, s_addr is in fact a *bitfield* for reasons best + know to Cray. This means we can't memcpy in to it. On the + other hand, h_addr is a char*, so we can't just assign. + + Since there's meant to be only one field inside the in_addr + structure we will try just copying over the top and see how + that goes. */ + memcpy (&ret, hp->h_addr, hp->h_length); - return(&ret); + return &ret; }