Coverage Report

Created: 2025-07-01 06:46

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