Coverage Report

Created: 2024-09-08 06:20

/src/FreeRDP/libfreerdp/core/tcp.c
Line
Count
Source (jump to first uncovered line)
1
/**
2
 * FreeRDP: A Remote Desktop Protocol Implementation
3
 * Transmission Control Protocol (TCP)
4
 *
5
 * Copyright 2011 Vic Lee
6
 * Copyright 2011 Marc-Andre Moreau <marcandre.moreau@gmail.com>
7
 *
8
 * Licensed under the Apache License, Version 2.0 (the "License");
9
 * you may not use this file except in compliance with the License.
10
 * You may obtain a copy of the License at
11
 *
12
 *     http://www.apache.org/licenses/LICENSE-2.0
13
 *
14
 * Unless required by applicable law or agreed to in writing, software
15
 * distributed under the License is distributed on an "AS IS" BASIS,
16
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17
 * See the License for the specific language governing permissions and
18
 * limitations under the License.
19
 */
20
21
#include <freerdp/config.h>
22
23
#include "settings.h"
24
25
#include <time.h>
26
#include <errno.h>
27
#include <fcntl.h>
28
29
#include <winpr/crt.h>
30
#include <winpr/platform.h>
31
#include <winpr/winsock.h>
32
33
#include "rdp.h"
34
#include "utils.h"
35
36
#if !defined(_WIN32)
37
38
#include <netdb.h>
39
#include <unistd.h>
40
#include <sys/ioctl.h>
41
#include <sys/socket.h>
42
#include <netinet/in.h>
43
#include <netinet/tcp.h>
44
#include <net/if.h>
45
#include <sys/types.h>
46
#include <arpa/inet.h>
47
48
#ifdef WINPR_HAVE_POLL_H
49
#include <poll.h>
50
#else
51
#include <time.h>
52
#include <sys/select.h>
53
#endif
54
55
#if defined(__FreeBSD__) || defined(__OpenBSD__)
56
#ifndef SOL_TCP
57
#define SOL_TCP IPPROTO_TCP
58
#endif
59
#endif
60
61
#ifdef __APPLE__
62
#ifndef SOL_TCP
63
#define SOL_TCP IPPROTO_TCP
64
#endif
65
#ifndef TCP_KEEPIDLE
66
#define TCP_KEEPIDLE TCP_KEEPALIVE
67
#endif
68
#endif
69
70
#else
71
72
#include <winpr/windows.h>
73
74
#include <winpr/crt.h>
75
76
#define SHUT_RDWR SD_BOTH
77
#define close(_fd) closesocket(_fd)
78
79
#endif
80
81
#include <freerdp/log.h>
82
83
#include <winpr/stream.h>
84
85
#include "tcp.h"
86
#include "../crypto/opensslcompat.h"
87
88
#if defined(HAVE_AF_VSOCK_H)
89
#include <ctype.h>
90
#include <linux/vm_sockets.h>
91
#endif
92
93
#define TAG FREERDP_TAG("core")
94
95
/* Simple Socket BIO */
96
97
typedef struct
98
{
99
  SOCKET socket;
100
  HANDLE hEvent;
101
} WINPR_BIO_SIMPLE_SOCKET;
102
103
static int transport_bio_simple_init(BIO* bio, SOCKET socket, int shutdown);
104
static int transport_bio_simple_uninit(BIO* bio);
105
106
static long transport_bio_simple_callback(BIO* bio, int mode, const char* argp, int argi, long argl,
107
                                          long ret)
