2009-01-09 Miguel de Icaza <miguel@novell.com>
[mono.git] / mono / io-layer / sockets.c
1 /*
2  * sockets.c:  Socket handles
3  *
4  * Author:
5  *      Dick Porter (dick@ximian.com)
6  *
7  * (C) 2002 Ximian, Inc.
8  */
9
10 #include <config.h>
11 #include <glib.h>
12 #include <pthread.h>
13 #include <errno.h>
14 #include <string.h>
15 #include <sys/types.h>
16 #include <sys/socket.h>
17 #include <sys/ioctl.h>
18 #include <sys/poll.h>
19 #ifdef HAVE_SYS_FILIO_H
20 #include <sys/filio.h>     /* defines FIONBIO and FIONREAD */
21 #endif
22 #ifdef HAVE_SYS_SOCKIO_H
23 #include <sys/sockio.h>    /* defines SIOCATMARK */
24 #endif
25 #include <unistd.h>
26 #include <fcntl.h>
27
28 #ifndef HAVE_MSG_NOSIGNAL
29 #include <signal.h>
30 #endif
31
32 #include <mono/io-layer/wapi.h>
33 #include <mono/io-layer/wapi-private.h>
34 #include <mono/io-layer/socket-private.h>
35 #include <mono/io-layer/handles-private.h>
36 #include <mono/io-layer/socket-wrappers.h>
37
38 #include <netinet/in.h>
39 #include <netinet/tcp.h>
40 #include <netdb.h>
41 #include <arpa/inet.h>
42
43 #undef DEBUG
44
45 static guint32 startup_count=0;
46
47 static void socket_close (gpointer handle, gpointer data);
48
49 struct _WapiHandleOps _wapi_socket_ops = {
50         socket_close,           /* close */
51         NULL,                   /* signal */
52         NULL,                   /* own */
53         NULL,                   /* is_owned */
54         NULL,                   /* special_wait */
55         NULL                    /* prewait */
56 };
57
58 static mono_once_t socket_ops_once=MONO_ONCE_INIT;
59
60 static void socket_ops_init (void)
61 {
62         /* No capabilities to register */
63 }
64
65 static void socket_close (gpointer handle, gpointer data)
66 {
67         int ret;
68         struct _WapiHandle_socket *socket_handle = (struct _WapiHandle_socket *)data;
69
70 #ifdef DEBUG
71         g_message ("%s: closing socket handle %p", __func__, handle);
72 #endif
73
74         if (startup_count == 0) {
75                 WSASetLastError (WSANOTINITIALISED);
76                 return;
77         }
78
79         /* Shutdown the socket for reading, to interrupt any potential
80          * receives that may be blocking for data.  See bug 75705.
81          */
82         shutdown (GPOINTER_TO_UINT (handle), SHUT_RD);
83         
84         do {
85                 ret = close (GPOINTER_TO_UINT(handle));
86         } while (ret == -1 && errno == EINTR &&
87                  !_wapi_thread_cur_apc_pending ());
88         
89         if (ret == -1) {
90                 gint errnum = errno;
91 #ifdef DEBUG
92                 g_message ("%s: close error: %s", __func__, strerror (errno));
93 #endif
94                 errnum = errno_to_WSA (errnum, __func__);
95                 WSASetLastError (errnum);
96         }
97
98         socket_handle->saved_error = 0;
99 }
100
101 int WSAStartup(guint32 requested, WapiWSAData *data)
102 {
103         if (data == NULL) {
104                 return(WSAEFAULT);
105         }
106
107         /* Insist on v2.0+ */
108         if (requested < MAKEWORD(2,0)) {
109                 return(WSAVERNOTSUPPORTED);
110         }
111
112         startup_count++;
113
114         /* I've no idea what is the minor version of the spec I read */
115         data->wHighVersion = MAKEWORD(2,2);
116         
117         data->wVersion = requested < data->wHighVersion? requested:
118                 data->wHighVersion;
119
120 #ifdef DEBUG
121         g_message ("%s: high version 0x%x", __func__, data->wHighVersion);
122 #endif
123         
124         strncpy (data->szDescription, "WAPI", WSADESCRIPTION_LEN);
125         strncpy (data->szSystemStatus, "groovy", WSASYS_STATUS_LEN);
126         
127         return(0);
128 }
129
130 static gboolean
131 cleanup_close (gpointer handle, gpointer data)
132 {
133         _wapi_handle_ops_close (handle, NULL);
134         return TRUE;
135 }
136
137 int WSACleanup(void)
138 {
139 #ifdef DEBUG
140         g_message ("%s: cleaning up", __func__);
141 #endif
142
143         if (--startup_count) {
144                 /* Do nothing */
145                 return(0);
146         }
147
148         _wapi_handle_foreach (WAPI_HANDLE_SOCKET, cleanup_close, NULL);
149         return(0);
150 }
151
152 void WSASetLastError(int error)
153 {
154         SetLastError (error);
155 }
156
157 int WSAGetLastError(void)
158 {
159         return(GetLastError ());
160 }
161
162 int closesocket(guint32 fd)
163 {
164         gpointer handle = GUINT_TO_POINTER (fd);
165         
166         if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
167                 WSASetLastError (WSAENOTSOCK);
168                 return(0);
169         }
170         
171         _wapi_handle_unref (handle);
172         return(0);
173 }
174
175 guint32 _wapi_accept(guint32 fd, struct sockaddr *addr, socklen_t *addrlen)
176 {
177         gpointer handle = GUINT_TO_POINTER (fd);
178         gpointer new_handle;
179         struct _WapiHandle_socket *socket_handle;
180         struct _WapiHandle_socket new_socket_handle = {0};
181         gboolean ok;
182         int new_fd;
183         
184         if (startup_count == 0) {
185                 WSASetLastError (WSANOTINITIALISED);
186                 return(INVALID_SOCKET);
187         }
188
189         if (addr != NULL && *addrlen < sizeof(struct sockaddr)) {
190                 WSASetLastError (WSAEFAULT);
191                 return(INVALID_SOCKET);
192         }
193         
194         if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
195                 WSASetLastError (WSAENOTSOCK);
196                 return(INVALID_SOCKET);
197         }
198         
199         ok = _wapi_lookup_handle (handle, WAPI_HANDLE_SOCKET,
200                                   (gpointer *)&socket_handle);
201         if (ok == FALSE) {
202                 g_warning ("%s: error looking up socket handle %p",
203                            __func__, handle);
204                 WSASetLastError (WSAENOTSOCK);
205                 return(INVALID_SOCKET);
206         }
207         
208         do {
209                 new_fd = accept (fd, addr, addrlen);
210         } while (new_fd == -1 && errno == EINTR &&
211                  !_wapi_thread_cur_apc_pending());
212
213         if (new_fd == -1) {
214                 gint errnum = errno;
215 #ifdef DEBUG
216                 g_message ("%s: accept error: %s", __func__, strerror(errno));
217 #endif
218
219                 errnum = errno_to_WSA (errnum, __func__);
220                 WSASetLastError (errnum);
221                 
222                 return(INVALID_SOCKET);
223         }
224
225         if (new_fd >= _wapi_fd_reserve) {
226 #ifdef DEBUG
227                 g_message ("%s: File descriptor is too big", __func__);
228 #endif
229
230                 WSASetLastError (WSASYSCALLFAILURE);
231                 
232                 close (new_fd);
233                 
234                 return(INVALID_SOCKET);
235         }
236
237         new_socket_handle.domain = socket_handle->domain;
238         new_socket_handle.type = socket_handle->type;
239         new_socket_handle.protocol = socket_handle->protocol;
240         new_socket_handle.still_readable = 1;
241
242         new_handle = _wapi_handle_new_fd (WAPI_HANDLE_SOCKET, new_fd,
243                                           &new_socket_handle);
244         if(new_handle == _WAPI_HANDLE_INVALID) {
245                 g_warning ("%s: error creating socket handle", __func__);
246                 WSASetLastError (ERROR_GEN_FAILURE);
247                 return(INVALID_SOCKET);
248         }
249
250 #ifdef DEBUG
251         g_message ("%s: returning newly accepted socket handle %p with",
252                    __func__, new_handle);
253 #endif
254         
255         return(new_fd);
256 }
257
258 int _wapi_bind(guint32 fd, struct sockaddr *my_addr, socklen_t addrlen)
259 {
260         gpointer handle = GUINT_TO_POINTER (fd);
261         int ret;
262         
263         if (startup_count == 0) {
264                 WSASetLastError (WSANOTINITIALISED);
265                 return(SOCKET_ERROR);
266         }
267
268         if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
269                 WSASetLastError (WSAENOTSOCK);
270                 return(SOCKET_ERROR);
271         }
272         
273         ret = bind (fd, my_addr, addrlen);
274         if (ret == -1) {
275                 gint errnum = errno;
276 #ifdef DEBUG
277                 g_message ("%s: bind error: %s", __func__, strerror(errno));
278 #endif
279                 errnum = errno_to_WSA (errnum, __func__);
280                 WSASetLastError (errnum);
281                 
282                 return(SOCKET_ERROR);
283         }
284         return(ret);
285 }
286
287 int _wapi_connect(guint32 fd, const struct sockaddr *serv_addr,
288                   socklen_t addrlen)
289 {
290         gpointer handle = GUINT_TO_POINTER (fd);
291         struct _WapiHandle_socket *socket_handle;
292         gboolean ok;
293         gint errnum;
294         
295         if (startup_count == 0) {
296                 WSASetLastError (WSANOTINITIALISED);
297                 return(SOCKET_ERROR);
298         }
299         
300         if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
301                 WSASetLastError (WSAENOTSOCK);
302                 return(SOCKET_ERROR);
303         }
304         
305         if (connect (fd, serv_addr, addrlen) == -1) {
306                 struct pollfd fds;
307                 int so_error;
308                 socklen_t len;
309                 
310                 errnum = errno;
311                 
312                 if (errno != EINTR) {
313 #ifdef DEBUG
314                         g_message ("%s: connect error: %s", __func__,
315                                    strerror (errnum));
316 #endif
317
318                         errnum = errno_to_WSA (errnum, __func__);
319                         if (errnum == WSAEINPROGRESS)
320                                 errnum = WSAEWOULDBLOCK; /* see bug #73053 */
321
322                         WSASetLastError (errnum);
323
324                         /* 
325                          * On solaris x86 getsockopt (SO_ERROR) is not set after 
326                          * connect () fails so we need to save this error.
327                          *
328                          * But don't do this for EWOULDBLOCK (bug 317315)
329                          */
330                         if (errnum != WSAEWOULDBLOCK) {
331                                 ok = _wapi_lookup_handle (handle,
332                                                           WAPI_HANDLE_SOCKET,
333                                                           (gpointer *)&socket_handle);
334                                 if (ok == FALSE) {
335                                         g_warning ("%s: error looking up socket handle %p", __func__, handle);
336                                 } else {
337                                         socket_handle->saved_error = errnum;
338                                 }
339                         }
340                         return(SOCKET_ERROR);
341                 }
342
343                 fds.fd = fd;
344                 fds.events = POLLOUT;
345                 while (poll (&fds, 1, -1) == -1 &&
346                        !_wapi_thread_cur_apc_pending ()) {
347                         if (errno != EINTR) {
348                                 errnum = errno_to_WSA (errno, __func__);
349
350 #ifdef DEBUG
351                                 g_message ("%s: connect poll error: %s",
352                                            __func__, strerror (errno));
353 #endif
354
355                                 WSASetLastError (errnum);
356                                 return(SOCKET_ERROR);
357                         }
358                 }
359
360                 len = sizeof(so_error);
361                 if (getsockopt (fd, SOL_SOCKET, SO_ERROR, &so_error,
362                                 &len) == -1) {
363                         errnum = errno_to_WSA (errno, __func__);
364
365 #ifdef DEBUG
366                         g_message ("%s: connect getsockopt error: %s",
367                                    __func__, strerror (errno));
368 #endif
369
370                         WSASetLastError (errnum);
371                         return(SOCKET_ERROR);
372                 }
373                 
374                 if (so_error != 0) {
375                         errnum = errno_to_WSA (so_error, __func__);
376
377                         /* Need to save this socket error */
378                         ok = _wapi_lookup_handle (handle, WAPI_HANDLE_SOCKET,
379                                                   (gpointer *)&socket_handle);
380                         if (ok == FALSE) {
381                                 g_warning ("%s: error looking up socket handle %p", __func__, handle);
382                         } else {
383                                 socket_handle->saved_error = errnum;
384                         }
385                         
386 #ifdef DEBUG
387                         g_message ("%s: connect getsockopt returned error: %s",
388                                    __func__, strerror (so_error));
389 #endif
390
391                         WSASetLastError (errnum);
392                         return(SOCKET_ERROR);
393                 }
394         }
395                 
396         return(0);
397 }
398
399 int _wapi_getpeername(guint32 fd, struct sockaddr *name, socklen_t *namelen)
400 {
401         gpointer handle = GUINT_TO_POINTER (fd);
402         int ret;
403         
404         if (startup_count == 0) {
405                 WSASetLastError (WSANOTINITIALISED);
406                 return(SOCKET_ERROR);
407         }
408         
409         if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
410                 WSASetLastError (WSAENOTSOCK);
411                 return(SOCKET_ERROR);
412         }
413
414         ret = getpeername (fd, name, namelen);
415         if (ret == -1) {
416                 gint errnum = errno;
417 #ifdef DEBUG
418                 g_message ("%s: getpeername error: %s", __func__,
419                            strerror (errno));
420 #endif
421
422                 errnum = errno_to_WSA (errnum, __func__);
423                 WSASetLastError (errnum);
424
425                 return(SOCKET_ERROR);
426         }
427         
428         return(ret);
429 }
430
431 int _wapi_getsockname(guint32 fd, struct sockaddr *name, socklen_t *namelen)
432 {
433         gpointer handle = GUINT_TO_POINTER (fd);
434         int ret;
435         
436         if (startup_count == 0) {
437                 WSASetLastError (WSANOTINITIALISED);
438                 return(SOCKET_ERROR);
439         }
440         
441         if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
442                 WSASetLastError (WSAENOTSOCK);
443                 return(SOCKET_ERROR);
444         }
445
446         ret = getsockname (fd, name, namelen);
447         if (ret == -1) {
448                 gint errnum = errno;
449 #ifdef DEBUG
450                 g_message ("%s: getsockname error: %s", __func__,
451                            strerror (errno));
452 #endif
453
454                 errnum = errno_to_WSA (errnum, __func__);
455                 WSASetLastError (errnum);
456
457                 return(SOCKET_ERROR);
458         }
459         
460         return(ret);
461 }
462
463 int _wapi_getsockopt(guint32 fd, int level, int optname, void *optval,
464                      socklen_t *optlen)
465 {
466         gpointer handle = GUINT_TO_POINTER (fd);
467         int ret;
468         struct timeval tv;
469         void *tmp_val;
470         struct _WapiHandle_socket *socket_handle;
471         gboolean ok;
472         
473         if (startup_count == 0) {
474                 WSASetLastError (WSANOTINITIALISED);
475                 return(SOCKET_ERROR);
476         }
477         
478         if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
479                 WSASetLastError (WSAENOTSOCK);
480                 return(SOCKET_ERROR);
481         }
482
483         tmp_val = optval;
484         if (level == SOL_SOCKET &&
485             (optname == SO_RCVTIMEO || optname == SO_SNDTIMEO)) {
486                 tmp_val = &tv;
487                 *optlen = sizeof (tv);
488         }
489
490         ret = getsockopt (fd, level, optname, tmp_val, optlen);
491         if (ret == -1) {
492                 gint errnum = errno;
493 #ifdef DEBUG
494                 g_message ("%s: getsockopt error: %s", __func__,
495                            strerror (errno));
496 #endif
497
498                 errnum = errno_to_WSA (errnum, __func__);
499                 WSASetLastError (errnum);
500                 
501                 return(SOCKET_ERROR);
502         }
503
504         if (level == SOL_SOCKET &&
505             (optname == SO_RCVTIMEO || optname == SO_SNDTIMEO)) {
506                 *((int *) optval)  = tv.tv_sec * 1000 + (tv.tv_usec / 1000);    // milli from micro
507                 *optlen = sizeof (int);
508         }
509
510         if (optname == SO_ERROR) {
511                 ok = _wapi_lookup_handle (handle, WAPI_HANDLE_SOCKET,
512                                           (gpointer *)&socket_handle);
513                 if (ok == FALSE) {
514                         g_warning ("%s: error looking up socket handle %p",
515                                    __func__, handle);
516
517                         /* can't extract the last error */
518                         *((int *) optval) = errno_to_WSA (*((int *)optval),
519                                                           __func__);
520                 } else {
521                         if (*((int *)optval) != 0) {
522                                 *((int *) optval) = errno_to_WSA (*((int *)optval),
523                                                                   __func__);
524                                 socket_handle->saved_error = *((int *)optval);
525                         } else {
526                                 *((int *)optval) = socket_handle->saved_error;
527                         }
528                 }
529         }
530         
531         return(ret);
532 }
533
534 int _wapi_listen(guint32 fd, int backlog)
535 {
536         gpointer handle = GUINT_TO_POINTER (fd);
537         int ret;
538         
539         if (startup_count == 0) {
540                 WSASetLastError (WSANOTINITIALISED);
541                 return(SOCKET_ERROR);
542         }
543         
544         if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
545                 WSASetLastError (WSAENOTSOCK);
546                 return(SOCKET_ERROR);
547         }
548         
549         ret = listen (fd, backlog);
550         if (ret == -1) {
551                 gint errnum = errno;
552 #ifdef DEBUG
553                 g_message ("%s: listen error: %s", __func__, strerror (errno));
554 #endif
555
556                 errnum = errno_to_WSA (errnum, __func__);
557                 WSASetLastError (errnum);
558
559                 return(SOCKET_ERROR);
560         }
561
562         return(0);
563 }
564
565 int _wapi_recv(guint32 fd, void *buf, size_t len, int recv_flags)
566 {
567         return(_wapi_recvfrom (fd, buf, len, recv_flags, NULL, 0));
568 }
569
570 int _wapi_recvfrom(guint32 fd, void *buf, size_t len, int recv_flags,
571                    struct sockaddr *from, socklen_t *fromlen)
572 {
573         gpointer handle = GUINT_TO_POINTER (fd);
574         struct _WapiHandle_socket *socket_handle;
575         gboolean ok;
576         int ret;
577         
578         if (startup_count == 0) {
579                 WSASetLastError (WSANOTINITIALISED);
580                 return(SOCKET_ERROR);
581         }
582         
583         if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
584                 WSASetLastError (WSAENOTSOCK);
585                 return(SOCKET_ERROR);
586         }
587         
588         do {
589                 ret = recvfrom (fd, buf, len, recv_flags, from, fromlen);
590         } while (ret == -1 && errno == EINTR &&
591                  !_wapi_thread_cur_apc_pending ());
592
593         if (ret == 0 && len > 0) {
594                 /* According to the Linux man page, recvfrom only
595                  * returns 0 when the socket has been shut down
596                  * cleanly.  Turn this into an EINTR to simulate win32
597                  * behaviour of returning EINTR when a socket is
598                  * closed while the recvfrom is blocking (we use a
599                  * shutdown() in socket_close() to trigger this.) See
600                  * bug 75705.
601                  */
602                 /* Distinguish between the socket being shut down at
603                  * the local or remote ends, and reads that request 0
604                  * bytes to be read
605                  */
606
607                 /* If this returns FALSE, it means the socket has been
608                  * closed locally.  If it returns TRUE, but
609                  * still_readable != 1 then shutdown
610                  * (SHUT_RD|SHUT_RDWR) has been called locally.
611                  */
612                 ok = _wapi_lookup_handle (handle, WAPI_HANDLE_SOCKET,
613                                           (gpointer *)&socket_handle);
614                 if (ok == FALSE || socket_handle->still_readable != 1) {
615                         ret = -1;
616                         errno = EINTR;
617                 }
618         }
619         
620         if (ret == -1) {
621                 gint errnum = errno;
622 #ifdef DEBUG
623                 g_message ("%s: recv error: %s", __func__, strerror(errno));
624 #endif
625
626                 errnum = errno_to_WSA (errnum, __func__);
627                 WSASetLastError (errnum);
628                 
629                 return(SOCKET_ERROR);
630         }
631         return(ret);
632 }
633
634 int _wapi_send(guint32 fd, const void *msg, size_t len, int send_flags)
635 {
636         gpointer handle = GUINT_TO_POINTER (fd);
637         int ret;
638         
639         if (startup_count == 0) {
640                 WSASetLastError (WSANOTINITIALISED);
641                 return(SOCKET_ERROR);
642         }
643         
644         if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
645                 WSASetLastError (WSAENOTSOCK);
646                 return(SOCKET_ERROR);
647         }
648
649         do {
650                 ret = send (fd, msg, len, send_flags);
651         } while (ret == -1 && errno == EINTR &&
652                  !_wapi_thread_cur_apc_pending ());
653
654         if (ret == -1) {
655                 gint errnum = errno;
656 #ifdef DEBUG
657                 g_message ("%s: send error: %s", __func__, strerror (errno));
658 #endif
659
660                 errnum = errno_to_WSA (errnum, __func__);
661                 WSASetLastError (errnum);
662                 
663                 return(SOCKET_ERROR);
664         }
665         return(ret);
666 }
667
668 int _wapi_sendto(guint32 fd, const void *msg, size_t len, int send_flags,
669                  const struct sockaddr *to, socklen_t tolen)
670 {
671         gpointer handle = GUINT_TO_POINTER (fd);
672         int ret;
673         
674         if (startup_count == 0) {
675                 WSASetLastError (WSANOTINITIALISED);
676                 return(SOCKET_ERROR);
677         }
678         
679         if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
680                 WSASetLastError (WSAENOTSOCK);
681                 return(SOCKET_ERROR);
682         }
683         
684         do {
685                 ret = sendto (fd, msg, len, send_flags, to, tolen);
686         } while (ret == -1 && errno == EINTR &&
687                  !_wapi_thread_cur_apc_pending ());
688
689         if (ret == -1) {
690                 gint errnum = errno;
691 #ifdef DEBUG
692                 g_message ("%s: send error: %s", __func__, strerror (errno));
693 #endif
694
695                 errnum = errno_to_WSA (errnum, __func__);
696                 WSASetLastError (errnum);
697                 
698                 return(SOCKET_ERROR);
699         }
700         return(ret);
701 }
702
703 int _wapi_setsockopt(guint32 fd, int level, int optname,
704                      const void *optval, socklen_t optlen)
705 {
706         gpointer handle = GUINT_TO_POINTER (fd);
707         int ret;
708         const void *tmp_val;
709         struct timeval tv;
710         
711         if (startup_count == 0) {
712                 WSASetLastError (WSANOTINITIALISED);
713                 return(SOCKET_ERROR);
714         }
715         
716         if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
717                 WSASetLastError (WSAENOTSOCK);
718                 return(SOCKET_ERROR);
719         }
720
721         tmp_val = optval;
722         if (level == SOL_SOCKET &&
723             (optname == SO_RCVTIMEO || optname == SO_SNDTIMEO)) {
724                 int ms = *((int *) optval);
725                 tv.tv_sec = ms / 1000;
726                 tv.tv_usec = (ms % 1000) * 1000;        // micro from milli
727                 tmp_val = &tv;
728                 optlen = sizeof (tv);
729 #if defined (__linux__)
730         } else if (level == SOL_SOCKET &&
731                    (optname == SO_SNDBUF || optname == SO_RCVBUF)) {
732                 /* According to socket(7) the Linux kernel doubles the
733                  * buffer sizes "to allow space for bookkeeping
734                  * overhead."
735                  */
736                 int bufsize = *((int *) optval);
737
738                 bufsize /= 2;
739                 tmp_val = &bufsize;
740 #endif
741         }
742                 
743         ret = setsockopt (fd, level, optname, tmp_val, optlen);
744         if (ret == -1) {
745                 gint errnum = errno;
746 #ifdef DEBUG
747                 g_message ("%s: setsockopt error: %s", __func__,
748                            strerror (errno));
749 #endif
750
751                 errnum = errno_to_WSA (errnum, __func__);
752                 WSASetLastError (errnum);
753                 
754                 return(SOCKET_ERROR);
755         }
756
757 #if defined(__FreeBSD__)
758         /* FreeBSD's multicast sockets also need SO_REUSEPORT when SO_REUSEADDR is requested.  */
759         if (level == SOL_SOCKET && optname == SO_REUSEADDR) {
760                 int type;
761                 int type_len = sizeof (type);
762
763                 if (!getsockopt (fd, level, SO_TYPE, &type, &type_len)) {
764                         if (type == SOCK_DGRAM)
765                                 setsockopt (fd, level, SO_REUSEPORT, tmp_val, optlen);
766                 }
767         }
768 #endif
769         
770         return(ret);
771 }
772
773 int _wapi_shutdown(guint32 fd, int how)
774 {
775         struct _WapiHandle_socket *socket_handle;
776         gboolean ok;
777         gpointer handle = GUINT_TO_POINTER (fd);
778         int ret;
779         
780         if (startup_count == 0) {
781                 WSASetLastError (WSANOTINITIALISED);
782                 return(SOCKET_ERROR);
783         }
784         
785         if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
786                 WSASetLastError (WSAENOTSOCK);
787                 return(SOCKET_ERROR);
788         }
789
790         if (how == SHUT_RD ||
791             how == SHUT_RDWR) {
792                 ok = _wapi_lookup_handle (handle, WAPI_HANDLE_SOCKET,
793                                           (gpointer *)&socket_handle);
794                 if (ok == FALSE) {
795                         g_warning ("%s: error looking up socket handle %p",
796                                    __func__, handle);
797                         WSASetLastError (WSAENOTSOCK);
798                         return(SOCKET_ERROR);
799                 }
800                 
801                 socket_handle->still_readable = 0;
802         }
803         
804         ret = shutdown (fd, how);
805         if (ret == -1) {
806                 gint errnum = errno;
807 #ifdef DEBUG
808                 g_message ("%s: shutdown error: %s", __func__,
809                            strerror (errno));
810 #endif
811
812                 errnum = errno_to_WSA (errnum, __func__);
813                 WSASetLastError (errnum);
814                 
815                 return(SOCKET_ERROR);
816         }
817         
818         return(ret);
819 }
820
821 guint32 _wapi_socket(int domain, int type, int protocol, void *unused,
822                      guint32 unused2, guint32 unused3)
823 {
824         struct _WapiHandle_socket socket_handle = {0};
825         gpointer handle;
826         int fd;
827         
828         socket_handle.domain = domain;
829         socket_handle.type = type;
830         socket_handle.protocol = protocol;
831         socket_handle.still_readable = 1;
832         
833         fd = socket (domain, type, protocol);
834         if (fd == -1 && domain == AF_INET && type == SOCK_RAW &&
835             protocol == 0) {
836                 /* Retry with protocol == 4 (see bug #54565) */
837                 socket_handle.protocol = 4;
838                 fd = socket (AF_INET, SOCK_RAW, 4);
839         }
840         
841         if (fd == -1) {
842                 gint errnum = errno;
843 #ifdef DEBUG
844                 g_message ("%s: socket error: %s", __func__, strerror (errno));
845 #endif
846                 errnum = errno_to_WSA (errnum, __func__);
847                 WSASetLastError (errnum);
848
849                 return(INVALID_SOCKET);
850         }
851
852         if (fd >= _wapi_fd_reserve) {
853 #ifdef DEBUG
854                 g_message ("%s: File descriptor is too big (%d >= %d)",
855                            __func__, fd, _wapi_fd_reserve);
856 #endif
857
858                 WSASetLastError (WSASYSCALLFAILURE);
859                 close (fd);
860                 
861                 return(INVALID_SOCKET);
862         }
863
864         /* .net seems to set this by default for SOCK_STREAM, not for
865          * SOCK_DGRAM (see bug #36322)
866          *
867          * It seems winsock has a rather different idea of what
868          * SO_REUSEADDR means.  If it's set, then a new socket can be
869          * bound over an existing listening socket.  There's a new
870          * windows-specific option called SO_EXCLUSIVEADDRUSE but
871          * using that means the socket MUST be closed properly, or a
872          * denial of service can occur.  Luckily for us, winsock
873          * behaves as though any other system would when SO_REUSEADDR
874          * is true, so we don't need to do anything else here.  See
875          * bug 53992.
876          */
877         {
878                 int ret, true = 1;
879         
880                 ret = setsockopt (fd, SOL_SOCKET, SO_REUSEADDR, &true,
881                                   sizeof (true));
882                 if (ret == -1) {
883                         int errnum = errno;
884
885 #ifdef DEBUG
886                         g_message ("%s: Error setting SO_REUSEADDR", __func__);
887 #endif
888                         
889                         errnum = errno_to_WSA (errnum, __func__);
890                         WSASetLastError (errnum);
891
892                         close (fd);
893
894                         return(INVALID_SOCKET);                 
895                 }
896         }
897         
898         
899         mono_once (&socket_ops_once, socket_ops_init);
900         
901         handle = _wapi_handle_new_fd (WAPI_HANDLE_SOCKET, fd, &socket_handle);
902         if (handle == _WAPI_HANDLE_INVALID) {
903                 g_warning ("%s: error creating socket handle", __func__);
904                 WSASetLastError (WSASYSCALLFAILURE);
905                 close (fd);
906                 return(INVALID_SOCKET);
907         }
908
909 #ifdef DEBUG
910         g_message ("%s: returning socket handle %p", __func__, handle);
911 #endif
912
913         return(fd);
914 }
915
916 struct hostent *_wapi_gethostbyname(const char *hostname)
917 {
918         struct hostent *he;
919         
920         if (startup_count == 0) {
921                 WSASetLastError (WSANOTINITIALISED);
922                 return(NULL);
923         }
924
925         he = gethostbyname (hostname);
926         if (he == NULL) {
927 #ifdef DEBUG
928                 g_message ("%s: gethostbyname error: %s", __func__,
929                            strerror (h_errno));
930 #endif
931
932                 switch(h_errno) {
933                 case HOST_NOT_FOUND:
934                         WSASetLastError (WSAHOST_NOT_FOUND);
935                         break;
936 #if NO_ADDRESS != NO_DATA
937                 case NO_ADDRESS:
938 #endif
939                 case NO_DATA:
940                         WSASetLastError (WSANO_DATA);
941                         break;
942                 case NO_RECOVERY:
943                         WSASetLastError (WSANO_RECOVERY);
944                         break;
945                 case TRY_AGAIN:
946                         WSASetLastError (WSATRY_AGAIN);
947                         break;
948                 default:
949                         g_warning ("%s: Need to translate %d into winsock error", __func__, h_errno);
950                         break;
951                 }
952         }
953         
954         return(he);
955 }
956
957 static gboolean socket_disconnect (guint32 fd)
958 {
959         struct _WapiHandle_socket *socket_handle;
960         gboolean ok;
961         gpointer handle = GUINT_TO_POINTER (fd);
962         int newsock, ret;
963         
964         ok = _wapi_lookup_handle (handle, WAPI_HANDLE_SOCKET,
965                                   (gpointer *)&socket_handle);
966         if (ok == FALSE) {
967                 g_warning ("%s: error looking up socket handle %p", __func__,
968                            handle);
969                 WSASetLastError (WSAENOTSOCK);
970                 return(FALSE);
971         }
972         
973         newsock = socket (socket_handle->domain, socket_handle->type,
974                           socket_handle->protocol);
975         if (newsock == -1) {
976                 gint errnum = errno;
977
978 #ifdef DEBUG
979                 g_message ("%s: socket error: %s", __func__, strerror (errno));
980 #endif
981
982                 errnum = errno_to_WSA (errnum, __func__);
983                 WSASetLastError (errnum);
984                 
985                 return(FALSE);
986         }
987
988         /* According to Stevens "Advanced Programming in the UNIX
989          * Environment: UNIX File I/O" dup2() is atomic so there
990          * should not be a race condition between the old fd being
991          * closed and the new socket fd being copied over
992          */
993         do {
994                 ret = dup2 (newsock, fd);
995         } while (ret == -1 && errno == EAGAIN);
996         
997         if (ret == -1) {
998                 gint errnum = errno;
999                 
1000 #ifdef DEBUG
1001                 g_message ("%s: dup2 error: %s", __func__, strerror (errno));
1002 #endif
1003
1004                 errnum = errno_to_WSA (errnum, __func__);
1005                 WSASetLastError (errnum);
1006                 
1007                 return(FALSE);
1008         }
1009
1010         close (newsock);
1011         
1012         return(TRUE);
1013 }
1014
1015 static gboolean wapi_disconnectex (guint32 fd, WapiOverlapped *overlapped,
1016                                    guint32 flags, guint32 reserved)
1017 {
1018 #ifdef DEBUG
1019         g_message ("%s: called on socket %d!", __func__, fd);
1020 #endif
1021         
1022         if (reserved != 0) {
1023                 WSASetLastError (WSAEINVAL);
1024                 return(FALSE);
1025         }
1026
1027         /* We could check the socket type here and fail unless its
1028          * SOCK_STREAM, SOCK_SEQPACKET or SOCK_RDM (according to msdn)
1029          * if we really wanted to
1030          */
1031
1032         return(socket_disconnect (fd));
1033 }
1034
1035 /* NB only supports NULL file handle, NULL buffers and
1036  * TF_DISCONNECT|TF_REUSE_SOCKET flags to disconnect the socket fd.
1037  * Shouldn't actually ever need to be called anyway though, because we
1038  * have DisconnectEx ().
1039  */
1040 static gboolean wapi_transmitfile (guint32 fd, gpointer file,
1041                                    guint32 num_write, guint32 num_per_send,
1042                                    WapiOverlapped *overlapped,
1043                                    WapiTransmitFileBuffers *buffers,
1044                                    WapiTransmitFileFlags flags)
1045 {
1046 #ifdef DEBUG
1047         g_message ("%s: called on socket %d!", __func__, fd);
1048 #endif
1049         
1050         g_assert (file == NULL);
1051         g_assert (overlapped == NULL);
1052         g_assert (buffers == NULL);
1053         g_assert (num_write == 0);
1054         g_assert (num_per_send == 0);
1055         g_assert (flags == (TF_DISCONNECT | TF_REUSE_SOCKET));
1056
1057         return(socket_disconnect (fd));
1058 }
1059
1060 static struct 
1061 {
1062         WapiGuid guid;
1063         gpointer func;
1064 } extension_functions[] = {
1065         {WSAID_DISCONNECTEX, wapi_disconnectex},
1066         {WSAID_TRANSMITFILE, wapi_transmitfile},
1067         {{0}, NULL},
1068 };
1069
1070 int
1071 WSAIoctl (guint32 fd, gint32 command,
1072           gchar *input, gint i_len,
1073           gchar *output, gint o_len, glong *written,
1074           void *unused1, void *unused2)
1075 {
1076         gpointer handle = GUINT_TO_POINTER (fd);
1077         int ret;
1078         gchar *buffer = NULL;
1079
1080         if (startup_count == 0) {
1081                 WSASetLastError (WSANOTINITIALISED);
1082                 return(SOCKET_ERROR);
1083         }
1084
1085         if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
1086                 WSASetLastError (WSAENOTSOCK);
1087                 return SOCKET_ERROR;
1088         }
1089
1090         if (command == SIO_GET_EXTENSION_FUNCTION_POINTER) {
1091                 int i = 0;
1092                 WapiGuid *guid = (WapiGuid *)input;
1093                 
1094                 if (i_len < sizeof(WapiGuid)) {
1095                         /* As far as I can tell, windows doesn't
1096                          * actually set an error here...
1097                          */
1098                         WSASetLastError (WSAEINVAL);
1099                         return(SOCKET_ERROR);
1100                 }
1101
1102                 if (o_len < sizeof(gpointer)) {
1103                         /* Or here... */
1104                         WSASetLastError (WSAEINVAL);
1105                         return(SOCKET_ERROR);
1106                 }
1107
1108                 if (output == NULL) {
1109                         /* Or here */
1110                         WSASetLastError (WSAEINVAL);
1111                         return(SOCKET_ERROR);
1112                 }
1113                 
1114                 while(extension_functions[i].func != NULL) {
1115                         if (!memcmp (guid, &extension_functions[i].guid,
1116                                      sizeof(WapiGuid))) {
1117                                 memcpy (output, &extension_functions[i].func,
1118                                         sizeof(gpointer));
1119                                 *written = sizeof(gpointer);
1120                                 return(0);
1121                         }
1122
1123                         i++;
1124                 }
1125                 
1126                 WSASetLastError (WSAEINVAL);
1127                 return(SOCKET_ERROR);
1128         }
1129
1130         if (i_len > 0) {
1131                 buffer = g_memdup (input, i_len);
1132         }
1133
1134         ret = ioctl (fd, command, buffer);
1135         if (ret == -1) {
1136                 gint errnum = errno;
1137 #ifdef DEBUG
1138                 g_message("%s: WSAIoctl error: %s", __func__,
1139                           strerror (errno));
1140 #endif
1141
1142                 errnum = errno_to_WSA (errnum, __func__);
1143                 WSASetLastError (errnum);
1144                 g_free (buffer);
1145                 
1146                 return(SOCKET_ERROR);
1147         }
1148
1149         if (buffer == NULL) {
1150                 *written = 0;
1151         } else {
1152                 /* We just copy the buffer to the output. Some ioctls
1153                  * don't even output any data, but, well...
1154                  *
1155                  * NB windows returns WSAEFAULT if o_len is too small
1156                  */
1157                 i_len = (i_len > o_len) ? o_len : i_len;
1158
1159                 if (i_len > 0 && output != NULL) {
1160                         memcpy (output, buffer, i_len);
1161                 }
1162                 
1163                 g_free (buffer);
1164                 *written = i_len;
1165         }
1166
1167         return(0);
1168 }
1169
1170 int ioctlsocket(guint32 fd, gint32 command, gpointer arg)
1171 {
1172         gpointer handle = GUINT_TO_POINTER (fd);
1173         int ret;
1174         
1175         if (startup_count == 0) {
1176                 WSASetLastError (WSANOTINITIALISED);
1177                 return(SOCKET_ERROR);
1178         }
1179         
1180         if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
1181                 WSASetLastError (WSAENOTSOCK);
1182                 return(SOCKET_ERROR);
1183         }
1184
1185         switch(command){
1186                 case FIONBIO:
1187 #ifdef O_NONBLOCK
1188                         /* This works better than ioctl(...FIONBIO...) 
1189                          * on Linux (it causes connect to return
1190                          * EINPROGRESS, but the ioctl doesn't seem to)
1191                          */
1192                         ret = fcntl(fd, F_GETFL, 0);
1193                         if (ret != -1) {
1194                                 if (*(gboolean *)arg) {
1195                                         ret |= O_NONBLOCK;
1196                                 } else {
1197                                         ret &= ~O_NONBLOCK;
1198                                 }
1199                                 ret = fcntl(fd, F_SETFL, ret);
1200                         }
1201                         break;
1202 #endif /* O_NONBLOCK */
1203                 case FIONREAD:
1204                 case SIOCATMARK:
1205                         ret = ioctl (fd, command, arg);
1206                         break;
1207                 default:
1208                         WSASetLastError (WSAEINVAL);
1209                         return(SOCKET_ERROR);
1210         }
1211
1212         if (ret == -1) {
1213                 gint errnum = errno;
1214 #ifdef DEBUG
1215                 g_message ("%s: ioctl error: %s", __func__, strerror (errno));
1216 #endif
1217
1218                 errnum = errno_to_WSA (errnum, __func__);
1219                 WSASetLastError (errnum);
1220                 
1221                 return(SOCKET_ERROR);
1222         }
1223         
1224         return(0);
1225 }
1226
1227 int _wapi_select(int nfds G_GNUC_UNUSED, fd_set *readfds, fd_set *writefds,
1228                  fd_set *exceptfds, struct timeval *timeout)
1229 {
1230         int ret, maxfd;
1231         
1232         if (startup_count == 0) {
1233                 WSASetLastError (WSANOTINITIALISED);
1234                 return(SOCKET_ERROR);
1235         }
1236
1237         for (maxfd = FD_SETSIZE-1; maxfd >= 0; maxfd--) {
1238                 if ((readfds && FD_ISSET (maxfd, readfds)) ||
1239                     (writefds && FD_ISSET (maxfd, writefds)) ||
1240                     (exceptfds && FD_ISSET (maxfd, exceptfds))) {
1241                         break;
1242                 }
1243         }
1244
1245         if (maxfd == -1) {
1246                 WSASetLastError (WSAEINVAL);
1247                 return(SOCKET_ERROR);
1248         }
1249
1250         do {
1251                 ret = select(maxfd + 1, readfds, writefds, exceptfds,
1252                              timeout);
1253         } while (ret == -1 && errno == EINTR &&
1254                  !_wapi_thread_cur_apc_pending ());
1255
1256         if (ret == -1) {
1257                 gint errnum = errno;
1258 #ifdef DEBUG
1259                 g_message ("%s: select error: %s", __func__, strerror (errno));
1260 #endif
1261                 errnum = errno_to_WSA (errnum, __func__);
1262                 WSASetLastError (errnum);
1263                 
1264                 return(SOCKET_ERROR);
1265         }
1266
1267         return(ret);
1268 }
1269
1270 void _wapi_FD_CLR(guint32 fd, fd_set *set)
1271 {
1272         gpointer handle = GUINT_TO_POINTER (fd);
1273         
1274         if (fd >= FD_SETSIZE) {
1275                 WSASetLastError (WSAEINVAL);
1276                 return;
1277         }
1278         
1279         if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
1280                 WSASetLastError (WSAENOTSOCK);
1281                 return;
1282         }
1283
1284         FD_CLR (fd, set);
1285 }
1286
1287 int _wapi_FD_ISSET(guint32 fd, fd_set *set)
1288 {
1289         gpointer handle = GUINT_TO_POINTER (fd);
1290         
1291         if (fd >= FD_SETSIZE) {
1292                 WSASetLastError (WSAEINVAL);
1293                 return(0);
1294         }
1295         
1296         if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
1297                 WSASetLastError (WSAENOTSOCK);
1298                 return(0);
1299         }
1300
1301         return(FD_ISSET (fd, set));
1302 }
1303
1304 void _wapi_FD_SET(guint32 fd, fd_set *set)
1305 {
1306         gpointer handle = GUINT_TO_POINTER (fd);
1307         
1308         if (fd >= FD_SETSIZE) {
1309                 WSASetLastError (WSAEINVAL);
1310                 return;
1311         }
1312
1313         if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
1314                 WSASetLastError (WSAENOTSOCK);
1315                 return;
1316         }
1317
1318         FD_SET (fd, set);
1319 }
1320
1321 int WSARecv (guint32 fd, WapiWSABuf *buffers, guint32 count, guint32 *received,
1322              guint32 *flags, WapiOverlapped *overlapped,
1323              WapiOverlappedCB *complete)
1324 {
1325         int ret, i, buflen = 0, offset = 0, copylen;
1326         gint8 *recvbuf;
1327
1328         g_assert (overlapped == NULL);
1329         g_assert (complete == NULL);
1330         
1331         for(i = 0; i < count; i++) {
1332                 buflen += buffers[i].len;
1333         }
1334
1335         recvbuf = g_new0 (gint8, buflen);
1336         ret = _wapi_recvfrom (fd, recvbuf, buflen, *flags, NULL, 0);
1337         if(ret == SOCKET_ERROR) {
1338                 g_free (recvbuf);
1339                 return(ret);
1340         }
1341         
1342         for(i = 0; i < count; i++) {
1343                 copylen = buffers[i].len > (buflen - offset)? (buflen - offset):buffers[i].len;
1344                 memcpy (buffers[i].buf, recvbuf + offset, copylen);
1345
1346                 if (copylen != buffers[i].len) {
1347                         break;
1348                 }
1349                 offset += copylen;
1350         }
1351         
1352         *received = ret;
1353         return(0);
1354 }
1355
1356 int WSASend (guint32 fd, WapiWSABuf *buffers, guint32 count, guint32 *sent,
1357              guint32 flags, WapiOverlapped *overlapped,
1358              WapiOverlappedCB *complete)
1359 {
1360         int ret, i, buflen = 0, offset = 0, copylen;
1361         gint8 *sendbuf;
1362
1363         g_assert (overlapped == NULL);
1364         g_assert (complete == NULL);
1365         
1366         for(i = 0; i < count; i++) {
1367                 buflen += buffers[i].len;
1368         }
1369         
1370         sendbuf = g_new0 (gint8, buflen);
1371         for(i = 0; i < count; i++) {
1372                 copylen = buffers[i].len;
1373                 memcpy (sendbuf + offset, buffers[i].buf, copylen);
1374                 offset += copylen;
1375         }
1376
1377         ret = _wapi_sendto (fd, sendbuf, buflen, flags, NULL, 0);
1378         if(ret == SOCKET_ERROR) {
1379                 g_free (sendbuf);
1380                 return(ret);
1381         }
1382         
1383         *sent = ret;
1384         return(0);
1385 }