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

Last change on this file since 10367 was 9887, checked in by sandervl, 22 years ago

Removed wrong checks for invalid address parameters in sendto & recvfrom

File size: 48.5 KB
Line 
1/* $Id: wsock32.cpp,v 1.52 2003-03-03 16:34:39 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 //NOTE: do not check from & fromlen; they are allowed to be NULL/0
727
728 if(from) {
729 dprintf(("recvfrom to %s", inet_ntoa(((sockaddr_in*)from)->sin_addr)));
730 }
731 ret = recvfrom(s, buf, len, flags, from, fromlen);
732
733 if(ret == SOCKET_ERROR) {
734 WSASetLastError(wsaErrno());
735 }
736 else {
737#ifdef DUMP_PACKETS
738 dprintf2(("Packet length %d", ret));
739 for(int i=0;i<(ret+7)/8;i++) {
740 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]));
741 }
742#endif
743 WSASetLastError(NO_ERROR);
744 }
745
746 //Reset FD_READ event flagfor WSAAsyncSelect thread if one was created for this socket
747 EnableAsyncEvent(s, FD_READ);
748 return ret;
749}
750//******************************************************************************
751//******************************************************************************
752ODINFUNCTION4(int,OS2send,
753 SOCKET,s,
754 const char *,buf,
755 int,len,
756 int,flags)
757{
758 int ret;
759 int optlen;
760 int option;
761
762 if(!fWSAInitialized) {
763 WSASetLastError(WSANOTINITIALISED);
764 return SOCKET_ERROR;
765 }
766 else
767 if(WSAIsBlocking()) {
768 WSASetLastError(WSAEINPROGRESS);
769 return SOCKET_ERROR;
770 }
771 // check if the socket is a raw socket and has the IP_HDRINCL switch
772 // if this is the case, we overwrite the IP header length field with
773 // the actual length because some apps tend to put garbage in there
774 // and rely on Windows to correct this
775 optlen = sizeof(option);
776 option = 0;
777 ret = getsockopt(s, IPPROTO_IP, IP_HDRINCL_OS2, (char *)&option, &optlen);
778 if(ret == 0 && option != FALSE) {
779 *(u_short *)&buf[2] = len;
780 }
781
782#ifdef DUMP_PACKETS
783 dprintf2(("Packet length %d", len));
784 for(int i=0;i<(len+7)/8;i++) {
785 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]));
786 }
787#endif
788 ret = send(s, (char *)buf, len, flags);
789
790 if(ret == SOCKET_ERROR) {
791 WSASetLastError(wsaErrno());
792 }
793 else WSASetLastError(NO_ERROR);
794
795 //Reset FD_WRITE event flagfor WSAAsyncSelect thread if one was created for this socket
796 EnableAsyncEvent(s, FD_WRITE);
797 return ret;
798}
799//******************************************************************************
800//******************************************************************************
801ODINFUNCTION6(int,OS2sendto,
802 SOCKET,s,
803 const char *,buf,
804 int,len,
805 int,flags,
806 const struct sockaddr *,to,
807 int,tolen)
808{
809 int ret;
810 int optlen;
811 int option;
812
813 if(!fWSAInitialized) {
814 WSASetLastError(WSANOTINITIALISED);
815 return SOCKET_ERROR;
816 }
817 else
818 if(WSAIsBlocking()) {
819 WSASetLastError(WSAEINPROGRESS);
820 return SOCKET_ERROR;
821 }
822 //NOTE: do not check to & tolen; they are allowed to be NULL/0
823
824 // check if the socket is a raw socket and has the IP_HDRINCL switch
825 // if this is the case, we overwrite the IP header length field with
826 // the actual length because some apps tend to put garbage in there
827 // and rely on Windows to correct this
828 optlen = sizeof(option);
829 option = 0;
830 ret = getsockopt(s, IPPROTO_IP, IP_HDRINCL_OS2, (char *)&option, &optlen);
831 if(ret == 0 && option != FALSE) {
832 *(u_short *)&buf[2] = len;
833 }
834 if(to) {
835 dprintf(("sending to %s", inet_ntoa(((sockaddr_in*)to)->sin_addr)));
836 }
837#ifdef DUMP_PACKETS
838 dprintf2(("Packet length %d", len));
839 for(int i=0;i<(len+7)/8;i++) {
840 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]));
841 }
842#endif
843 ret = sendto(s, (char *)buf, len, flags, (struct sockaddr *)to, tolen);
844
845 if(ret == SOCKET_ERROR) {
846 WSASetLastError(wsaErrno());
847 }
848 else WSASetLastError(NO_ERROR);
849
850 //Reset FD_WRITE event flag for WSAAsyncSelect thread if one was created for this socket
851 EnableAsyncEvent(s, FD_WRITE);
852 return ret;
853}
854//******************************************************************************
855//******************************************************************************
856ODINFUNCTION5(int,OS2select,
857 int,nfds,
858 ws_fd_set *,readfds,
859 ws_fd_set *,writefds,
860 ws_fd_set *,exceptfds,
861 const struct timeval *,timeout)
862{
863 int ret, i, j;
864 int *sockets, *socktmp;
865 int nrread, nrwrite, nrexcept;
866 ULONG ttimeout;
867
868 WSASetLastError(NO_ERROR);
869
870 if(!fWSAInitialized) {
871 WSASetLastError(WSANOTINITIALISED);
872 return SOCKET_ERROR;
873 }
874 else
875 if(WSAIsBlocking()) {
876 WSASetLastError(WSAEINPROGRESS);
877 return SOCKET_ERROR;
878 }
879 else {
880 nrread = nrwrite = nrexcept = 0;
881 if(readfds) {
882 nrread += readfds->fd_count;
883 }
884 if(writefds) {
885 nrwrite += writefds->fd_count;
886 }
887 if(exceptfds) {
888 nrexcept += exceptfds->fd_count;
889 }
890#if 0
891 if(nrread + nrwrite + nrexcept == 0) {
892 dprintf(("ERROR: nrread + nrwrite + nrexcept == 0"));
893 WSASetLastError(WSAEINVAL);
894 return SOCKET_ERROR;
895 }
896#endif
897 if(timeout != NULL && (timeout->tv_sec < 0 || timeout->tv_usec < 0)) {
898 dprintf(("ERROR: timeout->tv_sec < 0 || timeout->tv_usec < 0"));
899 WSASetLastError(WSAEINVAL);
900 return SOCKET_ERROR;
901 }
902 if(timeout == NULL) {
903 ttimeout = -1L; // no timeout
904 }
905 else ttimeout = timeout->tv_sec * 1000 + timeout->tv_usec / 1000;
906
907 sockets = (int *)malloc(sizeof(int) * (nrread+nrwrite+nrexcept));
908 if(readfds) {
909 memcpy(&sockets[0], readfds->fd_array, nrread * sizeof(SOCKET));
910 }
911 if(writefds) {
912 memcpy(&sockets[nrread], writefds->fd_array, nrwrite * sizeof(SOCKET));
913 }
914 if(exceptfds) {
915 memcpy(&sockets[nrread+nrwrite], exceptfds->fd_array, nrexcept * sizeof(SOCKET));
916 }
917
918 ret = select(sockets, nrread, nrwrite, nrexcept, ttimeout);
919
920 if(ret == SOCKET_ERROR)
921 {
922 if(readfds != NULL)
923 readfds->fd_count = 0;
924
925 if(writefds != NULL)
926 writefds->fd_count = 0;
927
928 if(exceptfds != NULL)
929 exceptfds->fd_count = 0;
930
931 WSASetLastError(wsaErrno());
932 free(sockets);
933 return SOCKET_ERROR;
934 }
935
936 if(ret != 0) {
937 socktmp = sockets;
938 if(readfds != NULL) {
939 j = 0;
940 for(i=0;i<nrread;i++) {
941 if(socktmp[i] != -1) {
942 readfds->fd_array[i] = socktmp[i];
943 j++;
944 }
945 }
946 readfds->fd_count = j;
947 socktmp += nrread;
948 }
949
950 if(writefds != NULL) {
951 j = 0;
952 for(i=0;i<nrwrite;i++) {
953 if(socktmp[i] != -1) {
954 writefds->fd_array[i] = socktmp[i];
955 j++;
956 }
957 }
958 writefds->fd_count = j;
959 socktmp += nrwrite;
960 }
961 if(exceptfds != NULL) {
962 j = 0;
963 for(i=0;i<nrexcept;i++) {
964 if(socktmp[i] != -1) {
965 exceptfds->fd_array[i] = socktmp[i];
966 j++;
967 }
968 }
969 exceptfds->fd_count = j;
970 }
971 }
972 else {
973 if(readfds != NULL)
974 readfds->fd_count = 0;
975
976 if(writefds != NULL)
977 writefds->fd_count = 0;
978
979 if(exceptfds != NULL)
980 exceptfds->fd_count = 0;
981 }
982 free(sockets);
983 }
984 return ret;
985}
986//******************************************************************************
987//******************************************************************************
988ODINFUNCTION5(int,OS2setsockopt,
989 SOCKET,s,
990 int,level,
991 int,optname,
992 const char *,optval,
993 int,optlen)
994{
995 struct ws_linger *yy;
996 struct linger xx;
997 int ret, val;
998 ULONG size;
999 char *safeoptval;
1000
1001 if(!fWSAInitialized) {
1002 dprintf(("WSA not initialized"));
1003 WSASetLastError(WSANOTINITIALISED);
1004 return SOCKET_ERROR;
1005 }
1006 else
1007 if(WSAIsBlocking()) {
1008 dprintf(("WSA is blocking"));
1009 WSASetLastError(WSAEINPROGRESS);
1010 return SOCKET_ERROR;
1011 }
1012 //SvL: The 16 bits TCP/IP stack doesn't like high addresses, so copy
1013 // the option value(s) on the stack.
1014 safeoptval = (char *)alloca(optlen);
1015 if(safeoptval == NULL) {
1016 DebugInt3();
1017 WSASetLastError(WSAEFAULT);
1018 return SOCKET_ERROR;
1019 }
1020 memcpy(safeoptval, optval, optlen);
1021 optval = safeoptval;
1022
1023 if (level == SOL_SOCKET)
1024 {
1025 switch(optname)
1026 {
1027 case SO_DONTLINGER:
1028 case SO_LINGER:
1029 if(optlen < (int)sizeof(ws_linger))
1030 {
1031 dprintf(("SOL_SOCKET, SO_LINGER, optlen too small"));
1032 WSASetLastError(WSAEFAULT);
1033 return SOCKET_ERROR;
1034 }
1035 yy = (struct ws_linger *)optval;
1036 dprintf(("%s: onoff %x linger %x", (optname == SO_DONTLINGER) ? "SO_DONTLINGER" : "SO_LINGER", (int)yy->l_onoff, (int)yy->l_linger));
1037 xx.l_onoff = (optname == SO_DONTLINGER) ? !yy->l_onoff : yy->l_onoff;
1038 xx.l_linger = yy->l_linger;
1039
1040 ret = setsockopt(s,level,optname,(char *)&xx, sizeof(xx));
1041 break;
1042 case SO_SNDBUF:
1043 case SO_RCVBUF:
1044 if(optlen < (int)sizeof(int))
1045 {
1046 dprintf(("SOL_SOCKET, SO_RCVBUF, optlen too small"));
1047 WSASetLastError(WSAEFAULT);
1048 return SOCKET_ERROR;
1049 }
1050
1051 size = *(ULONG *)optval;
1052tryagain:
1053 ret = setsockopt(s,level,optname, (char *)&size, sizeof(ULONG));
1054 if(ret == SOCKET_ERROR && wsaErrno() == WSAENOBUFS && size > 4096) {
1055 int newsize = (size > 65535) ? 63*1024 : (size-1024);
1056 dprintf(("setsockopt: change size from %d to %d", size, newsize));
1057 //SvL: Limit send & receive buffer length to 64k
1058 // (only happens with 16 bits tcpip stack?)
1059 size = newsize;
1060 goto tryagain;
1061 }
1062 break;
1063
1064 case SO_SNDTIMEO:
1065 case SO_RCVTIMEO:
1066 // convert "int" to "struct timeval"
1067 struct timeval tv;
1068 tv.tv_sec = *optval / 1000;
1069 tv.tv_usec = (*optval % 1000) * 1000;
1070 ret = setsockopt(s, level, optname, (char *)&tv, sizeof(tv) );
1071 break;
1072
1073 case SO_BROADCAST:
1074 case SO_DEBUG:
1075 case SO_KEEPALIVE:
1076 case SO_DONTROUTE:
1077 case SO_OOBINLINE:
1078 case SO_REUSEADDR:
1079 if(optlen < (int)sizeof(int)) {
1080 dprintf(("SOL_SOCKET, SO_REUSEADDR, optlen too small"));
1081 WSASetLastError(WSAEFAULT);
1082 return SOCKET_ERROR;
1083 }
1084 ret = setsockopt(s, level, optname, (char *)optval, optlen);
1085 break;
1086 default:
1087 dprintf(("setsockopt: SOL_SOCKET, unknown option %x", optname));
1088 WSASetLastError(WSAENOPROTOOPT);
1089 return SOCKET_ERROR;
1090 }
1091 }
1092 else
1093 if(level == IPPROTO_TCP)
1094 {
1095 if(optname == TCP_NODELAY) {
1096 if(optlen < (int)sizeof(int)) {
1097 dprintf(("IPPROTO_TCP, TCP_NODELAY, optlen too small"));
1098 WSASetLastError(WSAEFAULT);
1099 return SOCKET_ERROR;
1100 }
1101 dprintf(("IPPROTO_TCP, TCP_NODELAY 0x%x", *optval));
1102 ret = setsockopt(s, level, optname, (char *)optval, optlen);
1103 }
1104 else {
1105 dprintf(("setsockopt: IPPROTO_TCP, unknown option %x", optname));
1106 WSASetLastError(WSAENOPROTOOPT);
1107 return SOCKET_ERROR;
1108 }
1109 }
1110 else
1111 if (level == IPPROTO_IP)
1112 {
1113 switch (optname)
1114 {
1115 case IP_MULTICAST_IF:
1116 case WS2_IPPROTO_OPT(IP_MULTICAST_IF_WS2):
1117 {
1118 if (optlen < sizeof(in_addr))
1119 {
1120 dprintf(("IPPROTO_IP, IP_MULTICAST_IP, optlen too small"));
1121 WSASetLastError(WSAEFAULT);
1122 return SOCKET_ERROR;
1123 }
1124 //TODO convert common interface names!
1125 ret = setsockopt(s, IPPROTO_IP, IP_MULTICAST_IF_OS2, (char *)optval, optlen);
1126 break;
1127 }
1128
1129 case IP_ADD_MEMBERSHIP:
1130 case WS2_IPPROTO_OPT(IP_ADD_MEMBERSHIP_WS2):
1131 if (optlen < sizeof(struct ip_mreq))
1132 {
1133 dprintf(("IPPROTO_IP, IP_ADD_MEMBERSHIP, optlen too small"));
1134 WSASetLastError(WSAEFAULT);
1135 return SOCKET_ERROR;
1136 }
1137 ret = setsockopt(s, IPPROTO_IP, IP_ADD_MEMBERSHIP_OS2, (char *)optval, optlen);
1138 break;
1139
1140 case IP_DROP_MEMBERSHIP:
1141 case WS2_IPPROTO_OPT(IP_DROP_MEMBERSHIP_WS2):
1142 if (optlen < sizeof(struct ip_mreq))
1143 {
1144 dprintf(("IPPROTO_IP, IP_DROP_MEMBERSHIP, optlen too small"));
1145 WSASetLastError(WSAEFAULT);
1146 return SOCKET_ERROR;
1147 }
1148 ret = setsockopt(s, IPPROTO_IP, IP_DROP_MEMBERSHIP_OS2, (char *)optval, optlen);
1149 break;
1150
1151 case IP_MULTICAST_LOOP:
1152 case WS2_IPPROTO_OPT(IP_MULTICAST_LOOP_WS2):
1153 {
1154 u_int flLoop;
1155 if (optlen < sizeof(u_char))
1156 {
1157 dprintf(("IPPROTO_IP, IP_MULTICAST_LOOP/IP_MULTICAST_TTL, optlen too small"));
1158 WSASetLastError(WSAEFAULT);
1159 return SOCKET_ERROR;
1160 }
1161 flLoop = (*optval == 0) ? 0 : 1;
1162 dprintf(("IP_MULTICAST_LOOP %d", *optval));
1163 ret = setsockopt(s, IPPROTO_IP, IP_MULTICAST_LOOP_OS2, (char *)&flLoop, optlen);
1164 break;
1165 }
1166
1167 case IP_MULTICAST_TTL:
1168 case WS2_IPPROTO_OPT(IP_MULTICAST_TTL_WS2):
1169 if (optlen < sizeof(u_char))
1170 {
1171 dprintf(("IPPROTO_IP, IP_MULTICAST_TTL, optlen too small"));
1172 WSASetLastError(WSAEFAULT);
1173 return SOCKET_ERROR;
1174 }
1175 ret = setsockopt(s, IPPROTO_IP, IP_MULTICAST_TTL_OS2, (char *)optval, optlen);
1176 break;
1177
1178 case IP_TTL:
1179 case WS2_IPPROTO_OPT(IP_TTL_WS2):
1180 if (optlen < sizeof(u_int))
1181 {
1182 dprintf(("IPPROTO_IP, IP_TTL_WS2, optlen too small"));
1183 WSASetLastError(WSAEFAULT);
1184 return SOCKET_ERROR;
1185 }
1186 dprintf(("IPPROTO_IP, IP_TTL 0x%x", *optval));
1187 ret = setsockopt(s, IPPROTO_IP, IP_TTL_OS2, (char *)optval, optlen);
1188 break;
1189
1190 case IP_TOS:
1191 case WS2_IPPROTO_OPT(IP_TOS_WS2):
1192 if (optlen < sizeof(u_int))
1193 {
1194 dprintf(("IPPROTO_IP, IP_TOS_WS2, optlen too small"));
1195 WSASetLastError(WSAEFAULT);
1196 return SOCKET_ERROR;
1197 }
1198 dprintf(("IPPROTO_IP, IP_TOS 0x%x", *optval));
1199 ret = setsockopt(s, IPPROTO_IP, IP_TOS_OS2, (char *)optval, optlen);
1200 break;
1201
1202 case WS2_IPPROTO_OPT(IP_HDRINCL_WS2):
1203 if (optlen < sizeof(u_int))
1204 {
1205 dprintf(("IPPROTO_IP, IP_HDRINCL_WS2, optlen too small"));
1206 WSASetLastError(WSAEFAULT);
1207 return SOCKET_ERROR;
1208 }
1209 val = *optval;
1210 dprintf(("IPPROTO_IP, IP_HDRINCL 0x%x", val));
1211 ret = setsockopt(s, IPPROTO_IP, IP_HDRINCL_OS2, (char *)&val, optlen);
1212 break;
1213
1214 default:
1215 dprintf(("setsockopt: IPPROTO_IP, unknown option %x", optname));
1216 WSASetLastError(WSAENOPROTOOPT);
1217 return SOCKET_ERROR;
1218 }
1219 }
1220 else {
1221 dprintf(("unknown level code!"));
1222 WSASetLastError(WSAEINVAL);
1223 return SOCKET_ERROR;
1224 }
1225
1226 if(ret == SOCKET_ERROR) {
1227 WSASetLastError(wsaErrno());
1228 }
1229 else WSASetLastError(NO_ERROR);
1230 return ret;
1231}
1232//******************************************************************************
1233//******************************************************************************
1234ODINFUNCTION5(int,OS2getsockopt,
1235 SOCKET, s,
1236 int, level,
1237 int, optname,
1238 char *, optval,
1239 int *,optlen)
1240{
1241 struct ws_linger *yy;
1242 struct linger xx;
1243 int ret;
1244 int size, options;
1245
1246 if(!fWSAInitialized) {
1247 WSASetLastError(WSANOTINITIALISED);
1248 return SOCKET_ERROR;
1249 }
1250 else
1251 if(WSAIsBlocking()) {
1252 WSASetLastError(WSAEINPROGRESS);
1253 return SOCKET_ERROR;
1254 }
1255 if (level == SOL_SOCKET) {
1256 switch(optname) {
1257 case SO_DONTLINGER:
1258 case SO_LINGER:
1259 if(optlen == NULL || *optlen < sizeof(ws_linger)) {
1260 WSASetLastError(WSAEFAULT);
1261 return SOCKET_ERROR;
1262 }
1263 size = sizeof(xx);
1264 ret = getsockopt(s,level,optname,(char *)&xx, &size);
1265 yy = (struct ws_linger *)optval;
1266 yy->l_onoff = (optname == SO_DONTLINGER) ? !xx.l_onoff : xx.l_onoff;
1267 yy->l_linger = xx.l_linger;
1268 *optlen = size;
1269 break;
1270
1271 case SO_SNDBUF:
1272 case SO_RCVBUF:
1273 case SO_BROADCAST:
1274 case SO_DEBUG:
1275 case SO_KEEPALIVE:
1276 case SO_DONTROUTE:
1277 case SO_OOBINLINE:
1278 case SO_REUSEADDR:
1279 case SO_TYPE:
1280 if(optlen == NULL || *optlen < sizeof(int)) {
1281 WSASetLastError(WSAEFAULT);
1282 return SOCKET_ERROR;
1283 }
1284 ret = getsockopt(s, level, optname, (char *)optval, optlen);
1285 break;
1286 case SO_ACCEPTCONN:
1287 if(optlen == NULL || *optlen < sizeof(int)) {
1288 WSASetLastError(WSAEFAULT);
1289 return SOCKET_ERROR;
1290 }
1291 size = sizeof(options);
1292 ret = getsockopt(s, SOL_SOCKET, SO_OPTIONS, (char *)&options, &size);
1293 if(ret != SOCKET_ERROR) {
1294 *(BOOL *)optval = (options & SO_ACCEPTCONN) == SO_ACCEPTCONN;
1295 *optlen = sizeof(BOOL);
1296 }
1297 break;
1298 default:
1299 dprintf(("getsockopt: unknown option %x", optname));
1300 WSASetLastError(WSAENOPROTOOPT);
1301 return SOCKET_ERROR;
1302 }
1303 }
1304 else
1305 if(level == IPPROTO_TCP) {
1306 if(optname == TCP_NODELAY) {
1307 if(optlen == NULL || *optlen < sizeof(int)) {
1308 WSASetLastError(WSAEFAULT);
1309 return SOCKET_ERROR;
1310 }
1311 ret = getsockopt(s, level, optname, (char *)optval, optlen);
1312 }
1313 else {
1314 dprintf(("getsockopt: unknown option %x", optname));
1315 WSASetLastError(WSAENOPROTOOPT);
1316 return SOCKET_ERROR;
1317 }
1318 }
1319 else
1320 if(level == IPPROTO_IP) {
1321 switch (optname)
1322 {
1323 case IP_MULTICAST_IF:
1324 case WS2_IPPROTO_OPT(IP_MULTICAST_IF_WS2):
1325 {
1326 if (*optlen < sizeof(in_addr))
1327 {
1328 dprintf(("IPPROTO_IP, IP_MULTICAST_IP, optlen too small"));
1329 WSASetLastError(WSAEFAULT);
1330 return SOCKET_ERROR;
1331 }
1332 //TODO convert common interface names!
1333 ret = getsockopt(s, IPPROTO_IP, IP_MULTICAST_IF_OS2, (char *)optval, optlen);
1334 break;
1335 }
1336
1337 case IP_ADD_MEMBERSHIP:
1338 case WS2_IPPROTO_OPT(IP_ADD_MEMBERSHIP_WS2):
1339 if (*optlen < sizeof(struct ip_mreq))
1340 {
1341 dprintf(("IPPROTO_IP, IP_ADD_MEMBERSHIP, optlen too small"));
1342 WSASetLastError(WSAEFAULT);
1343 return SOCKET_ERROR;
1344 }
1345 ret = getsockopt(s, IPPROTO_IP, IP_ADD_MEMBERSHIP_OS2, (char *)optval, optlen);
1346 break;
1347
1348 case IP_DROP_MEMBERSHIP:
1349 case WS2_IPPROTO_OPT(IP_DROP_MEMBERSHIP_WS2):
1350 if (*optlen < sizeof(struct ip_mreq))
1351 {
1352 dprintf(("IPPROTO_IP, IP_DROP_MEMBERSHIP, optlen too small"));
1353 WSASetLastError(WSAEFAULT);
1354 return SOCKET_ERROR;
1355 }
1356 ret = getsockopt(s, IPPROTO_IP, IP_DROP_MEMBERSHIP_OS2, (char *)optval, optlen);
1357 break;
1358
1359 case IP_MULTICAST_LOOP:
1360 case WS2_IPPROTO_OPT(IP_MULTICAST_LOOP_WS2):
1361 {
1362 if (*optlen < sizeof(u_char))
1363 {
1364 dprintf(("IPPROTO_IP, IP_MULTICAST_LOOP/IP_MULTICAST_TTL, optlen too small"));
1365 WSASetLastError(WSAEFAULT);
1366 return SOCKET_ERROR;
1367 }
1368 ret = getsockopt(s, IPPROTO_IP, IP_MULTICAST_LOOP_OS2, (char *)optval, optlen);
1369 break;
1370 }
1371
1372 case IP_MULTICAST_TTL:
1373 case WS2_IPPROTO_OPT(IP_MULTICAST_TTL_WS2):
1374 if (*optlen < sizeof(u_char))
1375 {
1376 dprintf(("IPPROTO_IP, IP_MULTICAST_TTL, optlen too small"));
1377 WSASetLastError(WSAEFAULT);
1378 return SOCKET_ERROR;
1379 }
1380 ret = getsockopt(s, IPPROTO_IP, IP_MULTICAST_TTL_OS2, (char *)optval, optlen);
1381 break;
1382
1383 case IP_TTL:
1384 case WS2_IPPROTO_OPT(IP_TTL_WS2):
1385 if (*optlen < sizeof(u_int))
1386 {
1387 dprintf(("IPPROTO_IP, IP_TTL_WS2, optlen too small"));
1388 WSASetLastError(WSAEFAULT);
1389 return SOCKET_ERROR;
1390 }
1391 ret = getsockopt(s, IPPROTO_IP, IP_TTL_OS2, (char *)optval, optlen);
1392 break;
1393
1394 case IP_TOS:
1395 case WS2_IPPROTO_OPT(IP_TOS_WS2):
1396 if (*optlen < sizeof(u_int))
1397 {
1398 dprintf(("IPPROTO_IP, IP_TOS_WS2, optlen too small"));
1399 WSASetLastError(WSAEFAULT);
1400 return SOCKET_ERROR;
1401 }
1402 ret = getsockopt(s, IPPROTO_IP, IP_TOS_OS2, (char *)optval, optlen);
1403 break;
1404
1405 case WS2_IPPROTO_OPT(IP_HDRINCL_WS2):
1406 if (*optlen < sizeof(u_int))
1407 {
1408 dprintf(("IPPROTO_IP, IP_HDRINCL_WS2, optlen too small"));
1409 WSASetLastError(WSAEFAULT);
1410 return SOCKET_ERROR;
1411 }
1412 ret = getsockopt(s, IPPROTO_IP, IP_HDRINCL_OS2, (char *)optval, optlen);
1413 if(ret == 0) {
1414 ret = (ret != FALSE) ? TRUE : FALSE;
1415 }
1416 break;
1417
1418 default:
1419 dprintf(("getsockopt: IPPROTO_IP, unknown option %x", optname));
1420 WSASetLastError(WSAENOPROTOOPT);
1421 return SOCKET_ERROR;
1422 }
1423 }
1424 else {
1425 WSASetLastError(WSAEINVAL);
1426 return SOCKET_ERROR;
1427 }
1428
1429 if(ret == SOCKET_ERROR) {
1430 WSASetLastError(wsaErrno());
1431 }
1432 else WSASetLastError(NO_ERROR);
1433 return ret;
1434}
1435//******************************************************************************
1436//******************************************************************************
1437/* Database function prototypes */
1438//******************************************************************************
1439//******************************************************************************
1440ODINFUNCTION2(int,OS2gethostname,
1441 char *,name,
1442 int,namelen)
1443{
1444 int ret;
1445
1446 ret = gethostname(name, namelen);
1447 if(ret == NULL) {
1448 dprintf(("gethostname returned %s", name));
1449 WSASetLastError(NO_ERROR);
1450 return 0;
1451 }
1452 WSASetLastError((errno == EINVAL) ? WSAEFAULT : wsaErrno());
1453 return SOCKET_ERROR;
1454}
1455//******************************************************************************
1456//******************************************************************************
1457ODINFUNCTION3(ws_hostent *,OS2gethostbyaddr,
1458 const char *,addr,
1459 int,len,
1460 int,type)
1461{
1462 LPWSINFO pwsi = WINSOCK_GetIData();
1463
1464 if( pwsi )
1465 {
1466 struct hostent* host;
1467 if( (host = gethostbyaddr((char *)addr, len, type)) != NULL ) {
1468 if( WS_dup_he(pwsi, host) ) {
1469 WSASetLastError(NO_ERROR);
1470 return pwsi->he;
1471 }
1472 else WSASetLastError(WSAENOBUFS);
1473 }
1474 else WSASetLastError((h_errno < 0) ? wsaErrno() : wsaHerrno());
1475 }
1476 else WSASetLastError(WSANOTINITIALISED);
1477 return NULL;
1478}
1479//******************************************************************************
1480//NOTE: This function can possibly block for a very long time
1481// I.e. start ISDNPM without dialing in. gethostbyname will query
1482// each name server and retry several times (60+ seconds per name server)
1483//******************************************************************************
1484ODINFUNCTION1(ws_hostent *,OS2gethostbyname,
1485 const char *,name)
1486{
1487 LPWSINFO pwsi = WINSOCK_GetIData();
1488
1489 if( pwsi )
1490 {
1491 struct hostent* host;
1492 char localhostname[256];
1493
1494 dprintf(("gethostbyname %s", name));
1495 if(gethostname(localhostname, sizeof(localhostname)) == NO_ERROR)
1496 {
1497 if(!strcmp(name, localhostname)) {
1498 strcpy(localhostname, "localhost");
1499 name = localhostname;
1500 dprintf(("using localhost"));
1501 }
1502 }
1503
1504 host = gethostbyname( (char*) name);
1505
1506 if( host != NULL )
1507 {
1508 if( WS_dup_he(pwsi, host) )
1509 {
1510 WSASetLastError(NO_ERROR);
1511 return pwsi->he;
1512 }
1513 else
1514 WSASetLastError(WSAENOBUFS);
1515 }
1516 else
1517 WSASetLastError((h_errno < 0) ? wsaErrno() : wsaHerrno());
1518 }
1519 else
1520 WSASetLastError(WSANOTINITIALISED);
1521
1522 return NULL;
1523}
1524//******************************************************************************
1525//******************************************************************************
1526ODINFUNCTION2(struct ws_servent *,OS2getservbyport,
1527 int, port,
1528 const char *, proto)
1529{
1530 LPWSINFO pwsi = WINSOCK_GetIData();
1531
1532 if( pwsi )
1533 {
1534 struct servent* serv;
1535 if( (serv = getservbyport(port, (char *)proto)) != NULL ) {
1536 if( WS_dup_se(pwsi, serv) ) {
1537 WSASetLastError(NO_ERROR);
1538 return pwsi->se;
1539 }
1540 else WSASetLastError(WSAENOBUFS);
1541 }
1542 else WSASetLastError(WSANO_DATA);
1543 }
1544 else WSASetLastError(WSANOTINITIALISED);
1545 return NULL;
1546}
1547//******************************************************************************
1548//******************************************************************************
1549ODINFUNCTION2(struct ws_servent *,OS2getservbyname,
1550 const char *, name,
1551 const char *, proto)
1552{
1553 LPWSINFO pwsi = WINSOCK_GetIData();
1554
1555 if( pwsi )
1556 {
1557 struct servent *serv;
1558 if( (serv = getservbyname((char *)name, (char *)proto)) != NULL ) {
1559 if( WS_dup_se(pwsi, serv) ) {
1560 WSASetLastError(NO_ERROR);
1561 return pwsi->se;
1562 }
1563 else WSASetLastError(WSAENOBUFS);
1564 }
1565 else WSASetLastError(WSANO_DATA);
1566 }
1567 else WSASetLastError(WSANOTINITIALISED);
1568 return NULL;
1569}
1570//******************************************************************************
1571//******************************************************************************
1572ODINFUNCTION1(struct ws_protoent *,OS2getprotobynumber,
1573 int,number)
1574{
1575 LPWSINFO pwsi = WINSOCK_GetIData();
1576
1577 if( pwsi )
1578 {
1579 struct protoent* proto;
1580 if( (proto = getprotobynumber(number)) != NULL ) {
1581 if( WS_dup_pe(pwsi, proto) ) {
1582 WSASetLastError(NO_ERROR);
1583 return pwsi->pe;
1584 }
1585 else WSASetLastError(WSAENOBUFS);
1586 }
1587 else WSASetLastError(WSANO_DATA);
1588 }
1589 else WSASetLastError(WSANOTINITIALISED);
1590 return NULL;
1591}
1592//******************************************************************************
1593//******************************************************************************
1594ODINFUNCTION1(struct ws_protoent *,OS2getprotobyname,
1595 const char *,name)
1596{
1597 LPWSINFO pwsi = WINSOCK_GetIData();
1598
1599 if( pwsi )
1600 {
1601 struct protoent * proto;
1602 if( (proto = getprotobyname((char *)name)) != NULL ) {
1603 if(WS_dup_pe(pwsi, proto)) {
1604 WSASetLastError(NO_ERROR);
1605 return pwsi->pe;
1606 }
1607 else WSASetLastError(WSAENOBUFS);
1608 }
1609 else WSASetLastError((h_errno < 0) ? wsaErrno() : wsaHerrno());
1610 }
1611 else WSASetLastError(WSANOTINITIALISED);
1612 return NULL;
1613}
1614//******************************************************************************
1615//******************************************************************************
Note: See TracBrowser for help on using the repository browser.