common.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637
  1. /*
  2. 3APA3A simpliest proxy server
  3. (c) 2002-2016 by Vladimir Dubrovin <3proxy@3proxy.ru>
  4. please read License Agreement
  5. */
  6. #include "proxy.h"
  7. char * copyright = COPYRIGHT;
  8. int randomizer = 1;
  9. #ifndef _WIN32
  10. pthread_attr_t pa;
  11. void daemonize(void){
  12. if(fork() > 0) {
  13. usleep(SLEEPTIME);
  14. _exit(0);
  15. }
  16. setsid();
  17. }
  18. #endif
  19. char **stringtable = NULL;
  20. #ifdef WITH_LINUX_FUTEX
  21. int sys_futex(void *addr1, int op, int val1, struct timespec *timeout, void *addr2, int val3)
  22. {
  23. return syscall(SYS_futex, addr1, op, val1, timeout, addr2, val3);
  24. }
  25. int mutex_lock(int *val)
  26. {
  27. int c;
  28. if ((c = __sync_val_compare_and_swap(val, 0, 1)) != 0)
  29. do {
  30. if(c == 2 || __sync_val_compare_and_swap(val, 1, 2) != 0)
  31. sys_futex(val, FUTEX_WAIT_PRIVATE, 2, NULL, NULL, 0);
  32. } while ((c = __sync_val_compare_and_swap(val, 0, 2)) != 0);
  33. return 0;
  34. }
  35. int mutex_unlock(int *val)
  36. {
  37. if(__sync_fetch_and_sub (val, 1) != 1){
  38. *val = 0;
  39. sys_futex(val, FUTEX_WAKE_PRIVATE, 1, NULL, NULL, 0);
  40. }
  41. return 0;
  42. }
  43. #endif
  44. int myinet_ntop(int af, void *src, char *dst, socklen_t size){
  45. #ifndef NOIPV6
  46. if(af != AF_INET6){
  47. #endif
  48. unsigned u = ntohl(((struct in_addr *)src)->s_addr);
  49. return sprintf(dst, "%u.%u.%u.%u",
  50. ((u&0xFF000000)>>24),
  51. ((u&0x00FF0000)>>16),
  52. ((u&0x0000FF00)>>8),
  53. ((u&0x000000FF)));
  54. #ifndef NOIPV6
  55. }
  56. *dst = 0;
  57. inet_ntop(af, src, dst, size);
  58. return (int)strlen(dst);
  59. #endif
  60. }
  61. char *rotations[] = {
  62. "",
  63. "/min",
  64. "/hour",
  65. "/day",
  66. "/week",
  67. "/month",
  68. "/year",
  69. "",
  70. };
  71. struct extparam conf = {
  72. {1, 5, 30, 60, 180, 1800, 15, 60, 15, 5, 0, 0}, /* int timeouts[12]; */
  73. NULL, /*struct ace * acl; */
  74. NULL, /* char * conffile; */
  75. NULL, NULL, /* struct bandlim * bandlimiter, *bandlimiterout; */
  76. NULL, /* struct connlim * connlimiter; */
  77. NULL, /* struct trafcount * trafcounter; */
  78. NULL, /* struct srvparam *services; */
  79. 0, /* int stacksize, */
  80. 0, -1, 0, 0, 0, 0, /* threadinit, counterd, haveerror, rotate, paused, archiverc, */
  81. 0, 500, 0, 0, 0, 0, 0, /* demon, maxchild, needreload, timetoexit, version, noforce, bandlimver; */
  82. 6, 600, /* int authcachetype, authcachetime; */
  83. 1048576, /* int filtermaxsize; */
  84. NULL, /* **archiver; */
  85. NONE, NONE, /* ROTATION logtype, countertype; */
  86. NULL, /* char * counterfile; */
  87. #ifndef NOIPV6
  88. {AF_INET},{AF_INET6},{AF_INET}, /* struct sockaddr_in6 intsa;
  89. struct sockaddr_in6 extsa6;
  90. struct sockaddr_in6 extsa; */
  91. #else
  92. {AF_INET},{AF_INET}, /* struct sockaddr_in intsa;
  93. struct sockaddr_in extsa; */
  94. #endif
  95. NULL, /* struct passwords *pwl; */
  96. NULL, /* struct auth * authenticate; */
  97. doconnect, /* AUTHFUNC authfunc; */
  98. NULL, /* BANDLIMFUNC bandlimfunc; */
  99. NULL, /* TRAFCOUNTFUNC trafcountfunc; */
  100. NULL, /* void (*prelog)(struct clientparam * param); */
  101. NULL, NULL, /* char *logtarget, *logformat; */
  102. NULL, /* struct filemon * fmon; */
  103. NULL, /* struct filter * filters; */
  104. NULL, /* struct auth *authfuncs; */
  105. NULL, /* char* demanddialprog; */
  106. NULL, /* char **stringtable; */
  107. (time_t)0, /* time_t time; */
  108. 0,0, /* unsigned logdumpsrv, logdumpcli; */
  109. '@', /* char delimchar; */
  110. };
  111. int numservers=0;
  112. char* NULLADDR="\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0";
  113. int myrand(void * entropy, int len){
  114. int i;
  115. unsigned short init;
  116. init = randomizer;
  117. for(i=0; i < len/2; i++){
  118. init ^= ((unsigned short *)entropy)[i];
  119. }
  120. srand(init);
  121. randomizer = rand();
  122. return rand();
  123. }
  124. #ifndef WITH_POLL
  125. #ifndef WITH_WSAPOLL
  126. int
  127. #ifdef _WIN32
  128. WINAPI
  129. #endif
  130. mypoll(struct mypollfd *fds, unsigned int nfds, int timeout){
  131. fd_set readfd;
  132. fd_set writefd;
  133. fd_set oobfd;
  134. struct timeval tv;
  135. unsigned i;
  136. int num;
  137. SOCKET maxfd = 0;
  138. tv.tv_sec = timeout/1000;
  139. tv.tv_usec = (timeout%1000)*1000;
  140. FD_ZERO(&readfd);
  141. FD_ZERO(&writefd);
  142. FD_ZERO(&oobfd);
  143. for(i=0; i<nfds; i++){
  144. if((fds[i].events&POLLIN))FD_SET(fds[i].fd, &readfd);
  145. if((fds[i].events&POLLOUT))FD_SET(fds[i].fd, &writefd);
  146. if((fds[i].events&POLLPRI))FD_SET(fds[i].fd, &oobfd);
  147. fds[i].revents = 0;
  148. if(fds[i].fd > maxfd) maxfd = fds[i].fd;
  149. }
  150. if((num = select(((int)(maxfd))+1, &readfd, &writefd, &oobfd, &tv)) < 1) return num;
  151. for(i=0; i<nfds; i++){
  152. if(FD_ISSET(fds[i].fd, &readfd)) fds[i].revents |= POLLIN;
  153. if(FD_ISSET(fds[i].fd, &writefd)) fds[i].revents |= POLLOUT;
  154. if(FD_ISSET(fds[i].fd, &oobfd)) fds[i].revents |= POLLPRI;
  155. }
  156. return num;
  157. }
  158. #endif
  159. #endif
  160. struct sockfuncs so = {
  161. socket,
  162. accept,
  163. bind,
  164. listen,
  165. connect,
  166. getpeername,
  167. getsockname,
  168. getsockopt,
  169. setsockopt,
  170. #ifndef WITH_POLL
  171. #ifndef WITH_WSAPOLL
  172. mypoll,
  173. #else
  174. WSAPoll,
  175. #endif
  176. #else
  177. poll,
  178. #endif
  179. (void *)send,
  180. (void *)sendto,
  181. (void *)recv,
  182. (void *)recvfrom,
  183. shutdown,
  184. #ifdef _WIN32
  185. closesocket
  186. #else
  187. close
  188. #endif
  189. };
  190. #ifdef _WINCE
  191. static char cebuf[1024];
  192. static char ceargbuf[256];
  193. char * ceargv[32];
  194. char * CEToUnicode (const char *str){
  195. int i;
  196. for(i=0; i<510 && str[i]; i++){
  197. cebuf[(i*2)] = str[i];
  198. cebuf[(i*2)+1] = 0;
  199. }
  200. cebuf[(i*2)] = 0;
  201. cebuf[(i*2)+1] = 0;
  202. return cebuf;
  203. };
  204. int cesystem(const char *str){
  205. STARTUPINFO startupInfo = {0};
  206. startupInfo.cb = sizeof(startupInfo);
  207. PROCESS_INFORMATION processInformation;
  208. return CreateProcessW((LPWSTR)CEToUnicode(str), NULL, NULL, NULL, FALSE, NORMAL_PRIORITY_CLASS, NULL, NULL, &startupInfo, &processInformation);
  209. }
  210. int ceparseargs(const char *str){
  211. int argc = 0, i;
  212. int space = 1;
  213. for(i=0; i<250 && argc<30 && str[2*i]; i++){
  214. ceargbuf[i] = str[2*i];
  215. if(space && ceargbuf[i]!=' '&& ceargbuf[i]!='\t'&& ceargbuf[i]!='\r'&& ceargbuf[i]!='\n'){
  216. ceargv[argc++] = ceargbuf + i;
  217. space = 0;
  218. }
  219. else if(!space && (ceargbuf[i]==' ' || ceargbuf[i]=='\t' || ceargbuf[i]=='\r' || ceargbuf[i]=='\n')){
  220. ceargbuf[i] = 0;
  221. space = 1;
  222. }
  223. }
  224. return argc;
  225. }
  226. #endif
  227. int parsehost(int family, char *host, struct sockaddr *sa){
  228. char *sp=NULL,*se=NULL;
  229. unsigned short port=0;
  230. int ret = 0;
  231. if(!host) return 2;
  232. if(*host == '[') se=strchr((char *)host, ']');
  233. if ( (sp = strchr(se?se:(char *)host, ':')) && !strchr(sp+1, ':')) *sp = 0;
  234. if(se){
  235. *se = 0;
  236. }
  237. if(sp){
  238. port = atoi(sp+1);
  239. }
  240. ret = !getip46(family, host + (se!=0), (struct sockaddr *)sa);
  241. if(se) *se = ']';
  242. if(sp) *sp = ':';
  243. if(port)*SAPORT(sa) = htons(port);
  244. return ret;
  245. }
  246. int parsehostname(char *hostname, struct clientparam *param, unsigned short port){
  247. char *sp=NULL,*se=NULL;
  248. int ret = 0;
  249. if(!hostname || !*hostname)return 2;
  250. if(*hostname == '[') se=strchr(hostname, ']');
  251. if (sp = strchr(se?se:hostname, ':')) {
  252. if(strchr(sp+1, ':'))sp = NULL;
  253. else *sp = 0;
  254. }
  255. if(se){
  256. *se = 0;
  257. }
  258. if(hostname != (char *)param->hostname){
  259. if(param->hostname) myfree(param->hostname);
  260. param->hostname = (char *)mystrdup(hostname + (se!=0));
  261. }
  262. if(sp){
  263. port = atoi(sp+1);
  264. }
  265. ret = !getip46(param->srv->family, param->hostname, (struct sockaddr *)&param->req);
  266. if(se) *se = ']';
  267. if(sp) *sp = ':';
  268. *SAPORT(&param->req) = htons(port);
  269. memset(&param->sinsr, 0, sizeof(param->sinsr));
  270. return ret;
  271. }
  272. int parseusername(char *username, struct clientparam *param, int extpasswd){
  273. char *sb = NULL, *se = NULL, *sp = NULL;
  274. if(!username || !*username) return 1;
  275. if(param->srv->needuser && (sb = strchr(username, ':')) && (se = strchr(sb + 1, ':')) && (!extpasswd || (sp = strchr(se + 1, ':')))){
  276. *sb = 0;
  277. *se = 0;
  278. if(sp) *sp = 0;
  279. if(*(sb+1)) {
  280. if(param->password) myfree(param->password);
  281. param->password = (char *)mystrdup(sb+1);
  282. }
  283. if(*username) {
  284. if(param->username) myfree(param->username);
  285. param->username = (char *)mystrdup(username);
  286. }
  287. username = se+1;
  288. }
  289. if(extpasswd){
  290. if(!sp) sp = strchr(username, ':');
  291. if(sp){
  292. *sp = 0;
  293. if(param->extpassword) myfree(param->extpassword);
  294. param->extpassword = (char *) mystrdup(sp+1);
  295. }
  296. }
  297. if(param->extusername) myfree(param->extusername);
  298. param->extusername = (char *)mystrdup(username);
  299. if(sb) *sb = ':';
  300. if(se) *se = ':';
  301. if(sp) *sp = ':';
  302. return 0;
  303. }
  304. int parseconnusername(char *username, struct clientparam *param, int extpasswd, unsigned short port){
  305. char *sb, *se;
  306. if(!username || !*username) return 1;
  307. if ((sb=strchr(username, conf.delimchar)) == NULL){
  308. if(!param->hostname && param->remsock == INVALID_SOCKET) return 2;
  309. if(param->hostname)parsehostname((char *)param->hostname, param, port);
  310. return parseusername(username, param, extpasswd);
  311. }
  312. while ((se=strchr(sb+1, conf.delimchar)))sb=se;
  313. *(sb) = 0;
  314. if(parseusername(username, param, extpasswd)) return 3;
  315. *(sb) = conf.delimchar;
  316. if(parsehostname(sb+1, param, port)) return 4;
  317. return 0;
  318. }
  319. int connectwithpoll(SOCKET sock, struct sockaddr *sa, SASIZETYPE size, int to){
  320. struct pollfd fds[1];
  321. #ifdef _WIN32
  322. unsigned long ul = 1;
  323. ioctlsocket(sock, FIONBIO, &ul);
  324. #else
  325. fcntl(sock,F_SETFL, O_NONBLOCK | fcntl(sock,F_GETFL));
  326. #endif
  327. if(so._connect(sock,sa,size)) {
  328. if(errno != EAGAIN && errno != EINPROGRESS) return (13);
  329. }
  330. memset(fds, 0, sizeof(fds));
  331. fds[0].fd = sock;
  332. fds[0].events = POLLOUT;
  333. if(so._poll(fds, 1, to*1000) <= 0) {
  334. return (13);
  335. }
  336. return 0;
  337. }
  338. int doconnect(struct clientparam * param){
  339. SASIZETYPE size;
  340. if (*SAFAMILY(&param->sincl) == *SAFAMILY(&param->req) && !memcmp(SAADDR(&param->sincl), SAADDR(&param->req), SAADDRLEN(&param->req)) &&
  341. *SAPORT(&param->sincl) == *SAPORT(&param->req)) return 519;
  342. if (param->operation == ADMIN || param->operation == DNSRESOLVE || param->operation == BIND || param->operation == UDPASSOC)
  343. return 0;
  344. if (param->remsock != INVALID_SOCKET){
  345. size = sizeof(param->sinsr);
  346. if(so._getpeername(param->remsock, (struct sockaddr *)&param->sinsr, &size)==-1) {return (15);}
  347. }
  348. else {
  349. struct linger lg = {1,conf.timeouts[SINGLEBYTE_S]};
  350. if(SAISNULL(&param->sinsr)){
  351. if(SAISNULL(&param->req)) {
  352. return 100;
  353. }
  354. *SAFAMILY(&param->sinsr) = *SAFAMILY(&param->req);
  355. memcpy(SAADDR(&param->sinsr), SAADDR(&param->req), SAADDRLEN(&param->req));
  356. }
  357. if(!*SAPORT(&param->sinsr))*SAPORT(&param->sinsr) = *SAPORT(&param->req);
  358. if ((param->remsock=so._socket(SASOCK(&param->sinsr), SOCK_STREAM, IPPROTO_TCP)) == INVALID_SOCKET) {return (11);}
  359. setopts(param->remsock, param->srv->srvsockopts);
  360. so._setsockopt(param->remsock, SOL_SOCKET, SO_LINGER, (char *)&lg, sizeof(lg));
  361. #ifdef REUSE
  362. {
  363. int opt;
  364. #ifdef SO_REUSEADDR
  365. opt = 1;
  366. so._setsockopt(param->remsock, SOL_SOCKET, SO_REUSEADDR, (char *)&opt, sizeof(int));
  367. #endif
  368. #ifdef SO_REUSEPORT
  369. opt = 1;
  370. so._setsockopt(param->remsock, SOL_SOCKET, SO_REUSEPORT, (char *)&opt, sizeof(int));
  371. #endif
  372. }
  373. #endif
  374. #ifdef SO_BINDTODEVICE
  375. if(param->srv->obindtodevice) {
  376. if(so._setsockopt(param->remsock, SOL_SOCKET, SO_BINDTODEVICE, param->srv->obindtodevice, strlen(param->srv->obindtodevice) + 1))
  377. return 12;
  378. }
  379. #endif
  380. if(SAISNULL(&param->sinsl)){
  381. #ifndef NOIPV6
  382. if(*SAFAMILY(&param->sinsr) == AF_INET6) param->sinsl = param->srv->extsa6;
  383. else
  384. #endif
  385. param->sinsl = param->srv->extsa;
  386. }
  387. *SAPORT(&param->sinsl) = 0;
  388. if(so._bind(param->remsock, (struct sockaddr*)&param->sinsl, SASIZE(&param->sinsl))==-1) {
  389. return 12;
  390. }
  391. if(param->operation >= 256 || (param->operation & CONNECT)){
  392. if(connectwithpoll(param->remsock,(struct sockaddr *)&param->sinsr,SASIZE(&param->sinsr),CONNECT_TO)) {
  393. return 13;
  394. }
  395. }
  396. size = sizeof(param->sinsl);
  397. if(so._getsockname(param->remsock, (struct sockaddr *)&param->sinsl, &size)==-1) {return (15);}
  398. }
  399. return 0;
  400. }
  401. int scanaddr(const char *s, unsigned long * ip, unsigned long * mask) {
  402. unsigned d1, d2, d3, d4, m;
  403. int res;
  404. if ((res = sscanf((char *)s, "%u.%u.%u.%u/%u", &d1, &d2, &d3, &d4, &m)) < 4) return 0;
  405. if(mask && res == 4) *mask = 0xFFFFFFFF;
  406. else if (mask) *mask = htonl(0xFFFFFFFF << (32 - m));
  407. *ip = htonl ((d1<<24) ^ (d2<<16) ^ (d3<<8) ^ d4);
  408. return res;
  409. }
  410. RESOLVFUNC resolvfunc = NULL;
  411. #ifndef _WIN32
  412. pthread_mutex_t gethostbyname_mutex;
  413. int ghbn_init = 0;
  414. #endif
  415. #ifdef GETHOSTBYNAME_R
  416. struct hostent * my_gethostbyname(char *name, char *buf, struct hostent *hp){
  417. struct hostent *result;
  418. int gherrno;
  419. #ifdef _SOLARIS
  420. return gethostbyname_r(name, hp, buf, 1024, &gherrno);
  421. #else
  422. if(gethostbyname_r(name, hp, buf, 1024, &result, &gherrno) != 0)
  423. return NULL;
  424. return result;
  425. #endif
  426. }
  427. #endif
  428. #ifdef NOIPV6
  429. unsigned long getip(char *name){
  430. unsigned long retval;
  431. int i;
  432. int ndots = 0;
  433. struct hostent *hp=NULL;
  434. RESOLVFUNC tmpresolv;
  435. #ifdef GETHOSTBYNAME_R
  436. struct hostent he;
  437. char ghbuf[1024];
  438. #define gethostbyname(NAME) my_gethostbyname(NAME, ghbuf, &he)
  439. #endif
  440. if(strlen((char *)name)>255)name[255] = 0;
  441. for(i=0; name[i]; i++){
  442. if(name[i] == '.'){
  443. if(++ndots > 3) break;
  444. continue;
  445. }
  446. if(name[i] <'0' || name[i] >'9') break;
  447. }
  448. if(!name[i] && ndots == 3){
  449. if(scanaddr(name, &retval, NULL) == 4){
  450. return retval;
  451. }
  452. }
  453. if((tmpresolv=resolvfunc)){
  454. if((*tmpresolv)(AF_INET, name, (char *)&retval)) return retval;
  455. return (*tmpresolv)(AF_INET, name, (char *)&retval)?retval:0;
  456. }
  457. #if !defined(_WIN32) && !defined(GETHOSTBYNAME_R)
  458. if(!ghbn_init){
  459. pthread_mutex_init(&gethostbyname_mutex, NULL);
  460. ghbn_init++;
  461. }
  462. pthread_mutex_lock(&gethostbyname_mutex);
  463. #endif
  464. hp=gethostbyname((char *)name);
  465. if (!hp && conf.demanddialprog) {
  466. system(conf.demanddialprog);
  467. hp=gethostbyname((char *)name);
  468. }
  469. retval = hp?*(unsigned long *)hp->h_addr:0;
  470. #if !defined(_WIN32) && !defined(GETHOSTBYNAME_R)
  471. pthread_mutex_unlock(&gethostbyname_mutex);
  472. #endif
  473. #ifdef GETHOSTBYNAME_R
  474. #undef gethostbyname
  475. #endif
  476. return retval;
  477. }
  478. #endif
  479. int afdetect(char *name){
  480. int ndots=0, ncols=0, nhex=0;
  481. int i;
  482. for(i=0; name[i]; i++){
  483. if(name[i] == '.'){
  484. if(++ndots > 3) {
  485. return -1;
  486. }
  487. }
  488. else if(name[i] == ':'){
  489. if(++ncols > 7) {
  490. return -1;
  491. }
  492. }
  493. else if(name[i] == '%' || (name[i] >= 'a' && name[i] <= 'f') || (name[i] >= 'A' && name[i] <= 'F')){
  494. nhex++;
  495. }
  496. else if(name[i] <'0' || name[i] >'9') {
  497. return -1;
  498. }
  499. }
  500. if(ndots == 3 && ncols == 0 && nhex == 0){
  501. return AF_INET;
  502. }
  503. if(ncols >= 2) {
  504. return AF_INET6;
  505. }
  506. return -1;
  507. }
  508. unsigned long getip46(int family, char *name, struct sockaddr *sa){
  509. #ifndef NOIPV6
  510. int detect;
  511. struct addrinfo *ai, hint;
  512. RESOLVFUNC tmpresolv;
  513. if(!sa) return 0;
  514. if(!family) {
  515. family = 4;
  516. #else
  517. ((struct sockaddr_in *)sa)->sin_family = AF_INET;
  518. return (((struct sockaddr_in *)sa)->sin_addr.s_addr = getip(name))? AF_INET:0;
  519. #endif
  520. #ifndef NOIPV6
  521. }
  522. detect = afdetect(name);
  523. if(detect != -1){
  524. if(family == 4 && detect != AF_INET) return 0;
  525. *SAFAMILY(sa) = (family == 6)? AF_INET6 : detect;
  526. return inet_pton(*SAFAMILY(sa), (char *)name, SAADDR(sa))? *SAFAMILY(sa) : 0;
  527. }
  528. if((tmpresolv = resolvfunc)){
  529. int f = (family == 6 || family == 64)?AF_INET6:AF_INET;
  530. *SAFAMILY(sa) = f;
  531. if(tmpresolv(f, name, SAADDR(sa))) return f;
  532. if(family == 4 || family == 6) return 0;
  533. f = (family == 46)? AF_INET6 : AF_INET;
  534. *SAFAMILY(sa) = f;
  535. if(tmpresolv(f, name, SAADDR(sa))) return f;
  536. return 0;
  537. }
  538. memset(&hint, 0, sizeof(hint));
  539. hint.ai_family = (family == 6 || family == 64)?AF_INET6:AF_INET;
  540. if (getaddrinfo((char *)name, NULL, &hint, &ai)) {
  541. if(family == 64 || family == 46){
  542. hint.ai_family = (family == 64)?AF_INET:AF_INET6;
  543. if (getaddrinfo((char *)name, NULL, &hint, &ai)) return 0;
  544. }
  545. else return 0;
  546. }
  547. if(ai){
  548. if(ai->ai_addr->sa_family == AF_INET || ai->ai_addr->sa_family == AF_INET6){
  549. *SAFAMILY(sa)=ai->ai_addr->sa_family;
  550. memcpy(SAADDR(sa), SAADDR(ai->ai_addr), SAADDRLEN(ai->ai_addr));
  551. freeaddrinfo(ai);
  552. return *SAFAMILY(sa);
  553. }
  554. freeaddrinfo(ai);
  555. }
  556. return 0;
  557. #endif
  558. }