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