1 /**
2  * WinPR: Windows Portable Runtime
3  * Windows Sockets (Winsock)
4  *
5  * Copyright 2012 Marc-Andre Moreau <marcandre.moreau@gmail.com>
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  *     http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  */
19 
20 #ifdef HAVE_CONFIG_H
21 #include "config.h"
22 #endif
23 
24 #include <winpr/crt.h>
25 #include <winpr/synch.h>
26 
27 #include <winpr/winsock.h>
28 
29 #ifdef HAVE_UNISTD_H
30 #include <unistd.h>
31 #endif
32 #ifdef HAVE_SYS_FILIO_H
33 #include <sys/filio.h>
34 #endif
35 #ifdef HAVE_SYS_SOCKIO_H
36 #include <sys/sockio.h>
37 #endif
38 
39 #ifndef _WIN32
40 #include <fcntl.h>
41 #endif
42 
43 #ifdef __APPLE__
44 #define WSAIOCTL_IFADDRS
45 #include <ifaddrs.h>
46 #endif
47 
48 /**
49  * ws2_32.dll:
50  *
51  * __WSAFDIsSet
52  * accept
53  * bind
54  * closesocket
55  * connect
56  * freeaddrinfo
57  * FreeAddrInfoEx
58  * FreeAddrInfoExW
59  * FreeAddrInfoW
60  * getaddrinfo
61  * GetAddrInfoExA
62  * GetAddrInfoExCancel
63  * GetAddrInfoExOverlappedResult
64  * GetAddrInfoExW
65  * GetAddrInfoW
66  * gethostbyaddr
67  * gethostbyname
68  * gethostname
69  * GetHostNameW
70  * getnameinfo
71  * GetNameInfoW
72  * getpeername
73  * getprotobyname
74  * getprotobynumber
75  * getservbyname
76  * getservbyport
77  * getsockname
78  * getsockopt
79  * htonl
80  * htons
81  * inet_addr
82  * inet_ntoa
83  * inet_ntop
84  * inet_pton
85  * InetNtopW
86  * InetPtonW
87  * ioctlsocket
88  * listen
89  * ntohl
90  * ntohs
91  * recv
92  * recvfrom
93  * select
94  * send
95  * sendto
96  * SetAddrInfoExA
97  * SetAddrInfoExW
98  * setsockopt
99  * shutdown
100  * socket
101  * WahCloseApcHelper
102  * WahCloseHandleHelper
103  * WahCloseNotificationHandleHelper
104  * WahCloseSocketHandle
105  * WahCloseThread
106  * WahCompleteRequest
107  * WahCreateHandleContextTable
108  * WahCreateNotificationHandle
109  * WahCreateSocketHandle
110  * WahDestroyHandleContextTable
111  * WahDisableNonIFSHandleSupport
112  * WahEnableNonIFSHandleSupport
113  * WahEnumerateHandleContexts
114  * WahInsertHandleContext
115  * WahNotifyAllProcesses
116  * WahOpenApcHelper
117  * WahOpenCurrentThread
118  * WahOpenHandleHelper
119  * WahOpenNotificationHandleHelper
120  * WahQueueUserApc
121  * WahReferenceContextByHandle
122  * WahRemoveHandleContext
123  * WahWaitForNotification
124  * WahWriteLSPEvent
125  * WEP
126  * WPUCompleteOverlappedRequest
127  * WPUGetProviderPathEx
128  * WSAAccept
129  * WSAAddressToStringA
130  * WSAAddressToStringW
131  * WSAAdvertiseProvider
132  * WSAAsyncGetHostByAddr
133  * WSAAsyncGetHostByName
134  * WSAAsyncGetProtoByName
135  * WSAAsyncGetProtoByNumber
136  * WSAAsyncGetServByName
137  * WSAAsyncGetServByPort
138  * WSAAsyncSelect
139  * WSACancelAsyncRequest
140  * WSACancelBlockingCall
141  * WSACleanup
142  * WSACloseEvent
143  * WSAConnect
144  * WSAConnectByList
145  * WSAConnectByNameA
146  * WSAConnectByNameW
147  * WSACreateEvent
148  * WSADuplicateSocketA
149  * WSADuplicateSocketW
150  * WSAEnumNameSpaceProvidersA
151  * WSAEnumNameSpaceProvidersExA
152  * WSAEnumNameSpaceProvidersExW
153  * WSAEnumNameSpaceProvidersW
154  * WSAEnumNetworkEvents
155  * WSAEnumProtocolsA
156  * WSAEnumProtocolsW
157  * WSAEventSelect
158  * WSAGetLastError
159  * WSAGetOverlappedResult
160  * WSAGetQOSByName
161  * WSAGetServiceClassInfoA
162  * WSAGetServiceClassInfoW
163  * WSAGetServiceClassNameByClassIdA
164  * WSAGetServiceClassNameByClassIdW
165  * WSAHtonl
166  * WSAHtons
167  * WSAInstallServiceClassA
168  * WSAInstallServiceClassW
169  * WSAIoctl
170  * WSAIsBlocking
171  * WSAJoinLeaf
172  * WSALookupServiceBeginA
173  * WSALookupServiceBeginW
174  * WSALookupServiceEnd
175  * WSALookupServiceNextA
176  * WSALookupServiceNextW
177  * WSANSPIoctl
178  * WSANtohl
179  * WSANtohs
180  * WSAPoll
181  * WSAProviderCompleteAsyncCall
182  * WSAProviderConfigChange
183  * WSApSetPostRoutine
184  * WSARecv
185  * WSARecvDisconnect
186  * WSARecvFrom
187  * WSARemoveServiceClass
188  * WSAResetEvent
189  * WSASend
190  * WSASendDisconnect
191  * WSASendMsg
192  * WSASendTo
193  * WSASetBlockingHook
194  * WSASetEvent
195  * WSASetLastError
196  * WSASetServiceA
197  * WSASetServiceW
198  * WSASocketA
199  * WSASocketW
200  * WSAStartup
201  * WSAStringToAddressA
202  * WSAStringToAddressW
203  * WSAUnadvertiseProvider
204  * WSAUnhookBlockingHook
205  * WSAWaitForMultipleEvents
206  * WSCDeinstallProvider
207  * WSCDeinstallProviderEx
208  * WSCEnableNSProvider
209  * WSCEnumProtocols
210  * WSCEnumProtocolsEx
211  * WSCGetApplicationCategory
212  * WSCGetApplicationCategoryEx
213  * WSCGetProviderInfo
214  * WSCGetProviderPath
215  * WSCInstallNameSpace
216  * WSCInstallNameSpaceEx
217  * WSCInstallNameSpaceEx2
218  * WSCInstallProvider
219  * WSCInstallProviderAndChains
220  * WSCInstallProviderEx
221  * WSCSetApplicationCategory
222  * WSCSetApplicationCategoryEx
223  * WSCSetProviderInfo
224  * WSCUnInstallNameSpace
225  * WSCUnInstallNameSpaceEx2
226  * WSCUpdateProvider
227  * WSCUpdateProviderEx
228  * WSCWriteNameSpaceOrder
229  * WSCWriteProviderOrder
230  * WSCWriteProviderOrderEx
231  */
232 
233 #ifdef _WIN32
234 
235 #if (_WIN32_WINNT < 0x0600)
236 
winpr_inet_ntop(INT Family,PVOID pAddr,PSTR pStringBuf,size_t StringBufSize)237 PCSTR winpr_inet_ntop(INT Family, PVOID pAddr, PSTR pStringBuf, size_t StringBufSize)
238 {
239 	if (Family == AF_INET)
240 	{
241 		struct sockaddr_in in;
242 		memset(&in, 0, sizeof(in));
243 		in.sin_family = AF_INET;
244 		memcpy(&in.sin_addr, pAddr, sizeof(struct in_addr));
245 		getnameinfo((struct sockaddr*)&in, sizeof(struct sockaddr_in), pStringBuf, StringBufSize,
246 		            NULL, 0, NI_NUMERICHOST);
247 		return pStringBuf;
248 	}
249 	else if (Family == AF_INET6)
250 	{
251 		struct sockaddr_in6 in;
252 		memset(&in, 0, sizeof(in));
253 		in.sin6_family = AF_INET6;
254 		memcpy(&in.sin6_addr, pAddr, sizeof(struct in_addr6));
255 		getnameinfo((struct sockaddr*)&in, sizeof(struct sockaddr_in6), pStringBuf, StringBufSize,
256 		            NULL, 0, NI_NUMERICHOST);
257 		return pStringBuf;
258 	}
259 
260 	return NULL;
261 }
262 
winpr_inet_pton(INT Family,PCSTR pszAddrString,PVOID pAddrBuf)263 INT winpr_inet_pton(INT Family, PCSTR pszAddrString, PVOID pAddrBuf)
264 {
265 	SOCKADDR_STORAGE addr;
266 	int addr_len = sizeof(addr);
267 
268 	if ((Family != AF_INET) && (Family != AF_INET6))
269 		return -1;
270 
271 	if (WSAStringToAddressA((char*)pszAddrString, Family, NULL, (struct sockaddr*)&addr,
272 	                        &addr_len) != 0)
273 		return 0;
274 
275 	if (Family == AF_INET)
276 	{
277 		memcpy(pAddrBuf, &((struct sockaddr_in*)&addr)->sin_addr, sizeof(struct in_addr));
278 	}
279 	else if (Family == AF_INET6)
280 	{
281 		memcpy(pAddrBuf, &((struct sockaddr_in6*)&addr)->sin6_addr, sizeof(struct in6_addr));
282 	}
283 
284 	return 1;
285 }
286 
287 #endif /* (_WIN32_WINNT < 0x0600) */
288 
289 #else /* _WIN32 */
290 
291 #include <netdb.h>
292 #include <errno.h>
293 #include <unistd.h>
294 #include <sys/ioctl.h>
295 #include <sys/socket.h>
296 #include <netinet/in.h>
297 #include <netinet/tcp.h>
298 #include <net/if.h>
299 
300 #ifndef MSG_NOSIGNAL
301 #define MSG_NOSIGNAL 0
302 #endif
303 
WSAStartup(WORD wVersionRequired,LPWSADATA lpWSAData)304 int WSAStartup(WORD wVersionRequired, LPWSADATA lpWSAData)
305 {
306 	ZeroMemory(lpWSAData, sizeof(WSADATA));
307 	lpWSAData->wVersion = wVersionRequired;
308 	lpWSAData->wHighVersion = MAKEWORD(2, 2);
309 	return 0; /* success */
310 }
311 
WSACleanup(void)312 int WSACleanup(void)
313 {
314 	return 0; /* success */
315 }
316 
WSASetLastError(int iError)317 void WSASetLastError(int iError)
318 {
319 	switch (iError)
320 	{
321 		/* Base error codes */
322 		case WSAEINTR:
323 			errno = EINTR;
324 			break;
325 
326 		case WSAEBADF:
327 			errno = EBADF;
328 			break;
329 
330 		case WSAEACCES:
331 			errno = EACCES;
332 			break;
333 
334 		case WSAEFAULT:
335 			errno = EFAULT;
336 			break;
337 
338 		case WSAEINVAL:
339 			errno = EINVAL;
340 			break;
341 
342 		case WSAEMFILE:
343 			errno = EMFILE;
344 			break;
345 
346 			/* BSD sockets error codes */
347 
348 		case WSAEWOULDBLOCK:
349 			errno = EWOULDBLOCK;
350 			break;
351 
352 		case WSAEINPROGRESS:
353 			errno = EINPROGRESS;
354 			break;
355 
356 		case WSAEALREADY:
357 			errno = EALREADY;
358 			break;
359 
360 		case WSAENOTSOCK:
361 			errno = ENOTSOCK;
362 			break;
363 
364 		case WSAEDESTADDRREQ:
365 			errno = EDESTADDRREQ;
366 			break;
367 
368 		case WSAEMSGSIZE:
369 			errno = EMSGSIZE;
370 			break;
371 
372 		case WSAEPROTOTYPE:
373 			errno = EPROTOTYPE;
374 			break;
375 
376 		case WSAENOPROTOOPT:
377 			errno = ENOPROTOOPT;
378 			break;
379 
380 		case WSAEPROTONOSUPPORT:
381 			errno = EPROTONOSUPPORT;
382 			break;
383 
384 		case WSAESOCKTNOSUPPORT:
385 			errno = ESOCKTNOSUPPORT;
386 			break;
387 
388 		case WSAEOPNOTSUPP:
389 			errno = EOPNOTSUPP;
390 			break;
391 
392 		case WSAEPFNOSUPPORT:
393 			errno = EPFNOSUPPORT;
394 			break;
395 
396 		case WSAEAFNOSUPPORT:
397 			errno = EAFNOSUPPORT;
398 			break;
399 
400 		case WSAEADDRINUSE:
401 			errno = EADDRINUSE;
402 			break;
403 
404 		case WSAEADDRNOTAVAIL:
405 			errno = EADDRNOTAVAIL;
406 			break;
407 
408 		case WSAENETDOWN:
409 			errno = ENETDOWN;
410 			break;
411 
412 		case WSAENETUNREACH:
413 			errno = ENETUNREACH;
414 			break;
415 
416 		case WSAENETRESET:
417 			errno = ENETRESET;
418 			break;
419 
420 		case WSAECONNABORTED:
421 			errno = ECONNABORTED;
422 			break;
423 
424 		case WSAECONNRESET:
425 			errno = ECONNRESET;
426 			break;
427 
428 		case WSAENOBUFS:
429 			errno = ENOBUFS;
430 			break;
431 
432 		case WSAEISCONN:
433 			errno = EISCONN;
434 			break;
435 
436 		case WSAENOTCONN:
437 			errno = ENOTCONN;
438 			break;
439 
440 		case WSAESHUTDOWN:
441 			errno = ESHUTDOWN;
442 			break;
443 
444 		case WSAETOOMANYREFS:
445 			errno = ETOOMANYREFS;
446 			break;
447 
448 		case WSAETIMEDOUT:
449 			errno = ETIMEDOUT;
450 			break;
451 
452 		case WSAECONNREFUSED:
453 			errno = ECONNREFUSED;
454 			break;
455 
456 		case WSAELOOP:
457 			errno = ELOOP;
458 			break;
459 
460 		case WSAENAMETOOLONG:
461 			errno = ENAMETOOLONG;
462 			break;
463 
464 		case WSAEHOSTDOWN:
465 			errno = EHOSTDOWN;
466 			break;
467 
468 		case WSAEHOSTUNREACH:
469 			errno = EHOSTUNREACH;
470 			break;
471 
472 		case WSAENOTEMPTY:
473 			errno = ENOTEMPTY;
474 			break;
475 #ifdef EPROCLIM
476 
477 		case WSAEPROCLIM:
478 			errno = EPROCLIM;
479 			break;
480 #endif
481 
482 		case WSAEUSERS:
483 			errno = EUSERS;
484 			break;
485 
486 		case WSAEDQUOT:
487 			errno = EDQUOT;
488 			break;
489 
490 		case WSAESTALE:
491 			errno = ESTALE;
492 			break;
493 
494 		case WSAEREMOTE:
495 			errno = EREMOTE;
496 			break;
497 	}
498 }
499 
WSAGetLastError(void)500 int WSAGetLastError(void)
501 {
502 	int iError = 0;
503 
504 	switch (errno)
505 	{
506 		/* Base error codes */
507 		case EINTR:
508 			iError = WSAEINTR;
509 			break;
510 
511 		case EBADF:
512 			iError = WSAEBADF;
513 			break;
514 
515 		case EACCES:
516 			iError = WSAEACCES;
517 			break;
518 
519 		case EFAULT:
520 			iError = WSAEFAULT;
521 			break;
522 
523 		case EINVAL:
524 			iError = WSAEINVAL;
525 			break;
526 
527 		case EMFILE:
528 			iError = WSAEMFILE;
529 			break;
530 
531 			/* BSD sockets error codes */
532 
533 		case EWOULDBLOCK:
534 			iError = WSAEWOULDBLOCK;
535 			break;
536 
537 		case EINPROGRESS:
538 			iError = WSAEINPROGRESS;
539 			break;
540 
541 		case EALREADY:
542 			iError = WSAEALREADY;
543 			break;
544 
545 		case ENOTSOCK:
546 			iError = WSAENOTSOCK;
547 			break;
548 
549 		case EDESTADDRREQ:
550 			iError = WSAEDESTADDRREQ;
551 			break;
552 
553 		case EMSGSIZE:
554 			iError = WSAEMSGSIZE;
555 			break;
556 
557 		case EPROTOTYPE:
558 			iError = WSAEPROTOTYPE;
559 			break;
560 
561 		case ENOPROTOOPT:
562 			iError = WSAENOPROTOOPT;
563 			break;
564 
565 		case EPROTONOSUPPORT:
566 			iError = WSAEPROTONOSUPPORT;
567 			break;
568 
569 		case ESOCKTNOSUPPORT:
570 			iError = WSAESOCKTNOSUPPORT;
571 			break;
572 
573 		case EOPNOTSUPP:
574 			iError = WSAEOPNOTSUPP;
575 			break;
576 
577 		case EPFNOSUPPORT:
578 			iError = WSAEPFNOSUPPORT;
579 			break;
580 
581 		case EAFNOSUPPORT:
582 			iError = WSAEAFNOSUPPORT;
583 			break;
584 
585 		case EADDRINUSE:
586 			iError = WSAEADDRINUSE;
587 			break;
588 
589 		case EADDRNOTAVAIL:
590 			iError = WSAEADDRNOTAVAIL;
591 			break;
592 
593 		case ENETDOWN:
594 			iError = WSAENETDOWN;
595 			break;
596 
597 		case ENETUNREACH:
598 			iError = WSAENETUNREACH;
599 			break;
600 
601 		case ENETRESET:
602 			iError = WSAENETRESET;
603 			break;
604 
605 		case ECONNABORTED:
606 			iError = WSAECONNABORTED;
607 			break;
608 
609 		case ECONNRESET:
610 			iError = WSAECONNRESET;
611 			break;
612 
613 		case ENOBUFS:
614 			iError = WSAENOBUFS;
615 			break;
616 
617 		case EISCONN:
618 			iError = WSAEISCONN;
619 			break;
620 
621 		case ENOTCONN:
622 			iError = WSAENOTCONN;
623 			break;
624 
625 		case ESHUTDOWN:
626 			iError = WSAESHUTDOWN;
627 			break;
628 
629 		case ETOOMANYREFS:
630 			iError = WSAETOOMANYREFS;
631 			break;
632 
633 		case ETIMEDOUT:
634 			iError = WSAETIMEDOUT;
635 			break;
636 
637 		case ECONNREFUSED:
638 			iError = WSAECONNREFUSED;
639 			break;
640 
641 		case ELOOP:
642 			iError = WSAELOOP;
643 			break;
644 
645 		case ENAMETOOLONG:
646 			iError = WSAENAMETOOLONG;
647 			break;
648 
649 		case EHOSTDOWN:
650 			iError = WSAEHOSTDOWN;
651 			break;
652 
653 		case EHOSTUNREACH:
654 			iError = WSAEHOSTUNREACH;
655 			break;
656 
657 		case ENOTEMPTY:
658 			iError = WSAENOTEMPTY;
659 			break;
660 #ifdef EPROCLIM
661 
662 		case EPROCLIM:
663 			iError = WSAEPROCLIM;
664 			break;
665 #endif
666 
667 		case EUSERS:
668 			iError = WSAEUSERS;
669 			break;
670 
671 		case EDQUOT:
672 			iError = WSAEDQUOT;
673 			break;
674 
675 		case ESTALE:
676 			iError = WSAESTALE;
677 			break;
678 
679 		case EREMOTE:
680 			iError = WSAEREMOTE;
681 			break;
682 			/* Special cases */
683 #if (EAGAIN != EWOULDBLOCK)
684 
685 		case EAGAIN:
686 			iError = WSAEWOULDBLOCK;
687 			break;
688 #endif
689 #if defined(EPROTO)
690 
691 		case EPROTO:
692 			iError = WSAECONNRESET;
693 			break;
694 #endif
695 	}
696 
697 	/**
698 	 * Windows Sockets Extended Error Codes:
699 	 *
700 	 * WSASYSNOTREADY
701 	 * WSAVERNOTSUPPORTED
702 	 * WSANOTINITIALISED
703 	 * WSAEDISCON
704 	 * WSAENOMORE
705 	 * WSAECANCELLED
706 	 * WSAEINVALIDPROCTABLE
707 	 * WSAEINVALIDPROVIDER
708 	 * WSAEPROVIDERFAILEDINIT
709 	 * WSASYSCALLFAILURE
710 	 * WSASERVICE_NOT_FOUND
711 	 * WSATYPE_NOT_FOUND
712 	 * WSA_E_NO_MORE
713 	 * WSA_E_CANCELLED
714 	 * WSAEREFUSED
715 	 */
716 	return iError;
717 }
718 
WSACreateEvent(void)719 HANDLE WSACreateEvent(void)
720 {
721 	return CreateEvent(NULL, TRUE, FALSE, NULL);
722 }
723 
WSASetEvent(HANDLE hEvent)724 BOOL WSASetEvent(HANDLE hEvent)
725 {
726 	return SetEvent(hEvent);
727 }
728 
WSAResetEvent(HANDLE hEvent)729 BOOL WSAResetEvent(HANDLE hEvent)
730 {
731 	/* POSIX systems auto reset the socket,
732 	 * if no more data is available. */
733 	return TRUE;
734 }
735 
WSACloseEvent(HANDLE hEvent)736 BOOL WSACloseEvent(HANDLE hEvent)
737 {
738 	BOOL status;
739 	status = CloseHandle(hEvent);
740 
741 	if (!status)
742 		SetLastError(6);
743 
744 	return status;
745 }
746 
WSAEventSelect(SOCKET s,WSAEVENT hEventObject,LONG lNetworkEvents)747 int WSAEventSelect(SOCKET s, WSAEVENT hEventObject, LONG lNetworkEvents)
748 {
749 	u_long arg = 1;
750 	ULONG mode = 0;
751 
752 	if (_ioctlsocket(s, FIONBIO, &arg) != 0)
753 		return SOCKET_ERROR;
754 
755 	if (arg == 0)
756 		return 0;
757 
758 	if (lNetworkEvents & FD_READ)
759 		mode |= WINPR_FD_READ;
760 
761 	if (lNetworkEvents & FD_WRITE)
762 		mode |= WINPR_FD_WRITE;
763 
764 	if (SetEventFileDescriptor(hEventObject, s, mode) < 0)
765 		return SOCKET_ERROR;
766 
767 	return 0;
768 }
769 
WSAWaitForMultipleEvents(DWORD cEvents,const HANDLE * lphEvents,BOOL fWaitAll,DWORD dwTimeout,BOOL fAlertable)770 DWORD WSAWaitForMultipleEvents(DWORD cEvents, const HANDLE* lphEvents, BOOL fWaitAll,
771                                DWORD dwTimeout, BOOL fAlertable)
772 {
773 	return WaitForMultipleObjectsEx(cEvents, lphEvents, fWaitAll, dwTimeout, fAlertable);
774 }
775 
WSASocketA(int af,int type,int protocol,LPWSAPROTOCOL_INFOA lpProtocolInfo,GROUP g,DWORD dwFlags)776 SOCKET WSASocketA(int af, int type, int protocol, LPWSAPROTOCOL_INFOA lpProtocolInfo, GROUP g,
777                   DWORD dwFlags)
778 {
779 	SOCKET s;
780 	s = _socket(af, type, protocol);
781 	return s;
782 }
783 
WSASocketW(int af,int type,int protocol,LPWSAPROTOCOL_INFOW lpProtocolInfo,GROUP g,DWORD dwFlags)784 SOCKET WSASocketW(int af, int type, int protocol, LPWSAPROTOCOL_INFOW lpProtocolInfo, GROUP g,
785                   DWORD dwFlags)
786 {
787 	return WSASocketA(af, type, protocol, (LPWSAPROTOCOL_INFOA)lpProtocolInfo, g, dwFlags);
788 }
789 
WSAIoctl(SOCKET s,DWORD dwIoControlCode,LPVOID lpvInBuffer,DWORD cbInBuffer,LPVOID lpvOutBuffer,DWORD cbOutBuffer,LPDWORD lpcbBytesReturned,LPWSAOVERLAPPED lpOverlapped,LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine)790 int WSAIoctl(SOCKET s, DWORD dwIoControlCode, LPVOID lpvInBuffer, DWORD cbInBuffer,
791              LPVOID lpvOutBuffer, DWORD cbOutBuffer, LPDWORD lpcbBytesReturned,
792              LPWSAOVERLAPPED lpOverlapped, LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine)
793 {
794 	int fd;
795 	int index;
796 	ULONG nFlags;
797 	size_t offset;
798 	size_t ifreq_len;
799 	struct ifreq* ifreq;
800 	struct ifconf ifconf;
801 	char address[128];
802 	char broadcast[128];
803 	char netmask[128];
804 	char buffer[4096];
805 	int numInterfaces;
806 	int maxNumInterfaces;
807 	INTERFACE_INFO* pInterface;
808 	INTERFACE_INFO* pInterfaces;
809 	struct sockaddr_in* pAddress;
810 	struct sockaddr_in* pBroadcast;
811 	struct sockaddr_in* pNetmask;
812 
813 	if ((dwIoControlCode != SIO_GET_INTERFACE_LIST) ||
814 	    (!lpvOutBuffer || !cbOutBuffer || !lpcbBytesReturned))
815 	{
816 		WSASetLastError(WSAEINVAL);
817 		return SOCKET_ERROR;
818 	}
819 
820 	fd = (int)s;
821 	pInterfaces = (INTERFACE_INFO*)lpvOutBuffer;
822 	maxNumInterfaces = cbOutBuffer / sizeof(INTERFACE_INFO);
823 #ifdef WSAIOCTL_IFADDRS
824 	{
825 		struct ifaddrs* ifa = NULL;
826 		struct ifaddrs* ifap = NULL;
827 
828 		if (getifaddrs(&ifap) != 0)
829 		{
830 			WSASetLastError(WSAENETDOWN);
831 			return SOCKET_ERROR;
832 		}
833 
834 		index = 0;
835 		numInterfaces = 0;
836 
837 		for (ifa = ifap; ifa; ifa = ifa->ifa_next)
838 		{
839 			pInterface = &pInterfaces[index];
840 			pAddress = (struct sockaddr_in*)&pInterface->iiAddress;
841 			pBroadcast = (struct sockaddr_in*)&pInterface->iiBroadcastAddress;
842 			pNetmask = (struct sockaddr_in*)&pInterface->iiNetmask;
843 			nFlags = 0;
844 
845 			if (ifa->ifa_flags & IFF_UP)
846 				nFlags |= _IFF_UP;
847 
848 			if (ifa->ifa_flags & IFF_BROADCAST)
849 				nFlags |= _IFF_BROADCAST;
850 
851 			if (ifa->ifa_flags & IFF_LOOPBACK)
852 				nFlags |= _IFF_LOOPBACK;
853 
854 			if (ifa->ifa_flags & IFF_POINTOPOINT)
855 				nFlags |= _IFF_POINTTOPOINT;
856 
857 			if (ifa->ifa_flags & IFF_MULTICAST)
858 				nFlags |= _IFF_MULTICAST;
859 
860 			pInterface->iiFlags = nFlags;
861 
862 			if (ifa->ifa_addr)
863 			{
864 				if ((ifa->ifa_addr->sa_family != AF_INET) && (ifa->ifa_addr->sa_family != AF_INET6))
865 					continue;
866 
867 				getnameinfo(ifa->ifa_addr, sizeof(struct sockaddr), address, sizeof(address), 0, 0,
868 				            NI_NUMERICHOST);
869 				inet_pton(ifa->ifa_addr->sa_family, address, (void*)&pAddress->sin_addr);
870 			}
871 			else
872 			{
873 				ZeroMemory(pAddress, sizeof(struct sockaddr_in));
874 			}
875 
876 			if (ifa->ifa_dstaddr)
877 			{
878 				if ((ifa->ifa_dstaddr->sa_family != AF_INET) &&
879 				    (ifa->ifa_dstaddr->sa_family != AF_INET6))
880 					continue;
881 
882 				getnameinfo(ifa->ifa_dstaddr, sizeof(struct sockaddr), broadcast, sizeof(broadcast),
883 				            0, 0, NI_NUMERICHOST);
884 				inet_pton(ifa->ifa_dstaddr->sa_family, broadcast, (void*)&pBroadcast->sin_addr);
885 			}
886 			else
887 			{
888 				ZeroMemory(pBroadcast, sizeof(struct sockaddr_in));
889 			}
890 
891 			if (ifa->ifa_netmask)
892 			{
893 				if ((ifa->ifa_netmask->sa_family != AF_INET) &&
894 				    (ifa->ifa_netmask->sa_family != AF_INET6))
895 					continue;
896 
897 				getnameinfo(ifa->ifa_netmask, sizeof(struct sockaddr), netmask, sizeof(netmask), 0,
898 				            0, NI_NUMERICHOST);
899 				inet_pton(ifa->ifa_netmask->sa_family, netmask, (void*)&pNetmask->sin_addr);
900 			}
901 			else
902 			{
903 				ZeroMemory(pNetmask, sizeof(struct sockaddr_in));
904 			}
905 
906 			numInterfaces++;
907 			index++;
908 		}
909 
910 		*lpcbBytesReturned = (DWORD)(numInterfaces * sizeof(INTERFACE_INFO));
911 		freeifaddrs(ifap);
912 		return 0;
913 	}
914 #endif
915 	ifconf.ifc_len = sizeof(buffer);
916 	ifconf.ifc_buf = buffer;
917 
918 	if (ioctl(fd, SIOCGIFCONF, &ifconf) != 0)
919 	{
920 		WSASetLastError(WSAENETDOWN);
921 		return SOCKET_ERROR;
922 	}
923 
924 	index = 0;
925 	offset = 0;
926 	numInterfaces = 0;
927 	ifreq = ifconf.ifc_req;
928 
929 	while ((ifconf.ifc_len >= 0) && (offset < (size_t)ifconf.ifc_len) &&
930 	       (numInterfaces < maxNumInterfaces))
931 	{
932 		pInterface = &pInterfaces[index];
933 		pAddress = (struct sockaddr_in*)&pInterface->iiAddress;
934 		pBroadcast = (struct sockaddr_in*)&pInterface->iiBroadcastAddress;
935 		pNetmask = (struct sockaddr_in*)&pInterface->iiNetmask;
936 
937 		if (ioctl(fd, SIOCGIFFLAGS, ifreq) != 0)
938 			goto next_ifreq;
939 
940 		nFlags = 0;
941 
942 		if (ifreq->ifr_flags & IFF_UP)
943 			nFlags |= _IFF_UP;
944 
945 		if (ifreq->ifr_flags & IFF_BROADCAST)
946 			nFlags |= _IFF_BROADCAST;
947 
948 		if (ifreq->ifr_flags & IFF_LOOPBACK)
949 			nFlags |= _IFF_LOOPBACK;
950 
951 		if (ifreq->ifr_flags & IFF_POINTOPOINT)
952 			nFlags |= _IFF_POINTTOPOINT;
953 
954 		if (ifreq->ifr_flags & IFF_MULTICAST)
955 			nFlags |= _IFF_MULTICAST;
956 
957 		pInterface->iiFlags = nFlags;
958 
959 		if (ioctl(fd, SIOCGIFADDR, ifreq) != 0)
960 			goto next_ifreq;
961 
962 		if ((ifreq->ifr_addr.sa_family != AF_INET) && (ifreq->ifr_addr.sa_family != AF_INET6))
963 			goto next_ifreq;
964 
965 		getnameinfo(&ifreq->ifr_addr, sizeof(ifreq->ifr_addr), address, sizeof(address), 0, 0,
966 		            NI_NUMERICHOST);
967 		inet_pton(ifreq->ifr_addr.sa_family, address, (void*)&pAddress->sin_addr);
968 
969 		if (ioctl(fd, SIOCGIFBRDADDR, ifreq) != 0)
970 			goto next_ifreq;
971 
972 		if ((ifreq->ifr_addr.sa_family != AF_INET) && (ifreq->ifr_addr.sa_family != AF_INET6))
973 			goto next_ifreq;
974 
975 		getnameinfo(&ifreq->ifr_addr, sizeof(ifreq->ifr_addr), broadcast, sizeof(broadcast), 0, 0,
976 		            NI_NUMERICHOST);
977 		inet_pton(ifreq->ifr_addr.sa_family, broadcast, (void*)&pBroadcast->sin_addr);
978 
979 		if (ioctl(fd, SIOCGIFNETMASK, ifreq) != 0)
980 			goto next_ifreq;
981 
982 		if ((ifreq->ifr_addr.sa_family != AF_INET) && (ifreq->ifr_addr.sa_family != AF_INET6))
983 			goto next_ifreq;
984 
985 		getnameinfo(&ifreq->ifr_addr, sizeof(ifreq->ifr_addr), netmask, sizeof(netmask), 0, 0,
986 		            NI_NUMERICHOST);
987 		inet_pton(ifreq->ifr_addr.sa_family, netmask, (void*)&pNetmask->sin_addr);
988 		numInterfaces++;
989 	next_ifreq:
990 #if !defined(__linux__) && !defined(__sun__) && !defined(__CYGWIN__)
991 		ifreq_len = IFNAMSIZ + ifreq->ifr_addr.sa_len;
992 #else
993 		ifreq_len = sizeof(*ifreq);
994 #endif
995 		ifreq = (struct ifreq*)&((BYTE*)ifreq)[ifreq_len];
996 		offset += ifreq_len;
997 		index++;
998 	}
999 
1000 	*lpcbBytesReturned = (DWORD)(numInterfaces * sizeof(INTERFACE_INFO));
1001 	return 0;
1002 }
1003 
_accept(SOCKET s,struct sockaddr * addr,int * addrlen)1004 SOCKET _accept(SOCKET s, struct sockaddr* addr, int* addrlen)
1005 {
1006 	int status;
1007 	int fd = (int)s;
1008 	socklen_t s_addrlen = (socklen_t)*addrlen;
1009 	status = accept(fd, addr, &s_addrlen);
1010 	*addrlen = (socklen_t)s_addrlen;
1011 	return status;
1012 }
1013 
_bind(SOCKET s,const struct sockaddr * addr,int namelen)1014 int _bind(SOCKET s, const struct sockaddr* addr, int namelen)
1015 {
1016 	int status;
1017 	int fd = (int)s;
1018 	status = bind(fd, addr, (socklen_t)namelen);
1019 
1020 	if (status < 0)
1021 		return SOCKET_ERROR;
1022 
1023 	return status;
1024 }
1025 
closesocket(SOCKET s)1026 int closesocket(SOCKET s)
1027 {
1028 	int status;
1029 	int fd = (int)s;
1030 	status = close(fd);
1031 	return status;
1032 }
1033 
_connect(SOCKET s,const struct sockaddr * name,int namelen)1034 int _connect(SOCKET s, const struct sockaddr* name, int namelen)
1035 {
1036 	int status;
1037 	int fd = (int)s;
1038 	status = connect(fd, name, (socklen_t)namelen);
1039 
1040 	if (status < 0)
1041 		return SOCKET_ERROR;
1042 
1043 	return status;
1044 }
1045 
_ioctlsocket(SOCKET s,long cmd,u_long * argp)1046 int _ioctlsocket(SOCKET s, long cmd, u_long* argp)
1047 {
1048 	int fd = (int)s;
1049 
1050 	if (cmd == FIONBIO)
1051 	{
1052 		int flags;
1053 
1054 		if (!argp)
1055 			return SOCKET_ERROR;
1056 
1057 		flags = fcntl(fd, F_GETFL);
1058 
1059 		if (flags == -1)
1060 			return SOCKET_ERROR;
1061 
1062 		if (*argp)
1063 			fcntl(fd, F_SETFL, flags | O_NONBLOCK);
1064 		else
1065 			fcntl(fd, F_SETFL, flags & ~(O_NONBLOCK));
1066 	}
1067 
1068 	return 0;
1069 }
1070 
_getpeername(SOCKET s,struct sockaddr * name,int * namelen)1071 int _getpeername(SOCKET s, struct sockaddr* name, int* namelen)
1072 {
1073 	int status;
1074 	int fd = (int)s;
1075 	socklen_t s_namelen = (socklen_t)*namelen;
1076 	status = getpeername(fd, name, &s_namelen);
1077 	*namelen = (int)s_namelen;
1078 	return status;
1079 }
1080 
_getsockname(SOCKET s,struct sockaddr * name,int * namelen)1081 int _getsockname(SOCKET s, struct sockaddr* name, int* namelen)
1082 {
1083 	int status;
1084 	int fd = (int)s;
1085 	socklen_t s_namelen = (socklen_t)*namelen;
1086 	status = getsockname(fd, name, &s_namelen);
1087 	*namelen = (int)s_namelen;
1088 	return status;
1089 }
1090 
_getsockopt(SOCKET s,int level,int optname,char * optval,int * optlen)1091 int _getsockopt(SOCKET s, int level, int optname, char* optval, int* optlen)
1092 {
1093 	int status;
1094 	int fd = (int)s;
1095 	socklen_t s_optlen = (socklen_t)*optlen;
1096 	status = getsockopt(fd, level, optname, (void*)optval, &s_optlen);
1097 	*optlen = (socklen_t)s_optlen;
1098 	return status;
1099 }
1100 
_htonl(u_long hostlong)1101 u_long _htonl(u_long hostlong)
1102 {
1103 	return htonl(hostlong);
1104 }
1105 
_htons(u_short hostshort)1106 u_short _htons(u_short hostshort)
1107 {
1108 	return htons(hostshort);
1109 }
1110 
_inet_addr(const char * cp)1111 unsigned long _inet_addr(const char* cp)
1112 {
1113 	return (long)inet_addr(cp);
1114 }
1115 
_inet_ntoa(struct in_addr in)1116 char* _inet_ntoa(struct in_addr in)
1117 {
1118 	return inet_ntoa(in);
1119 }
1120 
_listen(SOCKET s,int backlog)1121 int _listen(SOCKET s, int backlog)
1122 {
1123 	int status;
1124 	int fd = (int)s;
1125 	status = listen(fd, backlog);
1126 	return status;
1127 }
1128 
_ntohl(u_long netlong)1129 u_long _ntohl(u_long netlong)
1130 {
1131 	return ntohl(netlong);
1132 }
1133 
_ntohs(u_short netshort)1134 u_short _ntohs(u_short netshort)
1135 {
1136 	return ntohs(netshort);
1137 }
1138 
_recv(SOCKET s,char * buf,int len,int flags)1139 int _recv(SOCKET s, char* buf, int len, int flags)
1140 {
1141 	int status;
1142 	int fd = (int)s;
1143 	status = (int)recv(fd, (void*)buf, (size_t)len, flags);
1144 	return status;
1145 }
1146 
_winsock_recvfrom(SOCKET s,char * buf,int len,int flags,struct sockaddr * from,int * fromlen)1147 int _winsock_recvfrom(SOCKET s, char* buf, int len, int flags, struct sockaddr* from, int* fromlen)
1148 {
1149 	int status;
1150 	int fd = (int)s;
1151 	socklen_t s_fromlen = (socklen_t)*fromlen;
1152 	status = (int)recvfrom(fd, (void*)buf, (size_t)len, flags, from, &s_fromlen);
1153 	*fromlen = (int)s_fromlen;
1154 	return status;
1155 }
1156 
_select(int nfds,fd_set * readfds,fd_set * writefds,fd_set * exceptfds,const struct timeval * timeout)1157 int _select(int nfds, fd_set* readfds, fd_set* writefds, fd_set* exceptfds,
1158             const struct timeval* timeout)
1159 {
1160 	int status;
1161 
1162 	do
1163 	{
1164 		status = select(nfds, readfds, writefds, exceptfds, (struct timeval*)timeout);
1165 	} while ((status < 0) && (errno == EINTR));
1166 
1167 	return status;
1168 }
1169 
_send(SOCKET s,const char * buf,int len,int flags)1170 int _send(SOCKET s, const char* buf, int len, int flags)
1171 {
1172 	int status;
1173 	int fd = (int)s;
1174 	flags |= MSG_NOSIGNAL;
1175 	status = (int)send(fd, (void*)buf, (size_t)len, flags);
1176 	return status;
1177 }
1178 
_sendto(SOCKET s,const char * buf,int len,int flags,const struct sockaddr * to,int tolen)1179 int _sendto(SOCKET s, const char* buf, int len, int flags, const struct sockaddr* to, int tolen)
1180 {
1181 	int status;
1182 	int fd = (int)s;
1183 	status = (int)sendto(fd, (void*)buf, (size_t)len, flags, to, (socklen_t)tolen);
1184 	return status;
1185 }
1186 
_setsockopt(SOCKET s,int level,int optname,const char * optval,int optlen)1187 int _setsockopt(SOCKET s, int level, int optname, const char* optval, int optlen)
1188 {
1189 	int status;
1190 	int fd = (int)s;
1191 	status = setsockopt(fd, level, optname, (void*)optval, (socklen_t)optlen);
1192 	return status;
1193 }
1194 
_shutdown(SOCKET s,int how)1195 int _shutdown(SOCKET s, int how)
1196 {
1197 	int status;
1198 	int fd = (int)s;
1199 	int s_how = -1;
1200 
1201 	switch (how)
1202 	{
1203 		case SD_RECEIVE:
1204 			s_how = SHUT_RD;
1205 			break;
1206 
1207 		case SD_SEND:
1208 			s_how = SHUT_WR;
1209 			break;
1210 
1211 		case SD_BOTH:
1212 			s_how = SHUT_RDWR;
1213 			break;
1214 	}
1215 
1216 	if (s_how < 0)
1217 		return SOCKET_ERROR;
1218 
1219 	status = shutdown(fd, s_how);
1220 	return status;
1221 }
1222 
_socket(int af,int type,int protocol)1223 SOCKET _socket(int af, int type, int protocol)
1224 {
1225 	int fd;
1226 	SOCKET s;
1227 	fd = socket(af, type, protocol);
1228 
1229 	if (fd < 0)
1230 		return INVALID_SOCKET;
1231 
1232 	s = (SOCKET)fd;
1233 	return s;
1234 }
1235 
_gethostbyaddr(const char * addr,int len,int type)1236 struct hostent* _gethostbyaddr(const char* addr, int len, int type)
1237 {
1238 	struct hostent* host;
1239 	host = gethostbyaddr((void*)addr, (socklen_t)len, type);
1240 	return host;
1241 }
1242 
_gethostbyname(const char * name)1243 struct hostent* _gethostbyname(const char* name)
1244 {
1245 	struct hostent* host;
1246 	host = gethostbyname(name);
1247 	return host;
1248 }
1249 
_gethostname(char * name,int namelen)1250 int _gethostname(char* name, int namelen)
1251 {
1252 	int status;
1253 	status = gethostname(name, (size_t)namelen);
1254 	return status;
1255 }
1256 
_getservbyport(int port,const char * proto)1257 struct servent* _getservbyport(int port, const char* proto)
1258 {
1259 	struct servent* serv;
1260 	serv = getservbyport(port, proto);
1261 	return serv;
1262 }
1263 
_getservbyname(const char * name,const char * proto)1264 struct servent* _getservbyname(const char* name, const char* proto)
1265 {
1266 	struct servent* serv;
1267 	serv = getservbyname(name, proto);
1268 	return serv;
1269 }
1270 
_getprotobynumber(int number)1271 struct protoent* _getprotobynumber(int number)
1272 {
1273 	struct protoent* proto;
1274 	proto = getprotobynumber(number);
1275 	return proto;
1276 }
1277 
_getprotobyname(const char * name)1278 struct protoent* _getprotobyname(const char* name)
1279 {
1280 	struct protoent* proto;
1281 	proto = getprotobyname(name);
1282 	return proto;
1283 }
1284 
1285 #endif /* _WIN32 */
1286