Ignore setsockopt calls that make the size of the receive buffer too
[wine.git] / dlls / winsock / socket.c
blob7f4e92a89ba3baa72eca0ef6b70dbddd34e6819c
1 /*
2 * based on Windows Sockets 1.1 specs
3 * (ftp.microsoft.com:/Advsys/winsock/spec11/WINSOCK.TXT)
4 *
5 * (C) 1993,1994,1996,1997 John Brezak, Erik Bos, Alex Korobka.
7 * NOTE: If you make any changes to fix a particular app, make sure
8 * they don't break something else like Netscape or telnet and ftp
9 * clients and servers (www.winsite.com got a lot of those).
11 * NOTE 2: Many winsock structs such as servent, hostent, protoent, ...
12 * are used with 1-byte alignment for Win16 programs and 4-byte alignment
13 * for Win32 programs in winsock.h. winsock2.h uses forced 4-byte alignment.
14 * So we have non-forced (just as MSDN) ws_XXXXent (winsock.h), 4-byte forced
15 * ws_XXXXent32 (winsock2.h) and 1-byte forced ws_XXXXent16 (winsock16.h).
18 #include "config.h"
20 #include <string.h>
21 #include <sys/types.h>
22 #ifdef HAVE_SYS_IPC_H
23 # include <sys/ipc.h>
24 #endif
25 #include <sys/ioctl.h>
26 #ifdef HAVE_SYS_FILIO_H
27 # include <sys/filio.h>
28 #endif
29 #ifdef HAVE_SYS_SOCKIO_H
30 # include <sys/sockio.h>
31 #endif
33 #if defined(__EMX__)
34 # include <sys/so_ioctl.h>
35 #endif
37 #ifdef HAVE_SYS_PARAM_H
38 # include <sys/param.h>
39 #endif
41 #ifdef HAVE_SYS_MSG_H
42 # include <sys/msg.h>
43 #endif
44 #ifdef HAVE_SYS_WAIT_H
45 # include <sys/wait.h>
46 #endif
47 #ifdef HAVE_SYS_SOCKET_H
48 #include <sys/socket.h>
49 #endif
50 #ifdef HAVE_NETINET_IN_H
51 # include <netinet/in.h>
52 #endif
53 #ifdef HAVE_NETINET_TCP_H
54 # include <netinet/tcp.h>
55 #endif
56 #ifdef HAVE_ARPA_INET_H
57 # include <arpa/inet.h>
58 #endif
59 #include <ctype.h>
60 #include <fcntl.h>
61 #include <errno.h>
62 #ifdef HAVE_SYS_ERRNO_H
63 #include <sys/errno.h>
64 #endif
65 #include <netdb.h>
66 #include <unistd.h>
67 #include <stdlib.h>
68 #ifdef HAVE_ARPA_NAMESER_H
69 # include <arpa/nameser.h>
70 #endif
71 #ifdef HAVE_RESOLV_H
72 # include <resolv.h>
73 #endif
74 #ifdef HAVE_NET_IF_H
75 # include <net/if.h>
76 #endif
77 #ifdef HAVE_IPX_GNU
78 # include <netipx/ipx.h>
79 # define HAVE_IPX
80 #endif
81 #ifdef HAVE_IPX_LINUX
82 # include <asm/types.h>
83 # include <linux/ipx.h>
84 # define HAVE_IPX
85 #endif
87 #include "wine/winbase16.h"
88 #include "wingdi.h"
89 #include "winuser.h"
90 #include "winsock2.h"
91 #include "wine/winsock16.h"
92 #include "winnt.h"
93 #include "heap.h"
94 #include "task.h"
95 #include "wine/port.h"
96 #include "services.h"
97 #include "server.h"
98 #include "file.h"
99 #include "debugtools.h"
102 DEFAULT_DEBUG_CHANNEL(winsock);
104 /* critical section to protect some non-rentrant net function */
105 extern CRITICAL_SECTION csWSgetXXXbyYYY;
107 #define DEBUG_SOCKADDR 0
108 #define dump_sockaddr(a) \
109 DPRINTF("sockaddr_in: family %d, address %s, port %d\n", \
110 ((struct sockaddr_in *)a)->sin_family, \
111 inet_ntoa(((struct sockaddr_in *)a)->sin_addr), \
112 ntohs(((struct sockaddr_in *)a)->sin_port))
114 /* ----------------------------------- internal data */
116 /* ws_... struct conversion flags */
118 #define WS_DUP_LINEAR 0x0001
119 #define WS_DUP_NATIVE 0x0000 /* not used anymore */
120 #define WS_DUP_OFFSET 0x0002 /* internal pointers are offsets */
121 #define WS_DUP_SEGPTR 0x0004 /* internal pointers are SEGPTRs */
122 /* by default, internal pointers are linear */
123 typedef struct /* WSAAsyncSelect() control struct */
125 HANDLE service, event, sock;
126 HWND hWnd;
127 UINT uMsg;
128 LONG lEvent;
129 struct _WSINFO *pwsi;
130 } ws_select_info;
132 #define WS_MAX_SOCKETS_PER_PROCESS 128 /* reasonable guess */
133 #define WS_MAX_UDP_DATAGRAM 1024
135 #define WS_ACCEPT_QUEUE 6
137 #define WSI_BLOCKINGCALL 0x00000001 /* per-thread info flags */
138 #define WSI_BLOCKINGHOOK 0x00000002 /* 32-bit callback */
140 #define PROCFS_NETDEV_FILE "/proc/net/dev" /* Points to the file in the /proc fs
141 that lists the network devices.
142 Do we need an #ifdef LINUX for this? */
144 typedef struct _WSINFO
146 DWORD dwThisProcess;
147 struct _WSINFO *lpNextIData;
149 unsigned flags;
150 INT16 num_startup; /* reference counter */
151 INT16 num_async_rq;
152 INT16 last_free; /* entry in the socket table */
153 UINT16 buflen;
154 char* buffer; /* allocated from SEGPTR heap */
155 void *he; /* typecast for Win16/32 ws_hostent */
156 int helen;
157 void *se; /* typecast for Win16/32 ws_servent */
158 int selen;
159 void *pe; /* typecast for Win16/32 ws_protoent */
160 int pelen;
161 char* dbuffer; /* buffer for dummies (32 bytes) */
163 DWORD blocking_hook;
165 volatile HANDLE accept_old[WS_ACCEPT_QUEUE], accept_new[WS_ACCEPT_QUEUE];
166 } WSINFO, *LPWSINFO;
168 /* function prototypes */
169 int WS_dup_he(LPWSINFO pwsi, struct hostent* p_he, int flag);
170 int WS_dup_pe(LPWSINFO pwsi, struct protoent* p_pe, int flag);
171 int WS_dup_se(LPWSINFO pwsi, struct servent* p_se, int flag);
173 typedef void WIN_hostent;
174 typedef void WIN_protoent;
175 typedef void WIN_servent;
177 int WSAIOCTL_GetInterfaceCount(void);
178 int WSAIOCTL_GetInterfaceName(int intNumber, char *intName);
180 UINT16 wsaErrno(void);
181 UINT16 wsaHerrno(int errnr);
183 static HANDLE _WSHeap = 0;
185 #define WS_ALLOC(size) \
186 HeapAlloc(_WSHeap, HEAP_ZERO_MEMORY, (size) )
187 #define WS_FREE(ptr) \
188 HeapFree(_WSHeap, 0, (ptr) )
190 static INT _ws_sock_ops[] =
191 { WS_SO_DEBUG, WS_SO_REUSEADDR, WS_SO_KEEPALIVE, WS_SO_DONTROUTE,
192 WS_SO_BROADCAST, WS_SO_LINGER, WS_SO_OOBINLINE, WS_SO_SNDBUF,
193 WS_SO_RCVBUF, WS_SO_ERROR, WS_SO_TYPE,
194 #ifdef SO_RCVTIMEO
195 WS_SO_RCVTIMEO,
196 #endif
197 #ifdef SO_SNDTIMEO
198 WS_SO_SNDTIMEO,
199 #endif
200 0 };
201 static int _px_sock_ops[] =
202 { SO_DEBUG, SO_REUSEADDR, SO_KEEPALIVE, SO_DONTROUTE, SO_BROADCAST,
203 SO_LINGER, SO_OOBINLINE, SO_SNDBUF, SO_RCVBUF, SO_ERROR, SO_TYPE,
204 #ifdef SO_RCVTIMEO
205 SO_RCVTIMEO,
206 #endif
207 #ifdef SO_SNDTIMEO
208 SO_SNDTIMEO,
209 #endif
212 static INT _ws_tcp_ops[] = {
213 #ifdef TCP_NODELAY
214 WS_TCP_NODELAY,
215 #endif
218 static int _px_tcp_ops[] = {
219 #ifdef TCP_NODELAY
220 TCP_NODELAY,
221 #endif
225 /* we need a special routine to handle WSA* errors */
226 static inline int sock_server_call( enum request req )
228 unsigned int res = server_call_noerr( req );
229 if (res)
231 /* do not map WSA errors */
232 if ((res < WSABASEERR) || (res >= 0x10000000)) res = RtlNtStatusToDosError(res);
233 SetLastError( res );
235 return res;
238 static int _check_ws(LPWSINFO pwsi, SOCKET s);
239 static char* _check_buffer(LPWSINFO pwsi, int size);
241 static int _get_sock_fd(SOCKET s)
243 int fd = FILE_GetUnixHandle( s, GENERIC_READ );
244 if (fd == -1)
245 FIXME("handle %d is not a socket (GLE %ld)\n",s,GetLastError());
246 return fd;
249 static void _enable_event(SOCKET s, unsigned int event,
250 unsigned int sstate, unsigned int cstate)
252 SERVER_START_REQ
254 struct enable_socket_event_request *req = server_alloc_req( sizeof(*req), 0 );
256 req->handle = s;
257 req->mask = event;
258 req->sstate = sstate;
259 req->cstate = cstate;
260 sock_server_call( REQ_ENABLE_SOCKET_EVENT );
262 SERVER_END_REQ;
265 static int _is_blocking(SOCKET s)
267 int ret;
268 SERVER_START_REQ
270 struct get_socket_event_request *req = server_alloc_req( sizeof(*req), 0 );
272 req->handle = s;
273 req->service = FALSE;
274 req->s_event = 0;
275 req->c_event = 0;
276 sock_server_call( REQ_GET_SOCKET_EVENT );
277 ret = (req->state & WS_FD_NONBLOCKING) == 0;
279 SERVER_END_REQ;
280 return ret;
283 static unsigned int _get_sock_mask(SOCKET s)
285 unsigned int ret;
286 SERVER_START_REQ
288 struct get_socket_event_request *req = server_alloc_req( sizeof(*req), 0 );
290 req->handle = s;
291 req->service = FALSE;
292 req->s_event = 0;
293 req->c_event = 0;
294 sock_server_call( REQ_GET_SOCKET_EVENT );
295 ret = req->mask;
297 SERVER_END_REQ;
298 return ret;
301 static void _sync_sock_state(SOCKET s)
303 /* do a dummy wineserver request in order to let
304 the wineserver run through its select loop once */
305 (void)_is_blocking(s);
308 static int _get_sock_error(SOCKET s, unsigned int bit)
310 int ret;
311 SERVER_START_REQ
313 struct get_socket_event_request *req = server_alloc_req( sizeof(*req),
314 FD_MAX_EVENTS*sizeof(int) );
315 req->handle = s;
316 req->service = FALSE;
317 req->s_event = 0;
318 req->c_event = 0;
319 sock_server_call( REQ_GET_SOCKET_EVENT );
320 ret = *((int *)server_data_ptr(req) + bit);
322 SERVER_END_REQ;
323 return ret;
326 static LPWSINFO lpFirstIData = NULL;
328 static LPWSINFO WINSOCK_GetIData(void)
330 DWORD pid = GetCurrentProcessId();
331 LPWSINFO iData;
333 for (iData = lpFirstIData; iData; iData = iData->lpNextIData) {
334 if (iData->dwThisProcess == pid)
335 break;
337 return iData;
340 static BOOL WINSOCK_CreateIData(void)
342 LPWSINFO iData;
344 iData = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(WSINFO));
345 if (!iData)
346 return FALSE;
347 iData->dwThisProcess = GetCurrentProcessId();
348 iData->lpNextIData = lpFirstIData;
349 lpFirstIData = iData;
350 return TRUE;
353 static void WINSOCK_DeleteIData(void)
355 LPWSINFO iData = WINSOCK_GetIData();
356 LPWSINFO* ppid;
357 if (iData) {
358 for (ppid = &lpFirstIData; *ppid; ppid = &(*ppid)->lpNextIData) {
359 if (*ppid == iData) {
360 *ppid = iData->lpNextIData;
361 break;
365 if( iData->flags & WSI_BLOCKINGCALL )
366 TRACE("\tinside blocking call!\n");
368 /* delete scratch buffers */
370 if( iData->buffer ) SEGPTR_FREE(iData->buffer);
371 if( iData->dbuffer ) SEGPTR_FREE(iData->dbuffer);
373 HeapFree(GetProcessHeap(), 0, iData);
377 /***********************************************************************
378 * WSOCK32_LibMain (WSOCK32.init)
380 BOOL WINAPI WSOCK32_LibMain(HINSTANCE hInstDLL, DWORD fdwReason, LPVOID fImpLoad)
382 TRACE("0x%x 0x%lx %p\n", hInstDLL, fdwReason, fImpLoad);
383 switch (fdwReason) {
384 case DLL_PROCESS_DETACH:
385 WINSOCK_DeleteIData();
386 break;
388 return TRUE;
391 /***********************************************************************
392 * WINSOCK_LibMain (WINSOCK.init)
394 BOOL WINAPI WINSOCK_LibMain(DWORD fdwReason, HINSTANCE hInstDLL, WORD ds,
395 WORD wHeapSize, DWORD dwReserved1, WORD wReserved2)
397 TRACE("0x%x 0x%lx\n", hInstDLL, fdwReason);
398 switch (fdwReason) {
399 case DLL_PROCESS_DETACH:
400 WINSOCK_DeleteIData();
401 break;
403 return TRUE;
406 /***********************************************************************
407 * convert_sockopt()
409 * Converts socket flags from Windows format.
410 * Return 1 if converted, 0 if not (error).
412 static int convert_sockopt(INT *level, INT *optname)
414 int i;
415 switch (*level)
417 case WS_SOL_SOCKET:
418 *level = SOL_SOCKET;
419 for(i=0; _ws_sock_ops[i]; i++)
420 if( _ws_sock_ops[i] == *optname ) break;
421 if( _ws_sock_ops[i] ) {
422 *optname = _px_sock_ops[i];
423 return 1;
425 FIXME("Unknown SOL_SOCKET optname 0x%x\n", *optname);
426 break;
427 case WS_IPPROTO_TCP:
428 *level = IPPROTO_TCP;
429 for(i=0; _ws_tcp_ops[i]; i++)
430 if ( _ws_tcp_ops[i] == *optname ) break;
431 if( _ws_tcp_ops[i] ) {
432 *optname = _px_tcp_ops[i];
433 return 1;
435 FIXME("Unknown IPPROTO_TCP optname 0x%x\n", *optname);
436 break;
438 return 0;
441 /* ----------------------------------- Per-thread info (or per-process?) */
443 static int wsi_strtolo(LPWSINFO pwsi, const char* name, const char* opt)
445 /* Stuff a lowercase copy of the string into the local buffer */
447 int i = strlen(name) + 2;
448 char* p = _check_buffer(pwsi, i + ((opt)?strlen(opt):0));
450 if( p )
452 do *p++ = tolower(*name); while(*name++);
453 i = (p - (char*)(pwsi->buffer));
454 if( opt ) do *p++ = tolower(*opt); while(*opt++);
455 return i;
457 return 0;
460 static fd_set* fd_set_import( fd_set* fds, LPWSINFO pwsi, void* wsfds, int* highfd, int lfd[], BOOL b32 )
462 /* translate Winsock fd set into local fd set */
464 if( wsfds )
466 #define wsfds16 ((ws_fd_set16*)wsfds)
467 #define wsfds32 ((ws_fd_set32*)wsfds)
468 int i, count;
470 FD_ZERO(fds);
471 count = b32 ? wsfds32->fd_count : wsfds16->fd_count;
473 for( i = 0; i < count; i++ )
475 int s = (b32) ? wsfds32->fd_array[i]
476 : wsfds16->fd_array[i];
477 if( _check_ws(pwsi, s) )
479 int fd = _get_sock_fd(s);
480 lfd[ i ] = fd;
481 if( fd > *highfd ) *highfd = fd;
482 FD_SET(fd, fds);
484 else lfd[ i ] = -1;
486 #undef wsfds32
487 #undef wsfds16
488 return fds;
490 return NULL;
493 inline static int sock_error_p(int s)
495 unsigned int optval, optlen;
497 optlen = sizeof(optval);
498 getsockopt(s, SOL_SOCKET, SO_ERROR, (void *) &optval, &optlen);
499 if (optval) WARN("\t[%i] error: %d\n", s, optval);
500 return optval != 0;
503 static int fd_set_export( LPWSINFO pwsi, fd_set* fds, fd_set* exceptfds, void* wsfds, int lfd[], BOOL b32 )
505 int num_err = 0;
507 /* translate local fd set into Winsock fd set, adding
508 * errors to exceptfds (only if app requested it) */
510 if( wsfds )
512 #define wsfds16 ((ws_fd_set16*)wsfds)
513 #define wsfds32 ((ws_fd_set32*)wsfds)
514 int i, j, count = (b32) ? wsfds32->fd_count : wsfds16->fd_count;
516 for( i = 0, j = 0; i < count; i++ )
518 if( lfd[i] >= 0 )
520 int fd = lfd[i];
521 if( FD_ISSET(fd, fds) )
523 if ( exceptfds && sock_error_p(fd) )
525 FD_SET(fd, exceptfds);
526 num_err++;
528 else if( b32 )
529 wsfds32->fd_array[j++] = wsfds32->fd_array[i];
530 else
531 wsfds16->fd_array[j++] = wsfds16->fd_array[i];
533 close(fd);
534 lfd[i] = -1;
538 if( b32 ) wsfds32->fd_count = j;
539 else wsfds16->fd_count = j;
541 TRACE("\n");
542 #undef wsfds32
543 #undef wsfds16
545 return num_err;
548 static void fd_set_unimport( void* wsfds, int lfd[], BOOL b32 )
550 if ( wsfds )
552 #define wsfds16 ((ws_fd_set16*)wsfds)
553 #define wsfds32 ((ws_fd_set32*)wsfds)
554 int i, count = (b32) ? wsfds32->fd_count : wsfds16->fd_count;
556 for( i = 0; i < count; i++ )
557 if ( lfd[i] >= 0 )
558 close(lfd[i]);
560 TRACE("\n");
561 #undef wsfds32
562 #undef wsfds16
566 static int do_block( int fd, int mask )
568 fd_set fds[3];
569 int i, r;
571 FD_ZERO(&fds[0]);
572 FD_ZERO(&fds[1]);
573 FD_ZERO(&fds[2]);
574 for (i=0; i<3; i++)
575 if (mask & (1<<i))
576 FD_SET(fd, &fds[i]);
577 i = select( fd+1, &fds[0], &fds[1], &fds[2], NULL );
578 if (i <= 0) return -1;
579 r = 0;
580 for (i=0; i<3; i++)
581 if (FD_ISSET(fd, &fds[i]))
582 r |= 1<<i;
583 return r;
586 void* __ws_memalloc( int size )
588 return WS_ALLOC(size);
591 void __ws_memfree(void* ptr)
593 WS_FREE(ptr);
597 /* ----------------------------------- API -----
599 * Init / cleanup / error checking.
602 /***********************************************************************
603 * WSAStartup16() (WINSOCK.115)
605 * Create socket control struct, attach it to the global list and
606 * update a pointer in the task struct.
608 INT16 WINAPI WSAStartup16(UINT16 wVersionRequested, LPWSADATA lpWSAData)
610 WSADATA WINSOCK_data = { 0x0101, 0x0101,
611 "WINE Sockets 1.1",
612 #ifdef linux
613 "Linux/i386",
614 #elif defined(__NetBSD__)
615 "NetBSD/i386",
616 #elif defined(sunos)
617 "SunOS",
618 #elif defined(__FreeBSD__)
619 "FreeBSD",
620 #elif defined(__OpenBSD__)
621 "OpenBSD/i386",
622 #else
623 "Unknown",
624 #endif
625 WS_MAX_SOCKETS_PER_PROCESS,
626 WS_MAX_UDP_DATAGRAM, (SEGPTR)NULL };
627 LPWSINFO pwsi;
629 TRACE("verReq=%x\n", wVersionRequested);
631 if (LOBYTE(wVersionRequested) < 1 || (LOBYTE(wVersionRequested) == 1 &&
632 HIBYTE(wVersionRequested) < 1)) return WSAVERNOTSUPPORTED;
634 if (!lpWSAData) return WSAEINVAL;
636 /* initialize socket heap */
638 if( !_WSHeap )
640 _WSHeap = HeapCreate(HEAP_ZERO_MEMORY, 8120, 32768);
641 if( !_WSHeap )
643 ERR("Fatal: failed to create WinSock heap\n");
644 return 0;
647 if( _WSHeap == 0 ) return WSASYSNOTREADY;
649 pwsi = WINSOCK_GetIData();
650 if( pwsi == NULL )
652 WINSOCK_CreateIData();
653 pwsi = WINSOCK_GetIData();
654 if (!pwsi) return WSASYSNOTREADY;
656 pwsi->num_startup++;
658 /* return winsock information */
660 memcpy(lpWSAData, &WINSOCK_data, sizeof(WINSOCK_data));
662 TRACE("succeeded\n");
663 return 0;
666 /***********************************************************************
667 * WSAStartup() (WS2_32.115)
669 INT WINAPI WSAStartup(UINT wVersionRequested, LPWSADATA lpWSAData)
671 WSADATA WINSOCK_data = { 0x0202, 0x0202,
672 "WINE Sockets 2.0",
673 #ifdef linux
674 "Linux/i386",
675 #elif defined(__NetBSD__)
676 "NetBSD/i386",
677 #elif defined(sunos)
678 "SunOS",
679 #elif defined(__FreeBSD__)
680 "FreeBSD",
681 #elif defined(__OpenBSD__)
682 "OpenBSD/i386",
683 #else
684 "Unknown",
685 #endif
686 WS_MAX_SOCKETS_PER_PROCESS,
687 WS_MAX_UDP_DATAGRAM, (SEGPTR)NULL };
688 LPWSINFO pwsi;
690 TRACE("verReq=%x\n", wVersionRequested);
692 if (LOBYTE(wVersionRequested) < 1)
693 return WSAVERNOTSUPPORTED;
695 if (!lpWSAData) return WSAEINVAL;
697 /* initialize socket heap */
699 if( !_WSHeap )
701 _WSHeap = HeapCreate(HEAP_ZERO_MEMORY, 8120, 32768);
702 if( !_WSHeap )
704 ERR("Fatal: failed to create WinSock heap\n");
705 return 0;
708 if( _WSHeap == 0 ) return WSASYSNOTREADY;
710 pwsi = WINSOCK_GetIData();
711 if( pwsi == NULL )
713 WINSOCK_CreateIData();
714 pwsi = WINSOCK_GetIData();
715 if (!pwsi) return WSASYSNOTREADY;
717 pwsi->num_startup++;
719 /* return winsock information */
720 memcpy(lpWSAData, &WINSOCK_data, sizeof(WINSOCK_data));
722 /* that's the whole of the negotiation for now */
723 lpWSAData->wVersion = wVersionRequested;
725 TRACE("succeeded\n");
726 return 0;
730 /***********************************************************************
731 * WSACleanup() (WINSOCK.116)
733 INT WINAPI WSACleanup(void)
735 LPWSINFO pwsi = WINSOCK_GetIData();
736 if( pwsi ) {
737 if( --pwsi->num_startup > 0 ) return 0;
739 WINSOCK_DeleteIData();
740 return 0;
742 SetLastError(WSANOTINITIALISED);
743 return SOCKET_ERROR;
747 /***********************************************************************
748 * WSAGetLastError() (WSOCK32.111)(WINSOCK.111)
750 INT WINAPI WSAGetLastError(void)
752 return GetLastError();
755 /***********************************************************************
756 * WSASetLastError() (WSOCK32.112)
758 void WINAPI WSASetLastError(INT iError) {
759 SetLastError(iError);
762 /***********************************************************************
763 * WSASetLastError16() (WINSOCK.112)
765 void WINAPI WSASetLastError16(INT16 iError)
767 WSASetLastError(iError);
770 int _check_ws(LPWSINFO pwsi, SOCKET s)
772 if( pwsi )
774 int fd;
775 if( pwsi->flags & WSI_BLOCKINGCALL ) SetLastError(WSAEINPROGRESS);
776 if ( (fd = _get_sock_fd(s)) < 0 ) {
777 SetLastError(WSAENOTSOCK);
778 return 0;
780 /* FIXME: maybe check whether fd is really a socket? */
781 close( fd );
782 return 1;
784 return 0;
787 char* _check_buffer(LPWSINFO pwsi, int size)
789 if( pwsi->buffer && pwsi->buflen >= size ) return pwsi->buffer;
790 else SEGPTR_FREE(pwsi->buffer);
792 pwsi->buffer = (char*)SEGPTR_ALLOC((pwsi->buflen = size));
793 return pwsi->buffer;
796 struct ws_hostent* _check_buffer_he(LPWSINFO pwsi, int size)
798 if( pwsi->he && pwsi->helen >= size ) return pwsi->he;
799 else SEGPTR_FREE(pwsi->he);
801 pwsi->he = SEGPTR_ALLOC((pwsi->helen = size));
802 return pwsi->he;
805 void* _check_buffer_se(LPWSINFO pwsi, int size)
807 if( pwsi->se && pwsi->selen >= size ) return pwsi->se;
808 else SEGPTR_FREE(pwsi->se);
810 pwsi->se = SEGPTR_ALLOC((pwsi->selen = size));
811 return pwsi->se;
814 struct ws_protoent* _check_buffer_pe(LPWSINFO pwsi, int size)
816 if( pwsi->pe && pwsi->pelen >= size ) return pwsi->pe;
817 else SEGPTR_FREE(pwsi->pe);
819 pwsi->pe = SEGPTR_ALLOC((pwsi->pelen = size));
820 return pwsi->pe;
823 /* ----------------------------------- i/o APIs */
825 /***********************************************************************
826 * accept() (WSOCK32.1)
828 static void WSOCK32_async_accept(LPWSINFO pwsi, SOCKET s, SOCKET as)
830 int q;
831 /* queue socket for WSAAsyncSelect */
832 for (q=0; q<WS_ACCEPT_QUEUE; q++)
833 if (InterlockedCompareExchange((PVOID*)&pwsi->accept_old[q], (PVOID)s, (PVOID)0) == (PVOID)0)
834 break;
835 if (q<WS_ACCEPT_QUEUE)
836 pwsi->accept_new[q] = as;
837 else
838 ERR("accept queue too small\n");
839 /* now signal our AsyncSelect handler */
840 _enable_event(s, WS_FD_SERVEVENT, 0, 0);
843 SOCKET WINAPI WSOCK32_accept(SOCKET s, struct sockaddr *addr,
844 INT *addrlen32)
846 LPWSINFO pwsi = WINSOCK_GetIData();
847 #ifdef HAVE_IPX
848 struct ws_sockaddr_ipx* addr2 = (struct ws_sockaddr_ipx *)addr;
849 #endif
851 TRACE("(%08x): socket %04x\n",
852 (unsigned)pwsi, (UINT16)s );
853 if( _check_ws(pwsi, s) )
855 SOCKET as;
856 if (_is_blocking(s))
858 /* block here */
859 int fd = _get_sock_fd(s);
860 do_block(fd, 5);
861 close(fd);
862 _sync_sock_state(s); /* let wineserver notice connection */
863 /* retrieve any error codes from it */
864 SetLastError(_get_sock_error(s, FD_ACCEPT_BIT));
865 /* FIXME: care about the error? */
867 SERVER_START_REQ
869 struct accept_socket_request *req = server_alloc_req( sizeof(*req), 0 );
871 req->lhandle = s;
872 req->access = GENERIC_READ|GENERIC_WRITE|SYNCHRONIZE;
873 req->inherit = TRUE;
874 sock_server_call( REQ_ACCEPT_SOCKET );
875 as = req->handle;
877 SERVER_END_REQ;
878 if( ((int)as) >= 0 )
880 unsigned omask = _get_sock_mask( s );
881 int fd = _get_sock_fd( as );
882 if( getpeername(fd, addr, addrlen32) != -1 )
884 #ifdef HAVE_IPX
885 if (addr && ((struct sockaddr_ipx *)addr)->sipx_family == AF_IPX) {
886 addr = (struct sockaddr *)
887 malloc(addrlen32 ? *addrlen32 : sizeof(*addr2));
888 memcpy(addr, addr2,
889 addrlen32 ? *addrlen32 : sizeof(*addr2));
890 addr2->sipx_family = WS_AF_IPX;
891 addr2->sipx_network = ((struct sockaddr_ipx *)addr)->sipx_network;
892 addr2->sipx_port = ((struct sockaddr_ipx *)addr)->sipx_port;
893 memcpy(addr2->sipx_node,
894 ((struct sockaddr_ipx *)addr)->sipx_node, IPX_NODE_LEN);
895 free(addr);
897 #endif
898 } else SetLastError(wsaErrno());
899 close(fd);
900 if (omask & WS_FD_SERVEVENT)
901 WSOCK32_async_accept(pwsi, s, as);
902 return as;
905 return INVALID_SOCKET;
908 /***********************************************************************
909 * accept() (WINSOCK.1)
911 SOCKET16 WINAPI WINSOCK_accept16(SOCKET16 s, struct sockaddr* addr,
912 INT16* addrlen16 )
914 INT addrlen32 = addrlen16 ? *addrlen16 : 0;
915 SOCKET retSocket = WSOCK32_accept( s, addr, &addrlen32 );
916 if( addrlen16 ) *addrlen16 = (INT16)addrlen32;
917 return (SOCKET16)retSocket;
920 /***********************************************************************
921 * bind() (WSOCK32.2)
923 INT WINAPI WSOCK32_bind(SOCKET s, struct sockaddr *name, INT namelen)
925 LPWSINFO pwsi = WINSOCK_GetIData();
926 #ifdef HAVE_IPX
927 struct ws_sockaddr_ipx* name2 = (struct ws_sockaddr_ipx *)name;
928 #endif
930 TRACE("(%08x): socket %04x, ptr %8x, length %d\n",
931 (unsigned)pwsi, s, (int) name, namelen);
932 #if DEBUG_SOCKADDR
933 dump_sockaddr(name);
934 #endif
936 if ( _check_ws(pwsi, s) )
938 int fd = _get_sock_fd(s);
939 /* FIXME: what family does this really map to on the Unix side? */
940 if (name && ((struct ws_sockaddr_ipx *)name)->sipx_family == WS_AF_PUP)
941 ((struct ws_sockaddr_ipx *)name)->sipx_family = AF_UNSPEC;
942 #ifdef HAVE_IPX
943 else if (name &&
944 ((struct ws_sockaddr_ipx *)name)->sipx_family == WS_AF_IPX)
946 name = (struct sockaddr *) malloc(sizeof(struct sockaddr_ipx));
947 memset(name, '\0', sizeof(struct sockaddr_ipx));
948 ((struct sockaddr_ipx *)name)->sipx_family = AF_IPX;
949 ((struct sockaddr_ipx *)name)->sipx_port = name2->sipx_port;
950 ((struct sockaddr_ipx *)name)->sipx_network = name2->sipx_network;
951 memcpy(((struct sockaddr_ipx *)name)->sipx_node,
952 name2->sipx_node, IPX_NODE_LEN);
953 namelen = sizeof(struct sockaddr_ipx);
955 #endif
956 if ( namelen >= sizeof(*name) )
958 if ( name && (((struct ws_sockaddr_in *)name)->sin_family == AF_INET
959 #ifdef HAVE_IPX
960 || ((struct sockaddr_ipx *)name)->sipx_family == AF_IPX
961 #endif
964 if ( bind(fd, name, namelen) < 0 )
966 int loc_errno = errno;
967 WARN("\tfailure - errno = %i\n", errno);
968 errno = loc_errno;
969 switch(errno)
971 case EBADF: SetLastError(WSAENOTSOCK); break;
972 case EADDRNOTAVAIL: SetLastError(WSAEINVAL); break;
973 default: SetLastError(wsaErrno());break;
976 else {
977 #ifdef HAVE_IPX
978 if (((struct sockaddr_ipx *)name)->sipx_family == AF_IPX)
979 free(name);
980 #endif
981 close(fd);
982 return 0; /* success */
984 } else SetLastError(WSAEAFNOSUPPORT);
985 } else SetLastError(WSAEFAULT);
986 #ifdef HAVE_IPX
987 if (name && ((struct sockaddr_ipx *)name)->sipx_family == AF_IPX)
988 free(name);
989 #endif
990 close(fd);
992 return SOCKET_ERROR;
995 /***********************************************************************
996 * bind() (WINSOCK.2)
998 INT16 WINAPI WINSOCK_bind16(SOCKET16 s, struct sockaddr *name, INT16 namelen)
1000 return (INT16)WSOCK32_bind( s, name, namelen );
1003 /***********************************************************************
1004 * closesocket() (WSOCK32.3)
1006 INT WINAPI WSOCK32_closesocket(SOCKET s)
1008 LPWSINFO pwsi = WINSOCK_GetIData();
1010 TRACE("(%08x): socket %08x\n", (unsigned)pwsi, s);
1012 if( _check_ws(pwsi, s) )
1014 if( CloseHandle(s) )
1015 return 0;
1017 return SOCKET_ERROR;
1020 /***********************************************************************
1021 * closesocket() (WINSOCK.3)
1023 INT16 WINAPI WINSOCK_closesocket16(SOCKET16 s)
1025 return (INT16)WSOCK32_closesocket(s);
1028 /***********************************************************************
1029 * connect() (WSOCK32.4)
1031 INT WINAPI WSOCK32_connect(SOCKET s, struct sockaddr *name, INT namelen)
1033 LPWSINFO pwsi = WINSOCK_GetIData();
1034 #ifdef HAVE_IPX
1035 struct ws_sockaddr_ipx* name2 = (struct ws_sockaddr_ipx *)name;
1036 #endif
1038 TRACE("(%08x): socket %04x, ptr %8x, length %d\n",
1039 (unsigned)pwsi, s, (int) name, namelen);
1040 #if DEBUG_SOCKADDR
1041 dump_sockaddr(name);
1042 #endif
1044 if( _check_ws(pwsi, s) )
1046 int fd = _get_sock_fd(s);
1047 if (name && ((struct ws_sockaddr_ipx *)name)->sipx_family == WS_AF_PUP)
1048 ((struct ws_sockaddr_ipx *)name)->sipx_family = AF_UNSPEC;
1049 #ifdef HAVE_IPX
1050 else if (name && ((struct ws_sockaddr_ipx *)name)->sipx_family == WS_AF_IPX)
1052 name = (struct sockaddr *) malloc(sizeof(struct sockaddr_ipx));
1053 memset(name, '\0', sizeof(struct sockaddr_ipx));
1054 ((struct sockaddr_ipx *)name)->sipx_family = AF_IPX;
1055 ((struct sockaddr_ipx *)name)->sipx_port = name2->sipx_port;
1056 ((struct sockaddr_ipx *)name)->sipx_network = name2->sipx_network;
1057 memcpy(((struct sockaddr_ipx *)name)->sipx_node,
1058 name2->sipx_node, IPX_NODE_LEN);
1059 namelen = sizeof(struct sockaddr_ipx);
1061 #endif
1062 if (connect(fd, name, namelen) == 0) {
1063 close(fd);
1064 goto connect_success;
1066 if (errno == EINPROGRESS)
1068 /* tell wineserver that a connection is in progress */
1069 _enable_event(s, FD_CONNECT|FD_READ|FD_WRITE,
1070 WS_FD_CONNECT|WS_FD_READ|WS_FD_WRITE,
1071 WS_FD_CONNECTED|WS_FD_LISTENING);
1072 if (_is_blocking(s))
1074 int result;
1075 /* block here */
1076 do_block(fd, 6);
1077 _sync_sock_state(s); /* let wineserver notice connection */
1078 /* retrieve any error codes from it */
1079 result = _get_sock_error(s, FD_CONNECT_BIT);
1080 if (result)
1081 SetLastError(result);
1082 else {
1083 close(fd);
1084 goto connect_success;
1087 else SetLastError(WSAEWOULDBLOCK);
1088 close(fd);
1090 else
1092 SetLastError(wsaErrno());
1093 close(fd);
1096 #ifdef HAVE_IPX
1097 if (name && ((struct sockaddr_ipx *)name)->sipx_family == AF_IPX)
1098 free(name);
1099 #endif
1100 return SOCKET_ERROR;
1101 connect_success:
1102 #ifdef HAVE_IPX
1103 if (((struct sockaddr_ipx *)name)->sipx_family == AF_IPX)
1104 free(name);
1105 #endif
1106 _enable_event(s, FD_CONNECT|FD_READ|FD_WRITE,
1107 WS_FD_CONNECTED|WS_FD_READ|WS_FD_WRITE,
1108 WS_FD_CONNECT|WS_FD_LISTENING);
1109 return 0;
1112 /***********************************************************************
1113 * connect() (WINSOCK.4)
1115 INT16 WINAPI WINSOCK_connect16(SOCKET16 s, struct sockaddr *name, INT16 namelen)
1117 return (INT16)WSOCK32_connect( s, name, namelen );
1120 /***********************************************************************
1121 * getpeername() (WSOCK32.5)
1123 INT WINAPI WSOCK32_getpeername(SOCKET s, struct sockaddr *name,
1124 INT *namelen)
1126 LPWSINFO pwsi = WINSOCK_GetIData();
1127 #ifdef HAVE_IPX
1128 struct ws_sockaddr_ipx* name2 = (struct ws_sockaddr_ipx *)name;
1129 #endif
1131 TRACE("(%08x): socket: %04x, ptr %8x, ptr %8x\n",
1132 (unsigned)pwsi, s, (int) name, *namelen);
1133 if( _check_ws(pwsi, s) )
1135 int fd = _get_sock_fd(s);
1136 if (getpeername(fd, name, namelen) == 0) {
1137 #ifdef HAVE_IPX
1138 if (((struct ws_sockaddr_ipx *)name)->sipx_family == AF_IPX) {
1139 name = (struct sockaddr *)
1140 malloc(namelen ? *namelen : sizeof(*name2));
1141 memcpy(name, name2, namelen ? *namelen : sizeof(*name2));
1142 name2->sipx_family = WS_AF_IPX;
1143 name2->sipx_network = ((struct sockaddr_ipx *)name)->sipx_network;
1144 name2->sipx_port = ((struct sockaddr_ipx *)name)->sipx_port;
1145 memcpy(name2->sipx_node,
1146 ((struct sockaddr_ipx *)name)->sipx_node, IPX_NODE_LEN);
1147 free(name);
1149 #endif
1150 close(fd);
1151 return 0;
1153 SetLastError(wsaErrno());
1154 close(fd);
1156 return SOCKET_ERROR;
1159 /***********************************************************************
1160 * getpeername() (WINSOCK.5)
1162 INT16 WINAPI WINSOCK_getpeername16(SOCKET16 s, struct sockaddr *name,
1163 INT16 *namelen16)
1165 INT namelen32 = *namelen16;
1166 INT retVal = WSOCK32_getpeername( s, name, &namelen32 );
1168 #if DEBUG_SOCKADDR
1169 dump_sockaddr(name);
1170 #endif
1172 *namelen16 = namelen32;
1173 return (INT16)retVal;
1176 /***********************************************************************
1177 * getsockname() (WSOCK32.6)
1179 INT WINAPI WSOCK32_getsockname(SOCKET s, struct sockaddr *name,
1180 INT *namelen)
1182 LPWSINFO pwsi = WINSOCK_GetIData();
1183 #ifdef HAVE_IPX
1184 struct ws_sockaddr_ipx* name2 = (struct ws_sockaddr_ipx *)name;
1185 #endif
1187 TRACE("(%08x): socket: %04x, ptr %8x, ptr %8x\n",
1188 (unsigned)pwsi, s, (int) name, (int) *namelen);
1189 if( _check_ws(pwsi, s) )
1191 int fd = _get_sock_fd(s);
1192 if (getsockname(fd, name, namelen) == 0) {
1193 #ifdef HAVE_IPX
1194 if (((struct sockaddr_ipx *)name)->sipx_family == AF_IPX) {
1195 name = (struct sockaddr *)
1196 malloc(namelen ? *namelen : sizeof(*name2));
1197 memcpy(name, name2, namelen ? *namelen : sizeof(*name2));
1198 name2->sipx_family = WS_AF_IPX;
1199 name2->sipx_network = ((struct sockaddr_ipx *)name)->sipx_network;
1200 name2->sipx_port = ((struct sockaddr_ipx *)name)->sipx_port;
1201 memcpy(name2->sipx_node,
1202 ((struct sockaddr_ipx *)name)->sipx_node, IPX_NODE_LEN);
1203 free(name);
1205 #endif
1206 close(fd);
1207 return 0;
1209 SetLastError(wsaErrno());
1210 close(fd);
1212 return SOCKET_ERROR;
1215 /***********************************************************************
1216 * getsockname() (WINSOCK.6)
1218 INT16 WINAPI WINSOCK_getsockname16(SOCKET16 s, struct sockaddr *name,
1219 INT16 *namelen16)
1221 INT retVal;
1223 if( namelen16 )
1225 INT namelen32 = *namelen16;
1226 retVal = WSOCK32_getsockname( s, name, &namelen32 );
1227 *namelen16 = namelen32;
1229 #if DEBUG_SOCKADDR
1230 dump_sockaddr(name);
1231 #endif
1234 else retVal = SOCKET_ERROR;
1235 return (INT16)retVal;
1239 /***********************************************************************
1240 * getsockopt() (WSOCK32.7)
1242 INT WINAPI WSOCK32_getsockopt(SOCKET s, INT level,
1243 INT optname, char *optval, INT *optlen)
1245 LPWSINFO pwsi = WINSOCK_GetIData();
1247 TRACE("(%08x): socket: %04x, opt 0x%x, ptr %8x, len %d\n",
1248 (unsigned)pwsi, s, level, (int) optval, (int) *optlen);
1249 if( _check_ws(pwsi, s) )
1251 int fd = _get_sock_fd(s);
1252 if (!convert_sockopt(&level, &optname)) {
1253 SetLastError(WSAENOPROTOOPT); /* Unknown option */
1254 } else {
1255 if (getsockopt(fd, (int) level, optname, optval, optlen) == 0 )
1257 close(fd);
1258 return 0;
1260 SetLastError((errno == EBADF) ? WSAENOTSOCK : wsaErrno());
1262 close(fd);
1264 return SOCKET_ERROR;
1267 /***********************************************************************
1268 * getsockopt() (WINSOCK.7)
1270 INT16 WINAPI WINSOCK_getsockopt16(SOCKET16 s, INT16 level,
1271 INT16 optname, char *optval, INT16 *optlen)
1273 INT optlen32;
1274 INT *p = &optlen32;
1275 INT retVal;
1276 if( optlen ) optlen32 = *optlen; else p = NULL;
1277 retVal = WSOCK32_getsockopt( s, (UINT16)level, optname, optval, p );
1278 if( optlen ) *optlen = optlen32;
1279 return (INT16)retVal;
1282 /***********************************************************************
1283 * htonl() (WINSOCK.8)(WSOCK32.8)
1285 u_long WINAPI WINSOCK_htonl(u_long hostlong) { return( htonl(hostlong) ); }
1286 /***********************************************************************
1287 * htons() (WINSOCK.9)(WSOCK32.9)
1289 u_short WINAPI WINSOCK_htons(u_short hostshort) { return( htons(hostshort) ); }
1290 /***********************************************************************
1291 * inet_addr() (WINSOCK.10)(WSOCK32.10)
1293 u_long WINAPI WINSOCK_inet_addr(char *cp) { return( inet_addr(cp) ); }
1294 /***********************************************************************
1295 * ntohl() (WINSOCK.14)(WSOCK32.14)
1297 u_long WINAPI WINSOCK_ntohl(u_long netlong) { return( ntohl(netlong) ); }
1298 /***********************************************************************
1299 * ntohs() (WINSOCK.15)(WSOCK32.15)
1301 u_short WINAPI WINSOCK_ntohs(u_short netshort) { return( ntohs(netshort) ); }
1303 /***********************************************************************
1304 * inet_ntoa() (WINSOCK.11)(WSOCK32.11)
1306 char* WINAPI WSOCK32_inet_ntoa(struct in_addr in)
1308 /* use "buffer for dummies" here because some applications have
1309 * propensity to decode addresses in ws_hostent structure without
1310 * saving them first...
1313 LPWSINFO pwsi = WINSOCK_GetIData();
1315 if( pwsi )
1317 char* s = inet_ntoa(in);
1318 if( s )
1320 if( pwsi->dbuffer == NULL ) {
1321 /* Yes, 16: 4*3 digits + 3 '.' + 1 '\0' */
1322 if((pwsi->dbuffer = (char*) SEGPTR_ALLOC(16)) == NULL )
1324 SetLastError(WSAENOBUFS);
1325 return NULL;
1328 strcpy(pwsi->dbuffer, s);
1329 return pwsi->dbuffer;
1331 SetLastError(wsaErrno());
1333 return NULL;
1336 SEGPTR WINAPI WINSOCK_inet_ntoa16(struct in_addr in)
1338 char* retVal = WSOCK32_inet_ntoa(in);
1339 return retVal ? SEGPTR_GET(retVal) : (SEGPTR)NULL;
1343 /**********************************************************************
1344 * WSAIoctl (WS2_32)
1347 * FIXME: Only SIO_GET_INTERFACE_LIST option implemented.
1349 INT WINAPI WSAIoctl (SOCKET s,
1350 DWORD dwIoControlCode,
1351 LPVOID lpvInBuffer,
1352 DWORD cbInBuffer,
1353 LPVOID lpbOutBuffer,
1354 DWORD cbOutBuffer,
1355 LPDWORD lpcbBytesReturned,
1356 LPWSAOVERLAPPED lpOverlapped,
1357 LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine)
1359 LPWSINFO pwsi = WINSOCK_GetIData();
1361 if( _check_ws(pwsi, s) )
1363 int fd = _get_sock_fd(s);
1365 switch( dwIoControlCode )
1367 case SIO_GET_INTERFACE_LIST:
1369 INTERFACE_INFO* intArray = (INTERFACE_INFO*)lpbOutBuffer;
1370 int i, numInt;
1371 struct ifreq ifInfo;
1372 char ifName[512];
1375 TRACE ("-> SIO_GET_INTERFACE_LIST request\n");
1377 numInt = WSAIOCTL_GetInterfaceCount();
1378 if (numInt < 0)
1380 ERR ("Unable to open /proc filesystem to determine number of network interfaces!\n");
1381 close(fd);
1382 WSASetLastError(WSAEINVAL);
1383 return (SOCKET_ERROR);
1386 for (i=0; i<numInt; i++)
1388 if (!WSAIOCTL_GetInterfaceName(i, ifName))
1390 ERR ("Error parsing /proc filesystem!\n");
1391 close(fd);
1392 WSASetLastError(WSAEINVAL);
1393 return (SOCKET_ERROR);
1396 ifInfo.ifr_addr.sa_family = AF_INET;
1398 /* IP Address */
1399 strcpy (ifInfo.ifr_name, ifName);
1400 if (ioctl(fd, SIOCGIFADDR, &ifInfo) < 0)
1402 ERR ("Error obtaining IP address\n");
1403 close(fd);
1404 WSASetLastError(WSAEINVAL);
1405 return (SOCKET_ERROR);
1407 else
1409 struct ws_sockaddr_in *ipTemp = (struct ws_sockaddr_in *)&ifInfo.ifr_addr;
1411 intArray->iiAddress.AddressIn.sin_family = AF_INET;
1412 intArray->iiAddress.AddressIn.sin_port = ipTemp->sin_port;
1413 intArray->iiAddress.AddressIn.sin_addr.ws_addr = ipTemp->sin_addr.S_un.S_addr;
1416 /* Broadcast Address */
1417 strcpy (ifInfo.ifr_name, ifName);
1418 if (ioctl(fd, SIOCGIFBRDADDR, &ifInfo) < 0)
1420 ERR ("Error obtaining Broadcast IP address\n");
1421 close(fd);
1422 WSASetLastError(WSAEINVAL);
1423 return (SOCKET_ERROR);
1425 else
1427 struct ws_sockaddr_in *ipTemp = (struct ws_sockaddr_in *)&ifInfo.ifr_broadaddr;
1429 intArray->iiBroadcastAddress.AddressIn.sin_family = AF_INET;
1430 intArray->iiBroadcastAddress.AddressIn.sin_port = ipTemp->sin_port;
1431 intArray->iiBroadcastAddress.AddressIn.sin_addr.ws_addr = ipTemp->sin_addr.S_un.S_addr;
1434 /* Subnet Mask */
1435 strcpy (ifInfo.ifr_name, ifName);
1436 if (ioctl(fd, SIOCGIFNETMASK, &ifInfo) < 0)
1438 ERR ("Error obtaining Subnet IP address\n");
1439 close(fd);
1440 WSASetLastError(WSAEINVAL);
1441 return (SOCKET_ERROR);
1443 else
1445 /* Trying to avoid some compile problems across platforms.
1446 (Linux, FreeBSD, Solaris...) */
1447 #ifndef ifr_netmask
1448 #ifndef ifr_addr
1449 intArray->iiNetmask.AddressIn.sin_family = AF_INET;
1450 intArray->iiNetmask.AddressIn.sin_port = 0;
1451 intArray->iiNetmask.AddressIn.sin_addr.ws_addr = 0;
1452 ERR ("Unable to determine Netmask on your platform!\n");
1453 #else
1454 struct ws_sockaddr_in *ipTemp = (struct ws_sockaddr_in *)&ifInfo.ifr_addr;
1456 intArray->iiNetmask.AddressIn.sin_family = AF_INET;
1457 intArray->iiNetmask.AddressIn.sin_port = ipTemp->sin_port;
1458 intArray->iiNetmask.AddressIn.sin_addr.ws_addr = ipTemp->sin_addr.S_un.S_addr;
1459 #endif
1460 #else
1461 struct ws_sockaddr_in *ipTemp = (struct ws_sockaddr_in *)&ifInfo.ifr_netmask;
1463 intArray->iiNetmask.AddressIn.sin_family = AF_INET;
1464 intArray->iiNetmask.AddressIn.sin_port = ipTemp->sin_port;
1465 intArray->iiNetmask.AddressIn.sin_addr.ws_addr = ipTemp->sin_addr.S_un.S_addr;
1466 #endif
1469 /* Socket Status Flags */
1470 strcpy(ifInfo.ifr_name, ifName);
1471 if (ioctl(fd, SIOCGIFFLAGS, &ifInfo) < 0)
1473 ERR ("Error obtaining status flags for socket!\n");
1474 close(fd);
1475 WSASetLastError(WSAEINVAL);
1476 return (SOCKET_ERROR);
1478 else
1480 /* FIXME - Is this the right flag to use? */
1481 intArray->iiFlags = ifInfo.ifr_flags;
1483 intArray++; /* Prepare for another interface */
1486 /* Calculate the size of the array being returned */
1487 *lpcbBytesReturned = sizeof(INTERFACE_INFO) * numInt;
1488 break;
1491 default:
1493 WARN("\tunsupported WS_IOCTL cmd (%08lx)\n", dwIoControlCode);
1494 close(fd);
1495 WSASetLastError(WSAEOPNOTSUPP);
1496 return (SOCKET_ERROR);
1500 /* Function executed with no errors */
1501 close(fd);
1502 return (0);
1504 else
1506 WSASetLastError(WSAENOTSOCK);
1507 return (SOCKET_ERROR);
1513 Helper function for WSAIoctl - Get count of the number of interfaces
1514 by parsing /proc filesystem.
1516 int WSAIOCTL_GetInterfaceCount(void)
1518 FILE *procfs;
1519 char buf[512]; /* Size doesn't matter, something big */
1520 int intcnt=0;
1523 /* Open /proc filesystem file for network devices */
1524 procfs = fopen(PROCFS_NETDEV_FILE, "r");
1525 if (!procfs)
1527 /* If we can't open the file, return an error */
1528 return (-1);
1531 /* Omit first two lines, they are only headers */
1532 fgets(buf, sizeof buf, procfs);
1533 fgets(buf, sizeof buf, procfs);
1535 while (fgets(buf, sizeof buf, procfs))
1537 /* Each line in the file represents a network interface */
1538 intcnt++;
1541 fclose(procfs);
1542 return(intcnt);
1547 Helper function for WSAIoctl - Get name of device from interface number
1548 by parsing /proc filesystem.
1550 int WSAIOCTL_GetInterfaceName(int intNumber, char *intName)
1552 FILE *procfs;
1553 char buf[512]; /* Size doesn't matter, something big */
1554 int i;
1556 /* Open /proc filesystem file for network devices */
1557 procfs = fopen(PROCFS_NETDEV_FILE, "r");
1558 if (!procfs)
1560 /* If we can't open the file, return an error */
1561 return (-1);
1564 /* Omit first two lines, they are only headers */
1565 fgets(buf, sizeof(buf), procfs);
1566 fgets(buf, sizeof(buf), procfs);
1568 for (i=0; i<intNumber; i++)
1570 /* Skip the lines that don't interest us. */
1571 fgets(buf, sizeof(buf), procfs);
1573 fgets(buf, sizeof(buf), procfs); /* This is the line we want */
1576 /* Parse out the line, grabbing only the name of the device
1577 to the intName variable
1579 The Line comes in like this: (we only care about the device name)
1580 lo: 21970 377 0 0 0 0 0 0 21970 377 0 0 0 0 0 0
1582 i=0;
1583 while (isspace(buf[i])) /* Skip initial space(s) */
1585 i++;
1588 while (buf[i])
1590 if (isspace(buf[i]))
1592 break;
1595 if (buf[i] == ':') /* FIXME: Not sure if this block (alias detection) works properly */
1597 /* This interface could be an alias... */
1598 int hold = i;
1599 char *dotname = intName;
1600 *intName++ = buf[i++];
1602 while (isdigit(buf[i]))
1604 *intName++ = buf[i++];
1607 if (buf[i] != ':')
1609 /* ... It wasn't, so back up */
1610 i = hold;
1611 intName = dotname;
1614 if (buf[i] == '\0')
1616 fclose(procfs);
1617 return(FALSE);
1620 i++;
1621 break;
1624 *intName++ = buf[i++];
1626 *intName++ = '\0';
1628 fclose(procfs);
1629 return(TRUE);
1633 /***********************************************************************
1634 * ioctlsocket() (WSOCK32.12)
1636 INT WINAPI WSOCK32_ioctlsocket(SOCKET s, LONG cmd, ULONG *argp)
1638 LPWSINFO pwsi = WINSOCK_GetIData();
1640 TRACE("(%08x): socket %04x, cmd %08lx, ptr %8x\n",
1641 (unsigned)pwsi, s, cmd, (unsigned) argp);
1642 if( _check_ws(pwsi, s) )
1644 int fd = _get_sock_fd(s);
1645 long newcmd = cmd;
1647 switch( cmd )
1649 case WS_FIONREAD:
1650 newcmd=FIONREAD;
1651 break;
1653 case WS_FIONBIO:
1654 newcmd=FIONBIO;
1655 if( _get_sock_mask(s) )
1657 /* AsyncSelect()'ed sockets are always nonblocking */
1658 if (*argp) {
1659 close(fd);
1660 return 0;
1662 SetLastError(WSAEINVAL);
1663 close(fd);
1664 return SOCKET_ERROR;
1666 close(fd);
1667 if (*argp)
1668 _enable_event(s, 0, WS_FD_NONBLOCKING, 0);
1669 else
1670 _enable_event(s, 0, 0, WS_FD_NONBLOCKING);
1671 return 0;
1673 case WS_SIOCATMARK:
1674 newcmd=SIOCATMARK;
1675 break;
1677 case WS_IOW('f',125,u_long):
1678 WARN("Warning: WS1.1 shouldn't be using async I/O\n");
1679 SetLastError(WSAEINVAL);
1680 return SOCKET_ERROR;
1682 default:
1683 /* Netscape tries hard to use bogus ioctl 0x667e */
1684 WARN("\tunknown WS_IOCTL cmd (%08lx)\n", cmd);
1686 if( ioctl(fd, newcmd, (char*)argp ) == 0 )
1688 close(fd);
1689 return 0;
1691 SetLastError((errno == EBADF) ? WSAENOTSOCK : wsaErrno());
1692 close(fd);
1694 return SOCKET_ERROR;
1697 /***********************************************************************
1698 * ioctlsocket() (WINSOCK.12)
1700 INT16 WINAPI WINSOCK_ioctlsocket16(SOCKET16 s, LONG cmd, ULONG *argp)
1702 return (INT16)WSOCK32_ioctlsocket( s, cmd, argp );
1706 /***********************************************************************
1707 * listen() (WSOCK32.13)
1709 INT WINAPI WSOCK32_listen(SOCKET s, INT backlog)
1711 LPWSINFO pwsi = WINSOCK_GetIData();
1713 TRACE("(%08x): socket %04x, backlog %d\n",
1714 (unsigned)pwsi, s, backlog);
1715 if( _check_ws(pwsi, s) )
1717 int fd = _get_sock_fd(s);
1718 if (listen(fd, backlog) == 0)
1720 close(fd);
1721 _enable_event(s, FD_ACCEPT,
1722 WS_FD_LISTENING,
1723 WS_FD_CONNECT|WS_FD_CONNECTED);
1724 return 0;
1726 SetLastError(wsaErrno());
1728 else SetLastError(WSAENOTSOCK);
1729 return SOCKET_ERROR;
1732 /***********************************************************************
1733 * listen() (WINSOCK.13)
1735 INT16 WINAPI WINSOCK_listen16(SOCKET16 s, INT16 backlog)
1737 return (INT16)WSOCK32_listen( s, backlog );
1741 /***********************************************************************
1742 * recv() (WSOCK32.16)
1744 INT WINAPI WSOCK32_recv(SOCKET s, char *buf, INT len, INT flags)
1746 LPWSINFO pwsi = WINSOCK_GetIData();
1748 TRACE("(%08x): socket %04x, buf %8x, len %d, "
1749 "flags %d\n", (unsigned)pwsi, s, (unsigned)buf,
1750 len, flags);
1751 if( _check_ws(pwsi, s) )
1753 int fd = _get_sock_fd(s);
1754 INT length;
1756 if (_is_blocking(s))
1758 /* block here */
1759 /* FIXME: OOB and exceptfds? */
1760 do_block(fd, 1);
1762 if ((length = recv(fd, buf, len, flags)) >= 0)
1764 TRACE(" -> %i bytes\n", length);
1766 close(fd);
1767 _enable_event(s, FD_READ, 0, 0);
1768 return length;
1770 SetLastError(wsaErrno());
1771 close(fd);
1773 else SetLastError(WSAENOTSOCK);
1774 WARN(" -> ERROR\n");
1775 return SOCKET_ERROR;
1778 /***********************************************************************
1779 * recv() (WINSOCK.16)
1781 INT16 WINAPI WINSOCK_recv16(SOCKET16 s, char *buf, INT16 len, INT16 flags)
1783 return (INT16)WSOCK32_recv( s, buf, len, flags );
1787 /***********************************************************************
1788 * recvfrom() (WSOCK32.17)
1790 INT WINAPI WSOCK32_recvfrom(SOCKET s, char *buf, INT len, INT flags,
1791 struct sockaddr *from, INT *fromlen32)
1793 LPWSINFO pwsi = WINSOCK_GetIData();
1794 #ifdef HAVE_IPX
1795 struct ws_sockaddr_ipx* from2 = (struct ws_sockaddr_ipx *)from;
1796 #endif
1798 TRACE("(%08x): socket %04x, ptr %08x, "
1799 "len %d, flags %d\n", (unsigned)pwsi, s, (unsigned)buf,
1800 len, flags);
1801 #if DEBUG_SOCKADDR
1802 if( from ) dump_sockaddr(from);
1803 else DPRINTF("from = NULL\n");
1804 #endif
1806 if( _check_ws(pwsi, s) )
1808 int fd = _get_sock_fd(s);
1809 int length;
1811 if (_is_blocking(s))
1813 /* block here */
1814 /* FIXME: OOB and exceptfds */
1815 do_block(fd, 1);
1817 if ((length = recvfrom(fd, buf, len, flags, from, fromlen32)) >= 0)
1819 TRACE(" -> %i bytes\n", length);
1821 #ifdef HAVE_IPX
1822 if (from && ((struct sockaddr_ipx *)from)->sipx_family == AF_IPX) {
1823 from = (struct sockaddr *)
1824 malloc(fromlen32 ? *fromlen32 : sizeof(*from2));
1825 memcpy(from, from2, fromlen32 ? *fromlen32 : sizeof(*from2));
1826 from2->sipx_family = WS_AF_IPX;
1827 from2->sipx_network = ((struct sockaddr_ipx *)from)->sipx_network;
1828 from2->sipx_port = ((struct sockaddr_ipx *)from)->sipx_port;
1829 memcpy(from2->sipx_node,
1830 ((struct sockaddr_ipx *)from)->sipx_node, IPX_NODE_LEN);
1831 free(from);
1833 #endif
1834 close(fd);
1835 _enable_event(s, FD_READ, 0, 0);
1836 return (INT16)length;
1838 SetLastError(wsaErrno());
1839 close(fd);
1841 else SetLastError(WSAENOTSOCK);
1842 WARN(" -> ERROR\n");
1843 #ifdef HAVE_IPX
1844 if (from && ((struct sockaddr_ipx *)from)->sipx_family == AF_IPX) {
1845 from = (struct sockaddr *)
1846 malloc(fromlen32 ? *fromlen32 : sizeof(*from2));
1847 memcpy(from, from2, fromlen32 ? *fromlen32 : sizeof(*from2));
1848 from2->sipx_family = WS_AF_IPX;
1849 from2->sipx_network = ((struct sockaddr_ipx *)from)->sipx_network;
1850 from2->sipx_port = ((struct sockaddr_ipx *)from)->sipx_port;
1851 memcpy(from2->sipx_node,
1852 ((struct sockaddr_ipx *)from)->sipx_node, IPX_NODE_LEN);
1853 free(from);
1855 #endif
1856 return SOCKET_ERROR;
1859 /***********************************************************************
1860 * recvfrom() (WINSOCK.17)
1862 INT16 WINAPI WINSOCK_recvfrom16(SOCKET16 s, char *buf, INT16 len, INT16 flags,
1863 struct sockaddr *from, INT16 *fromlen16)
1865 INT fromlen32;
1866 INT *p = &fromlen32;
1867 INT retVal;
1869 if( fromlen16 ) fromlen32 = *fromlen16; else p = NULL;
1870 retVal = WSOCK32_recvfrom( s, buf, len, flags, from, p );
1871 if( fromlen16 ) *fromlen16 = fromlen32;
1872 return (INT16)retVal;
1875 /***********************************************************************
1876 * select() (WINSOCK.18)(WSOCK32.18)
1878 static INT __ws_select( BOOL b32, void *ws_readfds, void *ws_writefds, void *ws_exceptfds,
1879 struct timeval *timeout )
1881 LPWSINFO pwsi = WINSOCK_GetIData();
1883 TRACE("(%08x): read %8x, write %8x, excp %8x\n",
1884 (unsigned) pwsi, (unsigned) ws_readfds, (unsigned) ws_writefds, (unsigned) ws_exceptfds);
1886 if( pwsi )
1888 int highfd = 0;
1889 fd_set readfds, writefds, exceptfds;
1890 fd_set *p_read, *p_write, *p_except;
1891 int readfd[FD_SETSIZE], writefd[FD_SETSIZE], exceptfd[FD_SETSIZE];
1893 p_read = fd_set_import(&readfds, pwsi, ws_readfds, &highfd, readfd, b32);
1894 p_write = fd_set_import(&writefds, pwsi, ws_writefds, &highfd, writefd, b32);
1895 p_except = fd_set_import(&exceptfds, pwsi, ws_exceptfds, &highfd, exceptfd, b32);
1897 if( (highfd = select(highfd + 1, p_read, p_write, p_except, timeout)) > 0 )
1899 fd_set_export(pwsi, &readfds, p_except, ws_readfds, readfd, b32);
1900 fd_set_export(pwsi, &writefds, p_except, ws_writefds, writefd, b32);
1902 if (p_except && ws_exceptfds)
1904 #define wsfds16 ((ws_fd_set16*)ws_exceptfds)
1905 #define wsfds32 ((ws_fd_set32*)ws_exceptfds)
1906 int i, j, count = (b32) ? wsfds32->fd_count : wsfds16->fd_count;
1908 for (i = j = 0; i < count; i++)
1910 int fd = exceptfd[i];
1911 if( fd >= 0 && FD_ISSET(fd, &exceptfds) )
1913 if( b32 )
1914 wsfds32->fd_array[j++] = wsfds32->fd_array[i];
1915 else
1916 wsfds16->fd_array[j++] = wsfds16->fd_array[i];
1918 if( fd >= 0 ) close(fd);
1919 exceptfd[i] = -1;
1921 if( b32 )
1922 wsfds32->fd_count = j;
1923 else
1924 wsfds16->fd_count = j;
1925 #undef wsfds32
1926 #undef wsfds16
1928 return highfd;
1930 fd_set_unimport(ws_readfds, readfd, b32);
1931 fd_set_unimport(ws_writefds, writefd, b32);
1932 fd_set_unimport(ws_exceptfds, exceptfd, b32);
1933 if( ws_readfds ) ((ws_fd_set32*)ws_readfds)->fd_count = 0;
1934 if( ws_writefds ) ((ws_fd_set32*)ws_writefds)->fd_count = 0;
1935 if( ws_exceptfds ) ((ws_fd_set32*)ws_exceptfds)->fd_count = 0;
1937 if( highfd == 0 ) return 0;
1938 SetLastError(wsaErrno());
1940 return SOCKET_ERROR;
1943 INT16 WINAPI WINSOCK_select16(INT16 nfds, ws_fd_set16 *ws_readfds,
1944 ws_fd_set16 *ws_writefds, ws_fd_set16 *ws_exceptfds,
1945 struct timeval *timeout)
1947 return (INT16)__ws_select( FALSE, ws_readfds, ws_writefds, ws_exceptfds, timeout );
1950 INT WINAPI WSOCK32_select(INT nfds, ws_fd_set32 *ws_readfds,
1951 ws_fd_set32 *ws_writefds, ws_fd_set32 *ws_exceptfds,
1952 struct timeval *timeout)
1954 /* struct timeval is the same for both 32- and 16-bit code */
1955 return (INT)__ws_select( TRUE, ws_readfds, ws_writefds, ws_exceptfds, timeout );
1959 /***********************************************************************
1960 * send() (WSOCK32.19)
1962 INT WINAPI WSOCK32_send(SOCKET s, char *buf, INT len, INT flags)
1964 LPWSINFO pwsi = WINSOCK_GetIData();
1966 TRACE("(%08x): socket %04x, ptr %08x, length %d, flags %d\n",
1967 (unsigned)pwsi, s, (unsigned) buf, len, flags);
1968 if( _check_ws(pwsi, s) )
1970 int fd = _get_sock_fd(s);
1971 int length;
1973 if (_is_blocking(s))
1975 /* block here */
1976 /* FIXME: exceptfds */
1977 do_block(fd, 2);
1979 if ((length = send(fd, buf, len, flags)) < 0 )
1981 SetLastError(wsaErrno());
1982 if( GetLastError() == WSAEWOULDBLOCK )
1983 _enable_event(s, FD_WRITE, 0, 0);
1985 else
1987 close(fd);
1988 return (INT16)length;
1990 close(fd);
1992 else SetLastError(WSAENOTSOCK);
1993 return SOCKET_ERROR;
1996 /***********************************************************************
1997 * send() (WINSOCK.19)
1999 INT16 WINAPI WINSOCK_send16(SOCKET16 s, char *buf, INT16 len, INT16 flags)
2001 return WSOCK32_send( s, buf, len, flags );
2004 /***********************************************************************
2005 * sendto() (WSOCK32.20)
2007 INT WINAPI WSOCK32_sendto(SOCKET s, char *buf, INT len, INT flags,
2008 struct sockaddr *to, INT tolen)
2010 LPWSINFO pwsi = WINSOCK_GetIData();
2011 #ifdef HAVE_IPX
2012 struct ws_sockaddr_ipx* to2 = (struct ws_sockaddr_ipx *)to;
2013 #endif
2015 TRACE("(%08x): socket %04x, ptr %08x, length %d, flags %d\n",
2016 (unsigned)pwsi, s, (unsigned) buf, len, flags);
2017 if( _check_ws(pwsi, s) )
2019 int fd = _get_sock_fd(s);
2020 INT length;
2022 if (to && ((struct ws_sockaddr_ipx *)to)->sipx_family == WS_AF_PUP)
2023 ((struct ws_sockaddr_ipx *)to)->sipx_family = AF_UNSPEC;
2024 #ifdef HAVE_IPX
2025 else if (to &&
2026 ((struct ws_sockaddr_ipx *)to)->sipx_family == WS_AF_IPX)
2028 to = (struct sockaddr *) malloc(sizeof(struct sockaddr_ipx));
2029 memset(to, '\0', sizeof(struct sockaddr_ipx));
2030 ((struct sockaddr_ipx *)to)->sipx_family = AF_IPX;
2031 ((struct sockaddr_ipx *)to)->sipx_port = to2->sipx_port;
2032 ((struct sockaddr_ipx *)to)->sipx_network = to2->sipx_network;
2033 memcpy(((struct sockaddr_ipx *)to)->sipx_node,
2034 to2->sipx_node, IPX_NODE_LEN);
2035 tolen = sizeof(struct sockaddr_ipx);
2037 #endif
2038 if (_is_blocking(s))
2040 /* block here */
2041 /* FIXME: exceptfds */
2042 do_block(fd, 2);
2044 if ((length = sendto(fd, buf, len, flags, to, tolen)) < 0 )
2046 SetLastError(wsaErrno());
2047 if( GetLastError() == WSAEWOULDBLOCK )
2048 _enable_event(s, FD_WRITE, 0, 0);
2050 else {
2051 #ifdef HAVE_IPX
2052 if (to && ((struct sockaddr_ipx *)to)->sipx_family == AF_IPX) {
2053 free(to);
2055 #endif
2056 close(fd);
2057 return length;
2059 close(fd);
2061 else SetLastError(WSAENOTSOCK);
2062 #ifdef HAVE_IPX
2063 if (to && ((struct sockaddr_ipx *)to)->sipx_family == AF_IPX) {
2064 free(to);
2066 #endif
2067 return SOCKET_ERROR;
2070 /***********************************************************************
2071 * sendto() (WINSOCK.20)
2073 INT16 WINAPI WINSOCK_sendto16(SOCKET16 s, char *buf, INT16 len, INT16 flags,
2074 struct sockaddr *to, INT16 tolen)
2076 return (INT16)WSOCK32_sendto( s, buf, len, flags, to, tolen );
2079 /***********************************************************************
2080 * setsockopt() (WSOCK32.21)
2082 INT WINAPI WSOCK32_setsockopt(SOCKET16 s, INT level, INT optname,
2083 char *optval, INT optlen)
2085 LPWSINFO pwsi = WINSOCK_GetIData();
2087 TRACE("(%08x): socket %04x, lev %d, opt 0x%x, ptr %08x, len %d\n",
2088 (unsigned)pwsi, s, level, optname, (int) optval, optlen);
2089 if( _check_ws(pwsi, s) )
2091 struct linger linger;
2092 int fd = _get_sock_fd(s);
2093 int woptval;
2095 if(optname == WS_SO_DONTLINGER) {
2096 /* This is unique to WinSock and takes special conversion */
2097 linger.l_onoff = *((int*)optval) ? 0: 1;
2098 linger.l_linger = 0;
2099 optname=SO_LINGER;
2100 optval = (char*)&linger;
2101 optlen = sizeof(struct linger);
2102 }else{
2103 if (!convert_sockopt(&level, &optname)) {
2104 SetLastError(WSAENOPROTOOPT);
2105 close(fd);
2106 return SOCKET_ERROR;
2109 if (optname == SO_LINGER && optval) {
2110 /* yes, uses unsigned short in both win16/win32 */
2111 linger.l_onoff = ((UINT16*)optval)[0];
2112 linger.l_linger = ((UINT16*)optval)[1];
2113 /* FIXME: what is documented behavior if SO_LINGER optval
2114 is null?? */
2115 optval = (char*)&linger;
2116 optlen = sizeof(struct linger);
2117 } else if (optlen < sizeof(int)){
2118 woptval= *((INT16 *) optval);
2119 optval= (char*) &woptval;
2120 optlen=sizeof(int);
2122 if(optname == SO_RCVBUF && *(int*)optval < 2048) {
2123 WARN("SO_RCVBF for %d bytes is too small: ignored\n", *(int*)optval );
2124 close( fd);
2125 return 0;
2128 if (setsockopt(fd, level, optname, optval, optlen) == 0)
2130 close(fd);
2131 return 0;
2133 SetLastError(wsaErrno());
2134 close(fd);
2136 else SetLastError(WSAENOTSOCK);
2137 return SOCKET_ERROR;
2140 /***********************************************************************
2141 * setsockopt() (WINSOCK.21)
2143 INT16 WINAPI WINSOCK_setsockopt16(SOCKET16 s, INT16 level, INT16 optname,
2144 char *optval, INT16 optlen)
2146 if( !optval ) return SOCKET_ERROR;
2147 return (INT16)WSOCK32_setsockopt( s, (UINT16)level, optname, optval, optlen );
2151 /***********************************************************************
2152 * shutdown() (WSOCK32.22)
2154 INT WINAPI WSOCK32_shutdown(SOCKET s, INT how)
2156 LPWSINFO pwsi = WINSOCK_GetIData();
2158 TRACE("(%08x): socket %04x, how %i\n",
2159 (unsigned)pwsi, s, how );
2160 if( _check_ws(pwsi, s) )
2162 int fd = _get_sock_fd(s);
2163 switch( how )
2165 case 0: /* drop receives */
2166 _enable_event(s, 0, 0, WS_FD_READ);
2167 #ifdef SHUT_RD
2168 how = SHUT_RD;
2169 #endif
2170 break;
2172 case 1: /* drop sends */
2173 _enable_event(s, 0, 0, WS_FD_WRITE);
2174 #ifdef SHUT_WR
2175 how = SHUT_WR;
2176 #endif
2177 break;
2179 case 2: /* drop all */
2180 #ifdef SHUT_RDWR
2181 how = SHUT_RDWR;
2182 #endif
2183 default:
2184 WSAAsyncSelect( s, 0, 0, 0 );
2185 break;
2188 if (shutdown(fd, how) == 0)
2190 if( how > 1 )
2192 _enable_event(s, 0, 0, WS_FD_CONNECTED|WS_FD_LISTENING);
2194 close(fd);
2195 return 0;
2197 SetLastError(wsaErrno());
2198 close(fd);
2200 else SetLastError(WSAENOTSOCK);
2201 return SOCKET_ERROR;
2204 /***********************************************************************
2205 * shutdown() (WINSOCK.22)
2207 INT16 WINAPI WINSOCK_shutdown16(SOCKET16 s, INT16 how)
2209 return (INT16)WSOCK32_shutdown( s, how );
2213 /***********************************************************************
2214 * socket() (WSOCK32.23)
2216 SOCKET WINAPI WSOCK32_socket(INT af, INT type, INT protocol)
2218 LPWSINFO pwsi = WINSOCK_GetIData();
2219 SOCKET ret;
2221 TRACE("(%08x): af=%d type=%d protocol=%d\n",
2222 (unsigned)pwsi, af, type, protocol);
2224 if( pwsi )
2226 /* check the socket family */
2227 switch(af)
2229 #ifdef HAVE_IPX
2230 case WS_AF_IPX: af = AF_IPX;
2231 #endif
2232 case AF_INET:
2233 case AF_UNSPEC: break;
2234 default: SetLastError(WSAEAFNOSUPPORT);
2235 return INVALID_SOCKET;
2238 /* check the socket type */
2239 switch(type)
2241 case SOCK_STREAM:
2242 case SOCK_DGRAM:
2243 case SOCK_RAW: break;
2244 default: SetLastError(WSAESOCKTNOSUPPORT);
2245 return INVALID_SOCKET;
2248 /* check the protocol type */
2249 if ( protocol < 0 ) /* don't support negative values */
2250 { SetLastError(WSAEPROTONOSUPPORT); return INVALID_SOCKET; }
2252 if ( af == AF_UNSPEC) /* did they not specify the address family? */
2253 switch(protocol)
2255 case IPPROTO_TCP:
2256 if (type == SOCK_STREAM) { af = AF_INET; break; }
2257 case IPPROTO_UDP:
2258 if (type == SOCK_DGRAM) { af = AF_INET; break; }
2259 default: SetLastError(WSAEPROTOTYPE); return INVALID_SOCKET;
2262 SERVER_START_REQ
2264 struct create_socket_request *req = server_alloc_req( sizeof(*req), 0 );
2265 req->family = af;
2266 req->type = type;
2267 req->protocol = protocol;
2268 req->access = GENERIC_READ|GENERIC_WRITE|SYNCHRONIZE;
2269 req->inherit = TRUE;
2270 sock_server_call( REQ_CREATE_SOCKET );
2271 ret = req->handle;
2273 SERVER_END_REQ;
2274 if ( ((int) ret) >= 0)
2276 TRACE("\tcreated %04x\n", ret );
2277 return ret;
2280 if (GetLastError() == WSAEACCES) /* raw socket denied */
2282 if (type == SOCK_RAW)
2283 MESSAGE("WARNING: Trying to create a socket of type SOCK_RAW, will fail unless running as root\n");
2284 else
2285 MESSAGE("WS_SOCKET: not enough privileges to create socket, try running as root\n");
2286 SetLastError(WSAESOCKTNOSUPPORT);
2290 WARN("\t\tfailed!\n");
2291 return INVALID_SOCKET;
2294 /***********************************************************************
2295 * socket() (WINSOCK.23)
2297 SOCKET16 WINAPI WINSOCK_socket16(INT16 af, INT16 type, INT16 protocol)
2299 return (SOCKET16)WSOCK32_socket( af, type, protocol );
2303 /* ----------------------------------- DNS services
2305 * IMPORTANT: 16-bit API structures have SEGPTR pointers inside them.
2306 * Also, we have to use wsock32 stubs to convert structures and
2307 * error codes from Unix to WSA, hence there is no direct mapping in
2308 * the relay32/wsock32.spec.
2311 static char* NULL_STRING = "NULL";
2313 /***********************************************************************
2314 * gethostbyaddr() (WINSOCK.51)(WSOCK32.51)
2316 static WIN_hostent* __ws_gethostbyaddr(const char *addr, int len, int type, int dup_flag)
2318 WIN_hostent *retval = NULL;
2319 LPWSINFO pwsi = WINSOCK_GetIData();
2321 if( pwsi )
2323 struct hostent* host;
2324 #if HAVE_LINUX_GETHOSTBYNAME_R_6
2325 char *extrabuf;
2326 int ebufsize=1024;
2327 struct hostent hostentry;
2328 int locerr=ENOBUFS;
2329 host = NULL;
2330 extrabuf=HeapAlloc(GetProcessHeap(),0,ebufsize) ;
2331 while(extrabuf) {
2332 int res = gethostbyaddr_r(addr, len, type,
2333 &hostentry, extrabuf, ebufsize, &host, &locerr);
2334 if( res != ERANGE) break;
2335 ebufsize *=2;
2336 extrabuf=HeapReAlloc(GetProcessHeap(),0,extrabuf,ebufsize) ;
2338 if (!host) SetLastError((locerr < 0) ? wsaErrno() : wsaHerrno(locerr));
2339 #else
2340 EnterCriticalSection( &csWSgetXXXbyYYY );
2341 host = gethostbyaddr(addr, len, type);
2342 if (!host) SetLastError((h_errno < 0) ? wsaErrno() : wsaHerrno(h_errno));
2343 #endif
2344 if( host != NULL )
2346 if( WS_dup_he(pwsi, host, dup_flag) )
2347 retval = (WIN_hostent*)(pwsi->he);
2348 else
2349 SetLastError(WSAENOBUFS);
2351 #ifdef HAVE_LINUX_GETHOSTBYNAME_R_6
2352 HeapFree(GetProcessHeap(),0,extrabuf);
2353 #else
2354 LeaveCriticalSection( &csWSgetXXXbyYYY );
2355 #endif
2357 return retval;
2360 SEGPTR WINAPI WINSOCK_gethostbyaddr16(const char *addr, INT16 len, INT16 type)
2362 WIN_hostent* retval;
2363 TRACE("ptr %08x, len %d, type %d\n",
2364 (unsigned) addr, len, type);
2365 retval = __ws_gethostbyaddr( addr, len, type, WS_DUP_SEGPTR );
2366 return retval ? SEGPTR_GET(retval) : ((SEGPTR)NULL);
2369 WIN_hostent* WINAPI WSOCK32_gethostbyaddr(const char *addr, INT len,
2370 INT type)
2372 TRACE("ptr %08x, len %d, type %d\n",
2373 (unsigned) addr, len, type);
2374 return __ws_gethostbyaddr(addr, len, type, WS_DUP_LINEAR);
2377 /***********************************************************************
2378 * gethostbyname() (WINSOCK.52)(WSOCK32.52)
2380 static WIN_hostent * __ws_gethostbyname(const char *name, int dup_flag)
2382 WIN_hostent *retval = NULL;
2383 LPWSINFO pwsi = WINSOCK_GetIData();
2385 if( pwsi )
2387 struct hostent* host;
2388 #ifdef HAVE_LINUX_GETHOSTBYNAME_R_6
2389 char *extrabuf;
2390 int ebufsize=1024;
2391 struct hostent hostentry;
2392 int locerr = ENOBUFS;
2393 host = NULL;
2394 extrabuf=HeapAlloc(GetProcessHeap(),0,ebufsize) ;
2395 while(extrabuf) {
2396 int res = gethostbyname_r(name, &hostentry, extrabuf, ebufsize, &host, &locerr);
2397 if( res != ERANGE) break;
2398 ebufsize *=2;
2399 extrabuf=HeapReAlloc(GetProcessHeap(),0,extrabuf,ebufsize) ;
2401 if (!host) SetLastError((locerr < 0) ? wsaErrno() : wsaHerrno(locerr));
2402 #else
2403 EnterCriticalSection( &csWSgetXXXbyYYY );
2404 host = gethostbyname(name);
2405 if (!host) SetLastError((h_errno < 0) ? wsaErrno() : wsaHerrno(h_errno));
2406 #endif
2407 if( host != NULL )
2409 if( WS_dup_he(pwsi, host, dup_flag) )
2410 retval = (WIN_hostent*)(pwsi->he);
2411 else SetLastError(WSAENOBUFS);
2413 #ifdef HAVE_LINUX_GETHOSTBYNAME_R_6
2414 HeapFree(GetProcessHeap(),0,extrabuf);
2415 #else
2416 LeaveCriticalSection( &csWSgetXXXbyYYY );
2417 #endif
2419 return retval;
2422 SEGPTR WINAPI WINSOCK_gethostbyname16(const char *name)
2424 WIN_hostent* retval;
2425 TRACE("%s\n", (name)?name:NULL_STRING);
2426 retval = __ws_gethostbyname( name, WS_DUP_SEGPTR );
2427 return (retval)? SEGPTR_GET(retval) : ((SEGPTR)NULL) ;
2430 WIN_hostent* WINAPI WSOCK32_gethostbyname(const char* name)
2432 TRACE("%s\n", (name)?name:NULL_STRING);
2433 return __ws_gethostbyname( name, WS_DUP_LINEAR );
2437 /***********************************************************************
2438 * getprotobyname() (WINSOCK.53)(WSOCK32.53)
2440 static WIN_protoent* __ws_getprotobyname(const char *name, int dup_flag)
2442 WIN_protoent* retval = NULL;
2443 LPWSINFO pwsi = WINSOCK_GetIData();
2445 if( pwsi )
2447 struct protoent* proto;
2448 EnterCriticalSection( &csWSgetXXXbyYYY );
2449 if( (proto = getprotobyname(name)) != NULL )
2451 if( WS_dup_pe(pwsi, proto, dup_flag) )
2452 retval = (WIN_protoent*)(pwsi->pe);
2453 else SetLastError(WSAENOBUFS);
2455 else {
2456 MESSAGE("protocol %s not found; You might want to add "
2457 "this to /etc/protocols\n", debugstr_a(name) );
2458 SetLastError(WSANO_DATA);
2460 LeaveCriticalSection( &csWSgetXXXbyYYY );
2461 } else SetLastError(WSANOTINITIALISED);
2462 return retval;
2465 SEGPTR WINAPI WINSOCK_getprotobyname16(const char *name)
2467 WIN_protoent* retval;
2468 TRACE("%s\n", (name)?name:NULL_STRING);
2469 retval = __ws_getprotobyname(name, WS_DUP_SEGPTR);
2470 return retval ? SEGPTR_GET(retval) : ((SEGPTR)NULL);
2473 WIN_protoent* WINAPI WSOCK32_getprotobyname(const char* name)
2475 TRACE("%s\n", (name)?name:NULL_STRING);
2476 return __ws_getprotobyname(name, WS_DUP_LINEAR);
2480 /***********************************************************************
2481 * getprotobynumber() (WINSOCK.54)(WSOCK32.54)
2483 static WIN_protoent* __ws_getprotobynumber(int number, int dup_flag)
2485 WIN_protoent* retval = NULL;
2486 LPWSINFO pwsi = WINSOCK_GetIData();
2488 if( pwsi )
2490 struct protoent* proto;
2491 EnterCriticalSection( &csWSgetXXXbyYYY );
2492 if( (proto = getprotobynumber(number)) != NULL )
2494 if( WS_dup_pe(pwsi, proto, dup_flag) )
2495 retval = (WIN_protoent*)(pwsi->pe);
2496 else SetLastError(WSAENOBUFS);
2498 else {
2499 MESSAGE("protocol number %d not found; You might want to add "
2500 "this to /etc/protocols\n", number );
2501 SetLastError(WSANO_DATA);
2503 LeaveCriticalSection( &csWSgetXXXbyYYY );
2504 } else SetLastError(WSANOTINITIALISED);
2505 return retval;
2508 SEGPTR WINAPI WINSOCK_getprotobynumber16(INT16 number)
2510 WIN_protoent* retval;
2511 TRACE("%i\n", number);
2512 retval = __ws_getprotobynumber(number, WS_DUP_SEGPTR);
2513 return retval ? SEGPTR_GET(retval) : ((SEGPTR)NULL);
2516 WIN_protoent* WINAPI WSOCK32_getprotobynumber(INT number)
2518 TRACE("%i\n", number);
2519 return __ws_getprotobynumber(number, WS_DUP_LINEAR);
2523 /***********************************************************************
2524 * getservbyname() (WINSOCK.55)(WSOCK32.55)
2526 static WIN_servent* __ws_getservbyname(const char *name, const char *proto, int dup_flag)
2528 WIN_servent* retval = NULL;
2529 LPWSINFO pwsi = WINSOCK_GetIData();
2531 if( pwsi )
2533 struct servent* serv;
2534 int i = wsi_strtolo( pwsi, name, proto );
2536 if( i ) {
2537 EnterCriticalSection( &csWSgetXXXbyYYY );
2538 serv = getservbyname(pwsi->buffer,
2539 proto ? (pwsi->buffer + i) : NULL);
2540 if( serv != NULL )
2542 if( WS_dup_se(pwsi, serv, dup_flag) )
2543 retval = (WIN_servent*)(pwsi->se);
2544 else SetLastError(WSAENOBUFS);
2546 else {
2547 MESSAGE("service %s protocol %s not found; You might want to add "
2548 "this to /etc/services\n", debugstr_a(pwsi->buffer),
2549 proto ? debugstr_a(pwsi->buffer+i):"*");
2550 SetLastError(WSANO_DATA);
2552 LeaveCriticalSection( &csWSgetXXXbyYYY );
2554 else SetLastError(WSAENOBUFS);
2555 } else SetLastError(WSANOTINITIALISED);
2556 return retval;
2559 SEGPTR WINAPI WINSOCK_getservbyname16(const char *name, const char *proto)
2561 WIN_servent* retval;
2562 TRACE("'%s', '%s'\n",
2563 (name)?name:NULL_STRING, (proto)?proto:NULL_STRING);
2564 retval = __ws_getservbyname(name, proto, WS_DUP_SEGPTR);
2565 return retval ? SEGPTR_GET(retval) : ((SEGPTR)NULL);
2568 WIN_servent* WINAPI WSOCK32_getservbyname(const char *name, const char *proto)
2570 TRACE("'%s', '%s'\n",
2571 (name)?name:NULL_STRING, (proto)?proto:NULL_STRING);
2572 return __ws_getservbyname(name, proto, WS_DUP_LINEAR);
2576 /***********************************************************************
2577 * getservbyport() (WINSOCK.56)(WSOCK32.56)
2579 static WIN_servent* __ws_getservbyport(int port, const char* proto, int dup_flag)
2581 WIN_servent* retval = NULL;
2582 LPWSINFO pwsi = WINSOCK_GetIData();
2584 if( pwsi )
2586 struct servent* serv;
2587 if (!proto || wsi_strtolo( pwsi, proto, NULL )) {
2588 EnterCriticalSection( &csWSgetXXXbyYYY );
2589 if( (serv = getservbyport(port, (proto) ? pwsi->buffer : NULL)) != NULL ) {
2590 if( WS_dup_se(pwsi, serv, dup_flag) )
2591 retval = (WIN_servent*)(pwsi->se);
2592 else SetLastError(WSAENOBUFS);
2594 else {
2595 MESSAGE("service on port %lu protocol %s not found; You might want to add "
2596 "this to /etc/services\n", (unsigned long)ntohl(port),
2597 proto ? debugstr_a(pwsi->buffer) : "*");
2598 SetLastError(WSANO_DATA);
2600 LeaveCriticalSection( &csWSgetXXXbyYYY );
2602 else SetLastError(WSAENOBUFS);
2603 } else SetLastError(WSANOTINITIALISED);
2604 return retval;
2607 SEGPTR WINAPI WINSOCK_getservbyport16(INT16 port, const char *proto)
2609 WIN_servent* retval;
2610 TRACE("%d (i.e. port %d), '%s'\n",
2611 (int)port, (int)ntohl(port), (proto)?proto:NULL_STRING);
2612 retval = __ws_getservbyport(port, proto, WS_DUP_SEGPTR);
2613 return retval ? SEGPTR_GET(retval) : ((SEGPTR)NULL);
2616 WIN_servent* WINAPI WSOCK32_getservbyport(INT port, const char *proto)
2618 TRACE("%d (i.e. port %d), '%s'\n",
2619 (int)port, (int)ntohl(port), (proto)?proto:NULL_STRING);
2620 return __ws_getservbyport(port, proto, WS_DUP_LINEAR);
2624 /***********************************************************************
2625 * gethostname() (WSOCK32.57)
2627 INT WINAPI WSOCK32_gethostname(char *name, INT namelen)
2629 LPWSINFO pwsi = WINSOCK_GetIData();
2631 TRACE("(%08x): name %s, len %d\n",
2632 (unsigned)pwsi, (name)?name:NULL_STRING, namelen);
2633 if( pwsi )
2635 if (gethostname(name, namelen) == 0) return 0;
2636 SetLastError((errno == EINVAL) ? WSAEFAULT : wsaErrno());
2638 return SOCKET_ERROR;
2641 /***********************************************************************
2642 * gethostname() (WINSOCK.57)
2644 INT16 WINAPI WINSOCK_gethostname16(char *name, INT16 namelen)
2646 return (INT16)WSOCK32_gethostname(name, namelen);
2650 /* ------------------------------------- Windows sockets extensions -- *
2652 * ------------------------------------------------------------------- */
2654 /***********************************************************************
2655 * WSAEnumNetworkEvents
2657 int WINAPI WSAEnumNetworkEvents(SOCKET s, WSAEVENT hEvent, LPWSANETWORKEVENTS lpEvent)
2659 LPWSINFO pwsi = WINSOCK_GetIData();
2661 TRACE("(%08x): %08x, hEvent %08x, lpEvent %08x\n",
2662 (unsigned)pwsi, s, hEvent, (unsigned)lpEvent );
2663 if( _check_ws(pwsi, s) )
2665 SERVER_START_REQ
2667 struct get_socket_event_request *req = server_alloc_req( sizeof(*req),
2668 sizeof(lpEvent->iErrorCode) );
2669 req->handle = s;
2670 req->service = TRUE;
2671 req->s_event = 0;
2672 req->c_event = hEvent;
2673 sock_server_call( REQ_GET_SOCKET_EVENT );
2674 lpEvent->lNetworkEvents = req->pmask;
2675 memcpy(lpEvent->iErrorCode, server_data_ptr(req), server_data_size(req) );
2677 SERVER_END_REQ;
2678 return 0;
2680 else SetLastError(WSAEINVAL);
2681 return SOCKET_ERROR;
2684 /***********************************************************************
2685 * WSAEventSelect
2687 int WINAPI WSAEventSelect(SOCKET s, WSAEVENT hEvent, LONG lEvent)
2689 LPWSINFO pwsi = WINSOCK_GetIData();
2691 TRACE("(%08x): %08x, hEvent %08x, event %08x\n",
2692 (unsigned)pwsi, s, hEvent, (unsigned)lEvent );
2693 if( _check_ws(pwsi, s) )
2695 SERVER_START_REQ
2697 struct set_socket_event_request *req = server_alloc_req( sizeof(*req), 0 );
2698 req->handle = s;
2699 req->mask = lEvent;
2700 req->event = hEvent;
2701 sock_server_call( REQ_SET_SOCKET_EVENT );
2703 SERVER_END_REQ;
2704 return 0;
2706 else SetLastError(WSAEINVAL);
2707 return SOCKET_ERROR;
2710 /***********************************************************************
2711 * WSAAsyncSelect() (WINSOCK.101)(WSOCK32.101)
2714 VOID CALLBACK WINSOCK_DoAsyncEvent( ULONG_PTR ptr )
2716 ws_select_info *info = (ws_select_info*)ptr;
2717 LPWSINFO pwsi = info->pwsi;
2718 unsigned int i, pmask, orphan = FALSE;
2719 int errors[FD_MAX_EVENTS];
2721 TRACE("socket %08x, event %08x\n", info->sock, info->event);
2722 SetLastError(0);
2723 SERVER_START_REQ
2725 struct get_socket_event_request *req = server_alloc_req( sizeof(*req), sizeof(errors) );
2726 req->handle = info->sock;
2727 req->service = TRUE;
2728 req->s_event = info->event; /* <== avoid race conditions */
2729 req->c_event = info->event;
2730 sock_server_call( REQ_GET_SOCKET_EVENT );
2731 pmask = req->pmask;
2732 memcpy( errors, server_data_ptr(req), server_data_size(req) );
2734 SERVER_END_REQ;
2735 if ( (GetLastError() == WSAENOTSOCK) || (GetLastError() == WSAEINVAL) )
2737 /* orphaned event (socket closed or something) */
2738 pmask = WS_FD_SERVEVENT;
2739 orphan = TRUE;
2742 /* check for accepted sockets that needs to inherit WSAAsyncSelect */
2743 if (pmask & WS_FD_SERVEVENT) {
2744 int q;
2745 for (q=0; q<WS_ACCEPT_QUEUE; q++)
2746 if (pwsi->accept_old[q] == info->sock) {
2747 /* there's only one service thread per pwsi, no lock necessary */
2748 HANDLE as = pwsi->accept_new[q];
2749 if (as) {
2750 pwsi->accept_new[q] = 0;
2751 pwsi->accept_old[q] = 0;
2752 WSAAsyncSelect(as, info->hWnd, info->uMsg, info->lEvent);
2755 pmask &= ~WS_FD_SERVEVENT;
2757 /* dispatch network events */
2758 for (i=0; i<FD_MAX_EVENTS; i++)
2759 if (pmask & (1<<i)) {
2760 TRACE("post: event bit %d, error %d\n", i, errors[i]);
2761 PostMessageA(info->hWnd, info->uMsg, info->sock,
2762 WSAMAKESELECTREPLY(1<<i, errors[i]));
2764 /* cleanup */
2765 if (orphan)
2767 TRACE("orphaned event, self-destructing\n");
2768 /* SERVICE_Delete closes the event object */
2769 SERVICE_Delete( info->service );
2770 WS_FREE(info);
2774 INT WINAPI WSAAsyncSelect(SOCKET s, HWND hWnd, UINT uMsg, LONG lEvent)
2776 LPWSINFO pwsi = WINSOCK_GetIData();
2778 TRACE("(%08x): %04x, hWnd %04x, uMsg %08x, event %08x\n",
2779 (unsigned)pwsi, (SOCKET16)s, (HWND16)hWnd, uMsg, (unsigned)lEvent );
2780 if( _check_ws(pwsi, s) )
2782 if( lEvent )
2784 ws_select_info *info = (ws_select_info*)WS_ALLOC(sizeof(ws_select_info));
2785 if( info )
2787 HANDLE hObj = CreateEventA( NULL, TRUE, FALSE, NULL );
2788 INT err;
2790 info->sock = s;
2791 info->event = hObj;
2792 info->hWnd = hWnd;
2793 info->uMsg = uMsg;
2794 info->lEvent = lEvent;
2795 info->pwsi = pwsi;
2796 info->service = SERVICE_AddObject( hObj, WINSOCK_DoAsyncEvent, (ULONG_PTR)info );
2798 err = WSAEventSelect( s, hObj, lEvent | WS_FD_SERVEVENT );
2799 if (err) {
2800 /* SERVICE_Delete closes the event object */
2801 SERVICE_Delete( info->service );
2802 WS_FREE(info);
2803 return err;
2806 return 0; /* success */
2808 else SetLastError(WSAENOBUFS);
2810 else
2812 WSAEventSelect(s, 0, 0);
2813 return 0;
2816 else SetLastError(WSAEINVAL);
2817 return SOCKET_ERROR;
2820 INT16 WINAPI WSAAsyncSelect16(SOCKET16 s, HWND16 hWnd, UINT16 wMsg, LONG lEvent)
2822 return (INT16)WSAAsyncSelect( s, hWnd, wMsg, lEvent );
2825 /***********************************************************************
2826 * WSARecvEx() (WSOCK32.1107)
2828 * WSARecvEx is a Microsoft specific extension to winsock that is identical to recv
2829 * except that has an in/out argument call flags that has the value MSG_PARTIAL ored
2830 * into the flags parameter when a partial packet is read. This only applies to
2831 * sockets using the datagram protocol. This method does not seem to be implemented
2832 * correctly by microsoft as the winsock implementation does not set the MSG_PARTIAL
2833 * flag when a fragmented packet arrives.
2835 INT WINAPI WSARecvEx(SOCKET s, char *buf, INT len, INT *flags) {
2836 FIXME("(WSARecvEx) partial packet return value not set \n");
2838 return WSOCK32_recv(s, buf, len, *flags);
2842 /***********************************************************************
2843 * WSARecvEx16() (WINSOCK.1107)
2845 * See description for WSARecvEx()
2847 INT16 WINAPI WSARecvEx16(SOCKET16 s, char *buf, INT16 len, INT16 *flags) {
2848 FIXME("(WSARecvEx16) partial packet return value not set \n");
2850 return WINSOCK_recv16(s, buf, len, *flags);
2854 /***********************************************************************
2855 * WSACreateEvent() (WS2_32.???)
2858 WSAEVENT WINAPI WSACreateEvent(void)
2860 /* Create a manual-reset event, with initial state: unsignealed */
2861 TRACE("\n");
2863 return CreateEventA(NULL, TRUE, FALSE, NULL);
2866 /***********************************************************************
2867 * WSACloseEvent() (WS2_32.???)
2870 BOOL WINAPI WSACloseEvent(WSAEVENT event)
2872 TRACE ("event=0x%x\n", event);
2874 return CloseHandle(event);
2877 /***********************************************************************
2878 * WSASocketA() (WS2_32.???)
2881 SOCKET WINAPI WSASocketA(int af, int type, int protocol,
2882 LPWSAPROTOCOL_INFOA lpProtocolInfo,
2883 GROUP g, DWORD dwFlags)
2886 FIXME: The "advanced" parameters of WSASocketA (lpProtocolInfo,
2887 g, dwFlags) are ignored.
2890 TRACE("af=%d type=%d protocol=%d protocol_info=%p group=%d flags=0x%lx\n",
2891 af, type, protocol, lpProtocolInfo, g, dwFlags );
2893 return ( WSOCK32_socket (af, type, protocol) );
2897 /***********************************************************************
2898 * __WSAFDIsSet() (WINSOCK.151)
2900 INT16 WINAPI __WSAFDIsSet16(SOCKET16 s, ws_fd_set16 *set)
2902 int i = set->fd_count;
2904 TRACE("(%d,%8lx(%i))\n", s,(unsigned long)set, i);
2906 while (i--)
2907 if (set->fd_array[i] == s) return 1;
2908 return 0;
2911 /***********************************************************************
2912 * __WSAFDIsSet() (WSOCK32.151)
2914 INT WINAPI __WSAFDIsSet(SOCKET s, ws_fd_set32 *set)
2916 int i = set->fd_count;
2918 TRACE("(%d,%8lx(%i))\n", s,(unsigned long)set, i);
2920 while (i--)
2921 if (set->fd_array[i] == s) return 1;
2922 return 0;
2925 /***********************************************************************
2926 * WSAIsBlocking() (WINSOCK.114)(WSOCK32.114)
2928 BOOL WINAPI WSAIsBlocking(void)
2930 /* By default WinSock should set all its sockets to non-blocking mode
2931 * and poll in PeekMessage loop when processing "blocking" ones. This
2932 * function is supposed to tell if the program is in this loop. Our
2933 * blocking calls are truly blocking so we always return FALSE.
2935 * Note: It is allowed to call this function without prior WSAStartup().
2938 TRACE("\n");
2939 return FALSE;
2942 /***********************************************************************
2943 * WSACancelBlockingCall() (WINSOCK.113)(WSOCK32.113)
2945 INT WINAPI WSACancelBlockingCall(void)
2947 LPWSINFO pwsi = WINSOCK_GetIData();
2949 TRACE("(%08x)\n", (unsigned)pwsi);
2951 if( pwsi ) return 0;
2952 return SOCKET_ERROR;
2956 /***********************************************************************
2957 * WSASetBlockingHook16() (WINSOCK.109)
2959 FARPROC16 WINAPI WSASetBlockingHook16(FARPROC16 lpBlockFunc)
2961 FARPROC16 prev;
2962 LPWSINFO pwsi = WINSOCK_GetIData();
2964 TRACE("(%08x): hook %08x\n",
2965 (unsigned)pwsi, (unsigned) lpBlockFunc);
2966 if( pwsi )
2968 prev = (FARPROC16)pwsi->blocking_hook;
2969 pwsi->blocking_hook = (DWORD)lpBlockFunc;
2970 pwsi->flags &= ~WSI_BLOCKINGHOOK;
2971 return prev;
2973 return 0;
2977 /***********************************************************************
2978 * WSASetBlockingHook()
2980 FARPROC WINAPI WSASetBlockingHook(FARPROC lpBlockFunc)
2982 FARPROC prev;
2983 LPWSINFO pwsi = WINSOCK_GetIData();
2985 TRACE("(%08x): hook %08x\n",
2986 (unsigned)pwsi, (unsigned) lpBlockFunc);
2987 if( pwsi ) {
2988 prev = (FARPROC)pwsi->blocking_hook;
2989 pwsi->blocking_hook = (DWORD)lpBlockFunc;
2990 pwsi->flags |= WSI_BLOCKINGHOOK;
2991 return prev;
2993 return NULL;
2997 /***********************************************************************
2998 * WSAUnhookBlockingHook16() (WINSOCK.110)
3000 INT16 WINAPI WSAUnhookBlockingHook16(void)
3002 LPWSINFO pwsi = WINSOCK_GetIData();
3004 TRACE("(%08x)\n", (unsigned)pwsi);
3005 if( pwsi ) return (INT16)(pwsi->blocking_hook = 0);
3006 return SOCKET_ERROR;
3010 /***********************************************************************
3011 * WSAUnhookBlockingHook()
3013 INT WINAPI WSAUnhookBlockingHook(void)
3015 LPWSINFO pwsi = WINSOCK_GetIData();
3017 TRACE("(%08x)\n", (unsigned)pwsi);
3018 if( pwsi )
3020 pwsi->blocking_hook = 0;
3021 pwsi->flags &= ~WSI_BLOCKINGHOOK;
3022 return 0;
3024 return SOCKET_ERROR;
3028 /* ----------------------------------- end of API stuff */
3030 /* ----------------------------------- helper functions -
3032 * TODO: Merge WS_dup_..() stuff into one function that
3033 * would operate with a generic structure containing internal
3034 * pointers (via a template of some kind).
3037 static int list_size(char** l, int item_size)
3039 int i,j = 0;
3040 if(l)
3041 { for(i=0;l[i];i++)
3042 j += (item_size) ? item_size : strlen(l[i]) + 1;
3043 j += (i + 1) * sizeof(char*); }
3044 return j;
3047 static int list_dup(char** l_src, char* ref, char* base, int item_size)
3049 /* base is either either equal to ref or 0 or SEGPTR */
3051 char* p = ref;
3052 char** l_to = (char**)ref;
3053 int i,j,k;
3055 for(j=0;l_src[j];j++) ;
3056 p += (j + 1) * sizeof(char*);
3057 for(i=0;i<j;i++)
3058 { l_to[i] = base + (p - ref);
3059 k = ( item_size ) ? item_size : strlen(l_src[i]) + 1;
3060 memcpy(p, l_src[i], k); p += k; }
3061 l_to[i] = NULL;
3062 return (p - ref);
3065 /* ----- hostent */
3067 static int hostent_size(struct hostent* p_he)
3069 int size = 0;
3070 if( p_he )
3071 { size = sizeof(struct hostent);
3072 size += strlen(p_he->h_name) + 1;
3073 size += list_size(p_he->h_aliases, 0);
3074 size += list_size(p_he->h_addr_list, p_he->h_length ); }
3075 return size;
3078 /* duplicate hostent entry
3079 * and handle all Win16/Win32 dependent things (struct size, ...) *correctly*.
3080 * Dito for protoent and servent.
3082 int WS_dup_he(LPWSINFO pwsi, struct hostent* p_he, int flag)
3084 /* Convert hostent structure into ws_hostent so that the data fits
3085 * into pwsi->buffer. Internal pointers can be linear, SEGPTR, or
3086 * relative to pwsi->buffer depending on "flag" value. Returns size
3087 * of the data copied (also in the pwsi->buflen).
3090 int size = hostent_size(p_he);
3091 if( size )
3093 char *p_name,*p_aliases,*p_addr,*p_base,*p;
3094 char *p_to;
3095 struct ws_hostent16 *p_to16;
3096 struct ws_hostent32 *p_to32;
3098 _check_buffer_he(pwsi, size);
3099 p_to = (char *)pwsi->he;
3100 p_to16 = (struct ws_hostent16*)pwsi->he;
3101 p_to32 = (struct ws_hostent32*)pwsi->he;
3103 p = p_to;
3104 p_base = (flag & WS_DUP_OFFSET) ? NULL
3105 : ((flag & WS_DUP_SEGPTR) ? (char*)SEGPTR_GET(p) : p);
3106 p += (flag & WS_DUP_SEGPTR) ?
3107 sizeof(struct ws_hostent16) : sizeof(struct ws_hostent32);
3108 p_name = p;
3109 strcpy(p, p_he->h_name); p += strlen(p) + 1;
3110 p_aliases = p;
3111 p += list_dup(p_he->h_aliases, p, p_base + (p - p_to), 0);
3112 p_addr = p;
3113 list_dup(p_he->h_addr_list, p, p_base + (p - p_to), p_he->h_length);
3115 if (flag & WS_DUP_SEGPTR) /* Win16 */
3117 p_to16->h_addrtype = (INT16)p_he->h_addrtype;
3118 p_to16->h_length = (INT16)p_he->h_length;
3119 p_to16->h_name = (SEGPTR)(p_base + (p_name - p_to));
3120 p_to16->h_aliases = (SEGPTR)(p_base + (p_aliases - p_to));
3121 p_to16->h_addr_list = (SEGPTR)(p_base + (p_addr - p_to));
3122 size += (sizeof(struct ws_hostent16) - sizeof(struct hostent));
3124 else /* Win32 */
3126 p_to32->h_addrtype = p_he->h_addrtype;
3127 p_to32->h_length = p_he->h_length;
3128 p_to32->h_name = (p_base + (p_name - p_to));
3129 p_to32->h_aliases = (char **)(p_base + (p_aliases - p_to));
3130 p_to32->h_addr_list = (char **)(p_base + (p_addr - p_to));
3131 size += (sizeof(struct ws_hostent32) - sizeof(struct hostent));
3134 return size;
3137 /* ----- protoent */
3139 static int protoent_size(struct protoent* p_pe)
3141 int size = 0;
3142 if( p_pe )
3143 { size = sizeof(struct protoent);
3144 size += strlen(p_pe->p_name) + 1;
3145 size += list_size(p_pe->p_aliases, 0); }
3146 return size;
3149 int WS_dup_pe(LPWSINFO pwsi, struct protoent* p_pe, int flag)
3151 int size = protoent_size(p_pe);
3152 if( size )
3154 char *p_to;
3155 struct ws_protoent16 *p_to16;
3156 struct ws_protoent32 *p_to32;
3157 char *p_name,*p_aliases,*p_base,*p;
3159 _check_buffer_pe(pwsi, size);
3160 p_to = (char *)pwsi->pe;
3161 p_to16 = (struct ws_protoent16*)pwsi->pe;
3162 p_to32 = (struct ws_protoent32*)pwsi->pe;
3163 p = p_to;
3164 p_base = (flag & WS_DUP_OFFSET) ? NULL
3165 : ((flag & WS_DUP_SEGPTR) ? (char*)SEGPTR_GET(p) : p);
3166 p += (flag & WS_DUP_SEGPTR) ?
3167 sizeof(struct ws_protoent16) : sizeof(struct ws_protoent32);
3168 p_name = p;
3169 strcpy(p, p_pe->p_name); p += strlen(p) + 1;
3170 p_aliases = p;
3171 list_dup(p_pe->p_aliases, p, p_base + (p - p_to), 0);
3173 if (flag & WS_DUP_SEGPTR) /* Win16 */
3175 p_to16->p_proto = (INT16)p_pe->p_proto;
3176 p_to16->p_name = (SEGPTR)(p_base) + (p_name - p_to);
3177 p_to16->p_aliases = (SEGPTR)((p_base) + (p_aliases - p_to));
3178 size += (sizeof(struct ws_protoent16) - sizeof(struct protoent));
3180 else /* Win32 */
3182 p_to32->p_proto = p_pe->p_proto;
3183 p_to32->p_name = (p_base) + (p_name - p_to);
3184 p_to32->p_aliases = (char **)((p_base) + (p_aliases - p_to));
3185 size += (sizeof(struct ws_protoent32) - sizeof(struct protoent));
3188 return size;
3191 /* ----- servent */
3193 static int servent_size(struct servent* p_se)
3195 int size = 0;
3196 if( p_se )
3197 { size += sizeof(struct servent);
3198 size += strlen(p_se->s_proto) + strlen(p_se->s_name) + 2;
3199 size += list_size(p_se->s_aliases, 0); }
3200 return size;
3203 int WS_dup_se(LPWSINFO pwsi, struct servent* p_se, int flag)
3205 int size = servent_size(p_se);
3206 if( size )
3208 char *p_name,*p_aliases,*p_proto,*p_base,*p;
3209 char *p_to;
3210 struct ws_servent16 *p_to16;
3211 struct ws_servent32 *p_to32;
3213 _check_buffer_se(pwsi, size);
3214 p_to = (char *)pwsi->se;
3215 p_to16 = (struct ws_servent16*)pwsi->se;
3216 p_to32 = (struct ws_servent32*)pwsi->se;
3217 p = p_to;
3218 p_base = (flag & WS_DUP_OFFSET) ? NULL
3219 : ((flag & WS_DUP_SEGPTR) ? (char*)SEGPTR_GET(p) : p);
3220 p += (flag & WS_DUP_SEGPTR) ?
3221 sizeof(struct ws_servent16) : sizeof(struct ws_servent32);
3222 p_name = p;
3223 strcpy(p, p_se->s_name); p += strlen(p) + 1;
3224 p_proto = p;
3225 strcpy(p, p_se->s_proto); p += strlen(p) + 1;
3226 p_aliases = p;
3227 list_dup(p_se->s_aliases, p, p_base + (p - p_to), 0);
3229 if (flag & WS_DUP_SEGPTR) /* Win16 */
3231 p_to16->s_port = (INT16)p_se->s_port;
3232 p_to16->s_name = (SEGPTR)(p_base + (p_name - p_to));
3233 p_to16->s_proto = (SEGPTR)(p_base + (p_proto - p_to));
3234 p_to16->s_aliases = (SEGPTR)(p_base + (p_aliases - p_to));
3235 size += (sizeof(struct ws_servent16) - sizeof(struct servent));
3237 else /* Win32 */
3239 p_to32->s_port = p_se->s_port;
3240 p_to32->s_name = (p_base + (p_name - p_to));
3241 p_to32->s_proto = (p_base + (p_proto - p_to));
3242 p_to32->s_aliases = (char **)(p_base + (p_aliases - p_to));
3243 size += (sizeof(struct ws_servent32) - sizeof(struct servent));
3246 return size;
3249 /* ----------------------------------- error handling */
3251 UINT16 wsaErrno(void)
3253 int loc_errno = errno;
3254 WARN("errno %d, (%s).\n", loc_errno, strerror(loc_errno));
3256 switch(loc_errno)
3258 case EINTR: return WSAEINTR;
3259 case EBADF: return WSAEBADF;
3260 case EPERM:
3261 case EACCES: return WSAEACCES;
3262 case EFAULT: return WSAEFAULT;
3263 case EINVAL: return WSAEINVAL;
3264 case EMFILE: return WSAEMFILE;
3265 case EWOULDBLOCK: return WSAEWOULDBLOCK;
3266 case EINPROGRESS: return WSAEINPROGRESS;
3267 case EALREADY: return WSAEALREADY;
3268 case ENOTSOCK: return WSAENOTSOCK;
3269 case EDESTADDRREQ: return WSAEDESTADDRREQ;
3270 case EMSGSIZE: return WSAEMSGSIZE;
3271 case EPROTOTYPE: return WSAEPROTOTYPE;
3272 case ENOPROTOOPT: return WSAENOPROTOOPT;
3273 case EPROTONOSUPPORT: return WSAEPROTONOSUPPORT;
3274 case ESOCKTNOSUPPORT: return WSAESOCKTNOSUPPORT;
3275 case EOPNOTSUPP: return WSAEOPNOTSUPP;
3276 case EPFNOSUPPORT: return WSAEPFNOSUPPORT;
3277 case EAFNOSUPPORT: return WSAEAFNOSUPPORT;
3278 case EADDRINUSE: return WSAEADDRINUSE;
3279 case EADDRNOTAVAIL: return WSAEADDRNOTAVAIL;
3280 case ENETDOWN: return WSAENETDOWN;
3281 case ENETUNREACH: return WSAENETUNREACH;
3282 case ENETRESET: return WSAENETRESET;
3283 case ECONNABORTED: return WSAECONNABORTED;
3284 case EPIPE:
3285 case ECONNRESET: return WSAECONNRESET;
3286 case ENOBUFS: return WSAENOBUFS;
3287 case EISCONN: return WSAEISCONN;
3288 case ENOTCONN: return WSAENOTCONN;
3289 case ESHUTDOWN: return WSAESHUTDOWN;
3290 case ETOOMANYREFS: return WSAETOOMANYREFS;
3291 case ETIMEDOUT: return WSAETIMEDOUT;
3292 case ECONNREFUSED: return WSAECONNREFUSED;
3293 case ELOOP: return WSAELOOP;
3294 case ENAMETOOLONG: return WSAENAMETOOLONG;
3295 case EHOSTDOWN: return WSAEHOSTDOWN;
3296 case EHOSTUNREACH: return WSAEHOSTUNREACH;
3297 case ENOTEMPTY: return WSAENOTEMPTY;
3298 #ifdef EPROCLIM
3299 case EPROCLIM: return WSAEPROCLIM;
3300 #endif
3301 #ifdef EUSERS
3302 case EUSERS: return WSAEUSERS;
3303 #endif
3304 #ifdef EDQUOT
3305 case EDQUOT: return WSAEDQUOT;
3306 #endif
3307 #ifdef ESTALE
3308 case ESTALE: return WSAESTALE;
3309 #endif
3310 #ifdef EREMOTE
3311 case EREMOTE: return WSAEREMOTE;
3312 #endif
3314 /* just in case we ever get here and there are no problems */
3315 case 0: return 0;
3316 default:
3317 WARN("Unknown errno %d!\n", loc_errno);
3318 return WSAEOPNOTSUPP;
3322 UINT16 wsaHerrno(int loc_errno)
3325 WARN("h_errno %d.\n", loc_errno);
3327 switch(loc_errno)
3329 case HOST_NOT_FOUND: return WSAHOST_NOT_FOUND;
3330 case TRY_AGAIN: return WSATRY_AGAIN;
3331 case NO_RECOVERY: return WSANO_RECOVERY;
3332 case NO_DATA: return WSANO_DATA;
3333 case ENOBUFS: return WSAENOBUFS;
3335 case 0: return 0;
3336 default:
3337 WARN("Unknown h_errno %d!\n", loc_errno);
3338 return WSAEOPNOTSUPP;