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