108
0
{
109
0
  return 1;
110
0
}
111
112
static int transport_bio_simple_write(BIO* bio, const char* buf, int size)
113
235
{
114
235
  int error = 0;
115
235
  int status = 0;
116
235
  WINPR_BIO_SIMPLE_SOCKET* ptr = (WINPR_BIO_SIMPLE_SOCKET*)BIO_get_data(bio);
117
118
235
  if (!buf)
119
0
    return 0;
120
121
235
  BIO_clear_flags(bio, BIO_FLAGS_WRITE);
122
235
  status = _send(ptr->socket, buf, size, 0);
123
124
235
  if (status <= 0)
125
235
  {
126
235
    error = WSAGetLastError();
127
128
235
    if ((error == WSAEWOULDBLOCK) || (error == WSAEINTR) || (error == WSAEINPROGRESS) ||
129
235
        (error == WSAEALREADY))
130
0
    {
131
0
      BIO_set_flags(bio, (BIO_FLAGS_WRITE | BIO_FLAGS_SHOULD_RETRY));
132
0
    }
133
235
    else
134
235
    {
135
235
      BIO_clear_flags(bio, BIO_FLAGS_SHOULD_RETRY);
136
235
    }
137
235
  }
138
139
235
  return status;
140
235
}
141
142
static int transport_bio_simple_read(BIO* bio, char* buf, int size)
143
0
{
144
0
  int error = 0;
145
0
  int status = 0;
146
0
  WINPR_BIO_SIMPLE_SOCKET* ptr = (WINPR_BIO_SIMPLE_SOCKET*)BIO_get_data(bio);
147
148
0
  if (!buf)
149
0
    return 0;
150
151
0
  BIO_clear_flags(bio, BIO_FLAGS_READ);
152
0
  WSAResetEvent(ptr->hEvent);
153
0
  status = _recv(ptr->socket, buf, size, 0);
154
155
0
  if (status > 0)
156
0
  {
157
0
    return status;
158
0
  }
159
160
0
  if (status == 0)
161
0
  {
162
0
    BIO_clear_flags(bio, BIO_FLAGS_SHOULD_RETRY);
163
0
    return 0;
164
0
  }
165
166
0
  error = WSAGetLastError();
167
168
0
  if ((error == WSAEWOULDBLOCK) || (error == WSAEINTR) || (error == WSAEINPROGRESS) ||
169
0
      (error == WSAEALREADY))
170
0
  {
171
0
    BIO_set_flags(bio, (BIO_FLAGS_READ | BIO_FLAGS_SHOULD_RETRY));
172
0
  }
173
0
  else
174
0
  {
175
0
    BIO_clear_flags(bio, BIO_FLAGS_SHOULD_RETRY);
176
0
  }
177
178
0
  return -1;
179
0
}
180
181
static int transport_bio_simple_puts(BIO* bio, const char* str)
182
0
{
183
0
  return 1;
184
0
}
185
186
static int transport_bio_simple_gets(BIO* bio, char* str, int size)
187
0
{
188
0
  return 1;
189
0
}
190
191
static long transport_bio_simple_ctrl(BIO* bio, int cmd, long arg1, void* arg2)
192
19.0k
{
193
19.0k
  int status = -1;
194
19.0k
  WINPR_BIO_SIMPLE_SOCKET* ptr = (WINPR_BIO_SIMPLE_SOCKET*)BIO_get_data(bio);
195
196
19.0k
  switch (cmd)
197
19.0k
  {
198
0
    case BIO_C_SET_SOCKET:
199
0
      transport_bio_simple_uninit(bio);
200
0
      transport_bio_simple_init(bio, (SOCKET)arg2, (int)arg1);
201
0
      return 1;
202
0
    case BIO_C_GET_SOCKET:
203
0
      if (!BIO_get_init(bio) || !arg2)
204
0
        return 0;
205
206
0
      *((SOCKET*)arg2) = ptr->socket;
207
0
      return 1;
208
0
    case BIO_C_GET_EVENT:
209
0
      if (!BIO_get_init(bio) || !arg2)
210
0
        return 0;
211
212
0
      *((HANDLE*)arg2) = ptr->hEvent;
213
0
      return 1;
214
6.33k
    case BIO_C_SET_NONBLOCK:
215
6.33k
    {
216
6.33k
#ifndef _WIN32
217
6.33k
      int flags = 0;
218
6.33k
      flags = fcntl((int)ptr->socket, F_GETFL);
219
220
6.33k
      if (flags == -1)
221
0
        return 0;
222
223
6.33k
      if (arg1)
224
6.33k
        fcntl((int)ptr->socket, F_SETFL, flags | O_NONBLOCK);
225
0
      else
226
0
        fcntl((int)ptr->socket, F_SETFL, flags & ~(O_NONBLOCK));
227
228
#else
229
      /* the internal socket is always non-blocking */
230
#endif
231
6.33k
      return 1;
232
6.33k
    }
233
0
    case BIO_C_WAIT_READ:
234
0
    {
235
0
      int timeout = (int)arg1;
236
0
      int sockfd = (int)ptr->socket;
237
0
#ifdef WINPR_HAVE_POLL_H
238
0
      struct pollfd pollset;
239
0
      pollset.fd = sockfd;
240
0
      pollset.events = POLLIN;
241
0
      pollset.revents = 0;
242
243
0
      do
244
0
      {
245
0
        status = poll(&pollset, 1, timeout);
246
0
      } while ((status < 0) && (errno == EINTR));
247
248
#else
249
      fd_set rset;
250
      struct timeval tv;
251
      FD_ZERO(&rset);
252
      FD_SET(sockfd, &rset);
253
254
      if (timeout)
255
      {
256
        tv.tv_sec = timeout / 1000;
257
        tv.tv_usec = (timeout % 1000) * 1000;
258
      }
259
260
      do
261
      {
262
        status = select(sockfd + 1, &rset, NULL, NULL, timeout ? &tv : NULL);
263
      } while ((status < 0) && (errno == EINTR));
264
265
#endif
266
      /* Convert timeout to error return */
267
0
      if (status == 0)
268
0
        errno = ETIMEDOUT;
269
0
    }
270
0
    break;
271
272
0
    case BIO_C_WAIT_WRITE:
273
0
    {
274
0
      int timeout = (int)arg1;
275
0
      int sockfd = (int)ptr->socket;
276
0
#ifdef WINPR_HAVE_POLL_H
277
0
      struct pollfd pollset;
278
0
      pollset.fd = sockfd;
279
0
      pollset.events = POLLOUT;
280
0
      pollset.revents = 0;
281
282
0
      do
283
0
      {
284
0
        status = poll(&pollset, 1, timeout);
285
0
      } while ((status < 0) && (errno == EINTR));
286
287
#else
288
      fd_set rset;
289
      struct timeval tv;
290
      FD_ZERO(&rset);
291
      FD_SET(sockfd, &rset);
292
293
      if (timeout)
294
      {
295
        tv.tv_sec = timeout / 1000;
296
        tv.tv_usec = (timeout % 1000) * 1000;
297
      }
298
299
      do
300
      {
301
        status = select(sockfd + 1, NULL, &rset, NULL, timeout ? &tv : NULL);
302
      } while ((status < 0) && (errno == EINTR));
303
304
#endif
305
      /* Convert timeout to error return */
306
0
      if (status == 0)
307
0
        errno = ETIMEDOUT;
308
0
    }
309
0
    break;
310
311
6.33k
    case BIO_C_SET_FD:
312
6.33k
      if (arg2)
313
6.33k
      {
314
6.33k
        transport_bio_simple_uninit(bio);
315
6.33k
        transport_bio_simple_init(bio, (SOCKET) * ((int*)arg2), (int)arg1);
316
6.33k
        status = 1;
317
6.33k
      }
318
319
6.33k
      break;
320
321
0
    case BIO_C_GET_FD:
322
0
      if (BIO_get_init(bio))
323
0
      {
324
0
        if (arg2)
325
0
          *((int*)arg2) = (int)ptr->socket;
326
327
0
        status = (int)ptr->socket;
328
0
      }
329
330
0
      break;
331
332
0
    case BIO_CTRL_GET_CLOSE:
333
0
      status = BIO_get_shutdown(bio);
334
0
      break;
335
336
0
    case BIO_CTRL_SET_CLOSE:
337
0
      BIO_set_shutdown(bio, (int)arg1);
338
0
      status = 1;
339
0
      break;
340
341
0
    case BIO_CTRL_FLUSH:
342
0
    case BIO_CTRL_DUP:
343
0
      status = 1;
344
0
      break;
345
346
6.33k
    default:
347
6.33k
      status = 0;
348
6.33k
      break;
349
19.0k
  }
350
351
12.6k
  return status;
352
19.0k
}
353
354
static int transport_bio_simple_init(BIO* bio, SOCKET socket, int shutdown)
355
6.33k
{
356
6.33k
  WINPR_BIO_SIMPLE_SOCKET* ptr = (WINPR_BIO_SIMPLE_SOCKET*)BIO_get_data(bio);
357
6.33k
  ptr->socket = socket;
358
6.33k
  BIO_set_shutdown(bio, shutdown);
359
6.33k
  BIO_set_flags(bio, BIO_FLAGS_SHOULD_RETRY);
360
6.33k
  BIO_set_init(bio, 1);
361
6.33k
  ptr->hEvent = WSACreateEvent();
362
363
6.33k
  if (!ptr->hEvent)
364
0
    return 0;
365
366
  /* WSAEventSelect automatically sets the socket in non-blocking mode */
367
6.33k
  if (WSAEventSelect(ptr->socket, ptr->hEvent, FD_READ | FD_ACCEPT | FD_CLOSE))
368
0
  {
369
0
    WLog_ERR(TAG, "WSAEventSelect returned 0x%08X", WSAGetLastError());
370
0
    return 0;
371
0
  }
372
373
6.33k
  return 1;
374
6.33k
}
375
376
static int transport_bio_simple_uninit(BIO* bio)
377
12.6k
{
378
12.6k
  WINPR_BIO_SIMPLE_SOCKET* ptr = (WINPR_BIO_SIMPLE_SOCKET*)BIO_get_data(bio);
379
380
12.6k
  if (BIO_get_shutdown(bio))
381
12.6k
  {
382
12.6k
    if (BIO_get_init(bio) && ptr)
383
6.33k
    {
384
6.33k
      _shutdown(ptr->socket, SD_BOTH);
385
6.33k
      closesocket(ptr->socket);
386
6.33k
      ptr->socket = 0;
387
6.33k
    }
388
12.6k
  }
389
390
12.6k
  if (ptr && ptr->hEvent)
391
6.33k
  {
392
6.33k
    CloseHandle(ptr->hEvent);
393
6.33k
    ptr->hEvent = NULL;
394
6.33k
  }
395
396
12.6k
  BIO_set_init(bio, 0);
397
12.6k
  BIO_set_flags(bio, 0);
398
12.6k
  return 1;
399
12.6k
}
400
401
static int transport_bio_simple_new(BIO* bio)
402
6.33k
{
403
6.33k
  WINPR_BIO_SIMPLE_SOCKET* ptr = NULL;
404
6.33k
  BIO_set_flags(bio, BIO_FLAGS_SHOULD_RETRY);
405
6.33k
  ptr = (WINPR_BIO_SIMPLE_SOCKET*)calloc(1, sizeof(WINPR_BIO_SIMPLE_SOCKET));
406
407
6.33k
  if (!ptr)
408
0
    return 0;
409
410
6.33k
  BIO_set_data(bio, ptr);
411
6.33k
  return 1;
412
6.33k
}
413
414
static int transport_bio_simple_free(BIO* bio)
415
6.33k
{
416
6.33k
  WINPR_BIO_SIMPLE_SOCKET* ptr = NULL;
417
418
6.33k
  if (!bio)
419
0
    return 0;
420
421
6.33k
  transport_bio_simple_uninit(bio);
422
6.33k
  ptr = (WINPR_BIO_SIMPLE_SOCKET*)BIO_get_data(bio);
423
424
6.33k
  if (ptr)
425
6.33k
  {
426
6.33k
    BIO_set_data(bio, NULL);
427
6.33k
    free(ptr);
428
6.33k
  }
429
430
6.33k
  return 1;
431
6.33k
}
432
433
BIO_METHOD* BIO_s_simple_socket(void)
434
6.33k
{
435
6.33k
  static BIO_METHOD* bio_methods = NULL;
436
437
6.33k
  if (bio_methods == NULL)
438
1
  {
439
1
    if (!(bio_methods = BIO_meth_new(BIO_TYPE_SIMPLE, "SimpleSocket")))
440
0
      return NULL;
441
442
1
    BIO_meth_set_write(bio_methods, transport_bio_simple_write);
443
1
    BIO_meth_set_read(bio_methods, transport_bio_simple_read);
444
1
    BIO_meth_set_puts(bio_methods, transport_bio_simple_puts);
445
1
    BIO_meth_set_gets(bio_methods, transport_bio_simple_gets);
446
1
    BIO_meth_set_ctrl(bio_methods, transport_bio_simple_ctrl);
447
1
    BIO_meth_set_create(bio_methods, transport_bio_simple_new);
448
1
    BIO_meth_set_destroy(bio_methods, transport_bio_simple_free);
449
1
  }
450
451
6.33k
  return bio_methods;
452
6.33k
}
453
454
/* Buffered Socket BIO */
455
456
typedef struct
457
{
458
  BIO* bufferedBio;
459
  BOOL readBlocked;
460
  BOOL writeBlocked;
461
  RingBuffer xmitBuffer;
462
} WINPR_BIO_BUFFERED_SOCKET;
463
464
static long transport_bio_buffered_callback(BIO* bio, int mode, const char* argp, int argi,
465
                                            long argl, long ret)
