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
00036 static const char default_name[] = "UNKNOWN";
00037
00038
00039
00040
00041
00042 char *client_addr(int fd)
00043 {
00044 struct sockaddr_storage ss;
00045 socklen_t length = sizeof ss;
00046 static char addr_buf[100];
00047 static int initialised;
00048
00049 if (initialised) return addr_buf;
00050
00051 initialised = 1;
00052
00053 client_sockaddr(fd, &ss, &length);
00054
00055 getnameinfo((struct sockaddr *)&ss, length,
00056 addr_buf, sizeof(addr_buf), NULL, 0, NI_NUMERICHOST);
00057
00058 return addr_buf;
00059 }
00060
00061
00062 static int get_sockaddr_family(const struct sockaddr_storage *ss)
00063 {
00064 return ((struct sockaddr *) ss)->sa_family;
00065 }
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081 char *client_name(int fd)
00082 {
00083 struct sockaddr_storage ss;
00084 socklen_t ss_len = sizeof ss;
00085 static char name_buf[100];
00086 static char port_buf[100];
00087 static int initialised;
00088
00089 if (initialised) return name_buf;
00090
00091 strcpy(name_buf, default_name);
00092 initialised = 1;
00093
00094 client_sockaddr(fd, &ss, &ss_len);
00095
00096 if (!lookup_name(fd, &ss, ss_len, name_buf, sizeof name_buf,
00097 port_buf, sizeof port_buf))
00098 check_name(fd, &ss, name_buf);
00099
00100 return name_buf;
00101 }
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111 void client_sockaddr(int fd,
00112 struct sockaddr_storage *ss,
00113 socklen_t *ss_len)
00114 {
00115 if (getpeername(fd, (struct sockaddr *) ss, ss_len)) {
00116
00117 rprintf(FERROR, RSYNC_NAME ": getpeername on fd%d failed: %s\n",
00118 fd, strerror(errno));
00119 exit_cleanup(RERR_SOCKETIO);
00120 }
00121
00122 #ifdef INET6
00123 if (get_sockaddr_family(ss) == AF_INET6 &&
00124 IN6_IS_ADDR_V4MAPPED(&((struct sockaddr_in6 *)ss)->sin6_addr)) {
00125
00126
00127
00128
00129
00130
00131 struct sockaddr_in6 sin6;
00132 struct sockaddr_in *sin;
00133
00134 memcpy(&sin6, ss, sizeof(sin6));
00135 sin = (struct sockaddr_in *)ss;
00136 memset(sin, 0, sizeof(*sin));
00137 sin->sin_family = AF_INET;
00138 *ss_len = sizeof(struct sockaddr_in);
00139 #ifdef HAVE_SOCKADDR_LEN
00140 sin->sin_len = *ss_len;
00141 #endif
00142 sin->sin_port = sin6.sin6_port;
00143
00144
00145
00146
00147 memcpy(&sin->sin_addr, &sin6.sin6_addr.s6_addr[12],
00148 sizeof(sin->sin_addr));
00149 }
00150 #endif
00151 }
00152
00153
00154
00155
00156
00157
00158
00159 int lookup_name(int fd, const struct sockaddr_storage *ss,
00160 socklen_t ss_len,
00161 char *name_buf, size_t name_buf_len,
00162 char *port_buf, size_t port_buf_len)
00163 {
00164 int name_err;
00165
00166
00167 name_err = getnameinfo((struct sockaddr *) ss, ss_len,
00168 name_buf, name_buf_len,
00169 port_buf, port_buf_len,
00170 NI_NAMEREQD | NI_NUMERICSERV);
00171 if (name_err != 0) {
00172 strcpy(name_buf, default_name);
00173 rprintf(FERROR, RSYNC_NAME ": name lookup failed for %s: %s\n",
00174 client_addr(fd),
00175 gai_strerror(name_err));
00176 return name_err;
00177 }
00178
00179 return 0;
00180 }
00181
00182
00183
00184
00185
00186
00187
00188
00189 int compare_addrinfo_sockaddr(const struct addrinfo *ai,
00190 const struct sockaddr_storage *ss)
00191 {
00192 int ss_family = get_sockaddr_family(ss);
00193 const char fn[] = "compare_addrinfo_sockaddr";
00194
00195 if (ai->ai_family != ss_family) {
00196 rprintf(FERROR,
00197 "%s: response family %d != %d\n",
00198 fn, ai->ai_family, ss_family);
00199 return 1;
00200 }
00201
00202
00203 if (ss_family == AF_INET) {
00204 const struct sockaddr_in *sin1, *sin2;
00205
00206 sin1 = (const struct sockaddr_in *) ss;
00207 sin2 = (const struct sockaddr_in *) ai->ai_addr;
00208
00209 return memcmp(&sin1->sin_addr, &sin2->sin_addr,
00210 sizeof sin1->sin_addr);
00211 }
00212 #ifdef INET6
00213 else if (ss_family == AF_INET6) {
00214 const struct sockaddr_in6 *sin1, *sin2;
00215
00216 sin1 = (const struct sockaddr_in6 *) ss;
00217 sin2 = (const struct sockaddr_in6 *) ai->ai_addr;
00218
00219 return memcmp(&sin1->sin6_addr, &sin2->sin6_addr,
00220 sizeof sin1->sin6_addr);
00221 }
00222 #endif
00223 else {
00224
00225 return 1;
00226 }
00227 }
00228
00229
00230
00231
00232
00233
00234
00235
00236
00237
00238
00239
00240 int check_name(int fd,
00241 const struct sockaddr_storage *ss,
00242 char *name_buf)
00243 {
00244 struct addrinfo hints, *res, *res0;
00245 int error;
00246 int ss_family = get_sockaddr_family(ss);
00247
00248 memset(&hints, 0, sizeof(hints));
00249 hints.ai_family = ss_family;
00250 hints.ai_flags = AI_CANONNAME;
00251 hints.ai_socktype = SOCK_STREAM;
00252 error = getaddrinfo(name_buf, NULL, &hints, &res0);
00253 if (error) {
00254 rprintf(FERROR,
00255 RSYNC_NAME ": forward name lookup for %s failed: %s\n",
00256 name_buf, gai_strerror(error));
00257 strcpy(name_buf, default_name);
00258 return error;
00259 }
00260
00261
00262
00263
00264 for (res = res0; res; res = res->ai_next) {
00265 if (!compare_addrinfo_sockaddr(res, ss))
00266 break;
00267 }
00268
00269 if (!res0) {
00270
00271
00272 rprintf(FERROR, RSYNC_NAME
00273 ": no known address for \"%s\": "
00274 "spoofed address?\n",
00275 name_buf);
00276 strcpy(name_buf, default_name);
00277 } else if (res == NULL) {
00278
00279
00280 rprintf(FERROR, RSYNC_NAME
00281 ": %s is not a known address for \"%s\": "
00282 "spoofed address?\n",
00283 client_addr(fd),
00284 name_buf);
00285 strcpy(name_buf, default_name);
00286 }
00287
00288 freeaddrinfo(res0);
00289 return 0;
00290 }
00291