This source file includes following definitions.
- sim_get_err_sock
- sim_err_sock
- s_freeaddrinfo
- s_getaddrinfo
- s_getnameinfo
- load_function
- load_ws2
- sim_parse_addr
- sim_parse_addr_ex
- sim_init_sock
- sim_cleanup_sock
- sim_setnonblock
- sim_setnonblock
- sim_setnodelay
- sim_create_sock
- sim_master_sock_ex
- sim_connect_sock_ex
- sim_accept_conn_ex
- sim_check_conn
- _sim_getaddrname
- sim_getnames_sock
- sim_read_sock
- sim_write_sock
- sim_close_sock
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41 #include "sim_sock.h"
42 #include <signal.h>
43 #include <stdio.h>
44 #include <stdlib.h>
45
46 #ifdef __CYGWIN__
47 # include <dlfcn.h>
48 # include <libloaderapi.h>
49 #endif
50
51 #if defined(AF_INET6) && defined(_WIN32)
52 # include <ws2tcpip.h>
53 #endif
54
55 #if !defined(_WIN32) && !defined(CROSS_MINGW32) && !defined(CROSS_MINGW64) && !defined(__MINGW32__) && !defined(__MINGW64__) && !defined(__CYGWIN__)
56 # include <sys/select.h>
57 #endif
58
59 #ifndef WSAAPI
60 # define WSAAPI
61 #endif
62
63 #if defined(SHUT_RDWR) && !defined(SD_BOTH)
64 # define SD_BOTH SHUT_RDWR
65 #endif
66
67 #ifndef NI_MAXHOST
68 # define NI_MAXHOST 1025
69 #endif
70
71 #undef FREE
72 #ifdef TESTING
73 # define FREE(p) free(p)
74 #else
75 # define FREE(p) do \
76 { \
77 free((p)); \
78 (p) = NULL; \
79 } while(0)
80 #endif
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99 static struct sock_errors {
100 int value;
101 const char *text;
102 } sock_errors[] = {
103 {WSAEWOULDBLOCK, "Operation would block"},
104 {WSAENAMETOOLONG, "File name too long"},
105 {WSAEINPROGRESS, "Operation now in progress "},
106 {WSAETIMEDOUT, "Connection timed out"},
107 {WSAEISCONN, "Transport endpoint is already connected"},
108 {WSAECONNRESET, "Connection reset by peer"},
109 {WSAECONNREFUSED, "Connection refused"},
110 {WSAECONNABORTED, "Connection aborted"},
111 {WSAEHOSTUNREACH, "No route to host"},
112 {WSAEADDRINUSE, "Address already in use"},
113 #if defined (WSAEAFNOSUPPORT)
114 {WSAEAFNOSUPPORT, "Address family not supported by protocol"},
115 #endif
116 {WSAEACCES, "Permission denied"},
117 {0, NULL}
118 };
119
120 const char *sim_get_err_sock (const char *emsg)
121 {
122 int err = WSAGetLastError ();
123 int i;
124 static char err_buf[512];
125
126 for (i=0; (sock_errors[i].text) && (sock_errors[i].value != err); i++)
127 ;
128 if (sock_errors[i].value == err)
129 sprintf (err_buf, "Sockets: %s error %d - %s\n", emsg, err, sock_errors[i].text);
130 else
131 #if defined(_WIN32)
132 sprintf (err_buf, "Sockets: %s error %d\n", emsg, err);
133 #else
134 sprintf (err_buf, "Sockets: %s error %d - %s\n", emsg, err, strerror(err));
135 #endif
136 return err_buf;
137 }
138
139 SOCKET sim_err_sock (SOCKET s, const char *emsg)
140 {
141 sim_printf ("%s", sim_get_err_sock (emsg));
142 if (s != INVALID_SOCKET) {
143 int err = WSAGetLastError ();
144 sim_close_sock (s);
145 WSASetLastError (err);
146 }
147 return INVALID_SOCKET;
148 }
149
150 typedef void (WSAAPI *freeaddrinfo_func) (struct addrinfo *ai);
151 static freeaddrinfo_func p_freeaddrinfo;
152
153 typedef int (WSAAPI *getaddrinfo_func) (const char *hostname,
154 const char *service,
155 const struct addrinfo *hints,
156 struct addrinfo **res);
157 static getaddrinfo_func p_getaddrinfo;
158
159 typedef int (WSAAPI *getnameinfo_func) (const struct sockaddr *sa, socklen_t salen, char *host, size_t hostlen, char *serv, size_t servlen, int flags);
160 static getnameinfo_func p_getnameinfo;
161
162 #if defined(_WIN32) || defined(__CYGWIN__)
163 static void WSAAPI s_freeaddrinfo (struct addrinfo *ai)
164 {
165 struct addrinfo *a, *an;
166
167 for (a=ai; a != NULL; a=an) {
168 an = a->ai_next;
169 FREE (a->ai_canonname);
170 FREE (a->ai_addr);
171 FREE (a);
172 }
173 }
174
175 static int WSAAPI s_getaddrinfo (const char *hostname,
176 const char *service,
177 const struct addrinfo *hints,
178 struct addrinfo **res)
179 {
180 struct hostent *he;
181 struct servent *se = NULL;
182 struct sockaddr_in *sin;
183 struct addrinfo *result = NULL;
184 struct addrinfo *ai, *lai = NULL;
185 struct addrinfo dhints;
186 struct in_addr ipaddr;
187 struct in_addr *fixed[2];
188 struct in_addr **ips = NULL;
189 struct in_addr **ip;
190 const char *cname = NULL;
191 int port = 0;
192
193
194 if ((hostname == NULL) && (service == NULL))
195 return EAI_NONAME;
196
197 if (hints) {
198 if ((hints->ai_family != PF_INET) && (hints->ai_family != PF_UNSPEC))
199 return EAI_FAMILY;
200 switch (hints->ai_socktype)
201 {
202 default:
203 return EAI_SOCKTYPE;
204 case SOCK_DGRAM:
205 case SOCK_STREAM:
206 case 0:
207 break;
208 }
209 }
210 else {
211 hints = &dhints;
212 memset(&dhints, 0, sizeof(dhints));
213 dhints.ai_family = PF_UNSPEC;
214 }
215 if (service) {
216 char *c;
217
218 port = strtoul(service, &c, 10);
219 if ((port == 0) || (*c != '\0')) {
220 switch (hints->ai_socktype)
221 {
222 case SOCK_DGRAM:
223 se = getservbyname(service, "udp");
224 break;
225 case SOCK_STREAM:
226 case 0:
227 se = getservbyname(service, "tcp");
228 break;
229 }
230 if (NULL == se)
231 return EAI_SERVICE;
232 port = se->s_port;
233 }
234 }
235
236 if (hostname) {
237 if ((0xffffffff != (ipaddr.s_addr = inet_addr(hostname))) ||
238 (0 == strcmp("255.255.255.255", hostname))) {
239 fixed[0] = &ipaddr;
240 fixed[1] = NULL;
241 }
242 else {
243 if ((0xffffffff != (ipaddr.s_addr = inet_addr(hostname))) ||
244 (0 == strcmp("255.255.255.255", hostname))) {
245 fixed[0] = &ipaddr;
246 fixed[1] = NULL;
247 if ((hints->ai_flags & AI_CANONNAME) && !(hints->ai_flags & AI_NUMERICHOST)) {
248 he = gethostbyaddr((char *)&ipaddr, 4, AF_INET);
249 if (NULL != he)
250 cname = he->h_name;
251 else
252 cname = hostname;
253 }
254 ips = fixed;
255 }
256 else {
257 if (hints->ai_flags & AI_NUMERICHOST)
258 return EAI_NONAME;
259 he = gethostbyname(hostname);
260 if (he) {
261 ips = (struct in_addr **)he->h_addr_list;
262 if (hints->ai_flags & AI_CANONNAME)
263 cname = he->h_name;
264 }
265 else {
266 switch (h_errno)
267 {
268 case HOST_NOT_FOUND:
269 case NO_DATA:
270 return EAI_NONAME;
271 case TRY_AGAIN:
272 return EAI_AGAIN;
273 default:
274 return EAI_FAIL;
275 }
276 }
277 }
278 }
279 }
280 else {
281 if (hints->ai_flags & AI_PASSIVE)
282 ipaddr.s_addr = htonl(INADDR_ANY);
283 else
284 ipaddr.s_addr = htonl(INADDR_LOOPBACK);
285 fixed[0] = &ipaddr;
286 fixed[1] = NULL;
287 ips = fixed;
288 }
289 for (ip=ips; (ip != NULL) && (*ip != NULL); ++ip) {
290 ai = (struct addrinfo *)calloc(1, sizeof(*ai));
291 if (NULL == ai) {
292 s_freeaddrinfo(result);
293 return EAI_MEMORY;
294 }
295 ai->ai_family = PF_INET;
296 ai->ai_socktype = hints->ai_socktype;
297 ai->ai_protocol = hints->ai_protocol;
298 ai->ai_addr = NULL;
299 ai->ai_addrlen = sizeof(struct sockaddr_in);
300 ai->ai_canonname = NULL;
301 ai->ai_next = NULL;
302 ai->ai_addr = (struct sockaddr *)calloc(1, sizeof(struct sockaddr_in));
303 if (NULL == ai->ai_addr) {
304 FREE(ai);
305 s_freeaddrinfo(result);
306 return EAI_MEMORY;
307 }
308 sin = (struct sockaddr_in *)ai->ai_addr;
309 sin->sin_family = PF_INET;
310 sin->sin_port = (unsigned short)port;
311 memcpy(&sin->sin_addr, *ip, sizeof(sin->sin_addr));
312 if (NULL == result)
313 result = ai;
314 else
315 lai->ai_next = ai;
316 lai = ai;
317 }
318 if (cname) {
319 result->ai_canonname = (char *)calloc(1, strlen(cname)+1);
320 if (NULL == result->ai_canonname) {
321 s_freeaddrinfo(result);
322 return EAI_MEMORY;
323 }
324 strcpy(result->ai_canonname, cname);
325 }
326 *res = result;
327 return 0;
328 }
329
330 # ifndef EAI_OVERFLOW
331 # define EAI_OVERFLOW WSAENAMETOOLONG
332 # endif
333
334 static int WSAAPI s_getnameinfo (const struct sockaddr *sa, socklen_t salen,
335 char *host, size_t hostlen,
336 char *serv, size_t servlen,
337 int flags)
338 {
339 struct hostent *he;
340 struct servent *se = NULL;
341 const struct sockaddr_in *sin = (const struct sockaddr_in *)sa;
342
343 if (sin->sin_family != PF_INET)
344 return EAI_FAMILY;
345 if ((NULL == host) && (NULL == serv))
346 return EAI_NONAME;
347 if ((serv) && (servlen > 0)) {
348 if (flags & NI_NUMERICSERV)
349 se = NULL;
350 else
351 if (flags & NI_DGRAM)
352 se = getservbyport(sin->sin_port, "udp");
353 else
354 se = getservbyport(sin->sin_port, "tcp");
355 if (se) {
356 if (servlen <= strlen(se->s_name))
357 return EAI_OVERFLOW;
358 strcpy(serv, se->s_name);
359 }
360 else {
361 char buf[16];
362
363 sprintf(buf, "%d", ntohs(sin->sin_port));
364 if (servlen <= strlen(buf))
365 return EAI_OVERFLOW;
366 strcpy(serv, buf);
367 }
368 }
369 if ((host) && (hostlen > 0)) {
370 if (flags & NI_NUMERICHOST)
371 he = NULL;
372 else
373 he = gethostbyaddr((const char *)&sin->sin_addr, 4, AF_INET);
374 if (he) {
375 if (hostlen < strlen(he->h_name)+1)
376 return EAI_OVERFLOW;
377 strcpy(host, he->h_name);
378 }
379 else {
380 if (flags & NI_NAMEREQD)
381 return EAI_NONAME;
382 if (hostlen < strlen(inet_ntoa(sin->sin_addr))+1)
383 return EAI_OVERFLOW;
384 strcpy(host, inet_ntoa(sin->sin_addr));
385 }
386 }
387 return 0;
388 }
389
390 # if !defined(IPV6_V6ONLY)
391 # define IPV6_V6ONLY 27
392 # endif
393
394 # ifdef _WIN32
395 static HINSTANCE hLib = 0;
396 # else
397 static void *hLib = NULL;
398 # endif
399 static int lib_loaded = 0;
400 static const char* lib_name = "Ws2_32.dll";
401
402
403 typedef int (*_func)();
404
405 static void load_function(const char* function, _func* func_ptr) {
406 # ifdef _WIN32
407 *func_ptr = (_func)GetProcAddress(hLib, function);
408 # else
409 *func_ptr = (_func)dlsym(hLib, function);
410 # endif
411 if (*func_ptr == 0) {
412 sim_printf ("Sockets: Failed to find function '%s' in %s\r\n", function, lib_name);
413 lib_loaded = 3;
414 }
415 }
416
417
418 int load_ws2(void) {
419 switch(lib_loaded) {
420 case 0:
421 # if defined(_WIN32) || defined(__CYGWIN__)
422 hLib = LoadLibraryA(lib_name);
423 # else
424 hLib = dlopen(lib_name, RTLD_NOW);
425 # endif
426 if (hLib == 0) {
427
428 sim_printf ("Sockets: Failed to load %s\r\n", lib_name);
429 lib_loaded = 2;
430 break;
431 } else {
432
433 lib_loaded = 1;
434 }
435
436
437 load_function("getaddrinfo", (_func *) &p_getaddrinfo);
438 load_function("getnameinfo", (_func *) &p_getnameinfo);
439 load_function("freeaddrinfo", (_func *) &p_freeaddrinfo);
440
441 if (lib_loaded != 1) {
442
443 p_getaddrinfo = (getaddrinfo_func)s_getaddrinfo;
444 p_getnameinfo = (getnameinfo_func)s_getnameinfo;
445 p_freeaddrinfo = (freeaddrinfo_func)s_freeaddrinfo;
446 }
447 break;
448 default:
449 break;
450 }
451 return (lib_loaded == 1) ? 1 : 0;
452 }
453 #endif
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488 int sim_parse_addr (const char *cptr, char *host, size_t host_len, const char *default_host, char *port, size_t port_len, const char *default_port, const char *validate_addr)
489 {
490 char gbuf[CBUFSIZE], default_pbuf[CBUFSIZE];
491 const char *hostp;
492 char *portp;
493 char *endc;
494 unsigned long portval;
495
496 if ((host != NULL) && (host_len != 0))
497 memset (host, 0, host_len);
498 if ((port != NULL) && (port_len != 0))
499 memset (port, 0, port_len);
500 if ((cptr == NULL) || (*cptr == 0)) {
501 if (((default_host == NULL) || (*default_host == 0)) || ((default_port == NULL) || (*default_port == 0)))
502 return -1;
503 if ((host == NULL) || (port == NULL))
504 return -1;
505 if ((strlen(default_host) >= host_len) || (strlen(default_port) >= port_len))
506 return -1;
507 strcpy (host, default_host);
508 strcpy (port, default_port);
509 return 0;
510 }
511 memset (default_pbuf, 0, sizeof(default_pbuf));
512 if (default_port)
513 strncpy (default_pbuf, default_port, sizeof(default_pbuf)-1);
514 gbuf[sizeof(gbuf)-1] = '\0';
515 strncpy (gbuf, cptr, sizeof(gbuf)-1);
516 hostp = gbuf;
517 portp = NULL;
518
519 if ((portp = strrchr (gbuf, ':')) &&
520 (NULL == strchr (portp, ']'))) {
521 *portp++ = 0;
522 if (*portp == '\0')
523 portp = default_pbuf;
524 }
525 else {
526 portp = gbuf;
527 hostp = (const char *)default_host;
528 }
529 if (portp != NULL) {
530 portval = strtoul(portp, &endc, 10);
531 if ((*endc == '\0') && ((portval == 0) || (portval > 65535)))
532 return -1;
533 if (*endc != '\0') {
534 struct servent *se = getservbyname(portp, "tcp");
535
536 if (se == NULL)
537 return -1;
538 }
539 }
540 if (port)
541 if (portp != NULL) {
542 if (strlen(portp) >= port_len)
543 return -1;
544 else
545 strcpy (port, portp);
546 }
547 if (hostp != NULL) {
548 if (']' == hostp[strlen(hostp)-1]) {
549 if ('[' != hostp[0])
550 return -1;
551
552 strncpy(gbuf, hostp+1, sizeof(gbuf)-1);
553 gbuf[strlen(gbuf)-1] = '\0';
554 hostp = gbuf;
555 }
556 }
557 if (host) {
558 if (hostp != NULL) {
559 if (strlen(hostp) >= host_len)
560 return -1;
561 else
562 if (('\0' != hostp[0]) || (default_host == NULL))
563 strcpy (host, hostp);
564 else
565 if (strlen(default_host) >= host_len)
566 return -1;
567 else
568 strcpy (host, default_host);
569 }
570 else {
571 if (default_host) {
572 if (strlen(default_host) >= host_len)
573 return -1;
574 else
575 strcpy (host, default_host);
576 }
577 }
578 }
579 if (validate_addr) {
580 struct addrinfo *ai_host, *ai_validate, *ai, *aiv;
581 int status;
582
583 if (hostp == NULL)
584 return -1;
585 if (p_getaddrinfo(hostp, NULL, NULL, &ai_host))
586 return -1;
587 if (p_getaddrinfo(validate_addr, NULL, NULL, &ai_validate)) {
588 p_freeaddrinfo (ai_host);
589 return -1;
590 }
591 status = -1;
592 for (ai = ai_host; ai != NULL; ai = ai->ai_next) {
593 for (aiv = ai_validate; aiv != NULL; aiv = aiv->ai_next) {
594 if ((ai->ai_addrlen == aiv->ai_addrlen) &&
595 (ai->ai_family == aiv->ai_family) &&
596 (0 == memcmp (ai->ai_addr, aiv->ai_addr, ai->ai_addrlen))) {
597 status = 0;
598 break;
599 }
600 }
601 }
602 if (status != 0) {
603
604 if (((0 == strcmp("127.0.0.1", hostp)) &&
605 (0 == strcmp("::1", validate_addr))) ||
606 ((0 == strcmp("127.0.0.1", validate_addr)) &&
607 (0 == strcmp("::1", hostp))))
608 status = 0;
609 }
610 p_freeaddrinfo (ai_host);
611 p_freeaddrinfo (ai_validate);
612 return status;
613 }
614 return 0;
615 }
616
617 #ifdef UNUSED
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652 int sim_parse_addr_ex (const char *cptr, char *host, size_t hostlen, const char *default_host, char *port, size_t port_len, char *localport, size_t localport_len, const char *default_port)
653 {
654 const char *hostp;
655
656 if ((localport != NULL) && (localport_len != 0))
657 memset (localport, 0, localport_len);
658 hostp = strchr (cptr, ':');
659 if ((hostp != NULL) && ((hostp[1] == '[') || (NULL != strchr (hostp+1, ':')))) {
660 if ((localport != NULL) && (localport_len != 0)) {
661 localport_len -= 1;
662 if (localport_len > (size_t)(hostp-cptr))
663 localport_len = (size_t)(hostp-cptr);
664 memcpy (localport, cptr, localport_len);
665 }
666 return sim_parse_addr (hostp+1, host, hostlen, default_host, port, port_len, default_port, NULL);
667 }
668 return sim_parse_addr (cptr, host, hostlen, default_host, port, port_len, default_port, NULL);
669 }
670 #endif
671
672 void sim_init_sock (void)
673 {
674 #if defined (_WIN32)
675 int err;
676 WORD wVersionRequested;
677 WSADATA wsaData;
678 wVersionRequested = MAKEWORD (2, 2);
679
680 err = WSAStartup (wVersionRequested, &wsaData);
681 if (err != 0)
682 sim_printf ("Winsock: startup error %d\n", err);
683 # if defined(AF_INET6)
684 load_ws2 ();
685 # endif
686 #else
687 # if defined(AF_INET6)
688 p_getaddrinfo = (getaddrinfo_func)getaddrinfo;
689 p_getnameinfo = (getnameinfo_func)getnameinfo;
690 p_freeaddrinfo = (freeaddrinfo_func)freeaddrinfo;
691 # else
692
693 p_getaddrinfo = (getaddrinfo_func)s_getaddrinfo;
694 p_getnameinfo = (getnameinfo_func)s_getnameinfo;
695 p_freeaddrinfo = (freeaddrinfo_func)s_freeaddrinfo;
696 # endif
697 #endif
698 #if defined (SIGPIPE)
699 signal (SIGPIPE, SIG_IGN);
700 #endif
701 }
702
703 void sim_cleanup_sock (void)
704 {
705 #if defined (_WIN32)
706 WSACleanup ();
707 #endif
708 }
709
710 #if defined (_WIN32)
711 static int sim_setnonblock (SOCKET sock)
712 {
713 unsigned long non_block = 1;
714
715 return ioctlsocket (sock, FIONBIO, &non_block);
716 }
717
718 #else
719 static int sim_setnonblock (SOCKET sock)
720 {
721 int fl, sta;
722
723 fl = fcntl (sock, F_GETFL,0);
724 if (fl == -1)
725 return SOCKET_ERROR;
726 sta = fcntl (sock, F_SETFL, fl | O_NONBLOCK);
727 if (sta == -1)
728 return SOCKET_ERROR;
729 # if !defined (__HAIKU__)
730 # if !defined (__serenity__)
731 sta = fcntl (sock, F_SETOWN, getpid());
732 if (sta == -1)
733 return SOCKET_ERROR;
734 # endif
735 # endif
736 return 0;
737 }
738 #endif
739
740 static int sim_setnodelay (SOCKET sock)
741 {
742 int nodelay = 1;
743 int sta;
744
745
746 sta = setsockopt (sock, IPPROTO_TCP, TCP_NODELAY, (char *)&nodelay, sizeof(nodelay));
747 if (sta == -1)
748 return SOCKET_ERROR;
749
750 #if defined(TCP_NODELAYACK)
751
752 sta = setsockopt (sock, IPPROTO_TCP, TCP_NODELAYACK, (char *)&nodelay, sizeof(nodelay));
753 if (sta == -1)
754 return SOCKET_ERROR;
755 #endif
756
757 #if defined(TCP_QUICKACK)
758
759 sta = setsockopt (sock, IPPROTO_TCP, TCP_QUICKACK, (char *)&nodelay, sizeof(nodelay));
760 if (sta == -1)
761 return SOCKET_ERROR;
762 #endif
763
764 return sta;
765 }
766
767 static SOCKET sim_create_sock (int af, int opt_flags)
768 {
769 SOCKET newsock;
770 int err;
771
772 newsock = socket (af, ((opt_flags & SIM_SOCK_OPT_DATAGRAM) ? SOCK_DGRAM : SOCK_STREAM), 0);
773 if (newsock == INVALID_SOCKET) {
774 #if defined(WSAEAFNOSUPPORT)
775 err = WSAGetLastError ();
776 if (err == WSAEAFNOSUPPORT)
777 return newsock;
778 #endif
779 return sim_err_sock (newsock, "socket");
780 }
781 return newsock;
782 }
783
784
785
786
787
788
789
790
791 SOCKET sim_master_sock_ex (const char *hostport, int *parse_status, int opt_flags)
792 {
793 SOCKET newsock = INVALID_SOCKET;
794 int sta;
795 char host[CBUFSIZE], port[CBUFSIZE];
796 int r;
797 struct addrinfo hints;
798 struct addrinfo *result = NULL, *preferred;
799
800 r = sim_parse_addr (hostport, host, sizeof(host), NULL, port, sizeof(port), NULL, NULL);
801 if (parse_status)
802 *parse_status = r;
803 if (r)
804 return newsock;
805
806 memset(&hints, 0, sizeof(hints));
807 hints.ai_flags = AI_PASSIVE;
808 hints.ai_family = AF_UNSPEC;
809 hints.ai_protocol = IPPROTO_TCP;
810 hints.ai_socktype = SOCK_STREAM;
811 if (p_getaddrinfo(host[0] ? host : NULL, port[0] ? port : NULL, &hints, &result)) {
812 if (parse_status)
813 *parse_status = -1;
814 return newsock;
815 }
816 preferred = result;
817 #ifdef IPV6_V6ONLY
818
819
820
821
822 for (; preferred != NULL; preferred = preferred->ai_next) {
823 if (preferred->ai_family == AF_INET6)
824 break;
825 }
826 if (preferred == NULL)
827 preferred = result;
828 #endif
829 retry:
830 if (preferred != NULL)
831 newsock = sim_create_sock (preferred->ai_family, 0);
832 if (newsock == INVALID_SOCKET) {
833 #ifndef IPV6_V6ONLY
834 if (preferred->ai_next) {
835 preferred = preferred->ai_next;
836 goto retry;
837 }
838 #else
839 if (preferred != NULL)
840 if ((preferred->ai_family == AF_INET6) &&
841 (preferred != result)) {
842 preferred = result;
843 goto retry;
844 }
845 #endif
846 p_freeaddrinfo(result);
847 return newsock;
848 }
849 #ifdef IPV6_V6ONLY
850 if (preferred->ai_family == AF_INET6) {
851 int off = 0;
852 sta = setsockopt (newsock, IPPROTO_IPV6, IPV6_V6ONLY, (char *)&off, sizeof(off));
853 }
854 #endif
855 if (opt_flags & SIM_SOCK_OPT_REUSEADDR) {
856 int on = 1;
857
858 sta = setsockopt (newsock, SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof(on));
859 }
860 #if defined (SO_EXCLUSIVEADDRUSE)
861 else {
862 int on = 1;
863
864 sta = setsockopt (newsock, SOL_SOCKET, SO_EXCLUSIVEADDRUSE, (char *)&on, sizeof(on));
865 }
866 #endif
867 sta = bind (newsock, preferred->ai_addr, preferred->ai_addrlen);
868 p_freeaddrinfo(result);
869 if (sta == SOCKET_ERROR)
870 return sim_err_sock (newsock, "bind");
871 if (!(opt_flags & SIM_SOCK_OPT_BLOCKING)) {
872 sta = sim_setnonblock (newsock);
873 if (sta == SOCKET_ERROR)
874 return sim_err_sock (newsock, "setnonblock");
875 }
876 sta = listen (newsock, 1);
877 if (sta == SOCKET_ERROR)
878 return sim_err_sock (newsock, "listen");
879 return newsock;
880 }
881
882 SOCKET sim_connect_sock_ex (const char *sourcehostport, const char *hostport, const char *default_host, const char *default_port, int opt_flags)
883 {
884 SOCKET newsock = INVALID_SOCKET;
885 int sta;
886 char host[CBUFSIZE], port[CBUFSIZE];
887 struct addrinfo hints;
888 struct addrinfo *result = NULL, *source = NULL;
889
890 if (sim_parse_addr (hostport, host, sizeof(host), default_host, port, sizeof(port), default_port, NULL))
891 return INVALID_SOCKET;
892
893 memset(&hints, 0, sizeof(hints));
894 hints.ai_family = AF_UNSPEC;
895 hints.ai_protocol = ((opt_flags & SIM_SOCK_OPT_DATAGRAM) ? IPPROTO_UDP : IPPROTO_TCP);
896 hints.ai_socktype = ((opt_flags & SIM_SOCK_OPT_DATAGRAM) ? SOCK_DGRAM : SOCK_STREAM);
897 if (p_getaddrinfo(host[0] ? host : NULL, port[0] ? port : NULL, &hints, &result))
898 return INVALID_SOCKET;
899
900 if (sourcehostport) {
901
902
903 if (sim_parse_addr (sourcehostport, host, sizeof(host), NULL, port, sizeof(port), NULL, NULL)) {
904 p_freeaddrinfo (result);
905 return INVALID_SOCKET;
906 }
907
908 memset(&hints, 0, sizeof(hints));
909 hints.ai_flags = AI_PASSIVE;
910 hints.ai_family = result->ai_family;
911 hints.ai_protocol = ((opt_flags & SIM_SOCK_OPT_DATAGRAM) ? IPPROTO_UDP : IPPROTO_TCP);
912 hints.ai_socktype = ((opt_flags & SIM_SOCK_OPT_DATAGRAM) ? SOCK_DGRAM : SOCK_STREAM);
913 if (p_getaddrinfo(host[0] ? host : NULL, port[0] ? port : NULL, &hints, &source)) {
914 p_freeaddrinfo (result);
915 return INVALID_SOCKET;
916 }
917
918 newsock = sim_create_sock (result->ai_family, opt_flags & SIM_SOCK_OPT_DATAGRAM);
919 if (newsock == INVALID_SOCKET) {
920 p_freeaddrinfo (result);
921 p_freeaddrinfo (source);
922 return newsock;
923 }
924
925 sta = bind (newsock, source->ai_addr, source->ai_addrlen);
926 p_freeaddrinfo(source);
927 source = NULL;
928 if (sta == SOCKET_ERROR) {
929 p_freeaddrinfo (result);
930 return sim_err_sock (newsock, "bind");
931 }
932 }
933
934 if (newsock == INVALID_SOCKET) {
935 newsock = sim_create_sock (result->ai_family, opt_flags & SIM_SOCK_OPT_DATAGRAM);
936 if (newsock == INVALID_SOCKET) {
937 p_freeaddrinfo (result);
938 return newsock;
939 }
940 }
941
942 if (!(opt_flags & SIM_SOCK_OPT_BLOCKING)) {
943 sta = sim_setnonblock (newsock);
944 if (sta == SOCKET_ERROR) {
945 p_freeaddrinfo (result);
946 return sim_err_sock (newsock, "setnonblock");
947 }
948 }
949 if ((!(opt_flags & SIM_SOCK_OPT_DATAGRAM)) && (opt_flags & SIM_SOCK_OPT_NODELAY)) {
950 sta = sim_setnodelay (newsock);
951 if (sta == SOCKET_ERROR) {
952 p_freeaddrinfo (result);
953 return sim_err_sock (newsock, "setnodelay");
954 }
955 }
956 if (!(opt_flags & SIM_SOCK_OPT_DATAGRAM)) {
957 int keepalive = 1;
958
959
960 sta = setsockopt (newsock, SOL_SOCKET, SO_KEEPALIVE, (char *)&keepalive, sizeof(keepalive));
961 if (sta == -1)
962 return sim_err_sock (newsock, "setsockopt KEEPALIVE");
963 }
964 if (!(opt_flags & SIM_SOCK_OPT_BLOCKING)) {
965 sta = sim_setnonblock (newsock);
966 if (sta == SOCKET_ERROR)
967 return sim_err_sock (newsock, "setnonblock");
968 }
969 sta = connect (newsock, result->ai_addr, result->ai_addrlen);
970 p_freeaddrinfo (result);
971 if (sta == SOCKET_ERROR) {
972 if (opt_flags & SIM_SOCK_OPT_BLOCKING) {
973 if ((WSAGetLastError () == WSAETIMEDOUT) ||
974 (WSAGetLastError () == WSAEHOSTUNREACH) ||
975 (WSAGetLastError () == WSAECONNREFUSED) ||
976 (WSAGetLastError () == WSAECONNABORTED) ||
977 (WSAGetLastError () == WSAECONNRESET)) {
978 sim_close_sock (newsock);
979 newsock = INVALID_SOCKET;
980 }
981 else
982 return sim_err_sock (newsock, "connect");
983 }
984 else
985 if ((WSAGetLastError () != WSAEWOULDBLOCK) &&
986 (WSAGetLastError () != WSAEINPROGRESS))
987 return sim_err_sock (newsock, "connect");
988 }
989 return newsock;
990 }
991
992 SOCKET sim_accept_conn_ex (SOCKET master, char **connectaddr, int opt_flags)
993 {
994 int sta = 0, err;
995 int keepalive = 1;
996 #ifdef _WIN32
997 int size;
998 #else
999 socklen_t size;
1000 #endif
1001 SOCKET newsock;
1002 struct sockaddr_storage clientname;
1003
1004 if (master == 0)
1005 return INVALID_SOCKET;
1006 size = sizeof (clientname);
1007 memset (&clientname, 0, sizeof(clientname));
1008 newsock = accept (master, (struct sockaddr *) &clientname, &size);
1009 if (newsock == INVALID_SOCKET) {
1010 err = WSAGetLastError ();
1011 if (err != WSAEWOULDBLOCK)
1012 sim_err_sock(newsock, "accept");
1013 return INVALID_SOCKET;
1014 }
1015 if (connectaddr != NULL) {
1016 *connectaddr = (char *)calloc(1, NI_MAXHOST+1);
1017 #ifdef AF_INET6
1018 p_getnameinfo((struct sockaddr *)&clientname, size, *connectaddr, NI_MAXHOST, NULL, 0, NI_NUMERICHOST);
1019 if (*connectaddr)
1020 if (0 == memcmp("::ffff:", *connectaddr, 7))
1021 memmove(*connectaddr, 7+*connectaddr,
1022 strlen(*connectaddr) - 7 + 1);
1023 #else
1024 strcpy(*connectaddr, inet_ntoa(((struct sockaddr_in *)&connectaddr)->s_addr));
1025 #endif
1026 }
1027
1028 if (!(opt_flags & SIM_SOCK_OPT_BLOCKING)) {
1029 sta = sim_setnonblock (newsock);
1030 if (sta == SOCKET_ERROR)
1031 return sim_err_sock (newsock, "setnonblock");
1032 }
1033
1034 if ((opt_flags & SIM_SOCK_OPT_NODELAY)) {
1035 sta = sim_setnodelay (newsock);
1036 if (sta == SOCKET_ERROR)
1037 return sim_err_sock (newsock, "setnodelay");
1038 }
1039
1040
1041 sta = setsockopt (newsock, SOL_SOCKET, SO_KEEPALIVE, (char *)&keepalive, sizeof(keepalive));
1042 if (sta == -1)
1043 return sim_err_sock (newsock, "setsockopt KEEPALIVE");
1044
1045 return newsock;
1046 }
1047
1048 int sim_check_conn (SOCKET sock, int rd)
1049 {
1050 fd_set rw_set, er_set;
1051 fd_set *rw_p = &rw_set;
1052 fd_set *er_p = &er_set;
1053 struct timeval zero;
1054 struct sockaddr_storage peername;
1055 #ifdef _WIN32
1056 int peernamesize = (int)sizeof(peername);
1057 #else
1058 socklen_t peernamesize = (socklen_t)sizeof(peername);
1059 #endif
1060
1061 memset (&zero, 0, sizeof(zero));
1062 FD_ZERO (rw_p);
1063 FD_ZERO (er_p);
1064 FD_SET (sock, rw_p);
1065 FD_SET (sock, er_p);
1066 if (rd)
1067 select ((int) sock + 1, rw_p, NULL, er_p, &zero);
1068 else
1069 select ((int) sock + 1, NULL, rw_p, er_p, &zero);
1070 if (FD_ISSET (sock, er_p))
1071 return -1;
1072 if (FD_ISSET (sock, rw_p)) {
1073 if (0 == getpeername (sock, (struct sockaddr *)&peername, &peernamesize))
1074 return 1;
1075 else
1076 return -1;
1077 }
1078 return 0;
1079 }
1080
1081 static int _sim_getaddrname (struct sockaddr *addr, size_t addrsize, char *hostnamebuf, char *portnamebuf)
1082 {
1083 int ret = 0;
1084
1085 #ifdef AF_INET6
1086 # ifdef _WIN32
1087 int size = (int)addrsize;
1088 # else
1089 socklen_t size = (socklen_t)addrsize;
1090 # endif
1091 *hostnamebuf = '\0';
1092 *portnamebuf = '\0';
1093 ret = p_getnameinfo(addr, size, hostnamebuf, NI_MAXHOST, NULL, 0, NI_NUMERICHOST);
1094 if (0 == memcmp("::ffff:", hostnamebuf, 7))
1095 memmove(hostnamebuf, 7+hostnamebuf,
1096 strlen(hostnamebuf) + 7 - 1);
1097 if (!ret)
1098 ret = p_getnameinfo(addr, size, NULL, 0, portnamebuf, NI_MAXSERV, NI_NUMERICSERV);
1099 #else
1100 strcpy(hostnamebuf, inet_ntoa(((struct sockaddr_in *)addr)->s_addr));
1101 sprintf(portnamebuf, "%d", (int)ntohs(((struct sockaddr_in *)addr)->s_port));
1102 #endif
1103 return ret;
1104 }
1105
1106 int sim_getnames_sock (SOCKET sock, char **socknamebuf, char **peernamebuf)
1107 {
1108 struct sockaddr_storage sockname, peername;
1109 #ifdef _WIN32
1110 int socknamesize = (int)sizeof(sockname);
1111 int peernamesize = (int)sizeof(peername);
1112 #else
1113 socklen_t socknamesize = (socklen_t)sizeof(sockname);
1114 socklen_t peernamesize = (socklen_t)sizeof(peername);
1115 #endif
1116 char hostbuf[NI_MAXHOST+1];
1117 char portbuf[NI_MAXSERV+1];
1118
1119 if (socknamebuf)
1120 *socknamebuf = (char *)calloc(1, NI_MAXHOST+NI_MAXSERV+4);
1121 if (peernamebuf)
1122 *peernamebuf = (char *)calloc(1, NI_MAXHOST+NI_MAXSERV+4);
1123 getsockname (sock, (struct sockaddr *)&sockname, &socknamesize);
1124 getpeername (sock, (struct sockaddr *)&peername, &peernamesize);
1125 if (socknamebuf != NULL) {
1126 _sim_getaddrname ((struct sockaddr *)&sockname, (size_t)socknamesize, hostbuf, portbuf);
1127 sprintf(*socknamebuf, "[%s]:%s", hostbuf, portbuf);
1128 }
1129 if (peernamebuf != NULL) {
1130 _sim_getaddrname ((struct sockaddr *)&peername, (size_t)peernamesize, hostbuf, portbuf);
1131 sprintf(*peernamebuf, "[%s]:%s", hostbuf, portbuf);
1132 }
1133 return 0;
1134 }
1135
1136 int sim_read_sock (SOCKET sock, char *buf, int nbytes)
1137 {
1138 int rbytes, err;
1139
1140 rbytes = recv (sock, buf, nbytes, 0);
1141 if (rbytes == 0)
1142 return -1;
1143 if (rbytes == SOCKET_ERROR) {
1144 err = WSAGetLastError ();
1145 if (err == WSAEWOULDBLOCK)
1146 return 0;
1147 #if defined(EAGAIN)
1148 if (err == EAGAIN)
1149 return 0;
1150 #endif
1151 if ((err != WSAETIMEDOUT) &&
1152 (err != WSAEHOSTUNREACH) &&
1153 (err != WSAECONNREFUSED) &&
1154 (err != WSAECONNABORTED) &&
1155 (err != WSAECONNRESET) &&
1156 (err != WSAEINTR))
1157 sim_err_sock (INVALID_SOCKET, "read");
1158 return -1;
1159 }
1160 return rbytes;
1161 }
1162
1163 int sim_write_sock (SOCKET sock, const char *msg, int nbytes)
1164 {
1165 int err, sbytes = send (sock, msg, nbytes, 0);
1166
1167 if (sbytes == SOCKET_ERROR) {
1168 err = WSAGetLastError ();
1169 if (err == WSAEWOULDBLOCK)
1170 return 0;
1171 #if defined(EAGAIN)
1172 if (err == EAGAIN)
1173 return 0;
1174 #endif
1175 }
1176 return sbytes;
1177 }
1178
1179 void sim_close_sock (SOCKET sock)
1180 {
1181 shutdown(sock, SD_BOTH);
1182 closesocket (sock);
1183 }
1184