source: trunk/src/wsock32/wsock32.cpp@ 7805

Last change on this file since 7805 was 7805, checked in by sandervl, 24 years ago

minor recv update (error handling)

File size: 45.7 KB
Line 
1/* $Id: wsock32.cpp,v 1.46 2002-02-06 10:33:56 sandervl Exp $ */
2
3/*
4 *
5 * Project Odin Software License can be found in LICENSE.TXT
6 *
7 * Win32 SOCK32 for OS/2
8 *
9 * Copyright (C) 1999 Patrick Haller <phaller@gmx.net>
10 * Copyright (C) 2000 Sander van Leeuwen (sandervl@xs4all.nl)
11 *
12 * Some parts based on Wine code: (dlls\winsock\socket.c)
13 * (C) 1993,1994,1996,1997 John Brezak, Erik Bos, Alex Korobka.
14 *
15 */
16
17/* Remark:
18 * 1999/11/21 experimental rewrite using IBM's PMWSock only
19 * -> some structural differences remain! (hostent)
20 * 1999/12/01 experimental rewrite works (TELNET)
21 * -> open issue: WSASetLastError / WSAGetLastError
22 * call SetLastError / GetLastError according to docs
23 *
24 * 2000/22/03 Complete rewrite -> got rid of pmwsock
25 *
26 * identical structures:
27 * - sockaddr_in
28 * - WSADATA
29 * - sockaddr
30 * - fd_set
31 * - timeval
32 *
33 * incompatible structures:
34 * - hostent
35 * - netent
36 * - servent
37 * - protent
38 * - linger
39 */
40
41
42/*****************************************************************************
43 * Includes *
44 *****************************************************************************/
45
46#define INCL_BASE
47#include <os2wrap.h> //Odin32 OS/2 api wrappers
48
49#include <string.h>
50#include <odinwrap.h>
51#include <os2sel.h>
52#include <stdlib.h>
53#include <win32api.h>
54#define NO_DCDATA
55#include <winuser32.h>
56#include <wprocess.h>
57#include <misc.h>
58
59#include "wsock32.h"
60#include <ws2tcpip.h>
61#include "wsastruct.h"
62#include "asyncthread.h"
63
64#define DBG_LOCALLOG DBG_wsock32
65#include "dbglocal.h"
66
67//kso: dirty fix to make this compile! not permanent!
68BOOL WINAPI QueryPerformanceCounter(LARGE_INTEGER *p);
69#define LowPart u.LowPart
70
71
72ODINDEBUGCHANNEL(WSOCK32-WSOCK32)
73
74
75/*****************************************************************************
76 * Local variables *
77 *****************************************************************************/
78
79static LPWSINFO lpFirstIData = NULL;
80
81
82//******************************************************************************
83//******************************************************************************
84
85// Note: for the TCP/IP 4.0 headers, SO_SNDTIMEO and SO_RCDTIMEO are
86// unfortunately not defined, so we do this here.
87#ifndef SO_SNDTIMEO
88#define SO_SNDTIMEO 0x1005
89#endif
90
91#ifndef SO_RCVTIMEO
92#define SO_RCVTIMEO 0x1006
93#endif
94
95
96//******************************************************************************
97//******************************************************************************
98LPWSINFO WINSOCK_GetIData(HANDLE tid)
99{
100 LPWSINFO iData;
101 BOOL fCurrentThread = FALSE;
102
103 if(tid == CURRENT_THREAD) {
104 tid = GetCurrentThread();
105 fCurrentThread = TRUE;
106 }
107tryagain:
108 for (iData = lpFirstIData; iData; iData = iData->lpNextIData) {
109 if (iData->dwThisThread == tid)
110 break;
111 }
112 if(iData == NULL && fCurrentThread) {
113 WINSOCK_CreateIData();
114 fCurrentThread = FALSE; //just to prevent infinite loops
115 goto tryagain;
116 }
117 if(iData == NULL) {
118 dprintf(("WINSOCK_GetIData: couldn't find struct for thread %x", tid));
119 DebugInt3();// should never happen!!!!!!!
120 }
121 return iData;
122}
123//******************************************************************************
124//******************************************************************************
125BOOL WINSOCK_CreateIData(void)
126{
127 LPWSINFO iData;
128
129 iData = (LPWSINFO)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(WSINFO));
130 if (!iData)
131 return FALSE;
132 iData->dwThisThread = GetCurrentThread();
133 iData->lpNextIData = lpFirstIData;
134 lpFirstIData = iData;
135 return TRUE;
136}
137//******************************************************************************
138//******************************************************************************
139void WINSOCK_DeleteIData(void)
140{
141 LPWSINFO iData = WINSOCK_GetIData();
142 LPWSINFO* ppid;
143 if (iData) {
144 for (ppid = &lpFirstIData; *ppid; ppid = &(*ppid)->lpNextIData) {
145 if (*ppid == iData) {
146 *ppid = iData->lpNextIData;
147 break;
148 }
149 }
150
151 if( iData->flags & WSI_BLOCKINGCALL )
152 dprintf(("\tinside blocking call!\n"));
153
154 /* delete scratch buffers */
155 if(iData->he) free(iData->he);
156 if(iData->se) free(iData->se);
157 if(iData->pe) free(iData->pe);
158
159 //// if( iData->buffer ) SEGPTR_FREE(iData->buffer);
160 //// if( iData->dbuffer ) SEGPTR_FREE(iData->dbuffer);
161
162 HeapFree(GetProcessHeap(), 0, iData);
163 }
164}
165//******************************************************************************
166//******************************************************************************
167void WIN32API WSASetLastError(int iError)
168{
169#ifdef DEBUG
170 char msg[20];
171#endif
172 // according to the docs, WSASetLastError() is just a call-through
173 // to SetLastError()
174 SetLastError(iError);
175#ifdef DEBUG
176 switch (iError)
177 {
178 case NO_ERROR:
179 strcpy(msg, "no error");
180 break;
181 case WSAEINTR:
182 strcpy(msg, "WSAEINTR");
183 break;
184 case WSAEBADF:
185 strcpy(msg, "WSAEBADF");
186 break;
187 case WSAEACCES:
188 strcpy(msg, "WSAEACCES");
189 break;
190 case WSAEFAULT:
191 strcpy(msg, "WSAEFAULT");
192 break;
193 case WSAEINVAL:
194 strcpy(msg, "WSAEINVAL");
195 break;
196 case WSAEMFILE:
197 strcpy(msg, "WSAEMFILE");
198 break;
199 case WSAEWOULDBLOCK:
200 strcpy(msg, "WSAEWOULDBLOCK");
201 break;
202 case WSAEINPROGRESS:
203 strcpy(msg, "WSAEINPROGRESS");
204 break;
205 case WSAEALREADY:
206 strcpy(msg, "WSAEALREADY");
207 break;
208 case WSAHOST_NOT_FOUND:
209 strcpy(msg, "WSAHOST_NOT_FOUND");
210 break;
211 default:
212 strcpy(msg, "unknown");
213 }
214 if (iError != 0)
215 {
216 dprintf(("WSASetLastError 0x%x - %s", iError, msg));
217 }
218#endif
219}
220//******************************************************************************
221//******************************************************************************
222int WIN32API WSAGetLastError()
223{
224 return GetLastError();
225}
226//******************************************************************************
227//******************************************************************************
228ODINFUNCTION2(int,OS2shutdown,
229 SOCKET,s,
230 int,how)
231{
232 int ret;
233
234 if(!fWSAInitialized) {
235 WSASetLastError(WSANOTINITIALISED);
236 return SOCKET_ERROR;
237 }
238 else
239 if(WSAIsBlocking()) {
240 WSASetLastError(WSAEINPROGRESS);
241 return SOCKET_ERROR;
242 }
243 ret = shutdown(s, how);
244
245 if(ret == SOCKET_ERROR) {
246 WSASetLastError(wsaErrno());
247 }
248 else WSASetLastError(NO_ERROR);
249 return ret;
250}
251//******************************************************************************
252//******************************************************************************
253ODINFUNCTION3(SOCKET,OS2socket,
254 int,af,
255 int,type,
256 int,protocol)
257{
258 SOCKET s;
259
260 if(!fWSAInitialized) {
261 WSASetLastError(WSANOTINITIALISED);
262 return SOCKET_ERROR;
263 }
264 else
265 if(WSAIsBlocking()) {
266 WSASetLastError(WSAEINPROGRESS);
267 return SOCKET_ERROR;
268 }
269 s = socket(af, type, protocol);
270
271 if(s == SOCKET_ERROR && sock_errno() == SOCEPFNOSUPPORT) {
272 //map SOCEPFNOSUPPORT to SOCEPFNOSUPPORT
273 WSASetLastError(SOCEPFNOSUPPORT);
274 }
275 else
276 if(s == SOCKET_ERROR) {
277 WSASetLastError(wsaErrno());
278 }
279 else WSASetLastError(NO_ERROR);
280 return s;
281}
282//******************************************************************************
283//******************************************************************************
284ODINFUNCTION1(int,OS2closesocket,SOCKET, s)
285{
286 int ret;
287
288 if(!fWSAInitialized) {
289 WSASetLastError(WSANOTINITIALISED);
290 return SOCKET_ERROR;
291 }
292 else
293 if(WSAIsBlocking()) {
294 WSASetLastError(WSAEINPROGRESS);
295 return SOCKET_ERROR;
296 }
297 //Close WSAAsyncSelect thread if one was created for this socket
298 FindAndSetAsyncEvent(s, WSA_SELECT_HWND, 0, 0, 0);
299
300 // wait thread termination
301 DosSleep(10);
302 ret = soclose(s);
303
304 if(ret == SOCKET_ERROR) {
305 WSASetLastError(wsaErrno());
306 }
307 else WSASetLastError(NO_ERROR);
308 return ret;
309}
310//******************************************************************************
311//******************************************************************************
312ODINFUNCTION3(int,OS2connect,
313 SOCKET, s,
314 const struct sockaddr *,name,
315 int, namelen)
316{
317 int ret;
318
319 if(!fWSAInitialized) {
320 WSASetLastError(WSANOTINITIALISED);
321 return SOCKET_ERROR;
322 }
323 else
324 if(WSAIsBlocking()) {
325 WSASetLastError(WSAEINPROGRESS);
326 return SOCKET_ERROR;
327 }
328 ret = connect(s, (sockaddr *)name, namelen);
329 // map BSD error codes
330 if(ret == SOCKET_ERROR) {
331 int sockerror = sock_errno();
332 if(sockerror && sockerror < SOCBASEERR) {
333 sockerror += SOCBASEERR;
334 }
335 if(sockerror == SOCEINPROGRESS) {
336 WSASetLastError(WSAEWOULDBLOCK);
337 }
338 else
339 if(sockerror == SOCEOPNOTSUPP) {
340 WSASetLastError(WSAEINVAL);
341 }
342 else WSASetLastError(wsaErrno());
343 }
344 else WSASetLastError(NO_ERROR);
345 return ret;
346}
347//******************************************************************************
348//******************************************************************************
349ODINFUNCTION3(int,OS2ioctlsocket,
350 SOCKET,s,
351 long, cmd,
352 u_long *,argp)
353{
354 int ret;
355
356 if(!fWSAInitialized) {
357 WSASetLastError(WSANOTINITIALISED);
358 return SOCKET_ERROR;
359 }
360 else
361 if(WSAIsBlocking()) {
362 WSASetLastError(WSAEINPROGRESS);
363 return SOCKET_ERROR;
364 }
365 // clear high word (not used in OS/2's tcpip stack)
366 cmd = LOUSHORT(cmd);
367
368 if(cmd != FIONBIO && cmd != FIONREAD && cmd != SIOCATMARK) {
369 WSASetLastError(WSAEINVAL);
370 return SOCKET_ERROR;
371 }
372
373 WSASetLastError(NO_ERROR);
374
375 //check if app want to set a socket, which has an outstanding async select,
376 //to blocking mode
377 if (cmd == FIONBIO) {
378 HWND hwnd;
379 int msg;
380 ULONG lEvent;
381
382 if(QueryAsyncEvent(s, &hwnd, &msg, &lEvent) == TRUE) {
383 if(*argp != 0) {
384 //nothing to do; already non-blocking
385 return NO_ERROR;
386 }
387 else
388 if(lEvent != 0) {
389 dprintf(("Trying to set socket to blocking mode while async select active -> return error!"));
390 WSASetLastError(WSAEINVAL);
391 return SOCKET_ERROR;
392 }
393 }
394 }
395 ret = ioctl(s, cmd, (char *)argp, sizeof(int));
396
397 // Map EOPNOTSUPP to EINVAL
398 int sockerror = sock_errno();
399 if(sockerror && sockerror < SOCBASEERR) {
400 sockerror += SOCBASEERR;
401 }
402
403 if(ret == SOCKET_ERROR && sockerror == SOCEOPNOTSUPP)
404 WSASetLastError(WSAEINVAL);
405 else
406 if(ret == SOCKET_ERROR) {
407 WSASetLastError(wsaErrno());
408 }
409 else WSASetLastError(NO_ERROR);
410 return ret;
411}
412//******************************************************************************
413//******************************************************************************
414ODINFUNCTION3(int,OS2getpeername,
415 SOCKET, s,
416 struct sockaddr *,name,
417 int *, namelen)
418{
419 int ret;
420
421 if(!fWSAInitialized) {
422 WSASetLastError(WSANOTINITIALISED);
423 return SOCKET_ERROR;
424 }
425 else
426 if(WSAIsBlocking()) {
427 WSASetLastError(WSAEINPROGRESS);
428 return SOCKET_ERROR;
429 }
430 else
431 if (namelen == NULL || *namelen < (int)sizeof(struct sockaddr_in)) {
432 WSASetLastError(WSAEFAULT);
433 return SOCKET_ERROR;
434 }
435 ret = getsockname(s, name, namelen);
436 if(ret == SOCKET_ERROR) {
437 WSASetLastError(wsaErrno());
438 }
439 else WSASetLastError(NO_ERROR);
440 return ret;
441}
442//******************************************************************************
443//******************************************************************************
444ODINFUNCTION3(int,OS2getsockname,
445 SOCKET,s,
446 struct sockaddr *,name,
447 int *, namelen)
448{
449 int ret;
450
451 if(!fWSAInitialized) {
452 WSASetLastError(WSANOTINITIALISED);
453 return SOCKET_ERROR;
454 }
455 else
456 if(WSAIsBlocking()) {
457 WSASetLastError(WSAEINPROGRESS);
458 return SOCKET_ERROR;
459 }
460 else
461 if (namelen == NULL || *namelen < (int)sizeof(struct sockaddr_in)) {
462 WSASetLastError(WSAEFAULT);
463 return SOCKET_ERROR;
464 }
465 ret = getsockname(s, name, namelen);
466 if(ret == SOCKET_ERROR) {
467 WSASetLastError(wsaErrno());
468 }
469 else WSASetLastError(NO_ERROR);
470 return ret;
471}
472//******************************************************************************
473//******************************************************************************
474ODINFUNCTION1(u_long,OS2htonl,
475 u_long,hostlong)
476{
477 return(htonl(hostlong));
478}
479//******************************************************************************
480//******************************************************************************
481ODINFUNCTION1(u_short,OS2htons,
482 u_short,hostshort)
483{
484 return(htons(hostshort));
485}
486//******************************************************************************
487//******************************************************************************
488ODINFUNCTION1(u_long,OS2ntohl,
489 u_long,netlong)
490{
491 return(ntohl(netlong));
492}
493//******************************************************************************
494//******************************************************************************
495ODINFUNCTION1(u_short,OS2ntohs,
496 u_short,netshort)
497{
498 return(ntohs(netshort));
499}
500//******************************************************************************
501//******************************************************************************
502ODINFUNCTION1(unsigned long,OS2inet_addr,
503 const char *, cp)
504{
505 dprintf(("WSOCK32: OS2inet_addr(%s)\n",
506 cp));
507
508 return (inet_addr((char *)cp));
509}
510//******************************************************************************
511//******************************************************************************
512ODINFUNCTION1(char *,OS2inet_ntoa,
513 struct in_addr, in)
514{
515 return(inet_ntoa(in));
516}
517//******************************************************************************
518//******************************************************************************
519ODINFUNCTION3(SOCKET,OS2accept, SOCKET, s,
520 struct sockaddr *,addr,
521 int *, addrlen)
522{
523 int ret, msg;
524 HWND hwnd;
525 ULONG lEvent;
526
527 if(!fWSAInitialized) {
528 WSASetLastError(WSANOTINITIALISED);
529 return SOCKET_ERROR;
530 }
531 else
532 if(WSAIsBlocking()) {
533 WSASetLastError(WSAEINPROGRESS);
534 return SOCKET_ERROR;
535 }
536 else
537 if ((addr != NULL) && (addrlen != NULL)) {
538 if (*addrlen < (int)sizeof(struct sockaddr_in)) {
539 WSASetLastError(WSAEFAULT);
540 return SOCKET_ERROR;
541 }
542 }
543 ret = accept(s, addr, addrlen);
544
545 if(ret != SOCKET_ERROR) {
546 //Enable FD_ACCEPT event flag if WSAAsyncSelect was called for this socket
547 EnableAsyncEvent(s, FD_ACCEPT);
548
549 //if this socket has an active async. select pending, then call WSAAsyncSelect
550 //with the same parameters for the new socket (see docs)
551 if(QueryAsyncEvent(s, &hwnd, &msg, &lEvent) == TRUE) {
552 if(WSAAsyncSelect(ret, hwnd, msg, lEvent) == SOCKET_ERROR) {
553 ret = SOCKET_ERROR;
554 }
555 }
556 }
557 if(ret == SOCKET_ERROR) {
558 WSASetLastError(wsaErrno());
559 }
560 else WSASetLastError(NO_ERROR);
561 return ret;
562}
563//******************************************************************************
564//******************************************************************************
565ODINFUNCTION3(int,OS2bind,
566 SOCKET ,s,
567 const struct sockaddr *,addr,
568 int, namelen)
569{
570 int ret;
571
572 if(!fWSAInitialized) {
573 WSASetLastError(WSANOTINITIALISED);
574 return SOCKET_ERROR;
575 }
576 else
577 if(WSAIsBlocking()) {
578 WSASetLastError(WSAEINPROGRESS);
579 return SOCKET_ERROR;
580 }
581 else
582 if(namelen < (int)sizeof(struct sockaddr_in)) {
583 WSASetLastError(WSAEFAULT);
584 return SOCKET_ERROR;
585 }
586 ret = bind(s, (struct sockaddr *)addr, namelen);
587
588 if(ret == SOCKET_ERROR) {
589 WSASetLastError(wsaErrno());
590 }
591 else WSASetLastError(NO_ERROR);
592 return ret;
593}
594//******************************************************************************
595//******************************************************************************
596ODINFUNCTION2(int,OS2listen,
597 SOCKET, s,
598 int, backlog)
599{
600 int ret, tmp, namelen;
601 struct sockaddr_in name;
602
603 if(!fWSAInitialized) {
604 WSASetLastError(WSANOTINITIALISED);
605 return SOCKET_ERROR;
606 }
607 else
608 if(WSAIsBlocking()) {
609 WSASetLastError(WSAEINPROGRESS);
610 return SOCKET_ERROR;
611 }
612 namelen = sizeof(name);
613 ret = getsockname(s, (struct sockaddr *)&name, &namelen);
614 if (ret == 0) {
615 if (name.sin_port == 0 && name.sin_addr.s_addr == 0) {
616 // Socket is not bound
617 WSASetLastError(WSAEINVAL);
618 return SOCKET_ERROR;
619 }
620 ret = ioctl(s, FIOBSTATUS, (char *)&tmp, sizeof(tmp)) &
621 (SS_ISCONNECTING | SS_ISCONNECTED | SS_ISDISCONNECTING);
622 if(ret) {
623 // Socket is already connected
624 WSASetLastError(WSAEISCONN);
625 return SOCKET_ERROR;
626 }
627 ret = listen(s, backlog);
628 //todo: reset FD_ACCEPT bit? (wine seems to do this, but it's not documented)
629 }
630 if(ret == SOCKET_ERROR) {
631 WSASetLastError(wsaErrno());
632 }
633 else WSASetLastError(NO_ERROR);
634 return ret;
635}
636//******************************************************************************
637//******************************************************************************
638ODINFUNCTION4(int,OS2recv,
639 SOCKET,s,
640 char *,buf,
641 int,len,
642 int,flags)
643{
644 int ret;
645
646 if(!fWSAInitialized) {
647 WSASetLastError(WSANOTINITIALISED);
648 return SOCKET_ERROR;
649 }
650 else
651 if(WSAIsBlocking()) {
652 WSASetLastError(WSAEINPROGRESS);
653 return SOCKET_ERROR;
654 }
655 ret = recv(s, buf, len, flags);
656
657 if(ret == SOCKET_ERROR) {
658 WSASetLastError(wsaErrno());
659 return SOCKET_ERROR;
660 }
661 else
662 if(ret == 0) {
663 int tmp, state;
664
665 state = ioctl(s, FIOBSTATUS, (char *)&tmp, sizeof(tmp));
666 if(state & SS_CANTRCVMORE) {
667 dprintf(("recv returned 0, socket is no longer connected -> return WSAENOTCONN"));
668 WSASetLastError(WSANO_DATA);
669 return 0; //graceful close
670 }
671 else
672 if(state & (SS_ISDISCONNECTING|SS_ISDISCONNECTED)) {
673 dprintf(("recv returned 0, socket is no longer connected -> return WSAENOTCONN"));
674 WSASetLastError(WSAENOTCONN);
675 return 0; //graceful close
676 }
677 else
678 if(state & SS_ISCONNECTED && flags != MSG_PEEK) {
679 dprintf(("recv returned 0, but socket is still connected -> return WSAWOULDBLOCK"));
680 WSASetLastError(WSAEWOULDBLOCK);
681 return SOCKET_ERROR;
682 }
683 }
684 else WSASetLastError(NO_ERROR);
685
686 //Reset FD_READ event flagfor WSAAsyncSelect thread if one was created for this socket
687 EnableAsyncEvent(s, FD_READ);
688 return ret;
689}
690//******************************************************************************
691//******************************************************************************
692ODINFUNCTION6(int,OS2recvfrom,
693 SOCKET,s,
694 char *,buf,
695 int,len,
696 int,flags,
697 struct sockaddr *,from,
698 int *,fromlen)
699{
700 int ret;
701
702 if(!fWSAInitialized) {
703 WSASetLastError(WSANOTINITIALISED);
704 return SOCKET_ERROR;
705 }
706 else
707 if(WSAIsBlocking()) {
708 WSASetLastError(WSAEINPROGRESS);
709 return SOCKET_ERROR;
710 }
711 else
712 if(fromlen == NULL || *fromlen < (int)sizeof(struct sockaddr_in)) {
713 WSASetLastError(WSAEFAULT);
714 return SOCKET_ERROR;
715 }
716 ret = recvfrom(s, buf, len, flags, from, fromlen);
717
718 if(ret == SOCKET_ERROR) {
719 WSASetLastError(wsaErrno());
720 }
721 else WSASetLastError(NO_ERROR);
722
723 //Reset FD_READ event flagfor WSAAsyncSelect thread if one was created for this socket
724 EnableAsyncEvent(s, FD_READ);
725 return ret;
726}
727//******************************************************************************
728//******************************************************************************
729ODINFUNCTION4(int,OS2send,
730 SOCKET,s,
731 const char *,buf,
732 int,len,
733 int,flags)
734{
735 int ret;
736
737 if(!fWSAInitialized) {
738 WSASetLastError(WSANOTINITIALISED);
739 return SOCKET_ERROR;
740 }
741 else
742 if(WSAIsBlocking()) {
743 WSASetLastError(WSAEINPROGRESS);
744 return SOCKET_ERROR;
745 }
746 ret = send(s, (char *)buf, len, flags);
747
748 if(ret == SOCKET_ERROR) {
749 WSASetLastError(wsaErrno());
750 }
751 else WSASetLastError(NO_ERROR);
752
753 //Reset FD_WRITE event flagfor WSAAsyncSelect thread if one was created for this socket
754 EnableAsyncEvent(s, FD_WRITE);
755 return ret;
756}
757//******************************************************************************
758//******************************************************************************
759ODINFUNCTION6(int,OS2sendto,
760 SOCKET,s,
761 const char *,buf,
762 int,len,
763 int,flags,
764 const struct sockaddr *,to,
765 int,tolen)
766{
767 int ret;
768 int optlen;
769 int option;
770
771 if(!fWSAInitialized) {
772 WSASetLastError(WSANOTINITIALISED);
773 return SOCKET_ERROR;
774 }
775 else
776 if(WSAIsBlocking()) {
777 WSASetLastError(WSAEINPROGRESS);
778 return SOCKET_ERROR;
779 }
780 else
781 if(tolen < (int)sizeof(struct sockaddr_in)) {
782 WSASetLastError(WSAEFAULT);
783 return SOCKET_ERROR;
784 }
785 // check if the socket is a raw socket and has the IP_HDRINCL switch
786 // if this is the case, we overwrite the IP header length field with
787 // the actual length because some apps tend to put in garbage in there
788 // and rely on Windows correcting this
789 optlen = sizeof(option);
790 option = 0;
791 ret = getsockopt(s, IPPROTO_IP, IP_HDRINCL_OS2, (char *)&option, &optlen);
792 if(ret == 0 && option != FALSE) {
793 *(u_short *)&buf[2] = len;
794 }
795 dprintf(("sending to %s", inet_ntoa(((sockaddr_in*)to)->sin_addr)));
796 ret = sendto(s, (char *)buf, len, flags, (struct sockaddr *)to, tolen);
797
798 if(ret == SOCKET_ERROR) {
799 WSASetLastError(wsaErrno());
800 }
801 else WSASetLastError(NO_ERROR);
802
803 //Reset FD_WRITE event flag for WSAAsyncSelect thread if one was created for this socket
804 EnableAsyncEvent(s, FD_WRITE);
805 return ret;
806}
807//******************************************************************************
808//******************************************************************************
809ODINFUNCTION5(int,OS2select,
810 int,nfds,
811 ws_fd_set *,readfds,
812 ws_fd_set *,writefds,
813 ws_fd_set *,exceptfds,
814 const struct timeval *,timeout)
815{
816 int ret, i, j;
817 int *sockets, *socktmp;
818 int nrread, nrwrite, nrexcept;
819 ULONG ttimeout;
820
821 WSASetLastError(NO_ERROR);
822
823 if(!fWSAInitialized) {
824 WSASetLastError(WSANOTINITIALISED);
825 return SOCKET_ERROR;
826 }
827 else
828 if(WSAIsBlocking()) {
829 WSASetLastError(WSAEINPROGRESS);
830 return SOCKET_ERROR;
831 }
832 else {
833 nrread = nrwrite = nrexcept = 0;
834 if(readfds) {
835 nrread += readfds->fd_count;
836 }
837 if(writefds) {
838 nrwrite += writefds->fd_count;
839 }
840 if(exceptfds) {
841 nrexcept += exceptfds->fd_count;
842 }
843#if 0
844 if(nrread + nrwrite + nrexcept == 0) {
845 dprintf(("ERROR: nrread + nrwrite + nrexcept == 0"));
846 WSASetLastError(WSAEINVAL);
847 return SOCKET_ERROR;
848 }
849#endif
850 if(timeout != NULL && (timeout->tv_sec < 0 || timeout->tv_usec < 0)) {
851 dprintf(("ERROR: timeout->tv_sec < 0 || timeout->tv_usec < 0"));
852 WSASetLastError(WSAEINVAL);
853 return SOCKET_ERROR;
854 }
855 if(timeout == NULL) {
856 ttimeout = -1L; // no timeout
857 }
858 else ttimeout = timeout->tv_sec * 1000 + timeout->tv_usec / 1000;
859
860 sockets = (int *)malloc(sizeof(int) * (nrread+nrwrite+nrexcept));
861 if(readfds) {
862 memcpy(&sockets[0], readfds->fd_array, nrread * sizeof(SOCKET));
863 }
864 if(writefds) {
865 memcpy(&sockets[nrread], writefds->fd_array, nrwrite * sizeof(SOCKET));
866 }
867 if(exceptfds) {
868 memcpy(&sockets[nrread+nrwrite], exceptfds->fd_array, nrexcept * sizeof(SOCKET));
869 }
870
871 ret = select(sockets, nrread, nrwrite, nrexcept, ttimeout);
872
873 if(ret == SOCKET_ERROR)
874 {
875 if(readfds != NULL)
876 readfds->fd_count = 0;
877
878 if(writefds != NULL)
879 writefds->fd_count = 0;
880
881 if(exceptfds != NULL)
882 exceptfds->fd_count = 0;
883
884 WSASetLastError(wsaErrno());
885 free(sockets);
886 return SOCKET_ERROR;
887 }
888
889 if(ret != 0) {
890 socktmp = sockets;
891 if(readfds != NULL) {
892 j = 0;
893 for(i=0;i<nrread;i++) {
894 if(socktmp[i] != -1) {
895 readfds->fd_array[i] = socktmp[i];
896 j++;
897 }
898 }
899 readfds->fd_count = j;
900 socktmp += nrread;
901 }
902
903 if(writefds != NULL) {
904 j = 0;
905 for(i=0;i<nrwrite;i++) {
906 if(socktmp[i] != -1) {
907 writefds->fd_array[i] = socktmp[i];
908 j++;
909 }
910 }
911 writefds->fd_count = j;
912 socktmp += nrwrite;
913 }
914 if(exceptfds != NULL) {
915 j = 0;
916 for(i=0;i<nrexcept;i++) {
917 if(socktmp[i] != -1) {
918 exceptfds->fd_array[i] = socktmp[i];
919 j++;
920 }
921 }
922 exceptfds->fd_count = j;
923 }
924 }
925 else {
926 if(readfds != NULL)
927 readfds->fd_count = 0;
928
929 if(writefds != NULL)
930 writefds->fd_count = 0;
931
932 if(exceptfds != NULL)
933 exceptfds->fd_count = 0;
934 }
935 free(sockets);
936 }
937 return ret;
938}
939//******************************************************************************
940//******************************************************************************
941ODINFUNCTION5(int,OS2setsockopt,
942 SOCKET,s,
943 int,level,
944 int,optname,
945 const char *,optval,
946 int,optlen)
947{
948 struct ws_linger *yy;
949 struct linger xx;
950 int ret;
951 ULONG size;
952 char *safeoptval;
953
954 if(!fWSAInitialized) {
955 dprintf(("WSA not initialized"));
956 WSASetLastError(WSANOTINITIALISED);
957 return SOCKET_ERROR;
958 }
959 else
960 if(WSAIsBlocking()) {
961 dprintf(("WSA is blocking"));
962 WSASetLastError(WSAEINPROGRESS);
963 return SOCKET_ERROR;
964 }
965 //SvL: The 16 bits TCP/IP stack doesn't like high addresses, so copy
966 // the option value(s) on the stack.
967 safeoptval = (char *)alloca(optlen);
968 if(safeoptval == NULL) {
969 DebugInt3();
970 WSASetLastError(WSAEFAULT);
971 return SOCKET_ERROR;
972 }
973 memcpy(safeoptval, optval, optlen);
974 optval = safeoptval;
975
976 if (level == SOL_SOCKET)
977 {
978 switch(optname)
979 {
980 case SO_DONTLINGER:
981 case SO_LINGER:
982 if(optlen < (int)sizeof(ws_linger))
983 {
984 dprintf(("SOL_SOCKET, SO_LINGER, optlen too small"));
985 WSASetLastError(WSAEFAULT);
986 return SOCKET_ERROR;
987 }
988 yy = (struct ws_linger *)optval;
989 dprintf(("%s: onoff %x linger %x", (optname == SO_DONTLINGER) ? "SO_DONTLINGER" : "SO_LINGER", (int)yy->l_onoff, (int)yy->l_linger));
990 xx.l_onoff = (optname == SO_DONTLINGER) ? !yy->l_onoff : yy->l_onoff;
991 xx.l_linger = yy->l_linger;
992
993 ret = setsockopt(s,level,optname,(char *)&xx, sizeof(xx));
994 break;
995 case SO_SNDBUF:
996 case SO_RCVBUF:
997 if(optlen < (int)sizeof(int))
998 {
999 dprintf(("SOL_SOCKET, SO_RCVBUF, optlen too small"));
1000 WSASetLastError(WSAEFAULT);
1001 return SOCKET_ERROR;
1002 }
1003
1004 size = *(ULONG *)optval;
1005tryagain:
1006 ret = setsockopt(s,level,optname, (char *)&size, sizeof(ULONG));
1007 if(ret == SOCKET_ERROR && wsaErrno() == WSAENOBUFS && size > 4096) {
1008 int newsize = (size > 65535) ? 63*1024 : (size-1024);
1009 dprintf(("setsockopt: change size from %d to %d", size, newsize));
1010 //SvL: Limit send & receive buffer length to 64k
1011 // (only happens with 16 bits tcpip stack?)
1012 size = newsize;
1013 goto tryagain;
1014 }
1015 break;
1016
1017 case SO_SNDTIMEO:
1018 case SO_RCVTIMEO:
1019 // convert "int" to "struct timeval"
1020 struct timeval tv;
1021 tv.tv_sec = *optval / 1000;
1022 tv.tv_usec = (*optval % 1000) * 1000;
1023 ret = setsockopt(s, level, optname, (char *)&tv, sizeof(tv) );
1024 break;
1025
1026 case SO_BROADCAST:
1027 case SO_DEBUG:
1028 case SO_KEEPALIVE:
1029 case SO_DONTROUTE:
1030 case SO_OOBINLINE:
1031 case SO_REUSEADDR:
1032 if(optlen < (int)sizeof(int)) {
1033 dprintf(("SOL_SOCKET, SO_REUSEADDR, optlen too small"));
1034 WSASetLastError(WSAEFAULT);
1035 return SOCKET_ERROR;
1036 }
1037 ret = setsockopt(s, level, optname, (char *)optval, optlen);
1038 break;
1039 default:
1040 dprintf(("setsockopt: SOL_SOCKET, unknown option %x", optname));
1041 WSASetLastError(WSAENOPROTOOPT);
1042 return SOCKET_ERROR;
1043 }
1044 }
1045 else
1046 if(level == IPPROTO_TCP)
1047 {
1048 if(optname == TCP_NODELAY) {
1049 if(optlen < (int)sizeof(int)) {
1050 dprintf(("IPPROTO_TCP, TCP_NODELAY, optlen too small"));
1051 WSASetLastError(WSAEFAULT);
1052 return SOCKET_ERROR;
1053 }
1054 ret = setsockopt(s, level, optname, (char *)optval, optlen);
1055 }
1056 else {
1057 dprintf(("setsockopt: IPPROTO_TCP, unknown option %x", optname));
1058 WSASetLastError(WSAENOPROTOOPT);
1059 return SOCKET_ERROR;
1060 }
1061 }
1062 else
1063 if (level == IPPROTO_IP)
1064 {
1065 switch (optname)
1066 {
1067 case IP_MULTICAST_IF:
1068 case WS2_IPPROTO_OPT(IP_MULTICAST_IF_WS2):
1069 {
1070 if (optlen < sizeof(in_addr))
1071 {
1072 dprintf(("IPPROTO_IP, IP_MULTICAST_IP, optlen too small"));
1073 WSASetLastError(WSAEFAULT);
1074 return SOCKET_ERROR;
1075 }
1076 //TODO convert common interface names!
1077 ret = setsockopt(s, IPPROTO_IP, IP_MULTICAST_IF_OS2, (char *)optval, optlen);
1078 break;
1079 }
1080
1081 case IP_ADD_MEMBERSHIP:
1082 case WS2_IPPROTO_OPT(IP_ADD_MEMBERSHIP_WS2):
1083 if (optlen < sizeof(struct ip_mreq))
1084 {
1085 dprintf(("IPPROTO_IP, IP_ADD_MEMBERSHIP, optlen too small"));
1086 WSASetLastError(WSAEFAULT);
1087 return SOCKET_ERROR;
1088 }
1089 ret = setsockopt(s, IPPROTO_IP, IP_ADD_MEMBERSHIP_OS2, (char *)optval, optlen);
1090 break;
1091
1092 case IP_DROP_MEMBERSHIP:
1093 case WS2_IPPROTO_OPT(IP_DROP_MEMBERSHIP_WS2):
1094 if (optlen < sizeof(struct ip_mreq))
1095 {
1096 dprintf(("IPPROTO_IP, IP_DROP_MEMBERSHIP, optlen too small"));
1097 WSASetLastError(WSAEFAULT);
1098 return SOCKET_ERROR;
1099 }
1100 ret = setsockopt(s, IPPROTO_IP, IP_DROP_MEMBERSHIP_OS2, (char *)optval, optlen);
1101 break;
1102
1103 case IP_MULTICAST_LOOP:
1104 case WS2_IPPROTO_OPT(IP_MULTICAST_LOOP_WS2):
1105 {
1106 u_int flLoop;
1107 if (optlen < sizeof(u_char))
1108 {
1109 dprintf(("IPPROTO_IP, IP_MULTICAST_LOOP/IP_MULTICAST_TTL, optlen too small"));
1110 WSASetLastError(WSAEFAULT);
1111 return SOCKET_ERROR;
1112 }
1113 flLoop = (*optval == 0) ? 0 : 1;
1114 dprintf(("IP_MULTICAST_LOOP %d", *optval));
1115 ret = setsockopt(s, IPPROTO_IP, IP_MULTICAST_LOOP_OS2, (char *)&flLoop, optlen);
1116 break;
1117 }
1118
1119 case IP_MULTICAST_TTL:
1120 case WS2_IPPROTO_OPT(IP_MULTICAST_TTL_WS2):
1121 if (optlen < sizeof(u_char))
1122 {
1123 dprintf(("IPPROTO_IP, IP_MULTICAST_TTL, optlen too small"));
1124 WSASetLastError(WSAEFAULT);
1125 return SOCKET_ERROR;
1126 }
1127 ret = setsockopt(s, IPPROTO_IP, IP_MULTICAST_TTL_OS2, (char *)optval, optlen);
1128 break;
1129
1130 case IP_TTL:
1131 case WS2_IPPROTO_OPT(IP_TTL_WS2):
1132 if (optlen < sizeof(u_int))
1133 {
1134 dprintf(("IPPROTO_IP, IP_TTL_WS2, optlen too small"));
1135 WSASetLastError(WSAEFAULT);
1136 return SOCKET_ERROR;
1137 }
1138 dprintf(("IPPROTO_IP, IP_TTL 0x%x", *optval));
1139 ret = setsockopt(s, IPPROTO_IP, IP_TTL_OS2, (char *)optval, optlen);
1140 break;
1141
1142 case IP_TOS:
1143 case WS2_IPPROTO_OPT(IP_TOS_WS2):
1144 if (optlen < sizeof(u_int))
1145 {
1146 dprintf(("IPPROTO_IP, IP_TOS_WS2, optlen too small"));
1147 WSASetLastError(WSAEFAULT);
1148 return SOCKET_ERROR;
1149 }
1150 dprintf(("IPPROTO_IP, IP_TOS 0x%x", *optval));
1151 ret = setsockopt(s, IPPROTO_IP, IP_TOS_OS2, (char *)optval, optlen);
1152 break;
1153
1154 case WS2_IPPROTO_OPT(IP_HDRINCL_WS2):
1155 if (optlen < sizeof(u_int))
1156 {
1157 dprintf(("IPPROTO_IP, IP_HDRINCL_WS2, optlen too small"));
1158 WSASetLastError(WSAEFAULT);
1159 return SOCKET_ERROR;
1160 }
1161 dprintf(("IPPROTO_IP, IP_HDRINCL 0x%x", *optval));
1162 ret = setsockopt(s, IPPROTO_IP, IP_HDRINCL_OS2, (char *)optval, optlen);
1163 break;
1164
1165 default:
1166 dprintf(("setsockopt: IPPROTO_IP, unknown option %x", optname));
1167 WSASetLastError(WSAENOPROTOOPT);
1168 return SOCKET_ERROR;
1169 }
1170 }
1171 else {
1172 dprintf(("unknown level code!"));
1173 WSASetLastError(WSAEINVAL);
1174 return SOCKET_ERROR;
1175 }
1176
1177 if(ret == SOCKET_ERROR) {
1178 WSASetLastError(wsaErrno());
1179 }
1180 else WSASetLastError(NO_ERROR);
1181 return ret;
1182}
1183//******************************************************************************
1184//******************************************************************************
1185ODINFUNCTION5(int,OS2getsockopt,
1186 SOCKET, s,
1187 int, level,
1188 int, optname,
1189 char *, optval,
1190 int *,optlen)
1191{
1192 struct ws_linger *yy;
1193 struct linger xx;
1194 int ret;
1195 int size, options;
1196
1197 if(!fWSAInitialized) {
1198 WSASetLastError(WSANOTINITIALISED);
1199 return SOCKET_ERROR;
1200 }
1201 else
1202 if(WSAIsBlocking()) {
1203 WSASetLastError(WSAEINPROGRESS);
1204 return SOCKET_ERROR;
1205 }
1206 if (level == SOL_SOCKET) {
1207 switch(optname) {
1208 case SO_DONTLINGER:
1209 case SO_LINGER:
1210 if(optlen == NULL || *optlen < sizeof(ws_linger)) {
1211 WSASetLastError(WSAEFAULT);
1212 return SOCKET_ERROR;
1213 }
1214 size = sizeof(xx);
1215 ret = getsockopt(s,level,optname,(char *)&xx, &size);
1216 yy = (struct ws_linger *)optval;
1217 yy->l_onoff = (optname == SO_DONTLINGER) ? !xx.l_onoff : xx.l_onoff;
1218 yy->l_linger = xx.l_linger;
1219 *optlen = size;
1220 break;
1221
1222 case SO_SNDBUF:
1223 case SO_RCVBUF:
1224 case SO_BROADCAST:
1225 case SO_DEBUG:
1226 case SO_KEEPALIVE:
1227 case SO_DONTROUTE:
1228 case SO_OOBINLINE:
1229 case SO_REUSEADDR:
1230 case SO_TYPE:
1231 if(optlen == NULL || *optlen < sizeof(int)) {
1232 WSASetLastError(WSAEFAULT);
1233 return SOCKET_ERROR;
1234 }
1235 ret = getsockopt(s, level, optname, (char *)optval, optlen);
1236 break;
1237 case SO_ACCEPTCONN:
1238 if(optlen == NULL || *optlen < sizeof(int)) {
1239 WSASetLastError(WSAEFAULT);
1240 return SOCKET_ERROR;
1241 }
1242 size = sizeof(options);
1243 ret = getsockopt(s, SOL_SOCKET, SO_OPTIONS, (char *)&options, &size);
1244 if(ret != SOCKET_ERROR) {
1245 *(BOOL *)optval = (options & SO_ACCEPTCONN) == SO_ACCEPTCONN;
1246 *optlen = sizeof(BOOL);
1247 }
1248 break;
1249 default:
1250 dprintf(("getsockopt: unknown option %x", optname));
1251 WSASetLastError(WSAENOPROTOOPT);
1252 return SOCKET_ERROR;
1253 }
1254 }
1255 else
1256 if(level == IPPROTO_TCP) {
1257 if(optname == TCP_NODELAY) {
1258 if(optlen == NULL || *optlen < sizeof(int)) {
1259 WSASetLastError(WSAEFAULT);
1260 return SOCKET_ERROR;
1261 }
1262 ret = getsockopt(s, level, optname, (char *)optval, optlen);
1263 }
1264 else {
1265 dprintf(("getsockopt: unknown option %x", optname));
1266 WSASetLastError(WSAENOPROTOOPT);
1267 return SOCKET_ERROR;
1268 }
1269 }
1270 else
1271 if(level == IPPROTO_IP) {
1272 switch (optname)
1273 {
1274 case IP_MULTICAST_IF:
1275 case WS2_IPPROTO_OPT(IP_MULTICAST_IF_WS2):
1276 {
1277 if (*optlen < sizeof(in_addr))
1278 {
1279 dprintf(("IPPROTO_IP, IP_MULTICAST_IP, optlen too small"));
1280 WSASetLastError(WSAEFAULT);
1281 return SOCKET_ERROR;
1282 }
1283 //TODO convert common interface names!
1284 ret = getsockopt(s, IPPROTO_IP, IP_MULTICAST_IF_OS2, (char *)optval, optlen);
1285 break;
1286 }
1287
1288 case IP_ADD_MEMBERSHIP:
1289 case WS2_IPPROTO_OPT(IP_ADD_MEMBERSHIP_WS2):
1290 if (*optlen < sizeof(struct ip_mreq))
1291 {
1292 dprintf(("IPPROTO_IP, IP_ADD_MEMBERSHIP, optlen too small"));
1293 WSASetLastError(WSAEFAULT);
1294 return SOCKET_ERROR;
1295 }
1296 ret = getsockopt(s, IPPROTO_IP, IP_ADD_MEMBERSHIP_OS2, (char *)optval, optlen);
1297 break;
1298
1299 case IP_DROP_MEMBERSHIP:
1300 case WS2_IPPROTO_OPT(IP_DROP_MEMBERSHIP_WS2):
1301 if (*optlen < sizeof(struct ip_mreq))
1302 {
1303 dprintf(("IPPROTO_IP, IP_DROP_MEMBERSHIP, optlen too small"));
1304 WSASetLastError(WSAEFAULT);
1305 return SOCKET_ERROR;
1306 }
1307 ret = getsockopt(s, IPPROTO_IP, IP_DROP_MEMBERSHIP_OS2, (char *)optval, optlen);
1308 break;
1309
1310 case IP_MULTICAST_LOOP:
1311 case WS2_IPPROTO_OPT(IP_MULTICAST_LOOP_WS2):
1312 {
1313 if (*optlen < sizeof(u_char))
1314 {
1315 dprintf(("IPPROTO_IP, IP_MULTICAST_LOOP/IP_MULTICAST_TTL, optlen too small"));
1316 WSASetLastError(WSAEFAULT);
1317 return SOCKET_ERROR;
1318 }
1319 ret = getsockopt(s, IPPROTO_IP, IP_MULTICAST_LOOP_OS2, (char *)optval, optlen);
1320 break;
1321 }
1322
1323 case IP_MULTICAST_TTL:
1324 case WS2_IPPROTO_OPT(IP_MULTICAST_TTL_WS2):
1325 if (*optlen < sizeof(u_char))
1326 {
1327 dprintf(("IPPROTO_IP, IP_MULTICAST_TTL, optlen too small"));
1328 WSASetLastError(WSAEFAULT);
1329 return SOCKET_ERROR;
1330 }
1331 ret = getsockopt(s, IPPROTO_IP, IP_MULTICAST_TTL_OS2, (char *)optval, optlen);
1332 break;
1333
1334 case IP_TTL:
1335 case WS2_IPPROTO_OPT(IP_TTL_WS2):
1336 if (*optlen < sizeof(u_int))
1337 {
1338 dprintf(("IPPROTO_IP, IP_TTL_WS2, optlen too small"));
1339 WSASetLastError(WSAEFAULT);
1340 return SOCKET_ERROR;
1341 }
1342 ret = getsockopt(s, IPPROTO_IP, IP_TTL_OS2, (char *)optval, optlen);
1343 break;
1344
1345 case IP_TOS:
1346 case WS2_IPPROTO_OPT(IP_TOS_WS2):
1347 if (*optlen < sizeof(u_int))
1348 {
1349 dprintf(("IPPROTO_IP, IP_TOS_WS2, optlen too small"));
1350 WSASetLastError(WSAEFAULT);
1351 return SOCKET_ERROR;
1352 }
1353 ret = getsockopt(s, IPPROTO_IP, IP_TOS_OS2, (char *)optval, optlen);
1354 break;
1355
1356 case WS2_IPPROTO_OPT(IP_HDRINCL_WS2):
1357 if (*optlen < sizeof(u_int))
1358 {
1359 dprintf(("IPPROTO_IP, IP_HDRINCL_WS2, optlen too small"));
1360 WSASetLastError(WSAEFAULT);
1361 return SOCKET_ERROR;
1362 }
1363 ret = getsockopt(s, IPPROTO_IP, IP_HDRINCL_OS2, (char *)optval, optlen);
1364 if(ret == 0) {
1365 ret = (ret != FALSE) ? TRUE : FALSE;
1366 }
1367 break;
1368
1369 default:
1370 dprintf(("getsockopt: IPPROTO_IP, unknown option %x", optname));
1371 WSASetLastError(WSAENOPROTOOPT);
1372 return SOCKET_ERROR;
1373 }
1374 }
1375 else {
1376 WSASetLastError(WSAEINVAL);
1377 return SOCKET_ERROR;
1378 }
1379
1380 if(ret == SOCKET_ERROR) {
1381 WSASetLastError(wsaErrno());
1382 }
1383 else WSASetLastError(NO_ERROR);
1384 return ret;
1385}
1386//******************************************************************************
1387//******************************************************************************
1388/* Database function prototypes */
1389//******************************************************************************
1390//******************************************************************************
1391ODINFUNCTION2(int,OS2gethostname,
1392 char *,name,
1393 int,namelen)
1394{
1395 int ret;
1396
1397 ret = gethostname(name, namelen);
1398 if(ret == NULL) {
1399 dprintf(("gethostname returned %s", name));
1400 WSASetLastError(NO_ERROR);
1401 return 0;
1402 }
1403 WSASetLastError((errno == EINVAL) ? WSAEFAULT : wsaErrno());
1404 return SOCKET_ERROR;
1405}
1406//******************************************************************************
1407//******************************************************************************
1408ODINFUNCTION3(ws_hostent *,OS2gethostbyaddr,
1409 const char *,addr,
1410 int,len,
1411 int,type)
1412{
1413 LPWSINFO pwsi = WINSOCK_GetIData();
1414
1415 if( pwsi )
1416 {
1417 struct hostent* host;
1418 if( (host = gethostbyaddr((char *)addr, len, type)) != NULL ) {
1419 if( WS_dup_he(pwsi, host) ) {
1420 WSASetLastError(NO_ERROR);
1421 return pwsi->he;
1422 }
1423 else WSASetLastError(WSAENOBUFS);
1424 }
1425 else WSASetLastError((h_errno < 0) ? wsaErrno() : wsaHerrno());
1426 }
1427 else WSASetLastError(WSANOTINITIALISED);
1428 return NULL;
1429}
1430//******************************************************************************
1431//NOTE: This function can possibly block for a very long time
1432// I.e. start ISDNPM without dialing in. gethostbyname will query
1433// each name server and retry several times (60+ seconds per name server)
1434//******************************************************************************
1435ODINFUNCTION1(ws_hostent *,OS2gethostbyname,
1436 const char *,name)
1437{
1438 LPWSINFO pwsi = WINSOCK_GetIData();
1439
1440 if( pwsi )
1441 {
1442 struct hostent* host;
1443
1444 dprintf(("gethostbyname %s", name));
1445
1446 host = gethostbyname( (char*) name);
1447
1448 if( host != NULL )
1449 {
1450 if( WS_dup_he(pwsi, host) )
1451 {
1452 WSASetLastError(NO_ERROR);
1453 return pwsi->he;
1454 }
1455 else
1456 WSASetLastError(WSAENOBUFS);
1457 }
1458 else
1459 WSASetLastError((h_errno < 0) ? wsaErrno() : wsaHerrno());
1460 }
1461 else
1462 WSASetLastError(WSANOTINITIALISED);
1463
1464 return NULL;
1465}
1466//******************************************************************************
1467//******************************************************************************
1468ODINFUNCTION2(struct ws_servent *,OS2getservbyport,
1469 int, port,
1470 const char *, proto)
1471{
1472 LPWSINFO pwsi = WINSOCK_GetIData();
1473
1474 if( pwsi )
1475 {
1476 struct servent* serv;
1477 if( (serv = getservbyport(port, (char *)proto)) != NULL ) {
1478 if( WS_dup_se(pwsi, serv) ) {
1479 WSASetLastError(NO_ERROR);
1480 return pwsi->se;
1481 }
1482 else WSASetLastError(WSAENOBUFS);
1483 }
1484 else WSASetLastError(WSANO_DATA);
1485 }
1486 else WSASetLastError(WSANOTINITIALISED);
1487 return NULL;
1488}
1489//******************************************************************************
1490//******************************************************************************
1491ODINFUNCTION2(struct ws_servent *,OS2getservbyname,
1492 const char *, name,
1493 const char *, proto)
1494{
1495 LPWSINFO pwsi = WINSOCK_GetIData();
1496
1497 if( pwsi )
1498 {
1499 struct servent *serv;
1500 if( (serv = getservbyname((char *)name, (char *)proto)) != NULL ) {
1501 if( WS_dup_se(pwsi, serv) ) {
1502 WSASetLastError(NO_ERROR);
1503 return pwsi->se;
1504 }
1505 else WSASetLastError(WSAENOBUFS);
1506 }
1507 else WSASetLastError(WSANO_DATA);
1508 }
1509 else WSASetLastError(WSANOTINITIALISED);
1510 return NULL;
1511}
1512//******************************************************************************
1513//******************************************************************************
1514ODINFUNCTION1(struct ws_protoent *,OS2getprotobynumber,
1515 int,number)
1516{
1517 LPWSINFO pwsi = WINSOCK_GetIData();
1518
1519 if( pwsi )
1520 {
1521 struct protoent* proto;
1522 if( (proto = getprotobynumber(number)) != NULL ) {
1523 if( WS_dup_pe(pwsi, proto) ) {
1524 WSASetLastError(NO_ERROR);
1525 return pwsi->pe;
1526 }
1527 else WSASetLastError(WSAENOBUFS);
1528 }
1529 else WSASetLastError(WSANO_DATA);
1530 }
1531 else WSASetLastError(WSANOTINITIALISED);
1532 return NULL;
1533}
1534//******************************************************************************
1535//******************************************************************************
1536ODINFUNCTION1(struct ws_protoent *,OS2getprotobyname,
1537 const char *,name)
1538{
1539 LPWSINFO pwsi = WINSOCK_GetIData();
1540
1541 if( pwsi )
1542 {
1543 struct protoent * proto;
1544 if( (proto = getprotobyname((char *)name)) != NULL ) {
1545 if(WS_dup_pe(pwsi, proto)) {
1546 WSASetLastError(NO_ERROR);
1547 return pwsi->pe;
1548 }
1549 else WSASetLastError(WSAENOBUFS);
1550 }
1551 else WSASetLastError((h_errno < 0) ? wsaErrno() : wsaHerrno());
1552 }
1553 else WSASetLastError(WSANOTINITIALISED);
1554 return NULL;
1555}
1556//******************************************************************************
1557//******************************************************************************
Note: See TracBrowser for help on using the repository browser.