Prevent multiple definitions caused by MSVCRT headers.
[wine.git] / dlls / winsock / socket.c
blob59b3a04bf77d92c215c1839c6c0239a82c20e3fd
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 <stdio.h>
21 #include <string.h>
22 #include <sys/types.h>
23 #ifdef HAVE_SYS_IPC_H
24 # include <sys/ipc.h>
25 #endif
26 #include <sys/ioctl.h>
27 #ifdef HAVE_SYS_FILIO_H
28 # include <sys/filio.h>
29 #endif
30 #ifdef HAVE_SYS_SOCKIO_H
31 # include <sys/sockio.h>
32 #endif
34 #if defined(__EMX__)
35 # include <sys/so_ioctl.h>
36 #endif
38 #ifdef HAVE_SYS_PARAM_H
39 # include <sys/param.h>
40 #endif
42 #ifdef HAVE_SYS_MSG_H
43 # include <sys/msg.h>
44 #endif
45 #ifdef HAVE_SYS_WAIT_H
46 # include <sys/wait.h>
47 #endif
48 #ifdef HAVE_SYS_SOCKET_H
49 #include <sys/socket.h>
50 #endif
51 #ifdef HAVE_NETINET_IN_H
52 # include <netinet/in.h>
53 #endif
54 #ifdef HAVE_NETINET_TCP_H
55 # include <netinet/tcp.h>
56 #endif
57 #ifdef HAVE_ARPA_INET_H
58 # include <arpa/inet.h>
59 #endif
60 #include <ctype.h>
61 #include <fcntl.h>
62 #include <errno.h>
63 #ifdef HAVE_SYS_ERRNO_H
64 #include <sys/errno.h>
65 #endif
66 #ifdef HAVE_NETDB_H
67 #include <netdb.h>
68 #endif
69 #include <unistd.h>
70 #include <stdlib.h>
71 #ifdef HAVE_ARPA_NAMESER_H
72 # include <arpa/nameser.h>
73 #endif
74 #ifdef HAVE_RESOLV_H
75 # include <resolv.h>
76 #endif
77 #ifdef HAVE_NET_IF_H
78 # include <net/if.h>
79 #endif
80 #ifdef HAVE_IPX_GNU
81 # include <netipx/ipx.h>
82 # define HAVE_IPX
83 #endif
84 #ifdef HAVE_IPX_LINUX
85 # include <asm/types.h>
86 # include <linux/ipx.h>
87 # define HAVE_IPX
88 #endif
90 #include "wine/winbase16.h"
91 #include "wingdi.h"
92 #include "winuser.h"
93 #include "winsock2.h"
94 #include "wine/winsock16.h"
95 #include "winnt.h"
96 #include "heap.h"
97 #include "wine/port.h"
98 #include "services.h"
99 #include "server.h"
100 #include "file.h"
101 #include "debugtools.h"
104 DEFAULT_DEBUG_CHANNEL(winsock);
106 /* critical section to protect some non-rentrant net function */
107 extern CRITICAL_SECTION csWSgetXXXbyYYY;
109 #define DEBUG_SOCKADDR 0
110 #define dump_sockaddr(a) \
111 DPRINTF("sockaddr_in: family %d, address %s, port %d\n", \
112 ((struct sockaddr_in *)a)->sin_family, \
113 inet_ntoa(((struct sockaddr_in *)a)->sin_addr), \
114 ntohs(((struct sockaddr_in *)a)->sin_port))
116 /* ----------------------------------- internal data */
118 /* ws_... struct conversion flags */
120 #define WS_DUP_LINEAR 0x0001
121 #define WS_DUP_NATIVE 0x0000 /* not used anymore */
122 #define WS_DUP_OFFSET 0x0002 /* internal pointers are offsets */
123 #define WS_DUP_SEGPTR 0x0004 /* internal pointers are SEGPTRs */
124 /* by default, internal pointers are linear */
125 typedef struct /* WSAAsyncSelect() control struct */
127 HANDLE service, event, sock;
128 HWND hWnd;
129 UINT uMsg;
130 LONG lEvent;
131 } ws_select_info;
133 #define WS_MAX_SOCKETS_PER_PROCESS 128 /* reasonable guess */
134 #define WS_MAX_UDP_DATAGRAM 1024
136 #define WS_ACCEPT_QUEUE 6
138 #define PROCFS_NETDEV_FILE "/proc/net/dev" /* Points to the file in the /proc fs
139 that lists the network devices.
140 Do we need an #ifdef LINUX for this? */
142 static volatile HANDLE accept_old[WS_ACCEPT_QUEUE], accept_new[WS_ACCEPT_QUEUE];
144 static void *he_buffer; /* typecast for Win16/32 ws_hostent */
145 static void *se_buffer; /* typecast for Win16/32 ws_servent */
146 static void *pe_buffer; /* typecast for Win16/32 ws_protoent */
147 static char* local_buffer; /* allocated from SEGPTR heap */
148 static char* dbuffer; /* buffer for dummies (32 bytes) */
149 static INT num_startup; /* reference counter */
150 static FARPROC blocking_hook;
152 /* function prototypes */
153 int WS_dup_he(struct hostent* p_he, int flag);
154 int WS_dup_pe(struct protoent* p_pe, int flag);
155 int WS_dup_se(struct servent* p_se, int flag);
157 typedef void WIN_hostent;
158 typedef void WIN_protoent;
159 typedef void WIN_servent;
161 int WSAIOCTL_GetInterfaceCount(void);
162 int WSAIOCTL_GetInterfaceName(int intNumber, char *intName);
164 UINT16 wsaErrno(void);
165 UINT16 wsaHerrno(int errnr);
167 static HANDLE _WSHeap = 0;
169 #define WS_ALLOC(size) \
170 HeapAlloc(_WSHeap, HEAP_ZERO_MEMORY, (size) )
171 #define WS_FREE(ptr) \
172 HeapFree(_WSHeap, 0, (ptr) )
174 static INT _ws_sock_ops[] =
175 { WS_SO_DEBUG, WS_SO_REUSEADDR, WS_SO_KEEPALIVE, WS_SO_DONTROUTE,
176 WS_SO_BROADCAST, WS_SO_LINGER, WS_SO_OOBINLINE, WS_SO_SNDBUF,
177 WS_SO_RCVBUF, WS_SO_ERROR, WS_SO_TYPE,
178 #ifdef SO_RCVTIMEO
179 WS_SO_RCVTIMEO,
180 #endif
181 #ifdef SO_SNDTIMEO
182 WS_SO_SNDTIMEO,
183 #endif
184 0 };
185 static int _px_sock_ops[] =
186 { SO_DEBUG, SO_REUSEADDR, SO_KEEPALIVE, SO_DONTROUTE, SO_BROADCAST,
187 SO_LINGER, SO_OOBINLINE, SO_SNDBUF, SO_RCVBUF, SO_ERROR, SO_TYPE,
188 #ifdef SO_RCVTIMEO
189 SO_RCVTIMEO,
190 #endif
191 #ifdef SO_SNDTIMEO
192 SO_SNDTIMEO,
193 #endif
196 static INT _ws_tcp_ops[] = {
197 #ifdef TCP_NODELAY
198 WS_TCP_NODELAY,
199 #endif
202 static int _px_tcp_ops[] = {
203 #ifdef TCP_NODELAY
204 TCP_NODELAY,
205 #endif
209 /* set last error code from NT status without mapping WSA errors */
210 inline static unsigned int set_error( unsigned int err )
212 if (err)
214 /* do not map WSA errors */
215 if ((err < WSABASEERR) || (err >= 0x10000000)) err = RtlNtStatusToDosError(err);
216 SetLastError( err );
218 return err;
221 static char* check_buffer(int size);
223 static int _get_sock_fd(SOCKET s)
225 int fd = FILE_GetUnixHandle( s, GENERIC_READ );
226 if (fd == -1)
227 FIXME("handle %d is not a socket (GLE %ld)\n",s,GetLastError());
228 return fd;
231 static void _enable_event(SOCKET s, unsigned int event,
232 unsigned int sstate, unsigned int cstate)
234 SERVER_START_REQ( enable_socket_event )
236 req->handle = s;
237 req->mask = event;
238 req->sstate = sstate;
239 req->cstate = cstate;
240 SERVER_CALL();
242 SERVER_END_REQ;
245 static int _is_blocking(SOCKET s)
247 int ret;
248 SERVER_START_REQ( get_socket_event )
250 req->handle = s;
251 req->service = FALSE;
252 req->s_event = 0;
253 req->c_event = 0;
254 SERVER_CALL();
255 ret = (req->state & WS_FD_NONBLOCKING) == 0;
257 SERVER_END_REQ;
258 return ret;
261 static unsigned int _get_sock_mask(SOCKET s)
263 unsigned int ret;
264 SERVER_START_REQ( get_socket_event )
266 req->handle = s;
267 req->service = FALSE;
268 req->s_event = 0;
269 req->c_event = 0;
270 SERVER_CALL();
271 ret = req->mask;
273 SERVER_END_REQ;
274 return ret;
277 static void _sync_sock_state(SOCKET s)
279 /* do a dummy wineserver request in order to let
280 the wineserver run through its select loop once */
281 (void)_is_blocking(s);
284 static int _get_sock_error(SOCKET s, unsigned int bit)
286 int ret;
287 SERVER_START_VAR_REQ( get_socket_event, FD_MAX_EVENTS*sizeof(int) )
289 req->handle = s;
290 req->service = FALSE;
291 req->s_event = 0;
292 req->c_event = 0;
293 SERVER_CALL();
294 ret = *((int *)server_data_ptr(req) + bit);
296 SERVER_END_VAR_REQ;
297 return ret;
300 static void WINSOCK_DeleteIData(void)
302 /* delete scratch buffers */
304 if (he_buffer) SEGPTR_FREE(he_buffer);
305 if (se_buffer) SEGPTR_FREE(se_buffer);
306 if (pe_buffer) SEGPTR_FREE(pe_buffer);
307 if (local_buffer) SEGPTR_FREE(local_buffer);
308 if (dbuffer) SEGPTR_FREE(dbuffer);
309 he_buffer = NULL;
310 se_buffer = NULL;
311 pe_buffer = NULL;
312 local_buffer = NULL;
313 dbuffer = NULL;
314 num_startup = 0;
317 /***********************************************************************
318 * WSOCK32_LibMain (WSOCK32.init)
320 BOOL WINAPI WSOCK32_LibMain(HINSTANCE hInstDLL, DWORD fdwReason, LPVOID fImpLoad)
322 TRACE("0x%x 0x%lx %p\n", hInstDLL, fdwReason, fImpLoad);
323 switch (fdwReason) {
324 case DLL_PROCESS_DETACH:
325 WINSOCK_DeleteIData();
326 break;
328 return TRUE;
331 /***********************************************************************
332 * convert_sockopt()
334 * Converts socket flags from Windows format.
335 * Return 1 if converted, 0 if not (error).
337 static int convert_sockopt(INT *level, INT *optname)
339 int i;
340 switch (*level)
342 case WS_SOL_SOCKET:
343 *level = SOL_SOCKET;
344 for(i=0; _ws_sock_ops[i]; i++)
345 if( _ws_sock_ops[i] == *optname ) break;
346 if( _ws_sock_ops[i] ) {
347 *optname = _px_sock_ops[i];
348 return 1;
350 FIXME("Unknown SOL_SOCKET optname 0x%x\n", *optname);
351 break;
352 case WS_IPPROTO_TCP:
353 *level = IPPROTO_TCP;
354 for(i=0; _ws_tcp_ops[i]; i++)
355 if ( _ws_tcp_ops[i] == *optname ) break;
356 if( _ws_tcp_ops[i] ) {
357 *optname = _px_tcp_ops[i];
358 return 1;
360 FIXME("Unknown IPPROTO_TCP optname 0x%x\n", *optname);
361 break;
363 return 0;
366 /* ----------------------------------- Per-thread info (or per-process?) */
368 static int wsi_strtolo(const char* name, const char* opt)
370 /* Stuff a lowercase copy of the string into the local buffer */
372 int i = strlen(name) + 2;
373 char* p = check_buffer(i + ((opt)?strlen(opt):0));
375 if( p )
377 do *p++ = tolower(*name); while(*name++);
378 i = (p - local_buffer);
379 if( opt ) do *p++ = tolower(*opt); while(*opt++);
380 return i;
382 return 0;
385 static fd_set* fd_set_import( fd_set* fds, void* wsfds, int* highfd, int lfd[], BOOL b32 )
387 /* translate Winsock fd set into local fd set */
389 if( wsfds )
391 #define wsfds16 ((ws_fd_set16*)wsfds)
392 #define wsfds32 ((ws_fd_set32*)wsfds)
393 int i, count;
395 FD_ZERO(fds);
396 count = b32 ? wsfds32->fd_count : wsfds16->fd_count;
398 for( i = 0; i < count; i++ )
400 int s = (b32) ? wsfds32->fd_array[i]
401 : wsfds16->fd_array[i];
402 int fd = _get_sock_fd(s);
403 if (fd != -1)
405 lfd[ i ] = fd;
406 if( fd > *highfd ) *highfd = fd;
407 FD_SET(fd, fds);
409 else lfd[ i ] = -1;
411 #undef wsfds32
412 #undef wsfds16
413 return fds;
415 return NULL;
418 inline static int sock_error_p(int s)
420 unsigned int optval, optlen;
422 optlen = sizeof(optval);
423 getsockopt(s, SOL_SOCKET, SO_ERROR, (void *) &optval, &optlen);
424 if (optval) WARN("\t[%i] error: %d\n", s, optval);
425 return optval != 0;
428 static int fd_set_export( fd_set* fds, fd_set* exceptfds, void* wsfds, int lfd[], BOOL b32 )
430 int num_err = 0;
432 /* translate local fd set into Winsock fd set, adding
433 * errors to exceptfds (only if app requested it) */
435 if( wsfds )
437 #define wsfds16 ((ws_fd_set16*)wsfds)
438 #define wsfds32 ((ws_fd_set32*)wsfds)
439 int i, j, count = (b32) ? wsfds32->fd_count : wsfds16->fd_count;
441 for( i = 0, j = 0; i < count; i++ )
443 if( lfd[i] >= 0 )
445 int fd = lfd[i];
446 if( FD_ISSET(fd, fds) )
448 if ( exceptfds && sock_error_p(fd) )
450 FD_SET(fd, exceptfds);
451 num_err++;
453 else if( b32 )
454 wsfds32->fd_array[j++] = wsfds32->fd_array[i];
455 else
456 wsfds16->fd_array[j++] = wsfds16->fd_array[i];
458 close(fd);
459 lfd[i] = -1;
463 if( b32 ) wsfds32->fd_count = j;
464 else wsfds16->fd_count = j;
466 TRACE("\n");
467 #undef wsfds32
468 #undef wsfds16
470 return num_err;
473 static void fd_set_unimport( void* wsfds, int lfd[], BOOL b32 )
475 if ( wsfds )
477 #define wsfds16 ((ws_fd_set16*)wsfds)
478 #define wsfds32 ((ws_fd_set32*)wsfds)
479 int i, count = (b32) ? wsfds32->fd_count : wsfds16->fd_count;
481 for( i = 0; i < count; i++ )
482 if ( lfd[i] >= 0 )
483 close(lfd[i]);
485 TRACE("\n");
486 #undef wsfds32
487 #undef wsfds16
491 static int do_block( int fd, int mask )
493 fd_set fds[3];
494 int i, r;
496 FD_ZERO(&fds[0]);
497 FD_ZERO(&fds[1]);
498 FD_ZERO(&fds[2]);
499 for (i=0; i<3; i++)
500 if (mask & (1<<i))
501 FD_SET(fd, &fds[i]);
502 i = select( fd+1, &fds[0], &fds[1], &fds[2], NULL );
503 if (i <= 0) return -1;
504 r = 0;
505 for (i=0; i<3; i++)
506 if (FD_ISSET(fd, &fds[i]))
507 r |= 1<<i;
508 return r;
511 void* __ws_memalloc( int size )
513 return WS_ALLOC(size);
516 void __ws_memfree(void* ptr)
518 WS_FREE(ptr);
522 /* ----------------------------------- API -----
524 * Init / cleanup / error checking.
527 /***********************************************************************
528 * WSAStartup16() (WINSOCK.115)
530 * Create socket control struct, attach it to the global list and
531 * update a pointer in the task struct.
533 INT16 WINAPI WSAStartup16(UINT16 wVersionRequested, LPWSADATA lpWSAData)
535 WSADATA WINSOCK_data = { 0x0101, 0x0101,
536 "WINE Sockets 1.1",
537 #ifdef linux
538 "Linux/i386",
539 #elif defined(__NetBSD__)
540 "NetBSD/i386",
541 #elif defined(sunos)
542 "SunOS",
543 #elif defined(__FreeBSD__)
544 "FreeBSD",
545 #elif defined(__OpenBSD__)
546 "OpenBSD/i386",
547 #else
548 "Unknown",
549 #endif
550 WS_MAX_SOCKETS_PER_PROCESS,
551 WS_MAX_UDP_DATAGRAM, (SEGPTR)NULL };
553 TRACE("verReq=%x\n", wVersionRequested);
555 if (LOBYTE(wVersionRequested) < 1 || (LOBYTE(wVersionRequested) == 1 &&
556 HIBYTE(wVersionRequested) < 1)) return WSAVERNOTSUPPORTED;
558 if (!lpWSAData) return WSAEINVAL;
560 /* initialize socket heap */
562 if( !_WSHeap )
564 _WSHeap = HeapCreate(HEAP_ZERO_MEMORY, 8120, 32768);
565 if( !_WSHeap )
567 ERR("Fatal: failed to create WinSock heap\n");
568 return 0;
571 if( _WSHeap == 0 ) return WSASYSNOTREADY;
573 num_startup++;
575 /* return winsock information */
577 memcpy(lpWSAData, &WINSOCK_data, sizeof(WINSOCK_data));
579 TRACE("succeeded\n");
580 return 0;
583 /***********************************************************************
584 * WSAStartup() (WS2_32.115)
586 INT WINAPI WSAStartup(UINT wVersionRequested, LPWSADATA lpWSAData)
588 WSADATA WINSOCK_data = { 0x0202, 0x0202,
589 "WINE Sockets 2.0",
590 #ifdef linux
591 "Linux/i386",
592 #elif defined(__NetBSD__)
593 "NetBSD/i386",
594 #elif defined(sunos)
595 "SunOS",
596 #elif defined(__FreeBSD__)
597 "FreeBSD",
598 #elif defined(__OpenBSD__)
599 "OpenBSD/i386",
600 #else
601 "Unknown",
602 #endif
603 WS_MAX_SOCKETS_PER_PROCESS,
604 WS_MAX_UDP_DATAGRAM, (SEGPTR)NULL };
606 TRACE("verReq=%x\n", wVersionRequested);
608 if (LOBYTE(wVersionRequested) < 1)
609 return WSAVERNOTSUPPORTED;
611 if (!lpWSAData) return WSAEINVAL;
613 /* initialize socket heap */
615 if( !_WSHeap )
617 _WSHeap = HeapCreate(HEAP_ZERO_MEMORY, 8120, 32768);
618 if( !_WSHeap )
620 ERR("Fatal: failed to create WinSock heap\n");
621 return 0;
624 if( _WSHeap == 0 ) return WSASYSNOTREADY;
626 num_startup++;
628 /* return winsock information */
629 memcpy(lpWSAData, &WINSOCK_data, sizeof(WINSOCK_data));
631 /* that's the whole of the negotiation for now */
632 lpWSAData->wVersion = wVersionRequested;
634 TRACE("succeeded\n");
635 return 0;
639 /***********************************************************************
640 * WSACleanup() (WINSOCK.116)
642 INT WINAPI WSACleanup(void)
644 if (num_startup)
646 if (--num_startup > 0) return 0;
647 WINSOCK_DeleteIData();
648 return 0;
650 SetLastError(WSANOTINITIALISED);
651 return SOCKET_ERROR;
655 /***********************************************************************
656 * WSAGetLastError() (WSOCK32.111)(WINSOCK.111)
658 INT WINAPI WSAGetLastError(void)
660 return GetLastError();
663 /***********************************************************************
664 * WSASetLastError() (WSOCK32.112)
666 void WINAPI WSASetLastError(INT iError) {
667 SetLastError(iError);
670 /***********************************************************************
671 * WSASetLastError16() (WINSOCK.112)
673 void WINAPI WSASetLastError16(INT16 iError)
675 WSASetLastError(iError);
678 static char* check_buffer(int size)
680 static int local_buflen;
682 if (local_buffer)
684 if (local_buflen >= size ) return local_buffer;
685 SEGPTR_FREE(local_buffer);
687 local_buffer = SEGPTR_ALLOC((local_buflen = size));
688 return local_buffer;
691 static struct ws_hostent* check_buffer_he(int size)
693 static int he_len;
694 if (he_buffer)
696 if (he_len >= size ) return he_buffer;
697 SEGPTR_FREE(he_buffer);
699 he_buffer = SEGPTR_ALLOC((he_len = size));
700 return he_buffer;
703 static void* check_buffer_se(int size)
705 static int se_len;
706 if (se_buffer)
708 if (se_len >= size ) return se_buffer;
709 SEGPTR_FREE(se_buffer);
711 se_buffer = SEGPTR_ALLOC((se_len = size));
712 return se_buffer;
715 static struct ws_protoent* check_buffer_pe(int size)
717 static int pe_len;
718 if (pe_buffer)
720 if (pe_len >= size ) return pe_buffer;
721 SEGPTR_FREE(pe_buffer);
723 pe_buffer = SEGPTR_ALLOC((pe_len = size));
724 return pe_buffer;
727 /* ----------------------------------- i/o APIs */
729 /***********************************************************************
730 * accept() (WSOCK32.1)
732 static void WSOCK32_async_accept(SOCKET s, SOCKET as)
734 int q;
735 /* queue socket for WSAAsyncSelect */
736 for (q=0; q<WS_ACCEPT_QUEUE; q++)
737 if (InterlockedCompareExchange((PVOID*)&accept_old[q], (PVOID)s, (PVOID)0) == (PVOID)0)
738 break;
739 if (q<WS_ACCEPT_QUEUE)
740 accept_new[q] = as;
741 else
742 ERR("accept queue too small\n");
743 /* now signal our AsyncSelect handler */
744 _enable_event(s, WS_FD_SERVEVENT, 0, 0);
747 /**********************************************************************/
749 SOCKET WINAPI WSOCK32_accept(SOCKET s, struct sockaddr *addr,
750 INT *addrlen32)
752 #ifdef HAVE_IPX
753 struct ws_sockaddr_ipx* addr2 = (struct ws_sockaddr_ipx *)addr;
754 #endif
755 int fd = _get_sock_fd(s);
757 TRACE("socket %04x\n", (UINT16)s );
758 if (fd != -1)
760 SOCKET as;
761 if (_is_blocking(s))
763 /* block here */
764 do_block(fd, 5);
765 _sync_sock_state(s); /* let wineserver notice connection */
766 /* retrieve any error codes from it */
767 SetLastError(_get_sock_error(s, FD_ACCEPT_BIT));
768 /* FIXME: care about the error? */
770 close(fd);
771 SERVER_START_REQ( accept_socket )
773 req->lhandle = s;
774 req->access = GENERIC_READ|GENERIC_WRITE|SYNCHRONIZE;
775 req->inherit = TRUE;
776 set_error( SERVER_CALL() );
777 as = (SOCKET)req->handle;
779 SERVER_END_REQ;
780 if (as)
782 unsigned omask = _get_sock_mask( s );
783 int fd = _get_sock_fd( as );
784 if( getpeername(fd, addr, addrlen32) != -1 )
786 #ifdef HAVE_IPX
787 if (addr && ((struct sockaddr_ipx *)addr)->sipx_family == AF_IPX) {
788 addr = (struct sockaddr *)
789 malloc(addrlen32 ? *addrlen32 : sizeof(*addr2));
790 memcpy(addr, addr2,
791 addrlen32 ? *addrlen32 : sizeof(*addr2));
792 addr2->sipx_family = WS_AF_IPX;
793 addr2->sipx_network = ((struct sockaddr_ipx *)addr)->sipx_network;
794 addr2->sipx_port = ((struct sockaddr_ipx *)addr)->sipx_port;
795 memcpy(addr2->sipx_node,
796 ((struct sockaddr_ipx *)addr)->sipx_node, IPX_NODE_LEN);
797 free(addr);
799 #endif
800 } else SetLastError(wsaErrno());
801 close(fd);
802 if (omask & WS_FD_SERVEVENT)
803 WSOCK32_async_accept(s, as);
804 return as;
807 return INVALID_SOCKET;
810 /***********************************************************************
811 * accept() (WINSOCK.1)
813 SOCKET16 WINAPI WINSOCK_accept16(SOCKET16 s, struct sockaddr* addr,
814 INT16* addrlen16 )
816 INT addrlen32 = addrlen16 ? *addrlen16 : 0;
817 SOCKET retSocket = WSOCK32_accept( s, addr, &addrlen32 );
818 if( addrlen16 ) *addrlen16 = (INT16)addrlen32;
819 return (SOCKET16)retSocket;
822 /***********************************************************************
823 * bind() (WSOCK32.2)
825 INT WINAPI WSOCK32_bind(SOCKET s, struct sockaddr *name, INT namelen)
827 #ifdef HAVE_IPX
828 struct ws_sockaddr_ipx* name2 = (struct ws_sockaddr_ipx *)name;
829 #endif
830 int fd = _get_sock_fd(s);
832 TRACE("socket %04x, ptr %8x, length %d\n", s, (int) name, namelen);
833 #if DEBUG_SOCKADDR
834 dump_sockaddr(name);
835 #endif
837 if (fd != -1)
839 /* FIXME: what family does this really map to on the Unix side? */
840 if (name && ((struct ws_sockaddr_ipx *)name)->sipx_family == WS_AF_PUP)
841 ((struct ws_sockaddr_ipx *)name)->sipx_family = AF_UNSPEC;
842 #ifdef HAVE_IPX
843 else if (name &&
844 ((struct ws_sockaddr_ipx *)name)->sipx_family == WS_AF_IPX)
846 name = (struct sockaddr *) malloc(sizeof(struct sockaddr_ipx));
847 memset(name, '\0', sizeof(struct sockaddr_ipx));
848 ((struct sockaddr_ipx *)name)->sipx_family = AF_IPX;
849 ((struct sockaddr_ipx *)name)->sipx_port = name2->sipx_port;
850 ((struct sockaddr_ipx *)name)->sipx_network = name2->sipx_network;
851 memcpy(((struct sockaddr_ipx *)name)->sipx_node,
852 name2->sipx_node, IPX_NODE_LEN);
853 namelen = sizeof(struct sockaddr_ipx);
855 #endif
856 if ( namelen >= sizeof(*name) )
858 if ( name && (((struct ws_sockaddr_in *)name)->sin_family == AF_INET
859 #ifdef HAVE_IPX
860 || ((struct sockaddr_ipx *)name)->sipx_family == AF_IPX
861 #endif
864 if ( bind(fd, name, namelen) < 0 )
866 int loc_errno = errno;
867 WARN("\tfailure - errno = %i\n", errno);
868 errno = loc_errno;
869 switch(errno)
871 case EBADF: SetLastError(WSAENOTSOCK); break;
872 case EADDRNOTAVAIL: SetLastError(WSAEINVAL); break;
873 default: SetLastError(wsaErrno());break;
876 else {
877 #ifdef HAVE_IPX
878 if (((struct sockaddr_ipx *)name)->sipx_family == AF_IPX)
879 free(name);
880 #endif
881 close(fd);
882 return 0; /* success */
884 } else SetLastError(WSAEAFNOSUPPORT);
885 } else SetLastError(WSAEFAULT);
886 #ifdef HAVE_IPX
887 if (name && ((struct sockaddr_ipx *)name)->sipx_family == AF_IPX)
888 free(name);
889 #endif
890 close(fd);
892 return SOCKET_ERROR;
895 /***********************************************************************
896 * bind() (WINSOCK.2)
898 INT16 WINAPI WINSOCK_bind16(SOCKET16 s, struct sockaddr *name, INT16 namelen)
900 return (INT16)WSOCK32_bind( s, name, namelen );
903 /***********************************************************************
904 * closesocket() (WSOCK32.3)
906 INT WINAPI WSOCK32_closesocket(SOCKET s)
908 TRACE("socket %08x\n", s);
909 if (CloseHandle(s)) return 0;
910 return SOCKET_ERROR;
913 /***********************************************************************
914 * closesocket() (WINSOCK.3)
916 INT16 WINAPI WINSOCK_closesocket16(SOCKET16 s)
918 return (INT16)WSOCK32_closesocket(s);
921 /***********************************************************************
922 * connect() (WSOCK32.4)
924 INT WINAPI WSOCK32_connect(SOCKET s, struct sockaddr *name, INT namelen)
926 #ifdef HAVE_IPX
927 struct ws_sockaddr_ipx* name2 = (struct ws_sockaddr_ipx *)name;
928 #endif
929 int fd = _get_sock_fd(s);
931 TRACE("socket %04x, ptr %8x, length %d\n", s, (int) name, namelen);
932 #if DEBUG_SOCKADDR
933 dump_sockaddr(name);
934 #endif
936 if (fd != -1)
938 if (name && ((struct ws_sockaddr_ipx *)name)->sipx_family == WS_AF_PUP)
939 ((struct ws_sockaddr_ipx *)name)->sipx_family = AF_UNSPEC;
940 #ifdef HAVE_IPX
941 else if (name && ((struct ws_sockaddr_ipx *)name)->sipx_family == WS_AF_IPX)
943 name = (struct sockaddr *) malloc(sizeof(struct sockaddr_ipx));
944 memset(name, '\0', sizeof(struct sockaddr_ipx));
945 ((struct sockaddr_ipx *)name)->sipx_family = AF_IPX;
946 ((struct sockaddr_ipx *)name)->sipx_port = name2->sipx_port;
947 ((struct sockaddr_ipx *)name)->sipx_network = name2->sipx_network;
948 memcpy(((struct sockaddr_ipx *)name)->sipx_node,
949 name2->sipx_node, IPX_NODE_LEN);
950 namelen = sizeof(struct sockaddr_ipx);
952 #endif
953 if (connect(fd, name, namelen) == 0) {
954 close(fd);
955 goto connect_success;
957 if (errno == EINPROGRESS)
959 /* tell wineserver that a connection is in progress */
960 _enable_event(s, FD_CONNECT|FD_READ|FD_WRITE,
961 WS_FD_CONNECT|WS_FD_READ|WS_FD_WRITE,
962 WS_FD_CONNECTED|WS_FD_LISTENING);
963 if (_is_blocking(s))
965 int result;
966 /* block here */
967 do_block(fd, 7);
968 _sync_sock_state(s); /* let wineserver notice connection */
969 /* retrieve any error codes from it */
970 result = _get_sock_error(s, FD_CONNECT_BIT);
971 if (result)
972 SetLastError(result);
973 else {
974 close(fd);
975 goto connect_success;
978 else SetLastError(WSAEWOULDBLOCK);
979 close(fd);
981 else
983 SetLastError(wsaErrno());
984 close(fd);
987 #ifdef HAVE_IPX
988 if (name && ((struct sockaddr_ipx *)name)->sipx_family == AF_IPX)
989 free(name);
990 #endif
991 return SOCKET_ERROR;
992 connect_success:
993 #ifdef HAVE_IPX
994 if (((struct sockaddr_ipx *)name)->sipx_family == AF_IPX)
995 free(name);
996 #endif
997 _enable_event(s, FD_CONNECT|FD_READ|FD_WRITE,
998 WS_FD_CONNECTED|WS_FD_READ|WS_FD_WRITE,
999 WS_FD_CONNECT|WS_FD_LISTENING);
1000 return 0;
1003 /***********************************************************************
1004 * connect() (WINSOCK.4)
1006 INT16 WINAPI WINSOCK_connect16(SOCKET16 s, struct sockaddr *name, INT16 namelen)
1008 return (INT16)WSOCK32_connect( s, name, namelen );
1011 /***********************************************************************
1012 * getpeername() (WSOCK32.5)
1014 INT WINAPI WSOCK32_getpeername(SOCKET s, struct sockaddr *name,
1015 INT *namelen)
1017 #ifdef HAVE_IPX
1018 struct ws_sockaddr_ipx* name2 = (struct ws_sockaddr_ipx *)name;
1019 #endif
1020 int fd = _get_sock_fd(s);
1022 TRACE("socket: %04x, ptr %8x, ptr %8x\n", s, (int) name, *namelen);
1023 if (fd != -1)
1025 if (getpeername(fd, name, namelen) == 0) {
1026 #ifdef HAVE_IPX
1027 if (((struct ws_sockaddr_ipx *)name)->sipx_family == AF_IPX) {
1028 name = (struct sockaddr *)
1029 malloc(namelen ? *namelen : sizeof(*name2));
1030 memcpy(name, name2, namelen ? *namelen : sizeof(*name2));
1031 name2->sipx_family = WS_AF_IPX;
1032 name2->sipx_network = ((struct sockaddr_ipx *)name)->sipx_network;
1033 name2->sipx_port = ((struct sockaddr_ipx *)name)->sipx_port;
1034 memcpy(name2->sipx_node,
1035 ((struct sockaddr_ipx *)name)->sipx_node, IPX_NODE_LEN);
1036 free(name);
1038 #endif
1039 close(fd);
1040 return 0;
1042 SetLastError(wsaErrno());
1043 close(fd);
1045 return SOCKET_ERROR;
1048 /***********************************************************************
1049 * getpeername() (WINSOCK.5)
1051 INT16 WINAPI WINSOCK_getpeername16(SOCKET16 s, struct sockaddr *name,
1052 INT16 *namelen16)
1054 INT namelen32 = *namelen16;
1055 INT retVal = WSOCK32_getpeername( s, name, &namelen32 );
1057 #if DEBUG_SOCKADDR
1058 dump_sockaddr(name);
1059 #endif
1061 *namelen16 = namelen32;
1062 return (INT16)retVal;
1065 /***********************************************************************
1066 * getsockname() (WSOCK32.6)
1068 INT WINAPI WSOCK32_getsockname(SOCKET s, struct sockaddr *name,
1069 INT *namelen)
1071 #ifdef HAVE_IPX
1072 struct ws_sockaddr_ipx* name2 = (struct ws_sockaddr_ipx *)name;
1073 #endif
1074 int fd = _get_sock_fd(s);
1076 TRACE("socket: %04x, ptr %8x, ptr %8x\n", s, (int) name, (int) *namelen);
1077 if (fd != -1)
1079 if (getsockname(fd, name, namelen) == 0) {
1080 #ifdef HAVE_IPX
1081 if (((struct sockaddr_ipx *)name)->sipx_family == AF_IPX) {
1082 name = (struct sockaddr *)
1083 malloc(namelen ? *namelen : sizeof(*name2));
1084 memcpy(name, name2, namelen ? *namelen : sizeof(*name2));
1085 name2->sipx_family = WS_AF_IPX;
1086 name2->sipx_network = ((struct sockaddr_ipx *)name)->sipx_network;
1087 name2->sipx_port = ((struct sockaddr_ipx *)name)->sipx_port;
1088 memcpy(name2->sipx_node,
1089 ((struct sockaddr_ipx *)name)->sipx_node, IPX_NODE_LEN);
1090 free(name);
1092 #endif
1093 close(fd);
1094 return 0;
1096 SetLastError(wsaErrno());
1097 close(fd);
1099 return SOCKET_ERROR;
1102 /***********************************************************************
1103 * getsockname() (WINSOCK.6)
1105 INT16 WINAPI WINSOCK_getsockname16(SOCKET16 s, struct sockaddr *name,
1106 INT16 *namelen16)
1108 INT retVal;
1110 if( namelen16 )
1112 INT namelen32 = *namelen16;
1113 retVal = WSOCK32_getsockname( s, name, &namelen32 );
1114 *namelen16 = namelen32;
1116 #if DEBUG_SOCKADDR
1117 dump_sockaddr(name);
1118 #endif
1121 else retVal = SOCKET_ERROR;
1122 return (INT16)retVal;
1126 /***********************************************************************
1127 * getsockopt() (WSOCK32.7)
1129 INT WINAPI WSOCK32_getsockopt(SOCKET s, INT level,
1130 INT optname, char *optval, INT *optlen)
1132 int fd = _get_sock_fd(s);
1134 TRACE("socket: %04x, opt 0x%x, ptr %8x, len %d\n", s, level, (int) optval, (int) *optlen);
1135 if (fd != -1)
1137 if (!convert_sockopt(&level, &optname)) {
1138 SetLastError(WSAENOPROTOOPT); /* Unknown option */
1139 } else {
1140 if (getsockopt(fd, (int) level, optname, optval, optlen) == 0 )
1142 close(fd);
1143 return 0;
1145 SetLastError((errno == EBADF) ? WSAENOTSOCK : wsaErrno());
1147 close(fd);
1149 return SOCKET_ERROR;
1152 /***********************************************************************
1153 * getsockopt() (WINSOCK.7)
1155 INT16 WINAPI WINSOCK_getsockopt16(SOCKET16 s, INT16 level,
1156 INT16 optname, char *optval, INT16 *optlen)
1158 INT optlen32;
1159 INT *p = &optlen32;
1160 INT retVal;
1161 if( optlen ) optlen32 = *optlen; else p = NULL;
1162 retVal = WSOCK32_getsockopt( s, (UINT16)level, optname, optval, p );
1163 if( optlen ) *optlen = optlen32;
1164 return (INT16)retVal;
1167 /***********************************************************************
1168 * htonl() (WINSOCK.8)(WSOCK32.8)
1170 u_long WINAPI WINSOCK_htonl(u_long hostlong) { return( htonl(hostlong) ); }
1171 /***********************************************************************
1172 * htons() (WINSOCK.9)(WSOCK32.9)
1174 u_short WINAPI WINSOCK_htons(u_short hostshort) { return( htons(hostshort) ); }
1175 /***********************************************************************
1176 * inet_addr() (WINSOCK.10)(WSOCK32.10)
1178 u_long WINAPI WINSOCK_inet_addr(char *cp) { return( inet_addr(cp) ); }
1179 /***********************************************************************
1180 * ntohl() (WINSOCK.14)(WSOCK32.14)
1182 u_long WINAPI WINSOCK_ntohl(u_long netlong) { return( ntohl(netlong) ); }
1183 /***********************************************************************
1184 * ntohs() (WINSOCK.15)(WSOCK32.15)
1186 u_short WINAPI WINSOCK_ntohs(u_short netshort) { return( ntohs(netshort) ); }
1188 /***********************************************************************
1189 * inet_ntoa() (WINSOCK.11)(WSOCK32.11)
1191 char* WINAPI WSOCK32_inet_ntoa(struct in_addr in)
1193 /* use "buffer for dummies" here because some applications have
1194 * propensity to decode addresses in ws_hostent structure without
1195 * saving them first...
1197 char* s = inet_ntoa(in);
1198 if( s )
1200 if( dbuffer == NULL ) {
1201 /* Yes, 16: 4*3 digits + 3 '.' + 1 '\0' */
1202 if((dbuffer = (char*) SEGPTR_ALLOC(16)) == NULL )
1204 SetLastError(WSAENOBUFS);
1205 return NULL;
1208 strcpy(dbuffer, s);
1209 return dbuffer;
1211 SetLastError(wsaErrno());
1212 return NULL;
1215 /**********************************************************************/
1217 SEGPTR WINAPI WINSOCK_inet_ntoa16(struct in_addr in)
1219 char* retVal = WSOCK32_inet_ntoa(in);
1220 return SEGPTR_GET(retVal);
1224 /**********************************************************************
1225 * WSAIoctl (WS2_32)
1228 * FIXME: Only SIO_GET_INTERFACE_LIST option implemented.
1230 INT WINAPI WSAIoctl (SOCKET s,
1231 DWORD dwIoControlCode,
1232 LPVOID lpvInBuffer,
1233 DWORD cbInBuffer,
1234 LPVOID lpbOutBuffer,
1235 DWORD cbOutBuffer,
1236 LPDWORD lpcbBytesReturned,
1237 LPWSAOVERLAPPED lpOverlapped,
1238 LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine)
1240 int fd = _get_sock_fd(s);
1242 if (fd != -1)
1244 switch( dwIoControlCode )
1246 case SIO_GET_INTERFACE_LIST:
1248 INTERFACE_INFO* intArray = (INTERFACE_INFO*)lpbOutBuffer;
1249 int i, numInt;
1250 struct ifreq ifInfo;
1251 char ifName[512];
1254 TRACE ("-> SIO_GET_INTERFACE_LIST request\n");
1256 numInt = WSAIOCTL_GetInterfaceCount();
1257 if (numInt < 0)
1259 ERR ("Unable to open /proc filesystem to determine number of network interfaces!\n");
1260 close(fd);
1261 WSASetLastError(WSAEINVAL);
1262 return (SOCKET_ERROR);
1265 for (i=0; i<numInt; i++)
1267 if (!WSAIOCTL_GetInterfaceName(i, ifName))
1269 ERR ("Error parsing /proc filesystem!\n");
1270 close(fd);
1271 WSASetLastError(WSAEINVAL);
1272 return (SOCKET_ERROR);
1275 ifInfo.ifr_addr.sa_family = AF_INET;
1277 /* IP Address */
1278 strcpy (ifInfo.ifr_name, ifName);
1279 if (ioctl(fd, SIOCGIFADDR, &ifInfo) < 0)
1281 ERR ("Error obtaining IP address\n");
1282 close(fd);
1283 WSASetLastError(WSAEINVAL);
1284 return (SOCKET_ERROR);
1286 else
1288 struct ws_sockaddr_in *ipTemp = (struct ws_sockaddr_in *)&ifInfo.ifr_addr;
1290 intArray->iiAddress.AddressIn.sin_family = AF_INET;
1291 intArray->iiAddress.AddressIn.sin_port = ipTemp->sin_port;
1292 intArray->iiAddress.AddressIn.sin_addr.ws_addr = ipTemp->sin_addr.S_un.S_addr;
1295 /* Broadcast Address */
1296 strcpy (ifInfo.ifr_name, ifName);
1297 if (ioctl(fd, SIOCGIFBRDADDR, &ifInfo) < 0)
1299 ERR ("Error obtaining Broadcast IP address\n");
1300 close(fd);
1301 WSASetLastError(WSAEINVAL);
1302 return (SOCKET_ERROR);
1304 else
1306 struct ws_sockaddr_in *ipTemp = (struct ws_sockaddr_in *)&ifInfo.ifr_broadaddr;
1308 intArray->iiBroadcastAddress.AddressIn.sin_family = AF_INET;
1309 intArray->iiBroadcastAddress.AddressIn.sin_port = ipTemp->sin_port;
1310 intArray->iiBroadcastAddress.AddressIn.sin_addr.ws_addr = ipTemp->sin_addr.S_un.S_addr;
1313 /* Subnet Mask */
1314 strcpy (ifInfo.ifr_name, ifName);
1315 if (ioctl(fd, SIOCGIFNETMASK, &ifInfo) < 0)
1317 ERR ("Error obtaining Subnet IP address\n");
1318 close(fd);
1319 WSASetLastError(WSAEINVAL);
1320 return (SOCKET_ERROR);
1322 else
1324 /* Trying to avoid some compile problems across platforms.
1325 (Linux, FreeBSD, Solaris...) */
1326 #ifndef ifr_netmask
1327 #ifndef ifr_addr
1328 intArray->iiNetmask.AddressIn.sin_family = AF_INET;
1329 intArray->iiNetmask.AddressIn.sin_port = 0;
1330 intArray->iiNetmask.AddressIn.sin_addr.ws_addr = 0;
1331 ERR ("Unable to determine Netmask on your platform!\n");
1332 #else
1333 struct ws_sockaddr_in *ipTemp = (struct ws_sockaddr_in *)&ifInfo.ifr_addr;
1335 intArray->iiNetmask.AddressIn.sin_family = AF_INET;
1336 intArray->iiNetmask.AddressIn.sin_port = ipTemp->sin_port;
1337 intArray->iiNetmask.AddressIn.sin_addr.ws_addr = ipTemp->sin_addr.S_un.S_addr;
1338 #endif
1339 #else
1340 struct ws_sockaddr_in *ipTemp = (struct ws_sockaddr_in *)&ifInfo.ifr_netmask;
1342 intArray->iiNetmask.AddressIn.sin_family = AF_INET;
1343 intArray->iiNetmask.AddressIn.sin_port = ipTemp->sin_port;
1344 intArray->iiNetmask.AddressIn.sin_addr.ws_addr = ipTemp->sin_addr.S_un.S_addr;
1345 #endif
1348 /* Socket Status Flags */
1349 strcpy(ifInfo.ifr_name, ifName);
1350 if (ioctl(fd, SIOCGIFFLAGS, &ifInfo) < 0)
1352 ERR ("Error obtaining status flags for socket!\n");
1353 close(fd);
1354 WSASetLastError(WSAEINVAL);
1355 return (SOCKET_ERROR);
1357 else
1359 /* FIXME - Is this the right flag to use? */
1360 intArray->iiFlags = ifInfo.ifr_flags;
1362 intArray++; /* Prepare for another interface */
1365 /* Calculate the size of the array being returned */
1366 *lpcbBytesReturned = sizeof(INTERFACE_INFO) * numInt;
1367 break;
1370 default:
1372 WARN("\tunsupported WS_IOCTL cmd (%08lx)\n", dwIoControlCode);
1373 close(fd);
1374 WSASetLastError(WSAEOPNOTSUPP);
1375 return (SOCKET_ERROR);
1379 /* Function executed with no errors */
1380 close(fd);
1381 return (0);
1383 else
1385 WSASetLastError(WSAENOTSOCK);
1386 return (SOCKET_ERROR);
1392 Helper function for WSAIoctl - Get count of the number of interfaces
1393 by parsing /proc filesystem.
1395 int WSAIOCTL_GetInterfaceCount(void)
1397 FILE *procfs;
1398 char buf[512]; /* Size doesn't matter, something big */
1399 int intcnt=0;
1402 /* Open /proc filesystem file for network devices */
1403 procfs = fopen(PROCFS_NETDEV_FILE, "r");
1404 if (!procfs)
1406 /* If we can't open the file, return an error */
1407 return (-1);
1410 /* Omit first two lines, they are only headers */
1411 fgets(buf, sizeof buf, procfs);
1412 fgets(buf, sizeof buf, procfs);
1414 while (fgets(buf, sizeof buf, procfs))
1416 /* Each line in the file represents a network interface */
1417 intcnt++;
1420 fclose(procfs);
1421 return(intcnt);
1426 Helper function for WSAIoctl - Get name of device from interface number
1427 by parsing /proc filesystem.
1429 int WSAIOCTL_GetInterfaceName(int intNumber, char *intName)
1431 FILE *procfs;
1432 char buf[512]; /* Size doesn't matter, something big */
1433 int i;
1435 /* Open /proc filesystem file for network devices */
1436 procfs = fopen(PROCFS_NETDEV_FILE, "r");
1437 if (!procfs)
1439 /* If we can't open the file, return an error */
1440 return (-1);
1443 /* Omit first two lines, they are only headers */
1444 fgets(buf, sizeof(buf), procfs);
1445 fgets(buf, sizeof(buf), procfs);
1447 for (i=0; i<intNumber; i++)
1449 /* Skip the lines that don't interest us. */
1450 fgets(buf, sizeof(buf), procfs);
1452 fgets(buf, sizeof(buf), procfs); /* This is the line we want */
1455 /* Parse out the line, grabbing only the name of the device
1456 to the intName variable
1458 The Line comes in like this: (we only care about the device name)
1459 lo: 21970 377 0 0 0 0 0 0 21970 377 0 0 0 0 0 0
1461 i=0;
1462 while (isspace(buf[i])) /* Skip initial space(s) */
1464 i++;
1467 while (buf[i])
1469 if (isspace(buf[i]))
1471 break;
1474 if (buf[i] == ':') /* FIXME: Not sure if this block (alias detection) works properly */
1476 /* This interface could be an alias... */
1477 int hold = i;
1478 char *dotname = intName;
1479 *intName++ = buf[i++];
1481 while (isdigit(buf[i]))
1483 *intName++ = buf[i++];
1486 if (buf[i] != ':')
1488 /* ... It wasn't, so back up */
1489 i = hold;
1490 intName = dotname;
1493 if (buf[i] == '\0')
1495 fclose(procfs);
1496 return(FALSE);
1499 i++;
1500 break;
1503 *intName++ = buf[i++];
1505 *intName++ = '\0';
1507 fclose(procfs);
1508 return(TRUE);
1512 /***********************************************************************
1513 * ioctlsocket() (WSOCK32.12)
1515 INT WINAPI WSOCK32_ioctlsocket(SOCKET s, LONG cmd, ULONG *argp)
1517 int fd = _get_sock_fd(s);
1519 TRACE("socket %04x, cmd %08lx, ptr %8x\n", s, cmd, (unsigned) argp);
1520 if (fd != -1)
1522 long newcmd = cmd;
1524 switch( cmd )
1526 case WS_FIONREAD:
1527 newcmd=FIONREAD;
1528 break;
1530 case WS_FIONBIO:
1531 newcmd=FIONBIO;
1532 if( _get_sock_mask(s) )
1534 /* AsyncSelect()'ed sockets are always nonblocking */
1535 if (*argp) {
1536 close(fd);
1537 return 0;
1539 SetLastError(WSAEINVAL);
1540 close(fd);
1541 return SOCKET_ERROR;
1543 close(fd);
1544 if (*argp)
1545 _enable_event(s, 0, WS_FD_NONBLOCKING, 0);
1546 else
1547 _enable_event(s, 0, 0, WS_FD_NONBLOCKING);
1548 return 0;
1550 case WS_SIOCATMARK:
1551 newcmd=SIOCATMARK;
1552 break;
1554 case WS_IOW('f',125,u_long):
1555 WARN("Warning: WS1.1 shouldn't be using async I/O\n");
1556 SetLastError(WSAEINVAL);
1557 return SOCKET_ERROR;
1559 case SIOCGIFBRDADDR:
1560 case SIOCGIFNETMASK:
1561 case SIOCGIFADDR:
1562 /* These don't need any special handling. They are used by
1563 WsControl, and are here to suppress an unecessary warning. */
1564 break;
1567 default:
1568 /* Netscape tries hard to use bogus ioctl 0x667e */
1569 WARN("\tunknown WS_IOCTL cmd (%08lx)\n", cmd);
1571 if( ioctl(fd, newcmd, (char*)argp ) == 0 )
1573 close(fd);
1574 return 0;
1576 SetLastError((errno == EBADF) ? WSAENOTSOCK : wsaErrno());
1577 close(fd);
1579 return SOCKET_ERROR;
1582 /***********************************************************************
1583 * ioctlsocket() (WINSOCK.12)
1585 INT16 WINAPI WINSOCK_ioctlsocket16(SOCKET16 s, LONG cmd, ULONG *argp)
1587 return (INT16)WSOCK32_ioctlsocket( s, cmd, argp );
1591 /***********************************************************************
1592 * listen() (WSOCK32.13)
1594 INT WINAPI WSOCK32_listen(SOCKET s, INT backlog)
1596 int fd = _get_sock_fd(s);
1598 TRACE("socket %04x, backlog %d\n", s, backlog);
1599 if (fd != -1)
1601 if (listen(fd, backlog) == 0)
1603 close(fd);
1604 _enable_event(s, FD_ACCEPT,
1605 WS_FD_LISTENING,
1606 WS_FD_CONNECT|WS_FD_CONNECTED);
1607 return 0;
1609 SetLastError(wsaErrno());
1611 else SetLastError(WSAENOTSOCK);
1612 return SOCKET_ERROR;
1615 /***********************************************************************
1616 * listen() (WINSOCK.13)
1618 INT16 WINAPI WINSOCK_listen16(SOCKET16 s, INT16 backlog)
1620 return (INT16)WSOCK32_listen( s, backlog );
1624 /***********************************************************************
1625 * recv() (WSOCK32.16)
1627 INT WINAPI WSOCK32_recv(SOCKET s, char *buf, INT len, INT flags)
1629 int fd = _get_sock_fd(s);
1631 TRACE("socket %04x, buf %8x, len %d, flags %d\n", s, (unsigned)buf, len, flags);
1633 if (fd != -1)
1635 INT length;
1637 if (_is_blocking(s))
1639 /* block here */
1640 /* FIXME: OOB and exceptfds? */
1641 do_block(fd, 1);
1643 if ((length = recv(fd, buf, len, flags)) >= 0)
1645 TRACE(" -> %i bytes\n", length);
1647 close(fd);
1648 _enable_event(s, FD_READ, 0, 0);
1649 return length;
1651 SetLastError(wsaErrno());
1652 close(fd);
1654 else SetLastError(WSAENOTSOCK);
1655 WARN(" -> ERROR\n");
1656 return SOCKET_ERROR;
1659 /***********************************************************************
1660 * recv() (WINSOCK.16)
1662 INT16 WINAPI WINSOCK_recv16(SOCKET16 s, char *buf, INT16 len, INT16 flags)
1664 return (INT16)WSOCK32_recv( s, buf, len, flags );
1668 /***********************************************************************
1669 * recvfrom() (WSOCK32.17)
1671 INT WINAPI WSOCK32_recvfrom(SOCKET s, char *buf, INT len, INT flags,
1672 struct sockaddr *from, INT *fromlen32)
1674 #ifdef HAVE_IPX
1675 struct ws_sockaddr_ipx* from2 = (struct ws_sockaddr_ipx *)from;
1676 #endif
1677 int fd = _get_sock_fd(s);
1679 TRACE("socket %04x, ptr %08x, len %d, flags %d\n", s, (unsigned)buf, len, flags);
1680 #if DEBUG_SOCKADDR
1681 if( from ) dump_sockaddr(from);
1682 else DPRINTF("from = NULL\n");
1683 #endif
1685 if (fd != -1)
1687 int length;
1689 if (_is_blocking(s))
1691 /* block here */
1692 /* FIXME: OOB and exceptfds */
1693 do_block(fd, 1);
1695 if ((length = recvfrom(fd, buf, len, flags, from, fromlen32)) >= 0)
1697 TRACE(" -> %i bytes\n", length);
1699 #ifdef HAVE_IPX
1700 if (from && ((struct sockaddr_ipx *)from)->sipx_family == AF_IPX) {
1701 from = (struct sockaddr *)
1702 malloc(fromlen32 ? *fromlen32 : sizeof(*from2));
1703 memcpy(from, from2, fromlen32 ? *fromlen32 : sizeof(*from2));
1704 from2->sipx_family = WS_AF_IPX;
1705 from2->sipx_network = ((struct sockaddr_ipx *)from)->sipx_network;
1706 from2->sipx_port = ((struct sockaddr_ipx *)from)->sipx_port;
1707 memcpy(from2->sipx_node,
1708 ((struct sockaddr_ipx *)from)->sipx_node, IPX_NODE_LEN);
1709 free(from);
1711 #endif
1712 close(fd);
1713 _enable_event(s, FD_READ, 0, 0);
1714 return (INT16)length;
1716 SetLastError(wsaErrno());
1717 close(fd);
1719 else SetLastError(WSAENOTSOCK);
1720 WARN(" -> ERROR\n");
1721 #ifdef HAVE_IPX
1722 if (from && ((struct sockaddr_ipx *)from)->sipx_family == AF_IPX) {
1723 from = (struct sockaddr *)
1724 malloc(fromlen32 ? *fromlen32 : sizeof(*from2));
1725 memcpy(from, from2, fromlen32 ? *fromlen32 : sizeof(*from2));
1726 from2->sipx_family = WS_AF_IPX;
1727 from2->sipx_network = ((struct sockaddr_ipx *)from)->sipx_network;
1728 from2->sipx_port = ((struct sockaddr_ipx *)from)->sipx_port;
1729 memcpy(from2->sipx_node,
1730 ((struct sockaddr_ipx *)from)->sipx_node, IPX_NODE_LEN);
1731 free(from);
1733 #endif
1734 return SOCKET_ERROR;
1737 /***********************************************************************
1738 * recvfrom() (WINSOCK.17)
1740 INT16 WINAPI WINSOCK_recvfrom16(SOCKET16 s, char *buf, INT16 len, INT16 flags,
1741 struct sockaddr *from, INT16 *fromlen16)
1743 INT fromlen32;
1744 INT *p = &fromlen32;
1745 INT retVal;
1747 if( fromlen16 ) fromlen32 = *fromlen16; else p = NULL;
1748 retVal = WSOCK32_recvfrom( s, buf, len, flags, from, p );
1749 if( fromlen16 ) *fromlen16 = fromlen32;
1750 return (INT16)retVal;
1753 /***********************************************************************
1754 * select() (WINSOCK.18)(WSOCK32.18)
1756 static INT __ws_select( BOOL b32, void *ws_readfds, void *ws_writefds, void *ws_exceptfds,
1757 struct timeval *timeout )
1759 int highfd = 0;
1760 fd_set readfds, writefds, exceptfds;
1761 fd_set *p_read, *p_write, *p_except;
1762 int readfd[FD_SETSIZE], writefd[FD_SETSIZE], exceptfd[FD_SETSIZE];
1764 TRACE("read %p, write %p, excp %p\n", ws_readfds, ws_writefds, ws_exceptfds);
1766 p_read = fd_set_import(&readfds, ws_readfds, &highfd, readfd, b32);
1767 p_write = fd_set_import(&writefds, ws_writefds, &highfd, writefd, b32);
1768 p_except = fd_set_import(&exceptfds, ws_exceptfds, &highfd, exceptfd, b32);
1770 if( (highfd = select(highfd + 1, p_read, p_write, p_except, timeout)) > 0 )
1772 fd_set_export(&readfds, p_except, ws_readfds, readfd, b32);
1773 fd_set_export(&writefds, p_except, ws_writefds, writefd, b32);
1775 if (p_except && ws_exceptfds)
1777 #define wsfds16 ((ws_fd_set16*)ws_exceptfds)
1778 #define wsfds32 ((ws_fd_set32*)ws_exceptfds)
1779 int i, j, count = (b32) ? wsfds32->fd_count : wsfds16->fd_count;
1781 for (i = j = 0; i < count; i++)
1783 int fd = exceptfd[i];
1784 if( fd >= 0 && FD_ISSET(fd, &exceptfds) )
1786 if( b32 )
1787 wsfds32->fd_array[j++] = wsfds32->fd_array[i];
1788 else
1789 wsfds16->fd_array[j++] = wsfds16->fd_array[i];
1791 if( fd >= 0 ) close(fd);
1792 exceptfd[i] = -1;
1794 if( b32 )
1795 wsfds32->fd_count = j;
1796 else
1797 wsfds16->fd_count = j;
1798 #undef wsfds32
1799 #undef wsfds16
1801 return highfd;
1803 fd_set_unimport(ws_readfds, readfd, b32);
1804 fd_set_unimport(ws_writefds, writefd, b32);
1805 fd_set_unimport(ws_exceptfds, exceptfd, b32);
1806 if( ws_readfds ) ((ws_fd_set32*)ws_readfds)->fd_count = 0;
1807 if( ws_writefds ) ((ws_fd_set32*)ws_writefds)->fd_count = 0;
1808 if( ws_exceptfds ) ((ws_fd_set32*)ws_exceptfds)->fd_count = 0;
1810 if( highfd == 0 ) return 0;
1811 SetLastError(wsaErrno());
1812 return SOCKET_ERROR;
1815 INT16 WINAPI WINSOCK_select16(INT16 nfds, ws_fd_set16 *ws_readfds,
1816 ws_fd_set16 *ws_writefds, ws_fd_set16 *ws_exceptfds,
1817 struct timeval *timeout)
1819 return (INT16)__ws_select( FALSE, ws_readfds, ws_writefds, ws_exceptfds, timeout );
1822 INT WINAPI WSOCK32_select(INT nfds, ws_fd_set32 *ws_readfds,
1823 ws_fd_set32 *ws_writefds, ws_fd_set32 *ws_exceptfds,
1824 struct timeval *timeout)
1826 /* struct timeval is the same for both 32- and 16-bit code */
1827 return (INT)__ws_select( TRUE, ws_readfds, ws_writefds, ws_exceptfds, timeout );
1831 /***********************************************************************
1832 * send() (WSOCK32.19)
1834 INT WINAPI WSOCK32_send(SOCKET s, char *buf, INT len, INT flags)
1836 int fd = _get_sock_fd(s);
1838 TRACE("socket %04x, ptr %p, length %d, flags %d\n", s, buf, len, flags);
1839 if (fd != -1)
1841 int length;
1843 if (_is_blocking(s))
1845 /* block here */
1846 /* FIXME: exceptfds */
1847 do_block(fd, 2);
1849 if ((length = send(fd, buf, len, flags)) < 0 )
1851 SetLastError(wsaErrno());
1852 if( GetLastError() == WSAEWOULDBLOCK )
1853 _enable_event(s, FD_WRITE, 0, 0);
1855 else
1857 close(fd);
1858 return (INT16)length;
1860 close(fd);
1862 else SetLastError(WSAENOTSOCK);
1863 return SOCKET_ERROR;
1866 /***********************************************************************
1867 * WSASend (WSOCK32.72)
1869 INT WINAPI WSASend( SOCKET s, LPWSABUF lpBuffers, DWORD dwBufferCount,
1870 LPDWORD lpNumberOfBytesSent, DWORD dwFlags,
1871 LPWSAOVERLAPPED lpOverlapped,
1872 LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine )
1874 INT iFlags = 0;
1875 INT rc = 0;
1876 DWORD dwCount;
1878 /* Overlapped is not supported or checked for */
1879 FIXME( "(%u,%p,0x%lx,%p,0x%lx,%p,%p): semi stub\n",
1880 s, lpBuffers, dwBufferCount, lpNumberOfBytesSent,
1881 dwFlags, lpOverlapped, lpCompletionRoutine );
1883 /* Convert setup flags */
1884 if( dwFlags & MSG_DONTROUTE )
1886 iFlags |= MSG_DONTROUTE;
1889 if( dwFlags & MSG_OOB )
1891 iFlags |= MSG_OOB;
1894 /* Indicate nothing yet sent */
1895 *lpNumberOfBytesSent = 0;
1897 /* Send all buffers with the same flags */
1898 for(dwCount = 0; dwCount < dwBufferCount; dwCount++ )
1900 if( ( rc = WSOCK32_send( s, lpBuffers[ dwCount ].buf,
1901 lpBuffers[ dwCount ].len, iFlags ) ) != 0 )
1903 break;
1906 /* Indicate that we've sent something */
1907 *lpNumberOfBytesSent += lpBuffers[ dwCount ].len;
1910 return rc;
1913 /***********************************************************************
1914 * send() (WINSOCK.19)
1916 INT16 WINAPI WINSOCK_send16(SOCKET16 s, char *buf, INT16 len, INT16 flags)
1918 return WSOCK32_send( s, buf, len, flags );
1921 /***********************************************************************
1922 * sendto() (WSOCK32.20)
1924 INT WINAPI WSOCK32_sendto(SOCKET s, char *buf, INT len, INT flags,
1925 struct sockaddr *to, INT tolen)
1927 #ifdef HAVE_IPX
1928 struct ws_sockaddr_ipx* to2 = (struct ws_sockaddr_ipx *)to;
1929 #endif
1930 int fd = _get_sock_fd(s);
1932 TRACE("socket %04x, ptr %p, length %d, flags %d\n", s, buf, len, flags);
1933 if (fd != -1)
1935 INT length;
1937 if (to && ((struct ws_sockaddr_ipx *)to)->sipx_family == WS_AF_PUP)
1938 ((struct ws_sockaddr_ipx *)to)->sipx_family = AF_UNSPEC;
1939 #ifdef HAVE_IPX
1940 else if (to &&
1941 ((struct ws_sockaddr_ipx *)to)->sipx_family == WS_AF_IPX)
1943 to = (struct sockaddr *) malloc(sizeof(struct sockaddr_ipx));
1944 memset(to, '\0', sizeof(struct sockaddr_ipx));
1945 ((struct sockaddr_ipx *)to)->sipx_family = AF_IPX;
1946 ((struct sockaddr_ipx *)to)->sipx_port = to2->sipx_port;
1947 ((struct sockaddr_ipx *)to)->sipx_network = to2->sipx_network;
1948 memcpy(((struct sockaddr_ipx *)to)->sipx_node,
1949 to2->sipx_node, IPX_NODE_LEN);
1950 tolen = sizeof(struct sockaddr_ipx);
1952 #endif
1953 if (_is_blocking(s))
1955 /* block here */
1956 /* FIXME: exceptfds */
1957 do_block(fd, 2);
1959 if ((length = sendto(fd, buf, len, flags, to, tolen)) < 0 )
1961 SetLastError(wsaErrno());
1962 if( GetLastError() == WSAEWOULDBLOCK )
1963 _enable_event(s, FD_WRITE, 0, 0);
1965 else {
1966 #ifdef HAVE_IPX
1967 if (to && ((struct sockaddr_ipx *)to)->sipx_family == AF_IPX) {
1968 free(to);
1970 #endif
1971 close(fd);
1972 return length;
1974 close(fd);
1976 else SetLastError(WSAENOTSOCK);
1977 #ifdef HAVE_IPX
1978 if (to && ((struct sockaddr_ipx *)to)->sipx_family == AF_IPX) {
1979 free(to);
1981 #endif
1982 return SOCKET_ERROR;
1985 /***********************************************************************
1986 * sendto() (WINSOCK.20)
1988 INT16 WINAPI WINSOCK_sendto16(SOCKET16 s, char *buf, INT16 len, INT16 flags,
1989 struct sockaddr *to, INT16 tolen)
1991 return (INT16)WSOCK32_sendto( s, buf, len, flags, to, tolen );
1994 /***********************************************************************
1995 * setsockopt() (WSOCK32.21)
1997 INT WINAPI WSOCK32_setsockopt(SOCKET16 s, INT level, INT optname,
1998 char *optval, INT optlen)
2000 int fd = _get_sock_fd(s);
2002 TRACE("socket %04x, lev %d, opt 0x%x, ptr %08x, len %d\n",
2003 s, level, optname, (int) optval, optlen);
2004 if (fd != -1)
2006 struct linger linger;
2007 int woptval;
2009 /* Is a privileged and useless operation, so we don't. */
2010 if ((optname == WS_SO_DEBUG) && (level == WS_SOL_SOCKET)) {
2011 FIXME("(%d,SOL_SOCKET,SO_DEBUG,%p(%ld)) attempted (is privileged). Ignoring.\n",s,optval,*(DWORD*)optval);
2012 return 0;
2015 if(optname == WS_SO_DONTLINGER && level == WS_SOL_SOCKET) {
2016 /* This is unique to WinSock and takes special conversion */
2017 linger.l_onoff = *((int*)optval) ? 0: 1;
2018 linger.l_linger = 0;
2019 optname=SO_LINGER;
2020 optval = (char*)&linger;
2021 optlen = sizeof(struct linger);
2022 level = SOL_SOCKET;
2023 }else{
2024 if (!convert_sockopt(&level, &optname)) {
2025 SetLastError(WSAENOPROTOOPT);
2026 close(fd);
2027 return SOCKET_ERROR;
2029 if (optname == SO_LINGER && optval) {
2030 /* yes, uses unsigned short in both win16/win32 */
2031 linger.l_onoff = ((UINT16*)optval)[0];
2032 linger.l_linger = ((UINT16*)optval)[1];
2033 /* FIXME: what is documented behavior if SO_LINGER optval
2034 is null?? */
2035 optval = (char*)&linger;
2036 optlen = sizeof(struct linger);
2037 } else if (optlen < sizeof(int)){
2038 woptval= *((INT16 *) optval);
2039 optval= (char*) &woptval;
2040 optlen=sizeof(int);
2043 if(optname == SO_RCVBUF && *(int*)optval < 2048) {
2044 WARN("SO_RCVBF for %d bytes is too small: ignored\n", *(int*)optval );
2045 close( fd);
2046 return 0;
2049 if (setsockopt(fd, level, optname, optval, optlen) == 0)
2051 close(fd);
2052 return 0;
2054 SetLastError(wsaErrno());
2055 close(fd);
2057 else SetLastError(WSAENOTSOCK);
2058 return SOCKET_ERROR;
2061 /***********************************************************************
2062 * setsockopt() (WINSOCK.21)
2064 INT16 WINAPI WINSOCK_setsockopt16(SOCKET16 s, INT16 level, INT16 optname,
2065 char *optval, INT16 optlen)
2067 if( !optval ) return SOCKET_ERROR;
2068 return (INT16)WSOCK32_setsockopt( s, (UINT16)level, optname, optval, optlen );
2072 /***********************************************************************
2073 * shutdown() (WSOCK32.22)
2075 INT WINAPI WSOCK32_shutdown(SOCKET s, INT how)
2077 int fd = _get_sock_fd(s);
2079 TRACE("socket %04x, how %i\n", s, how );
2080 if (fd != -1)
2082 switch( how )
2084 case 0: /* drop receives */
2085 _enable_event(s, 0, 0, WS_FD_READ);
2086 #ifdef SHUT_RD
2087 how = SHUT_RD;
2088 #endif
2089 break;
2091 case 1: /* drop sends */
2092 _enable_event(s, 0, 0, WS_FD_WRITE);
2093 #ifdef SHUT_WR
2094 how = SHUT_WR;
2095 #endif
2096 break;
2098 case 2: /* drop all */
2099 #ifdef SHUT_RDWR
2100 how = SHUT_RDWR;
2101 #endif
2102 default:
2103 WSAAsyncSelect( s, 0, 0, 0 );
2104 break;
2107 if (shutdown(fd, how) == 0)
2109 if( how > 1 )
2111 _enable_event(s, 0, 0, WS_FD_CONNECTED|WS_FD_LISTENING);
2113 close(fd);
2114 return 0;
2116 SetLastError(wsaErrno());
2117 close(fd);
2119 else SetLastError(WSAENOTSOCK);
2120 return SOCKET_ERROR;
2123 /***********************************************************************
2124 * shutdown() (WINSOCK.22)
2126 INT16 WINAPI WINSOCK_shutdown16(SOCKET16 s, INT16 how)
2128 return (INT16)WSOCK32_shutdown( s, how );
2132 /***********************************************************************
2133 * socket() (WSOCK32.23)
2135 SOCKET WINAPI WSOCK32_socket(INT af, INT type, INT protocol)
2137 SOCKET ret;
2139 TRACE("af=%d type=%d protocol=%d\n", af, type, protocol);
2141 /* check the socket family */
2142 switch(af)
2144 #ifdef HAVE_IPX
2145 case WS_AF_IPX: af = AF_IPX;
2146 #endif
2147 case AF_INET:
2148 case AF_UNSPEC: break;
2149 default: SetLastError(WSAEAFNOSUPPORT);
2150 return INVALID_SOCKET;
2153 /* check the socket type */
2154 switch(type)
2156 case SOCK_STREAM:
2157 case SOCK_DGRAM:
2158 case SOCK_RAW: break;
2159 default: SetLastError(WSAESOCKTNOSUPPORT);
2160 return INVALID_SOCKET;
2163 /* check the protocol type */
2164 if ( protocol < 0 ) /* don't support negative values */
2165 { SetLastError(WSAEPROTONOSUPPORT); return INVALID_SOCKET; }
2167 if ( af == AF_UNSPEC) /* did they not specify the address family? */
2168 switch(protocol)
2170 case IPPROTO_TCP:
2171 if (type == SOCK_STREAM) { af = AF_INET; break; }
2172 case IPPROTO_UDP:
2173 if (type == SOCK_DGRAM) { af = AF_INET; break; }
2174 default: SetLastError(WSAEPROTOTYPE); return INVALID_SOCKET;
2177 SERVER_START_REQ( create_socket )
2179 req->family = af;
2180 req->type = type;
2181 req->protocol = protocol;
2182 req->access = GENERIC_READ|GENERIC_WRITE|SYNCHRONIZE;
2183 req->inherit = TRUE;
2184 set_error( SERVER_CALL() );
2185 ret = (SOCKET)req->handle;
2187 SERVER_END_REQ;
2188 if (ret)
2190 TRACE("\tcreated %04x\n", ret );
2191 return ret;
2194 if (GetLastError() == WSAEACCES) /* raw socket denied */
2196 if (type == SOCK_RAW)
2197 MESSAGE("WARNING: Trying to create a socket of type SOCK_RAW, will fail unless running as root\n");
2198 else
2199 MESSAGE("WS_SOCKET: not enough privileges to create socket, try running as root\n");
2200 SetLastError(WSAESOCKTNOSUPPORT);
2203 WARN("\t\tfailed!\n");
2204 return INVALID_SOCKET;
2207 /***********************************************************************
2208 * socket() (WINSOCK.23)
2210 SOCKET16 WINAPI WINSOCK_socket16(INT16 af, INT16 type, INT16 protocol)
2212 return (SOCKET16)WSOCK32_socket( af, type, protocol );
2216 /* ----------------------------------- DNS services
2218 * IMPORTANT: 16-bit API structures have SEGPTR pointers inside them.
2219 * Also, we have to use wsock32 stubs to convert structures and
2220 * error codes from Unix to WSA, hence there is no direct mapping in
2221 * the relay32/wsock32.spec.
2224 static char* NULL_STRING = "NULL";
2226 /***********************************************************************
2227 * gethostbyaddr() (WINSOCK.51)(WSOCK32.51)
2229 static WIN_hostent* __ws_gethostbyaddr(const char *addr, int len, int type, int dup_flag)
2231 WIN_hostent *retval = NULL;
2233 struct hostent* host;
2234 #if HAVE_LINUX_GETHOSTBYNAME_R_6
2235 char *extrabuf;
2236 int ebufsize=1024;
2237 struct hostent hostentry;
2238 int locerr=ENOBUFS;
2239 host = NULL;
2240 extrabuf=HeapAlloc(GetProcessHeap(),0,ebufsize) ;
2241 while(extrabuf) {
2242 int res = gethostbyaddr_r(addr, len, type,
2243 &hostentry, extrabuf, ebufsize, &host, &locerr);
2244 if( res != ERANGE) break;
2245 ebufsize *=2;
2246 extrabuf=HeapReAlloc(GetProcessHeap(),0,extrabuf,ebufsize) ;
2248 if (!host) SetLastError((locerr < 0) ? wsaErrno() : wsaHerrno(locerr));
2249 #else
2250 EnterCriticalSection( &csWSgetXXXbyYYY );
2251 host = gethostbyaddr(addr, len, type);
2252 if (!host) SetLastError((h_errno < 0) ? wsaErrno() : wsaHerrno(h_errno));
2253 #endif
2254 if( host != NULL )
2256 if( WS_dup_he(host, dup_flag) )
2257 retval = he_buffer;
2258 else
2259 SetLastError(WSAENOBUFS);
2261 #ifdef HAVE_LINUX_GETHOSTBYNAME_R_6
2262 HeapFree(GetProcessHeap(),0,extrabuf);
2263 #else
2264 LeaveCriticalSection( &csWSgetXXXbyYYY );
2265 #endif
2266 return retval;
2269 SEGPTR WINAPI WINSOCK_gethostbyaddr16(const char *addr, INT16 len, INT16 type)
2271 WIN_hostent* retval;
2272 TRACE("ptr %08x, len %d, type %d\n",
2273 (unsigned) addr, len, type);
2274 retval = __ws_gethostbyaddr( addr, len, type, WS_DUP_SEGPTR );
2275 return SEGPTR_GET(retval);
2278 WIN_hostent* WINAPI WSOCK32_gethostbyaddr(const char *addr, INT len,
2279 INT type)
2281 TRACE("ptr %08x, len %d, type %d\n",
2282 (unsigned) addr, len, type);
2283 return __ws_gethostbyaddr(addr, len, type, WS_DUP_LINEAR);
2286 /***********************************************************************
2287 * gethostbyname() (WINSOCK.52)(WSOCK32.52)
2289 static WIN_hostent * __ws_gethostbyname(const char *name, int dup_flag)
2291 WIN_hostent *retval = NULL;
2292 struct hostent* host;
2293 #ifdef HAVE_LINUX_GETHOSTBYNAME_R_6
2294 char *extrabuf;
2295 int ebufsize=1024;
2296 struct hostent hostentry;
2297 int locerr = ENOBUFS;
2298 host = NULL;
2299 extrabuf=HeapAlloc(GetProcessHeap(),0,ebufsize) ;
2300 while(extrabuf) {
2301 int res = gethostbyname_r(name, &hostentry, extrabuf, ebufsize, &host, &locerr);
2302 if( res != ERANGE) break;
2303 ebufsize *=2;
2304 extrabuf=HeapReAlloc(GetProcessHeap(),0,extrabuf,ebufsize) ;
2306 if (!host) SetLastError((locerr < 0) ? wsaErrno() : wsaHerrno(locerr));
2307 #else
2308 EnterCriticalSection( &csWSgetXXXbyYYY );
2309 host = gethostbyname(name);
2310 if (!host) SetLastError((h_errno < 0) ? wsaErrno() : wsaHerrno(h_errno));
2311 #endif
2312 if( host != NULL )
2314 if( WS_dup_he(host, dup_flag) )
2315 retval = he_buffer;
2316 else SetLastError(WSAENOBUFS);
2318 #ifdef HAVE_LINUX_GETHOSTBYNAME_R_6
2319 HeapFree(GetProcessHeap(),0,extrabuf);
2320 #else
2321 LeaveCriticalSection( &csWSgetXXXbyYYY );
2322 #endif
2323 return retval;
2326 SEGPTR WINAPI WINSOCK_gethostbyname16(const char *name)
2328 WIN_hostent* retval;
2329 TRACE("%s\n", (name)?name:NULL_STRING);
2330 retval = __ws_gethostbyname( name, WS_DUP_SEGPTR );
2331 return SEGPTR_GET(retval);
2334 WIN_hostent* WINAPI WSOCK32_gethostbyname(const char* name)
2336 TRACE("%s\n", (name)?name:NULL_STRING);
2337 return __ws_gethostbyname( name, WS_DUP_LINEAR );
2341 /***********************************************************************
2342 * getprotobyname() (WINSOCK.53)(WSOCK32.53)
2344 static WIN_protoent* __ws_getprotobyname(const char *name, int dup_flag)
2346 WIN_protoent* retval = NULL;
2348 struct protoent* proto;
2349 EnterCriticalSection( &csWSgetXXXbyYYY );
2350 if( (proto = getprotobyname(name)) != NULL )
2352 if( WS_dup_pe(proto, dup_flag) )
2353 retval = pe_buffer;
2354 else SetLastError(WSAENOBUFS);
2356 else {
2357 MESSAGE("protocol %s not found; You might want to add "
2358 "this to /etc/protocols\n", debugstr_a(name) );
2359 SetLastError(WSANO_DATA);
2361 LeaveCriticalSection( &csWSgetXXXbyYYY );
2362 return retval;
2365 SEGPTR WINAPI WINSOCK_getprotobyname16(const char *name)
2367 WIN_protoent* retval;
2368 TRACE("%s\n", (name)?name:NULL_STRING);
2369 retval = __ws_getprotobyname(name, WS_DUP_SEGPTR);
2370 return SEGPTR_GET(retval);
2373 WIN_protoent* WINAPI WSOCK32_getprotobyname(const char* name)
2375 TRACE("%s\n", (name)?name:NULL_STRING);
2376 return __ws_getprotobyname(name, WS_DUP_LINEAR);
2380 /***********************************************************************
2381 * getprotobynumber() (WINSOCK.54)(WSOCK32.54)
2383 static WIN_protoent* __ws_getprotobynumber(int number, int dup_flag)
2385 WIN_protoent* retval = NULL;
2386 struct protoent* proto;
2387 EnterCriticalSection( &csWSgetXXXbyYYY );
2388 if( (proto = getprotobynumber(number)) != NULL )
2390 if( WS_dup_pe(proto, dup_flag) )
2391 retval = pe_buffer;
2392 else SetLastError(WSAENOBUFS);
2394 else {
2395 MESSAGE("protocol number %d not found; You might want to add "
2396 "this to /etc/protocols\n", number );
2397 SetLastError(WSANO_DATA);
2399 LeaveCriticalSection( &csWSgetXXXbyYYY );
2400 return retval;
2403 SEGPTR WINAPI WINSOCK_getprotobynumber16(INT16 number)
2405 WIN_protoent* retval;
2406 TRACE("%i\n", number);
2407 retval = __ws_getprotobynumber(number, WS_DUP_SEGPTR);
2408 return SEGPTR_GET(retval);
2411 WIN_protoent* WINAPI WSOCK32_getprotobynumber(INT number)
2413 TRACE("%i\n", number);
2414 return __ws_getprotobynumber(number, WS_DUP_LINEAR);
2418 /***********************************************************************
2419 * getservbyname() (WINSOCK.55)(WSOCK32.55)
2421 static WIN_servent* __ws_getservbyname(const char *name, const char *proto, int dup_flag)
2423 WIN_servent* retval = NULL;
2424 struct servent* serv;
2425 int i = wsi_strtolo( name, proto );
2427 if( i ) {
2428 EnterCriticalSection( &csWSgetXXXbyYYY );
2429 serv = getservbyname(local_buffer,
2430 proto ? (local_buffer + i) : NULL);
2431 if( serv != NULL )
2433 if( WS_dup_se(serv, dup_flag) )
2434 retval = se_buffer;
2435 else SetLastError(WSAENOBUFS);
2437 else {
2438 MESSAGE("service %s protocol %s not found; You might want to add "
2439 "this to /etc/services\n", debugstr_a(local_buffer),
2440 proto ? debugstr_a(local_buffer+i):"*");
2441 SetLastError(WSANO_DATA);
2443 LeaveCriticalSection( &csWSgetXXXbyYYY );
2445 else SetLastError(WSAENOBUFS);
2446 return retval;
2449 SEGPTR WINAPI WINSOCK_getservbyname16(const char *name, const char *proto)
2451 WIN_servent* retval;
2452 TRACE("'%s', '%s'\n",
2453 (name)?name:NULL_STRING, (proto)?proto:NULL_STRING);
2454 retval = __ws_getservbyname(name, proto, WS_DUP_SEGPTR);
2455 return SEGPTR_GET(retval);
2458 WIN_servent* WINAPI WSOCK32_getservbyname(const char *name, const char *proto)
2460 TRACE("'%s', '%s'\n",
2461 (name)?name:NULL_STRING, (proto)?proto:NULL_STRING);
2462 return __ws_getservbyname(name, proto, WS_DUP_LINEAR);
2466 /***********************************************************************
2467 * getservbyport() (WINSOCK.56)(WSOCK32.56)
2469 static WIN_servent* __ws_getservbyport(int port, const char* proto, int dup_flag)
2471 WIN_servent* retval = NULL;
2472 struct servent* serv;
2473 if (!proto || wsi_strtolo( proto, NULL )) {
2474 EnterCriticalSection( &csWSgetXXXbyYYY );
2475 if( (serv = getservbyport(port, (proto) ? local_buffer : NULL)) != NULL ) {
2476 if( WS_dup_se(serv, dup_flag) )
2477 retval = se_buffer;
2478 else SetLastError(WSAENOBUFS);
2480 else {
2481 MESSAGE("service on port %lu protocol %s not found; You might want to add "
2482 "this to /etc/services\n", (unsigned long)ntohl(port),
2483 proto ? debugstr_a(local_buffer) : "*");
2484 SetLastError(WSANO_DATA);
2486 LeaveCriticalSection( &csWSgetXXXbyYYY );
2488 else SetLastError(WSAENOBUFS);
2489 return retval;
2492 SEGPTR WINAPI WINSOCK_getservbyport16(INT16 port, const char *proto)
2494 WIN_servent* retval;
2495 TRACE("%d (i.e. port %d), '%s'\n",
2496 (int)port, (int)ntohl(port), (proto)?proto:NULL_STRING);
2497 retval = __ws_getservbyport(port, proto, WS_DUP_SEGPTR);
2498 return SEGPTR_GET(retval);
2501 WIN_servent* WINAPI WSOCK32_getservbyport(INT port, const char *proto)
2503 TRACE("%d (i.e. port %d), '%s'\n",
2504 (int)port, (int)ntohl(port), (proto)?proto:NULL_STRING);
2505 return __ws_getservbyport(port, proto, WS_DUP_LINEAR);
2509 /***********************************************************************
2510 * gethostname() (WSOCK32.57)
2512 INT WINAPI WSOCK32_gethostname(char *name, INT namelen)
2514 TRACE("name %p, len %d\n", name, namelen);
2516 if (gethostname(name, namelen) == 0)
2518 TRACE("<- '%s'\n", name);
2519 return 0;
2521 SetLastError((errno == EINVAL) ? WSAEFAULT : wsaErrno());
2522 TRACE("<- ERROR !\n");
2523 return SOCKET_ERROR;
2526 /***********************************************************************
2527 * gethostname() (WINSOCK.57)
2529 INT16 WINAPI WINSOCK_gethostname16(char *name, INT16 namelen)
2531 return (INT16)WSOCK32_gethostname(name, namelen);
2535 /* ------------------------------------- Windows sockets extensions -- *
2537 * ------------------------------------------------------------------- */
2539 /***********************************************************************
2540 * WSAEnumNetworkEvents
2542 int WINAPI WSAEnumNetworkEvents(SOCKET s, WSAEVENT hEvent, LPWSANETWORKEVENTS lpEvent)
2544 int ret;
2546 TRACE("%08x, hEvent %08x, lpEvent %08x\n", s, hEvent, (unsigned)lpEvent );
2548 SERVER_START_VAR_REQ( get_socket_event, sizeof(lpEvent->iErrorCode) )
2550 req->handle = s;
2551 req->service = TRUE;
2552 req->s_event = 0;
2553 req->c_event = hEvent;
2554 if (!(ret = SERVER_CALL()))
2556 lpEvent->lNetworkEvents = req->pmask;
2557 memcpy(lpEvent->iErrorCode, server_data_ptr(req), server_data_size(req) );
2560 SERVER_END_VAR_REQ;
2561 if (!ret) return 0;
2562 SetLastError(WSAEINVAL);
2563 return SOCKET_ERROR;
2566 /***********************************************************************
2567 * WSAEventSelect
2569 int WINAPI WSAEventSelect(SOCKET s, WSAEVENT hEvent, LONG lEvent)
2571 int ret;
2573 TRACE("%08x, hEvent %08x, event %08x\n", s, hEvent, (unsigned)lEvent );
2575 SERVER_START_REQ( set_socket_event )
2577 req->handle = s;
2578 req->mask = lEvent;
2579 req->event = hEvent;
2580 ret = SERVER_CALL();
2582 SERVER_END_REQ;
2583 if (!ret) return 0;
2584 SetLastError(WSAEINVAL);
2585 return SOCKET_ERROR;
2588 /***********************************************************************
2589 * WSAAsyncSelect() (WINSOCK.101)(WSOCK32.101)
2592 VOID CALLBACK WINSOCK_DoAsyncEvent( ULONG_PTR ptr )
2594 ws_select_info *info = (ws_select_info*)ptr;
2595 unsigned int i, pmask, orphan = FALSE;
2596 int errors[FD_MAX_EVENTS];
2598 TRACE("socket %08x, event %08x\n", info->sock, info->event);
2599 SetLastError(0);
2600 SERVER_START_VAR_REQ( get_socket_event, sizeof(errors) )
2602 req->handle = info->sock;
2603 req->service = TRUE;
2604 req->s_event = info->event; /* <== avoid race conditions */
2605 req->c_event = info->event;
2606 set_error( SERVER_CALL() );
2607 pmask = req->pmask;
2608 memcpy( errors, server_data_ptr(req), server_data_size(req) );
2610 SERVER_END_VAR_REQ;
2611 if ( (GetLastError() == WSAENOTSOCK) || (GetLastError() == WSAEINVAL) )
2613 /* orphaned event (socket closed or something) */
2614 pmask = WS_FD_SERVEVENT;
2615 orphan = TRUE;
2618 /* check for accepted sockets that needs to inherit WSAAsyncSelect */
2619 if (pmask & WS_FD_SERVEVENT) {
2620 int q;
2621 for (q=0; q<WS_ACCEPT_QUEUE; q++)
2622 if (accept_old[q] == info->sock) {
2623 /* there's only one service thread per process, no lock necessary */
2624 HANDLE as = accept_new[q];
2625 if (as) {
2626 accept_new[q] = 0;
2627 accept_old[q] = 0;
2628 WSAAsyncSelect(as, info->hWnd, info->uMsg, info->lEvent);
2631 pmask &= ~WS_FD_SERVEVENT;
2633 /* dispatch network events */
2634 for (i=0; i<FD_MAX_EVENTS; i++)
2635 if (pmask & (1<<i)) {
2636 TRACE("post: event bit %d, error %d\n", i, errors[i]);
2637 PostMessageA(info->hWnd, info->uMsg, info->sock,
2638 WSAMAKESELECTREPLY(1<<i, errors[i]));
2640 /* cleanup */
2641 if (orphan)
2643 TRACE("orphaned event, self-destructing\n");
2644 /* SERVICE_Delete closes the event object */
2645 SERVICE_Delete( info->service );
2646 WS_FREE(info);
2650 /**********************************************************************/
2652 INT WINAPI WSAAsyncSelect(SOCKET s, HWND hWnd, UINT uMsg, LONG lEvent)
2654 int fd = _get_sock_fd(s);
2656 TRACE("%04x, hWnd %04x, uMsg %08x, event %08x\n",
2657 (SOCKET16)s, (HWND16)hWnd, uMsg, (unsigned)lEvent );
2658 if (fd != -1)
2660 close(fd);
2661 if( lEvent )
2663 ws_select_info *info = (ws_select_info*)WS_ALLOC(sizeof(ws_select_info));
2664 if( info )
2666 HANDLE hObj = CreateEventA( NULL, TRUE, FALSE, NULL );
2667 INT err;
2669 info->sock = s;
2670 info->event = hObj;
2671 info->hWnd = hWnd;
2672 info->uMsg = uMsg;
2673 info->lEvent = lEvent;
2674 info->service = SERVICE_AddObject( hObj, WINSOCK_DoAsyncEvent, (ULONG_PTR)info );
2676 err = WSAEventSelect( s, hObj, lEvent | WS_FD_SERVEVENT );
2677 if (err) {
2678 /* SERVICE_Delete closes the event object */
2679 SERVICE_Delete( info->service );
2680 WS_FREE(info);
2681 return err;
2684 return 0; /* success */
2686 else SetLastError(WSAENOBUFS);
2688 else
2690 WSAEventSelect(s, 0, 0);
2691 return 0;
2694 else SetLastError(WSAEINVAL);
2695 return SOCKET_ERROR;
2698 /**********************************************************************/
2700 INT16 WINAPI WSAAsyncSelect16(SOCKET16 s, HWND16 hWnd, UINT16 wMsg, LONG lEvent)
2702 return (INT16)WSAAsyncSelect( s, hWnd, wMsg, lEvent );
2705 /***********************************************************************
2706 * WSARecvEx16() (WINSOCK.1107)
2708 * See description for WSARecvEx()
2710 INT16 WINAPI WSARecvEx16(SOCKET16 s, char *buf, INT16 len, INT16 *flags) {
2711 FIXME("(WSARecvEx16) partial packet return value not set \n");
2713 return WINSOCK_recv16(s, buf, len, *flags);
2717 /***********************************************************************
2718 * WSACreateEvent() (WS2_32.???)
2721 WSAEVENT WINAPI WSACreateEvent(void)
2723 /* Create a manual-reset event, with initial state: unsignealed */
2724 TRACE("\n");
2726 return CreateEventA(NULL, TRUE, FALSE, NULL);
2729 /***********************************************************************
2730 * WSACloseEvent() (WS2_32.???)
2733 BOOL WINAPI WSACloseEvent(WSAEVENT event)
2735 TRACE ("event=0x%x\n", event);
2737 return CloseHandle(event);
2740 /***********************************************************************
2741 * WSASocketA() (WS2_32.???)
2744 SOCKET WINAPI WSASocketA(int af, int type, int protocol,
2745 LPWSAPROTOCOL_INFOA lpProtocolInfo,
2746 GROUP g, DWORD dwFlags)
2749 FIXME: The "advanced" parameters of WSASocketA (lpProtocolInfo,
2750 g, dwFlags) are ignored.
2753 TRACE("af=%d type=%d protocol=%d protocol_info=%p group=%d flags=0x%lx\n",
2754 af, type, protocol, lpProtocolInfo, g, dwFlags );
2756 return ( WSOCK32_socket (af, type, protocol) );
2760 /***********************************************************************
2761 * __WSAFDIsSet() (WINSOCK.151)
2763 INT16 WINAPI __WSAFDIsSet16(SOCKET16 s, ws_fd_set16 *set)
2765 int i = set->fd_count;
2767 TRACE("(%d,%8lx(%i))\n", s,(unsigned long)set, i);
2769 while (i--)
2770 if (set->fd_array[i] == s) return 1;
2771 return 0;
2774 /***********************************************************************
2775 * __WSAFDIsSet() (WSOCK32.151)
2777 INT WINAPI __WSAFDIsSet(SOCKET s, ws_fd_set32 *set)
2779 int i = set->fd_count;
2781 TRACE("(%d,%8lx(%i))\n", s,(unsigned long)set, i);
2783 while (i--)
2784 if (set->fd_array[i] == s) return 1;
2785 return 0;
2788 /***********************************************************************
2789 * WSAIsBlocking() (WINSOCK.114)(WSOCK32.114)
2791 BOOL WINAPI WSAIsBlocking(void)
2793 /* By default WinSock should set all its sockets to non-blocking mode
2794 * and poll in PeekMessage loop when processing "blocking" ones. This
2795 * function is supposed to tell if the program is in this loop. Our
2796 * blocking calls are truly blocking so we always return FALSE.
2798 * Note: It is allowed to call this function without prior WSAStartup().
2801 TRACE("\n");
2802 return FALSE;
2805 /***********************************************************************
2806 * WSACancelBlockingCall() (WINSOCK.113)(WSOCK32.113)
2808 INT WINAPI WSACancelBlockingCall(void)
2810 TRACE("\n");
2811 return 0;
2815 /***********************************************************************
2816 * WSASetBlockingHook16() (WINSOCK.109)
2818 FARPROC16 WINAPI WSASetBlockingHook16(FARPROC16 lpBlockFunc)
2820 FARPROC16 prev = (FARPROC16)blocking_hook;
2821 blocking_hook = (FARPROC)lpBlockFunc;
2822 TRACE("hook %p\n", lpBlockFunc);
2823 return prev;
2827 /***********************************************************************
2828 * WSASetBlockingHook()
2830 FARPROC WINAPI WSASetBlockingHook(FARPROC lpBlockFunc)
2832 FARPROC prev = blocking_hook;
2833 blocking_hook = lpBlockFunc;
2834 TRACE("hook %p\n", lpBlockFunc);
2835 return prev;
2839 /***********************************************************************
2840 * WSAUnhookBlockingHook16() (WINSOCK.110)
2842 INT16 WINAPI WSAUnhookBlockingHook16(void)
2844 blocking_hook = NULL;
2845 return 0;
2849 /***********************************************************************
2850 * WSAUnhookBlockingHook()
2852 INT WINAPI WSAUnhookBlockingHook(void)
2854 blocking_hook = NULL;
2855 return 0;
2859 /* ----------------------------------- end of API stuff */
2861 /* ----------------------------------- helper functions -
2863 * TODO: Merge WS_dup_..() stuff into one function that
2864 * would operate with a generic structure containing internal
2865 * pointers (via a template of some kind).
2868 static int list_size(char** l, int item_size)
2870 int i,j = 0;
2871 if(l)
2872 { for(i=0;l[i];i++)
2873 j += (item_size) ? item_size : strlen(l[i]) + 1;
2874 j += (i + 1) * sizeof(char*); }
2875 return j;
2878 static int list_dup(char** l_src, char* ref, char* base, int item_size)
2880 /* base is either either equal to ref or 0 or SEGPTR */
2882 char* p = ref;
2883 char** l_to = (char**)ref;
2884 int i,j,k;
2886 for(j=0;l_src[j];j++) ;
2887 p += (j + 1) * sizeof(char*);
2888 for(i=0;i<j;i++)
2889 { l_to[i] = base + (p - ref);
2890 k = ( item_size ) ? item_size : strlen(l_src[i]) + 1;
2891 memcpy(p, l_src[i], k); p += k; }
2892 l_to[i] = NULL;
2893 return (p - ref);
2896 /* ----- hostent */
2898 static int hostent_size(struct hostent* p_he)
2900 int size = 0;
2901 if( p_he )
2902 { size = sizeof(struct hostent);
2903 size += strlen(p_he->h_name) + 1;
2904 size += list_size(p_he->h_aliases, 0);
2905 size += list_size(p_he->h_addr_list, p_he->h_length ); }
2906 return size;
2909 /* duplicate hostent entry
2910 * and handle all Win16/Win32 dependent things (struct size, ...) *correctly*.
2911 * Dito for protoent and servent.
2913 int WS_dup_he(struct hostent* p_he, int flag)
2915 /* Convert hostent structure into ws_hostent so that the data fits
2916 * into local_buffer. Internal pointers can be linear, SEGPTR, or
2917 * relative to local_buffer depending on "flag" value. Returns size
2918 * of the data copied.
2921 int size = hostent_size(p_he);
2922 if( size )
2924 char *p_name,*p_aliases,*p_addr,*p_base,*p;
2925 char *p_to;
2926 struct ws_hostent16 *p_to16;
2927 struct ws_hostent32 *p_to32;
2929 check_buffer_he(size);
2930 p_to = he_buffer;
2931 p_to16 = he_buffer;
2932 p_to32 = he_buffer;
2934 p = p_to;
2935 p_base = (flag & WS_DUP_OFFSET) ? NULL
2936 : ((flag & WS_DUP_SEGPTR) ? (char*)SEGPTR_GET(p) : p);
2937 p += (flag & WS_DUP_SEGPTR) ?
2938 sizeof(struct ws_hostent16) : sizeof(struct ws_hostent32);
2939 p_name = p;
2940 strcpy(p, p_he->h_name); p += strlen(p) + 1;
2941 p_aliases = p;
2942 p += list_dup(p_he->h_aliases, p, p_base + (p - p_to), 0);
2943 p_addr = p;
2944 list_dup(p_he->h_addr_list, p, p_base + (p - p_to), p_he->h_length);
2946 if (flag & WS_DUP_SEGPTR) /* Win16 */
2948 p_to16->h_addrtype = (INT16)p_he->h_addrtype;
2949 p_to16->h_length = (INT16)p_he->h_length;
2950 p_to16->h_name = (SEGPTR)(p_base + (p_name - p_to));
2951 p_to16->h_aliases = (SEGPTR)(p_base + (p_aliases - p_to));
2952 p_to16->h_addr_list = (SEGPTR)(p_base + (p_addr - p_to));
2953 size += (sizeof(struct ws_hostent16) - sizeof(struct hostent));
2955 else /* Win32 */
2957 p_to32->h_addrtype = p_he->h_addrtype;
2958 p_to32->h_length = p_he->h_length;
2959 p_to32->h_name = (p_base + (p_name - p_to));
2960 p_to32->h_aliases = (char **)(p_base + (p_aliases - p_to));
2961 p_to32->h_addr_list = (char **)(p_base + (p_addr - p_to));
2962 size += (sizeof(struct ws_hostent32) - sizeof(struct hostent));
2965 return size;
2968 /* ----- protoent */
2970 static int protoent_size(struct protoent* p_pe)
2972 int size = 0;
2973 if( p_pe )
2974 { size = sizeof(struct protoent);
2975 size += strlen(p_pe->p_name) + 1;
2976 size += list_size(p_pe->p_aliases, 0); }
2977 return size;
2980 int WS_dup_pe(struct protoent* p_pe, int flag)
2982 int size = protoent_size(p_pe);
2983 if( size )
2985 char *p_to;
2986 struct ws_protoent16 *p_to16;
2987 struct ws_protoent32 *p_to32;
2988 char *p_name,*p_aliases,*p_base,*p;
2990 check_buffer_pe(size);
2991 p_to = pe_buffer;
2992 p_to16 = pe_buffer;
2993 p_to32 = pe_buffer;
2994 p = p_to;
2995 p_base = (flag & WS_DUP_OFFSET) ? NULL
2996 : ((flag & WS_DUP_SEGPTR) ? (char*)SEGPTR_GET(p) : p);
2997 p += (flag & WS_DUP_SEGPTR) ?
2998 sizeof(struct ws_protoent16) : sizeof(struct ws_protoent32);
2999 p_name = p;
3000 strcpy(p, p_pe->p_name); p += strlen(p) + 1;
3001 p_aliases = p;
3002 list_dup(p_pe->p_aliases, p, p_base + (p - p_to), 0);
3004 if (flag & WS_DUP_SEGPTR) /* Win16 */
3006 p_to16->p_proto = (INT16)p_pe->p_proto;
3007 p_to16->p_name = (SEGPTR)(p_base) + (p_name - p_to);
3008 p_to16->p_aliases = (SEGPTR)((p_base) + (p_aliases - p_to));
3009 size += (sizeof(struct ws_protoent16) - sizeof(struct protoent));
3011 else /* Win32 */
3013 p_to32->p_proto = p_pe->p_proto;
3014 p_to32->p_name = (p_base) + (p_name - p_to);
3015 p_to32->p_aliases = (char **)((p_base) + (p_aliases - p_to));
3016 size += (sizeof(struct ws_protoent32) - sizeof(struct protoent));
3019 return size;
3022 /* ----- servent */
3024 static int servent_size(struct servent* p_se)
3026 int size = 0;
3027 if( p_se )
3028 { size += sizeof(struct servent);
3029 size += strlen(p_se->s_proto) + strlen(p_se->s_name) + 2;
3030 size += list_size(p_se->s_aliases, 0); }
3031 return size;
3034 int WS_dup_se(struct servent* p_se, int flag)
3036 int size = servent_size(p_se);
3037 if( size )
3039 char *p_name,*p_aliases,*p_proto,*p_base,*p;
3040 char *p_to;
3041 struct ws_servent16 *p_to16;
3042 struct ws_servent32 *p_to32;
3044 check_buffer_se(size);
3045 p_to = se_buffer;
3046 p_to16 = se_buffer;
3047 p_to32 = se_buffer;
3048 p = p_to;
3049 p_base = (flag & WS_DUP_OFFSET) ? NULL
3050 : ((flag & WS_DUP_SEGPTR) ? (char*)SEGPTR_GET(p) : p);
3051 p += (flag & WS_DUP_SEGPTR) ?
3052 sizeof(struct ws_servent16) : sizeof(struct ws_servent32);
3053 p_name = p;
3054 strcpy(p, p_se->s_name); p += strlen(p) + 1;
3055 p_proto = p;
3056 strcpy(p, p_se->s_proto); p += strlen(p) + 1;
3057 p_aliases = p;
3058 list_dup(p_se->s_aliases, p, p_base + (p - p_to), 0);
3060 if (flag & WS_DUP_SEGPTR) /* Win16 */
3062 p_to16->s_port = (INT16)p_se->s_port;
3063 p_to16->s_name = (SEGPTR)(p_base + (p_name - p_to));
3064 p_to16->s_proto = (SEGPTR)(p_base + (p_proto - p_to));
3065 p_to16->s_aliases = (SEGPTR)(p_base + (p_aliases - p_to));
3066 size += (sizeof(struct ws_servent16) - sizeof(struct servent));
3068 else /* Win32 */
3070 p_to32->s_port = p_se->s_port;
3071 p_to32->s_name = (p_base + (p_name - p_to));
3072 p_to32->s_proto = (p_base + (p_proto - p_to));
3073 p_to32->s_aliases = (char **)(p_base + (p_aliases - p_to));
3074 size += (sizeof(struct ws_servent32) - sizeof(struct servent));
3077 return size;
3080 /* ----------------------------------- error handling */
3082 UINT16 wsaErrno(void)
3084 int loc_errno = errno;
3085 WARN("errno %d, (%s).\n", loc_errno, strerror(loc_errno));
3087 switch(loc_errno)
3089 case EINTR: return WSAEINTR;
3090 case EBADF: return WSAEBADF;
3091 case EPERM:
3092 case EACCES: return WSAEACCES;
3093 case EFAULT: return WSAEFAULT;
3094 case EINVAL: return WSAEINVAL;
3095 case EMFILE: return WSAEMFILE;
3096 case EWOULDBLOCK: return WSAEWOULDBLOCK;
3097 case EINPROGRESS: return WSAEINPROGRESS;
3098 case EALREADY: return WSAEALREADY;
3099 case ENOTSOCK: return WSAENOTSOCK;
3100 case EDESTADDRREQ: return WSAEDESTADDRREQ;
3101 case EMSGSIZE: return WSAEMSGSIZE;
3102 case EPROTOTYPE: return WSAEPROTOTYPE;
3103 case ENOPROTOOPT: return WSAENOPROTOOPT;
3104 case EPROTONOSUPPORT: return WSAEPROTONOSUPPORT;
3105 case ESOCKTNOSUPPORT: return WSAESOCKTNOSUPPORT;
3106 case EOPNOTSUPP: return WSAEOPNOTSUPP;
3107 case EPFNOSUPPORT: return WSAEPFNOSUPPORT;
3108 case EAFNOSUPPORT: return WSAEAFNOSUPPORT;
3109 case EADDRINUSE: return WSAEADDRINUSE;
3110 case EADDRNOTAVAIL: return WSAEADDRNOTAVAIL;
3111 case ENETDOWN: return WSAENETDOWN;
3112 case ENETUNREACH: return WSAENETUNREACH;
3113 case ENETRESET: return WSAENETRESET;
3114 case ECONNABORTED: return WSAECONNABORTED;
3115 case EPIPE:
3116 case ECONNRESET: return WSAECONNRESET;
3117 case ENOBUFS: return WSAENOBUFS;
3118 case EISCONN: return WSAEISCONN;
3119 case ENOTCONN: return WSAENOTCONN;
3120 case ESHUTDOWN: return WSAESHUTDOWN;
3121 case ETOOMANYREFS: return WSAETOOMANYREFS;
3122 case ETIMEDOUT: return WSAETIMEDOUT;
3123 case ECONNREFUSED: return WSAECONNREFUSED;
3124 case ELOOP: return WSAELOOP;
3125 case ENAMETOOLONG: return WSAENAMETOOLONG;
3126 case EHOSTDOWN: return WSAEHOSTDOWN;
3127 case EHOSTUNREACH: return WSAEHOSTUNREACH;
3128 case ENOTEMPTY: return WSAENOTEMPTY;
3129 #ifdef EPROCLIM
3130 case EPROCLIM: return WSAEPROCLIM;
3131 #endif
3132 #ifdef EUSERS
3133 case EUSERS: return WSAEUSERS;
3134 #endif
3135 #ifdef EDQUOT
3136 case EDQUOT: return WSAEDQUOT;
3137 #endif
3138 #ifdef ESTALE
3139 case ESTALE: return WSAESTALE;
3140 #endif
3141 #ifdef EREMOTE
3142 case EREMOTE: return WSAEREMOTE;
3143 #endif
3145 /* just in case we ever get here and there are no problems */
3146 case 0: return 0;
3147 default:
3148 WARN("Unknown errno %d!\n", loc_errno);
3149 return WSAEOPNOTSUPP;
3153 UINT16 wsaHerrno(int loc_errno)
3156 WARN("h_errno %d.\n", loc_errno);
3158 switch(loc_errno)
3160 case HOST_NOT_FOUND: return WSAHOST_NOT_FOUND;
3161 case TRY_AGAIN: return WSATRY_AGAIN;
3162 case NO_RECOVERY: return WSANO_RECOVERY;
3163 case NO_DATA: return WSANO_DATA;
3164 case ENOBUFS: return WSAENOBUFS;
3166 case 0: return 0;
3167 default:
3168 WARN("Unknown h_errno %d!\n", loc_errno);
3169 return WSAEOPNOTSUPP;