466
0
{
467
0
  return 1;
468
0
}
469
470
static int transport_bio_buffered_write(BIO* bio, const char* buf, int num)
471
235
{
472
235
  int ret = num;
473
235
  int nchunks = 0;
474
235
  size_t committedBytes = 0;
475
235
  DataChunk chunks[2] = { 0 };
476
235
  WINPR_BIO_BUFFERED_SOCKET* ptr = (WINPR_BIO_BUFFERED_SOCKET*)BIO_get_data(bio);
477
235
  BIO* next_bio = NULL;
478
479
235
  WINPR_ASSERT(bio);
480
235
  WINPR_ASSERT(ptr);
481
482
235
  ptr->writeBlocked = FALSE;
483
235
  BIO_clear_flags(bio, BIO_FLAGS_WRITE);
484
485
  /* we directly append extra bytes in the xmit buffer, this could be prevented
486
   * but for now it makes the code more simple.
487
   */
488
235
  if (buf && num && !ringbuffer_write(&ptr->xmitBuffer, (const BYTE*)buf, num))
489
0
  {
490
0
    WLog_ERR(TAG, "an error occurred when writing (num: %d)", num);
491
0
    return -1;
492
0
  }
493
494
235
  nchunks = ringbuffer_peek(&ptr->xmitBuffer, chunks, ringbuffer_used(&ptr->xmitBuffer));
495
235
  next_bio = BIO_next(bio);
496
497
235
  for (int i = 0; i < nchunks; i++)
498
235
  {
499
235
    while (chunks[i].size)
500
235
    {
501
235
      ERR_clear_error();
502
235
      const int status = BIO_write(next_bio, chunks[i].data, chunks[i].size);
503
504
235
      if (status <= 0)
505
235
      {
506
235
        if (!BIO_should_retry(next_bio))
507
235
        {
508
235
          BIO_clear_flags(bio, BIO_FLAGS_SHOULD_RETRY);
509
235
          ret = -1; /* fatal error */
510
235
          goto out;
511
235
        }
512
513
0
        if (BIO_should_write(next_bio))
514
0
        {
515
0
          BIO_set_flags(bio, BIO_FLAGS_WRITE);
516
0
          ptr->writeBlocked = TRUE;
517
0
          goto out; /* EWOULDBLOCK */
518
0
        }
519
0
      }
520
0
      else
521
0
      {
522
0
        committedBytes += (size_t)status;
523
0
        chunks[i].size -= (size_t)status;
524
0
        chunks[i].data += status;
525
0
      }
526
235
    }
527
235
  }
528
529
235
out:
530
235
  ringbuffer_commit_read_bytes(&ptr->xmitBuffer, committedBytes);
531
235
  return ret;
532
235
}
533
534
static int transport_bio_buffered_read(BIO* bio, char* buf, int size)
535
0
{
536
0
  int status = 0;
537
0
  WINPR_BIO_BUFFERED_SOCKET* ptr = (WINPR_BIO_BUFFERED_SOCKET*)BIO_get_data(bio);
538
0
  BIO* next_bio = BIO_next(bio);
539
0
  ptr->readBlocked = FALSE;
540
0
  BIO_clear_flags(bio, BIO_FLAGS_READ);
541
0
  ERR_clear_error();
542
0
  status = BIO_read(next_bio, buf, size);
543
544
0
  if (status <= 0)
545
0
  {
546
0
    if (!BIO_should_retry(next_bio))
547
0
    {
548
0
      BIO_clear_flags(bio, BIO_FLAGS_SHOULD_RETRY);
549
0
      goto out;
550
0
    }
551
552
0
    BIO_set_flags(bio, BIO_FLAGS_SHOULD_RETRY);
553
554
0
    if (BIO_should_read(next_bio))
555
0
    {
556
0
      BIO_set_flags(bio, BIO_FLAGS_READ);
557
0
      ptr->readBlocked = TRUE;
558
0
      goto out;
559
0
    }
560
0
  }
561
562
0
out:
563
0
  return status;
564
0
}
565
566
static int transport_bio_buffered_puts(BIO* bio, const char* str)
567
0
{
568
0
  return 1;
569
0
}
570
571
static int transport_bio_buffered_gets(BIO* bio, char* str, int size)
572
0
{
573
0
  return 1;
574
0
}
575
576
static long transport_bio_buffered_ctrl(BIO* bio, int cmd, long arg1, void* arg2)
577
12.6k
{
578
12.6k
  long status = -1;
579
12.6k
  WINPR_BIO_BUFFERED_SOCKET* ptr = (WINPR_BIO_BUFFERED_SOCKET*)BIO_get_data(bio);
580
581
12.6k
  switch (cmd)
582
12.6k
  {
583
0
    case BIO_CTRL_FLUSH:
584
0
      if (!ringbuffer_used(&ptr->xmitBuffer))
585
0
        status = 1;
586
0
      else
587
0
        status = (transport_bio_buffered_write(bio, NULL, 0) >= 0) ? 1 : -1;
588
589
0
      break;
590
591
0
    case BIO_CTRL_WPENDING:
592
0
      status = ringbuffer_used(&ptr->xmitBuffer);
593
0
      break;
594
595
0
    case BIO_CTRL_PENDING:
596
0
      status = 0;
597
0
      break;
598
599
0
    case BIO_C_READ_BLOCKED:
600
0
      status = (int)ptr->readBlocked;
601
0
      break;
602
603
0
    case BIO_C_WRITE_BLOCKED:
604
0
      status = (int)ptr->writeBlocked;
605
0
      break;
606
607
12.6k
    default:
608
12.6k
      status = BIO_ctrl(BIO_next(bio), cmd, arg1, arg2);
609
12.6k
      break;
610
12.6k
  }
611
612
12.6k
  return status;
613
12.6k
}
614
615
static int transport_bio_buffered_new(BIO* bio)
616
6.33k
{
617
6.33k
  WINPR_BIO_BUFFERED_SOCKET* ptr = NULL;
618
6.33k
  BIO_set_init(bio, 1);
619
6.33k
  BIO_set_flags(bio, BIO_FLAGS_SHOULD_RETRY);
620
6.33k
  ptr = (WINPR_BIO_BUFFERED_SOCKET*)calloc(1, sizeof(WINPR_BIO_BUFFERED_SOCKET));
621
622
6.33k
  if (!ptr)
623
0
    return -1;
624
625
6.33k
  BIO_set_data(bio, (void*)ptr);
626
627
6.33k
  if (!ringbuffer_init(&ptr->xmitBuffer, 0x10000))
628
0
    return -1;
629
630
6.33k
  return 1;
631
6.33k
}
632
633
/* Free the buffered BIO.
634
 * Do not free other elements in the BIO stack,
635
 * let BIO_free_all handle that. */
