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

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

Don't send FD_CONNECT for sockets that are returned by accept

File size: 48.3 KB
Line 
1/* $Id: wsock32.cpp,v 1.49 2002-02-23 16:39:10 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 dprintf(("%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 dprintf(("Packet length %d", ret));
741 for(int i=0;i<(ret+7)/8;i++) {
742 dprintf(("%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 dprintf(("Packet length %d", len));
786 for(int i=0;i<(len+7)/8;i++) {
787 dprintf(("%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 dprintf(("Packet length %d", len));
842 for(int i=0;i<(len+7)/8;i++) {
843 dprintf(("%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
1496 dprintf(("gethostbyname %s", name));
1497
1498 host = gethostbyname( (char*) name);
1499
1500 if( host != NULL )
1501 {
1502 if( WS_dup_he(pwsi, host) )
1503 {
1504 WSASetLastError(NO_ERROR);
1505 return pwsi->he;
1506 }
1507 else
1508 WSASetLastError(WSAENOBUFS);
1509 }
1510 else
1511 WSASetLastError((h_errno < 0) ? wsaErrno() : wsaHerrno());
1512 }
1513 else
1514 WSASetLastError(WSANOTINITIALISED);
1515
1516 return NULL;
1517}
1518//******************************************************************************
1519//******************************************************************************
1520ODINFUNCTION2(struct ws_servent *,OS2getservbyport,
1521 int, port,
1522 const char *, proto)
1523{
1524 LPWSINFO pwsi = WINSOCK_GetIData();
1525
1526 if( pwsi )
1527 {
1528 struct servent* serv;
1529 if( (serv = getservbyport(port, (char *)proto)) != NULL ) {
1530 if( WS_dup_se(pwsi, serv) ) {
1531 WSASetLastError(NO_ERROR);
1532 return pwsi->se;
1533 }
1534 else WSASetLastError(WSAENOBUFS);
1535 }
1536 else WSASetLastError(WSANO_DATA);
1537 }
1538 else WSASetLastError(WSANOTINITIALISED);
1539 return NULL;
1540}
1541//******************************************************************************
1542//******************************************************************************
1543ODINFUNCTION2(struct ws_servent *,OS2getservbyname,
1544 const char *, name,
1545 const char *, proto)
1546{
1547 LPWSINFO pwsi = WINSOCK_GetIData();
1548
1549 if( pwsi )
1550 {
1551 struct servent *serv;
1552 if( (serv = getservbyname((char *)name, (char *)proto)) != NULL ) {
1553 if( WS_dup_se(pwsi, serv) ) {
1554 WSASetLastError(NO_ERROR);
1555 return pwsi->se;
1556 }
1557 else WSASetLastError(WSAENOBUFS);
1558 }
1559 else WSASetLastError(WSANO_DATA);
1560 }
1561 else WSASetLastError(WSANOTINITIALISED);
1562 return NULL;
1563}
1564//******************************************************************************
1565//******************************************************************************
1566ODINFUNCTION1(struct ws_protoent *,OS2getprotobynumber,
1567 int,number)
1568{
1569 LPWSINFO pwsi = WINSOCK_GetIData();
1570
1571 if( pwsi )
1572 {
1573 struct protoent* proto;
1574 if( (proto = getprotobynumber(number)) != NULL ) {
1575 if( WS_dup_pe(pwsi, proto) ) {
1576 WSASetLastError(NO_ERROR);
1577 return pwsi->pe;
1578 }
1579 else WSASetLastError(WSAENOBUFS);
1580 }
1581 else WSASetLastError(WSANO_DATA);
1582 }
1583 else WSASetLastError(WSANOTINITIALISED);
1584 return NULL;
1585}
1586//******************************************************************************
1587//******************************************************************************
1588ODINFUNCTION1(struct ws_protoent *,OS2getprotobyname,
1589 const char *,name)
1590{
1591 LPWSINFO pwsi = WINSOCK_GetIData();
1592
1593 if( pwsi )
1594 {
1595 struct protoent * proto;
1596 if( (proto = getprotobyname((char *)name)) != NULL ) {
1597 if(WS_dup_pe(pwsi, proto)) {
1598 WSASetLastError(NO_ERROR);
1599 return pwsi->pe;
1600 }
1601 else WSASetLastError(WSAENOBUFS);
1602 }
1603 else WSASetLastError((h_errno < 0) ? wsaErrno() : wsaHerrno());
1604 }
1605 else WSASetLastError(WSANOTINITIALISED);
1606 return NULL;
1607}
1608//******************************************************************************
1609//******************************************************************************
Note: See TracBrowser for help on using the repository browser.