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

Last change on this file since 9852 was 9844, checked in by sandervl, 23 years ago

check for local host name in gethostbyname. if identical, then use localhost instead

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