636
static int transport_bio_buffered_free(BIO* bio)
637
6.33k
{
638
6.33k
  WINPR_BIO_BUFFERED_SOCKET* ptr = (WINPR_BIO_BUFFERED_SOCKET*)BIO_get_data(bio);
639
640
6.33k
  if (!ptr)
641
0
    return 0;
642
643
6.33k
  ringbuffer_destroy(&ptr->xmitBuffer);
644
6.33k
  free(ptr);
645
6.33k
  return 1;
646
6.33k
}
647
648
BIO_METHOD* BIO_s_buffered_socket(void)
649
6.33k
{
650
6.33k
  static BIO_METHOD* bio_methods = NULL;
651
652
6.33k
  if (bio_methods == NULL)
653
1
  {
654
1
    if (!(bio_methods = BIO_meth_new(BIO_TYPE_BUFFERED, "BufferedSocket")))
655
0
      return NULL;
656
657
1
    BIO_meth_set_write(bio_methods, transport_bio_buffered_write);
658
1
    BIO_meth_set_read(bio_methods, transport_bio_buffered_read);
659
1
    BIO_meth_set_puts(bio_methods, transport_bio_buffered_puts);
660
1
    BIO_meth_set_gets(bio_methods, transport_bio_buffered_gets);
661
1
    BIO_meth_set_ctrl(bio_methods, transport_bio_buffered_ctrl);
662
1
    BIO_meth_set_create(bio_methods, transport_bio_buffered_new);
663
1
    BIO_meth_set_destroy(bio_methods, transport_bio_buffered_free);
664
1
  }
665
666
6.33k
  return bio_methods;
667
6.33k
}
668
669
char* freerdp_tcp_address_to_string(const struct sockaddr_storage* addr, BOOL* pIPv6)
670
0
{
671
0
  char ipAddress[INET6_ADDRSTRLEN + 1] = { 0 };
672
0
  const struct sockaddr_in6* sockaddr_ipv6 = (const struct sockaddr_in6*)addr;
673
0
  const struct sockaddr_in* sockaddr_ipv4 = (const struct sockaddr_in*)addr;
674
675
0
  if (addr == NULL)
676
0
  {
677
0
    return NULL;
678
0
  }
679
680
0
  switch (sockaddr_ipv4->sin_family)
681
0
  {
682
0
    case AF_INET:
683
0
      if (!inet_ntop(sockaddr_ipv4->sin_family, &sockaddr_ipv4->sin_addr, ipAddress,
684
0
                     sizeof(ipAddress)))
685
0
        return NULL;
686
687
0
      break;
688
689
0
    case AF_INET6:
690
0
      if (!inet_ntop(sockaddr_ipv6->sin6_family, &sockaddr_ipv6->sin6_addr, ipAddress,
691
0
                     sizeof(ipAddress)))
692
0
        return NULL;
693
694
0
      break;
695
696
0
    case AF_UNIX:
697
0
      (void)sprintf_s(ipAddress, ARRAYSIZE(ipAddress), "127.0.0.1");
698
0
      break;
699
700
0
    default:
701
0
      return NULL;
702
0
  }
703
704
0
  if (pIPv6 != NULL)
705
0
  {
706
0
    *pIPv6 = (sockaddr_ipv4->sin_family == AF_INET6);
707
0
  }
708
709
0
  return _strdup(ipAddress);
710
0
}
711
712
static char* freerdp_tcp_get_ip_address(int sockfd, BOOL* pIPv6)
713
0
{
714
0
  struct sockaddr_storage saddr = { 0 };
715
0
  socklen_t length = sizeof(struct sockaddr_storage);
716
717
0
  if (getsockname(sockfd, (struct sockaddr*)&saddr, &length) != 0)
718
0
  {
719
0
    return NULL;
720
0
  }
721
722
0
  return freerdp_tcp_address_to_string(&saddr, pIPv6);
723
0
}
724
725
char* freerdp_tcp_get_peer_address(SOCKET sockfd)
726
0
{
727
0
  struct sockaddr_storage saddr = { 0 };
728
0
  socklen_t length = sizeof(struct sockaddr_storage);
729
730
0
  if (getpeername(sockfd, (struct sockaddr*)&saddr, &length) != 0)
731
0
  {
732
0
    return NULL;
733
0
  }
734
735
0
  return freerdp_tcp_address_to_string(&saddr, NULL);
736
0
}
737
738
static int freerdp_uds_connect(const char* path)
739
0
{
740
0
#ifndef _WIN32
741
0
  int status = 0;
742
0
  int sockfd = 0;
743
0
  struct sockaddr_un addr = { 0 };
744
0
  sockfd = socket(AF_UNIX, SOCK_STREAM, 0);
745
746
0
  if (sockfd == -1)
747
0
  {
748
0
    WLog_ERR(TAG, "socket");
749
0
    return -1;
750
0
  }
751
752
0
  addr.sun_family = AF_UNIX;
753
0
  strncpy(addr.sun_path, path, sizeof(addr.sun_path) - 1);
754
0
  status = connect(sockfd, (struct sockaddr*)&addr, sizeof(addr));
755
756
0
  if (status < 0)
757
0
  {
758
0
    WLog_ERR(TAG, "connect");
759
0
    close(sockfd);
760
0
    return -1;
761
0
  }
762
763
0
  return sockfd;
764
#else /* ifndef _WIN32 */
765
  return -1;
766
#endif
767
0
}
768
769
struct addrinfo* freerdp_tcp_resolve_host(const char* hostname, int port, int ai_flags)
770
0
{
771
0
  char* service = NULL;
772
0
  char port_str[16];
773
0
  int status = 0;
774
0
  struct addrinfo hints = { 0 };
775
0
  struct addrinfo* result = NULL;
776
0
  hints.ai_family = AF_UNSPEC;
777
0
  hints.ai_socktype = SOCK_STREAM;
778
0
  hints.ai_flags = ai_flags;
779
780
0
  if (port >= 0)
781
0
  {
782
0
    (void)sprintf_s(port_str, sizeof(port_str) - 1, "%d", port);
783
0
    service = port_str;
784
0
  }
785
786
0
  status = getaddrinfo(hostname, service, &hints, &result);
787
788
0
  if (status)
789
0
    return NULL;
790
791
0
  return result;
792
0
}
793
794
static BOOL freerdp_tcp_is_hostname_resolvable(rdpContext* context, const char* hostname)
795
0
{
796
0
  struct addrinfo* result = freerdp_tcp_resolve_host(hostname, -1, 0);
797
798
0
  if (!result)
799
0
  {
800
0
    freerdp_set_last_error_if_not(context, FREERDP_ERROR_DNS_NAME_NOT_FOUND);
801
802
0
    return FALSE;
803
0
  }
804
805
0
  freerdp_set_last_error_log(context, 0);
806
0
  freeaddrinfo(result);
807
0
  return TRUE;
808
0
}
809
810
static BOOL freerdp_tcp_connect_timeout(rdpContext* context, int sockfd, struct sockaddr* addr,
811
                                        socklen_t addrlen, UINT32 timeout)
