Adds an initial WSAIoctl function with support for only the
[wine.git] / dlls / winsock / socket.c
blob4b4e3915b2872fc1d6cfb3798ba12a822dadbf24
1 /*
2 * based on Windows Sockets 1.1 specs
3 * (ftp.microsoft.com:/Advsys/winsock/spec11/WINSOCK.TXT)
4 *
5 * (C) 1993,1994,1996,1997 John Brezak, Erik Bos, Alex Korobka.
7 * NOTE: If you make any changes to fix a particular app, make sure
8 * they don't break something else like Netscape or telnet and ftp
9 * clients and servers (www.winsite.com got a lot of those).
13 #include "config.h"
15 #include <string.h>
16 #include <sys/types.h>
17 #ifdef HAVE_SYS_IPC_H
18 # include <sys/ipc.h>
19 #endif
20 #include <sys/ioctl.h>
21 #ifdef HAVE_SYS_FILIO_H
22 # include <sys/filio.h>
23 #endif
24 #if defined(__svr4__) || defined(__sun)
25 #include <sys/ioccom.h>
26 #ifdef HAVE_SYS_SOCKIO_H
27 # include <sys/sockio.h>
28 #endif
29 #endif
31 #if defined(__EMX__)
32 # include <sys/so_ioctl.h>
33 #endif
35 #ifdef HAVE_SYS_PARAM_H
36 # include <sys/param.h>
37 #endif
39 #ifdef HAVE_SYS_MSG_H
40 # include <sys/msg.h>
41 #endif
42 #ifdef HAVE_SYS_WAIT_H
43 # include <sys/wait.h>
44 #endif
45 #ifdef HAVE_SYS_SOCKET_H
46 #include <sys/socket.h>
47 #endif
48 #ifdef HAVE_NETINET_IN_H
49 # include <netinet/in.h>
50 #endif
51 #ifdef HAVE_NETINET_TCP_H
52 # include <netinet/tcp.h>
53 #endif
54 #ifdef HAVE_ARPA_INET_H
55 # include <arpa/inet.h>
56 #endif
57 #include <ctype.h>
58 #include <fcntl.h>
59 #include <errno.h>
60 #ifdef HAVE_SYS_ERRNO_H
61 #include <sys/errno.h>
62 #endif
63 #include <netdb.h>
64 #include <unistd.h>
65 #include <stdlib.h>
66 #ifdef HAVE_ARPA_NAMESER_H
67 # include <arpa/nameser.h>
68 #endif
69 #ifdef HAVE_RESOLV_H
70 # include <resolv.h>
71 #endif
72 #ifdef HAVE_NET_IF_H
73 # include <net/if.h>
74 #endif
76 #include "wine/winbase16.h"
77 #include "wingdi.h"
78 #include "winuser.h"
79 #include "winsock2.h"
80 #include "winnt.h"
81 #include "heap.h"
82 #include "task.h"
83 #include "message.h"
84 #include "miscemu.h"
85 #include "wine/port.h"
86 #include "services.h"
87 #include "server.h"
88 #include "debugtools.h"
91 DEFAULT_DEBUG_CHANNEL(winsock)
93 #define DEBUG_SOCKADDR 0
94 #define dump_sockaddr(a) \
95 DPRINTF("sockaddr_in: family %d, address %s, port %d\n", \
96 ((struct sockaddr_in *)a)->sin_family, \
97 inet_ntoa(((struct sockaddr_in *)a)->sin_addr), \
98 ntohs(((struct sockaddr_in *)a)->sin_port))
100 /* ----------------------------------- internal data */
102 /* ws_... struct conversion flags */
104 #define WS_DUP_LINEAR 0x0001
105 #define WS_DUP_NATIVE 0x0000 /* not used anymore */
106 #define WS_DUP_OFFSET 0x0002 /* internal pointers are offsets */
107 #define WS_DUP_SEGPTR 0x0004 /* internal pointers are SEGPTRs */
108 /* by default, internal pointers are linear */
109 typedef struct /* WSAAsyncSelect() control struct */
111 HANDLE service, event, sock;
112 HWND hWnd;
113 UINT uMsg;
114 LONG lEvent;
115 struct _WSINFO *pwsi;
116 } ws_select_info;
118 #define WS_MAX_SOCKETS_PER_PROCESS 128 /* reasonable guess */
119 #define WS_MAX_UDP_DATAGRAM 1024
121 #define WS_ACCEPT_QUEUE 6
123 #define WSI_BLOCKINGCALL 0x00000001 /* per-thread info flags */
124 #define WSI_BLOCKINGHOOK 0x00000002 /* 32-bit callback */
126 #define PROCFS_NETDEV_FILE "/proc/net/dev" /* Points to the file in the /proc fs
127 that lists the network devices.
128 Do we need an #ifdef LINUX for this? */
130 typedef struct _WSINFO
132 DWORD dwThisProcess;
133 struct _WSINFO *lpNextIData;
135 unsigned flags;
136 INT16 num_startup; /* reference counter */
137 INT16 num_async_rq;
138 INT16 last_free; /* entry in the socket table */
139 UINT16 buflen;
140 char* buffer; /* allocated from SEGPTR heap */
141 struct ws_hostent *he;
142 int helen;
143 struct ws_servent *se;
144 int selen;
145 struct ws_protoent *pe;
146 int pelen;
147 char* dbuffer; /* buffer for dummies (32 bytes) */
149 DWORD blocking_hook;
151 volatile HANDLE accept_old[WS_ACCEPT_QUEUE], accept_new[WS_ACCEPT_QUEUE];
152 } WSINFO, *LPWSINFO;
154 /* function prototypes */
155 int WS_dup_he(LPWSINFO pwsi, struct hostent* p_he, int flag);
156 int WS_dup_pe(LPWSINFO pwsi, struct protoent* p_pe, int flag);
157 int WS_dup_se(LPWSINFO pwsi, struct servent* p_se, int flag);
159 int WSAIOCTL_GetInterfaceCount(void);
160 int WSAIOCTL_GetInterfaceName(int intNumber, char *intName);
162 UINT16 wsaErrno(void);
163 UINT16 wsaHerrno(void);
165 static HANDLE _WSHeap = 0;
167 #define WS_ALLOC(size) \
168 HeapAlloc(_WSHeap, HEAP_ZERO_MEMORY, (size) )
169 #define WS_FREE(ptr) \
170 HeapFree(_WSHeap, 0, (ptr) )
172 static INT _ws_sock_ops[] =
173 { WS_SO_DEBUG, WS_SO_REUSEADDR, WS_SO_KEEPALIVE, WS_SO_DONTROUTE,
174 WS_SO_BROADCAST, WS_SO_LINGER, WS_SO_OOBINLINE, WS_SO_SNDBUF,
175 WS_SO_RCVBUF, WS_SO_ERROR, WS_SO_TYPE, WS_SO_DONTLINGER,
176 #ifdef SO_RCVTIMEO
177 WS_SO_RCVTIMEO,
178 #endif
179 0 };
180 static int _px_sock_ops[] =
181 { SO_DEBUG, SO_REUSEADDR, SO_KEEPALIVE, SO_DONTROUTE, SO_BROADCAST,
182 SO_LINGER, SO_OOBINLINE, SO_SNDBUF, SO_RCVBUF, SO_ERROR, SO_TYPE,
183 WS_SO_DONTLINGER, /* no unix equivalent */
184 #ifdef SO_RCVTIMEO
185 SO_RCVTIMEO,
186 #endif
189 static INT _ws_tcp_ops[] = {
190 #ifdef TCP_NODELAY
191 WS_TCP_NODELAY,
192 #endif
195 static int _px_tcp_ops[] = {
196 #ifdef TCP_NODELAY
197 TCP_NODELAY,
198 #endif
202 /* we need a special routine to handle WSA* errors */
203 static inline int sock_server_call( enum request req )
205 unsigned int res = server_call_noerr( req );
206 if (res)
208 /* do not map WSA errors */
209 if ((res < WSABASEERR) || (res >= 0x10000000)) res = RtlNtStatusToDosError(res);
210 SetLastError( res );
212 return res;
215 static int _check_ws(LPWSINFO pwsi, SOCKET s);
216 static char* _check_buffer(LPWSINFO pwsi, int size);
218 static int _get_sock_fd(SOCKET s)
220 struct get_read_fd_request *req = get_req_buffer();
221 int fd;
223 req->handle = s;
224 server_call_fd( REQ_GET_READ_FD, -1, &fd );
225 if (fd == -1)
226 FIXME("handle %d is not a socket (GLE %ld)\n",s,GetLastError());
227 return fd;
230 static void _enable_event(SOCKET s, unsigned int event,
231 unsigned int sstate, unsigned int cstate)
233 struct enable_socket_event_request *req = get_req_buffer();
235 req->handle = s;
236 req->mask = event;
237 req->sstate = sstate;
238 req->cstate = cstate;
239 sock_server_call( REQ_ENABLE_SOCKET_EVENT );
242 static int _is_blocking(SOCKET s)
244 struct get_socket_event_request *req = get_req_buffer();
246 req->handle = s;
247 req->service = FALSE;
248 req->s_event = 0;
249 req->c_event = 0;
250 sock_server_call( REQ_GET_SOCKET_EVENT );
251 return (req->state & WS_FD_NONBLOCKING) == 0;
254 static unsigned int _get_sock_mask(SOCKET s)
256 struct get_socket_event_request *req = get_req_buffer();
258 req->handle = s;
259 req->service = FALSE;
260 req->s_event = 0;
261 req->c_event = 0;
262 sock_server_call( REQ_GET_SOCKET_EVENT );
263 return req->mask;
266 static void _sync_sock_state(SOCKET s)
268 /* do a dummy wineserver request in order to let
269 the wineserver run through its select loop once */
270 (void)_is_blocking(s);
273 static int _get_sock_error(SOCKET s, unsigned int bit)
275 struct get_socket_event_request *req = get_req_buffer();
277 req->handle = s;
278 req->service = FALSE;
279 req->s_event = 0;
280 req->c_event = 0;
281 sock_server_call( REQ_GET_SOCKET_EVENT );
282 return req->errors[bit];
285 static LPWSINFO lpFirstIData = NULL;
287 static LPWSINFO WINSOCK_GetIData(void)
289 DWORD pid = GetCurrentProcessId();
290 LPWSINFO iData;
292 for (iData = lpFirstIData; iData; iData = iData->lpNextIData) {
293 if (iData->dwThisProcess == pid)
294 break;
296 return iData;
299 static BOOL WINSOCK_CreateIData(void)
301 LPWSINFO iData;
303 iData = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(WSINFO));
304 if (!iData)
305 return FALSE;
306 iData->dwThisProcess = GetCurrentProcessId();
307 iData->lpNextIData = lpFirstIData;
308 lpFirstIData = iData;
309 return TRUE;
312 static void WINSOCK_DeleteIData(void)
314 LPWSINFO iData = WINSOCK_GetIData();
315 LPWSINFO* ppid;
316 if (iData) {
317 for (ppid = &lpFirstIData; *ppid; ppid = &(*ppid)->lpNextIData) {
318 if (*ppid == iData) {
319 *ppid = iData->lpNextIData;
320 break;
324 if( iData->flags & WSI_BLOCKINGCALL )
325 TRACE("\tinside blocking call!\n");
327 /* delete scratch buffers */
329 if( iData->buffer ) SEGPTR_FREE(iData->buffer);
330 if( iData->dbuffer ) SEGPTR_FREE(iData->dbuffer);
332 HeapFree(GetProcessHeap(), 0, iData);
336 /***********************************************************************
337 * WSOCK32_LibMain (WSOCK32.init)
339 BOOL WINAPI WSOCK32_LibMain(HINSTANCE hInstDLL, DWORD fdwReason, LPVOID fImpLoad)
341 TRACE("0x%x 0x%lx %p\n", hInstDLL, fdwReason, fImpLoad);
342 switch (fdwReason) {
343 case DLL_PROCESS_DETACH:
344 WINSOCK_DeleteIData();
345 break;
347 return TRUE;
350 /***********************************************************************
351 * WINSOCK_LibMain (WINSOCK.init)
353 BOOL WINAPI WINSOCK_LibMain(DWORD fdwReason, HINSTANCE hInstDLL, WORD ds,
354 WORD wHeapSize, DWORD dwReserved1, WORD wReserved2)
356 TRACE("0x%x 0x%lx\n", hInstDLL, fdwReason);
357 switch (fdwReason) {
358 case DLL_PROCESS_DETACH:
359 WINSOCK_DeleteIData();
360 break;
362 return TRUE;
365 /***********************************************************************
366 * convert_sockopt()
368 * Converts socket flags from Windows format.
370 static void convert_sockopt(INT *level, INT *optname)
372 int i;
373 switch (*level)
375 case WS_SOL_SOCKET:
376 *level = SOL_SOCKET;
377 for(i=0; _ws_sock_ops[i]; i++)
378 if( _ws_sock_ops[i] == *optname ) break;
379 if( _ws_sock_ops[i] ) *optname = _px_sock_ops[i];
380 else FIXME("Unknown SOL_SOCKET optname %d\n", *optname);
381 break;
382 case WS_IPPROTO_TCP:
383 *level = IPPROTO_TCP;
384 for(i=0; _ws_tcp_ops[i]; i++)
385 if ( _ws_tcp_ops[i] == *optname ) break;
386 if( _ws_tcp_ops[i] ) *optname = _px_tcp_ops[i];
387 else FIXME("Unknown IPPROTO_TCP optname %d\n", *optname);
388 break;
392 /* ----------------------------------- Per-thread info (or per-process?) */
394 static int wsi_strtolo(LPWSINFO pwsi, const char* name, const char* opt)
396 /* Stuff a lowercase copy of the string into the local buffer */
398 int i = strlen(name) + 2;
399 char* p = _check_buffer(pwsi, i + ((opt)?strlen(opt):0));
401 if( p )
403 do *p++ = tolower(*name); while(*name++);
404 i = (p - (char*)(pwsi->buffer));
405 if( opt ) do *p++ = tolower(*opt); while(*opt++);
406 return i;
408 return 0;
411 static fd_set* fd_set_import( fd_set* fds, LPWSINFO pwsi, void* wsfds, int* highfd, int lfd[], BOOL b32 )
413 /* translate Winsock fd set into local fd set */
415 if( wsfds )
417 #define wsfds16 ((ws_fd_set16*)wsfds)
418 #define wsfds32 ((ws_fd_set32*)wsfds)
419 int i, count;
421 FD_ZERO(fds);
422 count = b32 ? wsfds32->fd_count : wsfds16->fd_count;
424 for( i = 0; i < count; i++ )
426 int s = (b32) ? wsfds32->fd_array[i]
427 : wsfds16->fd_array[i];
428 if( _check_ws(pwsi, s) )
430 int fd = _get_sock_fd(s);
431 lfd[ i ] = fd;
432 if( fd > *highfd ) *highfd = fd;
433 FD_SET(fd, fds);
435 else lfd[ i ] = -1;
437 #undef wsfds32
438 #undef wsfds16
439 return fds;
441 return NULL;
444 inline static int sock_error_p(int s)
446 unsigned int optval, optlen;
448 optlen = sizeof(optval);
449 getsockopt(s, SOL_SOCKET, SO_ERROR, (void *) &optval, &optlen);
450 if (optval) WARN("\t[%i] error: %d\n", s, optval);
451 return optval != 0;
454 static int fd_set_export( LPWSINFO pwsi, fd_set* fds, fd_set* exceptfds, void* wsfds, int lfd[], BOOL b32 )
456 int num_err = 0;
458 /* translate local fd set into Winsock fd set, adding
459 * errors to exceptfds (only if app requested it) */
461 if( wsfds )
463 #define wsfds16 ((ws_fd_set16*)wsfds)
464 #define wsfds32 ((ws_fd_set32*)wsfds)
465 int i, j, count = (b32) ? wsfds32->fd_count : wsfds16->fd_count;
467 for( i = 0, j = 0; i < count; i++ )
469 if( lfd[i] >= 0 )
471 int fd = lfd[i];
472 if( FD_ISSET(fd, fds) )
474 if ( exceptfds && sock_error_p(fd) )
476 FD_SET(fd, exceptfds);
477 num_err++;
479 else if( b32 )
480 wsfds32->fd_array[j++] = wsfds32->fd_array[i];
481 else
482 wsfds16->fd_array[j++] = wsfds16->fd_array[i];
484 close(fd);
485 lfd[i] = -1;
489 if( b32 ) wsfds32->fd_count = j;
490 else wsfds16->fd_count = j;
492 TRACE("\n");
493 #undef wsfds32
494 #undef wsfds16
496 return num_err;
499 static void fd_set_unimport( void* wsfds, int lfd[], BOOL b32 )
501 if ( wsfds )
503 #define wsfds16 ((ws_fd_set16*)wsfds)
504 #define wsfds32 ((ws_fd_set32*)wsfds)
505 int i, count = (b32) ? wsfds32->fd_count : wsfds16->fd_count;
507 for( i = 0; i < count; i++ )
508 if ( lfd[i] >= 0 )
509 close(lfd[i]);
511 TRACE("\n");
512 #undef wsfds32
513 #undef wsfds16
517 static int do_block( int fd, int mask )
519 fd_set fds[3];
520 int i, r;
522 FD_ZERO(&fds[0]);
523 FD_ZERO(&fds[1]);
524 FD_ZERO(&fds[2]);
525 for (i=0; i<3; i++)
526 if (mask & (1<<i))
527 FD_SET(fd, &fds[i]);
528 i = select( fd+1, &fds[0], &fds[1], &fds[2], NULL );
529 if (i <= 0) return -1;
530 r = 0;
531 for (i=0; i<3; i++)
532 if (FD_ISSET(fd, &fds[i]))
533 r |= 1<<i;
534 return r;
537 void* __ws_memalloc( int size )
539 return WS_ALLOC(size);
542 void __ws_memfree(void* ptr)
544 WS_FREE(ptr);
548 /* ----------------------------------- API -----
550 * Init / cleanup / error checking.
553 /***********************************************************************
554 * WSAStartup16() (WINSOCK.115)
556 * Create socket control struct, attach it to the global list and
557 * update a pointer in the task struct.
559 INT16 WINAPI WSAStartup16(UINT16 wVersionRequested, LPWSADATA lpWSAData)
561 WSADATA WINSOCK_data = { 0x0101, 0x0101,
562 "WINE Sockets 1.1",
563 #ifdef linux
564 "Linux/i386",
565 #elif defined(__NetBSD__)
566 "NetBSD/i386",
567 #elif defined(sunos)
568 "SunOS",
569 #elif defined(__FreeBSD__)
570 "FreeBSD",
571 #elif defined(__OpenBSD__)
572 "OpenBSD/i386",
573 #else
574 "Unknown",
575 #endif
576 WS_MAX_SOCKETS_PER_PROCESS,
577 WS_MAX_UDP_DATAGRAM, (SEGPTR)NULL };
578 LPWSINFO pwsi;
580 TRACE("verReq=%x\n", wVersionRequested);
582 if (LOBYTE(wVersionRequested) < 1 || (LOBYTE(wVersionRequested) == 1 &&
583 HIBYTE(wVersionRequested) < 1)) return WSAVERNOTSUPPORTED;
585 if (!lpWSAData) return WSAEINVAL;
587 /* initialize socket heap */
589 if( !_WSHeap )
591 _WSHeap = HeapCreate(HEAP_ZERO_MEMORY, 8120, 32768);
592 if( !_WSHeap )
594 ERR("Fatal: failed to create WinSock heap\n");
595 return 0;
598 if( _WSHeap == 0 ) return WSASYSNOTREADY;
600 pwsi = WINSOCK_GetIData();
601 if( pwsi == NULL )
603 WINSOCK_CreateIData();
604 pwsi = WINSOCK_GetIData();
605 if (!pwsi) return WSASYSNOTREADY;
607 pwsi->num_startup++;
609 /* return winsock information */
611 memcpy(lpWSAData, &WINSOCK_data, sizeof(WINSOCK_data));
613 TRACE("succeeded\n");
614 return 0;
617 /***********************************************************************
618 * WSAStartup() (WS2_32.115)
620 INT WINAPI WSAStartup(UINT wVersionRequested, LPWSADATA lpWSAData)
622 WSADATA WINSOCK_data = { 0x0202, 0x0202,
623 "WINE Sockets 2.0",
624 #ifdef linux
625 "Linux/i386",
626 #elif defined(__NetBSD__)
627 "NetBSD/i386",
628 #elif defined(sunos)
629 "SunOS",
630 #elif defined(__FreeBSD__)
631 "FreeBSD",
632 #elif defined(__OpenBSD__)
633 "OpenBSD/i386",
634 #else
635 "Unknown",
636 #endif
637 WS_MAX_SOCKETS_PER_PROCESS,
638 WS_MAX_UDP_DATAGRAM, (SEGPTR)NULL };
639 LPWSINFO pwsi;
641 TRACE("verReq=%x\n", wVersionRequested);
643 if (LOBYTE(wVersionRequested) < 1)
644 return WSAVERNOTSUPPORTED;
646 if (!lpWSAData) return WSAEINVAL;
648 /* initialize socket heap */
650 if( !_WSHeap )
652 _WSHeap = HeapCreate(HEAP_ZERO_MEMORY, 8120, 32768);
653 if( !_WSHeap )
655 ERR("Fatal: failed to create WinSock heap\n");
656 return 0;
659 if( _WSHeap == 0 ) return WSASYSNOTREADY;
661 pwsi = WINSOCK_GetIData();
662 if( pwsi == NULL )
664 WINSOCK_CreateIData();
665 pwsi = WINSOCK_GetIData();
666 if (!pwsi) return WSASYSNOTREADY;
668 pwsi->num_startup++;
670 /* return winsock information */
671 memcpy(lpWSAData, &WINSOCK_data, sizeof(WINSOCK_data));
673 /* that's the whole of the negotiation for now */
674 lpWSAData->wVersion = wVersionRequested;
676 TRACE("succeeded\n");
677 return 0;
681 /***********************************************************************
682 * WSACleanup() (WINSOCK.116)
684 INT WINAPI WSACleanup(void)
686 LPWSINFO pwsi = WINSOCK_GetIData();
687 if( pwsi ) {
688 if( --pwsi->num_startup > 0 ) return 0;
690 WINSOCK_DeleteIData();
691 return 0;
693 SetLastError(WSANOTINITIALISED);
694 return SOCKET_ERROR;
698 /***********************************************************************
699 * WSAGetLastError() (WSOCK32.111)(WINSOCK.111)
701 INT WINAPI WSAGetLastError(void)
703 return GetLastError();
706 /***********************************************************************
707 * WSASetLastError() (WSOCK32.112)
709 void WINAPI WSASetLastError(INT iError) {
710 SetLastError(iError);
713 /***********************************************************************
714 * WSASetLastError16() (WINSOCK.112)
716 void WINAPI WSASetLastError16(INT16 iError)
718 WSASetLastError(iError);
721 int _check_ws(LPWSINFO pwsi, SOCKET s)
723 if( pwsi )
725 int fd;
726 if( pwsi->flags & WSI_BLOCKINGCALL ) SetLastError(WSAEINPROGRESS);
727 if ( (fd = _get_sock_fd(s)) < 0 ) {
728 SetLastError(WSAENOTSOCK);
729 return 0;
731 /* FIXME: maybe check whether fd is really a socket? */
732 close( fd );
733 return 1;
735 return 0;
738 char* _check_buffer(LPWSINFO pwsi, int size)
740 if( pwsi->buffer && pwsi->buflen >= size ) return pwsi->buffer;
741 else SEGPTR_FREE(pwsi->buffer);
743 pwsi->buffer = (char*)SEGPTR_ALLOC((pwsi->buflen = size));
744 return pwsi->buffer;
747 struct ws_hostent* _check_buffer_he(LPWSINFO pwsi, int size)
749 if( pwsi->he && pwsi->helen >= size ) return pwsi->he;
750 else SEGPTR_FREE(pwsi->he);
752 pwsi->he = (struct ws_hostent*)SEGPTR_ALLOC((pwsi->helen = size));
753 return pwsi->he;
756 struct ws_servent* _check_buffer_se(LPWSINFO pwsi, int size)
758 if( pwsi->se && pwsi->selen >= size ) return pwsi->se;
759 else SEGPTR_FREE(pwsi->se);
761 pwsi->se = (struct ws_servent*)SEGPTR_ALLOC((pwsi->selen = size));
762 return pwsi->se;
765 struct ws_protoent* _check_buffer_pe(LPWSINFO pwsi, int size)
767 if( pwsi->pe && pwsi->pelen >= size ) return pwsi->pe;
768 else SEGPTR_FREE(pwsi->pe);
770 pwsi->pe = (struct ws_protoent*)SEGPTR_ALLOC((pwsi->pelen = size));
771 return pwsi->pe;
774 /* ----------------------------------- i/o APIs */
776 /***********************************************************************
777 * accept() (WSOCK32.1)
779 static void WSOCK32_async_accept(LPWSINFO pwsi, SOCKET s, SOCKET as)
781 int q;
782 /* queue socket for WSAAsyncSelect */
783 for (q=0; q<WS_ACCEPT_QUEUE; q++)
784 if (InterlockedCompareExchange((PVOID*)&pwsi->accept_old[q], (PVOID)s, (PVOID)0) == (PVOID)0)
785 break;
786 if (q<WS_ACCEPT_QUEUE)
787 pwsi->accept_new[q] = as;
788 else
789 ERR("accept queue too small\n");
790 /* now signal our AsyncSelect handler */
791 _enable_event(s, WS_FD_SERVEVENT, 0, 0);
794 SOCKET WINAPI WSOCK32_accept(SOCKET s, struct sockaddr *addr,
795 INT *addrlen32)
797 LPWSINFO pwsi = WINSOCK_GetIData();
798 #ifdef HAVE_IPX
799 struct ws_sockaddr_ipx* addr2 = (struct ws_sockaddr_ipx *)addr;
800 #endif
801 struct accept_socket_request *req = get_req_buffer();
803 TRACE("(%08x): socket %04x\n",
804 (unsigned)pwsi, (UINT16)s );
805 if( _check_ws(pwsi, s) )
807 if (_is_blocking(s))
809 /* block here */
810 int fd = _get_sock_fd(s);
811 do_block(fd, 5);
812 close(fd);
813 _sync_sock_state(s); /* let wineserver notice connection */
814 /* retrieve any error codes from it */
815 SetLastError(_get_sock_error(s, FD_ACCEPT_BIT));
816 /* FIXME: care about the error? */
818 req->lhandle = s;
819 req->access = GENERIC_READ|GENERIC_WRITE|SYNCHRONIZE;
820 req->inherit = TRUE;
821 sock_server_call( REQ_ACCEPT_SOCKET );
822 if( req->handle >= 0 )
824 SOCKET as = req->handle;
825 unsigned omask = _get_sock_mask( s );
826 int fd = _get_sock_fd( as );
827 if( getpeername(fd, addr, addrlen32) != -1 )
829 #ifdef HAVE_IPX
830 if (addr && ((struct sockaddr_ipx *)addr)->sipx_family == AF_IPX) {
831 addr = (struct sockaddr *)
832 malloc(addrlen32 ? *addrlen32 : sizeof(*addr2));
833 memcpy(addr, addr2,
834 addrlen32 ? *addrlen32 : sizeof(*addr2));
835 addr2->sipx_family = WS_AF_IPX;
836 addr2->sipx_network = ((struct sockaddr_ipx *)addr)->sipx_network;
837 addr2->sipx_port = ((struct sockaddr_ipx *)addr)->sipx_port;
838 memcpy(addr2->sipx_node,
839 ((struct sockaddr_ipx *)addr)->sipx_node, IPX_NODE_LEN);
840 free(addr);
842 #endif
843 } else SetLastError(wsaErrno());
844 close(fd);
845 if (omask & WS_FD_SERVEVENT)
846 WSOCK32_async_accept(pwsi, s, as);
847 return as;
850 return INVALID_SOCKET;
853 /***********************************************************************
854 * accept() (WINSOCK.1)
856 SOCKET16 WINAPI WINSOCK_accept16(SOCKET16 s, struct sockaddr* addr,
857 INT16* addrlen16 )
859 INT addrlen32 = addrlen16 ? *addrlen16 : 0;
860 SOCKET retSocket = WSOCK32_accept( s, addr, &addrlen32 );
861 if( addrlen16 ) *addrlen16 = (INT16)addrlen32;
862 return (SOCKET16)retSocket;
865 /***********************************************************************
866 * bind() (WSOCK32.2)
868 INT WINAPI WSOCK32_bind(SOCKET s, struct sockaddr *name, INT namelen)
870 LPWSINFO pwsi = WINSOCK_GetIData();
871 #ifdef HAVE_IPX
872 struct ws_sockaddr_ipx* name2 = (struct ws_sockaddr_ipx *)name;
873 #endif
875 TRACE("(%08x): socket %04x, ptr %8x, length %d\n",
876 (unsigned)pwsi, s, (int) name, namelen);
877 #if DEBUG_SOCKADDR
878 dump_sockaddr(name);
879 #endif
881 if ( _check_ws(pwsi, s) )
883 int fd = _get_sock_fd(s);
884 /* FIXME: what family does this really map to on the Unix side? */
885 if (name && ((struct ws_sockaddr_ipx *)name)->sipx_family == WS_AF_PUP)
886 ((struct ws_sockaddr_ipx *)name)->sipx_family = AF_UNSPEC;
887 #ifdef HAVE_IPX
888 else if (name &&
889 ((struct ws_sockaddr_ipx *)name)->sipx_family == WS_AF_IPX)
891 name = (struct sockaddr *) malloc(sizeof(struct sockaddr_ipx));
892 memset(name, '\0', sizeof(struct sockaddr_ipx));
893 ((struct sockaddr_ipx *)name)->sipx_family = AF_IPX;
894 ((struct sockaddr_ipx *)name)->sipx_port = name2->sipx_port;
895 ((struct sockaddr_ipx *)name)->sipx_network = name2->sipx_network;
896 memcpy(((struct sockaddr_ipx *)name)->sipx_node,
897 name2->sipx_node, IPX_NODE_LEN);
898 namelen = sizeof(struct sockaddr_ipx);
900 #endif
901 if ( namelen >= sizeof(*name) )
903 if ( name && (((struct ws_sockaddr_in *)name)->sin_family == AF_INET
904 #ifdef HAVE_IPX
905 || ((struct sockaddr_ipx *)name)->sipx_family == AF_IPX
906 #endif
909 if ( bind(fd, name, namelen) < 0 )
911 int loc_errno = errno;
912 WARN("\tfailure - errno = %i\n", errno);
913 errno = loc_errno;
914 switch(errno)
916 case EBADF: SetLastError(WSAENOTSOCK); break;
917 case EADDRNOTAVAIL: SetLastError(WSAEINVAL); break;
918 default: SetLastError(wsaErrno());break;
921 else {
922 #ifdef HAVE_IPX
923 if (((struct sockaddr_ipx *)name)->sipx_family == AF_IPX)
924 free(name);
925 #endif
926 close(fd);
927 return 0; /* success */
929 } else SetLastError(WSAEAFNOSUPPORT);
930 } else SetLastError(WSAEFAULT);
931 #ifdef HAVE_IPX
932 if (name && ((struct sockaddr_ipx *)name)->sipx_family == AF_IPX)
933 free(name);
934 #endif
935 close(fd);
937 return SOCKET_ERROR;
940 /***********************************************************************
941 * bind() (WINSOCK.2)
943 INT16 WINAPI WINSOCK_bind16(SOCKET16 s, struct sockaddr *name, INT16 namelen)
945 return (INT16)WSOCK32_bind( s, name, namelen );
948 /***********************************************************************
949 * closesocket() (WSOCK32.3)
951 INT WINAPI WSOCK32_closesocket(SOCKET s)
953 LPWSINFO pwsi = WINSOCK_GetIData();
955 TRACE("(%08x): socket %08x\n", (unsigned)pwsi, s);
957 if( _check_ws(pwsi, s) )
959 if( CloseHandle(s) )
960 return 0;
962 return SOCKET_ERROR;
965 /***********************************************************************
966 * closesocket() (WINSOCK.3)
968 INT16 WINAPI WINSOCK_closesocket16(SOCKET16 s)
970 return (INT16)WSOCK32_closesocket(s);
973 /***********************************************************************
974 * connect() (WSOCK32.4)
976 INT WINAPI WSOCK32_connect(SOCKET s, struct sockaddr *name, INT namelen)
978 LPWSINFO pwsi = WINSOCK_GetIData();
979 #ifdef HAVE_IPX
980 struct ws_sockaddr_ipx* name2 = (struct ws_sockaddr_ipx *)name;
981 #endif
983 TRACE("(%08x): socket %04x, ptr %8x, length %d\n",
984 (unsigned)pwsi, s, (int) name, namelen);
985 #if DEBUG_SOCKADDR
986 dump_sockaddr(name);
987 #endif
989 if( _check_ws(pwsi, s) )
991 int fd = _get_sock_fd(s);
992 if (name && ((struct ws_sockaddr_ipx *)name)->sipx_family == WS_AF_PUP)
993 ((struct ws_sockaddr_ipx *)name)->sipx_family = AF_UNSPEC;
994 #ifdef HAVE_IPX
995 else if (name && ((struct ws_sockaddr_ipx *)name)->sipx_family == WS_AF_IPX)
997 name = (struct sockaddr *) malloc(sizeof(struct sockaddr_ipx));
998 memset(name, '\0', sizeof(struct sockaddr_ipx));
999 ((struct sockaddr_ipx *)name)->sipx_family = AF_IPX;
1000 ((struct sockaddr_ipx *)name)->sipx_port = name2->sipx_port;
1001 ((struct sockaddr_ipx *)name)->sipx_network = name2->sipx_network;
1002 memcpy(((struct sockaddr_ipx *)name)->sipx_node,
1003 name2->sipx_node, IPX_NODE_LEN);
1004 namelen = sizeof(struct sockaddr_ipx);
1006 #endif
1007 if (connect(fd, name, namelen) == 0) {
1008 close(fd);
1009 goto connect_success;
1011 if (errno == EINPROGRESS)
1013 /* tell wineserver that a connection is in progress */
1014 _enable_event(s, FD_CONNECT|FD_READ|FD_WRITE,
1015 WS_FD_CONNECT|WS_FD_READ|WS_FD_WRITE,
1016 WS_FD_CONNECTED|WS_FD_LISTENING);
1017 if (_is_blocking(s))
1019 int result;
1020 /* block here */
1021 do_block(fd, 6);
1022 _sync_sock_state(s); /* let wineserver notice connection */
1023 /* retrieve any error codes from it */
1024 result = _get_sock_error(s, FD_CONNECT_BIT);
1025 if (result)
1026 SetLastError(result);
1027 else {
1028 close(fd);
1029 goto connect_success;
1032 else SetLastError(WSAEWOULDBLOCK);
1033 close(fd);
1035 else
1037 SetLastError(wsaErrno());
1038 close(fd);
1041 #ifdef HAVE_IPX
1042 if (name && ((struct sockaddr_ipx *)name)->sipx_family == AF_IPX)
1043 free(name);
1044 #endif
1045 return SOCKET_ERROR;
1046 connect_success:
1047 #ifdef HAVE_IPX
1048 if (((struct sockaddr_ipx *)name)->sipx_family == AF_IPX)
1049 free(name);
1050 #endif
1051 _enable_event(s, FD_CONNECT|FD_READ|FD_WRITE,
1052 WS_FD_CONNECTED|WS_FD_READ|WS_FD_WRITE,
1053 WS_FD_CONNECT|WS_FD_LISTENING);
1054 return 0;
1057 /***********************************************************************
1058 * connect() (WINSOCK.4)
1060 INT16 WINAPI WINSOCK_connect16(SOCKET16 s, struct sockaddr *name, INT16 namelen)
1062 return (INT16)WSOCK32_connect( s, name, namelen );
1065 /***********************************************************************
1066 * getpeername() (WSOCK32.5)
1068 INT WINAPI WSOCK32_getpeername(SOCKET s, struct sockaddr *name,
1069 INT *namelen)
1071 LPWSINFO pwsi = WINSOCK_GetIData();
1072 #ifdef HAVE_IPX
1073 struct ws_sockaddr_ipx* name2 = (struct ws_sockaddr_ipx *)name;
1074 #endif
1076 TRACE("(%08x): socket: %04x, ptr %8x, ptr %8x\n",
1077 (unsigned)pwsi, s, (int) name, *namelen);
1078 if( _check_ws(pwsi, s) )
1080 int fd = _get_sock_fd(s);
1081 if (getpeername(fd, name, namelen) == 0) {
1082 #ifdef HAVE_IPX
1083 if (((struct ws_sockaddr_ipx *)name)->sipx_family == AF_IPX) {
1084 name = (struct sockaddr *)
1085 malloc(namelen ? *namelen : sizeof(*name2));
1086 memcpy(name, name2, namelen ? *namelen : sizeof(*name2));
1087 name2->sipx_family = WS_AF_IPX;
1088 name2->sipx_network = ((struct sockaddr_ipx *)name)->sipx_network;
1089 name2->sipx_port = ((struct sockaddr_ipx *)name)->sipx_port;
1090 memcpy(name2->sipx_node,
1091 ((struct sockaddr_ipx *)name)->sipx_node, IPX_NODE_LEN);
1092 free(name);
1094 #endif
1095 close(fd);
1096 return 0;
1098 SetLastError(wsaErrno());
1099 close(fd);
1101 return SOCKET_ERROR;
1104 /***********************************************************************
1105 * getpeername() (WINSOCK.5)
1107 INT16 WINAPI WINSOCK_getpeername16(SOCKET16 s, struct sockaddr *name,
1108 INT16 *namelen16)
1110 INT namelen32 = *namelen16;
1111 INT retVal = WSOCK32_getpeername( s, name, &namelen32 );
1113 #if DEBUG_SOCKADDR
1114 dump_sockaddr(name);
1115 #endif
1117 *namelen16 = namelen32;
1118 return (INT16)retVal;
1121 /***********************************************************************
1122 * getsockname() (WSOCK32.6)
1124 INT WINAPI WSOCK32_getsockname(SOCKET s, struct sockaddr *name,
1125 INT *namelen)
1127 LPWSINFO pwsi = WINSOCK_GetIData();
1128 #ifdef HAVE_IPX
1129 struct ws_sockaddr_ipx* name2 = (struct ws_sockaddr_ipx *)name;
1130 #endif
1132 TRACE("(%08x): socket: %04x, ptr %8x, ptr %8x\n",
1133 (unsigned)pwsi, s, (int) name, (int) *namelen);
1134 if( _check_ws(pwsi, s) )
1136 int fd = _get_sock_fd(s);
1137 if (getsockname(fd, name, namelen) == 0) {
1138 #ifdef HAVE_IPX
1139 if (((struct sockaddr_ipx *)name)->sipx_family == AF_IPX) {
1140 name = (struct sockaddr *)
1141 malloc(namelen ? *namelen : sizeof(*name2));
1142 memcpy(name, name2, namelen ? *namelen : sizeof(*name2));
1143 name2->sipx_family = WS_AF_IPX;
1144 name2->sipx_network = ((struct sockaddr_ipx *)name)->sipx_network;
1145 name2->sipx_port = ((struct sockaddr_ipx *)name)->sipx_port;
1146 memcpy(name2->sipx_node,
1147 ((struct sockaddr_ipx *)name)->sipx_node, IPX_NODE_LEN);
1148 free(name);
1150 #endif
1151 close(fd);
1152 return 0;
1154 SetLastError(wsaErrno());
1155 close(fd);
1157 return SOCKET_ERROR;
1160 /***********************************************************************
1161 * getsockname() (WINSOCK.6)
1163 INT16 WINAPI WINSOCK_getsockname16(SOCKET16 s, struct sockaddr *name,
1164 INT16 *namelen16)
1166 INT retVal;
1168 if( namelen16 )
1170 INT namelen32 = *namelen16;
1171 retVal = WSOCK32_getsockname( s, name, &namelen32 );
1172 *namelen16 = namelen32;
1174 #if DEBUG_SOCKADDR
1175 dump_sockaddr(name);
1176 #endif
1179 else retVal = SOCKET_ERROR;
1180 return (INT16)retVal;
1184 /***********************************************************************
1185 * getsockopt() (WSOCK32.7)
1187 INT WINAPI WSOCK32_getsockopt(SOCKET s, INT level,
1188 INT optname, char *optval, INT *optlen)
1190 LPWSINFO pwsi = WINSOCK_GetIData();
1192 TRACE("(%08x): socket: %04x, opt %d, ptr %8x, ptr %8x\n",
1193 (unsigned)pwsi, s, level, (int) optval, (int) *optlen);
1194 if( _check_ws(pwsi, s) )
1196 int fd = _get_sock_fd(s);
1197 convert_sockopt(&level, &optname);
1198 if (getsockopt(fd, (int) level, optname, optval, optlen) == 0 )
1200 close(fd);
1201 return 0;
1203 SetLastError((errno == EBADF) ? WSAENOTSOCK : wsaErrno());
1204 close(fd);
1206 return SOCKET_ERROR;
1209 /***********************************************************************
1210 * getsockopt() (WINSOCK.7)
1212 INT16 WINAPI WINSOCK_getsockopt16(SOCKET16 s, INT16 level,
1213 INT16 optname, char *optval, INT16 *optlen)
1215 INT optlen32;
1216 INT *p = &optlen32;
1217 INT retVal;
1218 if( optlen ) optlen32 = *optlen; else p = NULL;
1219 retVal = WSOCK32_getsockopt( s, (UINT16)level, optname, optval, p );
1220 if( optlen ) *optlen = optlen32;
1221 return (INT16)retVal;
1224 /***********************************************************************
1225 * htonl() (WINSOCK.8)(WSOCK32.8)
1227 u_long WINAPI WINSOCK_htonl(u_long hostlong) { return( htonl(hostlong) ); }
1228 /***********************************************************************
1229 * htons() (WINSOCK.9)(WSOCK32.9)
1231 u_short WINAPI WINSOCK_htons(u_short hostshort) { return( htons(hostshort) ); }
1232 /***********************************************************************
1233 * inet_addr() (WINSOCK.10)(WSOCK32.10)
1235 u_long WINAPI WINSOCK_inet_addr(char *cp) { return( inet_addr(cp) ); }
1236 /***********************************************************************
1237 * ntohl() (WINSOCK.14)(WSOCK32.14)
1239 u_long WINAPI WINSOCK_ntohl(u_long netlong) { return( ntohl(netlong) ); }
1240 /***********************************************************************
1241 * ntohs() (WINSOCK.15)(WSOCK32.15)
1243 u_short WINAPI WINSOCK_ntohs(u_short netshort) { return( ntohs(netshort) ); }
1245 /***********************************************************************
1246 * inet_ntoa() (WINSOCK.11)(WSOCK32.11)
1248 char* WINAPI WSOCK32_inet_ntoa(struct in_addr in)
1250 /* use "buffer for dummies" here because some applications have
1251 * propensity to decode addresses in ws_hostent structure without
1252 * saving them first...
1255 LPWSINFO pwsi = WINSOCK_GetIData();
1257 if( pwsi )
1259 char* s = inet_ntoa(in);
1260 if( s )
1262 if( pwsi->dbuffer == NULL ) {
1263 /* Yes, 16: 4*3 digits + 3 '.' + 1 '\0' */
1264 if((pwsi->dbuffer = (char*) SEGPTR_ALLOC(16)) == NULL )
1266 SetLastError(WSAENOBUFS);
1267 return NULL;
1270 strcpy(pwsi->dbuffer, s);
1271 return pwsi->dbuffer;
1273 SetLastError(wsaErrno());
1275 return NULL;
1278 SEGPTR WINAPI WINSOCK_inet_ntoa16(struct in_addr in)
1280 char* retVal = WSOCK32_inet_ntoa(in);
1281 return retVal ? SEGPTR_GET(retVal) : (SEGPTR)NULL;
1285 /**********************************************************************
1286 * WSAIoctl (WS2_32)
1289 * FIXME: Only SIO_GET_INTERFACE_LIST option implemented.
1291 INT WINAPI WSAIoctl (SOCKET s,
1292 DWORD dwIoControlCode,
1293 LPVOID lpvInBuffer,
1294 DWORD cbInBuffer,
1295 LPVOID lpbOutBuffer,
1296 DWORD cbOutBuffer,
1297 LPDWORD lpcbBytesReturned,
1298 LPWSAOVERLAPPED lpOverlapped,
1299 LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine)
1301 LPWSINFO pwsi = WINSOCK_GetIData();
1303 if( _check_ws(pwsi, s) )
1305 int fd = _get_sock_fd(s);
1307 switch( dwIoControlCode )
1309 case SIO_GET_INTERFACE_LIST:
1311 INTERFACE_INFO* intArray = (INTERFACE_INFO*)lpbOutBuffer;
1312 int i, numInt;
1313 struct ifreq ifInfo;
1314 char ifName[512];
1317 TRACE ("-> SIO_GET_INTERFACE_LIST request\n");
1319 numInt = WSAIOCTL_GetInterfaceCount();
1320 if (numInt < 0)
1322 ERR ("Unable to open /proc filesystem to determine number of network interfaces!\n");
1323 close(fd);
1324 WSASetLastError(WSAEINVAL);
1325 return (SOCKET_ERROR);
1328 for (i=0; i<numInt; i++)
1330 if (!WSAIOCTL_GetInterfaceName(i, ifName))
1332 ERR ("Error parsing /proc filesystem!\n");
1333 close(fd);
1334 WSASetLastError(WSAEINVAL);
1335 return (SOCKET_ERROR);
1338 ifInfo.ifr_addr.sa_family = AF_INET;
1340 /* IP Address */
1341 strcpy (ifInfo.ifr_name, ifName);
1342 if (ioctl(fd, SIOCGIFADDR, &ifInfo) < 0)
1344 ERR ("Error obtaining IP address\n");
1345 close(fd);
1346 WSASetLastError(WSAEINVAL);
1347 return (SOCKET_ERROR);
1349 else
1351 struct ws_sockaddr_in *ipTemp = (struct ws_sockaddr_in *)&ifInfo.ifr_addr;
1353 intArray->iiAddress.AddressIn.sin_family = AF_INET;
1354 intArray->iiAddress.AddressIn.sin_port = ipTemp->sin_port;
1355 intArray->iiAddress.AddressIn.sin_addr.ws_addr = ipTemp->sin_addr.S_un.S_addr;
1358 /* Broadcast Address */
1359 strcpy (ifInfo.ifr_name, ifName);
1360 if (ioctl(fd, SIOCGIFBRDADDR, &ifInfo) < 0)
1362 ERR ("Error obtaining Broadcast IP address\n");
1363 close(fd);
1364 WSASetLastError(WSAEINVAL);
1365 return (SOCKET_ERROR);
1367 else
1369 struct ws_sockaddr_in *ipTemp = (struct ws_sockaddr_in *)&ifInfo.ifr_broadaddr;
1371 intArray->iiBroadcastAddress.AddressIn.sin_family = AF_INET;
1372 intArray->iiBroadcastAddress.AddressIn.sin_port = ipTemp->sin_port;
1373 intArray->iiBroadcastAddress.AddressIn.sin_addr.ws_addr = ipTemp->sin_addr.S_un.S_addr;
1376 /* Subnet Mask */
1377 strcpy (ifInfo.ifr_name, ifName);
1378 if (ioctl(fd, SIOCGIFNETMASK, &ifInfo) < 0)
1380 ERR ("Error obtaining Subnet IP address\n");
1381 close(fd);
1382 WSASetLastError(WSAEINVAL);
1383 return (SOCKET_ERROR);
1385 else
1387 struct ws_sockaddr_in *ipTemp = (struct ws_sockaddr_in *)&ifInfo.ifr_netmask;
1389 intArray->iiNetmask.AddressIn.sin_family = AF_INET;
1390 intArray->iiNetmask.AddressIn.sin_port = ipTemp->sin_port;
1391 intArray->iiNetmask.AddressIn.sin_addr.ws_addr = ipTemp->sin_addr.S_un.S_addr;
1394 /* Socket Status Flags */
1395 strcpy(ifInfo.ifr_name, ifName);
1396 if (ioctl(fd, SIOCGIFFLAGS, &ifInfo) < 0)
1398 ERR ("Error obtaining status flags for socket!\n");
1399 close(fd);
1400 WSASetLastError(WSAEINVAL);
1401 return (SOCKET_ERROR);
1403 else
1405 /* FIXME - Is this the right flag to use? */
1406 intArray->iiFlags = ifInfo.ifr_flags;
1408 intArray++; /* Prepare for another interface */
1411 /* Calculate the size of the array being returned */
1412 *lpcbBytesReturned = sizeof(INTERFACE_INFO) * numInt;
1413 break;
1416 default:
1418 WARN("\tunsupported WS_IOCTL cmd (%08lx)\n", dwIoControlCode);
1419 close(fd);
1420 WSASetLastError(WSAEOPNOTSUPP);
1421 return (SOCKET_ERROR);
1425 /* Function executed with no errors */
1426 close(fd);
1427 return (0);
1429 else
1431 WSASetLastError(WSAENOTSOCK);
1432 return (SOCKET_ERROR);
1438 Helper function for WSAIoctl - Get count of the number of interfaces
1439 by parsing /proc filesystem.
1441 int WSAIOCTL_GetInterfaceCount(void)
1443 FILE *procfs;
1444 char buf[512]; /* Size doesn't matter, something big */
1445 int intcnt=0;
1448 /* Open /proc filesystem file for network devices */
1449 procfs = fopen(PROCFS_NETDEV_FILE, "r");
1450 if (!procfs)
1452 /* If we can't open the file, return an error */
1453 return (-1);
1456 /* Omit first two lines, they are only headers */
1457 fgets(buf, sizeof buf, procfs);
1458 fgets(buf, sizeof buf, procfs);
1460 while (fgets(buf, sizeof buf, procfs))
1462 /* Each line in the file represents a network interface */
1463 intcnt++;
1466 fclose(procfs);
1467 return(intcnt);
1472 Helper function for WSAIoctl - Get name of device from interface number
1473 by parsing /proc filesystem.
1475 int WSAIOCTL_GetInterfaceName(int intNumber, char *intName)
1477 FILE *procfs;
1478 char buf[512]; /* Size doesn't matter, something big */
1479 int i;
1481 /* Open /proc filesystem file for network devices */
1482 procfs = fopen(PROCFS_NETDEV_FILE, "r");
1483 if (!procfs)
1485 /* If we can't open the file, return an error */
1486 return (-1);
1489 /* Omit first two lines, they are only headers */
1490 fgets(buf, sizeof(buf), procfs);
1491 fgets(buf, sizeof(buf), procfs);
1493 for (i=0; i<intNumber; i++)
1495 /* Skip the lines that don't interest us. */
1496 fgets(buf, sizeof(buf), procfs);
1498 fgets(buf, sizeof(buf), procfs); /* This is the line we want */
1501 /* Parse out the line, grabbing only the name of the device
1502 to the intName variable
1504 The Line comes in like this: (we only care about the device name)
1505 lo: 21970 377 0 0 0 0 0 0 21970 377 0 0 0 0 0 0
1507 i=0;
1508 while (isspace(buf[i])) /* Skip initial space(s) */
1510 i++;
1513 while (buf[i])
1515 if (isspace(buf[i]))
1517 break;
1520 if (buf[i] == ':') /* FIXME: Not sure if this block (alias detection) works properly */
1522 /* This interface could be an alias... */
1523 int hold = i;
1524 char *dotname = intName;
1525 *intName++ = buf[i++];
1527 while (isdigit(buf[i]))
1529 *intName++ = buf[i++];
1532 if (buf[i] != ':')
1534 /* ... It wasn't, so back up */
1535 i = hold;
1536 intName = dotname;
1539 if (buf[i] == '\0')
1541 fclose(procfs);
1542 return(FALSE);
1545 i++;
1546 break;
1549 *intName++ = buf[i++];
1551 *intName++ = '\0';
1553 fclose(procfs);
1554 return(TRUE);
1558 /***********************************************************************
1559 * ioctlsocket() (WSOCK32.12)
1561 INT WINAPI WSOCK32_ioctlsocket(SOCKET s, LONG cmd, ULONG *argp)
1563 LPWSINFO pwsi = WINSOCK_GetIData();
1565 TRACE("(%08x): socket %04x, cmd %08lx, ptr %8x\n",
1566 (unsigned)pwsi, s, cmd, (unsigned) argp);
1567 if( _check_ws(pwsi, s) )
1569 int fd = _get_sock_fd(s);
1570 long newcmd = cmd;
1572 switch( cmd )
1574 case WS_FIONREAD:
1575 newcmd=FIONREAD;
1576 break;
1578 case WS_FIONBIO:
1579 newcmd=FIONBIO;
1580 if( _get_sock_mask(s) )
1582 /* AsyncSelect()'ed sockets are always nonblocking */
1583 if (*argp) {
1584 close(fd);
1585 return 0;
1587 SetLastError(WSAEINVAL);
1588 close(fd);
1589 return SOCKET_ERROR;
1591 close(fd);
1592 if (*argp)
1593 _enable_event(s, 0, WS_FD_NONBLOCKING, 0);
1594 else
1595 _enable_event(s, 0, 0, WS_FD_NONBLOCKING);
1596 return 0;
1598 case WS_SIOCATMARK:
1599 newcmd=SIOCATMARK;
1600 break;
1602 case WS_IOW('f',125,u_long):
1603 WARN("Warning: WS1.1 shouldn't be using async I/O\n");
1604 SetLastError(WSAEINVAL);
1605 return SOCKET_ERROR;
1607 default:
1608 /* Netscape tries hard to use bogus ioctl 0x667e */
1609 WARN("\tunknown WS_IOCTL cmd (%08lx)\n", cmd);
1611 if( ioctl(fd, newcmd, (char*)argp ) == 0 )
1613 close(fd);
1614 return 0;
1616 SetLastError((errno == EBADF) ? WSAENOTSOCK : wsaErrno());
1617 close(fd);
1619 return SOCKET_ERROR;
1622 /***********************************************************************
1623 * ioctlsocket() (WINSOCK.12)
1625 INT16 WINAPI WINSOCK_ioctlsocket16(SOCKET16 s, LONG cmd, ULONG *argp)
1627 return (INT16)WSOCK32_ioctlsocket( s, cmd, argp );
1631 /***********************************************************************
1632 * listen() (WSOCK32.13)
1634 INT WINAPI WSOCK32_listen(SOCKET s, INT backlog)
1636 LPWSINFO pwsi = WINSOCK_GetIData();
1638 TRACE("(%08x): socket %04x, backlog %d\n",
1639 (unsigned)pwsi, s, backlog);
1640 if( _check_ws(pwsi, s) )
1642 int fd = _get_sock_fd(s);
1643 if (listen(fd, backlog) == 0)
1645 close(fd);
1646 _enable_event(s, FD_ACCEPT,
1647 WS_FD_LISTENING,
1648 WS_FD_CONNECT|WS_FD_CONNECTED);
1649 return 0;
1651 SetLastError(wsaErrno());
1653 else SetLastError(WSAENOTSOCK);
1654 return SOCKET_ERROR;
1657 /***********************************************************************
1658 * listen() (WINSOCK.13)
1660 INT16 WINAPI WINSOCK_listen16(SOCKET16 s, INT16 backlog)
1662 return (INT16)WSOCK32_listen( s, backlog );
1666 /***********************************************************************
1667 * recv() (WSOCK32.16)
1669 INT WINAPI WSOCK32_recv(SOCKET s, char *buf, INT len, INT flags)
1671 LPWSINFO pwsi = WINSOCK_GetIData();
1673 TRACE("(%08x): socket %04x, buf %8x, len %d, "
1674 "flags %d\n", (unsigned)pwsi, s, (unsigned)buf,
1675 len, flags);
1676 if( _check_ws(pwsi, s) )
1678 int fd = _get_sock_fd(s);
1679 INT length;
1681 if (_is_blocking(s))
1683 /* block here */
1684 /* FIXME: OOB and exceptfds? */
1685 do_block(fd, 1);
1687 if ((length = recv(fd, buf, len, flags)) >= 0)
1689 TRACE(" -> %i bytes\n", length);
1691 close(fd);
1692 _enable_event(s, FD_READ, 0, 0);
1693 return length;
1695 SetLastError(wsaErrno());
1696 close(fd);
1698 else SetLastError(WSAENOTSOCK);
1699 WARN(" -> ERROR\n");
1700 return SOCKET_ERROR;
1703 /***********************************************************************
1704 * recv() (WINSOCK.16)
1706 INT16 WINAPI WINSOCK_recv16(SOCKET16 s, char *buf, INT16 len, INT16 flags)
1708 return (INT16)WSOCK32_recv( s, buf, len, flags );
1712 /***********************************************************************
1713 * recvfrom() (WSOCK32.17)
1715 INT WINAPI WSOCK32_recvfrom(SOCKET s, char *buf, INT len, INT flags,
1716 struct sockaddr *from, INT *fromlen32)
1718 LPWSINFO pwsi = WINSOCK_GetIData();
1719 #ifdef HAVE_IPX
1720 struct ws_sockaddr_ipx* from2 = (struct ws_sockaddr_ipx *)from;
1721 #endif
1723 TRACE("(%08x): socket %04x, ptr %08x, "
1724 "len %d, flags %d\n", (unsigned)pwsi, s, (unsigned)buf,
1725 len, flags);
1726 #if DEBUG_SOCKADDR
1727 if( from ) dump_sockaddr(from);
1728 else DPRINTF("from = NULL\n");
1729 #endif
1731 if( _check_ws(pwsi, s) )
1733 int fd = _get_sock_fd(s);
1734 int length;
1736 if (_is_blocking(s))
1738 /* block here */
1739 /* FIXME: OOB and exceptfds */
1740 do_block(fd, 1);
1742 if ((length = recvfrom(fd, buf, len, flags, from, fromlen32)) >= 0)
1744 TRACE(" -> %i bytes\n", length);
1746 #ifdef HAVE_IPX
1747 if (from && ((struct sockaddr_ipx *)from)->sipx_family == AF_IPX) {
1748 from = (struct sockaddr *)
1749 malloc(fromlen32 ? *fromlen32 : sizeof(*from2));
1750 memcpy(from, from2, fromlen32 ? *fromlen32 : sizeof(*from2));
1751 from2->sipx_family = WS_AF_IPX;
1752 from2->sipx_network = ((struct sockaddr_ipx *)from)->sipx_network;
1753 from2->sipx_port = ((struct sockaddr_ipx *)from)->sipx_port;
1754 memcpy(from2->sipx_node,
1755 ((struct sockaddr_ipx *)from)->sipx_node, IPX_NODE_LEN);
1756 free(from);
1758 #endif
1759 close(fd);
1760 _enable_event(s, FD_READ, 0, 0);
1761 return (INT16)length;
1763 SetLastError(wsaErrno());
1764 close(fd);
1766 else SetLastError(WSAENOTSOCK);
1767 WARN(" -> ERROR\n");
1768 #ifdef HAVE_IPX
1769 if (from && ((struct sockaddr_ipx *)from)->sipx_family == AF_IPX) {
1770 from = (struct sockaddr *)
1771 malloc(fromlen32 ? *fromlen32 : sizeof(*from2));
1772 memcpy(from, from2, fromlen32 ? *fromlen32 : sizeof(*from2));
1773 from2->sipx_family = WS_AF_IPX;
1774 from2->sipx_network = ((struct sockaddr_ipx *)from)->sipx_network;
1775 from2->sipx_port = ((struct sockaddr_ipx *)from)->sipx_port;
1776 memcpy(from2->sipx_node,
1777 ((struct sockaddr_ipx *)from)->sipx_node, IPX_NODE_LEN);
1778 free(from);
1780 #endif
1781 return SOCKET_ERROR;
1784 /***********************************************************************
1785 * recvfrom() (WINSOCK.17)
1787 INT16 WINAPI WINSOCK_recvfrom16(SOCKET16 s, char *buf, INT16 len, INT16 flags,
1788 struct sockaddr *from, INT16 *fromlen16)
1790 INT fromlen32;
1791 INT *p = &fromlen32;
1792 INT retVal;
1794 if( fromlen16 ) fromlen32 = *fromlen16; else p = NULL;
1795 retVal = WSOCK32_recvfrom( s, buf, len, flags, from, p );
1796 if( fromlen16 ) *fromlen16 = fromlen32;
1797 return (INT16)retVal;
1800 /***********************************************************************
1801 * select() (WINSOCK.18)(WSOCK32.18)
1803 static INT __ws_select( BOOL b32, void *ws_readfds, void *ws_writefds, void *ws_exceptfds,
1804 struct timeval *timeout )
1806 LPWSINFO pwsi = WINSOCK_GetIData();
1808 TRACE("(%08x): read %8x, write %8x, excp %8x\n",
1809 (unsigned) pwsi, (unsigned) ws_readfds, (unsigned) ws_writefds, (unsigned) ws_exceptfds);
1811 if( pwsi )
1813 int highfd = 0;
1814 fd_set readfds, writefds, exceptfds;
1815 fd_set *p_read, *p_write, *p_except;
1816 int readfd[FD_SETSIZE], writefd[FD_SETSIZE], exceptfd[FD_SETSIZE];
1818 p_read = fd_set_import(&readfds, pwsi, ws_readfds, &highfd, readfd, b32);
1819 p_write = fd_set_import(&writefds, pwsi, ws_writefds, &highfd, writefd, b32);
1820 p_except = fd_set_import(&exceptfds, pwsi, ws_exceptfds, &highfd, exceptfd, b32);
1822 if( (highfd = select(highfd + 1, p_read, p_write, p_except, timeout)) > 0 )
1824 fd_set_export(pwsi, &readfds, p_except, ws_readfds, readfd, b32);
1825 fd_set_export(pwsi, &writefds, p_except, ws_writefds, writefd, b32);
1827 if (p_except && ws_exceptfds)
1829 #define wsfds16 ((ws_fd_set16*)ws_exceptfds)
1830 #define wsfds32 ((ws_fd_set32*)ws_exceptfds)
1831 int i, j, count = (b32) ? wsfds32->fd_count : wsfds16->fd_count;
1833 for (i = j = 0; i < count; i++)
1835 int fd = exceptfd[i];
1836 if( fd >= 0 && FD_ISSET(fd, &exceptfds) )
1838 if( b32 )
1839 wsfds32->fd_array[j++] = wsfds32->fd_array[i];
1840 else
1841 wsfds16->fd_array[j++] = wsfds16->fd_array[i];
1843 if( fd >= 0 ) close(fd);
1844 exceptfd[i] = -1;
1846 if( b32 )
1847 wsfds32->fd_count = j;
1848 else
1849 wsfds16->fd_count = j;
1850 #undef wsfds32
1851 #undef wsfds16
1853 return highfd;
1855 fd_set_unimport(ws_readfds, readfd, b32);
1856 fd_set_unimport(ws_writefds, writefd, b32);
1857 fd_set_unimport(ws_exceptfds, exceptfd, b32);
1858 if( ws_readfds ) ((ws_fd_set32*)ws_readfds)->fd_count = 0;
1859 if( ws_writefds ) ((ws_fd_set32*)ws_writefds)->fd_count = 0;
1860 if( ws_exceptfds ) ((ws_fd_set32*)ws_exceptfds)->fd_count = 0;
1862 if( highfd == 0 ) return 0;
1863 SetLastError(wsaErrno());
1865 return SOCKET_ERROR;
1868 INT16 WINAPI WINSOCK_select16(INT16 nfds, ws_fd_set16 *ws_readfds,
1869 ws_fd_set16 *ws_writefds, ws_fd_set16 *ws_exceptfds,
1870 struct timeval *timeout)
1872 return (INT16)__ws_select( FALSE, ws_readfds, ws_writefds, ws_exceptfds, timeout );
1875 INT WINAPI WSOCK32_select(INT nfds, ws_fd_set32 *ws_readfds,
1876 ws_fd_set32 *ws_writefds, ws_fd_set32 *ws_exceptfds,
1877 struct timeval *timeout)
1879 /* struct timeval is the same for both 32- and 16-bit code */
1880 return (INT)__ws_select( TRUE, ws_readfds, ws_writefds, ws_exceptfds, timeout );
1884 /***********************************************************************
1885 * send() (WSOCK32.19)
1887 INT WINAPI WSOCK32_send(SOCKET s, char *buf, INT len, INT flags)
1889 LPWSINFO pwsi = WINSOCK_GetIData();
1891 TRACE("(%08x): socket %04x, ptr %08x, length %d, flags %d\n",
1892 (unsigned)pwsi, s, (unsigned) buf, len, flags);
1893 if( _check_ws(pwsi, s) )
1895 int fd = _get_sock_fd(s);
1896 int length;
1898 if (_is_blocking(s))
1900 /* block here */
1901 /* FIXME: exceptfds */
1902 do_block(fd, 2);
1904 if ((length = send(fd, buf, len, flags)) < 0 )
1906 SetLastError(wsaErrno());
1907 if( GetLastError() == WSAEWOULDBLOCK )
1908 _enable_event(s, FD_WRITE, 0, 0);
1910 else
1912 close(fd);
1913 return (INT16)length;
1915 close(fd);
1917 else SetLastError(WSAENOTSOCK);
1918 return SOCKET_ERROR;
1921 /***********************************************************************
1922 * send() (WINSOCK.19)
1924 INT16 WINAPI WINSOCK_send16(SOCKET16 s, char *buf, INT16 len, INT16 flags)
1926 return WSOCK32_send( s, buf, len, flags );
1929 /***********************************************************************
1930 * sendto() (WSOCK32.20)
1932 INT WINAPI WSOCK32_sendto(SOCKET s, char *buf, INT len, INT flags,
1933 struct sockaddr *to, INT tolen)
1935 LPWSINFO pwsi = WINSOCK_GetIData();
1936 #ifdef HAVE_IPX
1937 struct ws_sockaddr_ipx* to2 = (struct ws_sockaddr_ipx *)to;
1938 #endif
1940 TRACE("(%08x): socket %04x, ptr %08x, length %d, flags %d\n",
1941 (unsigned)pwsi, s, (unsigned) buf, len, flags);
1942 if( _check_ws(pwsi, s) )
1944 int fd = _get_sock_fd(s);
1945 INT length;
1947 if (to && ((struct ws_sockaddr_ipx *)to)->sipx_family == WS_AF_PUP)
1948 ((struct ws_sockaddr_ipx *)to)->sipx_family = AF_UNSPEC;
1949 #ifdef HAVE_IPX
1950 else if (to &&
1951 ((struct ws_sockaddr_ipx *)to)->sipx_family == WS_AF_IPX)
1953 to = (struct sockaddr *) malloc(sizeof(struct sockaddr_ipx));
1954 memset(to, '\0', sizeof(struct sockaddr_ipx));
1955 ((struct sockaddr_ipx *)to)->sipx_family = AF_IPX;
1956 ((struct sockaddr_ipx *)to)->sipx_port = to2->sipx_port;
1957 ((struct sockaddr_ipx *)to)->sipx_network = to2->sipx_network;
1958 memcpy(((struct sockaddr_ipx *)to)->sipx_node,
1959 to2->sipx_node, IPX_NODE_LEN);
1960 tolen = sizeof(struct sockaddr_ipx);
1962 #endif
1963 if (_is_blocking(s))
1965 /* block here */
1966 /* FIXME: exceptfds */
1967 do_block(fd, 2);
1969 if ((length = sendto(fd, buf, len, flags, to, tolen)) < 0 )
1971 SetLastError(wsaErrno());
1972 if( GetLastError() == WSAEWOULDBLOCK )
1973 _enable_event(s, FD_WRITE, 0, 0);
1975 else {
1976 #ifdef HAVE_IPX
1977 if (to && ((struct sockaddr_ipx *)to)->sipx_family == AF_IPX) {
1978 free(to);
1980 #endif
1981 close(fd);
1982 return length;
1984 close(fd);
1986 else SetLastError(WSAENOTSOCK);
1987 #ifdef HAVE_IPX
1988 if (to && ((struct sockaddr_ipx *)to)->sipx_family == AF_IPX) {
1989 free(to);
1991 #endif
1992 return SOCKET_ERROR;
1995 /***********************************************************************
1996 * sendto() (WINSOCK.20)
1998 INT16 WINAPI WINSOCK_sendto16(SOCKET16 s, char *buf, INT16 len, INT16 flags,
1999 struct sockaddr *to, INT16 tolen)
2001 return (INT16)WSOCK32_sendto( s, buf, len, flags, to, tolen );
2004 /***********************************************************************
2005 * setsockopt() (WSOCK32.21)
2007 INT WINAPI WSOCK32_setsockopt(SOCKET16 s, INT level, INT optname,
2008 char *optval, INT optlen)
2010 LPWSINFO pwsi = WINSOCK_GetIData();
2012 TRACE("(%08x): socket %04x, lev %d, opt %d, ptr %08x, len %d\n",
2013 (unsigned)pwsi, s, level, optname, (int) optval, optlen);
2014 if( _check_ws(pwsi, s) )
2016 struct linger linger;
2017 int fd = _get_sock_fd(s);
2018 int woptval;
2020 convert_sockopt(&level, &optname);
2021 if(optname == WS_SO_DONTLINGER) {
2022 linger.l_onoff = *((int*)optval) ? 0: 1;
2023 linger.l_linger = 0;
2024 optname=SO_LINGER;
2025 optval = (char*)&linger;
2026 optlen = sizeof(struct linger);
2027 }else{
2028 if (optname == SO_LINGER && optval) {
2029 /* yes, uses unsigned short in both win16/win32 */
2030 linger.l_onoff = ((UINT16*)optval)[0];
2031 linger.l_linger = ((UINT16*)optval)[1];
2032 /* FIXME: what is documented behavior if SO_LINGER optval
2033 is null?? */
2034 optval = (char*)&linger;
2035 optlen = sizeof(struct linger);
2036 } else if (optlen < sizeof(int)){
2037 woptval= *((INT16 *) optval);
2038 optval= (char*) &woptval;
2039 optlen=sizeof(int);
2042 if (setsockopt(fd, level, optname, optval, optlen) == 0)
2044 close(fd);
2045 return 0;
2047 SetLastError(wsaErrno());
2048 close(fd);
2050 else SetLastError(WSAENOTSOCK);
2051 return SOCKET_ERROR;
2054 /***********************************************************************
2055 * setsockopt() (WINSOCK.21)
2057 INT16 WINAPI WINSOCK_setsockopt16(SOCKET16 s, INT16 level, INT16 optname,
2058 char *optval, INT16 optlen)
2060 if( !optval ) return SOCKET_ERROR;
2061 return (INT16)WSOCK32_setsockopt( s, (UINT16)level, optname, optval, optlen );
2065 /***********************************************************************
2066 * shutdown() (WSOCK32.22)
2068 INT WINAPI WSOCK32_shutdown(SOCKET s, INT how)
2070 LPWSINFO pwsi = WINSOCK_GetIData();
2072 TRACE("(%08x): socket %04x, how %i\n",
2073 (unsigned)pwsi, s, how );
2074 if( _check_ws(pwsi, s) )
2076 int fd = _get_sock_fd(s);
2077 switch( how )
2079 case 0: /* drop receives */
2080 _enable_event(s, 0, 0, WS_FD_READ);
2081 #ifdef SHUT_RD
2082 how = SHUT_RD;
2083 #endif
2084 break;
2086 case 1: /* drop sends */
2087 _enable_event(s, 0, 0, WS_FD_WRITE);
2088 #ifdef SHUT_WR
2089 how = SHUT_WR;
2090 #endif
2091 break;
2093 case 2: /* drop all */
2094 #ifdef SHUT_RDWR
2095 how = SHUT_RDWR;
2096 #endif
2097 default:
2098 WSAAsyncSelect( s, 0, 0, 0 );
2099 break;
2102 if (shutdown(fd, how) == 0)
2104 if( how > 1 )
2106 _enable_event(s, 0, 0, WS_FD_CONNECTED|WS_FD_LISTENING);
2108 close(fd);
2109 return 0;
2111 SetLastError(wsaErrno());
2112 close(fd);
2114 else SetLastError(WSAENOTSOCK);
2115 return SOCKET_ERROR;
2118 /***********************************************************************
2119 * shutdown() (WINSOCK.22)
2121 INT16 WINAPI WINSOCK_shutdown16(SOCKET16 s, INT16 how)
2123 return (INT16)WSOCK32_shutdown( s, how );
2127 /***********************************************************************
2128 * socket() (WSOCK32.23)
2130 SOCKET WINAPI WSOCK32_socket(INT af, INT type, INT protocol)
2132 LPWSINFO pwsi = WINSOCK_GetIData();
2133 struct create_socket_request *req = get_req_buffer();
2135 TRACE("(%08x): af=%d type=%d protocol=%d\n",
2136 (unsigned)pwsi, af, type, protocol);
2138 if( pwsi )
2140 /* check the socket family */
2141 switch(af)
2143 #ifdef HAVE_IPX
2144 case WS_AF_IPX: af = AF_IPX;
2145 #endif
2146 case AF_INET:
2147 case AF_UNSPEC: break;
2148 default: SetLastError(WSAEAFNOSUPPORT);
2149 return INVALID_SOCKET;
2152 /* check the socket type */
2153 switch(type)
2155 case SOCK_STREAM:
2156 case SOCK_DGRAM:
2157 case SOCK_RAW: break;
2158 default: SetLastError(WSAESOCKTNOSUPPORT);
2159 return INVALID_SOCKET;
2162 /* check the protocol type */
2163 if ( protocol < 0 ) /* don't support negative values */
2164 { SetLastError(WSAEPROTONOSUPPORT); return INVALID_SOCKET; }
2166 if ( af == AF_UNSPEC) /* did they not specify the address family? */
2167 switch(protocol)
2169 case IPPROTO_TCP:
2170 if (type == SOCK_STREAM) { af = AF_INET; break; }
2171 case IPPROTO_UDP:
2172 if (type == SOCK_DGRAM) { af = AF_INET; break; }
2173 default: SetLastError(WSAEPROTOTYPE); return INVALID_SOCKET;
2176 req->family = af;
2177 req->type = type;
2178 req->protocol = protocol;
2179 req->access = GENERIC_READ|GENERIC_WRITE|SYNCHRONIZE;
2180 req->inherit = TRUE;
2181 sock_server_call( REQ_CREATE_SOCKET );
2182 if ( req->handle >= 0)
2184 TRACE("\tcreated %04x\n", req->handle);
2186 return req->handle;
2189 if (GetLastError() == WSAEACCES) /* raw socket denied */
2191 if (type == SOCK_RAW)
2192 MESSAGE("WARNING: Trying to create a socket of type SOCK_RAW, will fail unless running as root\n");
2193 else
2194 MESSAGE("WS_SOCKET: not enough privileges to create socket, try running as root\n");
2195 SetLastError(WSAESOCKTNOSUPPORT);
2199 WARN("\t\tfailed!\n");
2200 return INVALID_SOCKET;
2203 /***********************************************************************
2204 * socket() (WINSOCK.23)
2206 SOCKET16 WINAPI WINSOCK_socket16(INT16 af, INT16 type, INT16 protocol)
2208 return (SOCKET16)WSOCK32_socket( af, type, protocol );
2212 /* ----------------------------------- DNS services
2214 * IMPORTANT: 16-bit API structures have SEGPTR pointers inside them.
2215 * Also, we have to use wsock32 stubs to convert structures and
2216 * error codes from Unix to WSA, hence there is no direct mapping in
2217 * the relay32/wsock32.spec.
2220 static char* NULL_STRING = "NULL";
2222 /***********************************************************************
2223 * gethostbyaddr() (WINSOCK.51)(WSOCK32.51)
2225 static struct WIN_hostent* __ws_gethostbyaddr(const char *addr, int len, int type, int dup_flag)
2227 LPWSINFO pwsi = WINSOCK_GetIData();
2229 if( pwsi )
2231 struct hostent* host;
2232 if( (host = gethostbyaddr(addr, len, type)) != NULL )
2233 if( WS_dup_he(pwsi, host, dup_flag) )
2234 return (struct WIN_hostent*)(pwsi->he);
2235 else
2236 SetLastError(WSAENOBUFS);
2237 else
2238 SetLastError((h_errno < 0) ? wsaErrno() : wsaHerrno());
2240 return NULL;
2243 SEGPTR WINAPI WINSOCK_gethostbyaddr16(const char *addr, INT16 len, INT16 type)
2245 struct WIN_hostent* retval;
2246 TRACE("ptr %08x, len %d, type %d\n",
2247 (unsigned) addr, len, type);
2248 retval = __ws_gethostbyaddr( addr, len, type, WS_DUP_SEGPTR );
2249 return retval ? SEGPTR_GET(retval) : ((SEGPTR)NULL);
2252 struct WIN_hostent* WINAPI WSOCK32_gethostbyaddr(const char *addr, INT len,
2253 INT type)
2255 TRACE("ptr %08x, len %d, type %d\n",
2256 (unsigned) addr, len, type);
2257 return __ws_gethostbyaddr(addr, len, type, WS_DUP_LINEAR);
2260 /***********************************************************************
2261 * gethostbyname() (WINSOCK.52)(WSOCK32.52)
2263 static struct WIN_hostent * __ws_gethostbyname(const char *name, int dup_flag)
2265 LPWSINFO pwsi = WINSOCK_GetIData();
2267 if( pwsi )
2269 struct hostent* host;
2270 if( (host = gethostbyname(name)) != NULL )
2271 if( WS_dup_he(pwsi, host, dup_flag) )
2272 return (struct WIN_hostent*)(pwsi->he);
2273 else SetLastError(WSAENOBUFS);
2274 else SetLastError((h_errno < 0) ? wsaErrno() : wsaHerrno());
2276 return NULL;
2279 SEGPTR WINAPI WINSOCK_gethostbyname16(const char *name)
2281 struct WIN_hostent* retval;
2282 TRACE("%s\n", (name)?name:NULL_STRING);
2283 retval = __ws_gethostbyname( name, WS_DUP_SEGPTR );
2284 return (retval)? SEGPTR_GET(retval) : ((SEGPTR)NULL) ;
2287 struct WIN_hostent* WINAPI WSOCK32_gethostbyname(const char* name)
2289 TRACE("%s\n", (name)?name:NULL_STRING);
2290 return __ws_gethostbyname( name, WS_DUP_LINEAR );
2294 /***********************************************************************
2295 * getprotobyname() (WINSOCK.53)(WSOCK32.53)
2297 static struct WIN_protoent* __ws_getprotobyname(const char *name, int dup_flag)
2299 LPWSINFO pwsi = WINSOCK_GetIData();
2301 if( pwsi )
2303 struct protoent* proto;
2304 if( (proto = getprotobyname(name)) != NULL )
2305 if( WS_dup_pe(pwsi, proto, dup_flag) )
2306 return (struct WIN_protoent*)(pwsi->pe);
2307 else SetLastError(WSAENOBUFS);
2308 else {
2309 MESSAGE("protocol %s not found; You might want to add "
2310 "this to /etc/protocols\n", debugstr_a(name) );
2311 SetLastError(WSANO_DATA);
2313 } else SetLastError(WSANOTINITIALISED);
2314 return NULL;
2317 SEGPTR WINAPI WINSOCK_getprotobyname16(const char *name)
2319 struct WIN_protoent* retval;
2320 TRACE("%s\n", (name)?name:NULL_STRING);
2321 retval = __ws_getprotobyname(name, WS_DUP_SEGPTR);
2322 return retval ? SEGPTR_GET(retval) : ((SEGPTR)NULL);
2325 struct WIN_protoent* WINAPI WSOCK32_getprotobyname(const char* name)
2327 TRACE("%s\n", (name)?name:NULL_STRING);
2328 return __ws_getprotobyname(name, WS_DUP_LINEAR);
2332 /***********************************************************************
2333 * getprotobynumber() (WINSOCK.54)(WSOCK32.54)
2335 static struct WIN_protoent* __ws_getprotobynumber(int number, int dup_flag)
2337 LPWSINFO pwsi = WINSOCK_GetIData();
2339 if( pwsi )
2341 struct protoent* proto;
2342 if( (proto = getprotobynumber(number)) != NULL )
2343 if( WS_dup_pe(pwsi, proto, dup_flag) )
2344 return (struct WIN_protoent*)(pwsi->pe);
2345 else SetLastError(WSAENOBUFS);
2346 else {
2347 MESSAGE("protocol number %d not found; You might want to add "
2348 "this to /etc/protocols\n", number );
2349 SetLastError(WSANO_DATA);
2351 } else SetLastError(WSANOTINITIALISED);
2352 return NULL;
2355 SEGPTR WINAPI WINSOCK_getprotobynumber16(INT16 number)
2357 struct WIN_protoent* retval;
2358 TRACE("%i\n", number);
2359 retval = __ws_getprotobynumber(number, WS_DUP_SEGPTR);
2360 return retval ? SEGPTR_GET(retval) : ((SEGPTR)NULL);
2363 struct WIN_protoent* WINAPI WSOCK32_getprotobynumber(INT number)
2365 TRACE("%i\n", number);
2366 return __ws_getprotobynumber(number, WS_DUP_LINEAR);
2370 /***********************************************************************
2371 * getservbyname() (WINSOCK.55)(WSOCK32.55)
2373 struct WIN_servent* __ws_getservbyname(const char *name, const char *proto, int dup_flag)
2375 LPWSINFO pwsi = WINSOCK_GetIData();
2377 if( pwsi )
2379 struct servent* serv;
2380 int i = wsi_strtolo( pwsi, name, proto );
2382 if( i ) {
2383 serv = getservbyname(pwsi->buffer,
2384 proto ? (pwsi->buffer + i) : NULL);
2385 if( serv != NULL )
2386 if( WS_dup_se(pwsi, serv, dup_flag) )
2387 return (struct WIN_servent*)(pwsi->se);
2388 else SetLastError(WSAENOBUFS);
2389 else {
2390 MESSAGE("service %s protocol %s not found; You might want to add "
2391 "this to /etc/services\n", debugstr_a(pwsi->buffer),
2392 proto ? debugstr_a(pwsi->buffer+i):"*");
2393 SetLastError(WSANO_DATA);
2396 else SetLastError(WSAENOBUFS);
2397 } else SetLastError(WSANOTINITIALISED);
2398 return NULL;
2401 SEGPTR WINAPI WINSOCK_getservbyname16(const char *name, const char *proto)
2403 struct WIN_servent* retval;
2404 TRACE("'%s', '%s'\n",
2405 (name)?name:NULL_STRING, (proto)?proto:NULL_STRING);
2406 retval = __ws_getservbyname(name, proto, WS_DUP_SEGPTR);
2407 return retval ? SEGPTR_GET(retval) : ((SEGPTR)NULL);
2410 struct WIN_servent* WINAPI WSOCK32_getservbyname(const char *name, const char *proto)
2412 TRACE("'%s', '%s'\n",
2413 (name)?name:NULL_STRING, (proto)?proto:NULL_STRING);
2414 return __ws_getservbyname(name, proto, WS_DUP_LINEAR);
2418 /***********************************************************************
2419 * getservbyport() (WINSOCK.56)(WSOCK32.56)
2421 static struct WIN_servent* __ws_getservbyport(int port, const char* proto, int dup_flag)
2423 LPWSINFO pwsi = WINSOCK_GetIData();
2425 if( pwsi )
2427 struct servent* serv;
2428 if (!proto || wsi_strtolo( pwsi, proto, NULL )) {
2429 if( (serv = getservbyport(port, (proto) ? pwsi->buffer : NULL)) != NULL ) {
2430 if( WS_dup_se(pwsi, serv, dup_flag) )
2431 return (struct WIN_servent*)(pwsi->se);
2432 else SetLastError(WSAENOBUFS);
2434 else {
2435 MESSAGE("service on port %lu protocol %s not found; You might want to add "
2436 "this to /etc/services\n", (unsigned long)ntohl(port),
2437 proto ? debugstr_a(pwsi->buffer) : "*");
2438 SetLastError(WSANO_DATA);
2441 else SetLastError(WSAENOBUFS);
2442 } else SetLastError(WSANOTINITIALISED);
2443 return NULL;
2446 SEGPTR WINAPI WINSOCK_getservbyport16(INT16 port, const char *proto)
2448 struct WIN_servent* retval;
2449 TRACE("%i, '%s'\n",
2450 (int)port, (proto)?proto:NULL_STRING);
2451 retval = __ws_getservbyport(port, proto, WS_DUP_SEGPTR);
2452 return retval ? SEGPTR_GET(retval) : ((SEGPTR)NULL);
2455 struct WIN_servent* WINAPI WSOCK32_getservbyport(INT port, const char *proto)
2457 TRACE("%i, '%s'\n",
2458 (int)port, (proto)?proto:NULL_STRING);
2459 return __ws_getservbyport(port, proto, WS_DUP_LINEAR);
2463 /***********************************************************************
2464 * gethostname() (WSOCK32.57)
2466 INT WINAPI WSOCK32_gethostname(char *name, INT namelen)
2468 LPWSINFO pwsi = WINSOCK_GetIData();
2470 TRACE("(%08x): name %s, len %d\n",
2471 (unsigned)pwsi, (name)?name:NULL_STRING, namelen);
2472 if( pwsi )
2474 if (gethostname(name, namelen) == 0) return 0;
2475 SetLastError((errno == EINVAL) ? WSAEFAULT : wsaErrno());
2477 return SOCKET_ERROR;
2480 /***********************************************************************
2481 * gethostname() (WINSOCK.57)
2483 INT16 WINAPI WINSOCK_gethostname16(char *name, INT16 namelen)
2485 return (INT16)WSOCK32_gethostname(name, namelen);
2489 /* ------------------------------------- Windows sockets extensions -- *
2491 * ------------------------------------------------------------------- */
2493 /***********************************************************************
2494 * WSAEnumNetworkEvents
2496 int WINAPI WSAEnumNetworkEvents(SOCKET s, WSAEVENT hEvent, LPWSANETWORKEVENTS lpEvent)
2498 LPWSINFO pwsi = WINSOCK_GetIData();
2499 struct get_socket_event_request *req = get_req_buffer();
2501 TRACE("(%08x): %08x, hEvent %08x, lpEvent %08x\n",
2502 (unsigned)pwsi, s, hEvent, (unsigned)lpEvent );
2503 if( _check_ws(pwsi, s) )
2505 req->handle = s;
2506 req->service = TRUE;
2507 req->s_event = 0;
2508 req->c_event = hEvent;
2509 sock_server_call( REQ_GET_SOCKET_EVENT );
2510 lpEvent->lNetworkEvents = req->pmask;
2511 memcpy(lpEvent->iErrorCode, req->errors, sizeof(lpEvent->iErrorCode));
2512 return 0;
2514 else SetLastError(WSAEINVAL);
2515 return SOCKET_ERROR;
2518 /***********************************************************************
2519 * WSAEventSelect
2521 int WINAPI WSAEventSelect(SOCKET s, WSAEVENT hEvent, LONG lEvent)
2523 LPWSINFO pwsi = WINSOCK_GetIData();
2524 struct set_socket_event_request *req = get_req_buffer();
2526 TRACE("(%08x): %08x, hEvent %08x, event %08x\n",
2527 (unsigned)pwsi, s, hEvent, (unsigned)lEvent );
2528 if( _check_ws(pwsi, s) )
2530 req->handle = s;
2531 req->mask = lEvent;
2532 req->event = hEvent;
2533 sock_server_call( REQ_SET_SOCKET_EVENT );
2534 return 0;
2536 else SetLastError(WSAEINVAL);
2537 return SOCKET_ERROR;
2540 /***********************************************************************
2541 * WSAAsyncSelect() (WINSOCK.101)(WSOCK32.101)
2544 VOID CALLBACK WINSOCK_DoAsyncEvent( ULONG_PTR ptr )
2546 ws_select_info *info = (ws_select_info*)ptr;
2547 LPWSINFO pwsi = info->pwsi;
2548 struct get_socket_event_request *req = get_req_buffer();
2549 unsigned int i, pmask, orphan = FALSE;
2551 TRACE("socket %08x, event %08x\n", info->sock, info->event);
2552 SetLastError(0);
2553 req->handle = info->sock;
2554 req->service = TRUE;
2555 req->s_event = info->event; /* <== avoid race conditions */
2556 req->c_event = info->event;
2557 sock_server_call( REQ_GET_SOCKET_EVENT );
2558 if ( (GetLastError() == WSAENOTSOCK) || (GetLastError() == WSAEINVAL) )
2560 /* orphaned event (socket closed or something) */
2561 pmask = WS_FD_SERVEVENT;
2562 orphan = TRUE;
2563 } else
2564 pmask = req->pmask;
2565 /* check for accepted sockets that needs to inherit WSAAsyncSelect */
2566 if (pmask & WS_FD_SERVEVENT) {
2567 int q;
2568 for (q=0; q<WS_ACCEPT_QUEUE; q++)
2569 if (pwsi->accept_old[q] == info->sock) {
2570 /* there's only one service thread per pwsi, no lock necessary */
2571 HANDLE as = pwsi->accept_new[q];
2572 if (as) {
2573 pwsi->accept_new[q] = 0;
2574 pwsi->accept_old[q] = 0;
2575 WSAAsyncSelect(as, info->hWnd, info->uMsg, info->lEvent);
2578 pmask &= ~WS_FD_SERVEVENT;
2580 /* dispatch network events */
2581 for (i=0; i<FD_MAX_EVENTS; i++)
2582 if (pmask & (1<<i)) {
2583 TRACE("post: event bit %d, error %d\n", i, req->errors[i]);
2584 PostMessageA(info->hWnd, info->uMsg, info->sock,
2585 WSAMAKESELECTREPLY(1<<i, req->errors[i]));
2587 /* cleanup */
2588 if (orphan)
2590 TRACE("orphaned event, self-destructing\n");
2591 /* SERVICE_Delete closes the event object */
2592 SERVICE_Delete( info->service );
2593 WS_FREE(info);
2597 INT WINAPI WSAAsyncSelect(SOCKET s, HWND hWnd, UINT uMsg, LONG lEvent)
2599 LPWSINFO pwsi = WINSOCK_GetIData();
2601 TRACE("(%08x): %04x, hWnd %04x, uMsg %08x, event %08x\n",
2602 (unsigned)pwsi, (SOCKET16)s, (HWND16)hWnd, uMsg, (unsigned)lEvent );
2603 if( _check_ws(pwsi, s) )
2605 if( lEvent )
2607 ws_select_info *info = (ws_select_info*)WS_ALLOC(sizeof(ws_select_info));
2608 if( info )
2610 HANDLE hObj = CreateEventA( NULL, TRUE, FALSE, NULL );
2611 INT err;
2613 info->sock = s;
2614 info->event = hObj;
2615 info->hWnd = hWnd;
2616 info->uMsg = uMsg;
2617 info->lEvent = lEvent;
2618 info->pwsi = pwsi;
2619 info->service = SERVICE_AddObject( hObj, WINSOCK_DoAsyncEvent, (ULONG_PTR)info );
2621 err = WSAEventSelect( s, hObj, lEvent | WS_FD_SERVEVENT );
2622 if (err) {
2623 /* SERVICE_Delete closes the event object */
2624 SERVICE_Delete( info->service );
2625 WS_FREE(info);
2626 return err;
2629 return 0; /* success */
2631 else SetLastError(WSAENOBUFS);
2633 else
2635 WSAEventSelect(s, 0, 0);
2636 return 0;
2639 else SetLastError(WSAEINVAL);
2640 return SOCKET_ERROR;
2643 INT16 WINAPI WSAAsyncSelect16(SOCKET16 s, HWND16 hWnd, UINT16 wMsg, LONG lEvent)
2645 return (INT16)WSAAsyncSelect( s, hWnd, wMsg, lEvent );
2648 /***********************************************************************
2649 * WSARecvEx() (WSOCK32.1107)
2651 * WSARecvEx is a Microsoft specific extension to winsock that is identical to recv
2652 * except that has an in/out argument call flags that has the value MSG_PARTIAL ored
2653 * into the flags parameter when a partial packet is read. This only applies to
2654 * sockets using the datagram protocol. This method does not seem to be implemented
2655 * correctly by microsoft as the winsock implementation does not set the MSG_PARTIAL
2656 * flag when a fragmented packet arrives.
2658 INT WINAPI WSARecvEx(SOCKET s, char *buf, INT len, INT *flags) {
2659 FIXME("(WSARecvEx) partial packet return value not set \n");
2661 return WSOCK32_recv(s, buf, len, *flags);
2665 /***********************************************************************
2666 * WSARecvEx16() (WINSOCK.1107)
2668 * See description for WSARecvEx()
2670 INT16 WINAPI WSARecvEx16(SOCKET16 s, char *buf, INT16 len, INT16 *flags) {
2671 FIXME("(WSARecvEx16) partial packet return value not set \n");
2673 return WINSOCK_recv16(s, buf, len, *flags);
2677 /***********************************************************************
2678 * WSACreateEvent() (WS2_32.???)
2681 WSAEVENT WINAPI WSACreateEvent(void)
2683 /* Create a manual-reset event, with initial state: unsignealed */
2684 TRACE("\n");
2686 return CreateEventA(NULL, TRUE, FALSE, NULL);
2689 /***********************************************************************
2690 * WSACloseEvent() (WS2_32.???)
2693 BOOL WINAPI WSACloseEvent(WSAEVENT event)
2695 TRACE ("event=0x%x\n", event);
2697 return CloseHandle(event);
2700 /***********************************************************************
2701 * WSASocketA() (WS2_32.???)
2704 SOCKET WINAPI WSASocketA(int af, int type, int protocol,
2705 LPWSAPROTOCOL_INFOA lpProtocolInfo,
2706 GROUP g, DWORD dwFlags)
2709 FIXME: The "advanced" parameters of WSASocketA (lpProtocolInfo,
2710 g, dwFlags) are ignored.
2713 TRACE("af=%d type=%d protocol=%d protocol_info=%p group=%d flags=0x%lx\n",
2714 af, type, protocol, lpProtocolInfo, g, dwFlags );
2716 return ( WSOCK32_socket (af, type, protocol) );
2720 /***********************************************************************
2721 * __WSAFDIsSet() (WINSOCK.151)
2723 INT16 WINAPI __WSAFDIsSet16(SOCKET16 s, ws_fd_set16 *set)
2725 int i = set->fd_count;
2727 TRACE("(%d,%8lx(%i))\n", s,(unsigned long)set, i);
2729 while (i--)
2730 if (set->fd_array[i] == s) return 1;
2731 return 0;
2734 /***********************************************************************
2735 * __WSAFDIsSet() (WSOCK32.151)
2737 INT WINAPI __WSAFDIsSet(SOCKET s, ws_fd_set32 *set)
2739 int i = set->fd_count;
2741 TRACE("(%d,%8lx(%i))\n", s,(unsigned long)set, i);
2743 while (i--)
2744 if (set->fd_array[i] == s) return 1;
2745 return 0;
2748 /***********************************************************************
2749 * WSAIsBlocking() (WINSOCK.114)(WSOCK32.114)
2751 BOOL WINAPI WSAIsBlocking(void)
2753 /* By default WinSock should set all its sockets to non-blocking mode
2754 * and poll in PeekMessage loop when processing "blocking" ones. This
2755 * function is supposed to tell if the program is in this loop. Our
2756 * blocking calls are truly blocking so we always return FALSE.
2758 * Note: It is allowed to call this function without prior WSAStartup().
2761 TRACE("\n");
2762 return FALSE;
2765 /***********************************************************************
2766 * WSACancelBlockingCall() (WINSOCK.113)(WSOCK32.113)
2768 INT WINAPI WSACancelBlockingCall(void)
2770 LPWSINFO pwsi = WINSOCK_GetIData();
2772 TRACE("(%08x)\n", (unsigned)pwsi);
2774 if( pwsi ) return 0;
2775 return SOCKET_ERROR;
2779 /***********************************************************************
2780 * WSASetBlockingHook16() (WINSOCK.109)
2782 FARPROC16 WINAPI WSASetBlockingHook16(FARPROC16 lpBlockFunc)
2784 FARPROC16 prev;
2785 LPWSINFO pwsi = WINSOCK_GetIData();
2787 TRACE("(%08x): hook %08x\n",
2788 (unsigned)pwsi, (unsigned) lpBlockFunc);
2789 if( pwsi )
2791 prev = (FARPROC16)pwsi->blocking_hook;
2792 pwsi->blocking_hook = (DWORD)lpBlockFunc;
2793 pwsi->flags &= ~WSI_BLOCKINGHOOK;
2794 return prev;
2796 return 0;
2800 /***********************************************************************
2801 * WSASetBlockingHook()
2803 FARPROC WINAPI WSASetBlockingHook(FARPROC lpBlockFunc)
2805 FARPROC prev;
2806 LPWSINFO pwsi = WINSOCK_GetIData();
2808 TRACE("(%08x): hook %08x\n",
2809 (unsigned)pwsi, (unsigned) lpBlockFunc);
2810 if( pwsi ) {
2811 prev = (FARPROC)pwsi->blocking_hook;
2812 pwsi->blocking_hook = (DWORD)lpBlockFunc;
2813 pwsi->flags |= WSI_BLOCKINGHOOK;
2814 return prev;
2816 return NULL;
2820 /***********************************************************************
2821 * WSAUnhookBlockingHook16() (WINSOCK.110)
2823 INT16 WINAPI WSAUnhookBlockingHook16(void)
2825 LPWSINFO pwsi = WINSOCK_GetIData();
2827 TRACE("(%08x)\n", (unsigned)pwsi);
2828 if( pwsi ) return (INT16)(pwsi->blocking_hook = 0);
2829 return SOCKET_ERROR;
2833 /***********************************************************************
2834 * WSAUnhookBlockingHook()
2836 INT WINAPI WSAUnhookBlockingHook(void)
2838 LPWSINFO pwsi = WINSOCK_GetIData();
2840 TRACE("(%08x)\n", (unsigned)pwsi);
2841 if( pwsi )
2843 pwsi->blocking_hook = 0;
2844 pwsi->flags &= ~WSI_BLOCKINGHOOK;
2845 return 0;
2847 return SOCKET_ERROR;
2851 /* ----------------------------------- end of API stuff */
2853 /* ----------------------------------- helper functions -
2855 * TODO: Merge WS_dup_..() stuff into one function that
2856 * would operate with a generic structure containing internal
2857 * pointers (via a template of some kind).
2860 static int list_size(char** l, int item_size)
2862 int i,j = 0;
2863 if(l)
2864 { for(i=0;l[i];i++)
2865 j += (item_size) ? item_size : strlen(l[i]) + 1;
2866 j += (i + 1) * sizeof(char*); }
2867 return j;
2870 static int list_dup(char** l_src, char* ref, char* base, int item_size)
2872 /* base is either either equal to ref or 0 or SEGPTR */
2874 char* p = ref;
2875 char** l_to = (char**)ref;
2876 int i,j,k;
2878 for(j=0;l_src[j];j++) ;
2879 p += (j + 1) * sizeof(char*);
2880 for(i=0;i<j;i++)
2881 { l_to[i] = base + (p - ref);
2882 k = ( item_size ) ? item_size : strlen(l_src[i]) + 1;
2883 memcpy(p, l_src[i], k); p += k; }
2884 l_to[i] = NULL;
2885 return (p - ref);
2888 /* ----- hostent */
2890 static int hostent_size(struct hostent* p_he)
2892 int size = 0;
2893 if( p_he )
2894 { size = sizeof(struct hostent);
2895 size += strlen(p_he->h_name) + 1;
2896 size += list_size(p_he->h_aliases, 0);
2897 size += list_size(p_he->h_addr_list, p_he->h_length ); }
2898 return size;
2901 int WS_dup_he(LPWSINFO pwsi, struct hostent* p_he, int flag)
2903 /* Convert hostent structure into ws_hostent so that the data fits
2904 * into pwsi->buffer. Internal pointers can be linear, SEGPTR, or
2905 * relative to pwsi->buffer depending on "flag" value. Returns size
2906 * of the data copied (also in the pwsi->buflen).
2909 int size = hostent_size(p_he);
2911 if( size )
2913 struct ws_hostent* p_to;
2914 char* p_name,*p_aliases,*p_addr,*p_base,*p;
2916 _check_buffer_he(pwsi, size);
2917 p_to = (struct ws_hostent*)pwsi->he;
2918 p = (char*)pwsi->he;
2919 p_base = (flag & WS_DUP_OFFSET) ? NULL
2920 : ((flag & WS_DUP_SEGPTR) ? (char*)SEGPTR_GET(p) : p);
2921 p += sizeof(struct ws_hostent);
2922 p_name = p;
2923 strcpy(p, p_he->h_name); p += strlen(p) + 1;
2924 p_aliases = p;
2925 p += list_dup(p_he->h_aliases, p, p_base + (p - (char*)pwsi->he), 0);
2926 p_addr = p;
2927 list_dup(p_he->h_addr_list, p, p_base + (p - (char*)pwsi->he), p_he->h_length);
2929 p_to->h_addrtype = (INT16)p_he->h_addrtype;
2930 p_to->h_length = (INT16)p_he->h_length;
2931 p_to->h_name = (SEGPTR)(p_base + (p_name - (char*)pwsi->he));
2932 p_to->h_aliases = (SEGPTR)(p_base + (p_aliases - (char*)pwsi->he));
2933 p_to->h_addr_list = (SEGPTR)(p_base + (p_addr - (char*)pwsi->he));
2935 size += (sizeof(struct ws_hostent) - sizeof(struct hostent));
2937 return size;
2940 /* ----- protoent */
2942 static int protoent_size(struct protoent* p_pe)
2944 int size = 0;
2945 if( p_pe )
2946 { size = sizeof(struct protoent);
2947 size += strlen(p_pe->p_name) + 1;
2948 size += list_size(p_pe->p_aliases, 0); }
2949 return size;
2952 int WS_dup_pe(LPWSINFO pwsi, struct protoent* p_pe, int flag)
2954 int size = protoent_size(p_pe);
2955 if( size )
2957 struct ws_protoent* p_to;
2958 char* p_name,*p_aliases,*p_base,*p;
2960 _check_buffer_pe(pwsi, size);
2961 p_to = (struct ws_protoent*)pwsi->pe;
2962 p = (char*)pwsi->pe;
2963 p_base = (flag & WS_DUP_OFFSET) ? NULL
2964 : ((flag & WS_DUP_SEGPTR) ? (char*)SEGPTR_GET(p) : p);
2965 p += sizeof(struct ws_protoent);
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 - (char*)pwsi->pe), 0);
2971 p_to->p_proto = (INT16)p_pe->p_proto;
2972 p_to->p_name = (SEGPTR)(p_base) + (p_name - (char*)pwsi->pe);
2973 p_to->p_aliases = (SEGPTR)((p_base) + (p_aliases - (char*)pwsi->pe));
2975 size += (sizeof(struct ws_protoent) - sizeof(struct protoent));
2977 return size;
2980 /* ----- servent */
2982 static int servent_size(struct servent* p_se)
2984 int size = 0;
2985 if( p_se )
2986 { size += sizeof(struct servent);
2987 size += strlen(p_se->s_proto) + strlen(p_se->s_name) + 2;
2988 size += list_size(p_se->s_aliases, 0); }
2989 return size;
2992 int WS_dup_se(LPWSINFO pwsi, struct servent* p_se, int flag)
2994 int size = servent_size(p_se);
2995 if( size )
2997 struct ws_servent* p_to;
2998 char* p_name,*p_aliases,*p_proto,*p_base,*p;
3000 _check_buffer_se(pwsi, size);
3001 p_to = (struct ws_servent*)pwsi->se;
3002 p = (char*)pwsi->se;
3003 p_base = (flag & WS_DUP_OFFSET) ? NULL
3004 : ((flag & WS_DUP_SEGPTR) ? (char*)SEGPTR_GET(p) : p);
3005 p += sizeof(struct ws_servent);
3006 p_name = p;
3007 strcpy(p, p_se->s_name); p += strlen(p) + 1;
3008 p_proto = p;
3009 strcpy(p, p_se->s_proto); p += strlen(p) + 1;
3010 p_aliases = p;
3011 list_dup(p_se->s_aliases, p, p_base + (p - (char*)pwsi->se), 0);
3013 p_to->s_port = (INT16)p_se->s_port;
3014 p_to->s_name = (SEGPTR)(p_base + (p_name - (char*)pwsi->se));
3015 p_to->s_proto = (SEGPTR)(p_base + (p_proto - (char*)pwsi->se));
3016 p_to->s_aliases = (SEGPTR)(p_base + (p_aliases - (char*)pwsi->se));
3018 size += (sizeof(struct ws_servent) - sizeof(struct servent));
3020 return size;
3023 /* ----------------------------------- error handling */
3025 UINT16 wsaErrno(void)
3027 int loc_errno = errno;
3028 #ifdef HAVE_STRERROR
3029 WARN("errno %d, (%s).\n", loc_errno, strerror(loc_errno));
3030 #else
3031 WARN("errno %d\n", loc_errno);
3032 #endif
3034 switch(loc_errno)
3036 case EINTR: return WSAEINTR;
3037 case EBADF: return WSAEBADF;
3038 case EPERM:
3039 case EACCES: return WSAEACCES;
3040 case EFAULT: return WSAEFAULT;
3041 case EINVAL: return WSAEINVAL;
3042 case EMFILE: return WSAEMFILE;
3043 case EWOULDBLOCK: return WSAEWOULDBLOCK;
3044 case EINPROGRESS: return WSAEINPROGRESS;
3045 case EALREADY: return WSAEALREADY;
3046 case ENOTSOCK: return WSAENOTSOCK;
3047 case EDESTADDRREQ: return WSAEDESTADDRREQ;
3048 case EMSGSIZE: return WSAEMSGSIZE;
3049 case EPROTOTYPE: return WSAEPROTOTYPE;
3050 case ENOPROTOOPT: return WSAENOPROTOOPT;
3051 case EPROTONOSUPPORT: return WSAEPROTONOSUPPORT;
3052 case ESOCKTNOSUPPORT: return WSAESOCKTNOSUPPORT;
3053 case EOPNOTSUPP: return WSAEOPNOTSUPP;
3054 case EPFNOSUPPORT: return WSAEPFNOSUPPORT;
3055 case EAFNOSUPPORT: return WSAEAFNOSUPPORT;
3056 case EADDRINUSE: return WSAEADDRINUSE;
3057 case EADDRNOTAVAIL: return WSAEADDRNOTAVAIL;
3058 case ENETDOWN: return WSAENETDOWN;
3059 case ENETUNREACH: return WSAENETUNREACH;
3060 case ENETRESET: return WSAENETRESET;
3061 case ECONNABORTED: return WSAECONNABORTED;
3062 case EPIPE:
3063 case ECONNRESET: return WSAECONNRESET;
3064 case ENOBUFS: return WSAENOBUFS;
3065 case EISCONN: return WSAEISCONN;
3066 case ENOTCONN: return WSAENOTCONN;
3067 case ESHUTDOWN: return WSAESHUTDOWN;
3068 case ETOOMANYREFS: return WSAETOOMANYREFS;
3069 case ETIMEDOUT: return WSAETIMEDOUT;
3070 case ECONNREFUSED: return WSAECONNREFUSED;
3071 case ELOOP: return WSAELOOP;
3072 case ENAMETOOLONG: return WSAENAMETOOLONG;
3073 case EHOSTDOWN: return WSAEHOSTDOWN;
3074 case EHOSTUNREACH: return WSAEHOSTUNREACH;
3075 case ENOTEMPTY: return WSAENOTEMPTY;
3076 #ifdef EPROCLIM
3077 case EPROCLIM: return WSAEPROCLIM;
3078 #endif
3079 #ifdef EUSERS
3080 case EUSERS: return WSAEUSERS;
3081 #endif
3082 #ifdef EDQUOT
3083 case EDQUOT: return WSAEDQUOT;
3084 #endif
3085 #ifdef ESTALE
3086 case ESTALE: return WSAESTALE;
3087 #endif
3088 #ifdef EREMOTE
3089 case EREMOTE: return WSAEREMOTE;
3090 #endif
3092 /* just in case we ever get here and there are no problems */
3093 case 0: return 0;
3094 default:
3095 WARN("Unknown errno %d!\n", loc_errno);
3096 return WSAEOPNOTSUPP;
3100 UINT16 wsaHerrno(void)
3102 int loc_errno = h_errno;
3104 WARN("h_errno %d.\n", loc_errno);
3106 switch(loc_errno)
3108 case HOST_NOT_FOUND: return WSAHOST_NOT_FOUND;
3109 case TRY_AGAIN: return WSATRY_AGAIN;
3110 case NO_RECOVERY: return WSANO_RECOVERY;
3111 case NO_DATA: return WSANO_DATA;
3113 case 0: return 0;
3114 default:
3115 WARN("Unknown h_errno %d!\n", loc_errno);
3116 return WSAEOPNOTSUPP;