FindResourceExA/W should search for the specified language resource only.
[wine.git] / dlls / winsock / socket.c
blob3a72fac639f6f58f2c56737b6cd1b12f74f56b61
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).
13 #include "config.h"
15 #include <string.h>
16 #include <sys/types.h>
17 #ifdef HAVE_SYS_IPC_H
18 # include <sys/ipc.h>
19 #endif
20 #include <sys/ioctl.h>
21 #ifdef HAVE_SYS_FILIO_H
22 # include <sys/filio.h>
23 #endif
24 #ifdef HAVE_SYS_SOCKIO_H
25 # include <sys/sockio.h>
26 #endif
28 #if defined(__EMX__)
29 # include <sys/so_ioctl.h>
30 #endif
32 #ifdef HAVE_SYS_PARAM_H
33 # include <sys/param.h>
34 #endif
36 #ifdef HAVE_SYS_MSG_H
37 # include <sys/msg.h>
38 #endif
39 #ifdef HAVE_SYS_WAIT_H
40 # include <sys/wait.h>
41 #endif
42 #ifdef HAVE_SYS_SOCKET_H
43 #include <sys/socket.h>
44 #endif
45 #ifdef HAVE_NETINET_IN_H
46 # include <netinet/in.h>
47 #endif
48 #ifdef HAVE_NETINET_TCP_H
49 # include <netinet/tcp.h>
50 #endif
51 #ifdef HAVE_ARPA_INET_H
52 # include <arpa/inet.h>
53 #endif
54 #include <ctype.h>
55 #include <fcntl.h>
56 #include <errno.h>
57 #ifdef HAVE_SYS_ERRNO_H
58 #include <sys/errno.h>
59 #endif
60 #include <netdb.h>
61 #include <unistd.h>
62 #include <stdlib.h>
63 #ifdef HAVE_ARPA_NAMESER_H
64 # include <arpa/nameser.h>
65 #endif
66 #ifdef HAVE_RESOLV_H
67 # include <resolv.h>
68 #endif
69 #ifdef HAVE_NET_IF_H
70 # include <net/if.h>
71 #endif
73 #include "wine/winbase16.h"
74 #include "wingdi.h"
75 #include "winuser.h"
76 #include "winsock2.h"
77 #include "winnt.h"
78 #include "heap.h"
79 #include "task.h"
80 #include "message.h"
81 #include "miscemu.h"
82 #include "wine/port.h"
83 #include "services.h"
84 #include "server.h"
85 #include "debugtools.h"
88 DEFAULT_DEBUG_CHANNEL(winsock)
90 #define DEBUG_SOCKADDR 0
91 #define dump_sockaddr(a) \
92 DPRINTF("sockaddr_in: family %d, address %s, port %d\n", \
93 ((struct sockaddr_in *)a)->sin_family, \
94 inet_ntoa(((struct sockaddr_in *)a)->sin_addr), \
95 ntohs(((struct sockaddr_in *)a)->sin_port))
97 /* ----------------------------------- internal data */
99 /* ws_... struct conversion flags */
101 #define WS_DUP_LINEAR 0x0001
102 #define WS_DUP_NATIVE 0x0000 /* not used anymore */
103 #define WS_DUP_OFFSET 0x0002 /* internal pointers are offsets */
104 #define WS_DUP_SEGPTR 0x0004 /* internal pointers are SEGPTRs */
105 /* by default, internal pointers are linear */
106 typedef struct /* WSAAsyncSelect() control struct */
108 HANDLE service, event, sock;
109 HWND hWnd;
110 UINT uMsg;
111 LONG lEvent;
112 struct _WSINFO *pwsi;
113 } ws_select_info;
115 #define WS_MAX_SOCKETS_PER_PROCESS 128 /* reasonable guess */
116 #define WS_MAX_UDP_DATAGRAM 1024
118 #define WS_ACCEPT_QUEUE 6
120 #define WSI_BLOCKINGCALL 0x00000001 /* per-thread info flags */
121 #define WSI_BLOCKINGHOOK 0x00000002 /* 32-bit callback */
123 #define PROCFS_NETDEV_FILE "/proc/net/dev" /* Points to the file in the /proc fs
124 that lists the network devices.
125 Do we need an #ifdef LINUX for this? */
127 typedef struct _WSINFO
129 DWORD dwThisProcess;
130 struct _WSINFO *lpNextIData;
132 unsigned flags;
133 INT16 num_startup; /* reference counter */
134 INT16 num_async_rq;
135 INT16 last_free; /* entry in the socket table */
136 UINT16 buflen;
137 char* buffer; /* allocated from SEGPTR heap */
138 struct ws_hostent *he;
139 int helen;
140 struct ws_servent *se;
141 int selen;
142 struct ws_protoent *pe;
143 int pelen;
144 char* dbuffer; /* buffer for dummies (32 bytes) */
146 DWORD blocking_hook;
148 volatile HANDLE accept_old[WS_ACCEPT_QUEUE], accept_new[WS_ACCEPT_QUEUE];
149 } WSINFO, *LPWSINFO;
151 /* function prototypes */
152 int WS_dup_he(LPWSINFO pwsi, struct hostent* p_he, int flag);
153 int WS_dup_pe(LPWSINFO pwsi, struct protoent* p_pe, int flag);
154 int WS_dup_se(LPWSINFO pwsi, struct servent* p_se, int flag);
156 int WSAIOCTL_GetInterfaceCount(void);
157 int WSAIOCTL_GetInterfaceName(int intNumber, char *intName);
159 UINT16 wsaErrno(void);
160 UINT16 wsaHerrno(void);
162 static HANDLE _WSHeap = 0;
164 #define WS_ALLOC(size) \
165 HeapAlloc(_WSHeap, HEAP_ZERO_MEMORY, (size) )
166 #define WS_FREE(ptr) \
167 HeapFree(_WSHeap, 0, (ptr) )
169 static INT _ws_sock_ops[] =
170 { WS_SO_DEBUG, WS_SO_REUSEADDR, WS_SO_KEEPALIVE, WS_SO_DONTROUTE,
171 WS_SO_BROADCAST, WS_SO_LINGER, WS_SO_OOBINLINE, WS_SO_SNDBUF,
172 WS_SO_RCVBUF, WS_SO_ERROR, WS_SO_TYPE, WS_SO_DONTLINGER,
173 #ifdef SO_RCVTIMEO
174 WS_SO_RCVTIMEO,
175 #endif
176 0 };
177 static int _px_sock_ops[] =
178 { SO_DEBUG, SO_REUSEADDR, SO_KEEPALIVE, SO_DONTROUTE, SO_BROADCAST,
179 SO_LINGER, SO_OOBINLINE, SO_SNDBUF, SO_RCVBUF, SO_ERROR, SO_TYPE,
180 WS_SO_DONTLINGER, /* no unix equivalent */
181 #ifdef SO_RCVTIMEO
182 SO_RCVTIMEO,
183 #endif
186 static INT _ws_tcp_ops[] = {
187 #ifdef TCP_NODELAY
188 WS_TCP_NODELAY,
189 #endif
192 static int _px_tcp_ops[] = {
193 #ifdef TCP_NODELAY
194 TCP_NODELAY,
195 #endif
199 /* we need a special routine to handle WSA* errors */
200 static inline int sock_server_call( enum request req )
202 unsigned int res = server_call_noerr( req );
203 if (res)
205 /* do not map WSA errors */
206 if ((res < WSABASEERR) || (res >= 0x10000000)) res = RtlNtStatusToDosError(res);
207 SetLastError( res );
209 return res;
212 static int _check_ws(LPWSINFO pwsi, SOCKET s);
213 static char* _check_buffer(LPWSINFO pwsi, int size);
215 static int _get_sock_fd(SOCKET s)
217 struct get_read_fd_request *req = get_req_buffer();
218 int fd;
220 req->handle = s;
221 server_call_fd( REQ_GET_READ_FD, -1, &fd );
222 if (fd == -1)
223 FIXME("handle %d is not a socket (GLE %ld)\n",s,GetLastError());
224 return fd;
227 static void _enable_event(SOCKET s, unsigned int event,
228 unsigned int sstate, unsigned int cstate)
230 struct enable_socket_event_request *req = get_req_buffer();
232 req->handle = s;
233 req->mask = event;
234 req->sstate = sstate;
235 req->cstate = cstate;
236 sock_server_call( REQ_ENABLE_SOCKET_EVENT );
239 static int _is_blocking(SOCKET s)
241 struct get_socket_event_request *req = get_req_buffer();
243 req->handle = s;
244 req->service = FALSE;
245 req->s_event = 0;
246 req->c_event = 0;
247 sock_server_call( REQ_GET_SOCKET_EVENT );
248 return (req->state & WS_FD_NONBLOCKING) == 0;
251 static unsigned int _get_sock_mask(SOCKET s)
253 struct get_socket_event_request *req = get_req_buffer();
255 req->handle = s;
256 req->service = FALSE;
257 req->s_event = 0;
258 req->c_event = 0;
259 sock_server_call( REQ_GET_SOCKET_EVENT );
260 return req->mask;
263 static void _sync_sock_state(SOCKET s)
265 /* do a dummy wineserver request in order to let
266 the wineserver run through its select loop once */
267 (void)_is_blocking(s);
270 static int _get_sock_error(SOCKET s, unsigned int bit)
272 struct get_socket_event_request *req = get_req_buffer();
274 req->handle = s;
275 req->service = FALSE;
276 req->s_event = 0;
277 req->c_event = 0;
278 sock_server_call( REQ_GET_SOCKET_EVENT );
279 return req->errors[bit];
282 static LPWSINFO lpFirstIData = NULL;
284 static LPWSINFO WINSOCK_GetIData(void)
286 DWORD pid = GetCurrentProcessId();
287 LPWSINFO iData;
289 for (iData = lpFirstIData; iData; iData = iData->lpNextIData) {
290 if (iData->dwThisProcess == pid)
291 break;
293 return iData;
296 static BOOL WINSOCK_CreateIData(void)
298 LPWSINFO iData;
300 iData = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(WSINFO));
301 if (!iData)
302 return FALSE;
303 iData->dwThisProcess = GetCurrentProcessId();
304 iData->lpNextIData = lpFirstIData;
305 lpFirstIData = iData;
306 return TRUE;
309 static void WINSOCK_DeleteIData(void)
311 LPWSINFO iData = WINSOCK_GetIData();
312 LPWSINFO* ppid;
313 if (iData) {
314 for (ppid = &lpFirstIData; *ppid; ppid = &(*ppid)->lpNextIData) {
315 if (*ppid == iData) {
316 *ppid = iData->lpNextIData;
317 break;
321 if( iData->flags & WSI_BLOCKINGCALL )
322 TRACE("\tinside blocking call!\n");
324 /* delete scratch buffers */
326 if( iData->buffer ) SEGPTR_FREE(iData->buffer);
327 if( iData->dbuffer ) SEGPTR_FREE(iData->dbuffer);
329 HeapFree(GetProcessHeap(), 0, iData);
333 /***********************************************************************
334 * WSOCK32_LibMain (WSOCK32.init)
336 BOOL WINAPI WSOCK32_LibMain(HINSTANCE hInstDLL, DWORD fdwReason, LPVOID fImpLoad)
338 TRACE("0x%x 0x%lx %p\n", hInstDLL, fdwReason, fImpLoad);
339 switch (fdwReason) {
340 case DLL_PROCESS_DETACH:
341 WINSOCK_DeleteIData();
342 break;
344 return TRUE;
347 /***********************************************************************
348 * WINSOCK_LibMain (WINSOCK.init)
350 BOOL WINAPI WINSOCK_LibMain(DWORD fdwReason, HINSTANCE hInstDLL, WORD ds,
351 WORD wHeapSize, DWORD dwReserved1, WORD wReserved2)
353 TRACE("0x%x 0x%lx\n", hInstDLL, fdwReason);
354 switch (fdwReason) {
355 case DLL_PROCESS_DETACH:
356 WINSOCK_DeleteIData();
357 break;
359 return TRUE;
362 /***********************************************************************
363 * convert_sockopt()
365 * Converts socket flags from Windows format.
367 static void convert_sockopt(INT *level, INT *optname)
369 int i;
370 switch (*level)
372 case WS_SOL_SOCKET:
373 *level = SOL_SOCKET;
374 for(i=0; _ws_sock_ops[i]; i++)
375 if( _ws_sock_ops[i] == *optname ) break;
376 if( _ws_sock_ops[i] ) *optname = _px_sock_ops[i];
377 else FIXME("Unknown SOL_SOCKET optname %d\n", *optname);
378 break;
379 case WS_IPPROTO_TCP:
380 *level = IPPROTO_TCP;
381 for(i=0; _ws_tcp_ops[i]; i++)
382 if ( _ws_tcp_ops[i] == *optname ) break;
383 if( _ws_tcp_ops[i] ) *optname = _px_tcp_ops[i];
384 else FIXME("Unknown IPPROTO_TCP optname %d\n", *optname);
385 break;
389 /* ----------------------------------- Per-thread info (or per-process?) */
391 static int wsi_strtolo(LPWSINFO pwsi, const char* name, const char* opt)
393 /* Stuff a lowercase copy of the string into the local buffer */
395 int i = strlen(name) + 2;
396 char* p = _check_buffer(pwsi, i + ((opt)?strlen(opt):0));
398 if( p )
400 do *p++ = tolower(*name); while(*name++);
401 i = (p - (char*)(pwsi->buffer));
402 if( opt ) do *p++ = tolower(*opt); while(*opt++);
403 return i;
405 return 0;
408 static fd_set* fd_set_import( fd_set* fds, LPWSINFO pwsi, void* wsfds, int* highfd, int lfd[], BOOL b32 )
410 /* translate Winsock fd set into local fd set */
412 if( wsfds )
414 #define wsfds16 ((ws_fd_set16*)wsfds)
415 #define wsfds32 ((ws_fd_set32*)wsfds)
416 int i, count;
418 FD_ZERO(fds);
419 count = b32 ? wsfds32->fd_count : wsfds16->fd_count;
421 for( i = 0; i < count; i++ )
423 int s = (b32) ? wsfds32->fd_array[i]
424 : wsfds16->fd_array[i];
425 if( _check_ws(pwsi, s) )
427 int fd = _get_sock_fd(s);
428 lfd[ i ] = fd;
429 if( fd > *highfd ) *highfd = fd;
430 FD_SET(fd, fds);
432 else lfd[ i ] = -1;
434 #undef wsfds32
435 #undef wsfds16
436 return fds;
438 return NULL;
441 inline static int sock_error_p(int s)
443 unsigned int optval, optlen;
445 optlen = sizeof(optval);
446 getsockopt(s, SOL_SOCKET, SO_ERROR, (void *) &optval, &optlen);
447 if (optval) WARN("\t[%i] error: %d\n", s, optval);
448 return optval != 0;
451 static int fd_set_export( LPWSINFO pwsi, fd_set* fds, fd_set* exceptfds, void* wsfds, int lfd[], BOOL b32 )
453 int num_err = 0;
455 /* translate local fd set into Winsock fd set, adding
456 * errors to exceptfds (only if app requested it) */
458 if( wsfds )
460 #define wsfds16 ((ws_fd_set16*)wsfds)
461 #define wsfds32 ((ws_fd_set32*)wsfds)
462 int i, j, count = (b32) ? wsfds32->fd_count : wsfds16->fd_count;
464 for( i = 0, j = 0; i < count; i++ )
466 if( lfd[i] >= 0 )
468 int fd = lfd[i];
469 if( FD_ISSET(fd, fds) )
471 if ( exceptfds && sock_error_p(fd) )
473 FD_SET(fd, exceptfds);
474 num_err++;
476 else if( b32 )
477 wsfds32->fd_array[j++] = wsfds32->fd_array[i];
478 else
479 wsfds16->fd_array[j++] = wsfds16->fd_array[i];
481 close(fd);
482 lfd[i] = -1;
486 if( b32 ) wsfds32->fd_count = j;
487 else wsfds16->fd_count = j;
489 TRACE("\n");
490 #undef wsfds32
491 #undef wsfds16
493 return num_err;
496 static void fd_set_unimport( void* wsfds, int lfd[], BOOL b32 )
498 if ( wsfds )
500 #define wsfds16 ((ws_fd_set16*)wsfds)
501 #define wsfds32 ((ws_fd_set32*)wsfds)
502 int i, count = (b32) ? wsfds32->fd_count : wsfds16->fd_count;
504 for( i = 0; i < count; i++ )
505 if ( lfd[i] >= 0 )
506 close(lfd[i]);
508 TRACE("\n");
509 #undef wsfds32
510 #undef wsfds16
514 static int do_block( int fd, int mask )
516 fd_set fds[3];
517 int i, r;
519 FD_ZERO(&fds[0]);
520 FD_ZERO(&fds[1]);
521 FD_ZERO(&fds[2]);
522 for (i=0; i<3; i++)
523 if (mask & (1<<i))
524 FD_SET(fd, &fds[i]);
525 i = select( fd+1, &fds[0], &fds[1], &fds[2], NULL );
526 if (i <= 0) return -1;
527 r = 0;
528 for (i=0; i<3; i++)
529 if (FD_ISSET(fd, &fds[i]))
530 r |= 1<<i;
531 return r;
534 void* __ws_memalloc( int size )
536 return WS_ALLOC(size);
539 void __ws_memfree(void* ptr)
541 WS_FREE(ptr);
545 /* ----------------------------------- API -----
547 * Init / cleanup / error checking.
550 /***********************************************************************
551 * WSAStartup16() (WINSOCK.115)
553 * Create socket control struct, attach it to the global list and
554 * update a pointer in the task struct.
556 INT16 WINAPI WSAStartup16(UINT16 wVersionRequested, LPWSADATA lpWSAData)
558 WSADATA WINSOCK_data = { 0x0101, 0x0101,
559 "WINE Sockets 1.1",
560 #ifdef linux
561 "Linux/i386",
562 #elif defined(__NetBSD__)
563 "NetBSD/i386",
564 #elif defined(sunos)
565 "SunOS",
566 #elif defined(__FreeBSD__)
567 "FreeBSD",
568 #elif defined(__OpenBSD__)
569 "OpenBSD/i386",
570 #else
571 "Unknown",
572 #endif
573 WS_MAX_SOCKETS_PER_PROCESS,
574 WS_MAX_UDP_DATAGRAM, (SEGPTR)NULL };
575 LPWSINFO pwsi;
577 TRACE("verReq=%x\n", wVersionRequested);
579 if (LOBYTE(wVersionRequested) < 1 || (LOBYTE(wVersionRequested) == 1 &&
580 HIBYTE(wVersionRequested) < 1)) return WSAVERNOTSUPPORTED;
582 if (!lpWSAData) return WSAEINVAL;
584 /* initialize socket heap */
586 if( !_WSHeap )
588 _WSHeap = HeapCreate(HEAP_ZERO_MEMORY, 8120, 32768);
589 if( !_WSHeap )
591 ERR("Fatal: failed to create WinSock heap\n");
592 return 0;
595 if( _WSHeap == 0 ) return WSASYSNOTREADY;
597 pwsi = WINSOCK_GetIData();
598 if( pwsi == NULL )
600 WINSOCK_CreateIData();
601 pwsi = WINSOCK_GetIData();
602 if (!pwsi) return WSASYSNOTREADY;
604 pwsi->num_startup++;
606 /* return winsock information */
608 memcpy(lpWSAData, &WINSOCK_data, sizeof(WINSOCK_data));
610 TRACE("succeeded\n");
611 return 0;
614 /***********************************************************************
615 * WSAStartup() (WS2_32.115)
617 INT WINAPI WSAStartup(UINT wVersionRequested, LPWSADATA lpWSAData)
619 WSADATA WINSOCK_data = { 0x0202, 0x0202,
620 "WINE Sockets 2.0",
621 #ifdef linux
622 "Linux/i386",
623 #elif defined(__NetBSD__)
624 "NetBSD/i386",
625 #elif defined(sunos)
626 "SunOS",
627 #elif defined(__FreeBSD__)
628 "FreeBSD",
629 #elif defined(__OpenBSD__)
630 "OpenBSD/i386",
631 #else
632 "Unknown",
633 #endif
634 WS_MAX_SOCKETS_PER_PROCESS,
635 WS_MAX_UDP_DATAGRAM, (SEGPTR)NULL };
636 LPWSINFO pwsi;
638 TRACE("verReq=%x\n", wVersionRequested);
640 if (LOBYTE(wVersionRequested) < 1)
641 return WSAVERNOTSUPPORTED;
643 if (!lpWSAData) return WSAEINVAL;
645 /* initialize socket heap */
647 if( !_WSHeap )
649 _WSHeap = HeapCreate(HEAP_ZERO_MEMORY, 8120, 32768);
650 if( !_WSHeap )
652 ERR("Fatal: failed to create WinSock heap\n");
653 return 0;
656 if( _WSHeap == 0 ) return WSASYSNOTREADY;
658 pwsi = WINSOCK_GetIData();
659 if( pwsi == NULL )
661 WINSOCK_CreateIData();
662 pwsi = WINSOCK_GetIData();
663 if (!pwsi) return WSASYSNOTREADY;
665 pwsi->num_startup++;
667 /* return winsock information */
668 memcpy(lpWSAData, &WINSOCK_data, sizeof(WINSOCK_data));
670 /* that's the whole of the negotiation for now */
671 lpWSAData->wVersion = wVersionRequested;
673 TRACE("succeeded\n");
674 return 0;
678 /***********************************************************************
679 * WSACleanup() (WINSOCK.116)
681 INT WINAPI WSACleanup(void)
683 LPWSINFO pwsi = WINSOCK_GetIData();
684 if( pwsi ) {
685 if( --pwsi->num_startup > 0 ) return 0;
687 WINSOCK_DeleteIData();
688 return 0;
690 SetLastError(WSANOTINITIALISED);
691 return SOCKET_ERROR;
695 /***********************************************************************
696 * WSAGetLastError() (WSOCK32.111)(WINSOCK.111)
698 INT WINAPI WSAGetLastError(void)
700 return GetLastError();
703 /***********************************************************************
704 * WSASetLastError() (WSOCK32.112)
706 void WINAPI WSASetLastError(INT iError) {
707 SetLastError(iError);
710 /***********************************************************************
711 * WSASetLastError16() (WINSOCK.112)
713 void WINAPI WSASetLastError16(INT16 iError)
715 WSASetLastError(iError);
718 int _check_ws(LPWSINFO pwsi, SOCKET s)
720 if( pwsi )
722 int fd;
723 if( pwsi->flags & WSI_BLOCKINGCALL ) SetLastError(WSAEINPROGRESS);
724 if ( (fd = _get_sock_fd(s)) < 0 ) {
725 SetLastError(WSAENOTSOCK);
726 return 0;
728 /* FIXME: maybe check whether fd is really a socket? */
729 close( fd );
730 return 1;
732 return 0;
735 char* _check_buffer(LPWSINFO pwsi, int size)
737 if( pwsi->buffer && pwsi->buflen >= size ) return pwsi->buffer;
738 else SEGPTR_FREE(pwsi->buffer);
740 pwsi->buffer = (char*)SEGPTR_ALLOC((pwsi->buflen = size));
741 return pwsi->buffer;
744 struct ws_hostent* _check_buffer_he(LPWSINFO pwsi, int size)
746 if( pwsi->he && pwsi->helen >= size ) return pwsi->he;
747 else SEGPTR_FREE(pwsi->he);
749 pwsi->he = (struct ws_hostent*)SEGPTR_ALLOC((pwsi->helen = size));
750 return pwsi->he;
753 struct ws_servent* _check_buffer_se(LPWSINFO pwsi, int size)
755 if( pwsi->se && pwsi->selen >= size ) return pwsi->se;
756 else SEGPTR_FREE(pwsi->se);
758 pwsi->se = (struct ws_servent*)SEGPTR_ALLOC((pwsi->selen = size));
759 return pwsi->se;
762 struct ws_protoent* _check_buffer_pe(LPWSINFO pwsi, int size)
764 if( pwsi->pe && pwsi->pelen >= size ) return pwsi->pe;
765 else SEGPTR_FREE(pwsi->pe);
767 pwsi->pe = (struct ws_protoent*)SEGPTR_ALLOC((pwsi->pelen = size));
768 return pwsi->pe;
771 /* ----------------------------------- i/o APIs */
773 /***********************************************************************
774 * accept() (WSOCK32.1)
776 static void WSOCK32_async_accept(LPWSINFO pwsi, SOCKET s, SOCKET as)
778 int q;
779 /* queue socket for WSAAsyncSelect */
780 for (q=0; q<WS_ACCEPT_QUEUE; q++)
781 if (InterlockedCompareExchange((PVOID*)&pwsi->accept_old[q], (PVOID)s, (PVOID)0) == (PVOID)0)
782 break;
783 if (q<WS_ACCEPT_QUEUE)
784 pwsi->accept_new[q] = as;
785 else
786 ERR("accept queue too small\n");
787 /* now signal our AsyncSelect handler */
788 _enable_event(s, WS_FD_SERVEVENT, 0, 0);
791 SOCKET WINAPI WSOCK32_accept(SOCKET s, struct sockaddr *addr,
792 INT *addrlen32)
794 LPWSINFO pwsi = WINSOCK_GetIData();
795 #ifdef HAVE_IPX
796 struct ws_sockaddr_ipx* addr2 = (struct ws_sockaddr_ipx *)addr;
797 #endif
798 struct accept_socket_request *req = get_req_buffer();
800 TRACE("(%08x): socket %04x\n",
801 (unsigned)pwsi, (UINT16)s );
802 if( _check_ws(pwsi, s) )
804 if (_is_blocking(s))
806 /* block here */
807 int fd = _get_sock_fd(s);
808 do_block(fd, 5);
809 close(fd);
810 _sync_sock_state(s); /* let wineserver notice connection */
811 /* retrieve any error codes from it */
812 SetLastError(_get_sock_error(s, FD_ACCEPT_BIT));
813 /* FIXME: care about the error? */
815 req->lhandle = s;
816 req->access = GENERIC_READ|GENERIC_WRITE|SYNCHRONIZE;
817 req->inherit = TRUE;
818 sock_server_call( REQ_ACCEPT_SOCKET );
819 if( req->handle >= 0 )
821 SOCKET as = req->handle;
822 unsigned omask = _get_sock_mask( s );
823 int fd = _get_sock_fd( as );
824 if( getpeername(fd, addr, addrlen32) != -1 )
826 #ifdef HAVE_IPX
827 if (addr && ((struct sockaddr_ipx *)addr)->sipx_family == AF_IPX) {
828 addr = (struct sockaddr *)
829 malloc(addrlen32 ? *addrlen32 : sizeof(*addr2));
830 memcpy(addr, addr2,
831 addrlen32 ? *addrlen32 : sizeof(*addr2));
832 addr2->sipx_family = WS_AF_IPX;
833 addr2->sipx_network = ((struct sockaddr_ipx *)addr)->sipx_network;
834 addr2->sipx_port = ((struct sockaddr_ipx *)addr)->sipx_port;
835 memcpy(addr2->sipx_node,
836 ((struct sockaddr_ipx *)addr)->sipx_node, IPX_NODE_LEN);
837 free(addr);
839 #endif
840 } else SetLastError(wsaErrno());
841 close(fd);
842 if (omask & WS_FD_SERVEVENT)
843 WSOCK32_async_accept(pwsi, s, as);
844 return as;
847 return INVALID_SOCKET;
850 /***********************************************************************
851 * accept() (WINSOCK.1)
853 SOCKET16 WINAPI WINSOCK_accept16(SOCKET16 s, struct sockaddr* addr,
854 INT16* addrlen16 )
856 INT addrlen32 = addrlen16 ? *addrlen16 : 0;
857 SOCKET retSocket = WSOCK32_accept( s, addr, &addrlen32 );
858 if( addrlen16 ) *addrlen16 = (INT16)addrlen32;
859 return (SOCKET16)retSocket;
862 /***********************************************************************
863 * bind() (WSOCK32.2)
865 INT WINAPI WSOCK32_bind(SOCKET s, struct sockaddr *name, INT namelen)
867 LPWSINFO pwsi = WINSOCK_GetIData();
868 #ifdef HAVE_IPX
869 struct ws_sockaddr_ipx* name2 = (struct ws_sockaddr_ipx *)name;
870 #endif
872 TRACE("(%08x): socket %04x, ptr %8x, length %d\n",
873 (unsigned)pwsi, s, (int) name, namelen);
874 #if DEBUG_SOCKADDR
875 dump_sockaddr(name);
876 #endif
878 if ( _check_ws(pwsi, s) )
880 int fd = _get_sock_fd(s);
881 /* FIXME: what family does this really map to on the Unix side? */
882 if (name && ((struct ws_sockaddr_ipx *)name)->sipx_family == WS_AF_PUP)
883 ((struct ws_sockaddr_ipx *)name)->sipx_family = AF_UNSPEC;
884 #ifdef HAVE_IPX
885 else if (name &&
886 ((struct ws_sockaddr_ipx *)name)->sipx_family == WS_AF_IPX)
888 name = (struct sockaddr *) malloc(sizeof(struct sockaddr_ipx));
889 memset(name, '\0', sizeof(struct sockaddr_ipx));
890 ((struct sockaddr_ipx *)name)->sipx_family = AF_IPX;
891 ((struct sockaddr_ipx *)name)->sipx_port = name2->sipx_port;
892 ((struct sockaddr_ipx *)name)->sipx_network = name2->sipx_network;
893 memcpy(((struct sockaddr_ipx *)name)->sipx_node,
894 name2->sipx_node, IPX_NODE_LEN);
895 namelen = sizeof(struct sockaddr_ipx);
897 #endif
898 if ( namelen >= sizeof(*name) )
900 if ( name && (((struct ws_sockaddr_in *)name)->sin_family == AF_INET
901 #ifdef HAVE_IPX
902 || ((struct sockaddr_ipx *)name)->sipx_family == AF_IPX
903 #endif
906 if ( bind(fd, name, namelen) < 0 )
908 int loc_errno = errno;
909 WARN("\tfailure - errno = %i\n", errno);
910 errno = loc_errno;
911 switch(errno)
913 case EBADF: SetLastError(WSAENOTSOCK); break;
914 case EADDRNOTAVAIL: SetLastError(WSAEINVAL); break;
915 default: SetLastError(wsaErrno());break;
918 else {
919 #ifdef HAVE_IPX
920 if (((struct sockaddr_ipx *)name)->sipx_family == AF_IPX)
921 free(name);
922 #endif
923 close(fd);
924 return 0; /* success */
926 } else SetLastError(WSAEAFNOSUPPORT);
927 } else SetLastError(WSAEFAULT);
928 #ifdef HAVE_IPX
929 if (name && ((struct sockaddr_ipx *)name)->sipx_family == AF_IPX)
930 free(name);
931 #endif
932 close(fd);
934 return SOCKET_ERROR;
937 /***********************************************************************
938 * bind() (WINSOCK.2)
940 INT16 WINAPI WINSOCK_bind16(SOCKET16 s, struct sockaddr *name, INT16 namelen)
942 return (INT16)WSOCK32_bind( s, name, namelen );
945 /***********************************************************************
946 * closesocket() (WSOCK32.3)
948 INT WINAPI WSOCK32_closesocket(SOCKET s)
950 LPWSINFO pwsi = WINSOCK_GetIData();
952 TRACE("(%08x): socket %08x\n", (unsigned)pwsi, s);
954 if( _check_ws(pwsi, s) )
956 if( CloseHandle(s) )
957 return 0;
959 return SOCKET_ERROR;
962 /***********************************************************************
963 * closesocket() (WINSOCK.3)
965 INT16 WINAPI WINSOCK_closesocket16(SOCKET16 s)
967 return (INT16)WSOCK32_closesocket(s);
970 /***********************************************************************
971 * connect() (WSOCK32.4)
973 INT WINAPI WSOCK32_connect(SOCKET s, struct sockaddr *name, INT namelen)
975 LPWSINFO pwsi = WINSOCK_GetIData();
976 #ifdef HAVE_IPX
977 struct ws_sockaddr_ipx* name2 = (struct ws_sockaddr_ipx *)name;
978 #endif
980 TRACE("(%08x): socket %04x, ptr %8x, length %d\n",
981 (unsigned)pwsi, s, (int) name, namelen);
982 #if DEBUG_SOCKADDR
983 dump_sockaddr(name);
984 #endif
986 if( _check_ws(pwsi, s) )
988 int fd = _get_sock_fd(s);
989 if (name && ((struct ws_sockaddr_ipx *)name)->sipx_family == WS_AF_PUP)
990 ((struct ws_sockaddr_ipx *)name)->sipx_family = AF_UNSPEC;
991 #ifdef HAVE_IPX
992 else if (name && ((struct ws_sockaddr_ipx *)name)->sipx_family == WS_AF_IPX)
994 name = (struct sockaddr *) malloc(sizeof(struct sockaddr_ipx));
995 memset(name, '\0', sizeof(struct sockaddr_ipx));
996 ((struct sockaddr_ipx *)name)->sipx_family = AF_IPX;
997 ((struct sockaddr_ipx *)name)->sipx_port = name2->sipx_port;
998 ((struct sockaddr_ipx *)name)->sipx_network = name2->sipx_network;
999 memcpy(((struct sockaddr_ipx *)name)->sipx_node,
1000 name2->sipx_node, IPX_NODE_LEN);
1001 namelen = sizeof(struct sockaddr_ipx);
1003 #endif
1004 if (connect(fd, name, namelen) == 0) {
1005 close(fd);
1006 goto connect_success;
1008 if (errno == EINPROGRESS)
1010 /* tell wineserver that a connection is in progress */
1011 _enable_event(s, FD_CONNECT|FD_READ|FD_WRITE,
1012 WS_FD_CONNECT|WS_FD_READ|WS_FD_WRITE,
1013 WS_FD_CONNECTED|WS_FD_LISTENING);
1014 if (_is_blocking(s))
1016 int result;
1017 /* block here */
1018 do_block(fd, 6);
1019 _sync_sock_state(s); /* let wineserver notice connection */
1020 /* retrieve any error codes from it */
1021 result = _get_sock_error(s, FD_CONNECT_BIT);
1022 if (result)
1023 SetLastError(result);
1024 else {
1025 close(fd);
1026 goto connect_success;
1029 else SetLastError(WSAEWOULDBLOCK);
1030 close(fd);
1032 else
1034 SetLastError(wsaErrno());
1035 close(fd);
1038 #ifdef HAVE_IPX
1039 if (name && ((struct sockaddr_ipx *)name)->sipx_family == AF_IPX)
1040 free(name);
1041 #endif
1042 return SOCKET_ERROR;
1043 connect_success:
1044 #ifdef HAVE_IPX
1045 if (((struct sockaddr_ipx *)name)->sipx_family == AF_IPX)
1046 free(name);
1047 #endif
1048 _enable_event(s, FD_CONNECT|FD_READ|FD_WRITE,
1049 WS_FD_CONNECTED|WS_FD_READ|WS_FD_WRITE,
1050 WS_FD_CONNECT|WS_FD_LISTENING);
1051 return 0;
1054 /***********************************************************************
1055 * connect() (WINSOCK.4)
1057 INT16 WINAPI WINSOCK_connect16(SOCKET16 s, struct sockaddr *name, INT16 namelen)
1059 return (INT16)WSOCK32_connect( s, name, namelen );
1062 /***********************************************************************
1063 * getpeername() (WSOCK32.5)
1065 INT WINAPI WSOCK32_getpeername(SOCKET s, struct sockaddr *name,
1066 INT *namelen)
1068 LPWSINFO pwsi = WINSOCK_GetIData();
1069 #ifdef HAVE_IPX
1070 struct ws_sockaddr_ipx* name2 = (struct ws_sockaddr_ipx *)name;
1071 #endif
1073 TRACE("(%08x): socket: %04x, ptr %8x, ptr %8x\n",
1074 (unsigned)pwsi, s, (int) name, *namelen);
1075 if( _check_ws(pwsi, s) )
1077 int fd = _get_sock_fd(s);
1078 if (getpeername(fd, name, namelen) == 0) {
1079 #ifdef HAVE_IPX
1080 if (((struct ws_sockaddr_ipx *)name)->sipx_family == AF_IPX) {
1081 name = (struct sockaddr *)
1082 malloc(namelen ? *namelen : sizeof(*name2));
1083 memcpy(name, name2, namelen ? *namelen : sizeof(*name2));
1084 name2->sipx_family = WS_AF_IPX;
1085 name2->sipx_network = ((struct sockaddr_ipx *)name)->sipx_network;
1086 name2->sipx_port = ((struct sockaddr_ipx *)name)->sipx_port;
1087 memcpy(name2->sipx_node,
1088 ((struct sockaddr_ipx *)name)->sipx_node, IPX_NODE_LEN);
1089 free(name);
1091 #endif
1092 close(fd);
1093 return 0;
1095 SetLastError(wsaErrno());
1096 close(fd);
1098 return SOCKET_ERROR;
1101 /***********************************************************************
1102 * getpeername() (WINSOCK.5)
1104 INT16 WINAPI WINSOCK_getpeername16(SOCKET16 s, struct sockaddr *name,
1105 INT16 *namelen16)
1107 INT namelen32 = *namelen16;
1108 INT retVal = WSOCK32_getpeername( s, name, &namelen32 );
1110 #if DEBUG_SOCKADDR
1111 dump_sockaddr(name);
1112 #endif
1114 *namelen16 = namelen32;
1115 return (INT16)retVal;
1118 /***********************************************************************
1119 * getsockname() (WSOCK32.6)
1121 INT WINAPI WSOCK32_getsockname(SOCKET s, struct sockaddr *name,
1122 INT *namelen)
1124 LPWSINFO pwsi = WINSOCK_GetIData();
1125 #ifdef HAVE_IPX
1126 struct ws_sockaddr_ipx* name2 = (struct ws_sockaddr_ipx *)name;
1127 #endif
1129 TRACE("(%08x): socket: %04x, ptr %8x, ptr %8x\n",
1130 (unsigned)pwsi, s, (int) name, (int) *namelen);
1131 if( _check_ws(pwsi, s) )
1133 int fd = _get_sock_fd(s);
1134 if (getsockname(fd, name, namelen) == 0) {
1135 #ifdef HAVE_IPX
1136 if (((struct sockaddr_ipx *)name)->sipx_family == AF_IPX) {
1137 name = (struct sockaddr *)
1138 malloc(namelen ? *namelen : sizeof(*name2));
1139 memcpy(name, name2, namelen ? *namelen : sizeof(*name2));
1140 name2->sipx_family = WS_AF_IPX;
1141 name2->sipx_network = ((struct sockaddr_ipx *)name)->sipx_network;
1142 name2->sipx_port = ((struct sockaddr_ipx *)name)->sipx_port;
1143 memcpy(name2->sipx_node,
1144 ((struct sockaddr_ipx *)name)->sipx_node, IPX_NODE_LEN);
1145 free(name);
1147 #endif
1148 close(fd);
1149 return 0;
1151 SetLastError(wsaErrno());
1152 close(fd);
1154 return SOCKET_ERROR;
1157 /***********************************************************************
1158 * getsockname() (WINSOCK.6)
1160 INT16 WINAPI WINSOCK_getsockname16(SOCKET16 s, struct sockaddr *name,
1161 INT16 *namelen16)
1163 INT retVal;
1165 if( namelen16 )
1167 INT namelen32 = *namelen16;
1168 retVal = WSOCK32_getsockname( s, name, &namelen32 );
1169 *namelen16 = namelen32;
1171 #if DEBUG_SOCKADDR
1172 dump_sockaddr(name);
1173 #endif
1176 else retVal = SOCKET_ERROR;
1177 return (INT16)retVal;
1181 /***********************************************************************
1182 * getsockopt() (WSOCK32.7)
1184 INT WINAPI WSOCK32_getsockopt(SOCKET s, INT level,
1185 INT optname, char *optval, INT *optlen)
1187 LPWSINFO pwsi = WINSOCK_GetIData();
1189 TRACE("(%08x): socket: %04x, opt %d, ptr %8x, ptr %8x\n",
1190 (unsigned)pwsi, s, level, (int) optval, (int) *optlen);
1191 if( _check_ws(pwsi, s) )
1193 int fd = _get_sock_fd(s);
1194 convert_sockopt(&level, &optname);
1195 if (getsockopt(fd, (int) level, optname, optval, optlen) == 0 )
1197 close(fd);
1198 return 0;
1200 SetLastError((errno == EBADF) ? WSAENOTSOCK : wsaErrno());
1201 close(fd);
1203 return SOCKET_ERROR;
1206 /***********************************************************************
1207 * getsockopt() (WINSOCK.7)
1209 INT16 WINAPI WINSOCK_getsockopt16(SOCKET16 s, INT16 level,
1210 INT16 optname, char *optval, INT16 *optlen)
1212 INT optlen32;
1213 INT *p = &optlen32;
1214 INT retVal;
1215 if( optlen ) optlen32 = *optlen; else p = NULL;
1216 retVal = WSOCK32_getsockopt( s, (UINT16)level, optname, optval, p );
1217 if( optlen ) *optlen = optlen32;
1218 return (INT16)retVal;
1221 /***********************************************************************
1222 * htonl() (WINSOCK.8)(WSOCK32.8)
1224 u_long WINAPI WINSOCK_htonl(u_long hostlong) { return( htonl(hostlong) ); }
1225 /***********************************************************************
1226 * htons() (WINSOCK.9)(WSOCK32.9)
1228 u_short WINAPI WINSOCK_htons(u_short hostshort) { return( htons(hostshort) ); }
1229 /***********************************************************************
1230 * inet_addr() (WINSOCK.10)(WSOCK32.10)
1232 u_long WINAPI WINSOCK_inet_addr(char *cp) { return( inet_addr(cp) ); }
1233 /***********************************************************************
1234 * ntohl() (WINSOCK.14)(WSOCK32.14)
1236 u_long WINAPI WINSOCK_ntohl(u_long netlong) { return( ntohl(netlong) ); }
1237 /***********************************************************************
1238 * ntohs() (WINSOCK.15)(WSOCK32.15)
1240 u_short WINAPI WINSOCK_ntohs(u_short netshort) { return( ntohs(netshort) ); }
1242 /***********************************************************************
1243 * inet_ntoa() (WINSOCK.11)(WSOCK32.11)
1245 char* WINAPI WSOCK32_inet_ntoa(struct in_addr in)
1247 /* use "buffer for dummies" here because some applications have
1248 * propensity to decode addresses in ws_hostent structure without
1249 * saving them first...
1252 LPWSINFO pwsi = WINSOCK_GetIData();
1254 if( pwsi )
1256 char* s = inet_ntoa(in);
1257 if( s )
1259 if( pwsi->dbuffer == NULL ) {
1260 /* Yes, 16: 4*3 digits + 3 '.' + 1 '\0' */
1261 if((pwsi->dbuffer = (char*) SEGPTR_ALLOC(16)) == NULL )
1263 SetLastError(WSAENOBUFS);
1264 return NULL;
1267 strcpy(pwsi->dbuffer, s);
1268 return pwsi->dbuffer;
1270 SetLastError(wsaErrno());
1272 return NULL;
1275 SEGPTR WINAPI WINSOCK_inet_ntoa16(struct in_addr in)
1277 char* retVal = WSOCK32_inet_ntoa(in);
1278 return retVal ? SEGPTR_GET(retVal) : (SEGPTR)NULL;
1282 /**********************************************************************
1283 * WSAIoctl (WS2_32)
1286 * FIXME: Only SIO_GET_INTERFACE_LIST option implemented.
1288 INT WINAPI WSAIoctl (SOCKET s,
1289 DWORD dwIoControlCode,
1290 LPVOID lpvInBuffer,
1291 DWORD cbInBuffer,
1292 LPVOID lpbOutBuffer,
1293 DWORD cbOutBuffer,
1294 LPDWORD lpcbBytesReturned,
1295 LPWSAOVERLAPPED lpOverlapped,
1296 LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine)
1298 LPWSINFO pwsi = WINSOCK_GetIData();
1300 if( _check_ws(pwsi, s) )
1302 int fd = _get_sock_fd(s);
1304 switch( dwIoControlCode )
1306 case SIO_GET_INTERFACE_LIST:
1308 INTERFACE_INFO* intArray = (INTERFACE_INFO*)lpbOutBuffer;
1309 int i, numInt;
1310 struct ifreq ifInfo;
1311 char ifName[512];
1314 TRACE ("-> SIO_GET_INTERFACE_LIST request\n");
1316 numInt = WSAIOCTL_GetInterfaceCount();
1317 if (numInt < 0)
1319 ERR ("Unable to open /proc filesystem to determine number of network interfaces!\n");
1320 close(fd);
1321 WSASetLastError(WSAEINVAL);
1322 return (SOCKET_ERROR);
1325 for (i=0; i<numInt; i++)
1327 if (!WSAIOCTL_GetInterfaceName(i, ifName))
1329 ERR ("Error parsing /proc filesystem!\n");
1330 close(fd);
1331 WSASetLastError(WSAEINVAL);
1332 return (SOCKET_ERROR);
1335 ifInfo.ifr_addr.sa_family = AF_INET;
1337 /* IP Address */
1338 strcpy (ifInfo.ifr_name, ifName);
1339 if (ioctl(fd, SIOCGIFADDR, &ifInfo) < 0)
1341 ERR ("Error obtaining IP address\n");
1342 close(fd);
1343 WSASetLastError(WSAEINVAL);
1344 return (SOCKET_ERROR);
1346 else
1348 struct ws_sockaddr_in *ipTemp = (struct ws_sockaddr_in *)&ifInfo.ifr_addr;
1350 intArray->iiAddress.AddressIn.sin_family = AF_INET;
1351 intArray->iiAddress.AddressIn.sin_port = ipTemp->sin_port;
1352 intArray->iiAddress.AddressIn.sin_addr.ws_addr = ipTemp->sin_addr.S_un.S_addr;
1355 /* Broadcast Address */
1356 strcpy (ifInfo.ifr_name, ifName);
1357 if (ioctl(fd, SIOCGIFBRDADDR, &ifInfo) < 0)
1359 ERR ("Error obtaining Broadcast IP address\n");
1360 close(fd);
1361 WSASetLastError(WSAEINVAL);
1362 return (SOCKET_ERROR);
1364 else
1366 struct ws_sockaddr_in *ipTemp = (struct ws_sockaddr_in *)&ifInfo.ifr_broadaddr;
1368 intArray->iiBroadcastAddress.AddressIn.sin_family = AF_INET;
1369 intArray->iiBroadcastAddress.AddressIn.sin_port = ipTemp->sin_port;
1370 intArray->iiBroadcastAddress.AddressIn.sin_addr.ws_addr = ipTemp->sin_addr.S_un.S_addr;
1373 /* Subnet Mask */
1374 strcpy (ifInfo.ifr_name, ifName);
1375 if (ioctl(fd, SIOCGIFNETMASK, &ifInfo) < 0)
1377 ERR ("Error obtaining Subnet IP address\n");
1378 close(fd);
1379 WSASetLastError(WSAEINVAL);
1380 return (SOCKET_ERROR);
1382 else
1384 /* Trying to avoid some compile problems across platforms.
1385 (Linux, FreeBSD, Solaris...) */
1386 #ifndef ifr_netmask
1387 #ifndef ifr_addr
1388 intArray->iiNetmask.AddressIn.sin_family = AF_INET;
1389 intArray->iiNetmask.AddressIn.sin_port = 0;
1390 intArray->iiNetmask.AddressIn.sin_addr.ws_addr = 0;
1391 ERR ("Unable to determine Netmask on your platform!\n");
1392 #else
1393 struct ws_sockaddr_in *ipTemp = (struct ws_sockaddr_in *)&ifInfo.ifr_addr;
1395 intArray->iiNetmask.AddressIn.sin_family = AF_INET;
1396 intArray->iiNetmask.AddressIn.sin_port = ipTemp->sin_port;
1397 intArray->iiNetmask.AddressIn.sin_addr.ws_addr = ipTemp->sin_addr.S_un.S_addr;
1398 #endif
1399 #else
1400 struct ws_sockaddr_in *ipTemp = (struct ws_sockaddr_in *)&ifInfo.ifr_netmask;
1402 intArray->iiNetmask.AddressIn.sin_family = AF_INET;
1403 intArray->iiNetmask.AddressIn.sin_port = ipTemp->sin_port;
1404 intArray->iiNetmask.AddressIn.sin_addr.ws_addr = ipTemp->sin_addr.S_un.S_addr;
1405 #endif
1408 /* Socket Status Flags */
1409 strcpy(ifInfo.ifr_name, ifName);
1410 if (ioctl(fd, SIOCGIFFLAGS, &ifInfo) < 0)
1412 ERR ("Error obtaining status flags for socket!\n");
1413 close(fd);
1414 WSASetLastError(WSAEINVAL);
1415 return (SOCKET_ERROR);
1417 else
1419 /* FIXME - Is this the right flag to use? */
1420 intArray->iiFlags = ifInfo.ifr_flags;
1422 intArray++; /* Prepare for another interface */
1425 /* Calculate the size of the array being returned */
1426 *lpcbBytesReturned = sizeof(INTERFACE_INFO) * numInt;
1427 break;
1430 default:
1432 WARN("\tunsupported WS_IOCTL cmd (%08lx)\n", dwIoControlCode);
1433 close(fd);
1434 WSASetLastError(WSAEOPNOTSUPP);
1435 return (SOCKET_ERROR);
1439 /* Function executed with no errors */
1440 close(fd);
1441 return (0);
1443 else
1445 WSASetLastError(WSAENOTSOCK);
1446 return (SOCKET_ERROR);
1452 Helper function for WSAIoctl - Get count of the number of interfaces
1453 by parsing /proc filesystem.
1455 int WSAIOCTL_GetInterfaceCount(void)
1457 FILE *procfs;
1458 char buf[512]; /* Size doesn't matter, something big */
1459 int intcnt=0;
1462 /* Open /proc filesystem file for network devices */
1463 procfs = fopen(PROCFS_NETDEV_FILE, "r");
1464 if (!procfs)
1466 /* If we can't open the file, return an error */
1467 return (-1);
1470 /* Omit first two lines, they are only headers */
1471 fgets(buf, sizeof buf, procfs);
1472 fgets(buf, sizeof buf, procfs);
1474 while (fgets(buf, sizeof buf, procfs))
1476 /* Each line in the file represents a network interface */
1477 intcnt++;
1480 fclose(procfs);
1481 return(intcnt);
1486 Helper function for WSAIoctl - Get name of device from interface number
1487 by parsing /proc filesystem.
1489 int WSAIOCTL_GetInterfaceName(int intNumber, char *intName)
1491 FILE *procfs;
1492 char buf[512]; /* Size doesn't matter, something big */
1493 int i;
1495 /* Open /proc filesystem file for network devices */
1496 procfs = fopen(PROCFS_NETDEV_FILE, "r");
1497 if (!procfs)
1499 /* If we can't open the file, return an error */
1500 return (-1);
1503 /* Omit first two lines, they are only headers */
1504 fgets(buf, sizeof(buf), procfs);
1505 fgets(buf, sizeof(buf), procfs);
1507 for (i=0; i<intNumber; i++)
1509 /* Skip the lines that don't interest us. */
1510 fgets(buf, sizeof(buf), procfs);
1512 fgets(buf, sizeof(buf), procfs); /* This is the line we want */
1515 /* Parse out the line, grabbing only the name of the device
1516 to the intName variable
1518 The Line comes in like this: (we only care about the device name)
1519 lo: 21970 377 0 0 0 0 0 0 21970 377 0 0 0 0 0 0
1521 i=0;
1522 while (isspace(buf[i])) /* Skip initial space(s) */
1524 i++;
1527 while (buf[i])
1529 if (isspace(buf[i]))
1531 break;
1534 if (buf[i] == ':') /* FIXME: Not sure if this block (alias detection) works properly */
1536 /* This interface could be an alias... */
1537 int hold = i;
1538 char *dotname = intName;
1539 *intName++ = buf[i++];
1541 while (isdigit(buf[i]))
1543 *intName++ = buf[i++];
1546 if (buf[i] != ':')
1548 /* ... It wasn't, so back up */
1549 i = hold;
1550 intName = dotname;
1553 if (buf[i] == '\0')
1555 fclose(procfs);
1556 return(FALSE);
1559 i++;
1560 break;
1563 *intName++ = buf[i++];
1565 *intName++ = '\0';
1567 fclose(procfs);
1568 return(TRUE);
1572 /***********************************************************************
1573 * ioctlsocket() (WSOCK32.12)
1575 INT WINAPI WSOCK32_ioctlsocket(SOCKET s, LONG cmd, ULONG *argp)
1577 LPWSINFO pwsi = WINSOCK_GetIData();
1579 TRACE("(%08x): socket %04x, cmd %08lx, ptr %8x\n",
1580 (unsigned)pwsi, s, cmd, (unsigned) argp);
1581 if( _check_ws(pwsi, s) )
1583 int fd = _get_sock_fd(s);
1584 long newcmd = cmd;
1586 switch( cmd )
1588 case WS_FIONREAD:
1589 newcmd=FIONREAD;
1590 break;
1592 case WS_FIONBIO:
1593 newcmd=FIONBIO;
1594 if( _get_sock_mask(s) )
1596 /* AsyncSelect()'ed sockets are always nonblocking */
1597 if (*argp) {
1598 close(fd);
1599 return 0;
1601 SetLastError(WSAEINVAL);
1602 close(fd);
1603 return SOCKET_ERROR;
1605 close(fd);
1606 if (*argp)
1607 _enable_event(s, 0, WS_FD_NONBLOCKING, 0);
1608 else
1609 _enable_event(s, 0, 0, WS_FD_NONBLOCKING);
1610 return 0;
1612 case WS_SIOCATMARK:
1613 newcmd=SIOCATMARK;
1614 break;
1616 case WS_IOW('f',125,u_long):
1617 WARN("Warning: WS1.1 shouldn't be using async I/O\n");
1618 SetLastError(WSAEINVAL);
1619 return SOCKET_ERROR;
1621 default:
1622 /* Netscape tries hard to use bogus ioctl 0x667e */
1623 WARN("\tunknown WS_IOCTL cmd (%08lx)\n", cmd);
1625 if( ioctl(fd, newcmd, (char*)argp ) == 0 )
1627 close(fd);
1628 return 0;
1630 SetLastError((errno == EBADF) ? WSAENOTSOCK : wsaErrno());
1631 close(fd);
1633 return SOCKET_ERROR;
1636 /***********************************************************************
1637 * ioctlsocket() (WINSOCK.12)
1639 INT16 WINAPI WINSOCK_ioctlsocket16(SOCKET16 s, LONG cmd, ULONG *argp)
1641 return (INT16)WSOCK32_ioctlsocket( s, cmd, argp );
1645 /***********************************************************************
1646 * listen() (WSOCK32.13)
1648 INT WINAPI WSOCK32_listen(SOCKET s, INT backlog)
1650 LPWSINFO pwsi = WINSOCK_GetIData();
1652 TRACE("(%08x): socket %04x, backlog %d\n",
1653 (unsigned)pwsi, s, backlog);
1654 if( _check_ws(pwsi, s) )
1656 int fd = _get_sock_fd(s);
1657 if (listen(fd, backlog) == 0)
1659 close(fd);
1660 _enable_event(s, FD_ACCEPT,
1661 WS_FD_LISTENING,
1662 WS_FD_CONNECT|WS_FD_CONNECTED);
1663 return 0;
1665 SetLastError(wsaErrno());
1667 else SetLastError(WSAENOTSOCK);
1668 return SOCKET_ERROR;
1671 /***********************************************************************
1672 * listen() (WINSOCK.13)
1674 INT16 WINAPI WINSOCK_listen16(SOCKET16 s, INT16 backlog)
1676 return (INT16)WSOCK32_listen( s, backlog );
1680 /***********************************************************************
1681 * recv() (WSOCK32.16)
1683 INT WINAPI WSOCK32_recv(SOCKET s, char *buf, INT len, INT flags)
1685 LPWSINFO pwsi = WINSOCK_GetIData();
1687 TRACE("(%08x): socket %04x, buf %8x, len %d, "
1688 "flags %d\n", (unsigned)pwsi, s, (unsigned)buf,
1689 len, flags);
1690 if( _check_ws(pwsi, s) )
1692 int fd = _get_sock_fd(s);
1693 INT length;
1695 if (_is_blocking(s))
1697 /* block here */
1698 /* FIXME: OOB and exceptfds? */
1699 do_block(fd, 1);
1701 if ((length = recv(fd, buf, len, flags)) >= 0)
1703 TRACE(" -> %i bytes\n", length);
1705 close(fd);
1706 _enable_event(s, FD_READ, 0, 0);
1707 return length;
1709 SetLastError(wsaErrno());
1710 close(fd);
1712 else SetLastError(WSAENOTSOCK);
1713 WARN(" -> ERROR\n");
1714 return SOCKET_ERROR;
1717 /***********************************************************************
1718 * recv() (WINSOCK.16)
1720 INT16 WINAPI WINSOCK_recv16(SOCKET16 s, char *buf, INT16 len, INT16 flags)
1722 return (INT16)WSOCK32_recv( s, buf, len, flags );
1726 /***********************************************************************
1727 * recvfrom() (WSOCK32.17)
1729 INT WINAPI WSOCK32_recvfrom(SOCKET s, char *buf, INT len, INT flags,
1730 struct sockaddr *from, INT *fromlen32)
1732 LPWSINFO pwsi = WINSOCK_GetIData();
1733 #ifdef HAVE_IPX
1734 struct ws_sockaddr_ipx* from2 = (struct ws_sockaddr_ipx *)from;
1735 #endif
1737 TRACE("(%08x): socket %04x, ptr %08x, "
1738 "len %d, flags %d\n", (unsigned)pwsi, s, (unsigned)buf,
1739 len, flags);
1740 #if DEBUG_SOCKADDR
1741 if( from ) dump_sockaddr(from);
1742 else DPRINTF("from = NULL\n");
1743 #endif
1745 if( _check_ws(pwsi, s) )
1747 int fd = _get_sock_fd(s);
1748 int length;
1750 if (_is_blocking(s))
1752 /* block here */
1753 /* FIXME: OOB and exceptfds */
1754 do_block(fd, 1);
1756 if ((length = recvfrom(fd, buf, len, flags, from, fromlen32)) >= 0)
1758 TRACE(" -> %i bytes\n", length);
1760 #ifdef HAVE_IPX
1761 if (from && ((struct sockaddr_ipx *)from)->sipx_family == AF_IPX) {
1762 from = (struct sockaddr *)
1763 malloc(fromlen32 ? *fromlen32 : sizeof(*from2));
1764 memcpy(from, from2, fromlen32 ? *fromlen32 : sizeof(*from2));
1765 from2->sipx_family = WS_AF_IPX;
1766 from2->sipx_network = ((struct sockaddr_ipx *)from)->sipx_network;
1767 from2->sipx_port = ((struct sockaddr_ipx *)from)->sipx_port;
1768 memcpy(from2->sipx_node,
1769 ((struct sockaddr_ipx *)from)->sipx_node, IPX_NODE_LEN);
1770 free(from);
1772 #endif
1773 close(fd);
1774 _enable_event(s, FD_READ, 0, 0);
1775 return (INT16)length;
1777 SetLastError(wsaErrno());
1778 close(fd);
1780 else SetLastError(WSAENOTSOCK);
1781 WARN(" -> ERROR\n");
1782 #ifdef HAVE_IPX
1783 if (from && ((struct sockaddr_ipx *)from)->sipx_family == AF_IPX) {
1784 from = (struct sockaddr *)
1785 malloc(fromlen32 ? *fromlen32 : sizeof(*from2));
1786 memcpy(from, from2, fromlen32 ? *fromlen32 : sizeof(*from2));
1787 from2->sipx_family = WS_AF_IPX;
1788 from2->sipx_network = ((struct sockaddr_ipx *)from)->sipx_network;
1789 from2->sipx_port = ((struct sockaddr_ipx *)from)->sipx_port;
1790 memcpy(from2->sipx_node,
1791 ((struct sockaddr_ipx *)from)->sipx_node, IPX_NODE_LEN);
1792 free(from);
1794 #endif
1795 return SOCKET_ERROR;
1798 /***********************************************************************
1799 * recvfrom() (WINSOCK.17)
1801 INT16 WINAPI WINSOCK_recvfrom16(SOCKET16 s, char *buf, INT16 len, INT16 flags,
1802 struct sockaddr *from, INT16 *fromlen16)
1804 INT fromlen32;
1805 INT *p = &fromlen32;
1806 INT retVal;
1808 if( fromlen16 ) fromlen32 = *fromlen16; else p = NULL;
1809 retVal = WSOCK32_recvfrom( s, buf, len, flags, from, p );
1810 if( fromlen16 ) *fromlen16 = fromlen32;
1811 return (INT16)retVal;
1814 /***********************************************************************
1815 * select() (WINSOCK.18)(WSOCK32.18)
1817 static INT __ws_select( BOOL b32, void *ws_readfds, void *ws_writefds, void *ws_exceptfds,
1818 struct timeval *timeout )
1820 LPWSINFO pwsi = WINSOCK_GetIData();
1822 TRACE("(%08x): read %8x, write %8x, excp %8x\n",
1823 (unsigned) pwsi, (unsigned) ws_readfds, (unsigned) ws_writefds, (unsigned) ws_exceptfds);
1825 if( pwsi )
1827 int highfd = 0;
1828 fd_set readfds, writefds, exceptfds;
1829 fd_set *p_read, *p_write, *p_except;
1830 int readfd[FD_SETSIZE], writefd[FD_SETSIZE], exceptfd[FD_SETSIZE];
1832 p_read = fd_set_import(&readfds, pwsi, ws_readfds, &highfd, readfd, b32);
1833 p_write = fd_set_import(&writefds, pwsi, ws_writefds, &highfd, writefd, b32);
1834 p_except = fd_set_import(&exceptfds, pwsi, ws_exceptfds, &highfd, exceptfd, b32);
1836 if( (highfd = select(highfd + 1, p_read, p_write, p_except, timeout)) > 0 )
1838 fd_set_export(pwsi, &readfds, p_except, ws_readfds, readfd, b32);
1839 fd_set_export(pwsi, &writefds, p_except, ws_writefds, writefd, b32);
1841 if (p_except && ws_exceptfds)
1843 #define wsfds16 ((ws_fd_set16*)ws_exceptfds)
1844 #define wsfds32 ((ws_fd_set32*)ws_exceptfds)
1845 int i, j, count = (b32) ? wsfds32->fd_count : wsfds16->fd_count;
1847 for (i = j = 0; i < count; i++)
1849 int fd = exceptfd[i];
1850 if( fd >= 0 && FD_ISSET(fd, &exceptfds) )
1852 if( b32 )
1853 wsfds32->fd_array[j++] = wsfds32->fd_array[i];
1854 else
1855 wsfds16->fd_array[j++] = wsfds16->fd_array[i];
1857 if( fd >= 0 ) close(fd);
1858 exceptfd[i] = -1;
1860 if( b32 )
1861 wsfds32->fd_count = j;
1862 else
1863 wsfds16->fd_count = j;
1864 #undef wsfds32
1865 #undef wsfds16
1867 return highfd;
1869 fd_set_unimport(ws_readfds, readfd, b32);
1870 fd_set_unimport(ws_writefds, writefd, b32);
1871 fd_set_unimport(ws_exceptfds, exceptfd, b32);
1872 if( ws_readfds ) ((ws_fd_set32*)ws_readfds)->fd_count = 0;
1873 if( ws_writefds ) ((ws_fd_set32*)ws_writefds)->fd_count = 0;
1874 if( ws_exceptfds ) ((ws_fd_set32*)ws_exceptfds)->fd_count = 0;
1876 if( highfd == 0 ) return 0;
1877 SetLastError(wsaErrno());
1879 return SOCKET_ERROR;
1882 INT16 WINAPI WINSOCK_select16(INT16 nfds, ws_fd_set16 *ws_readfds,
1883 ws_fd_set16 *ws_writefds, ws_fd_set16 *ws_exceptfds,
1884 struct timeval *timeout)
1886 return (INT16)__ws_select( FALSE, ws_readfds, ws_writefds, ws_exceptfds, timeout );
1889 INT WINAPI WSOCK32_select(INT nfds, ws_fd_set32 *ws_readfds,
1890 ws_fd_set32 *ws_writefds, ws_fd_set32 *ws_exceptfds,
1891 struct timeval *timeout)
1893 /* struct timeval is the same for both 32- and 16-bit code */
1894 return (INT)__ws_select( TRUE, ws_readfds, ws_writefds, ws_exceptfds, timeout );
1898 /***********************************************************************
1899 * send() (WSOCK32.19)
1901 INT WINAPI WSOCK32_send(SOCKET s, char *buf, INT len, INT flags)
1903 LPWSINFO pwsi = WINSOCK_GetIData();
1905 TRACE("(%08x): socket %04x, ptr %08x, length %d, flags %d\n",
1906 (unsigned)pwsi, s, (unsigned) buf, len, flags);
1907 if( _check_ws(pwsi, s) )
1909 int fd = _get_sock_fd(s);
1910 int length;
1912 if (_is_blocking(s))
1914 /* block here */
1915 /* FIXME: exceptfds */
1916 do_block(fd, 2);
1918 if ((length = send(fd, buf, len, flags)) < 0 )
1920 SetLastError(wsaErrno());
1921 if( GetLastError() == WSAEWOULDBLOCK )
1922 _enable_event(s, FD_WRITE, 0, 0);
1924 else
1926 close(fd);
1927 return (INT16)length;
1929 close(fd);
1931 else SetLastError(WSAENOTSOCK);
1932 return SOCKET_ERROR;
1935 /***********************************************************************
1936 * send() (WINSOCK.19)
1938 INT16 WINAPI WINSOCK_send16(SOCKET16 s, char *buf, INT16 len, INT16 flags)
1940 return WSOCK32_send( s, buf, len, flags );
1943 /***********************************************************************
1944 * sendto() (WSOCK32.20)
1946 INT WINAPI WSOCK32_sendto(SOCKET s, char *buf, INT len, INT flags,
1947 struct sockaddr *to, INT tolen)
1949 LPWSINFO pwsi = WINSOCK_GetIData();
1950 #ifdef HAVE_IPX
1951 struct ws_sockaddr_ipx* to2 = (struct ws_sockaddr_ipx *)to;
1952 #endif
1954 TRACE("(%08x): socket %04x, ptr %08x, length %d, flags %d\n",
1955 (unsigned)pwsi, s, (unsigned) buf, len, flags);
1956 if( _check_ws(pwsi, s) )
1958 int fd = _get_sock_fd(s);
1959 INT length;
1961 if (to && ((struct ws_sockaddr_ipx *)to)->sipx_family == WS_AF_PUP)
1962 ((struct ws_sockaddr_ipx *)to)->sipx_family = AF_UNSPEC;
1963 #ifdef HAVE_IPX
1964 else if (to &&
1965 ((struct ws_sockaddr_ipx *)to)->sipx_family == WS_AF_IPX)
1967 to = (struct sockaddr *) malloc(sizeof(struct sockaddr_ipx));
1968 memset(to, '\0', sizeof(struct sockaddr_ipx));
1969 ((struct sockaddr_ipx *)to)->sipx_family = AF_IPX;
1970 ((struct sockaddr_ipx *)to)->sipx_port = to2->sipx_port;
1971 ((struct sockaddr_ipx *)to)->sipx_network = to2->sipx_network;
1972 memcpy(((struct sockaddr_ipx *)to)->sipx_node,
1973 to2->sipx_node, IPX_NODE_LEN);
1974 tolen = sizeof(struct sockaddr_ipx);
1976 #endif
1977 if (_is_blocking(s))
1979 /* block here */
1980 /* FIXME: exceptfds */
1981 do_block(fd, 2);
1983 if ((length = sendto(fd, buf, len, flags, to, tolen)) < 0 )
1985 SetLastError(wsaErrno());
1986 if( GetLastError() == WSAEWOULDBLOCK )
1987 _enable_event(s, FD_WRITE, 0, 0);
1989 else {
1990 #ifdef HAVE_IPX
1991 if (to && ((struct sockaddr_ipx *)to)->sipx_family == AF_IPX) {
1992 free(to);
1994 #endif
1995 close(fd);
1996 return length;
1998 close(fd);
2000 else SetLastError(WSAENOTSOCK);
2001 #ifdef HAVE_IPX
2002 if (to && ((struct sockaddr_ipx *)to)->sipx_family == AF_IPX) {
2003 free(to);
2005 #endif
2006 return SOCKET_ERROR;
2009 /***********************************************************************
2010 * sendto() (WINSOCK.20)
2012 INT16 WINAPI WINSOCK_sendto16(SOCKET16 s, char *buf, INT16 len, INT16 flags,
2013 struct sockaddr *to, INT16 tolen)
2015 return (INT16)WSOCK32_sendto( s, buf, len, flags, to, tolen );
2018 /***********************************************************************
2019 * setsockopt() (WSOCK32.21)
2021 INT WINAPI WSOCK32_setsockopt(SOCKET16 s, INT level, INT optname,
2022 char *optval, INT optlen)
2024 LPWSINFO pwsi = WINSOCK_GetIData();
2026 TRACE("(%08x): socket %04x, lev %d, opt %d, ptr %08x, len %d\n",
2027 (unsigned)pwsi, s, level, optname, (int) optval, optlen);
2028 if( _check_ws(pwsi, s) )
2030 struct linger linger;
2031 int fd = _get_sock_fd(s);
2032 int woptval;
2034 convert_sockopt(&level, &optname);
2035 if(optname == WS_SO_DONTLINGER) {
2036 linger.l_onoff = *((int*)optval) ? 0: 1;
2037 linger.l_linger = 0;
2038 optname=SO_LINGER;
2039 optval = (char*)&linger;
2040 optlen = sizeof(struct linger);
2041 }else{
2042 if (optname == SO_LINGER && optval) {
2043 /* yes, uses unsigned short in both win16/win32 */
2044 linger.l_onoff = ((UINT16*)optval)[0];
2045 linger.l_linger = ((UINT16*)optval)[1];
2046 /* FIXME: what is documented behavior if SO_LINGER optval
2047 is null?? */
2048 optval = (char*)&linger;
2049 optlen = sizeof(struct linger);
2050 } else if (optlen < sizeof(int)){
2051 woptval= *((INT16 *) optval);
2052 optval= (char*) &woptval;
2053 optlen=sizeof(int);
2056 if (setsockopt(fd, level, optname, optval, optlen) == 0)
2058 close(fd);
2059 return 0;
2061 SetLastError(wsaErrno());
2062 close(fd);
2064 else SetLastError(WSAENOTSOCK);
2065 return SOCKET_ERROR;
2068 /***********************************************************************
2069 * setsockopt() (WINSOCK.21)
2071 INT16 WINAPI WINSOCK_setsockopt16(SOCKET16 s, INT16 level, INT16 optname,
2072 char *optval, INT16 optlen)
2074 if( !optval ) return SOCKET_ERROR;
2075 return (INT16)WSOCK32_setsockopt( s, (UINT16)level, optname, optval, optlen );
2079 /***********************************************************************
2080 * shutdown() (WSOCK32.22)
2082 INT WINAPI WSOCK32_shutdown(SOCKET s, INT how)
2084 LPWSINFO pwsi = WINSOCK_GetIData();
2086 TRACE("(%08x): socket %04x, how %i\n",
2087 (unsigned)pwsi, s, how );
2088 if( _check_ws(pwsi, s) )
2090 int fd = _get_sock_fd(s);
2091 switch( how )
2093 case 0: /* drop receives */
2094 _enable_event(s, 0, 0, WS_FD_READ);
2095 #ifdef SHUT_RD
2096 how = SHUT_RD;
2097 #endif
2098 break;
2100 case 1: /* drop sends */
2101 _enable_event(s, 0, 0, WS_FD_WRITE);
2102 #ifdef SHUT_WR
2103 how = SHUT_WR;
2104 #endif
2105 break;
2107 case 2: /* drop all */
2108 #ifdef SHUT_RDWR
2109 how = SHUT_RDWR;
2110 #endif
2111 default:
2112 WSAAsyncSelect( s, 0, 0, 0 );
2113 break;
2116 if (shutdown(fd, how) == 0)
2118 if( how > 1 )
2120 _enable_event(s, 0, 0, WS_FD_CONNECTED|WS_FD_LISTENING);
2122 close(fd);
2123 return 0;
2125 SetLastError(wsaErrno());
2126 close(fd);
2128 else SetLastError(WSAENOTSOCK);
2129 return SOCKET_ERROR;
2132 /***********************************************************************
2133 * shutdown() (WINSOCK.22)
2135 INT16 WINAPI WINSOCK_shutdown16(SOCKET16 s, INT16 how)
2137 return (INT16)WSOCK32_shutdown( s, how );
2141 /***********************************************************************
2142 * socket() (WSOCK32.23)
2144 SOCKET WINAPI WSOCK32_socket(INT af, INT type, INT protocol)
2146 LPWSINFO pwsi = WINSOCK_GetIData();
2147 struct create_socket_request *req = get_req_buffer();
2149 TRACE("(%08x): af=%d type=%d protocol=%d\n",
2150 (unsigned)pwsi, af, type, protocol);
2152 if( pwsi )
2154 /* check the socket family */
2155 switch(af)
2157 #ifdef HAVE_IPX
2158 case WS_AF_IPX: af = AF_IPX;
2159 #endif
2160 case AF_INET:
2161 case AF_UNSPEC: break;
2162 default: SetLastError(WSAEAFNOSUPPORT);
2163 return INVALID_SOCKET;
2166 /* check the socket type */
2167 switch(type)
2169 case SOCK_STREAM:
2170 case SOCK_DGRAM:
2171 case SOCK_RAW: break;
2172 default: SetLastError(WSAESOCKTNOSUPPORT);
2173 return INVALID_SOCKET;
2176 /* check the protocol type */
2177 if ( protocol < 0 ) /* don't support negative values */
2178 { SetLastError(WSAEPROTONOSUPPORT); return INVALID_SOCKET; }
2180 if ( af == AF_UNSPEC) /* did they not specify the address family? */
2181 switch(protocol)
2183 case IPPROTO_TCP:
2184 if (type == SOCK_STREAM) { af = AF_INET; break; }
2185 case IPPROTO_UDP:
2186 if (type == SOCK_DGRAM) { af = AF_INET; break; }
2187 default: SetLastError(WSAEPROTOTYPE); return INVALID_SOCKET;
2190 req->family = af;
2191 req->type = type;
2192 req->protocol = protocol;
2193 req->access = GENERIC_READ|GENERIC_WRITE|SYNCHRONIZE;
2194 req->inherit = TRUE;
2195 sock_server_call( REQ_CREATE_SOCKET );
2196 if ( req->handle >= 0)
2198 TRACE("\tcreated %04x\n", req->handle);
2200 return req->handle;
2203 if (GetLastError() == WSAEACCES) /* raw socket denied */
2205 if (type == SOCK_RAW)
2206 MESSAGE("WARNING: Trying to create a socket of type SOCK_RAW, will fail unless running as root\n");
2207 else
2208 MESSAGE("WS_SOCKET: not enough privileges to create socket, try running as root\n");
2209 SetLastError(WSAESOCKTNOSUPPORT);
2213 WARN("\t\tfailed!\n");
2214 return INVALID_SOCKET;
2217 /***********************************************************************
2218 * socket() (WINSOCK.23)
2220 SOCKET16 WINAPI WINSOCK_socket16(INT16 af, INT16 type, INT16 protocol)
2222 return (SOCKET16)WSOCK32_socket( af, type, protocol );
2226 /* ----------------------------------- DNS services
2228 * IMPORTANT: 16-bit API structures have SEGPTR pointers inside them.
2229 * Also, we have to use wsock32 stubs to convert structures and
2230 * error codes from Unix to WSA, hence there is no direct mapping in
2231 * the relay32/wsock32.spec.
2234 static char* NULL_STRING = "NULL";
2236 /***********************************************************************
2237 * gethostbyaddr() (WINSOCK.51)(WSOCK32.51)
2239 static struct WIN_hostent* __ws_gethostbyaddr(const char *addr, int len, int type, int dup_flag)
2241 LPWSINFO pwsi = WINSOCK_GetIData();
2243 if( pwsi )
2245 struct hostent* host;
2246 if( (host = gethostbyaddr(addr, len, type)) != NULL )
2247 if( WS_dup_he(pwsi, host, dup_flag) )
2248 return (struct WIN_hostent*)(pwsi->he);
2249 else
2250 SetLastError(WSAENOBUFS);
2251 else
2252 SetLastError((h_errno < 0) ? wsaErrno() : wsaHerrno());
2254 return NULL;
2257 SEGPTR WINAPI WINSOCK_gethostbyaddr16(const char *addr, INT16 len, INT16 type)
2259 struct WIN_hostent* retval;
2260 TRACE("ptr %08x, len %d, type %d\n",
2261 (unsigned) addr, len, type);
2262 retval = __ws_gethostbyaddr( addr, len, type, WS_DUP_SEGPTR );
2263 return retval ? SEGPTR_GET(retval) : ((SEGPTR)NULL);
2266 struct WIN_hostent* WINAPI WSOCK32_gethostbyaddr(const char *addr, INT len,
2267 INT type)
2269 TRACE("ptr %08x, len %d, type %d\n",
2270 (unsigned) addr, len, type);
2271 return __ws_gethostbyaddr(addr, len, type, WS_DUP_LINEAR);
2274 /***********************************************************************
2275 * gethostbyname() (WINSOCK.52)(WSOCK32.52)
2277 static struct WIN_hostent * __ws_gethostbyname(const char *name, int dup_flag)
2279 LPWSINFO pwsi = WINSOCK_GetIData();
2281 if( pwsi )
2283 struct hostent* host;
2284 if( (host = gethostbyname(name)) != NULL )
2285 if( WS_dup_he(pwsi, host, dup_flag) )
2286 return (struct WIN_hostent*)(pwsi->he);
2287 else SetLastError(WSAENOBUFS);
2288 else SetLastError((h_errno < 0) ? wsaErrno() : wsaHerrno());
2290 return NULL;
2293 SEGPTR WINAPI WINSOCK_gethostbyname16(const char *name)
2295 struct WIN_hostent* retval;
2296 TRACE("%s\n", (name)?name:NULL_STRING);
2297 retval = __ws_gethostbyname( name, WS_DUP_SEGPTR );
2298 return (retval)? SEGPTR_GET(retval) : ((SEGPTR)NULL) ;
2301 struct WIN_hostent* WINAPI WSOCK32_gethostbyname(const char* name)
2303 TRACE("%s\n", (name)?name:NULL_STRING);
2304 return __ws_gethostbyname( name, WS_DUP_LINEAR );
2308 /***********************************************************************
2309 * getprotobyname() (WINSOCK.53)(WSOCK32.53)
2311 static struct WIN_protoent* __ws_getprotobyname(const char *name, int dup_flag)
2313 LPWSINFO pwsi = WINSOCK_GetIData();
2315 if( pwsi )
2317 struct protoent* proto;
2318 if( (proto = getprotobyname(name)) != NULL )
2319 if( WS_dup_pe(pwsi, proto, dup_flag) )
2320 return (struct WIN_protoent*)(pwsi->pe);
2321 else SetLastError(WSAENOBUFS);
2322 else {
2323 MESSAGE("protocol %s not found; You might want to add "
2324 "this to /etc/protocols\n", debugstr_a(name) );
2325 SetLastError(WSANO_DATA);
2327 } else SetLastError(WSANOTINITIALISED);
2328 return NULL;
2331 SEGPTR WINAPI WINSOCK_getprotobyname16(const char *name)
2333 struct WIN_protoent* retval;
2334 TRACE("%s\n", (name)?name:NULL_STRING);
2335 retval = __ws_getprotobyname(name, WS_DUP_SEGPTR);
2336 return retval ? SEGPTR_GET(retval) : ((SEGPTR)NULL);
2339 struct WIN_protoent* WINAPI WSOCK32_getprotobyname(const char* name)
2341 TRACE("%s\n", (name)?name:NULL_STRING);
2342 return __ws_getprotobyname(name, WS_DUP_LINEAR);
2346 /***********************************************************************
2347 * getprotobynumber() (WINSOCK.54)(WSOCK32.54)
2349 static struct WIN_protoent* __ws_getprotobynumber(int number, int dup_flag)
2351 LPWSINFO pwsi = WINSOCK_GetIData();
2353 if( pwsi )
2355 struct protoent* proto;
2356 if( (proto = getprotobynumber(number)) != NULL )
2357 if( WS_dup_pe(pwsi, proto, dup_flag) )
2358 return (struct WIN_protoent*)(pwsi->pe);
2359 else SetLastError(WSAENOBUFS);
2360 else {
2361 MESSAGE("protocol number %d not found; You might want to add "
2362 "this to /etc/protocols\n", number );
2363 SetLastError(WSANO_DATA);
2365 } else SetLastError(WSANOTINITIALISED);
2366 return NULL;
2369 SEGPTR WINAPI WINSOCK_getprotobynumber16(INT16 number)
2371 struct WIN_protoent* retval;
2372 TRACE("%i\n", number);
2373 retval = __ws_getprotobynumber(number, WS_DUP_SEGPTR);
2374 return retval ? SEGPTR_GET(retval) : ((SEGPTR)NULL);
2377 struct WIN_protoent* WINAPI WSOCK32_getprotobynumber(INT number)
2379 TRACE("%i\n", number);
2380 return __ws_getprotobynumber(number, WS_DUP_LINEAR);
2384 /***********************************************************************
2385 * getservbyname() (WINSOCK.55)(WSOCK32.55)
2387 struct WIN_servent* __ws_getservbyname(const char *name, const char *proto, int dup_flag)
2389 LPWSINFO pwsi = WINSOCK_GetIData();
2391 if( pwsi )
2393 struct servent* serv;
2394 int i = wsi_strtolo( pwsi, name, proto );
2396 if( i ) {
2397 serv = getservbyname(pwsi->buffer,
2398 proto ? (pwsi->buffer + i) : NULL);
2399 if( serv != NULL )
2400 if( WS_dup_se(pwsi, serv, dup_flag) )
2401 return (struct WIN_servent*)(pwsi->se);
2402 else SetLastError(WSAENOBUFS);
2403 else {
2404 MESSAGE("service %s protocol %s not found; You might want to add "
2405 "this to /etc/services\n", debugstr_a(pwsi->buffer),
2406 proto ? debugstr_a(pwsi->buffer+i):"*");
2407 SetLastError(WSANO_DATA);
2410 else SetLastError(WSAENOBUFS);
2411 } else SetLastError(WSANOTINITIALISED);
2412 return NULL;
2415 SEGPTR WINAPI WINSOCK_getservbyname16(const char *name, const char *proto)
2417 struct WIN_servent* retval;
2418 TRACE("'%s', '%s'\n",
2419 (name)?name:NULL_STRING, (proto)?proto:NULL_STRING);
2420 retval = __ws_getservbyname(name, proto, WS_DUP_SEGPTR);
2421 return retval ? SEGPTR_GET(retval) : ((SEGPTR)NULL);
2424 struct WIN_servent* WINAPI WSOCK32_getservbyname(const char *name, const char *proto)
2426 TRACE("'%s', '%s'\n",
2427 (name)?name:NULL_STRING, (proto)?proto:NULL_STRING);
2428 return __ws_getservbyname(name, proto, WS_DUP_LINEAR);
2432 /***********************************************************************
2433 * getservbyport() (WINSOCK.56)(WSOCK32.56)
2435 static struct WIN_servent* __ws_getservbyport(int port, const char* proto, int dup_flag)
2437 LPWSINFO pwsi = WINSOCK_GetIData();
2439 if( pwsi )
2441 struct servent* serv;
2442 if (!proto || wsi_strtolo( pwsi, proto, NULL )) {
2443 if( (serv = getservbyport(port, (proto) ? pwsi->buffer : NULL)) != NULL ) {
2444 if( WS_dup_se(pwsi, serv, dup_flag) )
2445 return (struct WIN_servent*)(pwsi->se);
2446 else SetLastError(WSAENOBUFS);
2448 else {
2449 MESSAGE("service on port %lu protocol %s not found; You might want to add "
2450 "this to /etc/services\n", (unsigned long)ntohl(port),
2451 proto ? debugstr_a(pwsi->buffer) : "*");
2452 SetLastError(WSANO_DATA);
2455 else SetLastError(WSAENOBUFS);
2456 } else SetLastError(WSANOTINITIALISED);
2457 return NULL;
2460 SEGPTR WINAPI WINSOCK_getservbyport16(INT16 port, const char *proto)
2462 struct WIN_servent* retval;
2463 TRACE("%i, '%s'\n",
2464 (int)port, (proto)?proto:NULL_STRING);
2465 retval = __ws_getservbyport(port, proto, WS_DUP_SEGPTR);
2466 return retval ? SEGPTR_GET(retval) : ((SEGPTR)NULL);
2469 struct WIN_servent* WINAPI WSOCK32_getservbyport(INT port, const char *proto)
2471 TRACE("%i, '%s'\n",
2472 (int)port, (proto)?proto:NULL_STRING);
2473 return __ws_getservbyport(port, proto, WS_DUP_LINEAR);
2477 /***********************************************************************
2478 * gethostname() (WSOCK32.57)
2480 INT WINAPI WSOCK32_gethostname(char *name, INT namelen)
2482 LPWSINFO pwsi = WINSOCK_GetIData();
2484 TRACE("(%08x): name %s, len %d\n",
2485 (unsigned)pwsi, (name)?name:NULL_STRING, namelen);
2486 if( pwsi )
2488 if (gethostname(name, namelen) == 0) return 0;
2489 SetLastError((errno == EINVAL) ? WSAEFAULT : wsaErrno());
2491 return SOCKET_ERROR;
2494 /***********************************************************************
2495 * gethostname() (WINSOCK.57)
2497 INT16 WINAPI WINSOCK_gethostname16(char *name, INT16 namelen)
2499 return (INT16)WSOCK32_gethostname(name, namelen);
2503 /* ------------------------------------- Windows sockets extensions -- *
2505 * ------------------------------------------------------------------- */
2507 /***********************************************************************
2508 * WSAEnumNetworkEvents
2510 int WINAPI WSAEnumNetworkEvents(SOCKET s, WSAEVENT hEvent, LPWSANETWORKEVENTS lpEvent)
2512 LPWSINFO pwsi = WINSOCK_GetIData();
2513 struct get_socket_event_request *req = get_req_buffer();
2515 TRACE("(%08x): %08x, hEvent %08x, lpEvent %08x\n",
2516 (unsigned)pwsi, s, hEvent, (unsigned)lpEvent );
2517 if( _check_ws(pwsi, s) )
2519 req->handle = s;
2520 req->service = TRUE;
2521 req->s_event = 0;
2522 req->c_event = hEvent;
2523 sock_server_call( REQ_GET_SOCKET_EVENT );
2524 lpEvent->lNetworkEvents = req->pmask;
2525 memcpy(lpEvent->iErrorCode, req->errors, sizeof(lpEvent->iErrorCode));
2526 return 0;
2528 else SetLastError(WSAEINVAL);
2529 return SOCKET_ERROR;
2532 /***********************************************************************
2533 * WSAEventSelect
2535 int WINAPI WSAEventSelect(SOCKET s, WSAEVENT hEvent, LONG lEvent)
2537 LPWSINFO pwsi = WINSOCK_GetIData();
2538 struct set_socket_event_request *req = get_req_buffer();
2540 TRACE("(%08x): %08x, hEvent %08x, event %08x\n",
2541 (unsigned)pwsi, s, hEvent, (unsigned)lEvent );
2542 if( _check_ws(pwsi, s) )
2544 req->handle = s;
2545 req->mask = lEvent;
2546 req->event = hEvent;
2547 sock_server_call( REQ_SET_SOCKET_EVENT );
2548 return 0;
2550 else SetLastError(WSAEINVAL);
2551 return SOCKET_ERROR;
2554 /***********************************************************************
2555 * WSAAsyncSelect() (WINSOCK.101)(WSOCK32.101)
2558 VOID CALLBACK WINSOCK_DoAsyncEvent( ULONG_PTR ptr )
2560 ws_select_info *info = (ws_select_info*)ptr;
2561 LPWSINFO pwsi = info->pwsi;
2562 struct get_socket_event_request *req = get_req_buffer();
2563 unsigned int i, pmask, orphan = FALSE;
2565 TRACE("socket %08x, event %08x\n", info->sock, info->event);
2566 SetLastError(0);
2567 req->handle = info->sock;
2568 req->service = TRUE;
2569 req->s_event = info->event; /* <== avoid race conditions */
2570 req->c_event = info->event;
2571 sock_server_call( REQ_GET_SOCKET_EVENT );
2572 if ( (GetLastError() == WSAENOTSOCK) || (GetLastError() == WSAEINVAL) )
2574 /* orphaned event (socket closed or something) */
2575 pmask = WS_FD_SERVEVENT;
2576 orphan = TRUE;
2577 } else
2578 pmask = req->pmask;
2579 /* check for accepted sockets that needs to inherit WSAAsyncSelect */
2580 if (pmask & WS_FD_SERVEVENT) {
2581 int q;
2582 for (q=0; q<WS_ACCEPT_QUEUE; q++)
2583 if (pwsi->accept_old[q] == info->sock) {
2584 /* there's only one service thread per pwsi, no lock necessary */
2585 HANDLE as = pwsi->accept_new[q];
2586 if (as) {
2587 pwsi->accept_new[q] = 0;
2588 pwsi->accept_old[q] = 0;
2589 WSAAsyncSelect(as, info->hWnd, info->uMsg, info->lEvent);
2592 pmask &= ~WS_FD_SERVEVENT;
2594 /* dispatch network events */
2595 for (i=0; i<FD_MAX_EVENTS; i++)
2596 if (pmask & (1<<i)) {
2597 TRACE("post: event bit %d, error %d\n", i, req->errors[i]);
2598 PostMessageA(info->hWnd, info->uMsg, info->sock,
2599 WSAMAKESELECTREPLY(1<<i, req->errors[i]));
2601 /* cleanup */
2602 if (orphan)
2604 TRACE("orphaned event, self-destructing\n");
2605 /* SERVICE_Delete closes the event object */
2606 SERVICE_Delete( info->service );
2607 WS_FREE(info);
2611 INT WINAPI WSAAsyncSelect(SOCKET s, HWND hWnd, UINT uMsg, LONG lEvent)
2613 LPWSINFO pwsi = WINSOCK_GetIData();
2615 TRACE("(%08x): %04x, hWnd %04x, uMsg %08x, event %08x\n",
2616 (unsigned)pwsi, (SOCKET16)s, (HWND16)hWnd, uMsg, (unsigned)lEvent );
2617 if( _check_ws(pwsi, s) )
2619 if( lEvent )
2621 ws_select_info *info = (ws_select_info*)WS_ALLOC(sizeof(ws_select_info));
2622 if( info )
2624 HANDLE hObj = CreateEventA( NULL, TRUE, FALSE, NULL );
2625 INT err;
2627 info->sock = s;
2628 info->event = hObj;
2629 info->hWnd = hWnd;
2630 info->uMsg = uMsg;
2631 info->lEvent = lEvent;
2632 info->pwsi = pwsi;
2633 info->service = SERVICE_AddObject( hObj, WINSOCK_DoAsyncEvent, (ULONG_PTR)info );
2635 err = WSAEventSelect( s, hObj, lEvent | WS_FD_SERVEVENT );
2636 if (err) {
2637 /* SERVICE_Delete closes the event object */
2638 SERVICE_Delete( info->service );
2639 WS_FREE(info);
2640 return err;
2643 return 0; /* success */
2645 else SetLastError(WSAENOBUFS);
2647 else
2649 WSAEventSelect(s, 0, 0);
2650 return 0;
2653 else SetLastError(WSAEINVAL);
2654 return SOCKET_ERROR;
2657 INT16 WINAPI WSAAsyncSelect16(SOCKET16 s, HWND16 hWnd, UINT16 wMsg, LONG lEvent)
2659 return (INT16)WSAAsyncSelect( s, hWnd, wMsg, lEvent );
2662 /***********************************************************************
2663 * WSARecvEx() (WSOCK32.1107)
2665 * WSARecvEx is a Microsoft specific extension to winsock that is identical to recv
2666 * except that has an in/out argument call flags that has the value MSG_PARTIAL ored
2667 * into the flags parameter when a partial packet is read. This only applies to
2668 * sockets using the datagram protocol. This method does not seem to be implemented
2669 * correctly by microsoft as the winsock implementation does not set the MSG_PARTIAL
2670 * flag when a fragmented packet arrives.
2672 INT WINAPI WSARecvEx(SOCKET s, char *buf, INT len, INT *flags) {
2673 FIXME("(WSARecvEx) partial packet return value not set \n");
2675 return WSOCK32_recv(s, buf, len, *flags);
2679 /***********************************************************************
2680 * WSARecvEx16() (WINSOCK.1107)
2682 * See description for WSARecvEx()
2684 INT16 WINAPI WSARecvEx16(SOCKET16 s, char *buf, INT16 len, INT16 *flags) {
2685 FIXME("(WSARecvEx16) partial packet return value not set \n");
2687 return WINSOCK_recv16(s, buf, len, *flags);
2691 /***********************************************************************
2692 * WSACreateEvent() (WS2_32.???)
2695 WSAEVENT WINAPI WSACreateEvent(void)
2697 /* Create a manual-reset event, with initial state: unsignealed */
2698 TRACE("\n");
2700 return CreateEventA(NULL, TRUE, FALSE, NULL);
2703 /***********************************************************************
2704 * WSACloseEvent() (WS2_32.???)
2707 BOOL WINAPI WSACloseEvent(WSAEVENT event)
2709 TRACE ("event=0x%x\n", event);
2711 return CloseHandle(event);
2714 /***********************************************************************
2715 * WSASocketA() (WS2_32.???)
2718 SOCKET WINAPI WSASocketA(int af, int type, int protocol,
2719 LPWSAPROTOCOL_INFOA lpProtocolInfo,
2720 GROUP g, DWORD dwFlags)
2723 FIXME: The "advanced" parameters of WSASocketA (lpProtocolInfo,
2724 g, dwFlags) are ignored.
2727 TRACE("af=%d type=%d protocol=%d protocol_info=%p group=%d flags=0x%lx\n",
2728 af, type, protocol, lpProtocolInfo, g, dwFlags );
2730 return ( WSOCK32_socket (af, type, protocol) );
2734 /***********************************************************************
2735 * __WSAFDIsSet() (WINSOCK.151)
2737 INT16 WINAPI __WSAFDIsSet16(SOCKET16 s, ws_fd_set16 *set)
2739 int i = set->fd_count;
2741 TRACE("(%d,%8lx(%i))\n", s,(unsigned long)set, i);
2743 while (i--)
2744 if (set->fd_array[i] == s) return 1;
2745 return 0;
2748 /***********************************************************************
2749 * __WSAFDIsSet() (WSOCK32.151)
2751 INT WINAPI __WSAFDIsSet(SOCKET s, ws_fd_set32 *set)
2753 int i = set->fd_count;
2755 TRACE("(%d,%8lx(%i))\n", s,(unsigned long)set, i);
2757 while (i--)
2758 if (set->fd_array[i] == s) return 1;
2759 return 0;
2762 /***********************************************************************
2763 * WSAIsBlocking() (WINSOCK.114)(WSOCK32.114)
2765 BOOL WINAPI WSAIsBlocking(void)
2767 /* By default WinSock should set all its sockets to non-blocking mode
2768 * and poll in PeekMessage loop when processing "blocking" ones. This
2769 * function is supposed to tell if the program is in this loop. Our
2770 * blocking calls are truly blocking so we always return FALSE.
2772 * Note: It is allowed to call this function without prior WSAStartup().
2775 TRACE("\n");
2776 return FALSE;
2779 /***********************************************************************
2780 * WSACancelBlockingCall() (WINSOCK.113)(WSOCK32.113)
2782 INT WINAPI WSACancelBlockingCall(void)
2784 LPWSINFO pwsi = WINSOCK_GetIData();
2786 TRACE("(%08x)\n", (unsigned)pwsi);
2788 if( pwsi ) return 0;
2789 return SOCKET_ERROR;
2793 /***********************************************************************
2794 * WSASetBlockingHook16() (WINSOCK.109)
2796 FARPROC16 WINAPI WSASetBlockingHook16(FARPROC16 lpBlockFunc)
2798 FARPROC16 prev;
2799 LPWSINFO pwsi = WINSOCK_GetIData();
2801 TRACE("(%08x): hook %08x\n",
2802 (unsigned)pwsi, (unsigned) lpBlockFunc);
2803 if( pwsi )
2805 prev = (FARPROC16)pwsi->blocking_hook;
2806 pwsi->blocking_hook = (DWORD)lpBlockFunc;
2807 pwsi->flags &= ~WSI_BLOCKINGHOOK;
2808 return prev;
2810 return 0;
2814 /***********************************************************************
2815 * WSASetBlockingHook()
2817 FARPROC WINAPI WSASetBlockingHook(FARPROC lpBlockFunc)
2819 FARPROC prev;
2820 LPWSINFO pwsi = WINSOCK_GetIData();
2822 TRACE("(%08x): hook %08x\n",
2823 (unsigned)pwsi, (unsigned) lpBlockFunc);
2824 if( pwsi ) {
2825 prev = (FARPROC)pwsi->blocking_hook;
2826 pwsi->blocking_hook = (DWORD)lpBlockFunc;
2827 pwsi->flags |= WSI_BLOCKINGHOOK;
2828 return prev;
2830 return NULL;
2834 /***********************************************************************
2835 * WSAUnhookBlockingHook16() (WINSOCK.110)
2837 INT16 WINAPI WSAUnhookBlockingHook16(void)
2839 LPWSINFO pwsi = WINSOCK_GetIData();
2841 TRACE("(%08x)\n", (unsigned)pwsi);
2842 if( pwsi ) return (INT16)(pwsi->blocking_hook = 0);
2843 return SOCKET_ERROR;
2847 /***********************************************************************
2848 * WSAUnhookBlockingHook()
2850 INT WINAPI WSAUnhookBlockingHook(void)
2852 LPWSINFO pwsi = WINSOCK_GetIData();
2854 TRACE("(%08x)\n", (unsigned)pwsi);
2855 if( pwsi )
2857 pwsi->blocking_hook = 0;
2858 pwsi->flags &= ~WSI_BLOCKINGHOOK;
2859 return 0;
2861 return SOCKET_ERROR;
2865 /* ----------------------------------- end of API stuff */
2867 /* ----------------------------------- helper functions -
2869 * TODO: Merge WS_dup_..() stuff into one function that
2870 * would operate with a generic structure containing internal
2871 * pointers (via a template of some kind).
2874 static int list_size(char** l, int item_size)
2876 int i,j = 0;
2877 if(l)
2878 { for(i=0;l[i];i++)
2879 j += (item_size) ? item_size : strlen(l[i]) + 1;
2880 j += (i + 1) * sizeof(char*); }
2881 return j;
2884 static int list_dup(char** l_src, char* ref, char* base, int item_size)
2886 /* base is either either equal to ref or 0 or SEGPTR */
2888 char* p = ref;
2889 char** l_to = (char**)ref;
2890 int i,j,k;
2892 for(j=0;l_src[j];j++) ;
2893 p += (j + 1) * sizeof(char*);
2894 for(i=0;i<j;i++)
2895 { l_to[i] = base + (p - ref);
2896 k = ( item_size ) ? item_size : strlen(l_src[i]) + 1;
2897 memcpy(p, l_src[i], k); p += k; }
2898 l_to[i] = NULL;
2899 return (p - ref);
2902 /* ----- hostent */
2904 static int hostent_size(struct hostent* p_he)
2906 int size = 0;
2907 if( p_he )
2908 { size = sizeof(struct hostent);
2909 size += strlen(p_he->h_name) + 1;
2910 size += list_size(p_he->h_aliases, 0);
2911 size += list_size(p_he->h_addr_list, p_he->h_length ); }
2912 return size;
2915 int WS_dup_he(LPWSINFO pwsi, struct hostent* p_he, int flag)
2917 /* Convert hostent structure into ws_hostent so that the data fits
2918 * into pwsi->buffer. Internal pointers can be linear, SEGPTR, or
2919 * relative to pwsi->buffer depending on "flag" value. Returns size
2920 * of the data copied (also in the pwsi->buflen).
2923 int size = hostent_size(p_he);
2925 if( size )
2927 struct ws_hostent* p_to;
2928 char* p_name,*p_aliases,*p_addr,*p_base,*p;
2930 _check_buffer_he(pwsi, size);
2931 p_to = (struct ws_hostent*)pwsi->he;
2932 p = (char*)pwsi->he;
2933 p_base = (flag & WS_DUP_OFFSET) ? NULL
2934 : ((flag & WS_DUP_SEGPTR) ? (char*)SEGPTR_GET(p) : p);
2935 p += sizeof(struct ws_hostent);
2936 p_name = p;
2937 strcpy(p, p_he->h_name); p += strlen(p) + 1;
2938 p_aliases = p;
2939 p += list_dup(p_he->h_aliases, p, p_base + (p - (char*)pwsi->he), 0);
2940 p_addr = p;
2941 list_dup(p_he->h_addr_list, p, p_base + (p - (char*)pwsi->he), p_he->h_length);
2943 p_to->h_addrtype = (INT16)p_he->h_addrtype;
2944 p_to->h_length = (INT16)p_he->h_length;
2945 p_to->h_name = (SEGPTR)(p_base + (p_name - (char*)pwsi->he));
2946 p_to->h_aliases = (SEGPTR)(p_base + (p_aliases - (char*)pwsi->he));
2947 p_to->h_addr_list = (SEGPTR)(p_base + (p_addr - (char*)pwsi->he));
2949 size += (sizeof(struct ws_hostent) - sizeof(struct hostent));
2951 return size;
2954 /* ----- protoent */
2956 static int protoent_size(struct protoent* p_pe)
2958 int size = 0;
2959 if( p_pe )
2960 { size = sizeof(struct protoent);
2961 size += strlen(p_pe->p_name) + 1;
2962 size += list_size(p_pe->p_aliases, 0); }
2963 return size;
2966 int WS_dup_pe(LPWSINFO pwsi, struct protoent* p_pe, int flag)
2968 int size = protoent_size(p_pe);
2969 if( size )
2971 struct ws_protoent* p_to;
2972 char* p_name,*p_aliases,*p_base,*p;
2974 _check_buffer_pe(pwsi, size);
2975 p_to = (struct ws_protoent*)pwsi->pe;
2976 p = (char*)pwsi->pe;
2977 p_base = (flag & WS_DUP_OFFSET) ? NULL
2978 : ((flag & WS_DUP_SEGPTR) ? (char*)SEGPTR_GET(p) : p);
2979 p += sizeof(struct ws_protoent);
2980 p_name = p;
2981 strcpy(p, p_pe->p_name); p += strlen(p) + 1;
2982 p_aliases = p;
2983 list_dup(p_pe->p_aliases, p, p_base + (p - (char*)pwsi->pe), 0);
2985 p_to->p_proto = (INT16)p_pe->p_proto;
2986 p_to->p_name = (SEGPTR)(p_base) + (p_name - (char*)pwsi->pe);
2987 p_to->p_aliases = (SEGPTR)((p_base) + (p_aliases - (char*)pwsi->pe));
2989 size += (sizeof(struct ws_protoent) - sizeof(struct protoent));
2991 return size;
2994 /* ----- servent */
2996 static int servent_size(struct servent* p_se)
2998 int size = 0;
2999 if( p_se )
3000 { size += sizeof(struct servent);
3001 size += strlen(p_se->s_proto) + strlen(p_se->s_name) + 2;
3002 size += list_size(p_se->s_aliases, 0); }
3003 return size;
3006 int WS_dup_se(LPWSINFO pwsi, struct servent* p_se, int flag)
3008 int size = servent_size(p_se);
3009 if( size )
3011 struct ws_servent* p_to;
3012 char* p_name,*p_aliases,*p_proto,*p_base,*p;
3014 _check_buffer_se(pwsi, size);
3015 p_to = (struct ws_servent*)pwsi->se;
3016 p = (char*)pwsi->se;
3017 p_base = (flag & WS_DUP_OFFSET) ? NULL
3018 : ((flag & WS_DUP_SEGPTR) ? (char*)SEGPTR_GET(p) : p);
3019 p += sizeof(struct ws_servent);
3020 p_name = p;
3021 strcpy(p, p_se->s_name); p += strlen(p) + 1;
3022 p_proto = p;
3023 strcpy(p, p_se->s_proto); p += strlen(p) + 1;
3024 p_aliases = p;
3025 list_dup(p_se->s_aliases, p, p_base + (p - (char*)pwsi->se), 0);
3027 p_to->s_port = (INT16)p_se->s_port;
3028 p_to->s_name = (SEGPTR)(p_base + (p_name - (char*)pwsi->se));
3029 p_to->s_proto = (SEGPTR)(p_base + (p_proto - (char*)pwsi->se));
3030 p_to->s_aliases = (SEGPTR)(p_base + (p_aliases - (char*)pwsi->se));
3032 size += (sizeof(struct ws_servent) - sizeof(struct servent));
3034 return size;
3037 /* ----------------------------------- error handling */
3039 UINT16 wsaErrno(void)
3041 int loc_errno = errno;
3042 #ifdef HAVE_STRERROR
3043 WARN("errno %d, (%s).\n", loc_errno, strerror(loc_errno));
3044 #else
3045 WARN("errno %d\n", loc_errno);
3046 #endif
3048 switch(loc_errno)
3050 case EINTR: return WSAEINTR;
3051 case EBADF: return WSAEBADF;
3052 case EPERM:
3053 case EACCES: return WSAEACCES;
3054 case EFAULT: return WSAEFAULT;
3055 case EINVAL: return WSAEINVAL;
3056 case EMFILE: return WSAEMFILE;
3057 case EWOULDBLOCK: return WSAEWOULDBLOCK;
3058 case EINPROGRESS: return WSAEINPROGRESS;
3059 case EALREADY: return WSAEALREADY;
3060 case ENOTSOCK: return WSAENOTSOCK;
3061 case EDESTADDRREQ: return WSAEDESTADDRREQ;
3062 case EMSGSIZE: return WSAEMSGSIZE;
3063 case EPROTOTYPE: return WSAEPROTOTYPE;
3064 case ENOPROTOOPT: return WSAENOPROTOOPT;
3065 case EPROTONOSUPPORT: return WSAEPROTONOSUPPORT;
3066 case ESOCKTNOSUPPORT: return WSAESOCKTNOSUPPORT;
3067 case EOPNOTSUPP: return WSAEOPNOTSUPP;
3068 case EPFNOSUPPORT: return WSAEPFNOSUPPORT;
3069 case EAFNOSUPPORT: return WSAEAFNOSUPPORT;
3070 case EADDRINUSE: return WSAEADDRINUSE;
3071 case EADDRNOTAVAIL: return WSAEADDRNOTAVAIL;
3072 case ENETDOWN: return WSAENETDOWN;
3073 case ENETUNREACH: return WSAENETUNREACH;
3074 case ENETRESET: return WSAENETRESET;
3075 case ECONNABORTED: return WSAECONNABORTED;
3076 case EPIPE:
3077 case ECONNRESET: return WSAECONNRESET;
3078 case ENOBUFS: return WSAENOBUFS;
3079 case EISCONN: return WSAEISCONN;
3080 case ENOTCONN: return WSAENOTCONN;
3081 case ESHUTDOWN: return WSAESHUTDOWN;
3082 case ETOOMANYREFS: return WSAETOOMANYREFS;
3083 case ETIMEDOUT: return WSAETIMEDOUT;
3084 case ECONNREFUSED: return WSAECONNREFUSED;
3085 case ELOOP: return WSAELOOP;
3086 case ENAMETOOLONG: return WSAENAMETOOLONG;
3087 case EHOSTDOWN: return WSAEHOSTDOWN;
3088 case EHOSTUNREACH: return WSAEHOSTUNREACH;
3089 case ENOTEMPTY: return WSAENOTEMPTY;
3090 #ifdef EPROCLIM
3091 case EPROCLIM: return WSAEPROCLIM;
3092 #endif
3093 #ifdef EUSERS
3094 case EUSERS: return WSAEUSERS;
3095 #endif
3096 #ifdef EDQUOT
3097 case EDQUOT: return WSAEDQUOT;
3098 #endif
3099 #ifdef ESTALE
3100 case ESTALE: return WSAESTALE;
3101 #endif
3102 #ifdef EREMOTE
3103 case EREMOTE: return WSAEREMOTE;
3104 #endif
3106 /* just in case we ever get here and there are no problems */
3107 case 0: return 0;
3108 default:
3109 WARN("Unknown errno %d!\n", loc_errno);
3110 return WSAEOPNOTSUPP;
3114 UINT16 wsaHerrno(void)
3116 int loc_errno = h_errno;
3118 WARN("h_errno %d.\n", loc_errno);
3120 switch(loc_errno)
3122 case HOST_NOT_FOUND: return WSAHOST_NOT_FOUND;
3123 case TRY_AGAIN: return WSATRY_AGAIN;
3124 case NO_RECOVERY: return WSANO_RECOVERY;
3125 case NO_DATA: return WSANO_DATA;
3127 case 0: return 0;
3128 default:
3129 WARN("Unknown h_errno %d!\n", loc_errno);
3130 return WSAEOPNOTSUPP;