812
0
{
813
0
  BOOL rc = FALSE;
814
0
  HANDLE handles[2];
815
0
  int status = 0;
816
0
  int count = 0;
817
0
  u_long arg = 0;
818
0
  DWORD tout = (timeout > 0) ? timeout : INFINITE;
819
820
0
  handles[count] = CreateEvent(NULL, TRUE, FALSE, NULL);
821
822
0
  if (!handles[count])
823
0
    return FALSE;
824
825
0
  status = WSAEventSelect(sockfd, handles[count++], FD_READ | FD_WRITE | FD_CONNECT | FD_CLOSE);
826
827
0
  if (status < 0)
828
0
  {
829
0
    WLog_ERR(TAG, "WSAEventSelect failed with %d", WSAGetLastError());
830
0
    goto fail;
831
0
  }
832
833
0
  handles[count++] = utils_get_abort_event(context->rdp);
834
0
  status = _connect(sockfd, addr, addrlen);
835
836
0
  if (status < 0)
837
0
  {
838
0
    status = WSAGetLastError();
839
840
0
    switch (status)
841
0
    {
842
0
      case WSAEINPROGRESS:
843
0
      case WSAEWOULDBLOCK:
844
0
        break;
845
846
0
      default:
847
0
        goto fail;
848
0
    }
849
0
  }
850
851
0
  status = WaitForMultipleObjects(count, handles, FALSE, tout);
852
853
0
  if (WAIT_OBJECT_0 != status)
854
0
    goto fail;
855
856
0
  status = recv(sockfd, NULL, 0, 0);
857
858
0
  if (status == SOCKET_ERROR)
859
0
  {
860
0
    if (WSAGetLastError() == WSAECONNRESET)
861
0
      goto fail;
862
0
  }
863
864
0
  status = WSAEventSelect(sockfd, handles[0], 0);
865
866
0
  if (status < 0)
867
0
  {
868
0
    WLog_ERR(TAG, "WSAEventSelect failed with %d", WSAGetLastError());
869
0
    goto fail;
870
0
  }
871
872
0
  if (_ioctlsocket(sockfd, FIONBIO, &arg) != 0)
873
0
    goto fail;
874
875
0
  rc = TRUE;
876
0
fail:
877
0
  CloseHandle(handles[0]);
878
0
  return rc;
879
0
}
880
881
typedef struct
882
{
883
  SOCKET s;
884
  struct addrinfo* addr;
885
  struct addrinfo* result;
886
} t_peer;
887
888
static void peer_free(t_peer* peer)
889
0
{
890
0
  if (peer->s != INVALID_SOCKET)
891
0
    closesocket(peer->s);
892
893
0
  freeaddrinfo(peer->addr);
894
0
  memset(peer, 0, sizeof(t_peer));
895
0
  peer->s = INVALID_SOCKET;
896
0
}
897
898
static int freerdp_tcp_connect_multi(rdpContext* context, char** hostnames, const UINT32* ports,
899
                                     UINT32 count, UINT16 port, UINT32 timeout)
