Release 960717
[wine.git] / misc / winsocket.c
blobd90ff8200320f2e4424e5f23fb83ac8bf654fa25
1 /*
2 * based on Windows Sockets 1.1 specs
3 * (ftp.microsoft.com:/Advsys/winsock/spec11/WINSOCK.TXT)
4 *
5 * (C) 1993,1994 John Brezak, Erik Bos.
6 */
8 #include <stdio.h>
9 #include <string.h>
10 #include <signal.h>
11 #include <sys/types.h>
12 #include <sys/ipc.h>
13 #include <sys/ioctl.h>
14 #if defined(__svr4__)
15 #include <sys/filio.h>
16 #include <sys/ioccom.h>
17 #endif
18 #include <sys/msg.h>
19 #include <sys/socket.h>
20 #include <netinet/in.h>
21 #include <arpa/inet.h>
22 #include <fcntl.h>
23 #include <errno.h>
24 #include <netdb.h>
25 #include <unistd.h>
27 #include "winsock.h"
28 #include "global.h"
29 #include "stddebug.h"
30 #include "debug.h"
32 #ifdef _SCO_DS
33 #define _IOR _IOSR
34 #define _IOW _IOSW
35 #endif
37 static WORD wsa_errno;
38 static int wsa_initted;
39 static key_t wine_key = 0;
40 static FARPROC16 BlockFunction;
41 static fd_set fd_in_use;
43 extern int h_errno;
45 struct ipc_packet {
46 long mtype;
47 HANDLE handle;
48 HWND hWnd;
49 WORD wMsg;
50 LONG lParam;
53 #ifndef WINELIB
54 #pragma pack(1)
55 #endif
57 #define WINSOCK_MAX_SOCKETS 256
58 #define WINSOCK_MAX_UDPDG 1024
60 /* we are out by two with the following, is it due to byte alignment?
61 * #define IPC_PACKET_SIZE (sizeof(struct ipc_packet) - sizeof(long))
63 #define IPC_PACKET_SIZE (sizeof(struct ipc_packet) - sizeof(long) - 2)
64 /*#define MTYPE 0xb0b0eb05*/
65 #define MTYPE 0x30b0eb05
67 /* These structures are Win16 only */
69 struct WIN_hostent {
70 SEGPTR h_name WINE_PACKED; /* official name of host */
71 SEGPTR h_aliases WINE_PACKED; /* alias list */
72 INT h_addrtype WINE_PACKED; /* host address type */
73 INT h_length WINE_PACKED; /* length of address */
74 char **h_addr_list WINE_PACKED; /* list of addresses from name server */
75 char *names[2];
76 char hostname[200];
79 struct WIN_protoent {
80 SEGPTR p_name WINE_PACKED; /* official protocol name */
81 SEGPTR p_aliases WINE_PACKED; /* alias list */
82 INT p_proto WINE_PACKED; /* protocol # */
85 struct WIN_servent {
86 SEGPTR s_name WINE_PACKED; /* official service name */
87 SEGPTR s_aliases WINE_PACKED; /* alias list */
88 INT s_port WINE_PACKED; /* port # */
89 SEGPTR s_proto WINE_PACKED; /* protocol to use */
92 struct WinSockHeap {
93 char ntoa_buffer[32];
95 struct WIN_hostent hostent_addr;
96 struct WIN_hostent hostent_name;
97 struct WIN_protoent protoent_name;
98 struct WIN_protoent protoent_number;
99 struct WIN_servent servent_name;
100 struct WIN_servent servent_port;
102 struct WIN_hostent WSAhostent_addr;
103 struct WIN_hostent WSAhostent_name;
104 struct WIN_protoent WSAprotoent_name;
105 struct WIN_protoent WSAprotoent_number;
106 struct WIN_servent WSAservent_name;
107 struct WIN_servent WSAservent_port;
108 /* 8K scratch buffer for aliases and friends are hopefully enough */
109 char scratch[8192];
111 static struct WinSockHeap *Heap;
112 static HANDLE HeapHandle;
113 #ifndef WINELIB32
114 static int ScratchPtr;
115 #endif
117 #ifndef WINELIB
118 #define GET_SEG_PTR(x) MAKELONG((int)((char*)(x)-(char*)Heap), \
119 GlobalHandleToSel(HeapHandle))
120 #else
121 #define GET_SEG_PTR(x) ((SEGPTR)x)
122 #endif
124 #ifndef WINELIB
125 #pragma pack(4)
126 #endif
128 #define dump_sockaddr(a) \
129 fprintf(stderr, "sockaddr_in: family %d, address %s, port %d\n", \
130 ((struct sockaddr_in *)a)->sin_family, \
131 inet_ntoa(((struct sockaddr_in *)a)->sin_addr), \
132 ntohs(((struct sockaddr_in *)a)->sin_port))
134 #ifndef WINELIB32
135 static void ResetScratch()
137 ScratchPtr=0;
140 static void *scratch_alloc(int size)
142 char *ret;
143 if(ScratchPtr+size > sizeof(Heap->scratch))
144 return 0;
145 ret = Heap->scratch + ScratchPtr;
146 ScratchPtr += size;
147 return ret;
150 static SEGPTR scratch_strdup(char * s)
152 char *ret=scratch_alloc(strlen(s)+1);
153 strcpy(ret,s);
154 return GET_SEG_PTR(ret);
156 #endif
158 static WORD wsaerrno(void)
160 #ifdef DEBUG_WINSOCK
161 #ifndef sun
162 #if defined(__FreeBSD__)
163 fprintf(stderr, "winsock: errno %d, (%s).\n",
164 errno, sys_errlist[errno]);
165 #else
166 fprintf(stderr, "winsock: errno %d\n", errno);
167 #endif
168 #else
169 fprintf(stderr, "winsock: errno %d\n", errno);
170 #endif
171 #endif
173 switch(errno)
175 case EINTR: return WSAEINTR;
176 case EBADF: return WSAEBADF;
177 case EACCES: return WSAEACCES;
178 case EFAULT: return WSAEFAULT;
179 case EINVAL: return WSAEINVAL;
180 case EMFILE: return WSAEMFILE;
181 case EWOULDBLOCK: return WSAEWOULDBLOCK;
182 case EINPROGRESS: return WSAEINPROGRESS;
183 case EALREADY: return WSAEALREADY;
184 case ENOTSOCK: return WSAENOTSOCK;
185 case EDESTADDRREQ: return WSAEDESTADDRREQ;
186 case EMSGSIZE: return WSAEMSGSIZE;
187 case EPROTOTYPE: return WSAEPROTOTYPE;
188 case ENOPROTOOPT: return WSAENOPROTOOPT;
189 case EPROTONOSUPPORT: return WSAEPROTONOSUPPORT;
190 case ESOCKTNOSUPPORT: return WSAESOCKTNOSUPPORT;
191 case EOPNOTSUPP: return WSAEOPNOTSUPP;
192 case EPFNOSUPPORT: return WSAEPFNOSUPPORT;
193 case EAFNOSUPPORT: return WSAEAFNOSUPPORT;
194 case EADDRINUSE: return WSAEADDRINUSE;
195 case EADDRNOTAVAIL: return WSAEADDRNOTAVAIL;
196 case ENETDOWN: return WSAENETDOWN;
197 case ENETUNREACH: return WSAENETUNREACH;
198 case ENETRESET: return WSAENETRESET;
199 case ECONNABORTED: return WSAECONNABORTED;
200 case ECONNRESET: return WSAECONNRESET;
201 case ENOBUFS: return WSAENOBUFS;
202 case EISCONN: return WSAEISCONN;
203 case ENOTCONN: return WSAENOTCONN;
204 case ESHUTDOWN: return WSAESHUTDOWN;
205 case ETOOMANYREFS: return WSAETOOMANYREFS;
206 case ETIMEDOUT: return WSAETIMEDOUT;
207 case ECONNREFUSED: return WSAECONNREFUSED;
208 case ELOOP: return WSAELOOP;
209 case ENAMETOOLONG: return WSAENAMETOOLONG;
210 case EHOSTDOWN: return WSAEHOSTDOWN;
211 case EHOSTUNREACH: return WSAEHOSTUNREACH;
212 case ENOTEMPTY: return WSAENOTEMPTY;
213 #ifdef EPROCLIM
214 case EPROCLIM: return WSAEPROCLIM;
215 #endif
216 #ifdef EUSERS
217 case EUSERS: return WSAEUSERS;
218 #endif
219 #ifdef EDQUOT
220 case EDQUOT: return WSAEDQUOT;
221 #endif
222 case ESTALE: return WSAESTALE;
223 case EREMOTE: return WSAEREMOTE;
224 /* just in case we ever get here and there are no problems */
225 case 0: return 0;
227 default:
228 fprintf(stderr, "winsock: unknown errorno %d!\n", errno);
229 return WSAEOPNOTSUPP;
233 static void errno_to_wsaerrno(void)
235 wsa_errno = wsaerrno();
239 static WORD wsaherrno(void)
241 #if DEBUG_WINSOCK
242 #ifndef sun
243 #if defined(__FreeBSD__)
244 fprintf(stderr, "winsock: h_errno %d, (%s).\n",
245 h_errno, sys_errlist[h_errno]);
246 #else
247 fprintf(stderr, "winsock: h_errno %d.\n", h_errno);
248 herror("wine: winsock: wsaherrno");
249 #endif
250 #else
251 fprintf(stderr, "winsock: h_errno %d\n", h_errno);
252 #endif
253 #endif
255 switch(h_errno)
257 case HOST_NOT_FOUND: return WSAHOST_NOT_FOUND;
258 case TRY_AGAIN: return WSATRY_AGAIN;
259 case NO_RECOVERY: return WSANO_RECOVERY;
260 case NO_DATA: return WSANO_DATA;
261 /* just in case we ever get here and there are no problems */
262 case 0: return 0;
265 default:
266 fprintf(stderr, "winsock: unknown h_errorno %d!\n", h_errno);
267 return WSAEOPNOTSUPP;
272 static void herrno_to_wsaerrno(void)
274 wsa_errno = wsaherrno();
278 static void convert_sockopt(INT *level, INT *optname)
280 /* $%#%!#! why couldn't they use the same values for both winsock and unix ? */
282 switch (*level) {
283 case -1:
284 *level = SOL_SOCKET;
285 switch (*optname) {
286 case 0x01: *optname = SO_DEBUG;
287 break;
288 case 0x04: *optname = SO_REUSEADDR;
289 break;
290 case 0x08: *optname = SO_KEEPALIVE;
291 break;
292 case 0x10: *optname = SO_DONTROUTE;
293 break;
294 case 0x20: *optname = SO_BROADCAST;
295 break;
296 case 0x80: *optname = SO_LINGER;
297 break;
298 case 0x100: *optname = SO_OOBINLINE;
299 break;
300 case 0x1001: *optname = SO_SNDBUF;
301 break;
302 case 0x1002: *optname = SO_RCVBUF;
303 break;
304 case 0x1007: *optname = SO_ERROR;
305 break;
306 case 0x1008: *optname = SO_TYPE;
307 break;
308 default:
309 fprintf(stderr, "convert_sockopt() unknown optname %d\n", *optname);
310 break;
312 break;
313 case 6: *optname = IPPROTO_TCP;
317 #ifndef WINELIB
318 static SEGPTR copy_stringlist(char **list)
320 SEGPTR *s_list;
321 int i;
322 for(i=0;list[i];i++)
324 s_list = scratch_alloc(sizeof(SEGPTR)*(i+1));
325 for(i=0;list[i];i++)
327 void *copy = scratch_alloc(strlen(list[i])+1);
328 strcpy(copy,list[i]);
329 s_list[i]=GET_SEG_PTR(copy);
331 s_list[i]=0;
332 return GET_SEG_PTR(s_list);
336 static void CONVERT_HOSTENT(struct WIN_hostent *heapent, struct hostent *host)
338 SEGPTR *addr_list;
339 int i;
340 ResetScratch();
341 strcpy(heapent->hostname,host->h_name);
342 heapent->h_name = GET_SEG_PTR(heapent->hostname);
343 /* Convert aliases. Have to create array with FAR pointers */
344 if(!host->h_aliases)
345 heapent->h_aliases = 0;
346 else
347 heapent->h_aliases = copy_stringlist(host->h_aliases);
349 heapent->h_addrtype = host->h_addrtype;
350 heapent->h_length = host->h_length;
351 for(i=0;host->h_addr_list[i];i++)
353 addr_list=scratch_alloc(sizeof(SEGPTR)*(i+1));
354 heapent->h_addr_list = (char**)GET_SEG_PTR(addr_list);
355 for(i=0;host->h_addr_list[i];i++)
357 void *addr=scratch_alloc(host->h_length);
358 memcpy(addr,host->h_addr_list[i],host->h_length);
359 addr_list[i]=GET_SEG_PTR(addr);
361 addr_list[i]=0;
364 static void CONVERT_PROTOENT(struct WIN_protoent *heapent,
365 struct protoent *proto)
367 ResetScratch();
368 heapent->p_name= scratch_strdup(proto->p_name);
369 heapent->p_aliases=proto->p_aliases ?
370 copy_stringlist(proto->p_aliases) : 0;
371 heapent->p_proto = proto->p_proto;
374 static void CONVERT_SERVENT(struct WIN_servent *heapent, struct servent *serv)
376 ResetScratch();
377 heapent->s_name = scratch_strdup(serv->s_name);
378 heapent->s_aliases = serv->s_aliases ?
379 copy_stringlist(serv->s_aliases) : 0;
380 heapent->s_port = serv->s_port;
381 heapent->s_proto = scratch_strdup(serv->s_proto);
383 #else
384 #define CONVERT_HOSTENT(a,b) memcpy(a, &b, sizeof(a))
385 #define CONVERT_PROTOENT(a,b) memcpy(a, &b, sizeof(a))
386 #define CONVERT_SERVENT(a,b) memcpy(a, &b, sizeof(a))
387 #endif
389 SOCKET WINSOCK_accept(SOCKET s, struct sockaddr *addr, INT *addrlen)
391 int sock;
393 dprintf_winsock(stddeb, "WSA_accept: socket %d, ptr %8x, length %d\n", s, (int) addr, *addrlen);
395 if (!wsa_initted) {
396 WSASetLastError(WSANOTINITIALISED);
397 return INVALID_SOCKET;
400 if ((sock = accept(s, addr, (int *) addrlen)) < 0) {
401 errno_to_wsaerrno();
402 return INVALID_SOCKET;
404 return sock;
407 INT WINSOCK_bind(SOCKET s, struct sockaddr *name, INT namelen)
410 dprintf_winsock(stddeb, "WSA_bind: socket %d, ptr %8x, length %d\n", s, (int) name, namelen);
411 dump_sockaddr(name);
413 if (!wsa_initted) {
414 WSASetLastError(WSANOTINITIALISED);
415 return SOCKET_ERROR;
418 if (namelen < sizeof(*name)) {
419 WSASetLastError(WSAEFAULT);
420 return SOCKET_ERROR;
423 /* check the socket family */
424 if ( ((struct sockaddr_in *)name)->sin_family != AF_INET ) {
425 WSASetLastError(WSAEAFNOSUPPORT);
426 return SOCKET_ERROR;
429 if (bind(s, name, namelen) < 0) {
430 switch(errno) {
431 case EBADF:
432 WSASetLastError(WSAENOTSOCK);
433 break;
434 case EADDRNOTAVAIL:
435 WSASetLastError(WSAEINVAL);
436 break;
437 default:
438 errno_to_wsaerrno();
439 break;
441 return SOCKET_ERROR;
443 return 0;
446 INT WINSOCK_closesocket(SOCKET s)
448 dprintf_winsock(stddeb, "WSA_closesocket: socket %d\n", s);
450 if (!wsa_initted) {
451 WSASetLastError(WSANOTINITIALISED);
452 return SOCKET_ERROR;
455 FD_CLR(s, &fd_in_use);
457 if (close(s) < 0) {
458 if (errno == EBADF)
459 WSASetLastError(WSAENOTSOCK);
460 else
461 errno_to_wsaerrno();
462 return SOCKET_ERROR;
464 return 0;
467 INT WINSOCK_connect(SOCKET s, struct sockaddr *name, INT namelen)
469 dprintf_winsock(stddeb, "WSA_connect: socket %d, ptr %8x, length %d\n", s, (int) name, namelen);
470 dump_sockaddr(name);
472 if (!wsa_initted) {
473 WSASetLastError(WSANOTINITIALISED);
474 return SOCKET_ERROR;
477 if (connect(s, name, namelen) < 0) {
478 errno_to_wsaerrno();
479 return SOCKET_ERROR;
481 return 0;
484 INT WINSOCK_getpeername(SOCKET s, struct sockaddr *name, INT *namelen)
486 dprintf_winsock(stddeb, "WSA_getpeername: socket: %d, ptr %8x, ptr %8x\n", s, (int) name, *namelen);
487 dump_sockaddr(name);
489 if (!wsa_initted) {
490 WSASetLastError(WSANOTINITIALISED);
491 return SOCKET_ERROR;
494 if (getpeername(s, name, (int *) namelen) < 0) {
495 if (h_errno < 0) {
496 errno_to_wsaerrno();
497 } else {
498 herrno_to_wsaerrno();
500 return SOCKET_ERROR;
502 return 0;
505 INT WINSOCK_getsockname(SOCKET s, struct sockaddr *name, INT *namelen)
507 dprintf_winsock(stddeb, "WSA_getsockname: socket: %d, ptr %8x, ptr %8x\n", s, (int) name, (int) *namelen);
509 if (!wsa_initted) {
510 WSASetLastError(WSANOTINITIALISED);
511 return SOCKET_ERROR;
514 if (getsockname(s, name, (int *) namelen) < 0) {
515 if (h_errno < 0) {
516 errno_to_wsaerrno();
517 } else {
518 herrno_to_wsaerrno();
520 return SOCKET_ERROR;
522 return 0;
526 WINSOCK_getsockopt(SOCKET s, INT level, INT optname, char *optval, INT *optlen)
528 dprintf_winsock(stddeb, "WSA_getsockopt: socket: %d, opt %d, ptr %8x, ptr %8x\n", s, level, (int) optval, (int) *optlen);
530 if (!wsa_initted) {
531 WSASetLastError(WSANOTINITIALISED);
532 return SOCKET_ERROR;
535 convert_sockopt(&level, &optname);
537 if (getsockopt(s, (int) level, optname, optval, (int *) optlen) < 0) {
538 if (errno == EBADF)
539 WSASetLastError(WSAENOTSOCK);
540 else
541 errno_to_wsaerrno();
542 return SOCKET_ERROR;
544 return 0;
547 u_long WINSOCK_htonl(u_long hostlong)
549 return( htonl(hostlong) );
552 u_short WINSOCK_htons(u_short hostshort)
554 return( htons(hostshort) );
557 u_long WINSOCK_inet_addr(char *cp)
559 return( inet_addr(cp) );
562 char *WINSOCK_inet_ntoa(struct in_addr in)
564 char *s;
566 /* dprintf_winsock(stddeb, "WSA_inet_ntoa: %8lx\n", (int) in);*/
568 if ((s = inet_ntoa(in)) == NULL) {
569 errno_to_wsaerrno();
570 return NULL;
573 strncpy(Heap->ntoa_buffer, s, sizeof(Heap->ntoa_buffer) );
575 return (char *) GET_SEG_PTR(&Heap->ntoa_buffer);
578 INT WINSOCK_ioctlsocket(SOCKET s, u_long cmd, u_long *argp)
580 long newcmd;
581 u_long *newargp;
582 char *ctlname;
583 dprintf_winsock(stddeb, "WSA_ioctl: socket %d, cmd %lX, ptr %8x\n", s, cmd, (int) argp);
585 if (!wsa_initted) {
586 WSASetLastError(WSANOTINITIALISED);
587 return SOCKET_ERROR;
590 /* Why can't they all use the same ioctl numbers */
591 newcmd=cmd;
592 newargp=argp;
593 ctlname=0;
594 if(cmd == _IOR('f',127,u_long))
596 ctlname="FIONREAD";
597 newcmd=FIONREAD;
598 }else
599 if(cmd == _IOW('f',126,u_long) || cmd == _IOR('f',126,u_long))
601 ctlname="FIONBIO";
602 newcmd=FIONBIO;
603 }else
604 if(cmd == _IOW('f',125,u_long))
606 ctlname="FIOASYNC";
607 newcmd=FIOASYNC;
610 if(!ctlname)
611 fprintf(stderr,"Unknown winsock ioctl. Trying anyway\n");
612 else
613 dprintf_winsock(stddeb,"Recognized as %s\n", ctlname);
616 if (ioctl(s, newcmd, newargp) < 0) {
617 if (errno == EBADF)
618 WSASetLastError(WSAENOTSOCK);
619 else
620 errno_to_wsaerrno();
621 return SOCKET_ERROR;
623 return 0;
626 INT WINSOCK_listen(SOCKET s, INT backlog)
628 dprintf_winsock(stddeb, "WSA_listen: socket %d, backlog %d\n", s, backlog);
630 if (!wsa_initted) {
631 WSASetLastError(WSANOTINITIALISED);
632 return SOCKET_ERROR;
635 if (listen(s, backlog) < 0) {
636 errno_to_wsaerrno();
637 return SOCKET_ERROR;
639 return 0;
642 u_long WINSOCK_ntohl(u_long netlong)
644 return( ntohl(netlong) );
647 u_short WINSOCK_ntohs(u_short netshort)
649 return( ntohs(netshort) );
652 INT WINSOCK_recv(SOCKET s, char *buf, INT len, INT flags)
654 int length;
656 dprintf_winsock(stddeb, "WSA_recv: socket %d, ptr %8x, length %d, flags %d\n", s, (int) buf, len, flags);
658 if (!wsa_initted) {
659 WSASetLastError(WSANOTINITIALISED);
660 return SOCKET_ERROR;
663 if ((length = recv(s, buf, len, flags)) < 0) {
664 errno_to_wsaerrno();
665 return SOCKET_ERROR;
667 return length;
670 INT WINSOCK_recvfrom(SOCKET s, char *buf, INT len, INT flags,
671 struct sockaddr *from, int *fromlen)
673 int length;
675 dprintf_winsock(stddeb, "WSA_recvfrom: socket %d, ptr %8lx, length %d, flags %d\n", s, (unsigned long)buf, len, flags);
677 if (!wsa_initted) {
678 WSASetLastError(WSANOTINITIALISED);
679 return SOCKET_ERROR;
682 if ((length = recvfrom(s, buf, len, flags, from, fromlen)) < 0) {
683 errno_to_wsaerrno();
684 return SOCKET_ERROR;
686 return length;
689 INT WINSOCK_select(INT nfds, fd_set *readfds, fd_set *writefds,
690 fd_set *exceptfds, struct timeval *timeout)
692 dprintf_winsock(stddeb, "WSA_select: fd # %d, ptr %8lx, ptr %8lx, ptr %8lX\n", nfds, (unsigned long) readfds, (unsigned long) writefds, (unsigned long) exceptfds);
694 if (!wsa_initted) {
695 WSASetLastError(WSANOTINITIALISED);
696 return SOCKET_ERROR;
698 /* FIXME */
699 return(select(nfds, readfds, writefds, exceptfds, timeout));
702 INT WINSOCK_send(SOCKET s, char *buf, INT len, INT flags)
704 int length;
706 dprintf_winsock(stddeb, "WSA_send: socket %d, ptr %8lx, length %d, flags %d\n", s, (unsigned long) buf, len, flags);
708 if (!wsa_initted) {
709 WSASetLastError(WSANOTINITIALISED);
710 return SOCKET_ERROR;
713 if ((length = send(s, buf, len, flags)) < 0) {
714 errno_to_wsaerrno();
715 return SOCKET_ERROR;
717 return length;
720 INT WINSOCK_sendto(SOCKET s, char *buf, INT len, INT flags,
721 struct sockaddr *to, INT tolen)
723 int length;
725 dprintf_winsock(stddeb, "WSA_sendto: socket %d, ptr %8lx, length %d, flags %d\n", s, (unsigned long) buf, len, flags);
727 if (!wsa_initted) {
728 WSASetLastError(WSANOTINITIALISED);
729 return SOCKET_ERROR;
732 if ((length = sendto(s, buf, len, flags, to, tolen)) < 0) {
733 errno_to_wsaerrno();
734 return SOCKET_ERROR;
736 return length;
739 INT WINSOCK_setsockopt(SOCKET s, INT level, INT optname, const char *optval,
740 INT optlen)
742 dprintf_winsock(stddeb, "WSA_setsockopt: socket %d, level %d, opt %d, ptr %8x, len %d\n", s, level, optname, (int) optval, optlen);
743 convert_sockopt(&level, &optname);
745 if (!wsa_initted) {
746 WSASetLastError(WSANOTINITIALISED);
747 return SOCKET_ERROR;
750 if (setsockopt(s, level, optname, optval, optlen) < 0) {
751 errno_to_wsaerrno();
752 return SOCKET_ERROR;
754 return 0;
757 INT WINSOCK_shutdown(SOCKET s, INT how)
759 dprintf_winsock(stddeb, "WSA_shutdown: socket s %d, how %d\n", s, how);
761 if (!wsa_initted) {
762 WSASetLastError(WSANOTINITIALISED);
763 return SOCKET_ERROR;
766 if (shutdown(s, how) < 0) {
767 errno_to_wsaerrno();
768 return SOCKET_ERROR;
770 return 0;
773 SOCKET WINSOCK_socket(INT af, INT type, INT protocol)
775 int sock;
777 dprintf_winsock(stddeb, "WSA_socket: af=%d type=%d protocol=%d\n", af, type, protocol);
779 if (!wsa_initted) {
780 WSASetLastError(WSANOTINITIALISED);
781 return INVALID_SOCKET;
784 /* check the socket family */
785 switch(af) {
786 case AF_INET:
787 case AF_UNSPEC:
788 break;
789 default:
790 WSASetLastError(WSAEAFNOSUPPORT);
791 return INVALID_SOCKET;
792 break;
795 /* check the socket type */
796 switch(type) {
797 case SOCK_STREAM:
798 case SOCK_DGRAM:
799 case SOCK_RAW:
800 break;
801 default:
802 WSASetLastError(WSAESOCKTNOSUPPORT);
803 return INVALID_SOCKET;
804 break;
807 /* check the protocol type */
808 if ( protocol < 0 ) { /* don't support negative values */
809 WSASetLastError(WSAEPROTONOSUPPORT);
810 return INVALID_SOCKET;
813 if ( af == AF_UNSPEC) { /* did they not specify the address family? */
814 switch(protocol) {
815 case IPPROTO_TCP:
816 if (type == SOCK_STREAM) {
817 af = AF_INET;
818 break;
820 case IPPROTO_UDP:
821 if (type == SOCK_DGRAM) {
822 af = AF_INET;
823 break;
825 default:
826 WSASetLastError(WSAEPROTOTYPE);
827 return INVALID_SOCKET;
828 break;
832 if ((sock = socket(af, type, protocol)) < 0) {
833 if (errno == EPERM) {
834 /* non super-user wants a raw socket */
835 fprintf(stderr, "WSA_socket: not enough privileges\n");
836 WSASetLastError(WSAESOCKTNOSUPPORT);
837 } else
838 errno_to_wsaerrno();
839 dprintf_winsock(stddeb, "WSA_socket: failed !\n");
840 return INVALID_SOCKET;
843 if (sock > WINSOCK_MAX_SOCKETS) {
844 /* we only support socket numbers up to WINSOCK_MAX_SOCKETS.
845 * The return value indicates no more descriptors are available
847 WSASetLastError(WSAEMFILE);
848 return INVALID_SOCKET;
851 FD_SET(sock, &fd_in_use);
853 dprintf_winsock(stddeb, "WSA_socket: fd %d\n", sock);
854 return sock;
858 struct WIN_hostent *
860 SEGPTR WINSOCK_gethostbyaddr(const char *addr, INT len, INT type)
862 struct hostent *host;
864 dprintf_winsock(stddeb, "WSA_gethostbyaddr: ptr %8x, len %d, type %d\n", (int) addr, len, type);
866 if (!wsa_initted) {
867 WSASetLastError(WSANOTINITIALISED);
868 return NULL;
871 if ((host = gethostbyaddr(addr, len, type)) == NULL) {
872 if (h_errno < 0) {
873 errno_to_wsaerrno();
874 } else {
875 herrno_to_wsaerrno();
877 return NULL;
879 CONVERT_HOSTENT(&Heap->hostent_addr, host);
881 return GET_SEG_PTR(&Heap->hostent_addr);
885 struct WIN_hostent *
887 SEGPTR WINSOCK_gethostbyname(const char *name)
889 struct hostent *host;
891 dprintf_winsock(stddeb, "WSA_gethostbyname: %s\n", name);
893 if (!wsa_initted) {
894 WSASetLastError(WSANOTINITIALISED);
895 return NULL;
898 if ((host = gethostbyname(name)) == NULL) {
899 if (h_errno < 0) {
900 errno_to_wsaerrno();
901 } else {
902 herrno_to_wsaerrno();
904 return NULL;
906 CONVERT_HOSTENT(&Heap->hostent_name, host);
908 return GET_SEG_PTR(&Heap->hostent_name);
911 INT WINSOCK_gethostname(char *name, INT namelen)
913 dprintf_winsock(stddeb, "WSA_gethostname: name %s, len %d\n", name, namelen);
915 if (!wsa_initted) {
916 WSASetLastError(WSANOTINITIALISED);
917 return SOCKET_ERROR;
920 if (gethostname(name, namelen) < 0) {
921 if (errno == EINVAL)
922 WSASetLastError(WSAEFAULT);
923 else
924 errno_to_wsaerrno();
925 return SOCKET_ERROR;
927 return 0;
931 struct WIN_protoent *
933 SEGPTR WINSOCK_getprotobyname(char *name)
935 struct protoent *proto;
937 dprintf_winsock(stddeb, "WSA_getprotobyname: name %s\n", name);
939 if (!wsa_initted) {
940 WSASetLastError(WSANOTINITIALISED);
941 return NULL;
944 if ((proto = getprotobyname(name)) == NULL) {
945 if (h_errno < 0) {
946 errno_to_wsaerrno();
947 } else {
948 herrno_to_wsaerrno();
950 return NULL;
952 CONVERT_PROTOENT(&Heap->protoent_name, proto);
954 return GET_SEG_PTR(&Heap->protoent_name);
958 struct WIN_protoent *
960 SEGPTR WINSOCK_getprotobynumber(INT number)
962 struct protoent *proto;
964 dprintf_winsock(stddeb, "WSA_getprotobynumber: num %d\n", number);
966 if (!wsa_initted) {
967 WSASetLastError(WSANOTINITIALISED);
968 return NULL;
971 if ((proto = getprotobynumber(number)) == NULL) {
972 #if 0
973 if (h_errno < 0) {
974 errno_to_wsaerrno();
975 } else {
976 herrno_to_wsaerrno();
978 #endif
979 WSASetLastError(WSANO_DATA);
980 return NULL;
982 CONVERT_PROTOENT(&Heap->protoent_number, proto);
984 return GET_SEG_PTR(&Heap->protoent_number);
988 struct WIN_servent *
990 SEGPTR WINSOCK_getservbyname(const char *name, const char *proto)
992 struct servent *service;
994 if (proto == NULL)
995 proto = "tcp";
997 dprintf_winsock(stddeb, "WSA_getservbyname: name %s, proto %s\n", name, proto);
999 if (!wsa_initted) {
1000 WSASetLastError(WSANOTINITIALISED);
1001 return NULL;
1004 if ((service = getservbyname(name, proto)) == NULL) {
1005 if (h_errno < 0) {
1006 errno_to_wsaerrno();
1007 } else {
1008 herrno_to_wsaerrno();
1010 return NULL;
1012 CONVERT_SERVENT(&Heap->servent_name, service);
1014 return GET_SEG_PTR(&Heap->servent_name);
1018 struct WIN_servent *
1020 SEGPTR WINSOCK_getservbyport(INT port, const char *proto)
1022 struct servent *service;
1024 dprintf_winsock(stddeb, "WSA_getservbyport: port %d, name %s\n", port, proto);
1026 if (!wsa_initted) {
1027 WSASetLastError(WSANOTINITIALISED);
1028 return NULL;
1031 if ((service = getservbyport(port, proto)) == NULL) {
1032 if (h_errno < 0) {
1033 errno_to_wsaerrno();
1034 } else {
1035 herrno_to_wsaerrno();
1037 return NULL;
1039 CONVERT_SERVENT(&Heap->servent_port, service);
1041 return GET_SEG_PTR(&Heap->servent_port);
1044 /******************** winsock specific functions ************************
1047 static HANDLE new_handle = 1;
1049 static HANDLE AllocWSAHandle(void)
1051 return new_handle++;
1054 static void recv_message(int sig)
1056 static struct ipc_packet message;
1057 int message_is_valid = 0;
1058 BOOL result;
1060 message.mtype = MTYPE;
1062 signal(SIGUSR1, recv_message);
1063 while (1) {
1065 if (!message_is_valid) {
1066 if (msgrcv(wine_key, (struct msgbuf*)&(message),
1067 IPC_PACKET_SIZE, 0 /*MTYPE*/, IPC_NOWAIT) == -1) {
1068 perror("wine: winsock: msgrcv");
1069 break;
1073 result = PostMessage(message.hWnd, message.wMsg,
1074 (WPARAM)message.handle, message.lParam);
1075 if (result != FALSE) {
1076 message_is_valid = 1;
1077 break;
1079 else
1080 message_is_valid = 0;
1084 if ((wine_key = msgget(IPC_PRIVATE, 0600)) == -1)
1085 perror("wine: winsock: msgget");
1089 static void send_message( HWND hWnd, u_int wMsg, HANDLE handle, long lParam)
1091 struct ipc_packet message;
1093 message.mtype = MTYPE;
1094 message.handle = handle;
1095 message.hWnd = hWnd;
1096 message.wMsg = wMsg;
1097 message.lParam = lParam;
1099 if (msgsnd(wine_key, (struct msgbuf*)&(message),
1100 IPC_PACKET_SIZE, 0/*IPC_NOWAIT*/) == -1)
1101 perror("wine: winsock: msgsnd");
1103 kill(getppid(), SIGUSR1);
1107 HANDLE WSAAsyncGetHostByAddr(HWND hWnd, u_int wMsg, LPCSTR addr,
1108 INT len, INT type, LPSTR buf, INT buflen)
1110 HANDLE handle;
1111 struct hostent *host;
1112 int newpid;
1114 if (!wsa_initted) {
1115 WSASetLastError(WSANOTINITIALISED);
1116 return 0;
1119 handle = AllocWSAHandle();
1121 newpid = fork();
1122 if (newpid) {
1123 dprintf_winsock(stddeb, "forked, child is (%d)\n",newpid);
1124 return handle;
1125 } else {
1126 if ((host = gethostbyaddr(addr, len, type)) == NULL) {
1127 if (h_errno < 0) {
1128 errno_to_wsaerrno();
1129 } else {
1130 herrno_to_wsaerrno();
1132 send_message(hWnd, wMsg, handle, wsaerrno() << 16);
1133 exit(0);
1135 memcpy(buf, host, buflen);
1136 send_message(hWnd, wMsg, handle, 0);
1137 exit(0);
1142 HANDLE WSAAsyncGetHostByName(HWND hWnd, u_int wMsg, LPCSTR name,
1143 LPSTR buf, INT buflen)
1145 HANDLE handle;
1146 struct hostent *host;
1147 int newpid;
1149 if (!wsa_initted) {
1150 WSASetLastError(WSANOTINITIALISED);
1151 return 0;
1154 handle = AllocWSAHandle();
1156 newpid = fork();
1157 if (newpid) {
1158 dprintf_winsock(stddeb, "forked, child is (%d)\n",newpid);
1159 return handle;
1160 } else {
1161 if ((host = gethostbyname(name)) == NULL) {
1162 if (h_errno < 0) {
1163 errno_to_wsaerrno();
1164 } else {
1165 herrno_to_wsaerrno();
1167 send_message(hWnd, wMsg, handle, wsaerrno() << 16);
1168 exit(0);
1170 memcpy(buf, host, buflen);
1171 send_message(hWnd, wMsg, handle, 0);
1172 exit(0);
1177 HANDLE WSAAsyncGetProtoByName(HWND hWnd, u_int wMsg, LPCSTR name,
1178 LPSTR buf, INT buflen)
1180 HANDLE handle;
1181 struct protoent *proto;
1182 int newpid;
1184 if (!wsa_initted) {
1185 WSASetLastError(WSANOTINITIALISED);
1186 return 0;
1189 handle = AllocWSAHandle();
1191 newpid = fork();
1192 if (newpid) {
1193 dprintf_winsock(stddeb, "forked, child is (%d)\n",newpid);
1194 return handle;
1195 } else {
1196 if ((proto = getprotobyname(name)) == NULL) {
1197 if (h_errno < 0) {
1198 errno_to_wsaerrno();
1199 } else {
1200 herrno_to_wsaerrno();
1202 send_message(hWnd, wMsg, handle, wsaerrno() << 16);
1203 exit(0);
1205 memcpy(buf, proto, buflen);
1206 send_message(hWnd, wMsg, handle, 0);
1207 exit(0);
1212 HANDLE WSAAsyncGetProtoByNumber(HWND hWnd, u_int wMsg, INT number,
1213 LPSTR buf, INT buflen)
1215 HANDLE handle;
1216 struct protoent *proto;
1217 int newpid;
1219 if (!wsa_initted) {
1220 WSASetLastError(WSANOTINITIALISED);
1221 return 0;
1224 handle = AllocWSAHandle();
1226 newpid = fork();
1227 if (newpid) {
1228 dprintf_winsock(stddeb, "forked, child is (%d)\n",newpid);
1229 return handle;
1230 } else {
1231 if ((proto = getprotobynumber(number)) == NULL) {
1232 if (h_errno < 0) {
1233 errno_to_wsaerrno();
1234 } else {
1235 herrno_to_wsaerrno();
1237 send_message(hWnd, wMsg, handle, wsaerrno() << 16);
1238 exit(0);
1240 memcpy(buf, proto, buflen);
1241 send_message(hWnd, wMsg, handle, 0);
1242 exit(0);
1247 HANDLE WSAAsyncGetServByName(HWND hWnd, u_int wMsg, LPCSTR name,
1248 LPCSTR proto, LPSTR buf, INT buflen)
1250 HANDLE handle;
1251 struct servent *service;
1252 int newpid;
1254 if (!wsa_initted) {
1255 WSASetLastError(WSANOTINITIALISED);
1256 return 0;
1259 handle = AllocWSAHandle();
1261 newpid = fork();
1262 if (newpid) {
1263 dprintf_winsock(stddeb, "forked, child is (%d)\n",newpid);
1264 return handle;
1265 } else {
1266 if ((service = getservbyname(name, proto)) == NULL) {
1267 if (h_errno < 0) {
1268 errno_to_wsaerrno();
1269 } else {
1270 herrno_to_wsaerrno();
1272 send_message(hWnd, wMsg, handle, wsaerrno() << 16);
1273 exit(0);
1275 memcpy(buf, service, buflen);
1276 send_message(hWnd, wMsg, handle, 0);
1277 exit(0);
1282 HANDLE WSAAsyncGetServByPort(HWND hWnd, u_int wMsg, INT port, LPCSTR proto,
1283 LPSTR buf, INT buflen)
1285 HANDLE handle;
1286 struct servent *service;
1287 int newpid;
1289 if (!wsa_initted) {
1290 WSASetLastError(WSANOTINITIALISED);
1291 return 0;
1294 handle = AllocWSAHandle();
1296 newpid = fork();
1297 if (newpid) {
1298 dprintf_winsock(stddeb, "forked, child is (%d)\n",newpid);
1299 return handle;
1300 } else {
1301 if ((service = getservbyport(port, proto)) == NULL) {
1302 if (h_errno < 0) {
1303 errno_to_wsaerrno();
1304 } else {
1305 herrno_to_wsaerrno();
1307 send_message(hWnd, wMsg, handle, wsaerrno() << 16);
1308 exit(0);
1310 memcpy(buf, service, buflen);
1311 send_message(hWnd, wMsg, handle, 0);
1312 exit(0);
1316 INT WSAAsyncSelect(SOCKET s, HWND hWnd, u_int wMsg, long lEvent)
1318 long event;
1319 fd_set read_fds, write_fds, except_fds;
1320 int errors = 0;
1321 int newpid;
1323 if (!wsa_initted) {
1324 WSASetLastError(WSANOTINITIALISED);
1325 return SOCKET_ERROR;
1328 dprintf_winsock(stddeb, "WSA_AsyncSelect: socket %d, HWND %04x, wMsg %d, event %ld\n", s, hWnd, wMsg, lEvent);
1330 /* remove outstanding asyncselect() processes */
1331 /* kill */
1333 if (wMsg == 0 && lEvent == 0)
1334 return 0;
1336 newpid = fork();
1337 if (newpid) {
1338 dprintf_winsock(stddeb, "forked, child is (%d)\n",newpid);
1339 return 0;
1340 } else {
1341 while (1) {
1342 FD_ZERO(&read_fds);
1343 FD_ZERO(&write_fds);
1344 FD_ZERO(&except_fds);
1346 if (lEvent & FD_READ)
1347 FD_SET(s, &read_fds);
1348 if (lEvent & FD_WRITE)
1349 FD_SET(s, &write_fds);
1351 fcntl(s, F_SETFL, O_NONBLOCK);
1352 if (select(s + 1, &read_fds, &write_fds, &except_fds, NULL)<0) {
1353 errors = wsaerrno();
1356 event = 0;
1357 if (FD_ISSET(s, &read_fds))
1358 event |= FD_READ;
1359 if (FD_ISSET(s, &write_fds))
1360 event |= FD_WRITE;
1361 send_message(hWnd, wMsg, s, WSAMAKESELECTREPLY(event,errors));
1366 INT WSAFDIsSet(INT fd, fd_set *set)
1368 return( FD_ISSET(fd, set) );
1371 INT WSACancelAsyncRequest(HANDLE hAsyncTaskHandle)
1373 dprintf_winsock(stddeb, "WSA_AsyncRequest: handle %04x\n", hAsyncTaskHandle);
1375 if (!wsa_initted) {
1376 WSASetLastError(WSANOTINITIALISED);
1377 return SOCKET_ERROR;
1380 return 0;
1383 INT WSACancelBlockingCall(void)
1385 dprintf_winsock(stddeb, "WSA_CancelBlockCall\n");
1387 if (!wsa_initted) {
1388 WSASetLastError(WSANOTINITIALISED);
1389 return SOCKET_ERROR;
1392 return 0;
1395 INT WSAGetLastError(void)
1397 dprintf_winsock(stddeb, "WSA_GetLastError = %x\n", wsa_errno);
1399 return wsa_errno;
1402 void WSASetLastError(INT iError)
1404 dprintf_winsock(stddeb, "WSA_SetLastErorr %d\n", iError);
1406 /* technically, we should make sure that WINESockets
1407 * has been started up correctly. But since this function
1408 * is also used internally, it makes no sense.
1410 *if (!wsa_initted) {
1411 * WSASetLastError(WSANOTINITIALISED);
1412 * return SOCKET_ERROR;
1416 wsa_errno = iError;
1419 BOOL WSAIsBlocking(void)
1421 dprintf_winsock(stddeb, "WSA_IsBlocking\n");
1423 return 0;
1426 FARPROC16 WSASetBlockingHook(FARPROC16 lpBlockFunc)
1428 dprintf_winsock(stddeb, "WSA_SetBlockHook %8lx, STUB!\n", (unsigned long) lpBlockFunc);
1430 if (!wsa_initted) {
1431 WSASetLastError(WSANOTINITIALISED);
1432 return NULL;
1435 BlockFunction = lpBlockFunc;
1437 return (FARPROC16) lpBlockFunc;
1440 INT WSAUnhookBlockingHook(void)
1442 dprintf_winsock(stddeb, "WSA_UnhookBlockingHook\n");
1444 if (!wsa_initted) {
1445 WSASetLastError(WSANOTINITIALISED);
1446 return NULL;
1449 BlockFunction = NULL;
1451 return 0;
1454 #ifdef 0
1455 WSADATA WINSOCK_data = {
1456 0x0101,
1457 0x0101,
1458 "WINE Sockets",
1459 #ifdef linux
1460 "LINUX/i386",
1461 #elif defined(__NetBSD__)
1462 "NetBSD/i386",
1463 #elif defined(sunos)
1464 "SunOS",
1465 #elif defined(__FreeBSD__)
1466 "FreeBSD",
1467 #else
1468 "Unknown",
1469 #endif
1470 WINSOCK_MAX_SOCKETS,
1471 WINSOCK_MAX_UDPDG,
1472 NULL
1474 #endif
1476 INT WSAStartup(WORD wVersionRequested, LPWSADATA lpWSAData)
1479 WSADATA WINSOCK_data = {
1480 0x0101,
1481 0x0101,
1482 "WINE Sockets",
1483 #ifdef linux
1484 "Linux/i386",
1485 #elif defined(__NetBSD__)
1486 "NetBSD/i386",
1487 #elif defined(sunos)
1488 "SunOS",
1489 #elif defined(__FreeBSD__)
1490 "FreeBSD",
1491 #else
1492 "Unknown",
1493 #endif
1494 WINSOCK_MAX_SOCKETS,
1495 WINSOCK_MAX_UDPDG,
1496 NULL
1499 dprintf_winsock(stddeb, "WSAStartup: verReq=%x\n", wVersionRequested);
1501 if (LOBYTE(wVersionRequested) < 1 ||
1502 (LOBYTE(wVersionRequested) == 1 &&
1503 HIBYTE(wVersionRequested) < 1))
1504 return WSAVERNOTSUPPORTED;
1506 if (!lpWSAData)
1507 return WSAEINVAL;
1509 /* alloc winsock heap */
1511 if ((HeapHandle = GlobalAlloc16(GMEM_FIXED,sizeof(struct WinSockHeap))) == 0)
1512 return WSASYSNOTREADY;
1514 Heap = (struct WinSockHeap *) GlobalLock16(HeapHandle);
1516 /* return winsock information */
1517 memcpy(lpWSAData, &WINSOCK_data, sizeof(WINSOCK_data));
1519 /* ipc stuff */
1521 if ((wine_key = msgget(IPC_PRIVATE, 0600)) == -1)
1522 perror("wine: winsock: msgget");
1524 signal(SIGUSR1, recv_message);
1526 /* clear */
1528 FD_ZERO(&fd_in_use);
1530 /* increment our usage count */
1531 wsa_initted++;
1532 dprintf_winsock(stddeb, "WSAStartup: succeeded\n");
1533 return(0);
1536 INT WSACleanup(void)
1538 int fd;
1540 dprintf_winsock(stddeb, "WSACleanup (%d)\n",getpid());
1542 if (!wsa_initted) {
1543 WSASetLastError(WSANOTINITIALISED);
1544 return SOCKET_ERROR;
1547 /* decrement usage count */
1548 wsa_initted--;
1550 if (wsa_initted == 0) {
1551 if (wine_key)
1552 if (msgctl(wine_key, IPC_RMID, NULL) == -1)
1553 perror("wine: winsock: msgctl");
1555 for (fd = 0; fd != FD_SETSIZE; fd++)
1556 if (FD_ISSET(fd, &fd_in_use))
1557 close(fd);
1560 return 0;