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