900
0
{
901
0
  UINT32 sindex = count;
902
0
  int status = -1;
903
0
  SOCKET sockfd = INVALID_SOCKET;
904
0
  HANDLE* events = NULL;
905
0
  struct addrinfo* addr = NULL;
906
0
  struct addrinfo* result = NULL;
907
0
  t_peer* peers = NULL;
908
0
  events = (HANDLE*)calloc(count + 1, sizeof(HANDLE));
909
0
  peers = (t_peer*)calloc(count, sizeof(t_peer));
910
911
0
  if (!peers || !events || (count < 1))
912
0
  {
913
0
    free(peers);
914
0
    free(events);
915
0
    return -1;
916
0
  }
917
918
0
  for (UINT32 index = 0; index < count; index++)
919
0
  {
920
0
    int curPort = port;
921
922
0
    if (ports)
923
0
      curPort = ports[index];
924
925
0
    result = freerdp_tcp_resolve_host(hostnames[index], curPort, 0);
926
927
0
    if (!result)
928
0
      continue;
929
930
0
    addr = result;
931
932
0
    if ((addr->ai_family == AF_INET6) && (addr->ai_next != 0))
933
0
    {
934
0
      while ((addr = addr->ai_next))
935
0
      {
936
0
        if (addr->ai_family == AF_INET)
937
0
          break;
938
0
      }
939
940
0
      if (!addr)
941
0
        addr = result;
942
0
    }
943
944
0
    peers[index].s = _socket(addr->ai_family, addr->ai_socktype, addr->ai_protocol);
945
946
0
    if (peers[index].s == INVALID_SOCKET)
947
0
    {
948
0
      freeaddrinfo(result);
949
0
      continue;
950
0
    }
951
952
0
    peers[index].addr = addr;
953
0
    peers[index].result = result;
954
0
  }
955
956
0
  for (UINT32 index = 0; index < count; index++)
957
0
  {
958
0
    sockfd = peers[index].s;
959
0
    addr = peers[index].addr;
960
961
0
    if ((sockfd == INVALID_SOCKET) || (!addr))
962
0
      continue;
963
964
    /* blocking tcp connect */
965
0
    status = _connect(sockfd, addr->ai_addr, addr->ai_addrlen);
966
967
0
    if (status >= 0)
968
0
    {
969
      /* connection success */
970
0
      sindex = index;
971
0
      break;
972
0
    }
973
0
  }
974
975
0
  if (sindex < count)
976
0
  {
977
0
    sockfd = peers[sindex].s;
978
0
    peers[sindex].s = INVALID_SOCKET;
979
0
  }
980
0
  else
981
0
    freerdp_set_last_error_log(context, FREERDP_ERROR_CONNECT_CANCELLED);
982
983
0
  for (UINT32 index = 0; index < count; index++)
984
0
    peer_free(&peers[index]);
985
986
0
  free(peers);
987
0
  free(events);
988
0
  return sockfd;
989
0
}
990
991
BOOL freerdp_tcp_set_keep_alive_mode(const rdpSettings* settings, int sockfd)
992
6.33k
{
993
6.33k
  const BOOL keepalive = (freerdp_settings_get_bool(settings, FreeRDP_TcpKeepAlive));
994
6.33k
  UINT32 optval = 0;
995
6.33k
  socklen_t optlen = 0;
996
6.33k
  optval = keepalive ? 1 : 0;
997
6.33k
  optlen = sizeof(optval);
998
999
6.33k
  if (setsockopt(sockfd, SOL_SOCKET, SO_KEEPALIVE, (void*)&optval, optlen) < 0)
1000
6.33k
  {
1001
6.33k
    WLog_WARN(TAG, "setsockopt() SOL_SOCKET, SO_KEEPALIVE");
1002
6.33k
  }
1003
1004
6.33k
#ifndef _WIN32
1005
6.33k
#ifdef TCP_KEEPIDLE
1006
6.33k
  optval = keepalive ? freerdp_settings_get_uint32(settings, FreeRDP_TcpKeepAliveDelay) : 0;
1007
6.33k
  optlen = sizeof(optval);
1008
1009
6.33k
  if (setsockopt(sockfd, IPPROTO_TCP, TCP_KEEPIDLE, (void*)&optval, optlen) < 0)
1010
6.33k
  {
1011
6.33k
    WLog_WARN(TAG, "setsockopt() IPPROTO_TCP, TCP_KEEPIDLE");
1012
6.33k
  }
1013
1014
6.33k
#endif
1015
#ifndef SOL_TCP
1016
  /* "tcp" from /etc/protocols as getprotobyname(3C) */
1017
#define SOL_TCP 6
1018
#endif
1019
6.33k
#ifdef TCP_KEEPCNT
1020
6.33k
  optval = keepalive ? freerdp_settings_get_uint32(settings, FreeRDP_TcpKeepAliveRetries) : 0;
1021
6.33k
  optlen = sizeof(optval);
1022
1023
6.33k
  if (setsockopt(sockfd, SOL_TCP, TCP_KEEPCNT, (void*)&optval, optlen) < 0)
1024
6.33k
  {
1025
6.33k
    WLog_WARN(TAG, "setsockopt() SOL_TCP, TCP_KEEPCNT");
1026
6.33k
  }
1027
1028
6.33k
#endif
1029
6.33k
#ifdef TCP_KEEPINTVL
1030
6.33k
  optval = keepalive ? freerdp_settings_get_uint32(settings, FreeRDP_TcpKeepAliveInterval) : 0;
1031
6.33k
  optlen = sizeof(optval);
1032
1033
6.33k
  if (setsockopt(sockfd, SOL_TCP, TCP_KEEPINTVL, (void*)&optval, optlen) < 0)
1034
6.33k
  {
1035
6.33k
    WLog_WARN(TAG, "setsockopt() SOL_TCP, TCP_KEEPINTVL");
1036
6.33k
  }
1037
1038
6.33k
#endif
1039
6.33k
#endif
1040
#if defined(__MACOSX__) || defined(__IOS__)
1041
  optval = 1;
1042
  optlen = sizeof(optval);
1043
1044
  if (setsockopt(sockfd, SOL_SOCKET, SO_NOSIGPIPE, (void*)&optval, optlen) < 0)
1045
  {
1046
    WLog_WARN(TAG, "setsockopt() SOL_SOCKET, SO_NOSIGPIPE");
1047
  }
1048
1049
#endif
1050
6.33k
#ifdef TCP_USER_TIMEOUT
1051
6.33k
  optval = freerdp_settings_get_uint32(settings, FreeRDP_TcpAckTimeout);
1052
6.33k
  optlen = sizeof(optval);
1053
1054
6.33k
  if (setsockopt(sockfd, SOL_TCP, TCP_USER_TIMEOUT, (void*)&optval, optlen) < 0)
1055
6.33k
  {
1056
6.33k
    WLog_WARN(TAG, "setsockopt() SOL_TCP, TCP_USER_TIMEOUT");
1057
6.33k
  }
1058
1059
6.33k
#endif
1060
6.33k
  return TRUE;
1061
6.33k
}
1062
1063
int freerdp_tcp_connect(rdpContext* context, const char* hostname, int port, DWORD timeout)
1064
0
{
1065
0
  rdpTransport* transport = NULL;
1066
0
  if (!context || !context->rdp)
1067
0
    return -1;
1068
0
  transport = context->rdp->transport;
1069
0
  if (!transport)
1070
0
    return -1;
1071
0
  return transport_tcp_connect(context->rdp->transport, hostname, port, timeout);
1072
0
}
1073
1074
static int get_next_addrinfo(rdpContext* context, struct addrinfo* input, struct addrinfo** result,
1075
                             UINT32 errorCode)
1076
0
{
1077
0
  WINPR_ASSERT(context);
1078
0
  WINPR_ASSERT(result);
1079
1080
0
  struct addrinfo* addr = input;
1081
0
  if (!addr)
1082
0
    goto fail;
1083
1084
0
  if (freerdp_settings_get_bool(context->settings, FreeRDP_PreferIPv6OverIPv4))
1085
0
  {
1086
0
    while (addr && (addr->ai_family != AF_INET6))
1087
0
      addr = addr->ai_next;
1088
0
    if (!addr)
1089
0
      addr = input;
1090
0
  }
1091
1092
  /* We want to force IPvX, abort if not detected */
1093
0
  const UINT32 IPvX = freerdp_settings_get_uint32(context->settings, FreeRDP_ForceIPvX);
1094
0
  switch (IPvX)
1095
0
  {
1096
0
    case 4:
1097
0
    case 6:
1098
0
    {
1099
0
      const int family = (IPvX == 4) ? AF_INET : AF_INET6;
1100
0
      while (addr && (addr->ai_family != family))
1101
0
        addr = addr->ai_next;
1102
0
      if (!addr)
1103
0
        goto fail;
1104
0
    }
1105
0
    break;
1106
0
    default:
1107
0
      break;
1108
0
  }
1109
1110
0
  if (!addr)
1111
0
    goto fail;
1112
1113
0
  *result = addr;
1114
0
  return 0;
1115
1116
0
fail:
1117
0
  freerdp_set_last_error_if_not(context, errorCode);
1118
0
  freeaddrinfo(input);
1119
0
  return -1;
1120
0
}
1121
1122
int freerdp_tcp_default_connect(rdpContext* context, rdpSettings* settings, const char* hostname,
1123
                                int port, DWORD timeout)
