Got rid of the WSINFO structure. Fixed a couple of bugs.
[wine/multimedia.git] / dlls / winsock / socket.c
blobb4484bab014df4d3d31d619bb676fb8b788971cd
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 /* we need a special routine to handle WSA* errors */
210 static inline int sock_server_call( enum request req )
212 unsigned int res = server_call_noerr( req );
213 if (res)
215 /* do not map WSA errors */
216 if ((res < WSABASEERR) || (res >= 0x10000000)) res = RtlNtStatusToDosError(res);
217 SetLastError( res );
219 return res;
222 static char* check_buffer(int size);
224 static int _get_sock_fd(SOCKET s)
226 int fd = FILE_GetUnixHandle( s, GENERIC_READ );
227 if (fd == -1)
228 FIXME("handle %d is not a socket (GLE %ld)\n",s,GetLastError());
229 return fd;
232 static void _enable_event(SOCKET s, unsigned int event,
233 unsigned int sstate, unsigned int cstate)
235 SERVER_START_REQ
237 struct enable_socket_event_request *req = server_alloc_req( sizeof(*req), 0 );
239 req->handle = s;
240 req->mask = event;
241 req->sstate = sstate;
242 req->cstate = cstate;
243 sock_server_call( REQ_ENABLE_SOCKET_EVENT );
245 SERVER_END_REQ;
248 static int _is_blocking(SOCKET s)
250 int ret;
251 SERVER_START_REQ
253 struct get_socket_event_request *req = server_alloc_req( sizeof(*req), 0 );
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 ret = (req->state & WS_FD_NONBLOCKING) == 0;
262 SERVER_END_REQ;
263 return ret;
266 static unsigned int _get_sock_mask(SOCKET s)
268 unsigned int ret;
269 SERVER_START_REQ
271 struct get_socket_event_request *req = server_alloc_req( sizeof(*req), 0 );
273 req->handle = s;
274 req->service = FALSE;
275 req->s_event = 0;
276 req->c_event = 0;
277 sock_server_call( REQ_GET_SOCKET_EVENT );
278 ret = req->mask;
280 SERVER_END_REQ;
281 return ret;
284 static void _sync_sock_state(SOCKET s)
286 /* do a dummy wineserver request in order to let
287 the wineserver run through its select loop once */
288 (void)_is_blocking(s);
291 static int _get_sock_error(SOCKET s, unsigned int bit)
293 int ret;
294 SERVER_START_REQ
296 struct get_socket_event_request *req = server_alloc_req( sizeof(*req),
297 FD_MAX_EVENTS*sizeof(int) );
298 req->handle = s;
299 req->service = FALSE;
300 req->s_event = 0;
301 req->c_event = 0;
302 sock_server_call( REQ_GET_SOCKET_EVENT );
303 ret = *((int *)server_data_ptr(req) + bit);
305 SERVER_END_REQ;
306 return ret;
309 static void WINSOCK_DeleteIData(void)
311 /* delete scratch buffers */
313 if (he_buffer) SEGPTR_FREE(he_buffer);
314 if (se_buffer) SEGPTR_FREE(se_buffer);
315 if (pe_buffer) SEGPTR_FREE(pe_buffer);
316 if (local_buffer) SEGPTR_FREE(local_buffer);
317 if (dbuffer) SEGPTR_FREE(dbuffer);
318 he_buffer = NULL;
319 se_buffer = NULL;
320 pe_buffer = NULL;
321 local_buffer = NULL;
322 dbuffer = NULL;
323 num_startup = 0;
326 /***********************************************************************
327 * WSOCK32_LibMain (WSOCK32.init)
329 BOOL WINAPI WSOCK32_LibMain(HINSTANCE hInstDLL, DWORD fdwReason, LPVOID fImpLoad)
331 TRACE("0x%x 0x%lx %p\n", hInstDLL, fdwReason, fImpLoad);
332 switch (fdwReason) {
333 case DLL_PROCESS_DETACH:
334 WINSOCK_DeleteIData();
335 break;
337 return TRUE;
340 /***********************************************************************
341 * convert_sockopt()
343 * Converts socket flags from Windows format.
344 * Return 1 if converted, 0 if not (error).
346 static int convert_sockopt(INT *level, INT *optname)
348 int i;
349 switch (*level)
351 case WS_SOL_SOCKET:
352 *level = SOL_SOCKET;
353 for(i=0; _ws_sock_ops[i]; i++)
354 if( _ws_sock_ops[i] == *optname ) break;
355 if( _ws_sock_ops[i] ) {
356 *optname = _px_sock_ops[i];
357 return 1;
359 FIXME("Unknown SOL_SOCKET optname 0x%x\n", *optname);
360 break;
361 case WS_IPPROTO_TCP:
362 *level = IPPROTO_TCP;
363 for(i=0; _ws_tcp_ops[i]; i++)
364 if ( _ws_tcp_ops[i] == *optname ) break;
365 if( _ws_tcp_ops[i] ) {
366 *optname = _px_tcp_ops[i];
367 return 1;
369 FIXME("Unknown IPPROTO_TCP optname 0x%x\n", *optname);
370 break;
372 return 0;
375 /* ----------------------------------- Per-thread info (or per-process?) */
377 static int wsi_strtolo(const char* name, const char* opt)
379 /* Stuff a lowercase copy of the string into the local buffer */
381 int i = strlen(name) + 2;
382 char* p = check_buffer(i + ((opt)?strlen(opt):0));
384 if( p )
386 do *p++ = tolower(*name); while(*name++);
387 i = (p - local_buffer);
388 if( opt ) do *p++ = tolower(*opt); while(*opt++);
389 return i;
391 return 0;
394 static fd_set* fd_set_import( fd_set* fds, void* wsfds, int* highfd, int lfd[], BOOL b32 )
396 /* translate Winsock fd set into local fd set */
398 if( wsfds )
400 #define wsfds16 ((ws_fd_set16*)wsfds)
401 #define wsfds32 ((ws_fd_set32*)wsfds)
402 int i, count;
404 FD_ZERO(fds);
405 count = b32 ? wsfds32->fd_count : wsfds16->fd_count;
407 for( i = 0; i < count; i++ )
409 int s = (b32) ? wsfds32->fd_array[i]
410 : wsfds16->fd_array[i];
411 int fd = _get_sock_fd(s);
412 if (fd != -1)
414 lfd[ i ] = fd;
415 if( fd > *highfd ) *highfd = fd;
416 FD_SET(fd, fds);
418 else lfd[ i ] = -1;
420 #undef wsfds32
421 #undef wsfds16
422 return fds;
424 return NULL;
427 inline static int sock_error_p(int s)
429 unsigned int optval, optlen;
431 optlen = sizeof(optval);
432 getsockopt(s, SOL_SOCKET, SO_ERROR, (void *) &optval, &optlen);
433 if (optval) WARN("\t[%i] error: %d\n", s, optval);
434 return optval != 0;
437 static int fd_set_export( fd_set* fds, fd_set* exceptfds, void* wsfds, int lfd[], BOOL b32 )
439 int num_err = 0;
441 /* translate local fd set into Winsock fd set, adding
442 * errors to exceptfds (only if app requested it) */
444 if( wsfds )
446 #define wsfds16 ((ws_fd_set16*)wsfds)
447 #define wsfds32 ((ws_fd_set32*)wsfds)
448 int i, j, count = (b32) ? wsfds32->fd_count : wsfds16->fd_count;
450 for( i = 0, j = 0; i < count; i++ )
452 if( lfd[i] >= 0 )
454 int fd = lfd[i];
455 if( FD_ISSET(fd, fds) )
457 if ( exceptfds && sock_error_p(fd) )
459 FD_SET(fd, exceptfds);
460 num_err++;
462 else if( b32 )
463 wsfds32->fd_array[j++] = wsfds32->fd_array[i];
464 else
465 wsfds16->fd_array[j++] = wsfds16->fd_array[i];
467 close(fd);
468 lfd[i] = -1;
472 if( b32 ) wsfds32->fd_count = j;
473 else wsfds16->fd_count = j;
475 TRACE("\n");
476 #undef wsfds32
477 #undef wsfds16
479 return num_err;
482 static void fd_set_unimport( void* wsfds, int lfd[], BOOL b32 )
484 if ( wsfds )
486 #define wsfds16 ((ws_fd_set16*)wsfds)
487 #define wsfds32 ((ws_fd_set32*)wsfds)
488 int i, count = (b32) ? wsfds32->fd_count : wsfds16->fd_count;
490 for( i = 0; i < count; i++ )
491 if ( lfd[i] >= 0 )
492 close(lfd[i]);
494 TRACE("\n");
495 #undef wsfds32
496 #undef wsfds16
500 static int do_block( int fd, int mask )
502 fd_set fds[3];
503 int i, r;
505 FD_ZERO(&fds[0]);
506 FD_ZERO(&fds[1]);
507 FD_ZERO(&fds[2]);
508 for (i=0; i<3; i++)
509 if (mask & (1<<i))
510 FD_SET(fd, &fds[i]);
511 i = select( fd+1, &fds[0], &fds[1], &fds[2], NULL );
512 if (i <= 0) return -1;
513 r = 0;
514 for (i=0; i<3; i++)
515 if (FD_ISSET(fd, &fds[i]))
516 r |= 1<<i;
517 return r;
520 void* __ws_memalloc( int size )
522 return WS_ALLOC(size);
525 void __ws_memfree(void* ptr)
527 WS_FREE(ptr);
531 /* ----------------------------------- API -----
533 * Init / cleanup / error checking.
536 /***********************************************************************
537 * WSAStartup16() (WINSOCK.115)
539 * Create socket control struct, attach it to the global list and
540 * update a pointer in the task struct.
542 INT16 WINAPI WSAStartup16(UINT16 wVersionRequested, LPWSADATA lpWSAData)
544 WSADATA WINSOCK_data = { 0x0101, 0x0101,
545 "WINE Sockets 1.1",
546 #ifdef linux
547 "Linux/i386",
548 #elif defined(__NetBSD__)
549 "NetBSD/i386",
550 #elif defined(sunos)
551 "SunOS",
552 #elif defined(__FreeBSD__)
553 "FreeBSD",
554 #elif defined(__OpenBSD__)
555 "OpenBSD/i386",
556 #else
557 "Unknown",
558 #endif
559 WS_MAX_SOCKETS_PER_PROCESS,
560 WS_MAX_UDP_DATAGRAM, (SEGPTR)NULL };
562 TRACE("verReq=%x\n", wVersionRequested);
564 if (LOBYTE(wVersionRequested) < 1 || (LOBYTE(wVersionRequested) == 1 &&
565 HIBYTE(wVersionRequested) < 1)) return WSAVERNOTSUPPORTED;
567 if (!lpWSAData) return WSAEINVAL;
569 /* initialize socket heap */
571 if( !_WSHeap )
573 _WSHeap = HeapCreate(HEAP_ZERO_MEMORY, 8120, 32768);
574 if( !_WSHeap )
576 ERR("Fatal: failed to create WinSock heap\n");
577 return 0;
580 if( _WSHeap == 0 ) return WSASYSNOTREADY;
582 num_startup++;
584 /* return winsock information */
586 memcpy(lpWSAData, &WINSOCK_data, sizeof(WINSOCK_data));
588 TRACE("succeeded\n");
589 return 0;
592 /***********************************************************************
593 * WSAStartup() (WS2_32.115)
595 INT WINAPI WSAStartup(UINT wVersionRequested, LPWSADATA lpWSAData)
597 WSADATA WINSOCK_data = { 0x0202, 0x0202,
598 "WINE Sockets 2.0",
599 #ifdef linux
600 "Linux/i386",
601 #elif defined(__NetBSD__)
602 "NetBSD/i386",
603 #elif defined(sunos)
604 "SunOS",
605 #elif defined(__FreeBSD__)
606 "FreeBSD",
607 #elif defined(__OpenBSD__)
608 "OpenBSD/i386",
609 #else
610 "Unknown",
611 #endif
612 WS_MAX_SOCKETS_PER_PROCESS,
613 WS_MAX_UDP_DATAGRAM, (SEGPTR)NULL };
615 TRACE("verReq=%x\n", wVersionRequested);
617 if (LOBYTE(wVersionRequested) < 1)
618 return WSAVERNOTSUPPORTED;
620 if (!lpWSAData) return WSAEINVAL;
622 /* initialize socket heap */
624 if( !_WSHeap )
626 _WSHeap = HeapCreate(HEAP_ZERO_MEMORY, 8120, 32768);
627 if( !_WSHeap )
629 ERR("Fatal: failed to create WinSock heap\n");
630 return 0;
633 if( _WSHeap == 0 ) return WSASYSNOTREADY;
635 num_startup++;
637 /* return winsock information */
638 memcpy(lpWSAData, &WINSOCK_data, sizeof(WINSOCK_data));
640 /* that's the whole of the negotiation for now */
641 lpWSAData->wVersion = wVersionRequested;
643 TRACE("succeeded\n");
644 return 0;
648 /***********************************************************************
649 * WSACleanup() (WINSOCK.116)
651 INT WINAPI WSACleanup(void)
653 if (num_startup)
655 if (--num_startup > 0) return 0;
656 WINSOCK_DeleteIData();
657 return 0;
659 SetLastError(WSANOTINITIALISED);
660 return SOCKET_ERROR;
664 /***********************************************************************
665 * WSAGetLastError() (WSOCK32.111)(WINSOCK.111)
667 INT WINAPI WSAGetLastError(void)
669 return GetLastError();
672 /***********************************************************************
673 * WSASetLastError() (WSOCK32.112)
675 void WINAPI WSASetLastError(INT iError) {
676 SetLastError(iError);
679 /***********************************************************************
680 * WSASetLastError16() (WINSOCK.112)
682 void WINAPI WSASetLastError16(INT16 iError)
684 WSASetLastError(iError);
687 static char* check_buffer(int size)
689 static int local_buflen;
691 if (local_buffer)
693 if (local_buflen >= size ) return local_buffer;
694 SEGPTR_FREE(local_buffer);
696 local_buffer = SEGPTR_ALLOC((local_buflen = size));
697 return local_buffer;
700 static struct ws_hostent* check_buffer_he(int size)
702 static int he_len;
703 if (he_buffer)
705 if (he_len >= size ) return he_buffer;
706 SEGPTR_FREE(he_buffer);
708 he_buffer = SEGPTR_ALLOC((he_len = size));
709 return he_buffer;
712 static void* check_buffer_se(int size)
714 static int se_len;
715 if (se_buffer)
717 if (se_len >= size ) return se_buffer;
718 SEGPTR_FREE(se_buffer);
720 se_buffer = SEGPTR_ALLOC((se_len = size));
721 return se_buffer;
724 static struct ws_protoent* check_buffer_pe(int size)
726 static int pe_len;
727 if (pe_buffer)
729 if (pe_len >= size ) return pe_buffer;
730 SEGPTR_FREE(pe_buffer);
732 pe_buffer = SEGPTR_ALLOC((pe_len = size));
733 return pe_buffer;
736 /* ----------------------------------- i/o APIs */
738 /***********************************************************************
739 * accept() (WSOCK32.1)
741 static void WSOCK32_async_accept(SOCKET s, SOCKET as)
743 int q;
744 /* queue socket for WSAAsyncSelect */
745 for (q=0; q<WS_ACCEPT_QUEUE; q++)
746 if (InterlockedCompareExchange((PVOID*)&accept_old[q], (PVOID)s, (PVOID)0) == (PVOID)0)
747 break;
748 if (q<WS_ACCEPT_QUEUE)
749 accept_new[q] = as;
750 else
751 ERR("accept queue too small\n");
752 /* now signal our AsyncSelect handler */
753 _enable_event(s, WS_FD_SERVEVENT, 0, 0);
756 /**********************************************************************/
758 SOCKET WINAPI WSOCK32_accept(SOCKET s, struct sockaddr *addr,
759 INT *addrlen32)
761 #ifdef HAVE_IPX
762 struct ws_sockaddr_ipx* addr2 = (struct ws_sockaddr_ipx *)addr;
763 #endif
764 int fd = _get_sock_fd(s);
766 TRACE("socket %04x\n", (UINT16)s );
767 if (fd != -1)
769 SOCKET as;
770 if (_is_blocking(s))
772 /* block here */
773 do_block(fd, 5);
774 _sync_sock_state(s); /* let wineserver notice connection */
775 /* retrieve any error codes from it */
776 SetLastError(_get_sock_error(s, FD_ACCEPT_BIT));
777 /* FIXME: care about the error? */
779 close(fd);
780 SERVER_START_REQ
782 struct accept_socket_request *req = server_alloc_req( sizeof(*req), 0 );
784 req->lhandle = s;
785 req->access = GENERIC_READ|GENERIC_WRITE|SYNCHRONIZE;
786 req->inherit = TRUE;
787 sock_server_call( REQ_ACCEPT_SOCKET );
788 as = (SOCKET)req->handle;
790 SERVER_END_REQ;
791 if (as)
793 unsigned omask = _get_sock_mask( s );
794 int fd = _get_sock_fd( as );
795 if( getpeername(fd, addr, addrlen32) != -1 )
797 #ifdef HAVE_IPX
798 if (addr && ((struct sockaddr_ipx *)addr)->sipx_family == AF_IPX) {
799 addr = (struct sockaddr *)
800 malloc(addrlen32 ? *addrlen32 : sizeof(*addr2));
801 memcpy(addr, addr2,
802 addrlen32 ? *addrlen32 : sizeof(*addr2));
803 addr2->sipx_family = WS_AF_IPX;
804 addr2->sipx_network = ((struct sockaddr_ipx *)addr)->sipx_network;
805 addr2->sipx_port = ((struct sockaddr_ipx *)addr)->sipx_port;
806 memcpy(addr2->sipx_node,
807 ((struct sockaddr_ipx *)addr)->sipx_node, IPX_NODE_LEN);
808 free(addr);
810 #endif
811 } else SetLastError(wsaErrno());
812 close(fd);
813 if (omask & WS_FD_SERVEVENT)
814 WSOCK32_async_accept(s, as);
815 return as;
818 return INVALID_SOCKET;
821 /***********************************************************************
822 * accept() (WINSOCK.1)
824 SOCKET16 WINAPI WINSOCK_accept16(SOCKET16 s, struct sockaddr* addr,
825 INT16* addrlen16 )
827 INT addrlen32 = addrlen16 ? *addrlen16 : 0;
828 SOCKET retSocket = WSOCK32_accept( s, addr, &addrlen32 );
829 if( addrlen16 ) *addrlen16 = (INT16)addrlen32;
830 return (SOCKET16)retSocket;
833 /***********************************************************************
834 * bind() (WSOCK32.2)
836 INT WINAPI WSOCK32_bind(SOCKET s, struct sockaddr *name, INT namelen)
838 #ifdef HAVE_IPX
839 struct ws_sockaddr_ipx* name2 = (struct ws_sockaddr_ipx *)name;
840 #endif
841 int fd = _get_sock_fd(s);
843 TRACE("socket %04x, ptr %8x, length %d\n", s, (int) name, namelen);
844 #if DEBUG_SOCKADDR
845 dump_sockaddr(name);
846 #endif
848 if (fd != -1)
850 /* FIXME: what family does this really map to on the Unix side? */
851 if (name && ((struct ws_sockaddr_ipx *)name)->sipx_family == WS_AF_PUP)
852 ((struct ws_sockaddr_ipx *)name)->sipx_family = AF_UNSPEC;
853 #ifdef HAVE_IPX
854 else if (name &&
855 ((struct ws_sockaddr_ipx *)name)->sipx_family == WS_AF_IPX)
857 name = (struct sockaddr *) malloc(sizeof(struct sockaddr_ipx));
858 memset(name, '\0', sizeof(struct sockaddr_ipx));
859 ((struct sockaddr_ipx *)name)->sipx_family = AF_IPX;
860 ((struct sockaddr_ipx *)name)->sipx_port = name2->sipx_port;
861 ((struct sockaddr_ipx *)name)->sipx_network = name2->sipx_network;
862 memcpy(((struct sockaddr_ipx *)name)->sipx_node,
863 name2->sipx_node, IPX_NODE_LEN);
864 namelen = sizeof(struct sockaddr_ipx);
866 #endif
867 if ( namelen >= sizeof(*name) )
869 if ( name && (((struct ws_sockaddr_in *)name)->sin_family == AF_INET
870 #ifdef HAVE_IPX
871 || ((struct sockaddr_ipx *)name)->sipx_family == AF_IPX
872 #endif
875 if ( bind(fd, name, namelen) < 0 )
877 int loc_errno = errno;
878 WARN("\tfailure - errno = %i\n", errno);
879 errno = loc_errno;
880 switch(errno)
882 case EBADF: SetLastError(WSAENOTSOCK); break;
883 case EADDRNOTAVAIL: SetLastError(WSAEINVAL); break;
884 default: SetLastError(wsaErrno());break;
887 else {
888 #ifdef HAVE_IPX
889 if (((struct sockaddr_ipx *)name)->sipx_family == AF_IPX)
890 free(name);
891 #endif
892 close(fd);
893 return 0; /* success */
895 } else SetLastError(WSAEAFNOSUPPORT);
896 } else SetLastError(WSAEFAULT);
897 #ifdef HAVE_IPX
898 if (name && ((struct sockaddr_ipx *)name)->sipx_family == AF_IPX)
899 free(name);
900 #endif
901 close(fd);
903 return SOCKET_ERROR;
906 /***********************************************************************
907 * bind() (WINSOCK.2)
909 INT16 WINAPI WINSOCK_bind16(SOCKET16 s, struct sockaddr *name, INT16 namelen)
911 return (INT16)WSOCK32_bind( s, name, namelen );
914 /***********************************************************************
915 * closesocket() (WSOCK32.3)
917 INT WINAPI WSOCK32_closesocket(SOCKET s)
919 TRACE("socket %08x\n", s);
920 if (CloseHandle(s)) return 0;
921 return SOCKET_ERROR;
924 /***********************************************************************
925 * closesocket() (WINSOCK.3)
927 INT16 WINAPI WINSOCK_closesocket16(SOCKET16 s)
929 return (INT16)WSOCK32_closesocket(s);
932 /***********************************************************************
933 * connect() (WSOCK32.4)
935 INT WINAPI WSOCK32_connect(SOCKET s, struct sockaddr *name, INT namelen)
937 #ifdef HAVE_IPX
938 struct ws_sockaddr_ipx* name2 = (struct ws_sockaddr_ipx *)name;
939 #endif
940 int fd = _get_sock_fd(s);
942 TRACE("socket %04x, ptr %8x, length %d\n", s, (int) name, namelen);
943 #if DEBUG_SOCKADDR
944 dump_sockaddr(name);
945 #endif
947 if (fd != -1)
949 if (name && ((struct ws_sockaddr_ipx *)name)->sipx_family == WS_AF_PUP)
950 ((struct ws_sockaddr_ipx *)name)->sipx_family = AF_UNSPEC;
951 #ifdef HAVE_IPX
952 else if (name && ((struct ws_sockaddr_ipx *)name)->sipx_family == WS_AF_IPX)
954 name = (struct sockaddr *) malloc(sizeof(struct sockaddr_ipx));
955 memset(name, '\0', sizeof(struct sockaddr_ipx));
956 ((struct sockaddr_ipx *)name)->sipx_family = AF_IPX;
957 ((struct sockaddr_ipx *)name)->sipx_port = name2->sipx_port;
958 ((struct sockaddr_ipx *)name)->sipx_network = name2->sipx_network;
959 memcpy(((struct sockaddr_ipx *)name)->sipx_node,
960 name2->sipx_node, IPX_NODE_LEN);
961 namelen = sizeof(struct sockaddr_ipx);
963 #endif
964 if (connect(fd, name, namelen) == 0) {
965 close(fd);
966 goto connect_success;
968 if (errno == EINPROGRESS)
970 /* tell wineserver that a connection is in progress */
971 _enable_event(s, FD_CONNECT|FD_READ|FD_WRITE,
972 WS_FD_CONNECT|WS_FD_READ|WS_FD_WRITE,
973 WS_FD_CONNECTED|WS_FD_LISTENING);
974 if (_is_blocking(s))
976 int result;
977 /* block here */
978 do_block(fd, 7);
979 _sync_sock_state(s); /* let wineserver notice connection */
980 /* retrieve any error codes from it */
981 result = _get_sock_error(s, FD_CONNECT_BIT);
982 if (result)
983 SetLastError(result);
984 else {
985 close(fd);
986 goto connect_success;
989 else SetLastError(WSAEWOULDBLOCK);
990 close(fd);
992 else
994 SetLastError(wsaErrno());
995 close(fd);
998 #ifdef HAVE_IPX
999 if (name && ((struct sockaddr_ipx *)name)->sipx_family == AF_IPX)
1000 free(name);
1001 #endif
1002 return SOCKET_ERROR;
1003 connect_success:
1004 #ifdef HAVE_IPX
1005 if (((struct sockaddr_ipx *)name)->sipx_family == AF_IPX)
1006 free(name);
1007 #endif
1008 _enable_event(s, FD_CONNECT|FD_READ|FD_WRITE,
1009 WS_FD_CONNECTED|WS_FD_READ|WS_FD_WRITE,
1010 WS_FD_CONNECT|WS_FD_LISTENING);
1011 return 0;
1014 /***********************************************************************
1015 * connect() (WINSOCK.4)
1017 INT16 WINAPI WINSOCK_connect16(SOCKET16 s, struct sockaddr *name, INT16 namelen)
1019 return (INT16)WSOCK32_connect( s, name, namelen );
1022 /***********************************************************************
1023 * getpeername() (WSOCK32.5)
1025 INT WINAPI WSOCK32_getpeername(SOCKET s, struct sockaddr *name,
1026 INT *namelen)
1028 #ifdef HAVE_IPX
1029 struct ws_sockaddr_ipx* name2 = (struct ws_sockaddr_ipx *)name;
1030 #endif
1031 int fd = _get_sock_fd(s);
1033 TRACE("socket: %04x, ptr %8x, ptr %8x\n", s, (int) name, *namelen);
1034 if (fd != -1)
1036 if (getpeername(fd, name, namelen) == 0) {
1037 #ifdef HAVE_IPX
1038 if (((struct ws_sockaddr_ipx *)name)->sipx_family == AF_IPX) {
1039 name = (struct sockaddr *)
1040 malloc(namelen ? *namelen : sizeof(*name2));
1041 memcpy(name, name2, namelen ? *namelen : sizeof(*name2));
1042 name2->sipx_family = WS_AF_IPX;
1043 name2->sipx_network = ((struct sockaddr_ipx *)name)->sipx_network;
1044 name2->sipx_port = ((struct sockaddr_ipx *)name)->sipx_port;
1045 memcpy(name2->sipx_node,
1046 ((struct sockaddr_ipx *)name)->sipx_node, IPX_NODE_LEN);
1047 free(name);
1049 #endif
1050 close(fd);
1051 return 0;
1053 SetLastError(wsaErrno());
1054 close(fd);
1056 return SOCKET_ERROR;
1059 /***********************************************************************
1060 * getpeername() (WINSOCK.5)
1062 INT16 WINAPI WINSOCK_getpeername16(SOCKET16 s, struct sockaddr *name,
1063 INT16 *namelen16)
1065 INT namelen32 = *namelen16;
1066 INT retVal = WSOCK32_getpeername( s, name, &namelen32 );
1068 #if DEBUG_SOCKADDR
1069 dump_sockaddr(name);
1070 #endif
1072 *namelen16 = namelen32;
1073 return (INT16)retVal;
1076 /***********************************************************************
1077 * getsockname() (WSOCK32.6)
1079 INT WINAPI WSOCK32_getsockname(SOCKET s, struct sockaddr *name,
1080 INT *namelen)
1082 #ifdef HAVE_IPX
1083 struct ws_sockaddr_ipx* name2 = (struct ws_sockaddr_ipx *)name;
1084 #endif
1085 int fd = _get_sock_fd(s);
1087 TRACE("socket: %04x, ptr %8x, ptr %8x\n", s, (int) name, (int) *namelen);
1088 if (fd != -1)
1090 if (getsockname(fd, name, namelen) == 0) {
1091 #ifdef HAVE_IPX
1092 if (((struct sockaddr_ipx *)name)->sipx_family == AF_IPX) {
1093 name = (struct sockaddr *)
1094 malloc(namelen ? *namelen : sizeof(*name2));
1095 memcpy(name, name2, namelen ? *namelen : sizeof(*name2));
1096 name2->sipx_family = WS_AF_IPX;
1097 name2->sipx_network = ((struct sockaddr_ipx *)name)->sipx_network;
1098 name2->sipx_port = ((struct sockaddr_ipx *)name)->sipx_port;
1099 memcpy(name2->sipx_node,
1100 ((struct sockaddr_ipx *)name)->sipx_node, IPX_NODE_LEN);
1101 free(name);
1103 #endif
1104 close(fd);
1105 return 0;
1107 SetLastError(wsaErrno());
1108 close(fd);
1110 return SOCKET_ERROR;
1113 /***********************************************************************
1114 * getsockname() (WINSOCK.6)
1116 INT16 WINAPI WINSOCK_getsockname16(SOCKET16 s, struct sockaddr *name,
1117 INT16 *namelen16)
1119 INT retVal;
1121 if( namelen16 )
1123 INT namelen32 = *namelen16;
1124 retVal = WSOCK32_getsockname( s, name, &namelen32 );
1125 *namelen16 = namelen32;
1127 #if DEBUG_SOCKADDR
1128 dump_sockaddr(name);
1129 #endif
1132 else retVal = SOCKET_ERROR;
1133 return (INT16)retVal;
1137 /***********************************************************************
1138 * getsockopt() (WSOCK32.7)
1140 INT WINAPI WSOCK32_getsockopt(SOCKET s, INT level,
1141 INT optname, char *optval, INT *optlen)
1143 int fd = _get_sock_fd(s);
1145 TRACE("socket: %04x, opt 0x%x, ptr %8x, len %d\n", s, level, (int) optval, (int) *optlen);
1146 if (fd != -1)
1148 if (!convert_sockopt(&level, &optname)) {
1149 SetLastError(WSAENOPROTOOPT); /* Unknown option */
1150 } else {
1151 if (getsockopt(fd, (int) level, optname, optval, optlen) == 0 )
1153 close(fd);
1154 return 0;
1156 SetLastError((errno == EBADF) ? WSAENOTSOCK : wsaErrno());
1158 close(fd);
1160 return SOCKET_ERROR;
1163 /***********************************************************************
1164 * getsockopt() (WINSOCK.7)
1166 INT16 WINAPI WINSOCK_getsockopt16(SOCKET16 s, INT16 level,
1167 INT16 optname, char *optval, INT16 *optlen)
1169 INT optlen32;
1170 INT *p = &optlen32;
1171 INT retVal;
1172 if( optlen ) optlen32 = *optlen; else p = NULL;
1173 retVal = WSOCK32_getsockopt( s, (UINT16)level, optname, optval, p );
1174 if( optlen ) *optlen = optlen32;
1175 return (INT16)retVal;
1178 /***********************************************************************
1179 * htonl() (WINSOCK.8)(WSOCK32.8)
1181 u_long WINAPI WINSOCK_htonl(u_long hostlong) { return( htonl(hostlong) ); }
1182 /***********************************************************************
1183 * htons() (WINSOCK.9)(WSOCK32.9)
1185 u_short WINAPI WINSOCK_htons(u_short hostshort) { return( htons(hostshort) ); }
1186 /***********************************************************************
1187 * inet_addr() (WINSOCK.10)(WSOCK32.10)
1189 u_long WINAPI WINSOCK_inet_addr(char *cp) { return( inet_addr(cp) ); }
1190 /***********************************************************************
1191 * ntohl() (WINSOCK.14)(WSOCK32.14)
1193 u_long WINAPI WINSOCK_ntohl(u_long netlong) { return( ntohl(netlong) ); }
1194 /***********************************************************************
1195 * ntohs() (WINSOCK.15)(WSOCK32.15)
1197 u_short WINAPI WINSOCK_ntohs(u_short netshort) { return( ntohs(netshort) ); }
1199 /***********************************************************************
1200 * inet_ntoa() (WINSOCK.11)(WSOCK32.11)
1202 char* WINAPI WSOCK32_inet_ntoa(struct in_addr in)
1204 /* use "buffer for dummies" here because some applications have
1205 * propensity to decode addresses in ws_hostent structure without
1206 * saving them first...
1208 char* s = inet_ntoa(in);
1209 if( s )
1211 if( dbuffer == NULL ) {
1212 /* Yes, 16: 4*3 digits + 3 '.' + 1 '\0' */
1213 if((dbuffer = (char*) SEGPTR_ALLOC(16)) == NULL )
1215 SetLastError(WSAENOBUFS);
1216 return NULL;
1219 strcpy(dbuffer, s);
1220 return dbuffer;
1222 SetLastError(wsaErrno());
1223 return NULL;
1226 /**********************************************************************/
1228 SEGPTR WINAPI WINSOCK_inet_ntoa16(struct in_addr in)
1230 char* retVal = WSOCK32_inet_ntoa(in);
1231 return SEGPTR_GET(retVal);
1235 /**********************************************************************
1236 * WSAIoctl (WS2_32)
1239 * FIXME: Only SIO_GET_INTERFACE_LIST option implemented.
1241 INT WINAPI WSAIoctl (SOCKET s,
1242 DWORD dwIoControlCode,
1243 LPVOID lpvInBuffer,
1244 DWORD cbInBuffer,
1245 LPVOID lpbOutBuffer,
1246 DWORD cbOutBuffer,
1247 LPDWORD lpcbBytesReturned,
1248 LPWSAOVERLAPPED lpOverlapped,
1249 LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine)
1251 int fd = _get_sock_fd(s);
1253 if (fd != -1)
1255 switch( dwIoControlCode )
1257 case SIO_GET_INTERFACE_LIST:
1259 INTERFACE_INFO* intArray = (INTERFACE_INFO*)lpbOutBuffer;
1260 int i, numInt;
1261 struct ifreq ifInfo;
1262 char ifName[512];
1265 TRACE ("-> SIO_GET_INTERFACE_LIST request\n");
1267 numInt = WSAIOCTL_GetInterfaceCount();
1268 if (numInt < 0)
1270 ERR ("Unable to open /proc filesystem to determine number of network interfaces!\n");
1271 close(fd);
1272 WSASetLastError(WSAEINVAL);
1273 return (SOCKET_ERROR);
1276 for (i=0; i<numInt; i++)
1278 if (!WSAIOCTL_GetInterfaceName(i, ifName))
1280 ERR ("Error parsing /proc filesystem!\n");
1281 close(fd);
1282 WSASetLastError(WSAEINVAL);
1283 return (SOCKET_ERROR);
1286 ifInfo.ifr_addr.sa_family = AF_INET;
1288 /* IP Address */
1289 strcpy (ifInfo.ifr_name, ifName);
1290 if (ioctl(fd, SIOCGIFADDR, &ifInfo) < 0)
1292 ERR ("Error obtaining IP address\n");
1293 close(fd);
1294 WSASetLastError(WSAEINVAL);
1295 return (SOCKET_ERROR);
1297 else
1299 struct ws_sockaddr_in *ipTemp = (struct ws_sockaddr_in *)&ifInfo.ifr_addr;
1301 intArray->iiAddress.AddressIn.sin_family = AF_INET;
1302 intArray->iiAddress.AddressIn.sin_port = ipTemp->sin_port;
1303 intArray->iiAddress.AddressIn.sin_addr.ws_addr = ipTemp->sin_addr.S_un.S_addr;
1306 /* Broadcast Address */
1307 strcpy (ifInfo.ifr_name, ifName);
1308 if (ioctl(fd, SIOCGIFBRDADDR, &ifInfo) < 0)
1310 ERR ("Error obtaining Broadcast IP address\n");
1311 close(fd);
1312 WSASetLastError(WSAEINVAL);
1313 return (SOCKET_ERROR);
1315 else
1317 struct ws_sockaddr_in *ipTemp = (struct ws_sockaddr_in *)&ifInfo.ifr_broadaddr;
1319 intArray->iiBroadcastAddress.AddressIn.sin_family = AF_INET;
1320 intArray->iiBroadcastAddress.AddressIn.sin_port = ipTemp->sin_port;
1321 intArray->iiBroadcastAddress.AddressIn.sin_addr.ws_addr = ipTemp->sin_addr.S_un.S_addr;
1324 /* Subnet Mask */
1325 strcpy (ifInfo.ifr_name, ifName);
1326 if (ioctl(fd, SIOCGIFNETMASK, &ifInfo) < 0)
1328 ERR ("Error obtaining Subnet IP address\n");
1329 close(fd);
1330 WSASetLastError(WSAEINVAL);
1331 return (SOCKET_ERROR);
1333 else
1335 /* Trying to avoid some compile problems across platforms.
1336 (Linux, FreeBSD, Solaris...) */
1337 #ifndef ifr_netmask
1338 #ifndef ifr_addr
1339 intArray->iiNetmask.AddressIn.sin_family = AF_INET;
1340 intArray->iiNetmask.AddressIn.sin_port = 0;
1341 intArray->iiNetmask.AddressIn.sin_addr.ws_addr = 0;
1342 ERR ("Unable to determine Netmask on your platform!\n");
1343 #else
1344 struct ws_sockaddr_in *ipTemp = (struct ws_sockaddr_in *)&ifInfo.ifr_addr;
1346 intArray->iiNetmask.AddressIn.sin_family = AF_INET;
1347 intArray->iiNetmask.AddressIn.sin_port = ipTemp->sin_port;
1348 intArray->iiNetmask.AddressIn.sin_addr.ws_addr = ipTemp->sin_addr.S_un.S_addr;
1349 #endif
1350 #else
1351 struct ws_sockaddr_in *ipTemp = (struct ws_sockaddr_in *)&ifInfo.ifr_netmask;
1353 intArray->iiNetmask.AddressIn.sin_family = AF_INET;
1354 intArray->iiNetmask.AddressIn.sin_port = ipTemp->sin_port;
1355 intArray->iiNetmask.AddressIn.sin_addr.ws_addr = ipTemp->sin_addr.S_un.S_addr;
1356 #endif
1359 /* Socket Status Flags */
1360 strcpy(ifInfo.ifr_name, ifName);
1361 if (ioctl(fd, SIOCGIFFLAGS, &ifInfo) < 0)
1363 ERR ("Error obtaining status flags for socket!\n");
1364 close(fd);
1365 WSASetLastError(WSAEINVAL);
1366 return (SOCKET_ERROR);
1368 else
1370 /* FIXME - Is this the right flag to use? */
1371 intArray->iiFlags = ifInfo.ifr_flags;
1373 intArray++; /* Prepare for another interface */
1376 /* Calculate the size of the array being returned */
1377 *lpcbBytesReturned = sizeof(INTERFACE_INFO) * numInt;
1378 break;
1381 default:
1383 WARN("\tunsupported WS_IOCTL cmd (%08lx)\n", dwIoControlCode);
1384 close(fd);
1385 WSASetLastError(WSAEOPNOTSUPP);
1386 return (SOCKET_ERROR);
1390 /* Function executed with no errors */
1391 close(fd);
1392 return (0);
1394 else
1396 WSASetLastError(WSAENOTSOCK);
1397 return (SOCKET_ERROR);
1403 Helper function for WSAIoctl - Get count of the number of interfaces
1404 by parsing /proc filesystem.
1406 int WSAIOCTL_GetInterfaceCount(void)
1408 FILE *procfs;
1409 char buf[512]; /* Size doesn't matter, something big */
1410 int intcnt=0;
1413 /* Open /proc filesystem file for network devices */
1414 procfs = fopen(PROCFS_NETDEV_FILE, "r");
1415 if (!procfs)
1417 /* If we can't open the file, return an error */
1418 return (-1);
1421 /* Omit first two lines, they are only headers */
1422 fgets(buf, sizeof buf, procfs);
1423 fgets(buf, sizeof buf, procfs);
1425 while (fgets(buf, sizeof buf, procfs))
1427 /* Each line in the file represents a network interface */
1428 intcnt++;
1431 fclose(procfs);
1432 return(intcnt);
1437 Helper function for WSAIoctl - Get name of device from interface number
1438 by parsing /proc filesystem.
1440 int WSAIOCTL_GetInterfaceName(int intNumber, char *intName)
1442 FILE *procfs;
1443 char buf[512]; /* Size doesn't matter, something big */
1444 int i;
1446 /* Open /proc filesystem file for network devices */
1447 procfs = fopen(PROCFS_NETDEV_FILE, "r");
1448 if (!procfs)
1450 /* If we can't open the file, return an error */
1451 return (-1);
1454 /* Omit first two lines, they are only headers */
1455 fgets(buf, sizeof(buf), procfs);
1456 fgets(buf, sizeof(buf), procfs);
1458 for (i=0; i<intNumber; i++)
1460 /* Skip the lines that don't interest us. */
1461 fgets(buf, sizeof(buf), procfs);
1463 fgets(buf, sizeof(buf), procfs); /* This is the line we want */
1466 /* Parse out the line, grabbing only the name of the device
1467 to the intName variable
1469 The Line comes in like this: (we only care about the device name)
1470 lo: 21970 377 0 0 0 0 0 0 21970 377 0 0 0 0 0 0
1472 i=0;
1473 while (isspace(buf[i])) /* Skip initial space(s) */
1475 i++;
1478 while (buf[i])
1480 if (isspace(buf[i]))
1482 break;
1485 if (buf[i] == ':') /* FIXME: Not sure if this block (alias detection) works properly */
1487 /* This interface could be an alias... */
1488 int hold = i;
1489 char *dotname = intName;
1490 *intName++ = buf[i++];
1492 while (isdigit(buf[i]))
1494 *intName++ = buf[i++];
1497 if (buf[i] != ':')
1499 /* ... It wasn't, so back up */
1500 i = hold;
1501 intName = dotname;
1504 if (buf[i] == '\0')
1506 fclose(procfs);
1507 return(FALSE);
1510 i++;
1511 break;
1514 *intName++ = buf[i++];
1516 *intName++ = '\0';
1518 fclose(procfs);
1519 return(TRUE);
1523 /***********************************************************************
1524 * ioctlsocket() (WSOCK32.12)
1526 INT WINAPI WSOCK32_ioctlsocket(SOCKET s, LONG cmd, ULONG *argp)
1528 int fd = _get_sock_fd(s);
1530 TRACE("socket %04x, cmd %08lx, ptr %8x\n", s, cmd, (unsigned) argp);
1531 if (fd != -1)
1533 long newcmd = cmd;
1535 switch( cmd )
1537 case WS_FIONREAD:
1538 newcmd=FIONREAD;
1539 break;
1541 case WS_FIONBIO:
1542 newcmd=FIONBIO;
1543 if( _get_sock_mask(s) )
1545 /* AsyncSelect()'ed sockets are always nonblocking */
1546 if (*argp) {
1547 close(fd);
1548 return 0;
1550 SetLastError(WSAEINVAL);
1551 close(fd);
1552 return SOCKET_ERROR;
1554 close(fd);
1555 if (*argp)
1556 _enable_event(s, 0, WS_FD_NONBLOCKING, 0);
1557 else
1558 _enable_event(s, 0, 0, WS_FD_NONBLOCKING);
1559 return 0;
1561 case WS_SIOCATMARK:
1562 newcmd=SIOCATMARK;
1563 break;
1565 case WS_IOW('f',125,u_long):
1566 WARN("Warning: WS1.1 shouldn't be using async I/O\n");
1567 SetLastError(WSAEINVAL);
1568 return SOCKET_ERROR;
1570 case SIOCGIFBRDADDR:
1571 case SIOCGIFNETMASK:
1572 case SIOCGIFADDR:
1573 /* These don't need any special handling. They are used by
1574 WsControl, and are here to suppress an unecessary warning. */
1575 break;
1578 default:
1579 /* Netscape tries hard to use bogus ioctl 0x667e */
1580 WARN("\tunknown WS_IOCTL cmd (%08lx)\n", cmd);
1582 if( ioctl(fd, newcmd, (char*)argp ) == 0 )
1584 close(fd);
1585 return 0;
1587 SetLastError((errno == EBADF) ? WSAENOTSOCK : wsaErrno());
1588 close(fd);
1590 return SOCKET_ERROR;
1593 /***********************************************************************
1594 * ioctlsocket() (WINSOCK.12)
1596 INT16 WINAPI WINSOCK_ioctlsocket16(SOCKET16 s, LONG cmd, ULONG *argp)
1598 return (INT16)WSOCK32_ioctlsocket( s, cmd, argp );
1602 /***********************************************************************
1603 * listen() (WSOCK32.13)
1605 INT WINAPI WSOCK32_listen(SOCKET s, INT backlog)
1607 int fd = _get_sock_fd(s);
1609 TRACE("socket %04x, backlog %d\n", s, backlog);
1610 if (fd != -1)
1612 if (listen(fd, backlog) == 0)
1614 close(fd);
1615 _enable_event(s, FD_ACCEPT,
1616 WS_FD_LISTENING,
1617 WS_FD_CONNECT|WS_FD_CONNECTED);
1618 return 0;
1620 SetLastError(wsaErrno());
1622 else SetLastError(WSAENOTSOCK);
1623 return SOCKET_ERROR;
1626 /***********************************************************************
1627 * listen() (WINSOCK.13)
1629 INT16 WINAPI WINSOCK_listen16(SOCKET16 s, INT16 backlog)
1631 return (INT16)WSOCK32_listen( s, backlog );
1635 /***********************************************************************
1636 * recv() (WSOCK32.16)
1638 INT WINAPI WSOCK32_recv(SOCKET s, char *buf, INT len, INT flags)
1640 int fd = _get_sock_fd(s);
1642 TRACE("socket %04x, buf %8x, len %d, flags %d\n", s, (unsigned)buf, len, flags);
1644 if (fd != -1)
1646 INT length;
1648 if (_is_blocking(s))
1650 /* block here */
1651 /* FIXME: OOB and exceptfds? */
1652 do_block(fd, 1);
1654 if ((length = recv(fd, buf, len, flags)) >= 0)
1656 TRACE(" -> %i bytes\n", length);
1658 close(fd);
1659 _enable_event(s, FD_READ, 0, 0);
1660 return length;
1662 SetLastError(wsaErrno());
1663 close(fd);
1665 else SetLastError(WSAENOTSOCK);
1666 WARN(" -> ERROR\n");
1667 return SOCKET_ERROR;
1670 /***********************************************************************
1671 * recv() (WINSOCK.16)
1673 INT16 WINAPI WINSOCK_recv16(SOCKET16 s, char *buf, INT16 len, INT16 flags)
1675 return (INT16)WSOCK32_recv( s, buf, len, flags );
1679 /***********************************************************************
1680 * recvfrom() (WSOCK32.17)
1682 INT WINAPI WSOCK32_recvfrom(SOCKET s, char *buf, INT len, INT flags,
1683 struct sockaddr *from, INT *fromlen32)
1685 #ifdef HAVE_IPX
1686 struct ws_sockaddr_ipx* from2 = (struct ws_sockaddr_ipx *)from;
1687 #endif
1688 int fd = _get_sock_fd(s);
1690 TRACE("socket %04x, ptr %08x, len %d, flags %d\n", s, (unsigned)buf, len, flags);
1691 #if DEBUG_SOCKADDR
1692 if( from ) dump_sockaddr(from);
1693 else DPRINTF("from = NULL\n");
1694 #endif
1696 if (fd != -1)
1698 int length;
1700 if (_is_blocking(s))
1702 /* block here */
1703 /* FIXME: OOB and exceptfds */
1704 do_block(fd, 1);
1706 if ((length = recvfrom(fd, buf, len, flags, from, fromlen32)) >= 0)
1708 TRACE(" -> %i bytes\n", length);
1710 #ifdef HAVE_IPX
1711 if (from && ((struct sockaddr_ipx *)from)->sipx_family == AF_IPX) {
1712 from = (struct sockaddr *)
1713 malloc(fromlen32 ? *fromlen32 : sizeof(*from2));
1714 memcpy(from, from2, fromlen32 ? *fromlen32 : sizeof(*from2));
1715 from2->sipx_family = WS_AF_IPX;
1716 from2->sipx_network = ((struct sockaddr_ipx *)from)->sipx_network;
1717 from2->sipx_port = ((struct sockaddr_ipx *)from)->sipx_port;
1718 memcpy(from2->sipx_node,
1719 ((struct sockaddr_ipx *)from)->sipx_node, IPX_NODE_LEN);
1720 free(from);
1722 #endif
1723 close(fd);
1724 _enable_event(s, FD_READ, 0, 0);
1725 return (INT16)length;
1727 SetLastError(wsaErrno());
1728 close(fd);
1730 else SetLastError(WSAENOTSOCK);
1731 WARN(" -> ERROR\n");
1732 #ifdef HAVE_IPX
1733 if (from && ((struct sockaddr_ipx *)from)->sipx_family == AF_IPX) {
1734 from = (struct sockaddr *)
1735 malloc(fromlen32 ? *fromlen32 : sizeof(*from2));
1736 memcpy(from, from2, fromlen32 ? *fromlen32 : sizeof(*from2));
1737 from2->sipx_family = WS_AF_IPX;
1738 from2->sipx_network = ((struct sockaddr_ipx *)from)->sipx_network;
1739 from2->sipx_port = ((struct sockaddr_ipx *)from)->sipx_port;
1740 memcpy(from2->sipx_node,
1741 ((struct sockaddr_ipx *)from)->sipx_node, IPX_NODE_LEN);
1742 free(from);
1744 #endif
1745 return SOCKET_ERROR;
1748 /***********************************************************************
1749 * recvfrom() (WINSOCK.17)
1751 INT16 WINAPI WINSOCK_recvfrom16(SOCKET16 s, char *buf, INT16 len, INT16 flags,
1752 struct sockaddr *from, INT16 *fromlen16)
1754 INT fromlen32;
1755 INT *p = &fromlen32;
1756 INT retVal;
1758 if( fromlen16 ) fromlen32 = *fromlen16; else p = NULL;
1759 retVal = WSOCK32_recvfrom( s, buf, len, flags, from, p );
1760 if( fromlen16 ) *fromlen16 = fromlen32;
1761 return (INT16)retVal;
1764 /***********************************************************************
1765 * select() (WINSOCK.18)(WSOCK32.18)
1767 static INT __ws_select( BOOL b32, void *ws_readfds, void *ws_writefds, void *ws_exceptfds,
1768 struct timeval *timeout )
1770 int highfd = 0;
1771 fd_set readfds, writefds, exceptfds;
1772 fd_set *p_read, *p_write, *p_except;
1773 int readfd[FD_SETSIZE], writefd[FD_SETSIZE], exceptfd[FD_SETSIZE];
1775 TRACE("read %p, write %p, excp %p\n", ws_readfds, ws_writefds, ws_exceptfds);
1777 p_read = fd_set_import(&readfds, ws_readfds, &highfd, readfd, b32);
1778 p_write = fd_set_import(&writefds, ws_writefds, &highfd, writefd, b32);
1779 p_except = fd_set_import(&exceptfds, ws_exceptfds, &highfd, exceptfd, b32);
1781 if( (highfd = select(highfd + 1, p_read, p_write, p_except, timeout)) > 0 )
1783 fd_set_export(&readfds, p_except, ws_readfds, readfd, b32);
1784 fd_set_export(&writefds, p_except, ws_writefds, writefd, b32);
1786 if (p_except && ws_exceptfds)
1788 #define wsfds16 ((ws_fd_set16*)ws_exceptfds)
1789 #define wsfds32 ((ws_fd_set32*)ws_exceptfds)
1790 int i, j, count = (b32) ? wsfds32->fd_count : wsfds16->fd_count;
1792 for (i = j = 0; i < count; i++)
1794 int fd = exceptfd[i];
1795 if( fd >= 0 && FD_ISSET(fd, &exceptfds) )
1797 if( b32 )
1798 wsfds32->fd_array[j++] = wsfds32->fd_array[i];
1799 else
1800 wsfds16->fd_array[j++] = wsfds16->fd_array[i];
1802 if( fd >= 0 ) close(fd);
1803 exceptfd[i] = -1;
1805 if( b32 )
1806 wsfds32->fd_count = j;
1807 else
1808 wsfds16->fd_count = j;
1809 #undef wsfds32
1810 #undef wsfds16
1812 return highfd;
1814 fd_set_unimport(ws_readfds, readfd, b32);
1815 fd_set_unimport(ws_writefds, writefd, b32);
1816 fd_set_unimport(ws_exceptfds, exceptfd, b32);
1817 if( ws_readfds ) ((ws_fd_set32*)ws_readfds)->fd_count = 0;
1818 if( ws_writefds ) ((ws_fd_set32*)ws_writefds)->fd_count = 0;
1819 if( ws_exceptfds ) ((ws_fd_set32*)ws_exceptfds)->fd_count = 0;
1821 if( highfd == 0 ) return 0;
1822 SetLastError(wsaErrno());
1823 return SOCKET_ERROR;
1826 INT16 WINAPI WINSOCK_select16(INT16 nfds, ws_fd_set16 *ws_readfds,
1827 ws_fd_set16 *ws_writefds, ws_fd_set16 *ws_exceptfds,
1828 struct timeval *timeout)
1830 return (INT16)__ws_select( FALSE, ws_readfds, ws_writefds, ws_exceptfds, timeout );
1833 INT WINAPI WSOCK32_select(INT nfds, ws_fd_set32 *ws_readfds,
1834 ws_fd_set32 *ws_writefds, ws_fd_set32 *ws_exceptfds,
1835 struct timeval *timeout)
1837 /* struct timeval is the same for both 32- and 16-bit code */
1838 return (INT)__ws_select( TRUE, ws_readfds, ws_writefds, ws_exceptfds, timeout );
1842 /***********************************************************************
1843 * send() (WSOCK32.19)
1845 INT WINAPI WSOCK32_send(SOCKET s, char *buf, INT len, INT flags)
1847 int fd = _get_sock_fd(s);
1849 TRACE("socket %04x, ptr %p, length %d, flags %d\n", s, buf, len, flags);
1850 if (fd != -1)
1852 int length;
1854 if (_is_blocking(s))
1856 /* block here */
1857 /* FIXME: exceptfds */
1858 do_block(fd, 2);
1860 if ((length = send(fd, buf, len, flags)) < 0 )
1862 SetLastError(wsaErrno());
1863 if( GetLastError() == WSAEWOULDBLOCK )
1864 _enable_event(s, FD_WRITE, 0, 0);
1866 else
1868 close(fd);
1869 return (INT16)length;
1871 close(fd);
1873 else SetLastError(WSAENOTSOCK);
1874 return SOCKET_ERROR;
1877 /***********************************************************************
1878 * send() (WINSOCK.19)
1880 INT16 WINAPI WINSOCK_send16(SOCKET16 s, char *buf, INT16 len, INT16 flags)
1882 return WSOCK32_send( s, buf, len, flags );
1885 /***********************************************************************
1886 * sendto() (WSOCK32.20)
1888 INT WINAPI WSOCK32_sendto(SOCKET s, char *buf, INT len, INT flags,
1889 struct sockaddr *to, INT tolen)
1891 #ifdef HAVE_IPX
1892 struct ws_sockaddr_ipx* to2 = (struct ws_sockaddr_ipx *)to;
1893 #endif
1894 int fd = _get_sock_fd(s);
1896 TRACE("socket %04x, ptr %p, length %d, flags %d\n", s, buf, len, flags);
1897 if (fd != -1)
1899 INT length;
1901 if (to && ((struct ws_sockaddr_ipx *)to)->sipx_family == WS_AF_PUP)
1902 ((struct ws_sockaddr_ipx *)to)->sipx_family = AF_UNSPEC;
1903 #ifdef HAVE_IPX
1904 else if (to &&
1905 ((struct ws_sockaddr_ipx *)to)->sipx_family == WS_AF_IPX)
1907 to = (struct sockaddr *) malloc(sizeof(struct sockaddr_ipx));
1908 memset(to, '\0', sizeof(struct sockaddr_ipx));
1909 ((struct sockaddr_ipx *)to)->sipx_family = AF_IPX;
1910 ((struct sockaddr_ipx *)to)->sipx_port = to2->sipx_port;
1911 ((struct sockaddr_ipx *)to)->sipx_network = to2->sipx_network;
1912 memcpy(((struct sockaddr_ipx *)to)->sipx_node,
1913 to2->sipx_node, IPX_NODE_LEN);
1914 tolen = sizeof(struct sockaddr_ipx);
1916 #endif
1917 if (_is_blocking(s))
1919 /* block here */
1920 /* FIXME: exceptfds */
1921 do_block(fd, 2);
1923 if ((length = sendto(fd, buf, len, flags, to, tolen)) < 0 )
1925 SetLastError(wsaErrno());
1926 if( GetLastError() == WSAEWOULDBLOCK )
1927 _enable_event(s, FD_WRITE, 0, 0);
1929 else {
1930 #ifdef HAVE_IPX
1931 if (to && ((struct sockaddr_ipx *)to)->sipx_family == AF_IPX) {
1932 free(to);
1934 #endif
1935 close(fd);
1936 return length;
1938 close(fd);
1940 else SetLastError(WSAENOTSOCK);
1941 #ifdef HAVE_IPX
1942 if (to && ((struct sockaddr_ipx *)to)->sipx_family == AF_IPX) {
1943 free(to);
1945 #endif
1946 return SOCKET_ERROR;
1949 /***********************************************************************
1950 * sendto() (WINSOCK.20)
1952 INT16 WINAPI WINSOCK_sendto16(SOCKET16 s, char *buf, INT16 len, INT16 flags,
1953 struct sockaddr *to, INT16 tolen)
1955 return (INT16)WSOCK32_sendto( s, buf, len, flags, to, tolen );
1958 /***********************************************************************
1959 * setsockopt() (WSOCK32.21)
1961 INT WINAPI WSOCK32_setsockopt(SOCKET16 s, INT level, INT optname,
1962 char *optval, INT optlen)
1964 int fd = _get_sock_fd(s);
1966 TRACE("socket %04x, lev %d, opt 0x%x, ptr %08x, len %d\n",
1967 s, level, optname, (int) optval, optlen);
1968 if (fd != -1)
1970 struct linger linger;
1971 int woptval;
1973 /* Is a privileged and useless operation, so we don't. */
1974 if ((optname == WS_SO_DEBUG) && (level == WS_SOL_SOCKET)) {
1975 FIXME("(%d,SOL_SOCKET,SO_DEBUG,%p(%ld)) attempted (is privileged). Ignoring.\n",s,optval,*(DWORD*)optval);
1976 return 0;
1979 if(optname == WS_SO_DONTLINGER && level == WS_SOL_SOCKET) {
1980 /* This is unique to WinSock and takes special conversion */
1981 linger.l_onoff = *((int*)optval) ? 0: 1;
1982 linger.l_linger = 0;
1983 optname=SO_LINGER;
1984 optval = (char*)&linger;
1985 optlen = sizeof(struct linger);
1986 level = SOL_SOCKET;
1987 }else{
1988 if (!convert_sockopt(&level, &optname)) {
1989 SetLastError(WSAENOPROTOOPT);
1990 close(fd);
1991 return SOCKET_ERROR;
1993 if (optname == SO_LINGER && optval) {
1994 /* yes, uses unsigned short in both win16/win32 */
1995 linger.l_onoff = ((UINT16*)optval)[0];
1996 linger.l_linger = ((UINT16*)optval)[1];
1997 /* FIXME: what is documented behavior if SO_LINGER optval
1998 is null?? */
1999 optval = (char*)&linger;
2000 optlen = sizeof(struct linger);
2001 } else if (optlen < sizeof(int)){
2002 woptval= *((INT16 *) optval);
2003 optval= (char*) &woptval;
2004 optlen=sizeof(int);
2007 if(optname == SO_RCVBUF && *(int*)optval < 2048) {
2008 WARN("SO_RCVBF for %d bytes is too small: ignored\n", *(int*)optval );
2009 close( fd);
2010 return 0;
2013 if (setsockopt(fd, level, optname, optval, optlen) == 0)
2015 close(fd);
2016 return 0;
2018 SetLastError(wsaErrno());
2019 close(fd);
2021 else SetLastError(WSAENOTSOCK);
2022 return SOCKET_ERROR;
2025 /***********************************************************************
2026 * setsockopt() (WINSOCK.21)
2028 INT16 WINAPI WINSOCK_setsockopt16(SOCKET16 s, INT16 level, INT16 optname,
2029 char *optval, INT16 optlen)
2031 if( !optval ) return SOCKET_ERROR;
2032 return (INT16)WSOCK32_setsockopt( s, (UINT16)level, optname, optval, optlen );
2036 /***********************************************************************
2037 * shutdown() (WSOCK32.22)
2039 INT WINAPI WSOCK32_shutdown(SOCKET s, INT how)
2041 int fd = _get_sock_fd(s);
2043 TRACE("socket %04x, how %i\n", s, how );
2044 if (fd != -1)
2046 switch( how )
2048 case 0: /* drop receives */
2049 _enable_event(s, 0, 0, WS_FD_READ);
2050 #ifdef SHUT_RD
2051 how = SHUT_RD;
2052 #endif
2053 break;
2055 case 1: /* drop sends */
2056 _enable_event(s, 0, 0, WS_FD_WRITE);
2057 #ifdef SHUT_WR
2058 how = SHUT_WR;
2059 #endif
2060 break;
2062 case 2: /* drop all */
2063 #ifdef SHUT_RDWR
2064 how = SHUT_RDWR;
2065 #endif
2066 default:
2067 WSAAsyncSelect( s, 0, 0, 0 );
2068 break;
2071 if (shutdown(fd, how) == 0)
2073 if( how > 1 )
2075 _enable_event(s, 0, 0, WS_FD_CONNECTED|WS_FD_LISTENING);
2077 close(fd);
2078 return 0;
2080 SetLastError(wsaErrno());
2081 close(fd);
2083 else SetLastError(WSAENOTSOCK);
2084 return SOCKET_ERROR;
2087 /***********************************************************************
2088 * shutdown() (WINSOCK.22)
2090 INT16 WINAPI WINSOCK_shutdown16(SOCKET16 s, INT16 how)
2092 return (INT16)WSOCK32_shutdown( s, how );
2096 /***********************************************************************
2097 * socket() (WSOCK32.23)
2099 SOCKET WINAPI WSOCK32_socket(INT af, INT type, INT protocol)
2101 SOCKET ret;
2103 TRACE("af=%d type=%d protocol=%d\n", af, type, protocol);
2105 /* check the socket family */
2106 switch(af)
2108 #ifdef HAVE_IPX
2109 case WS_AF_IPX: af = AF_IPX;
2110 #endif
2111 case AF_INET:
2112 case AF_UNSPEC: break;
2113 default: SetLastError(WSAEAFNOSUPPORT);
2114 return INVALID_SOCKET;
2117 /* check the socket type */
2118 switch(type)
2120 case SOCK_STREAM:
2121 case SOCK_DGRAM:
2122 case SOCK_RAW: break;
2123 default: SetLastError(WSAESOCKTNOSUPPORT);
2124 return INVALID_SOCKET;
2127 /* check the protocol type */
2128 if ( protocol < 0 ) /* don't support negative values */
2129 { SetLastError(WSAEPROTONOSUPPORT); return INVALID_SOCKET; }
2131 if ( af == AF_UNSPEC) /* did they not specify the address family? */
2132 switch(protocol)
2134 case IPPROTO_TCP:
2135 if (type == SOCK_STREAM) { af = AF_INET; break; }
2136 case IPPROTO_UDP:
2137 if (type == SOCK_DGRAM) { af = AF_INET; break; }
2138 default: SetLastError(WSAEPROTOTYPE); return INVALID_SOCKET;
2141 SERVER_START_REQ
2143 struct create_socket_request *req = server_alloc_req( sizeof(*req), 0 );
2144 req->family = af;
2145 req->type = type;
2146 req->protocol = protocol;
2147 req->access = GENERIC_READ|GENERIC_WRITE|SYNCHRONIZE;
2148 req->inherit = TRUE;
2149 sock_server_call( REQ_CREATE_SOCKET );
2150 ret = (SOCKET)req->handle;
2152 SERVER_END_REQ;
2153 if (ret)
2155 TRACE("\tcreated %04x\n", ret );
2156 return ret;
2159 if (GetLastError() == WSAEACCES) /* raw socket denied */
2161 if (type == SOCK_RAW)
2162 MESSAGE("WARNING: Trying to create a socket of type SOCK_RAW, will fail unless running as root\n");
2163 else
2164 MESSAGE("WS_SOCKET: not enough privileges to create socket, try running as root\n");
2165 SetLastError(WSAESOCKTNOSUPPORT);
2168 WARN("\t\tfailed!\n");
2169 return INVALID_SOCKET;
2172 /***********************************************************************
2173 * socket() (WINSOCK.23)
2175 SOCKET16 WINAPI WINSOCK_socket16(INT16 af, INT16 type, INT16 protocol)
2177 return (SOCKET16)WSOCK32_socket( af, type, protocol );
2181 /* ----------------------------------- DNS services
2183 * IMPORTANT: 16-bit API structures have SEGPTR pointers inside them.
2184 * Also, we have to use wsock32 stubs to convert structures and
2185 * error codes from Unix to WSA, hence there is no direct mapping in
2186 * the relay32/wsock32.spec.
2189 static char* NULL_STRING = "NULL";
2191 /***********************************************************************
2192 * gethostbyaddr() (WINSOCK.51)(WSOCK32.51)
2194 static WIN_hostent* __ws_gethostbyaddr(const char *addr, int len, int type, int dup_flag)
2196 WIN_hostent *retval = NULL;
2198 struct hostent* host;
2199 #if HAVE_LINUX_GETHOSTBYNAME_R_6
2200 char *extrabuf;
2201 int ebufsize=1024;
2202 struct hostent hostentry;
2203 int locerr=ENOBUFS;
2204 host = NULL;
2205 extrabuf=HeapAlloc(GetProcessHeap(),0,ebufsize) ;
2206 while(extrabuf) {
2207 int res = gethostbyaddr_r(addr, len, type,
2208 &hostentry, extrabuf, ebufsize, &host, &locerr);
2209 if( res != ERANGE) break;
2210 ebufsize *=2;
2211 extrabuf=HeapReAlloc(GetProcessHeap(),0,extrabuf,ebufsize) ;
2213 if (!host) SetLastError((locerr < 0) ? wsaErrno() : wsaHerrno(locerr));
2214 #else
2215 EnterCriticalSection( &csWSgetXXXbyYYY );
2216 host = gethostbyaddr(addr, len, type);
2217 if (!host) SetLastError((h_errno < 0) ? wsaErrno() : wsaHerrno(h_errno));
2218 #endif
2219 if( host != NULL )
2221 if( WS_dup_he(host, dup_flag) )
2222 retval = he_buffer;
2223 else
2224 SetLastError(WSAENOBUFS);
2226 #ifdef HAVE_LINUX_GETHOSTBYNAME_R_6
2227 HeapFree(GetProcessHeap(),0,extrabuf);
2228 #else
2229 LeaveCriticalSection( &csWSgetXXXbyYYY );
2230 #endif
2231 return retval;
2234 SEGPTR WINAPI WINSOCK_gethostbyaddr16(const char *addr, INT16 len, INT16 type)
2236 WIN_hostent* retval;
2237 TRACE("ptr %08x, len %d, type %d\n",
2238 (unsigned) addr, len, type);
2239 retval = __ws_gethostbyaddr( addr, len, type, WS_DUP_SEGPTR );
2240 return SEGPTR_GET(retval);
2243 WIN_hostent* WINAPI WSOCK32_gethostbyaddr(const char *addr, INT len,
2244 INT type)
2246 TRACE("ptr %08x, len %d, type %d\n",
2247 (unsigned) addr, len, type);
2248 return __ws_gethostbyaddr(addr, len, type, WS_DUP_LINEAR);
2251 /***********************************************************************
2252 * gethostbyname() (WINSOCK.52)(WSOCK32.52)
2254 static WIN_hostent * __ws_gethostbyname(const char *name, int dup_flag)
2256 WIN_hostent *retval = NULL;
2257 struct hostent* host;
2258 #ifdef HAVE_LINUX_GETHOSTBYNAME_R_6
2259 char *extrabuf;
2260 int ebufsize=1024;
2261 struct hostent hostentry;
2262 int locerr = ENOBUFS;
2263 host = NULL;
2264 extrabuf=HeapAlloc(GetProcessHeap(),0,ebufsize) ;
2265 while(extrabuf) {
2266 int res = gethostbyname_r(name, &hostentry, extrabuf, ebufsize, &host, &locerr);
2267 if( res != ERANGE) break;
2268 ebufsize *=2;
2269 extrabuf=HeapReAlloc(GetProcessHeap(),0,extrabuf,ebufsize) ;
2271 if (!host) SetLastError((locerr < 0) ? wsaErrno() : wsaHerrno(locerr));
2272 #else
2273 EnterCriticalSection( &csWSgetXXXbyYYY );
2274 host = gethostbyname(name);
2275 if (!host) SetLastError((h_errno < 0) ? wsaErrno() : wsaHerrno(h_errno));
2276 #endif
2277 if( host != NULL )
2279 if( WS_dup_he(host, dup_flag) )
2280 retval = he_buffer;
2281 else SetLastError(WSAENOBUFS);
2283 #ifdef HAVE_LINUX_GETHOSTBYNAME_R_6
2284 HeapFree(GetProcessHeap(),0,extrabuf);
2285 #else
2286 LeaveCriticalSection( &csWSgetXXXbyYYY );
2287 #endif
2288 return retval;
2291 SEGPTR WINAPI WINSOCK_gethostbyname16(const char *name)
2293 WIN_hostent* retval;
2294 TRACE("%s\n", (name)?name:NULL_STRING);
2295 retval = __ws_gethostbyname( name, WS_DUP_SEGPTR );
2296 return SEGPTR_GET(retval);
2299 WIN_hostent* WINAPI WSOCK32_gethostbyname(const char* name)
2301 TRACE("%s\n", (name)?name:NULL_STRING);
2302 return __ws_gethostbyname( name, WS_DUP_LINEAR );
2306 /***********************************************************************
2307 * getprotobyname() (WINSOCK.53)(WSOCK32.53)
2309 static WIN_protoent* __ws_getprotobyname(const char *name, int dup_flag)
2311 WIN_protoent* retval = NULL;
2313 struct protoent* proto;
2314 EnterCriticalSection( &csWSgetXXXbyYYY );
2315 if( (proto = getprotobyname(name)) != NULL )
2317 if( WS_dup_pe(proto, dup_flag) )
2318 retval = pe_buffer;
2319 else SetLastError(WSAENOBUFS);
2321 else {
2322 MESSAGE("protocol %s not found; You might want to add "
2323 "this to /etc/protocols\n", debugstr_a(name) );
2324 SetLastError(WSANO_DATA);
2326 LeaveCriticalSection( &csWSgetXXXbyYYY );
2327 return retval;
2330 SEGPTR WINAPI WINSOCK_getprotobyname16(const char *name)
2332 WIN_protoent* retval;
2333 TRACE("%s\n", (name)?name:NULL_STRING);
2334 retval = __ws_getprotobyname(name, WS_DUP_SEGPTR);
2335 return SEGPTR_GET(retval);
2338 WIN_protoent* WINAPI WSOCK32_getprotobyname(const char* name)
2340 TRACE("%s\n", (name)?name:NULL_STRING);
2341 return __ws_getprotobyname(name, WS_DUP_LINEAR);
2345 /***********************************************************************
2346 * getprotobynumber() (WINSOCK.54)(WSOCK32.54)
2348 static WIN_protoent* __ws_getprotobynumber(int number, int dup_flag)
2350 WIN_protoent* retval = NULL;
2351 struct protoent* proto;
2352 EnterCriticalSection( &csWSgetXXXbyYYY );
2353 if( (proto = getprotobynumber(number)) != NULL )
2355 if( WS_dup_pe(proto, dup_flag) )
2356 retval = pe_buffer;
2357 else SetLastError(WSAENOBUFS);
2359 else {
2360 MESSAGE("protocol number %d not found; You might want to add "
2361 "this to /etc/protocols\n", number );
2362 SetLastError(WSANO_DATA);
2364 LeaveCriticalSection( &csWSgetXXXbyYYY );
2365 return retval;
2368 SEGPTR WINAPI WINSOCK_getprotobynumber16(INT16 number)
2370 WIN_protoent* retval;
2371 TRACE("%i\n", number);
2372 retval = __ws_getprotobynumber(number, WS_DUP_SEGPTR);
2373 return SEGPTR_GET(retval);
2376 WIN_protoent* WINAPI WSOCK32_getprotobynumber(INT number)
2378 TRACE("%i\n", number);
2379 return __ws_getprotobynumber(number, WS_DUP_LINEAR);
2383 /***********************************************************************
2384 * getservbyname() (WINSOCK.55)(WSOCK32.55)
2386 static WIN_servent* __ws_getservbyname(const char *name, const char *proto, int dup_flag)
2388 WIN_servent* retval = NULL;
2389 struct servent* serv;
2390 int i = wsi_strtolo( name, proto );
2392 if( i ) {
2393 EnterCriticalSection( &csWSgetXXXbyYYY );
2394 serv = getservbyname(local_buffer,
2395 proto ? (local_buffer + i) : NULL);
2396 if( serv != NULL )
2398 if( WS_dup_se(serv, dup_flag) )
2399 retval = se_buffer;
2400 else SetLastError(WSAENOBUFS);
2402 else {
2403 MESSAGE("service %s protocol %s not found; You might want to add "
2404 "this to /etc/services\n", debugstr_a(local_buffer),
2405 proto ? debugstr_a(local_buffer+i):"*");
2406 SetLastError(WSANO_DATA);
2408 LeaveCriticalSection( &csWSgetXXXbyYYY );
2410 else SetLastError(WSAENOBUFS);
2411 return retval;
2414 SEGPTR WINAPI WINSOCK_getservbyname16(const char *name, const char *proto)
2416 WIN_servent* retval;
2417 TRACE("'%s', '%s'\n",
2418 (name)?name:NULL_STRING, (proto)?proto:NULL_STRING);
2419 retval = __ws_getservbyname(name, proto, WS_DUP_SEGPTR);
2420 return SEGPTR_GET(retval);
2423 WIN_servent* WINAPI WSOCK32_getservbyname(const char *name, const char *proto)
2425 TRACE("'%s', '%s'\n",
2426 (name)?name:NULL_STRING, (proto)?proto:NULL_STRING);
2427 return __ws_getservbyname(name, proto, WS_DUP_LINEAR);
2431 /***********************************************************************
2432 * getservbyport() (WINSOCK.56)(WSOCK32.56)
2434 static WIN_servent* __ws_getservbyport(int port, const char* proto, int dup_flag)
2436 WIN_servent* retval = NULL;
2437 struct servent* serv;
2438 if (!proto || wsi_strtolo( proto, NULL )) {
2439 EnterCriticalSection( &csWSgetXXXbyYYY );
2440 if( (serv = getservbyport(port, (proto) ? local_buffer : NULL)) != NULL ) {
2441 if( WS_dup_se(serv, dup_flag) )
2442 retval = se_buffer;
2443 else SetLastError(WSAENOBUFS);
2445 else {
2446 MESSAGE("service on port %lu protocol %s not found; You might want to add "
2447 "this to /etc/services\n", (unsigned long)ntohl(port),
2448 proto ? debugstr_a(local_buffer) : "*");
2449 SetLastError(WSANO_DATA);
2451 LeaveCriticalSection( &csWSgetXXXbyYYY );
2453 else SetLastError(WSAENOBUFS);
2454 return retval;
2457 SEGPTR WINAPI WINSOCK_getservbyport16(INT16 port, const char *proto)
2459 WIN_servent* retval;
2460 TRACE("%d (i.e. port %d), '%s'\n",
2461 (int)port, (int)ntohl(port), (proto)?proto:NULL_STRING);
2462 retval = __ws_getservbyport(port, proto, WS_DUP_SEGPTR);
2463 return SEGPTR_GET(retval);
2466 WIN_servent* WINAPI WSOCK32_getservbyport(INT port, const char *proto)
2468 TRACE("%d (i.e. port %d), '%s'\n",
2469 (int)port, (int)ntohl(port), (proto)?proto:NULL_STRING);
2470 return __ws_getservbyport(port, proto, WS_DUP_LINEAR);
2474 /***********************************************************************
2475 * gethostname() (WSOCK32.57)
2477 INT WINAPI WSOCK32_gethostname(char *name, INT namelen)
2479 TRACE("name %p, len %d\n", name, namelen);
2481 if (gethostname(name, namelen) == 0)
2483 TRACE("<- '%s'\n", name);
2484 return 0;
2486 SetLastError((errno == EINVAL) ? WSAEFAULT : wsaErrno());
2487 TRACE("<- ERROR !\n");
2488 return SOCKET_ERROR;
2491 /***********************************************************************
2492 * gethostname() (WINSOCK.57)
2494 INT16 WINAPI WINSOCK_gethostname16(char *name, INT16 namelen)
2496 return (INT16)WSOCK32_gethostname(name, namelen);
2500 /* ------------------------------------- Windows sockets extensions -- *
2502 * ------------------------------------------------------------------- */
2504 /***********************************************************************
2505 * WSAEnumNetworkEvents
2507 int WINAPI WSAEnumNetworkEvents(SOCKET s, WSAEVENT hEvent, LPWSANETWORKEVENTS lpEvent)
2509 int ret;
2511 TRACE("%08x, hEvent %08x, lpEvent %08x\n", s, hEvent, (unsigned)lpEvent );
2513 SERVER_START_REQ
2515 struct get_socket_event_request *req = server_alloc_req( sizeof(*req),
2516 sizeof(lpEvent->iErrorCode) );
2517 req->handle = s;
2518 req->service = TRUE;
2519 req->s_event = 0;
2520 req->c_event = hEvent;
2521 ret = sock_server_call( REQ_GET_SOCKET_EVENT );
2522 lpEvent->lNetworkEvents = req->pmask;
2523 memcpy(lpEvent->iErrorCode, server_data_ptr(req), server_data_size(req) );
2525 SERVER_END_REQ;
2526 if (!ret) return 0;
2527 SetLastError(WSAEINVAL);
2528 return SOCKET_ERROR;
2531 /***********************************************************************
2532 * WSAEventSelect
2534 int WINAPI WSAEventSelect(SOCKET s, WSAEVENT hEvent, LONG lEvent)
2536 int ret;
2538 TRACE("%08x, hEvent %08x, event %08x\n", s, hEvent, (unsigned)lEvent );
2540 SERVER_START_REQ
2542 struct set_socket_event_request *req = server_alloc_req( sizeof(*req), 0 );
2543 req->handle = s;
2544 req->mask = lEvent;
2545 req->event = hEvent;
2546 ret = sock_server_call( REQ_SET_SOCKET_EVENT );
2548 SERVER_END_REQ;
2549 if (!ret) return 0;
2550 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 unsigned int i, pmask, orphan = FALSE;
2562 int errors[FD_MAX_EVENTS];
2564 TRACE("socket %08x, event %08x\n", info->sock, info->event);
2565 SetLastError(0);
2566 SERVER_START_REQ
2568 struct get_socket_event_request *req = server_alloc_req( sizeof(*req), sizeof(errors) );
2569 req->handle = info->sock;
2570 req->service = TRUE;
2571 req->s_event = info->event; /* <== avoid race conditions */
2572 req->c_event = info->event;
2573 sock_server_call( REQ_GET_SOCKET_EVENT );
2574 pmask = req->pmask;
2575 memcpy( errors, server_data_ptr(req), server_data_size(req) );
2577 SERVER_END_REQ;
2578 if ( (GetLastError() == WSAENOTSOCK) || (GetLastError() == WSAEINVAL) )
2580 /* orphaned event (socket closed or something) */
2581 pmask = WS_FD_SERVEVENT;
2582 orphan = TRUE;
2585 /* check for accepted sockets that needs to inherit WSAAsyncSelect */
2586 if (pmask & WS_FD_SERVEVENT) {
2587 int q;
2588 for (q=0; q<WS_ACCEPT_QUEUE; q++)
2589 if (accept_old[q] == info->sock) {
2590 /* there's only one service thread per process, no lock necessary */
2591 HANDLE as = accept_new[q];
2592 if (as) {
2593 accept_new[q] = 0;
2594 accept_old[q] = 0;
2595 WSAAsyncSelect(as, info->hWnd, info->uMsg, info->lEvent);
2598 pmask &= ~WS_FD_SERVEVENT;
2600 /* dispatch network events */
2601 for (i=0; i<FD_MAX_EVENTS; i++)
2602 if (pmask & (1<<i)) {
2603 TRACE("post: event bit %d, error %d\n", i, errors[i]);
2604 PostMessageA(info->hWnd, info->uMsg, info->sock,
2605 WSAMAKESELECTREPLY(1<<i, errors[i]));
2607 /* cleanup */
2608 if (orphan)
2610 TRACE("orphaned event, self-destructing\n");
2611 /* SERVICE_Delete closes the event object */
2612 SERVICE_Delete( info->service );
2613 WS_FREE(info);
2617 /**********************************************************************/
2619 INT WINAPI WSAAsyncSelect(SOCKET s, HWND hWnd, UINT uMsg, LONG lEvent)
2621 int fd = _get_sock_fd(s);
2623 TRACE("%04x, hWnd %04x, uMsg %08x, event %08x\n",
2624 (SOCKET16)s, (HWND16)hWnd, uMsg, (unsigned)lEvent );
2625 if (fd != -1)
2627 close(fd);
2628 if( lEvent )
2630 ws_select_info *info = (ws_select_info*)WS_ALLOC(sizeof(ws_select_info));
2631 if( info )
2633 HANDLE hObj = CreateEventA( NULL, TRUE, FALSE, NULL );
2634 INT err;
2636 info->sock = s;
2637 info->event = hObj;
2638 info->hWnd = hWnd;
2639 info->uMsg = uMsg;
2640 info->lEvent = lEvent;
2641 info->service = SERVICE_AddObject( hObj, WINSOCK_DoAsyncEvent, (ULONG_PTR)info );
2643 err = WSAEventSelect( s, hObj, lEvent | WS_FD_SERVEVENT );
2644 if (err) {
2645 /* SERVICE_Delete closes the event object */
2646 SERVICE_Delete( info->service );
2647 WS_FREE(info);
2648 return err;
2651 return 0; /* success */
2653 else SetLastError(WSAENOBUFS);
2655 else
2657 WSAEventSelect(s, 0, 0);
2658 return 0;
2661 else SetLastError(WSAEINVAL);
2662 return SOCKET_ERROR;
2665 /**********************************************************************/
2667 INT16 WINAPI WSAAsyncSelect16(SOCKET16 s, HWND16 hWnd, UINT16 wMsg, LONG lEvent)
2669 return (INT16)WSAAsyncSelect( s, hWnd, wMsg, lEvent );
2672 /***********************************************************************
2673 * WSARecvEx16() (WINSOCK.1107)
2675 * See description for WSARecvEx()
2677 INT16 WINAPI WSARecvEx16(SOCKET16 s, char *buf, INT16 len, INT16 *flags) {
2678 FIXME("(WSARecvEx16) partial packet return value not set \n");
2680 return WINSOCK_recv16(s, buf, len, *flags);
2684 /***********************************************************************
2685 * WSACreateEvent() (WS2_32.???)
2688 WSAEVENT WINAPI WSACreateEvent(void)
2690 /* Create a manual-reset event, with initial state: unsignealed */
2691 TRACE("\n");
2693 return CreateEventA(NULL, TRUE, FALSE, NULL);
2696 /***********************************************************************
2697 * WSACloseEvent() (WS2_32.???)
2700 BOOL WINAPI WSACloseEvent(WSAEVENT event)
2702 TRACE ("event=0x%x\n", event);
2704 return CloseHandle(event);
2707 /***********************************************************************
2708 * WSASocketA() (WS2_32.???)
2711 SOCKET WINAPI WSASocketA(int af, int type, int protocol,
2712 LPWSAPROTOCOL_INFOA lpProtocolInfo,
2713 GROUP g, DWORD dwFlags)
2716 FIXME: The "advanced" parameters of WSASocketA (lpProtocolInfo,
2717 g, dwFlags) are ignored.
2720 TRACE("af=%d type=%d protocol=%d protocol_info=%p group=%d flags=0x%lx\n",
2721 af, type, protocol, lpProtocolInfo, g, dwFlags );
2723 return ( WSOCK32_socket (af, type, protocol) );
2727 /***********************************************************************
2728 * __WSAFDIsSet() (WINSOCK.151)
2730 INT16 WINAPI __WSAFDIsSet16(SOCKET16 s, ws_fd_set16 *set)
2732 int i = set->fd_count;
2734 TRACE("(%d,%8lx(%i))\n", s,(unsigned long)set, i);
2736 while (i--)
2737 if (set->fd_array[i] == s) return 1;
2738 return 0;
2741 /***********************************************************************
2742 * __WSAFDIsSet() (WSOCK32.151)
2744 INT WINAPI __WSAFDIsSet(SOCKET s, ws_fd_set32 *set)
2746 int i = set->fd_count;
2748 TRACE("(%d,%8lx(%i))\n", s,(unsigned long)set, i);
2750 while (i--)
2751 if (set->fd_array[i] == s) return 1;
2752 return 0;
2755 /***********************************************************************
2756 * WSAIsBlocking() (WINSOCK.114)(WSOCK32.114)
2758 BOOL WINAPI WSAIsBlocking(void)
2760 /* By default WinSock should set all its sockets to non-blocking mode
2761 * and poll in PeekMessage loop when processing "blocking" ones. This
2762 * function is supposed to tell if the program is in this loop. Our
2763 * blocking calls are truly blocking so we always return FALSE.
2765 * Note: It is allowed to call this function without prior WSAStartup().
2768 TRACE("\n");
2769 return FALSE;
2772 /***********************************************************************
2773 * WSACancelBlockingCall() (WINSOCK.113)(WSOCK32.113)
2775 INT WINAPI WSACancelBlockingCall(void)
2777 TRACE("\n");
2778 return 0;
2782 /***********************************************************************
2783 * WSASetBlockingHook16() (WINSOCK.109)
2785 FARPROC16 WINAPI WSASetBlockingHook16(FARPROC16 lpBlockFunc)
2787 FARPROC16 prev = (FARPROC16)blocking_hook;
2788 blocking_hook = (FARPROC)lpBlockFunc;
2789 TRACE("hook %p\n", lpBlockFunc);
2790 return prev;
2794 /***********************************************************************
2795 * WSASetBlockingHook()
2797 FARPROC WINAPI WSASetBlockingHook(FARPROC lpBlockFunc)
2799 FARPROC prev = blocking_hook;
2800 blocking_hook = lpBlockFunc;
2801 TRACE("hook %p\n", lpBlockFunc);
2802 return prev;
2806 /***********************************************************************
2807 * WSAUnhookBlockingHook16() (WINSOCK.110)
2809 INT16 WINAPI WSAUnhookBlockingHook16(void)
2811 blocking_hook = NULL;
2812 return 0;
2816 /***********************************************************************
2817 * WSAUnhookBlockingHook()
2819 INT WINAPI WSAUnhookBlockingHook(void)
2821 blocking_hook = NULL;
2822 return 0;
2826 /* ----------------------------------- end of API stuff */
2828 /* ----------------------------------- helper functions -
2830 * TODO: Merge WS_dup_..() stuff into one function that
2831 * would operate with a generic structure containing internal
2832 * pointers (via a template of some kind).
2835 static int list_size(char** l, int item_size)
2837 int i,j = 0;
2838 if(l)
2839 { for(i=0;l[i];i++)
2840 j += (item_size) ? item_size : strlen(l[i]) + 1;
2841 j += (i + 1) * sizeof(char*); }
2842 return j;
2845 static int list_dup(char** l_src, char* ref, char* base, int item_size)
2847 /* base is either either equal to ref or 0 or SEGPTR */
2849 char* p = ref;
2850 char** l_to = (char**)ref;
2851 int i,j,k;
2853 for(j=0;l_src[j];j++) ;
2854 p += (j + 1) * sizeof(char*);
2855 for(i=0;i<j;i++)
2856 { l_to[i] = base + (p - ref);
2857 k = ( item_size ) ? item_size : strlen(l_src[i]) + 1;
2858 memcpy(p, l_src[i], k); p += k; }
2859 l_to[i] = NULL;
2860 return (p - ref);
2863 /* ----- hostent */
2865 static int hostent_size(struct hostent* p_he)
2867 int size = 0;
2868 if( p_he )
2869 { size = sizeof(struct hostent);
2870 size += strlen(p_he->h_name) + 1;
2871 size += list_size(p_he->h_aliases, 0);
2872 size += list_size(p_he->h_addr_list, p_he->h_length ); }
2873 return size;
2876 /* duplicate hostent entry
2877 * and handle all Win16/Win32 dependent things (struct size, ...) *correctly*.
2878 * Dito for protoent and servent.
2880 int WS_dup_he(struct hostent* p_he, int flag)
2882 /* Convert hostent structure into ws_hostent so that the data fits
2883 * into local_buffer. Internal pointers can be linear, SEGPTR, or
2884 * relative to local_buffer depending on "flag" value. Returns size
2885 * of the data copied.
2888 int size = hostent_size(p_he);
2889 if( size )
2891 char *p_name,*p_aliases,*p_addr,*p_base,*p;
2892 char *p_to;
2893 struct ws_hostent16 *p_to16;
2894 struct ws_hostent32 *p_to32;
2896 check_buffer_he(size);
2897 p_to = he_buffer;
2898 p_to16 = he_buffer;
2899 p_to32 = he_buffer;
2901 p = p_to;
2902 p_base = (flag & WS_DUP_OFFSET) ? NULL
2903 : ((flag & WS_DUP_SEGPTR) ? (char*)SEGPTR_GET(p) : p);
2904 p += (flag & WS_DUP_SEGPTR) ?
2905 sizeof(struct ws_hostent16) : sizeof(struct ws_hostent32);
2906 p_name = p;
2907 strcpy(p, p_he->h_name); p += strlen(p) + 1;
2908 p_aliases = p;
2909 p += list_dup(p_he->h_aliases, p, p_base + (p - p_to), 0);
2910 p_addr = p;
2911 list_dup(p_he->h_addr_list, p, p_base + (p - p_to), p_he->h_length);
2913 if (flag & WS_DUP_SEGPTR) /* Win16 */
2915 p_to16->h_addrtype = (INT16)p_he->h_addrtype;
2916 p_to16->h_length = (INT16)p_he->h_length;
2917 p_to16->h_name = (SEGPTR)(p_base + (p_name - p_to));
2918 p_to16->h_aliases = (SEGPTR)(p_base + (p_aliases - p_to));
2919 p_to16->h_addr_list = (SEGPTR)(p_base + (p_addr - p_to));
2920 size += (sizeof(struct ws_hostent16) - sizeof(struct hostent));
2922 else /* Win32 */
2924 p_to32->h_addrtype = p_he->h_addrtype;
2925 p_to32->h_length = p_he->h_length;
2926 p_to32->h_name = (p_base + (p_name - p_to));
2927 p_to32->h_aliases = (char **)(p_base + (p_aliases - p_to));
2928 p_to32->h_addr_list = (char **)(p_base + (p_addr - p_to));
2929 size += (sizeof(struct ws_hostent32) - sizeof(struct hostent));
2932 return size;
2935 /* ----- protoent */
2937 static int protoent_size(struct protoent* p_pe)
2939 int size = 0;
2940 if( p_pe )
2941 { size = sizeof(struct protoent);
2942 size += strlen(p_pe->p_name) + 1;
2943 size += list_size(p_pe->p_aliases, 0); }
2944 return size;
2947 int WS_dup_pe(struct protoent* p_pe, int flag)
2949 int size = protoent_size(p_pe);
2950 if( size )
2952 char *p_to;
2953 struct ws_protoent16 *p_to16;
2954 struct ws_protoent32 *p_to32;
2955 char *p_name,*p_aliases,*p_base,*p;
2957 check_buffer_pe(size);
2958 p_to = pe_buffer;
2959 p_to16 = pe_buffer;
2960 p_to32 = pe_buffer;
2961 p = p_to;
2962 p_base = (flag & WS_DUP_OFFSET) ? NULL
2963 : ((flag & WS_DUP_SEGPTR) ? (char*)SEGPTR_GET(p) : p);
2964 p += (flag & WS_DUP_SEGPTR) ?
2965 sizeof(struct ws_protoent16) : sizeof(struct ws_protoent32);
2966 p_name = p;
2967 strcpy(p, p_pe->p_name); p += strlen(p) + 1;
2968 p_aliases = p;
2969 list_dup(p_pe->p_aliases, p, p_base + (p - p_to), 0);
2971 if (flag & WS_DUP_SEGPTR) /* Win16 */
2973 p_to16->p_proto = (INT16)p_pe->p_proto;
2974 p_to16->p_name = (SEGPTR)(p_base) + (p_name - p_to);
2975 p_to16->p_aliases = (SEGPTR)((p_base) + (p_aliases - p_to));
2976 size += (sizeof(struct ws_protoent16) - sizeof(struct protoent));
2978 else /* Win32 */
2980 p_to32->p_proto = p_pe->p_proto;
2981 p_to32->p_name = (p_base) + (p_name - p_to);
2982 p_to32->p_aliases = (char **)((p_base) + (p_aliases - p_to));
2983 size += (sizeof(struct ws_protoent32) - sizeof(struct protoent));
2986 return size;
2989 /* ----- servent */
2991 static int servent_size(struct servent* p_se)
2993 int size = 0;
2994 if( p_se )
2995 { size += sizeof(struct servent);
2996 size += strlen(p_se->s_proto) + strlen(p_se->s_name) + 2;
2997 size += list_size(p_se->s_aliases, 0); }
2998 return size;
3001 int WS_dup_se(struct servent* p_se, int flag)
3003 int size = servent_size(p_se);
3004 if( size )
3006 char *p_name,*p_aliases,*p_proto,*p_base,*p;
3007 char *p_to;
3008 struct ws_servent16 *p_to16;
3009 struct ws_servent32 *p_to32;
3011 check_buffer_se(size);
3012 p_to = se_buffer;
3013 p_to16 = se_buffer;
3014 p_to32 = se_buffer;
3015 p = p_to;
3016 p_base = (flag & WS_DUP_OFFSET) ? NULL
3017 : ((flag & WS_DUP_SEGPTR) ? (char*)SEGPTR_GET(p) : p);
3018 p += (flag & WS_DUP_SEGPTR) ?
3019 sizeof(struct ws_servent16) : sizeof(struct ws_servent32);
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 - p_to), 0);
3027 if (flag & WS_DUP_SEGPTR) /* Win16 */
3029 p_to16->s_port = (INT16)p_se->s_port;
3030 p_to16->s_name = (SEGPTR)(p_base + (p_name - p_to));
3031 p_to16->s_proto = (SEGPTR)(p_base + (p_proto - p_to));
3032 p_to16->s_aliases = (SEGPTR)(p_base + (p_aliases - p_to));
3033 size += (sizeof(struct ws_servent16) - sizeof(struct servent));
3035 else /* Win32 */
3037 p_to32->s_port = p_se->s_port;
3038 p_to32->s_name = (p_base + (p_name - p_to));
3039 p_to32->s_proto = (p_base + (p_proto - p_to));
3040 p_to32->s_aliases = (char **)(p_base + (p_aliases - p_to));
3041 size += (sizeof(struct ws_servent32) - sizeof(struct servent));
3044 return size;
3047 /* ----------------------------------- error handling */
3049 UINT16 wsaErrno(void)
3051 int loc_errno = errno;
3052 WARN("errno %d, (%s).\n", loc_errno, strerror(loc_errno));
3054 switch(loc_errno)
3056 case EINTR: return WSAEINTR;
3057 case EBADF: return WSAEBADF;
3058 case EPERM:
3059 case EACCES: return WSAEACCES;
3060 case EFAULT: return WSAEFAULT;
3061 case EINVAL: return WSAEINVAL;
3062 case EMFILE: return WSAEMFILE;
3063 case EWOULDBLOCK: return WSAEWOULDBLOCK;
3064 case EINPROGRESS: return WSAEINPROGRESS;
3065 case EALREADY: return WSAEALREADY;
3066 case ENOTSOCK: return WSAENOTSOCK;
3067 case EDESTADDRREQ: return WSAEDESTADDRREQ;
3068 case EMSGSIZE: return WSAEMSGSIZE;
3069 case EPROTOTYPE: return WSAEPROTOTYPE;
3070 case ENOPROTOOPT: return WSAENOPROTOOPT;
3071 case EPROTONOSUPPORT: return WSAEPROTONOSUPPORT;
3072 case ESOCKTNOSUPPORT: return WSAESOCKTNOSUPPORT;
3073 case EOPNOTSUPP: return WSAEOPNOTSUPP;
3074 case EPFNOSUPPORT: return WSAEPFNOSUPPORT;
3075 case EAFNOSUPPORT: return WSAEAFNOSUPPORT;
3076 case EADDRINUSE: return WSAEADDRINUSE;
3077 case EADDRNOTAVAIL: return WSAEADDRNOTAVAIL;
3078 case ENETDOWN: return WSAENETDOWN;
3079 case ENETUNREACH: return WSAENETUNREACH;
3080 case ENETRESET: return WSAENETRESET;
3081 case ECONNABORTED: return WSAECONNABORTED;
3082 case EPIPE:
3083 case ECONNRESET: return WSAECONNRESET;
3084 case ENOBUFS: return WSAENOBUFS;
3085 case EISCONN: return WSAEISCONN;
3086 case ENOTCONN: return WSAENOTCONN;
3087 case ESHUTDOWN: return WSAESHUTDOWN;
3088 case ETOOMANYREFS: return WSAETOOMANYREFS;
3089 case ETIMEDOUT: return WSAETIMEDOUT;
3090 case ECONNREFUSED: return WSAECONNREFUSED;
3091 case ELOOP: return WSAELOOP;
3092 case ENAMETOOLONG: return WSAENAMETOOLONG;
3093 case EHOSTDOWN: return WSAEHOSTDOWN;
3094 case EHOSTUNREACH: return WSAEHOSTUNREACH;
3095 case ENOTEMPTY: return WSAENOTEMPTY;
3096 #ifdef EPROCLIM
3097 case EPROCLIM: return WSAEPROCLIM;
3098 #endif
3099 #ifdef EUSERS
3100 case EUSERS: return WSAEUSERS;
3101 #endif
3102 #ifdef EDQUOT
3103 case EDQUOT: return WSAEDQUOT;
3104 #endif
3105 #ifdef ESTALE
3106 case ESTALE: return WSAESTALE;
3107 #endif
3108 #ifdef EREMOTE
3109 case EREMOTE: return WSAEREMOTE;
3110 #endif
3112 /* just in case we ever get here and there are no problems */
3113 case 0: return 0;
3114 default:
3115 WARN("Unknown errno %d!\n", loc_errno);
3116 return WSAEOPNOTSUPP;
3120 UINT16 wsaHerrno(int loc_errno)
3123 WARN("h_errno %d.\n", loc_errno);
3125 switch(loc_errno)
3127 case HOST_NOT_FOUND: return WSAHOST_NOT_FOUND;
3128 case TRY_AGAIN: return WSATRY_AGAIN;
3129 case NO_RECOVERY: return WSANO_RECOVERY;
3130 case NO_DATA: return WSANO_DATA;
3131 case ENOBUFS: return WSAENOBUFS;
3133 case 0: return 0;
3134 default:
3135 WARN("Unknown h_errno %d!\n", loc_errno);
3136 return WSAEOPNOTSUPP;