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