Added an unknown VxD error code.
[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 (WSOCK32.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  *      WSAStartup16()                  (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()               (WSOCK32.111)(WINSOCK.111)
657  */
658 INT WINAPI WSAGetLastError(void)
659 {
660         return GetLastError();
661 }
662
663 /***********************************************************************
664  *      WSASetLastError()               (WSOCK32.112)
665  */
666 void WINAPI WSASetLastError(INT iError) {
667     SetLastError(iError);
668 }
669
670 /***********************************************************************
671  *      WSASetLastError16()             (WINSOCK.112)
672  */
673 void WINAPI WSASetLastError16(INT16 iError)
674 {
675     WSASetLastError(iError);
676 }
677
678 static char* check_buffer(int size)
679 {
680     static int local_buflen;
681
682     if (local_buffer)
683     {
684         if (local_buflen >= size ) return local_buffer;
685         SEGPTR_FREE(local_buffer);
686     }
687     local_buffer = SEGPTR_ALLOC((local_buflen = size));
688     return local_buffer;
689 }
690
691 static struct ws_hostent* check_buffer_he(int size)
692 {
693     static int he_len;
694     if (he_buffer)
695     {
696         if (he_len >= size ) return he_buffer;
697         SEGPTR_FREE(he_buffer);
698     }
699     he_buffer = SEGPTR_ALLOC((he_len = size));
700     return he_buffer;
701 }
702
703 static void* check_buffer_se(int size)
704 {
705     static int se_len;
706     if (se_buffer)
707     {
708         if (se_len >= size ) return se_buffer;
709         SEGPTR_FREE(se_buffer);
710     }
711     se_buffer = SEGPTR_ALLOC((se_len = size));
712     return se_buffer;
713 }
714
715 static struct ws_protoent* check_buffer_pe(int size)
716 {
717     static int pe_len;
718     if (pe_buffer)
719     {
720         if (pe_len >= size ) return pe_buffer;
721         SEGPTR_FREE(pe_buffer);
722     }
723     pe_buffer = SEGPTR_ALLOC((pe_len = size));
724     return pe_buffer;
725 }
726
727 /* ----------------------------------- i/o APIs */
728
729 /***********************************************************************
730  *              accept()                (WSOCK32.1)
731  */
732 static void WSOCK32_async_accept(SOCKET s, SOCKET as)
733 {
734     int q;
735     /* queue socket for WSAAsyncSelect */
736     for (q=0; q<WS_ACCEPT_QUEUE; q++)
737         if (InterlockedCompareExchange((PVOID*)&accept_old[q], (PVOID)s, (PVOID)0) == (PVOID)0)
738             break;
739     if (q<WS_ACCEPT_QUEUE)
740         accept_new[q] = as;
741     else
742         ERR("accept queue too small\n");
743     /* now signal our AsyncSelect handler */
744     _enable_event(s, WS_FD_SERVEVENT, 0, 0);
745 }
746
747 /**********************************************************************/
748
749 SOCKET WINAPI WSOCK32_accept(SOCKET s, struct sockaddr *addr,
750                                  INT *addrlen32)
751 {
752 #ifdef HAVE_IPX
753     struct ws_sockaddr_ipx*  addr2 = (struct ws_sockaddr_ipx *)addr;
754 #endif
755     int fd = _get_sock_fd(s);
756
757     TRACE("socket %04x\n", (UINT16)s );
758     if (fd != -1)
759     {
760         SOCKET as;
761         if (_is_blocking(s))
762         {
763             /* block here */
764             do_block(fd, 5);
765             _sync_sock_state(s); /* let wineserver notice connection */
766             /* retrieve any error codes from it */
767             SetLastError(_get_sock_error(s, FD_ACCEPT_BIT));
768             /* FIXME: care about the error? */
769         }
770         close(fd);
771         SERVER_START_REQ( accept_socket )
772         {
773             req->lhandle = s;
774             req->access  = GENERIC_READ|GENERIC_WRITE|SYNCHRONIZE;
775             req->inherit = TRUE;
776             set_error( SERVER_CALL() );
777             as = (SOCKET)req->handle;
778         }
779         SERVER_END_REQ;
780         if (as)
781         {
782             unsigned omask = _get_sock_mask( s );
783             int fd = _get_sock_fd( as );
784             if( getpeername(fd, addr, addrlen32) != -1 )
785             {
786 #ifdef HAVE_IPX
787                 if (addr && ((struct sockaddr_ipx *)addr)->sipx_family == AF_IPX) {
788                     addr = (struct sockaddr *)
789                                 malloc(addrlen32 ? *addrlen32 : sizeof(*addr2));
790                     memcpy(addr, addr2,
791                                 addrlen32 ? *addrlen32 : sizeof(*addr2));
792                     addr2->sipx_family = WS_AF_IPX;
793                     addr2->sipx_network = ((struct sockaddr_ipx *)addr)->sipx_network;
794                     addr2->sipx_port = ((struct sockaddr_ipx *)addr)->sipx_port;
795                     memcpy(addr2->sipx_node,
796                         ((struct sockaddr_ipx *)addr)->sipx_node, IPX_NODE_LEN);
797                     free(addr);
798                 }
799 #endif
800             } else SetLastError(wsaErrno());
801             close(fd);
802             if (omask & WS_FD_SERVEVENT)
803                 WSOCK32_async_accept(s, as);
804             return as;
805         }
806     }
807     return INVALID_SOCKET;
808 }
809
810 /***********************************************************************
811  *              accept()                (WINSOCK.1)
812  */
813 SOCKET16 WINAPI WINSOCK_accept16(SOCKET16 s, struct sockaddr* addr,
814                                  INT16* addrlen16 )
815 {
816     INT addrlen32 = addrlen16 ? *addrlen16 : 0;
817     SOCKET retSocket = WSOCK32_accept( s, addr, &addrlen32 );
818     if( addrlen16 ) *addrlen16 = (INT16)addrlen32;
819     return (SOCKET16)retSocket;
820 }
821
822 /***********************************************************************
823  *              bind()                  (WSOCK32.2)
824  */
825 INT WINAPI WSOCK32_bind(SOCKET s, struct sockaddr *name, INT namelen)
826 {
827 #ifdef HAVE_IPX
828     struct ws_sockaddr_ipx*  name2 = (struct ws_sockaddr_ipx *)name;
829 #endif
830     int fd = _get_sock_fd(s);
831
832     TRACE("socket %04x, ptr %8x, length %d\n", s, (int) name, namelen);
833 #if DEBUG_SOCKADDR
834     dump_sockaddr(name);
835 #endif
836
837     if (fd != -1)
838     {
839       /* FIXME: what family does this really map to on the Unix side? */
840       if (name && ((struct ws_sockaddr_ipx *)name)->sipx_family == WS_AF_PUP)
841         ((struct ws_sockaddr_ipx *)name)->sipx_family = AF_UNSPEC;
842 #ifdef HAVE_IPX
843       else if (name &&
844                 ((struct ws_sockaddr_ipx *)name)->sipx_family == WS_AF_IPX)
845       {
846         name = (struct sockaddr *) malloc(sizeof(struct sockaddr_ipx));
847         memset(name, '\0', sizeof(struct sockaddr_ipx));
848         ((struct sockaddr_ipx *)name)->sipx_family = AF_IPX;
849         ((struct sockaddr_ipx *)name)->sipx_port = name2->sipx_port;
850         ((struct sockaddr_ipx *)name)->sipx_network = name2->sipx_network;
851         memcpy(((struct sockaddr_ipx *)name)->sipx_node,
852                 name2->sipx_node, IPX_NODE_LEN);
853         namelen = sizeof(struct sockaddr_ipx);
854       }
855 #endif
856       if ( namelen >= sizeof(*name) ) 
857       {
858         if ( name && (((struct ws_sockaddr_in *)name)->sin_family == AF_INET
859 #ifdef HAVE_IPX
860              || ((struct sockaddr_ipx *)name)->sipx_family == AF_IPX
861 #endif
862            ))
863         {
864           if ( bind(fd, name, namelen) < 0 ) 
865           {
866              int        loc_errno = errno;
867              WARN("\tfailure - errno = %i\n", errno);
868              errno = loc_errno;
869              switch(errno)
870              {
871                 case EBADF: SetLastError(WSAENOTSOCK); break;
872                 case EADDRNOTAVAIL: SetLastError(WSAEINVAL); break;
873                 default: SetLastError(wsaErrno());break;
874              }
875           }
876           else {
877 #ifdef HAVE_IPX
878             if (((struct sockaddr_ipx *)name)->sipx_family == AF_IPX)
879                 free(name);
880 #endif
881             close(fd);
882             return 0; /* success */
883           }
884         } else SetLastError(WSAEAFNOSUPPORT);
885       } else SetLastError(WSAEFAULT);
886 #ifdef HAVE_IPX
887       if (name && ((struct sockaddr_ipx *)name)->sipx_family == AF_IPX)
888         free(name);
889 #endif
890       close(fd);
891     }
892     return SOCKET_ERROR;
893 }
894
895 /***********************************************************************
896  *              bind()                  (WINSOCK.2)
897  */
898 INT16 WINAPI WINSOCK_bind16(SOCKET16 s, struct sockaddr *name, INT16 namelen)
899 {
900   return (INT16)WSOCK32_bind( s, name, namelen );
901 }
902
903 /***********************************************************************
904  *              closesocket()           (WSOCK32.3)
905  */
906 INT WINAPI WSOCK32_closesocket(SOCKET s)
907 {
908     TRACE("socket %08x\n", s);
909     if (CloseHandle(s)) return 0;
910     return SOCKET_ERROR;
911 }
912
913 /***********************************************************************
914  *              closesocket()           (WINSOCK.3)
915  */
916 INT16 WINAPI WINSOCK_closesocket16(SOCKET16 s)
917 {
918     return (INT16)WSOCK32_closesocket(s);
919 }
920
921 /***********************************************************************
922  *              connect()               (WSOCK32.4)
923  */
924 INT WINAPI WSOCK32_connect(SOCKET s, struct sockaddr *name, INT namelen)
925 {
926 #ifdef HAVE_IPX
927   struct ws_sockaddr_ipx*  name2 = (struct ws_sockaddr_ipx *)name;
928 #endif
929   int fd = _get_sock_fd(s);
930
931   TRACE("socket %04x, ptr %8x, length %d\n", s, (int) name, namelen);
932 #if DEBUG_SOCKADDR
933   dump_sockaddr(name);
934 #endif
935
936   if (fd != -1)
937   {
938     if (name && ((struct ws_sockaddr_ipx *)name)->sipx_family == WS_AF_PUP)
939         ((struct ws_sockaddr_ipx *)name)->sipx_family = AF_UNSPEC;
940 #ifdef HAVE_IPX
941     else if (name && ((struct ws_sockaddr_ipx *)name)->sipx_family == WS_AF_IPX)
942     {
943         name = (struct sockaddr *) malloc(sizeof(struct sockaddr_ipx));
944         memset(name, '\0', sizeof(struct sockaddr_ipx));
945         ((struct sockaddr_ipx *)name)->sipx_family = AF_IPX;
946         ((struct sockaddr_ipx *)name)->sipx_port = name2->sipx_port;
947         ((struct sockaddr_ipx *)name)->sipx_network = name2->sipx_network;
948         memcpy(((struct sockaddr_ipx *)name)->sipx_node,
949                 name2->sipx_node, IPX_NODE_LEN);
950         namelen = sizeof(struct sockaddr_ipx);
951     }
952 #endif
953     if (connect(fd, name, namelen) == 0) {
954         close(fd);
955         goto connect_success;
956     }
957     if (errno == EINPROGRESS)
958     {
959         /* tell wineserver that a connection is in progress */
960         _enable_event(s, FD_CONNECT|FD_READ|FD_WRITE,
961                       WS_FD_CONNECT|WS_FD_READ|WS_FD_WRITE,
962                       WS_FD_CONNECTED|WS_FD_LISTENING);
963         if (_is_blocking(s))
964         {
965             int result;
966             /* block here */
967             do_block(fd, 7);
968             _sync_sock_state(s); /* let wineserver notice connection */
969             /* retrieve any error codes from it */
970             result = _get_sock_error(s, FD_CONNECT_BIT);
971             if (result)
972                 SetLastError(result);
973             else {
974                 close(fd);
975                 goto connect_success;
976             }
977         }
978         else SetLastError(WSAEWOULDBLOCK);
979         close(fd);
980     }
981     else
982     {
983         SetLastError(wsaErrno());
984         close(fd);
985     }
986   }
987 #ifdef HAVE_IPX
988   if (name && ((struct sockaddr_ipx *)name)->sipx_family == AF_IPX)
989     free(name);
990 #endif
991   return SOCKET_ERROR;
992 connect_success:
993 #ifdef HAVE_IPX
994     if (((struct sockaddr_ipx *)name)->sipx_family == AF_IPX)
995         free(name);
996 #endif
997     _enable_event(s, FD_CONNECT|FD_READ|FD_WRITE,
998                   WS_FD_CONNECTED|WS_FD_READ|WS_FD_WRITE,
999                   WS_FD_CONNECT|WS_FD_LISTENING);
1000     return 0; 
1001 }
1002
1003 /***********************************************************************
1004  *              connect()               (WINSOCK.4)
1005  */
1006 INT16 WINAPI WINSOCK_connect16(SOCKET16 s, struct sockaddr *name, INT16 namelen)
1007 {
1008   return (INT16)WSOCK32_connect( s, name, namelen );
1009 }
1010
1011 /***********************************************************************
1012  *              getpeername()           (WSOCK32.5)
1013  */
1014 INT WINAPI WSOCK32_getpeername(SOCKET s, struct sockaddr *name,
1015                                    INT *namelen)
1016 {
1017 #ifdef HAVE_IPX
1018     struct ws_sockaddr_ipx*  name2 = (struct ws_sockaddr_ipx *)name;
1019 #endif
1020     int fd = _get_sock_fd(s);
1021
1022     TRACE("socket: %04x, ptr %8x, ptr %8x\n", s, (int) name, *namelen);
1023     if (fd != -1)
1024     {
1025         if (getpeername(fd, name, namelen) == 0) {
1026 #ifdef HAVE_IPX
1027             if (((struct ws_sockaddr_ipx *)name)->sipx_family == AF_IPX) {
1028                 name = (struct sockaddr *)
1029                                 malloc(namelen ? *namelen : sizeof(*name2));
1030                 memcpy(name, name2, namelen ? *namelen : sizeof(*name2));
1031                 name2->sipx_family = WS_AF_IPX;
1032                 name2->sipx_network = ((struct sockaddr_ipx *)name)->sipx_network;
1033                 name2->sipx_port = ((struct sockaddr_ipx *)name)->sipx_port;
1034                 memcpy(name2->sipx_node,
1035                         ((struct sockaddr_ipx *)name)->sipx_node, IPX_NODE_LEN);
1036                 free(name);
1037             }
1038 #endif
1039             close(fd);
1040             return 0; 
1041         }
1042         SetLastError(wsaErrno());
1043         close(fd);
1044     }
1045     return SOCKET_ERROR;
1046 }
1047
1048 /***********************************************************************
1049  *              getpeername()           (WINSOCK.5)
1050  */
1051 INT16 WINAPI WINSOCK_getpeername16(SOCKET16 s, struct sockaddr *name,
1052                                    INT16 *namelen16)
1053 {
1054     INT namelen32 = *namelen16;
1055     INT retVal = WSOCK32_getpeername( s, name, &namelen32 );
1056
1057 #if DEBUG_SOCKADDR
1058     dump_sockaddr(name);
1059 #endif
1060
1061    *namelen16 = namelen32;
1062     return (INT16)retVal;
1063 }
1064
1065 /***********************************************************************
1066  *              getsockname()           (WSOCK32.6)
1067  */
1068 INT WINAPI WSOCK32_getsockname(SOCKET s, struct sockaddr *name,
1069                                    INT *namelen)
1070 {
1071 #ifdef HAVE_IPX
1072     struct ws_sockaddr_ipx*  name2 = (struct ws_sockaddr_ipx *)name;
1073 #endif
1074     int fd = _get_sock_fd(s);
1075
1076     TRACE("socket: %04x, ptr %8x, ptr %8x\n", s, (int) name, (int) *namelen);
1077     if (fd != -1)
1078     {
1079         if (getsockname(fd, name, namelen) == 0) {
1080 #ifdef HAVE_IPX
1081             if (((struct sockaddr_ipx *)name)->sipx_family == AF_IPX) {
1082                 name = (struct sockaddr *)
1083                                 malloc(namelen ? *namelen : sizeof(*name2));
1084                 memcpy(name, name2, namelen ? *namelen : sizeof(*name2));
1085                 name2->sipx_family = WS_AF_IPX;
1086                 name2->sipx_network = ((struct sockaddr_ipx *)name)->sipx_network;
1087                 name2->sipx_port = ((struct sockaddr_ipx *)name)->sipx_port;
1088                 memcpy(name2->sipx_node,
1089                         ((struct sockaddr_ipx *)name)->sipx_node, IPX_NODE_LEN);
1090                 free(name);
1091             }
1092 #endif
1093             close(fd);
1094             return 0; 
1095         }
1096         SetLastError(wsaErrno());
1097         close(fd);
1098     }
1099     return SOCKET_ERROR;
1100 }
1101
1102 /***********************************************************************
1103  *              getsockname()           (WINSOCK.6)
1104  */
1105 INT16 WINAPI WINSOCK_getsockname16(SOCKET16 s, struct sockaddr *name,
1106                                    INT16 *namelen16)
1107 {
1108     INT retVal;
1109
1110     if( namelen16 )
1111     {
1112         INT namelen32 = *namelen16;
1113         retVal = WSOCK32_getsockname( s, name, &namelen32 );
1114        *namelen16 = namelen32;
1115
1116 #if DEBUG_SOCKADDR
1117     dump_sockaddr(name);
1118 #endif
1119
1120     }
1121     else retVal = SOCKET_ERROR;
1122     return (INT16)retVal;
1123 }
1124
1125
1126 /***********************************************************************
1127  *              getsockopt()            (WSOCK32.7)
1128  */
1129 INT WINAPI WSOCK32_getsockopt(SOCKET s, INT level, 
1130                                   INT optname, char *optval, INT *optlen)
1131 {
1132     int fd = _get_sock_fd(s);
1133
1134     TRACE("socket: %04x, opt 0x%x, ptr %8x, len %d\n", s, level, (int) optval, (int) *optlen);
1135     if (fd != -1)
1136     {
1137         if (!convert_sockopt(&level, &optname)) {
1138             SetLastError(WSAENOPROTOOPT);       /* Unknown option */
1139         } else {
1140             if (getsockopt(fd, (int) level, optname, optval, optlen) == 0 )
1141             {
1142                 close(fd);
1143                 return 0;
1144             }
1145             SetLastError((errno == EBADF) ? WSAENOTSOCK : wsaErrno());
1146         }
1147         close(fd);
1148     }
1149     return SOCKET_ERROR;
1150 }
1151
1152 /***********************************************************************
1153  *              getsockopt()            (WINSOCK.7)
1154  */
1155 INT16 WINAPI WINSOCK_getsockopt16(SOCKET16 s, INT16 level,
1156                                   INT16 optname, char *optval, INT16 *optlen)
1157 {
1158     INT optlen32;
1159     INT *p = &optlen32;
1160     INT retVal;
1161     if( optlen ) optlen32 = *optlen; else p = NULL;
1162     retVal = WSOCK32_getsockopt( s, (UINT16)level, optname, optval, p );
1163     if( optlen ) *optlen = optlen32;
1164     return (INT16)retVal;
1165 }
1166
1167 /***********************************************************************
1168  *              htonl()                 (WINSOCK.8)(WSOCK32.8)
1169  */
1170 u_long WINAPI WINSOCK_htonl(u_long hostlong)   { return( htonl(hostlong) ); }
1171 /***********************************************************************
1172  *              htons()                 (WINSOCK.9)(WSOCK32.9)
1173  */
1174 u_short WINAPI WINSOCK_htons(u_short hostshort) { return( htons(hostshort) ); }
1175 /***********************************************************************
1176  *              inet_addr()             (WINSOCK.10)(WSOCK32.10)
1177  */
1178 u_long WINAPI WINSOCK_inet_addr(char *cp)      { return( inet_addr(cp) ); }
1179 /***********************************************************************
1180  *              ntohl()                 (WINSOCK.14)(WSOCK32.14)
1181  */
1182 u_long WINAPI WINSOCK_ntohl(u_long netlong)    { return( ntohl(netlong) ); }
1183 /***********************************************************************
1184  *              ntohs()                 (WINSOCK.15)(WSOCK32.15)
1185  */
1186 u_short WINAPI WINSOCK_ntohs(u_short netshort)  { return( ntohs(netshort) ); }
1187
1188 /***********************************************************************
1189  *              inet_ntoa()             (WINSOCK.11)(WSOCK32.11)
1190  */
1191 char* WINAPI WSOCK32_inet_ntoa(struct in_addr in)
1192 {
1193   /* use "buffer for dummies" here because some applications have 
1194    * propensity to decode addresses in ws_hostent structure without 
1195    * saving them first...
1196    */
1197     char* s = inet_ntoa(in);
1198     if( s )
1199     {
1200         if( dbuffer == NULL ) {
1201             /* Yes, 16: 4*3 digits + 3 '.' + 1 '\0' */
1202             if((dbuffer = (char*) SEGPTR_ALLOC(16)) == NULL )
1203             {
1204                 SetLastError(WSAENOBUFS);
1205                 return NULL;
1206             }
1207         }
1208         strcpy(dbuffer, s);
1209         return dbuffer;
1210     }
1211     SetLastError(wsaErrno());
1212     return NULL;
1213 }
1214
1215 /**********************************************************************/
1216
1217 SEGPTR WINAPI WINSOCK_inet_ntoa16(struct in_addr in)
1218 {
1219   char* retVal = WSOCK32_inet_ntoa(in);
1220   return SEGPTR_GET(retVal);
1221 }
1222
1223
1224 /**********************************************************************
1225  *              WSAIoctl                (WS2_32)
1226  *
1227  *
1228  *   FIXME:  Only SIO_GET_INTERFACE_LIST option implemented.
1229  */
1230 INT WINAPI WSAIoctl (SOCKET s,
1231                      DWORD   dwIoControlCode,
1232                      LPVOID  lpvInBuffer,
1233                      DWORD   cbInBuffer,
1234                      LPVOID  lpbOutBuffer,
1235                      DWORD   cbOutBuffer,
1236                      LPDWORD lpcbBytesReturned,
1237                      LPWSAOVERLAPPED lpOverlapped,
1238                      LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine)
1239 {
1240    int fd = _get_sock_fd(s);
1241
1242    if (fd != -1)
1243    {
1244       switch( dwIoControlCode )
1245       {
1246          case SIO_GET_INTERFACE_LIST:
1247          {
1248             INTERFACE_INFO* intArray = (INTERFACE_INFO*)lpbOutBuffer;
1249             int i, numInt;
1250             struct ifreq ifInfo;
1251             char ifName[512];
1252             
1253
1254             TRACE ("-> SIO_GET_INTERFACE_LIST request\n");
1255             
1256             numInt = WSAIOCTL_GetInterfaceCount(); 
1257             if (numInt < 0)
1258             {
1259                ERR ("Unable to open /proc filesystem to determine number of network interfaces!\n");
1260                close(fd);
1261                WSASetLastError(WSAEINVAL);
1262                return (SOCKET_ERROR);
1263             }
1264             
1265             for (i=0; i<numInt; i++)
1266             {
1267                if (!WSAIOCTL_GetInterfaceName(i, ifName))
1268                {
1269                   ERR ("Error parsing /proc filesystem!\n");
1270                   close(fd);
1271                   WSASetLastError(WSAEINVAL);
1272                   return (SOCKET_ERROR);
1273                }
1274                
1275                ifInfo.ifr_addr.sa_family = AF_INET; 
1276             
1277                /* IP Address */
1278                strcpy (ifInfo.ifr_name, ifName);
1279                if (ioctl(fd, SIOCGIFADDR, &ifInfo) < 0) 
1280                {
1281                   ERR ("Error obtaining IP address\n");
1282                   close(fd);
1283                   WSASetLastError(WSAEINVAL);
1284                   return (SOCKET_ERROR);
1285                }
1286                else
1287                {
1288                   struct ws_sockaddr_in *ipTemp = (struct ws_sockaddr_in *)&ifInfo.ifr_addr;
1289                
1290                   intArray->iiAddress.AddressIn.sin_family = AF_INET;
1291                   intArray->iiAddress.AddressIn.sin_port = ipTemp->sin_port;
1292                   intArray->iiAddress.AddressIn.sin_addr.ws_addr = ipTemp->sin_addr.S_un.S_addr;
1293                }
1294                
1295                /* Broadcast Address */
1296                strcpy (ifInfo.ifr_name, ifName);
1297                if (ioctl(fd, SIOCGIFBRDADDR, &ifInfo) < 0)
1298                {
1299                   ERR ("Error obtaining Broadcast IP address\n");
1300                   close(fd);
1301                   WSASetLastError(WSAEINVAL);
1302                   return (SOCKET_ERROR);
1303                }
1304                else
1305                {
1306                   struct ws_sockaddr_in *ipTemp = (struct ws_sockaddr_in *)&ifInfo.ifr_broadaddr;
1307                
1308                   intArray->iiBroadcastAddress.AddressIn.sin_family = AF_INET; 
1309                   intArray->iiBroadcastAddress.AddressIn.sin_port = ipTemp->sin_port;
1310                   intArray->iiBroadcastAddress.AddressIn.sin_addr.ws_addr = ipTemp->sin_addr.S_un.S_addr; 
1311                }
1312
1313                /* Subnet Mask */
1314                strcpy (ifInfo.ifr_name, ifName);
1315                if (ioctl(fd, SIOCGIFNETMASK, &ifInfo) < 0)
1316                {
1317                   ERR ("Error obtaining Subnet IP address\n");
1318                   close(fd);
1319                   WSASetLastError(WSAEINVAL);
1320                   return (SOCKET_ERROR);
1321                }
1322                else
1323                {
1324                   /* Trying to avoid some compile problems across platforms.
1325                      (Linux, FreeBSD, Solaris...) */
1326                   #ifndef ifr_netmask
1327                     #ifndef ifr_addr
1328                        intArray->iiNetmask.AddressIn.sin_family = AF_INET; 
1329                        intArray->iiNetmask.AddressIn.sin_port = 0;
1330                        intArray->iiNetmask.AddressIn.sin_addr.ws_addr = 0; 
1331                        ERR ("Unable to determine Netmask on your platform!\n");
1332                     #else
1333                        struct ws_sockaddr_in *ipTemp = (struct ws_sockaddr_in *)&ifInfo.ifr_addr;
1334             
1335                        intArray->iiNetmask.AddressIn.sin_family = AF_INET; 
1336                        intArray->iiNetmask.AddressIn.sin_port = ipTemp->sin_port;
1337                        intArray->iiNetmask.AddressIn.sin_addr.ws_addr = ipTemp->sin_addr.S_un.S_addr; 
1338                     #endif
1339                   #else
1340                      struct ws_sockaddr_in *ipTemp = (struct ws_sockaddr_in *)&ifInfo.ifr_netmask;
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                }
1347                
1348                /* Socket Status Flags */
1349                strcpy(ifInfo.ifr_name, ifName);
1350                if (ioctl(fd, SIOCGIFFLAGS, &ifInfo) < 0) 
1351                {
1352                   ERR ("Error obtaining status flags for socket!\n");
1353                   close(fd);
1354                   WSASetLastError(WSAEINVAL);
1355                   return (SOCKET_ERROR);
1356                }
1357                else
1358                {
1359                   /* FIXME - Is this the right flag to use? */
1360                   intArray->iiFlags = ifInfo.ifr_flags;
1361                }
1362                intArray++; /* Prepare for another interface */
1363             }
1364             
1365             /* Calculate the size of the array being returned */
1366             *lpcbBytesReturned = sizeof(INTERFACE_INFO) * numInt;
1367             break;
1368          }
1369
1370          default:
1371          {
1372             WARN("\tunsupported WS_IOCTL cmd (%08lx)\n", dwIoControlCode);
1373             close(fd);
1374             WSASetLastError(WSAEOPNOTSUPP);
1375             return (SOCKET_ERROR);
1376          }
1377       }
1378
1379       /* Function executed with no errors */
1380       close(fd);
1381       return (0); 
1382    }
1383    else
1384    {
1385       WSASetLastError(WSAENOTSOCK);
1386       return (SOCKET_ERROR);
1387    }
1388 }
1389
1390
1391 /* 
1392   Helper function for WSAIoctl - Get count of the number of interfaces
1393   by parsing /proc filesystem.
1394 */
1395 int WSAIOCTL_GetInterfaceCount(void)
1396 {
1397    FILE *procfs;
1398    char buf[512];  /* Size doesn't matter, something big */
1399    int  intcnt=0;
1400  
1401  
1402    /* Open /proc filesystem file for network devices */ 
1403    procfs = fopen(PROCFS_NETDEV_FILE, "r");
1404    if (!procfs) 
1405    {
1406       /* If we can't open the file, return an error */
1407       return (-1);
1408    }
1409    
1410    /* Omit first two lines, they are only headers */
1411    fgets(buf, sizeof buf, procfs);      
1412    fgets(buf, sizeof buf, procfs);
1413
1414    while (fgets(buf, sizeof buf, procfs)) 
1415    {
1416       /* Each line in the file represents a network interface */
1417       intcnt++;
1418    }
1419
1420    fclose(procfs);
1421    return(intcnt);
1422 }
1423
1424
1425 /*
1426    Helper function for WSAIoctl - Get name of device from interface number
1427    by parsing /proc filesystem.
1428 */
1429 int WSAIOCTL_GetInterfaceName(int intNumber, char *intName)
1430 {
1431    FILE *procfs;
1432    char buf[512]; /* Size doesn't matter, something big */
1433    int  i;
1434
1435    /* Open /proc filesystem file for network devices */ 
1436    procfs = fopen(PROCFS_NETDEV_FILE, "r");
1437    if (!procfs) 
1438    {
1439       /* If we can't open the file, return an error */
1440       return (-1);
1441    }
1442    
1443    /* Omit first two lines, they are only headers */
1444    fgets(buf, sizeof(buf), procfs);     
1445    fgets(buf, sizeof(buf), procfs);
1446
1447    for (i=0; i<intNumber; i++)
1448    {
1449       /* Skip the lines that don't interest us. */
1450       fgets(buf, sizeof(buf), procfs);
1451    }
1452    fgets(buf, sizeof(buf), procfs); /* This is the line we want */
1453
1454    
1455    /* Parse out the line, grabbing only the name of the device
1456       to the intName variable 
1457       
1458       The Line comes in like this: (we only care about the device name)
1459       lo:   21970 377 0 0 0 0 0 0 21970 377 0 0 0 0 0 0
1460    */
1461    i=0; 
1462    while (isspace(buf[i])) /* Skip initial space(s) */
1463    {
1464       i++;
1465    }
1466
1467    while (buf[i]) 
1468    {
1469       if (isspace(buf[i]))
1470       {
1471          break;
1472       }
1473       
1474       if (buf[i] == ':')  /* FIXME: Not sure if this block (alias detection) works properly */
1475       {
1476          /* This interface could be an alias... */
1477          int hold = i;
1478          char *dotname = intName;
1479          *intName++ = buf[i++];
1480          
1481          while (isdigit(buf[i]))
1482          {
1483             *intName++ = buf[i++];
1484          }
1485          
1486          if (buf[i] != ':') 
1487          {
1488             /* ... It wasn't, so back up */
1489             i = hold;
1490             intName = dotname;
1491          }
1492  
1493          if (buf[i] == '\0')
1494          {
1495             fclose(procfs);
1496             return(FALSE);
1497          }
1498          
1499          i++;
1500          break;
1501       }
1502       
1503       *intName++ = buf[i++];
1504    }
1505    *intName++ = '\0';
1506
1507    fclose(procfs);
1508    return(TRUE);
1509  }
1510
1511
1512 /***********************************************************************
1513  *              ioctlsocket()           (WSOCK32.12)
1514  */
1515 INT WINAPI WSOCK32_ioctlsocket(SOCKET s, LONG cmd, ULONG *argp)
1516 {
1517   int fd = _get_sock_fd(s);
1518
1519   TRACE("socket %04x, cmd %08lx, ptr %8x\n", s, cmd, (unsigned) argp);
1520   if (fd != -1)
1521   {
1522     long        newcmd  = cmd;
1523
1524     switch( cmd )
1525     {
1526         case WS_FIONREAD:   
1527                 newcmd=FIONREAD; 
1528                 break;
1529
1530         case WS_FIONBIO:    
1531                 newcmd=FIONBIO;  
1532                 if( _get_sock_mask(s) )
1533                 {
1534                     /* AsyncSelect()'ed sockets are always nonblocking */
1535                     if (*argp) {
1536                         close(fd);
1537                         return 0;
1538                     }
1539                     SetLastError(WSAEINVAL); 
1540                     close(fd);
1541                     return SOCKET_ERROR; 
1542                 }
1543                 close(fd);
1544                 if (*argp)
1545                     _enable_event(s, 0, WS_FD_NONBLOCKING, 0);
1546                 else
1547                     _enable_event(s, 0, 0, WS_FD_NONBLOCKING);
1548                 return 0;
1549
1550         case WS_SIOCATMARK: 
1551                 newcmd=SIOCATMARK; 
1552                 break;
1553
1554         case WS_IOW('f',125,u_long): 
1555                 WARN("Warning: WS1.1 shouldn't be using async I/O\n");
1556                 SetLastError(WSAEINVAL); 
1557                 return SOCKET_ERROR;
1558         
1559         case SIOCGIFBRDADDR:
1560         case SIOCGIFNETMASK:
1561         case SIOCGIFADDR:
1562                 /* These don't need any special handling.  They are used by
1563                    WsControl, and are here to suppress an unecessary warning. */
1564                 break;
1565                    
1566         
1567         default:          
1568                 /* Netscape tries hard to use bogus ioctl 0x667e */
1569                 WARN("\tunknown WS_IOCTL cmd (%08lx)\n", cmd);
1570     }
1571     if( ioctl(fd, newcmd, (char*)argp ) == 0 )
1572     {
1573         close(fd);
1574         return 0;
1575     }
1576     SetLastError((errno == EBADF) ? WSAENOTSOCK : wsaErrno()); 
1577     close(fd);
1578   }
1579   return SOCKET_ERROR;
1580 }
1581
1582 /***********************************************************************
1583  *              ioctlsocket()           (WINSOCK.12)
1584  */
1585 INT16 WINAPI WINSOCK_ioctlsocket16(SOCKET16 s, LONG cmd, ULONG *argp)
1586 {
1587     return (INT16)WSOCK32_ioctlsocket( s, cmd, argp );
1588 }
1589
1590
1591 /***********************************************************************
1592  *              listen()                (WSOCK32.13)
1593  */
1594 INT WINAPI WSOCK32_listen(SOCKET s, INT backlog)
1595 {
1596     int fd = _get_sock_fd(s);
1597
1598     TRACE("socket %04x, backlog %d\n", s, backlog);
1599     if (fd != -1)
1600     {
1601         if (listen(fd, backlog) == 0)
1602         {
1603             close(fd);
1604             _enable_event(s, FD_ACCEPT,
1605                           WS_FD_LISTENING,
1606                           WS_FD_CONNECT|WS_FD_CONNECTED);
1607             return 0;
1608         }
1609         SetLastError(wsaErrno());
1610     }
1611     else SetLastError(WSAENOTSOCK);
1612     return SOCKET_ERROR;
1613 }
1614
1615 /***********************************************************************
1616  *              listen()                (WINSOCK.13)
1617  */
1618 INT16 WINAPI WINSOCK_listen16(SOCKET16 s, INT16 backlog)
1619 {
1620     return (INT16)WSOCK32_listen( s, backlog );
1621 }
1622
1623
1624 /***********************************************************************
1625  *              recv()                  (WSOCK32.16)
1626  */
1627 INT WINAPI WSOCK32_recv(SOCKET s, char *buf, INT len, INT flags)
1628 {
1629     int fd = _get_sock_fd(s);
1630
1631     TRACE("socket %04x, buf %8x, len %d, flags %d\n", s, (unsigned)buf, len, flags);
1632
1633     if (fd != -1)
1634     {
1635         INT length;
1636
1637         if (_is_blocking(s))
1638         {
1639             /* block here */
1640             /* FIXME: OOB and exceptfds? */
1641             do_block(fd, 1);
1642         }
1643         if ((length = recv(fd, buf, len, flags)) >= 0) 
1644         { 
1645             TRACE(" -> %i bytes\n", length);
1646
1647             close(fd);
1648             _enable_event(s, FD_READ, 0, 0);
1649             return length;
1650         }
1651         SetLastError(wsaErrno());
1652         close(fd);
1653     }
1654     else SetLastError(WSAENOTSOCK);
1655     WARN(" -> ERROR\n");
1656     return SOCKET_ERROR;
1657 }
1658
1659 /***********************************************************************
1660  *              recv()                  (WINSOCK.16)
1661  */
1662 INT16 WINAPI WINSOCK_recv16(SOCKET16 s, char *buf, INT16 len, INT16 flags)
1663 {
1664     return (INT16)WSOCK32_recv( s, buf, len, flags );
1665 }
1666
1667
1668 /***********************************************************************
1669  *              recvfrom()              (WSOCK32.17)
1670  */
1671 INT WINAPI WSOCK32_recvfrom(SOCKET s, char *buf, INT len, INT flags, 
1672                                 struct sockaddr *from, INT *fromlen32)
1673 {
1674 #ifdef HAVE_IPX
1675     struct ws_sockaddr_ipx*  from2 = (struct ws_sockaddr_ipx *)from;
1676 #endif
1677     int fd = _get_sock_fd(s);
1678
1679     TRACE("socket %04x, ptr %08x, len %d, flags %d\n", s, (unsigned)buf, len, flags);
1680 #if DEBUG_SOCKADDR
1681     if( from ) dump_sockaddr(from);
1682     else DPRINTF("from = NULL\n");
1683 #endif
1684
1685     if (fd != -1)
1686     {
1687         int length;
1688
1689         if (_is_blocking(s))
1690         {
1691             /* block here */
1692             /* FIXME: OOB and exceptfds */
1693             do_block(fd, 1);
1694         }
1695         if ((length = recvfrom(fd, buf, len, flags, from, fromlen32)) >= 0)
1696         {
1697             TRACE(" -> %i bytes\n", length);
1698
1699 #ifdef HAVE_IPX
1700         if (from && ((struct sockaddr_ipx *)from)->sipx_family == AF_IPX) {
1701             from = (struct sockaddr *)
1702                                 malloc(fromlen32 ? *fromlen32 : sizeof(*from2));
1703             memcpy(from, from2, fromlen32 ? *fromlen32 : sizeof(*from2));
1704             from2->sipx_family = WS_AF_IPX;
1705             from2->sipx_network = ((struct sockaddr_ipx *)from)->sipx_network;
1706             from2->sipx_port = ((struct sockaddr_ipx *)from)->sipx_port;
1707             memcpy(from2->sipx_node,
1708                         ((struct sockaddr_ipx *)from)->sipx_node, IPX_NODE_LEN);
1709             free(from);
1710         }
1711 #endif
1712             close(fd);
1713             _enable_event(s, FD_READ, 0, 0);
1714             return length;
1715         }
1716         SetLastError(wsaErrno());
1717         close(fd);
1718     }
1719     else SetLastError(WSAENOTSOCK);
1720     WARN(" -> ERROR\n");
1721 #ifdef HAVE_IPX
1722     if (from && ((struct sockaddr_ipx *)from)->sipx_family == AF_IPX) {
1723         from = (struct sockaddr *)
1724                                 malloc(fromlen32 ? *fromlen32 : sizeof(*from2));
1725         memcpy(from, from2, fromlen32 ? *fromlen32 : sizeof(*from2));
1726         from2->sipx_family = WS_AF_IPX;
1727         from2->sipx_network = ((struct sockaddr_ipx *)from)->sipx_network;
1728         from2->sipx_port = ((struct sockaddr_ipx *)from)->sipx_port;
1729         memcpy(from2->sipx_node,
1730                 ((struct sockaddr_ipx *)from)->sipx_node, IPX_NODE_LEN);
1731         free(from);
1732     }
1733 #endif
1734     return SOCKET_ERROR;
1735 }
1736
1737 /***********************************************************************
1738  *              recvfrom()              (WINSOCK.17)
1739  */
1740 INT16 WINAPI WINSOCK_recvfrom16(SOCKET16 s, char *buf, INT16 len, INT16 flags,
1741                                 struct sockaddr *from, INT16 *fromlen16)
1742 {
1743     INT fromlen32;
1744     INT *p = &fromlen32;
1745     INT retVal;
1746
1747     if( fromlen16 ) fromlen32 = *fromlen16; else p = NULL;
1748     retVal = WSOCK32_recvfrom( s, buf, len, flags, from, p );
1749     if( fromlen16 ) *fromlen16 = fromlen32;
1750     return (INT16)retVal;
1751 }
1752
1753 /***********************************************************************
1754  *              select()                (WINSOCK.18)(WSOCK32.18)
1755  */
1756 static INT __ws_select( BOOL b32, void *ws_readfds, void *ws_writefds, void *ws_exceptfds,
1757                           struct timeval *timeout )
1758 {
1759     int         highfd = 0;
1760     fd_set      readfds, writefds, exceptfds;
1761     fd_set     *p_read, *p_write, *p_except;
1762     int         readfd[FD_SETSIZE], writefd[FD_SETSIZE], exceptfd[FD_SETSIZE];
1763
1764     TRACE("read %p, write %p, excp %p\n", ws_readfds, ws_writefds, ws_exceptfds);
1765
1766     p_read = fd_set_import(&readfds, ws_readfds, &highfd, readfd, b32);
1767     p_write = fd_set_import(&writefds, ws_writefds, &highfd, writefd, b32);
1768     p_except = fd_set_import(&exceptfds, ws_exceptfds, &highfd, exceptfd, b32);
1769
1770     if( (highfd = select(highfd + 1, p_read, p_write, p_except, timeout)) > 0 )
1771     {
1772         fd_set_export(&readfds, p_except, ws_readfds, readfd, b32);
1773         fd_set_export(&writefds, p_except, ws_writefds, writefd, b32);
1774
1775         if (p_except && ws_exceptfds)
1776         {
1777 #define wsfds16 ((ws_fd_set16*)ws_exceptfds)
1778 #define wsfds32 ((ws_fd_set32*)ws_exceptfds)
1779             int i, j, count = (b32) ? wsfds32->fd_count : wsfds16->fd_count;
1780
1781             for (i = j = 0; i < count; i++)
1782             {
1783                 int fd = exceptfd[i];
1784                 if( fd >= 0 && FD_ISSET(fd, &exceptfds) )
1785                 {
1786                     if( b32 )
1787                         wsfds32->fd_array[j++] = wsfds32->fd_array[i];
1788                     else
1789                         wsfds16->fd_array[j++] = wsfds16->fd_array[i];
1790                 }
1791                 if( fd >= 0 ) close(fd);
1792                 exceptfd[i] = -1;
1793             }
1794             if( b32 )
1795                 wsfds32->fd_count = j;
1796             else
1797                 wsfds16->fd_count = j;
1798 #undef wsfds32
1799 #undef wsfds16
1800         }
1801         return highfd;
1802     }
1803     fd_set_unimport(ws_readfds, readfd, b32);
1804     fd_set_unimport(ws_writefds, writefd, b32);
1805     fd_set_unimport(ws_exceptfds, exceptfd, b32);
1806     if( ws_readfds ) ((ws_fd_set32*)ws_readfds)->fd_count = 0;
1807     if( ws_writefds ) ((ws_fd_set32*)ws_writefds)->fd_count = 0;
1808     if( ws_exceptfds ) ((ws_fd_set32*)ws_exceptfds)->fd_count = 0;
1809
1810     if( highfd == 0 ) return 0;
1811     SetLastError(wsaErrno());
1812     return SOCKET_ERROR;
1813 }
1814
1815 INT16 WINAPI WINSOCK_select16(INT16 nfds, ws_fd_set16 *ws_readfds,
1816                               ws_fd_set16 *ws_writefds, ws_fd_set16 *ws_exceptfds,
1817                               struct timeval *timeout)
1818 {
1819     return (INT16)__ws_select( FALSE, ws_readfds, ws_writefds, ws_exceptfds, timeout );
1820 }
1821
1822 INT WINAPI WSOCK32_select(INT nfds, ws_fd_set32 *ws_readfds,
1823                               ws_fd_set32 *ws_writefds, ws_fd_set32 *ws_exceptfds,
1824                               struct timeval *timeout)
1825 {
1826     /* struct timeval is the same for both 32- and 16-bit code */
1827     return (INT)__ws_select( TRUE, ws_readfds, ws_writefds, ws_exceptfds, timeout );
1828 }
1829
1830
1831 /***********************************************************************
1832  *              send()                  (WSOCK32.19)
1833  */
1834 INT WINAPI WSOCK32_send(SOCKET s, char *buf, INT len, INT flags)
1835 {
1836     int fd = _get_sock_fd(s);
1837
1838     TRACE("socket %04x, ptr %p, length %d, flags %d\n", s, buf, len, flags);
1839     if (fd != -1)
1840     {
1841         int     length;
1842
1843         if (_is_blocking(s))
1844         {
1845             /* block here */
1846             /* FIXME: exceptfds */
1847             do_block(fd, 2);
1848         }
1849         if ((length = send(fd, buf, len, flags)) < 0 ) 
1850         {
1851             SetLastError(wsaErrno());
1852             if( GetLastError() == WSAEWOULDBLOCK )
1853                 _enable_event(s, FD_WRITE, 0, 0);
1854         }
1855         else
1856         {
1857             close(fd);
1858             return length;
1859         }
1860         close(fd);
1861     }
1862     else SetLastError(WSAENOTSOCK);
1863     return SOCKET_ERROR;
1864 }
1865
1866 /***********************************************************************
1867  *              WSASend                 (WSOCK32.72)
1868  */
1869 INT WINAPI WSASend( SOCKET s, LPWSABUF lpBuffers, DWORD dwBufferCount,
1870                     LPDWORD lpNumberOfBytesSent, DWORD dwFlags,
1871                     LPWSAOVERLAPPED lpOverlapped,
1872                     LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine )
1873 {
1874   INT iFlags = 0;
1875   INT rc = 0;
1876   DWORD dwCount;
1877
1878   /* Overlapped is not supported or checked for */
1879   FIXME( "(%u,%p,0x%lx,%p,0x%lx,%p,%p): semi stub\n", 
1880            s, lpBuffers, dwBufferCount, lpNumberOfBytesSent,
1881            dwFlags, lpOverlapped, lpCompletionRoutine );
1882
1883   /* Convert setup flags */
1884   if( dwFlags & MSG_DONTROUTE )
1885   {
1886     iFlags |= MSG_DONTROUTE;
1887   }
1888
1889   if( dwFlags & MSG_OOB )
1890   {
1891     iFlags |= MSG_OOB;
1892   }
1893
1894   /* Indicate nothing yet sent */
1895   *lpNumberOfBytesSent = 0;
1896
1897   /* Send all buffers with the same flags */
1898   for(dwCount = 0; dwCount < dwBufferCount; dwCount++ )
1899   {
1900     if( ( rc = WSOCK32_send( s, lpBuffers[ dwCount ].buf, 
1901                              lpBuffers[ dwCount ].len, iFlags ) ) != 0 )
1902     {
1903       break;
1904     }
1905
1906     /* Indicate that we've sent something */
1907     *lpNumberOfBytesSent += lpBuffers[ dwCount ].len;
1908   }
1909
1910   return rc;
1911 }
1912
1913 /***********************************************************************
1914  *              send()                  (WINSOCK.19)
1915  */
1916 INT16 WINAPI WINSOCK_send16(SOCKET16 s, char *buf, INT16 len, INT16 flags)
1917 {
1918     return WSOCK32_send( s, buf, len, flags );
1919 }
1920
1921 /***********************************************************************
1922  *              sendto()                (WSOCK32.20)
1923  */
1924 INT WINAPI WSOCK32_sendto(SOCKET s, char *buf, INT len, INT flags,
1925                               struct sockaddr *to, INT tolen)
1926 {
1927 #ifdef HAVE_IPX
1928     struct ws_sockaddr_ipx*  to2 = (struct ws_sockaddr_ipx *)to;
1929 #endif
1930     int fd = _get_sock_fd(s);
1931
1932     TRACE("socket %04x, ptr %p, length %d, flags %d\n", s, buf, len, flags);
1933     if (fd != -1)
1934     {
1935         INT     length;
1936
1937         if (to && ((struct ws_sockaddr_ipx *)to)->sipx_family == WS_AF_PUP)
1938             ((struct ws_sockaddr_ipx *)to)->sipx_family = AF_UNSPEC;
1939 #ifdef HAVE_IPX
1940         else if (to &&
1941                 ((struct ws_sockaddr_ipx *)to)->sipx_family == WS_AF_IPX)
1942         {
1943             to = (struct sockaddr *) malloc(sizeof(struct sockaddr_ipx));
1944             memset(to, '\0', sizeof(struct sockaddr_ipx));
1945             ((struct sockaddr_ipx *)to)->sipx_family = AF_IPX;
1946             ((struct sockaddr_ipx *)to)->sipx_port = to2->sipx_port;
1947             ((struct sockaddr_ipx *)to)->sipx_network = to2->sipx_network;
1948             memcpy(((struct sockaddr_ipx *)to)->sipx_node,
1949                         to2->sipx_node, IPX_NODE_LEN);
1950             tolen = sizeof(struct sockaddr_ipx);
1951         }
1952 #endif
1953         if (_is_blocking(s))
1954         {
1955             /* block here */
1956             /* FIXME: exceptfds */
1957             do_block(fd, 2);
1958         }
1959         if ((length = sendto(fd, buf, len, flags, to, tolen)) < 0 )
1960         {
1961             SetLastError(wsaErrno());
1962             if( GetLastError() == WSAEWOULDBLOCK )
1963                 _enable_event(s, FD_WRITE, 0, 0);
1964         } 
1965         else {
1966 #ifdef HAVE_IPX
1967             if (to && ((struct sockaddr_ipx *)to)->sipx_family == AF_IPX) {
1968                 free(to);
1969             }
1970 #endif
1971             close(fd);
1972             return length;
1973         }
1974         close(fd);
1975     }
1976     else SetLastError(WSAENOTSOCK);
1977 #ifdef HAVE_IPX
1978     if (to && ((struct sockaddr_ipx *)to)->sipx_family == AF_IPX) {
1979         free(to);
1980     }
1981 #endif
1982     return SOCKET_ERROR;
1983 }
1984
1985 /***********************************************************************
1986  *              sendto()                (WINSOCK.20)
1987  */
1988 INT16 WINAPI WINSOCK_sendto16(SOCKET16 s, char *buf, INT16 len, INT16 flags,
1989                               struct sockaddr *to, INT16 tolen)
1990 {
1991     return (INT16)WSOCK32_sendto( s, buf, len, flags, to, tolen );
1992 }
1993
1994 /***********************************************************************
1995  *              setsockopt()            (WSOCK32.21)
1996  */
1997 INT WINAPI WSOCK32_setsockopt(SOCKET16 s, INT level, INT optname, 
1998                                   char *optval, INT optlen)
1999 {
2000     int fd = _get_sock_fd(s);
2001
2002     TRACE("socket %04x, lev %d, opt 0x%x, ptr %08x, len %d\n",
2003           s, level, optname, (int) optval, optlen);
2004     if (fd != -1)
2005     {
2006         struct  linger linger;
2007         int woptval;
2008
2009         /* Is a privileged and useless operation, so we don't. */
2010         if ((optname == WS_SO_DEBUG) && (level == WS_SOL_SOCKET)) {
2011             FIXME("(%d,SOL_SOCKET,SO_DEBUG,%p(%ld)) attempted (is privileged). Ignoring.\n",s,optval,*(DWORD*)optval);
2012             return 0;
2013         }
2014
2015         if(optname == WS_SO_DONTLINGER && level == WS_SOL_SOCKET) {
2016             /* This is unique to WinSock and takes special conversion */
2017             linger.l_onoff      = *((int*)optval) ? 0: 1;
2018             linger.l_linger     = 0;
2019             optname=SO_LINGER;
2020             optval = (char*)&linger;
2021             optlen = sizeof(struct linger);
2022             level = SOL_SOCKET;
2023         }else{
2024             if (!convert_sockopt(&level, &optname)) {
2025                 SetLastError(WSAENOPROTOOPT);
2026                 close(fd);
2027                 return SOCKET_ERROR;
2028             }
2029             if (optname == SO_LINGER && optval) {
2030                 /* yes, uses unsigned short in both win16/win32 */
2031                 linger.l_onoff  = ((UINT16*)optval)[0];
2032                 linger.l_linger = ((UINT16*)optval)[1];
2033                 /* FIXME: what is documented behavior if SO_LINGER optval
2034                    is null?? */
2035                 optval = (char*)&linger;
2036                 optlen = sizeof(struct linger);
2037             } else if (optlen < sizeof(int)){
2038                 woptval= *((INT16 *) optval);
2039                 optval= (char*) &woptval;
2040                 optlen=sizeof(int);
2041             }
2042         }
2043         if(optname == SO_RCVBUF && *(int*)optval < 2048) {
2044             WARN("SO_RCVBF for %d bytes is too small: ignored\n", *(int*)optval );
2045             close( fd);
2046             return 0;
2047         }
2048
2049         if (setsockopt(fd, level, optname, optval, optlen) == 0)
2050         {
2051             close(fd);
2052             return 0;
2053         }
2054         SetLastError(wsaErrno());
2055         close(fd);
2056     }
2057     else SetLastError(WSAENOTSOCK);
2058     return SOCKET_ERROR;
2059 }
2060
2061 /***********************************************************************
2062  *              setsockopt()            (WINSOCK.21)
2063  */
2064 INT16 WINAPI WINSOCK_setsockopt16(SOCKET16 s, INT16 level, INT16 optname,
2065                                   char *optval, INT16 optlen)
2066 {
2067     if( !optval ) return SOCKET_ERROR;
2068     return (INT16)WSOCK32_setsockopt( s, (UINT16)level, optname, optval, optlen );
2069 }
2070
2071
2072 /***********************************************************************
2073  *              shutdown()              (WSOCK32.22)
2074  */
2075 INT WINAPI WSOCK32_shutdown(SOCKET s, INT how)
2076 {
2077     int fd = _get_sock_fd(s);
2078
2079     TRACE("socket %04x, how %i\n", s, how );
2080     if (fd != -1)
2081     {
2082             switch( how )
2083             {
2084                 case 0: /* drop receives */
2085                         _enable_event(s, 0, 0, WS_FD_READ);
2086 #ifdef SHUT_RD
2087                         how = SHUT_RD;
2088 #endif
2089                         break;
2090
2091                 case 1: /* drop sends */
2092                         _enable_event(s, 0, 0, WS_FD_WRITE);
2093 #ifdef SHUT_WR
2094                         how = SHUT_WR;
2095 #endif
2096                         break;
2097
2098                 case 2: /* drop all */
2099 #ifdef SHUT_RDWR
2100                         how = SHUT_RDWR;
2101 #endif
2102                 default:
2103                         WSAAsyncSelect( s, 0, 0, 0 );
2104                         break;
2105             }
2106
2107         if (shutdown(fd, how) == 0) 
2108         {
2109             if( how > 1 ) 
2110             {
2111                 _enable_event(s, 0, 0, WS_FD_CONNECTED|WS_FD_LISTENING);
2112             }
2113             close(fd);
2114             return 0;
2115         }
2116         SetLastError(wsaErrno());
2117         close(fd);
2118     } 
2119     else SetLastError(WSAENOTSOCK);
2120     return SOCKET_ERROR;
2121 }
2122
2123 /***********************************************************************
2124  *              shutdown()              (WINSOCK.22)
2125  */
2126 INT16 WINAPI WINSOCK_shutdown16(SOCKET16 s, INT16 how)
2127 {
2128     return (INT16)WSOCK32_shutdown( s, how );
2129 }
2130
2131
2132 /***********************************************************************
2133  *              socket()                (WSOCK32.23)
2134  */
2135 SOCKET WINAPI WSOCK32_socket(INT af, INT type, INT protocol)
2136 {
2137     SOCKET ret;
2138
2139     TRACE("af=%d type=%d protocol=%d\n", af, type, protocol);
2140
2141     /* check the socket family */
2142     switch(af) 
2143     {
2144 #ifdef HAVE_IPX
2145         case WS_AF_IPX: af = AF_IPX;
2146 #endif
2147         case AF_INET:
2148         case AF_UNSPEC: break;
2149         default:        SetLastError(WSAEAFNOSUPPORT); 
2150                         return INVALID_SOCKET;
2151     }
2152
2153     /* check the socket type */
2154     switch(type) 
2155     {
2156         case SOCK_STREAM:
2157         case SOCK_DGRAM:
2158         case SOCK_RAW:  break;
2159         default:        SetLastError(WSAESOCKTNOSUPPORT); 
2160                         return INVALID_SOCKET;
2161     }
2162
2163     /* check the protocol type */
2164     if ( protocol < 0 )  /* don't support negative values */
2165     { SetLastError(WSAEPROTONOSUPPORT); return INVALID_SOCKET; }
2166
2167     if ( af == AF_UNSPEC)  /* did they not specify the address family? */
2168         switch(protocol) 
2169         {
2170           case IPPROTO_TCP:
2171              if (type == SOCK_STREAM) { af = AF_INET; break; }
2172           case IPPROTO_UDP:
2173              if (type == SOCK_DGRAM)  { af = AF_INET; break; }
2174           default: SetLastError(WSAEPROTOTYPE); return INVALID_SOCKET;
2175         }
2176
2177     SERVER_START_REQ( create_socket )
2178     {
2179         req->family   = af;
2180         req->type     = type;
2181         req->protocol = protocol;
2182         req->access   = GENERIC_READ|GENERIC_WRITE|SYNCHRONIZE;
2183         req->inherit  = TRUE;
2184         set_error( SERVER_CALL() );
2185         ret = (SOCKET)req->handle;
2186     }
2187     SERVER_END_REQ;
2188     if (ret)
2189     {
2190         TRACE("\tcreated %04x\n", ret );
2191         return ret;
2192     }
2193
2194     if (GetLastError() == WSAEACCES) /* raw socket denied */
2195     {
2196         if (type == SOCK_RAW)
2197             MESSAGE("WARNING: Trying to create a socket of type SOCK_RAW, will fail unless running as root\n");
2198         else
2199             MESSAGE("WS_SOCKET: not enough privileges to create socket, try running as root\n");
2200         SetLastError(WSAESOCKTNOSUPPORT);
2201     }
2202
2203     WARN("\t\tfailed!\n");
2204     return INVALID_SOCKET;
2205 }
2206
2207 /***********************************************************************
2208  *              socket()                (WINSOCK.23)
2209  */
2210 SOCKET16 WINAPI WINSOCK_socket16(INT16 af, INT16 type, INT16 protocol)
2211 {
2212     return (SOCKET16)WSOCK32_socket( af, type, protocol );
2213 }
2214     
2215
2216 /* ----------------------------------- DNS services
2217  *
2218  * IMPORTANT: 16-bit API structures have SEGPTR pointers inside them.
2219  * Also, we have to use wsock32 stubs to convert structures and
2220  * error codes from Unix to WSA, hence there is no direct mapping in 
2221  * the relay32/wsock32.spec.
2222  */
2223
2224 static char*    NULL_STRING = "NULL";
2225
2226 /***********************************************************************
2227  *              gethostbyaddr()         (WINSOCK.51)(WSOCK32.51)
2228  */
2229 static WIN_hostent* __ws_gethostbyaddr(const char *addr, int len, int type, int dup_flag)
2230 {
2231     WIN_hostent *retval = NULL;
2232
2233     struct hostent* host;
2234 #if HAVE_LINUX_GETHOSTBYNAME_R_6
2235     char *extrabuf;
2236     int ebufsize=1024;
2237     struct hostent hostentry;
2238     int locerr=ENOBUFS;
2239     host = NULL;
2240     extrabuf=HeapAlloc(GetProcessHeap(),0,ebufsize) ;
2241     while(extrabuf) { 
2242         int res = gethostbyaddr_r(addr, len, type, 
2243                                   &hostentry, extrabuf, ebufsize, &host, &locerr);
2244         if( res != ERANGE) break;
2245         ebufsize *=2;
2246         extrabuf=HeapReAlloc(GetProcessHeap(),0,extrabuf,ebufsize) ;
2247     }
2248     if (!host) SetLastError((locerr < 0) ? wsaErrno() : wsaHerrno(locerr));
2249 #else
2250     EnterCriticalSection( &csWSgetXXXbyYYY );
2251     host = gethostbyaddr(addr, len, type);
2252     if (!host) SetLastError((h_errno < 0) ? wsaErrno() : wsaHerrno(h_errno));
2253 #endif
2254     if( host != NULL )
2255     {
2256         if( WS_dup_he(host, dup_flag) )
2257             retval = he_buffer;
2258         else 
2259             SetLastError(WSAENOBUFS);
2260     }
2261 #ifdef  HAVE_LINUX_GETHOSTBYNAME_R_6
2262     HeapFree(GetProcessHeap(),0,extrabuf);
2263 #else
2264     LeaveCriticalSection( &csWSgetXXXbyYYY );
2265 #endif
2266     return retval;
2267 }
2268
2269 SEGPTR WINAPI WINSOCK_gethostbyaddr16(const char *addr, INT16 len, INT16 type)
2270 {
2271     WIN_hostent* retval;
2272     TRACE("ptr %08x, len %d, type %d\n",
2273                             (unsigned) addr, len, type);
2274     retval = __ws_gethostbyaddr( addr, len, type, WS_DUP_SEGPTR );
2275     return SEGPTR_GET(retval);
2276 }
2277
2278 WIN_hostent* WINAPI WSOCK32_gethostbyaddr(const char *addr, INT len,
2279                                                 INT type)
2280 {
2281     TRACE("ptr %08x, len %d, type %d\n",
2282                              (unsigned) addr, len, type);
2283     return __ws_gethostbyaddr(addr, len, type, WS_DUP_LINEAR);
2284 }
2285
2286 /***********************************************************************
2287  *              gethostbyname()         (WINSOCK.52)(WSOCK32.52)
2288  */
2289 static WIN_hostent * __ws_gethostbyname(const char *name, int dup_flag)
2290 {
2291     WIN_hostent *retval = NULL;
2292     struct hostent*     host;
2293 #ifdef  HAVE_LINUX_GETHOSTBYNAME_R_6
2294     char *extrabuf;
2295     int ebufsize=1024;
2296     struct hostent hostentry;
2297     int locerr = ENOBUFS;
2298     host = NULL;
2299     extrabuf=HeapAlloc(GetProcessHeap(),0,ebufsize) ;
2300     while(extrabuf) {
2301         int res = gethostbyname_r(name, &hostentry, extrabuf, ebufsize, &host, &locerr);
2302         if( res != ERANGE) break;
2303         ebufsize *=2;
2304         extrabuf=HeapReAlloc(GetProcessHeap(),0,extrabuf,ebufsize) ;
2305     }
2306     if (!host) SetLastError((locerr < 0) ? wsaErrno() : wsaHerrno(locerr));
2307 #else
2308     EnterCriticalSection( &csWSgetXXXbyYYY );
2309     host = gethostbyname(name);
2310     if (!host) SetLastError((h_errno < 0) ? wsaErrno() : wsaHerrno(h_errno));
2311 #endif
2312     if( host  != NULL )
2313     {
2314         if( WS_dup_he(host, dup_flag) )
2315             retval = he_buffer;
2316         else SetLastError(WSAENOBUFS);
2317     }
2318 #ifdef  HAVE_LINUX_GETHOSTBYNAME_R_6
2319     HeapFree(GetProcessHeap(),0,extrabuf);
2320 #else
2321     LeaveCriticalSection( &csWSgetXXXbyYYY );
2322 #endif
2323     return retval;
2324 }
2325
2326 SEGPTR WINAPI WINSOCK_gethostbyname16(const char *name)
2327 {
2328     WIN_hostent* retval;
2329     TRACE("%s\n", (name)?name:NULL_STRING);
2330     retval = __ws_gethostbyname( name, WS_DUP_SEGPTR );
2331     return SEGPTR_GET(retval);
2332 }
2333
2334 WIN_hostent* WINAPI WSOCK32_gethostbyname(const char* name)
2335 {
2336     TRACE("%s\n", (name)?name:NULL_STRING);
2337     return __ws_gethostbyname( name, WS_DUP_LINEAR );
2338 }
2339
2340
2341 /***********************************************************************
2342  *              getprotobyname()        (WINSOCK.53)(WSOCK32.53)
2343  */
2344 static WIN_protoent* __ws_getprotobyname(const char *name, int dup_flag)
2345 {
2346     WIN_protoent* retval = NULL;
2347
2348     struct protoent*     proto;
2349     EnterCriticalSection( &csWSgetXXXbyYYY );
2350     if( (proto = getprotobyname(name)) != NULL )
2351     {
2352         if( WS_dup_pe(proto, dup_flag) )
2353             retval = pe_buffer;
2354         else SetLastError(WSAENOBUFS);
2355     }
2356     else {
2357         MESSAGE("protocol %s not found; You might want to add "
2358                 "this to /etc/protocols\n", debugstr_a(name) );
2359         SetLastError(WSANO_DATA);
2360     }
2361     LeaveCriticalSection( &csWSgetXXXbyYYY );
2362     return retval;
2363 }
2364
2365 SEGPTR WINAPI WINSOCK_getprotobyname16(const char *name)
2366 {
2367     WIN_protoent* retval;
2368     TRACE("%s\n", (name)?name:NULL_STRING);
2369     retval = __ws_getprotobyname(name, WS_DUP_SEGPTR);
2370     return SEGPTR_GET(retval);
2371 }
2372
2373 WIN_protoent* WINAPI WSOCK32_getprotobyname(const char* name)
2374 {
2375     TRACE("%s\n", (name)?name:NULL_STRING);
2376     return __ws_getprotobyname(name, WS_DUP_LINEAR);
2377 }
2378
2379
2380 /***********************************************************************
2381  *              getprotobynumber()      (WINSOCK.54)(WSOCK32.54)
2382  */
2383 static WIN_protoent* __ws_getprotobynumber(int number, int dup_flag)
2384 {
2385     WIN_protoent* retval = NULL;
2386     struct protoent*     proto;
2387     EnterCriticalSection( &csWSgetXXXbyYYY );
2388     if( (proto = getprotobynumber(number)) != NULL )
2389     {
2390         if( WS_dup_pe(proto, dup_flag) )
2391             retval = pe_buffer;
2392         else SetLastError(WSAENOBUFS);
2393     }
2394     else {
2395         MESSAGE("protocol number %d not found; You might want to add "
2396                 "this to /etc/protocols\n", number );
2397         SetLastError(WSANO_DATA);
2398     }
2399     LeaveCriticalSection( &csWSgetXXXbyYYY );
2400     return retval;
2401 }
2402
2403 SEGPTR WINAPI WINSOCK_getprotobynumber16(INT16 number)
2404 {
2405     WIN_protoent* retval;
2406     TRACE("%i\n", number);
2407     retval = __ws_getprotobynumber(number, WS_DUP_SEGPTR);
2408     return SEGPTR_GET(retval);
2409 }
2410
2411 WIN_protoent* WINAPI WSOCK32_getprotobynumber(INT number)
2412 {
2413     TRACE("%i\n", number);
2414     return __ws_getprotobynumber(number, WS_DUP_LINEAR);
2415 }
2416
2417
2418 /***********************************************************************
2419  *              getservbyname()         (WINSOCK.55)(WSOCK32.55)
2420  */
2421 static WIN_servent* __ws_getservbyname(const char *name, const char *proto, int dup_flag)
2422 {
2423     WIN_servent* retval = NULL;
2424     struct servent*     serv;
2425     int i = wsi_strtolo( name, proto );
2426
2427     if( i ) {
2428         EnterCriticalSection( &csWSgetXXXbyYYY );
2429         serv = getservbyname(local_buffer,
2430                              proto ? (local_buffer + i) : NULL);
2431         if( serv != NULL )
2432         {
2433             if( WS_dup_se(serv, dup_flag) )
2434                 retval = se_buffer;
2435             else SetLastError(WSAENOBUFS);
2436         }
2437         else {
2438             MESSAGE("service %s protocol %s not found; You might want to add "
2439                     "this to /etc/services\n", debugstr_a(local_buffer),
2440                     proto ? debugstr_a(local_buffer+i):"*");
2441             SetLastError(WSANO_DATA);
2442         }
2443         LeaveCriticalSection( &csWSgetXXXbyYYY );
2444     }
2445     else SetLastError(WSAENOBUFS);
2446     return retval;
2447 }
2448
2449 SEGPTR WINAPI WINSOCK_getservbyname16(const char *name, const char *proto)
2450 {
2451     WIN_servent* retval;
2452     TRACE("'%s', '%s'\n",
2453                             (name)?name:NULL_STRING, (proto)?proto:NULL_STRING);
2454     retval = __ws_getservbyname(name, proto, WS_DUP_SEGPTR);
2455     return SEGPTR_GET(retval);
2456 }
2457
2458 WIN_servent* WINAPI WSOCK32_getservbyname(const char *name, const char *proto)
2459 {
2460     TRACE("'%s', '%s'\n",
2461                             (name)?name:NULL_STRING, (proto)?proto:NULL_STRING);
2462     return __ws_getservbyname(name, proto, WS_DUP_LINEAR);
2463 }
2464
2465
2466 /***********************************************************************
2467  *              getservbyport()         (WINSOCK.56)(WSOCK32.56)
2468  */
2469 static WIN_servent* __ws_getservbyport(int port, const char* proto, int dup_flag)
2470 {
2471     WIN_servent* retval = NULL;
2472     struct servent*     serv;
2473     if (!proto || wsi_strtolo( proto, NULL )) {
2474         EnterCriticalSection( &csWSgetXXXbyYYY );
2475         if( (serv = getservbyport(port, (proto) ? local_buffer : NULL)) != NULL ) {
2476             if( WS_dup_se(serv, dup_flag) )
2477                 retval = se_buffer;
2478             else SetLastError(WSAENOBUFS);
2479         }
2480         else {
2481             MESSAGE("service on port %lu protocol %s not found; You might want to add "
2482                     "this to /etc/services\n", (unsigned long)ntohl(port),
2483                     proto ? debugstr_a(local_buffer) : "*");
2484             SetLastError(WSANO_DATA);
2485         }
2486         LeaveCriticalSection( &csWSgetXXXbyYYY );
2487     }
2488     else SetLastError(WSAENOBUFS);
2489     return retval;
2490 }
2491
2492 SEGPTR WINAPI WINSOCK_getservbyport16(INT16 port, const char *proto)
2493 {
2494     WIN_servent* retval;
2495     TRACE("%d (i.e. port %d), '%s'\n",
2496                             (int)port, (int)ntohl(port), (proto)?proto:NULL_STRING);
2497     retval = __ws_getservbyport(port, proto, WS_DUP_SEGPTR);
2498     return SEGPTR_GET(retval);
2499 }
2500
2501 WIN_servent* WINAPI WSOCK32_getservbyport(INT port, const char *proto)
2502 {
2503     TRACE("%d (i.e. port %d), '%s'\n",
2504                             (int)port, (int)ntohl(port), (proto)?proto:NULL_STRING);
2505     return __ws_getservbyport(port, proto, WS_DUP_LINEAR);
2506 }
2507
2508
2509 /***********************************************************************
2510  *              gethostname()           (WSOCK32.57)
2511  */
2512 INT WINAPI WSOCK32_gethostname(char *name, INT namelen)
2513 {
2514     TRACE("name %p, len %d\n", name, namelen);
2515
2516     if (gethostname(name, namelen) == 0)
2517     {
2518         TRACE("<- '%s'\n", name);
2519         return 0;
2520     }
2521     SetLastError((errno == EINVAL) ? WSAEFAULT : wsaErrno());
2522     TRACE("<- ERROR !\n");
2523     return SOCKET_ERROR;
2524 }
2525
2526 /***********************************************************************
2527  *              gethostname()           (WINSOCK.57)
2528  */
2529 INT16 WINAPI WINSOCK_gethostname16(char *name, INT16 namelen)
2530 {
2531     return (INT16)WSOCK32_gethostname(name, namelen);
2532 }
2533
2534
2535 /* ------------------------------------- Windows sockets extensions -- *
2536  *                                                                     *
2537  * ------------------------------------------------------------------- */
2538
2539 /***********************************************************************
2540  *              WSAEnumNetworkEvents
2541  */
2542 int WINAPI WSAEnumNetworkEvents(SOCKET s, WSAEVENT hEvent, LPWSANETWORKEVENTS lpEvent)
2543 {
2544     int ret;
2545
2546     TRACE("%08x, hEvent %08x, lpEvent %08x\n", s, hEvent, (unsigned)lpEvent );
2547
2548     SERVER_START_VAR_REQ( get_socket_event, sizeof(lpEvent->iErrorCode) )
2549     {
2550         req->handle  = s;
2551         req->service = TRUE;
2552         req->s_event = 0;
2553         req->c_event = hEvent;
2554         if (!(ret = SERVER_CALL()))
2555         {
2556             lpEvent->lNetworkEvents = req->pmask;
2557             memcpy(lpEvent->iErrorCode, server_data_ptr(req), server_data_size(req) );
2558         }
2559     }
2560     SERVER_END_VAR_REQ;
2561     if (!ret) return 0;
2562     SetLastError(WSAEINVAL);
2563     return SOCKET_ERROR;
2564 }
2565
2566 /***********************************************************************
2567  *              WSAEventSelect
2568  */
2569 int WINAPI WSAEventSelect(SOCKET s, WSAEVENT hEvent, LONG lEvent)
2570 {
2571     int ret;
2572
2573     TRACE("%08x, hEvent %08x, event %08x\n", s, hEvent, (unsigned)lEvent );
2574
2575     SERVER_START_REQ( set_socket_event )
2576     {
2577         req->handle = s;
2578         req->mask   = lEvent;
2579         req->event  = hEvent;
2580         ret = SERVER_CALL();
2581     }
2582     SERVER_END_REQ;
2583     if (!ret) return 0;
2584     SetLastError(WSAEINVAL);
2585     return SOCKET_ERROR;
2586 }
2587
2588 /***********************************************************************
2589  *      WSAAsyncSelect()                (WINSOCK.101)(WSOCK32.101)
2590  */
2591
2592 VOID CALLBACK WINSOCK_DoAsyncEvent( ULONG_PTR ptr )
2593 {
2594     ws_select_info *info = (ws_select_info*)ptr;
2595     unsigned int i, pmask, orphan = FALSE;
2596     int errors[FD_MAX_EVENTS];
2597
2598     TRACE("socket %08x, event %08x\n", info->sock, info->event);
2599     SetLastError(0);
2600     SERVER_START_VAR_REQ( get_socket_event, sizeof(errors) )
2601     {
2602         req->handle  = info->sock;
2603         req->service = TRUE;
2604         req->s_event = info->event; /* <== avoid race conditions */
2605         req->c_event = info->event;
2606         set_error( SERVER_CALL() );
2607         pmask = req->pmask;
2608         memcpy( errors, server_data_ptr(req), server_data_size(req) );
2609     }
2610     SERVER_END_VAR_REQ;
2611     if ( (GetLastError() == WSAENOTSOCK) || (GetLastError() == WSAEINVAL) )
2612     {
2613         /* orphaned event (socket closed or something) */
2614         pmask = WS_FD_SERVEVENT;
2615         orphan = TRUE;
2616     }
2617
2618     /* check for accepted sockets that needs to inherit WSAAsyncSelect */
2619     if (pmask & WS_FD_SERVEVENT) {
2620         int q;
2621         for (q=0; q<WS_ACCEPT_QUEUE; q++)
2622             if (accept_old[q] == info->sock) {
2623                 /* there's only one service thread per process, no lock necessary */
2624                 HANDLE as = accept_new[q];
2625                 if (as) {
2626                     accept_new[q] = 0;
2627                     accept_old[q] = 0;
2628                     WSAAsyncSelect(as, info->hWnd, info->uMsg, info->lEvent);
2629                 }
2630             }
2631         pmask &= ~WS_FD_SERVEVENT;
2632     }
2633     /* dispatch network events */
2634     for (i=0; i<FD_MAX_EVENTS; i++)
2635         if (pmask & (1<<i)) {
2636             TRACE("post: event bit %d, error %d\n", i, errors[i]);
2637             PostMessageA(info->hWnd, info->uMsg, info->sock,
2638                          WSAMAKESELECTREPLY(1<<i, errors[i]));
2639         }
2640     /* cleanup */
2641     if (orphan)
2642     {
2643         TRACE("orphaned event, self-destructing\n");
2644         /* SERVICE_Delete closes the event object */
2645         SERVICE_Delete( info->service );
2646         WS_FREE(info);
2647     }
2648 }
2649
2650 /**********************************************************************/
2651
2652 INT WINAPI WSAAsyncSelect(SOCKET s, HWND hWnd, UINT uMsg, LONG lEvent)
2653 {
2654     int fd = _get_sock_fd(s);
2655
2656     TRACE("%04x, hWnd %04x, uMsg %08x, event %08x\n",
2657           (SOCKET16)s, (HWND16)hWnd, uMsg, (unsigned)lEvent );
2658     if (fd != -1)
2659     {
2660         close(fd);
2661         if( lEvent )
2662         {
2663             ws_select_info *info = (ws_select_info*)WS_ALLOC(sizeof(ws_select_info));
2664             if( info )
2665             {
2666                 HANDLE hObj = CreateEventA( NULL, TRUE, FALSE, NULL );
2667                 INT err;
2668                 
2669                 info->sock   = s;
2670                 info->event  = hObj;
2671                 info->hWnd   = hWnd;
2672                 info->uMsg   = uMsg;
2673                 info->lEvent = lEvent;
2674                 info->service = SERVICE_AddObject( hObj, WINSOCK_DoAsyncEvent, (ULONG_PTR)info );
2675
2676                 err = WSAEventSelect( s, hObj, lEvent | WS_FD_SERVEVENT );
2677                 if (err) {
2678                     /* SERVICE_Delete closes the event object */
2679                     SERVICE_Delete( info->service );
2680                     WS_FREE(info);
2681                     return err;
2682                 }
2683
2684                 return 0; /* success */
2685             }
2686             else SetLastError(WSAENOBUFS);
2687         } 
2688         else
2689         {
2690             WSAEventSelect(s, 0, 0);
2691             return 0;
2692         }
2693     } 
2694     else SetLastError(WSAEINVAL);
2695     return SOCKET_ERROR; 
2696 }
2697
2698 /**********************************************************************/
2699
2700 INT16 WINAPI WSAAsyncSelect16(SOCKET16 s, HWND16 hWnd, UINT16 wMsg, LONG lEvent)
2701 {
2702     return (INT16)WSAAsyncSelect( s, hWnd, wMsg, lEvent );
2703 }
2704
2705 /***********************************************************************
2706  *              WSARecvEx16()                   (WINSOCK.1107)
2707  *
2708  * See description for WSARecvEx()
2709  */
2710 INT16     WINAPI WSARecvEx16(SOCKET16 s, char *buf, INT16 len, INT16 *flags) {
2711   FIXME("(WSARecvEx16) partial packet return value not set \n");
2712
2713   return WINSOCK_recv16(s, buf, len, *flags);
2714 }
2715
2716
2717 /***********************************************************************
2718  *      WSACreateEvent()          (WS2_32.???)
2719  *
2720  */
2721 WSAEVENT WINAPI WSACreateEvent(void)
2722 {
2723     /* Create a manual-reset event, with initial state: unsignealed */
2724     TRACE("\n");
2725     
2726     return CreateEventA(NULL, TRUE, FALSE, NULL);    
2727 }
2728
2729 /***********************************************************************
2730  *      WSACloseEvent()          (WS2_32.???)
2731  *
2732  */
2733 BOOL WINAPI WSACloseEvent(WSAEVENT event)
2734 {
2735     TRACE ("event=0x%x\n", event);
2736
2737     return CloseHandle(event);
2738 }
2739
2740 /***********************************************************************
2741  *      WSASocketA()          (WS2_32.???)
2742  *
2743  */
2744 SOCKET WINAPI WSASocketA(int af, int type, int protocol,
2745                          LPWSAPROTOCOL_INFOA lpProtocolInfo,
2746                          GROUP g, DWORD dwFlags)
2747 {
2748    /* 
2749       FIXME: The "advanced" parameters of WSASocketA (lpProtocolInfo,
2750       g, dwFlags) are ignored.
2751    */
2752    
2753    TRACE("af=%d type=%d protocol=%d protocol_info=%p group=%d flags=0x%lx\n", 
2754          af, type, protocol, lpProtocolInfo, g, dwFlags );
2755
2756    return ( WSOCK32_socket (af, type, protocol) );
2757 }
2758
2759
2760 /***********************************************************************
2761  *      __WSAFDIsSet()                  (WINSOCK.151)
2762  */
2763 INT16 WINAPI __WSAFDIsSet16(SOCKET16 s, ws_fd_set16 *set)
2764 {
2765   int i = set->fd_count;
2766   
2767   TRACE("(%d,%8lx(%i))\n", s,(unsigned long)set, i);
2768     
2769   while (i--)
2770       if (set->fd_array[i] == s) return 1;
2771   return 0;
2772 }                                                            
2773
2774 /***********************************************************************
2775  *      __WSAFDIsSet()                  (WSOCK32.151)
2776  */
2777 INT WINAPI __WSAFDIsSet(SOCKET s, ws_fd_set32 *set)
2778 {
2779   int i = set->fd_count;
2780
2781   TRACE("(%d,%8lx(%i))\n", s,(unsigned long)set, i);
2782
2783   while (i--)
2784       if (set->fd_array[i] == s) return 1;
2785   return 0;
2786 }
2787
2788 /***********************************************************************
2789  *      WSAIsBlocking()                 (WINSOCK.114)(WSOCK32.114)
2790  */
2791 BOOL WINAPI WSAIsBlocking(void)
2792 {
2793   /* By default WinSock should set all its sockets to non-blocking mode
2794    * and poll in PeekMessage loop when processing "blocking" ones. This 
2795    * function is supposed to tell if the program is in this loop. Our 
2796    * blocking calls are truly blocking so we always return FALSE.
2797    *
2798    * Note: It is allowed to call this function without prior WSAStartup().
2799    */
2800
2801   TRACE("\n");
2802   return FALSE;
2803 }
2804
2805 /***********************************************************************
2806  *      WSACancelBlockingCall()         (WINSOCK.113)(WSOCK32.113)
2807  */
2808 INT WINAPI WSACancelBlockingCall(void)
2809 {
2810     TRACE("\n");
2811     return 0;
2812 }
2813
2814
2815 /***********************************************************************
2816  *      WSASetBlockingHook16()          (WINSOCK.109)
2817  */
2818 FARPROC16 WINAPI WSASetBlockingHook16(FARPROC16 lpBlockFunc)
2819 {
2820   FARPROC16 prev = (FARPROC16)blocking_hook;
2821   blocking_hook = (FARPROC)lpBlockFunc;
2822   TRACE("hook %p\n", lpBlockFunc);
2823   return prev;
2824 }
2825
2826
2827 /***********************************************************************
2828  *      WSASetBlockingHook()
2829  */
2830 FARPROC WINAPI WSASetBlockingHook(FARPROC lpBlockFunc)
2831 {
2832   FARPROC prev = blocking_hook;
2833   blocking_hook = lpBlockFunc;
2834   TRACE("hook %p\n", lpBlockFunc);
2835   return prev;
2836 }
2837
2838
2839 /***********************************************************************
2840  *      WSAUnhookBlockingHook16()       (WINSOCK.110)
2841  */
2842 INT16 WINAPI WSAUnhookBlockingHook16(void)
2843 {
2844     blocking_hook = NULL;
2845     return 0;
2846 }
2847
2848
2849 /***********************************************************************
2850  *      WSAUnhookBlockingHook()
2851  */
2852 INT WINAPI WSAUnhookBlockingHook(void)
2853 {
2854     blocking_hook = NULL;
2855     return 0;
2856 }
2857
2858
2859 /* ----------------------------------- end of API stuff */
2860
2861 /* ----------------------------------- helper functions -
2862  *
2863  * TODO: Merge WS_dup_..() stuff into one function that
2864  * would operate with a generic structure containing internal
2865  * pointers (via a template of some kind).
2866  */
2867
2868 static int list_size(char** l, int item_size)
2869 {
2870   int i,j = 0;
2871   if(l)
2872   { for(i=0;l[i];i++) 
2873         j += (item_size) ? item_size : strlen(l[i]) + 1;
2874     j += (i + 1) * sizeof(char*); }
2875   return j;
2876 }
2877
2878 static int list_dup(char** l_src, char* ref, char* base, int item_size)
2879
2880    /* base is either either equal to ref or 0 or SEGPTR */
2881
2882    char*                p = ref;
2883    char**               l_to = (char**)ref;
2884    int                  i,j,k;
2885
2886    for(j=0;l_src[j];j++) ;
2887    p += (j + 1) * sizeof(char*);
2888    for(i=0;i<j;i++)
2889    { l_to[i] = base + (p - ref);
2890      k = ( item_size ) ? item_size : strlen(l_src[i]) + 1;
2891      memcpy(p, l_src[i], k); p += k; }
2892    l_to[i] = NULL;
2893    return (p - ref);
2894 }
2895
2896 /* ----- hostent */
2897
2898 static int hostent_size(struct hostent* p_he)
2899 {
2900   int size = 0;
2901   if( p_he )
2902   { size  = sizeof(struct hostent); 
2903     size += strlen(p_he->h_name) + 1;
2904     size += list_size(p_he->h_aliases, 0);  
2905     size += list_size(p_he->h_addr_list, p_he->h_length ); }
2906   return size;
2907 }
2908
2909 /* duplicate hostent entry
2910  * and handle all Win16/Win32 dependent things (struct size, ...) *correctly*.
2911  * Dito for protoent and servent.
2912  */
2913 int WS_dup_he(struct hostent* p_he, int flag)
2914 {
2915     /* Convert hostent structure into ws_hostent so that the data fits 
2916      * into local_buffer. Internal pointers can be linear, SEGPTR, or 
2917      * relative to local_buffer depending on "flag" value. Returns size
2918      * of the data copied.
2919      */
2920
2921     int size = hostent_size(p_he);
2922     if( size )
2923     {
2924         char *p_name,*p_aliases,*p_addr,*p_base,*p;
2925         char *p_to;
2926         struct ws_hostent16 *p_to16;
2927         struct ws_hostent32 *p_to32;
2928
2929         check_buffer_he(size);
2930         p_to = he_buffer;
2931         p_to16 = he_buffer;
2932         p_to32 = he_buffer;
2933
2934         p = p_to;
2935         p_base = (flag & WS_DUP_OFFSET) ? NULL
2936             : ((flag & WS_DUP_SEGPTR) ? (char*)SEGPTR_GET(p) : p);
2937         p += (flag & WS_DUP_SEGPTR) ?
2938             sizeof(struct ws_hostent16) : sizeof(struct ws_hostent32);
2939         p_name = p;
2940         strcpy(p, p_he->h_name); p += strlen(p) + 1;
2941         p_aliases = p;
2942         p += list_dup(p_he->h_aliases, p, p_base + (p - p_to), 0);
2943         p_addr = p;
2944         list_dup(p_he->h_addr_list, p, p_base + (p - p_to), p_he->h_length);
2945
2946         if (flag & WS_DUP_SEGPTR) /* Win16 */
2947         {
2948             p_to16->h_addrtype = (INT16)p_he->h_addrtype; 
2949             p_to16->h_length = (INT16)p_he->h_length;
2950             p_to16->h_name = (SEGPTR)(p_base + (p_name - p_to));
2951             p_to16->h_aliases = (SEGPTR)(p_base + (p_aliases - p_to));
2952             p_to16->h_addr_list = (SEGPTR)(p_base + (p_addr - p_to));
2953             size += (sizeof(struct ws_hostent16) - sizeof(struct hostent));
2954         }
2955         else /* Win32 */
2956         {
2957             p_to32->h_addrtype = p_he->h_addrtype; 
2958             p_to32->h_length = p_he->h_length;
2959             p_to32->h_name = (p_base + (p_name - p_to));
2960             p_to32->h_aliases = (char **)(p_base + (p_aliases - p_to));
2961             p_to32->h_addr_list = (char **)(p_base + (p_addr - p_to));
2962             size += (sizeof(struct ws_hostent32) - sizeof(struct hostent));
2963         }
2964     }
2965     return size;
2966 }
2967
2968 /* ----- protoent */
2969
2970 static int protoent_size(struct protoent* p_pe)
2971 {
2972   int size = 0;
2973   if( p_pe )
2974   { size  = sizeof(struct protoent);
2975     size += strlen(p_pe->p_name) + 1;
2976     size += list_size(p_pe->p_aliases, 0); }
2977   return size;
2978 }
2979
2980 int WS_dup_pe(struct protoent* p_pe, int flag)
2981 {
2982     int size = protoent_size(p_pe);
2983     if( size )
2984     {
2985         char *p_to;
2986         struct ws_protoent16 *p_to16;
2987         struct ws_protoent32 *p_to32;
2988         char *p_name,*p_aliases,*p_base,*p;
2989
2990         check_buffer_pe(size);
2991         p_to = pe_buffer;
2992         p_to16 = pe_buffer;
2993         p_to32 = pe_buffer;
2994         p = p_to;
2995         p_base = (flag & WS_DUP_OFFSET) ? NULL
2996             : ((flag & WS_DUP_SEGPTR) ? (char*)SEGPTR_GET(p) : p);
2997         p += (flag & WS_DUP_SEGPTR) ?
2998             sizeof(struct ws_protoent16) : sizeof(struct ws_protoent32);
2999         p_name = p;
3000         strcpy(p, p_pe->p_name); p += strlen(p) + 1;
3001         p_aliases = p;
3002         list_dup(p_pe->p_aliases, p, p_base + (p - p_to), 0);
3003
3004         if (flag & WS_DUP_SEGPTR) /* Win16 */
3005         {
3006             p_to16->p_proto = (INT16)p_pe->p_proto;
3007             p_to16->p_name = (SEGPTR)(p_base) + (p_name - p_to);
3008             p_to16->p_aliases = (SEGPTR)((p_base) + (p_aliases - p_to)); 
3009             size += (sizeof(struct ws_protoent16) - sizeof(struct protoent));
3010         }
3011         else /* Win32 */
3012         {
3013             p_to32->p_proto = p_pe->p_proto;
3014             p_to32->p_name = (p_base) + (p_name - p_to);
3015             p_to32->p_aliases = (char **)((p_base) + (p_aliases - p_to)); 
3016             size += (sizeof(struct ws_protoent32) - sizeof(struct protoent));
3017         }
3018     }
3019     return size;
3020 }
3021
3022 /* ----- servent */
3023
3024 static int servent_size(struct servent* p_se)
3025 {
3026   int size = 0;
3027   if( p_se )
3028   { size += sizeof(struct servent);
3029     size += strlen(p_se->s_proto) + strlen(p_se->s_name) + 2;
3030     size += list_size(p_se->s_aliases, 0); }
3031   return size;
3032 }
3033
3034 int WS_dup_se(struct servent* p_se, int flag)
3035 {
3036     int size = servent_size(p_se);
3037     if( size )
3038     {
3039         char *p_name,*p_aliases,*p_proto,*p_base,*p;
3040         char *p_to;
3041         struct ws_servent16 *p_to16;
3042         struct ws_servent32 *p_to32;
3043
3044         check_buffer_se(size);
3045         p_to = se_buffer;
3046         p_to16 = se_buffer;
3047         p_to32 = se_buffer;
3048         p = p_to;
3049         p_base = (flag & WS_DUP_OFFSET) ? NULL 
3050             : ((flag & WS_DUP_SEGPTR) ? (char*)SEGPTR_GET(p) : p);
3051         p += (flag & WS_DUP_SEGPTR) ?
3052             sizeof(struct ws_servent16) : sizeof(struct ws_servent32);
3053         p_name = p;
3054         strcpy(p, p_se->s_name); p += strlen(p) + 1;
3055         p_proto = p;
3056         strcpy(p, p_se->s_proto); p += strlen(p) + 1;
3057         p_aliases = p;
3058         list_dup(p_se->s_aliases, p, p_base + (p - p_to), 0);
3059
3060         if (flag & WS_DUP_SEGPTR) /* Win16 */
3061         { 
3062             p_to16->s_port = (INT16)p_se->s_port;
3063             p_to16->s_name = (SEGPTR)(p_base + (p_name - p_to));
3064             p_to16->s_proto = (SEGPTR)(p_base + (p_proto - p_to));
3065             p_to16->s_aliases = (SEGPTR)(p_base + (p_aliases - p_to));
3066             size += (sizeof(struct ws_servent16) - sizeof(struct servent));
3067         }
3068         else /* Win32 */
3069         {
3070             p_to32->s_port = p_se->s_port;
3071             p_to32->s_name = (p_base + (p_name - p_to));
3072             p_to32->s_proto = (p_base + (p_proto - p_to));
3073             p_to32->s_aliases = (char **)(p_base + (p_aliases - p_to));
3074             size += (sizeof(struct ws_servent32) - sizeof(struct servent));
3075         }
3076     }
3077     return size;
3078 }
3079
3080 /* ----------------------------------- error handling */
3081
3082 UINT16 wsaErrno(void)
3083 {
3084     int loc_errno = errno; 
3085     WARN("errno %d, (%s).\n", loc_errno, strerror(loc_errno));
3086
3087     switch(loc_errno)
3088     {
3089         case EINTR:             return WSAEINTR;
3090         case EBADF:             return WSAEBADF;
3091         case EPERM:
3092         case EACCES:            return WSAEACCES;
3093         case EFAULT:            return WSAEFAULT;
3094         case EINVAL:            return WSAEINVAL;
3095         case EMFILE:            return WSAEMFILE;
3096         case EWOULDBLOCK:       return WSAEWOULDBLOCK;
3097         case EINPROGRESS:       return WSAEINPROGRESS;
3098         case EALREADY:          return WSAEALREADY;
3099         case ENOTSOCK:          return WSAENOTSOCK;
3100         case EDESTADDRREQ:      return WSAEDESTADDRREQ;
3101         case EMSGSIZE:          return WSAEMSGSIZE;
3102         case EPROTOTYPE:        return WSAEPROTOTYPE;
3103         case ENOPROTOOPT:       return WSAENOPROTOOPT;
3104         case EPROTONOSUPPORT:   return WSAEPROTONOSUPPORT;
3105         case ESOCKTNOSUPPORT:   return WSAESOCKTNOSUPPORT;
3106         case EOPNOTSUPP:        return WSAEOPNOTSUPP;
3107         case EPFNOSUPPORT:      return WSAEPFNOSUPPORT;
3108         case EAFNOSUPPORT:      return WSAEAFNOSUPPORT;
3109         case EADDRINUSE:        return WSAEADDRINUSE;
3110         case EADDRNOTAVAIL:     return WSAEADDRNOTAVAIL;
3111         case ENETDOWN:          return WSAENETDOWN;
3112         case ENETUNREACH:       return WSAENETUNREACH;
3113         case ENETRESET:         return WSAENETRESET;
3114         case ECONNABORTED:      return WSAECONNABORTED;
3115         case EPIPE:
3116         case ECONNRESET:        return WSAECONNRESET;
3117         case ENOBUFS:           return WSAENOBUFS;
3118         case EISCONN:           return WSAEISCONN;
3119         case ENOTCONN:          return WSAENOTCONN;
3120         case ESHUTDOWN:         return WSAESHUTDOWN;
3121         case ETOOMANYREFS:      return WSAETOOMANYREFS;
3122         case ETIMEDOUT:         return WSAETIMEDOUT;
3123         case ECONNREFUSED:      return WSAECONNREFUSED;
3124         case ELOOP:             return WSAELOOP;
3125         case ENAMETOOLONG:      return WSAENAMETOOLONG;
3126         case EHOSTDOWN:         return WSAEHOSTDOWN;
3127         case EHOSTUNREACH:      return WSAEHOSTUNREACH;
3128         case ENOTEMPTY:         return WSAENOTEMPTY;
3129 #ifdef EPROCLIM
3130         case EPROCLIM:          return WSAEPROCLIM;
3131 #endif
3132 #ifdef EUSERS
3133         case EUSERS:            return WSAEUSERS;
3134 #endif
3135 #ifdef EDQUOT
3136         case EDQUOT:            return WSAEDQUOT;
3137 #endif
3138 #ifdef ESTALE
3139         case ESTALE:            return WSAESTALE;
3140 #endif
3141 #ifdef EREMOTE
3142         case EREMOTE:           return WSAEREMOTE;
3143 #endif
3144
3145        /* just in case we ever get here and there are no problems */
3146         case 0:                 return 0;
3147         default:
3148                 WARN("Unknown errno %d!\n", loc_errno);
3149                 return WSAEOPNOTSUPP;
3150     }
3151 }
3152
3153 UINT16 wsaHerrno(int loc_errno)
3154 {
3155
3156     WARN("h_errno %d.\n", loc_errno);
3157
3158     switch(loc_errno)
3159     {
3160         case HOST_NOT_FOUND:    return WSAHOST_NOT_FOUND;
3161         case TRY_AGAIN:         return WSATRY_AGAIN;
3162         case NO_RECOVERY:       return WSANO_RECOVERY;
3163         case NO_DATA:           return WSANO_DATA; 
3164         case ENOBUFS:           return WSAENOBUFS;
3165
3166         case 0:                 return 0;
3167         default:
3168                 WARN("Unknown h_errno %d!\n", loc_errno);
3169                 return WSAEOPNOTSUPP;
3170     }
3171 }