source: trunk/src/wsock32/wsock32.cpp

Last change on this file was 21916, checked in by dmik, 14 years ago

Merge branch gcc-kmk to trunk.

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