2 * based on Windows Sockets 1.1 specs
3 * (ftp.microsoft.com:/Advsys/winsock/spec11/WINSOCK.TXT)
5 * (C) 1993,1994 John Brezak, Erik Bos.
11 #include <sys/types.h>
13 #include <sys/socket.h>
14 #include <netinet/in.h>
15 #include <arpa/inet.h>
25 static WORD wsa_errno
;
26 static int wsa_initted
;
27 static key_t wine_key
= 0;
28 static FARPROC BlockFunction
;
29 static fd_set fd_in_use
;
38 #define IPC_PACKET_SIZE (sizeof(struct ipc_packet) - sizeof(long))
40 #define MTYPE 0xb0b0eb05
45 struct hostent hostent_addr
;
46 struct hostent hostent_name
;
47 struct protoent protoent_name
;
48 struct protoent protoent_number
;
49 struct servent servent_name
;
50 struct servent servent_port
;
52 struct hostent WSAhostent_addr
;
53 struct hostent WSAhostent_name
;
54 struct protoent WSAprotoent_name
;
55 struct protoent WSAprotoent_number
;
56 struct servent WSAservent_name
;
57 struct servent WSAservent_port
;
59 static struct WinSockHeap
*heap
;
61 #define dump_sockaddr(a) \
62 fprintf(stderr, "sockaddr_in: family %d, address %s, port %d\n", \
63 ((struct sockaddr_in *)a)->sin_family, \
64 inet_ntoa(((struct sockaddr_in *)a)->sin_addr), \
65 ntohs(((struct sockaddr_in *)a)->sin_port))
67 static WORD
wsaerrno(void)
71 #if defined(__FreeBSD__)
72 fprintf(stderr
, "winsock: errno %d, (%s).\n",
73 errno
, sys_errlist
[errno
]);
75 fprintf(stderr
, "winsock: errno %d, (%s).\n",
76 errno
, strerror(errno
));
79 fprintf(stderr
, "winsock: errno %d\n", errno
);
85 case EINTR
: return WSAEINTR
;
86 case EACCES
: return WSAEACCES
;
87 case EFAULT
: return WSAEFAULT
;
88 case EINVAL
: return WSAEINVAL
;
89 case EMFILE
: return WSAEMFILE
;
90 case EWOULDBLOCK
: return WSAEWOULDBLOCK
;
91 case EINPROGRESS
: return WSAEINPROGRESS
;
92 case EALREADY
: return WSAEALREADY
;
94 case ENOTSOCK
: return WSAENOTSOCK
;
95 case EDESTADDRREQ
: return WSAEDESTADDRREQ
;
96 case EMSGSIZE
: return WSAEMSGSIZE
;
97 case EPROTOTYPE
: return WSAEPROTOTYPE
;
98 case ENOPROTOOPT
: return WSAENOPROTOOPT
;
99 case EPROTONOSUPPORT
: return WSAEPROTONOSUPPORT
;
100 case ESOCKTNOSUPPORT
: return WSAESOCKTNOSUPPORT
;
101 case EOPNOTSUPP
: return WSAEOPNOTSUPP
;
102 case EPFNOSUPPORT
: return WSAEPFNOSUPPORT
;
103 case EAFNOSUPPORT
: return WSAEAFNOSUPPORT
;
104 case EADDRINUSE
: return WSAEADDRINUSE
;
105 case EADDRNOTAVAIL
: return WSAEADDRNOTAVAIL
;
106 case ENETDOWN
: return WSAENETDOWN
;
107 case ENETUNREACH
: return WSAENETUNREACH
;
108 case ENETRESET
: return WSAENETRESET
;
109 case ECONNABORTED
: return WSAECONNABORTED
;
110 case ECONNRESET
: return WSAECONNRESET
;
111 case ENOBUFS
: return WSAENOBUFS
;
112 case EISCONN
: return WSAEISCONN
;
113 case ENOTCONN
: return WSAENOTCONN
;
114 case ESHUTDOWN
: return WSAESHUTDOWN
;
115 case ETOOMANYREFS
: return WSAETOOMANYREFS
;
116 case ETIMEDOUT
: return WSAETIMEDOUT
;
117 case ECONNREFUSED
: return WSAECONNREFUSED
;
118 case ELOOP
: return WSAELOOP
;
119 case ENAMETOOLONG
: return WSAENAMETOOLONG
;
120 case EHOSTDOWN
: return WSAEHOSTDOWN
;
121 case EHOSTUNREACH
: return WSAEHOSTUNREACH
;
122 case ENOTEMPTY
: return WSAENOTEMPTY
;
123 /* case EPROCLIM: return WSAEPROCLIM; */
124 case EUSERS
: return WSAEUSERS
;
125 case EDQUOT
: return WSAEDQUOT
;
126 case ESTALE
: return WSAESTALE
;
127 case EREMOTE
: return WSAEREMOTE
;
130 fprintf(stderr
, "winsock: unknown errorno %d!\n", errno
);
131 return WSAEOPNOTSUPP
;
135 static WORD
errno_to_wsaerrno(void)
137 wsa_errno
= wsaerrno();
140 static void convert_sockopt(INT
*level
, INT
*optname
)
142 /* $%#%!@! why couldn't they use the same values for both winsock and unix ? */
148 case 0x01: *optname
= SO_DEBUG
;
150 case 0x04: *optname
= SO_REUSEADDR
;
152 case 0x08: *optname
= SO_KEEPALIVE
;
154 case 0x10: *optname
= SO_DONTROUTE
;
156 case 0x20: *optname
= SO_BROADCAST
;
158 case 0x80: *optname
= SO_LINGER
;
160 case 0x100: *optname
= SO_OOBINLINE
;
162 case 0x1001: *optname
= SO_SNDBUF
;
164 case 0x1002: *optname
= SO_RCVBUF
;
166 case 0x1007: *optname
= SO_ERROR
;
168 case 0x1008: *optname
= SO_TYPE
;
171 fprintf(stderr
, "convert_sockopt() unknown optname %d\n", optname
);
175 case 6: *optname
= IPPROTO_TCP
;
179 SOCKET
Winsock_accept(SOCKET s
, struct sockaddr
*addr
, INT
*addrlen
)
184 fprintf(stderr
, "WSA_accept: socket %d, ptr %8x, length %d\n", s
, (int) addr
, addrlen
);
187 if ((sock
= accept(s
, addr
, (int *) addrlen
)) < 0) {
189 return INVALID_SOCKET
;
194 INT
Winsock_bind(SOCKET s
, struct sockaddr
*name
, INT namelen
)
197 fprintf(stderr
, "WSA_bind: socket %d, ptr %8x, length %d\n", s
, (int) name
, namelen
);
201 if (bind(s
, name
, namelen
) < 0) {
208 INT
Winsock_closesocket(SOCKET s
)
211 fprintf(stderr
, "WSA_closesocket: socket %d\n", s
);
214 FD_CLR(s
, &fd_in_use
);
223 INT
Winsock_connect(SOCKET s
, struct sockaddr
*name
, INT namelen
)
226 fprintf(stderr
, "WSA_connect: socket %d, ptr %8x, length %d\n", s
, (int) name
, namelen
);
230 if (connect(s
, name
, namelen
) < 0) {
237 INT
Winsock_getpeername(SOCKET s
, struct sockaddr
*name
, INT
*namelen
)
240 fprintf(stderr
, "WSA_getpeername: socket: %d, ptr %8x, ptr %8x\n", s
, (int) name
, *namelen
);
244 if (getpeername(s
, name
, (int *) namelen
) < 0) {
251 INT
Winsock_getsockname(SOCKET s
, struct sockaddr
*name
, INT
*namelen
)
254 fprintf(stderr
, "WSA_getsockname: socket: %d, ptr %8x, ptr %8x\n", s
, (int) name
, (int) *namelen
);
256 if (getsockname(s
, name
, (int *) namelen
) < 0) {
264 Winsock_getsockopt(SOCKET s
, INT level
, INT optname
, char *optval
, INT
*optlen
)
267 fprintf(stderr
, "WSA_getsockopt: socket: %d, opt %d, ptr %8x, ptr %8x\n", s
, level
, (int) optval
, (int) *optlen
);
269 convert_sockopt(&level
, &optname
);
271 if (getsockopt(s
, (int) level
, optname
, optval
, (int *) optlen
) < 0) {
278 u_long
Winsock_htonl(u_long hostlong
)
280 return( htonl(hostlong
) );
283 u_short
Winsock_htons(u_short hostshort
)
285 return( htons(hostshort
) );
288 u_long
Winsock_inet_addr(char *cp
)
290 return( inet_addr(cp
) );
293 char *Winsock_inet_ntoa(struct in_addr in
)
298 fprintf(stderr
, "WSA_inet_ntoa: %8x\n", in
);
301 if ((s
= inet_ntoa(in
)) == NULL
) {
306 strncpy(heap
->ntoa_buffer
, s
, sizeof(heap
->ntoa_buffer
) );
308 return (char *) &heap
->ntoa_buffer
;
311 INT
Winsock_ioctlsocket(SOCKET s
, long cmd
, u_long
*argp
)
314 fprintf(stderr
, "WSA_ioctl: socket %d, cmd %d, ptr %8x\n", s
, cmd
, (int) argp
);
317 if (ioctl(s
, cmd
, argp
) < 0) {
324 INT
Winsock_listen(SOCKET s
, INT backlog
)
327 fprintf(stderr
, "WSA_listen: socket %d, backlog %d\n", s
, backlog
);
330 if (listen(s
, backlog
) < 0) {
337 u_long
Winsock_ntohl(u_long netlong
)
339 return( ntohl(netlong
) );
342 u_short
Winsock_ntohs(u_short netshort
)
344 return( ntohs(netshort
) );
347 INT
Winsock_recv(SOCKET s
, char *buf
, INT len
, INT flags
)
352 fprintf(stderr
, "WSA_recv: socket %d, ptr %8x, length %d, flags %d\n", s
, (int) buf
, len
, flags
);
355 if ((length
= recv(s
, buf
, len
, flags
)) < 0) {
362 INT
Winsock_recvfrom(SOCKET s
, char *buf
, INT len
, INT flags
,
363 struct sockaddr
*from
, int *fromlen
)
368 fprintf(stderr
, "WSA_recvfrom: socket %d, ptr %8x, length %d, flags %d\n", s
, buf
, len
, flags
);
371 if ((length
= recvfrom(s
, buf
, len
, flags
, from
, fromlen
)) < 0) {
378 INT
Winsock_select(INT nfds
, fd_set
*readfds
, fd_set
*writefds
,
379 fd_set
*exceptfds
, struct timeval
*timeout
)
382 fprintf(stderr
, "WSA_select: fd # %d, ptr %8x, ptr %8x, ptr %*X\n", nfds
, readfds
, writefds
, exceptfds
);
385 return(select(nfds
, readfds
, writefds
, exceptfds
, timeout
));
388 INT
Winsock_send(SOCKET s
, char *buf
, INT len
, INT flags
)
393 fprintf(stderr
, "WSA_send: socket %d, ptr %8x, length %d, flags %d\n", s
, buf
, len
, flags
);
396 if ((length
= send(s
, buf
, len
, flags
)) < 0) {
403 INT
Winsock_sendto(SOCKET s
, char *buf
, INT len
, INT flags
,
404 struct sockaddr
*to
, INT tolen
)
409 fprintf(stderr
, "WSA_sendto: socket %d, ptr %8x, length %d, flags %d\n", s
, buf
, len
, flags
);
412 if ((length
= sendto(s
, buf
, len
, flags
, to
, tolen
)) < 0) {
419 INT
Winsock_setsockopt(SOCKET s
, INT level
, INT optname
, const char *optval
,
423 fprintf(stderr
, "WSA_setsockopt: socket %d, level %d, opt %d, ptr %8x, len %d\n", s
, level
, optname
, (int) optval
, optlen
);
425 convert_sockopt(&level
, &optname
);
427 if (setsockopt(s
, level
, optname
, optval
, optlen
) < 0) {
434 INT
Winsock_shutdown(SOCKET s
, INT how
)
437 fprintf(stderr
, "WSA_shutdown: socket s %d, how %d\n", s
, how
);
440 if (shutdown(s
, how
) < 0) {
447 SOCKET
Winsock_socket(INT af
, INT type
, INT protocol
)
452 fprintf(stderr
, "WSA_socket: af=%d type=%d protocol=%d\n", af
, type
, protocol
);
455 if ((sock
= socket(af
, type
, protocol
)) < 0) {
458 fprintf(stderr
, "WSA_socket: failed !\n");
460 return INVALID_SOCKET
;
464 wsa_errno
= WSAEMFILE
;
465 return INVALID_SOCKET
;
468 FD_SET(sock
, &fd_in_use
);
471 fprintf(stderr
, "WSA_socket: fd %d\n", sock
);
476 struct hostent
*Winsock_gethostbyaddr(const char *addr
, INT len
, INT type
)
478 struct hostent
*host
;
481 fprintf(stderr
, "WSA_gethostbyaddr: ptr %8x, len %d, type %d\n", (int) addr
, len
, type
);
484 if ((host
= gethostbyaddr(addr
, len
, type
)) == NULL
) {
488 memcpy(&heap
->hostent_addr
, host
, sizeof(struct hostent
));
490 return (struct hostent
*) &heap
->hostent_addr
;
493 struct hostent
*Winsock_gethostbyname(const char *name
)
495 struct hostent
*host
;
498 fprintf(stderr
, "WSA_gethostbyname: name %s\n", name
);
501 if ((host
= gethostbyname(name
)) == NULL
) {
505 memcpy(&heap
->hostent_name
, host
, sizeof(struct hostent
));
507 return (struct hostent
*) &heap
->hostent_name
;
510 int Winsock_gethostname(char *name
, INT namelen
)
514 fprintf(stderr
, "WSA_gethostname: name %d, len %d\n", name
, namelen
);
517 if (gethostname(name
, namelen
) < 0) {
524 struct protoent
*Winsock_getprotobyname(char *name
)
526 struct protoent
*proto
;
529 fprintf(stderr
, "WSA_getprotobyname: name %s\n", name
);
532 if ((proto
= getprotobyname(name
)) == NULL
) {
536 memcpy(&heap
->protoent_name
, proto
, sizeof(struct protoent
));
538 return (struct protoent
*) &heap
->protoent_name
;
541 struct protoent
*Winsock_getprotobynumber(INT number
)
543 struct protoent
*proto
;
546 fprintf(stderr
, "WSA_getprotobynumber: num %d\n", number
);
549 if ((proto
= getprotobynumber(number
)) == NULL
) {
553 memcpy(&heap
->protoent_number
, proto
, sizeof(struct protoent
));
555 return (struct protoent
*) &heap
->protoent_number
;
558 struct servent
*Winsock_getservbyname(const char *name
, const char *proto
)
560 struct servent
*service
;
563 fprintf(stderr
, "WSA_getservbyname: name %s, proto %s\n", name
, proto
);
566 if ((service
= getservbyname(name
, proto
)) == NULL
) {
570 memcpy(&heap
->servent_name
, service
, sizeof(struct servent
));
572 return (struct servent
*) &heap
->servent_name
;
575 struct servent
*Winsock_getservbyport(INT port
, const char *proto
)
577 struct servent
*service
;
580 fprintf(stderr
, "WSA_getservbyport: port %d, name %s\n", port
, proto
);
583 if ((service
= getservbyport(port
, proto
)) == NULL
) {
587 memcpy(&heap
->servent_port
, service
, sizeof(struct servent
));
589 return (struct servent
*) &heap
->servent_port
;
592 /******************** winsock specific functions ************************
595 static HANDLE new_handle
= 0;
597 HANDLE
AllocWSAHandle(void)
602 static void recv_message(int sig
)
604 struct ipc_packet message
;
606 if (msgrcv(wine_key
, &message
, IPC_PACKET_SIZE
, MTYPE
, IPC_NOWAIT
) == -1)
607 perror("wine: msgrcv");
610 "WSA: PostMessage (hwnd %d, wMsg %d, wParam %d, lParam %d)\n",
616 PostMessage(message
.hWnd
, message
.wMsg
, message
.handle
, message
.lParam
);
618 signal(SIGUSR1
, recv_message
);
622 static void send_message(HANDLE handle
, HWND hWnd
, u_int wMsg
, long lParam
)
624 struct ipc_packet message
;
626 message
.mtype
= MTYPE
;
627 message
.handle
= handle
;
630 message
.lParam
= lParam
;
633 "WSA: send (hwnd %d, wMsg %d, handle %d, lParam %d)\n",
634 hWnd
, wMsg
, handle
, lParam
);
636 if (msgsnd(wine_key
, &message
, IPC_PACKET_SIZE
, IPC_NOWAIT
) == -1)
637 perror("wine: msgsnd");
639 kill(getppid(), SIGUSR1
);
643 HANDLE
WSAAsyncGetHostByAddr(HWND hWnd
, u_int wMsg
, const char *addr
,
644 INT len
, INT type
, char *buf
, INT buflen
)
647 struct hostent
*host
;
649 handle
= AllocWSAHandle();
654 if ((host
= gethostbyaddr(addr
, len
, type
)) == NULL
) {
655 send_message(hWnd
, wMsg
, handle
, wsaerrno() << 16);
658 memcpy(buf
, host
, buflen
);
659 send_message(hWnd
, wMsg
, handle
, 0);
665 HANDLE
WSAAsyncGetHostByName(HWND hWnd
, u_int wMsg
, const char *name
,
666 char *buf
, INT buflen
)
669 struct hostent
*host
;
671 handle
= AllocWSAHandle();
676 if ((host
= gethostbyname(name
)) == NULL
) {
677 send_message(hWnd
, wMsg
, handle
, wsaerrno() << 16);
680 memcpy(buf
, host
, buflen
);
681 send_message(hWnd
, wMsg
, handle
, 0);
687 HANDLE
WSAAsyncGetProtoByName(HWND hWnd
, u_int wMsg
, const char *name
,
688 char *buf
, INT buflen
)
691 struct protoent
*proto
;
693 handle
= AllocWSAHandle();
698 if ((proto
= getprotobyname(name
)) == NULL
) {
699 send_message(hWnd
, wMsg
, handle
, wsaerrno() << 16);
702 memcpy(buf
, proto
, buflen
);
703 send_message(hWnd
, wMsg
, handle
, 0);
709 HANDLE
WSAAsyncGetProtoByNumber(HWND hWnd
, u_int wMsg
, INT number
,
710 char *buf
, INT buflen
)
713 struct protoent
*proto
;
715 handle
= AllocWSAHandle();
720 if ((proto
= getprotobynumber(number
)) == NULL
) {
721 send_message(hWnd
, wMsg
, handle
, wsaerrno() << 16);
724 memcpy(buf
, proto
, buflen
);
725 send_message(hWnd
, wMsg
, handle
, 0);
731 HANDLE
WSAAsyncGetServByName(HWND hWnd
, u_int wMsg
, const char *name
,
732 const char *proto
, char *buf
, INT buflen
)
735 struct servent
*service
;
737 handle
= AllocWSAHandle();
742 if ((service
= getservbyname(name
, proto
)) == NULL
) {
743 send_message(hWnd
, wMsg
, handle
, wsaerrno() << 16);
746 memcpy(buf
, service
, buflen
);
747 send_message(hWnd
, wMsg
, handle
, 0);
753 HANDLE
WSAAsyncGetServByPort(HWND hWnd
, u_int wMsg
, INT port
, const char
754 *proto
, char *buf
, INT buflen
)
757 struct servent
*service
;
759 handle
= AllocWSAHandle();
764 if ((service
= getservbyport(port
, proto
)) == NULL
) {
765 send_message(hWnd
, wMsg
, handle
, wsaerrno() << 16);
768 memcpy(buf
, service
, buflen
);
769 send_message(hWnd
, wMsg
, handle
, 0);
774 INT
WSAAsyncSelect(SOCKET s
, HWND hWnd
, u_int wMsg
, long lEvent
)
777 fd_set read_fds
, write_fds
, except_fds
;
780 fprintf(stderr
, "WSA_AsyncSelect: socket %d, HWND %d, wMsg %d, event %d\n", s
, hWnd
, wMsg
, lEvent
);
783 /* remove outstanding asyncselect() processes */
786 if (wMsg
== 0 && lEvent
== 0)
795 FD_ZERO(&except_fds
);
797 if (lEvent
& FD_READ
)
798 FD_SET(s
, &read_fds
);
799 if (lEvent
& FD_WRITE
)
800 FD_SET(s
, &write_fds
);
802 fcntl(s
, F_SETFL
, O_NONBLOCK
);
803 select(s
+ 1, &read_fds
, &write_fds
, &except_fds
, NULL
);
806 if (FD_ISSET(s
, &read_fds
))
808 if (FD_ISSET(s
, &write_fds
))
811 send_message(hWnd
, wMsg
, s
, (wsaerrno() << 16) | event
);
816 INT
WSAFDIsSet(INT fd
, fd_set
*set
)
818 return( FD_ISSET(fd
, set
) );
821 INT
WSACancelAsyncRequest(HANDLE hAsyncTaskHandle
)
824 fprintf(stderr
, "WSA_AsyncRequest: handle %d\n", hAsyncTaskHandle
);
830 INT
WSACancelBlockingCall(void)
833 fprintf(stderr
, "WSA_CancelBlockCall\n");
838 INT
WSAGetLastError(void)
841 fprintf(stderr
, "WSA_GetLastError\n");
847 void WSASetLastError(INT iError
)
850 fprintf(stderr
, "WSA_SetLastErorr %d\n", iError
);
856 BOOL
WSAIsBlocking(void)
859 fprintf(stderr
, "WSA_IsBlocking\n");
863 FARPROC
WSASetBlockingHook(FARPROC lpBlockFunc
)
866 fprintf(stderr
, "WSA_SetBlockHook %8x, STUB!\n", lpBlockFunc
);
868 BlockFunction
= lpBlockFunc
;
873 INT
WSAUnhookBlockingHook(void)
876 fprintf(stderr
, "WSA_UnhookBlockingHook\n");
878 BlockFunction
= NULL
;
883 WSADATA Winsock_data
= {
901 INT
WSAStartup(WORD wVersionRequested
, LPWSADATA lpWSAData
)
907 fprintf(stderr
, "WSAStartup: verReq=%x\n", wVersionRequested
);
910 if (LOBYTE(wVersionRequested
) < 1 ||
911 (LOBYTE(wVersionRequested
) == 1 &&
912 HIBYTE(wVersionRequested
) < 1))
913 return WSAVERNOTSUPPORTED
;
918 /* alloc winsock heap */
920 if ((HeapHandle
= GlobalAlloc(GMEM_FIXED
,sizeof(struct WinSockHeap
))) == 0)
921 return WSASYSNOTREADY
;
923 heap
= (struct WinSockHeap
*) GlobalLock(HeapHandle
);
925 HEAP_Init(&MyHeap
, heap
, sizeof(struct WinSockHeap
));
927 bcopy(&Winsock_data
, lpWSAData
, sizeof(Winsock_data
));
931 if ((wine_key
= msgget(IPC_PRIVATE
, 0600)) == -1)
932 perror("wine: msgget");
934 signal(SIGUSR1
, recv_message
);
949 if (msgctl(wine_key
, IPC_RMID
, NULL
) == -1)
950 perror("wine: shmctl");
952 for (fd
= 0; fd
!= FD_SETSIZE
; fd
++)
953 if (FD_ISSET(fd
, &fd_in_use
))