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