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