1124
0
{
1125
0
  int sockfd = 0;
1126
0
  UINT32 optval = 0;
1127
0
  socklen_t optlen = 0;
1128
0
  BOOL ipcSocket = FALSE;
1129
0
  BOOL useExternalDefinedSocket = FALSE;
1130
1131
0
  if (!hostname)
1132
0
  {
1133
0
    freerdp_set_last_error_if_not(context, FREERDP_ERROR_CONNECT_FAILED);
1134
1135
0
    return -1;
1136
0
  }
1137
1138
0
  if (hostname[0] == '/')
1139
0
    ipcSocket = TRUE;
1140
1141
0
  if (hostname[0] == '|')
1142
0
    useExternalDefinedSocket = TRUE;
1143
1144
0
  const char* vsock = utils_is_vsock(hostname);
1145
0
  if (ipcSocket)
1146
0
  {
1147
0
    sockfd = freerdp_uds_connect(hostname);
1148
1149
0
    if (sockfd < 0)
1150
0
    {
1151
0
      freerdp_set_last_error_if_not(context, FREERDP_ERROR_CONNECT_FAILED);
1152
1153
0
      return -1;
1154
0
    }
1155
0
  }
1156
0
  else if (useExternalDefinedSocket)
1157
0
    sockfd = port;
1158
0
  else if (vsock)
1159
0
  {
1160
#if defined(HAVE_AF_VSOCK_H)
1161
    hostname = vsock;
1162
    sockfd = socket(AF_VSOCK, SOCK_STREAM, 0);
1163
    struct sockaddr_vm addr = { 0 };
1164
1165
    addr.svm_family = AF_VSOCK;
1166
    addr.svm_port = port;
1167
1168
    errno = 0;
1169
    char* ptr = NULL;
1170
    unsigned long val = strtoul(hostname, &ptr, 10);
1171
    if (errno || (val > UINT32_MAX))
1172
    {
1173
      char ebuffer[256] = { 0 };
1174
      WLog_ERR(TAG, "could not extract port from '%s', value=%ul, error=%s", hostname, val,
1175
               winpr_strerror(errno, ebuffer, sizeof(ebuffer)));
1176
      return -1;
1177
    }
1178
    addr.svm_cid = val;
1179
    if (addr.svm_cid == 2)
1180
    {
1181
      addr.svm_flags = VMADDR_FLAG_TO_HOST;
1182
    }
1183
    if ((connect(sockfd, (struct sockaddr*)&addr, sizeof(struct sockaddr_vm))) == -1)
1184
    {
1185
      WLog_ERR(TAG, "failed to connect to %s", hostname);
1186
      return -1;
1187
    }
1188
#else
1189
0
    WLog_ERR(TAG, "Compiled without AF_VSOCK, '%s' not supported", hostname);
1190
0
    return -1;
1191
0
#endif
1192
0
  }
1193
0
  else
1194
0
  {
1195
0
    sockfd = -1;
1196
1197
0
    if (!settings->GatewayEnabled)
1198
0
    {
1199
0
      if (!freerdp_tcp_is_hostname_resolvable(context, hostname) ||
1200
0
          settings->RemoteAssistanceMode)
1201
0
      {
1202
0
        if (settings->TargetNetAddressCount > 0)
1203
0
        {
1204
0
          sockfd = freerdp_tcp_connect_multi(
1205
0
              context, settings->TargetNetAddresses, settings->TargetNetPorts,
1206
0
              settings->TargetNetAddressCount, port, timeout);
1207
0
        }
1208
0
      }
1209
0
    }
1210
1211
0
    if (sockfd <= 0)
1212
0
    {
1213
0
      char* peerAddress = NULL;
1214
0
      struct addrinfo* addr = NULL;
1215
0
      struct addrinfo* result = NULL;
1216
1217
0
      result = freerdp_tcp_resolve_host(hostname, port, 0);
1218
1219
0
      if (!result)
1220
0
      {
1221
0
        freerdp_set_last_error_if_not(context, FREERDP_ERROR_DNS_NAME_NOT_FOUND);
1222
1223
0
        return -1;
1224
0
      }
1225
0
      freerdp_set_last_error_log(context, 0);
1226
1227
      /* By default we take the first returned entry.
1228
       *
1229
       * If PreferIPv6OverIPv4 = TRUE we force to IPv6 if there
1230
       * is such an address available, but fall back to first if not found
1231
       */
1232
0
      const int rc =
1233
0
          get_next_addrinfo(context, result, &addr, FREERDP_ERROR_DNS_NAME_NOT_FOUND);
1234
0
      if (rc < 0)
1235
0
        return rc;
1236
1237
0
      do
1238
0
      {
1239
0
        sockfd = socket(addr->ai_family, addr->ai_socktype, addr->ai_protocol);
1240
0
        if (sockfd < 0)
1241
0
        {
1242
0
          const int lrc = get_next_addrinfo(context, addr->ai_next, &addr,
1243
0
                                            FREERDP_ERROR_CONNECT_FAILED);
1244
0
          if (lrc < 0)
1245
0
            return lrc;
1246
0
        }
1247
0
      } while (sockfd < 0);
1248
1249
0
      if ((peerAddress = freerdp_tcp_address_to_string(
1250
0
               (const struct sockaddr_storage*)addr->ai_addr, NULL)) != NULL)
1251
0
      {
1252
0
        WLog_DBG(TAG, "connecting to peer %s", peerAddress);
1253
0
        free(peerAddress);
1254
0
      }
1255
1256
0
      if (!freerdp_tcp_connect_timeout(context, sockfd, addr->ai_addr, addr->ai_addrlen,
1257
0
                                       timeout))
1258
0
      {
1259
0
        freeaddrinfo(result);
1260
0
        close(sockfd);
1261
1262
0
        freerdp_set_last_error_if_not(context, FREERDP_ERROR_CONNECT_FAILED);
1263
1264
0
        WLog_ERR(TAG, "failed to connect to %s", hostname);
1265
0
        return -1;
1266
0
      }
1267
1268
0
      freeaddrinfo(result);
1269
0
    }
1270
0
  }
1271
1272
0
  if (!vsock)
1273
0
  {
1274
0
    free(settings->ClientAddress);
1275
0
    settings->ClientAddress = freerdp_tcp_get_ip_address(sockfd, &settings->IPv6Enabled);
1276
1277
0
    if (!settings->ClientAddress)
1278
0
    {
1279
0
      if (!useExternalDefinedSocket)
1280
0
        close(sockfd);
1281
1282
0
      freerdp_set_last_error_if_not(context, FREERDP_ERROR_CONNECT_FAILED);
1283
1284
0
      WLog_ERR(TAG, "Couldn't get socket ip address");
1285
0
      return -1;
1286
0
    }
1287
0
  }
1288
1289
0
  optval = 1;
1290
0
  optlen = sizeof(optval);
1291
1292
0
  if (!ipcSocket && !useExternalDefinedSocket)
1293
0
  {
1294
0
    if (setsockopt(sockfd, IPPROTO_TCP, TCP_NODELAY, (void*)&optval, optlen) < 0)
1295
0
      WLog_ERR(TAG, "unable to set TCP_NODELAY");
1296
0
  }
1297
1298
  /* receive buffer must be a least 32 K */
1299
0
  if (getsockopt(sockfd, SOL_SOCKET, SO_RCVBUF, (void*)&optval, &optlen) == 0)
1300
0
  {
1301
0
    if (optval < (1024 * 32))
1302
0
    {
1303
0
      optval = 1024 * 32;
1304
0
      optlen = sizeof(optval);
1305
1306
0
      if (setsockopt(sockfd, SOL_SOCKET, SO_RCVBUF, (void*)&optval, optlen) < 0)
1307
0
      {
1308
0
        close(sockfd);
1309
1310
0
        freerdp_set_last_error_if_not(context, FREERDP_ERROR_CONNECT_FAILED);
1311
1312
0
        WLog_ERR(TAG, "unable to set receive buffer len");
1313
0
        return -1;
1314
0
      }
1315
0
    }
1316
0
  }
1317
1318
0
  if (!ipcSocket && !useExternalDefinedSocket)
1319
0
  {
1320
0
    if (!freerdp_tcp_set_keep_alive_mode(settings, sockfd))
1321
0
    {
1322
0
      close(sockfd);
1323
1324
0
      freerdp_set_last_error_if_not(context, FREERDP_ERROR_CONNECT_FAILED);
1325
1326
0
      WLog_ERR(TAG, "Couldn't set keep alive mode.");
1327
0
      return -1;
1328
0
    }
1329
0
  }
1330
1331
0
  if (WaitForSingleObject(utils_get_abort_event(context->rdp), 0) == WAIT_OBJECT_0)
1332
0
  {
1333
0
    close(sockfd);
1334
0
    return -1;
1335
0
  }
1336
1337
0
  return sockfd;
1338
0
}
1339
1340
struct rdp_tcp_layer
1341
{
1342
  int sockfd;
1343
  HANDLE hEvent;
1344
};
1345
typedef struct rdp_tcp_layer rdpTcpLayer;
1346
1347
static int freerdp_tcp_layer_read(void* userContext, void* data, int bytes)
1348
0
{
1349
0
  if (!userContext)
1350
0
    return -1;
1351
0
  if (!data || !bytes)
1352
0
    return 0;
1353
1354
0
  rdpTcpLayer* tcpLayer = (rdpTcpLayer*)userContext;
1355
1356
0
  int error = 0;
1357
0
  int status = 0;
1358
1359
0
  WSAResetEvent(tcpLayer->hEvent);
1360
0
  status = _recv(tcpLayer->sockfd, data, bytes, 0);
1361
1362
0
  if (status > 0)
1363
0
    return status;
1364
1365
0
  if (status == 0)
1366
0
    return -1; /* socket closed */
1367
1368
0
  error = WSAGetLastError();
1369
1370
0
  if ((error == WSAEWOULDBLOCK) || (error == WSAEINTR) || (error == WSAEINPROGRESS) ||
1371
0
      (error == WSAEALREADY))
1372
0
  {
1373
0
    status = 0;
1374
0
  }
1375
0
  else
1376
0
  {
1377
0
    status = -1;
1378
0
  }
1379
1380
0
  return status;
1381
0
}
1382
1383
static int freerdp_tcp_layer_write(void* userContext, const void* data, int bytes)
1384
0
{
1385
0
  if (!userContext)
1386
0
    return -1;
1387
0
  if (!data || !bytes)
1388
0
    return 0;
1389
1390
0
  rdpTcpLayer* tcpLayer = (rdpTcpLayer*)userContext;
1391
1392
0
  int error = 0;
1393
0
  int status = 0;
1394
1395
0
  status = _send(tcpLayer->sockfd, data, bytes, 0);
1396
1397
0
  if (status <= 0)
1398
0
  {
1399
0
    error = WSAGetLastError();
1400
1401
0
    if ((error == WSAEWOULDBLOCK) || (error == WSAEINTR) || (error == WSAEINPROGRESS) ||
1402
0
        (error == WSAEALREADY))
1403
0
    {
1404
0
      status = 0;
1405
0
    }
1406
0
    else
1407
0
    {
1408
0
      status = -1;
1409
0
    }
1410
0
  }
1411
1412
0
  return status;
1413
0
}
1414
1415
static BOOL freerdp_tcp_layer_close(void* userContext)
1416
0
{
1417
0
  if (!userContext)
1418
0
    return FALSE;
1419
1420
0
  rdpTcpLayer* tcpLayer = (rdpTcpLayer*)userContext;
1421
1422
0
  if (tcpLayer->sockfd >= 0)
1423
0
    closesocket(tcpLayer->sockfd);
1424
0
  if (tcpLayer->hEvent)
1425
0
    CloseHandle(tcpLayer->hEvent);
1426
1427
0
  return TRUE;
1428
0
}
1429
1430
static BOOL freerdp_tcp_layer_wait(void* userContext, BOOL waitWrite, DWORD timeout)
1431
0
{
1432
0
  if (!userContext)
1433
0
    return FALSE;
1434
1435
0
  rdpTcpLayer* tcpLayer = (rdpTcpLayer*)userContext;
1436
1437
0
  int status = -1;
1438
0
  int sockfd = tcpLayer->sockfd;
1439
0
#ifdef WINPR_HAVE_POLL_H
1440
0
  struct pollfd pollset = { 0 };
1441
0
  pollset.fd = sockfd;
1442
0
  pollset.events = waitWrite ? POLLOUT : POLLIN;
1443
1444
0
  do
1445
0
  {
1446
0
    status = poll(&pollset, 1, (int)timeout);
1447
0
  } while ((status < 0) && (errno == EINTR));
1448
1449
#else
1450
  fd_set rset;
1451
  struct timeval tv;
1452
  FD_ZERO(&rset);
1453
  FD_SET(sockfd, &rset);
1454
1455
  if (timeout)
1456
  {
1457
    tv.tv_sec = timeout / 1000;
1458
    tv.tv_usec = (timeout % 1000) * 1000;
1459
  }
1460
1461
  do
1462
  {
1463
    if (waitWrite)
1464
      status = select(sockfd + 1, NULL, &rset, NULL, timeout ? &tv : NULL);
1465
    else
1466
      status = select(sockfd + 1, &rset, NULL, NULL, timeout ? &tv : NULL);
1467
  } while ((status < 0) && (errno == EINTR));
1468
1469
#endif
1470
1471
0
  return status != 0;
1472
0
}
1473
1474
static HANDLE freerdp_tcp_layer_get_event(void* userContext)
1475
0
{
1476
0
  if (!userContext)
1477
0
    return NULL;
1478
1479
0
  rdpTcpLayer* tcpLayer = (rdpTcpLayer*)userContext;
1480
1481
0
  return tcpLayer->hEvent;
1482
0
}
1483
1484
rdpTransportLayer* freerdp_tcp_connect_layer(rdpContext* context, const char* hostname, int port,
1485
                                             DWORD timeout)
