Convert the value of level when setsockopt is called with
[wine/testsucceed.git] / dlls / winsock / socket.c
blobf49c2d06294795b4af3506094c7595778260ac40
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 && level == WS_SOL_SOCKET) {
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 level = SOL_SOCKET;
2103 }else{
2104 if (!convert_sockopt(&level, &optname)) {
2105 SetLastError(WSAENOPROTOOPT);
2106 close(fd);
2107 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);
2123 if(optname == SO_RCVBUF && *(int*)optval < 2048) {
2124 WARN("SO_RCVBF for %d bytes is too small: ignored\n", *(int*)optval );
2125 close( fd);
2126 return 0;
2129 if (setsockopt(fd, level, optname, optval, optlen) == 0)
2131 close(fd);
2132 return 0;
2134 SetLastError(wsaErrno());
2135 close(fd);
2137 else SetLastError(WSAENOTSOCK);
2138 return SOCKET_ERROR;
2141 /***********************************************************************
2142 * setsockopt() (WINSOCK.21)
2144 INT16 WINAPI WINSOCK_setsockopt16(SOCKET16 s, INT16 level, INT16 optname,
2145 char *optval, INT16 optlen)
2147 if( !optval ) return SOCKET_ERROR;
2148 return (INT16)WSOCK32_setsockopt( s, (UINT16)level, optname, optval, optlen );
2152 /***********************************************************************
2153 * shutdown() (WSOCK32.22)
2155 INT WINAPI WSOCK32_shutdown(SOCKET s, INT how)
2157 LPWSINFO pwsi = WINSOCK_GetIData();
2159 TRACE("(%08x): socket %04x, how %i\n",
2160 (unsigned)pwsi, s, how );
2161 if( _check_ws(pwsi, s) )
2163 int fd = _get_sock_fd(s);
2164 switch( how )
2166 case 0: /* drop receives */
2167 _enable_event(s, 0, 0, WS_FD_READ);
2168 #ifdef SHUT_RD
2169 how = SHUT_RD;
2170 #endif
2171 break;
2173 case 1: /* drop sends */
2174 _enable_event(s, 0, 0, WS_FD_WRITE);
2175 #ifdef SHUT_WR
2176 how = SHUT_WR;
2177 #endif
2178 break;
2180 case 2: /* drop all */
2181 #ifdef SHUT_RDWR
2182 how = SHUT_RDWR;
2183 #endif
2184 default:
2185 WSAAsyncSelect( s, 0, 0, 0 );
2186 break;
2189 if (shutdown(fd, how) == 0)
2191 if( how > 1 )
2193 _enable_event(s, 0, 0, WS_FD_CONNECTED|WS_FD_LISTENING);
2195 close(fd);
2196 return 0;
2198 SetLastError(wsaErrno());
2199 close(fd);
2201 else SetLastError(WSAENOTSOCK);
2202 return SOCKET_ERROR;
2205 /***********************************************************************
2206 * shutdown() (WINSOCK.22)
2208 INT16 WINAPI WINSOCK_shutdown16(SOCKET16 s, INT16 how)
2210 return (INT16)WSOCK32_shutdown( s, how );
2214 /***********************************************************************
2215 * socket() (WSOCK32.23)
2217 SOCKET WINAPI WSOCK32_socket(INT af, INT type, INT protocol)
2219 LPWSINFO pwsi = WINSOCK_GetIData();
2220 SOCKET ret;
2222 TRACE("(%08x): af=%d type=%d protocol=%d\n",
2223 (unsigned)pwsi, af, type, protocol);
2225 if( pwsi )
2227 /* check the socket family */
2228 switch(af)
2230 #ifdef HAVE_IPX
2231 case WS_AF_IPX: af = AF_IPX;
2232 #endif
2233 case AF_INET:
2234 case AF_UNSPEC: break;
2235 default: SetLastError(WSAEAFNOSUPPORT);
2236 return INVALID_SOCKET;
2239 /* check the socket type */
2240 switch(type)
2242 case SOCK_STREAM:
2243 case SOCK_DGRAM:
2244 case SOCK_RAW: break;
2245 default: SetLastError(WSAESOCKTNOSUPPORT);
2246 return INVALID_SOCKET;
2249 /* check the protocol type */
2250 if ( protocol < 0 ) /* don't support negative values */
2251 { SetLastError(WSAEPROTONOSUPPORT); return INVALID_SOCKET; }
2253 if ( af == AF_UNSPEC) /* did they not specify the address family? */
2254 switch(protocol)
2256 case IPPROTO_TCP:
2257 if (type == SOCK_STREAM) { af = AF_INET; break; }
2258 case IPPROTO_UDP:
2259 if (type == SOCK_DGRAM) { af = AF_INET; break; }
2260 default: SetLastError(WSAEPROTOTYPE); return INVALID_SOCKET;
2263 SERVER_START_REQ
2265 struct create_socket_request *req = server_alloc_req( sizeof(*req), 0 );
2266 req->family = af;
2267 req->type = type;
2268 req->protocol = protocol;
2269 req->access = GENERIC_READ|GENERIC_WRITE|SYNCHRONIZE;
2270 req->inherit = TRUE;
2271 sock_server_call( REQ_CREATE_SOCKET );
2272 ret = req->handle;
2274 SERVER_END_REQ;
2275 if ( ((int) ret) >= 0)
2277 TRACE("\tcreated %04x\n", ret );
2278 return ret;
2281 if (GetLastError() == WSAEACCES) /* raw socket denied */
2283 if (type == SOCK_RAW)
2284 MESSAGE("WARNING: Trying to create a socket of type SOCK_RAW, will fail unless running as root\n");
2285 else
2286 MESSAGE("WS_SOCKET: not enough privileges to create socket, try running as root\n");
2287 SetLastError(WSAESOCKTNOSUPPORT);
2291 WARN("\t\tfailed!\n");
2292 return INVALID_SOCKET;
2295 /***********************************************************************
2296 * socket() (WINSOCK.23)
2298 SOCKET16 WINAPI WINSOCK_socket16(INT16 af, INT16 type, INT16 protocol)
2300 return (SOCKET16)WSOCK32_socket( af, type, protocol );
2304 /* ----------------------------------- DNS services
2306 * IMPORTANT: 16-bit API structures have SEGPTR pointers inside them.
2307 * Also, we have to use wsock32 stubs to convert structures and
2308 * error codes from Unix to WSA, hence there is no direct mapping in
2309 * the relay32/wsock32.spec.
2312 static char* NULL_STRING = "NULL";
2314 /***********************************************************************
2315 * gethostbyaddr() (WINSOCK.51)(WSOCK32.51)
2317 static WIN_hostent* __ws_gethostbyaddr(const char *addr, int len, int type, int dup_flag)
2319 WIN_hostent *retval = NULL;
2320 LPWSINFO pwsi = WINSOCK_GetIData();
2322 if( pwsi )
2324 struct hostent* host;
2325 #if HAVE_LINUX_GETHOSTBYNAME_R_6
2326 char *extrabuf;
2327 int ebufsize=1024;
2328 struct hostent hostentry;
2329 int locerr=ENOBUFS;
2330 host = NULL;
2331 extrabuf=HeapAlloc(GetProcessHeap(),0,ebufsize) ;
2332 while(extrabuf) {
2333 int res = gethostbyaddr_r(addr, len, type,
2334 &hostentry, extrabuf, ebufsize, &host, &locerr);
2335 if( res != ERANGE) break;
2336 ebufsize *=2;
2337 extrabuf=HeapReAlloc(GetProcessHeap(),0,extrabuf,ebufsize) ;
2339 if (!host) SetLastError((locerr < 0) ? wsaErrno() : wsaHerrno(locerr));
2340 #else
2341 EnterCriticalSection( &csWSgetXXXbyYYY );
2342 host = gethostbyaddr(addr, len, type);
2343 if (!host) SetLastError((h_errno < 0) ? wsaErrno() : wsaHerrno(h_errno));
2344 #endif
2345 if( host != NULL )
2347 if( WS_dup_he(pwsi, host, dup_flag) )
2348 retval = (WIN_hostent*)(pwsi->he);
2349 else
2350 SetLastError(WSAENOBUFS);
2352 #ifdef HAVE_LINUX_GETHOSTBYNAME_R_6
2353 HeapFree(GetProcessHeap(),0,extrabuf);
2354 #else
2355 LeaveCriticalSection( &csWSgetXXXbyYYY );
2356 #endif
2358 return retval;
2361 SEGPTR WINAPI WINSOCK_gethostbyaddr16(const char *addr, INT16 len, INT16 type)
2363 WIN_hostent* retval;
2364 TRACE("ptr %08x, len %d, type %d\n",
2365 (unsigned) addr, len, type);
2366 retval = __ws_gethostbyaddr( addr, len, type, WS_DUP_SEGPTR );
2367 return retval ? SEGPTR_GET(retval) : ((SEGPTR)NULL);
2370 WIN_hostent* WINAPI WSOCK32_gethostbyaddr(const char *addr, INT len,
2371 INT type)
2373 TRACE("ptr %08x, len %d, type %d\n",
2374 (unsigned) addr, len, type);
2375 return __ws_gethostbyaddr(addr, len, type, WS_DUP_LINEAR);
2378 /***********************************************************************
2379 * gethostbyname() (WINSOCK.52)(WSOCK32.52)
2381 static WIN_hostent * __ws_gethostbyname(const char *name, int dup_flag)
2383 WIN_hostent *retval = NULL;
2384 LPWSINFO pwsi = WINSOCK_GetIData();
2386 if( pwsi )
2388 struct hostent* host;
2389 #ifdef HAVE_LINUX_GETHOSTBYNAME_R_6
2390 char *extrabuf;
2391 int ebufsize=1024;
2392 struct hostent hostentry;
2393 int locerr = ENOBUFS;
2394 host = NULL;
2395 extrabuf=HeapAlloc(GetProcessHeap(),0,ebufsize) ;
2396 while(extrabuf) {
2397 int res = gethostbyname_r(name, &hostentry, extrabuf, ebufsize, &host, &locerr);
2398 if( res != ERANGE) break;
2399 ebufsize *=2;
2400 extrabuf=HeapReAlloc(GetProcessHeap(),0,extrabuf,ebufsize) ;
2402 if (!host) SetLastError((locerr < 0) ? wsaErrno() : wsaHerrno(locerr));
2403 #else
2404 EnterCriticalSection( &csWSgetXXXbyYYY );
2405 host = gethostbyname(name);
2406 if (!host) SetLastError((h_errno < 0) ? wsaErrno() : wsaHerrno(h_errno));
2407 #endif
2408 if( host != NULL )
2410 if( WS_dup_he(pwsi, host, dup_flag) )
2411 retval = (WIN_hostent*)(pwsi->he);
2412 else SetLastError(WSAENOBUFS);
2414 #ifdef HAVE_LINUX_GETHOSTBYNAME_R_6
2415 HeapFree(GetProcessHeap(),0,extrabuf);
2416 #else
2417 LeaveCriticalSection( &csWSgetXXXbyYYY );
2418 #endif
2420 return retval;
2423 SEGPTR WINAPI WINSOCK_gethostbyname16(const char *name)
2425 WIN_hostent* retval;
2426 TRACE("%s\n", (name)?name:NULL_STRING);
2427 retval = __ws_gethostbyname( name, WS_DUP_SEGPTR );
2428 return (retval)? SEGPTR_GET(retval) : ((SEGPTR)NULL) ;
2431 WIN_hostent* WINAPI WSOCK32_gethostbyname(const char* name)
2433 TRACE("%s\n", (name)?name:NULL_STRING);
2434 return __ws_gethostbyname( name, WS_DUP_LINEAR );
2438 /***********************************************************************
2439 * getprotobyname() (WINSOCK.53)(WSOCK32.53)
2441 static WIN_protoent* __ws_getprotobyname(const char *name, int dup_flag)
2443 WIN_protoent* retval = NULL;
2444 LPWSINFO pwsi = WINSOCK_GetIData();
2446 if( pwsi )
2448 struct protoent* proto;
2449 EnterCriticalSection( &csWSgetXXXbyYYY );
2450 if( (proto = getprotobyname(name)) != NULL )
2452 if( WS_dup_pe(pwsi, proto, dup_flag) )
2453 retval = (WIN_protoent*)(pwsi->pe);
2454 else SetLastError(WSAENOBUFS);
2456 else {
2457 MESSAGE("protocol %s not found; You might want to add "
2458 "this to /etc/protocols\n", debugstr_a(name) );
2459 SetLastError(WSANO_DATA);
2461 LeaveCriticalSection( &csWSgetXXXbyYYY );
2462 } else SetLastError(WSANOTINITIALISED);
2463 return retval;
2466 SEGPTR WINAPI WINSOCK_getprotobyname16(const char *name)
2468 WIN_protoent* retval;
2469 TRACE("%s\n", (name)?name:NULL_STRING);
2470 retval = __ws_getprotobyname(name, WS_DUP_SEGPTR);
2471 return retval ? SEGPTR_GET(retval) : ((SEGPTR)NULL);
2474 WIN_protoent* WINAPI WSOCK32_getprotobyname(const char* name)
2476 TRACE("%s\n", (name)?name:NULL_STRING);
2477 return __ws_getprotobyname(name, WS_DUP_LINEAR);
2481 /***********************************************************************
2482 * getprotobynumber() (WINSOCK.54)(WSOCK32.54)
2484 static WIN_protoent* __ws_getprotobynumber(int number, int dup_flag)
2486 WIN_protoent* retval = NULL;
2487 LPWSINFO pwsi = WINSOCK_GetIData();
2489 if( pwsi )
2491 struct protoent* proto;
2492 EnterCriticalSection( &csWSgetXXXbyYYY );
2493 if( (proto = getprotobynumber(number)) != NULL )
2495 if( WS_dup_pe(pwsi, proto, dup_flag) )
2496 retval = (WIN_protoent*)(pwsi->pe);
2497 else SetLastError(WSAENOBUFS);
2499 else {
2500 MESSAGE("protocol number %d not found; You might want to add "
2501 "this to /etc/protocols\n", number );
2502 SetLastError(WSANO_DATA);
2504 LeaveCriticalSection( &csWSgetXXXbyYYY );
2505 } else SetLastError(WSANOTINITIALISED);
2506 return retval;
2509 SEGPTR WINAPI WINSOCK_getprotobynumber16(INT16 number)
2511 WIN_protoent* retval;
2512 TRACE("%i\n", number);
2513 retval = __ws_getprotobynumber(number, WS_DUP_SEGPTR);
2514 return retval ? SEGPTR_GET(retval) : ((SEGPTR)NULL);
2517 WIN_protoent* WINAPI WSOCK32_getprotobynumber(INT number)
2519 TRACE("%i\n", number);
2520 return __ws_getprotobynumber(number, WS_DUP_LINEAR);
2524 /***********************************************************************
2525 * getservbyname() (WINSOCK.55)(WSOCK32.55)
2527 static WIN_servent* __ws_getservbyname(const char *name, const char *proto, int dup_flag)
2529 WIN_servent* retval = NULL;
2530 LPWSINFO pwsi = WINSOCK_GetIData();
2532 if( pwsi )
2534 struct servent* serv;
2535 int i = wsi_strtolo( pwsi, name, proto );
2537 if( i ) {
2538 EnterCriticalSection( &csWSgetXXXbyYYY );
2539 serv = getservbyname(pwsi->buffer,
2540 proto ? (pwsi->buffer + i) : NULL);
2541 if( serv != NULL )
2543 if( WS_dup_se(pwsi, serv, dup_flag) )
2544 retval = (WIN_servent*)(pwsi->se);
2545 else SetLastError(WSAENOBUFS);
2547 else {
2548 MESSAGE("service %s protocol %s not found; You might want to add "
2549 "this to /etc/services\n", debugstr_a(pwsi->buffer),
2550 proto ? debugstr_a(pwsi->buffer+i):"*");
2551 SetLastError(WSANO_DATA);
2553 LeaveCriticalSection( &csWSgetXXXbyYYY );
2555 else SetLastError(WSAENOBUFS);
2556 } else SetLastError(WSANOTINITIALISED);
2557 return retval;
2560 SEGPTR WINAPI WINSOCK_getservbyname16(const char *name, const char *proto)
2562 WIN_servent* retval;
2563 TRACE("'%s', '%s'\n",
2564 (name)?name:NULL_STRING, (proto)?proto:NULL_STRING);
2565 retval = __ws_getservbyname(name, proto, WS_DUP_SEGPTR);
2566 return retval ? SEGPTR_GET(retval) : ((SEGPTR)NULL);
2569 WIN_servent* WINAPI WSOCK32_getservbyname(const char *name, const char *proto)
2571 TRACE("'%s', '%s'\n",
2572 (name)?name:NULL_STRING, (proto)?proto:NULL_STRING);
2573 return __ws_getservbyname(name, proto, WS_DUP_LINEAR);
2577 /***********************************************************************
2578 * getservbyport() (WINSOCK.56)(WSOCK32.56)
2580 static WIN_servent* __ws_getservbyport(int port, const char* proto, int dup_flag)
2582 WIN_servent* retval = NULL;
2583 LPWSINFO pwsi = WINSOCK_GetIData();
2585 if( pwsi )
2587 struct servent* serv;
2588 if (!proto || wsi_strtolo( pwsi, proto, NULL )) {
2589 EnterCriticalSection( &csWSgetXXXbyYYY );
2590 if( (serv = getservbyport(port, (proto) ? pwsi->buffer : NULL)) != NULL ) {
2591 if( WS_dup_se(pwsi, serv, dup_flag) )
2592 retval = (WIN_servent*)(pwsi->se);
2593 else SetLastError(WSAENOBUFS);
2595 else {
2596 MESSAGE("service on port %lu protocol %s not found; You might want to add "
2597 "this to /etc/services\n", (unsigned long)ntohl(port),
2598 proto ? debugstr_a(pwsi->buffer) : "*");
2599 SetLastError(WSANO_DATA);
2601 LeaveCriticalSection( &csWSgetXXXbyYYY );
2603 else SetLastError(WSAENOBUFS);
2604 } else SetLastError(WSANOTINITIALISED);
2605 return retval;
2608 SEGPTR WINAPI WINSOCK_getservbyport16(INT16 port, const char *proto)
2610 WIN_servent* retval;
2611 TRACE("%d (i.e. port %d), '%s'\n",
2612 (int)port, (int)ntohl(port), (proto)?proto:NULL_STRING);
2613 retval = __ws_getservbyport(port, proto, WS_DUP_SEGPTR);
2614 return retval ? SEGPTR_GET(retval) : ((SEGPTR)NULL);
2617 WIN_servent* WINAPI WSOCK32_getservbyport(INT port, const char *proto)
2619 TRACE("%d (i.e. port %d), '%s'\n",
2620 (int)port, (int)ntohl(port), (proto)?proto:NULL_STRING);
2621 return __ws_getservbyport(port, proto, WS_DUP_LINEAR);
2625 /***********************************************************************
2626 * gethostname() (WSOCK32.57)
2628 INT WINAPI WSOCK32_gethostname(char *name, INT namelen)
2630 LPWSINFO pwsi = WINSOCK_GetIData();
2632 TRACE("(%08x): name %s, len %d\n",
2633 (unsigned)pwsi, (name)?name:NULL_STRING, namelen);
2634 if( pwsi )
2636 if (gethostname(name, namelen) == 0) return 0;
2637 SetLastError((errno == EINVAL) ? WSAEFAULT : wsaErrno());
2639 return SOCKET_ERROR;
2642 /***********************************************************************
2643 * gethostname() (WINSOCK.57)
2645 INT16 WINAPI WINSOCK_gethostname16(char *name, INT16 namelen)
2647 return (INT16)WSOCK32_gethostname(name, namelen);
2651 /* ------------------------------------- Windows sockets extensions -- *
2653 * ------------------------------------------------------------------- */
2655 /***********************************************************************
2656 * WSAEnumNetworkEvents
2658 int WINAPI WSAEnumNetworkEvents(SOCKET s, WSAEVENT hEvent, LPWSANETWORKEVENTS lpEvent)
2660 LPWSINFO pwsi = WINSOCK_GetIData();
2662 TRACE("(%08x): %08x, hEvent %08x, lpEvent %08x\n",
2663 (unsigned)pwsi, s, hEvent, (unsigned)lpEvent );
2664 if( _check_ws(pwsi, s) )
2666 SERVER_START_REQ
2668 struct get_socket_event_request *req = server_alloc_req( sizeof(*req),
2669 sizeof(lpEvent->iErrorCode) );
2670 req->handle = s;
2671 req->service = TRUE;
2672 req->s_event = 0;
2673 req->c_event = hEvent;
2674 sock_server_call( REQ_GET_SOCKET_EVENT );
2675 lpEvent->lNetworkEvents = req->pmask;
2676 memcpy(lpEvent->iErrorCode, server_data_ptr(req), server_data_size(req) );
2678 SERVER_END_REQ;
2679 return 0;
2681 else SetLastError(WSAEINVAL);
2682 return SOCKET_ERROR;
2685 /***********************************************************************
2686 * WSAEventSelect
2688 int WINAPI WSAEventSelect(SOCKET s, WSAEVENT hEvent, LONG lEvent)
2690 LPWSINFO pwsi = WINSOCK_GetIData();
2692 TRACE("(%08x): %08x, hEvent %08x, event %08x\n",
2693 (unsigned)pwsi, s, hEvent, (unsigned)lEvent );
2694 if( _check_ws(pwsi, s) )
2696 SERVER_START_REQ
2698 struct set_socket_event_request *req = server_alloc_req( sizeof(*req), 0 );
2699 req->handle = s;
2700 req->mask = lEvent;
2701 req->event = hEvent;
2702 sock_server_call( REQ_SET_SOCKET_EVENT );
2704 SERVER_END_REQ;
2705 return 0;
2707 else SetLastError(WSAEINVAL);
2708 return SOCKET_ERROR;
2711 /***********************************************************************
2712 * WSAAsyncSelect() (WINSOCK.101)(WSOCK32.101)
2715 VOID CALLBACK WINSOCK_DoAsyncEvent( ULONG_PTR ptr )
2717 ws_select_info *info = (ws_select_info*)ptr;
2718 LPWSINFO pwsi = info->pwsi;
2719 unsigned int i, pmask, orphan = FALSE;
2720 int errors[FD_MAX_EVENTS];
2722 TRACE("socket %08x, event %08x\n", info->sock, info->event);
2723 SetLastError(0);
2724 SERVER_START_REQ
2726 struct get_socket_event_request *req = server_alloc_req( sizeof(*req), sizeof(errors) );
2727 req->handle = info->sock;
2728 req->service = TRUE;
2729 req->s_event = info->event; /* <== avoid race conditions */
2730 req->c_event = info->event;
2731 sock_server_call( REQ_GET_SOCKET_EVENT );
2732 pmask = req->pmask;
2733 memcpy( errors, server_data_ptr(req), server_data_size(req) );
2735 SERVER_END_REQ;
2736 if ( (GetLastError() == WSAENOTSOCK) || (GetLastError() == WSAEINVAL) )
2738 /* orphaned event (socket closed or something) */
2739 pmask = WS_FD_SERVEVENT;
2740 orphan = TRUE;
2743 /* check for accepted sockets that needs to inherit WSAAsyncSelect */
2744 if (pmask & WS_FD_SERVEVENT) {
2745 int q;
2746 for (q=0; q<WS_ACCEPT_QUEUE; q++)
2747 if (pwsi->accept_old[q] == info->sock) {
2748 /* there's only one service thread per pwsi, no lock necessary */
2749 HANDLE as = pwsi->accept_new[q];
2750 if (as) {
2751 pwsi->accept_new[q] = 0;
2752 pwsi->accept_old[q] = 0;
2753 WSAAsyncSelect(as, info->hWnd, info->uMsg, info->lEvent);
2756 pmask &= ~WS_FD_SERVEVENT;
2758 /* dispatch network events */
2759 for (i=0; i<FD_MAX_EVENTS; i++)
2760 if (pmask & (1<<i)) {
2761 TRACE("post: event bit %d, error %d\n", i, errors[i]);
2762 PostMessageA(info->hWnd, info->uMsg, info->sock,
2763 WSAMAKESELECTREPLY(1<<i, errors[i]));
2765 /* cleanup */
2766 if (orphan)
2768 TRACE("orphaned event, self-destructing\n");
2769 /* SERVICE_Delete closes the event object */
2770 SERVICE_Delete( info->service );
2771 WS_FREE(info);
2775 INT WINAPI WSAAsyncSelect(SOCKET s, HWND hWnd, UINT uMsg, LONG lEvent)
2777 LPWSINFO pwsi = WINSOCK_GetIData();
2779 TRACE("(%08x): %04x, hWnd %04x, uMsg %08x, event %08x\n",
2780 (unsigned)pwsi, (SOCKET16)s, (HWND16)hWnd, uMsg, (unsigned)lEvent );
2781 if( _check_ws(pwsi, s) )
2783 if( lEvent )
2785 ws_select_info *info = (ws_select_info*)WS_ALLOC(sizeof(ws_select_info));
2786 if( info )
2788 HANDLE hObj = CreateEventA( NULL, TRUE, FALSE, NULL );
2789 INT err;
2791 info->sock = s;
2792 info->event = hObj;
2793 info->hWnd = hWnd;
2794 info->uMsg = uMsg;
2795 info->lEvent = lEvent;
2796 info->pwsi = pwsi;
2797 info->service = SERVICE_AddObject( hObj, WINSOCK_DoAsyncEvent, (ULONG_PTR)info );
2799 err = WSAEventSelect( s, hObj, lEvent | WS_FD_SERVEVENT );
2800 if (err) {
2801 /* SERVICE_Delete closes the event object */
2802 SERVICE_Delete( info->service );
2803 WS_FREE(info);
2804 return err;
2807 return 0; /* success */
2809 else SetLastError(WSAENOBUFS);
2811 else
2813 WSAEventSelect(s, 0, 0);
2814 return 0;
2817 else SetLastError(WSAEINVAL);
2818 return SOCKET_ERROR;
2821 INT16 WINAPI WSAAsyncSelect16(SOCKET16 s, HWND16 hWnd, UINT16 wMsg, LONG lEvent)
2823 return (INT16)WSAAsyncSelect( s, hWnd, wMsg, lEvent );
2826 /***********************************************************************
2827 * WSARecvEx() (WSOCK32.1107)
2829 * WSARecvEx is a Microsoft specific extension to winsock that is identical to recv
2830 * except that has an in/out argument call flags that has the value MSG_PARTIAL ored
2831 * into the flags parameter when a partial packet is read. This only applies to
2832 * sockets using the datagram protocol. This method does not seem to be implemented
2833 * correctly by microsoft as the winsock implementation does not set the MSG_PARTIAL
2834 * flag when a fragmented packet arrives.
2836 INT WINAPI WSARecvEx(SOCKET s, char *buf, INT len, INT *flags) {
2837 FIXME("(WSARecvEx) partial packet return value not set \n");
2839 return WSOCK32_recv(s, buf, len, *flags);
2843 /***********************************************************************
2844 * WSARecvEx16() (WINSOCK.1107)
2846 * See description for WSARecvEx()
2848 INT16 WINAPI WSARecvEx16(SOCKET16 s, char *buf, INT16 len, INT16 *flags) {
2849 FIXME("(WSARecvEx16) partial packet return value not set \n");
2851 return WINSOCK_recv16(s, buf, len, *flags);
2855 /***********************************************************************
2856 * WSACreateEvent() (WS2_32.???)
2859 WSAEVENT WINAPI WSACreateEvent(void)
2861 /* Create a manual-reset event, with initial state: unsignealed */
2862 TRACE("\n");
2864 return CreateEventA(NULL, TRUE, FALSE, NULL);
2867 /***********************************************************************
2868 * WSACloseEvent() (WS2_32.???)
2871 BOOL WINAPI WSACloseEvent(WSAEVENT event)
2873 TRACE ("event=0x%x\n", event);
2875 return CloseHandle(event);
2878 /***********************************************************************
2879 * WSASocketA() (WS2_32.???)
2882 SOCKET WINAPI WSASocketA(int af, int type, int protocol,
2883 LPWSAPROTOCOL_INFOA lpProtocolInfo,
2884 GROUP g, DWORD dwFlags)
2887 FIXME: The "advanced" parameters of WSASocketA (lpProtocolInfo,
2888 g, dwFlags) are ignored.
2891 TRACE("af=%d type=%d protocol=%d protocol_info=%p group=%d flags=0x%lx\n",
2892 af, type, protocol, lpProtocolInfo, g, dwFlags );
2894 return ( WSOCK32_socket (af, type, protocol) );
2898 /***********************************************************************
2899 * __WSAFDIsSet() (WINSOCK.151)
2901 INT16 WINAPI __WSAFDIsSet16(SOCKET16 s, ws_fd_set16 *set)
2903 int i = set->fd_count;
2905 TRACE("(%d,%8lx(%i))\n", s,(unsigned long)set, i);
2907 while (i--)
2908 if (set->fd_array[i] == s) return 1;
2909 return 0;
2912 /***********************************************************************
2913 * __WSAFDIsSet() (WSOCK32.151)
2915 INT WINAPI __WSAFDIsSet(SOCKET s, ws_fd_set32 *set)
2917 int i = set->fd_count;
2919 TRACE("(%d,%8lx(%i))\n", s,(unsigned long)set, i);
2921 while (i--)
2922 if (set->fd_array[i] == s) return 1;
2923 return 0;
2926 /***********************************************************************
2927 * WSAIsBlocking() (WINSOCK.114)(WSOCK32.114)
2929 BOOL WINAPI WSAIsBlocking(void)
2931 /* By default WinSock should set all its sockets to non-blocking mode
2932 * and poll in PeekMessage loop when processing "blocking" ones. This
2933 * function is supposed to tell if the program is in this loop. Our
2934 * blocking calls are truly blocking so we always return FALSE.
2936 * Note: It is allowed to call this function without prior WSAStartup().
2939 TRACE("\n");
2940 return FALSE;
2943 /***********************************************************************
2944 * WSACancelBlockingCall() (WINSOCK.113)(WSOCK32.113)
2946 INT WINAPI WSACancelBlockingCall(void)
2948 LPWSINFO pwsi = WINSOCK_GetIData();
2950 TRACE("(%08x)\n", (unsigned)pwsi);
2952 if( pwsi ) return 0;
2953 return SOCKET_ERROR;
2957 /***********************************************************************
2958 * WSASetBlockingHook16() (WINSOCK.109)
2960 FARPROC16 WINAPI WSASetBlockingHook16(FARPROC16 lpBlockFunc)
2962 FARPROC16 prev;
2963 LPWSINFO pwsi = WINSOCK_GetIData();
2965 TRACE("(%08x): hook %08x\n",
2966 (unsigned)pwsi, (unsigned) lpBlockFunc);
2967 if( pwsi )
2969 prev = (FARPROC16)pwsi->blocking_hook;
2970 pwsi->blocking_hook = (DWORD)lpBlockFunc;
2971 pwsi->flags &= ~WSI_BLOCKINGHOOK;
2972 return prev;
2974 return 0;
2978 /***********************************************************************
2979 * WSASetBlockingHook()
2981 FARPROC WINAPI WSASetBlockingHook(FARPROC lpBlockFunc)
2983 FARPROC prev;
2984 LPWSINFO pwsi = WINSOCK_GetIData();
2986 TRACE("(%08x): hook %08x\n",
2987 (unsigned)pwsi, (unsigned) lpBlockFunc);
2988 if( pwsi ) {
2989 prev = (FARPROC)pwsi->blocking_hook;
2990 pwsi->blocking_hook = (DWORD)lpBlockFunc;
2991 pwsi->flags |= WSI_BLOCKINGHOOK;
2992 return prev;
2994 return NULL;
2998 /***********************************************************************
2999 * WSAUnhookBlockingHook16() (WINSOCK.110)
3001 INT16 WINAPI WSAUnhookBlockingHook16(void)
3003 LPWSINFO pwsi = WINSOCK_GetIData();
3005 TRACE("(%08x)\n", (unsigned)pwsi);
3006 if( pwsi ) return (INT16)(pwsi->blocking_hook = 0);
3007 return SOCKET_ERROR;
3011 /***********************************************************************
3012 * WSAUnhookBlockingHook()
3014 INT WINAPI WSAUnhookBlockingHook(void)
3016 LPWSINFO pwsi = WINSOCK_GetIData();
3018 TRACE("(%08x)\n", (unsigned)pwsi);
3019 if( pwsi )
3021 pwsi->blocking_hook = 0;
3022 pwsi->flags &= ~WSI_BLOCKINGHOOK;
3023 return 0;
3025 return SOCKET_ERROR;
3029 /* ----------------------------------- end of API stuff */
3031 /* ----------------------------------- helper functions -
3033 * TODO: Merge WS_dup_..() stuff into one function that
3034 * would operate with a generic structure containing internal
3035 * pointers (via a template of some kind).
3038 static int list_size(char** l, int item_size)
3040 int i,j = 0;
3041 if(l)
3042 { for(i=0;l[i];i++)
3043 j += (item_size) ? item_size : strlen(l[i]) + 1;
3044 j += (i + 1) * sizeof(char*); }
3045 return j;
3048 static int list_dup(char** l_src, char* ref, char* base, int item_size)
3050 /* base is either either equal to ref or 0 or SEGPTR */
3052 char* p = ref;
3053 char** l_to = (char**)ref;
3054 int i,j,k;
3056 for(j=0;l_src[j];j++) ;
3057 p += (j + 1) * sizeof(char*);
3058 for(i=0;i<j;i++)
3059 { l_to[i] = base + (p - ref);
3060 k = ( item_size ) ? item_size : strlen(l_src[i]) + 1;
3061 memcpy(p, l_src[i], k); p += k; }
3062 l_to[i] = NULL;
3063 return (p - ref);
3066 /* ----- hostent */
3068 static int hostent_size(struct hostent* p_he)
3070 int size = 0;
3071 if( p_he )
3072 { size = sizeof(struct hostent);
3073 size += strlen(p_he->h_name) + 1;
3074 size += list_size(p_he->h_aliases, 0);
3075 size += list_size(p_he->h_addr_list, p_he->h_length ); }
3076 return size;
3079 /* duplicate hostent entry
3080 * and handle all Win16/Win32 dependent things (struct size, ...) *correctly*.
3081 * Dito for protoent and servent.
3083 int WS_dup_he(LPWSINFO pwsi, struct hostent* p_he, int flag)
3085 /* Convert hostent structure into ws_hostent so that the data fits
3086 * into pwsi->buffer. Internal pointers can be linear, SEGPTR, or
3087 * relative to pwsi->buffer depending on "flag" value. Returns size
3088 * of the data copied (also in the pwsi->buflen).
3091 int size = hostent_size(p_he);
3092 if( size )
3094 char *p_name,*p_aliases,*p_addr,*p_base,*p;
3095 char *p_to;
3096 struct ws_hostent16 *p_to16;
3097 struct ws_hostent32 *p_to32;
3099 _check_buffer_he(pwsi, size);
3100 p_to = (char *)pwsi->he;
3101 p_to16 = (struct ws_hostent16*)pwsi->he;
3102 p_to32 = (struct ws_hostent32*)pwsi->he;
3104 p = p_to;
3105 p_base = (flag & WS_DUP_OFFSET) ? NULL
3106 : ((flag & WS_DUP_SEGPTR) ? (char*)SEGPTR_GET(p) : p);
3107 p += (flag & WS_DUP_SEGPTR) ?
3108 sizeof(struct ws_hostent16) : sizeof(struct ws_hostent32);
3109 p_name = p;
3110 strcpy(p, p_he->h_name); p += strlen(p) + 1;
3111 p_aliases = p;
3112 p += list_dup(p_he->h_aliases, p, p_base + (p - p_to), 0);
3113 p_addr = p;
3114 list_dup(p_he->h_addr_list, p, p_base + (p - p_to), p_he->h_length);
3116 if (flag & WS_DUP_SEGPTR) /* Win16 */
3118 p_to16->h_addrtype = (INT16)p_he->h_addrtype;
3119 p_to16->h_length = (INT16)p_he->h_length;
3120 p_to16->h_name = (SEGPTR)(p_base + (p_name - p_to));
3121 p_to16->h_aliases = (SEGPTR)(p_base + (p_aliases - p_to));
3122 p_to16->h_addr_list = (SEGPTR)(p_base + (p_addr - p_to));
3123 size += (sizeof(struct ws_hostent16) - sizeof(struct hostent));
3125 else /* Win32 */
3127 p_to32->h_addrtype = p_he->h_addrtype;
3128 p_to32->h_length = p_he->h_length;
3129 p_to32->h_name = (p_base + (p_name - p_to));
3130 p_to32->h_aliases = (char **)(p_base + (p_aliases - p_to));
3131 p_to32->h_addr_list = (char **)(p_base + (p_addr - p_to));
3132 size += (sizeof(struct ws_hostent32) - sizeof(struct hostent));
3135 return size;
3138 /* ----- protoent */
3140 static int protoent_size(struct protoent* p_pe)
3142 int size = 0;
3143 if( p_pe )
3144 { size = sizeof(struct protoent);
3145 size += strlen(p_pe->p_name) + 1;
3146 size += list_size(p_pe->p_aliases, 0); }
3147 return size;
3150 int WS_dup_pe(LPWSINFO pwsi, struct protoent* p_pe, int flag)
3152 int size = protoent_size(p_pe);
3153 if( size )
3155 char *p_to;
3156 struct ws_protoent16 *p_to16;
3157 struct ws_protoent32 *p_to32;
3158 char *p_name,*p_aliases,*p_base,*p;
3160 _check_buffer_pe(pwsi, size);
3161 p_to = (char *)pwsi->pe;
3162 p_to16 = (struct ws_protoent16*)pwsi->pe;
3163 p_to32 = (struct ws_protoent32*)pwsi->pe;
3164 p = p_to;
3165 p_base = (flag & WS_DUP_OFFSET) ? NULL
3166 : ((flag & WS_DUP_SEGPTR) ? (char*)SEGPTR_GET(p) : p);
3167 p += (flag & WS_DUP_SEGPTR) ?
3168 sizeof(struct ws_protoent16) : sizeof(struct ws_protoent32);
3169 p_name = p;
3170 strcpy(p, p_pe->p_name); p += strlen(p) + 1;
3171 p_aliases = p;
3172 list_dup(p_pe->p_aliases, p, p_base + (p - p_to), 0);
3174 if (flag & WS_DUP_SEGPTR) /* Win16 */
3176 p_to16->p_proto = (INT16)p_pe->p_proto;
3177 p_to16->p_name = (SEGPTR)(p_base) + (p_name - p_to);
3178 p_to16->p_aliases = (SEGPTR)((p_base) + (p_aliases - p_to));
3179 size += (sizeof(struct ws_protoent16) - sizeof(struct protoent));
3181 else /* Win32 */
3183 p_to32->p_proto = p_pe->p_proto;
3184 p_to32->p_name = (p_base) + (p_name - p_to);
3185 p_to32->p_aliases = (char **)((p_base) + (p_aliases - p_to));
3186 size += (sizeof(struct ws_protoent32) - sizeof(struct protoent));
3189 return size;
3192 /* ----- servent */
3194 static int servent_size(struct servent* p_se)
3196 int size = 0;
3197 if( p_se )
3198 { size += sizeof(struct servent);
3199 size += strlen(p_se->s_proto) + strlen(p_se->s_name) + 2;
3200 size += list_size(p_se->s_aliases, 0); }
3201 return size;
3204 int WS_dup_se(LPWSINFO pwsi, struct servent* p_se, int flag)
3206 int size = servent_size(p_se);
3207 if( size )
3209 char *p_name,*p_aliases,*p_proto,*p_base,*p;
3210 char *p_to;
3211 struct ws_servent16 *p_to16;
3212 struct ws_servent32 *p_to32;
3214 _check_buffer_se(pwsi, size);
3215 p_to = (char *)pwsi->se;
3216 p_to16 = (struct ws_servent16*)pwsi->se;
3217 p_to32 = (struct ws_servent32*)pwsi->se;
3218 p = p_to;
3219 p_base = (flag & WS_DUP_OFFSET) ? NULL
3220 : ((flag & WS_DUP_SEGPTR) ? (char*)SEGPTR_GET(p) : p);
3221 p += (flag & WS_DUP_SEGPTR) ?
3222 sizeof(struct ws_servent16) : sizeof(struct ws_servent32);
3223 p_name = p;
3224 strcpy(p, p_se->s_name); p += strlen(p) + 1;
3225 p_proto = p;
3226 strcpy(p, p_se->s_proto); p += strlen(p) + 1;
3227 p_aliases = p;
3228 list_dup(p_se->s_aliases, p, p_base + (p - p_to), 0);
3230 if (flag & WS_DUP_SEGPTR) /* Win16 */
3232 p_to16->s_port = (INT16)p_se->s_port;
3233 p_to16->s_name = (SEGPTR)(p_base + (p_name - p_to));
3234 p_to16->s_proto = (SEGPTR)(p_base + (p_proto - p_to));
3235 p_to16->s_aliases = (SEGPTR)(p_base + (p_aliases - p_to));
3236 size += (sizeof(struct ws_servent16) - sizeof(struct servent));
3238 else /* Win32 */
3240 p_to32->s_port = p_se->s_port;
3241 p_to32->s_name = (p_base + (p_name - p_to));
3242 p_to32->s_proto = (p_base + (p_proto - p_to));
3243 p_to32->s_aliases = (char **)(p_base + (p_aliases - p_to));
3244 size += (sizeof(struct ws_servent32) - sizeof(struct servent));
3247 return size;
3250 /* ----------------------------------- error handling */
3252 UINT16 wsaErrno(void)
3254 int loc_errno = errno;
3255 WARN("errno %d, (%s).\n", loc_errno, strerror(loc_errno));
3257 switch(loc_errno)
3259 case EINTR: return WSAEINTR;
3260 case EBADF: return WSAEBADF;
3261 case EPERM:
3262 case EACCES: return WSAEACCES;
3263 case EFAULT: return WSAEFAULT;
3264 case EINVAL: return WSAEINVAL;
3265 case EMFILE: return WSAEMFILE;
3266 case EWOULDBLOCK: return WSAEWOULDBLOCK;
3267 case EINPROGRESS: return WSAEINPROGRESS;
3268 case EALREADY: return WSAEALREADY;
3269 case ENOTSOCK: return WSAENOTSOCK;
3270 case EDESTADDRREQ: return WSAEDESTADDRREQ;
3271 case EMSGSIZE: return WSAEMSGSIZE;
3272 case EPROTOTYPE: return WSAEPROTOTYPE;
3273 case ENOPROTOOPT: return WSAENOPROTOOPT;
3274 case EPROTONOSUPPORT: return WSAEPROTONOSUPPORT;
3275 case ESOCKTNOSUPPORT: return WSAESOCKTNOSUPPORT;
3276 case EOPNOTSUPP: return WSAEOPNOTSUPP;
3277 case EPFNOSUPPORT: return WSAEPFNOSUPPORT;
3278 case EAFNOSUPPORT: return WSAEAFNOSUPPORT;
3279 case EADDRINUSE: return WSAEADDRINUSE;
3280 case EADDRNOTAVAIL: return WSAEADDRNOTAVAIL;
3281 case ENETDOWN: return WSAENETDOWN;
3282 case ENETUNREACH: return WSAENETUNREACH;
3283 case ENETRESET: return WSAENETRESET;
3284 case ECONNABORTED: return WSAECONNABORTED;
3285 case EPIPE:
3286 case ECONNRESET: return WSAECONNRESET;
3287 case ENOBUFS: return WSAENOBUFS;
3288 case EISCONN: return WSAEISCONN;
3289 case ENOTCONN: return WSAENOTCONN;
3290 case ESHUTDOWN: return WSAESHUTDOWN;
3291 case ETOOMANYREFS: return WSAETOOMANYREFS;
3292 case ETIMEDOUT: return WSAETIMEDOUT;
3293 case ECONNREFUSED: return WSAECONNREFUSED;
3294 case ELOOP: return WSAELOOP;
3295 case ENAMETOOLONG: return WSAENAMETOOLONG;
3296 case EHOSTDOWN: return WSAEHOSTDOWN;
3297 case EHOSTUNREACH: return WSAEHOSTUNREACH;
3298 case ENOTEMPTY: return WSAENOTEMPTY;
3299 #ifdef EPROCLIM
3300 case EPROCLIM: return WSAEPROCLIM;
3301 #endif
3302 #ifdef EUSERS
3303 case EUSERS: return WSAEUSERS;
3304 #endif
3305 #ifdef EDQUOT
3306 case EDQUOT: return WSAEDQUOT;
3307 #endif
3308 #ifdef ESTALE
3309 case ESTALE: return WSAESTALE;
3310 #endif
3311 #ifdef EREMOTE
3312 case EREMOTE: return WSAEREMOTE;
3313 #endif
3315 /* just in case we ever get here and there are no problems */
3316 case 0: return 0;
3317 default:
3318 WARN("Unknown errno %d!\n", loc_errno);
3319 return WSAEOPNOTSUPP;
3323 UINT16 wsaHerrno(int loc_errno)
3326 WARN("h_errno %d.\n", loc_errno);
3328 switch(loc_errno)
3330 case HOST_NOT_FOUND: return WSAHOST_NOT_FOUND;
3331 case TRY_AGAIN: return WSATRY_AGAIN;
3332 case NO_RECOVERY: return WSANO_RECOVERY;
3333 case NO_DATA: return WSANO_DATA;
3334 case ENOBUFS: return WSAENOBUFS;
3336 case 0: return 0;
3337 default:
3338 WARN("Unknown h_errno %d!\n", loc_errno);
3339 return WSAEOPNOTSUPP;