Implemented a stub for WSARecvFrom.
[wine] / dlls / winsock / socket.c
1 /*
2  * based on Windows Sockets 1.1 specs
3  * (ftp.microsoft.com:/Advsys/winsock/spec11/WINSOCK.TXT)
4  * 
5  * (C) 1993,1994,1996,1997 John Brezak, Erik Bos, Alex Korobka.
6  *
7  * NOTE: If you make any changes to fix a particular app, make sure 
8  * they don't break something else like Netscape or telnet and ftp 
9  * clients and servers (www.winsite.com got a lot of those).
10  *
11  * NOTE 2: Many winsock structs such as servent, hostent, protoent, ...
12  * are used with 1-byte alignment for Win16 programs and 4-byte alignment
13  * for Win32 programs in winsock.h. winsock2.h uses forced 4-byte alignment.
14  * So we have non-forced (just as MSDN) ws_XXXXent (winsock.h), 4-byte forced
15  * ws_XXXXent32 (winsock2.h) and 1-byte forced ws_XXXXent16 (winsock16.h).
16  */
17  
18 #include "config.h"
19
20 #include <stdio.h>
21 #include <string.h>
22 #include <sys/types.h>
23 #ifdef HAVE_SYS_IPC_H
24 # include <sys/ipc.h>
25 #endif
26 #include <sys/ioctl.h>
27 #ifdef HAVE_SYS_FILIO_H
28 # include <sys/filio.h>
29 #endif
30 #ifdef HAVE_SYS_SOCKIO_H
31 # include <sys/sockio.h>
32 #endif
33
34 #if defined(__EMX__)
35 # include <sys/so_ioctl.h>
36 #endif
37
38 #ifdef HAVE_SYS_PARAM_H
39 # include <sys/param.h>
40 #endif
41
42 #ifdef HAVE_SYS_MSG_H
43 # include <sys/msg.h>
44 #endif
45 #ifdef HAVE_SYS_WAIT_H
46 # include <sys/wait.h>
47 #endif
48 #ifdef HAVE_SYS_SOCKET_H
49 #include <sys/socket.h>
50 #endif
51 #ifdef HAVE_NETINET_IN_H
52 # include <netinet/in.h>
53 #endif
54 #ifdef HAVE_NETINET_TCP_H
55 # include <netinet/tcp.h>
56 #endif
57 #ifdef HAVE_ARPA_INET_H
58 # include <arpa/inet.h>
59 #endif
60 #include <ctype.h>
61 #include <fcntl.h>
62 #include <errno.h>
63 #ifdef HAVE_SYS_ERRNO_H
64 #include <sys/errno.h>
65 #endif
66 #ifdef HAVE_NETDB_H
67 #include <netdb.h>
68 #endif
69 #include <unistd.h>
70 #include <stdlib.h>
71 #ifdef HAVE_ARPA_NAMESER_H
72 # include <arpa/nameser.h>
73 #endif
74 #ifdef HAVE_RESOLV_H
75 # include <resolv.h>
76 #endif
77 #ifdef HAVE_NET_IF_H
78 # include <net/if.h>
79 #endif
80 #ifdef HAVE_IPX_GNU
81 # include <netipx/ipx.h>
82 # define HAVE_IPX
83 #endif
84 #ifdef HAVE_IPX_LINUX
85 # include <asm/types.h>
86 # include <linux/ipx.h>
87 # define HAVE_IPX
88 #endif
89
90 #include "wine/winbase16.h"
91 #include "wingdi.h"
92 #include "winuser.h"
93 #include "winsock2.h"
94 #include "wine/winsock16.h"
95 #include "winnt.h"
96 #include "heap.h"
97 #include "wine/port.h"
98 #include "services.h"
99 #include "server.h"
100 #include "file.h"
101 #include "debugtools.h"
102
103
104 DEFAULT_DEBUG_CHANNEL(winsock);
105
106 /* critical section to protect some non-rentrant net function */
107 extern CRITICAL_SECTION csWSgetXXXbyYYY;
108
109 #define DEBUG_SOCKADDR 0
110 #define dump_sockaddr(a) \
111         DPRINTF("sockaddr_in: family %d, address %s, port %d\n", \
112                         ((struct sockaddr_in *)a)->sin_family, \
113                         inet_ntoa(((struct sockaddr_in *)a)->sin_addr), \
114                         ntohs(((struct sockaddr_in *)a)->sin_port))
115
116 /* ----------------------------------- internal data */
117
118 /* ws_... struct conversion flags */
119
120 #define WS_DUP_LINEAR           0x0001
121 #define WS_DUP_NATIVE           0x0000          /* not used anymore */
122 #define WS_DUP_OFFSET           0x0002          /* internal pointers are offsets */
123 #define WS_DUP_SEGPTR           0x0004          /* internal pointers are SEGPTRs */
124                                                 /* by default, internal pointers are linear */
125 typedef struct          /* WSAAsyncSelect() control struct */
126 {
127   HANDLE      service, event, sock;
128   HWND        hWnd;
129   UINT        uMsg;
130   LONG        lEvent;
131 } ws_select_info;  
132
133 #define WS_MAX_SOCKETS_PER_PROCESS      128     /* reasonable guess */
134 #define WS_MAX_UDP_DATAGRAM             1024
135
136 #define WS_ACCEPT_QUEUE 6
137
138 #define PROCFS_NETDEV_FILE   "/proc/net/dev" /* Points to the file in the /proc fs 
139                                                 that lists the network devices.
140                                                 Do we need an #ifdef LINUX for this? */
141
142 static volatile HANDLE accept_old[WS_ACCEPT_QUEUE], accept_new[WS_ACCEPT_QUEUE];
143
144 static void *he_buffer;          /* typecast for Win16/32 ws_hostent */
145 static void *se_buffer;          /* typecast for Win16/32 ws_servent */
146 static void *pe_buffer;          /* typecast for Win16/32 ws_protoent */
147 static char* local_buffer;       /* allocated from SEGPTR heap */
148 static char* dbuffer;            /* buffer for dummies (32 bytes) */
149 static INT num_startup;          /* reference counter */
150 static FARPROC blocking_hook;
151
152 /* function prototypes */
153 int WS_dup_he(struct hostent* p_he, int flag);
154 int WS_dup_pe(struct protoent* p_pe, int flag);
155 int WS_dup_se(struct servent* p_se, int flag);
156
157 typedef void    WIN_hostent;
158 typedef void    WIN_protoent;
159 typedef void    WIN_servent;
160
161 int WSAIOCTL_GetInterfaceCount(void);
162 int WSAIOCTL_GetInterfaceName(int intNumber, char *intName);
163
164 UINT16 wsaErrno(void);
165 UINT16 wsaHerrno(int errnr);
166                                                       
167 static HANDLE   _WSHeap = 0;
168
169 #define WS_ALLOC(size) \
170         HeapAlloc(_WSHeap, HEAP_ZERO_MEMORY, (size) )
171 #define WS_FREE(ptr) \
172         HeapFree(_WSHeap, 0, (ptr) )
173
174 static INT         _ws_sock_ops[] =
175        { WS_SO_DEBUG, WS_SO_REUSEADDR, WS_SO_KEEPALIVE, WS_SO_DONTROUTE,
176          WS_SO_BROADCAST, WS_SO_LINGER, WS_SO_OOBINLINE, WS_SO_SNDBUF,
177          WS_SO_RCVBUF, WS_SO_ERROR, WS_SO_TYPE,
178 #ifdef SO_RCVTIMEO
179          WS_SO_RCVTIMEO,
180 #endif
181 #ifdef SO_SNDTIMEO
182          WS_SO_SNDTIMEO,
183 #endif
184          0 };
185 static int           _px_sock_ops[] =
186        { SO_DEBUG, SO_REUSEADDR, SO_KEEPALIVE, SO_DONTROUTE, SO_BROADCAST,
187          SO_LINGER, SO_OOBINLINE, SO_SNDBUF, SO_RCVBUF, SO_ERROR, SO_TYPE,
188 #ifdef SO_RCVTIMEO
189          SO_RCVTIMEO,
190 #endif
191 #ifdef SO_SNDTIMEO
192          SO_SNDTIMEO,
193 #endif
194         };
195
196 static INT _ws_tcp_ops[] = {
197 #ifdef TCP_NODELAY
198         WS_TCP_NODELAY,
199 #endif
200         0
201 };
202 static int _px_tcp_ops[] = {
203 #ifdef TCP_NODELAY
204         TCP_NODELAY,
205 #endif
206         0
207 };
208
209 /* set last error code from NT status without mapping WSA errors */
210 inline static unsigned int set_error( unsigned int err )
211 {
212     if (err)
213     {
214         /* do not map WSA errors */
215         if ((err < WSABASEERR) || (err >= 0x10000000)) err = RtlNtStatusToDosError(err);
216         SetLastError( err );
217     }
218     return err;
219 }
220
221 static char* check_buffer(int size);
222
223 static int _get_sock_fd(SOCKET s)
224 {
225     int fd = FILE_GetUnixHandle( s, GENERIC_READ );
226     if (fd == -1)
227         FIXME("handle %d is not a socket (GLE %ld)\n",s,GetLastError());
228     return fd;    
229 }
230
231 static void _enable_event(SOCKET s, unsigned int event,
232                           unsigned int sstate, unsigned int cstate)
233 {
234     SERVER_START_REQ( enable_socket_event )
235     {
236         req->handle = s;
237         req->mask   = event;
238         req->sstate = sstate;
239         req->cstate = cstate;
240         SERVER_CALL();
241     }
242     SERVER_END_REQ;
243 }
244
245 static int _is_blocking(SOCKET s)
246 {
247     int ret;
248     SERVER_START_REQ( get_socket_event )
249     {
250         req->handle  = s;
251         req->service = FALSE;
252         req->s_event = 0;
253         req->c_event = 0;
254         SERVER_CALL();
255         ret = (req->state & WS_FD_NONBLOCKING) == 0;
256     }
257     SERVER_END_REQ;
258     return ret;
259 }
260
261 static unsigned int _get_sock_mask(SOCKET s)
262 {
263     unsigned int ret;
264     SERVER_START_REQ( get_socket_event )
265     {
266         req->handle  = s;
267         req->service = FALSE;
268         req->s_event = 0;
269         req->c_event = 0;
270         SERVER_CALL();
271         ret = req->mask;
272     }
273     SERVER_END_REQ;
274     return ret;
275 }
276
277 static void _sync_sock_state(SOCKET s)
278 {
279     /* do a dummy wineserver request in order to let
280        the wineserver run through its select loop once */
281     (void)_is_blocking(s);
282 }
283
284 static int _get_sock_error(SOCKET s, unsigned int bit)
285 {
286     int ret;
287     SERVER_START_VAR_REQ( get_socket_event, FD_MAX_EVENTS*sizeof(int) )
288     {
289         req->handle  = s;
290         req->service = FALSE;
291         req->s_event = 0;
292         req->c_event = 0;
293         SERVER_CALL();
294         ret = *((int *)server_data_ptr(req) + bit);
295     }
296     SERVER_END_VAR_REQ;
297     return ret;
298 }
299
300 static void WINSOCK_DeleteIData(void)
301 {
302     /* delete scratch buffers */
303
304     if (he_buffer) SEGPTR_FREE(he_buffer);
305     if (se_buffer) SEGPTR_FREE(se_buffer);
306     if (pe_buffer) SEGPTR_FREE(pe_buffer);
307     if (local_buffer) SEGPTR_FREE(local_buffer);
308     if (dbuffer) SEGPTR_FREE(dbuffer);
309     he_buffer = NULL;
310     se_buffer = NULL;
311     pe_buffer = NULL;
312     local_buffer = NULL;
313     dbuffer = NULL;
314     num_startup = 0;
315 }
316
317 /***********************************************************************
318  *              WSOCK32_LibMain (WS2_32.init)
319  */
320 BOOL WINAPI WSOCK32_LibMain(HINSTANCE hInstDLL, DWORD fdwReason, LPVOID fImpLoad)
321 {
322     TRACE("0x%x 0x%lx %p\n", hInstDLL, fdwReason, fImpLoad);
323     switch (fdwReason) {
324     case DLL_PROCESS_DETACH:
325         WINSOCK_DeleteIData();
326         break;
327     }
328     return TRUE;
329 }
330
331 /***********************************************************************
332  *          convert_sockopt()
333  *
334  * Converts socket flags from Windows format.
335  * Return 1 if converted, 0 if not (error).
336  */
337 static int convert_sockopt(INT *level, INT *optname)
338 {
339   int i;
340   switch (*level)
341   {
342      case WS_SOL_SOCKET:
343         *level = SOL_SOCKET;
344         for(i=0; _ws_sock_ops[i]; i++)
345             if( _ws_sock_ops[i] == *optname ) break;
346         if( _ws_sock_ops[i] ) {
347             *optname = _px_sock_ops[i];
348             return 1;
349         }
350         FIXME("Unknown SOL_SOCKET optname 0x%x\n", *optname);
351         break;
352      case WS_IPPROTO_TCP:
353         *level = IPPROTO_TCP;
354         for(i=0; _ws_tcp_ops[i]; i++)
355                 if ( _ws_tcp_ops[i] == *optname ) break;
356         if( _ws_tcp_ops[i] ) {
357             *optname = _px_tcp_ops[i];
358             return 1;
359         }
360         FIXME("Unknown IPPROTO_TCP optname 0x%x\n", *optname);
361         break;
362   }
363   return 0;
364 }
365
366 /* ----------------------------------- Per-thread info (or per-process?) */
367
368 static int wsi_strtolo(const char* name, const char* opt)
369 {
370     /* Stuff a lowercase copy of the string into the local buffer */
371
372     int i = strlen(name) + 2;
373     char* p = check_buffer(i + ((opt)?strlen(opt):0));
374
375     if( p )
376     {
377         do *p++ = tolower(*name); while(*name++);
378         i = (p - local_buffer);
379         if( opt ) do *p++ = tolower(*opt); while(*opt++);
380         return i;
381     }
382     return 0;
383 }
384
385 static fd_set* fd_set_import( fd_set* fds, void* wsfds, int* highfd, int lfd[], BOOL b32 )
386 {
387     /* translate Winsock fd set into local fd set */
388
389     if( wsfds ) 
390     { 
391 #define wsfds16 ((ws_fd_set16*)wsfds)
392 #define wsfds32 ((ws_fd_set32*)wsfds)
393         int i, count;
394
395         FD_ZERO(fds);
396         count = b32 ? wsfds32->fd_count : wsfds16->fd_count;
397
398         for( i = 0; i < count; i++ )
399         {
400              int s = (b32) ? wsfds32->fd_array[i]
401                            : wsfds16->fd_array[i];
402              int fd = _get_sock_fd(s);
403              if (fd != -1)
404              {
405                     lfd[ i ] = fd;
406                     if( fd > *highfd ) *highfd = fd;
407                     FD_SET(fd, fds);
408              }
409              else lfd[ i ] = -1;
410         }
411 #undef wsfds32
412 #undef wsfds16
413         return fds;
414     }
415     return NULL;
416 }
417
418 inline static int sock_error_p(int s)
419 {
420     unsigned int optval, optlen;
421
422     optlen = sizeof(optval);
423     getsockopt(s, SOL_SOCKET, SO_ERROR, (void *) &optval, &optlen);
424     if (optval) WARN("\t[%i] error: %d\n", s, optval);
425     return optval != 0;
426 }
427
428 static int fd_set_export( fd_set* fds, fd_set* exceptfds, void* wsfds, int lfd[], BOOL b32 )
429 {
430     int num_err = 0;
431
432     /* translate local fd set into Winsock fd set, adding
433      * errors to exceptfds (only if app requested it) */
434
435     if( wsfds )
436     {
437 #define wsfds16 ((ws_fd_set16*)wsfds)
438 #define wsfds32 ((ws_fd_set32*)wsfds)
439         int i, j, count = (b32) ? wsfds32->fd_count : wsfds16->fd_count;
440
441         for( i = 0, j = 0; i < count; i++ )
442         {
443             if( lfd[i] >= 0 )
444             {
445                 int fd = lfd[i];
446                 if( FD_ISSET(fd, fds) )
447                 {
448                     if ( exceptfds && sock_error_p(fd) )
449                     {
450                         FD_SET(fd, exceptfds);
451                         num_err++;
452                     }
453                     else if( b32 )
454                              wsfds32->fd_array[j++] = wsfds32->fd_array[i];
455                          else
456                              wsfds16->fd_array[j++] = wsfds16->fd_array[i];
457                 }
458                 close(fd);
459                 lfd[i] = -1;
460             }
461         }
462
463         if( b32 ) wsfds32->fd_count = j;
464         else wsfds16->fd_count = j;
465
466         TRACE("\n");
467 #undef wsfds32
468 #undef wsfds16
469     }
470     return num_err;
471 }
472
473 static void fd_set_unimport( void* wsfds, int lfd[], BOOL b32 )
474 {
475     if ( wsfds )
476     {
477 #define wsfds16 ((ws_fd_set16*)wsfds)
478 #define wsfds32 ((ws_fd_set32*)wsfds)
479         int i, count = (b32) ? wsfds32->fd_count : wsfds16->fd_count;
480
481         for( i = 0; i < count; i++ )
482             if ( lfd[i] >= 0 )
483                 close(lfd[i]);
484
485         TRACE("\n");
486 #undef wsfds32
487 #undef wsfds16
488     }
489 }
490
491 static int do_block( int fd, int mask )
492 {
493     fd_set fds[3];
494     int i, r;
495
496     FD_ZERO(&fds[0]);
497     FD_ZERO(&fds[1]);
498     FD_ZERO(&fds[2]);
499     for (i=0; i<3; i++)
500         if (mask & (1<<i))
501             FD_SET(fd, &fds[i]);
502     i = select( fd+1, &fds[0], &fds[1], &fds[2], NULL );
503     if (i <= 0) return -1;
504     r = 0;
505     for (i=0; i<3; i++)
506         if (FD_ISSET(fd, &fds[i]))
507             r |= 1<<i;
508     return r;
509 }
510
511 void* __ws_memalloc( int size )
512 {
513     return WS_ALLOC(size);
514 }
515
516 void __ws_memfree(void* ptr)
517 {
518     WS_FREE(ptr);
519 }
520
521
522 /* ----------------------------------- API ----- 
523  *
524  * Init / cleanup / error checking.
525  */
526
527 /***********************************************************************
528  *      WSAStartup                      (WINSOCK.115)
529  *
530  * Create socket control struct, attach it to the global list and
531  * update a pointer in the task struct.
532  */
533 INT16 WINAPI WSAStartup16(UINT16 wVersionRequested, LPWSADATA lpWSAData)
534 {
535     WSADATA WINSOCK_data = { 0x0101, 0x0101,
536                           "WINE Sockets 1.1",
537                         #ifdef linux
538                                 "Linux/i386",
539                         #elif defined(__NetBSD__)
540                                 "NetBSD/i386",
541                         #elif defined(sunos)
542                                 "SunOS",
543                         #elif defined(__FreeBSD__)
544                                 "FreeBSD",
545                         #elif defined(__OpenBSD__)
546                                 "OpenBSD/i386",
547                         #else
548                                 "Unknown",
549                         #endif
550                            WS_MAX_SOCKETS_PER_PROCESS,
551                            WS_MAX_UDP_DATAGRAM, (SEGPTR)NULL };
552
553     TRACE("verReq=%x\n", wVersionRequested);
554
555     if (LOBYTE(wVersionRequested) < 1 || (LOBYTE(wVersionRequested) == 1 &&
556         HIBYTE(wVersionRequested) < 1)) return WSAVERNOTSUPPORTED;
557
558     if (!lpWSAData) return WSAEINVAL;
559
560     /* initialize socket heap */
561
562     if( !_WSHeap )
563     {
564         _WSHeap = HeapCreate(HEAP_ZERO_MEMORY, 8120, 32768);
565         if( !_WSHeap )
566         {
567             ERR("Fatal: failed to create WinSock heap\n");
568             return 0;
569         }
570     }
571     if( _WSHeap == 0 ) return WSASYSNOTREADY;
572
573     num_startup++;
574
575     /* return winsock information */
576
577     memcpy(lpWSAData, &WINSOCK_data, sizeof(WINSOCK_data));
578
579     TRACE("succeeded\n");
580     return 0;
581 }
582
583 /***********************************************************************
584  *      WSAStartup              (WS2_32.115)
585  */
586 INT WINAPI WSAStartup(UINT wVersionRequested, LPWSADATA lpWSAData)
587 {
588     WSADATA WINSOCK_data = { 0x0202, 0x0202,
589                           "WINE Sockets 2.0",
590                         #ifdef linux
591                                 "Linux/i386",
592                         #elif defined(__NetBSD__)
593                                 "NetBSD/i386",
594                         #elif defined(sunos)
595                                 "SunOS",
596                         #elif defined(__FreeBSD__)
597                                 "FreeBSD",
598                         #elif defined(__OpenBSD__)
599                                 "OpenBSD/i386",
600                         #else
601                                 "Unknown",
602                         #endif
603                            WS_MAX_SOCKETS_PER_PROCESS,
604                            WS_MAX_UDP_DATAGRAM, (SEGPTR)NULL };
605
606     TRACE("verReq=%x\n", wVersionRequested);
607
608     if (LOBYTE(wVersionRequested) < 1)
609         return WSAVERNOTSUPPORTED;
610
611     if (!lpWSAData) return WSAEINVAL;
612
613     /* initialize socket heap */
614
615     if( !_WSHeap )
616     {
617         _WSHeap = HeapCreate(HEAP_ZERO_MEMORY, 8120, 32768);
618         if( !_WSHeap )
619         {
620             ERR("Fatal: failed to create WinSock heap\n");
621             return 0;
622         }
623     }
624     if( _WSHeap == 0 ) return WSASYSNOTREADY;
625
626     num_startup++;
627
628     /* return winsock information */
629     memcpy(lpWSAData, &WINSOCK_data, sizeof(WINSOCK_data));
630
631     /* that's the whole of the negotiation for now */
632     lpWSAData->wVersion = wVersionRequested;
633
634     TRACE("succeeded\n");
635     return 0;
636 }
637
638
639 /***********************************************************************
640  *      WSACleanup                      (WINSOCK.116)
641  */
642 INT WINAPI WSACleanup(void)
643 {
644     if (num_startup)
645     {
646         if (--num_startup > 0) return 0;
647         WINSOCK_DeleteIData();
648         return 0;
649     }
650     SetLastError(WSANOTINITIALISED);
651     return SOCKET_ERROR;
652 }
653
654
655 /***********************************************************************
656  *      WSAGetLastError         (WINSOCK.111)
657  *      WSAGetLastError         (WS2_32.111)
658  */
659 INT WINAPI WSAGetLastError(void)
660 {
661         return GetLastError();
662 }
663
664 /***********************************************************************
665  *      WSASetLastError         (WS2_32.112)
666  */
667 void WINAPI WSASetLastError(INT iError) {
668     SetLastError(iError);
669 }
670
671 /***********************************************************************
672  *      WSASetLastError         (WINSOCK.112)
673  */
674 void WINAPI WSASetLastError16(INT16 iError)
675 {
676     WSASetLastError(iError);
677 }
678
679 static char* check_buffer(int size)
680 {
681     static int local_buflen;
682
683     if (local_buffer)
684     {
685         if (local_buflen >= size ) return local_buffer;
686         SEGPTR_FREE(local_buffer);
687     }
688     local_buffer = SEGPTR_ALLOC((local_buflen = size));
689     return local_buffer;
690 }
691
692 static struct ws_hostent* check_buffer_he(int size)
693 {
694     static int he_len;
695     if (he_buffer)
696     {
697         if (he_len >= size ) return he_buffer;
698         SEGPTR_FREE(he_buffer);
699     }
700     he_buffer = SEGPTR_ALLOC((he_len = size));
701     return he_buffer;
702 }
703
704 static void* check_buffer_se(int size)
705 {
706     static int se_len;
707     if (se_buffer)
708     {
709         if (se_len >= size ) return se_buffer;
710         SEGPTR_FREE(se_buffer);
711     }
712     se_buffer = SEGPTR_ALLOC((se_len = size));
713     return se_buffer;
714 }
715
716 static struct ws_protoent* check_buffer_pe(int size)
717 {
718     static int pe_len;
719     if (pe_buffer)
720     {
721         if (pe_len >= size ) return pe_buffer;
722         SEGPTR_FREE(pe_buffer);
723     }
724     pe_buffer = SEGPTR_ALLOC((pe_len = size));
725     return pe_buffer;
726 }
727
728 /* ----------------------------------- i/o APIs */
729
730 /***********************************************************************
731  *              accept          (WS2_32.1)
732  */
733 static void WSOCK32_async_accept(SOCKET s, SOCKET as)
734 {
735     int q;
736     /* queue socket for WSAAsyncSelect */
737     for (q=0; q<WS_ACCEPT_QUEUE; q++)
738         if (InterlockedCompareExchange((PVOID*)&accept_old[q], (PVOID)s, (PVOID)0) == (PVOID)0)
739             break;
740     if (q<WS_ACCEPT_QUEUE)
741         accept_new[q] = as;
742     else
743         ERR("accept queue too small\n");
744     /* now signal our AsyncSelect handler */
745     _enable_event(s, WS_FD_SERVEVENT, 0, 0);
746 }
747
748 /**********************************************************************/
749
750 SOCKET WINAPI WSOCK32_accept(SOCKET s, struct sockaddr *addr,
751                                  INT *addrlen32)
752 {
753 #ifdef HAVE_IPX
754     struct ws_sockaddr_ipx*  addr2 = (struct ws_sockaddr_ipx *)addr;
755 #endif
756     int fd = _get_sock_fd(s);
757
758     TRACE("socket %04x\n", (UINT16)s );
759     if (fd != -1)
760     {
761         SOCKET as;
762         if (_is_blocking(s))
763         {
764             /* block here */
765             do_block(fd, 5);
766             _sync_sock_state(s); /* let wineserver notice connection */
767             /* retrieve any error codes from it */
768             SetLastError(_get_sock_error(s, FD_ACCEPT_BIT));
769             /* FIXME: care about the error? */
770         }
771         close(fd);
772         SERVER_START_REQ( accept_socket )
773         {
774             req->lhandle = s;
775             req->access  = GENERIC_READ|GENERIC_WRITE|SYNCHRONIZE;
776             req->inherit = TRUE;
777             set_error( SERVER_CALL() );
778             as = (SOCKET)req->handle;
779         }
780         SERVER_END_REQ;
781         if (as)
782         {
783             unsigned omask = _get_sock_mask( s );
784             int fd = _get_sock_fd( as );
785             if( getpeername(fd, addr, addrlen32) != -1 )
786             {
787 #ifdef HAVE_IPX
788                 if (addr && ((struct sockaddr_ipx *)addr)->sipx_family == AF_IPX) {
789                     addr = (struct sockaddr *)
790                                 malloc(addrlen32 ? *addrlen32 : sizeof(*addr2));
791                     memcpy(addr, addr2,
792                                 addrlen32 ? *addrlen32 : sizeof(*addr2));
793                     addr2->sipx_family = WS_AF_IPX;
794                     addr2->sipx_network = ((struct sockaddr_ipx *)addr)->sipx_network;
795                     addr2->sipx_port = ((struct sockaddr_ipx *)addr)->sipx_port;
796                     memcpy(addr2->sipx_node,
797                         ((struct sockaddr_ipx *)addr)->sipx_node, IPX_NODE_LEN);
798                     free(addr);
799                 }
800 #endif
801             } else SetLastError(wsaErrno());
802             close(fd);
803             if (omask & WS_FD_SERVEVENT)
804                 WSOCK32_async_accept(s, as);
805             return as;
806         }
807     }
808     return INVALID_SOCKET;
809 }
810
811 /***********************************************************************
812  *              accept          (WINSOCK.1)
813  */
814 SOCKET16 WINAPI WINSOCK_accept16(SOCKET16 s, struct sockaddr* addr,
815                                  INT16* addrlen16 )
816 {
817     INT addrlen32 = addrlen16 ? *addrlen16 : 0;
818     SOCKET retSocket = WSOCK32_accept( s, addr, &addrlen32 );
819     if( addrlen16 ) *addrlen16 = (INT16)addrlen32;
820     return (SOCKET16)retSocket;
821 }
822
823 /***********************************************************************
824  *              bind                    (WS2_32.2)
825  */
826 INT WINAPI WSOCK32_bind(SOCKET s, struct sockaddr *name, INT namelen)
827 {
828 #ifdef HAVE_IPX
829     struct ws_sockaddr_ipx*  name2 = (struct ws_sockaddr_ipx *)name;
830 #endif
831     int fd = _get_sock_fd(s);
832
833     TRACE("socket %04x, ptr %8x, length %d\n", s, (int) name, namelen);
834 #if DEBUG_SOCKADDR
835     dump_sockaddr(name);
836 #endif
837
838     if (fd != -1)
839     {
840       /* FIXME: what family does this really map to on the Unix side? */
841       if (name && ((struct ws_sockaddr_ipx *)name)->sipx_family == WS_AF_PUP)
842         ((struct ws_sockaddr_ipx *)name)->sipx_family = AF_UNSPEC;
843 #ifdef HAVE_IPX
844       else if (name &&
845                 ((struct ws_sockaddr_ipx *)name)->sipx_family == WS_AF_IPX)
846       {
847         name = (struct sockaddr *) malloc(sizeof(struct sockaddr_ipx));
848         memset(name, '\0', sizeof(struct sockaddr_ipx));
849         ((struct sockaddr_ipx *)name)->sipx_family = AF_IPX;
850         ((struct sockaddr_ipx *)name)->sipx_port = name2->sipx_port;
851         ((struct sockaddr_ipx *)name)->sipx_network = name2->sipx_network;
852         memcpy(((struct sockaddr_ipx *)name)->sipx_node,
853                 name2->sipx_node, IPX_NODE_LEN);
854         namelen = sizeof(struct sockaddr_ipx);
855       }
856 #endif
857       if ( namelen >= sizeof(*name) ) 
858       {
859         if ( name && (((struct ws_sockaddr_in *)name)->sin_family == AF_INET
860 #ifdef HAVE_IPX
861              || ((struct sockaddr_ipx *)name)->sipx_family == AF_IPX
862 #endif
863            ))
864         {
865           if ( bind(fd, name, namelen) < 0 ) 
866           {
867              int        loc_errno = errno;
868              WARN("\tfailure - errno = %i\n", errno);
869              errno = loc_errno;
870              switch(errno)
871              {
872                 case EBADF: SetLastError(WSAENOTSOCK); break;
873                 case EADDRNOTAVAIL: SetLastError(WSAEINVAL); break;
874                 default: SetLastError(wsaErrno());break;
875              }
876           }
877           else {
878 #ifdef HAVE_IPX
879             if (((struct sockaddr_ipx *)name)->sipx_family == AF_IPX)
880                 free(name);
881 #endif
882             close(fd);
883             return 0; /* success */
884           }
885         } else SetLastError(WSAEAFNOSUPPORT);
886       } else SetLastError(WSAEFAULT);
887 #ifdef HAVE_IPX
888       if (name && ((struct sockaddr_ipx *)name)->sipx_family == AF_IPX)
889         free(name);
890 #endif
891       close(fd);
892     }
893     return SOCKET_ERROR;
894 }
895
896 /***********************************************************************
897  *              bind                    (WINSOCK.2)
898  */
899 INT16 WINAPI WINSOCK_bind16(SOCKET16 s, struct sockaddr *name, INT16 namelen)
900 {
901   return (INT16)WSOCK32_bind( s, name, namelen );
902 }
903
904 /***********************************************************************
905  *              closesocket             (WS2_32.3)
906  */
907 INT WINAPI WSOCK32_closesocket(SOCKET s)
908 {
909     TRACE("socket %08x\n", s);
910     if (CloseHandle(s)) return 0;
911     return SOCKET_ERROR;
912 }
913
914 /***********************************************************************
915  *              closesocket           (WINSOCK.3)
916  */
917 INT16 WINAPI WINSOCK_closesocket16(SOCKET16 s)
918 {
919     return (INT16)WSOCK32_closesocket(s);
920 }
921
922 /***********************************************************************
923  *              connect         (WS2_32.4)
924  */
925 INT WINAPI WSOCK32_connect(SOCKET s, struct sockaddr *name, INT namelen)
926 {
927 #ifdef HAVE_IPX
928   struct ws_sockaddr_ipx*  name2 = (struct ws_sockaddr_ipx *)name;
929 #endif
930   int fd = _get_sock_fd(s);
931
932   TRACE("socket %04x, ptr %8x, length %d\n", s, (int) name, namelen);
933 #if DEBUG_SOCKADDR
934   dump_sockaddr(name);
935 #endif
936
937   if (fd != -1)
938   {
939     if (name && ((struct ws_sockaddr_ipx *)name)->sipx_family == WS_AF_PUP)
940         ((struct ws_sockaddr_ipx *)name)->sipx_family = AF_UNSPEC;
941 #ifdef HAVE_IPX
942     else if (name && ((struct ws_sockaddr_ipx *)name)->sipx_family == WS_AF_IPX)
943     {
944         name = (struct sockaddr *) malloc(sizeof(struct sockaddr_ipx));
945         memset(name, '\0', sizeof(struct sockaddr_ipx));
946         ((struct sockaddr_ipx *)name)->sipx_family = AF_IPX;
947         ((struct sockaddr_ipx *)name)->sipx_port = name2->sipx_port;
948         ((struct sockaddr_ipx *)name)->sipx_network = name2->sipx_network;
949         memcpy(((struct sockaddr_ipx *)name)->sipx_node,
950                 name2->sipx_node, IPX_NODE_LEN);
951         namelen = sizeof(struct sockaddr_ipx);
952     }
953 #endif
954     if (connect(fd, name, namelen) == 0) {
955         close(fd);
956         goto connect_success;
957     }
958     if (errno == EINPROGRESS)
959     {
960         /* tell wineserver that a connection is in progress */
961         _enable_event(s, FD_CONNECT|FD_READ|FD_WRITE,
962                       WS_FD_CONNECT|WS_FD_READ|WS_FD_WRITE,
963                       WS_FD_CONNECTED|WS_FD_LISTENING);
964         if (_is_blocking(s))
965         {
966             int result;
967             /* block here */
968             do_block(fd, 7);
969             _sync_sock_state(s); /* let wineserver notice connection */
970             /* retrieve any error codes from it */
971             result = _get_sock_error(s, FD_CONNECT_BIT);
972             if (result)
973                 SetLastError(result);
974             else {
975                 close(fd);
976                 goto connect_success;
977             }
978         }
979         else SetLastError(WSAEWOULDBLOCK);
980         close(fd);
981     }
982     else
983     {
984         SetLastError(wsaErrno());
985         close(fd);
986     }
987   }
988 #ifdef HAVE_IPX
989   if (name && ((struct sockaddr_ipx *)name)->sipx_family == AF_IPX)
990     free(name);
991 #endif
992   return SOCKET_ERROR;
993 connect_success:
994 #ifdef HAVE_IPX
995     if (((struct sockaddr_ipx *)name)->sipx_family == AF_IPX)
996         free(name);
997 #endif
998     _enable_event(s, FD_CONNECT|FD_READ|FD_WRITE,
999                   WS_FD_CONNECTED|WS_FD_READ|WS_FD_WRITE,
1000                   WS_FD_CONNECT|WS_FD_LISTENING);
1001     return 0; 
1002 }
1003
1004 /***********************************************************************
1005  *              connect               (WINSOCK.4)
1006  */
1007 INT16 WINAPI WINSOCK_connect16(SOCKET16 s, struct sockaddr *name, INT16 namelen)
1008 {
1009   return (INT16)WSOCK32_connect( s, name, namelen );
1010 }
1011
1012 /***********************************************************************
1013  *              getpeername             (WS2_32.5)
1014  */
1015 INT WINAPI WSOCK32_getpeername(SOCKET s, struct sockaddr *name,
1016                                    INT *namelen)
1017 {
1018 #ifdef HAVE_IPX
1019     struct ws_sockaddr_ipx*  name2 = (struct ws_sockaddr_ipx *)name;
1020 #endif
1021     int fd = _get_sock_fd(s);
1022
1023     TRACE("socket: %04x, ptr %8x, ptr %8x\n", s, (int) name, *namelen);
1024     if (fd != -1)
1025     {
1026         if (getpeername(fd, name, namelen) == 0) {
1027 #ifdef HAVE_IPX
1028             if (((struct ws_sockaddr_ipx *)name)->sipx_family == AF_IPX) {
1029                 name = (struct sockaddr *)
1030                                 malloc(namelen ? *namelen : sizeof(*name2));
1031                 memcpy(name, name2, namelen ? *namelen : sizeof(*name2));
1032                 name2->sipx_family = WS_AF_IPX;
1033                 name2->sipx_network = ((struct sockaddr_ipx *)name)->sipx_network;
1034                 name2->sipx_port = ((struct sockaddr_ipx *)name)->sipx_port;
1035                 memcpy(name2->sipx_node,
1036                         ((struct sockaddr_ipx *)name)->sipx_node, IPX_NODE_LEN);
1037                 free(name);
1038             }
1039 #endif
1040             close(fd);
1041             return 0; 
1042         }
1043         SetLastError(wsaErrno());
1044         close(fd);
1045     }
1046     return SOCKET_ERROR;
1047 }
1048
1049 /***********************************************************************
1050  *              getpeername             (WINSOCK.5)
1051  */
1052 INT16 WINAPI WINSOCK_getpeername16(SOCKET16 s, struct sockaddr *name,
1053                                    INT16 *namelen16)
1054 {
1055     INT namelen32 = *namelen16;
1056     INT retVal = WSOCK32_getpeername( s, name, &namelen32 );
1057
1058 #if DEBUG_SOCKADDR
1059     dump_sockaddr(name);
1060 #endif
1061
1062    *namelen16 = namelen32;
1063     return (INT16)retVal;
1064 }
1065
1066 /***********************************************************************
1067  *              getsockname             (WS2_32.6)
1068  */
1069 INT WINAPI WSOCK32_getsockname(SOCKET s, struct sockaddr *name,
1070                                    INT *namelen)
1071 {
1072 #ifdef HAVE_IPX
1073     struct ws_sockaddr_ipx*  name2 = (struct ws_sockaddr_ipx *)name;
1074 #endif
1075     int fd = _get_sock_fd(s);
1076
1077     TRACE("socket: %04x, ptr %8x, ptr %8x\n", s, (int) name, (int) *namelen);
1078     if (fd != -1)
1079     {
1080         if (getsockname(fd, name, namelen) == 0) {
1081 #ifdef HAVE_IPX
1082             if (((struct sockaddr_ipx *)name)->sipx_family == AF_IPX) {
1083                 name = (struct sockaddr *)
1084                                 malloc(namelen ? *namelen : sizeof(*name2));
1085                 memcpy(name, name2, namelen ? *namelen : sizeof(*name2));
1086                 name2->sipx_family = WS_AF_IPX;
1087                 name2->sipx_network = ((struct sockaddr_ipx *)name)->sipx_network;
1088                 name2->sipx_port = ((struct sockaddr_ipx *)name)->sipx_port;
1089                 memcpy(name2->sipx_node,
1090                         ((struct sockaddr_ipx *)name)->sipx_node, IPX_NODE_LEN);
1091                 free(name);
1092             }
1093 #endif
1094             close(fd);
1095             return 0; 
1096         }
1097         SetLastError(wsaErrno());
1098         close(fd);
1099     }
1100     return SOCKET_ERROR;
1101 }
1102
1103 /***********************************************************************
1104  *              getsockname             (WINSOCK.6)
1105  */
1106 INT16 WINAPI WINSOCK_getsockname16(SOCKET16 s, struct sockaddr *name,
1107                                    INT16 *namelen16)
1108 {
1109     INT retVal;
1110
1111     if( namelen16 )
1112     {
1113         INT namelen32 = *namelen16;
1114         retVal = WSOCK32_getsockname( s, name, &namelen32 );
1115        *namelen16 = namelen32;
1116
1117 #if DEBUG_SOCKADDR
1118     dump_sockaddr(name);
1119 #endif
1120
1121     }
1122     else retVal = SOCKET_ERROR;
1123     return (INT16)retVal;
1124 }
1125
1126
1127 /***********************************************************************
1128  *              getsockopt              (WS2_32.7)
1129  */
1130 INT WINAPI WSOCK32_getsockopt(SOCKET s, INT level, 
1131                                   INT optname, char *optval, INT *optlen)
1132 {
1133     int fd = _get_sock_fd(s);
1134
1135     TRACE("socket: %04x, opt 0x%x, ptr %8x, len %d\n", s, level, (int) optval, (int) *optlen);
1136     if (fd != -1)
1137     {
1138         if (!convert_sockopt(&level, &optname)) {
1139             SetLastError(WSAENOPROTOOPT);       /* Unknown option */
1140         } else {
1141             if (getsockopt(fd, (int) level, optname, optval, optlen) == 0 )
1142             {
1143                 close(fd);
1144                 return 0;
1145             }
1146             SetLastError((errno == EBADF) ? WSAENOTSOCK : wsaErrno());
1147         }
1148         close(fd);
1149     }
1150     return SOCKET_ERROR;
1151 }
1152
1153 /***********************************************************************
1154  *              getsockopt              (WINSOCK.7)
1155  */
1156 INT16 WINAPI WINSOCK_getsockopt16(SOCKET16 s, INT16 level,
1157                                   INT16 optname, char *optval, INT16 *optlen)
1158 {
1159     INT optlen32;
1160     INT *p = &optlen32;
1161     INT retVal;
1162     if( optlen ) optlen32 = *optlen; else p = NULL;
1163     retVal = WSOCK32_getsockopt( s, (UINT16)level, optname, optval, p );
1164     if( optlen ) *optlen = optlen32;
1165     return (INT16)retVal;
1166 }
1167
1168 /***********************************************************************
1169  *              htonl                   (WINSOCK.8)
1170  *              htonl                   (WS2_32.8)
1171  */
1172 u_long WINAPI WINSOCK_htonl(u_long hostlong)   { return( htonl(hostlong) ); }
1173 /***********************************************************************
1174  *              htons                   (WINSOCK.9)
1175  *              htons                   (WS2_32.9)
1176  */
1177 u_short WINAPI WINSOCK_htons(u_short hostshort) { return( htons(hostshort) ); }
1178 /***********************************************************************
1179  *              inet_addr               (WINSOCK.10)
1180  *              inet_addr               (WS2_32.11)
1181  */
1182 u_long WINAPI WINSOCK_inet_addr(char *cp)      { return( inet_addr(cp) ); }
1183 /***********************************************************************
1184  *              ntohl                   (WINSOCK.14)
1185  *              ntohl                   (WS2_32.14)
1186  */
1187 u_long WINAPI WINSOCK_ntohl(u_long netlong)    { return( ntohl(netlong) ); }
1188 /***********************************************************************
1189  *              ntohs                   (WINSOCK.15)
1190  *              ntohs                   (WS2_32.15)
1191  */
1192 u_short WINAPI WINSOCK_ntohs(u_short netshort)  { return( ntohs(netshort) ); }
1193
1194 /***********************************************************************
1195  *              inet_ntoa               (WS2_32.12)
1196  */
1197 char* WINAPI WSOCK32_inet_ntoa(struct in_addr in)
1198 {
1199   /* use "buffer for dummies" here because some applications have 
1200    * propensity to decode addresses in ws_hostent structure without 
1201    * saving them first...
1202    */
1203     char* s = inet_ntoa(in);
1204     if( s )
1205     {
1206         if( dbuffer == NULL ) {
1207             /* Yes, 16: 4*3 digits + 3 '.' + 1 '\0' */
1208             if((dbuffer = (char*) SEGPTR_ALLOC(16)) == NULL )
1209             {
1210                 SetLastError(WSAENOBUFS);
1211                 return NULL;
1212             }
1213         }
1214         strcpy(dbuffer, s);
1215         return dbuffer;
1216     }
1217     SetLastError(wsaErrno());
1218     return NULL;
1219 }
1220
1221 /***********************************************************************
1222  *              inet_ntoa               (WINSOCK.11)
1223  */
1224 SEGPTR WINAPI WINSOCK_inet_ntoa16(struct in_addr in)
1225 {
1226   char* retVal = WSOCK32_inet_ntoa(in);
1227   return SEGPTR_GET(retVal);
1228 }
1229
1230
1231 /**********************************************************************
1232  *              WSAIoctl                (WS2_32.50)
1233  *
1234  *
1235  *   FIXME:  Only SIO_GET_INTERFACE_LIST option implemented.
1236  */
1237 INT WINAPI WSAIoctl (SOCKET s,
1238                      DWORD   dwIoControlCode,
1239                      LPVOID  lpvInBuffer,
1240                      DWORD   cbInBuffer,
1241                      LPVOID  lpbOutBuffer,
1242                      DWORD   cbOutBuffer,
1243                      LPDWORD lpcbBytesReturned,
1244                      LPWSAOVERLAPPED lpOverlapped,
1245                      LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine)
1246 {
1247    int fd = _get_sock_fd(s);
1248
1249    if (fd != -1)
1250    {
1251       switch( dwIoControlCode )
1252       {
1253          case SIO_GET_INTERFACE_LIST:
1254          {
1255             INTERFACE_INFO* intArray = (INTERFACE_INFO*)lpbOutBuffer;
1256             int i, numInt;
1257             struct ifreq ifInfo;
1258             char ifName[512];
1259             
1260
1261             TRACE ("-> SIO_GET_INTERFACE_LIST request\n");
1262             
1263             numInt = WSAIOCTL_GetInterfaceCount(); 
1264             if (numInt < 0)
1265             {
1266                ERR ("Unable to open /proc filesystem to determine number of network interfaces!\n");
1267                close(fd);
1268                WSASetLastError(WSAEINVAL);
1269                return (SOCKET_ERROR);
1270             }
1271             
1272             for (i=0; i<numInt; i++)
1273             {
1274                if (!WSAIOCTL_GetInterfaceName(i, ifName))
1275                {
1276                   ERR ("Error parsing /proc filesystem!\n");
1277                   close(fd);
1278                   WSASetLastError(WSAEINVAL);
1279                   return (SOCKET_ERROR);
1280                }
1281                
1282                ifInfo.ifr_addr.sa_family = AF_INET; 
1283             
1284                /* IP Address */
1285                strcpy (ifInfo.ifr_name, ifName);
1286                if (ioctl(fd, SIOCGIFADDR, &ifInfo) < 0) 
1287                {
1288                   ERR ("Error obtaining IP address\n");
1289                   close(fd);
1290                   WSASetLastError(WSAEINVAL);
1291                   return (SOCKET_ERROR);
1292                }
1293                else
1294                {
1295                   struct ws_sockaddr_in *ipTemp = (struct ws_sockaddr_in *)&ifInfo.ifr_addr;
1296                
1297                   intArray->iiAddress.AddressIn.sin_family = AF_INET;
1298                   intArray->iiAddress.AddressIn.sin_port = ipTemp->sin_port;
1299                   intArray->iiAddress.AddressIn.sin_addr.ws_addr = ipTemp->sin_addr.S_un.S_addr;
1300                }
1301                
1302                /* Broadcast Address */
1303                strcpy (ifInfo.ifr_name, ifName);
1304                if (ioctl(fd, SIOCGIFBRDADDR, &ifInfo) < 0)
1305                {
1306                   ERR ("Error obtaining Broadcast IP address\n");
1307                   close(fd);
1308                   WSASetLastError(WSAEINVAL);
1309                   return (SOCKET_ERROR);
1310                }
1311                else
1312                {
1313                   struct ws_sockaddr_in *ipTemp = (struct ws_sockaddr_in *)&ifInfo.ifr_broadaddr;
1314                
1315                   intArray->iiBroadcastAddress.AddressIn.sin_family = AF_INET; 
1316                   intArray->iiBroadcastAddress.AddressIn.sin_port = ipTemp->sin_port;
1317                   intArray->iiBroadcastAddress.AddressIn.sin_addr.ws_addr = ipTemp->sin_addr.S_un.S_addr; 
1318                }
1319
1320                /* Subnet Mask */
1321                strcpy (ifInfo.ifr_name, ifName);
1322                if (ioctl(fd, SIOCGIFNETMASK, &ifInfo) < 0)
1323                {
1324                   ERR ("Error obtaining Subnet IP address\n");
1325                   close(fd);
1326                   WSASetLastError(WSAEINVAL);
1327                   return (SOCKET_ERROR);
1328                }
1329                else
1330                {
1331                   /* Trying to avoid some compile problems across platforms.
1332                      (Linux, FreeBSD, Solaris...) */
1333                   #ifndef ifr_netmask
1334                     #ifndef ifr_addr
1335                        intArray->iiNetmask.AddressIn.sin_family = AF_INET; 
1336                        intArray->iiNetmask.AddressIn.sin_port = 0;
1337                        intArray->iiNetmask.AddressIn.sin_addr.ws_addr = 0; 
1338                        ERR ("Unable to determine Netmask on your platform!\n");
1339                     #else
1340                        struct ws_sockaddr_in *ipTemp = (struct ws_sockaddr_in *)&ifInfo.ifr_addr;
1341             
1342                        intArray->iiNetmask.AddressIn.sin_family = AF_INET; 
1343                        intArray->iiNetmask.AddressIn.sin_port = ipTemp->sin_port;
1344                        intArray->iiNetmask.AddressIn.sin_addr.ws_addr = ipTemp->sin_addr.S_un.S_addr; 
1345                     #endif
1346                   #else
1347                      struct ws_sockaddr_in *ipTemp = (struct ws_sockaddr_in *)&ifInfo.ifr_netmask;
1348             
1349                      intArray->iiNetmask.AddressIn.sin_family = AF_INET; 
1350                      intArray->iiNetmask.AddressIn.sin_port = ipTemp->sin_port;
1351                      intArray->iiNetmask.AddressIn.sin_addr.ws_addr = ipTemp->sin_addr.S_un.S_addr; 
1352                   #endif
1353                }
1354                
1355                /* Socket Status Flags */
1356                strcpy(ifInfo.ifr_name, ifName);
1357                if (ioctl(fd, SIOCGIFFLAGS, &ifInfo) < 0) 
1358                {
1359                   ERR ("Error obtaining status flags for socket!\n");
1360                   close(fd);
1361                   WSASetLastError(WSAEINVAL);
1362                   return (SOCKET_ERROR);
1363                }
1364                else
1365                {
1366                   /* FIXME - Is this the right flag to use? */
1367                   intArray->iiFlags = ifInfo.ifr_flags;
1368                }
1369                intArray++; /* Prepare for another interface */
1370             }
1371             
1372             /* Calculate the size of the array being returned */
1373             *lpcbBytesReturned = sizeof(INTERFACE_INFO) * numInt;
1374             break;
1375          }
1376
1377          default:
1378          {
1379             WARN("\tunsupported WS_IOCTL cmd (%08lx)\n", dwIoControlCode);
1380             close(fd);
1381             WSASetLastError(WSAEOPNOTSUPP);
1382             return (SOCKET_ERROR);
1383          }
1384       }
1385
1386       /* Function executed with no errors */
1387       close(fd);
1388       return (0); 
1389    }
1390    else
1391    {
1392       WSASetLastError(WSAENOTSOCK);
1393       return (SOCKET_ERROR);
1394    }
1395 }
1396
1397
1398 /* 
1399   Helper function for WSAIoctl - Get count of the number of interfaces
1400   by parsing /proc filesystem.
1401 */
1402 int WSAIOCTL_GetInterfaceCount(void)
1403 {
1404    FILE *procfs;
1405    char buf[512];  /* Size doesn't matter, something big */
1406    int  intcnt=0;
1407  
1408  
1409    /* Open /proc filesystem file for network devices */ 
1410    procfs = fopen(PROCFS_NETDEV_FILE, "r");
1411    if (!procfs) 
1412    {
1413       /* If we can't open the file, return an error */
1414       return (-1);
1415    }
1416    
1417    /* Omit first two lines, they are only headers */
1418    fgets(buf, sizeof buf, procfs);      
1419    fgets(buf, sizeof buf, procfs);
1420
1421    while (fgets(buf, sizeof buf, procfs)) 
1422    {
1423       /* Each line in the file represents a network interface */
1424       intcnt++;
1425    }
1426
1427    fclose(procfs);
1428    return(intcnt);
1429 }
1430
1431
1432 /*
1433    Helper function for WSAIoctl - Get name of device from interface number
1434    by parsing /proc filesystem.
1435 */
1436 int WSAIOCTL_GetInterfaceName(int intNumber, char *intName)
1437 {
1438    FILE *procfs;
1439    char buf[512]; /* Size doesn't matter, something big */
1440    int  i;
1441
1442    /* Open /proc filesystem file for network devices */ 
1443    procfs = fopen(PROCFS_NETDEV_FILE, "r");
1444    if (!procfs) 
1445    {
1446       /* If we can't open the file, return an error */
1447       return (-1);
1448    }
1449    
1450    /* Omit first two lines, they are only headers */
1451    fgets(buf, sizeof(buf), procfs);     
1452    fgets(buf, sizeof(buf), procfs);
1453
1454    for (i=0; i<intNumber; i++)
1455    {
1456       /* Skip the lines that don't interest us. */
1457       fgets(buf, sizeof(buf), procfs);
1458    }
1459    fgets(buf, sizeof(buf), procfs); /* This is the line we want */
1460
1461    
1462    /* Parse out the line, grabbing only the name of the device
1463       to the intName variable 
1464       
1465       The Line comes in like this: (we only care about the device name)
1466       lo:   21970 377 0 0 0 0 0 0 21970 377 0 0 0 0 0 0
1467    */
1468    i=0; 
1469    while (isspace(buf[i])) /* Skip initial space(s) */
1470    {
1471       i++;
1472    }
1473
1474    while (buf[i]) 
1475    {
1476       if (isspace(buf[i]))
1477       {
1478          break;
1479       }
1480       
1481       if (buf[i] == ':')  /* FIXME: Not sure if this block (alias detection) works properly */
1482       {
1483          /* This interface could be an alias... */
1484          int hold = i;
1485          char *dotname = intName;
1486          *intName++ = buf[i++];
1487          
1488          while (isdigit(buf[i]))
1489          {
1490             *intName++ = buf[i++];
1491          }
1492          
1493          if (buf[i] != ':') 
1494          {
1495             /* ... It wasn't, so back up */
1496             i = hold;
1497             intName = dotname;
1498          }
1499  
1500          if (buf[i] == '\0')
1501          {
1502             fclose(procfs);
1503             return(FALSE);
1504          }
1505          
1506          i++;
1507          break;
1508       }
1509       
1510       *intName++ = buf[i++];
1511    }
1512    *intName++ = '\0';
1513
1514    fclose(procfs);
1515    return(TRUE);
1516  }
1517
1518
1519 /***********************************************************************
1520  *              ioctlsocket             (WS2_32.10)
1521  */
1522 INT WINAPI WSOCK32_ioctlsocket(SOCKET s, LONG cmd, ULONG *argp)
1523 {
1524   int fd = _get_sock_fd(s);
1525
1526   TRACE("socket %04x, cmd %08lx, ptr %8x\n", s, cmd, (unsigned) argp);
1527   if (fd != -1)
1528   {
1529     long        newcmd  = cmd;
1530
1531     switch( cmd )
1532     {
1533         case WS_FIONREAD:   
1534                 newcmd=FIONREAD; 
1535                 break;
1536
1537         case WS_FIONBIO:    
1538                 newcmd=FIONBIO;  
1539                 if( _get_sock_mask(s) )
1540                 {
1541                     /* AsyncSelect()'ed sockets are always nonblocking */
1542                     if (*argp) {
1543                         close(fd);
1544                         return 0;
1545                     }
1546                     SetLastError(WSAEINVAL); 
1547                     close(fd);
1548                     return SOCKET_ERROR; 
1549                 }
1550                 close(fd);
1551                 if (*argp)
1552                     _enable_event(s, 0, WS_FD_NONBLOCKING, 0);
1553                 else
1554                     _enable_event(s, 0, 0, WS_FD_NONBLOCKING);
1555                 return 0;
1556
1557         case WS_SIOCATMARK: 
1558                 newcmd=SIOCATMARK; 
1559                 break;
1560
1561         case WS_IOW('f',125,u_long): 
1562                 WARN("Warning: WS1.1 shouldn't be using async I/O\n");
1563                 SetLastError(WSAEINVAL); 
1564                 return SOCKET_ERROR;
1565         
1566         case SIOCGIFBRDADDR:
1567         case SIOCGIFNETMASK:
1568         case SIOCGIFADDR:
1569                 /* These don't need any special handling.  They are used by
1570                    WsControl, and are here to suppress an unecessary warning. */
1571                 break;
1572                    
1573         
1574         default:          
1575                 /* Netscape tries hard to use bogus ioctl 0x667e */
1576                 WARN("\tunknown WS_IOCTL cmd (%08lx)\n", cmd);
1577     }
1578     if( ioctl(fd, newcmd, (char*)argp ) == 0 )
1579     {
1580         close(fd);
1581         return 0;
1582     }
1583     SetLastError((errno == EBADF) ? WSAENOTSOCK : wsaErrno()); 
1584     close(fd);
1585   }
1586   return SOCKET_ERROR;
1587 }
1588
1589 /***********************************************************************
1590  *              ioctlsocket           (WINSOCK.12)
1591  */
1592 INT16 WINAPI WINSOCK_ioctlsocket16(SOCKET16 s, LONG cmd, ULONG *argp)
1593 {
1594     return (INT16)WSOCK32_ioctlsocket( s, cmd, argp );
1595 }
1596
1597
1598 /***********************************************************************
1599  *              listen          (WS2_32.13)
1600  */
1601 INT WINAPI WSOCK32_listen(SOCKET s, INT backlog)
1602 {
1603     int fd = _get_sock_fd(s);
1604
1605     TRACE("socket %04x, backlog %d\n", s, backlog);
1606     if (fd != -1)
1607     {
1608         if (listen(fd, backlog) == 0)
1609         {
1610             close(fd);
1611             _enable_event(s, FD_ACCEPT,
1612                           WS_FD_LISTENING,
1613                           WS_FD_CONNECT|WS_FD_CONNECTED);
1614             return 0;
1615         }
1616         SetLastError(wsaErrno());
1617     }
1618     else SetLastError(WSAENOTSOCK);
1619     return SOCKET_ERROR;
1620 }
1621
1622 /***********************************************************************
1623  *              listen          (WINSOCK.13)
1624  */
1625 INT16 WINAPI WINSOCK_listen16(SOCKET16 s, INT16 backlog)
1626 {
1627     return (INT16)WSOCK32_listen( s, backlog );
1628 }
1629
1630
1631 /***********************************************************************
1632  *              recv                    (WS2_32.16)
1633  */
1634 INT WINAPI WSOCK32_recv(SOCKET s, char *buf, INT len, INT flags)
1635 {
1636     int fd = _get_sock_fd(s);
1637
1638     TRACE("socket %04x, buf %8x, len %d, flags %d\n", s, (unsigned)buf, len, flags);
1639
1640     if (fd != -1)
1641     {
1642         INT length;
1643
1644         if (_is_blocking(s))
1645         {
1646             /* block here */
1647             /* FIXME: OOB and exceptfds? */
1648             do_block(fd, 1);
1649         }
1650         if ((length = recv(fd, buf, len, flags)) >= 0) 
1651         { 
1652             TRACE(" -> %i bytes\n", length);
1653
1654             close(fd);
1655             _enable_event(s, FD_READ, 0, 0);
1656             return length;
1657         }
1658         SetLastError(wsaErrno());
1659         close(fd);
1660     }
1661     else SetLastError(WSAENOTSOCK);
1662     WARN(" -> ERROR\n");
1663     return SOCKET_ERROR;
1664 }
1665
1666 /***********************************************************************
1667  *              recv                    (WINSOCK.16)
1668  */
1669 INT16 WINAPI WINSOCK_recv16(SOCKET16 s, char *buf, INT16 len, INT16 flags)
1670 {
1671     return (INT16)WSOCK32_recv( s, buf, len, flags );
1672 }
1673
1674
1675 /***********************************************************************
1676  *              recvfrom                (WS2_32.17)
1677  */
1678 INT WINAPI WSOCK32_recvfrom(SOCKET s, char *buf, INT len, INT flags, 
1679                                 struct sockaddr *from, INT *fromlen32)
1680 {
1681 #ifdef HAVE_IPX
1682     struct ws_sockaddr_ipx*  from2 = (struct ws_sockaddr_ipx *)from;
1683 #endif
1684     int fd = _get_sock_fd(s);
1685
1686     TRACE("socket %04x, ptr %08x, len %d, flags %d\n", s, (unsigned)buf, len, flags);
1687 #if DEBUG_SOCKADDR
1688     if( from ) dump_sockaddr(from);
1689     else DPRINTF("from = NULL\n");
1690 #endif
1691
1692     if (fd != -1)
1693     {
1694         int length;
1695
1696         if (_is_blocking(s))
1697         {
1698             /* block here */
1699             /* FIXME: OOB and exceptfds */
1700             do_block(fd, 1);
1701         }
1702         if ((length = recvfrom(fd, buf, len, flags, from, fromlen32)) >= 0)
1703         {
1704             TRACE(" -> %i bytes\n", length);
1705
1706 #ifdef HAVE_IPX
1707         if (from && ((struct sockaddr_ipx *)from)->sipx_family == AF_IPX) {
1708             from = (struct sockaddr *)
1709                                 malloc(fromlen32 ? *fromlen32 : sizeof(*from2));
1710             memcpy(from, from2, fromlen32 ? *fromlen32 : sizeof(*from2));
1711             from2->sipx_family = WS_AF_IPX;
1712             from2->sipx_network = ((struct sockaddr_ipx *)from)->sipx_network;
1713             from2->sipx_port = ((struct sockaddr_ipx *)from)->sipx_port;
1714             memcpy(from2->sipx_node,
1715                         ((struct sockaddr_ipx *)from)->sipx_node, IPX_NODE_LEN);
1716             free(from);
1717         }
1718 #endif
1719             close(fd);
1720             _enable_event(s, FD_READ, 0, 0);
1721             return length;
1722         }
1723         SetLastError(wsaErrno());
1724         close(fd);
1725     }
1726     else SetLastError(WSAENOTSOCK);
1727     WARN(" -> ERROR\n");
1728 #ifdef HAVE_IPX
1729     if (from && ((struct sockaddr_ipx *)from)->sipx_family == AF_IPX) {
1730         from = (struct sockaddr *)
1731                                 malloc(fromlen32 ? *fromlen32 : sizeof(*from2));
1732         memcpy(from, from2, fromlen32 ? *fromlen32 : sizeof(*from2));
1733         from2->sipx_family = WS_AF_IPX;
1734         from2->sipx_network = ((struct sockaddr_ipx *)from)->sipx_network;
1735         from2->sipx_port = ((struct sockaddr_ipx *)from)->sipx_port;
1736         memcpy(from2->sipx_node,
1737                 ((struct sockaddr_ipx *)from)->sipx_node, IPX_NODE_LEN);
1738         free(from);
1739     }
1740 #endif
1741     return SOCKET_ERROR;
1742 }
1743
1744 /***********************************************************************
1745  *              recvfrom                (WINSOCK.17)
1746  */
1747 INT16 WINAPI WINSOCK_recvfrom16(SOCKET16 s, char *buf, INT16 len, INT16 flags,
1748                                 struct sockaddr *from, INT16 *fromlen16)
1749 {
1750     INT fromlen32;
1751     INT *p = &fromlen32;
1752     INT retVal;
1753
1754     if( fromlen16 ) fromlen32 = *fromlen16; else p = NULL;
1755     retVal = WSOCK32_recvfrom( s, buf, len, flags, from, p );
1756     if( fromlen16 ) *fromlen16 = fromlen32;
1757     return (INT16)retVal;
1758 }
1759
1760 /***********************************************************************
1761  *              __ws_select
1762  */
1763 static INT __ws_select( BOOL b32, void *ws_readfds, void *ws_writefds, void *ws_exceptfds,
1764                           struct timeval *timeout )
1765 {
1766     int         highfd = 0;
1767     fd_set      readfds, writefds, exceptfds;
1768     fd_set     *p_read, *p_write, *p_except;
1769     int         readfd[FD_SETSIZE], writefd[FD_SETSIZE], exceptfd[FD_SETSIZE];
1770
1771     TRACE("read %p, write %p, excp %p\n", ws_readfds, ws_writefds, ws_exceptfds);
1772
1773     p_read = fd_set_import(&readfds, ws_readfds, &highfd, readfd, b32);
1774     p_write = fd_set_import(&writefds, ws_writefds, &highfd, writefd, b32);
1775     p_except = fd_set_import(&exceptfds, ws_exceptfds, &highfd, exceptfd, b32);
1776
1777     if( (highfd = select(highfd + 1, p_read, p_write, p_except, timeout)) > 0 )
1778     {
1779         fd_set_export(&readfds, p_except, ws_readfds, readfd, b32);
1780         fd_set_export(&writefds, p_except, ws_writefds, writefd, b32);
1781
1782         if (p_except && ws_exceptfds)
1783         {
1784 #define wsfds16 ((ws_fd_set16*)ws_exceptfds)
1785 #define wsfds32 ((ws_fd_set32*)ws_exceptfds)
1786             int i, j, count = (b32) ? wsfds32->fd_count : wsfds16->fd_count;
1787
1788             for (i = j = 0; i < count; i++)
1789             {
1790                 int fd = exceptfd[i];
1791                 if( fd >= 0 && FD_ISSET(fd, &exceptfds) )
1792                 {
1793                     if( b32 )
1794                         wsfds32->fd_array[j++] = wsfds32->fd_array[i];
1795                     else
1796                         wsfds16->fd_array[j++] = wsfds16->fd_array[i];
1797                 }
1798                 if( fd >= 0 ) close(fd);
1799                 exceptfd[i] = -1;
1800             }
1801             if( b32 )
1802                 wsfds32->fd_count = j;
1803             else
1804                 wsfds16->fd_count = j;
1805 #undef wsfds32
1806 #undef wsfds16
1807         }
1808         return highfd;
1809     }
1810     fd_set_unimport(ws_readfds, readfd, b32);
1811     fd_set_unimport(ws_writefds, writefd, b32);
1812     fd_set_unimport(ws_exceptfds, exceptfd, b32);
1813     if( ws_readfds ) ((ws_fd_set32*)ws_readfds)->fd_count = 0;
1814     if( ws_writefds ) ((ws_fd_set32*)ws_writefds)->fd_count = 0;
1815     if( ws_exceptfds ) ((ws_fd_set32*)ws_exceptfds)->fd_count = 0;
1816
1817     if( highfd == 0 ) return 0;
1818     SetLastError(wsaErrno());
1819     return SOCKET_ERROR;
1820 }
1821
1822 /***********************************************************************
1823  *              select                  (WINSOCK.18)
1824  */
1825 INT16 WINAPI WINSOCK_select16(INT16 nfds, ws_fd_set16 *ws_readfds,
1826                               ws_fd_set16 *ws_writefds, ws_fd_set16 *ws_exceptfds,
1827                               struct timeval *timeout)
1828 {
1829     return (INT16)__ws_select( FALSE, ws_readfds, ws_writefds, ws_exceptfds, timeout );
1830 }
1831
1832 /***********************************************************************
1833  *              select                  (WINSOCK.18)
1834  */
1835 INT WINAPI WSOCK32_select(INT nfds, ws_fd_set32 *ws_readfds,
1836                               ws_fd_set32 *ws_writefds, ws_fd_set32 *ws_exceptfds,
1837                               struct timeval *timeout)
1838 {
1839     /* struct timeval is the same for both 32- and 16-bit code */
1840     return (INT)__ws_select( TRUE, ws_readfds, ws_writefds, ws_exceptfds, timeout );
1841 }
1842
1843
1844 /***********************************************************************
1845  *              send                    (WS2_32.19)
1846  */
1847 INT WINAPI WSOCK32_send(SOCKET s, char *buf, INT len, INT flags)
1848 {
1849     int fd = _get_sock_fd(s);
1850
1851     TRACE("socket %04x, ptr %p, length %d, flags %d\n", s, buf, len, flags);
1852     if (fd != -1)
1853     {
1854         int     length;
1855
1856         if (_is_blocking(s))
1857         {
1858             /* block here */
1859             /* FIXME: exceptfds */
1860             do_block(fd, 2);
1861         }
1862         if ((length = send(fd, buf, len, flags)) < 0 ) 
1863         {
1864             SetLastError(wsaErrno());
1865             if( GetLastError() == WSAEWOULDBLOCK )
1866                 _enable_event(s, FD_WRITE, 0, 0);
1867         }
1868         else
1869         {
1870             close(fd);
1871             return length;
1872         }
1873         close(fd);
1874     }
1875     else SetLastError(WSAENOTSOCK);
1876     return SOCKET_ERROR;
1877 }
1878
1879 /***********************************************************************
1880  *              WSASend                 (WS2_32.72)
1881  */
1882 INT WINAPI WSASend( SOCKET s, LPWSABUF lpBuffers, DWORD dwBufferCount,
1883                     LPDWORD lpNumberOfBytesSent, DWORD dwFlags,
1884                     LPWSAOVERLAPPED lpOverlapped,
1885                     LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine )
1886 {
1887   INT iFlags = 0;
1888   INT rc = 0;
1889   DWORD dwCount;
1890
1891   /* Overlapped is not supported or checked for */
1892   FIXME( "(%u,%p,0x%lx,%p,0x%lx,%p,%p): semi stub\n", 
1893            s, lpBuffers, dwBufferCount, lpNumberOfBytesSent,
1894            dwFlags, lpOverlapped, lpCompletionRoutine );
1895
1896   /* Convert setup flags */
1897   if( dwFlags & MSG_DONTROUTE )
1898   {
1899     iFlags |= MSG_DONTROUTE;
1900   }
1901
1902   if( dwFlags & MSG_OOB )
1903   {
1904     iFlags |= MSG_OOB;
1905   }
1906
1907   /* Indicate nothing yet sent */
1908   *lpNumberOfBytesSent = 0;
1909
1910   /* Send all buffers with the same flags */
1911   for(dwCount = 0; dwCount < dwBufferCount; dwCount++ )
1912   {
1913     if( ( rc = WSOCK32_send( s, lpBuffers[ dwCount ].buf, 
1914                              lpBuffers[ dwCount ].len, iFlags ) ) != 0 )
1915     {
1916       break;
1917     }
1918
1919     /* Indicate that we've sent something */
1920     *lpNumberOfBytesSent += lpBuffers[ dwCount ].len;
1921   }
1922
1923   return rc;
1924 }
1925
1926 /***********************************************************************
1927  *              send                    (WINSOCK.19)
1928  */
1929 INT16 WINAPI WINSOCK_send16(SOCKET16 s, char *buf, INT16 len, INT16 flags)
1930 {
1931     return WSOCK32_send( s, buf, len, flags );
1932 }
1933
1934 /***********************************************************************
1935  *              sendto          (WS2_32.20)
1936  */
1937 INT WINAPI WSOCK32_sendto(SOCKET s, char *buf, INT len, INT flags,
1938                               struct sockaddr *to, INT tolen)
1939 {
1940 #ifdef HAVE_IPX
1941     struct ws_sockaddr_ipx*  to2 = (struct ws_sockaddr_ipx *)to;
1942 #endif
1943     int fd = _get_sock_fd(s);
1944
1945     TRACE("socket %04x, ptr %p, length %d, flags %d\n", s, buf, len, flags);
1946     if (fd != -1)
1947     {
1948         INT     length;
1949
1950         if (to && ((struct ws_sockaddr_ipx *)to)->sipx_family == WS_AF_PUP)
1951             ((struct ws_sockaddr_ipx *)to)->sipx_family = AF_UNSPEC;
1952 #ifdef HAVE_IPX
1953         else if (to &&
1954                 ((struct ws_sockaddr_ipx *)to)->sipx_family == WS_AF_IPX)
1955         {
1956             to = (struct sockaddr *) malloc(sizeof(struct sockaddr_ipx));
1957             memset(to, '\0', sizeof(struct sockaddr_ipx));
1958             ((struct sockaddr_ipx *)to)->sipx_family = AF_IPX;
1959             ((struct sockaddr_ipx *)to)->sipx_port = to2->sipx_port;
1960             ((struct sockaddr_ipx *)to)->sipx_network = to2->sipx_network;
1961             memcpy(((struct sockaddr_ipx *)to)->sipx_node,
1962                         to2->sipx_node, IPX_NODE_LEN);
1963             tolen = sizeof(struct sockaddr_ipx);
1964         }
1965 #endif
1966         if (_is_blocking(s))
1967         {
1968             /* block here */
1969             /* FIXME: exceptfds */
1970             do_block(fd, 2);
1971         }
1972         if ((length = sendto(fd, buf, len, flags, to, tolen)) < 0 )
1973         {
1974             SetLastError(wsaErrno());
1975             if( GetLastError() == WSAEWOULDBLOCK )
1976                 _enable_event(s, FD_WRITE, 0, 0);
1977         } 
1978         else {
1979 #ifdef HAVE_IPX
1980             if (to && ((struct sockaddr_ipx *)to)->sipx_family == AF_IPX) {
1981                 free(to);
1982             }
1983 #endif
1984             close(fd);
1985             return length;
1986         }
1987         close(fd);
1988     }
1989     else SetLastError(WSAENOTSOCK);
1990 #ifdef HAVE_IPX
1991     if (to && ((struct sockaddr_ipx *)to)->sipx_family == AF_IPX) {
1992         free(to);
1993     }
1994 #endif
1995     return SOCKET_ERROR;
1996 }
1997
1998 /***********************************************************************
1999  *              sendto          (WINSOCK.20)
2000  */
2001 INT16 WINAPI WINSOCK_sendto16(SOCKET16 s, char *buf, INT16 len, INT16 flags,
2002                               struct sockaddr *to, INT16 tolen)
2003 {
2004     return (INT16)WSOCK32_sendto( s, buf, len, flags, to, tolen );
2005 }
2006
2007 /***********************************************************************
2008  *              setsockopt              (WS2_32.21)
2009  */
2010 INT WINAPI WSOCK32_setsockopt(SOCKET16 s, INT level, INT optname, 
2011                                   char *optval, INT optlen)
2012 {
2013     int fd = _get_sock_fd(s);
2014
2015     TRACE("socket %04x, lev %d, opt 0x%x, ptr %08x, len %d\n",
2016           s, level, optname, (int) optval, optlen);
2017     if (fd != -1)
2018     {
2019         struct  linger linger;
2020         int woptval;
2021
2022         /* Is a privileged and useless operation, so we don't. */
2023         if ((optname == WS_SO_DEBUG) && (level == WS_SOL_SOCKET)) {
2024             FIXME("(%d,SOL_SOCKET,SO_DEBUG,%p(%ld)) attempted (is privileged). Ignoring.\n",s,optval,*(DWORD*)optval);
2025             return 0;
2026         }
2027
2028         if(optname == WS_SO_DONTLINGER && level == WS_SOL_SOCKET) {
2029             /* This is unique to WinSock and takes special conversion */
2030             linger.l_onoff      = *((int*)optval) ? 0: 1;
2031             linger.l_linger     = 0;
2032             optname=SO_LINGER;
2033             optval = (char*)&linger;
2034             optlen = sizeof(struct linger);
2035             level = SOL_SOCKET;
2036         }else{
2037             if (!convert_sockopt(&level, &optname)) {
2038                 SetLastError(WSAENOPROTOOPT);
2039                 close(fd);
2040                 return SOCKET_ERROR;
2041             }
2042             if (optname == SO_LINGER && optval) {
2043                 /* yes, uses unsigned short in both win16/win32 */
2044                 linger.l_onoff  = ((UINT16*)optval)[0];
2045                 linger.l_linger = ((UINT16*)optval)[1];
2046                 /* FIXME: what is documented behavior if SO_LINGER optval
2047                    is null?? */
2048                 optval = (char*)&linger;
2049                 optlen = sizeof(struct linger);
2050             } else if (optlen < sizeof(int)){
2051                 woptval= *((INT16 *) optval);
2052                 optval= (char*) &woptval;
2053                 optlen=sizeof(int);
2054             }
2055         }
2056         if(optname == SO_RCVBUF && *(int*)optval < 2048) {
2057             WARN("SO_RCVBF for %d bytes is too small: ignored\n", *(int*)optval );
2058             close( fd);
2059             return 0;
2060         }
2061
2062         if (setsockopt(fd, level, optname, optval, optlen) == 0)
2063         {
2064             close(fd);
2065             return 0;
2066         }
2067         SetLastError(wsaErrno());
2068         close(fd);
2069     }
2070     else SetLastError(WSAENOTSOCK);
2071     return SOCKET_ERROR;
2072 }
2073
2074 /***********************************************************************
2075  *              setsockopt              (WINSOCK.21)
2076  */
2077 INT16 WINAPI WINSOCK_setsockopt16(SOCKET16 s, INT16 level, INT16 optname,
2078                                   char *optval, INT16 optlen)
2079 {
2080     if( !optval ) return SOCKET_ERROR;
2081     return (INT16)WSOCK32_setsockopt( s, (UINT16)level, optname, optval, optlen );
2082 }
2083
2084
2085 /***********************************************************************
2086  *              shutdown                (WS2_32.22)
2087  */
2088 INT WINAPI WSOCK32_shutdown(SOCKET s, INT how)
2089 {
2090     int fd = _get_sock_fd(s);
2091
2092     TRACE("socket %04x, how %i\n", s, how );
2093     if (fd != -1)
2094     {
2095             switch( how )
2096             {
2097                 case 0: /* drop receives */
2098                         _enable_event(s, 0, 0, WS_FD_READ);
2099 #ifdef SHUT_RD
2100                         how = SHUT_RD;
2101 #endif
2102                         break;
2103
2104                 case 1: /* drop sends */
2105                         _enable_event(s, 0, 0, WS_FD_WRITE);
2106 #ifdef SHUT_WR
2107                         how = SHUT_WR;
2108 #endif
2109                         break;
2110
2111                 case 2: /* drop all */
2112 #ifdef SHUT_RDWR
2113                         how = SHUT_RDWR;
2114 #endif
2115                 default:
2116                         WSAAsyncSelect( s, 0, 0, 0 );
2117                         break;
2118             }
2119
2120         if (shutdown(fd, how) == 0) 
2121         {
2122             if( how > 1 ) 
2123             {
2124                 _enable_event(s, 0, 0, WS_FD_CONNECTED|WS_FD_LISTENING);
2125             }
2126             close(fd);
2127             return 0;
2128         }
2129         SetLastError(wsaErrno());
2130         close(fd);
2131     } 
2132     else SetLastError(WSAENOTSOCK);
2133     return SOCKET_ERROR;
2134 }
2135
2136 /***********************************************************************
2137  *              shutdown                (WINSOCK.22)
2138  */
2139 INT16 WINAPI WINSOCK_shutdown16(SOCKET16 s, INT16 how)
2140 {
2141     return (INT16)WSOCK32_shutdown( s, how );
2142 }
2143
2144
2145 /***********************************************************************
2146  *              socket          (WS2_32.23)
2147  */
2148 SOCKET WINAPI WSOCK32_socket(INT af, INT type, INT protocol)
2149 {
2150     SOCKET ret;
2151
2152     TRACE("af=%d type=%d protocol=%d\n", af, type, protocol);
2153
2154     /* check the socket family */
2155     switch(af) 
2156     {
2157 #ifdef HAVE_IPX
2158         case WS_AF_IPX: af = AF_IPX;
2159 #endif
2160         case AF_INET:
2161         case AF_UNSPEC: break;
2162         default:        SetLastError(WSAEAFNOSUPPORT); 
2163                         return INVALID_SOCKET;
2164     }
2165
2166     /* check the socket type */
2167     switch(type) 
2168     {
2169         case SOCK_STREAM:
2170         case SOCK_DGRAM:
2171         case SOCK_RAW:  break;
2172         default:        SetLastError(WSAESOCKTNOSUPPORT); 
2173                         return INVALID_SOCKET;
2174     }
2175
2176     /* check the protocol type */
2177     if ( protocol < 0 )  /* don't support negative values */
2178     { SetLastError(WSAEPROTONOSUPPORT); return INVALID_SOCKET; }
2179
2180     if ( af == AF_UNSPEC)  /* did they not specify the address family? */
2181         switch(protocol) 
2182         {
2183           case IPPROTO_TCP:
2184              if (type == SOCK_STREAM) { af = AF_INET; break; }
2185           case IPPROTO_UDP:
2186              if (type == SOCK_DGRAM)  { af = AF_INET; break; }
2187           default: SetLastError(WSAEPROTOTYPE); return INVALID_SOCKET;
2188         }
2189
2190     SERVER_START_REQ( create_socket )
2191     {
2192         req->family   = af;
2193         req->type     = type;
2194         req->protocol = protocol;
2195         req->access   = GENERIC_READ|GENERIC_WRITE|SYNCHRONIZE;
2196         req->inherit  = TRUE;
2197         set_error( SERVER_CALL() );
2198         ret = (SOCKET)req->handle;
2199     }
2200     SERVER_END_REQ;
2201     if (ret)
2202     {
2203         TRACE("\tcreated %04x\n", ret );
2204         return ret;
2205     }
2206
2207     if (GetLastError() == WSAEACCES) /* raw socket denied */
2208     {
2209         if (type == SOCK_RAW)
2210             MESSAGE("WARNING: Trying to create a socket of type SOCK_RAW, will fail unless running as root\n");
2211         else
2212             MESSAGE("WS_SOCKET: not enough privileges to create socket, try running as root\n");
2213         SetLastError(WSAESOCKTNOSUPPORT);
2214     }
2215
2216     WARN("\t\tfailed!\n");
2217     return INVALID_SOCKET;
2218 }
2219
2220 /***********************************************************************
2221  *              socket          (WINSOCK.23)
2222  */
2223 SOCKET16 WINAPI WINSOCK_socket16(INT16 af, INT16 type, INT16 protocol)
2224 {
2225     return (SOCKET16)WSOCK32_socket( af, type, protocol );
2226 }
2227     
2228
2229 /* ----------------------------------- DNS services
2230  *
2231  * IMPORTANT: 16-bit API structures have SEGPTR pointers inside them.
2232  * Also, we have to use wsock32 stubs to convert structures and
2233  * error codes from Unix to WSA, hence there is no direct mapping in 
2234  * the relay32/wsock32.spec.
2235  */
2236
2237 static char*    NULL_STRING = "NULL";
2238
2239 /***********************************************************************
2240  *              __ws_gethostbyaddr
2241  */
2242 static WIN_hostent* __ws_gethostbyaddr(const char *addr, int len, int type, int dup_flag)
2243 {
2244     WIN_hostent *retval = NULL;
2245
2246     struct hostent* host;
2247 #if HAVE_LINUX_GETHOSTBYNAME_R_6
2248     char *extrabuf;
2249     int ebufsize=1024;
2250     struct hostent hostentry;
2251     int locerr=ENOBUFS;
2252     host = NULL;
2253     extrabuf=HeapAlloc(GetProcessHeap(),0,ebufsize) ;
2254     while(extrabuf) { 
2255         int res = gethostbyaddr_r(addr, len, type, 
2256                                   &hostentry, extrabuf, ebufsize, &host, &locerr);
2257         if( res != ERANGE) break;
2258         ebufsize *=2;
2259         extrabuf=HeapReAlloc(GetProcessHeap(),0,extrabuf,ebufsize) ;
2260     }
2261     if (!host) SetLastError((locerr < 0) ? wsaErrno() : wsaHerrno(locerr));
2262 #else
2263     EnterCriticalSection( &csWSgetXXXbyYYY );
2264     host = gethostbyaddr(addr, len, type);
2265     if (!host) SetLastError((h_errno < 0) ? wsaErrno() : wsaHerrno(h_errno));
2266 #endif
2267     if( host != NULL )
2268     {
2269         if( WS_dup_he(host, dup_flag) )
2270             retval = he_buffer;
2271         else 
2272             SetLastError(WSAENOBUFS);
2273     }
2274 #ifdef  HAVE_LINUX_GETHOSTBYNAME_R_6
2275     HeapFree(GetProcessHeap(),0,extrabuf);
2276 #else
2277     LeaveCriticalSection( &csWSgetXXXbyYYY );
2278 #endif
2279     return retval;
2280 }
2281
2282 /***********************************************************************
2283  *              gethostbyaddr           (WINSOCK.51)
2284  */
2285 SEGPTR WINAPI WINSOCK_gethostbyaddr16(const char *addr, INT16 len, INT16 type)
2286 {
2287     WIN_hostent* retval;
2288     TRACE("ptr %08x, len %d, type %d\n",
2289                             (unsigned) addr, len, type);
2290     retval = __ws_gethostbyaddr( addr, len, type, WS_DUP_SEGPTR );
2291     return SEGPTR_GET(retval);
2292 }
2293
2294 /***********************************************************************
2295  *              gethostbyaddr           (WS2_32.51)
2296  */
2297 WIN_hostent* WINAPI WSOCK32_gethostbyaddr(const char *addr, INT len,
2298                                                 INT type)
2299 {
2300     TRACE("ptr %08x, len %d, type %d\n",
2301                              (unsigned) addr, len, type);
2302     return __ws_gethostbyaddr(addr, len, type, WS_DUP_LINEAR);
2303 }
2304
2305 /***********************************************************************
2306  *              __ws_gethostbyname
2307  */
2308 static WIN_hostent * __ws_gethostbyname(const char *name, int dup_flag)
2309 {
2310     WIN_hostent *retval = NULL;
2311     struct hostent*     host;
2312 #ifdef  HAVE_LINUX_GETHOSTBYNAME_R_6
2313     char *extrabuf;
2314     int ebufsize=1024;
2315     struct hostent hostentry;
2316     int locerr = ENOBUFS;
2317     host = NULL;
2318     extrabuf=HeapAlloc(GetProcessHeap(),0,ebufsize) ;
2319     while(extrabuf) {
2320         int res = gethostbyname_r(name, &hostentry, extrabuf, ebufsize, &host, &locerr);
2321         if( res != ERANGE) break;
2322         ebufsize *=2;
2323         extrabuf=HeapReAlloc(GetProcessHeap(),0,extrabuf,ebufsize) ;
2324     }
2325     if (!host) SetLastError((locerr < 0) ? wsaErrno() : wsaHerrno(locerr));
2326 #else
2327     EnterCriticalSection( &csWSgetXXXbyYYY );
2328     host = gethostbyname(name);
2329     if (!host) SetLastError((h_errno < 0) ? wsaErrno() : wsaHerrno(h_errno));
2330 #endif
2331     if( host  != NULL )
2332     {
2333         if( WS_dup_he(host, dup_flag) )
2334             retval = he_buffer;
2335         else SetLastError(WSAENOBUFS);
2336     }
2337 #ifdef  HAVE_LINUX_GETHOSTBYNAME_R_6
2338     HeapFree(GetProcessHeap(),0,extrabuf);
2339 #else
2340     LeaveCriticalSection( &csWSgetXXXbyYYY );
2341 #endif
2342     return retval;
2343 }
2344
2345 /***********************************************************************
2346  *              gethostbyname           (WINSOCK.52)
2347  */
2348 SEGPTR WINAPI WINSOCK_gethostbyname16(const char *name)
2349 {
2350     WIN_hostent* retval;
2351     TRACE("%s\n", (name)?name:NULL_STRING);
2352     retval = __ws_gethostbyname( name, WS_DUP_SEGPTR );
2353     return SEGPTR_GET(retval);
2354 }
2355
2356 /***********************************************************************
2357  *              gethostbyname           (WS2_32.52)
2358  */
2359 WIN_hostent* WINAPI WSOCK32_gethostbyname(const char* name)
2360 {
2361     TRACE("%s\n", (name)?name:NULL_STRING);
2362     return __ws_gethostbyname( name, WS_DUP_LINEAR );
2363 }
2364
2365
2366 /***********************************************************************
2367  *              __ws_getprotobyname
2368  */
2369 static WIN_protoent* __ws_getprotobyname(const char *name, int dup_flag)
2370 {
2371     WIN_protoent* retval = NULL;
2372
2373     struct protoent*     proto;
2374     EnterCriticalSection( &csWSgetXXXbyYYY );
2375     if( (proto = getprotobyname(name)) != NULL )
2376     {
2377         if( WS_dup_pe(proto, dup_flag) )
2378             retval = pe_buffer;
2379         else SetLastError(WSAENOBUFS);
2380     }
2381     else {
2382         MESSAGE("protocol %s not found; You might want to add "
2383                 "this to /etc/protocols\n", debugstr_a(name) );
2384         SetLastError(WSANO_DATA);
2385     }
2386     LeaveCriticalSection( &csWSgetXXXbyYYY );
2387     return retval;
2388 }
2389
2390 /***********************************************************************
2391  *              getprotobyname          (WINSOCK.53)
2392  */
2393 SEGPTR WINAPI WINSOCK_getprotobyname16(const char *name)
2394 {
2395     WIN_protoent* retval;
2396     TRACE("%s\n", (name)?name:NULL_STRING);
2397     retval = __ws_getprotobyname(name, WS_DUP_SEGPTR);
2398     return SEGPTR_GET(retval);
2399 }
2400
2401 /***********************************************************************
2402  *              getprotobyname          (WS2_32.53)
2403  */
2404 WIN_protoent* WINAPI WSOCK32_getprotobyname(const char* name)
2405 {
2406     TRACE("%s\n", (name)?name:NULL_STRING);
2407     return __ws_getprotobyname(name, WS_DUP_LINEAR);
2408 }
2409
2410
2411 /***********************************************************************
2412  *              __ws_getprotobynumber
2413  */
2414 static WIN_protoent* __ws_getprotobynumber(int number, int dup_flag)
2415 {
2416     WIN_protoent* retval = NULL;
2417     struct protoent*     proto;
2418     EnterCriticalSection( &csWSgetXXXbyYYY );
2419     if( (proto = getprotobynumber(number)) != NULL )
2420     {
2421         if( WS_dup_pe(proto, dup_flag) )
2422             retval = pe_buffer;
2423         else SetLastError(WSAENOBUFS);
2424     }
2425     else {
2426         MESSAGE("protocol number %d not found; You might want to add "
2427                 "this to /etc/protocols\n", number );
2428         SetLastError(WSANO_DATA);
2429     }
2430     LeaveCriticalSection( &csWSgetXXXbyYYY );
2431     return retval;
2432 }
2433
2434 /***********************************************************************
2435  *              getprotobynumber        (WINSOCK.54)
2436  */
2437 SEGPTR WINAPI WINSOCK_getprotobynumber16(INT16 number)
2438 {
2439     WIN_protoent* retval;
2440     TRACE("%i\n", number);
2441     retval = __ws_getprotobynumber(number, WS_DUP_SEGPTR);
2442     return SEGPTR_GET(retval);
2443 }
2444
2445 /***********************************************************************
2446  *              getprotobynumber        (WS2_32.54)
2447  */
2448 WIN_protoent* WINAPI WSOCK32_getprotobynumber(INT number)
2449 {
2450     TRACE("%i\n", number);
2451     return __ws_getprotobynumber(number, WS_DUP_LINEAR);
2452 }
2453
2454
2455 /***********************************************************************
2456  *              __ws_getservbyname
2457  */
2458 static WIN_servent* __ws_getservbyname(const char *name, const char *proto, int dup_flag)
2459 {
2460     WIN_servent* retval = NULL;
2461     struct servent*     serv;
2462     int i = wsi_strtolo( name, proto );
2463
2464     if( i ) {
2465         EnterCriticalSection( &csWSgetXXXbyYYY );
2466         serv = getservbyname(local_buffer,
2467                              proto ? (local_buffer + i) : NULL);
2468         if( serv != NULL )
2469         {
2470             if( WS_dup_se(serv, dup_flag) )
2471                 retval = se_buffer;
2472             else SetLastError(WSAENOBUFS);
2473         }
2474         else {
2475             MESSAGE("service %s protocol %s not found; You might want to add "
2476                     "this to /etc/services\n", debugstr_a(local_buffer),
2477                     proto ? debugstr_a(local_buffer+i):"*");
2478             SetLastError(WSANO_DATA);
2479         }
2480         LeaveCriticalSection( &csWSgetXXXbyYYY );
2481     }
2482     else SetLastError(WSAENOBUFS);
2483     return retval;
2484 }
2485
2486 /***********************************************************************
2487  *              getservbyname           (WINSOCK.55)
2488  */
2489 SEGPTR WINAPI WINSOCK_getservbyname16(const char *name, const char *proto)
2490 {
2491     WIN_servent* retval;
2492     TRACE("'%s', '%s'\n",
2493                             (name)?name:NULL_STRING, (proto)?proto:NULL_STRING);
2494     retval = __ws_getservbyname(name, proto, WS_DUP_SEGPTR);
2495     return SEGPTR_GET(retval);
2496 }
2497
2498 /***********************************************************************
2499  *              getservbyname           (WS2_32.55)
2500  */
2501 WIN_servent* WINAPI WSOCK32_getservbyname(const char *name, const char *proto)
2502 {
2503     TRACE("'%s', '%s'\n",
2504                             (name)?name:NULL_STRING, (proto)?proto:NULL_STRING);
2505     return __ws_getservbyname(name, proto, WS_DUP_LINEAR);
2506 }
2507
2508
2509 /***********************************************************************
2510  *              __ws_getservbyport
2511  */
2512 static WIN_servent* __ws_getservbyport(int port, const char* proto, int dup_flag)
2513 {
2514     WIN_servent* retval = NULL;
2515     struct servent*     serv;
2516     if (!proto || wsi_strtolo( proto, NULL )) {
2517         EnterCriticalSection( &csWSgetXXXbyYYY );
2518         if( (serv = getservbyport(port, (proto) ? local_buffer : NULL)) != NULL ) {
2519             if( WS_dup_se(serv, dup_flag) )
2520                 retval = se_buffer;
2521             else SetLastError(WSAENOBUFS);
2522         }
2523         else {
2524             MESSAGE("service on port %lu protocol %s not found; You might want to add "
2525                     "this to /etc/services\n", (unsigned long)ntohl(port),
2526                     proto ? debugstr_a(local_buffer) : "*");
2527             SetLastError(WSANO_DATA);
2528         }
2529         LeaveCriticalSection( &csWSgetXXXbyYYY );
2530     }
2531     else SetLastError(WSAENOBUFS);
2532     return retval;
2533 }
2534
2535 /***********************************************************************
2536  *              getservbyport           (WINSOCK.56)
2537  */
2538 SEGPTR WINAPI WINSOCK_getservbyport16(INT16 port, const char *proto)
2539 {
2540     WIN_servent* retval;
2541     TRACE("%d (i.e. port %d), '%s'\n",
2542                             (int)port, (int)ntohl(port), (proto)?proto:NULL_STRING);
2543     retval = __ws_getservbyport(port, proto, WS_DUP_SEGPTR);
2544     return SEGPTR_GET(retval);
2545 }
2546
2547 /***********************************************************************
2548  *              getservbyport           (WS2_32.56)
2549  */
2550 WIN_servent* WINAPI WSOCK32_getservbyport(INT port, const char *proto)
2551 {
2552     TRACE("%d (i.e. port %d), '%s'\n",
2553                             (int)port, (int)ntohl(port), (proto)?proto:NULL_STRING);
2554     return __ws_getservbyport(port, proto, WS_DUP_LINEAR);
2555 }
2556
2557
2558 /***********************************************************************
2559  *              gethostname           (WS2_32.57)
2560  */
2561 INT WINAPI WSOCK32_gethostname(char *name, INT namelen)
2562 {
2563     TRACE("name %p, len %d\n", name, namelen);
2564
2565     if (gethostname(name, namelen) == 0)
2566     {
2567         TRACE("<- '%s'\n", name);
2568         return 0;
2569     }
2570     SetLastError((errno == EINVAL) ? WSAEFAULT : wsaErrno());
2571     TRACE("<- ERROR !\n");
2572     return SOCKET_ERROR;
2573 }
2574
2575 /***********************************************************************
2576  *              gethostname           (WINSOCK.57)
2577  */
2578 INT16 WINAPI WINSOCK_gethostname16(char *name, INT16 namelen)
2579 {
2580     return (INT16)WSOCK32_gethostname(name, namelen);
2581 }
2582
2583
2584 /* ------------------------------------- Windows sockets extensions -- *
2585  *                                                                     *
2586  * ------------------------------------------------------------------- */
2587
2588 /***********************************************************************
2589  *              WSAEnumNetworkEvents (WS2_32.36)
2590  */
2591 int WINAPI WSAEnumNetworkEvents(SOCKET s, WSAEVENT hEvent, LPWSANETWORKEVENTS lpEvent)
2592 {
2593     int ret;
2594
2595     TRACE("%08x, hEvent %08x, lpEvent %08x\n", s, hEvent, (unsigned)lpEvent );
2596
2597     SERVER_START_VAR_REQ( get_socket_event, sizeof(lpEvent->iErrorCode) )
2598     {
2599         req->handle  = s;
2600         req->service = TRUE;
2601         req->s_event = 0;
2602         req->c_event = hEvent;
2603         if (!(ret = SERVER_CALL()))
2604         {
2605             lpEvent->lNetworkEvents = req->pmask;
2606             memcpy(lpEvent->iErrorCode, server_data_ptr(req), server_data_size(req) );
2607         }
2608     }
2609     SERVER_END_VAR_REQ;
2610     if (!ret) return 0;
2611     SetLastError(WSAEINVAL);
2612     return SOCKET_ERROR;
2613 }
2614
2615 /***********************************************************************
2616  *              WSAEventSelect (WS2_32.39)
2617  */
2618 int WINAPI WSAEventSelect(SOCKET s, WSAEVENT hEvent, LONG lEvent)
2619 {
2620     int ret;
2621
2622     TRACE("%08x, hEvent %08x, event %08x\n", s, hEvent, (unsigned)lEvent );
2623
2624     SERVER_START_REQ( set_socket_event )
2625     {
2626         req->handle = s;
2627         req->mask   = lEvent;
2628         req->event  = hEvent;
2629         ret = SERVER_CALL();
2630     }
2631     SERVER_END_REQ;
2632     if (!ret) return 0;
2633     SetLastError(WSAEINVAL);
2634     return SOCKET_ERROR;
2635 }
2636
2637 /***********************************************************************
2638  *      WINSOCK_DoAsyncSelect
2639  */
2640 VOID CALLBACK WINSOCK_DoAsyncEvent( ULONG_PTR ptr )
2641 {
2642     ws_select_info *info = (ws_select_info*)ptr;
2643     unsigned int i, pmask, orphan = FALSE;
2644     int errors[FD_MAX_EVENTS];
2645
2646     TRACE("socket %08x, event %08x\n", info->sock, info->event);
2647     SetLastError(0);
2648     SERVER_START_VAR_REQ( get_socket_event, sizeof(errors) )
2649     {
2650         req->handle  = info->sock;
2651         req->service = TRUE;
2652         req->s_event = info->event; /* <== avoid race conditions */
2653         req->c_event = info->event;
2654         set_error( SERVER_CALL() );
2655         pmask = req->pmask;
2656         memcpy( errors, server_data_ptr(req), server_data_size(req) );
2657     }
2658     SERVER_END_VAR_REQ;
2659     if ( (GetLastError() == WSAENOTSOCK) || (GetLastError() == WSAEINVAL) )
2660     {
2661         /* orphaned event (socket closed or something) */
2662         pmask = WS_FD_SERVEVENT;
2663         orphan = TRUE;
2664     }
2665
2666     /* check for accepted sockets that needs to inherit WSAAsyncSelect */
2667     if (pmask & WS_FD_SERVEVENT) {
2668         int q;
2669         for (q=0; q<WS_ACCEPT_QUEUE; q++)
2670             if (accept_old[q] == info->sock) {
2671                 /* there's only one service thread per process, no lock necessary */
2672                 HANDLE as = accept_new[q];
2673                 if (as) {
2674                     accept_new[q] = 0;
2675                     accept_old[q] = 0;
2676                     WSAAsyncSelect(as, info->hWnd, info->uMsg, info->lEvent);
2677                 }
2678             }
2679         pmask &= ~WS_FD_SERVEVENT;
2680     }
2681     /* dispatch network events */
2682     for (i=0; i<FD_MAX_EVENTS; i++)
2683         if (pmask & (1<<i)) {
2684             TRACE("post: event bit %d, error %d\n", i, errors[i]);
2685             PostMessageA(info->hWnd, info->uMsg, info->sock,
2686                          WSAMAKESELECTREPLY(1<<i, errors[i]));
2687         }
2688     /* cleanup */
2689     if (orphan)
2690     {
2691         TRACE("orphaned event, self-destructing\n");
2692         /* SERVICE_Delete closes the event object */
2693         SERVICE_Delete( info->service );
2694         WS_FREE(info);
2695     }
2696 }
2697
2698 /***********************************************************************
2699  *      WSAAsyncSelect                  (WS2_32.101)
2700  */
2701 INT WINAPI WSAAsyncSelect(SOCKET s, HWND hWnd, UINT uMsg, LONG lEvent)
2702 {
2703     int fd = _get_sock_fd(s);
2704
2705     TRACE("%04x, hWnd %04x, uMsg %08x, event %08x\n",
2706           (SOCKET16)s, (HWND16)hWnd, uMsg, (unsigned)lEvent );
2707     if (fd != -1)
2708     {
2709         close(fd);
2710         if( lEvent )
2711         {
2712             ws_select_info *info = (ws_select_info*)WS_ALLOC(sizeof(ws_select_info));
2713             if( info )
2714             {
2715                 HANDLE hObj = CreateEventA( NULL, TRUE, FALSE, NULL );
2716                 INT err;
2717                 
2718                 info->sock   = s;
2719                 info->event  = hObj;
2720                 info->hWnd   = hWnd;
2721                 info->uMsg   = uMsg;
2722                 info->lEvent = lEvent;
2723                 info->service = SERVICE_AddObject( hObj, WINSOCK_DoAsyncEvent, (ULONG_PTR)info );
2724
2725                 err = WSAEventSelect( s, hObj, lEvent | WS_FD_SERVEVENT );
2726                 if (err) {
2727                     /* SERVICE_Delete closes the event object */
2728                     SERVICE_Delete( info->service );
2729                     WS_FREE(info);
2730                     return err;
2731                 }
2732
2733                 return 0; /* success */
2734             }
2735             else SetLastError(WSAENOBUFS);
2736         } 
2737         else
2738         {
2739             WSAEventSelect(s, 0, 0);
2740             return 0;
2741         }
2742     } 
2743     else SetLastError(WSAEINVAL);
2744     return SOCKET_ERROR; 
2745 }
2746
2747 /***********************************************************************
2748  *      WSAAsyncSelect          (WINSOCK.101)
2749  */
2750 INT16 WINAPI WSAAsyncSelect16(SOCKET16 s, HWND16 hWnd, UINT16 wMsg, LONG lEvent)
2751 {
2752     return (INT16)WSAAsyncSelect( s, hWnd, wMsg, lEvent );
2753 }
2754
2755 /***********************************************************************
2756  *              WSARecvEx                       (WINSOCK.1107)
2757  *
2758  * See description for WSARecvEx()
2759  */
2760 INT16     WINAPI WSARecvEx16(SOCKET16 s, char *buf, INT16 len, INT16 *flags) {
2761   FIXME("(WSARecvEx16) partial packet return value not set \n");
2762
2763   return WINSOCK_recv16(s, buf, len, *flags);
2764 }
2765
2766
2767 /***********************************************************************
2768  *      WSACreateEvent          (WS2_32.31)
2769  *
2770  */
2771 WSAEVENT WINAPI WSACreateEvent(void)
2772 {
2773     /* Create a manual-reset event, with initial state: unsignealed */
2774     TRACE("\n");
2775     
2776     return CreateEventA(NULL, TRUE, FALSE, NULL);    
2777 }
2778
2779 /***********************************************************************
2780  *      WSACloseEvent          (WS2_32.29)
2781  *
2782  */
2783 BOOL WINAPI WSACloseEvent(WSAEVENT event)
2784 {
2785     TRACE ("event=0x%x\n", event);
2786
2787     return CloseHandle(event);
2788 }
2789
2790 /***********************************************************************
2791  *      WSASocketA          (WS2_32.78)
2792  *
2793  */
2794 SOCKET WINAPI WSASocketA(int af, int type, int protocol,
2795                          LPWSAPROTOCOL_INFOA lpProtocolInfo,
2796                          GROUP g, DWORD dwFlags)
2797 {
2798    /* 
2799       FIXME: The "advanced" parameters of WSASocketA (lpProtocolInfo,
2800       g, dwFlags) are ignored.
2801    */
2802    
2803    TRACE("af=%d type=%d protocol=%d protocol_info=%p group=%d flags=0x%lx\n", 
2804          af, type, protocol, lpProtocolInfo, g, dwFlags );
2805
2806    return ( WSOCK32_socket (af, type, protocol) );
2807 }
2808
2809
2810 /***********************************************************************
2811  *      __WSAFDIsSet                    (WINSOCK.151)
2812  */
2813 INT16 WINAPI __WSAFDIsSet16(SOCKET16 s, ws_fd_set16 *set)
2814 {
2815   int i = set->fd_count;
2816   
2817   TRACE("(%d,%8lx(%i))\n", s,(unsigned long)set, i);
2818     
2819   while (i--)
2820       if (set->fd_array[i] == s) return 1;
2821   return 0;
2822 }                                                            
2823
2824 /***********************************************************************
2825  *      __WSAFDIsSet                    (WS2_32.151)
2826  */
2827 INT WINAPI __WSAFDIsSet(SOCKET s, ws_fd_set32 *set)
2828 {
2829   int i = set->fd_count;
2830
2831   TRACE("(%d,%8lx(%i))\n", s,(unsigned long)set, i);
2832
2833   while (i--)
2834       if (set->fd_array[i] == s) return 1;
2835   return 0;
2836 }
2837
2838 /***********************************************************************
2839  *      WSAIsBlocking                   (WINSOCK.114)
2840  *      WSAIsBlocking                   (WS2_32.114)
2841  */
2842 BOOL WINAPI WSAIsBlocking(void)
2843 {
2844   /* By default WinSock should set all its sockets to non-blocking mode
2845    * and poll in PeekMessage loop when processing "blocking" ones. This 
2846    * function is supposed to tell if the program is in this loop. Our 
2847    * blocking calls are truly blocking so we always return FALSE.
2848    *
2849    * Note: It is allowed to call this function without prior WSAStartup().
2850    */
2851
2852   TRACE("\n");
2853   return FALSE;
2854 }
2855
2856 /***********************************************************************
2857  *      WSACancelBlockingCall           (WINSOCK.113)
2858  *      WSACancelBlockingCall           (WS2_32.113)
2859  */
2860 INT WINAPI WSACancelBlockingCall(void)
2861 {
2862     TRACE("\n");
2863     return 0;
2864 }
2865
2866
2867 /***********************************************************************
2868  *      WSASetBlockingHook              (WINSOCK.109)
2869  */
2870 FARPROC16 WINAPI WSASetBlockingHook16(FARPROC16 lpBlockFunc)
2871 {
2872   FARPROC16 prev = (FARPROC16)blocking_hook;
2873   blocking_hook = (FARPROC)lpBlockFunc;
2874   TRACE("hook %p\n", lpBlockFunc);
2875   return prev;
2876 }
2877
2878
2879 /***********************************************************************
2880  *      WSASetBlockingHook()
2881  */
2882 FARPROC WINAPI WSASetBlockingHook(FARPROC lpBlockFunc)
2883 {
2884   FARPROC prev = blocking_hook;
2885   blocking_hook = lpBlockFunc;
2886   TRACE("hook %p\n", lpBlockFunc);
2887   return prev;
2888 }
2889
2890
2891 /***********************************************************************
2892  *      WSAUnhookBlockingHook   (WINSOCK.110)
2893  */
2894 INT16 WINAPI WSAUnhookBlockingHook16(void)
2895 {
2896     blocking_hook = NULL;
2897     return 0;
2898 }
2899
2900
2901 /***********************************************************************
2902  *      WSAUnhookBlockingHook()
2903  */
2904 INT WINAPI WSAUnhookBlockingHook(void)
2905 {
2906     blocking_hook = NULL;
2907     return 0;
2908 }
2909
2910
2911 /* ----------------------------------- end of API stuff */
2912
2913 /* ----------------------------------- helper functions -
2914  *
2915  * TODO: Merge WS_dup_..() stuff into one function that
2916  * would operate with a generic structure containing internal
2917  * pointers (via a template of some kind).
2918  */
2919
2920 static int list_size(char** l, int item_size)
2921 {
2922   int i,j = 0;
2923   if(l)
2924   { for(i=0;l[i];i++) 
2925         j += (item_size) ? item_size : strlen(l[i]) + 1;
2926     j += (i + 1) * sizeof(char*); }
2927   return j;
2928 }
2929
2930 static int list_dup(char** l_src, char* ref, char* base, int item_size)
2931
2932    /* base is either either equal to ref or 0 or SEGPTR */
2933
2934    char*                p = ref;
2935    char**               l_to = (char**)ref;
2936    int                  i,j,k;
2937
2938    for(j=0;l_src[j];j++) ;
2939    p += (j + 1) * sizeof(char*);
2940    for(i=0;i<j;i++)
2941    { l_to[i] = base + (p - ref);
2942      k = ( item_size ) ? item_size : strlen(l_src[i]) + 1;
2943      memcpy(p, l_src[i], k); p += k; }
2944    l_to[i] = NULL;
2945    return (p - ref);
2946 }
2947
2948 /* ----- hostent */
2949
2950 static int hostent_size(struct hostent* p_he)
2951 {
2952   int size = 0;
2953   if( p_he )
2954   { size  = sizeof(struct hostent); 
2955     size += strlen(p_he->h_name) + 1;
2956     size += list_size(p_he->h_aliases, 0);  
2957     size += list_size(p_he->h_addr_list, p_he->h_length ); }
2958   return size;
2959 }
2960
2961 /* duplicate hostent entry
2962  * and handle all Win16/Win32 dependent things (struct size, ...) *correctly*.
2963  * Dito for protoent and servent.
2964  */
2965 int WS_dup_he(struct hostent* p_he, int flag)
2966 {
2967     /* Convert hostent structure into ws_hostent so that the data fits 
2968      * into local_buffer. Internal pointers can be linear, SEGPTR, or 
2969      * relative to local_buffer depending on "flag" value. Returns size
2970      * of the data copied.
2971      */
2972
2973     int size = hostent_size(p_he);
2974     if( size )
2975     {
2976         char *p_name,*p_aliases,*p_addr,*p_base,*p;
2977         char *p_to;
2978         struct ws_hostent16 *p_to16;
2979         struct ws_hostent32 *p_to32;
2980
2981         check_buffer_he(size);
2982         p_to = he_buffer;
2983         p_to16 = he_buffer;
2984         p_to32 = he_buffer;
2985
2986         p = p_to;
2987         p_base = (flag & WS_DUP_OFFSET) ? NULL
2988             : ((flag & WS_DUP_SEGPTR) ? (char*)SEGPTR_GET(p) : p);
2989         p += (flag & WS_DUP_SEGPTR) ?
2990             sizeof(struct ws_hostent16) : sizeof(struct ws_hostent32);
2991         p_name = p;
2992         strcpy(p, p_he->h_name); p += strlen(p) + 1;
2993         p_aliases = p;
2994         p += list_dup(p_he->h_aliases, p, p_base + (p - p_to), 0);
2995         p_addr = p;
2996         list_dup(p_he->h_addr_list, p, p_base + (p - p_to), p_he->h_length);
2997
2998         if (flag & WS_DUP_SEGPTR) /* Win16 */
2999         {
3000             p_to16->h_addrtype = (INT16)p_he->h_addrtype; 
3001             p_to16->h_length = (INT16)p_he->h_length;
3002             p_to16->h_name = (SEGPTR)(p_base + (p_name - p_to));
3003             p_to16->h_aliases = (SEGPTR)(p_base + (p_aliases - p_to));
3004             p_to16->h_addr_list = (SEGPTR)(p_base + (p_addr - p_to));
3005             size += (sizeof(struct ws_hostent16) - sizeof(struct hostent));
3006         }
3007         else /* Win32 */
3008         {
3009             p_to32->h_addrtype = p_he->h_addrtype; 
3010             p_to32->h_length = p_he->h_length;
3011             p_to32->h_name = (p_base + (p_name - p_to));
3012             p_to32->h_aliases = (char **)(p_base + (p_aliases - p_to));
3013             p_to32->h_addr_list = (char **)(p_base + (p_addr - p_to));
3014             size += (sizeof(struct ws_hostent32) - sizeof(struct hostent));
3015         }
3016     }
3017     return size;
3018 }
3019
3020 /* ----- protoent */
3021
3022 static int protoent_size(struct protoent* p_pe)
3023 {
3024   int size = 0;
3025   if( p_pe )
3026   { size  = sizeof(struct protoent);
3027     size += strlen(p_pe->p_name) + 1;
3028     size += list_size(p_pe->p_aliases, 0); }
3029   return size;
3030 }
3031
3032 int WS_dup_pe(struct protoent* p_pe, int flag)
3033 {
3034     int size = protoent_size(p_pe);
3035     if( size )
3036     {
3037         char *p_to;
3038         struct ws_protoent16 *p_to16;
3039         struct ws_protoent32 *p_to32;
3040         char *p_name,*p_aliases,*p_base,*p;
3041
3042         check_buffer_pe(size);
3043         p_to = pe_buffer;
3044         p_to16 = pe_buffer;
3045         p_to32 = pe_buffer;
3046         p = p_to;
3047         p_base = (flag & WS_DUP_OFFSET) ? NULL
3048             : ((flag & WS_DUP_SEGPTR) ? (char*)SEGPTR_GET(p) : p);
3049         p += (flag & WS_DUP_SEGPTR) ?
3050             sizeof(struct ws_protoent16) : sizeof(struct ws_protoent32);
3051         p_name = p;
3052         strcpy(p, p_pe->p_name); p += strlen(p) + 1;
3053         p_aliases = p;
3054         list_dup(p_pe->p_aliases, p, p_base + (p - p_to), 0);
3055
3056         if (flag & WS_DUP_SEGPTR) /* Win16 */
3057         {
3058             p_to16->p_proto = (INT16)p_pe->p_proto;
3059             p_to16->p_name = (SEGPTR)(p_base) + (p_name - p_to);
3060             p_to16->p_aliases = (SEGPTR)((p_base) + (p_aliases - p_to)); 
3061             size += (sizeof(struct ws_protoent16) - sizeof(struct protoent));
3062         }
3063         else /* Win32 */
3064         {
3065             p_to32->p_proto = p_pe->p_proto;
3066             p_to32->p_name = (p_base) + (p_name - p_to);
3067             p_to32->p_aliases = (char **)((p_base) + (p_aliases - p_to)); 
3068             size += (sizeof(struct ws_protoent32) - sizeof(struct protoent));
3069         }
3070     }
3071     return size;
3072 }
3073
3074 /* ----- servent */
3075
3076 static int servent_size(struct servent* p_se)
3077 {
3078   int size = 0;
3079   if( p_se )
3080   { size += sizeof(struct servent);
3081     size += strlen(p_se->s_proto) + strlen(p_se->s_name) + 2;
3082     size += list_size(p_se->s_aliases, 0); }
3083   return size;
3084 }
3085
3086 int WS_dup_se(struct servent* p_se, int flag)
3087 {
3088     int size = servent_size(p_se);
3089     if( size )
3090     {
3091         char *p_name,*p_aliases,*p_proto,*p_base,*p;
3092         char *p_to;
3093         struct ws_servent16 *p_to16;
3094         struct ws_servent32 *p_to32;
3095
3096         check_buffer_se(size);
3097         p_to = se_buffer;
3098         p_to16 = se_buffer;
3099         p_to32 = se_buffer;
3100         p = p_to;
3101         p_base = (flag & WS_DUP_OFFSET) ? NULL 
3102             : ((flag & WS_DUP_SEGPTR) ? (char*)SEGPTR_GET(p) : p);
3103         p += (flag & WS_DUP_SEGPTR) ?
3104             sizeof(struct ws_servent16) : sizeof(struct ws_servent32);
3105         p_name = p;
3106         strcpy(p, p_se->s_name); p += strlen(p) + 1;
3107         p_proto = p;
3108         strcpy(p, p_se->s_proto); p += strlen(p) + 1;
3109         p_aliases = p;
3110         list_dup(p_se->s_aliases, p, p_base + (p - p_to), 0);
3111
3112         if (flag & WS_DUP_SEGPTR) /* Win16 */
3113         { 
3114             p_to16->s_port = (INT16)p_se->s_port;
3115             p_to16->s_name = (SEGPTR)(p_base + (p_name - p_to));
3116             p_to16->s_proto = (SEGPTR)(p_base + (p_proto - p_to));
3117             p_to16->s_aliases = (SEGPTR)(p_base + (p_aliases - p_to));
3118             size += (sizeof(struct ws_servent16) - sizeof(struct servent));
3119         }
3120         else /* Win32 */
3121         {
3122             p_to32->s_port = p_se->s_port;
3123             p_to32->s_name = (p_base + (p_name - p_to));
3124             p_to32->s_proto = (p_base + (p_proto - p_to));
3125             p_to32->s_aliases = (char **)(p_base + (p_aliases - p_to));
3126             size += (sizeof(struct ws_servent32) - sizeof(struct servent));
3127         }
3128     }
3129     return size;
3130 }
3131
3132 /* ----------------------------------- error handling */
3133
3134 UINT16 wsaErrno(void)
3135 {
3136     int loc_errno = errno; 
3137     WARN("errno %d, (%s).\n", loc_errno, strerror(loc_errno));
3138
3139     switch(loc_errno)
3140     {
3141         case EINTR:             return WSAEINTR;
3142         case EBADF:             return WSAEBADF;
3143         case EPERM:
3144         case EACCES:            return WSAEACCES;
3145         case EFAULT:            return WSAEFAULT;
3146         case EINVAL:            return WSAEINVAL;
3147         case EMFILE:            return WSAEMFILE;
3148         case EWOULDBLOCK:       return WSAEWOULDBLOCK;
3149         case EINPROGRESS:       return WSAEINPROGRESS;
3150         case EALREADY:          return WSAEALREADY;
3151         case ENOTSOCK:          return WSAENOTSOCK;
3152         case EDESTADDRREQ:      return WSAEDESTADDRREQ;
3153         case EMSGSIZE:          return WSAEMSGSIZE;
3154         case EPROTOTYPE:        return WSAEPROTOTYPE;
3155         case ENOPROTOOPT:       return WSAENOPROTOOPT;
3156         case EPROTONOSUPPORT:   return WSAEPROTONOSUPPORT;
3157         case ESOCKTNOSUPPORT:   return WSAESOCKTNOSUPPORT;
3158         case EOPNOTSUPP:        return WSAEOPNOTSUPP;
3159         case EPFNOSUPPORT:      return WSAEPFNOSUPPORT;
3160         case EAFNOSUPPORT:      return WSAEAFNOSUPPORT;
3161         case EADDRINUSE:        return WSAEADDRINUSE;
3162         case EADDRNOTAVAIL:     return WSAEADDRNOTAVAIL;
3163         case ENETDOWN:          return WSAENETDOWN;
3164         case ENETUNREACH:       return WSAENETUNREACH;
3165         case ENETRESET:         return WSAENETRESET;
3166         case ECONNABORTED:      return WSAECONNABORTED;
3167         case EPIPE:
3168         case ECONNRESET:        return WSAECONNRESET;
3169         case ENOBUFS:           return WSAENOBUFS;
3170         case EISCONN:           return WSAEISCONN;
3171         case ENOTCONN:          return WSAENOTCONN;
3172         case ESHUTDOWN:         return WSAESHUTDOWN;
3173         case ETOOMANYREFS:      return WSAETOOMANYREFS;
3174         case ETIMEDOUT:         return WSAETIMEDOUT;
3175         case ECONNREFUSED:      return WSAECONNREFUSED;
3176         case ELOOP:             return WSAELOOP;
3177         case ENAMETOOLONG:      return WSAENAMETOOLONG;
3178         case EHOSTDOWN:         return WSAEHOSTDOWN;
3179         case EHOSTUNREACH:      return WSAEHOSTUNREACH;
3180         case ENOTEMPTY:         return WSAENOTEMPTY;
3181 #ifdef EPROCLIM
3182         case EPROCLIM:          return WSAEPROCLIM;
3183 #endif
3184 #ifdef EUSERS
3185         case EUSERS:            return WSAEUSERS;
3186 #endif
3187 #ifdef EDQUOT
3188         case EDQUOT:            return WSAEDQUOT;
3189 #endif
3190 #ifdef ESTALE
3191         case ESTALE:            return WSAESTALE;
3192 #endif
3193 #ifdef EREMOTE
3194         case EREMOTE:           return WSAEREMOTE;
3195 #endif
3196
3197        /* just in case we ever get here and there are no problems */
3198         case 0:                 return 0;
3199         default:
3200                 WARN("Unknown errno %d!\n", loc_errno);
3201                 return WSAEOPNOTSUPP;
3202     }
3203 }
3204
3205 UINT16 wsaHerrno(int loc_errno)
3206 {
3207
3208     WARN("h_errno %d.\n", loc_errno);
3209
3210     switch(loc_errno)
3211     {
3212         case HOST_NOT_FOUND:    return WSAHOST_NOT_FOUND;
3213         case TRY_AGAIN:         return WSATRY_AGAIN;
3214         case NO_RECOVERY:       return WSANO_RECOVERY;
3215         case NO_DATA:           return WSANO_DATA; 
3216         case ENOBUFS:           return WSAENOBUFS;
3217
3218         case 0:                 return 0;
3219         default:
3220                 WARN("Unknown h_errno %d!\n", loc_errno);
3221                 return WSAEOPNOTSUPP;
3222     }
3223 }
3224
3225
3226 /***********************************************************************
3227  *              WSARecvFrom             (WSOCK32.69)
3228  */
3229 INT WINAPI WSARecvFrom( SOCKET s, LPWSABUF lpBuffers, DWORD dwBufferCount,
3230                         LPDWORD lpNumberOfBytesRecvd, LPDWORD lpFlags, struct sockaddr *lpFrom,
3231                         LPINT lpFromlen, LPWSAOVERLAPPED lpOverlapped,
3232                         LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine )
3233 {
3234   DWORD dwCount;
3235   INT   rc;
3236
3237   FIXME( "(%i,%p,%lu,%p,%p,%p,%p,%p,%p: stub\n",
3238          s, lpBuffers, dwBufferCount, lpNumberOfBytesRecvd, lpFlags,
3239          lpFrom, lpFromlen, lpOverlapped, lpCompletionRoutine );
3240
3241   for( dwCount = 0, rc = 0; dwCount < dwBufferCount; dwCount++ )
3242   {
3243
3244     if( ( rc = WSOCK32_recvfrom(s, lpBuffers[ dwCount ].buf, (INT)lpBuffers[ dwCount ].len,
3245                                 (INT)*lpFlags, lpFrom, lpFromlen ) ) != 0 )
3246     {
3247        break;
3248     }
3249
3250   }
3251
3252   return rc;
3253 }