1 // SoftEther VPN Source Code - Developer Edition Master Branch
2 // Cedar Communication Module
3
4
5 // UdpAccel.c
6 // UDP acceleration function
7
8 #include "UdpAccel.h"
9
10 #include "Connection.h"
11
12 #include "Mayaqua/DNS.h"
13 #include "Mayaqua/Kernel.h"
14 #include "Mayaqua/Memory.h"
15 #include "Mayaqua/Object.h"
16 #include "Mayaqua/Str.h"
17 #include "Mayaqua/TcpIp.h"
18 #include "Mayaqua/Tick64.h"
19
20 #include <stdlib.h>
21
22 // Polling process
UdpAccelPoll(UDP_ACCEL * a)23 void UdpAccelPoll(UDP_ACCEL *a)
24 {
25 IP nat_t_ip;
26 UINT num_ignore_errors = 0;
27 UCHAR *tmp;
28 // Validate arguments
29 if (a == NULL)
30 {
31 return;
32 }
33
34 tmp = a->TmpBuf;
35
36 Lock(a->NatT_Lock);
37 {
38 Copy(&nat_t_ip, &a->NatT_IP, sizeof(IP));
39 }
40 Unlock(a->NatT_Lock);
41
42 if (IsZeroIp(&nat_t_ip) == false)
43 {
44 // Release the thread which gets the IP address of the NAT-T server because it is no longer needed
45 if (a->NatT_GetIpThread != NULL)
46 {
47 WaitThread(a->NatT_GetIpThread, INFINITE);
48 ReleaseThread(a->NatT_GetIpThread);
49 a->NatT_GetIpThread = NULL;
50 }
51 }
52
53 // Receive a new UDP packet
54 while (true)
55 {
56 IP src_ip;
57 UINT src_port;
58 UINT ret;
59
60 ret = RecvFrom(a->UdpSock, &src_ip, &src_port, tmp, UDP_ACCELERATION_TMP_BUF_SIZE);
61
62 if (ret != 0 && ret != SOCK_LATER)
63 {
64 if (a->UseUdpIpQuery && a->UdpIpQueryPacketSize >= 8 && CmpIpAddr(&a->UdpIpQueryHost, &src_ip) == 0 &&
65 src_port == a->UdpIpQueryPort)
66 {
67 /*
68 // Receive a response of the query for IP and port number
69 IP my_ip = {0};
70 UINT myport = 0;
71 BUF *b = MemToBuf(a->UdpIpQueryPacketData, a->UdpIpQueryPacketSize);
72 FreeBuf(b);
73 */
74 }
75 else if (IsZeroIp(&nat_t_ip) == false && CmpIpAddr(&nat_t_ip, &src_ip) == 0 &&
76 src_port == UDP_NAT_T_PORT)
77 {
78 // Receive a response from the NAT-T server
79 IP ip;
80 UINT port;
81 if (RUDPParseIPAndPortStr(tmp, ret, &ip, &port))
82 {
83 if (a->MyPortNatT != port && port >= 1 && port <= 65535)
84 {
85 Debug("NAT-T: MyIP = %r, MyPort = %hu\n", &ip, port);
86
87 a->CommToNatT_NumFail = 0;
88 Copy(&a->MyIpNatT, &ip, sizeof(a->MyIpNatT));
89 a->MyPortNatT = port;
90 a->MyIpOrPortNatTChanged = true;
91 }
92 }
93 /*
94 BUF *b = NewBuf();
95 PACK *p;
96
97 WriteBuf(b, tmp, ret);
98 SeekBufToBegin(b);
99
100 p = BufToPack(b);
101 if (p != NULL)
102 {
103 if (PackCmpStr(p, "opcode", "query_for_nat_traversal"))
104 {
105 if (PackGetBool(p, "ok"))
106 {
107 if (PackGetInt64(p, "tran_id") == a->NatT_TranId)
108 {
109 UINT myport = PackGetInt(p, "your_port");
110
111 if (myport >= 1 && myport <= 65535)
112 {
113 if (a->MyPortByNatTServer != myport)
114 {
115 a->MyPortByNatTServer = myport;
116 a->MyPortByNatTServerChanged = true;
117
118 Debug("NAT-T: MyPort = %u\n", myport);
119 }
120 }
121 }
122 }
123 }
124
125 FreePack(p);
126 }
127
128 FreeBuf(b);*/
129 }
130 else
131 {
132 BLOCK *b = UdpAccelProcessRecvPacket(a, tmp, ret, &src_ip, src_port);
133
134 //Debug("UDP Recv: %u %u %u\n", ret, (b == NULL ? 0 : b->Size), (b == NULL ? 0 : b->Compressed));
135
136 /*if (b != NULL)
137 {
138 char tmp[MAX_SIZE * 10];
139 BinToStr(tmp, sizeof(tmp), b->Buf, b->Size);
140 Debug("Recv Pkt: %s\n", tmp);
141 }*/
142
143 if (b != NULL)
144 {
145 // Receive a packet
146 InsertQueue(a->RecvBlockQueue, b);
147 }
148 }
149 }
150 else
151 {
152 if (ret == 0)
153 {
154 if (a->UdpSock->IgnoreRecvErr == false)
155 {
156 // Serious UDP reception error occurs
157 a->FatalError = true;
158 break;
159 }
160
161 if ((num_ignore_errors++) >= MAX_NUM_IGNORE_ERRORS)
162 {
163 a->FatalError = true;
164 break;
165 }
166 }
167 else
168 {
169 // SOCK_LATER
170 break;
171 }
172 }
173 }
174
175 // Send a Keep-Alive packet
176 if (a->NextSendKeepAlive == 0 || (a->NextSendKeepAlive <= a->Now) || a->YourIpOrPortNatTChanged)
177 {
178 a->YourIpOrPortNatTChanged = false;
179
180 if (UdpAccelIsSendReady(a, false))
181 {
182 UINT rand_interval;
183
184 if (a->FastDetect == false)
185 {
186 rand_interval = rand() % (UDP_ACCELERATION_KEEPALIVE_INTERVAL_MAX - UDP_ACCELERATION_KEEPALIVE_INTERVAL_MIN) + UDP_ACCELERATION_KEEPALIVE_INTERVAL_MIN;
187 }
188 else
189 {
190 rand_interval = rand() % (UDP_ACCELERATION_KEEPALIVE_INTERVAL_MAX_FAST - UDP_ACCELERATION_KEEPALIVE_INTERVAL_MIN_FAST) + UDP_ACCELERATION_KEEPALIVE_INTERVAL_MIN_FAST;
191 }
192
193 a->NextSendKeepAlive = a->Now + (UINT64)rand_interval;
194
195 //Debug("UDP KeepAlive\n");
196
197 UdpAccelSend(a, NULL, 0, false, 1000, false);
198 }
199 }
200
201 // Send a NAT-T request packet (Only if the connection by UDP has not be established yet)
202 if (a->NoNatT == false)
203 {
204 // In the usual case
205 if (IsZeroIp(&nat_t_ip) == false)
206 {
207 if (UdpAccelIsSendReady(a, true) == false)
208 {
209 if (a->NextPerformNatTTick == 0 || (a->NextPerformNatTTick <= a->Now))
210 {
211 UINT rand_interval;
212 UCHAR c = 'B';
213
214 a->CommToNatT_NumFail++;
215
216 rand_interval = UDP_NAT_T_INTERVAL_INITIAL * MIN(a->CommToNatT_NumFail, UDP_NAT_T_INTERVAL_FAIL_MAX);
217 //PACK *p = NewPack();
218 //BUF *b;
219
220 if (a->MyPortNatT != 0)
221 {
222 rand_interval = GenRandInterval(UDP_NAT_T_INTERVAL_MIN, UDP_NAT_T_INTERVAL_MAX);
223 }
224
225 a->NextPerformNatTTick = a->Now + (UINT64)rand_interval;
226
227 // Generate the request packet
228 /*PackAddStr(p, "description", UDP_NAT_T_SIGNATURE);
229 PackAddStr(p, "opcode", "query_for_nat_traversal");
230 PackAddInt64(p, "tran_id", a->NatT_TranId);
231 b = PackToBuf(p);
232 FreePack(p);*/
233
234 // Send the request packet
235 SendTo(a->UdpSock, &nat_t_ip, UDP_NAT_T_PORT, &c, 1);
236
237 //FreeBuf(b);
238 }
239 }
240 else
241 {
242 a->NextPerformNatTTick = 0;
243 a->CommToNatT_NumFail = 0;
244 }
245 }
246 }
247 else
248 {
249 // NAT_T is disabled, but there is a reference host (such as VGC)
250 if (a->UseUdpIpQuery || a->UseSuperRelayQuery)
251 {
252 }
253 }
254 }
255
256 // Send a packet block
UdpAccelSendBlock(UDP_ACCEL * a,BLOCK * b)257 void UdpAccelSendBlock(UDP_ACCEL *a, BLOCK *b)
258 {
259 // Validate arguments
260 if (a == NULL || b == NULL)
261 {
262 return;
263 }
264
265 UdpAccelSend(a, b->Buf, b->Size, b->Compressed ? 1 : 0, a->MaxUdpPacketSize, b->PriorityQoS);
266 }
267
268 // Calculate the best MSS
UdpAccelCalcMss(UDP_ACCEL * a)269 UINT UdpAccelCalcMss(UDP_ACCEL *a)
270 {
271 UINT ret;
272
273 // Validate arguments
274 if (a == NULL)
275 {
276 return 0;
277 }
278
279 ret = MTU_FOR_PPPOE;
280
281 // IPv4
282 if (a->IsIPv6)
283 {
284 ret -= 40;
285 }
286 else
287 {
288 ret -= 20;
289 }
290
291 // UDP
292 ret -= 8;
293
294 if (a->PlainTextMode == false)
295 {
296 // IV
297 ret -= UDP_ACCELERATION_PACKET_IV_SIZE_V1;
298 }
299
300 // Cookie
301 ret -= sizeof(UINT);
302
303 // My Tick
304 ret -= sizeof(UINT64);
305
306 // Your Tick
307 ret -= sizeof(UINT64);
308
309 // Size
310 ret -= sizeof(USHORT);
311
312 // Compress Flag
313 ret -= sizeof(UCHAR);
314
315 if (a->PlainTextMode == false)
316 {
317 // Verify
318 ret -= UDP_ACCELERATION_PACKET_IV_SIZE_V1;
319 }
320
321 // Ethernet header (communication packets)
322 ret -= 14;
323
324 // IPv4 Header (communication packets)
325 ret -= 20;
326
327 // TCP header (communication packet)
328 ret -= 20;
329
330 return ret;
331 }
332
333 // Send
UdpAccelSend(UDP_ACCEL * a,UCHAR * data,UINT data_size,UCHAR flag,UINT max_size,bool high_priority)334 void UdpAccelSend(UDP_ACCEL *a, UCHAR *data, UINT data_size, UCHAR flag, UINT max_size, bool high_priority)
335 {
336 UCHAR buffer[UDP_ACCELERATION_TMP_BUF_SIZE];
337 UCHAR *buf = buffer;
338 UINT size = 0;
339 UINT64 tmp;
340 UINT ret;
341 // Validate arguments
342 if (a == NULL || (data_size != 0 && data == NULL))
343 {
344 return;
345 }
346 if (max_size == 0)
347 {
348 max_size = INFINITE;
349 }
350
351 if (a->PlainTextMode == false)
352 {
353 if (a->Version > 1)
354 {
355 Copy(buf, a->NextIv_V2, UDP_ACCELERATION_PACKET_IV_SIZE_V2);
356
357 buf += UDP_ACCELERATION_PACKET_IV_SIZE_V2;
358 size += UDP_ACCELERATION_PACKET_IV_SIZE_V2;
359 }
360 else
361 {
362 Copy(buf, a->NextIv, UDP_ACCELERATION_PACKET_IV_SIZE_V1);
363
364 buf += UDP_ACCELERATION_PACKET_IV_SIZE_V1;
365 size += UDP_ACCELERATION_PACKET_IV_SIZE_V1;
366 }
367 }
368
369 // Cookie
370 tmp = Endian32(a->YourCookie);
371 Copy(buf, &tmp, sizeof(UINT));
372 buf += sizeof(UINT);
373 size += sizeof(UINT);
374
375 // My tick
376 tmp = Endian64(a->Now == 0 ? 1ULL : a->Now);
377 Copy(buf, &tmp, sizeof(UINT64));
378 buf += sizeof(UINT64);
379 size += sizeof(UINT64);
380
381 // Your tick
382 tmp = Endian64(a->LastRecvYourTick);
383 Copy(buf, &tmp, sizeof(UINT64));
384 buf += sizeof(UINT64);
385 size += sizeof(UINT64);
386
387 // Size
388 tmp = Endian16(data_size);
389 Copy(buf, &tmp, sizeof(USHORT));
390 buf += sizeof(USHORT);
391 size += sizeof(USHORT);
392
393 // Flag
394 Copy(buf, &flag, sizeof(UCHAR));
395 buf += sizeof(UCHAR);
396 size += sizeof(UCHAR);
397
398 // Data
399 Copy(buf, data, data_size);
400 buf += data_size;
401 size += data_size;
402
403 if (a->PlainTextMode == false)
404 {
405 // Add padding to make protocol identification harder to accomplish
406 const UINT current_total_size = size + (a->Version > 1 ? UDP_ACCELERATION_PACKET_MAC_SIZE_V2 : UDP_ACCELERATION_PACKET_IV_SIZE_V1);
407 if (current_total_size < max_size)
408 {
409 UCHAR pad[UDP_ACCELERATION_MAX_PADDING_SIZE];
410 UINT pad_size = MIN(max_size - current_total_size, UDP_ACCELERATION_MAX_PADDING_SIZE);
411 pad_size = rand() % pad_size;
412 Zero(pad, sizeof(pad));
413 Copy(buf, pad, pad_size);
414 buf += pad_size;
415 size += pad_size;
416 }
417
418 if (a->Version > 1)
419 {
420 const UINT inner_size = size - UDP_ACCELERATION_PACKET_IV_SIZE_V2;
421 UCHAR *inner = buffer + UDP_ACCELERATION_PACKET_IV_SIZE_V2;
422
423 ret = CipherProcessAead(a->CipherEncrypt, a->NextIv_V2, inner + inner_size, UDP_ACCELERATION_PACKET_MAC_SIZE_V2, inner, inner, inner_size, NULL, 0);
424 if (ret == 0)
425 {
426 Debug("UdpAccelSend(): CipherProcessAead() failed!\n");
427 return;
428 }
429
430 Copy(a->NextIv_V2, inner, UDP_ACCELERATION_PACKET_IV_SIZE_V2);
431
432 // Tag (appended to the buffer by CipherProcessAead())
433 size += UDP_ACCELERATION_PACKET_MAC_SIZE_V2;
434 }
435 else
436 {
437 UCHAR *inner = buffer + UDP_ACCELERATION_PACKET_IV_SIZE_V1;
438 UCHAR key[UDP_ACCELERATION_PACKET_KEY_SIZE_V1];
439 const UINT inner_size = size; // We don't have to subtract because we add below
440 CRYPT *c;
441
442 // Simple integrity check system: we fill some bytes with zeroes.
443 // The remote host verifies whether all the zeroes are present.
444 Zero(buf, UDP_ACCELERATION_PACKET_IV_SIZE_V1);
445 buf += UDP_ACCELERATION_PACKET_IV_SIZE_V1;
446 size += UDP_ACCELERATION_PACKET_IV_SIZE_V1;
447
448 UdpAccelCalcKeyV1(key, a->MyKey, a->NextIv);
449
450 c = NewCrypt(key, UDP_ACCELERATION_PACKET_KEY_SIZE_V1);
451 Encrypt(c, inner, inner, inner_size);
452 FreeCrypt(c);
453
454 Copy(a->NextIv, buf - UDP_ACCELERATION_PACKET_IV_SIZE_V1, UDP_ACCELERATION_PACKET_IV_SIZE_V1);
455 }
456 }
457
458 SetSockHighPriority(a->UdpSock, high_priority);
459
460 if (SendTo(a->UdpSock, &a->YourIp, a->YourPort, buffer, size) == 0)
461 {
462 Debug("UdpAccelSend(): SendTo() failed! IP: %r, port: %u, size: %u\n", &a->YourIp, a->YourPort, size);
463 if (a->UdpSock->IgnoreSendErr == false)
464 {
465 a->FatalError = true;
466 return;
467 }
468 }
469
470 if (data_size > 0 || UdpAccelIsSendReady(a, true))
471 {
472 return;
473 }
474
475 Debug("UdpAccelSend(): Peer has not replied in a while, sending keep-alive packet to alt destinations...\n");
476
477 IP *ips[3];
478 ips[0] = &a->YourIp;
479 ips[1] = CmpIpAddr(&a->YourIpReported, &a->YourIp) == 0 ? NULL : &a->YourIpReported;
480 ips[2] = CmpIpAddr(&a->YourIpNatT, &a->YourIp) == 0 || CmpIpAddr(&a->YourIpNatT, &a->YourIpReported) == 0 ? NULL : &a->YourIpNatT;
481
482 USHORT ports[3];
483 ports[0] = a->YourPort;
484 ports[1] = a->YourPortReported == a->YourPort ? 0 : a->YourPortReported;
485 ports[2] = a->YourPortNatT == a->YourPort || a->YourPortNatT == a->YourPortReported ? 0 : a->YourPortNatT;
486
487 for (BYTE i = 0; i < sizeof(ips) / sizeof(ips[0]); ++i)
488 {
489 if (IsZeroIP(ips[i]))
490 {
491 continue;
492 }
493
494 for (BYTE j = 0; j < sizeof(ports) / sizeof(ports[0]); ++j)
495 {
496 if (ports[j] == 0)
497 {
498 continue;
499 }
500
501 if (CmpIpAddr(ips[i], &a->YourIp) == 0 && ports[j] == a->YourPort)
502 {
503 continue;
504 }
505
506 if (SendTo(a->UdpSock, ips[i], ports[j], buffer, size) == 0)
507 {
508 Debug("UdpAccelSend(): SendTo() failed! IP: %r, port: %u, size: %u\n", ips[i], ports[j], size);
509 if (a->UdpSock->IgnoreSendErr == false)
510 {
511 a->FatalError = true;
512 return;
513 }
514 }
515
516 if (UdpAccelIsSendReady(a, true))
517 {
518 break;
519 }
520 }
521 }
522 }
523
524 // Determine whether transmission is possible
UdpAccelIsSendReady(UDP_ACCEL * a,bool check_keepalive)525 bool UdpAccelIsSendReady(UDP_ACCEL *a, bool check_keepalive)
526 {
527 UINT64 timeout_value;
528 // Validate arguments
529 if (a == NULL)
530 {
531 return false;
532 }
533
534 if (a->Inited == false)
535 {
536 return false;
537 }
538
539 if (a->YourPort == 0)
540 {
541 return false;
542 }
543
544 if (IsZeroIp(&a->YourIp))
545 {
546 return false;
547 }
548
549 timeout_value = UDP_ACCELERATION_KEEPALIVE_TIMEOUT;
550
551 if (a->FastDetect)
552 {
553 timeout_value = UDP_ACCELERATION_KEEPALIVE_TIMEOUT_FAST;
554 }
555
556 if (check_keepalive)
557 {
558 if (a->LastRecvTick == 0 || ((a->LastRecvTick + timeout_value) < a->Now))
559 {
560 a->FirstStableReceiveTick = 0;
561 return false;
562 }
563 else
564 {
565 if ((a->FirstStableReceiveTick + (UINT64)UDP_ACCELERATION_REQUIRE_CONTINUOUS) <= a->Now)
566 {
567 return true;
568 }
569 else
570 {
571 return false;
572 }
573 }
574 }
575
576 return true;
577 }
578
579 // Process the received packet
UdpAccelProcessRecvPacket(UDP_ACCEL * a,UCHAR * buf,UINT size,IP * src_ip,UINT src_port)580 BLOCK *UdpAccelProcessRecvPacket(UDP_ACCEL *a, UCHAR *buf, UINT size, IP *src_ip, UINT src_port)
581 {
582 UINT64 my_tick, your_tick;
583 UINT inner_size;
584 UCHAR *inner_data = NULL;
585 bool compress_flag;
586 UCHAR raw_flag;
587 BLOCK *b = NULL;
588 UINT cookie;
589 // Validate arguments
590 if (a == NULL || buf == NULL || size == 0 || src_ip == NULL)
591 {
592 return NULL;
593 }
594
595 if (a->PlainTextMode == false)
596 {
597 UCHAR *iv = buf;
598
599 if (a->Version > 1)
600 {
601 UINT data_size;
602
603 if (size < UDP_ACCELERATION_PACKET_IV_SIZE_V2)
604 {
605 return NULL;
606 }
607
608 buf += UDP_ACCELERATION_PACKET_IV_SIZE_V2;
609 size -= UDP_ACCELERATION_PACKET_IV_SIZE_V2;
610
611 if (size < UDP_ACCELERATION_PACKET_MAC_SIZE_V2)
612 {
613 return NULL;
614 }
615
616 data_size = size - UDP_ACCELERATION_PACKET_MAC_SIZE_V2;
617
618 if (CipherProcessAead(a->CipherDecrypt, iv, buf + data_size, UDP_ACCELERATION_PACKET_MAC_SIZE_V2, buf, buf, data_size, NULL, 0) == 0)
619 {
620 Debug("UdpAccelProcessRecvPacket(): CipherProcessAead() failed!\n");
621 return NULL;
622 }
623
624 size -= UDP_ACCELERATION_PACKET_MAC_SIZE_V2;
625 }
626 else
627 {
628 UCHAR key[UDP_ACCELERATION_PACKET_KEY_SIZE_V1];
629 CRYPT *c;
630
631 if (size < UDP_ACCELERATION_PACKET_IV_SIZE_V1)
632 {
633 return NULL;
634 }
635
636 buf += UDP_ACCELERATION_PACKET_IV_SIZE_V1;
637 size -= UDP_ACCELERATION_PACKET_IV_SIZE_V1;
638
639 UdpAccelCalcKeyV1(key, a->YourKey, iv);
640
641 c = NewCrypt(key, UDP_ACCELERATION_PACKET_KEY_SIZE_V1);
642 Encrypt(c, buf, buf, size);
643 FreeCrypt(c);
644 }
645 }
646
647 // Cookie
648 if (size < sizeof(UINT))
649 {
650 return NULL;
651 }
652 cookie = READ_UINT(buf);
653 buf += sizeof(UINT);
654 size -= sizeof(UINT);
655
656 if (cookie != a->MyCookie)
657 {
658 return NULL;
659 }
660
661 // My tick
662 if (size < sizeof(UINT64))
663 {
664 return NULL;
665 }
666 my_tick = READ_UINT64(buf);
667 buf += sizeof(UINT64);
668 size -= sizeof(UINT64);
669
670 // Your tick
671 if (size < sizeof(UINT64))
672 {
673 return NULL;
674 }
675 your_tick = READ_UINT64(buf);
676 buf += sizeof(UINT64);
677 size -= sizeof(UINT64);
678
679 // Inner data size
680 if (size < sizeof(USHORT))
681 {
682 return NULL;
683 }
684 inner_size = READ_USHORT(buf);
685 buf += sizeof(USHORT);
686 size -= sizeof(USHORT);
687
688 // Flag
689 if (size < sizeof(UCHAR))
690 {
691 return NULL;
692 }
693 if (a->ReadRawFlagMode == false)
694 {
695 compress_flag = *((UCHAR *)buf);
696 }
697 else
698 {
699 raw_flag = *((UCHAR *)buf);
700 }
701
702 buf += sizeof(UCHAR);
703 size -= sizeof(UCHAR);
704
705 if (size < inner_size)
706 {
707 return NULL;
708 }
709
710 // Inner_data
711 if (inner_size >= 1)
712 {
713 inner_data = buf;
714 buf += inner_size;
715 size -= inner_size;
716 }
717
718 if (a->PlainTextMode == false)
719 {
720 // Verify packet integrity
721 if (a->Version == 1)
722 {
723 UINT pad_size;
724
725 if (size < UDP_ACCELERATION_PACKET_IV_SIZE_V1)
726 {
727 return false;
728 }
729
730 pad_size = size - UDP_ACCELERATION_PACKET_IV_SIZE_V1;
731 buf += pad_size;
732 size -= pad_size;
733
734 if (size != UDP_ACCELERATION_PACKET_IV_SIZE_V1)
735 {
736 return NULL;
737 }
738
739 if (IsZero(buf, UDP_ACCELERATION_PACKET_IV_SIZE_V1) == false)
740 {
741 return NULL;
742 }
743 }
744 }
745
746 if (my_tick < a->LastRecvYourTick)
747 {
748 if ((a->LastRecvYourTick - my_tick) >= ((UINT64)UDP_ACCELERATION_WINDOW_SIZE_MSEC))
749 {
750 return NULL;
751 }
752 }
753
754 a->LastRecvMyTick = MAX(a->LastRecvMyTick, your_tick);
755 a->LastRecvYourTick = MAX(a->LastRecvYourTick, my_tick);
756
757 if (inner_size >= 1)
758 {
759 b = NewBlock(Clone(inner_data, inner_size), inner_size, a->ReadRawFlagMode == false ? (compress_flag ? -1 : 0) : 0);
760 if (a->ReadRawFlagMode)
761 {
762 b->RawFlagRetUdpAccel = raw_flag;
763 }
764 }
765
766 if (a->LastSetSrcIpAndPortTick < a->LastRecvYourTick)
767 {
768 a->LastSetSrcIpAndPortTick = a->LastRecvYourTick;
769
770 Copy(&a->YourIp, src_ip, sizeof(IP));
771 a->YourPort = src_port;
772 }
773
774 if (a->LastRecvMyTick != 0)
775 {
776 if ((a->LastRecvMyTick + (UINT64)(UDP_ACCELERATION_WINDOW_SIZE_MSEC)) >= a->Now)
777 {
778 a->LastRecvTick = a->Now;
779
780 a->IsReachedOnce = true;
781
782 if (a->FirstStableReceiveTick == 0)
783 {
784 a->FirstStableReceiveTick = a->Now;
785 }
786 }
787 }
788
789 return b;
790 }
791
792 // Calculate V1 key
UdpAccelCalcKeyV1(UCHAR * key,UCHAR * common_key,UCHAR * iv)793 void UdpAccelCalcKeyV1(UCHAR *key, UCHAR *common_key, UCHAR *iv)
794 {
795 UCHAR tmp[UDP_ACCELERATION_COMMON_KEY_SIZE_V1 + UDP_ACCELERATION_PACKET_IV_SIZE_V1];
796 // Validate arguments
797 if (key == NULL || common_key == NULL || iv == NULL)
798 {
799 return;
800 }
801
802 Copy(tmp, common_key, UDP_ACCELERATION_COMMON_KEY_SIZE_V1);
803 Copy(tmp + UDP_ACCELERATION_COMMON_KEY_SIZE_V1, iv, UDP_ACCELERATION_PACKET_IV_SIZE_V1);
804
805 Sha1(key, tmp, sizeof(tmp));
806 }
807
808 // Set the current time
UdpAccelSetTick(UDP_ACCEL * a,UINT64 tick64)809 void UdpAccelSetTick(UDP_ACCEL *a, UINT64 tick64)
810 {
811 // Validate arguments
812 if (a == NULL)
813 {
814 return;
815 }
816
817 a->Now = tick64;
818 }
819
820 // Initialize the server-side
UdpAccelInitServer(UDP_ACCEL * a,UCHAR * key,IP * detected_ip,IP * reported_ip,USHORT port)821 bool UdpAccelInitServer(UDP_ACCEL *a, UCHAR *key, IP *detected_ip, IP *reported_ip, USHORT port)
822 {
823 // Validate arguments
824 if (a == NULL || key == NULL || detected_ip == NULL || port == 0)
825 {
826 return false;
827 }
828
829 Debug("UdpAccelInitServer(): Version: %u, detected_ip: %r, reported_ip: %r, port: %hu, YourCookie: %u, MyCookie: %u\n",
830 a->Version, detected_ip, reported_ip, port, a->YourCookie, a->MyCookie);
831
832 if (IsIP6(detected_ip) != a->IsIPv6)
833 {
834 return false;
835 }
836
837 if (a->Version > 1)
838 {
839 a->CipherEncrypt = NewCipher("ChaCha20-Poly1305");
840 a->CipherDecrypt = NewCipher("ChaCha20-Poly1305");
841
842 SetCipherKey(a->CipherEncrypt, a->MyKey_V2, true);
843 SetCipherKey(a->CipherDecrypt, key, false);
844 }
845 else
846 {
847 Copy(a->YourKey, key, sizeof(a->YourKey));
848 }
849
850 Copy(&a->YourIp, detected_ip, sizeof(a->YourIp));
851 Copy(&a->YourIpReported, reported_ip, sizeof(a->YourIpReported));
852
853 a->YourPort = a->YourPortReported = port;
854
855 a->Now = Tick64();
856
857 a->Inited = true;
858
859 return true;
860 }
861
862 // Initialize the client-side
UdpAccelInitClient(UDP_ACCEL * a,UCHAR * key,IP * detected_ip,IP * reported_ip,USHORT port,UINT cookie,UINT my_cookie)863 bool UdpAccelInitClient(UDP_ACCEL *a, UCHAR *key, IP *detected_ip, IP *reported_ip, USHORT port, UINT cookie, UINT my_cookie)
864 {
865 // Validate arguments
866 if (a == NULL || key == NULL || detected_ip == NULL || port == 0)
867 {
868 return false;
869 }
870
871 Debug("UdpAccelInitClient(): Version: %u, detected_ip: %s, reported_ip: %s, port: %hu, cookie: %u, my_cookie: %u\n",
872 a->Version, detected_ip, reported_ip, port, cookie, my_cookie);
873
874 if (IsIP6(detected_ip) != a->IsIPv6)
875 {
876 return false;
877 }
878
879 if (a->Version > 1)
880 {
881 a->CipherEncrypt = NewCipher("ChaCha20-Poly1305");
882 a->CipherDecrypt = NewCipher("ChaCha20-Poly1305");
883
884 SetCipherKey(a->CipherEncrypt, a->MyKey_V2, true);
885 SetCipherKey(a->CipherDecrypt, key, false);
886 }
887 else
888 {
889 Copy(a->YourKey, key, sizeof(a->YourKey));
890 }
891
892 Copy(&a->YourIp, detected_ip, sizeof(a->YourIp));
893 Copy(&a->YourIpReported, reported_ip, sizeof(a->YourIpReported));
894
895 a->YourPort = a->YourPortReported = port;
896
897 a->Now = Tick64();
898
899 a->MyCookie = my_cookie;
900 a->YourCookie = cookie;
901
902 a->Inited = true;
903
904 return true;
905 }
906
907 // Create a new UDP acceleration function
NewUdpAccel(CEDAR * cedar,IP * ip,bool client_mode,bool random_port,bool no_nat_t)908 UDP_ACCEL *NewUdpAccel(CEDAR *cedar, IP *ip, bool client_mode, bool random_port, bool no_nat_t)
909 {
910 UDP_ACCEL *a;
911 SOCK *s;
912 UINT max_udp_size;
913 bool is_in_cedar_port_list = false;
914
915 if (IsZeroIP(ip))
916 {
917 ip = NULL;
918 }
919
920 if (client_mode || random_port)
921 {
922 // Use a appropriate vacant port number in the case of using random port or client mode
923 s = NewUDPEx3(0, ip);
924 }
925 else
926 {
927 // Specify in the range in the case of server mode
928 UINT i;
929 s = NULL;
930
931 LockList(cedar->UdpPortList);
932 {
933 for (i = UDP_SERVER_PORT_LOWER;i <= UDP_SERVER_PORT_HIGHER;i++)
934 {
935 if (IsIntInList(cedar->UdpPortList, i) == false)
936 {
937 s = NewUDPEx3(i, ip);
938
939 if (s != NULL)
940 {
941 is_in_cedar_port_list = true;
942 break;
943 }
944 }
945 }
946
947 if (s == NULL)
948 {
949 // Leave the port selection to the OS because the available port is not found within the range
950 s = NewUDPEx3(0, ip);
951 }
952
953 if (s != NULL && is_in_cedar_port_list)
954 {
955 AddIntDistinct(cedar->UdpPortList, i);
956 }
957 }
958 UnlockList(cedar->UdpPortList);
959 }
960
961 if (s == NULL)
962 {
963 return NULL;
964 }
965
966 a = ZeroMalloc(sizeof(UDP_ACCEL));
967
968 a->Cedar = cedar;
969 AddRef(a->Cedar->ref);
970
971 a->NoNatT = no_nat_t;
972
973 a->Version = 1;
974
975 a->NatT_TranId = Rand64();
976
977 a->CreatedTick = Tick64();
978
979 a->IsInCedarPortList = is_in_cedar_port_list;
980
981 a->ClientMode = client_mode;
982
983 a->Now = Tick64();
984 a->UdpSock = s;
985
986 Rand(a->MyKey, sizeof(a->MyKey));
987 Rand(a->MyKey_V2, sizeof(a->MyKey_V2));
988
989 Copy(&a->MyIp, ip, sizeof(a->MyIp));
990 a->MyPort = s->LocalPort;
991
992 a->IsIPv6 = IsIP6(ip);
993
994 if (a->IsIPv6)
995 {
996 a->NoNatT = true;
997 }
998
999 a->RecvBlockQueue = NewQueue();
1000
1001 Rand(a->NextIv, sizeof(a->NextIv));
1002 Rand(a->NextIv_V2, sizeof(a->NextIv_V2));
1003
1004 do
1005 {
1006 a->MyCookie = Rand32();
1007 }
1008 while (a->MyCookie == 0);
1009
1010 do
1011 {
1012 a->YourCookie = Rand32();
1013 }
1014 while (a->MyCookie == 0 || a->MyCookie == a->YourCookie);
1015
1016 // Calculate the maximum transmittable UDP packet size
1017 max_udp_size = MTU_FOR_PPPOE;
1018
1019 if (a->IsIPv6 == false)
1020 {
1021 // IPv4
1022 max_udp_size -= 20;
1023 }
1024 else
1025 {
1026 // IPv6
1027 max_udp_size -= 40;
1028 }
1029
1030 // UDP
1031 max_udp_size -= 8;
1032
1033 a->MaxUdpPacketSize = max_udp_size;
1034
1035 Debug("Udp Accel My Port = %u\n", a->MyPort);
1036
1037 // Initialize the NAT-T server IP address acquisition thread
1038 a->NatT_Lock = NewLock();
1039 a->NatT_HaltEvent = NewEvent();
1040
1041 if (a->NoNatT == false)
1042 {
1043 a->NatT_GetIpThread = NewThread(NatT_GetIpThread, a);
1044 }
1045
1046 return a;
1047 }
1048
1049 // NAT-T server IP address acquisition thread
NatT_GetIpThread(THREAD * thread,void * param)1050 void NatT_GetIpThread(THREAD *thread, void *param)
1051 {
1052 UDP_ACCEL *a;
1053 char hostname[MAX_SIZE];
1054 static IP dummy_ip = {0};
1055 UINT num_retry = 0;
1056 // Validate arguments
1057 if (thread == NULL || param == NULL)
1058 {
1059 return;
1060 }
1061
1062 a = (UDP_ACCEL *)param;
1063
1064 if (IsZeroIP(&dummy_ip))
1065 {
1066 SetIP(&dummy_ip, 11, Rand8(), Rand8(), Rand8());
1067 }
1068
1069 RUDPGetRegisterHostNameByIP(hostname, sizeof(hostname), &dummy_ip);
1070
1071 while (a->NatT_Halt == false)
1072 {
1073 IP ip;
1074 UINT wait_time = UDP_NAT_T_GET_IP_INTERVAL;
1075
1076 // Get the IP address
1077 bool ret = GetIP4Ex(&ip, hostname, 0, &a->NatT_Halt);
1078
1079 if (ret && (IsZeroIp(&ip) == false))
1080 {
1081 char tmp[128];
1082
1083 // Success to get
1084 Lock(a->NatT_Lock);
1085 {
1086 Copy(&a->NatT_IP, &ip, sizeof(IP));
1087 }
1088 Unlock(a->NatT_Lock);
1089
1090 IPToStr(tmp, sizeof(tmp), &ip);
1091 Debug("NAT-T IP Address Resolved: %s = %s\n", hostname, tmp);
1092
1093 a->NatT_IP_Changed = true;
1094
1095 break;
1096 }
1097
1098 // Fail to get
1099 num_retry++;
1100
1101 wait_time = (UINT)(MIN((UINT64)UDP_NAT_T_GET_IP_INTERVAL * (UINT64)num_retry, (UINT64)UDP_NAT_T_GET_IP_INTERVAL_MAX));
1102
1103 Wait(a->NatT_HaltEvent, wait_time);
1104 }
1105 }
1106
1107 // Release the UDP acceleration function
FreeUdpAccel(UDP_ACCEL * a)1108 void FreeUdpAccel(UDP_ACCEL *a)
1109 {
1110 // Validate arguments
1111 if (a == NULL)
1112 {
1113 return;
1114 }
1115
1116 while (true)
1117 {
1118 BLOCK *b = GetNext(a->RecvBlockQueue);
1119
1120 if (b == NULL)
1121 {
1122 break;
1123 }
1124
1125 FreeBlock(b);
1126 }
1127
1128 ReleaseQueue(a->RecvBlockQueue);
1129
1130 ReleaseSock(a->UdpSock);
1131
1132 if (a->IsInCedarPortList)
1133 {
1134 LockList(a->Cedar->UdpPortList);
1135 {
1136 DelInt(a->Cedar->UdpPortList, a->MyPort);
1137 }
1138 UnlockList(a->Cedar->UdpPortList);
1139 }
1140
1141 // Release of NAT-T related
1142 a->NatT_Halt = true;
1143 Set(a->NatT_HaltEvent);
1144
1145 if (a->NatT_GetIpThread != NULL)
1146 {
1147 WaitThread(a->NatT_GetIpThread, INFINITE);
1148 ReleaseThread(a->NatT_GetIpThread);
1149 }
1150
1151 ReleaseEvent(a->NatT_HaltEvent);
1152 DeleteLock(a->NatT_Lock);
1153
1154 ReleaseCedar(a->Cedar);
1155
1156 FreeCipher(a->CipherEncrypt);
1157 FreeCipher(a->CipherDecrypt);
1158
1159 Free(a);
1160 }
1161