5 Author: Pekka Riikonen <priikone@silcnet.org>
7 Copyright (C) 1997 - 2007 Pekka Riikonen
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; version 2 of the License.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
23 /************************** Types and definitions ***************************/
26 #define SIZEOF_SOCKADDR(so) ((so).sa.sa_family == AF_INET6 ? \
27 sizeof(so.sin6) : sizeof(so.sin))
29 #define SIZEOF_SOCKADDR(so) (sizeof(so.sin))
34 struct sockaddr_in sin;
36 struct sockaddr_in6 sin6;
41 /************************ Static utility functions **************************/
43 static SilcBool silc_net_set_sockaddr(SilcSockaddr *addr, const char *ip_addr,
48 memset(addr, 0, sizeof(*addr));
50 /* Check for IPv4 and IPv6 addresses */
52 if (!silc_net_is_ip(ip_addr)) {
53 SILC_LOG_ERROR(("%s is not IP address", ip_addr));
54 silc_set_errno_reason(SILC_ERR_BAD_IP, "%s is not an IP address",
59 if (silc_net_is_ip4(ip_addr)) {
61 len = sizeof(addr->sin.sin_addr);
62 if (!silc_net_addr2bin(ip_addr,
63 (unsigned char *)&addr->sin.sin_addr.s_addr,
66 addr->sin.sin_family = AF_INET;
67 addr->sin.sin_port = port ? htons(port) : 0;
71 len = sizeof(addr->sin6.sin6_addr);
72 if (!silc_net_addr2bin(ip_addr,
73 (unsigned char *)&addr->sin6.sin6_addr, len))
75 addr->sin6.sin6_family = AF_INET6;
76 addr->sin6.sin6_port = port ? htons(port) : 0;
78 SILC_LOG_ERROR(("Operating System does not support IPv6"));
84 addr->sin.sin_family = AF_INET;
85 addr->sin.sin_addr.s_addr = INADDR_ANY;
87 addr->sin.sin_port = htons(port);
94 /****************************** TCP Listener ********************************/
96 /* Deliver new stream to upper layer */
98 static void silc_net_accept_stream(SilcResult status,
99 SilcStream stream, void *context)
101 SilcNetListener listener = context;
103 if (status != SILC_OK)
106 listener->callback(SILC_OK, stream, listener->context);
109 /* Accept incoming connection and notify upper layer */
111 SILC_TASK_CALLBACK(silc_net_accept)
113 SilcNetListener listener = context;
116 SILC_LOG_DEBUG(("Accepting new connection"));
118 sock = silc_net_accept_connection(fd);
119 if (sock == INVALID_SOCKET)
122 /* Set socket options */
123 silc_net_set_socket_opt(sock, SOL_SOCKET, SO_REUSEADDR, 1);
125 /* Create socket stream */
126 silc_socket_tcp_stream_create(sock, listener->lookup,
127 listener->require_fqdn, schedule,
128 silc_net_accept_stream, listener);
131 /* Create TCP network listener */
134 silc_net_tcp_create_listener(const char **local_ip_addr,
135 SilcUInt32 local_ip_count, int port,
136 SilcBool lookup, SilcBool require_fqdn,
137 SilcSchedule schedule,
138 SilcNetCallback callback, void *context)
140 SilcNetListener listener = NULL;
144 const char *ipany = "0.0.0.0";
146 SILC_LOG_DEBUG(("Creating TCP listener"));
148 if (port < 0 || !schedule || !callback) {
149 silc_set_errno(SILC_ERR_INVALID_ARGUMENT);
153 listener = silc_calloc(1, sizeof(*listener));
156 listener->schedule = schedule;
157 listener->callback = callback;
158 listener->context = context;
159 listener->require_fqdn = require_fqdn;
160 listener->lookup = lookup;
162 if (local_ip_count > 0) {
163 listener->socks = silc_calloc(local_ip_count, sizeof(*listener->socks));
164 if (!listener->socks)
167 listener->socks = silc_calloc(1, sizeof(*listener->socks));
168 if (!listener->socks)
174 /* Bind to local addresses */
175 for (i = 0; i < local_ip_count; i++) {
176 SILC_LOG_DEBUG(("Binding to local address %s",
177 local_ip_addr ? local_ip_addr[i] : ipany));
179 /* Set sockaddr for server */
180 if (!silc_net_set_sockaddr(&server,
181 local_ip_addr ? local_ip_addr[i] : ipany,
185 /* Create the socket */
186 sock = socket(server.sin.sin_family, SOCK_STREAM, 0);
187 if (sock == INVALID_SOCKET) {
188 silc_set_errno_posix(WSAGetLastError());
189 SILC_LOG_ERROR(("Cannot create socket, error %s",
190 silc_errno_string(silc_errno)));
194 /* Set the socket options */
195 rval = silc_net_set_socket_opt(sock, SOL_SOCKET, SO_REUSEADDR, 1);
196 if (rval == SOCKET_ERROR) {
197 SILC_LOG_ERROR(("Cannot set socket options, error %s",
198 silc_errno_string(silc_errno)));
203 /* Bind the listener socket */
204 rval = bind(sock, &server.sa, SIZEOF_SOCKADDR(server));
205 if (rval == SOCKET_ERROR) {
206 silc_set_errno_posix(WSAGetLastError());
207 SILC_LOG_ERROR(("Cannot bind socket, error %s",
208 silc_errno_string(silc_errno)));
213 /* Specify that we are listenning */
214 rval = listen(sock, SOMAXCONN);
215 if (rval == SOCKET_ERROR) {
216 silc_set_errno_posix(WSAGetLastError());
217 SILC_LOG_ERROR(("Cannot set socket listenning, error %s",
218 silc_errno_string(silc_errno)));
223 /* Schedule for incoming connections */
224 silc_schedule_task_add_fd(schedule, sock, silc_net_accept, listener);
226 SILC_LOG_DEBUG(("TCP listener created, fd=%d", sock));
227 listener->socks[i] = sock;
228 listener->socks_count++;
235 silc_net_close_listener(listener);
239 /* Create TCP network, multiple ports */
242 silc_net_tcp_create_listener2(const char *local_ip_addr, int *ports,
243 SilcUInt32 port_count,
244 SilcBool ignore_port_error,
245 SilcBool lookup, SilcBool require_fqdn,
246 SilcSchedule schedule,
247 SilcNetCallback callback, void *context)
249 SilcNetListener listener = NULL;
253 const char *ipany = "0.0.0.0";
255 SILC_LOG_DEBUG(("Creating TCP listener"));
257 if (!schedule || !callback) {
258 silc_set_errno(SILC_ERR_INVALID_ARGUMENT);
262 listener = silc_calloc(1, sizeof(*listener));
265 listener->schedule = schedule;
266 listener->callback = callback;
267 listener->context = context;
268 listener->require_fqdn = require_fqdn;
269 listener->lookup = lookup;
271 if (port_count > 0) {
272 listener->socks = silc_calloc(port_count, sizeof(*listener->socks));
273 if (!listener->socks)
276 listener->socks = silc_calloc(1, sizeof(*listener->socks));
277 if (!listener->socks)
283 /* Bind to local addresses */
284 for (i = 0; i < local_ip_count; i++) {
285 SILC_LOG_DEBUG(("Binding to local address %s:%d",
286 local_ip_addr ? local_ip_addr : ipany,
287 ports ? ports[i] : 0));
289 /* Set sockaddr for server */
290 if (!silc_net_set_sockaddr(&server,
291 local_ip_addr ? local_ip_addr : ipany,
292 ports ? ports[i] : 0)) {
293 if (ignore_port_error)
298 /* Create the socket */
299 sock = socket(server.sin.sin_family, SOCK_STREAM, 0);
300 if (sock == INVALID_SOCKET) {
301 if (ignore_port_error)
303 silc_set_errno_posix(WSAGetLastError());
304 SILC_LOG_ERROR(("Cannot create socket, error %s",
305 silc_errno_string(silc_errno)));
309 /* Set the socket options */
310 rval = silc_net_set_socket_opt(sock, SOL_SOCKET, SO_REUSEADDR, 1);
311 if (rval == SOCKET_ERROR) {
313 if (ignore_port_error)
315 SILC_LOG_ERROR(("Cannot set socket options, error %s",
316 silc_errno_string(silc_errno)));
320 /* Bind the listener socket */
321 rval = bind(sock, &server.sa, SIZEOF_SOCKADDR(server));
322 if (rval == SOCKET_ERROR) {
324 if (ignore_port_error)
326 silc_set_errno_posix(WSAGetLastError());
327 SILC_LOG_ERROR(("Cannot bind socket, error %s",
328 silc_errno_string(silc_errno)));
332 /* Specify that we are listenning */
333 rval = listen(sock, SOMAXCONN);
334 if (rval == SOCKET_ERROR) {
336 if (ignore_port_error)
338 silc_set_errno_posix(WSAGetLastError());
339 SILC_LOG_ERROR(("Cannot set socket listenning, error %s",
340 silc_errno_string(silc_errno)));
344 /* Schedule for incoming connections */
345 silc_schedule_task_add_fd(schedule, sock, silc_net_accept, listener);
347 SILC_LOG_DEBUG(("TCP listener created, fd=%d", sock));
348 listener->socks[i] = sock;
349 listener->socks_count++;
352 if (ignore_port_error && !listener->socks_count)
359 silc_net_close_listener(listener);
363 /* Close network listener */
365 void silc_net_close_listener(SilcNetListener listener)
369 SILC_LOG_DEBUG(("Closing network listener"));
374 for (i = 0; i < listener->socks_count; i++) {
375 silc_schedule_task_del_by_fd(listener->schedule, listener->socks[i]);
376 shutdown(listener->socks[i], 2);
377 closesocket(listener->socks[i]);
380 silc_free(listener->socks);
384 /******************************* UDP Stream *********************************/
386 /* Create UDP stream */
389 silc_net_udp_connect(const char *local_ip_addr, int local_port,
390 const char *remote_ip_addr, int remote_port,
391 SilcSchedule schedule)
397 const char *ipany = "0.0.0.0";
399 SILC_LOG_DEBUG(("Creating UDP stream"));
404 /* Bind to local addresses */
405 SILC_LOG_DEBUG(("Binding to local address %s",
406 local_ip_addr ? local_ip_addr : ipany));
408 /* Set sockaddr for server */
409 if (!silc_net_set_sockaddr(&server, local_ip_addr ? local_ip_addr : ipany,
413 /* Create the socket */
414 sock = socket(server.sin.sin_family, SOCK_DGRAM, 0);
415 if (sock == INVALID_SOCKET) {
416 SILC_LOG_ERROR(("Cannot create socket"));
417 silc_set_errno_posix(WSAGetLastError());
421 /* Set the socket options */
422 rval = silc_net_set_socket_opt(sock, SOL_SOCKET, SO_REUSEADDR, 1);
423 if (rval == SOCKET_ERROR) {
424 SILC_LOG_ERROR(("Cannot set socket options"));
428 rval = silc_net_set_socket_opt(sock, SOL_SOCKET, SO_REUSEPORT, 1);
429 if (rval == SOCKET_ERROR) {
430 SILC_LOG_ERROR(("Cannot set socket options"));
433 #endif /* SO_REUSEPORT */
435 /* Bind the listener socket */
436 rval = bind(sock, &server.sa, SIZEOF_SOCKADDR(server));
437 if (rval == SOCKET_ERROR) {
438 SILC_LOG_DEBUG(("Cannot bind socket"));
439 silc_set_errno_posix(WSAGetLastError());
443 /* Set to connected state if remote address is provided. */
444 if (remote_ip_addr && remote_port) {
445 if (!silc_net_set_sockaddr(&server, remote_ip_addr, remote_port))
448 rval = connect(sock, &server.sa, SIZEOF_SOCKADDR(server));
449 if (rval == SOCKET_ERROR) {
450 SILC_LOG_DEBUG(("Cannot connect UDP stream"));
451 silc_set_errno_posix(WSAGetLastError());
456 /* Encapsulate into socket stream */
458 silc_socket_udp_stream_create(sock, local_ip_addr ?
459 silc_net_is_ip6(local_ip_addr) : FALSE,
460 remote_ip_addr ? TRUE : FALSE, schedule);
464 SILC_LOG_DEBUG(("UDP stream created, fd=%d", sock));
473 /* Receive UDP packet */
475 int silc_net_udp_receive(SilcStream stream, char *remote_ip_addr,
476 SilcUInt32 remote_ip_addr_size, int *remote_port,
477 unsigned char *ret_data, SilcUInt32 data_size)
479 SilcSocketStream sock = stream;
481 struct sockaddr *from;
484 SILC_LOG_DEBUG(("Reading data from UDP socket %d", sock->sock));
486 if (remote_ip_addr && remote_port) {
489 from = (struct sockaddr *)&s.sin6;
490 flen = sizeof(s.sin6);
491 #endif /* HAVE_IPV6 */
493 from = (struct sockaddr *)&s.sin;
494 flen = sizeof(s.sin);
496 len = recvfrom(sock->sock, ret_data, data_size, 0, from, &flen);
498 len = recv(sock->sock, ret_data, data_size, 0);
500 if (len == SOCKET_ERROR) {
501 err = WSAGetLastError();
502 silc_set_errno_posix(err);
503 if (err == WSAEWOULDBLOCK) {
504 SILC_LOG_DEBUG(("Could not read immediately, will do it later"));
505 silc_schedule_set_listen_fd(sock->schedule, sock->sock,
506 SILC_TASK_READ, FALSE);
509 SILC_LOG_DEBUG(("Cannot read from UDP socket: %d: %s", sock->sock,
510 silc_errno_string(silc_errno)));
511 silc_schedule_unset_listen_fd(sock->schedule, sock->sock);
515 SILC_LOG_DEBUG(("Read %d bytes", len));
518 silc_schedule_unset_listen_fd(sock->schedule, sock->sock);
520 /* Return remote address */
521 if (remote_ip_addr && remote_port) {
524 *remote_port = ntohs(s.sin6.sin6_port);
525 inet_ntop(AF_INET6, &s.sin6.sin6_addr, remote_ip_addr,
526 remote_ip_addr_size);
527 #endif /* HAVE_IPV6 */
529 const char *ip = inet_ntoa(s.sin.sin_addr);
531 silc_snprintf(remote_ip_addr, remote_ip_addr_size, ip);
532 *remote_port = ntohs(s.sin.sin_port);
535 SILC_LOG_DEBUG(("UDP packet from %s:%d", remote_ip_addr, *remote_port));
541 /* Send UDP packet */
543 int silc_net_udp_send(SilcStream stream,
544 const char *remote_ip_addr, int remote_port,
545 const unsigned char *data, SilcUInt32 data_len)
547 SilcSocketStream sock = stream;
551 SILC_LOG_DEBUG(("Sending data to UDP socket %d", sock->sock));
554 if (!silc_net_set_sockaddr(&remote, remote_ip_addr, remote_port))
558 ret = sendto(sock->sock, data, data_len, 0, &remote.sa,
559 SIZEOF_SOCKADDR(remote));
560 if (ret == SOCKET_ERROR) {
561 err = WSAGetLastError();
562 silc_set_errno_posix(err);
563 if (err == WSAEWOULDBLOCK) {
564 SILC_LOG_DEBUG(("Could not send immediately, will do it later"));
565 silc_schedule_set_listen_fd(sock->schedule, sock->sock,
566 SILC_TASK_READ | SILC_TASK_WRITE, FALSE);
569 SILC_LOG_DEBUG(("Cannot send to UDP socket: %s",
570 silc_errno_string(silc_errno)));
571 silc_schedule_unset_listen_fd(sock->schedule, sock->sock);
575 SILC_LOG_DEBUG(("Sent data %d bytes", ret));
576 if (silc_schedule_get_fd_events(sock->schedule, sock->sock) &
578 silc_schedule_set_listen_fd(sock->schedule, sock->sock,
579 SILC_TASK_READ, FALSE);
585 /******************************* TCP Stream *********************************/
591 SilcFSMThreadStruct thread;
592 SilcAsyncOperation op;
593 SilcAsyncOperation sop;
598 SilcNetCallback callback;
600 unsigned int port : 24;
601 unsigned int retry : 7;
602 unsigned int aborted : 1;
605 SILC_FSM_STATE(silc_net_connect_st_start);
606 SILC_FSM_STATE(silc_net_connect_st_stream);
607 SILC_FSM_STATE(silc_net_connect_st_finish);
609 static void silc_net_connect_wait_stream(SilcResult status,
610 SilcStream stream, void *context)
612 SilcNetConnect conn = context;
614 conn->status = status;
615 conn->stream = stream;
616 SILC_FSM_CALL_CONTINUE(&conn->thread);
619 /* Start connecting. Create a real thread where we connect. */
621 SILC_FSM_STATE(silc_net_connect_st_thread)
623 SilcNetConnect conn = fsm_context;
625 /* Connect in real thread so as to not block the application. */
626 silc_fsm_thread_init(&conn->thread, fsm, conn, NULL, NULL, TRUE);
627 silc_fsm_start(&conn->thread, silc_net_connect_st_start);
629 /* Wait for the thread to finish */
630 silc_fsm_next(fsm, silc_net_connect_st_finish);
631 SILC_FSM_THREAD_WAIT(&conn->thread);
634 /* Connecting thread */
636 SILC_FSM_STATE(silc_net_connect_st_start)
638 SilcNetConnect conn = fsm_context;
641 SilcSockaddr desthost;
642 SilcBool prefer_ipv6 = TRUE;
645 return SILC_FSM_FINISH;
649 if (!silc_net_gethostbyname(conn->remote, prefer_ipv6,
650 conn->ip_addr, sizeof(conn->ip_addr))) {
651 SILC_LOG_ERROR(("Network (%s) unreachable: could not resolve the "
652 "host, error %d", conn->remote, WSAGetLastError()));
654 /** Network unreachable */
655 conn->status = SILC_ERR_UNREACHABLE;
656 return SILC_FSM_FINISH;
659 /* Set sockaddr for this connection */
660 if (!silc_net_set_sockaddr(&desthost, conn->ip_addr, conn->port))
661 return SILC_FSM_FINISH;
663 /* Create the connection socket */
664 sock = socket(desthost.sin.sin_family, SOCK_STREAM, 0);
665 if (sock == INVALID_SOCKET) {
666 /* If address is IPv6, then fallback to IPv4 and see whether we can do
667 better with that on socket creation. */
668 if (prefer_ipv6 && silc_net_is_ip6(conn->ip_addr)) {
673 /** Cannot create socket */
674 silc_set_errno_posix(err);
675 SILC_LOG_ERROR(("Cannot create socket, error %d",
676 silc_errno_string(silc_errno)));
677 return SILC_FSM_FINISH;
680 /* Bind to the local address if provided */
681 if (conn->local_ip) {
684 /* Set sockaddr for local listener, and try to bind it. */
685 if (silc_net_set_sockaddr(&local, conn->local_ip, 0))
686 bind(sock, &local.sa, SIZEOF_SOCKADDR(local));
689 /* Connect to the host */
690 rval = connect(sock, &desthost.sa, SIZEOF_SOCKADDR(desthost));
691 err = WSAGetLastError();
692 if (rval == SOCKET_ERROR) {
693 if (err != WSAEWOULDBLOCK) {
697 /* Retry using an IPv4 address, if IPv6 didn't work */
698 if (prefer_ipv6 && silc_net_is_ip6(conn->ip_addr)) {
704 silc_set_errno_posix(err);
705 conn->status = silc_errno;
707 SILC_LOG_ERROR(("Cannot connect to remote host: %s",
708 silc_errno_string(silc_errno)));
709 return SILC_FSM_FINISH;
713 /* Set the socket to non-blocking mode */
714 silc_net_set_socket_nonblock(sock);
716 /* Set appropriate options */
717 #if defined(TCP_NODELAY)
718 silc_net_set_socket_opt(sock, IPPROTO_TCP, TCP_NODELAY, 1);
720 silc_net_set_socket_opt(sock, SOL_SOCKET, SO_KEEPALIVE, 1);
722 SILC_LOG_DEBUG(("TCP connection established"));
726 /** Connection created */
727 silc_fsm_next(fsm, silc_net_connect_st_stream);
728 SILC_FSM_CALL((conn->sop = silc_socket_tcp_stream_create(
729 conn->sock, TRUE, FALSE,
730 silc_fsm_get_schedule(&conn->fsm),
731 silc_net_connect_wait_stream, conn)));
734 /* TCP socket stream created */
736 SILC_FSM_STATE(silc_net_connect_st_stream)
738 SilcNetConnect conn = fsm_context;
741 return SILC_FSM_FINISH;
743 if (conn->status != SILC_OK) {
744 /** Stream creation failed */
745 return SILC_FSM_FINISH;
748 /** Stream created successfully */
749 SILC_LOG_DEBUG(("Connected successfully, sock %d", conn->sock));
750 conn->status = SILC_OK;
751 return SILC_FSM_FINISH;
754 SILC_FSM_STATE(silc_net_connect_st_finish)
756 SilcNetConnect conn = fsm_context;
758 /* Deliver error or new stream */
759 if (!conn->aborted) {
760 conn->callback(conn->status, conn->stream, conn->context);
762 silc_async_free(conn->op);
765 return SILC_FSM_FINISH;
768 static void silc_net_connect_abort(SilcAsyncOperation op, void *context)
770 SilcNetConnect conn = context;
771 conn->aborted = TRUE;
773 /* Abort underlaying stream creation too */
775 silc_async_abort(conn->sop, NULL, NULL);
780 static void silc_net_connect_destructor(SilcFSM fsm, void *fsm_context,
781 void *destructor_context)
783 SilcNetConnect conn = fsm_context;
784 silc_free(conn->local_ip);
785 silc_free(conn->remote);
789 /* Create asynchronous TCP/IP connection. */
791 SilcAsyncOperation silc_net_tcp_connect(const char *local_ip_addr,
792 const char *remote_ip_addr,
794 SilcSchedule schedule,
795 SilcNetCallback callback,
800 if (!remote_ip_addr || remote_port < 1 || !schedule || !callback) {
801 silc_set_errno(SILC_ERR_INVALID_ARGUMENT);
805 SILC_LOG_DEBUG(("Creating connection to host %s port %d",
806 remote_ip_addr, remote_port));
808 conn = silc_calloc(1, sizeof(*conn));
810 callback(SILC_ERR_OUT_OF_MEMORY, NULL, context);
814 /* Start async operation */
815 conn->op = silc_async_alloc(silc_net_connect_abort, NULL, conn);
818 callback(SILC_ERR_OUT_OF_MEMORY, NULL, context);
823 conn->local_ip = silc_strdup(local_ip_addr);
824 conn->remote = silc_strdup(remote_ip_addr);
826 silc_async_free(conn->op);
827 silc_free(conn->local_ip);
829 callback(SILC_ERR_OUT_OF_MEMORY, NULL, context);
832 conn->port = remote_port;
833 conn->callback = callback;
834 conn->context = context;
836 conn->status = SILC_ERR;
838 silc_fsm_init(&conn->fsm, conn, silc_net_connect_destructor, NULL, schedule);
839 silc_fsm_start(&conn->fsm, silc_net_connect_st_thread);
844 /* Closes the connection by closing the socket connection. */
846 void silc_net_close_connection(int sock)
848 SILC_LOG_DEBUG(("Closing sock %d", sock));
852 /* Converts the IP number string from numbers-and-dots notation to
855 SilcBool silc_net_addr2bin(const char *addr, void *bin, SilcUInt32 bin_len)
857 if (silc_net_is_ip4(addr)) {
859 int i = 0, c = 0, d = 0, len = strlen(addr);
860 unsigned char ret[4];
862 memset(ret, 0, sizeof(ret));
864 if (addr[i++] == '.') {
872 if (!isdigit((int)addr[i - 1]))
875 d = 10 * d + addr[i - 1] - '0';
883 if (bin_len < sizeof(ret)) {
884 silc_set_errno(SILC_ERR_OVERFLOW);
888 memcpy(bin, ret, sizeof(ret));
895 struct addrinfo hints, *ai;
900 silc_set_errno(SILC_ERR_INVALID_ARGUMENT);
904 memset(&hints, 0, sizeof(hints));
905 hints.ai_family = AF_INET6;
906 if (getaddrinfo(addr, NULL, &hints, &ai))
910 s = (SilcSockaddr *)ai->ai_addr;
911 memcpy(bin, &s->sin6.sin6_addr, sizeof(s->sin6.sin6_addr));
918 #endif /* HAVE_IPV6 */
922 /* Set socket to non-blocking mode. */
924 int silc_net_set_socket_nonblock(SilcSocket sock)
926 unsigned long on = 1;
927 return ioctlsocket(sock, FIONBIO, &on);