00001
00008
00009
00010
00011 #define BSD_COMP
00012 #include <errno.h>
00013 #include <memory.h>
00014 #include <stdio.h>
00015 #include <stdlib.h>
00016 #include <stddef.h>
00017 #include <string.h>
00018 #include <sys/types.h>
00019 #include <sys/stat.h>
00020 #include <fcntl.h>
00021
00022 #ifdef HAVE_CONFIG_H
00023 #include "config.h"
00024 #endif
00025
00026 #include "portability.h"
00027 #include "proxy_utils.h"
00028
00029 #ifndef INADDR_NONE
00030 #define INADDR_NONE ((unsigned int) 0xffffffff)
00031 #endif
00032
00043 static const char *
00044 inet_ntoa_replacement(const struct in_addr in)
00045 {
00046 static char buf[16];
00047 const unsigned char *p;
00048
00049 p = (const unsigned char *) &in.s_addr;
00050 sprintf(buf, "%u.%u.%u.%u",
00051 (unsigned int) (p[0] & 0xff), (unsigned int) (p[1] & 0xff),
00052 (unsigned int) (p[2] & 0xff), (unsigned int) (p[3] & 0xff));
00053 return buf;
00054 }
00055
00069 ipaddr_t
00070 proxy_get_my_ipaddr()
00071 {
00072 struct hostent *hp;
00073 ipaddr_t IPaddr;
00074 char buf[1024];
00075 int rv;
00076
00077 buf[0] = '\0';
00078
00079
00080
00081 rv = proxy_get_host_id(buf, sizeof(buf), SKIP_LOOPBACK, SKIP_PRIVATE);
00082
00083 if (rv < 0) {
00084
00085
00086 rv = proxy_get_host_id(buf, sizeof(buf), SKIP_LOOPBACK, INCLUDE_PRIVATE);
00087
00088 if (rv < 0) {
00089
00090
00091
00092 rv = proxy_get_host_id(buf, sizeof(buf), INCLUDE_LOOPBACK, INCLUDE_PRIVATE);
00093
00094 if (rv < 0) {
00095 fprintf(stderr,"All attempts to determine the IP address failed.\n");
00096 return -1;
00097 }
00098 }
00099 }
00100
00101 if (strlen(buf) == 0) {
00102 fprintf(stderr,"Strange.. after proxy_get_host_id, buf is empty.\n");
00103 return -1;
00104 }
00105
00106 if ((hp = gethostbyname(buf)) == NULL) {
00107 perror("gethostbyname()");
00108 return -1;
00109 }
00110 memcpy((void *) &IPaddr, hp->h_addr_list[0], sizeof(IPaddr));
00111 return IPaddr;
00112 }
00113
00114
00123 int
00124 proxy_is_socket_error(SOCKET s)
00125 {
00126 return (s == SOCKET_ERROR);
00127 }
00128
00137 int
00138 proxy_send_keepalive(SOCKET sock)
00139 {
00140 proxy_tag_t ktag;
00141
00142 ktag = PROXY_KEEPALIVE;
00143
00144 if(write_socket(sock, &ktag, sizeof(ktag)) < 0)
00145 return -1;
00146
00147 if(proxy_tread(sock, (char *)&ktag, sizeof(ktag), 1) < 0) {
00148 printf("Failed to receive ack for keepalive message.\n");
00149 return -1;
00150 }
00151
00152 return 0;
00153 }
00154
00164 int
00165 proxy_is_something_on_socket(SOCKET sock)
00166 {
00167 char buf[1];
00168 int try;
00169
00170 #ifdef WIN32
00171 u_long off = 0;
00172 u_long on = 1;
00173 ioctlsocket(sock, FIONBIO, &on);
00174 try = recv(sock, buf, 1, MSG_PEEK);
00175 ioctlsocket(sock, FIONBIO, &off);
00176 #else
00177 int off = 0;
00178 int on = 1;
00179 ioctl(sock, FIONBIO, &on);
00180 try = recv(sock, buf, 1, MSG_PEEK);
00181 ioctl(sock, FIONBIO, &off);
00182 #endif
00183
00184
00185
00186
00187
00188
00189
00190
00191
00192
00193 errno = errno_socket();
00194 if (proxy_is_socket_error(try) && (errno != EWOULDBLOCK) && (errno != EAGAIN))
00195 return -1;
00196
00197 if (try == 0)
00198 return 0;
00199
00200 return 1;
00201 }
00202
00203
00217 int
00218 proxy_get_host_id(char *hostid, int hostidlen, int skip_loopback,
00219 int skip_private)
00220 {
00221
00222 #if defined (WIN32)
00223
00224
00225
00226 strncpy(hostid, "localhost", hostidlen);
00227 hostid[hostidlen-1] = 0;
00228 return (strlen(hostid));
00229
00230
00231 #elif defined (__INTERIX)
00232
00233 SOCKET s = INVALID_SOCKET;
00234 struct sockaddr_in ia;
00235 int slen;
00236 char local_hostid[255];
00237 int status = -1;
00238
00239
00240 if ((s = socket(PF_INET, SOCK_STREAM, 0)) < 0) goto done;
00241 memset(&ia, 0, sizeof(ia));
00242 ia.sin_family = PF_INET;
00243 ia.sin_port = htons(80);
00244 ia.sin_addr.s_addr = inet_addr("216.239.59.99");
00245 if (connect(s, (struct sockaddr *)&ia, sizeof(ia)) < 0) goto done;
00246
00247
00248 memset(&ia, 0, sizeof(ia));
00249 slen = sizeof(ia);
00250 if (getsockname(s, (struct sockaddr *)&ia, &slen) < 0) goto done;
00251
00252 done:
00253
00254 if (s != INVALID_SOCKET) {
00255 strcpy(local_hostid, inet_ntoa_replacement(ia.sin_addr));
00256 strncpy(hostid, local_hostid, hostidlen);
00257 status = strlen(local_hostid);
00258 close_socket(s);
00259 }
00260
00261 return status;
00262
00263 #else
00264
00265 int s;
00266 int i;
00267 struct ifconf ifc;
00268 char local_hostid[255];
00269 char inbuf[8192];
00270 int status;
00271 struct in_addr ia;
00272
00273 status = -1;
00274
00275 if (hostidlen < 0) return status;
00276
00277 if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
00278 goto done;
00279
00280
00281 memset(inbuf, '\0', sizeof(inbuf));
00282
00283 ifc.ifc_len = sizeof(inbuf);
00284 ifc.ifc_buf = inbuf;
00285 if (ioctl(s, SIOCGIFCONF, (char *) &ifc) < 0)
00286 goto done;
00287
00288
00289 for (i = 0; i < ifc.ifc_len;) {
00290 struct ifreq *ifr = (struct ifreq *) (ifc.ifc_buf + i);
00291 struct sockaddr sa;
00292 #ifdef SIOCGIFFLAGS
00293 struct ifreq ifrf;
00294 #endif
00295
00296 #ifdef SOCKADDR_HAS_SA_LEN
00297 #define SA_LEN(x) ((x)->ifr_addr.sa_len)
00298 #else
00299 #define SA_LEN(x) (sizeof (struct sockaddr))
00300 #endif
00301
00302
00303
00304
00305
00306
00307
00308
00309 memcpy((char *)&sa, (char *)ifr + offsetof(struct ifreq, ifr_addr),
00310 sizeof(struct sockaddr));
00311
00312
00313
00314
00315 #ifdef _SIZEOF_ADDR_IFREQ
00316 i += _SIZEOF_ADDR_IFREQ(*ifr);
00317 #else
00318 #ifdef SOCKADDR_HAS_SA_LEN
00319 if (ifr->ifr_addr.sa_len > sizeof(struct sockaddr))
00320 i += sizeof(ifr->ifr_name) + ifr->ifr_addr.sa_len;
00321 else
00322 i += sizeof(ifr->ifr_name) + sizeof(struct sockaddr);
00323 #else
00324 i += sizeof(*ifr);
00325 #endif
00326 #endif
00327
00328 #ifdef PROXY_HOSTID_TEST
00329 printf("name %s\n", ifr->ifr_name);
00330 printf(" family %d\n", sa.sa_family);
00331 printf(" len %d\n", SA_LEN(ifr));
00332 #endif
00333
00334 if (sa.sa_family != AF_INET)
00335 continue;
00336
00337
00338
00339
00340 #ifdef SIOCGIFFLAGS
00341 memset(&ifrf, 0, sizeof(struct ifreq));
00342 strncpy(ifrf.ifr_name, ifr->ifr_name, sizeof(ifrf.ifr_name));
00343 ioctl(s, SIOCGIFFLAGS, (char *) &ifrf);
00344 # define IFRFREF ifrf
00345 #else
00346 # define IFRFREF (*ifr)
00347 #endif
00348
00349
00350
00351
00352 if ((IFRFREF.ifr_flags & IFF_UP) == 0)
00353 continue;
00354 if (((IFRFREF.ifr_flags & IFF_LOOPBACK) != 0) && (skip_loopback == SKIP_LOOPBACK))
00355 continue;
00356
00357
00358
00359
00360 ia = (((struct sockaddr_in *) &sa)->sin_addr);
00361 if (ia.s_addr == INADDR_ANY || ia.s_addr == INADDR_NONE)
00362 continue;
00363
00364 if (skip_private == SKIP_PRIVATE) {
00365 const unsigned char *p = (const unsigned char *) &ia.s_addr;
00366 unsigned int b1 = (unsigned int) (p[0] & 0xff);
00367 unsigned int b2 = (unsigned int) (p[1] & 0xff);
00368
00369 if (b1 == 10)
00370 continue;
00371
00372 if ((b1 == 172) && ((b2 >> 4) == 1))
00373 continue;
00374
00375 if ((b1 == 192) && (b2 == 168))
00376 continue;
00377
00378 if ((b1 == 169) && (b2 == 254))
00379 continue;
00380 }
00381
00382 if (hostidlen > 0) {
00383 goto done;
00384 }
00385 }
00386
00387 done:
00388 strcpy(local_hostid, inet_ntoa_replacement(ia));
00389 strncpy(hostid, local_hostid, hostidlen);
00390 status = strlen(local_hostid);
00391
00392 close_socket(s);
00393 return status;
00394
00395 #endif
00396 }
00397
00398
00410 int
00411 proxy_readable_timeout(SOCKET fd, int sec)
00412 {
00413 fd_set rset;
00414 struct timeval tv, *tvp;
00415
00416 FD_ZERO(&rset);
00417 FD_SET(fd, &rset);
00418
00419 tvp = NULL;
00420
00421 if(sec >= 0) {
00422 tv.tv_sec = sec;
00423 tv.tv_usec = 0;
00424
00425 tvp = &tv;
00426 }
00427
00428 return select(fd+1, &rset, NULL, NULL, tvp);
00429 }
00430
00447 int
00448 proxy_read_timeout(SOCKET d, char *b, int n, int sec)
00449 {
00450 int e;
00451
00452 if(sec != PROXY_TIMEOUT_NONE) {
00453 do {
00454 e = proxy_readable_timeout(d, sec);
00455 } while((e == -1) && ((errno=errno_socket()) == EINTR));
00456
00457 switch(e) {
00458 case 0:
00459 fprintf(stderr,"proxy_read_timeout(): timed out after %d seconds\n",
00460 sec);
00461 errno = EDEADLK;
00462 return -1;
00463 case -1:
00464 fprintf(stderr,"proxy_read_timeout(): failed to wait for desc\n");
00465 return -1;
00466
00467
00468
00469
00470 }
00471 }
00472
00473 if ((e = read_socket(d, b, n)) == SOCKET_ERROR) {
00474 perror("read");
00475 return e;
00476 }
00477
00478 return e;
00479 }
00480
00494 int
00495 proxy_tread(SOCKET fd, char *vptr, int n, int sec)
00496 {
00497 int nleft;
00498 int nread;
00499 char *ptr;
00500
00501 ptr = vptr;
00502 nleft = n;
00503 while (nleft > 0) {
00504 nread = proxy_read_timeout(fd, ptr, nleft, sec);
00505
00506 if (nread < 0) {
00507 if (errno == EINTR)
00508 nread = 0;
00509 else
00510 return(-1);
00511 } else if (nread == 0)
00512 break;
00513
00514 nleft -= nread;
00515 ptr += nread;
00516 }
00517
00518 if((n-nleft) <= 0)
00519 return -1;
00520
00521 return(n - nleft);
00522 }