Updated.
[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 (INT16)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 (INT16)length;
1859         }
1860         close(fd);
1861     }
1862     else SetLastError(WSAENOTSOCK);
1863     return SOCKET_ERROR;
1864 }
1865
1866 /***********************************************************************
1867  *              send()                  (WINSOCK.19)
1868  */
1869 INT16 WINAPI WINSOCK_send16(SOCKET16 s, char *buf, INT16 len, INT16 flags)
1870 {
1871     return WSOCK32_send( s, buf, len, flags );
1872 }
1873
1874 /***********************************************************************
1875  *              sendto()                (WSOCK32.20)
1876  */
1877 INT WINAPI WSOCK32_sendto(SOCKET s, char *buf, INT len, INT flags,
1878                               struct sockaddr *to, INT tolen)
1879 {
1880 #ifdef HAVE_IPX
1881     struct ws_sockaddr_ipx*  to2 = (struct ws_sockaddr_ipx *)to;
1882 #endif
1883     int fd = _get_sock_fd(s);
1884
1885     TRACE("socket %04x, ptr %p, length %d, flags %d\n", s, buf, len, flags);
1886     if (fd != -1)
1887     {
1888         INT     length;
1889
1890         if (to && ((struct ws_sockaddr_ipx *)to)->sipx_family == WS_AF_PUP)
1891             ((struct ws_sockaddr_ipx *)to)->sipx_family = AF_UNSPEC;
1892 #ifdef HAVE_IPX
1893         else if (to &&
1894                 ((struct ws_sockaddr_ipx *)to)->sipx_family == WS_AF_IPX)
1895         {
1896             to = (struct sockaddr *) malloc(sizeof(struct sockaddr_ipx));
1897             memset(to, '\0', sizeof(struct sockaddr_ipx));
1898             ((struct sockaddr_ipx *)to)->sipx_family = AF_IPX;
1899             ((struct sockaddr_ipx *)to)->sipx_port = to2->sipx_port;
1900             ((struct sockaddr_ipx *)to)->sipx_network = to2->sipx_network;
1901             memcpy(((struct sockaddr_ipx *)to)->sipx_node,
1902                         to2->sipx_node, IPX_NODE_LEN);
1903             tolen = sizeof(struct sockaddr_ipx);
1904         }
1905 #endif
1906         if (_is_blocking(s))
1907         {
1908             /* block here */
1909             /* FIXME: exceptfds */
1910             do_block(fd, 2);
1911         }
1912         if ((length = sendto(fd, buf, len, flags, to, tolen)) < 0 )
1913         {
1914             SetLastError(wsaErrno());
1915             if( GetLastError() == WSAEWOULDBLOCK )
1916                 _enable_event(s, FD_WRITE, 0, 0);
1917         } 
1918         else {
1919 #ifdef HAVE_IPX
1920             if (to && ((struct sockaddr_ipx *)to)->sipx_family == AF_IPX) {
1921                 free(to);
1922             }
1923 #endif
1924             close(fd);
1925             return length;
1926         }
1927         close(fd);
1928     }
1929     else SetLastError(WSAENOTSOCK);
1930 #ifdef HAVE_IPX
1931     if (to && ((struct sockaddr_ipx *)to)->sipx_family == AF_IPX) {
1932         free(to);
1933     }
1934 #endif
1935     return SOCKET_ERROR;
1936 }
1937
1938 /***********************************************************************
1939  *              sendto()                (WINSOCK.20)
1940  */
1941 INT16 WINAPI WINSOCK_sendto16(SOCKET16 s, char *buf, INT16 len, INT16 flags,
1942                               struct sockaddr *to, INT16 tolen)
1943 {
1944     return (INT16)WSOCK32_sendto( s, buf, len, flags, to, tolen );
1945 }
1946
1947 /***********************************************************************
1948  *              setsockopt()            (WSOCK32.21)
1949  */
1950 INT WINAPI WSOCK32_setsockopt(SOCKET16 s, INT level, INT optname, 
1951                                   char *optval, INT optlen)
1952 {
1953     int fd = _get_sock_fd(s);
1954
1955     TRACE("socket %04x, lev %d, opt 0x%x, ptr %08x, len %d\n",
1956           s, level, optname, (int) optval, optlen);
1957     if (fd != -1)
1958     {
1959         struct  linger linger;
1960         int woptval;
1961
1962         /* Is a privileged and useless operation, so we don't. */
1963         if ((optname == WS_SO_DEBUG) && (level == WS_SOL_SOCKET)) {
1964             FIXME("(%d,SOL_SOCKET,SO_DEBUG,%p(%ld)) attempted (is privileged). Ignoring.\n",s,optval,*(DWORD*)optval);
1965             return 0;
1966         }
1967
1968         if(optname == WS_SO_DONTLINGER && level == WS_SOL_SOCKET) {
1969             /* This is unique to WinSock and takes special conversion */
1970             linger.l_onoff      = *((int*)optval) ? 0: 1;
1971             linger.l_linger     = 0;
1972             optname=SO_LINGER;
1973             optval = (char*)&linger;
1974             optlen = sizeof(struct linger);
1975             level = SOL_SOCKET;
1976         }else{
1977             if (!convert_sockopt(&level, &optname)) {
1978                 SetLastError(WSAENOPROTOOPT);
1979                 close(fd);
1980                 return SOCKET_ERROR;
1981             }
1982             if (optname == SO_LINGER && optval) {
1983                 /* yes, uses unsigned short in both win16/win32 */
1984                 linger.l_onoff  = ((UINT16*)optval)[0];
1985                 linger.l_linger = ((UINT16*)optval)[1];
1986                 /* FIXME: what is documented behavior if SO_LINGER optval
1987                    is null?? */
1988                 optval = (char*)&linger;
1989                 optlen = sizeof(struct linger);
1990             } else if (optlen < sizeof(int)){
1991                 woptval= *((INT16 *) optval);
1992                 optval= (char*) &woptval;
1993                 optlen=sizeof(int);
1994             }
1995         }
1996         if(optname == SO_RCVBUF && *(int*)optval < 2048) {
1997             WARN("SO_RCVBF for %d bytes is too small: ignored\n", *(int*)optval );
1998             close( fd);
1999             return 0;
2000         }
2001
2002         if (setsockopt(fd, level, optname, optval, optlen) == 0)
2003         {
2004             close(fd);
2005             return 0;
2006         }
2007         SetLastError(wsaErrno());
2008         close(fd);
2009     }
2010     else SetLastError(WSAENOTSOCK);
2011     return SOCKET_ERROR;
2012 }
2013
2014 /***********************************************************************
2015  *              setsockopt()            (WINSOCK.21)
2016  */
2017 INT16 WINAPI WINSOCK_setsockopt16(SOCKET16 s, INT16 level, INT16 optname,
2018                                   char *optval, INT16 optlen)
2019 {
2020     if( !optval ) return SOCKET_ERROR;
2021     return (INT16)WSOCK32_setsockopt( s, (UINT16)level, optname, optval, optlen );
2022 }
2023
2024
2025 /***********************************************************************
2026  *              shutdown()              (WSOCK32.22)
2027  */
2028 INT WINAPI WSOCK32_shutdown(SOCKET s, INT how)
2029 {
2030     int fd = _get_sock_fd(s);
2031
2032     TRACE("socket %04x, how %i\n", s, how );
2033     if (fd != -1)
2034     {
2035             switch( how )
2036             {
2037                 case 0: /* drop receives */
2038                         _enable_event(s, 0, 0, WS_FD_READ);
2039 #ifdef SHUT_RD
2040                         how = SHUT_RD;
2041 #endif
2042                         break;
2043
2044                 case 1: /* drop sends */
2045                         _enable_event(s, 0, 0, WS_FD_WRITE);
2046 #ifdef SHUT_WR
2047                         how = SHUT_WR;
2048 #endif
2049                         break;
2050
2051                 case 2: /* drop all */
2052 #ifdef SHUT_RDWR
2053                         how = SHUT_RDWR;
2054 #endif
2055                 default:
2056                         WSAAsyncSelect( s, 0, 0, 0 );
2057                         break;
2058             }
2059
2060         if (shutdown(fd, how) == 0) 
2061         {
2062             if( how > 1 ) 
2063             {
2064                 _enable_event(s, 0, 0, WS_FD_CONNECTED|WS_FD_LISTENING);
2065             }
2066             close(fd);
2067             return 0;
2068         }
2069         SetLastError(wsaErrno());
2070         close(fd);
2071     } 
2072     else SetLastError(WSAENOTSOCK);
2073     return SOCKET_ERROR;
2074 }
2075
2076 /***********************************************************************
2077  *              shutdown()              (WINSOCK.22)
2078  */
2079 INT16 WINAPI WINSOCK_shutdown16(SOCKET16 s, INT16 how)
2080 {
2081     return (INT16)WSOCK32_shutdown( s, how );
2082 }
2083
2084
2085 /***********************************************************************
2086  *              socket()                (WSOCK32.23)
2087  */
2088 SOCKET WINAPI WSOCK32_socket(INT af, INT type, INT protocol)
2089 {
2090     SOCKET ret;
2091
2092     TRACE("af=%d type=%d protocol=%d\n", af, type, protocol);
2093
2094     /* check the socket family */
2095     switch(af) 
2096     {
2097 #ifdef HAVE_IPX
2098         case WS_AF_IPX: af = AF_IPX;
2099 #endif
2100         case AF_INET:
2101         case AF_UNSPEC: break;
2102         default:        SetLastError(WSAEAFNOSUPPORT); 
2103                         return INVALID_SOCKET;
2104     }
2105
2106     /* check the socket type */
2107     switch(type) 
2108     {
2109         case SOCK_STREAM:
2110         case SOCK_DGRAM:
2111         case SOCK_RAW:  break;
2112         default:        SetLastError(WSAESOCKTNOSUPPORT); 
2113                         return INVALID_SOCKET;
2114     }
2115
2116     /* check the protocol type */
2117     if ( protocol < 0 )  /* don't support negative values */
2118     { SetLastError(WSAEPROTONOSUPPORT); return INVALID_SOCKET; }
2119
2120     if ( af == AF_UNSPEC)  /* did they not specify the address family? */
2121         switch(protocol) 
2122         {
2123           case IPPROTO_TCP:
2124              if (type == SOCK_STREAM) { af = AF_INET; break; }
2125           case IPPROTO_UDP:
2126              if (type == SOCK_DGRAM)  { af = AF_INET; break; }
2127           default: SetLastError(WSAEPROTOTYPE); return INVALID_SOCKET;
2128         }
2129
2130     SERVER_START_REQ( create_socket )
2131     {
2132         req->family   = af;
2133         req->type     = type;
2134         req->protocol = protocol;
2135         req->access   = GENERIC_READ|GENERIC_WRITE|SYNCHRONIZE;
2136         req->inherit  = TRUE;
2137         set_error( SERVER_CALL() );
2138         ret = (SOCKET)req->handle;
2139     }
2140     SERVER_END_REQ;
2141     if (ret)
2142     {
2143         TRACE("\tcreated %04x\n", ret );
2144         return ret;
2145     }
2146
2147     if (GetLastError() == WSAEACCES) /* raw socket denied */
2148     {
2149         if (type == SOCK_RAW)
2150             MESSAGE("WARNING: Trying to create a socket of type SOCK_RAW, will fail unless running as root\n");
2151         else
2152             MESSAGE("WS_SOCKET: not enough privileges to create socket, try running as root\n");
2153         SetLastError(WSAESOCKTNOSUPPORT);
2154     }
2155
2156     WARN("\t\tfailed!\n");
2157     return INVALID_SOCKET;
2158 }
2159
2160 /***********************************************************************
2161  *              socket()                (WINSOCK.23)
2162  */
2163 SOCKET16 WINAPI WINSOCK_socket16(INT16 af, INT16 type, INT16 protocol)
2164 {
2165     return (SOCKET16)WSOCK32_socket( af, type, protocol );
2166 }
2167     
2168
2169 /* ----------------------------------- DNS services
2170  *
2171  * IMPORTANT: 16-bit API structures have SEGPTR pointers inside them.
2172  * Also, we have to use wsock32 stubs to convert structures and
2173  * error codes from Unix to WSA, hence there is no direct mapping in 
2174  * the relay32/wsock32.spec.
2175  */
2176
2177 static char*    NULL_STRING = "NULL";
2178
2179 /***********************************************************************
2180  *              gethostbyaddr()         (WINSOCK.51)(WSOCK32.51)
2181  */
2182 static WIN_hostent* __ws_gethostbyaddr(const char *addr, int len, int type, int dup_flag)
2183 {
2184     WIN_hostent *retval = NULL;
2185
2186     struct hostent* host;
2187 #if HAVE_LINUX_GETHOSTBYNAME_R_6
2188     char *extrabuf;
2189     int ebufsize=1024;
2190     struct hostent hostentry;
2191     int locerr=ENOBUFS;
2192     host = NULL;
2193     extrabuf=HeapAlloc(GetProcessHeap(),0,ebufsize) ;
2194     while(extrabuf) { 
2195         int res = gethostbyaddr_r(addr, len, type, 
2196                                   &hostentry, extrabuf, ebufsize, &host, &locerr);
2197         if( res != ERANGE) break;
2198         ebufsize *=2;
2199         extrabuf=HeapReAlloc(GetProcessHeap(),0,extrabuf,ebufsize) ;
2200     }
2201     if (!host) SetLastError((locerr < 0) ? wsaErrno() : wsaHerrno(locerr));
2202 #else
2203     EnterCriticalSection( &csWSgetXXXbyYYY );
2204     host = gethostbyaddr(addr, len, type);
2205     if (!host) SetLastError((h_errno < 0) ? wsaErrno() : wsaHerrno(h_errno));
2206 #endif
2207     if( host != NULL )
2208     {
2209         if( WS_dup_he(host, dup_flag) )
2210             retval = he_buffer;
2211         else 
2212             SetLastError(WSAENOBUFS);
2213     }
2214 #ifdef  HAVE_LINUX_GETHOSTBYNAME_R_6
2215     HeapFree(GetProcessHeap(),0,extrabuf);
2216 #else
2217     LeaveCriticalSection( &csWSgetXXXbyYYY );
2218 #endif
2219     return retval;
2220 }
2221
2222 SEGPTR WINAPI WINSOCK_gethostbyaddr16(const char *addr, INT16 len, INT16 type)
2223 {
2224     WIN_hostent* retval;
2225     TRACE("ptr %08x, len %d, type %d\n",
2226                             (unsigned) addr, len, type);
2227     retval = __ws_gethostbyaddr( addr, len, type, WS_DUP_SEGPTR );
2228     return SEGPTR_GET(retval);
2229 }
2230
2231 WIN_hostent* WINAPI WSOCK32_gethostbyaddr(const char *addr, INT len,
2232                                                 INT type)
2233 {
2234     TRACE("ptr %08x, len %d, type %d\n",
2235                              (unsigned) addr, len, type);
2236     return __ws_gethostbyaddr(addr, len, type, WS_DUP_LINEAR);
2237 }
2238
2239 /***********************************************************************
2240  *              gethostbyname()         (WINSOCK.52)(WSOCK32.52)
2241  */
2242 static WIN_hostent * __ws_gethostbyname(const char *name, int dup_flag)
2243 {
2244     WIN_hostent *retval = NULL;
2245     struct hostent*     host;
2246 #ifdef  HAVE_LINUX_GETHOSTBYNAME_R_6
2247     char *extrabuf;
2248     int ebufsize=1024;
2249     struct hostent hostentry;
2250     int locerr = ENOBUFS;
2251     host = NULL;
2252     extrabuf=HeapAlloc(GetProcessHeap(),0,ebufsize) ;
2253     while(extrabuf) {
2254         int res = gethostbyname_r(name, &hostentry, extrabuf, ebufsize, &host, &locerr);
2255         if( res != ERANGE) break;
2256         ebufsize *=2;
2257         extrabuf=HeapReAlloc(GetProcessHeap(),0,extrabuf,ebufsize) ;
2258     }
2259     if (!host) SetLastError((locerr < 0) ? wsaErrno() : wsaHerrno(locerr));
2260 #else
2261     EnterCriticalSection( &csWSgetXXXbyYYY );
2262     host = gethostbyname(name);
2263     if (!host) SetLastError((h_errno < 0) ? wsaErrno() : wsaHerrno(h_errno));
2264 #endif
2265     if( host  != NULL )
2266     {
2267         if( WS_dup_he(host, dup_flag) )
2268             retval = he_buffer;
2269         else SetLastError(WSAENOBUFS);
2270     }
2271 #ifdef  HAVE_LINUX_GETHOSTBYNAME_R_6
2272     HeapFree(GetProcessHeap(),0,extrabuf);
2273 #else
2274     LeaveCriticalSection( &csWSgetXXXbyYYY );
2275 #endif
2276     return retval;
2277 }
2278
2279 SEGPTR WINAPI WINSOCK_gethostbyname16(const char *name)
2280 {
2281     WIN_hostent* retval;
2282     TRACE("%s\n", (name)?name:NULL_STRING);
2283     retval = __ws_gethostbyname( name, WS_DUP_SEGPTR );
2284     return SEGPTR_GET(retval);
2285 }
2286
2287 WIN_hostent* WINAPI WSOCK32_gethostbyname(const char* name)
2288 {
2289     TRACE("%s\n", (name)?name:NULL_STRING);
2290     return __ws_gethostbyname( name, WS_DUP_LINEAR );
2291 }
2292
2293
2294 /***********************************************************************
2295  *              getprotobyname()        (WINSOCK.53)(WSOCK32.53)
2296  */
2297 static WIN_protoent* __ws_getprotobyname(const char *name, int dup_flag)
2298 {
2299     WIN_protoent* retval = NULL;
2300
2301     struct protoent*     proto;
2302     EnterCriticalSection( &csWSgetXXXbyYYY );
2303     if( (proto = getprotobyname(name)) != NULL )
2304     {
2305         if( WS_dup_pe(proto, dup_flag) )
2306             retval = pe_buffer;
2307         else SetLastError(WSAENOBUFS);
2308     }
2309     else {
2310         MESSAGE("protocol %s not found; You might want to add "
2311                 "this to /etc/protocols\n", debugstr_a(name) );
2312         SetLastError(WSANO_DATA);
2313     }
2314     LeaveCriticalSection( &csWSgetXXXbyYYY );
2315     return retval;
2316 }
2317
2318 SEGPTR WINAPI WINSOCK_getprotobyname16(const char *name)
2319 {
2320     WIN_protoent* retval;
2321     TRACE("%s\n", (name)?name:NULL_STRING);
2322     retval = __ws_getprotobyname(name, WS_DUP_SEGPTR);
2323     return SEGPTR_GET(retval);
2324 }
2325
2326 WIN_protoent* WINAPI WSOCK32_getprotobyname(const char* name)
2327 {
2328     TRACE("%s\n", (name)?name:NULL_STRING);
2329     return __ws_getprotobyname(name, WS_DUP_LINEAR);
2330 }
2331
2332
2333 /***********************************************************************
2334  *              getprotobynumber()      (WINSOCK.54)(WSOCK32.54)
2335  */
2336 static WIN_protoent* __ws_getprotobynumber(int number, int dup_flag)
2337 {
2338     WIN_protoent* retval = NULL;
2339     struct protoent*     proto;
2340     EnterCriticalSection( &csWSgetXXXbyYYY );
2341     if( (proto = getprotobynumber(number)) != NULL )
2342     {
2343         if( WS_dup_pe(proto, dup_flag) )
2344             retval = pe_buffer;
2345         else SetLastError(WSAENOBUFS);
2346     }
2347     else {
2348         MESSAGE("protocol number %d not found; You might want to add "
2349                 "this to /etc/protocols\n", number );
2350         SetLastError(WSANO_DATA);
2351     }
2352     LeaveCriticalSection( &csWSgetXXXbyYYY );
2353     return retval;
2354 }
2355
2356 SEGPTR WINAPI WINSOCK_getprotobynumber16(INT16 number)
2357 {
2358     WIN_protoent* retval;
2359     TRACE("%i\n", number);
2360     retval = __ws_getprotobynumber(number, WS_DUP_SEGPTR);
2361     return SEGPTR_GET(retval);
2362 }
2363
2364 WIN_protoent* WINAPI WSOCK32_getprotobynumber(INT number)
2365 {
2366     TRACE("%i\n", number);
2367     return __ws_getprotobynumber(number, WS_DUP_LINEAR);
2368 }
2369
2370
2371 /***********************************************************************
2372  *              getservbyname()         (WINSOCK.55)(WSOCK32.55)
2373  */
2374 static WIN_servent* __ws_getservbyname(const char *name, const char *proto, int dup_flag)
2375 {
2376     WIN_servent* retval = NULL;
2377     struct servent*     serv;
2378     int i = wsi_strtolo( name, proto );
2379
2380     if( i ) {
2381         EnterCriticalSection( &csWSgetXXXbyYYY );
2382         serv = getservbyname(local_buffer,
2383                              proto ? (local_buffer + i) : NULL);
2384         if( serv != NULL )
2385         {
2386             if( WS_dup_se(serv, dup_flag) )
2387                 retval = se_buffer;
2388             else SetLastError(WSAENOBUFS);
2389         }
2390         else {
2391             MESSAGE("service %s protocol %s not found; You might want to add "
2392                     "this to /etc/services\n", debugstr_a(local_buffer),
2393                     proto ? debugstr_a(local_buffer+i):"*");
2394             SetLastError(WSANO_DATA);
2395         }
2396         LeaveCriticalSection( &csWSgetXXXbyYYY );
2397     }
2398     else SetLastError(WSAENOBUFS);
2399     return retval;
2400 }
2401
2402 SEGPTR WINAPI WINSOCK_getservbyname16(const char *name, const char *proto)
2403 {
2404     WIN_servent* retval;
2405     TRACE("'%s', '%s'\n",
2406                             (name)?name:NULL_STRING, (proto)?proto:NULL_STRING);
2407     retval = __ws_getservbyname(name, proto, WS_DUP_SEGPTR);
2408     return SEGPTR_GET(retval);
2409 }
2410
2411 WIN_servent* WINAPI WSOCK32_getservbyname(const char *name, const char *proto)
2412 {
2413     TRACE("'%s', '%s'\n",
2414                             (name)?name:NULL_STRING, (proto)?proto:NULL_STRING);
2415     return __ws_getservbyname(name, proto, WS_DUP_LINEAR);
2416 }
2417
2418
2419 /***********************************************************************
2420  *              getservbyport()         (WINSOCK.56)(WSOCK32.56)
2421  */
2422 static WIN_servent* __ws_getservbyport(int port, const char* proto, int dup_flag)
2423 {
2424     WIN_servent* retval = NULL;
2425     struct servent*     serv;
2426     if (!proto || wsi_strtolo( proto, NULL )) {
2427         EnterCriticalSection( &csWSgetXXXbyYYY );
2428         if( (serv = getservbyport(port, (proto) ? local_buffer : NULL)) != NULL ) {
2429             if( WS_dup_se(serv, dup_flag) )
2430                 retval = se_buffer;
2431             else SetLastError(WSAENOBUFS);
2432         }
2433         else {
2434             MESSAGE("service on port %lu protocol %s not found; You might want to add "
2435                     "this to /etc/services\n", (unsigned long)ntohl(port),
2436                     proto ? debugstr_a(local_buffer) : "*");
2437             SetLastError(WSANO_DATA);
2438         }
2439         LeaveCriticalSection( &csWSgetXXXbyYYY );
2440     }
2441     else SetLastError(WSAENOBUFS);
2442     return retval;
2443 }
2444
2445 SEGPTR WINAPI WINSOCK_getservbyport16(INT16 port, const char *proto)
2446 {
2447     WIN_servent* retval;
2448     TRACE("%d (i.e. port %d), '%s'\n",
2449                             (int)port, (int)ntohl(port), (proto)?proto:NULL_STRING);
2450     retval = __ws_getservbyport(port, proto, WS_DUP_SEGPTR);
2451     return SEGPTR_GET(retval);
2452 }
2453
2454 WIN_servent* WINAPI WSOCK32_getservbyport(INT port, const char *proto)
2455 {
2456     TRACE("%d (i.e. port %d), '%s'\n",
2457                             (int)port, (int)ntohl(port), (proto)?proto:NULL_STRING);
2458     return __ws_getservbyport(port, proto, WS_DUP_LINEAR);
2459 }
2460
2461
2462 /***********************************************************************
2463  *              gethostname()           (WSOCK32.57)
2464  */
2465 INT WINAPI WSOCK32_gethostname(char *name, INT namelen)
2466 {
2467     TRACE("name %p, len %d\n", name, namelen);
2468
2469     if (gethostname(name, namelen) == 0)
2470     {
2471         TRACE("<- '%s'\n", name);
2472         return 0;
2473     }
2474     SetLastError((errno == EINVAL) ? WSAEFAULT : wsaErrno());
2475     TRACE("<- ERROR !\n");
2476     return SOCKET_ERROR;
2477 }
2478
2479 /***********************************************************************
2480  *              gethostname()           (WINSOCK.57)
2481  */
2482 INT16 WINAPI WINSOCK_gethostname16(char *name, INT16 namelen)
2483 {
2484     return (INT16)WSOCK32_gethostname(name, namelen);
2485 }
2486
2487
2488 /* ------------------------------------- Windows sockets extensions -- *
2489  *                                                                     *
2490  * ------------------------------------------------------------------- */
2491
2492 /***********************************************************************
2493  *              WSAEnumNetworkEvents
2494  */
2495 int WINAPI WSAEnumNetworkEvents(SOCKET s, WSAEVENT hEvent, LPWSANETWORKEVENTS lpEvent)
2496 {
2497     int ret;
2498
2499     TRACE("%08x, hEvent %08x, lpEvent %08x\n", s, hEvent, (unsigned)lpEvent );
2500
2501     SERVER_START_VAR_REQ( get_socket_event, sizeof(lpEvent->iErrorCode) )
2502     {
2503         req->handle  = s;
2504         req->service = TRUE;
2505         req->s_event = 0;
2506         req->c_event = hEvent;
2507         if (!(ret = SERVER_CALL()))
2508         {
2509             lpEvent->lNetworkEvents = req->pmask;
2510             memcpy(lpEvent->iErrorCode, server_data_ptr(req), server_data_size(req) );
2511         }
2512     }
2513     SERVER_END_VAR_REQ;
2514     if (!ret) return 0;
2515     SetLastError(WSAEINVAL);
2516     return SOCKET_ERROR;
2517 }
2518
2519 /***********************************************************************
2520  *              WSAEventSelect
2521  */
2522 int WINAPI WSAEventSelect(SOCKET s, WSAEVENT hEvent, LONG lEvent)
2523 {
2524     int ret;
2525
2526     TRACE("%08x, hEvent %08x, event %08x\n", s, hEvent, (unsigned)lEvent );
2527
2528     SERVER_START_REQ( set_socket_event )
2529     {
2530         req->handle = s;
2531         req->mask   = lEvent;
2532         req->event  = hEvent;
2533         ret = SERVER_CALL();
2534     }
2535     SERVER_END_REQ;
2536     if (!ret) return 0;
2537     SetLastError(WSAEINVAL);
2538     return SOCKET_ERROR;
2539 }
2540
2541 /***********************************************************************
2542  *      WSAAsyncSelect()                (WINSOCK.101)(WSOCK32.101)
2543  */
2544
2545 VOID CALLBACK WINSOCK_DoAsyncEvent( ULONG_PTR ptr )
2546 {
2547     ws_select_info *info = (ws_select_info*)ptr;
2548     unsigned int i, pmask, orphan = FALSE;
2549     int errors[FD_MAX_EVENTS];
2550
2551     TRACE("socket %08x, event %08x\n", info->sock, info->event);
2552     SetLastError(0);
2553     SERVER_START_VAR_REQ( get_socket_event, sizeof(errors) )
2554     {
2555         req->handle  = info->sock;
2556         req->service = TRUE;
2557         req->s_event = info->event; /* <== avoid race conditions */
2558         req->c_event = info->event;
2559         set_error( SERVER_CALL() );
2560         pmask = req->pmask;
2561         memcpy( errors, server_data_ptr(req), server_data_size(req) );
2562     }
2563     SERVER_END_VAR_REQ;
2564     if ( (GetLastError() == WSAENOTSOCK) || (GetLastError() == WSAEINVAL) )
2565     {
2566         /* orphaned event (socket closed or something) */
2567         pmask = WS_FD_SERVEVENT;
2568         orphan = TRUE;
2569     }
2570
2571     /* check for accepted sockets that needs to inherit WSAAsyncSelect */
2572     if (pmask & WS_FD_SERVEVENT) {
2573         int q;
2574         for (q=0; q<WS_ACCEPT_QUEUE; q++)
2575             if (accept_old[q] == info->sock) {
2576                 /* there's only one service thread per process, no lock necessary */
2577                 HANDLE as = accept_new[q];
2578                 if (as) {
2579                     accept_new[q] = 0;
2580                     accept_old[q] = 0;
2581                     WSAAsyncSelect(as, info->hWnd, info->uMsg, info->lEvent);
2582                 }
2583             }
2584         pmask &= ~WS_FD_SERVEVENT;
2585     }
2586     /* dispatch network events */
2587     for (i=0; i<FD_MAX_EVENTS; i++)
2588         if (pmask & (1<<i)) {
2589             TRACE("post: event bit %d, error %d\n", i, errors[i]);
2590             PostMessageA(info->hWnd, info->uMsg, info->sock,
2591                          WSAMAKESELECTREPLY(1<<i, errors[i]));
2592         }
2593     /* cleanup */
2594     if (orphan)
2595     {
2596         TRACE("orphaned event, self-destructing\n");
2597         /* SERVICE_Delete closes the event object */
2598         SERVICE_Delete( info->service );
2599         WS_FREE(info);
2600     }
2601 }
2602
2603 /**********************************************************************/
2604
2605 INT WINAPI WSAAsyncSelect(SOCKET s, HWND hWnd, UINT uMsg, LONG lEvent)
2606 {
2607     int fd = _get_sock_fd(s);
2608
2609     TRACE("%04x, hWnd %04x, uMsg %08x, event %08x\n",
2610           (SOCKET16)s, (HWND16)hWnd, uMsg, (unsigned)lEvent );
2611     if (fd != -1)
2612     {
2613         close(fd);
2614         if( lEvent )
2615         {
2616             ws_select_info *info = (ws_select_info*)WS_ALLOC(sizeof(ws_select_info));
2617             if( info )
2618             {
2619                 HANDLE hObj = CreateEventA( NULL, TRUE, FALSE, NULL );
2620                 INT err;
2621                 
2622                 info->sock   = s;
2623                 info->event  = hObj;
2624                 info->hWnd   = hWnd;
2625                 info->uMsg   = uMsg;
2626                 info->lEvent = lEvent;
2627                 info->service = SERVICE_AddObject( hObj, WINSOCK_DoAsyncEvent, (ULONG_PTR)info );
2628
2629                 err = WSAEventSelect( s, hObj, lEvent | WS_FD_SERVEVENT );
2630                 if (err) {
2631                     /* SERVICE_Delete closes the event object */
2632                     SERVICE_Delete( info->service );
2633                     WS_FREE(info);
2634                     return err;
2635                 }
2636
2637                 return 0; /* success */
2638             }
2639             else SetLastError(WSAENOBUFS);
2640         } 
2641         else
2642         {
2643             WSAEventSelect(s, 0, 0);
2644             return 0;
2645         }
2646     } 
2647     else SetLastError(WSAEINVAL);
2648     return SOCKET_ERROR; 
2649 }
2650
2651 /**********************************************************************/
2652
2653 INT16 WINAPI WSAAsyncSelect16(SOCKET16 s, HWND16 hWnd, UINT16 wMsg, LONG lEvent)
2654 {
2655     return (INT16)WSAAsyncSelect( s, hWnd, wMsg, lEvent );
2656 }
2657
2658 /***********************************************************************
2659  *              WSARecvEx16()                   (WINSOCK.1107)
2660  *
2661  * See description for WSARecvEx()
2662  */
2663 INT16     WINAPI WSARecvEx16(SOCKET16 s, char *buf, INT16 len, INT16 *flags) {
2664   FIXME("(WSARecvEx16) partial packet return value not set \n");
2665
2666   return WINSOCK_recv16(s, buf, len, *flags);
2667 }
2668
2669
2670 /***********************************************************************
2671  *      WSACreateEvent()          (WS2_32.???)
2672  *
2673  */
2674 WSAEVENT WINAPI WSACreateEvent(void)
2675 {
2676     /* Create a manual-reset event, with initial state: unsignealed */
2677     TRACE("\n");
2678     
2679     return CreateEventA(NULL, TRUE, FALSE, NULL);    
2680 }
2681
2682 /***********************************************************************
2683  *      WSACloseEvent()          (WS2_32.???)
2684  *
2685  */
2686 BOOL WINAPI WSACloseEvent(WSAEVENT event)
2687 {
2688     TRACE ("event=0x%x\n", event);
2689
2690     return CloseHandle(event);
2691 }
2692
2693 /***********************************************************************
2694  *      WSASocketA()          (WS2_32.???)
2695  *
2696  */
2697 SOCKET WINAPI WSASocketA(int af, int type, int protocol,
2698                          LPWSAPROTOCOL_INFOA lpProtocolInfo,
2699                          GROUP g, DWORD dwFlags)
2700 {
2701    /* 
2702       FIXME: The "advanced" parameters of WSASocketA (lpProtocolInfo,
2703       g, dwFlags) are ignored.
2704    */
2705    
2706    TRACE("af=%d type=%d protocol=%d protocol_info=%p group=%d flags=0x%lx\n", 
2707          af, type, protocol, lpProtocolInfo, g, dwFlags );
2708
2709    return ( WSOCK32_socket (af, type, protocol) );
2710 }
2711
2712
2713 /***********************************************************************
2714  *      __WSAFDIsSet()                  (WINSOCK.151)
2715  */
2716 INT16 WINAPI __WSAFDIsSet16(SOCKET16 s, ws_fd_set16 *set)
2717 {
2718   int i = set->fd_count;
2719   
2720   TRACE("(%d,%8lx(%i))\n", s,(unsigned long)set, i);
2721     
2722   while (i--)
2723       if (set->fd_array[i] == s) return 1;
2724   return 0;
2725 }                                                            
2726
2727 /***********************************************************************
2728  *      __WSAFDIsSet()                  (WSOCK32.151)
2729  */
2730 INT WINAPI __WSAFDIsSet(SOCKET s, ws_fd_set32 *set)
2731 {
2732   int i = set->fd_count;
2733
2734   TRACE("(%d,%8lx(%i))\n", s,(unsigned long)set, i);
2735
2736   while (i--)
2737       if (set->fd_array[i] == s) return 1;
2738   return 0;
2739 }
2740
2741 /***********************************************************************
2742  *      WSAIsBlocking()                 (WINSOCK.114)(WSOCK32.114)
2743  */
2744 BOOL WINAPI WSAIsBlocking(void)
2745 {
2746   /* By default WinSock should set all its sockets to non-blocking mode
2747    * and poll in PeekMessage loop when processing "blocking" ones. This 
2748    * function is supposed to tell if the program is in this loop. Our 
2749    * blocking calls are truly blocking so we always return FALSE.
2750    *
2751    * Note: It is allowed to call this function without prior WSAStartup().
2752    */
2753
2754   TRACE("\n");
2755   return FALSE;
2756 }
2757
2758 /***********************************************************************
2759  *      WSACancelBlockingCall()         (WINSOCK.113)(WSOCK32.113)
2760  */
2761 INT WINAPI WSACancelBlockingCall(void)
2762 {
2763     TRACE("\n");
2764     return 0;
2765 }
2766
2767
2768 /***********************************************************************
2769  *      WSASetBlockingHook16()          (WINSOCK.109)
2770  */
2771 FARPROC16 WINAPI WSASetBlockingHook16(FARPROC16 lpBlockFunc)
2772 {
2773   FARPROC16 prev = (FARPROC16)blocking_hook;
2774   blocking_hook = (FARPROC)lpBlockFunc;
2775   TRACE("hook %p\n", lpBlockFunc);
2776   return prev;
2777 }
2778
2779
2780 /***********************************************************************
2781  *      WSASetBlockingHook()
2782  */
2783 FARPROC WINAPI WSASetBlockingHook(FARPROC lpBlockFunc)
2784 {
2785   FARPROC prev = blocking_hook;
2786   blocking_hook = lpBlockFunc;
2787   TRACE("hook %p\n", lpBlockFunc);
2788   return prev;
2789 }
2790
2791
2792 /***********************************************************************
2793  *      WSAUnhookBlockingHook16()       (WINSOCK.110)
2794  */
2795 INT16 WINAPI WSAUnhookBlockingHook16(void)
2796 {
2797     blocking_hook = NULL;
2798     return 0;
2799 }
2800
2801
2802 /***********************************************************************
2803  *      WSAUnhookBlockingHook()
2804  */
2805 INT WINAPI WSAUnhookBlockingHook(void)
2806 {
2807     blocking_hook = NULL;
2808     return 0;
2809 }
2810
2811
2812 /* ----------------------------------- end of API stuff */
2813
2814 /* ----------------------------------- helper functions -
2815  *
2816  * TODO: Merge WS_dup_..() stuff into one function that
2817  * would operate with a generic structure containing internal
2818  * pointers (via a template of some kind).
2819  */
2820
2821 static int list_size(char** l, int item_size)
2822 {
2823   int i,j = 0;
2824   if(l)
2825   { for(i=0;l[i];i++) 
2826         j += (item_size) ? item_size : strlen(l[i]) + 1;
2827     j += (i + 1) * sizeof(char*); }
2828   return j;
2829 }
2830
2831 static int list_dup(char** l_src, char* ref, char* base, int item_size)
2832
2833    /* base is either either equal to ref or 0 or SEGPTR */
2834
2835    char*                p = ref;
2836    char**               l_to = (char**)ref;
2837    int                  i,j,k;
2838
2839    for(j=0;l_src[j];j++) ;
2840    p += (j + 1) * sizeof(char*);
2841    for(i=0;i<j;i++)
2842    { l_to[i] = base + (p - ref);
2843      k = ( item_size ) ? item_size : strlen(l_src[i]) + 1;
2844      memcpy(p, l_src[i], k); p += k; }
2845    l_to[i] = NULL;
2846    return (p - ref);
2847 }
2848
2849 /* ----- hostent */
2850
2851 static int hostent_size(struct hostent* p_he)
2852 {
2853   int size = 0;
2854   if( p_he )
2855   { size  = sizeof(struct hostent); 
2856     size += strlen(p_he->h_name) + 1;
2857     size += list_size(p_he->h_aliases, 0);  
2858     size += list_size(p_he->h_addr_list, p_he->h_length ); }
2859   return size;
2860 }
2861
2862 /* duplicate hostent entry
2863  * and handle all Win16/Win32 dependent things (struct size, ...) *correctly*.
2864  * Dito for protoent and servent.
2865  */
2866 int WS_dup_he(struct hostent* p_he, int flag)
2867 {
2868     /* Convert hostent structure into ws_hostent so that the data fits 
2869      * into local_buffer. Internal pointers can be linear, SEGPTR, or 
2870      * relative to local_buffer depending on "flag" value. Returns size
2871      * of the data copied.
2872      */
2873
2874     int size = hostent_size(p_he);
2875     if( size )
2876     {
2877         char *p_name,*p_aliases,*p_addr,*p_base,*p;
2878         char *p_to;
2879         struct ws_hostent16 *p_to16;
2880         struct ws_hostent32 *p_to32;
2881
2882         check_buffer_he(size);
2883         p_to = he_buffer;
2884         p_to16 = he_buffer;
2885         p_to32 = he_buffer;
2886
2887         p = p_to;
2888         p_base = (flag & WS_DUP_OFFSET) ? NULL
2889             : ((flag & WS_DUP_SEGPTR) ? (char*)SEGPTR_GET(p) : p);
2890         p += (flag & WS_DUP_SEGPTR) ?
2891             sizeof(struct ws_hostent16) : sizeof(struct ws_hostent32);
2892         p_name = p;
2893         strcpy(p, p_he->h_name); p += strlen(p) + 1;
2894         p_aliases = p;
2895         p += list_dup(p_he->h_aliases, p, p_base + (p - p_to), 0);
2896         p_addr = p;
2897         list_dup(p_he->h_addr_list, p, p_base + (p - p_to), p_he->h_length);
2898
2899         if (flag & WS_DUP_SEGPTR) /* Win16 */
2900         {
2901             p_to16->h_addrtype = (INT16)p_he->h_addrtype; 
2902             p_to16->h_length = (INT16)p_he->h_length;
2903             p_to16->h_name = (SEGPTR)(p_base + (p_name - p_to));
2904             p_to16->h_aliases = (SEGPTR)(p_base + (p_aliases - p_to));
2905             p_to16->h_addr_list = (SEGPTR)(p_base + (p_addr - p_to));
2906             size += (sizeof(struct ws_hostent16) - sizeof(struct hostent));
2907         }
2908         else /* Win32 */
2909         {
2910             p_to32->h_addrtype = p_he->h_addrtype; 
2911             p_to32->h_length = p_he->h_length;
2912             p_to32->h_name = (p_base + (p_name - p_to));
2913             p_to32->h_aliases = (char **)(p_base + (p_aliases - p_to));
2914             p_to32->h_addr_list = (char **)(p_base + (p_addr - p_to));
2915             size += (sizeof(struct ws_hostent32) - sizeof(struct hostent));
2916         }
2917     }
2918     return size;
2919 }
2920
2921 /* ----- protoent */
2922
2923 static int protoent_size(struct protoent* p_pe)
2924 {
2925   int size = 0;
2926   if( p_pe )
2927   { size  = sizeof(struct protoent);
2928     size += strlen(p_pe->p_name) + 1;
2929     size += list_size(p_pe->p_aliases, 0); }
2930   return size;
2931 }
2932
2933 int WS_dup_pe(struct protoent* p_pe, int flag)
2934 {
2935     int size = protoent_size(p_pe);
2936     if( size )
2937     {
2938         char *p_to;
2939         struct ws_protoent16 *p_to16;
2940         struct ws_protoent32 *p_to32;
2941         char *p_name,*p_aliases,*p_base,*p;
2942
2943         check_buffer_pe(size);
2944         p_to = pe_buffer;
2945         p_to16 = pe_buffer;
2946         p_to32 = pe_buffer;
2947         p = p_to;
2948         p_base = (flag & WS_DUP_OFFSET) ? NULL
2949             : ((flag & WS_DUP_SEGPTR) ? (char*)SEGPTR_GET(p) : p);
2950         p += (flag & WS_DUP_SEGPTR) ?
2951             sizeof(struct ws_protoent16) : sizeof(struct ws_protoent32);
2952         p_name = p;
2953         strcpy(p, p_pe->p_name); p += strlen(p) + 1;
2954         p_aliases = p;
2955         list_dup(p_pe->p_aliases, p, p_base + (p - p_to), 0);
2956
2957         if (flag & WS_DUP_SEGPTR) /* Win16 */
2958         {
2959             p_to16->p_proto = (INT16)p_pe->p_proto;
2960             p_to16->p_name = (SEGPTR)(p_base) + (p_name - p_to);
2961             p_to16->p_aliases = (SEGPTR)((p_base) + (p_aliases - p_to)); 
2962             size += (sizeof(struct ws_protoent16) - sizeof(struct protoent));
2963         }
2964         else /* Win32 */
2965         {
2966             p_to32->p_proto = p_pe->p_proto;
2967             p_to32->p_name = (p_base) + (p_name - p_to);
2968             p_to32->p_aliases = (char **)((p_base) + (p_aliases - p_to)); 
2969             size += (sizeof(struct ws_protoent32) - sizeof(struct protoent));
2970         }
2971     }
2972     return size;
2973 }
2974
2975 /* ----- servent */
2976
2977 static int servent_size(struct servent* p_se)
2978 {
2979   int size = 0;
2980   if( p_se )
2981   { size += sizeof(struct servent);
2982     size += strlen(p_se->s_proto) + strlen(p_se->s_name) + 2;
2983     size += list_size(p_se->s_aliases, 0); }
2984   return size;
2985 }
2986
2987 int WS_dup_se(struct servent* p_se, int flag)
2988 {
2989     int size = servent_size(p_se);
2990     if( size )
2991     {
2992         char *p_name,*p_aliases,*p_proto,*p_base,*p;
2993         char *p_to;
2994         struct ws_servent16 *p_to16;
2995         struct ws_servent32 *p_to32;
2996
2997         check_buffer_se(size);
2998         p_to = se_buffer;
2999         p_to16 = se_buffer;
3000         p_to32 = se_buffer;
3001         p = p_to;
3002         p_base = (flag & WS_DUP_OFFSET) ? NULL 
3003             : ((flag & WS_DUP_SEGPTR) ? (char*)SEGPTR_GET(p) : p);
3004         p += (flag & WS_DUP_SEGPTR) ?
3005             sizeof(struct ws_servent16) : sizeof(struct ws_servent32);
3006         p_name = p;
3007         strcpy(p, p_se->s_name); p += strlen(p) + 1;
3008         p_proto = p;
3009         strcpy(p, p_se->s_proto); p += strlen(p) + 1;
3010         p_aliases = p;
3011         list_dup(p_se->s_aliases, p, p_base + (p - p_to), 0);
3012
3013         if (flag & WS_DUP_SEGPTR) /* Win16 */
3014         { 
3015             p_to16->s_port = (INT16)p_se->s_port;
3016             p_to16->s_name = (SEGPTR)(p_base + (p_name - p_to));
3017             p_to16->s_proto = (SEGPTR)(p_base + (p_proto - p_to));
3018             p_to16->s_aliases = (SEGPTR)(p_base + (p_aliases - p_to));
3019             size += (sizeof(struct ws_servent16) - sizeof(struct servent));
3020         }
3021         else /* Win32 */
3022         {
3023             p_to32->s_port = p_se->s_port;
3024             p_to32->s_name = (p_base + (p_name - p_to));
3025             p_to32->s_proto = (p_base + (p_proto - p_to));
3026             p_to32->s_aliases = (char **)(p_base + (p_aliases - p_to));
3027             size += (sizeof(struct ws_servent32) - sizeof(struct servent));
3028         }
3029     }
3030     return size;
3031 }
3032
3033 /* ----------------------------------- error handling */
3034
3035 UINT16 wsaErrno(void)
3036 {
3037     int loc_errno = errno; 
3038     WARN("errno %d, (%s).\n", loc_errno, strerror(loc_errno));
3039
3040     switch(loc_errno)
3041     {
3042         case EINTR:             return WSAEINTR;
3043         case EBADF:             return WSAEBADF;
3044         case EPERM:
3045         case EACCES:            return WSAEACCES;
3046         case EFAULT:            return WSAEFAULT;
3047         case EINVAL:            return WSAEINVAL;
3048         case EMFILE:            return WSAEMFILE;
3049         case EWOULDBLOCK:       return WSAEWOULDBLOCK;
3050         case EINPROGRESS:       return WSAEINPROGRESS;
3051         case EALREADY:          return WSAEALREADY;
3052         case ENOTSOCK:          return WSAENOTSOCK;
3053         case EDESTADDRREQ:      return WSAEDESTADDRREQ;
3054         case EMSGSIZE:          return WSAEMSGSIZE;
3055         case EPROTOTYPE:        return WSAEPROTOTYPE;
3056         case ENOPROTOOPT:       return WSAENOPROTOOPT;
3057         case EPROTONOSUPPORT:   return WSAEPROTONOSUPPORT;
3058         case ESOCKTNOSUPPORT:   return WSAESOCKTNOSUPPORT;
3059         case EOPNOTSUPP:        return WSAEOPNOTSUPP;
3060         case EPFNOSUPPORT:      return WSAEPFNOSUPPORT;
3061         case EAFNOSUPPORT:      return WSAEAFNOSUPPORT;
3062         case EADDRINUSE:        return WSAEADDRINUSE;
3063         case EADDRNOTAVAIL:     return WSAEADDRNOTAVAIL;
3064         case ENETDOWN:          return WSAENETDOWN;
3065         case ENETUNREACH:       return WSAENETUNREACH;
3066         case ENETRESET:         return WSAENETRESET;
3067         case ECONNABORTED:      return WSAECONNABORTED;
3068         case EPIPE:
3069         case ECONNRESET:        return WSAECONNRESET;
3070         case ENOBUFS:           return WSAENOBUFS;
3071         case EISCONN:           return WSAEISCONN;
3072         case ENOTCONN:          return WSAENOTCONN;
3073         case ESHUTDOWN:         return WSAESHUTDOWN;
3074         case ETOOMANYREFS:      return WSAETOOMANYREFS;
3075         case ETIMEDOUT:         return WSAETIMEDOUT;
3076         case ECONNREFUSED:      return WSAECONNREFUSED;
3077         case ELOOP:             return WSAELOOP;
3078         case ENAMETOOLONG:      return WSAENAMETOOLONG;
3079         case EHOSTDOWN:         return WSAEHOSTDOWN;
3080         case EHOSTUNREACH:      return WSAEHOSTUNREACH;
3081         case ENOTEMPTY:         return WSAENOTEMPTY;
3082 #ifdef EPROCLIM
3083         case EPROCLIM:          return WSAEPROCLIM;
3084 #endif
3085 #ifdef EUSERS
3086         case EUSERS:            return WSAEUSERS;
3087 #endif
3088 #ifdef EDQUOT
3089         case EDQUOT:            return WSAEDQUOT;
3090 #endif
3091 #ifdef ESTALE
3092         case ESTALE:            return WSAESTALE;
3093 #endif
3094 #ifdef EREMOTE
3095         case EREMOTE:           return WSAEREMOTE;
3096 #endif
3097
3098        /* just in case we ever get here and there are no problems */
3099         case 0:                 return 0;
3100         default:
3101                 WARN("Unknown errno %d!\n", loc_errno);
3102                 return WSAEOPNOTSUPP;
3103     }
3104 }
3105
3106 UINT16 wsaHerrno(int loc_errno)
3107 {
3108
3109     WARN("h_errno %d.\n", loc_errno);
3110
3111     switch(loc_errno)
3112     {
3113         case HOST_NOT_FOUND:    return WSAHOST_NOT_FOUND;
3114         case TRY_AGAIN:         return WSATRY_AGAIN;
3115         case NO_RECOVERY:       return WSANO_RECOVERY;
3116         case NO_DATA:           return WSANO_DATA; 
3117         case ENOBUFS:           return WSAENOBUFS;
3118
3119         case 0:                 return 0;
3120         default:
3121                 WARN("Unknown h_errno %d!\n", loc_errno);
3122                 return WSAEOPNOTSUPP;
3123     }
3124 }