1486
0
{
1487
0
  WINPR_ASSERT(context);
1488
1489
0
  const rdpSettings* settings = context->settings;
1490
0
  WINPR_ASSERT(settings);
1491
1492
0
  rdpTransportLayer* layer = NULL;
1493
0
  rdpTcpLayer* tcpLayer = NULL;
1494
1495
0
  int sockfd = freerdp_tcp_connect(context, hostname, port, timeout);
1496
0
  if (sockfd < 0)
1497
0
    goto fail;
1498
0
  if (!freerdp_tcp_set_keep_alive_mode(settings, sockfd))
1499
0
    goto fail;
1500
1501
0
  layer = transport_layer_new(freerdp_get_transport(context), sizeof(rdpTcpLayer));
1502
0
  if (!layer)
1503
0
    goto fail;
1504
1505
0
  layer->Read = freerdp_tcp_layer_read;
1506
0
  layer->Write = freerdp_tcp_layer_write;
1507
0
  layer->Close = freerdp_tcp_layer_close;
1508
0
  layer->Wait = freerdp_tcp_layer_wait;
1509
0
  layer->GetEvent = freerdp_tcp_layer_get_event;
1510
1511
0
  tcpLayer = (rdpTcpLayer*)layer->userContext;
1512
0
  WINPR_ASSERT(tcpLayer);
1513
1514
0
  tcpLayer->sockfd = -1;
1515
0
  tcpLayer->hEvent = WSACreateEvent();
1516
0
  if (!tcpLayer->hEvent)
1517
0
    goto fail;
1518
1519
  /* WSAEventSelect automatically sets the socket in non-blocking mode */
1520
0
  if (WSAEventSelect(sockfd, tcpLayer->hEvent, FD_READ | FD_ACCEPT | FD_CLOSE))
1521
0
  {
1522
0
    WLog_ERR(TAG, "WSAEventSelect returned 0x%08X", WSAGetLastError());
1523
0
    goto fail;
1524
0
  }
1525
1526
0
  tcpLayer->sockfd = sockfd;
1527
1528
0
  return layer;
1529
1530
0
fail:
1531
0
  if (sockfd >= 0)
1532
0
    closesocket(sockfd);
1533
0
  transport_layer_free(layer);
1534
0
  return NULL;
1535
0
}