1 // SoftEther VPN Source Code - Developer Edition Master Branch
2 // Cedar Communication Module
3
4
5 // Virtual.c
6 // User-mode virtual host program
7
8 #include "Virtual.h"
9
10 #include "BridgeUnix.h"
11 #include "BridgeWin32.h"
12 #include "Connection.h"
13 #include "Hub.h"
14 #include "IPC.h"
15 #include "NativeStack.h"
16 #include "Server.h"
17
18 #include "Mayaqua/DNS.h"
19 #include "Mayaqua/FileIO.h"
20 #include "Mayaqua/Memory.h"
21 #include "Mayaqua/Object.h"
22 #include "Mayaqua/Str.h"
23 #include "Mayaqua/Tick64.h"
24
25 static UCHAR broadcast[6] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
26 static char v_vgs_hostname[256] = {0};
27
28 static char secure_nat_target_hostname[MAX_SIZE] = {0};
29
30 // Specify the destination host name to be used for connectivity testing in SecureNAT
NnSetSecureNatTargetHostname(char * name)31 void NnSetSecureNatTargetHostname(char *name)
32 {
33 // Validate arguments
34 if (name == NULL)
35 {
36 return;
37 }
38
39 StrCpy(secure_nat_target_hostname, sizeof(secure_nat_target_hostname), name);
40 }
41
42 // Delete the oldest NAT session if necessary
NnDeleteOldestNatSessionIfNecessary(NATIVE_NAT * t,UINT ip,UINT protocol)43 void NnDeleteOldestNatSessionIfNecessary(NATIVE_NAT *t, UINT ip, UINT protocol)
44 {
45 UINT current_num;
46 UINT max_sessions = 0;
47 // Validate arguments
48 if (t == NULL)
49 {
50 return;
51 }
52
53 if (t->v->HubOption != NULL)
54 {
55 HUB_OPTION *o = t->v->HubOption;
56
57 switch (protocol)
58 {
59 case NAT_TCP:
60 max_sessions = o->SecureNAT_MaxTcpSessionsPerIp;
61 break;
62
63 case NAT_UDP:
64 max_sessions = o->SecureNAT_MaxUdpSessionsPerIp;
65 break;
66
67 case NAT_ICMP:
68 max_sessions = o->SecureNAT_MaxIcmpSessionsPerIp;
69 break;
70 }
71 }
72
73 if (max_sessions == 0)
74 {
75 return;
76 }
77
78 current_num = NnGetNumNatEntriesPerIp(t, ip, protocol);
79
80 if (current_num >= max_sessions)
81 {
82 NnDeleteOldestNatSession(t, ip, protocol);
83 }
84 }
85
86 // Delete the oldest NAT session
NnDeleteOldestNatSession(NATIVE_NAT * t,UINT ip,UINT protocol)87 void NnDeleteOldestNatSession(NATIVE_NAT *t, UINT ip, UINT protocol)
88 {
89 NATIVE_NAT_ENTRY *e;
90 // Validate arguments
91 if (t == NULL)
92 {
93 return;
94 }
95
96 e = NnGetOldestNatEntryOfIp(t, ip, protocol);
97
98 if (e != NULL)
99 {
100 NnDeleteSession(t, e);
101 }
102 }
103
104 // Get the oldest NAT session
NnGetOldestNatEntryOfIp(NATIVE_NAT * t,UINT ip,UINT protocol)105 NATIVE_NAT_ENTRY *NnGetOldestNatEntryOfIp(NATIVE_NAT *t, UINT ip, UINT protocol)
106 {
107 UINT i;
108 NATIVE_NAT_ENTRY *oldest = NULL;
109 UINT64 oldest_tick = 0xFFFFFFFFFFFFFFFFULL;
110 // Validate arguments
111 if (t == NULL)
112 {
113 return NULL;
114 }
115
116 for (i = 0; i < LIST_NUM(t->NatTableForRecv->AllList); i++)
117 {
118 NATIVE_NAT_ENTRY *e = LIST_DATA(t->NatTableForRecv->AllList, i);
119
120 if (e->SrcIp == ip)
121 {
122 if (e->Protocol == protocol)
123 {
124 if (e->LastCommTime <= oldest_tick)
125 {
126 oldest_tick = e->LastCommTime;
127 oldest = e;
128 }
129 }
130 }
131 }
132
133 return oldest;
134 }
135
136 // Get the number of NAT sessions per IP address
NnGetNumNatEntriesPerIp(NATIVE_NAT * t,UINT src_ip,UINT protocol)137 UINT NnGetNumNatEntriesPerIp(NATIVE_NAT *t, UINT src_ip, UINT protocol)
138 {
139 UINT ret = 0;
140 UINT i;
141 // Validate arguments
142 if (t == NULL)
143 {
144 return 0;
145 }
146
147 for (i = 0; i < LIST_NUM(t->NatTableForRecv->AllList); i++)
148 {
149 NATIVE_NAT_ENTRY *e = LIST_DATA(t->NatTableForRecv->AllList, i);
150
151 if (e->SrcIp == src_ip)
152 {
153 if (e->Protocol == protocol)
154 {
155 ret++;
156 }
157 }
158 }
159
160 return ret;
161 }
162
163 // Delete the old NAT sessions
NnDeleteOldSessions(NATIVE_NAT * t)164 void NnDeleteOldSessions(NATIVE_NAT *t)
165 {
166 UINT i;
167 LIST *o;
168 UINT64 now;
169 // Validate arguments
170 if (t == NULL)
171 {
172 return;
173 }
174
175 o = NULL;
176 now = t->v->Now;
177
178 for (i = 0; i < LIST_NUM(t->NatTableForSend->AllList); i++)
179 {
180 NATIVE_NAT_ENTRY *e = LIST_DATA(t->NatTableForSend->AllList, i);
181 UINT64 timeout;
182
183 if (e->Status == NAT_TCP_CONNECTED || e->Status == NAT_TCP_ESTABLISHED)
184 {
185 timeout = e->LastCommTime + (UINT64)(e->Protocol == NAT_TCP ? t->v->NatTcpTimeout : t->v->NatUdpTimeout);
186 }
187 else
188 {
189 timeout = e->LastCommTime + (UINT64)NN_TIMEOUT_FOR_UNESTBALISHED_TCP;
190 }
191
192 if (timeout < now)
193 {
194 // Time-out occurs
195 if (o == NULL)
196 {
197 o = NewListFast(NULL);
198 }
199
200 Add(o, e);
201 }
202 }
203
204 if (o != NULL)
205 {
206 for (i = 0; i < LIST_NUM(o); i++)
207 {
208 NATIVE_NAT_ENTRY *e = LIST_DATA(o, i);
209
210 NnDeleteSession(t, e);
211 }
212
213 ReleaseList(o);
214 }
215 }
216
217 // Delete the NAT entry
NnDeleteSession(NATIVE_NAT * t,NATIVE_NAT_ENTRY * e)218 void NnDeleteSession(NATIVE_NAT *t, NATIVE_NAT_ENTRY *e)
219 {
220 // Validate arguments
221 if (t == NULL || e == NULL)
222 {
223 return;
224 }
225
226 switch (e->Protocol)
227 {
228 case NAT_TCP:
229 // Send a RST to the client side
230 SendTcp(t->v, e->DestIp, e->DestPort, e->SrcIp, e->SrcPort,
231 e->LastAck, e->LastSeq + (e->Status == NAT_TCP_CONNECTING ? 1 : 0), TCP_RST | TCP_ACK, 0, 0, NULL, 0);
232
233 NLog(t->v, "LH_NAT_TCP_DELETED", e->Id);
234 break;
235
236 case NAT_UDP:
237 NLog(t->v, "LH_NAT_UDP_DELETED", e->Id);
238 break;
239
240 case NAT_ICMP:
241 Debug("NAT ICMP %u Deleted.\n", e->Id);
242 break;
243 }
244
245 DeleteHash(t->NatTableForSend, e);
246 DeleteHash(t->NatTableForRecv, e);
247
248 Free(e);
249 }
250
251 // Poll the IP combining object
NnPollingIpCombine(NATIVE_NAT * t)252 void NnPollingIpCombine(NATIVE_NAT *t)
253 {
254 LIST *o;
255 UINT i;
256 // Validate arguments
257 if (t == NULL)
258 {
259 return;
260 }
261
262 // Discard the old combining object
263 o = NULL;
264 for (i = 0; i < LIST_NUM(t->IpCombine); i++)
265 {
266 IP_COMBINE *c = LIST_DATA(t->IpCombine, i);
267
268 if (c->Expire < t->v->Now)
269 {
270 if (o == NULL)
271 {
272 o = NewListFast(NULL);
273 }
274 Add(o, c);
275 }
276 }
277
278 if (o != NULL)
279 {
280 for (i = 0; i < LIST_NUM(o); i++)
281 {
282 IP_COMBINE *c = LIST_DATA(o, i);
283
284 // Remove from the list
285 Delete(t->IpCombine, c);
286
287 // Release the memory
288 NnFreeIpCombine(t, c);
289 }
290 ReleaseList(o);
291 }
292 }
293
294 // Combine the IP packet received to the IP combining object
NnCombineIp(NATIVE_NAT * t,IP_COMBINE * c,UINT offset,void * data,UINT size,bool last_packet,UCHAR * head_ip_header_data,UINT head_ip_header_size)295 void NnCombineIp(NATIVE_NAT *t, IP_COMBINE *c, UINT offset, void *data, UINT size, bool last_packet, UCHAR *head_ip_header_data, UINT head_ip_header_size)
296 {
297 UINT i;
298 IP_PART *p;
299 UINT need_size;
300 UINT data_size_delta;
301 // Validate arguments
302 if (c == NULL || data == NULL)
303 {
304 return;
305 }
306
307 // Check the size and offset
308 if ((offset + size) > 65535)
309 {
310 // Do not process a packet larger than 64Kbytes
311 return;
312 }
313
314 if (last_packet == false && c->Size != 0)
315 {
316 if ((offset + size) > c->Size)
317 {
318 // Do not process a packet larger than the packet size
319 return;
320 }
321 }
322
323 if (head_ip_header_data != NULL && head_ip_header_size >= sizeof(IPV4_HEADER))
324 {
325 if (c->HeadIpHeaderData == NULL)
326 {
327 c->HeadIpHeaderData = Clone(head_ip_header_data, head_ip_header_size);
328 c->HeadIpHeaderDataSize = head_ip_header_size;
329 }
330 }
331
332 need_size = offset + size;
333 data_size_delta = c->DataReserved;
334 // Ensure sufficient if the buffer is insufficient
335 while (c->DataReserved < need_size)
336 {
337 c->DataReserved = c->DataReserved * 4;
338 c->Data = ReAlloc(c->Data, c->DataReserved);
339 }
340 data_size_delta = c->DataReserved - data_size_delta;
341 t->CurrentIpQuota += data_size_delta;
342
343 // Overwrite the data into the buffer
344 Copy(((UCHAR *)c->Data) + offset, data, size);
345
346 if (last_packet)
347 {
348 // If No More Fragment packet arrives, the size of this datagram is finalized
349 c->Size = offset + size;
350 }
351
352 // Check the overlap between the region which is represented by the offset and size of the
353 // existing received list and the region which is represented by the offset and size
354 for (i = 0; i < LIST_NUM(c->IpParts); i++)
355 {
356 UINT moving_size;
357 IP_PART *p = LIST_DATA(c->IpParts, i);
358
359 // Check the overlapping between the existing area and head area
360 if ((p->Offset <= offset) && ((p->Offset + p->Size) > offset))
361 {
362 // Compress behind the offset of this packet since a duplication is
363 // found in the first part with the existing packet and this packet
364
365 if ((offset + size) <= (p->Offset + p->Size))
366 {
367 // This packet is buried in the existing packet
368 size = 0;
369 }
370 else
371 {
372 // Retral region is not overlapped
373 moving_size = p->Offset + p->Size - offset;
374 offset += moving_size;
375 size -= moving_size;
376 }
377 }
378 if ((p->Offset < (offset + size)) && ((p->Offset + p->Size) >= (offset + size)))
379 {
380 // Compress the size of this packet forward because a duplication is
381 // found between the posterior portion the existing packet and this packet
382
383 moving_size = p->Offset + p->Size - offset - size;
384 size -= moving_size;
385 }
386
387 if ((p->Offset >= offset) && ((p->Offset + p->Size) <= (offset + size)))
388 {
389 // This packet was overwritten to completely hunched over a existing packet
390 p->Size = 0;
391 }
392 }
393
394 if (size != 0)
395 {
396 // Register this packet
397 p = ZeroMalloc(sizeof(IP_PART));
398
399 p->Offset = offset;
400 p->Size = size;
401
402 Add(c->IpParts, p);
403 }
404
405 if (c->Size != 0)
406 {
407 // Get the total size of the data portion list already received
408 UINT total_size = 0;
409 UINT i;
410
411 for (i = 0; i < LIST_NUM(c->IpParts); i++)
412 {
413 IP_PART *p = LIST_DATA(c->IpParts, i);
414
415 total_size += p->Size;
416 }
417
418 if (total_size == c->Size)
419 {
420 // Received whole of the IP packet
421 //Debug("Combine: %u\n", total_size);
422 NnIpReceived(t, c->SrcIP, c->DestIP, c->Protocol, c->Data, c->Size, c->Ttl,
423 c->HeadIpHeaderData, c->HeadIpHeaderDataSize, c->MaxL3Size);
424
425 // Release the combining object
426 NnFreeIpCombine(t, c);
427
428 // Remove from the combining object list
429 Delete(t->IpCombine, c);
430 }
431 }
432 }
433
434 // Release the IP combining object
NnFreeIpCombine(NATIVE_NAT * t,IP_COMBINE * c)435 void NnFreeIpCombine(NATIVE_NAT *t, IP_COMBINE *c)
436 {
437 UINT i;
438 // Validate arguments
439 if (c == NULL)
440 {
441 return;
442 }
443
444 // Release the data
445 t->CurrentIpQuota -= c->DataReserved;
446 Free(c->Data);
447
448 // Release the partial list
449 for (i = 0; i < LIST_NUM(c->IpParts); i++)
450 {
451 IP_PART *p = LIST_DATA(c->IpParts, i);
452
453 Free(p);
454 }
455
456 Free(c->HeadIpHeaderData);
457
458 ReleaseList(c->IpParts);
459 Free(c);
460 }
461
462 // Search the IP combining list
NnSearchIpCombine(NATIVE_NAT * t,UINT src_ip,UINT dest_ip,USHORT id,UCHAR protocol)463 IP_COMBINE *NnSearchIpCombine(NATIVE_NAT *t, UINT src_ip, UINT dest_ip, USHORT id, UCHAR protocol)
464 {
465 IP_COMBINE *c, tt;
466 // Validate arguments
467 if (t == NULL)
468 {
469 return NULL;
470 }
471
472 tt.DestIP = dest_ip;
473 tt.SrcIP = src_ip;
474 tt.Id = id;
475 tt.Protocol = protocol;
476
477 c = Search(t->IpCombine, &tt);
478
479 return c;
480 }
481
482 // Insert by creating a new object to the IP combining list
NnInsertIpCombine(NATIVE_NAT * t,UINT src_ip,UINT dest_ip,USHORT id,UCHAR protocol,bool mac_broadcast,UCHAR ttl,bool src_is_localmac)483 IP_COMBINE *NnInsertIpCombine(NATIVE_NAT *t, UINT src_ip, UINT dest_ip, USHORT id, UCHAR protocol, bool mac_broadcast, UCHAR ttl, bool src_is_localmac)
484 {
485 IP_COMBINE *c;
486 // Validate arguments
487 if (t == NULL)
488 {
489 return NULL;
490 }
491
492 // Examine the quota
493 if ((t->CurrentIpQuota + IP_COMBINE_INITIAL_BUF_SIZE) > IP_COMBINE_WAIT_QUEUE_SIZE_QUOTA)
494 {
495 // IP packet can not be stored any more
496 return NULL;
497 }
498
499 c = ZeroMalloc(sizeof(IP_COMBINE));
500 c->SrcIsLocalMacAddr = src_is_localmac;
501 c->DestIP = dest_ip;
502 c->SrcIP = src_ip;
503 c->Id = id;
504 c->Expire = t->v->Now + (UINT64)IP_COMBINE_TIMEOUT;
505 c->Size = 0;
506 c->IpParts = NewList(NULL);
507 c->Protocol = protocol;
508 c->MacBroadcast = mac_broadcast;
509 c->Ttl = ttl;
510
511 // Secure the memory
512 c->DataReserved = IP_COMBINE_INITIAL_BUF_SIZE;
513 c->Data = Malloc(c->DataReserved);
514 t->CurrentIpQuota += c->DataReserved;
515
516 Insert(t->IpCombine, c);
517
518 return c;
519 }
520
521 // Initialize the IP combining list
NnInitIpCombineList(NATIVE_NAT * t)522 void NnInitIpCombineList(NATIVE_NAT *t)
523 {
524 // Validate arguments
525 if (t == NULL)
526 {
527 return;
528 }
529
530 t->IpCombine = NewList(CompareIpCombine);
531 }
532
533 // Release the IP combining list
NnFreeIpCombineList(NATIVE_NAT * t)534 void NnFreeIpCombineList(NATIVE_NAT *t)
535 {
536 UINT i;
537 // Validate arguments
538 if (t == NULL)
539 {
540 return;
541 }
542
543 for (i = 0; i < LIST_NUM(t->IpCombine); i++)
544 {
545 IP_COMBINE *c = LIST_DATA(t->IpCombine, i);
546
547 NnFreeIpCombine(t, c);
548 }
549
550 ReleaseList(t->IpCombine);
551 }
552
553 // A TCP packet is received
NnTcpReceived(NATIVE_NAT * t,UINT src_ip,UINT dest_ip,void * data,UINT size,UCHAR ttl,UINT max_l3_size)554 void NnTcpReceived(NATIVE_NAT *t, UINT src_ip, UINT dest_ip, void *data, UINT size, UCHAR ttl, UINT max_l3_size)
555 {
556 TCP_HEADER *tcp;
557 UCHAR *payload;
558 UINT payload_size;
559 UINT tcp_header_size;
560 // Validate arguments
561 if (t == NULL || data == NULL)
562 {
563 return;
564 }
565
566 // TCP header
567 if (size < sizeof(TCP_HEADER))
568 {
569 return;
570 }
571
572 tcp = (TCP_HEADER *)data;
573
574 // Get the TCP header size
575 tcp_header_size = TCP_GET_HEADER_SIZE(tcp) * 4;
576 if (size < tcp_header_size || tcp_header_size < sizeof(TCP_HEADER))
577 {
578 return;
579 }
580
581 // Payload
582 payload = ((UCHAR *)data) + tcp_header_size;
583 payload_size = size - tcp_header_size;
584
585 // Search the port from the NAT table
586 if (true)
587 {
588 NATIVE_NAT_ENTRY tt;
589 NATIVE_NAT_ENTRY *e;
590
591 NnSetNat(&tt, NAT_TCP, 0, 0, src_ip, Endian16(tcp->SrcPort), dest_ip, Endian16(tcp->DstPort));
592
593 e = SearchHash(t->NatTableForRecv, &tt);
594
595 if (e != NULL)
596 {
597 // Last communication time
598 e->LastCommTime = t->v->Now;
599 e->TotalRecv += (UINT64)size;
600
601 // Rewrite the TCP header
602 tcp->Checksum = 0;
603 tcp->DstPort = Endian16(e->SrcPort);
604
605 if (tcp->Flag & TCP_FIN || tcp->Flag & TCP_RST)
606 {
607 // Disconnect
608 e->Status = NAT_TCP_WAIT_DISCONNECT;
609 }
610
611 if (tcp->Flag & TCP_SYN && tcp->Flag & TCP_ACK)
612 {
613 // Connection complete
614 if (e->Status != NAT_TCP_WAIT_DISCONNECT)
615 {
616 e->Status = NAT_TCP_ESTABLISHED;
617 }
618 }
619
620 e->LastSeq = Endian32(tcp->AckNumber);
621 e->LastAck = Endian32(tcp->SeqNumber);
622
623 // Checksum recalculation
624 tcp->Checksum = CalcChecksumForIPv4(src_ip, e->SrcIp, IP_PROTO_TCP, tcp, size, 0);
625
626 // IP transmission
627 SendIp(t->v, e->SrcIp, src_ip, IP_PROTO_TCP, tcp, size);
628 }
629 }
630 }
631
632 // An ICMP packet has been received
NnIcmpReceived(NATIVE_NAT * t,UINT src_ip,UINT dest_ip,void * data,UINT size,UCHAR ttl,UINT max_l3_size)633 void NnIcmpReceived(NATIVE_NAT *t, UINT src_ip, UINT dest_ip, void *data, UINT size, UCHAR ttl, UINT max_l3_size)
634 {
635 ICMP_HEADER *icmp;
636 // Validate arguments
637 if (t == NULL || data == NULL)
638 {
639 return;
640 }
641 if (ttl == 0)
642 {
643 ttl = 1;
644 }
645
646 // ICMP header
647 if (size < sizeof(ICMP_HEADER))
648 {
649 return;
650 }
651
652 icmp = (ICMP_HEADER *)data;
653
654 if (icmp->Type == ICMP_TYPE_ECHO_RESPONSE)
655 {
656 UCHAR *payload;
657 UINT payload_size;
658 ICMP_ECHO *echo;
659 NATIVE_NAT_ENTRY tt, *e;
660
661 // Echo Response
662 echo = (ICMP_ECHO *)(((UCHAR *)data) + sizeof(ICMP_HEADER));
663
664 if (size < (sizeof(ICMP_HEADER) + sizeof(ICMP_ECHO)))
665 {
666 return;
667 }
668
669 payload = ((UCHAR *)data) + sizeof(ICMP_HEADER) + sizeof(ICMP_ECHO);
670 payload_size = size - (sizeof(ICMP_HEADER) + sizeof(ICMP_ECHO));
671
672 // Search the NAT
673 NnSetNat(&tt, NAT_ICMP, 0, 0, 0, 0, dest_ip, Endian16(echo->Identifier));
674
675 e = SearchHash(t->NatTableForRecv, &tt);
676
677 if (e != NULL)
678 {
679 // Rewrite the header
680 icmp->Checksum = 0;
681 echo->Identifier = Endian16(e->SrcPort);
682 icmp->Checksum = IpChecksum(icmp, size);
683
684 e->LastCommTime = t->v->Now;
685 e->TotalRecv += (UINT64)size;
686
687 // Transmission
688 SendIpEx(t->v, e->SrcIp, src_ip, IP_PROTO_ICMPV4, icmp, size, MAX(ttl - 1, 1));
689 }
690 }
691 else if (icmp->Type == ICMP_TYPE_ECHO_REQUEST)
692 {
693 UCHAR *payload;
694 UINT payload_size;
695 ICMP_ECHO *echo;
696
697 // Echo Response
698 echo = (ICMP_ECHO *)(((UCHAR *)data) + sizeof(ICMP_HEADER));
699
700 if (size < (sizeof(ICMP_HEADER) + sizeof(ICMP_ECHO)))
701 {
702 return;
703 }
704
705 payload = ((UCHAR *)data) + sizeof(ICMP_HEADER) + sizeof(ICMP_ECHO);
706 payload_size = size - (sizeof(ICMP_HEADER) + sizeof(ICMP_ECHO));
707
708 if (dest_ip == t->PublicIP)
709 {
710 // Respond as soon as the Echo Request is received at the public side interface
711 ICMP_HEADER *ret_icmp;
712 ICMP_ECHO *ret_echo;
713 UINT ret_size = sizeof(ICMP_HEADER) + sizeof(ICMP_ECHO) + payload_size;
714
715 ret_icmp = ZeroMalloc(ret_size);
716 ret_echo = (ICMP_ECHO *)(((UCHAR *)ret_icmp) + sizeof(ICMP_HEADER));
717
718 ret_icmp->Type = ICMP_TYPE_ECHO_RESPONSE;
719 ret_icmp->Code = icmp->Code;
720
721 ret_echo->Identifier = echo->Identifier;
722 ret_echo->SeqNo = echo->SeqNo;
723
724 Copy((UCHAR *)ret_icmp + sizeof(ICMP_HEADER) + sizeof(ICMP_ECHO),
725 payload, payload_size);
726
727 ret_icmp->Checksum = IpChecksum(ret_icmp, ret_size);
728
729 NnIpSendForInternet(t, IP_PROTO_ICMPV4, 0, dest_ip, src_ip, ret_icmp, ret_size, max_l3_size);
730
731 Free(ret_icmp);
732 }
733 }
734 else
735 {
736 if (icmp->Type == ICMP_TYPE_DESTINATION_UNREACHABLE || icmp->Type == ICMP_TYPE_TIME_EXCEEDED)
737 {
738 // Rewrite the Src IP of the IPv4 header of the ICMP response packet
739 if (size >= (sizeof(ICMP_HEADER) + sizeof(ICMP_ECHO) + sizeof(IPV4_HEADER)))
740 {
741 IPV4_HEADER *orig_ipv4 = (IPV4_HEADER *)(((UCHAR *)data) + sizeof(ICMP_HEADER) + sizeof(ICMP_ECHO));
742 UINT orig_ipv4_size = size - (sizeof(ICMP_HEADER) + sizeof(ICMP_ECHO));
743
744 UINT orig_ipv4_header_size = GetIpHeaderSize((UCHAR *)orig_ipv4, orig_ipv4_size);
745
746 if (orig_ipv4_header_size >= sizeof(IPV4_HEADER) && orig_ipv4_size >= orig_ipv4_header_size)
747 {
748 if (orig_ipv4->Protocol == IP_PROTO_ICMPV4)
749 {
750 // Search the inner ICMP header
751 UINT inner_icmp_size = orig_ipv4_size - orig_ipv4_header_size;
752
753 if (inner_icmp_size >= (sizeof(ICMP_HEADER) + sizeof(ICMP_ECHO)))
754 {
755 ICMP_HEADER *inner_icmp = (ICMP_HEADER *)(((UCHAR *)data) +
756 sizeof(ICMP_HEADER) + sizeof(ICMP_ECHO) + orig_ipv4_header_size);
757
758 if (inner_icmp->Type == ICMP_TYPE_ECHO_REQUEST)
759 {
760 ICMP_ECHO *inner_echo = (ICMP_ECHO *)(((UCHAR *)inner_icmp) + sizeof(ICMP_HEADER));
761 NATIVE_NAT_ENTRY tt, *e;
762
763 // Search for the existing NAT table entry
764 NnSetNat(&tt, NAT_ICMP, 0, 0, 0, 0, orig_ipv4->SrcIP, Endian16(inner_echo->Identifier));
765
766 e = SearchHash(t->NatTableForRecv, &tt);
767
768 if (e != NULL)
769 {
770 e->LastCommTime = t->v->Now;
771
772 // Rewrite the inner IP packet and the ICMP header according to the NAT table
773 inner_echo->Identifier = Endian16(e->SrcPort);
774 inner_icmp->Checksum = 0;
775
776 orig_ipv4->SrcIP = e->SrcIp;
777
778 orig_ipv4->Checksum = 0;
779 orig_ipv4->Checksum = IpChecksum(orig_ipv4, orig_ipv4_header_size);
780
781 // Rewrite the outer ICMP header
782 if (true)
783 {
784 UCHAR *payload;
785 UINT payload_size;
786 ICMP_ECHO *echo;
787
788 // Echo Response
789 echo = (ICMP_ECHO *)(((UCHAR *)data) + sizeof(ICMP_HEADER));
790
791 if (size < (sizeof(ICMP_HEADER) + sizeof(ICMP_ECHO)))
792 {
793 return;
794 }
795
796 payload = ((UCHAR *)data) + sizeof(ICMP_HEADER) + sizeof(ICMP_ECHO);
797 payload_size = size - (sizeof(ICMP_HEADER) + sizeof(ICMP_ECHO));
798
799 // Rewrite the header
800 icmp->Checksum = 0;
801 echo->Identifier = Endian16(e->SrcPort);
802 icmp->Checksum = IpChecksum(icmp, size);
803
804 // Transmission
805 SendIpEx(t->v, e->SrcIp, src_ip, IP_PROTO_ICMPV4, icmp, size, MAX(ttl - 1, 1));
806 }
807 }
808 }
809 }
810 }
811 }
812 }
813 }
814 }
815 }
816
817 // An UDP packet has been received
NnUdpReceived(NATIVE_NAT * t,UINT src_ip,UINT dest_ip,void * data,UINT size,UCHAR ttl,UINT max_l3_size)818 void NnUdpReceived(NATIVE_NAT *t, UINT src_ip, UINT dest_ip, void *data, UINT size, UCHAR ttl, UINT max_l3_size)
819 {
820 UDP_HEADER *udp;
821 UCHAR *payload;
822 UINT payload_size;
823 // Validate arguments
824 if (t == NULL || data == NULL)
825 {
826 return;
827 }
828
829 // UDP header
830 if (size <= sizeof(UDP_HEADER))
831 {
832 return;
833 }
834
835 udp = (UDP_HEADER *)data;
836
837 // Payload
838 payload = ((UCHAR *)data) + sizeof(UDP_HEADER);
839 payload_size = size - sizeof(UDP_HEADER);
840
841 // Inspect the payload size
842 if (payload_size < (Endian16(udp->PacketLength) - sizeof(UDP_HEADER)))
843 {
844 return;
845 }
846
847 // Truncate the payload
848 payload_size = Endian16(udp->PacketLength) - sizeof(UDP_HEADER);
849
850 // Search the port number from the NAT table
851 if (true)
852 {
853 NATIVE_NAT_ENTRY tt;
854 NATIVE_NAT_ENTRY *e;
855
856 NnSetNat(&tt, NAT_UDP, 0, 0, 0, 0, dest_ip, Endian16(udp->DstPort));
857
858 e = SearchHash(t->NatTableForRecv, &tt);
859
860 if (e != NULL)
861 {
862 // Last communication time
863 e->LastCommTime = t->v->Now;
864 e->TotalRecv += (UINT64)payload_size;
865
866 // Deliver to the client by rewriting the port number
867 SendUdp(t->v, e->SrcIp, e->SrcPort, src_ip, Endian16(udp->SrcPort),
868 payload, payload_size);
869 }
870 }
871 }
872
873 // A combined IP packet is received
NnIpReceived(NATIVE_NAT * t,UINT src_ip,UINT dest_ip,UINT protocol,void * data,UINT size,UCHAR ttl,UCHAR * ip_header,UINT ip_header_size,UINT max_l3_size)874 void NnIpReceived(NATIVE_NAT *t, UINT src_ip, UINT dest_ip, UINT protocol, void *data, UINT size,
875 UCHAR ttl, UCHAR *ip_header, UINT ip_header_size, UINT max_l3_size)
876 {
877 // Validate arguments
878 if (t == NULL || data == NULL)
879 {
880 return;
881 }
882
883 if (dest_ip != t->PublicIP)
884 {
885 // Destination IP is not a unicast
886 return;
887 }
888
889 switch (protocol)
890 {
891 case IP_PROTO_UDP:
892 // UDP
893 NnUdpReceived(t, src_ip, dest_ip, data, size, ttl, max_l3_size);
894 break;
895
896 case IP_PROTO_TCP:
897 // TCP
898 NnTcpReceived(t, src_ip, dest_ip, data, size, ttl, max_l3_size);
899 break;
900
901 case IP_PROTO_ICMPV4:
902 // ICMP
903 NnIcmpReceived(t, src_ip, dest_ip, data, size, ttl, max_l3_size);
904 break;
905 }
906 }
907
908 // Received an IP packet
NnFragmentedIpReceived(NATIVE_NAT * t,PKT * packet)909 void NnFragmentedIpReceived(NATIVE_NAT *t, PKT *packet)
910 {
911 IPV4_HEADER *ip;
912 void *data;
913 UINT data_size_recved;
914 UINT size;
915 UINT ipv4_header_size;
916 bool last_packet = false;
917 UINT l3_size = 0;
918 UCHAR *head_ip_header_data = NULL;
919 UINT head_ip_header_size = 0;
920 // Validate arguments
921 if (t == NULL || packet == NULL)
922 {
923 return;
924 }
925
926 ip = packet->L3.IPv4Header;
927
928 // Get the size of the IPv4 header
929 ipv4_header_size = IPV4_GET_HEADER_LEN(packet->L3.IPv4Header) * 4;
930 head_ip_header_size = ipv4_header_size;
931
932 // Get the pointer to the data
933 data = ((UCHAR *)packet->L3.PointerL3) + ipv4_header_size;
934
935 // Get the data size
936 size = l3_size = Endian16(ip->TotalLength);
937 if (size <= ipv4_header_size)
938 {
939 // There is no data
940 return;
941 }
942 size -= ipv4_header_size;
943
944 // Get the size of data actually received
945 data_size_recved = packet->PacketSize - (ipv4_header_size + MAC_HEADER_SIZE);
946 if (data_size_recved < size)
947 {
948 // Data insufficient (It may be missing on the way)
949 return;
950 }
951
952 if (IPV4_GET_OFFSET(ip) == 0 && (IPV4_GET_FLAGS(ip) & 0x01) == 0)
953 {
954 // Because this packet has not been fragmented, it can be passed to the upper layer immediately
955 head_ip_header_data = (UCHAR *)packet->L3.IPv4Header;
956 NnIpReceived(t, ip->SrcIP, ip->DstIP, ip->Protocol, data, size, ip->TimeToLive,
957 head_ip_header_data, head_ip_header_size, l3_size);
958 }
959 else
960 {
961 // This packet is necessary to combine because it is fragmented
962 UINT offset = IPV4_GET_OFFSET(ip) * 8;
963 IP_COMBINE *c = NnSearchIpCombine(t, ip->SrcIP, ip->DstIP, Endian16(ip->Identification), ip->Protocol);
964
965 if (offset == 0)
966 {
967 head_ip_header_data = (UCHAR *)packet->L3.IPv4Header;
968 }
969
970 last_packet = ((IPV4_GET_FLAGS(ip) & 0x01) == 0 ? true : false);
971
972 if (c != NULL)
973 {
974 // It is the second or subsequent packet
975 c->MaxL3Size = MAX(c->MaxL3Size, l3_size);
976 NnCombineIp(t, c, offset, data, size, last_packet, head_ip_header_data, head_ip_header_size);
977 }
978 else
979 {
980 // Create a combining object because it is the first packet
981 c = NnInsertIpCombine(
982 t, ip->SrcIP, ip->DstIP, Endian16(ip->Identification), ip->Protocol, packet->BroadcastPacket,
983 ip->TimeToLive, false);
984 if (c != NULL)
985 {
986 c->MaxL3Size = MAX(c->MaxL3Size, l3_size);
987 NnCombineIp(t, c, offset, data, size, last_packet, head_ip_header_data, head_ip_header_size);
988 }
989 }
990 }
991 }
992
993 // Layer 2 packet processing
NnLayer2(NATIVE_NAT * t,PKT * packet)994 void NnLayer2(NATIVE_NAT *t, PKT *packet)
995 {
996 // Validate arguments
997 if (t == NULL || packet == NULL)
998 {
999 return;
1000 }
1001
1002 if (packet->TypeL3 == L3_IPV4)
1003 {
1004 // IPv4
1005 NnFragmentedIpReceived(t, packet);
1006 }
1007 }
1008
1009 // Extract the received packets of native NAT, and deliver it to the VPN client
NnPoll(NATIVE_NAT * t)1010 void NnPoll(NATIVE_NAT *t)
1011 {
1012 // Validate arguments
1013 if (t == NULL)
1014 {
1015 return;
1016 }
1017
1018 LockQueue(t->RecvQueue);
1019 {
1020 while (true)
1021 {
1022 PKT *pkt = GetNext(t->RecvQueue);
1023
1024 if (pkt == NULL)
1025 {
1026 break;
1027 }
1028
1029 NnLayer2(t, pkt);
1030
1031 FreePacketWithData(pkt);
1032 }
1033 }
1034 UnlockQueue(t->RecvQueue);
1035
1036 if (t->SendStateChanged)
1037 {
1038 TUBE *halt_tube = NULL;
1039
1040 Lock(t->Lock);
1041 {
1042 if (t->HaltTube != NULL)
1043 {
1044 halt_tube = t->HaltTube;
1045
1046 AddRef(halt_tube->Ref);
1047 }
1048 }
1049 Unlock(t->Lock);
1050
1051 if (halt_tube != NULL)
1052 {
1053 TubeFlushEx(halt_tube, true);
1054
1055 t->SendStateChanged = false;
1056
1057 ReleaseTube(halt_tube);
1058 }
1059 }
1060
1061 NnPollingIpCombine(t);
1062
1063 NnDeleteOldSessions(t);
1064 }
1065
1066 // Send a fragmented IP packet to the Internet
NnIpSendFragmentedForInternet(NATIVE_NAT * t,UCHAR ip_protocol,UINT src_ip,UINT dest_ip,USHORT id,USHORT total_size,USHORT offset,void * data,UINT size,UCHAR ttl)1067 void NnIpSendFragmentedForInternet(NATIVE_NAT *t, UCHAR ip_protocol, UINT src_ip, UINT dest_ip, USHORT id, USHORT total_size,
1068 USHORT offset, void *data, UINT size, UCHAR ttl)
1069 {
1070 UCHAR *buf;
1071 IPV4_HEADER *ip;
1072 BLOCK *b;
1073 // Validate arguments
1074 if (t == NULL || data == NULL)
1075 {
1076 return;
1077 }
1078
1079 // Memory allocation
1080 buf = Malloc(size + IP_HEADER_SIZE);
1081 ip = (IPV4_HEADER *)&buf[0];
1082
1083 // IP header construction
1084 ip->VersionAndHeaderLength = 0;
1085 IPV4_SET_VERSION(ip, 4);
1086 IPV4_SET_HEADER_LEN(ip, (IP_HEADER_SIZE / 4));
1087 ip->TypeOfService = DEFAULT_IP_TOS;
1088 ip->TotalLength = Endian16((USHORT)(size + IP_HEADER_SIZE));
1089 ip->Identification = Endian16(id);
1090 ip->FlagsAndFragmentOffset[0] = ip->FlagsAndFragmentOffset[1] = 0;
1091 IPV4_SET_OFFSET(ip, (offset / 8));
1092 if ((offset + size) >= total_size)
1093 {
1094 IPV4_SET_FLAGS(ip, 0x00);
1095 }
1096 else
1097 {
1098 IPV4_SET_FLAGS(ip, 0x01);
1099 }
1100 ip->TimeToLive = (ttl == 0 ? DEFAULT_IP_TTL : ttl);
1101 ip->Protocol = ip_protocol;
1102 ip->Checksum = 0;
1103 ip->SrcIP = src_ip;
1104 ip->DstIP = dest_ip;
1105
1106 // Checksum calculation
1107 ip->Checksum = IpChecksum(ip, IP_HEADER_SIZE);
1108
1109 // Data copy
1110 Copy(buf + IP_HEADER_SIZE, data, size);
1111
1112 // Transmission
1113 b = NewBlock(buf, size + IP_HEADER_SIZE, 0);
1114
1115 LockQueue(t->SendQueue);
1116 {
1117 if (t->SendQueue->num_item <= NN_MAX_QUEUE_LENGTH)
1118 {
1119 InsertQueue(t->SendQueue, b);
1120
1121 t->SendStateChanged = true;
1122 }
1123 else
1124 {
1125 FreeBlock(b);
1126 }
1127 }
1128 UnlockQueue(t->SendQueue);
1129 }
1130
1131 // Send an IP packet to the Internet
NnIpSendForInternet(NATIVE_NAT * t,UCHAR ip_protocol,UCHAR ttl,UINT src_ip,UINT dest_ip,void * data,UINT size,UINT max_l3_size)1132 void NnIpSendForInternet(NATIVE_NAT *t, UCHAR ip_protocol, UCHAR ttl, UINT src_ip, UINT dest_ip, void *data, UINT size, UINT max_l3_size)
1133 {
1134 UINT mss = 0;
1135 UCHAR *buf;
1136 USHORT offset;
1137 USHORT id;
1138 USHORT total_size;
1139 UINT size_of_this_packet;
1140 // Validate arguments
1141 if (t == NULL || data == NULL)
1142 {
1143 return;
1144 }
1145
1146 // Maximum segment size
1147 if (max_l3_size > IP_HEADER_SIZE)
1148 {
1149 mss = max_l3_size - IP_HEADER_SIZE;
1150 }
1151
1152 if (mss == 0)
1153 {
1154 mss = t->v->IpMss;
1155 }
1156
1157 mss = MAX(mss, 1000);
1158
1159 // Buffer
1160 buf = (UCHAR *)data;
1161
1162 // ID
1163 id = (t->NextId++);
1164
1165 // Total size
1166 total_size = (USHORT)size;
1167
1168 // Start to fragment
1169 offset = 0;
1170
1171 while (true)
1172 {
1173 bool last_packet = false;
1174 // Get the size of this packet
1175 size_of_this_packet = MIN((USHORT)mss, (total_size - offset));
1176 if ((offset + (USHORT)size_of_this_packet) == total_size)
1177 {
1178 last_packet = true;
1179 }
1180
1181 // Transmit the fragmented packet
1182 NnIpSendFragmentedForInternet(t, ip_protocol, src_ip, dest_ip, id, total_size, offset,
1183 buf + offset, size_of_this_packet, ttl);
1184 if (last_packet)
1185 {
1186 break;
1187 }
1188
1189 offset += (USHORT)size_of_this_packet;
1190 }
1191 }
1192
1193 // Communication of ICMP towards the Internet
NnIcmpEchoRecvForInternet(VH * v,UINT src_ip,UINT dest_ip,void * data,UINT size,UCHAR ttl,void * icmp_data,UINT icmp_size,UCHAR * ip_header,UINT ip_header_size,UINT max_l3_size)1194 void NnIcmpEchoRecvForInternet(VH *v, UINT src_ip, UINT dest_ip, void *data, UINT size, UCHAR ttl, void *icmp_data, UINT icmp_size, UCHAR *ip_header, UINT ip_header_size, UINT max_l3_size)
1195 {
1196 NATIVE_NAT_ENTRY tt;
1197 NATIVE_NAT_ENTRY *e;
1198 NATIVE_NAT *t;
1199 USHORT src_port;
1200 ICMP_HEADER *old_icmp_header;
1201 ICMP_ECHO *old_icmp_echo;
1202 ICMP_HEADER *icmp;
1203 ICMP_ECHO *echo;
1204 UCHAR *payload_data;
1205 UINT payload_size;
1206 // Validate arguments
1207 if (NnIsActive(v) == false || icmp_data == NULL)
1208 {
1209 return;
1210 }
1211
1212 t = v->NativeNat;
1213
1214 old_icmp_header = (ICMP_HEADER *)icmp_data;
1215 old_icmp_echo = (ICMP_ECHO *)(((UCHAR *)icmp_data) + sizeof(ICMP_HEADER));
1216
1217 if (size < (sizeof(ICMP_HEADER) + sizeof(ICMP_ECHO)))
1218 {
1219 return;
1220 }
1221
1222 payload_data = ((UCHAR *)icmp_data) + (sizeof(ICMP_HEADER) + sizeof(ICMP_ECHO));
1223 payload_size = icmp_size - (sizeof(ICMP_HEADER) + sizeof(ICMP_ECHO));
1224
1225 if (dest_ip == v->HostIP)
1226 {
1227 // Respond because it is addressed to me
1228 VirtualIcmpEchoSendResponse(v, dest_ip, src_ip, Endian16(old_icmp_echo->Identifier),
1229 Endian16(old_icmp_echo->SeqNo), payload_data, payload_size);
1230
1231 return;
1232 }
1233
1234 if (ttl <= 1)
1235 {
1236 // Reply the Time Exceeded immediately for the packet whose TTL is 1
1237 UINT reply_size = sizeof(ICMP_HEADER) + 4 + ip_header_size + 8;
1238 UCHAR *reply_data = ZeroMalloc(reply_size);
1239 ICMP_HEADER *icmp = (ICMP_HEADER *)reply_data;
1240 icmp->Type = ICMP_TYPE_TIME_EXCEEDED;
1241 icmp->Code = ICMP_CODE_TTL_EXCEEDED_IN_TRANSIT;
1242 Copy(reply_data + sizeof(ICMP_HEADER) + 4, ip_header, ip_header_size);
1243 Copy(reply_data + sizeof(ICMP_HEADER) + 4 + ip_header_size, icmp_data, MIN(icmp_size, 8));
1244
1245 icmp->Checksum = IpChecksum(icmp, reply_size);
1246
1247 SendIp(v, src_ip, v->HostIP, IP_PROTO_ICMPV4, reply_data, reply_size);
1248
1249 Free(reply_data);
1250
1251 return;
1252 }
1253
1254 src_port = Endian16(old_icmp_echo->Identifier);
1255
1256 // Search whether there is an existing session
1257 NnSetNat(&tt, NAT_ICMP, src_ip, src_port, 0, 0, 0, 0);
1258
1259 e = SearchHash(t->NatTableForSend, &tt);
1260
1261 if (e == NULL)
1262 {
1263 // Create a new session because there is no existing one
1264 UINT public_port;
1265
1266 if (CanCreateNewNatEntry(v) == false)
1267 {
1268 // Can not make any more
1269 return;
1270 }
1271
1272 NnDeleteOldestNatSessionIfNecessary(t, src_ip, NAT_ICMP);
1273
1274 // Get a free port
1275 public_port = NnMapNewPublicPort(t, NAT_ICMP, 0, 0, t->PublicIP);
1276 if (public_port == 0)
1277 {
1278 // There are no free ports
1279 return;
1280 }
1281
1282 e = ZeroMalloc(sizeof(NATIVE_NAT_ENTRY));
1283
1284 e->Status = NAT_TCP_ESTABLISHED;
1285
1286 e->HashCodeForSend = INFINITE;
1287 e->HashCodeForRecv = INFINITE;
1288 e->Id = Inc(v->Counter);
1289 e->Protocol = NAT_ICMP;
1290 e->SrcIp = src_ip;
1291 e->SrcPort = src_port;
1292 e->DestIp = 0;
1293 e->DestPort = 0;
1294 e->PublicIp = t->PublicIP;
1295 e->PublicPort = public_port;
1296
1297 e->CreatedTime = v->Now;
1298 e->LastCommTime = v->Now;
1299
1300 // Add to the list
1301 AddHash(t->NatTableForSend, e);
1302 AddHash(t->NatTableForRecv, e);
1303
1304 // Log
1305 if (true)
1306 {
1307 IP ip1, ip2;
1308 char s1[MAX_SIZE], s2[MAX_SIZE];
1309 UINTToIP(&ip1, src_ip);
1310 UINTToIP(&ip2, dest_ip);
1311 IPToStr(s1, 0, &ip1);
1312 IPToStr(s2, 0, &ip2);
1313
1314 Debug("ICMP Session %u: %s:0x%x -> %s:0x%x\n", e->Id, s1, src_port, s2, public_port);
1315 }
1316 }
1317
1318 // Rebuild the ICMP header
1319 icmp = ZeroMalloc(sizeof(ICMP_HEADER) + sizeof(ICMP_ECHO) + payload_size);
1320 icmp->Code = old_icmp_header->Code;
1321 icmp->Type = old_icmp_header->Type;
1322 icmp->Checksum = 0;
1323
1324 echo = (ICMP_ECHO *)(((UCHAR *)icmp) + sizeof(ICMP_HEADER));
1325 echo->SeqNo = old_icmp_echo->SeqNo;
1326 echo->Identifier = Endian16(e->PublicPort);
1327
1328 Copy(((UCHAR *)icmp) + sizeof(ICMP_HEADER) + sizeof(ICMP_ECHO), payload_data, payload_size);
1329
1330 icmp->Checksum = IpChecksum(icmp, sizeof(ICMP_HEADER) + sizeof(ICMP_ECHO) + payload_size);
1331
1332 e->TotalSent += (UINT64)payload_size;
1333 e->LastCommTime = v->Now;
1334
1335 // Send to the Internet
1336 NnIpSendForInternet(t, IP_PROTO_ICMPV4, ttl - 1, e->PublicIp, dest_ip, icmp, sizeof(ICMP_HEADER) + sizeof(ICMP_ECHO) + payload_size, max_l3_size);
1337
1338 Free(icmp);
1339 }
1340
1341 // Communication of UDP towards the Internet
NnUdpRecvForInternet(VH * v,UINT src_ip,UINT src_port,UINT dest_ip,UINT dest_port,void * data,UINT size,UINT max_l3_size)1342 void NnUdpRecvForInternet(VH *v, UINT src_ip, UINT src_port, UINT dest_ip, UINT dest_port, void *data, UINT size, UINT max_l3_size)
1343 {
1344 NATIVE_NAT_ENTRY tt;
1345 NATIVE_NAT_ENTRY *e;
1346 NATIVE_NAT *t;
1347 UDP_HEADER *udp;
1348 // Validate arguments
1349 if (NnIsActive(v) == false || data == NULL)
1350 {
1351 return;
1352 }
1353
1354 t = v->NativeNat;
1355
1356 // Search whether there is an existing session
1357 NnSetNat(&tt, NAT_UDP, src_ip, src_port, 0, 0, 0, 0);
1358
1359 e = SearchHash(t->NatTableForSend, &tt);
1360
1361 if (e == NULL)
1362 {
1363 // Create a new session because there is no existing one
1364 UINT public_port;
1365
1366 if (CanCreateNewNatEntry(v) == false)
1367 {
1368 // Can not make any more
1369 return;
1370 }
1371
1372 NnDeleteOldestNatSessionIfNecessary(t, src_ip, NAT_UDP);
1373
1374 // Get a free port
1375 public_port = NnMapNewPublicPort(t, NAT_UDP, 0, 0, t->PublicIP);
1376 if (public_port == 0)
1377 {
1378 // There are no free ports
1379 return;
1380 }
1381
1382 e = ZeroMalloc(sizeof(NATIVE_NAT_ENTRY));
1383
1384 e->Status = NAT_TCP_ESTABLISHED;
1385
1386 e->HashCodeForSend = INFINITE;
1387 e->HashCodeForRecv = INFINITE;
1388 e->Id = Inc(v->Counter);
1389 e->Protocol = NAT_UDP;
1390 e->SrcIp = src_ip;
1391 e->SrcPort = src_port;
1392 e->DestIp = 0;
1393 e->DestPort = 0;
1394 e->PublicIp = t->PublicIP;
1395 e->PublicPort = public_port;
1396
1397 e->CreatedTime = v->Now;
1398 e->LastCommTime = v->Now;
1399
1400 // Add to the list
1401 AddHash(t->NatTableForSend, e);
1402 AddHash(t->NatTableForRecv, e);
1403
1404 // Log
1405 if (true)
1406 {
1407 IP ip1, ip2;
1408 char s1[MAX_SIZE], s2[MAX_SIZE];
1409 UINTToIP(&ip1, src_ip);
1410 UINTToIP(&ip2, dest_ip);
1411 IPToStr(s1, 0, &ip1);
1412 IPToStr(s2, 0, &ip2);
1413
1414 NLog(v, "LH_NAT_UDP_CREATED", e->Id, s1, src_port, s2, dest_port);
1415 }
1416 }
1417
1418 // Rebuild the UDP header
1419 udp = ZeroMalloc(sizeof(UDP_HEADER) + size);
1420
1421 udp->SrcPort = Endian16(e->PublicPort);
1422 udp->DstPort = Endian16(dest_port);
1423 udp->PacketLength = Endian16((USHORT)sizeof(UDP_HEADER) + size);
1424
1425 Copy(((UCHAR *)udp) + sizeof(UDP_HEADER), data, size);
1426
1427 udp->Checksum = CalcChecksumForIPv4(e->PublicIp, dest_ip, IP_PROTO_UDP, udp, sizeof(UDP_HEADER) + size, 0);
1428
1429 e->TotalSent += (UINT64)size;
1430 e->LastCommTime = v->Now;
1431
1432 // Send to the Internet
1433 NnIpSendForInternet(t, IP_PROTO_UDP, 127, e->PublicIp, dest_ip, udp, sizeof(UDP_HEADER) + size, max_l3_size);
1434
1435 Free(udp);
1436 }
1437
1438 // Communication of TCP towards the Internet
NnTcpRecvForInternet(VH * v,UINT src_ip,UINT src_port,UINT dest_ip,UINT dest_port,TCP_HEADER * old_tcp,void * data,UINT size,UINT max_l3_size)1439 void NnTcpRecvForInternet(VH *v, UINT src_ip, UINT src_port, UINT dest_ip, UINT dest_port, TCP_HEADER *old_tcp, void *data, UINT size, UINT max_l3_size)
1440 {
1441 NATIVE_NAT_ENTRY tt;
1442 NATIVE_NAT_ENTRY *e;
1443 NATIVE_NAT *t;
1444 UINT tcp_header_size;
1445 TCP_HEADER *tcp;
1446 // Validate arguments
1447 if (NnIsActive(v) == false || old_tcp == NULL || data == NULL)
1448 {
1449 return;
1450 }
1451
1452 t = v->NativeNat;
1453
1454 // Search whether there is an existing session
1455 NnSetNat(&tt, NAT_TCP, src_ip, src_port, dest_ip, dest_port, 0, 0);
1456
1457 e = SearchHash(t->NatTableForSend, &tt);
1458
1459 if (e == NULL)
1460 {
1461 // Create a new session because there is no existing one
1462 UINT public_port;
1463
1464 if (((old_tcp->Flag & TCP_SYN) && ((old_tcp->Flag & TCP_ACK) == 0)) == false)
1465 {
1466 // If there is no existing session, pass through only for SYN packet
1467 return;
1468 }
1469
1470 if (CanCreateNewNatEntry(v) == false)
1471 {
1472 // Can not make any more
1473 return;
1474 }
1475
1476 NnDeleteOldestNatSessionIfNecessary(t, src_ip, NAT_TCP);
1477
1478 // Get a free port
1479 public_port = NnMapNewPublicPort(t, NAT_TCP, dest_ip, dest_port, t->PublicIP);
1480 if (public_port == 0)
1481 {
1482 // There are no free ports
1483 return;
1484 }
1485
1486 e = ZeroMalloc(sizeof(NATIVE_NAT_ENTRY));
1487
1488 e->HashCodeForSend = INFINITE;
1489 e->HashCodeForRecv = INFINITE;
1490 e->Id = Inc(v->Counter);
1491 e->Status = NAT_TCP_CONNECTING;
1492 e->Protocol = NAT_TCP;
1493 e->SrcIp = src_ip;
1494 e->SrcPort = src_port;
1495 e->DestIp = dest_ip;
1496 e->DestPort = dest_port;
1497 e->PublicIp = t->PublicIP;
1498 e->PublicPort = public_port;
1499
1500 e->CreatedTime = v->Now;
1501 e->LastCommTime = v->Now;
1502
1503 // Add to the list
1504 AddHash(t->NatTableForSend, e);
1505 AddHash(t->NatTableForRecv, e);
1506
1507 // Log
1508 if (true)
1509 {
1510 IP ip1, ip2;
1511 char s1[MAX_SIZE], s2[MAX_SIZE];
1512 UINTToIP(&ip1, src_ip);
1513 UINTToIP(&ip2, dest_ip);
1514 IPToStr(s1, 0, &ip1);
1515 IPToStr(s2, 0, &ip2);
1516
1517 NLog(v, "LH_NAT_TCP_CREATED", e->Id, s1, src_port, s2, dest_port);
1518 }
1519 }
1520
1521 // Update the last communication time
1522 e->LastCommTime = v->Now;
1523
1524 e->TotalSent += (UINT64)size;
1525
1526 tcp_header_size = TCP_GET_HEADER_SIZE(old_tcp) * 4;
1527
1528 // Create a new TCP packet
1529 tcp = ZeroMalloc(tcp_header_size + size);
1530
1531 // Copy the old TCP header
1532 Copy(tcp, old_tcp, tcp_header_size);
1533
1534 if (tcp->Flag & TCP_RST || tcp->Flag & TCP_FIN)
1535 {
1536 // Disconnect
1537 e->Status = NAT_TCP_WAIT_DISCONNECT;
1538 }
1539
1540 // Rewrite the TCP header
1541 tcp->Checksum = 0;
1542 tcp->SrcPort = Endian16(e->PublicPort);
1543
1544 e->LastSeq = Endian32(tcp->SeqNumber);
1545 e->LastAck = Endian32(tcp->AckNumber);
1546
1547 // Payload
1548 Copy(((UCHAR *)tcp) + tcp_header_size, data, size);
1549
1550 // Checksum calculation
1551 tcp->Checksum = CalcChecksumForIPv4(e->PublicIp, dest_ip, IP_PROTO_TCP, tcp, tcp_header_size + size, 0);
1552
1553 // Send to the Internet
1554 NnIpSendForInternet(t, IP_PROTO_TCP, 127, e->PublicIp, dest_ip, tcp, tcp_header_size + size, max_l3_size);
1555
1556 Free(tcp);
1557 }
1558
1559 // Assign a new public-side port
NnMapNewPublicPort(NATIVE_NAT * t,UINT protocol,UINT dest_ip,UINT dest_port,UINT public_ip)1560 UINT NnMapNewPublicPort(NATIVE_NAT *t, UINT protocol, UINT dest_ip, UINT dest_port, UINT public_ip)
1561 {
1562 UINT i;
1563 UINT base_port;
1564 UINT port_start = 1025;
1565 UINT port_end = 65500;
1566 // Validate arguments
1567 if (t == NULL)
1568 {
1569 return 0;
1570 }
1571
1572 if (t->IsRawIpMode)
1573 {
1574 port_start = NN_RAW_IP_PORT_START;
1575 port_end = NN_RAW_IP_PORT_END;
1576 }
1577
1578 base_port = Rand32() % (port_end - port_start) + port_start;
1579
1580 for (i = 0; i < (port_end - port_start); i++)
1581 {
1582 UINT port;
1583 NATIVE_NAT_ENTRY tt;
1584 NATIVE_NAT *e;
1585
1586 port = base_port + i;
1587 if (port > port_end)
1588 {
1589 port = port - port_end + port_start;
1590 }
1591
1592 // Is this port vacant?
1593 NnSetNat(&tt, protocol, 0, 0, dest_ip, dest_port, public_ip, port);
1594
1595 e = SearchHash(t->NatTableForRecv, &tt);
1596
1597 if (e == NULL)
1598 {
1599 // Free port is found
1600 return port;
1601 }
1602 }
1603
1604 return 0;
1605 }
1606
1607 // Examine whether the native NAT is available
NnIsActive(VH * v)1608 bool NnIsActive(VH *v)
1609 {
1610 return NnIsActiveEx(v, NULL);
1611 }
NnIsActiveEx(VH * v,bool * is_ipraw_mode)1612 bool NnIsActiveEx(VH *v, bool *is_ipraw_mode)
1613 {
1614 // Validate arguments
1615 if (v == NULL)
1616 {
1617 return false;
1618 }
1619
1620 if (v->NativeNat == NULL)
1621 {
1622 return false;
1623 }
1624
1625 if (v->NativeNat->PublicIP == 0)
1626 {
1627 return false;
1628 }
1629
1630 if (v->NativeNat->Active)
1631 {
1632 if (is_ipraw_mode != NULL)
1633 {
1634 *is_ipraw_mode = v->NativeNat->IsRawIpMode;
1635 }
1636 }
1637
1638 return v->NativeNat->Active;
1639 }
1640
1641 // Native NAT main loop
NnMainLoop(NATIVE_NAT * t,NATIVE_STACK * a)1642 void NnMainLoop(NATIVE_NAT *t, NATIVE_STACK *a)
1643 {
1644 IPC *ipc;
1645 TUBE *tubes[3];
1646 UINT num_tubes = 0;
1647 UINT64 next_poll_tick = 0;
1648 INTERRUPT_MANAGER *interrupt;
1649 USHORT dns_src_port = 0;
1650 USHORT dns_tran_id = 0;
1651 USHORT tcp_src_port = 0;
1652 UINT tcp_seq = 0;
1653 IP yahoo_ip;
1654 bool wait_for_dns = false;
1655 UINT64 tcp_last_recv_tick = 0;
1656 UINT dhcp_renew_interval;
1657 UINT64 next_dhcp_renew_tick = 0;
1658 // Validate arguments
1659 if (t == NULL || a == NULL)
1660 {
1661 return;
1662 }
1663
1664 dhcp_renew_interval = a->CurrentDhcpOptionList.LeaseTime;
1665
1666 if (dhcp_renew_interval == 0)
1667 {
1668 dhcp_renew_interval = IPC_DHCP_DEFAULT_LEASE;
1669 }
1670
1671 dhcp_renew_interval = MAX(dhcp_renew_interval, IPC_DHCP_MIN_LEASE) / 2;
1672
1673 interrupt = NewInterruptManager();
1674
1675 ipc = a->Ipc;
1676
1677 tubes[num_tubes++] = ipc->Sock->RecvTube;
1678 //tubes[num_tubes++] = ipc->Sock->SendTube; // bug 2015.10.01 remove
1679 tubes[num_tubes++] = t->HaltTube;
1680
1681 Zero(&yahoo_ip, sizeof(yahoo_ip));
1682
1683 next_poll_tick = Tick64() + (UINT64)NN_POLL_CONNECTIVITY_INTERVAL;
1684 AddInterrupt(interrupt, next_poll_tick);
1685
1686 tcp_last_recv_tick = Tick64();
1687 next_dhcp_renew_tick = Tick64() + (UINT64)dhcp_renew_interval * 1000;
1688 AddInterrupt(interrupt, next_dhcp_renew_tick);
1689
1690 while (t->Halt == false && t->v->UseNat)
1691 {
1692 UINT64 now = Tick64();
1693 bool call_cancel = false;
1694 bool state_changed = false;
1695 UINT wait_interval;
1696
1697 if (t->v->HubOption != NULL)
1698 {
1699 if (t->IsRawIpMode == false && t->v->HubOption->DisableKernelModeSecureNAT)
1700 {
1701 break;
1702 }
1703 if (t->IsRawIpMode && t->v->HubOption->DisableIpRawModeSecureNAT)
1704 {
1705 break;
1706 }
1707 }
1708
1709 IPCFlushArpTable(ipc);
1710 call_cancel = false;
1711
1712 LABEL_RESTART:
1713 state_changed = false;
1714
1715 if (next_poll_tick == 0 || next_poll_tick <= now)
1716 {
1717 BUF *dns_query;
1718
1719 dns_src_port = NnGenSrcPort(a->IsIpRawMode);
1720 dns_tran_id = Rand16();
1721
1722 // Start a connectivity check periodically
1723 dns_query = NnBuildIpPacket(NnBuildUdpPacket(NnBuildDnsQueryPacket(NN_CHECK_HOSTNAME, dns_tran_id),
1724 IPToUINT(&ipc->ClientIPAddress), dns_src_port, IPToUINT(&a->DnsServerIP), 53),
1725 IPToUINT(&ipc->ClientIPAddress), IPToUINT(&a->DnsServerIP), IP_PROTO_UDP, 0);
1726
1727 IPCSendIPv4(ipc, dns_query->Buf, dns_query->Size);
1728
1729 wait_for_dns = true;
1730
1731 FreeBuf(dns_query);
1732
1733 next_poll_tick = now + (UINT64)NN_POLL_CONNECTIVITY_INTERVAL;
1734 AddInterrupt(interrupt, next_poll_tick);
1735 }
1736
1737 if (next_dhcp_renew_tick == 0 || next_dhcp_renew_tick <= now)
1738 {
1739 IP ip;
1740
1741 UINTToIP(&ip, a->CurrentDhcpOptionList.ServerAddress);
1742
1743 IPCDhcpRenewIP(ipc, &ip);
1744
1745 next_dhcp_renew_tick = now + (UINT64)dhcp_renew_interval * 1000;
1746 AddInterrupt(interrupt, next_dhcp_renew_tick);
1747 }
1748
1749 // Send an IP packet to IPC
1750 LockQueue(t->SendQueue);
1751 {
1752 while (true)
1753 {
1754 BLOCK *b = GetNext(t->SendQueue);
1755
1756 if (b == NULL)
1757 {
1758 break;
1759 }
1760
1761 IPCSendIPv4(ipc, b->Buf, b->Size);
1762
1763 state_changed = true;
1764
1765 FreeBlock(b);
1766 }
1767 }
1768 UnlockQueue(t->SendQueue);
1769
1770 // Happy processing
1771 IPCProcessL3EventsIPv4Only(ipc);
1772
1773 LockQueue(t->RecvQueue);
1774 {
1775 while (true)
1776 {
1777 // Receive an IP packet from IPC
1778 BLOCK *b = IPCRecvIPv4(ipc);
1779 PKT *pkt;
1780
1781 if (b == NULL)
1782 {
1783 // Can not receive any more
1784 break;
1785 }
1786
1787 // Parse the packet
1788 pkt = ParsePacketIPv4WithDummyMacHeader(b->Buf, b->Size);
1789
1790 FreeBlock(b);
1791
1792 if (pkt != NULL)
1793 {
1794 bool no_store = false;
1795
1796 // Read the contents of the packet first, to determine whether it is a response for the connectivity test packet
1797 if (wait_for_dns)
1798 {
1799 if (pkt->TypeL3 == L3_IPV4 && pkt->TypeL4 == L4_UDP &&
1800 pkt->L3.IPv4Header->SrcIP == IPToUINT(&a->DnsServerIP) &&
1801 pkt->L3.IPv4Header->DstIP == IPToUINT(&ipc->ClientIPAddress) &&
1802 pkt->L4.UDPHeader->SrcPort == Endian16(53) && pkt->L4.UDPHeader->DstPort == Endian16(dns_src_port))
1803 {
1804 DNSV4_HEADER *dns_header = (DNSV4_HEADER *)pkt->Payload;
1805 if (pkt->PayloadSize >= sizeof(DNSV4_HEADER))
1806 {
1807 if (dns_header->TransactionId == Endian16(dns_tran_id))
1808 {
1809 IP ret_ip;
1810
1811 if (NnParseDnsResponsePacket(pkt->Payload, pkt->PayloadSize, &ret_ip))
1812 {
1813 BUF *tcp_query;
1814
1815 Copy(&yahoo_ip, &ret_ip, sizeof(IP));
1816
1817 //SetIP(&yahoo_ip, 192, 168, 2, 32);
1818
1819 // DNS response has been received
1820 no_store = true;
1821
1822 tcp_src_port = NnGenSrcPort(a->IsIpRawMode);
1823
1824 // Generate a TCP connection attempt packet
1825 tcp_seq = Rand32();
1826 tcp_query = NnBuildIpPacket(NnBuildTcpPacket(NewBuf(), IPToUINT(&ipc->ClientIPAddress), tcp_src_port,
1827 IPToUINT(&yahoo_ip), 80, tcp_seq, 0, TCP_SYN, 8192, 1414),
1828 IPToUINT(&ipc->ClientIPAddress), IPToUINT(&yahoo_ip), IP_PROTO_TCP, 0);
1829
1830 IPCSendIPv4(ipc, tcp_query->Buf, tcp_query->Size);
1831
1832 FreeBuf(tcp_query);
1833
1834 wait_for_dns = false;
1835 }
1836 }
1837 }
1838 }
1839 }
1840
1841 if (pkt->TypeL3 == L3_IPV4 && pkt->TypeL4 == L4_TCP &&
1842 pkt->L3.IPv4Header->SrcIP == IPToUINT(&yahoo_ip) &&
1843 pkt->L3.IPv4Header->DstIP == IPToUINT(&ipc->ClientIPAddress) &&
1844 pkt->L4.TCPHeader->SrcPort == Endian16(80) && pkt->L4.TCPHeader->DstPort == Endian16(tcp_src_port))
1845 {
1846 TCP_HEADER *tcp_header = (TCP_HEADER *)pkt->L4.TCPHeader;
1847 if ((tcp_header->Flag & TCP_SYN) && (tcp_header->Flag & TCP_ACK))
1848 {
1849 // There was a TCP response
1850 BUF *tcp_query;
1851 UINT recv_seq = Endian32(tcp_header->SeqNumber) + 1;
1852
1853 no_store = true;
1854
1855 // Send a RST
1856 tcp_query = NnBuildIpPacket(NnBuildTcpPacket(NewBuf(), IPToUINT(&ipc->ClientIPAddress), tcp_src_port,
1857 IPToUINT(&yahoo_ip), 80, tcp_seq + 1, recv_seq, TCP_RST | TCP_ACK, 8192, 0),
1858 IPToUINT(&ipc->ClientIPAddress), IPToUINT(&yahoo_ip), IP_PROTO_TCP, 0);
1859
1860 IPCSendIPv4(ipc, tcp_query->Buf, tcp_query->Size);
1861
1862 FreeBuf(tcp_query);
1863
1864 tcp_last_recv_tick = now;
1865 }
1866 }
1867
1868 if (t->RecvQueue->num_item > NN_MAX_QUEUE_LENGTH)
1869 {
1870 no_store = true;
1871 }
1872
1873 if (no_store == false)
1874 {
1875 // Put in the queue
1876 InsertQueue(t->RecvQueue, pkt);
1877 call_cancel = true;
1878 state_changed = true;
1879 }
1880 else
1881 {
1882 // Release the packet
1883 FreePacketWithData(pkt);
1884 }
1885 }
1886 }
1887 }
1888 UnlockQueue(t->RecvQueue);
1889
1890 if (state_changed)
1891 {
1892 goto LABEL_RESTART;
1893 }
1894
1895 if (call_cancel)
1896 {
1897 CANCEL *c = NULL;
1898
1899 Lock(t->CancelLock);
1900 {
1901 c = t->Cancel;
1902
1903 AddRef(c->ref);
1904 }
1905 Unlock(t->CancelLock);
1906
1907 Cancel(c);
1908
1909 ReleaseCancel(c);
1910 }
1911
1912 if (IsTubeConnected(ipc->Sock->RecvTube) == false || IsTubeConnected(ipc->Sock->SendTube) == false)
1913 {
1914 // Disconnected
1915 break;
1916 }
1917
1918 if ((tcp_last_recv_tick + (UINT64)NN_POLL_CONNECTIVITY_TIMEOUT) < now)
1919 {
1920 // Connectivity test has timed out because a certain period of time has elapsed
1921 Debug("NN_POLL_CONNECTIVITY_TIMEOUT\n");
1922 break;
1923 }
1924
1925 wait_interval = GetNextIntervalForInterrupt(interrupt);
1926 wait_interval = MIN(wait_interval, 1234);
1927
1928 if (wait_interval != 0)
1929 {
1930 WaitForTubes(tubes, num_tubes, wait_interval);
1931 }
1932 }
1933
1934 FreeInterruptManager(interrupt);
1935 }
1936
1937 // Build an IP packet
NnBuildIpPacket(BUF * payload,UINT src_ip,UINT dst_ip,UCHAR protocol,UCHAR ttl)1938 BUF *NnBuildIpPacket(BUF *payload, UINT src_ip, UINT dst_ip, UCHAR protocol, UCHAR ttl)
1939 {
1940 BUF *ret = NewBuf();
1941 IPV4_HEADER h;
1942
1943 if (ttl == 0)
1944 {
1945 ttl = 127;
1946 }
1947
1948 // IP header
1949 Zero(&h, sizeof(h));
1950 IPV4_SET_VERSION(&h, 4);
1951 IPV4_SET_HEADER_LEN(&h, sizeof(IPV4_HEADER) / 4);
1952 h.TotalLength = Endian16((USHORT)sizeof(IPV4_HEADER) + payload->Size);
1953 h.Identification = Rand16();
1954 h.TimeToLive = ttl;
1955 h.Protocol = protocol;
1956 h.SrcIP = src_ip;
1957 h.DstIP = dst_ip;
1958
1959 h.Checksum = IpChecksum(&h, sizeof(h));
1960
1961 WriteBuf(ret, &h, sizeof(h));
1962 WriteBufBuf(ret, payload);
1963
1964 SeekBufToBegin(ret);
1965
1966 FreeBuf(payload);
1967
1968 return ret;
1969 }
1970
1971 // Build an UDP packet
NnBuildUdpPacket(BUF * payload,UINT src_ip,USHORT src_port,UINT dst_ip,USHORT dst_port)1972 BUF *NnBuildUdpPacket(BUF *payload, UINT src_ip, USHORT src_port, UINT dst_ip, USHORT dst_port)
1973 {
1974 BUF *ret = NewBuf();
1975 BUF *phbuf = NewBuf();
1976 UDPV4_PSEUDO_HEADER ph;
1977 UDP_HEADER h;
1978
1979 // UDP pseudo header
1980 Zero(&ph, sizeof(ph));
1981
1982 ph.SrcIP = src_ip;
1983 ph.DstIP = dst_ip;
1984 ph.SrcPort = Endian16(src_port);
1985 ph.DstPort = Endian16(dst_port);
1986 ph.Protocol = IP_PROTO_UDP;
1987 ph.PacketLength1 = ph.PacketLength2 = Endian16(payload->Size + (USHORT)sizeof(UDP_HEADER));
1988
1989 WriteBuf(phbuf, &ph, sizeof(ph));
1990 WriteBufBuf(phbuf, payload);
1991
1992 // UDP header
1993 Zero(&h, sizeof(h));
1994 h.SrcPort = Endian16(src_port);
1995 h.DstPort = Endian16(dst_port);
1996 h.PacketLength = Endian16(payload->Size + (USHORT)sizeof(UDP_HEADER));
1997 h.Checksum = IpChecksum(phbuf->Buf, phbuf->Size);
1998
1999 WriteBuf(ret, &h, sizeof(h));
2000 WriteBuf(ret, payload->Buf, payload->Size);
2001
2002 SeekBufToBegin(ret);
2003
2004 FreeBuf(payload);
2005 FreeBuf(phbuf);
2006
2007 return ret;
2008 }
2009
2010 // Build a TCP packet
NnBuildTcpPacket(BUF * payload,UINT src_ip,USHORT src_port,UINT dst_ip,USHORT dst_port,UINT seq,UINT ack,UINT flag,UINT window_size,UINT mss)2011 BUF *NnBuildTcpPacket(BUF *payload, UINT src_ip, USHORT src_port, UINT dst_ip, USHORT dst_port, UINT seq, UINT ack, UINT flag, UINT window_size, UINT mss)
2012 {
2013 BUF *ret;
2014 IPV4_PSEUDO_HEADER *vh;
2015 TCP_HEADER *tcp;
2016 static UCHAR tcp_mss_option[] = {0x02, 0x04, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00};
2017 UINT header_size = TCP_HEADER_SIZE;
2018 UINT total_size;
2019
2020 // Memory allocation
2021 vh = Malloc(sizeof(IPV4_PSEUDO_HEADER) + TCP_HEADER_SIZE + payload->Size + 32);
2022 tcp = (TCP_HEADER *)(((UCHAR *)vh) + sizeof(IPV4_PSEUDO_HEADER));
2023
2024 if (mss != 0)
2025 {
2026 USHORT *mss_size;
2027 mss_size = (USHORT *)(&tcp_mss_option[2]);
2028 *mss_size = Endian16((USHORT)mss);
2029 header_size += sizeof(tcp_mss_option);
2030 }
2031
2032 total_size = header_size + payload->Size;
2033
2034 // Pseudo header generation
2035 vh->SrcIP = src_ip;
2036 vh->DstIP = dst_ip;
2037 vh->Reserved = 0;
2038 vh->Protocol = IP_PROTO_TCP;
2039 vh->PacketLength = Endian16((USHORT)total_size);
2040
2041 // TCP header generation
2042 tcp->SrcPort = Endian16((USHORT)src_port);
2043 tcp->DstPort = Endian16((USHORT)dst_port);
2044 tcp->SeqNumber = Endian32(seq);
2045 tcp->AckNumber = Endian32(ack);
2046 tcp->HeaderSizeAndReserved = 0;
2047 TCP_SET_HEADER_SIZE(tcp, (UCHAR)(header_size / 4));
2048 tcp->Flag = (UCHAR)flag;
2049 tcp->WindowSize = Endian16((USHORT)window_size);
2050 tcp->Checksum = 0;
2051 tcp->UrgentPointer = 0;
2052
2053 // Copy the option values
2054 if (mss != 0)
2055 {
2056 Copy(((UCHAR *)tcp) + TCP_HEADER_SIZE, tcp_mss_option, sizeof(tcp_mss_option));
2057 }
2058
2059 // Data copy
2060 Copy(((UCHAR *)tcp) + header_size, payload->Buf, payload->Size);
2061
2062 // Checksum calculation
2063 tcp->Checksum = IpChecksum(vh, total_size + 12);
2064
2065 ret = NewBufFromMemory(tcp, total_size);
2066
2067 Free(vh);
2068
2069 FreeBuf(payload);
2070
2071 return ret;
2072 }
2073
2074 // Build a DNS query packet
NnBuildDnsQueryPacket(char * hostname,USHORT tran_id)2075 BUF *NnBuildDnsQueryPacket(char *hostname, USHORT tran_id)
2076 {
2077 BUF *buf = NewBuf();
2078 DNSV4_HEADER header;
2079
2080 Zero(&header, sizeof(header));
2081
2082 header.TransactionId = Endian16(tran_id);
2083 header.Flag1 = 0x01;
2084 header.Flag2 = 0x00;
2085 header.NumQuery = Endian16(1);
2086
2087 WriteBuf(buf, &header, sizeof(header));
2088
2089 BuildDnsQueryPacket(buf, hostname, false);
2090
2091 SeekBufToBegin(buf);
2092
2093 return buf;
2094 }
2095
2096 // Read a DNS record
NnReadDnsRecord(BUF * buf,bool answer,USHORT * ret_type,USHORT * ret_class)2097 BUF *NnReadDnsRecord(BUF *buf, bool answer, USHORT *ret_type, USHORT *ret_class)
2098 {
2099 USHORT type;
2100 USHORT clas;
2101 UINT ttl;
2102 BUF *ret = NULL;
2103 // Validate arguments
2104 if (buf == NULL)
2105 {
2106 return NULL;
2107 }
2108
2109 // Read the DNS label
2110 if (NnReadDnsLabel(buf) == false)
2111 {
2112 return false;
2113 }
2114
2115 // Type and Class
2116 if (ReadBuf(buf, &type, sizeof(USHORT)) != sizeof(USHORT))
2117 {
2118 return false;
2119 }
2120
2121 if (ret_type != NULL)
2122 {
2123 *ret_type = Endian16(type);
2124 }
2125
2126 if (ReadBuf(buf, &clas, sizeof(USHORT)) != sizeof(USHORT))
2127 {
2128 return false;
2129 }
2130
2131 if (ret_class != NULL)
2132 {
2133 *ret_class = Endian16(clas);
2134 }
2135
2136 if (answer)
2137 {
2138 USHORT data_len;
2139 UCHAR *data;
2140
2141 // TTL
2142 if (ReadBuf(buf, &ttl, sizeof(UINT)) != sizeof(UINT))
2143 {
2144 return false;
2145 }
2146
2147 // data_len
2148 if (ReadBuf(buf, &data_len, sizeof(USHORT)) != sizeof(USHORT))
2149 {
2150 return false;
2151 }
2152
2153 data_len = Endian16(data_len);
2154
2155 // data
2156 data = Malloc(data_len);
2157 if (ReadBuf(buf, data, data_len) != data_len)
2158 {
2159 Free(data);
2160 return false;
2161 }
2162
2163 ret = NewBufFromMemory(data, data_len);
2164
2165 Free(data);
2166 }
2167 else
2168 {
2169 ret = NewBuf();
2170 }
2171
2172 return ret;
2173 }
2174
2175 // Read the DNS label
NnReadDnsLabel(BUF * buf)2176 bool NnReadDnsLabel(BUF *buf)
2177 {
2178 UCHAR c;
2179 UCHAR tmp[256];
2180 // Validate arguments
2181 if (buf == NULL)
2182 {
2183 return false;
2184 }
2185
2186 LABEL_START:
2187
2188 if (ReadBuf(buf, &c, 1) != 1)
2189 {
2190 return false;
2191 }
2192
2193 if (c == 0)
2194 {
2195 return true;
2196 }
2197
2198 if (c & 0xC0)
2199 {
2200 // Compression label
2201 if (ReadBuf(buf, &c, 1) != 1)
2202 {
2203 return false;
2204 }
2205 else
2206 {
2207 return true;
2208 }
2209 }
2210 else
2211 {
2212 // Usual label
2213 if (ReadBuf(buf, tmp, c) != c)
2214 {
2215 return false;
2216 }
2217 else
2218 {
2219 goto LABEL_START;
2220 }
2221 }
2222
2223 }
2224
2225 // Parse the DNS response packet
NnParseDnsResponsePacket(UCHAR * data,UINT size,IP * ret_ip)2226 bool NnParseDnsResponsePacket(UCHAR *data, UINT size, IP *ret_ip)
2227 {
2228 BUF *buf = NewBufFromMemory(data, size);
2229 bool ret = false;
2230 DNSV4_HEADER h;
2231
2232 if (ReadBuf(buf, &h, sizeof(h)) == sizeof(h))
2233 {
2234 UINT num_questions = Endian16(h.NumQuery);
2235 UINT num_answers = Endian16(h.AnswerRRs);
2236 UINT i;
2237
2238 for (i = 0; i < num_questions; i++)
2239 {
2240 BUF *r = NnReadDnsRecord(buf, false, NULL, NULL);
2241
2242 if (r != NULL)
2243 {
2244 FreeBuf(r);
2245 }
2246 else
2247 {
2248 goto LABEL_CLEANUP;
2249 }
2250 }
2251
2252 for (i = 0; i < num_answers; i++)
2253 {
2254 USHORT tp, cl;
2255 BUF *r = NnReadDnsRecord(buf, true, &tp, &cl);
2256
2257 if (r != NULL)
2258 {
2259 if (tp == 0x0001 && cl == 0x0001 && r->Size == IPV4_SIZE)
2260 {
2261 ret = true;
2262
2263 if (ret_ip != NULL)
2264 {
2265 ZeroIP4(ret_ip);
2266 Copy(IPV4(ret_ip->address), r->Buf, IPV4_SIZE);
2267 }
2268 }
2269
2270 FreeBuf(r);
2271 }
2272 else
2273 {
2274 goto LABEL_CLEANUP;
2275 }
2276 }
2277 }
2278
2279 LABEL_CLEANUP:
2280 FreeBuf(buf);
2281
2282 return ret;
2283 }
2284
2285 // Test the connectivity of the stack to the Internet
NnTestConnectivity(NATIVE_STACK * a,TUBE * halt_tube)2286 bool NnTestConnectivity(NATIVE_STACK *a, TUBE *halt_tube)
2287 {
2288 BUF *dns_query;
2289 BUF *dns_query2;
2290 bool ok = false;
2291 USHORT dns_tran_id = Rand16();
2292 UINT64 next_send_tick = 0;
2293 UINT64 giveup_time;
2294 IPC *ipc;
2295 INTERRUPT_MANAGER *interrupt;
2296 TUBE *tubes[3];
2297 UINT num_tubes = 0;
2298 IP yahoo_ip;
2299 IP my_priv_ip;
2300 UINT num_send_dns = 0;
2301 IP using_dns;
2302 UINT src_port = 0;
2303 // Validate arguments
2304 if (a == NULL)
2305 {
2306 return false;
2307 }
2308
2309 src_port = NnGenSrcPort(a->IsIpRawMode);
2310
2311 Copy(&using_dns, &a->DnsServerIP, sizeof(IP));
2312
2313 // Get my physical IP
2314 if (a->IsIpRawMode)
2315 {
2316 if (GetMyPrivateIP(&my_priv_ip, false) == false)
2317 {
2318 Debug("NnTestConnectivity: GetMyPrivateIP failed.\n");
2319 return false;
2320 }
2321 else
2322 {
2323 Debug("NnTestConnectivity: GetMyPrivateIP ok: %r\n", &my_priv_ip);
2324
2325 if (a->Eth != NULL)
2326 {
2327 Copy(&a->Eth->MyPhysicalIPForce, &my_priv_ip, sizeof(IP));
2328 }
2329 }
2330 }
2331
2332 ipc = a->Ipc;
2333 interrupt = NewInterruptManager();
2334
2335 tubes[num_tubes++] = ipc->Sock->RecvTube;
2336 tubes[num_tubes++] = ipc->Sock->SendTube;
2337
2338 if (halt_tube != NULL)
2339 {
2340 tubes[num_tubes++] = halt_tube;
2341 }
2342
2343 Zero(&yahoo_ip, sizeof(yahoo_ip));
2344
2345 // Try to get an IP address of www.yahoo.com
2346 dns_query = NnBuildIpPacket(NnBuildUdpPacket(NnBuildDnsQueryPacket(NN_CHECK_HOSTNAME, dns_tran_id),
2347 IPToUINT(&ipc->ClientIPAddress), src_port, IPToUINT(&a->DnsServerIP), 53),
2348 IPToUINT(&ipc->ClientIPAddress), IPToUINT(&a->DnsServerIP), IP_PROTO_UDP, 0);
2349
2350 dns_query2 = NnBuildIpPacket(NnBuildUdpPacket(NnBuildDnsQueryPacket(NN_CHECK_HOSTNAME, dns_tran_id),
2351 IPToUINT(&ipc->ClientIPAddress), src_port, IPToUINT(&a->DnsServerIP), 53),
2352 IPToUINT(&ipc->ClientIPAddress), IPToUINT(&a->DnsServerIP2), IP_PROTO_UDP, 0);
2353
2354 giveup_time = Tick64() + NN_CHECK_CONNECTIVITY_TIMEOUT;
2355 AddInterrupt(interrupt, giveup_time);
2356 while (true)
2357 {
2358 UINT64 now = Tick64();
2359
2360 IPCFlushArpTable(a->Ipc);
2361
2362 if (now >= giveup_time)
2363 {
2364 break;
2365 }
2366
2367 // Send a packet periodically
2368 if (next_send_tick == 0 || next_send_tick <= now)
2369 {
2370 next_send_tick = now + (UINT64)NN_CHECK_CONNECTIVITY_INTERVAL;
2371
2372 AddInterrupt(interrupt, next_send_tick);
2373
2374 if ((num_send_dns % 2) == 0)
2375 {
2376 IPCSendIPv4(ipc, dns_query->Buf, dns_query->Size);
2377 }
2378 else
2379 {
2380 IPCSendIPv4(ipc, dns_query2->Buf, dns_query2->Size);
2381 }
2382
2383 num_send_dns++;
2384 }
2385
2386 // Happy processing
2387 IPCProcessL3EventsIPv4Only(ipc);
2388
2389 while (true)
2390 {
2391 // Receive a packet
2392 BLOCK *b = IPCRecvIPv4(ipc);
2393 PKT *pkt;
2394
2395 if (b == NULL)
2396 {
2397 break;
2398 }
2399
2400 // Parse the packet
2401 pkt = ParsePacketIPv4WithDummyMacHeader(b->Buf, b->Size);
2402
2403 if (pkt != NULL)
2404 {
2405 if (pkt->TypeL3 == L3_IPV4 && pkt->TypeL4 == L4_UDP &&
2406 (pkt->L3.IPv4Header->SrcIP == IPToUINT(&a->DnsServerIP) ||
2407 pkt->L3.IPv4Header->SrcIP == IPToUINT(&a->DnsServerIP2)) &&
2408 pkt->L3.IPv4Header->DstIP == IPToUINT(&ipc->ClientIPAddress) &&
2409 pkt->L4.UDPHeader->SrcPort == Endian16(53) && pkt->L4.UDPHeader->DstPort == Endian16(src_port))
2410 {
2411 DNSV4_HEADER *dns_header = (DNSV4_HEADER *)pkt->Payload;
2412 if (pkt->PayloadSize >= sizeof(DNSV4_HEADER))
2413 {
2414 if (dns_header->TransactionId == Endian16(dns_tran_id))
2415 {
2416 IP ret_ip;
2417
2418 if (NnParseDnsResponsePacket(pkt->Payload, pkt->PayloadSize, &ret_ip))
2419 {
2420 UINTToIP(&using_dns, pkt->L3.IPv4Header->SrcIP);
2421 Debug("NativeStack: Using DNS: %r\n", &using_dns);
2422
2423 Copy(&yahoo_ip, &ret_ip, sizeof(IP));
2424 }
2425 }
2426 }
2427 }
2428 }
2429
2430 FreePacketWithData(pkt);
2431 FreeBlock(b);
2432 }
2433
2434 if ((halt_tube != NULL && IsTubeConnected(halt_tube) == false) ||
2435 IsTubeConnected(ipc->Sock->SendTube) == false || IsTubeConnected(ipc->Sock->RecvTube) == false)
2436 {
2437 // Disconnected
2438 break;
2439 }
2440
2441 if (IsZeroIP(&yahoo_ip) == false)
2442 {
2443 // There is a response
2444 break;
2445 }
2446
2447 // Keep the CPU waiting
2448 WaitForTubes(tubes, num_tubes, GetNextIntervalForInterrupt(interrupt));
2449 }
2450
2451 FreeBuf(dns_query);
2452 FreeBuf(dns_query2);
2453
2454 if (IsZeroIP(&yahoo_ip) == false)
2455 {
2456 BUF *tcp_query;
2457 UINT seq = Rand32();
2458 bool tcp_get_response = false;
2459 UINT recv_seq = 0;
2460
2461 // Since the IP address of www.yahoo.com has gotten, try to connect by TCP
2462 giveup_time = Tick64() + NN_CHECK_CONNECTIVITY_TIMEOUT;
2463 AddInterrupt(interrupt, giveup_time);
2464
2465 // Generate a TCP packet
2466 tcp_query = NnBuildIpPacket(NnBuildTcpPacket(NewBuf(), IPToUINT(&ipc->ClientIPAddress), src_port,
2467 IPToUINT(&yahoo_ip), 80, seq, 0, TCP_SYN, 8192, 1414),
2468 IPToUINT(&ipc->ClientIPAddress), IPToUINT(&yahoo_ip), IP_PROTO_TCP, 0);
2469
2470 Debug("Test TCP to %r\n", &yahoo_ip);
2471
2472 next_send_tick = 0;
2473
2474 while (true)
2475 {
2476 UINT64 now = Tick64();
2477
2478 IPCFlushArpTable(a->Ipc);
2479
2480 if (now >= giveup_time)
2481 {
2482 break;
2483 }
2484
2485 // Send the packet periodically
2486 if (next_send_tick == 0 || next_send_tick <= now)
2487 {
2488 next_send_tick = now + (UINT64)NN_CHECK_CONNECTIVITY_INTERVAL;
2489
2490 AddInterrupt(interrupt, next_send_tick);
2491
2492 IPCSendIPv4(ipc, tcp_query->Buf, tcp_query->Size);
2493 }
2494
2495 // Happy procedure
2496 IPCProcessL3EventsIPv4Only(ipc);
2497
2498 while (true)
2499 {
2500 // Receive a packet
2501 BLOCK *b = IPCRecvIPv4(ipc);
2502 PKT *pkt;
2503
2504 if (b == NULL)
2505 {
2506 break;
2507 }
2508
2509 // Parse the packet
2510 pkt = ParsePacketIPv4WithDummyMacHeader(b->Buf, b->Size);
2511
2512 if (pkt != NULL)
2513 {
2514 if (pkt->TypeL3 == L3_IPV4 && pkt->TypeL4 == L4_TCP &&
2515 pkt->L3.IPv4Header->SrcIP == IPToUINT(&yahoo_ip) &&
2516 pkt->L3.IPv4Header->DstIP == IPToUINT(&ipc->ClientIPAddress) &&
2517 pkt->L4.TCPHeader->SrcPort == Endian16(80) && pkt->L4.TCPHeader->DstPort == Endian16(src_port))
2518 {
2519 TCP_HEADER *tcp_header = (TCP_HEADER *)pkt->L4.TCPHeader;
2520 if ((tcp_header->Flag & TCP_SYN) && (tcp_header->Flag & TCP_ACK))
2521 {
2522 // There was a TCP response
2523 tcp_get_response = true;
2524 recv_seq = Endian32(tcp_header->SeqNumber);
2525 }
2526 }
2527 }
2528
2529 FreePacketWithData(pkt);
2530 FreeBlock(b);
2531 }
2532
2533 if ((halt_tube != NULL && IsTubeConnected(halt_tube) == false) ||
2534 IsTubeConnected(ipc->Sock->SendTube) == false || IsTubeConnected(ipc->Sock->RecvTube) == false)
2535 {
2536 // Disconnected
2537 break;
2538 }
2539
2540 if (tcp_get_response)
2541 {
2542 WHERE;
2543 break;
2544 }
2545
2546 // Keep the CPU waiting
2547 WaitForTubes(tubes, num_tubes, GetNextIntervalForInterrupt(interrupt));
2548 }
2549
2550 FreeBuf(tcp_query);
2551
2552 // Send a RST
2553 if (recv_seq != 0)
2554 {
2555 recv_seq++;
2556 }
2557
2558 tcp_query = NnBuildIpPacket(NnBuildTcpPacket(NewBuf(), IPToUINT(&ipc->ClientIPAddress), src_port,
2559 IPToUINT(&yahoo_ip), 80, seq + 1, recv_seq, TCP_RST | TCP_ACK, 8192, 0),
2560 IPToUINT(&ipc->ClientIPAddress), IPToUINT(&yahoo_ip), IP_PROTO_TCP, 0);
2561
2562 IPCSendIPv4(ipc, tcp_query->Buf, tcp_query->Size);
2563
2564 FreeBuf(tcp_query);
2565
2566 SleepThread(100);
2567
2568 if (tcp_get_response)
2569 {
2570 ok = true;
2571 }
2572 }
2573
2574 FreeInterruptManager(interrupt);
2575
2576 if (ok)
2577 {
2578 if (IsZeroIP(&using_dns) == false)
2579 {
2580 Copy(&a->DnsServerIP, &using_dns, sizeof(IP));
2581 }
2582
2583 if (a->IsIpRawMode)
2584 {
2585 if (NsStartIpTablesTracking(a) == false)
2586 {
2587 Debug("NsStartIpTablesTracking failed.\n");
2588 ok = false;
2589 }
2590 }
2591 }
2592
2593 return ok;
2594 }
2595
2596 // Generate source port number by a random number
NnGenSrcPort(bool raw_ip_mode)2597 UINT NnGenSrcPort(bool raw_ip_mode)
2598 {
2599 if (raw_ip_mode == false)
2600 {
2601 return 1025 + Rand32() % (65500 - 1025);
2602 }
2603 else
2604 {
2605 return NN_RAW_IP_PORT_START + Rand32() % (NN_RAW_IP_PORT_END - NN_RAW_IP_PORT_START);
2606 }
2607 }
2608
2609 // Get a next good interface for the native NAT
NnGetNextInterface(NATIVE_NAT * t)2610 NATIVE_STACK *NnGetNextInterface(NATIVE_NAT *t)
2611 {
2612 NATIVE_STACK *ret = NULL;
2613 UINT current_hash;
2614 TOKEN_LIST *device_list;
2615 UINT i;
2616 char tmp[MAX_SIZE];
2617 char *dev_name;
2618 UINT current_ip_hash;
2619 // Validate arguments
2620 if (t == NULL)
2621 {
2622 return NULL;
2623 }
2624
2625 t->NextWaitTimeForRetry = NN_NEXT_WAIT_TIME_FOR_DEVICE_ENUM * MIN((t->FailedCount + 1), NN_NEXT_WAIT_TIME_MAX_FAIL_COUNT);
2626
2627 // Get the device list
2628 device_list = GetEthListEx(NULL,
2629 !(t->v->HubOption != NULL && t->v->HubOption->DisableKernelModeSecureNAT),
2630 !(t->v->HubOption != NULL && t->v->HubOption->DisableIpRawModeSecureNAT));
2631
2632 if (device_list == NULL || device_list->NumTokens == 0)
2633 {
2634 // Device list acquisition failure (Or no device acquired as a result)
2635 FreeToken(device_list);
2636 t->FailedCount++;
2637 return NULL;
2638 }
2639
2640 current_hash = GetEthDeviceHash();
2641 current_ip_hash = GetHostIPAddressHash32();
2642
2643 if (t->LastInterfaceDeviceHash != current_hash || t->LastHostAddressHash != current_ip_hash)
2644 {
2645 // Device list is altered from the previous search
2646 t->LastInterfaceIndex = INFINITE;
2647 t->FailedCount = 0;
2648 }
2649
2650 t->LastInterfaceDeviceHash = current_hash;
2651 t->LastHostAddressHash = current_ip_hash;
2652
2653 if (t->LastInterfaceIndex == INFINITE)
2654 {
2655 i = 0;
2656 }
2657 else
2658 {
2659 i = t->LastInterfaceIndex + 1;
2660 if (i >= device_list->NumTokens)
2661 {
2662 i = 0;
2663 }
2664 }
2665
2666 if ((i + 1) == device_list->NumTokens)
2667 {
2668 // Searched to the end
2669 t->LastInterfaceIndex = INFINITE;
2670
2671 // Increase the number of search failures by one
2672 t->FailedCount++;
2673 }
2674 else
2675 {
2676 // It is not the end yet
2677 t->LastInterfaceIndex = i;
2678 t->NextWaitTimeForRetry = 0;
2679 }
2680
2681 dev_name = device_list->Token[i];
2682
2683 if (IsInLinesFile(NN_NO_NATIVE_NAT_FILENAME, dev_name, true) == false)
2684 {
2685 // Try to open the device
2686 BinToStr(tmp, sizeof(tmp), t->v->MacAddress, 6);
2687 ret = NewNativeStack(NULL, dev_name, tmp);
2688
2689 if (ret != NULL)
2690 {
2691 // Test whether an IP address can be obtained from a DHCP server
2692 DHCP_OPTION_LIST opt;
2693
2694 Copy(t->CurrentMacAddress, ret->Ipc->MacAddress, 6);
2695
2696 Zero(&opt, sizeof(opt));
2697
2698 BinToStr(tmp, sizeof(tmp), ret->MacAddress, 6);
2699 Format(ret->Ipc->ClientHostname, sizeof(ret->Ipc->ClientHostname), NN_HOSTNAME_FORMAT, tmp);
2700 StrLower(ret->Ipc->ClientHostname);
2701
2702 Debug("IPCDhcpAllocateIP for %s\n", ret->DeviceName);
2703 if (IPCDhcpAllocateIP(ret->Ipc, &opt, t->HaltTube2))
2704 {
2705 char client_ip[64];
2706 char dhcp_ip[64];
2707 char client_mask[64];
2708 char gateway_ip[64];
2709
2710 IP ip;
2711 IP subnet;
2712 IP gw;
2713
2714 IPToStr32(client_ip, sizeof(client_ip), opt.ClientAddress);
2715 IPToStr32(client_mask, sizeof(client_mask), opt.SubnetMask);
2716 IPToStr32(dhcp_ip, sizeof(dhcp_ip), opt.ServerAddress);
2717 IPToStr32(gateway_ip, sizeof(gateway_ip), opt.Gateway);
2718
2719 Debug("DHCP: client_ip=%s, client_mask=%s, dhcp_ip=%s, gateway_ip=%s\n",
2720 client_ip, client_mask, dhcp_ip, gateway_ip);
2721
2722 Copy(&ret->CurrentDhcpOptionList, &opt, sizeof(DHCP_OPTION_LIST));
2723
2724 // IP parameter settings
2725 UINTToIP(&ip, opt.ClientAddress);
2726 UINTToIP(&subnet, opt.SubnetMask);
2727 UINTToIP(&gw, opt.Gateway);
2728
2729 IPCSetIPv4Parameters(ret->Ipc, &ip, &subnet, &gw, &opt.ClasslessRoute);
2730
2731 // Determine the DNS server to use
2732 UINTToIP(&ret->DnsServerIP, opt.DnsServer);
2733 UINTToIP(&ret->DnsServerIP2, opt.DnsServer2);
2734 if (IsZeroIP(&ret->DnsServerIP))
2735 {
2736 // Use 8.8.8.8 instead If the DNS is not assigned from the DHCP server
2737 SetIP(&ret->DnsServerIP, 8, 8, 8, 8);
2738 }
2739 if (IsZeroIP(&ret->DnsServerIP2))
2740 {
2741 // Use 8.8.4.4 instead If the DNS is not assigned from the DHCP server
2742 SetIP(&ret->DnsServerIP2, 8, 8, 4, 4);
2743 }
2744
2745 // Connectivity test
2746 // (always fail if the default gateway is not set)
2747 if (opt.Gateway != 0 &&
2748 NnTestConnectivity(ret, t->HaltTube2))
2749 {
2750 // Reset the number of search failures
2751 t->FailedCount = 0;
2752 Debug("Connectivity OK.\n");
2753 }
2754 else
2755 {
2756 Debug("Connectivity Failed.\n");
2757 FreeNativeStack(ret);
2758 ret = NULL;
2759 }
2760 }
2761 else
2762 {
2763 Debug("DHCP Failed.\n");
2764 FreeNativeStack(ret);
2765 ret = NULL;
2766
2767 Zero(t->CurrentMacAddress, sizeof(t->CurrentMacAddress));
2768 }
2769 }
2770 }
2771
2772 FreeToken(device_list);
2773
2774 return ret;
2775 }
2776
2777 // Native NAT thread
NativeNatThread(THREAD * thread,void * param)2778 void NativeNatThread(THREAD *thread, void *param)
2779 {
2780 NATIVE_NAT *t = (NATIVE_NAT *)param;
2781 void *wait_handle = InitWaitUntilHostIPAddressChanged();
2782 // Validate arguments
2783 if (thread == NULL || param == NULL)
2784 {
2785 return;
2786 }
2787
2788 while (t->Halt == false)
2789 {
2790 NATIVE_STACK *a;
2791
2792 while (t->v->UseNat == false || t->v->HubOption == NULL || (t->v->HubOption->DisableKernelModeSecureNAT && t->v->HubOption->DisableIpRawModeSecureNAT))
2793 {
2794 if (t->Halt)
2795 {
2796 break;
2797 }
2798
2799 // If the NAT is disabled, wait until it becomes enabled
2800 Wait(t->HaltEvent, 1234);
2801 }
2802
2803 if (t->Halt)
2804 {
2805 break;
2806 }
2807
2808 // Get a next good native NAT stack
2809 Debug("NnGetNextInterface Start.\n");
2810
2811 NnClearQueue(t);
2812
2813 a = NnGetNextInterface(t);
2814
2815 if (a != NULL)
2816 {
2817 char macstr[64];
2818 // Acquisition success
2819 Debug("NnGetNextInterface Ok: %s\n", a->DeviceName);
2820
2821 t->IsRawIpMode = a->IsIpRawMode;
2822
2823 Lock(t->Lock);
2824 {
2825 if (a->Sock1 != NULL)
2826 {
2827 t->HaltTube = a->Sock2->RecvTube;
2828
2829 if (t->HaltTube != NULL)
2830 {
2831 AddRef(t->HaltTube->Ref);
2832 }
2833 }
2834 }
2835 Unlock(t->Lock);
2836
2837 NnClearQueue(t);
2838
2839 t->PublicIP = IPToUINT(&a->Ipc->ClientIPAddress);
2840 t->Active = true;
2841
2842
2843 Debug("NnMainLoop Start.\n");
2844 MacToStr(macstr, sizeof(macstr), a->Ipc->MacAddress);
2845 NLog(t->v, "LH_KERNEL_MODE_START", a->DeviceName,
2846 &a->Ipc->ClientIPAddress, &a->Ipc->SubnetMask, &a->Ipc->DefaultGateway, &a->Ipc->BroadcastAddress,
2847 macstr, &a->CurrentDhcpOptionList.ServerAddress, &a->DnsServerIP);
2848 NnMainLoop(t, a);
2849 Debug("NnMainLoop End.\n");
2850
2851 t->IsRawIpMode = false;
2852
2853 t->Active = false;
2854 t->PublicIP = 0;
2855
2856
2857 NnClearQueue(t);
2858
2859 // Close the stack
2860 Lock(t->Lock);
2861 {
2862 if (t->HaltTube != NULL)
2863 {
2864 ReleaseTube(t->HaltTube);
2865 t->HaltTube = NULL;
2866 }
2867 }
2868 Unlock(t->Lock);
2869 FreeNativeStack(a);
2870
2871 Zero(t->CurrentMacAddress, 6);
2872 }
2873 else
2874 {
2875 Debug("NnGetNextInterface Failed.\n");
2876 }
2877
2878 // Wait for a certain period of time
2879 if (t->NextWaitTimeForRetry != 0)
2880 {
2881 WaitUntilHostIPAddressChanged(wait_handle, t->HaltEvent, t->NextWaitTimeForRetry, 1000);
2882 }
2883 }
2884
2885 FreeWaitUntilHostIPAddressChanged(wait_handle);
2886 }
2887
2888 // Erase the contents of the queue for transmission and reception
NnClearQueue(NATIVE_NAT * t)2889 void NnClearQueue(NATIVE_NAT *t)
2890 {
2891 // Validate arguments
2892 if (t == NULL)
2893 {
2894 return;
2895 }
2896
2897 LockQueue(t->SendQueue);
2898 {
2899 while (true)
2900 {
2901 BLOCK *b = GetNext(t->SendQueue);
2902
2903 if (b == NULL)
2904 {
2905 break;
2906 }
2907
2908 FreeBlock(b);
2909 }
2910 }
2911 UnlockQueue(t->SendQueue);
2912
2913 LockQueue(t->RecvQueue);
2914 {
2915 while (true)
2916 {
2917 PKT *p = GetNext(t->RecvQueue);
2918
2919 if (p == NULL)
2920 {
2921 break;
2922 }
2923
2924 FreePacketWithData(p);
2925 }
2926 }
2927 UnlockQueue(t->RecvQueue);
2928 }
2929
2930 // Structure setting function to search for native NAT
NnSetNat(NATIVE_NAT_ENTRY * e,UINT protocol,UINT src_ip,UINT src_port,UINT dest_ip,UINT dest_port,UINT pub_ip,UINT pub_port)2931 void NnSetNat(NATIVE_NAT_ENTRY *e, UINT protocol, UINT src_ip, UINT src_port, UINT dest_ip, UINT dest_port, UINT pub_ip, UINT pub_port)
2932 {
2933 // Validate arguments
2934 if (e == NULL)
2935 {
2936 return;
2937 }
2938
2939 Zero(e, sizeof(NATIVE_NAT_ENTRY));
2940
2941 e->Protocol = protocol;
2942 e->SrcIp = src_ip;
2943 e->SrcPort = src_port;
2944 e->DestIp = dest_ip;
2945 e->DestPort = dest_port;
2946 e->PublicIp = pub_ip;
2947 e->PublicPort = pub_port;
2948 e->HashCodeForSend = e->HashCodeForRecv = INFINITE;
2949 }
2950
2951 // Get the hash code of the native NAT table (receiving direction)
GetHashNativeNatTableForRecv(void * p)2952 UINT GetHashNativeNatTableForRecv(void *p)
2953 {
2954 UINT r;
2955 NATIVE_NAT_ENTRY *e = (NATIVE_NAT_ENTRY *)p;
2956 if (e == NULL)
2957 {
2958 return 0;
2959 }
2960
2961 if (e->HashCodeForRecv != INFINITE)
2962 {
2963 return e->HashCodeForRecv;
2964 }
2965
2966 r = 0;
2967
2968 r += e->Protocol;
2969 r += e->PublicIp;
2970 r += e->PublicPort;
2971
2972 if (e->Protocol == NAT_TCP)
2973 {
2974 r += e->DestIp;
2975 r += e->DestPort;
2976 }
2977
2978 e->HashCodeForRecv = r;
2979
2980 return r;
2981 }
2982
2983 // Comparison function of native NAT table (receiving direction)
CmpNativeNatTableForRecv(void * p1,void * p2)2984 int CmpNativeNatTableForRecv(void *p1, void *p2)
2985 {
2986 int r;
2987 NATIVE_NAT_ENTRY *e1, *e2;
2988 if (p1 == NULL || p2 == NULL)
2989 {
2990 return 0;
2991 }
2992 e1 = *(NATIVE_NAT_ENTRY **)p1;
2993 e2 = *(NATIVE_NAT_ENTRY **)p2;
2994 if (e1 == NULL || e2 == NULL)
2995 {
2996 return 0;
2997 }
2998
2999 r = COMPARE_RET(e1->Protocol, e2->Protocol);
3000 if (r != 0)
3001 {
3002 return r;
3003 }
3004
3005 r = COMPARE_RET(e1->PublicIp, e2->PublicIp);
3006 if (r != 0)
3007 {
3008 return r;
3009 }
3010
3011 r = COMPARE_RET(e1->PublicPort, e2->PublicPort);
3012 if (r != 0)
3013 {
3014 return r;
3015 }
3016
3017 if (e1->Protocol == NAT_TCP)
3018 {
3019 r = COMPARE_RET(e1->DestIp, e2->DestIp);
3020 if (r != 0)
3021 {
3022 return r;
3023 }
3024
3025 r = COMPARE_RET(e1->DestPort, e2->DestPort);
3026 if (r != 0)
3027 {
3028 return r;
3029 }
3030 }
3031
3032 return 0;
3033 }
3034
3035 // Get the hash code of the native NAT table (transmit direction)
GetHashNativeNatTableForSend(void * p)3036 UINT GetHashNativeNatTableForSend(void *p)
3037 {
3038 UINT r;
3039 NATIVE_NAT_ENTRY *e = (NATIVE_NAT_ENTRY *)p;
3040 if (e == NULL)
3041 {
3042 return 0;
3043 }
3044
3045 if (e->HashCodeForSend != INFINITE)
3046 {
3047 return e->HashCodeForSend;
3048 }
3049
3050 r = 0;
3051
3052 r += e->Protocol;
3053 r += e->SrcIp;
3054 r += e->SrcPort;
3055
3056 if (e->Protocol == NAT_TCP)
3057 {
3058 r += e->DestIp;
3059 r += e->DestPort;
3060 }
3061
3062 e->HashCodeForSend = r;
3063
3064 return r;
3065 }
3066
3067 // Comparison function of native NAT table (transmit direction)
CmpNativeNatTableForSend(void * p1,void * p2)3068 int CmpNativeNatTableForSend(void *p1, void *p2)
3069 {
3070 int r;
3071 NATIVE_NAT_ENTRY *e1, *e2;
3072 if (p1 == NULL || p2 == NULL)
3073 {
3074 return 0;
3075 }
3076 e1 = *(NATIVE_NAT_ENTRY **)p1;
3077 e2 = *(NATIVE_NAT_ENTRY **)p2;
3078 if (e1 == NULL || e2 == NULL)
3079 {
3080 return 0;
3081 }
3082
3083 r = COMPARE_RET(e1->Protocol, e2->Protocol);
3084 if (r != 0)
3085 {
3086 return r;
3087 }
3088
3089 r = COMPARE_RET(e1->SrcIp, e2->SrcIp);
3090 if (r != 0)
3091 {
3092 return r;
3093 }
3094
3095 r = COMPARE_RET(e1->SrcPort, e2->SrcPort);
3096 if (r != 0)
3097 {
3098 return r;
3099 }
3100
3101 if (e1->Protocol == NAT_TCP)
3102 {
3103 r = COMPARE_RET(e1->DestIp, e2->DestIp);
3104 if (r != 0)
3105 {
3106 return r;
3107 }
3108
3109 r = COMPARE_RET(e1->DestPort, e2->DestPort);
3110 if (r != 0)
3111 {
3112 return r;
3113 }
3114 }
3115
3116 return 0;
3117 }
3118
3119 // Start the native NAT
NewNativeNat(VH * v)3120 NATIVE_NAT *NewNativeNat(VH *v)
3121 {
3122 NATIVE_NAT *t;
3123 // Validate arguments
3124 if (v == NULL)
3125 {
3126 return NULL;
3127 }
3128
3129 t = ZeroMalloc(sizeof(NATIVE_NAT));
3130
3131 t->v = v;
3132
3133 t->Cancel = v->Cancel;
3134 AddRef(t->Cancel->ref);
3135
3136 // Data structure initialization
3137 t->LastInterfaceIndex = INFINITE;
3138 t->SendQueue = NewQueue();
3139 t->RecvQueue = NewQueue();
3140 NnInitIpCombineList(t);
3141
3142 t->Lock = NewLock();
3143
3144 t->CancelLock = NewLock();
3145
3146 t->HaltEvent = NewEvent();
3147
3148 NewTubePair(&t->HaltTube2, &t->HaltTube3, 0);
3149
3150 // Create a NAT table
3151 t->NatTableForSend = NewHashList(GetHashNativeNatTableForSend, CmpNativeNatTableForSend, 11, true);
3152 t->NatTableForRecv = NewHashList(GetHashNativeNatTableForRecv, CmpNativeNatTableForRecv, 11, true);
3153
3154 t->Thread = NewThread(NativeNatThread, t);
3155
3156 return t;
3157 }
3158
3159 // Stop the native NAT
FreeNativeNat(NATIVE_NAT * t)3160 void FreeNativeNat(NATIVE_NAT *t)
3161 {
3162 TUBE *tube;
3163 UINT i;
3164 // Validate arguments
3165 if (t == NULL)
3166 {
3167 return;
3168 }
3169
3170 t->Halt = true;
3171
3172 Lock(t->Lock);
3173 {
3174 tube = t->HaltTube;
3175
3176 if (tube != NULL)
3177 {
3178 AddRef(tube->Ref);
3179 }
3180 }
3181 Unlock(t->Lock);
3182
3183 if (tube != NULL)
3184 {
3185 TubeFlushEx(tube, true);
3186
3187 SleepThread(100);
3188
3189 TubeDisconnect(tube);
3190
3191 ReleaseTube(tube);
3192 }
3193
3194 TubeDisconnect(t->HaltTube2);
3195 TubeDisconnect(t->HaltTube3);
3196
3197 Set(t->HaltEvent);
3198
3199 WaitThread(t->Thread, INFINITE);
3200
3201 ReleaseThread(t->Thread);
3202
3203 DeleteLock(t->Lock);
3204
3205 DeleteLock(t->CancelLock);
3206
3207 ReleaseEvent(t->HaltEvent);
3208
3209 ReleaseTube(t->HaltTube2);
3210 ReleaseTube(t->HaltTube3);
3211
3212 NnClearQueue(t);
3213
3214 ReleaseQueue(t->RecvQueue);
3215 ReleaseQueue(t->SendQueue);
3216
3217 ReleaseCancel(t->Cancel);
3218
3219 // Release the NAT table
3220 for (i = 0; i < LIST_NUM(t->NatTableForSend->AllList); i++)
3221 {
3222 NATIVE_NAT_ENTRY *e = LIST_DATA(t->NatTableForSend->AllList, i);
3223
3224 Free(e);
3225 }
3226
3227 ReleaseHashList(t->NatTableForSend);
3228 ReleaseHashList(t->NatTableForRecv);
3229
3230 NnFreeIpCombineList(t);
3231
3232 Free(t);
3233 }
3234
3235 // Take the log of Virtual Host
VLog(VH * v,char * str)3236 void VLog(VH *v, char *str)
3237 {
3238 // Not take!!
3239 return;
3240 }
3241
3242 // Disconnect the NAT entry immediately
DisconnectNatEntryNow(VH * v,NAT_ENTRY * e)3243 void DisconnectNatEntryNow(VH *v, NAT_ENTRY *e)
3244 {
3245 // Validate arguments
3246 if (v == NULL || e == NULL)
3247 {
3248 return;
3249 }
3250
3251 if (e->DisconnectNow == false)
3252 {
3253 e->DisconnectNow = true;
3254
3255 SetSockEvent(v->SockEvent);
3256 }
3257 }
3258
3259 // Get the NAT entry with specified source IP address and the oldest last communication time
GetOldestNatEntryOfIp(VH * v,UINT ip,UINT protocol)3260 NAT_ENTRY *GetOldestNatEntryOfIp(VH *v, UINT ip, UINT protocol)
3261 {
3262 UINT i;
3263 NAT_ENTRY *oldest = NULL;
3264 UINT64 oldest_tick = 0xFFFFFFFFFFFFFFFFULL;
3265 // Validate arguments
3266 if (v == NULL)
3267 {
3268 return NULL;
3269 }
3270
3271 for (i = 0; i < LIST_NUM(v->NatTable); i++)
3272 {
3273 NAT_ENTRY *e = LIST_DATA(v->NatTable, i);
3274
3275 if (e->DisconnectNow == false)
3276 {
3277 if (e->SrcIp == ip)
3278 {
3279 if (e->Protocol == protocol)
3280 {
3281 if (protocol != NAT_TCP || e->TcpStatus != NAT_TCP_CONNECTING)
3282 {
3283 if (e->LastCommTime <= oldest_tick)
3284 {
3285 oldest_tick = e->LastCommTime;
3286 oldest = e;
3287 }
3288 }
3289 }
3290 }
3291 }
3292 }
3293
3294 return oldest;
3295 }
3296
3297 // Get the number of current NAT entries per IP address
GetNumNatEntriesPerIp(VH * v,UINT ip,UINT protocol,bool tcp_syn_sent)3298 UINT GetNumNatEntriesPerIp(VH *v, UINT ip, UINT protocol, bool tcp_syn_sent)
3299 {
3300 UINT ret = 0;
3301 UINT i;
3302 // Validate arguments
3303 if (v == NULL)
3304 {
3305 return 0;
3306 }
3307
3308 for (i = 0; i < LIST_NUM(v->NatTable); i++)
3309 {
3310 NAT_ENTRY *e = LIST_DATA(v->NatTable, i);
3311
3312 if (e->DisconnectNow == false)
3313 {
3314 if (e->SrcIp == ip)
3315 {
3316 if (e->Protocol == protocol)
3317 {
3318 bool ok = false;
3319
3320 if (protocol == NAT_TCP)
3321 {
3322 if (tcp_syn_sent)
3323 {
3324 if (e->TcpStatus == NAT_TCP_CONNECTING)
3325 {
3326 ok = true;
3327 }
3328 }
3329 else
3330 {
3331 if (e->TcpStatus != NAT_TCP_CONNECTING)
3332 {
3333 ok = true;
3334 }
3335 }
3336 }
3337 else
3338 {
3339 ok = true;
3340 }
3341
3342 if (ok)
3343 {
3344 ret++;
3345 }
3346 }
3347 }
3348 }
3349 }
3350
3351 return ret;
3352 }
3353
3354 // Check whether the NAT is available
CanCreateNewNatEntry(VH * v)3355 bool CanCreateNewNatEntry(VH *v)
3356 {
3357 // Validate arguments
3358 if (v == NULL)
3359 {
3360 return false;
3361 }
3362
3363 if (v->UseNat == false)
3364 {
3365 // NAT stopped
3366 return false;
3367 }
3368
3369 if (NnIsActive(v) && v->NativeNat != NULL && v->NativeNat->NatTableForRecv != NULL)
3370 {
3371 if (v->NativeNat->NatTableForRecv->AllList->num_item > NAT_MAX_SESSIONS_KERNEL)
3372 {
3373 // Number of sessions exceeded (kernel mode)
3374 return false;
3375 }
3376 }
3377 else
3378 {
3379 if (v->NatTable->num_item > NAT_MAX_SESSIONS)
3380 {
3381 // Number of sessions exceeded (user mode)
3382 return false;
3383 }
3384 }
3385
3386 return true;
3387 }
3388
3389 // Set a pointer to the Virtual HUB options
NatSetHubOption(VH * v,HUB_OPTION * o)3390 void NatSetHubOption(VH *v, HUB_OPTION *o)
3391 {
3392 // Validate arguments
3393 if (v == NULL)
3394 {
3395 return;
3396 }
3397
3398 v->HubOption = o;
3399 }
3400
3401 // Get a pointer to the Virtual HUB options
NatGetHubOption(VH * v)3402 HUB_OPTION *NatGetHubOption(VH *v)
3403 {
3404 // Validate arguments
3405 if (v == NULL)
3406 {
3407 return NULL;
3408 }
3409
3410 return v->HubOption;
3411 }
3412
3413 // The main function of NAT processing thread
NatThreadMain(VH * v)3414 void NatThreadMain(VH *v)
3415 {
3416 bool halt_flag;
3417 // Validate arguments
3418 if (v == NULL)
3419 {
3420 return;
3421 }
3422
3423 v->TmpBuf = Malloc(NAT_TMPBUF_SIZE);
3424
3425 while (true)
3426 {
3427 // Wait until the next event is set
3428 WaitSockEvent(v->SockEvent, SELECT_TIME);
3429
3430 halt_flag = false;
3431
3432 LockVirtual(v);
3433 {
3434 // Process on all NAT sessions
3435 UINT i, num;
3436
3437 v->Now = Tick64();
3438 v->NatDoCancelFlag = false;
3439
3440 LIST_ELEMENT_DELETED:
3441 num = LIST_NUM(v->NatTable);
3442 for (i = 0; i < num; i++)
3443 {
3444 NAT_ENTRY *n = LIST_DATA(v->NatTable, i);
3445
3446 switch (n->Protocol)
3447 {
3448 case NAT_TCP: // TCP
3449 if (NatTransactTcp(v, n) == false)
3450 {
3451 goto LIST_ELEMENT_DELETED;
3452 }
3453 break;
3454
3455 case NAT_UDP: // UDP
3456 if (NatTransactUdp(v, n) == false)
3457 {
3458 goto LIST_ELEMENT_DELETED;
3459 }
3460 break;
3461
3462 case NAT_ICMP: // ICMP
3463 if (NatTransactIcmp(v, n) == false)
3464 {
3465 goto LIST_ELEMENT_DELETED;
3466 }
3467 break;
3468
3469 case NAT_DNS: // DNS
3470 if (NatTransactDns(v, n) == false)
3471 {
3472 goto LIST_ELEMENT_DELETED;
3473 }
3474 break;
3475 }
3476 }
3477
3478 if (v->NatDoCancelFlag)
3479 {
3480 // Hit the cancel of the parent thread
3481 Cancel(v->Cancel);
3482 }
3483
3484 // Halting flag check
3485 if (v->HaltNat)
3486 {
3487 halt_flag = true;
3488 }
3489 }
3490 UnlockVirtual(v);
3491
3492 if (halt_flag)
3493 {
3494 // Terminate the thread by disconnecting all entries forcibly
3495 LockVirtual(v);
3496 {
3497 UINT num = LIST_NUM(v->NatTable);
3498 NAT_ENTRY **nn = ToArray(v->NatTable);
3499 UINT i;
3500
3501 for (i = 0; i < num; i++)
3502 {
3503 NAT_ENTRY *n = nn[i];
3504 n->DisconnectNow = true;
3505
3506 switch (n->Protocol)
3507 {
3508 case NAT_TCP: // TCP
3509 NatTransactTcp(v, n);
3510 break;
3511
3512 case NAT_UDP: // UDP
3513 NatTransactUdp(v, n);
3514 break;
3515
3516 case NAT_ICMP: // ICMP
3517 NatTransactIcmp(v, n);
3518 break;
3519
3520 case NAT_DNS: // DNS
3521 NatTransactDns(v, n);
3522 break;
3523 }
3524 }
3525
3526 Free(nn);
3527 }
3528 UnlockVirtual(v);
3529 break;
3530 }
3531 }
3532
3533 Free(v->TmpBuf);
3534 }
3535
3536 // DNS: Thread to get the IP address
NatGetIPThread(THREAD * t,void * param)3537 void NatGetIPThread(THREAD *t, void *param)
3538 {
3539 NAT_DNS_QUERY *q;
3540 // Validate arguments
3541 if (t == NULL || param == NULL)
3542 {
3543 return;
3544 }
3545
3546 q = (NAT_DNS_QUERY *)param;
3547 AddWaitThread(t);
3548
3549 q->Ok = GetIP(&q->Ip, q->Hostname);
3550
3551 DelWaitThread(t);
3552
3553 if (Release(q->ref) == 0)
3554 {
3555 Free(q);
3556 }
3557 }
3558
3559 // DNS: Get an IP address from host name
NatGetIP(IP * ip,char * hostname)3560 bool NatGetIP(IP *ip, char *hostname)
3561 {
3562 TOKEN_LIST *t;
3563 bool ret = false;
3564 // Validate arguments
3565 if (ip == NULL || hostname == NULL)
3566 {
3567 return false;
3568 }
3569
3570 t = ParseToken(hostname, ".");
3571 if (t == NULL)
3572 {
3573 return false;
3574 }
3575 if (t->NumTokens == 0)
3576 {
3577 FreeToken(t);
3578 return false;
3579 }
3580
3581 if (t->NumTokens == 1)
3582 {
3583 ret = GetIP(ip, hostname);
3584 }
3585 else
3586 {
3587 char *hostname2 = t->Token[0];
3588 NAT_DNS_QUERY *q1, *q2;
3589 THREAD *t1, *t2;
3590
3591 q1 = ZeroMalloc(sizeof(NAT_DNS_QUERY));
3592 q2 = ZeroMalloc(sizeof(NAT_DNS_QUERY));
3593 q1->ref = NewRef();
3594 q2->ref = NewRef();
3595 AddRef(q1->ref);
3596 AddRef(q2->ref);
3597 StrCpy(q1->Hostname, sizeof(q1->Hostname), hostname);
3598 StrCpy(q2->Hostname, sizeof(q2->Hostname), hostname2);
3599
3600 t1 = NewThread(NatGetIPThread, q1);
3601 t2 = NewThread(NatGetIPThread, q2);
3602
3603 WaitThread(t1, NAT_DNS_QUERY_TIMEOUT);
3604
3605 if (q1->Ok)
3606 {
3607 ret = true;
3608 Copy(ip, &q1->Ip, sizeof(IP));
3609 }
3610 else
3611 {
3612 WaitThread(t2, NAT_DNS_QUERY_TIMEOUT);
3613 if (q1->Ok)
3614 {
3615 ret = true;
3616 Copy(ip, &q1->Ip, sizeof(IP));
3617 }
3618 else if (q2->Ok)
3619 {
3620 ret = true;
3621 Copy(ip, &q2->Ip, sizeof(IP));
3622 }
3623 }
3624
3625 ReleaseThread(t1);
3626 ReleaseThread(t2);
3627
3628 if (Release(q1->ref) == 0)
3629 {
3630 Free(q1);
3631 }
3632 if (Release(q2->ref) == 0)
3633 {
3634 Free(q2);
3635 }
3636 }
3637
3638 FreeToken(t);
3639
3640 return ret;
3641 }
3642
3643 // DNS query function
NatDnsThread(THREAD * t,void * param)3644 void NatDnsThread(THREAD *t, void *param)
3645 {
3646 NAT_ENTRY *n;
3647 IP ip;
3648 // Validate arguments
3649 if (t == NULL || param == NULL)
3650 {
3651 return;
3652 }
3653 n = (NAT_ENTRY *)param;
3654
3655 // Notify the initialization completion
3656 NoticeThreadInit(t);
3657
3658 // Run processing
3659 if (EndWith(n->DnsTargetHostName, ".in-addr.arpa") == false)
3660 {
3661 // Forward resolution
3662 if (NatGetIP(&ip, n->DnsTargetHostName))
3663 {
3664 // Forward resolution success
3665 Copy(&n->DnsResponseIp, &ip, sizeof(IP));
3666 n->DnsOk = true;
3667 }
3668 }
3669 else
3670 {
3671 // Reverse resolution
3672 IP ip;
3673 n->DnsGetIpFromHost = true; // Set the reverse resolution flag
3674 // Convert a *.in-addr.arpa string to an IP address
3675 if (ArpaToIP(&ip, n->DnsTargetHostName))
3676 {
3677 // Reverse resolution process
3678 char tmp[256];
3679 if (GetHostName(tmp, sizeof(tmp), &ip))
3680 {
3681 // Reverse resolution success
3682 n->DnsResponseHostName = CopyStr(tmp);
3683 n->DnsOk = true;
3684 }
3685 }
3686 }
3687
3688 // Notify the results
3689 n->DnsFinished = true;
3690
3691 SetSockEvent(n->v->SockEvent);
3692 }
3693
3694 // Convert a reverse resolution address to an IP address
ArpaToIP(IP * ip,char * str)3695 bool ArpaToIP(IP *ip, char *str)
3696 {
3697 TOKEN_LIST *token;
3698 bool ret = false;
3699 // Validate arguments
3700 if (ip == NULL || str == NULL)
3701 {
3702 return false;
3703 }
3704
3705 // Token conversion
3706 token = ParseToken(str, ".");
3707 if (token->NumTokens == 6)
3708 {
3709 // Convert the token [0, 1, 2, 3] to IP
3710 UINT i;
3711 ZeroIP4(ip);
3712 for (i = 0; i < IPV4_SIZE; ++i)
3713 {
3714 IPV4(ip->address)[i] = (UCHAR)ToInt(token->Token[3 - i]);
3715 }
3716 ret = true;
3717 }
3718
3719 FreeToken(token);
3720
3721 if (IPToUINT(ip) == 0)
3722 {
3723 ret = false;
3724 }
3725
3726 return ret;
3727 }
3728
3729 // Handle a DNS entry
NatTransactDns(VH * v,NAT_ENTRY * n)3730 bool NatTransactDns(VH *v, NAT_ENTRY *n)
3731 {
3732 // Validate arguments
3733 if (v == NULL || n == NULL)
3734 {
3735 return true;
3736 }
3737
3738 if (n->DisconnectNow)
3739 {
3740 goto DISCONNECT;
3741 }
3742
3743 if (n->DnsThread == NULL && n->DnsFinished == false)
3744 {
3745 // Create a thread
3746 THREAD *t = NewThread(NatDnsThread, (void *)n);
3747 WaitThreadInit(t);
3748 n->DnsThread = t;
3749 }
3750 else
3751 {
3752 // Wait for the result
3753 if (n->DnsFinished)
3754 {
3755 // Results have been received
3756 WaitThread(n->DnsThread, INFINITE);
3757 ReleaseThread(n->DnsThread);
3758 n->DnsThread = NULL;
3759 // Notify to the main thread
3760 v->NatDoCancelFlag = true;
3761 }
3762 }
3763
3764 return true;
3765
3766 DISCONNECT:
3767
3768 // Releasing process
3769 if (n->DnsThread != NULL)
3770 {
3771 WaitThread(n->DnsThread, INFINITE);
3772 ReleaseThread(n->DnsThread);
3773 n->DnsThread = NULL;
3774 }
3775
3776 if (n->DnsTargetHostName != NULL)
3777 {
3778 Free(n->DnsTargetHostName);
3779 n->DnsTargetHostName = NULL;
3780 }
3781
3782 if (n->DnsResponseHostName != NULL)
3783 {
3784 Free(n->DnsResponseHostName);
3785 n->DnsResponseHostName = NULL;
3786 }
3787
3788 DeleteLock(n->lock);
3789 Delete(v->NatTable, n);
3790 Free(n);
3791
3792 return false;
3793 }
3794
3795 // ICMP thread procedure
NatIcmpThreadProc(THREAD * thread,void * param)3796 void NatIcmpThreadProc(THREAD *thread, void *param)
3797 {
3798 NAT_ENTRY *n;
3799 ICMP_RESULT *ret = NULL;
3800 USHORT src_id = 0, src_seqno = 0;
3801 // Validate arguments
3802 if (thread == NULL || param == NULL)
3803 {
3804 return;
3805 }
3806
3807 n = (NAT_ENTRY *)param;
3808
3809 if (n->IcmpQueryBlock)
3810 {
3811 UCHAR *data = n->IcmpQueryBlock->Buf;
3812 UINT size = n->IcmpQueryBlock->Size;
3813
3814 if (size >= (sizeof(ICMP_HEADER) + sizeof(ICMP_ECHO)))
3815 {
3816 ICMP_HEADER *icmp = (ICMP_HEADER *)data;
3817 ICMP_ECHO *echo = (ICMP_ECHO *)(data + sizeof(ICMP_HEADER));
3818
3819 if (icmp->Type == ICMP_TYPE_ECHO_REQUEST && icmp->Code == 0)
3820 {
3821 UCHAR *icmp_payload = data + sizeof(ICMP_HEADER) + sizeof(ICMP_ECHO);
3822 UINT icmp_payload_size = size - sizeof(ICMP_HEADER) - sizeof(ICMP_ECHO);
3823 IP dest_ip;
3824
3825 src_id = Endian16(echo->Identifier);
3826 src_seqno = Endian16(echo->SeqNo);
3827
3828 UINTToIP(&dest_ip, n->DestIp);
3829
3830 // Send a query by using the ICMP API
3831 ret = IcmpApiEchoSend(&dest_ip, n->IcmpQueryBlock->Ttl,
3832 icmp_payload, icmp_payload_size, NAT_ICMP_TIMEOUT_WITH_API);
3833 }
3834 }
3835 }
3836
3837 if (ret != NULL && ret->Timeout == false)
3838 {
3839 // Convert to an IPv4 + ICMP packet since the result of ICMP API was obtained
3840 IPV4_HEADER ipv4;
3841 ICMP_HEADER icmp;
3842 ICMP_ECHO echo;
3843 BUF *buf = NewBuf();
3844
3845 // IPv4 header
3846 Zero(&ipv4, sizeof(ipv4));
3847 IPV4_SET_VERSION(&ipv4, 4);
3848 IPV4_SET_HEADER_LEN(&ipv4, sizeof(IPV4_HEADER) / 4);
3849 ipv4.TimeToLive = ret->Ttl;
3850 ipv4.Protocol = IP_PROTO_ICMPV4;
3851 ipv4.SrcIP = IPToUINT(&ret->IpAddress);
3852 ipv4.DstIP = 0x01010101;
3853
3854
3855 // ICMP header
3856 Zero(&icmp, sizeof(icmp));
3857 Zero(&echo, sizeof(echo));
3858
3859 if (ret->Ok)
3860 {
3861 // Normal response
3862 echo.Identifier = Endian16(src_id);
3863 echo.SeqNo = Endian16(src_seqno);
3864
3865 ipv4.TotalLength = Endian16((USHORT)(sizeof(ipv4) + sizeof(icmp) + sizeof(echo) + ret->DataSize));
3866
3867 WriteBuf(buf, &ipv4, sizeof(ipv4));
3868 WriteBuf(buf, &icmp, sizeof(icmp));
3869 WriteBuf(buf, &echo, sizeof(echo));
3870 WriteBuf(buf, ret->Data, ret->DataSize);
3871 }
3872 else
3873 {
3874 // Error reply
3875 icmp.Type = ret->Type;
3876 icmp.Code = ret->Code;
3877 echo.Identifier = Endian16(src_id);
3878 echo.SeqNo = Endian16(src_seqno);
3879
3880 ipv4.TotalLength = Endian16((USHORT)(sizeof(ipv4) + sizeof(icmp) + sizeof(echo) + n->IcmpOriginalCopySize));
3881
3882 WriteBuf(buf, &ipv4, sizeof(ipv4));
3883 WriteBuf(buf, &icmp, sizeof(icmp));
3884 WriteBuf(buf, &echo, sizeof(echo));
3885
3886 // Copy of the original packet to be included in the response packet
3887 WriteBuf(buf, n->IcmpOriginalCopy, n->IcmpOriginalCopySize);
3888 }
3889
3890 n->IcmpResponseBlock = NewBlock(Clone(buf->Buf, buf->Size), buf->Size, 0);
3891 n->IcmpResponseBlock->Ttl = ret->Ttl;
3892
3893 FreeBuf(buf);
3894 }
3895 IcmpApiFreeResult(ret);
3896
3897 // Inform the completion of the processing
3898 n->IcmpTaskFinished = true;
3899 SetSockEvent(n->v->SockEvent);
3900 }
3901
3902 // Process ICMP entry
NatTransactIcmp(VH * v,NAT_ENTRY * n)3903 bool NatTransactIcmp(VH *v, NAT_ENTRY *n)
3904 {
3905 void *buf;
3906 UINT recv_size;
3907 BLOCK *block;
3908 IP dest_ip;
3909 UINT num_ignore_errors = 0;
3910 UINT dest_port = 0;
3911 // Validate arguments
3912 if (v == NULL || n == NULL)
3913 {
3914 return true;
3915 }
3916
3917 dest_port = n->DestPort;
3918
3919 if (n->DisconnectNow)
3920 {
3921 goto DISCONNECT;
3922 }
3923
3924 if (v->IcmpRawSocketOk)
3925 {
3926 // Environment that the Raw sockets are available
3927 if (n->UdpSocketCreated == false)
3928 {
3929 // Create a UDP socket
3930 n->Sock = NewUDP(MAKE_SPECIAL_PORT(IP_PROTO_ICMPV4));
3931 if (n->Sock == NULL)
3932 {
3933 // Socket creation failure
3934 goto DISCONNECT;
3935 }
3936 else
3937 {
3938 n->PublicIp = IPToUINT(&n->Sock->LocalIP);
3939 n->PublicPort = n->Sock->LocalPort;
3940
3941 JoinSockToSockEvent(n->Sock, v->SockEvent);
3942 n->UdpSocketCreated = true;
3943 }
3944 }
3945 }
3946 else
3947 {
3948 // Create a thread for using ICMP API if Raw sockets are not available
3949 if (n->IcmpThread == NULL)
3950 {
3951 if (n->UdpSendQueue->num_item >= 1)
3952 {
3953 // Since UdpSendQueue contains only 1 query, get a first query
3954 // and create a thread and pass the query to the thread
3955 BLOCK *block = GetNext(n->UdpSendQueue);
3956
3957 n->IcmpQueryBlock = block;
3958
3959 n->IcmpThread = NewThread(NatIcmpThreadProc, n);
3960 }
3961 }
3962
3963 if (n->IcmpTaskFinished)
3964 {
3965 if (n->IcmpResponseBlock != NULL)
3966 {
3967 // Because there was a response from the thread that calls ICMP API, pass this result to the stack
3968 block = n->IcmpResponseBlock;
3969 n->IcmpResponseBlock = NULL;
3970 InsertQueue(n->UdpRecvQueue, block);
3971 v->NatDoCancelFlag = true;
3972 n->LastCommTime = v->Now;
3973 }
3974 else
3975 {
3976 // Disconnect immediately when it fails
3977 goto DISCONNECT;
3978 }
3979 }
3980
3981 // Examine whether this session timed-out
3982 if ((n->LastCommTime + (UINT64)NAT_ICMP_TIMEOUT_WITH_API) < v->Now || n->LastCommTime > v->Now)
3983 {
3984 // Time-out
3985 goto DISCONNECT;
3986 }
3987
3988 return true;
3989 }
3990
3991 // Following are processed only for if the raw sockets are available
3992 buf = v->TmpBuf;
3993 UINTToIP(&dest_ip, n->DestIp);
3994
3995 // Try to receive data from the UDP socket
3996 while (true)
3997 {
3998 IP src_ip;
3999 UINT src_port;
4000 recv_size = RecvFrom(n->Sock, &src_ip, &src_port, buf, 65536);
4001
4002 if (recv_size == SOCK_LATER)
4003 {
4004 // Packet has not arrived
4005 break;
4006 }
4007 else if (recv_size == 0)
4008 {
4009 Debug("ICMP ERROR\n");
4010 // Error?
4011 if (n->Sock->IgnoreRecvErr == false)
4012 {
4013 // A fatal error occurred
4014 goto DISCONNECT;
4015 }
4016 else
4017 {
4018 if ((num_ignore_errors++) >= MAX_NUM_IGNORE_ERRORS)
4019 {
4020 goto DISCONNECT;
4021 }
4022 }
4023 }
4024 else
4025 {
4026 // Analyze the arriving packet
4027 ICMP_RESULT *ret = IcmpParseResult(&dest_ip, n->SrcPort, 0, buf, recv_size);
4028
4029 if (ret != NULL)
4030 {
4031 if ((ret->Ok && CmpIpAddr(&ret->IpAddress, &dest_ip) == 0) ||
4032 (ret->DataSize >= sizeof(IPV4_HEADER) && ((IPV4_HEADER *)ret->Data)->DstIP == n->DestIp))
4033 {
4034 // Insert to the queue
4035 void *data = Malloc(recv_size);
4036 Copy(data, buf, recv_size);
4037 block = NewBlock(data, recv_size, 0);
4038 InsertQueue(n->UdpRecvQueue, block);
4039 v->NatDoCancelFlag = true;
4040 n->LastCommTime = v->Now;
4041 }
4042
4043 IcmpFreeResult(ret);
4044 }
4045 }
4046 }
4047
4048 // Try to send data to the UDP socket
4049 while (block = GetNext(n->UdpSendQueue))
4050 {
4051 // Assemble the Echo header and ICMP header
4052 UINT send_size;
4053
4054 SetTtl(n->Sock, block->Ttl);
4055 send_size = SendTo(n->Sock, &dest_ip, dest_port, block->Buf, block->Size);
4056
4057 FreeBlock(block);
4058 if (send_size == 0)
4059 {
4060 Debug("ICMP ERROR\n");
4061 // Determine whether a fatal error
4062 if (n->Sock->IgnoreSendErr == false)
4063 {
4064 // A fatal error occurred
4065 goto DISCONNECT;
4066 }
4067 }
4068 else
4069 {
4070 n->LastCommTime = v->Now;
4071 }
4072 }
4073
4074 // Examine whether this session timed-out
4075 if ((n->LastCommTime + (UINT64)NAT_ICMP_TIMEOUT) < v->Now || n->LastCommTime > v->Now)
4076 {
4077 // Time-out
4078 goto DISCONNECT;
4079 }
4080
4081 return true;
4082
4083 DISCONNECT:
4084 // Disconnect this session
4085 if (n->UdpSocketCreated)
4086 {
4087 // Close the socket
4088 Disconnect(n->Sock);
4089 ReleaseSock(n->Sock);
4090 n->Sock = NULL;
4091 }
4092
4093 // Terminate if the thread has been created
4094 if (n->IcmpThread != NULL)
4095 {
4096 WaitThread(n->IcmpThread, INFINITE);
4097 ReleaseThread(n->IcmpThread);
4098 n->IcmpThread = NULL;
4099 }
4100
4101 // Delete the entry
4102 DeleteNatIcmp(v, n);
4103
4104 return false;
4105 }
4106
4107 // Process the UDP entry
NatTransactUdp(VH * v,NAT_ENTRY * n)4108 bool NatTransactUdp(VH *v, NAT_ENTRY *n)
4109 {
4110 void *buf;
4111 UINT recv_size;
4112 BLOCK *block;
4113 IP dest_ip;
4114 UINT num_ignore_errors;
4115 UINT dest_port = 0;
4116 // Validate arguments
4117 if (v == NULL || n == NULL)
4118 {
4119 return true;
4120 }
4121
4122 dest_port = n->DestPort;
4123
4124 if (n->DisconnectNow)
4125 {
4126 goto DISCONNECT;
4127 }
4128
4129 if (n->UdpSocketCreated == false)
4130 {
4131 // Create a UDP socket
4132 n->Sock = NewUDP(0);
4133 if (n->Sock == NULL)
4134 {
4135 // Socket creation failure
4136 goto DISCONNECT;
4137 }
4138 else
4139 {
4140 n->PublicIp = IPToUINT(&n->Sock->LocalIP);
4141 n->PublicPort = n->Sock->LocalPort;
4142
4143 JoinSockToSockEvent(n->Sock, v->SockEvent);
4144 n->UdpSocketCreated = true;
4145 }
4146 }
4147
4148 buf = v->TmpBuf;
4149 if (n->ProxyDns == false)
4150 {
4151 UINTToIP(&dest_ip, n->DestIp);
4152 }
4153 else
4154 {
4155 UINTToIP(&dest_ip, n->DestIpProxy);
4156 }
4157
4158 num_ignore_errors = 0;
4159
4160 // Try to receive data from the UDP socket
4161 while (true)
4162 {
4163 IP src_ip;
4164 UINT src_port;
4165 recv_size = RecvFrom(n->Sock, &src_ip, &src_port, buf, 65536);
4166
4167 if (recv_size == SOCK_LATER)
4168 {
4169 // Packet has not arrived
4170 break;
4171 }
4172 else if (recv_size == 0)
4173 {
4174 // Error?
4175 if (n->Sock->IgnoreRecvErr == false)
4176 {
4177 // A fatal error occurred
4178 goto DISCONNECT;
4179 }
4180 else
4181 {
4182 if ((num_ignore_errors++) > MAX_NUM_IGNORE_ERRORS)
4183 {
4184 goto DISCONNECT;
4185 }
4186 }
4187 }
4188 else
4189 {
4190 // Packet arrives. Check the source IP
4191 if (IPToUINT(&src_ip) == n->DestIp || n->DestIp == 0xFFFFFFFF || (IPToUINT(&src_ip) == n->DestIpProxy && n->ProxyDns) && src_port == n->DestPort)
4192 {
4193 // Insert to the queue
4194 void *data = Malloc(recv_size);
4195 Copy(data, buf, recv_size);
4196 block = NewBlock(data, recv_size, 0);
4197
4198 if (block != NULL)
4199 {
4200 if (src_port == SPECIAL_UDP_PORT_WSD || src_port == SPECIAL_UDP_PORT_SSDP)
4201 {
4202 // Make believe there is a response from the host really in the case of WSD packet
4203 block->Param1 = IPToUINT(&src_ip);
4204 }
4205 }
4206
4207 InsertQueue(n->UdpRecvQueue, block);
4208 v->NatDoCancelFlag = true;
4209 n->LastCommTime = v->Now;
4210 }
4211 }
4212 }
4213
4214 // Try to send data to the UDP socket
4215 while (block = GetNext(n->UdpSendQueue))
4216 {
4217 UINT send_size;
4218 bool is_nbtdgm = false;
4219 LIST *local_ip_list = NULL;
4220
4221 if (dest_port == SPECIAL_UDP_PORT_NBTDGM)
4222 {
4223 // Determine whether NetBIOS Datagram packet
4224 NBTDG_HEADER *nh = (NBTDG_HEADER *)block->Buf;
4225
4226 if (nh != NULL && block->Size >= sizeof(NBTDG_HEADER))
4227 {
4228 if (nh->SrcIP == n->SrcIp && Endian16(nh->SrcPort) == n->SrcPort)
4229 {
4230 local_ip_list = GetHostIPAddressList();
4231
4232 if (local_ip_list != NULL)
4233 {
4234 is_nbtdgm = true;
4235 }
4236 }
4237 }
4238 }
4239
4240 if (is_nbtdgm == false)
4241 {
4242 // Normal UDP packet
4243 send_size = SendTo(n->Sock, &dest_ip, dest_port, block->Buf, block->Size);
4244 }
4245 else
4246 {
4247 // IP address and port number is embedded in the NetBIOS Datagram Packet.
4248 // Transfer by rewriting it properly
4249 UINT i;
4250
4251 for (i = 0; i < LIST_NUM(local_ip_list); i++)
4252 {
4253 IP *my_ip = LIST_DATA(local_ip_list, i);
4254
4255 if (IsIP4(my_ip) && IsZeroIp(my_ip) == false && IsLocalHostIP(my_ip) == false)
4256 {
4257 NBTDG_HEADER *nh = (NBTDG_HEADER *)block->Buf;
4258
4259 nh->SrcIP = IPToUINT(my_ip);
4260 nh->SrcPort = Endian16(n->PublicPort);
4261
4262 send_size = SendTo(n->Sock, &dest_ip, dest_port, block->Buf, block->Size);
4263 }
4264 }
4265 }
4266
4267 if (local_ip_list != NULL)
4268 {
4269 FreeHostIPAddressList(local_ip_list);
4270 }
4271
4272 FreeBlock(block);
4273 if (send_size == 0)
4274 {
4275 // Determining whether a fatal error
4276 if (n->Sock->IgnoreSendErr == false)
4277 {
4278 // A fatal error occurred
4279 goto DISCONNECT;
4280 }
4281 }
4282 else
4283 {
4284 n->LastCommTime = v->Now;
4285 }
4286 }
4287
4288 // Examine whether this session timed-out
4289 if ((n->LastCommTime + (UINT64)v->NatUdpTimeout) < v->Now || n->LastCommTime > v->Now)
4290 {
4291 // Time-out
4292 goto DISCONNECT;
4293 }
4294
4295 return true;
4296
4297 DISCONNECT:
4298 // Disconnect this session
4299 if (n->UdpSocketCreated)
4300 {
4301 // Close the socket
4302 Disconnect(n->Sock);
4303 ReleaseSock(n->Sock);
4304 n->Sock = NULL;
4305 }
4306
4307 // Delete the entry
4308 DeleteNatUdp(v, n);
4309
4310 return false;
4311 }
4312
4313 // Thread to make a connection to the TCP host
NatTcpConnectThread(THREAD * t,void * p)4314 void NatTcpConnectThread(THREAD *t, void *p)
4315 {
4316 NAT_ENTRY *n = (NAT_ENTRY *)p;
4317 IP ip;
4318 char hostname[MAX_SIZE];
4319 UINT port_number;
4320 SOCK *sock;
4321 SOCK_EVENT *e;
4322 // Validate arguments
4323 if (n == NULL || t == NULL)
4324 {
4325 return;
4326 }
4327
4328 UINTToIP(&ip, n->DestIp);
4329 IPToStr(hostname, sizeof(hostname), &ip);
4330 port_number = n->DestPort;
4331 e = n->v->SockEvent;
4332 AddRef(e->ref);
4333
4334 // Notify the initialization completion
4335 NoticeThreadInit(t);
4336
4337 // Attempt to connect to the TCP host
4338 Debug("NatTcpConnect Connecting to %s:%u\n", hostname, port_number);
4339 sock = ConnectEx3(hostname, port_number, 0, &n->NatTcpCancelFlag, NULL, NULL, false, true);
4340 if (sock == NULL)
4341 {
4342 // Connection failure
4343 n->TcpMakeConnectionFailed = true;
4344 }
4345 else
4346 {
4347 // Successful connection
4348 n->TcpMakeConnectionSucceed = true;
4349 }
4350 n->Sock = sock;
4351 JoinSockToSockEvent(sock, e);
4352 SetSockEvent(e);
4353
4354 ReleaseSockEvent(e);
4355 }
4356
4357 // Create a thread for trying to connect to the TCP host
CreateNatTcpConnectThread(VH * v,NAT_ENTRY * n)4358 void CreateNatTcpConnectThread(VH *v, NAT_ENTRY *n)
4359 {
4360 // Validate arguments
4361 if (v == NULL || n == NULL)
4362 {
4363 return;
4364 }
4365
4366 // Create a thread
4367 n->NatTcpConnectThread = NewThread(NatTcpConnectThread, (void *)n);
4368
4369 // Wait for a thread initialization completion
4370 WaitThreadInit(n->NatTcpConnectThread);
4371 }
4372
4373 // Handle the TCP entry
NatTransactTcp(VH * v,NAT_ENTRY * n)4374 bool NatTransactTcp(VH *v, NAT_ENTRY *n)
4375 {
4376 char str[MAX_SIZE];
4377 bool timeouted = false;
4378 // Validate arguments
4379 if (v == NULL || n == NULL)
4380 {
4381 return false;
4382 }
4383
4384 if (n->DisconnectNow)
4385 {
4386 goto DISCONNECT;
4387 }
4388
4389 // Process by state of the TCP
4390 switch (n->TcpStatus)
4391 {
4392 case NAT_TCP_CONNECTING: // Waiting for connection
4393 if (n->NatTcpConnectThread == NULL)
4394 {
4395 // Start a connection by creating a connection thread
4396 CreateNatTcpConnectThread(v, n);
4397 }
4398 else
4399 {
4400 // Wait for the result of the connection thread that has already started
4401 if (n->TcpMakeConnectionFailed || n->TcpMakeConnectionSucceed)
4402 {
4403 // Use the results because operation thread has already finished
4404 WaitThread(n->NatTcpConnectThread, INFINITE);
4405 ReleaseThread(n->NatTcpConnectThread);
4406 n->NatTcpConnectThread = NULL;
4407
4408 if (n->TcpMakeConnectionSucceed)
4409 {
4410 // Connection is successful, and a Sock was created
4411 n->TcpStatus = NAT_TCP_CONNECTED;
4412 IPToStr32(str, sizeof(str), n->DestIp);
4413 NLog(v, "LH_NAT_TCP_SUCCEED", n->Id, n->Sock->RemoteHostname, str, n->DestPort);
4414 }
4415 else
4416 {
4417 // Failed to connect
4418 n->TcpStatus = NAT_TCP_SEND_RESET;
4419 IPToStr32(str, sizeof(str), n->DestIp);
4420 NLog(v, "LH_NAT_TCP_FAILED", n->Id, str, n->DestPort);
4421 }
4422 v->NatDoCancelFlag = true;
4423 }
4424 }
4425 break;
4426
4427 case NAT_TCP_CONNECTED: // TCP socket connection completed. Negotiating with the client host
4428 break;
4429
4430 case NAT_TCP_SEND_RESET: // TCP communication disconnection: Send a RST to the client host
4431 break;
4432
4433 case NAT_TCP_ESTABLISHED: // TCP connection established
4434 {
4435 UINT old_send_fifo_size = 0;
4436
4437 // Transmit to the socket if there is data in the receive buffer
4438 while (n->RecvFifo->size > 0)
4439 {
4440 UINT sent_size = Send(n->Sock, ((UCHAR *)n->RecvFifo->p) + n->RecvFifo->pos,
4441 n->RecvFifo->size, false);
4442 if (sent_size == 0)
4443 {
4444 // Communication has been disconnected
4445 n->TcpFinished = true;
4446 v->NatDoCancelFlag = true;
4447 break;
4448 }
4449 else if (sent_size == SOCK_LATER)
4450 {
4451 // Blocking
4452 break;
4453 }
4454 else
4455 {
4456 // Successful transmission
4457 ReadFifo(n->RecvFifo, NULL, sent_size);
4458 n->SendAckNext = true;
4459
4460 if (false)
4461 {
4462 IP ip;
4463
4464 n->test_TotalSent += sent_size;
4465
4466 UINTToIP(&ip, n->DestIp);
4467 Debug("TCP %u: %r:%u %u\n", n->Id, &ip, n->DestPort, (UINT)n->test_TotalSent);
4468 }
4469 }
4470 }
4471
4472 old_send_fifo_size = FifoSize(n->SendFifo);
4473
4474 // Write to the transmission buffer by obtaining data from the socket
4475 while (true)
4476 {
4477 void *buf = (void *)v->TmpBuf;
4478 UINT want_to_recv_size = 0;
4479 UINT recv_size;
4480 // Calculate the size of wanting to receive
4481 if (n->SendFifo->size < NAT_SEND_BUF_SIZE)
4482 {
4483 // Still can receive
4484 want_to_recv_size = MIN(NAT_SEND_BUF_SIZE - n->SendFifo->size, NAT_TMPBUF_SIZE);
4485 }
4486 if (want_to_recv_size == 0)
4487 {
4488 SetNoNeedToRead(n->Sock);
4489 break;
4490 }
4491 recv_size = Recv(n->Sock, buf, want_to_recv_size, false);
4492 if (recv_size == 0)
4493 {
4494 // Communication has been disconnected
4495 n->TcpFinished = true;
4496 v->NatDoCancelFlag = true;
4497 if (n->TcpDisconnected == false)
4498 {
4499 Disconnect(n->Sock);
4500 n->TcpDisconnected = true;
4501 }
4502 break;
4503 }
4504 else if (recv_size == SOCK_LATER)
4505 {
4506 // Blocking
4507 break;
4508 }
4509 else
4510 {
4511 // Successful reception
4512 WriteFifo(n->SendFifo, buf, recv_size);
4513 v->NatDoCancelFlag = true;
4514 }
4515 }
4516
4517 if (old_send_fifo_size == 0 && FifoSize(n->SendFifo) != 0)
4518 {
4519 // Reset the time data for timeout when the data is newly queued
4520 // in the empty transmission buffer in the transmission process
4521 n->TcpLastRecvAckTime = v->Now;
4522 }
4523
4524 // Raise a transmission time-out if a certain period of time elapsed
4525 // after receiving the last ACK, and the transmission buffer is not
4526 // empty, and the reception window size of other party is not 0
4527 if ((n->TcpLastRecvAckTime + (UINT64)VIRTUAL_TCP_SEND_TIMEOUT) < v->Now)
4528 {
4529 if (FifoSize(n->SendFifo) != 0 && n->TcpSendWindowSize != 0)
4530 {
4531 timeouted = true;
4532 }
4533 }
4534 }
4535 break;
4536
4537 }
4538
4539 // Timeout Detection
4540 if ((n->LastCommTime + (UINT64)v->NatTcpTimeout) < v->Now || n->LastCommTime > v->Now)
4541 {
4542 timeouted = true;
4543 }
4544
4545 if (timeouted)
4546 {
4547 // Time-out occurs, the session close
4548 n->TcpStatus = NAT_TCP_SEND_RESET;
4549 v->NatDoCancelFlag = true;
4550 }
4551
4552 return true;
4553
4554 DISCONNECT: // Disconnect and session disposal
4555 DeleteNatTcp(v, n);
4556
4557 return false;
4558 }
4559
4560 // Delete the entry of TCP NAT
DeleteNatTcp(VH * v,NAT_ENTRY * n)4561 void DeleteNatTcp(VH *v, NAT_ENTRY *n)
4562 {
4563 // Validate arguments
4564 if (v == NULL || n == NULL)
4565 {
4566 return;
4567 }
4568
4569 NLog(v, "LH_NAT_TCP_DELETED", n->Id);
4570
4571 // Shutdown of connection thread
4572 if (n->NatTcpConnectThread != NULL)
4573 {
4574 n->NatTcpCancelFlag = true;
4575
4576 WaitThread(n->NatTcpConnectThread, INFINITE);
4577 ReleaseThread(n->NatTcpConnectThread);
4578 n->NatTcpConnectThread = NULL;
4579 }
4580 if (n->Sock != NULL)
4581 {
4582 // Disconnect the socket
4583 Disconnect(n->Sock);
4584 ReleaseSock(n->Sock);
4585 n->Sock = NULL;
4586 }
4587
4588 // Release the window memory
4589 if (n->TcpRecvWindow != NULL)
4590 {
4591 ReleaseFifo(n->TcpRecvWindow);
4592 n->TcpRecvWindow = NULL;
4593 }
4594
4595 // Release the window reception list
4596 if (n->TcpRecvList != NULL)
4597 {
4598 UINT i;
4599 for (i = 0; i < LIST_NUM(n->TcpRecvList); i++)
4600 {
4601 IP_PART *p = LIST_DATA(n->TcpRecvList, i);
4602 Free(p);
4603 }
4604 ReleaseList(n->TcpRecvList);
4605 n->TcpRecvList = NULL;
4606 }
4607
4608 // FIFO release
4609 ReleaseFifo(n->SendFifo);
4610 ReleaseFifo(n->RecvFifo);
4611
4612 // Delete from the NAT entry
4613 Delete(v->NatTable, n);
4614
4615 DeleteLock(n->lock);
4616
4617 // Release the memory
4618 Free(n);
4619
4620 Debug("NAT_ENTRY: DeleteNatTcp\n");
4621 }
4622
4623 // NAT processing thread
NatThread(THREAD * t,void * param)4624 void NatThread(THREAD *t, void *param)
4625 {
4626 // Validate arguments
4627 if (t == NULL || param == NULL)
4628 {
4629 return;
4630 }
4631
4632 // Notify the initialization completion
4633 NoticeThreadInit(t);
4634
4635 NatThreadMain((VH *)param);
4636 }
4637
4638 // Send a beacon packet
SendBeacon(VH * v)4639 void SendBeacon(VH *v)
4640 {
4641 UINT dest_ip;
4642 ARPV4_HEADER arp;
4643 static char beacon_str[] =
4644 "SecureNAT Virtual TCP/IP Stack Beacon";
4645 // Validate arguments
4646 if (v == NULL)
4647 {
4648 return;
4649 }
4650
4651 // Send an UDP
4652 dest_ip = (v->HostIP & v->HostMask) | (~v->HostMask);
4653 SendUdp(v, dest_ip, 7, v->HostIP, 7, beacon_str, sizeof(beacon_str));
4654
4655 // Build the ARP header
4656 arp.HardwareType = Endian16(ARP_HARDWARE_TYPE_ETHERNET);
4657 arp.ProtocolType = Endian16(MAC_PROTO_IPV4);
4658 arp.HardwareSize = 6;
4659 arp.ProtocolSize = 4;
4660 arp.Operation = Endian16(ARP_OPERATION_RESPONSE);
4661 Copy(arp.SrcAddress, v->MacAddress, 6);
4662 arp.SrcIP = v->HostIP;
4663 arp.TargetAddress[0] =
4664 arp.TargetAddress[1] =
4665 arp.TargetAddress[2] =
4666 arp.TargetAddress[3] =
4667 arp.TargetAddress[4] =
4668 arp.TargetAddress[5] = 0xff;
4669 arp.TargetIP = dest_ip;
4670
4671 // Transmission
4672 VirtualLayer2Send(v, broadcast, v->MacAddress, MAC_PROTO_ARPV4, &arp, sizeof(arp));
4673 }
4674
4675 // Send a TCP packet
SendTcp(VH * v,UINT src_ip,UINT src_port,UINT dest_ip,UINT dest_port,UINT seq,UINT ack,UINT flag,UINT window_size,UINT mss,void * data,UINT size)4676 void SendTcp(VH *v, UINT src_ip, UINT src_port, UINT dest_ip, UINT dest_port, UINT seq, UINT ack, UINT flag, UINT window_size, UINT mss, void *data, UINT size)
4677 {
4678 static UCHAR tcp_mss_option[] = {0x02, 0x04, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00};
4679 IPV4_PSEUDO_HEADER *vh;
4680 TCP_HEADER *tcp;
4681 UINT header_size = TCP_HEADER_SIZE;
4682 UINT total_size;
4683 // Validate arguments
4684 if (v == NULL || (size != 0 && data == NULL))
4685 {
4686 return;
4687 }
4688
4689 // Memory allocation
4690 vh = Malloc(sizeof(IPV4_PSEUDO_HEADER) + TCP_HEADER_SIZE + size + 32);
4691 tcp = (TCP_HEADER *)(((UCHAR *)vh) + sizeof(IPV4_PSEUDO_HEADER));
4692
4693 if (mss != 0)
4694 {
4695 USHORT *mss_size;
4696 mss_size = (USHORT *)(&tcp_mss_option[2]);
4697 *mss_size = Endian16((USHORT)mss);
4698 header_size += sizeof(tcp_mss_option);
4699 }
4700
4701 total_size = header_size + size;
4702 if (total_size > 65536)
4703 {
4704 // Packet is too long
4705 Free(vh);
4706 return;
4707 }
4708
4709 // Pseudo header generation
4710 vh->SrcIP = src_ip;
4711 vh->DstIP = dest_ip;
4712 vh->Reserved = 0;
4713 vh->Protocol = IP_PROTO_TCP;
4714 vh->PacketLength = Endian16((USHORT)total_size);
4715
4716 // TCP header generation
4717 tcp->SrcPort = Endian16((USHORT)src_port);
4718 tcp->DstPort = Endian16((USHORT)dest_port);
4719 tcp->SeqNumber = Endian32(seq);
4720 tcp->AckNumber = Endian32(ack);
4721 tcp->HeaderSizeAndReserved = 0;
4722 TCP_SET_HEADER_SIZE(tcp, (UCHAR)(header_size / 4));
4723 tcp->Flag = (UCHAR)flag;
4724 tcp->WindowSize = Endian16((USHORT)window_size);
4725 tcp->Checksum = 0;
4726 tcp->UrgentPointer = 0;
4727
4728 // Copy the option values
4729 if (mss != 0)
4730 {
4731 Copy(((UCHAR *)tcp) + TCP_HEADER_SIZE, tcp_mss_option, sizeof(tcp_mss_option));
4732 }
4733
4734 // Data copy
4735 Copy(((UCHAR *)tcp) + header_size, data, size);
4736
4737 // Checksum calculation
4738 tcp->Checksum = IpChecksum(vh, total_size + 12);
4739
4740 // Submit as an IP packet
4741 SendIp(v, dest_ip, src_ip, IP_PROTO_TCP, tcp, total_size);
4742
4743 // Release the memory
4744 Free(vh);
4745 }
4746
4747 // Polling process of TCP
PollingNatTcp(VH * v,NAT_ENTRY * n)4748 void PollingNatTcp(VH *v, NAT_ENTRY *n)
4749 {
4750 // Validate arguments
4751 if (v == NULL || n == NULL)
4752 {
4753 return;
4754 }
4755
4756 switch (n->TcpStatus)
4757 {
4758 case NAT_TCP_CONNECTING: // Socket connecting: nothing to do
4759 break;
4760
4761 case NAT_TCP_CONNECTED: // The socket connected: process SYN + ACK, ACK
4762 if ((n->LastSynAckSentTime > v->Now) || n->LastSynAckSentTime == 0 || ((n->LastSynAckSentTime + (UINT64)(NAT_TCP_SYNACK_SEND_TIMEOUT * (UINT64)(n->SynAckSentCount + 1)) <= v->Now)))
4763 {
4764 n->LastSynAckSentTime = v->Now;
4765 // Send a SYN + ACK
4766 SendTcp(v, n->DestIp, n->DestPort, n->SrcIp, n->SrcPort,
4767 (UINT)(n->SendSeqInit + n->SendSeq),
4768 (UINT)(n->RecvSeqInit + n->RecvSeq),
4769 TCP_SYN | TCP_ACK, n->TcpRecvWindowSize,
4770 v->TcpMss, NULL, 0);
4771 n->SynAckSentCount++;
4772 }
4773 break;
4774
4775 case NAT_TCP_SEND_RESET: // Reset the connection
4776 // Send a RST
4777 if (n->TcpFinished == false || n->TcpForceReset)
4778 {
4779 SendTcp(v, n->DestIp, n->DestPort, n->SrcIp, n->SrcPort,
4780 (UINT)(n->SendSeq + n->SendSeqInit),
4781 (UINT)(n->SendSeq + n->SendSeqInit),
4782 TCP_RST, 0,
4783 0, NULL, 0);
4784 // Disconnect
4785 n->TcpStatus = NAT_TCP_WAIT_DISCONNECT;
4786 n->DisconnectNow = true;
4787 }
4788 else
4789 {
4790 // Send FINs for NAT_FIN_SEND_MAX_COUNT times
4791 if (n->FinSentTime == 0 || (n->FinSentTime > v->Now) || (n->FinSentTime + NAT_FIN_SEND_INTERVAL * (n->FinSentCount + 1)) < v->Now)
4792 {
4793 SendTcp(v, n->DestIp, n->DestPort, n->SrcIp, n->SrcPort,
4794 (UINT)(n->SendSeq + n->SendSeqInit),
4795 (UINT)(n->RecvSeq + n->RecvSeqInit),
4796 TCP_ACK | TCP_FIN, 0,
4797 0, NULL, 0);
4798 n->FinSentTime = v->Now;
4799 n->FinSentSeq = (UINT)(n->SendSeq + n->SendSeqInit);
4800 n->FinSentCount++;
4801 if (n->FinSentCount >= NAT_FIN_SEND_MAX_COUNT)
4802 {
4803 n->TcpFinished = false;
4804 }
4805 }
4806 }
4807 break;
4808
4809 case NAT_TCP_ESTABLISHED: // Connection established
4810 {
4811 UINT send_data_size;
4812 UINT current_pointer;
4813 UINT notice_window_size_value = 0;
4814 UINT buf_free_bytes = 0;
4815 // Determine the value of the window size to be notified
4816 if (FifoSize(n->RecvFifo) < NAT_RECV_BUF_SIZE)
4817 {
4818 buf_free_bytes = NAT_RECV_BUF_SIZE - FifoSize(n->RecvFifo);
4819 }
4820 notice_window_size_value = MIN(n->TcpRecvWindowSize, buf_free_bytes);
4821 if (n->LastSentKeepAliveTime == 0 ||
4822 (n->LastSentKeepAliveTime + (UINT64)NAT_ACK_KEEPALIVE_SPAN) < v->Now ||
4823 (n->LastSentKeepAliveTime > v->Now))
4824 {
4825 if (n->LastSentKeepAliveTime != 0)
4826 {
4827 // Send an ACK packet for Keep-Alive
4828 SendTcp(v, n->DestIp, n->DestPort, n->SrcIp, n->SrcPort,
4829 (UINT)(n->SendSeqInit + n->SendSeq),
4830 (UINT)(n->RecvSeqInit + n->RecvSeq) - 1,
4831 TCP_ACK,
4832 notice_window_size_value,
4833 0,
4834 NULL,
4835 0);
4836 }
4837 n->LastSentKeepAliveTime = v->Now;
4838 }
4839 if (n->TcpLastSentTime == 0 ||
4840 (n->TcpLastSentTime > v->Now) ||
4841 ((n->TcpLastSentTime + (UINT64)n->TcpSendTimeoutSpan) < v->Now) ||
4842 n->SendAckNext)
4843 {
4844 // If there is data to send, send the data
4845 // Calculate the segment size to be transmitted
4846 send_data_size = n->TcpSendWindowSize;
4847 if (send_data_size > (n->TcpSendCWnd * n->TcpSendMaxSegmentSize))
4848 {
4849 // Apply the cwnd value
4850 send_data_size = n->TcpSendCWnd * n->TcpSendMaxSegmentSize;
4851 }
4852 if (send_data_size > n->SendFifo->size)
4853 {
4854 // Can not be sent over the data that is currently held
4855 send_data_size = n->SendFifo->size;
4856 }
4857 if (send_data_size >= 1)
4858 {
4859 // Transmit the fragmented segments
4860 current_pointer = 0;
4861 while (send_data_size > 0)
4862 {
4863 UINT send_segment_size = MIN(n->TcpSendMaxSegmentSize, send_data_size);
4864 void *send_segment = (void *)(((UCHAR *)n->SendFifo->p) + n->SendFifo->pos + current_pointer);
4865 SendTcp(v, n->DestIp, n->DestPort, n->SrcIp, n->SrcPort,
4866 (UINT)(n->SendSeqInit + n->SendSeq + (UINT64)current_pointer),
4867 (UINT)(n->RecvSeqInit + n->RecvSeq),
4868 TCP_ACK | TCP_PSH,
4869 notice_window_size_value,
4870 0,
4871 send_segment,
4872 send_segment_size);
4873 current_pointer += send_segment_size;
4874 send_data_size -= send_segment_size;
4875 }
4876 // Record the transmission time
4877 n->TcpLastSentTime = v->Now;
4878 // Record the stream size to be transmitted this time
4879 n->SendMissionSize = current_pointer;
4880 n->CurrentSendingMission = true;
4881 // RTT measurement
4882 if (n->CalcRTTStartTime == 0)
4883 {
4884 n->CalcRTTStartTime = v->Now;
4885 n->CalcRTTStartValue = n->SendSeq + current_pointer - 1;
4886 }
4887 if (n->RetransmissionUsedFlag == false)
4888 {
4889 n->RetransmissionUsedFlag = true;
4890 }
4891 else
4892 {
4893 // Congestion is detected
4894 if (n->TcpSendCWnd > 2)
4895 {
4896 n->TcpSendCWnd--;
4897 }
4898 }
4899 }
4900 else if (n->SendAckNext)
4901 {
4902 // Send only an ACK
4903 SendTcp(v, n->DestIp, n->DestPort, n->SrcIp, n->SrcPort,
4904 (UINT)(n->SendSeqInit + n->SendSeq),
4905 (UINT)(n->RecvSeqInit + n->RecvSeq),
4906 TCP_ACK,
4907 notice_window_size_value,
4908 0,
4909 NULL,
4910 0);
4911 }
4912 n->SendAckNext = false;
4913 }
4914 if (n->TcpFinished)
4915 {
4916 // Disconnect if all data transmission has completed
4917 if (n->SendFifo->size == 0 && n->RecvFifo->size == 0)
4918 {
4919 n->TcpStatus = NAT_TCP_SEND_RESET;
4920 }
4921 }
4922 }
4923 break;
4924 }
4925 }
4926
4927 // Reception of TCP packets addressed to the Internet
TcpRecvForInternet(VH * v,UINT src_ip,UINT src_port,UINT dest_ip,UINT dest_port,TCP_HEADER * tcp,void * data,UINT size,UINT max_l3_size)4928 void TcpRecvForInternet(VH *v, UINT src_ip, UINT src_port, UINT dest_ip, UINT dest_port, TCP_HEADER *tcp, void *data, UINT size, UINT max_l3_size)
4929 {
4930 NAT_ENTRY *n, t;
4931 UINT seq, ack;
4932 UINT64 seq64 = 0, ack64 = 0;
4933 // Validate arguments
4934 if (v == NULL || tcp == NULL || data == NULL)
4935 {
4936 return;
4937 }
4938
4939 if (NnIsActive(v))
4940 {
4941 NnTcpRecvForInternet(v, src_ip, src_port, dest_ip, dest_port, tcp, data, size, max_l3_size);
4942 return;
4943 }
4944
4945 seq = Endian32(tcp->SeqNumber);
4946 ack = Endian32(tcp->AckNumber);
4947
4948 if (v->HubOption != NULL && v->HubOption->DisableUserModeSecureNAT)
4949 {
4950 // Disable User-mode NAT
4951 SendTcp(v, dest_ip, dest_port, src_ip, src_port,
4952 0, seq + 1, TCP_RST | TCP_ACK, 0, 0, NULL, 0);
4953 return;
4954 }
4955
4956 // Search for a session for this packet from the NAT table
4957 SetNat(&t, NAT_TCP, src_ip, src_port, dest_ip, dest_port, 0, 0);
4958 n = SearchNat(v, &t);
4959
4960 if (n == NULL)
4961 {
4962 // There is no existing session
4963 // Allow through only SYN packet
4964 if ((tcp->Flag & TCP_SYN) && ((tcp->Flag & TCP_ACK) == false))
4965 {
4966 TCP_OPTION o;
4967 // Create a new session
4968 n = CreateNatTcp(v, src_ip, src_port, dest_ip, dest_port);
4969 if (n == NULL)
4970 {
4971 // Return the RST if it was not possible to create
4972 SendTcp(v, dest_ip, dest_port, src_ip, src_port,
4973 0, seq + 1, TCP_RST | TCP_ACK, 0, 0, NULL, 0);
4974 return;
4975 }
4976
4977 // Get the options
4978 ParseTcpOption(&o, ((UCHAR *)tcp) + TCP_HEADER_SIZE, TCP_GET_HEADER_SIZE(tcp) * 4 - TCP_HEADER_SIZE);
4979 if (o.MaxSegmentSize == 0)
4980 {
4981 o.MaxSegmentSize = v->TcpMss;
4982 }
4983
4984 Debug("TCP SYN: MSS=%u, WS=%u\n", o.MaxSegmentSize, o.WindowScaling);
4985
4986 // Initial sequence number
4987 n->RecvSeqInit = (UINT64)Endian32(tcp->SeqNumber);
4988 n->RecvSeq = 1;
4989
4990 n->TcpSendMaxSegmentSize = o.MaxSegmentSize;
4991 n->TcpRecvWindowSize = NAT_TCP_RECV_WINDOW_SIZE;
4992 n->TcpSendWindowSize = (UINT)Endian16(tcp->WindowSize);
4993 if (o.WindowScaling != 0)
4994 {
4995 if (o.WindowScaling > 14)
4996 {
4997 o.WindowScaling = 14;
4998 }
4999 n->TcpSendWindowSize = (n->TcpSendWindowSize << o.WindowScaling);
5000 }
5001 }
5002 }
5003
5004 if (n == NULL)
5005 {
5006 // Return a RST since a packet which is not registered in the NAT entry arrived
5007 SendTcp(v, dest_ip, dest_port, src_ip, src_port,
5008 ack, ack, TCP_RST, 0, 0, NULL, 0);
5009 return;
5010 }
5011
5012 n->TcpLastRecvAckTime = v->Now;
5013
5014 switch (n->TcpStatus)
5015 {
5016 case NAT_TCP_SEND_RESET: // Disconnect the connection by sending a RST
5017 if ((tcp->Flag & TCP_ACK) && ((tcp->Flag & TCP_SYN) == false))
5018 {
5019 if (n->FinSentCount >= 1)
5020 {
5021 if (ack == (n->FinSentSeq + 1))
5022 {
5023 n->TcpForceReset = true;
5024 }
5025 }
5026 }
5027 break;
5028
5029 case NAT_TCP_CONNECTED: // Socket connection completion: SYN + ACK, ACK processing
5030 if ((tcp->Flag & TCP_ACK) && ((tcp->Flag & TCP_SYN) == false))
5031 {
5032 if (seq == (UINT)(n->RecvSeqInit + n->RecvSeq) &&
5033 ack == (UINT)(n->SendSeqInit + n->SendSeq + 1))
5034 {
5035 // Handshake complete since the ACK packet came back
5036 n->SendSeq++; // SYN packet consumes the seq by 1
5037 Debug("TCP Connection Established.\n");
5038 n->TcpStatus = NAT_TCP_ESTABLISHED;
5039 // Initialize the congestion window size
5040 n->TcpSendCWnd = 1;
5041 n->LastCommTime = v->Now;
5042 }
5043 else
5044 {
5045 goto TCP_RESET;
5046 }
5047 }
5048 else if (tcp->Flag & TCP_RST)
5049 {
5050 TCP_RESET:
5051 // Receive a RST
5052 Debug("TCP Connection Reseted.\n");
5053 n->TcpStatus = NAT_TCP_SEND_RESET;
5054 }
5055 break;
5056
5057 case NAT_TCP_ESTABLISHED: // Connection established
5058 if (tcp->Flag & TCP_FIN)
5059 {
5060 // Complete the connection
5061 n->TcpFinished = true;
5062 }
5063 if (tcp->Flag & TCP_RST)
5064 {
5065 // Receive a RST
5066 goto TCP_RESET;
5067 }
5068 else if (tcp->Flag & TCP_ACK)
5069 {
5070 TCP_OPTION opt;
5071 n->LastCommTime = v->Now;
5072 // Get the options, such as window size
5073 n->TcpSendWindowSize = Endian16(tcp->WindowSize);
5074 ParseTcpOption(&opt, ((UCHAR *)tcp) + TCP_HEADER_SIZE, TCP_GET_HEADER_SIZE(tcp) * 4 - TCP_HEADER_SIZE);
5075 if (opt.WindowScaling != 0)
5076 {
5077 if (opt.WindowScaling > 14)
5078 {
5079 opt.WindowScaling = 14;
5080 }
5081 n->TcpSendWindowSize = (n->TcpSendWindowSize << opt.WindowScaling);
5082 }
5083 // First, process the received ACK
5084 // Store the end position of the stream that has received the acknowledgment to ack64
5085 ack64 = n->SendSeq + (UINT64)ack - (n->SendSeqInit + n->SendSeq) % X32;
5086 if ((n->SendSeqInit + n->SendSeq) % X32 > ack)
5087 {
5088 if (((n->SendSeqInit + n->SendSeq) % X32 - ack) >= 0x80000000)
5089 {
5090 ack64 = n->SendSeq + (UINT64)ack + X32 - (n->SendSeqInit + n->SendSeq) % X32;
5091 }
5092 }
5093 if (ack64 > n->SendSeq)
5094 {
5095 // Reception of 1 byte or more seems to have been completed by the client
5096 UINT slide_offset = (UINT)(ack64 - n->SendSeq); // Sliding size of the window
5097 if (slide_offset == 0 || slide_offset > n->TcpSendWindowSize || slide_offset > n->SendFifo->size)
5098 {
5099 // Ignore because the offset value of acknowledgment is
5100 // larger than the size that should have been sent so far
5101 }
5102 else
5103 {
5104 // RTT measurement
5105 if (n->CalcRTTStartTime != 0)
5106 {
5107 if (n->CalcRTTStartValue < ack64)
5108 {
5109 UINT time_span;
5110 if (v->Now > n->CalcRTTStartTime)
5111 {
5112 time_span = (UINT)(v->Now - n->CalcRTTStartTime);
5113 }
5114 else
5115 {
5116 time_span = 100;
5117 }
5118 n->CalcRTTStartTime = 0;
5119
5120 // Smoothing
5121 n->CurrentRTT =
5122 (UINT)
5123 (
5124 ((UINT64)n->CurrentRTT * (UINT64)9 +
5125 (UINT64)time_span * (UINT64)1) / (UINT64)10
5126 );
5127 n->TcpSendTimeoutSpan = n->CurrentRTT * 2;
5128 }
5129 }
5130 // Reduce the transmission size
5131 n->SendMissionSize -= slide_offset;
5132 if (n->SendMissionSize == 0)
5133 {
5134 // Try to increase the transmission segment size because
5135 // all segments to be sent this time have been sent
5136 if (n->TcpSendCWnd < 65536)
5137 {
5138 n->TcpSendCWnd++;
5139 }
5140 n->CurrentSendingMission = false;
5141 n->TcpLastSentTime = 0;
5142 n->RetransmissionUsedFlag = false;
5143 }
5144 // Slide the buffer
5145 n->SendSeq += slide_offset;
5146 ReadFifo(n->SendFifo, NULL, slide_offset);
5147 // Send further by the size of confirmed transmission completion by the ACK this time
5148 if (n->SendMissionSize != 0 && false)
5149 {
5150 UINT notice_window_size_value = 0;
5151 UINT send_data_size;
5152 UINT buf_free_bytes;
5153 UINT send_offset = n->SendMissionSize;
5154 // Determine the value of the window size to be notified
5155 if (FifoSize(n->RecvFifo) < NAT_RECV_BUF_SIZE)
5156 {
5157 buf_free_bytes = NAT_RECV_BUF_SIZE - FifoSize(n->RecvFifo);
5158 }
5159 notice_window_size_value = MIN(n->TcpRecvWindowSize, buf_free_bytes);
5160 // Calculate the segment size to be transmitted
5161 send_data_size = n->TcpSendWindowSize;
5162 if (send_data_size > (n->TcpSendCWnd * n->TcpSendMaxSegmentSize))
5163 {
5164 // Apply the cwnd value
5165 send_data_size = n->TcpSendCWnd * n->TcpSendMaxSegmentSize;
5166 }
5167 if (n->SendFifo->size > send_offset)
5168 {
5169 send_data_size = MIN(send_data_size, n->SendFifo->size - send_offset);
5170 send_data_size = MIN(send_data_size, slide_offset);
5171 }
5172 else
5173 {
5174 send_data_size = 0;
5175 }
5176 if (send_data_size >= 1)
5177 {
5178 // Transmit the fragmented segments
5179 UINT current_pointer = 0;
5180 while (send_data_size > 0)
5181 {
5182 UINT send_segment_size = MIN(n->TcpSendMaxSegmentSize, send_data_size);
5183 void *send_segment = (void *)((
5184 (UCHAR *)n->SendFifo->p) + n->SendFifo->pos +
5185 current_pointer + send_offset);
5186
5187 SendTcp(v, n->DestIp, n->DestPort, n->SrcIp, n->SrcPort,
5188 (UINT)(n->SendSeqInit + n->SendSeq + (UINT64)current_pointer
5189 + (UINT)send_offset),
5190 (UINT)(n->RecvSeqInit + n->RecvSeq),
5191 TCP_ACK | TCP_PSH,
5192 notice_window_size_value,
5193 0,
5194 send_segment,
5195 send_segment_size);
5196 current_pointer += send_segment_size;
5197 send_data_size -= send_segment_size;
5198 }
5199 n->SendMissionSize += current_pointer;
5200 n->CurrentSendingMission = true;
5201 n->TcpLastSentTime = v->Now;
5202 // RTT measurement
5203 if (n->CalcRTTStartTime == 0)
5204 {
5205 n->CalcRTTStartTime = v->Now;
5206 n->CalcRTTStartValue = n->SendSeq + current_pointer - 1;
5207 }
5208 }
5209 }
5210 // Event occurs
5211 SetSockEvent(v->SockEvent);
5212 }
5213 }
5214 // Next, receive the data
5215 seq64 = n->RecvSeq + (UINT64)seq - (n->RecvSeqInit + n->RecvSeq) % X32;
5216 if ((n->RecvSeqInit + n->RecvSeq) % X32 > seq)
5217 {
5218 if (((n->RecvSeqInit + n->RecvSeq) % X32 - seq) >= 0x80000000)
5219 {
5220 seq64 = n->RecvSeq + (UINT64)seq + X32 - (n->RecvSeqInit + n->RecvSeq) % X32;
5221 }
5222 }
5223 // Position of the starting point of the data from the client is in the seq64 at this time
5224 if (seq64 >= n->RecvSeq && (seq64 + size) <= (n->RecvSeq + n->TcpRecvWindowSize))
5225 {
5226 if (size >= 1)
5227 {
5228 // One or more bytes of data has been received within the receive window
5229 UINT offset = (UINT)(seq64 - n->RecvSeq);
5230 UINT i;
5231 IP_PART *me;
5232 if (n->TcpRecvWindow == NULL)
5233 {
5234 n->TcpRecvWindow = NewFifo();
5235 }
5236 if (n->TcpRecvList == NULL)
5237 {
5238 n->TcpRecvList = NewListFast(NULL);
5239 }
5240 // Add to the list by overwriting arriving packets to the buffer
5241 if (FifoSize(n->TcpRecvWindow) < (offset + size))
5242 {
5243 // Buffer size expansion
5244 WriteFifo(n->TcpRecvWindow, NULL, offset + size - FifoSize(n->TcpRecvWindow));
5245 }
5246 Copy(((UCHAR *)n->TcpRecvWindow->p) + n->TcpRecvWindow->pos +
5247 offset, data, size);
5248 me = ZeroMalloc(sizeof(IP_PART));
5249 me->Offset = offset;
5250 me->Size = size;
5251 for (i = 0; i < LIST_NUM(n->TcpRecvList); i++)
5252 {
5253 IP_PART *p = LIST_DATA(n->TcpRecvList, i);
5254 // If there are overlapped region, remove these
5255 if (p->Size != 0)
5256 {
5257 if (me->Offset <= p->Offset && (me->Offset + me->Size) >= (p->Offset + p->Size))
5258 {
5259 // This packet completely overwrite the existing packet
5260 p->Size = 0;
5261 }
5262 else if (me->Offset >= p->Offset && (me->Offset + me->Size) <= (p->Offset + p->Size))
5263 {
5264 // Existing packet completely override this packet
5265 me->Size = 0;
5266 }
5267 else if (me->Offset > p->Offset && me->Offset < (p->Offset + p->Size) &&
5268 (me->Offset + me->Size) > (p->Offset + p->Size))
5269 {
5270 // Partially overlapped
5271 p->Size -= p->Offset + p->Size - me->Offset;
5272 }
5273 else if (me->Offset < p->Offset && (me->Offset + size) > p->Offset && (me->Offset + size) < (p->Offset + p->Size))
5274 {
5275 // Partially overlapped
5276 me->Size -= me->Offset + me->Size - p->Offset;
5277 }
5278 }
5279 }
5280 if (me->Size == 0)
5281 {
5282 Free(me);
5283 }
5284 else
5285 {
5286 Add(n->TcpRecvList, me);
5287 }
5288 KILL_NULL_FIRST:
5289 // Remove all blank items from reception list
5290 for (i = 0; i < LIST_NUM(n->TcpRecvList); i++)
5291 {
5292 IP_PART *p = LIST_DATA(n->TcpRecvList, i);
5293 if (p->Size == 0)
5294 {
5295 Delete(n->TcpRecvList, p);
5296 Free(p);
5297 goto KILL_NULL_FIRST;
5298 }
5299 }
5300 SCAN_FIRST:
5301 // Extract if there is something starting at offset 0 in the received list
5302 for (i = 0; i < LIST_NUM(n->TcpRecvList); i++)
5303 {
5304 IP_PART *p = LIST_DATA(n->TcpRecvList, i);
5305 UINT sz;
5306 if (p->Offset == 0)
5307 {
5308 // Since a data block starts with 0 is found,
5309 // slide it left by that amount and write the buffer
5310 // for extracting data to the FIFO
5311 sz = p->Size;
5312 WriteFifo(n->RecvFifo, ((UCHAR *)n->TcpRecvWindow->p) + n->TcpRecvWindow->pos, sz);
5313 // Release from the list
5314 Delete(n->TcpRecvList, p);
5315 Free(p);
5316 ReadFifo(n->TcpRecvWindow, NULL, sz);
5317 // Slide all the items to the left
5318 for (i = 0; i < LIST_NUM(n->TcpRecvList); i++)
5319 {
5320 p = LIST_DATA(n->TcpRecvList, i);
5321 p->Offset -= sz;
5322 }
5323 // Update the parameters of the TCB
5324 n->RecvSeq += (UINT64)sz;
5325 SetSockEvent(v->SockEvent);
5326 n->SendAckNext = true;
5327 // Re-scan from the beginning
5328 goto SCAN_FIRST;
5329 }
5330 }
5331 }
5332 }
5333 }
5334 break;
5335 }
5336
5337 SetSockEvent(v->SockEvent);
5338 }
5339
5340 // Parse the TCP options
ParseTcpOption(TCP_OPTION * o,void * data,UINT size)5341 void ParseTcpOption(TCP_OPTION *o, void *data, UINT size)
5342 {
5343 UCHAR *buf = (UCHAR *)data;
5344 UINT i = 0;
5345 UINT value_size = 0;
5346 UINT value_id = 0;
5347 UCHAR value[128];
5348 // Validate arguments
5349 if (o == NULL || data == NULL)
5350 {
5351 return;
5352 }
5353
5354 Zero(o, sizeof(TCP_OPTION));
5355
5356 while(i < size)
5357 {
5358 if (buf[i] == 0)
5359 {
5360 return;
5361 }
5362 else if (buf[i] == 1)
5363 {
5364 i++;
5365 continue;
5366 }
5367 else
5368 {
5369 value_id = buf[i];
5370 i++;
5371 if (i >= size)
5372 {
5373 return;
5374 }
5375 value_size = buf[i];
5376 if (value_size <= 1 || value_size > sizeof(value))
5377 {
5378 return;
5379 }
5380 i++;
5381 if (i >= size)
5382 {
5383 return;
5384 }
5385 value_size -= 2;
5386
5387 Copy(value, &buf[i], value_size);
5388 i += value_size;
5389 if (i > size)
5390 {
5391 return;
5392 }
5393
5394 switch (value_id)
5395 {
5396 case 2: // MSS
5397 if (value_size == 2)
5398 {
5399 USHORT *mss = (USHORT *)value;
5400 o->MaxSegmentSize = Endian16(*mss);
5401 }
5402 break;
5403
5404 case 3: // WSS
5405 if (value_size == 1)
5406 {
5407 UCHAR *wss = (UCHAR *)value;
5408 o->WindowScaling = *wss;
5409 }
5410 break;
5411
5412 }
5413 }
5414 }
5415 }
5416
5417 // Create a new NAT TCP session
CreateNatTcp(VH * v,UINT src_ip,UINT src_port,UINT dest_ip,UINT dest_port)5418 NAT_ENTRY *CreateNatTcp(VH *v, UINT src_ip, UINT src_port, UINT dest_ip, UINT dest_port)
5419 {
5420 NAT_ENTRY *n;
5421 HUB_OPTION *o;
5422 // Validate arguments
5423 if (v == NULL)
5424 {
5425 return NULL;
5426 }
5427
5428 if (CanCreateNewNatEntry(v) == false)
5429 {
5430 return NULL;
5431 }
5432
5433 o = NatGetHubOption(v);
5434
5435 // Fail immediately if the connection with SYN_SENT are too many
5436 if (o != NULL && o->SecureNAT_MaxTcpSynSentPerIp != 0)
5437 {
5438 if (GetNumNatEntriesPerIp(v, src_ip, NAT_TCP, true) >= o->SecureNAT_MaxTcpSynSentPerIp)
5439 {
5440 return NULL;
5441 }
5442 }
5443
5444 // If the connections other than SYN_SENT are too many, delete old ones
5445 if (o != NULL && o->SecureNAT_MaxTcpSessionsPerIp != 0)
5446 {
5447 if (GetNumNatEntriesPerIp(v, src_ip, NAT_TCP, false) >= o->SecureNAT_MaxTcpSessionsPerIp)
5448 {
5449 NAT_ENTRY *oldest = GetOldestNatEntryOfIp(v, src_ip, NAT_TCP);
5450
5451 if (oldest != NULL)
5452 {
5453 DisconnectNatEntryNow(v, oldest);
5454 }
5455 }
5456 }
5457
5458 // Create a NAT entry
5459 n = ZeroMalloc(sizeof(NAT_ENTRY));
5460 n->Id = Inc(v->Counter);
5461 n->v = v;
5462 n->lock = NewLock();
5463 n->Protocol = NAT_TCP;
5464 n->SrcIp = src_ip;
5465 n->SrcPort = src_port;
5466 n->DestIp = dest_ip;
5467 n->DestPort = dest_port;
5468 n->CreatedTime = n->LastCommTime = v->Now;
5469 n->TcpLastRecvAckTime = v->Now;
5470 n->Sock = NULL;
5471 n->DisconnectNow = false;
5472 n->TcpSendMaxSegmentSize = n->TcpRecvMaxSegmentSize = v->TcpMss;
5473
5474 n->SendFifo = NewFifo();
5475 n->RecvFifo = NewFifo();
5476
5477 n->TcpStatus = NAT_TCP_CONNECTING;
5478
5479 n->SendSeqInit = Rand32();
5480 n->CurrentRTT = NAT_INITIAL_RTT_VALUE;
5481 n->TcpSendTimeoutSpan = n->CurrentRTT * 2;
5482
5483 // Add to the NAT table
5484 Add(v->NatTable, n);
5485
5486
5487 #if 1
5488 {
5489 IP ip1, ip2;
5490 char s1[MAX_SIZE], s2[MAX_SIZE];
5491 UINTToIP(&ip1, src_ip);
5492 UINTToIP(&ip2, dest_ip);
5493 IPToStr(s1, 0, &ip1);
5494 IPToStr(s2, 0, &ip2);
5495 Debug("NAT_ENTRY: CreateNatTcp %s %u -> %s %u\n", s1, src_port, s2, dest_port);
5496
5497 NLog(v, "LH_NAT_TCP_CREATED", n->Id, s1, src_port, s2, dest_port);
5498 }
5499 #endif
5500
5501 return n;
5502 }
5503
5504 // Received TCP packets from the virtual network
VirtualTcpReceived(VH * v,UINT src_ip,UINT dest_ip,void * data,UINT size,UINT max_l3_size)5505 void VirtualTcpReceived(VH *v, UINT src_ip, UINT dest_ip, void *data, UINT size, UINT max_l3_size)
5506 {
5507 TCP_HEADER *tcp;
5508 UINT src_port, dest_port;
5509 UINT header_size, buf_size;
5510 void *buf;
5511 IP ip1, ip2;
5512 // Validate arguments
5513 if (v == NULL || data == NULL)
5514 {
5515 return;
5516 }
5517
5518 // Get the header
5519 if (size < TCP_HEADER_SIZE)
5520 {
5521 // Size is too small
5522 return;
5523 }
5524 tcp = (TCP_HEADER *)data;
5525 src_port = Endian16(tcp->SrcPort);
5526 dest_port = Endian16(tcp->DstPort);
5527 if (src_port == 0 || dest_port == 0)
5528 {
5529 // Port number is invalid
5530 return;
5531 }
5532 if (src_ip == dest_ip || src_ip == 0 || src_ip == 0xffffffff || dest_ip == 0 || dest_ip == 0xffffffff)
5533 {
5534 // IP address is invalid
5535 return;
5536 }
5537 UINTToIP(&ip1, src_ip);
5538 UINTToIP(&ip2, dest_ip);
5539 if (IsLocalHostIP4(&ip1) || IsLocalHostIP4(&ip2))
5540 {
5541 // Loopback IP address can not be specified
5542 return;
5543 }
5544 if (IsInNetwork(dest_ip, v->HostIP, v->HostMask))
5545 {
5546 // Ignore the packets toward the network of the virtual LAN side
5547 return;
5548 }
5549 // Get the header size
5550 header_size = TCP_GET_HEADER_SIZE(tcp) * 4;
5551 if (size < header_size)
5552 {
5553 // Header size is invalid
5554 return;
5555 }
5556 // Get the address and size of the buffer
5557 buf_size = size - header_size;
5558 buf = (void *)(((UCHAR *)data) + header_size);
5559
5560 TcpRecvForInternet(v, src_ip, src_port, dest_ip, dest_port, tcp, buf, buf_size, max_l3_size);
5561 }
5562
5563 // NAT ICMP polling
PollingNatIcmp(VH * v,NAT_ENTRY * n)5564 void PollingNatIcmp(VH *v, NAT_ENTRY *n)
5565 {
5566 // Validate arguments
5567 if (v == NULL || n == NULL)
5568 {
5569 return;
5570 }
5571
5572 // Process if there are any packets in the receive queue
5573 if (n->UdpRecvQueue->num_item != 0)
5574 {
5575 BLOCK *block;
5576
5577 // Send all ICMP packets to the virtual network
5578 while (block = GetNext(n->UdpRecvQueue))
5579 {
5580 // Rewrite the destination IP address of the returned packet to the IP address of the client
5581 UCHAR *data;
5582 UINT size;
5583
5584 data = (UCHAR *)block->Buf;
5585 size = block->Size;
5586
5587 if (size >= sizeof(IPV4_HEADER))
5588 {
5589 IPV4_HEADER *ipv4 = (IPV4_HEADER *)data;
5590 UINT ipv4_header_size = GetIpHeaderSize((UCHAR *)ipv4, size);
5591
5592 if (ipv4_header_size >= sizeof(IPV4_HEADER) && (Endian16(ipv4->TotalLength) >= ipv4_header_size))
5593 {
5594 UCHAR *ipv4_payload = data + ipv4_header_size;
5595 UINT ipv4_payload_size = Endian16(ipv4->TotalLength) - ipv4_header_size;
5596
5597 if (ipv4_payload_size >= sizeof(ICMP_HEADER) + sizeof(ICMP_ECHO))
5598 {
5599 ICMP_HEADER *icmp = (ICMP_HEADER *)(data + ipv4_header_size);
5600 UINT icmp_size = ipv4_payload_size;
5601
5602 if (icmp->Type == ICMP_TYPE_DESTINATION_UNREACHABLE || icmp->Type == ICMP_TYPE_TIME_EXCEEDED)
5603 {
5604 // Rewrite the Src IP of the IPv4 header of the ICMP response packet
5605 if (icmp_size >= (sizeof(ICMP_HEADER) + sizeof(ICMP_ECHO) + sizeof(IPV4_HEADER)))
5606 {
5607 IPV4_HEADER *orig_ipv4 = (IPV4_HEADER *)(data + ipv4_header_size + sizeof(ICMP_HEADER) + sizeof(ICMP_ECHO));
5608 UINT orig_ipv4_size = icmp_size - (sizeof(ICMP_HEADER) + sizeof(ICMP_ECHO));
5609
5610 UINT orig_ipv4_header_size = GetIpHeaderSize((UCHAR *)orig_ipv4, orig_ipv4_size);
5611
5612 if (orig_ipv4_header_size >= sizeof(IPV4_HEADER))
5613 {
5614 orig_ipv4->SrcIP = n->SrcIp;
5615 orig_ipv4->Checksum = 0;
5616 orig_ipv4->Checksum = IpChecksum(orig_ipv4, orig_ipv4_header_size);
5617 }
5618 }
5619 }
5620
5621 // Recalculate the checksum of ICMP
5622 icmp->Checksum = IpChecksum(icmp, icmp_size);
5623
5624 SendIpEx(v, n->SrcIp, ipv4->SrcIP, ipv4->Protocol, ipv4_payload, ipv4_payload_size,
5625 MAX(ipv4->TimeToLive - 1, 1));
5626 }
5627 }
5628 }
5629
5630 FreeBlock(block);
5631 }
5632
5633 if (v->IcmpRawSocketOk == false)
5634 {
5635 // Release the NAT entry as soon as the results is received in the case of using ICMP API
5636 n->DisconnectNow = true;
5637 }
5638 }
5639 }
5640
5641 // NAT UDP polling
PoolingNatUdp(VH * v,NAT_ENTRY * n)5642 void PoolingNatUdp(VH *v, NAT_ENTRY *n)
5643 {
5644 // Validate arguments
5645 if (v == NULL || n == NULL)
5646 {
5647 return;
5648 }
5649
5650 // Process if there are any packets in the receive queue
5651 if (n->UdpRecvQueue->num_item != 0)
5652 {
5653 BLOCK *block;
5654
5655 // Send all UDP packets to the virtual network
5656 while (block = GetNext(n->UdpRecvQueue))
5657 {
5658 UINT src_ip = n->DestIp;
5659
5660 if (src_ip == 0xFFFFFFFF)
5661 {
5662 src_ip = v->HostIP;
5663 }
5664
5665 if (block->Param1 != 0)
5666 {
5667 src_ip = block->Param1;
5668 }
5669
5670 SendUdp(v, n->SrcIp, n->SrcPort, src_ip, n->DestPort,
5671 block->Buf, block->Size);
5672
5673 FreeBlock(block);
5674 }
5675 }
5676 }
5677
5678 // NAT polling
PoolingNat(VH * v)5679 void PoolingNat(VH *v)
5680 {
5681 UINT i;
5682 // Validate arguments
5683 if (v == NULL)
5684 {
5685 return;
5686 }
5687
5688 if (NnIsActive(v))
5689 {
5690 // Poll whether the packet comes from native NAT
5691 NnPoll(v->NativeNat);
5692 }
5693
5694 // Process by scanning the all NAT entries
5695 for (i = 0; i < LIST_NUM(v->NatTable); i++)
5696 {
5697 NAT_ENTRY *n = LIST_DATA(v->NatTable, i);
5698
5699 switch (n->Protocol)
5700 {
5701 case NAT_TCP:
5702 PollingNatTcp(v, n);
5703 break;
5704
5705 case NAT_UDP:
5706 PoolingNatUdp(v, n);
5707 break;
5708
5709 case NAT_ICMP:
5710 PollingNatIcmp(v, n);
5711 break;
5712
5713 case NAT_DNS:
5714 PollingNatDns(v, n);
5715 break;
5716 }
5717 }
5718 }
5719
5720 // Comparison function of the NAT table entry
CompareNat(void * p1,void * p2)5721 int CompareNat(void *p1, void *p2)
5722 {
5723 NAT_ENTRY *n1, *n2;
5724 if (p1 == NULL || p2 == NULL)
5725 {
5726 return 0;
5727 }
5728 n1 = *(NAT_ENTRY **)p1;
5729 n2 = *(NAT_ENTRY **)p2;
5730 if (n1 == n2)
5731 {
5732 return 0;
5733 }
5734
5735 if (n1->SrcIp > n2->SrcIp) return 1;
5736 else if (n1->SrcIp < n2->SrcIp) return -1;
5737 else if (n1->DestIp > n2->DestIp) return 1;
5738 else if (n1->DestIp < n2->DestIp) return -1;
5739 else if (n1->SrcPort > n2->SrcPort) return 1;
5740 else if (n1->SrcPort < n2->SrcPort) return -1;
5741 else if (n1->DestPort > n2->DestPort) return 1;
5742 else if (n1->DestPort < n2->DestPort) return -1;
5743 else if (n1->Protocol > n2->Protocol) return 1;
5744 else if (n1->Protocol < n2->Protocol) return -1;
5745 else return 0;
5746 }
5747
5748 // Configure the NAT structure
SetNat(NAT_ENTRY * n,UINT protocol,UINT src_ip,UINT src_port,UINT dest_ip,UINT dest_port,UINT public_ip,UINT public_port)5749 void SetNat(NAT_ENTRY *n, UINT protocol, UINT src_ip, UINT src_port, UINT dest_ip, UINT dest_port, UINT public_ip, UINT public_port)
5750 {
5751 // Validate arguments
5752 if (n == NULL)
5753 {
5754 return;
5755 }
5756
5757 n->Protocol = protocol;
5758 n->SrcIp = src_ip;
5759 n->SrcPort = src_port;
5760 n->DestIp = dest_ip;
5761 n->DestPort = dest_port;
5762 n->PublicIp = public_ip;
5763 n->PublicPort = public_port;
5764 }
5765
5766 // Initialize the NAT
InitNat(VH * v)5767 void InitNat(VH *v)
5768 {
5769 // Validate arguments
5770 if (v == NULL)
5771 {
5772 return;
5773 }
5774
5775 // Create a NAT table
5776 v->NatTable = NewList(CompareNat);
5777
5778 // Create a socket event
5779 v->SockEvent = NewSockEvent();
5780
5781 // Create the NAT thread
5782 v->HaltNat = false;
5783 v->NatThread = NewThread(NatThread, (void *)v);
5784 WaitThreadInit(v->NatThread);
5785
5786 if (IsEthSupported())
5787 {
5788 // Start a native NAT if access to the layer 2 Ethernet is supported
5789 v->NativeNat = NewNativeNat(v);
5790 }
5791 }
5792
5793 // Release the NAT
FreeNat(VH * v)5794 void FreeNat(VH *v)
5795 {
5796 // Validate arguments
5797 if (v == NULL)
5798 {
5799 return;
5800 }
5801
5802 // Stop the native NAT
5803 if (v->NativeNat != NULL)
5804 {
5805 FreeNativeNat(v->NativeNat);
5806 v->NativeNat = NULL;
5807 }
5808
5809 // Stop the NAT thread
5810 v->HaltNat = true;
5811 SetSockEvent(v->SockEvent);
5812 WaitThread(v->NatThread, INFINITE);
5813 ReleaseThread(v->NatThread);
5814 v->NatThread = NULL;
5815 ReleaseSockEvent(v->SockEvent);
5816 v->SockEvent = NULL;
5817
5818 // Release the NAT table
5819 ReleaseList(v->NatTable);
5820 }
5821
5822 // Search the NAT table
SearchNat(VH * v,NAT_ENTRY * target)5823 NAT_ENTRY *SearchNat(VH *v, NAT_ENTRY *target)
5824 {
5825 NAT_ENTRY *n;
5826 // Validate arguments
5827 if (v == NULL || target == NULL)
5828 {
5829 return NULL;
5830 }
5831
5832 // Binary search
5833 n = (NAT_ENTRY *)Search(v->NatTable, target);
5834
5835 return n;
5836 }
5837
5838 // Delete the UDP NAT entry
DeleteNatUdp(VH * v,NAT_ENTRY * n)5839 void DeleteNatUdp(VH *v, NAT_ENTRY *n)
5840 {
5841 BLOCK *block;
5842 // Validate arguments
5843 if (v == NULL || n == NULL)
5844 {
5845 return;
5846 }
5847
5848 NLog(v, "LH_NAT_UDP_DELETED", n->Id);
5849
5850 // Release all queues
5851 while (block = GetNext(n->UdpRecvQueue))
5852 {
5853 FreeBlock(block);
5854 }
5855 ReleaseQueue(n->UdpRecvQueue);
5856 while (block = GetNext(n->UdpSendQueue))
5857 {
5858 FreeBlock(block);
5859 }
5860 ReleaseQueue(n->UdpSendQueue);
5861
5862 // Release the socket
5863 if (n->Sock != NULL)
5864 {
5865 Disconnect(n->Sock);
5866 ReleaseSock(n->Sock);
5867 n->Sock = NULL;
5868 }
5869
5870 DeleteLock(n->lock);
5871
5872 // Remove from the table
5873 Delete(v->NatTable, n);
5874
5875 // Release the memory
5876 Free(n);
5877
5878 Debug("NAT: DeleteNatUdp\n");
5879
5880 }
5881
5882 // Delete the ICMP NAT entry
DeleteNatIcmp(VH * v,NAT_ENTRY * n)5883 void DeleteNatIcmp(VH *v, NAT_ENTRY *n)
5884 {
5885 BLOCK *block;
5886 // Validate arguments
5887 if (v == NULL || n == NULL)
5888 {
5889 return;
5890 }
5891
5892 //NLog(v, "LH_NAT_ICMP_DELETED", n->Id);
5893
5894 // Release all queues
5895 while (block = GetNext(n->UdpRecvQueue))
5896 {
5897 FreeBlock(block);
5898 }
5899 ReleaseQueue(n->UdpRecvQueue);
5900 while (block = GetNext(n->UdpSendQueue))
5901 {
5902 FreeBlock(block);
5903 }
5904 ReleaseQueue(n->UdpSendQueue);
5905
5906 if (n->IcmpQueryBlock != NULL)
5907 {
5908 FreeBlock(n->IcmpQueryBlock);
5909 }
5910
5911 if (n->IcmpResponseBlock != NULL)
5912 {
5913 FreeBlock(n->IcmpResponseBlock);
5914 }
5915
5916 if (n->IcmpOriginalCopy != NULL)
5917 {
5918 Free(n->IcmpOriginalCopy);
5919 }
5920
5921 // Release the socket
5922 if (n->Sock != NULL)
5923 {
5924 Disconnect(n->Sock);
5925 ReleaseSock(n->Sock);
5926 n->Sock = NULL;
5927 }
5928
5929 DeleteLock(n->lock);
5930
5931 // Remove from the table
5932 Delete(v->NatTable, n);
5933
5934 // Release the memory
5935 Free(n);
5936
5937 Debug("NAT: DeleteNatIcmp\n");
5938
5939 }
5940
5941 // Create a NAT ICMP entry
CreateNatIcmp(VH * v,UINT src_ip,UINT src_port,UINT dest_ip,UINT dest_port,UCHAR * original_copy,UINT original_copy_size)5942 NAT_ENTRY *CreateNatIcmp(VH *v, UINT src_ip, UINT src_port, UINT dest_ip, UINT dest_port, UCHAR *original_copy, UINT original_copy_size)
5943 {
5944 NAT_ENTRY *n;
5945 HUB_OPTION *o;
5946 // Validate arguments
5947 if (v == NULL || original_copy == NULL || original_copy_size == 0)
5948 {
5949 return NULL;
5950 }
5951
5952 if (CanCreateNewNatEntry(v) == false)
5953 {
5954 return NULL;
5955 }
5956
5957 o = NatGetHubOption(v);
5958 if (o != NULL && o->SecureNAT_MaxIcmpSessionsPerIp != 0)
5959 {
5960 if (GetNumNatEntriesPerIp(v, src_ip, NAT_ICMP, false) >= o->SecureNAT_MaxIcmpSessionsPerIp)
5961 {
5962 NAT_ENTRY *oldest = GetOldestNatEntryOfIp(v, src_ip, NAT_ICMP);
5963
5964 if (oldest != NULL)
5965 {
5966 DisconnectNatEntryNow(v, oldest);
5967 }
5968 }
5969 }
5970
5971 n = ZeroMalloc(sizeof(NAT_ENTRY));
5972 n->Id = Inc(v->Counter);
5973 n->v = v;
5974 n->lock = NewLock();
5975 n->Protocol = NAT_ICMP;
5976 n->SrcIp = src_ip;
5977 n->SrcPort = src_port;
5978 n->DestIp = dest_ip;
5979 n->DestPort = dest_port;
5980
5981 n->CreatedTime = n->LastCommTime = v->Now;
5982
5983 n->UdpSendQueue = NewQueue();
5984 n->UdpRecvQueue = NewQueue();
5985
5986 n->UdpSocketCreated = false;
5987
5988 n->IcmpOriginalCopy = Clone(original_copy, original_copy_size);
5989 n->IcmpOriginalCopySize = original_copy_size;
5990
5991 SetSockEvent(v->SockEvent);
5992
5993 #if 1
5994 {
5995 IP ip1, ip2;
5996 char s1[MAX_SIZE], s2[MAX_SIZE];
5997 UINTToIP(&ip1, src_ip);
5998 UINTToIP(&ip2, dest_ip);
5999 IPToStr(s1, 0, &ip1);
6000 IPToStr(s2, 0, &ip2);
6001 Debug("NAT_ENTRY: CreateNatIcmp %s %u -> %s %u\n", s1, src_port, s2, dest_port);
6002
6003 //NLog(v, "LH_NAT_ICMP_CREATED", n->Id, s1, s2, src_port);
6004 }
6005 #endif
6006
6007 Add(v->NatTable, n);
6008
6009 return n;
6010 }
6011
6012 // Create a NAT UDP entry
CreateNatUdp(VH * v,UINT src_ip,UINT src_port,UINT dest_ip,UINT dest_port,UINT dns_proxy_ip)6013 NAT_ENTRY *CreateNatUdp(VH *v, UINT src_ip, UINT src_port, UINT dest_ip, UINT dest_port, UINT dns_proxy_ip)
6014 {
6015 NAT_ENTRY *n;
6016 HUB_OPTION *o;
6017 // Validate arguments
6018 if (v == NULL)
6019 {
6020 return NULL;
6021 }
6022
6023 if (CanCreateNewNatEntry(v) == false)
6024 {
6025 return NULL;
6026 }
6027
6028 o = NatGetHubOption(v);
6029 if (o != NULL && o->SecureNAT_MaxTcpSessionsPerIp != 0)
6030 {
6031 if (GetNumNatEntriesPerIp(v, src_ip, NAT_UDP, false) >= o->SecureNAT_MaxUdpSessionsPerIp)
6032 {
6033 NAT_ENTRY *oldest = GetOldestNatEntryOfIp(v, src_ip, NAT_UDP);
6034
6035 if (oldest != NULL)
6036 {
6037 DisconnectNatEntryNow(v, oldest);
6038 }
6039 }
6040 }
6041
6042 n = ZeroMalloc(sizeof(NAT_ENTRY));
6043 n->Id = Inc(v->Counter);
6044 n->v = v;
6045 n->lock = NewLock();
6046 n->Protocol = NAT_UDP;
6047 n->SrcIp = src_ip;
6048 n->SrcPort = src_port;
6049 n->DestIp = dest_ip;
6050 n->DestPort = dest_port;
6051
6052 if (dns_proxy_ip != 0)
6053 {
6054 n->ProxyDns = true;
6055 n->DestIpProxy = dns_proxy_ip;
6056 }
6057
6058 n->CreatedTime = n->LastCommTime = v->Now;
6059
6060 n->UdpSendQueue = NewQueue();
6061 n->UdpRecvQueue = NewQueue();
6062
6063 n->UdpSocketCreated = false;
6064
6065 SetSockEvent(v->SockEvent);
6066
6067 #if 1
6068 {
6069 IP ip1, ip2;
6070 char s1[MAX_SIZE], s2[MAX_SIZE];
6071 UINTToIP(&ip1, src_ip);
6072 UINTToIP(&ip2, dest_ip);
6073 IPToStr(s1, 0, &ip1);
6074 IPToStr(s2, 0, &ip2);
6075 Debug("NAT_ENTRY: CreateNatUdp %s %u -> %s %u\n", s1, src_port, s2, dest_port);
6076
6077 NLog(v, "LH_NAT_UDP_CREATED", n->Id, s1, src_port, s2, dest_port);
6078 }
6079 #endif
6080
6081 Add(v->NatTable, n);
6082
6083 return n;
6084 }
6085
6086 // Ignore for NetBIOS name registration packet
IsNetbiosRegistrationPacket(UCHAR * buf,UINT size)6087 bool IsNetbiosRegistrationPacket(UCHAR *buf, UINT size)
6088 {
6089 // Validate arguments
6090 if (buf == NULL || size == 0)
6091 {
6092 return false;
6093 }
6094
6095 if (size >= 4)
6096 {
6097 USHORT us = *((USHORT *)(buf + 2));
6098
6099 us = Endian16(us);
6100
6101 if (((us & 0x7800) >> 11) == 5)
6102 {
6103 return true;
6104 }
6105 }
6106
6107 return false;
6108 }
6109
6110 // Generate the encoded NetBIOS name
EncodeNetBiosName(UCHAR * dst,char * src)6111 void EncodeNetBiosName(UCHAR *dst, char *src)
6112 {
6113 char tmp[17];
6114 UINT i;
6115 UINT copy_len;
6116 UINT wp;
6117 // Validate arguments
6118 if (dst == NULL || src == NULL)
6119 {
6120 return;
6121 }
6122
6123 for (i = 0; i < 16; i++)
6124 {
6125 tmp[i] = ' ';
6126 }
6127 tmp[16] = 0;
6128
6129 copy_len = StrLen(src);
6130 if (copy_len > 16)
6131 {
6132 copy_len = 16;
6133 }
6134
6135 Copy(tmp, src, copy_len);
6136
6137 wp = 0;
6138
6139 tmp[15] = 0;
6140
6141 for (i = 0; i < 16; i++)
6142 {
6143 char c = tmp[i];
6144 char *s = CharToNetBiosStr(c);
6145
6146 dst[wp++] = s[0];
6147 dst[wp++] = s[1];
6148 }
6149 }
6150
6151 // Convert the string to NetBIOS characters
CharToNetBiosStr(char c)6152 char *CharToNetBiosStr(char c)
6153 {
6154 c = ToUpper(c);
6155
6156 switch (c)
6157 {
6158 case '\0':
6159 return "AA";
6160 case 'A':
6161 return "EB";
6162 case 'B':
6163 return "EC";
6164 case 'C':
6165 return "ED";
6166 case 'D':
6167 return "EE";
6168 case 'E':
6169 return "EF";
6170 case 'F':
6171 return "EG";
6172 case 'G':
6173 return "EH";
6174 case 'H':
6175 return "EI";
6176 case 'I':
6177 return "EJ";
6178 case 'J':
6179 return "EK";
6180 case 'K':
6181 return "EL";
6182 case 'L':
6183 return "EM";
6184 case 'M':
6185 return "EN";
6186 case 'N':
6187 return "EO";
6188 case 'O':
6189 return "EP";
6190 case 'P':
6191 return "FA";
6192 case 'Q':
6193 return "FB";
6194 case 'R':
6195 return "FC";
6196 case 'S':
6197 return "FD";
6198 case 'T':
6199 return "FE";
6200 case 'U':
6201 return "FF";
6202 case 'V':
6203 return "FG";
6204 case 'W':
6205 return "FH";
6206 case 'X':
6207 return "FI";
6208 case 'Y':
6209 return "FJ";
6210 case 'Z':
6211 return "FK";
6212 case '0':
6213 return "DA";
6214 case '1':
6215 return "DB";
6216 case '2':
6217 return "DC";
6218 case '3':
6219 return "DD";
6220 case '4':
6221 return "DE";
6222 case '5':
6223 return "DF";
6224 case '6':
6225 return "DG";
6226 case '7':
6227 return "DH";
6228 case '8':
6229 return "DI";
6230 case '9':
6231 return "DJ";
6232 case ' ':
6233 return "CA";
6234 case '!':
6235 return "CB";
6236 case '\"':
6237 return "CC";
6238 case '#':
6239 return "CD";
6240 case '$':
6241 return "CE";
6242 case '%':
6243 return "CF";
6244 case '&':
6245 return "CG";
6246 case '\'':
6247 return "CH";
6248 case '(':
6249 return "CI";
6250 case ')':
6251 return "CJ";
6252 case '*':
6253 return "CK";
6254 case '+':
6255 return "CL";
6256 case ',':
6257 return "CM";
6258 case '-':
6259 return "CN";
6260 case '.':
6261 return "CO";
6262 case '=':
6263 return "DN";
6264 case ':':
6265 return "DK";
6266 case ';':
6267 return "DL";
6268 case '@':
6269 return "EA";
6270 case '^':
6271 return "FO";
6272 case '_':
6273 return "FP";
6274 case '{':
6275 return "HL";
6276 case '}':
6277 return "HN";
6278 case '~':
6279 return "HO";
6280 }
6281
6282 return "CA";
6283 }
6284
6285 // Process if a NetBIOS name resolution packet for the my host name
ProcessNetBiosNameQueryPacketForMyself(VH * v,UINT src_ip,UINT src_port,UINT dest_ip,UINT dest_port,void * data,UINT size)6286 bool ProcessNetBiosNameQueryPacketForMyself(VH *v, UINT src_ip, UINT src_port, UINT dest_ip, UINT dest_port, void *data, UINT size)
6287 {
6288 BUF *rb;
6289 USHORT tran_id;
6290 USHORT flags;
6291 USHORT num_query;
6292 USHORT zero1, zero2, zero3;
6293 UCHAR name_size;
6294 UCHAR encoded_name[32];
6295 UCHAR node_type;
6296 USHORT type, classid;
6297 UCHAR my_pc_encoded_name[32];
6298 bool ret = false;
6299 // Validate arguments
6300 if (v == NULL || data == NULL)
6301 {
6302 return false;
6303 }
6304
6305 rb = NewBufFromMemory(data, size);
6306
6307 ReadBuf(rb, &tran_id, sizeof(USHORT));
6308
6309 ReadBuf(rb, &flags, sizeof(USHORT));
6310 flags = Endian16(flags);
6311
6312 ReadBuf(rb, &num_query, sizeof(USHORT));
6313 num_query = Endian16(num_query);
6314
6315 ReadBuf(rb, &zero1, sizeof(USHORT));
6316 ReadBuf(rb, &zero2, sizeof(USHORT));
6317 ReadBuf(rb, &zero3, sizeof(USHORT));
6318
6319 ReadBuf(rb, &name_size, 1);
6320
6321 ReadBuf(rb, encoded_name, 32);
6322
6323 ReadBuf(rb, &node_type, 1);
6324
6325 ReadBuf(rb, &type, sizeof(USHORT));
6326 type = Endian16(type);
6327
6328 if (ReadBuf(rb, &classid, sizeof(USHORT)) == sizeof(USHORT))
6329 {
6330 classid = Endian16(classid);
6331
6332 if (((flags >> 11) & 0x0F) == 0 &&
6333 num_query == 1 && name_size == 0x20 &&
6334 zero1 == 0 && zero2 == 0 && zero3 == 0 && node_type == 0 && type == 0x0020 && classid == 0x0001)
6335 {
6336 char my_pcname[MAX_SIZE];
6337
6338 // Get the encoded name of this PC
6339 Zero(my_pcname, sizeof(my_pcname));
6340 GetMachineHostName(my_pcname, sizeof(my_pcname));
6341
6342 EncodeNetBiosName(my_pc_encoded_name, my_pcname);
6343
6344 if (Cmp(my_pc_encoded_name, encoded_name, 30) == 0)
6345 {
6346 // Assemble the response packet since the name resolution packet which targets this PC name received
6347 BUF *sb = NewBuf();
6348 USHORT us;
6349 UINT ui;
6350 LIST *ip_list;
6351 BUF *ip_list_buf;
6352 bool found = false;
6353
6354 WriteBuf(sb, &tran_id, sizeof(USHORT));
6355
6356 flags = Endian16(0x8500);
6357 WriteBuf(sb, &flags, sizeof(USHORT));
6358
6359 num_query = 0;
6360 WriteBuf(sb, &num_query, sizeof(USHORT));
6361
6362 us = Endian16(1);
6363 WriteBuf(sb, &us, sizeof(USHORT));
6364
6365 us = 0;
6366 WriteBuf(sb, &us, sizeof(USHORT));
6367 WriteBuf(sb, &us, sizeof(USHORT));
6368
6369 name_size = 0x20;
6370 WriteBuf(sb, &name_size, 1);
6371
6372 WriteBuf(sb, encoded_name, 32);
6373
6374 node_type = 0;
6375 WriteBuf(sb, &node_type, 1);
6376
6377 type = Endian16(type);
6378 classid = Endian16(classid);
6379
6380 WriteBuf(sb, &type, sizeof(USHORT));
6381 WriteBuf(sb, &classid, sizeof(USHORT));
6382
6383 ui = Endian32((UINT)(Tick64() / 1000ULL));
6384 WriteBuf(sb, &ui, sizeof(UINT));
6385
6386 ip_list_buf = NewBuf();
6387
6388 ip_list = GetHostIPAddressList();
6389 if (ip_list != NULL)
6390 {
6391 UINT i;
6392
6393 // Return only private IP if there is a private IP
6394 for (i = 0; i < LIST_NUM(ip_list); i++)
6395 {
6396 IP *ip = LIST_DATA(ip_list, i);
6397
6398 if (IsIP4(ip) && IsLocalHostIP4(ip) == false && IsZeroIp(ip) == false)
6399 {
6400 if (IsIPPrivate(ip))
6401 {
6402 USHORT flags = Endian16(0x4000);
6403 UINT ip_uint = IPToUINT(ip);
6404
6405 WriteBuf(ip_list_buf, &flags, sizeof(USHORT));
6406 WriteBuf(ip_list_buf, &ip_uint, sizeof(UINT));
6407
6408 found = true;
6409 }
6410 }
6411 }
6412
6413 if (found == false)
6414 {
6415 // Return all IP if no private IP are found
6416 for (i = 0; i < LIST_NUM(ip_list); i++)
6417 {
6418 IP *ip = LIST_DATA(ip_list, i);
6419
6420 if (IsIP4(ip) && IsLocalHostIP4(ip) == false && IsZeroIp(ip) == false)
6421 {
6422 USHORT flags = Endian16(0x4000);
6423 UINT ip_uint = IPToUINT(ip);
6424
6425 WriteBuf(ip_list_buf, &flags, sizeof(USHORT));
6426 WriteBuf(ip_list_buf, &ip_uint, sizeof(UINT));
6427
6428 found = true;
6429 }
6430 }
6431 }
6432
6433 FreeHostIPAddressList(ip_list);
6434 }
6435
6436 us = Endian16(ip_list_buf->Size);
6437 WriteBuf(sb, &us, sizeof(USHORT));
6438
6439 WriteBufBuf(sb, ip_list_buf);
6440
6441 SendUdp(v, src_ip, src_port, v->HostIP, dest_port, sb->Buf, sb->Size);
6442
6443 FreeBuf(ip_list_buf);
6444
6445 FreeBuf(sb);
6446
6447 WHERE;
6448 }
6449 }
6450 }
6451
6452 FreeBuf(rb);
6453
6454 return ret;
6455 }
6456
6457 // Process the NetBIOS broadcast packet
UdpRecvForNetBiosBroadcast(VH * v,UINT src_ip,UINT src_port,UINT dest_ip,UINT dest_port,void * data,UINT size,bool dns_proxy,bool unicast)6458 void UdpRecvForNetBiosBroadcast(VH *v, UINT src_ip, UINT src_port, UINT dest_ip, UINT dest_port, void *data, UINT size, bool dns_proxy, bool unicast)
6459 {
6460 // Validate arguments
6461 if (data == NULL || v == NULL)
6462 {
6463 return;
6464 }
6465
6466 // Ignore for NetBIOS name registration packet
6467 if (IsNetbiosRegistrationPacket(data, size) == false)
6468 {
6469 if (unicast == false)
6470 {
6471 dest_ip = 0xFFFFFFFF;
6472 }
6473
6474 if (ProcessNetBiosNameQueryPacketForMyself(v, src_ip, src_port, dest_ip, dest_port, data, size) == false)
6475 {
6476 UdpRecvForInternet(v, src_ip, src_port, dest_ip, dest_port, data, size, false);
6477 }
6478 }
6479 }
6480
6481 // Process the UDP packet to the Internet
UdpRecvForInternet(VH * v,UINT src_ip,UINT src_port,UINT dest_ip,UINT dest_port,void * data,UINT size,bool dns_proxy)6482 void UdpRecvForInternet(VH *v, UINT src_ip, UINT src_port, UINT dest_ip, UINT dest_port, void *data, UINT size, bool dns_proxy)
6483 {
6484 NAT_ENTRY *n, t;
6485 BLOCK *block;
6486 void *buf;
6487 UINT dns_ip = 0;
6488 // Validate arguments
6489 if (data == NULL || v == NULL)
6490 {
6491 return;
6492 }
6493
6494 if (dns_proxy)
6495 {
6496 // Get the DNS server of the proxy to connect to
6497 IP ip;
6498 char tmp[MAX_SIZE];
6499 if (GetDefaultDns(&ip) == false)
6500 {
6501 // Failure
6502 Debug("Failed to GetDefaultDns()\n");
6503 return;
6504 }
6505 dns_ip = IPToUINT(&ip);
6506 IPToStr(tmp, sizeof(tmp), &ip);
6507 Debug("Redirect to DNS Server %s\n", tmp);
6508 }
6509
6510 // Examine whether the NAT entry for this packet has already been created
6511 SetNat(&t, NAT_UDP, src_ip, src_port, dest_ip, dest_port, 0, 0);
6512 n = SearchNat(v, &t);
6513
6514 if (n == NULL)
6515 {
6516 // Create a NAT entry because it is the first packet
6517 n = CreateNatUdp(v, src_ip, src_port, dest_ip, dest_port, dns_proxy ? dns_ip : 0);
6518 if (n == NULL)
6519 {
6520 // Entry creation failed
6521 return;
6522 }
6523
6524 if (dns_proxy)
6525 {
6526 n->ProxyDns = true;
6527 n->DestIpProxy = dns_ip;
6528 }
6529 }
6530
6531 // Set the event by inserting the packet into the queue
6532 buf = Malloc(size);
6533 Copy(buf, data, size);
6534 block = NewBlock(buf, size, 0);
6535 InsertQueue(n->UdpSendQueue, block);
6536
6537 SetSockEvent(v->SockEvent);
6538 }
6539
6540 // Attempt to interpret the DNS packet
ParseDnsPacket(VH * v,UINT src_ip,UINT src_port,UINT dest_ip,UINT dest_port,void * data,UINT size)6541 bool ParseDnsPacket(VH *v, UINT src_ip, UINT src_port, UINT dest_ip, UINT dest_port, void *data, UINT size)
6542 {
6543 return ParseDnsPacketEx(v, src_ip, src_port, dest_ip, dest_port, data, size, NULL);
6544 }
ParseDnsPacketEx(VH * v,UINT src_ip,UINT src_port,UINT dest_ip,UINT dest_port,void * data,UINT size,DNS_PARSED_PACKET * parsed_result)6545 bool ParseDnsPacketEx(VH *v, UINT src_ip, UINT src_port, UINT dest_ip, UINT dest_port, void *data, UINT size, DNS_PARSED_PACKET *parsed_result)
6546 {
6547 DNSV4_HEADER *dns;
6548 NAT_ENTRY *nat;
6549 UINT transaction_id;
6550 void *query_data;
6551 UINT query_data_size;
6552 char hostname[256];
6553 // Validate arguments
6554 if (v == NULL || data == NULL || size == 0)
6555 {
6556 return false;
6557 }
6558
6559 // Check the header size
6560 if (size < sizeof(DNSV4_HEADER))
6561 {
6562 // Undersize
6563 return false;
6564 }
6565
6566 // DNS header acquisition
6567 dns = (DNSV4_HEADER *)data;
6568 transaction_id = Endian16(dns->TransactionId);
6569 if ((dns->Flag1 & 78) != 0 || (dns->Flag1 & 0x80) != 0)
6570 {
6571 // Illegal opcode
6572 return false;
6573 }
6574 if (Endian16(dns->NumQuery) != 1)
6575 {
6576 // Number of queries is invalid
6577 return false;
6578 }
6579
6580 query_data = ((UCHAR *)dns) + sizeof(DNSV4_HEADER);
6581 query_data_size = size - sizeof(DNSV4_HEADER);
6582
6583 // Interpret the query
6584 if (ParseDnsQuery(hostname, sizeof(hostname), query_data, query_data_size) == false)
6585 {
6586 // Interpretation fails
6587 return false;
6588 }
6589
6590 if (parsed_result != NULL)
6591 {
6592 // Only analyse without processing
6593 Zero(parsed_result, sizeof(DNS_PARSED_PACKET));
6594 StrCpy(parsed_result->Hostname, sizeof(parsed_result->Hostname), hostname);
6595 parsed_result->TransactionId = transaction_id;
6596
6597 return true;
6598 }
6599
6600 // Create a DNS entry
6601 nat = CreateNatDns(v, src_ip, src_port, dest_ip, dest_port, transaction_id,
6602 false, hostname);
6603
6604 if (nat == false)
6605 {
6606 return false;
6607 }
6608
6609 return true;
6610 }
6611
6612 // Send the NAT DNS response packet
SendNatDnsResponse(VH * v,NAT_ENTRY * n)6613 void SendNatDnsResponse(VH *v, NAT_ENTRY *n)
6614 {
6615 BUF *b;
6616 UINT dns_header_size;
6617 DNSV4_HEADER *dns;
6618 UINT src_ip;
6619 // Validate arguments
6620 if (n == NULL || v == NULL)
6621 {
6622 return;
6623 }
6624
6625 // Generate the data
6626 b = NewBuf();
6627
6628 // Add a Query
6629 if (n->DnsGetIpFromHost == false)
6630 {
6631 BuildDnsQueryPacket(b, n->DnsTargetHostName, false);
6632 }
6633 else
6634 {
6635 BuildDnsQueryPacket(b, n->DnsTargetHostName, true);
6636 }
6637
6638 // Add a Response
6639 if (n->DnsOk)
6640 {
6641 if (n->DnsGetIpFromHost == false)
6642 {
6643 BuildDnsResponsePacketA(b, &n->DnsResponseIp);
6644 }
6645 else
6646 {
6647 BuildDnsResponsePacketPtr(b, n->DnsResponseHostName);
6648 }
6649 }
6650
6651 // Generate a DNS header
6652 dns_header_size = sizeof(DNSV4_HEADER) + b->Size;
6653
6654 dns = ZeroMalloc(dns_header_size);
6655 dns->TransactionId = Endian16((USHORT)n->DnsTransactionId);
6656
6657 // Generate a response flag
6658 if (n->DnsOk)
6659 {
6660 dns->Flag1 = 0x85;
6661 dns->Flag2 = 0x80;
6662 }
6663 else
6664 {
6665 dns->Flag1 = 0x85;
6666 dns->Flag2 = 0x83;
6667 }
6668
6669 dns->NumQuery = Endian16(1);
6670 dns->AnswerRRs = Endian16(n->DnsOk != false ? 1 : 0);
6671 dns->AuthorityRRs = 0;
6672 dns->AdditionalRRs = 0;
6673
6674 // Settings, such as the source IP address
6675 src_ip = n->DestIp;
6676 if (src_ip == Endian32(SPECIAL_IPV4_ADDR_LLMNR_DEST) && n->DestPort == SPECIAL_UDP_PORT_LLMNR)
6677 {
6678 // Make a unicast response in the case of LLMNR packet
6679 src_ip = v->HostIP;
6680
6681 dns->Flag1 = 0x84;
6682 dns->Flag2 = 0x00;
6683 }
6684
6685 // Copy data
6686 Copy(((UCHAR *)dns) + sizeof(DNSV4_HEADER), b->Buf, b->Size);
6687
6688 // Send this packet
6689 SendUdp(v, n->SrcIp, n->SrcPort, src_ip, n->DestPort, dns, dns_header_size);
6690
6691 // Release the memory
6692 Free(dns);
6693 FreeBuf(b);
6694 }
6695
6696 // Generate a DNS response packet (host name)
BuildDnsResponsePacketPtr(BUF * b,char * hostname)6697 void BuildDnsResponsePacketPtr(BUF *b, char *hostname)
6698 {
6699 USHORT magic;
6700 USHORT type, clas;
6701 UINT ttl;
6702 USHORT len;
6703 BUF *c;
6704 // Validate arguments
6705 if (b == NULL || hostname == NULL)
6706 {
6707 return;
6708 }
6709
6710 magic = Endian16(0xc00c);
6711 type = Endian16(0x000c);
6712 clas = Endian16(0x0001);
6713 ttl = Endian32(NAT_DNS_RESPONSE_TTL);
6714
6715 c = BuildDnsHostName(hostname);
6716 if (c == NULL)
6717 {
6718 return;
6719 }
6720 len = Endian16((USHORT)c->Size);
6721
6722 WriteBuf(b, &magic, 2);
6723 WriteBuf(b, &type, 2);
6724 WriteBuf(b, &clas, 2);
6725 WriteBuf(b, &ttl, 4);
6726 WriteBuf(b, &len, 2);
6727 WriteBuf(b, c->Buf, c->Size);
6728 FreeBuf(c);
6729 }
6730
6731 // Generate a DNS response packet (host IP address)
BuildDnsResponsePacketA(BUF * b,IP * ip)6732 void BuildDnsResponsePacketA(BUF *b, IP *ip)
6733 {
6734 UINT ip_addr;
6735 USHORT magic;
6736 USHORT type, clas;
6737 UINT ttl;
6738 USHORT len;
6739 // Validate arguments
6740 if (b == NULL || ip == NULL)
6741 {
6742 return;
6743 }
6744
6745 ip_addr = IPToUINT(ip);
6746 magic = Endian16(0xc00c);
6747 type = Endian16(0x0001);
6748 clas = Endian16(0x0001);
6749 ttl = Endian32(NAT_DNS_RESPONSE_TTL);
6750 len = Endian16((USHORT)sizeof(ttl));
6751
6752 WriteBuf(b, &magic, sizeof(magic));
6753 WriteBuf(b, &type, sizeof(type));
6754 WriteBuf(b, &clas, sizeof(clas));
6755 WriteBuf(b, &ttl, sizeof(ttl));
6756 WriteBuf(b, &len, sizeof(len));
6757 WriteBuf(b, &ip_addr, sizeof(ip_addr));
6758 }
6759
6760 // Generate a DNS query data packet
BuildDnsQueryPacket(BUF * b,char * hostname,bool ptr)6761 void BuildDnsQueryPacket(BUF *b, char *hostname, bool ptr)
6762 {
6763 USHORT val;
6764 BUF *c;
6765 // Validate arguments
6766 if (b == NULL || hostname == NULL)
6767 {
6768 return;
6769 }
6770
6771 // Convert the host name to a buffer
6772 c = BuildDnsHostName(hostname);
6773 if (c == NULL)
6774 {
6775 return;
6776 }
6777
6778 WriteBuf(b, c->Buf, c->Size);
6779 FreeBuf(c);
6780
6781 // Type and class
6782 if (ptr == false)
6783 {
6784 val = Endian16(0x0001);
6785 }
6786 else
6787 {
6788 val = Endian16(0x000c);
6789 }
6790 WriteBuf(b, &val, 2);
6791
6792 val = Endian16(0x0001);
6793 WriteBuf(b, &val, 2);
6794 }
6795
6796 // Generate a DNS host name buffer
BuildDnsHostName(char * hostname)6797 BUF *BuildDnsHostName(char *hostname)
6798 {
6799 UINT i;
6800 UCHAR size;
6801 TOKEN_LIST *token;
6802 BUF *b;
6803 // Validate arguments
6804 if (hostname == NULL)
6805 {
6806 return NULL;
6807 }
6808
6809 // Split the host name into tokens
6810 token = ParseToken(hostname, ".");
6811 if (token == NULL)
6812 {
6813 return NULL;
6814 }
6815
6816 b = NewBuf();
6817
6818 // Add a host string
6819 for (i = 0; i < token->NumTokens; i++)
6820 {
6821 size = (UCHAR)StrLen(token->Token[i]);
6822 WriteBuf(b, &size, 1);
6823 WriteBuf(b, token->Token[i], size);
6824 }
6825
6826 // NULL character
6827 size = 0;
6828 WriteBuf(b, &size, 1);
6829
6830 SeekBuf(b, 0, 0);
6831
6832 FreeToken(token);
6833
6834 return b;
6835 }
6836
6837 // Process the NAT DNS entry
PollingNatDns(VH * v,NAT_ENTRY * n)6838 void PollingNatDns(VH *v, NAT_ENTRY *n)
6839 {
6840 // Validate arguments
6841 if (v == NULL || n == NULL)
6842 {
6843 return;
6844 }
6845
6846 if (n->DnsFinished)
6847 {
6848 if (n->DnsPollingFlag == false)
6849 {
6850 n->DnsPollingFlag = true;
6851 // Process has been completed
6852 SendNatDnsResponse(v, n);
6853
6854 // Terminating
6855 n->DisconnectNow = true;
6856 }
6857 }
6858 }
6859
6860 // Create a NAT DNS entry
CreateNatDns(VH * v,UINT src_ip,UINT src_port,UINT dest_ip,UINT dest_port,UINT transaction_id,bool dns_get_ip_from_host,char * dns_target_host_name)6861 NAT_ENTRY *CreateNatDns(VH *v, UINT src_ip, UINT src_port, UINT dest_ip, UINT dest_port,
6862 UINT transaction_id, bool dns_get_ip_from_host, char *dns_target_host_name)
6863 {
6864 NAT_ENTRY *n;
6865 HUB_OPTION *o;
6866 // Validate arguments
6867 if (v == NULL || dns_target_host_name == NULL)
6868 {
6869 return NULL;
6870 }
6871
6872 if (CanCreateNewNatEntry(v) == false)
6873 {
6874 return NULL;
6875 }
6876
6877 o = NatGetHubOption(v);
6878 if (o != NULL && o->SecureNAT_MaxDnsSessionsPerIp != 0)
6879 {
6880 if (GetNumNatEntriesPerIp(v, src_ip, NAT_DNS, false) >= o->SecureNAT_MaxDnsSessionsPerIp)
6881 {
6882 NAT_ENTRY *oldest = GetOldestNatEntryOfIp(v, src_ip, NAT_DNS);
6883
6884 if (oldest != NULL)
6885 {
6886 DisconnectNatEntryNow(v, oldest);
6887 }
6888 }
6889 }
6890
6891 n = ZeroMalloc(sizeof(NAT_ENTRY));
6892 n->Id = Inc(v->Counter);
6893 n->v = v;
6894 n->lock = NewLock();
6895 n->Protocol = NAT_DNS;
6896 n->SrcIp = src_ip;
6897 n->SrcPort = src_port;
6898 n->DestIp = dest_ip;
6899 n->DestPort = dest_port;
6900 n->DnsTransactionId = transaction_id;
6901 n->CreatedTime = n->LastCommTime = v->Now;
6902 n->DisconnectNow = false;
6903
6904 n->DnsGetIpFromHost = false;
6905 n->DnsTargetHostName = CopyStr(dns_target_host_name);
6906
6907 Add(v->NatTable, n);
6908
6909 #if 1
6910 {
6911 IP ip1, ip2;
6912 char s1[MAX_SIZE], s2[MAX_SIZE];
6913 UINTToIP(&ip1, src_ip);
6914 UINTToIP(&ip2, dest_ip);
6915 IPToStr(s1, 0, &ip1);
6916 IPToStr(s2, 0, &ip2);
6917 Debug("NAT_ENTRY: CreateNatDns %s %u -> %s %u\n", s1, src_port, s2, dest_port);
6918 }
6919 #endif
6920
6921
6922 return n;
6923 }
6924
6925 // Set the VGS host name
SetDnsProxyVgsHostname(char * hostname)6926 void SetDnsProxyVgsHostname(char *hostname)
6927 {
6928 // Validate arguments
6929 if (hostname == NULL)
6930 {
6931 return;
6932 }
6933
6934 StrCpy(v_vgs_hostname, sizeof(v_vgs_hostname), hostname);
6935 }
6936
6937 // Operate as a DNS proxy
DnsProxy(VH * v,UINT src_ip,UINT src_port,UINT dest_ip,UINT dest_port,void * data,UINT size)6938 void DnsProxy(VH *v, UINT src_ip, UINT src_port, UINT dest_ip, UINT dest_port, void *data, UINT size)
6939 {
6940 // Validate arguments
6941 if (v == NULL || data == NULL || size == 0)
6942 {
6943 return;
6944 }
6945
6946 if (dest_port == SPECIAL_UDP_PORT_LLMNR)
6947 {
6948 // Process by analyzing the DNS query in the case of LLMNR
6949 ParseDnsPacket(v, src_ip, src_port, dest_ip, dest_port, data, size);
6950 }
6951 else
6952 {
6953 // Forward the packet as it is in the case of a normal DNS packet
6954 if (IsEmptyStr(v_vgs_hostname) == false)
6955 {
6956 // Response by proxy in the case of trying to get the IP of the VGS
6957 DNS_PARSED_PACKET p;
6958
6959 Zero(&p, sizeof(p));
6960 if (ParseDnsPacketEx(v, src_ip, src_port, dest_ip, dest_port, data, size, &p))
6961 {
6962 if (StrCmpi(p.Hostname, "254.254.211.10.in-addr.arpa") == 0)
6963 {
6964 NAT_ENTRY n;
6965
6966 Zero(&n, sizeof(n));
6967 n.DnsTargetHostName = p.Hostname;
6968 n.DnsGetIpFromHost = true;
6969 n.DnsResponseHostName = v_vgs_hostname;
6970 n.DnsTransactionId = p.TransactionId;
6971 n.DnsOk = true;
6972 n.DestIp = dest_ip;
6973 n.SrcIp = src_ip;
6974 n.DestPort = dest_port;
6975 n.SrcPort = src_port;
6976
6977 SendNatDnsResponse(v, &n);
6978 return;
6979 }
6980 }
6981 }
6982
6983 UdpRecvForInternet(v, src_ip, src_port, dest_ip, dest_port, data, size, true);
6984 }
6985 }
6986
6987 // Process the LLMNR query
UdpRecvLlmnr(VH * v,UINT src_ip,UINT src_port,UINT dest_ip,UINT dest_port,void * data,UINT size)6988 void UdpRecvLlmnr(VH *v, UINT src_ip, UINT src_port, UINT dest_ip, UINT dest_port, void *data, UINT size)
6989 {
6990 // Validate arguments
6991 if (data == NULL || v == NULL)
6992 {
6993 return;
6994 }
6995
6996 if (dest_port == SPECIAL_UDP_PORT_LLMNR)
6997 {
6998 // DNS proxy start
6999 DnsProxy(v, src_ip, src_port, dest_ip, dest_port, data, size);
7000 }
7001 }
7002
7003 // Process the UDP packet to the virtual host
UdpRecvForMe(VH * v,UINT src_ip,UINT src_port,UINT dest_ip,UINT dest_port,void * data,UINT size)7004 void UdpRecvForMe(VH *v, UINT src_ip, UINT src_port, UINT dest_ip, UINT dest_port, void *data, UINT size)
7005 {
7006 // Validate arguments
7007 if (data == NULL || v == NULL)
7008 {
7009 return;
7010 }
7011
7012 if (dest_port == NAT_DNS_PROXY_PORT)
7013 {
7014 // DNS proxy start
7015 DnsProxy(v, src_ip, src_port, dest_ip, dest_port, data, size);
7016 }
7017 }
7018
7019 // Process the UDP broadcast packet
UdpRecvForBroadcast(VH * v,UINT src_ip,UINT src_port,UINT dest_ip,UINT dest_port,void * data,UINT size)7020 void UdpRecvForBroadcast(VH *v, UINT src_ip, UINT src_port, UINT dest_ip, UINT dest_port, void *data, UINT size)
7021 {
7022 // Validate arguments
7023 if (data == NULL || v == NULL)
7024 {
7025 return;
7026 }
7027 }
7028
7029 // An UDP packet has been received
VirtualUdpReceived(VH * v,UINT src_ip,UINT dest_ip,void * data,UINT size,bool mac_broadcast,bool is_localmac,UINT max_l3_size)7030 void VirtualUdpReceived(VH *v, UINT src_ip, UINT dest_ip, void *data, UINT size, bool mac_broadcast, bool is_localmac, UINT max_l3_size)
7031 {
7032 UDP_HEADER *udp;
7033 UINT packet_length;
7034 void *buf;
7035 UINT buf_size;
7036 UINT src_port, dest_port;
7037 // Validate arguments
7038 if (v == NULL || data == NULL)
7039 {
7040 return;
7041 }
7042
7043 // Check the header
7044 udp = (UDP_HEADER *)data;
7045 if (size < UDP_HEADER_SIZE)
7046 {
7047 return;
7048 }
7049 packet_length = Endian16(udp->PacketLength);
7050 if (packet_length != size)
7051 {
7052 return;
7053 }
7054 buf = ((UCHAR *)data) + UDP_HEADER_SIZE;
7055 buf_size = size - UDP_HEADER_SIZE;
7056 src_port = Endian16(udp->SrcPort);
7057 dest_port = Endian16(udp->DstPort);
7058 // Check the port number
7059 if (dest_port == 0)
7060 {
7061 // Port number is invalid
7062 return;
7063 }
7064
7065 // Determine whether it's broadcast packet or packet addressed to myself
7066 if (dest_ip == v->HostIP)
7067 {
7068 // IP packet addressed to myself has arrived
7069 UdpRecvForMe(v, src_ip, src_port, dest_ip, dest_port, buf, buf_size);
7070 }
7071 else if ((mac_broadcast || dest_ip == Endian32(0xE00000FC)) && dest_port == SPECIAL_UDP_PORT_LLMNR)
7072 {
7073 if (is_localmac == false)
7074 {
7075 // Packet addressed to 224.0.0.252 (LLMNR) arrives
7076 UdpRecvLlmnr(v, src_ip, src_port, dest_ip, dest_port, buf, buf_size);
7077 }
7078 }
7079 else if (mac_broadcast && (dest_port == SPECIAL_UDP_PORT_WSD || dest_port == SPECIAL_UDP_PORT_SSDP))
7080 {
7081 if (is_localmac == false)
7082 {
7083 // WS-Discovery packet arrives
7084 UdpRecvForInternet(v, src_ip, src_port, 0xFFFFFFFF, dest_port, buf, buf_size, false);
7085 }
7086 }
7087 else if (mac_broadcast && (dest_port == SPECIAL_UDP_PORT_NBTDGM || dest_port == SPECIAL_UDP_PORT_NBTNS))
7088 {
7089 if (is_localmac == false)
7090 {
7091 // NetBIOS Broadcast packet arrived
7092 UdpRecvForNetBiosBroadcast(v, src_ip, src_port, dest_ip, dest_port, buf, buf_size, false, false);
7093 }
7094 }
7095 else if (mac_broadcast || dest_ip == 0xffffffff || dest_ip == GetBroadcastAddress(v->HostIP, v->HostMask))
7096 {
7097 if (is_localmac == false)
7098 {
7099 // Broadcast packet arrived
7100 UdpRecvForBroadcast(v, src_ip, src_port, dest_ip, dest_port, buf, buf_size);
7101 }
7102 }
7103 else if (IsInNetwork(dest_ip, v->HostIP, v->HostMask) == false)
7104 {
7105 // Packets to other than local address (that is on the Internet) has been received
7106 if (NnIsActive(v) == false)
7107 {
7108 if (v->HubOption != NULL && v->HubOption->DisableUserModeSecureNAT)
7109 {
7110 // User-mode NAT is disabled
7111 return;
7112 }
7113
7114 // User-mode NAT
7115 UdpRecvForInternet(v, src_ip, src_port, dest_ip, dest_port, buf, buf_size, false);
7116 }
7117 else
7118 {
7119 // Kernel-mode NAT
7120 NnUdpRecvForInternet(v, src_ip, src_port, dest_ip, dest_port, buf, buf_size, max_l3_size);
7121 }
7122 }
7123 else
7124 {
7125 // Local address has arrived. Ignore it
7126 }
7127 }
7128
7129 // Determine the network address of the subnet to which the specified IP address belongs
GetNetworkAddress(UINT addr,UINT mask)7130 UINT GetNetworkAddress(UINT addr, UINT mask)
7131 {
7132 return (addr & mask);
7133 }
7134
7135 // Determine the broadcast address of the subnet to which the specified IP address belongs
GetBroadcastAddress(UINT addr,UINT mask)7136 UINT GetBroadcastAddress(UINT addr, UINT mask)
7137 {
7138 return ((addr & mask) | (~mask));
7139 }
GetBroadcastAddress4(IP * dst,IP * addr,IP * mask)7140 void GetBroadcastAddress4(IP *dst, IP *addr, IP *mask)
7141 {
7142 // Validate arguments
7143 if (dst == NULL || IsIP4(addr) == false || IsIP4(mask) == false)
7144 {
7145 Zero(dst, sizeof(IP));
7146 return;
7147 }
7148
7149 UINTToIP(dst, GetBroadcastAddress(IPToUINT(addr), IPToUINT(mask)));
7150 }
7151
7152 // Determine whether the specified IP address belongs to the sub-network that is
7153 // represented by a another specified network address and a subnet mask
IsInNetwork(UINT uni_addr,UINT network_addr,UINT mask)7154 bool IsInNetwork(UINT uni_addr, UINT network_addr, UINT mask)
7155 {
7156 if (GetNetworkAddress(uni_addr, mask) == GetNetworkAddress(network_addr, mask))
7157 {
7158 return true;
7159 }
7160 return false;
7161 }
7162
7163 // Send an UDP packet
SendUdp(VH * v,UINT dest_ip,UINT dest_port,UINT src_ip,UINT src_port,void * data,UINT size)7164 void SendUdp(VH *v, UINT dest_ip, UINT dest_port, UINT src_ip, UINT src_port, void *data, UINT size)
7165 {
7166 UDPV4_PSEUDO_HEADER *vh;
7167 UDP_HEADER *udp;
7168 UINT udp_packet_length = UDP_HEADER_SIZE + size;
7169 USHORT checksum;
7170 // Validate arguments
7171 if (v == NULL || data == NULL)
7172 {
7173 return;
7174 }
7175 if (udp_packet_length > 65536)
7176 {
7177 return;
7178 }
7179
7180 // Generate a virtual header
7181 vh = Malloc(sizeof(UDPV4_PSEUDO_HEADER) + size);
7182 udp = (UDP_HEADER *)(((UCHAR *)vh) + 12);
7183
7184 vh->SrcIP = src_ip;
7185 vh->DstIP = dest_ip;
7186 vh->Reserved = 0;
7187 vh->Protocol = IP_PROTO_UDP;
7188 vh->PacketLength1 = Endian16((USHORT)udp_packet_length);
7189 udp->SrcPort = Endian16((USHORT)src_port);
7190 udp->DstPort = Endian16((USHORT)dest_port);
7191 udp->PacketLength = Endian16((USHORT)udp_packet_length);
7192 udp->Checksum = 0;
7193
7194 // Copy data
7195 Copy(((UCHAR *)udp) + UDP_HEADER_SIZE, data, size);
7196
7197 // Calculate the checksum
7198 checksum = IpChecksum(vh, udp_packet_length + 12);
7199 if (checksum == 0x0000)
7200 {
7201 checksum = 0xffff;
7202 }
7203 udp->Checksum = checksum;
7204
7205 // Send a packet
7206 SendIp(v, dest_ip, src_ip, IP_PROTO_UDP, udp, udp_packet_length);
7207
7208 // Release the memory
7209 Free(vh);
7210 }
7211
7212 // Poll the IP combining object
PollingIpCombine(VH * v)7213 void PollingIpCombine(VH *v)
7214 {
7215 LIST *o;
7216 UINT i;
7217 // Validate arguments
7218 if (v == NULL)
7219 {
7220 return;
7221 }
7222
7223 // Discard the old combining object
7224 o = NULL;
7225 for (i = 0; i < LIST_NUM(v->IpCombine); i++)
7226 {
7227 IP_COMBINE *c = LIST_DATA(v->IpCombine, i);
7228
7229 if (c->Expire < v->Now)
7230 {
7231 if (o == NULL)
7232 {
7233 o = NewListFast(NULL);
7234 }
7235 Add(o, c);
7236 }
7237 }
7238
7239 if (o != NULL)
7240 {
7241 for (i = 0; i < LIST_NUM(o); i++)
7242 {
7243 IP_COMBINE *c = LIST_DATA(o, i);
7244
7245 // Remove from the list
7246 Delete(v->IpCombine, c);
7247
7248 // Release the memory
7249 FreeIpCombine(v, c);
7250 }
7251 ReleaseList(o);
7252 }
7253 }
7254
7255 // Send an ICMP packet
VirtualIcmpSend(VH * v,UINT src_ip,UINT dst_ip,void * data,UINT size)7256 void VirtualIcmpSend(VH *v, UINT src_ip, UINT dst_ip, void *data, UINT size)
7257 {
7258 ICMP_HEADER *icmp;
7259 void *data_buf;
7260 // Validate arguments
7261 if (v == NULL || data == NULL)
7262 {
7263 return;
7264 }
7265
7266 // Build the header
7267 icmp = ZeroMalloc(sizeof(ICMP_HEADER) + size);
7268 // Data copy
7269 data_buf = ((UCHAR *)icmp) + sizeof(ICMP_HEADER);
7270 Copy(data_buf, data, size);
7271 // Other
7272 icmp->Checksum = 0;
7273 icmp->Code = 0;
7274 icmp->Type = ICMP_TYPE_ECHO_RESPONSE;
7275 // Checksum
7276 icmp->Checksum = IpChecksum(icmp, sizeof(ICMP_HEADER) + size);
7277
7278 // IP packet transmission
7279 SendIp(v, dst_ip, src_ip, IP_PROTO_ICMPV4, icmp, sizeof(ICMP_HEADER) + size);
7280
7281 // Release the memory
7282 Free(icmp);
7283 }
7284
7285 // Send the ICMP Echo Response packet
VirtualIcmpEchoSendResponse(VH * v,UINT src_ip,UINT dst_ip,USHORT id,USHORT seq_no,void * data,UINT size)7286 void VirtualIcmpEchoSendResponse(VH *v, UINT src_ip, UINT dst_ip, USHORT id, USHORT seq_no, void *data, UINT size)
7287 {
7288 ICMP_ECHO *e;
7289 // Validate arguments
7290 if (v == NULL || data == NULL)
7291 {
7292 return;
7293 }
7294
7295 // Build the header
7296 e = ZeroMalloc(sizeof(ICMP_ECHO) + size);
7297 e->Identifier = Endian16(id);
7298 e->SeqNo = Endian16(seq_no);
7299
7300 // Data copy
7301 Copy(((UCHAR *)e) + sizeof(ICMP_ECHO), data, size);
7302
7303 // Send an ICMP
7304 VirtualIcmpSend(v, src_ip, dst_ip, e, sizeof(ICMP_ECHO) + size);
7305
7306 // Release the memory
7307 Free(e);
7308 }
7309
7310 // Treat the ICMP Echo Request packet with a Raw Socket
VirtualIcmpEchoRequestReceivedRaw(VH * v,UINT src_ip,UINT dst_ip,void * data,UINT size,UCHAR ttl,void * icmp_data,UINT icmp_size,UCHAR * ip_header,UINT ip_header_size)7311 void VirtualIcmpEchoRequestReceivedRaw(VH *v, UINT src_ip, UINT dst_ip, void *data, UINT size, UCHAR ttl, void *icmp_data, UINT icmp_size, UCHAR *ip_header, UINT ip_header_size)
7312 {
7313 ICMP_ECHO *echo;
7314 UINT data_size;
7315 void *data_buf;
7316 USHORT id, seq_no;
7317 void *buf;
7318 BLOCK *block;
7319 // Validate arguments
7320 if (v == NULL || data == NULL || icmp_data == NULL || ip_header == NULL)
7321 {
7322 return;
7323 }
7324 if (ttl == 0)
7325 {
7326 ttl = 1;
7327 }
7328
7329 echo = (ICMP_ECHO *)data;
7330
7331 // Echo size check
7332 if (size < sizeof(ICMP_ECHO))
7333 {
7334 // Insufficient data
7335 return;
7336 }
7337
7338 id = Endian16(echo->Identifier);
7339 seq_no = Endian16(echo->SeqNo);
7340
7341 // Data size
7342 data_size = size - sizeof(ICMP_ECHO);
7343
7344 // Data body
7345 data_buf = ((UCHAR *)data) + sizeof(ICMP_ECHO);
7346
7347 if (dst_ip == v->HostIP)
7348 {
7349 // Respond because it is addressed to me
7350 VirtualIcmpEchoSendResponse(v, v->HostIP, src_ip, id, seq_no, data_buf, data_size);
7351 }
7352 else if (IsInNetwork(dst_ip, v->HostIP, v->HostMask) == false)
7353 {
7354 NAT_ENTRY *n = NULL, t;
7355 // Process by creating a NAT entry because it is addressed to the Internet
7356
7357 if (ttl <= 1)
7358 {
7359 // Reply the Time Exceeded immediately for the packet whose TTL is 1
7360 UINT reply_size = sizeof(ICMP_HEADER) + 4 + ip_header_size + 8;
7361 UCHAR *reply_data = ZeroMalloc(reply_size);
7362 ICMP_HEADER *icmp = (ICMP_HEADER *)reply_data;
7363 icmp->Type = ICMP_TYPE_TIME_EXCEEDED;
7364 icmp->Code = ICMP_CODE_TTL_EXCEEDED_IN_TRANSIT;
7365 Copy(reply_data + sizeof(ICMP_HEADER) + 4, ip_header, ip_header_size);
7366 Copy(reply_data + sizeof(ICMP_HEADER) + 4 + ip_header_size, icmp_data, MIN(icmp_size, 8));
7367
7368 icmp->Checksum = IpChecksum(icmp, reply_size);
7369
7370 SendIp(v, src_ip, v->HostIP, IP_PROTO_ICMPV4, reply_data, reply_size);
7371
7372 Free(reply_data);
7373 }
7374 else
7375 {
7376 SetNat(&t, NAT_ICMP, src_ip, id, dst_ip, id, 0, 0);
7377
7378 if (v->IcmpRawSocketOk)
7379 {
7380 // Examine whether a NAT entry for this packet has already been created
7381 n = SearchNat(v, &t);
7382 }
7383
7384 if (n == NULL)
7385 {
7386 // Create a NAT entry because it is the first packet
7387 n = CreateNatIcmp(v, src_ip, id, dst_ip, id, (UCHAR *)ip_header, ip_header_size + 8);
7388
7389 if (n == NULL)
7390 {
7391 // Entry creation failed
7392 return;
7393 }
7394 }
7395
7396 // Set the event by inserting the packet into the queue
7397 buf = Malloc(icmp_size);
7398 Copy(buf, icmp_data, icmp_size);
7399 block = NewBlock(buf, icmp_size, 0);
7400 block->Ttl = MAKESURE(ttl - 1, 1, 255);
7401 InsertQueue(n->UdpSendQueue, block);
7402
7403 SetSockEvent(v->SockEvent);
7404 }
7405 }
7406 }
7407
7408 // Receive an ICMP Echo Request packet
VirtualIcmpEchoRequestReceived(VH * v,UINT src_ip,UINT dst_ip,void * data,UINT size,UCHAR ttl,void * icmp_data,UINT icmp_size,UCHAR * ip_header,UINT ip_header_size,UINT max_l3_size)7409 void VirtualIcmpEchoRequestReceived(VH *v, UINT src_ip, UINT dst_ip, void *data, UINT size, UCHAR ttl, void *icmp_data, UINT icmp_size, UCHAR *ip_header, UINT ip_header_size, UINT max_l3_size)
7410 {
7411 ICMP_ECHO *echo;
7412 UINT data_size;
7413 void *data_buf;
7414 USHORT id, seq_no;
7415 // Validate arguments
7416 if (v == NULL || data == NULL || icmp_data == NULL)
7417 {
7418 return;
7419 }
7420
7421 //Debug("ICMP: %u\n", size);
7422
7423 if (NnIsActive(v))
7424 {
7425 // Process by the Native NAT
7426 NnIcmpEchoRecvForInternet(v, src_ip, dst_ip, data, size, ttl, icmp_data, icmp_size,
7427 ip_header, ip_header_size, max_l3_size);
7428 return;
7429 }
7430
7431 if (v->HubOption != NULL && v->HubOption->DisableUserModeSecureNAT)
7432 {
7433 // User-mode NAT is disabled
7434 return;
7435 }
7436
7437 if (v->IcmpRawSocketOk || v->IcmpApiOk)
7438 {
7439 // Process in the Raw Socket
7440 VirtualIcmpEchoRequestReceivedRaw(v, src_ip, dst_ip, data, size, ttl, icmp_data, icmp_size,
7441 ip_header, ip_header_size);
7442 return;
7443 }
7444
7445 // Returns the fake ICMP forcibly if any of Native NAT or Raw Socket can not be used
7446
7447 echo = (ICMP_ECHO *)data;
7448
7449 // Echo size check
7450 if (size < sizeof(ICMP_ECHO))
7451 {
7452 // Insufficient data
7453 return;
7454 }
7455
7456 id = Endian16(echo->Identifier);
7457 seq_no = Endian16(echo->SeqNo);
7458
7459 // Data size
7460 data_size = size - sizeof(ICMP_ECHO);
7461
7462 // Data body
7463 data_buf = ((UCHAR *)data) + sizeof(ICMP_ECHO);
7464
7465 // Return the ICMP Echo Response
7466 VirtualIcmpEchoSendResponse(v, dst_ip, src_ip, id, seq_no, data_buf, data_size);
7467 }
7468
7469 // An ICMP packet has been received
VirtualIcmpReceived(VH * v,UINT src_ip,UINT dst_ip,void * data,UINT size,UCHAR ttl,UCHAR * ip_header,UINT ip_header_size,UINT max_l3_size)7470 void VirtualIcmpReceived(VH *v, UINT src_ip, UINT dst_ip, void *data, UINT size, UCHAR ttl, UCHAR *ip_header, UINT ip_header_size, UINT max_l3_size)
7471 {
7472 ICMP_HEADER *icmp;
7473 UINT msg_size;
7474 USHORT checksum_calc, checksum_original;
7475 // Validate arguments
7476 if (v == NULL || data == NULL)
7477 {
7478 return;
7479 }
7480
7481 // Size check
7482 if (size < sizeof(ICMP_HEADER))
7483 {
7484 return;
7485 }
7486
7487 // ICMP header
7488 icmp = (ICMP_HEADER *)data;
7489
7490 // Get the ICMP message size
7491 msg_size = size - sizeof(ICMP_HEADER);
7492
7493 // Check the checksum of the ICMP header
7494 checksum_original = icmp->Checksum;
7495 icmp->Checksum = 0;
7496 checksum_calc = IpChecksum(data, size);
7497 icmp->Checksum = checksum_original;
7498
7499 if (checksum_calc != checksum_original)
7500 {
7501 // Checksum is invalid
7502 Debug("ICMP CheckSum Failed.\n");
7503 return;
7504 }
7505
7506 // Identified by the opcode
7507 switch (icmp->Type)
7508 {
7509 case ICMP_TYPE_ECHO_REQUEST: // ICMP Echo request
7510 VirtualIcmpEchoRequestReceived(v, src_ip, dst_ip, ((UCHAR *)data) + sizeof(ICMP_HEADER), msg_size, ttl,
7511 icmp, size, ip_header, ip_header_size, max_l3_size);
7512 break;
7513
7514 case ICMP_TYPE_ECHO_RESPONSE: // ICMP Echo response
7515 // Do Nothing
7516 break;
7517 }
7518 }
7519
7520 // Received an IP packet
IpReceived(VH * v,UINT src_ip,UINT dest_ip,UINT protocol,void * data,UINT size,bool mac_broadcast,UCHAR ttl,UCHAR * ip_header,UINT ip_header_size,bool is_local_mac,UINT max_l3_size)7521 void IpReceived(VH *v, UINT src_ip, UINT dest_ip, UINT protocol, void *data, UINT size, bool mac_broadcast, UCHAR ttl, UCHAR *ip_header, UINT ip_header_size, bool is_local_mac, UINT max_l3_size)
7522 {
7523 // Validate arguments
7524 if (v == NULL || data == NULL)
7525 {
7526 return;
7527 }
7528
7529 // Deliver the data to the supported high-level protocol
7530 switch (protocol)
7531 {
7532 case IP_PROTO_ICMPV4: // ICMPv4
7533 if (mac_broadcast == false)
7534 {
7535 VirtualIcmpReceived(v, src_ip, dest_ip, data, size, ttl, ip_header, ip_header_size, max_l3_size);
7536 }
7537 break;
7538
7539 case IP_PROTO_TCP: // TCP
7540 if (mac_broadcast == false)
7541 {
7542 VirtualTcpReceived(v, src_ip, dest_ip, data, size, max_l3_size);
7543 }
7544 break;
7545
7546 case IP_PROTO_UDP: // UDP
7547 VirtualUdpReceived(v, src_ip, dest_ip, data, size, mac_broadcast, is_local_mac, max_l3_size);
7548 break;
7549 }
7550 }
7551
7552 // Combine the IP packet received to the IP combining object
CombineIp(VH * v,IP_COMBINE * c,UINT offset,void * data,UINT size,bool last_packet,UCHAR * head_ip_header_data,UINT head_ip_header_size)7553 void CombineIp(VH *v, IP_COMBINE *c, UINT offset, void *data, UINT size, bool last_packet, UCHAR *head_ip_header_data, UINT head_ip_header_size)
7554 {
7555 UINT i;
7556 IP_PART *p;
7557 UINT need_size;
7558 UINT data_size_delta;
7559 // Validate arguments
7560 if (c == NULL || data == NULL)
7561 {
7562 return;
7563 }
7564
7565 // Check the size and offset
7566 if ((offset + size) > 65535)
7567 {
7568 // Do not process packet larger than 64Kbytes
7569 return;
7570 }
7571
7572 if (last_packet == false && c->Size != 0)
7573 {
7574 if ((offset + size) > c->Size)
7575 {
7576 // Do not process the packet larger than the packet size
7577 return;
7578 }
7579 }
7580
7581 if (head_ip_header_data != NULL && head_ip_header_size >= sizeof(IPV4_HEADER))
7582 {
7583 if (c->HeadIpHeaderData == NULL)
7584 {
7585 c->HeadIpHeaderData = Clone(head_ip_header_data, head_ip_header_size);
7586 c->HeadIpHeaderDataSize = head_ip_header_size;
7587 }
7588 }
7589
7590 need_size = offset + size;
7591 data_size_delta = c->DataReserved;
7592 // Ensure sufficient if the buffer is insufficient
7593 while (c->DataReserved < need_size)
7594 {
7595 c->DataReserved = c->DataReserved * 4;
7596 c->Data = ReAlloc(c->Data, c->DataReserved);
7597 }
7598 data_size_delta = c->DataReserved - data_size_delta;
7599 v->CurrentIpQuota += data_size_delta;
7600
7601 // Overwrite the data into the buffer
7602 Copy(((UCHAR *)c->Data) + offset, data, size);
7603
7604 if (last_packet)
7605 {
7606 // If No More Fragment packet arrives, the size of this datagram is finalized
7607 c->Size = offset + size;
7608 }
7609
7610 // Check the overlap between the region which is represented by the offset and size of the
7611 // existing received list and the region which is represented by the offset and size
7612 for (i = 0; i < LIST_NUM(c->IpParts); i++)
7613 {
7614 UINT moving_size;
7615 IP_PART *p = LIST_DATA(c->IpParts, i);
7616
7617 // Check the overlapping between the existing area and head area
7618 if ((p->Offset <= offset) && ((p->Offset + p->Size) > offset))
7619 {
7620 // Compress behind the offset of this packet since a duplication is
7621 // found in the first part with the existing packet and this packet
7622
7623 if ((offset + size) <= (p->Offset + p->Size))
7624 {
7625 // This packet is buried in the existing packet
7626 size = 0;
7627 }
7628 else
7629 {
7630 // Retral region is not overlapped
7631 moving_size = p->Offset + p->Size - offset;
7632 offset += moving_size;
7633 size -= moving_size;
7634 }
7635 }
7636 if ((p->Offset < (offset + size)) && ((p->Offset + p->Size) >= (offset + size)))
7637 {
7638 // Compress the size of this packet forward because a duplication is
7639 // found between the posterior portion the existing packet and this packet
7640
7641 moving_size = p->Offset + p->Size - offset - size;
7642 size -= moving_size;
7643 }
7644
7645 if ((p->Offset >= offset) && ((p->Offset + p->Size) <= (offset + size)))
7646 {
7647 // This packet was overwritten to completely cover an existing packet
7648 p->Size = 0;
7649 }
7650 }
7651
7652 if (size != 0)
7653 {
7654 // Register this packet
7655 p = ZeroMalloc(sizeof(IP_PART));
7656
7657 p->Offset = offset;
7658 p->Size = size;
7659
7660 Add(c->IpParts, p);
7661 }
7662
7663 if (c->Size != 0)
7664 {
7665 // Get the total size of the data portion list already received
7666 UINT total_size = 0;
7667 UINT i;
7668
7669 for (i = 0; i < LIST_NUM(c->IpParts); i++)
7670 {
7671 IP_PART *p = LIST_DATA(c->IpParts, i);
7672
7673 total_size += p->Size;
7674 }
7675
7676 if (total_size == c->Size)
7677 {
7678 // Received all of the IP packet
7679 IpReceived(v, c->SrcIP, c->DestIP, c->Protocol, c->Data, c->Size, c->MacBroadcast, c->Ttl,
7680 c->HeadIpHeaderData, c->HeadIpHeaderDataSize, c->SrcIsLocalMacAddr, c->MaxL3Size);
7681
7682 // Release the combining object
7683 FreeIpCombine(v, c);
7684
7685 // Remove from the combining object list
7686 Delete(v->IpCombine, c);
7687 }
7688 }
7689 }
7690
7691 // Release the IP combining object
FreeIpCombine(VH * v,IP_COMBINE * c)7692 void FreeIpCombine(VH *v, IP_COMBINE *c)
7693 {
7694 UINT i;
7695 // Validate arguments
7696 if (c == NULL)
7697 {
7698 return;
7699 }
7700
7701 // Release the data
7702 v->CurrentIpQuota -= c->DataReserved;
7703 Free(c->Data);
7704
7705 // Release the partial list
7706 for (i = 0; i < LIST_NUM(c->IpParts); i++)
7707 {
7708 IP_PART *p = LIST_DATA(c->IpParts, i);
7709
7710 Free(p);
7711 }
7712
7713 Free(c->HeadIpHeaderData);
7714
7715 ReleaseList(c->IpParts);
7716 Free(c);
7717 }
7718
7719 // Search the IP combining list
SearchIpCombine(VH * v,UINT src_ip,UINT dest_ip,USHORT id,UCHAR protocol)7720 IP_COMBINE *SearchIpCombine(VH *v, UINT src_ip, UINT dest_ip, USHORT id, UCHAR protocol)
7721 {
7722 IP_COMBINE *c, t;
7723 // Validate arguments
7724 if (v == NULL)
7725 {
7726 return NULL;
7727 }
7728
7729 t.DestIP = dest_ip;
7730 t.SrcIP = src_ip;
7731 t.Id = id;
7732 t.Protocol = protocol;
7733
7734 c = Search(v->IpCombine, &t);
7735
7736 return c;
7737 }
7738
7739 // Insert by creating a new object to the IP combining list
InsertIpCombine(VH * v,UINT src_ip,UINT dest_ip,USHORT id,UCHAR protocol,bool mac_broadcast,UCHAR ttl,bool src_is_localmac)7740 IP_COMBINE *InsertIpCombine(VH *v, UINT src_ip, UINT dest_ip, USHORT id, UCHAR protocol, bool mac_broadcast, UCHAR ttl, bool src_is_localmac)
7741 {
7742 IP_COMBINE *c;
7743 // Validate arguments
7744 if (v == NULL)
7745 {
7746 return NULL;
7747 }
7748
7749 // Examine the quota
7750 if ((v->CurrentIpQuota + IP_COMBINE_INITIAL_BUF_SIZE) > IP_COMBINE_WAIT_QUEUE_SIZE_QUOTA)
7751 {
7752 // IP packet can not be stored any more
7753 return NULL;
7754 }
7755
7756 c = ZeroMalloc(sizeof(IP_COMBINE));
7757 c->SrcIsLocalMacAddr = src_is_localmac;
7758 c->DestIP = dest_ip;
7759 c->SrcIP = src_ip;
7760 c->Id = id;
7761 c->Expire = v->Now + (UINT64)IP_COMBINE_TIMEOUT;
7762 c->Size = 0;
7763 c->IpParts = NewList(NULL);
7764 c->Protocol = protocol;
7765 c->MacBroadcast = mac_broadcast;
7766 c->Ttl = ttl;
7767
7768 // Secure the memory
7769 c->DataReserved = IP_COMBINE_INITIAL_BUF_SIZE;
7770 c->Data = Malloc(c->DataReserved);
7771 v->CurrentIpQuota += c->DataReserved;
7772
7773 Insert(v->IpCombine, c);
7774
7775 return c;
7776 }
7777
7778 // Initialize the IP combining list
InitIpCombineList(VH * v)7779 void InitIpCombineList(VH *v)
7780 {
7781 // Validate arguments
7782 if (v == NULL)
7783 {
7784 return;
7785 }
7786
7787 v->IpCombine = NewList(CompareIpCombine);
7788 }
7789
7790 // Release the IP combining list
FreeIpCombineList(VH * v)7791 void FreeIpCombineList(VH *v)
7792 {
7793 UINT i;
7794 // Validate arguments
7795 if (v == NULL)
7796 {
7797 return;
7798 }
7799
7800 for (i = 0; i < LIST_NUM(v->IpCombine); i++)
7801 {
7802 IP_COMBINE *c = LIST_DATA(v->IpCombine, i);
7803
7804 FreeIpCombine(v, c);
7805 }
7806
7807 ReleaseList(v->IpCombine);
7808 }
7809
7810 // Comparison of IP combining list entry
CompareIpCombine(void * p1,void * p2)7811 int CompareIpCombine(void *p1, void *p2)
7812 {
7813 IP_COMBINE *c1, *c2;
7814 if (p1 == NULL || p2 == NULL)
7815 {
7816 return 0;
7817 }
7818 c1 = *(IP_COMBINE **)p1;
7819 c2 = *(IP_COMBINE **)p2;
7820 if (c1 == NULL || c2 == NULL)
7821 {
7822 return 0;
7823 }
7824 if (c1->Id > c2->Id)
7825 {
7826 return 1;
7827 }
7828 else if (c1->Id < c2->Id)
7829 {
7830 return -1;
7831 }
7832 else if (c1->DestIP > c2->DestIP)
7833 {
7834 return 1;
7835 }
7836 else if (c1->DestIP < c2->DestIP)
7837 {
7838 return -1;
7839 }
7840 else if (c1->SrcIP > c2->SrcIP)
7841 {
7842 return 1;
7843 }
7844 else if (c1->SrcIP < c2->SrcIP)
7845 {
7846 return -1;
7847 }
7848 else if (c1->Protocol > c2->Protocol)
7849 {
7850 return 1;
7851 }
7852 else if (c1->Protocol < c2->Protocol)
7853 {
7854 return -1;
7855 }
7856 return 0;
7857 }
7858
7859 // Received an IP packet
VirtualIpReceived(VH * v,PKT * packet)7860 void VirtualIpReceived(VH *v, PKT *packet)
7861 {
7862 IPV4_HEADER *ip;
7863 void *data;
7864 UINT data_size_recved;
7865 UINT size;
7866 UINT ipv4_header_size;
7867 bool last_packet;
7868 UCHAR *head_ip_header_data = NULL;
7869 UINT head_ip_header_size = 0;
7870 bool is_local_mac = false;
7871 UINT ip_l3_size;
7872 // Validate arguments
7873 if (v == NULL || packet == NULL)
7874 {
7875 return;
7876 }
7877
7878 ip = packet->L3.IPv4Header;
7879
7880 if (packet->BroadcastPacket)
7881 {
7882 is_local_mac = IsMacAddressLocalFast(packet->MacAddressSrc);
7883 }
7884
7885 // Get the size of the IPv4 header
7886 ipv4_header_size = IPV4_GET_HEADER_LEN(packet->L3.IPv4Header) * 4;
7887 head_ip_header_size = ipv4_header_size;
7888
7889 // Calculate the checksum of the IPv4 header
7890 if (IpCheckChecksum(ip) == false)
7891 {
7892 return;
7893 }
7894
7895 // Get a pointer to the data
7896 data = ((UCHAR *)packet->L3.PointerL3) + ipv4_header_size;
7897
7898 // Register to the ARP table
7899 ArpIpWasKnown(v, packet->L3.IPv4Header->SrcIP, packet->MacAddressSrc);
7900
7901 // Get the data size
7902 size = ip_l3_size = Endian16(ip->TotalLength);
7903 if (size <= ipv4_header_size)
7904 {
7905 // There is no data
7906 return;
7907 }
7908 size -= ipv4_header_size;
7909
7910 // Get the size of data actually received
7911 data_size_recved = packet->PacketSize - (ipv4_header_size + MAC_HEADER_SIZE);
7912 if (data_size_recved < size)
7913 {
7914 // Data insufficient (It may be missing on the way)
7915 return;
7916 }
7917
7918 if (IPV4_GET_OFFSET(ip) == 0 && (IPV4_GET_FLAGS(ip) & 0x01) == 0)
7919 {
7920 // Because this packet has not been fragmented, it can be delivered to the upper layer immediately
7921 head_ip_header_data = (UCHAR *)packet->L3.IPv4Header;
7922 IpReceived(v, ip->SrcIP, ip->DstIP, ip->Protocol, data, size, packet->BroadcastPacket, ip->TimeToLive,
7923 head_ip_header_data, head_ip_header_size, is_local_mac, ip_l3_size);
7924 }
7925 else
7926 {
7927 // This packet is necessary to combine because it is fragmented
7928 UINT offset = IPV4_GET_OFFSET(ip) * 8;
7929 IP_COMBINE *c = SearchIpCombine(v, ip->SrcIP, ip->DstIP, Endian16(ip->Identification), ip->Protocol);
7930
7931 if (offset == 0)
7932 {
7933 head_ip_header_data = (UCHAR *)packet->L3.IPv4Header;
7934 }
7935
7936 last_packet = ((IPV4_GET_FLAGS(ip) & 0x01) == 0 ? true : false);
7937
7938 if (c != NULL)
7939 {
7940 // It is the second or subsequent packet
7941 c->MaxL3Size = MAX(c->MaxL3Size, ip_l3_size);
7942 CombineIp(v, c, offset, data, size, last_packet, head_ip_header_data, head_ip_header_size);
7943 }
7944 else
7945 {
7946 // Create a combining object because it is the first packet
7947 c = InsertIpCombine(
7948 v, ip->SrcIP, ip->DstIP, Endian16(ip->Identification), ip->Protocol, packet->BroadcastPacket,
7949 ip->TimeToLive, is_local_mac);
7950 if (c != NULL)
7951 {
7952 c->MaxL3Size = ip_l3_size;
7953
7954 CombineIp(v, c, offset, data, size, last_packet, head_ip_header_data, head_ip_header_size);
7955 }
7956 }
7957 }
7958 }
7959
7960 // Send the waiting IP packets from the specified IP address
SendWaitingIp(VH * v,UCHAR * mac,UINT dest_ip)7961 void SendWaitingIp(VH *v, UCHAR *mac, UINT dest_ip)
7962 {
7963 UINT i;
7964 LIST *o = NULL;
7965 // Validate arguments
7966 if (v == NULL || mac == NULL)
7967 {
7968 return;
7969 }
7970
7971 // Get a target list
7972 for (i = 0; i < LIST_NUM(v->IpWaitTable); i++)
7973 {
7974 IP_WAIT *w = LIST_DATA(v->IpWaitTable, i);
7975
7976 if (w->DestIP == dest_ip)
7977 {
7978 if (o == NULL)
7979 {
7980 o = NewListFast(NULL);
7981 }
7982 Add(o, w);
7983 }
7984 }
7985
7986 // Send the target packets at once
7987 if (o != NULL)
7988 {
7989 for (i = 0; i < LIST_NUM(o); i++)
7990 {
7991 IP_WAIT *w = LIST_DATA(o, i);
7992
7993 // Transmission processing
7994 VirtualIpSend(v, mac, w->Data, w->Size);
7995
7996 // Remove from the list
7997 Delete(v->IpWaitTable, w);
7998
7999 // Release the memory
8000 Free(w->Data);
8001 Free(w);
8002 }
8003
8004 ReleaseList(o);
8005 }
8006 }
8007
8008 // Remove the old IP waiting table entries
DeleteOldIpWaitTable(VH * v)8009 void DeleteOldIpWaitTable(VH *v)
8010 {
8011 UINT i;
8012 LIST *o = NULL;
8013 // Validate arguments
8014 if (v == NULL)
8015 {
8016 return;
8017 }
8018
8019 // Get the deleting list
8020 for (i = 0; i < LIST_NUM(v->IpWaitTable); i++)
8021 {
8022 IP_WAIT *w = LIST_DATA(v->IpWaitTable, i);
8023
8024 if (w->Expire < v->Now)
8025 {
8026 if (o == NULL)
8027 {
8028 o = NewListFast(NULL);
8029 }
8030 Add(o, w);
8031 }
8032 }
8033
8034 // Delete all at once
8035 if (o != NULL)
8036 {
8037 for (i = 0; i < LIST_NUM(o); i++)
8038 {
8039 IP_WAIT *w = LIST_DATA(o, i);
8040
8041 // Remove from the list
8042 Delete(v->IpWaitTable, w);
8043
8044 // Release the memory
8045 Free(w->Data);
8046 Free(w);
8047 }
8048 ReleaseList(o);
8049 }
8050 }
8051
8052 // Poll the IP waiting table
PollingIpWaitTable(VH * v)8053 void PollingIpWaitTable(VH *v)
8054 {
8055 // Delete the old table entries
8056 DeleteOldIpWaitTable(v);
8057 }
8058
8059 // Insert the IP packet to the IP waiting table
InsertIpWaitTable(VH * v,UINT dest_ip,UINT src_ip,void * data,UINT size)8060 void InsertIpWaitTable(VH *v, UINT dest_ip, UINT src_ip, void *data, UINT size)
8061 {
8062 IP_WAIT *w;
8063 // Validate arguments
8064 if (v == NULL || data == NULL || size == 0)
8065 {
8066 return;
8067 }
8068
8069 w = ZeroMalloc(sizeof(IP_WAIT));
8070 w->Data = data;
8071 w->Size = size;
8072 w->SrcIP = src_ip;
8073 w->DestIP = dest_ip;
8074 w->Expire = v->Now + (UINT64)IP_WAIT_FOR_ARP_TIMEOUT;
8075
8076 Add(v->IpWaitTable, w);
8077 }
8078
8079 // Initialize the IP waiting table
InitIpWaitTable(VH * v)8080 void InitIpWaitTable(VH *v)
8081 {
8082 // Validate arguments
8083 if (v == NULL)
8084 {
8085 return;
8086 }
8087
8088 v->IpWaitTable = NewList(NULL);
8089 }
8090
8091 // Release the IP waiting table
FreeIpWaitTable(VH * v)8092 void FreeIpWaitTable(VH *v)
8093 {
8094 UINT i;
8095 // Validate arguments
8096 if (v == NULL)
8097 {
8098 return;
8099 }
8100
8101 for (i = 0; i < LIST_NUM(v->IpWaitTable); i++)
8102 {
8103 IP_WAIT *w = LIST_DATA(v->IpWaitTable, i);
8104
8105 Free(w->Data);
8106 Free(w);
8107 }
8108
8109 ReleaseList(v->IpWaitTable);
8110 }
8111
8112 // MAC address for the IP address is found because something such as an ARP Response arrives
ArpIpWasKnown(VH * v,UINT ip,UCHAR * mac)8113 void ArpIpWasKnown(VH *v, UINT ip, UCHAR *mac)
8114 {
8115 // Validate arguments
8116 if (v == NULL || mac == NULL)
8117 {
8118 return;
8119 }
8120
8121 // If there is a query for this IP address in the ARP queue, delete it
8122 DeleteArpWaitTable(v, ip);
8123
8124 // Update or register in the ARP table
8125 InsertArpTable(v, mac, ip);
8126
8127 // Send the IP packets waiting in the IP waiting list
8128 SendWaitingIp(v, mac, ip);
8129 }
8130
8131 // Re-issue ARPs by checking the ARP waiting list
PollingArpWaitTable(VH * v)8132 void PollingArpWaitTable(VH *v)
8133 {
8134 UINT i;
8135 LIST *o;
8136 // Validate arguments
8137 if (v == NULL)
8138 {
8139 return;
8140 }
8141
8142 // Initialize the deletion list
8143 o = NULL;
8144
8145 // Scan whole ARP waiting list
8146 for (i = 0; i < LIST_NUM(v->ArpWaitTable); i++)
8147 {
8148 ARP_WAIT *w = LIST_DATA(v->ArpWaitTable, i);
8149
8150 if (w->GiveupTime < v->Now || (w->GiveupTime - 100 * 1000) > v->Now)
8151 {
8152 // Give up the sending of ARP
8153 if (o == NULL)
8154 {
8155 o = NewListFast(NULL);
8156 }
8157 Add(o, w);
8158 }
8159 else
8160 {
8161 if (w->TimeoutTime < v->Now)
8162 {
8163 // Send an ARP again
8164 VirtualArpSendRequest(v, w->IpAddress);
8165
8166 // Set the next timeout time
8167 w->TimeoutTime = v->Now + (UINT64)w->NextTimeoutTimeValue;
8168 // Increase the ARP transmission interval of the second and subsequent
8169 w->NextTimeoutTimeValue = w->NextTimeoutTimeValue + ARP_REQUEST_TIMEOUT;
8170 }
8171 }
8172 }
8173
8174 // Remove if there is a ARP waiting record to be deleted
8175 if (o != NULL)
8176 {
8177 for (i = 0; i < LIST_NUM(o); i++)
8178 {
8179 ARP_WAIT *w = LIST_DATA(o, i);
8180
8181 DeleteArpWaitTable(v, w->IpAddress);
8182 }
8183 ReleaseList(o);
8184 }
8185 }
8186
8187 // Issue an ARP
SendArp(VH * v,UINT ip)8188 void SendArp(VH *v, UINT ip)
8189 {
8190 ARP_WAIT *w;
8191 // Validate arguments
8192 if (v == NULL)
8193 {
8194 return;
8195 }
8196
8197 // Examine whether the destination IP address has been registered in the ARP waiting list first
8198 w = SearchArpWaitTable(v, ip);
8199 if (w != NULL)
8200 {
8201 // Do not do anything because it is already registered
8202 return;
8203 }
8204
8205 // Send an ARP packet first
8206 VirtualArpSendRequest(v, ip);
8207
8208 // Register in the ARP waiting list
8209 w = ZeroMalloc(sizeof(ARP_WAIT));
8210 w->GiveupTime = v->Now + (UINT64)ARP_REQUEST_GIVEUP;
8211 w->TimeoutTime = v->Now + (UINT64)ARP_REQUEST_TIMEOUT;
8212 w->NextTimeoutTimeValue = ARP_REQUEST_TIMEOUT;
8213 w->IpAddress = ip;
8214
8215 InsertArpWaitTable(v, w);
8216 }
8217
8218 // Delete the ARP waiting table
DeleteArpWaitTable(VH * v,UINT ip)8219 void DeleteArpWaitTable(VH *v, UINT ip)
8220 {
8221 ARP_WAIT *w;
8222 // Validate arguments
8223 if (v == NULL)
8224 {
8225 return;
8226 }
8227
8228 w = SearchArpWaitTable(v, ip);
8229 if (w == NULL)
8230 {
8231 return;
8232 }
8233 Delete(v->ArpWaitTable, w);
8234
8235 Free(w);
8236 }
8237
8238 // Search the ARP waiting table
SearchArpWaitTable(VH * v,UINT ip)8239 ARP_WAIT *SearchArpWaitTable(VH *v, UINT ip)
8240 {
8241 ARP_WAIT *w, t;
8242 // Validate arguments
8243 if (v == NULL)
8244 {
8245 return NULL;
8246 }
8247
8248 t.IpAddress = ip;
8249 w = Search(v->ArpWaitTable, &t);
8250
8251 return w;
8252 }
8253
8254 // Register in the ARP waiting table
InsertArpWaitTable(VH * v,ARP_WAIT * w)8255 void InsertArpWaitTable(VH *v, ARP_WAIT *w)
8256 {
8257 // Validate arguments
8258 if (v == NULL || w == NULL)
8259 {
8260 return;
8261 }
8262
8263 Add(v->ArpWaitTable, w);
8264 }
8265
8266 // Initialize the ARP waiting table
InitArpWaitTable(VH * v)8267 void InitArpWaitTable(VH *v)
8268 {
8269 // Validate arguments
8270 if (v == NULL)
8271 {
8272 return;
8273 }
8274
8275 v->ArpWaitTable = NewList(CompareArpWaitTable);
8276 }
8277
8278 // Release the ARP waiting table
FreeArpWaitTable(VH * v)8279 void FreeArpWaitTable(VH *v)
8280 {
8281 UINT i;
8282 // Validate arguments
8283 if (v == NULL)
8284 {
8285 return;
8286 }
8287
8288 for (i = 0; i < LIST_NUM(v->ArpWaitTable); i++)
8289 {
8290 ARP_WAIT *w = LIST_DATA(v->ArpWaitTable, i);
8291
8292 Free(w);
8293 }
8294
8295 ReleaseList(v->ArpWaitTable);
8296 }
8297
8298 // Insert an entry in the ARP table
InsertArpTable(VH * v,UCHAR * mac,UINT ip)8299 void InsertArpTable(VH *v, UCHAR *mac, UINT ip)
8300 {
8301 ARP_ENTRY *e, t;
8302 // Validate arguments
8303 if (v == NULL || mac == NULL || ip == 0 || ip == 0xffffffff || IsMacBroadcast(mac) || IsMacInvalid(mac))
8304 {
8305 return;
8306 }
8307
8308 // Check whether the same IP address is not already registered
8309 t.IpAddress = ip;
8310 e = Search(v->ArpTable, &t);
8311 if (e != NULL)
8312 {
8313 // Override this simply because it was registered
8314 if (Cmp(e->MacAddress, mac, 6) != 0)
8315 {
8316 e->Created = v->Now;
8317 Copy(e->MacAddress, mac, 6);
8318 }
8319 e->Expire = v->Now + (UINT64)ARP_ENTRY_EXPIRES;
8320 }
8321 else
8322 {
8323 // Create a new entry
8324 e = ZeroMalloc(sizeof(ARP_ENTRY));
8325
8326 e->Created = v->Now;
8327 e->Expire = v->Now + (UINT64)ARP_ENTRY_EXPIRES;
8328 Copy(e->MacAddress, mac, 6);
8329 e->IpAddress = ip;
8330
8331 Add(v->ArpTable, e);
8332 }
8333 }
8334
8335 // Poll the ARP table
PollingArpTable(VH * v)8336 void PollingArpTable(VH *v)
8337 {
8338 // Validate arguments
8339 if (v == NULL)
8340 {
8341 return;
8342 }
8343
8344 if (v->Now > v->NextArpTablePolling)
8345 {
8346 v->NextArpTablePolling = v->Now + (UINT64)ARP_ENTRY_POLLING_TIME;
8347 RefreshArpTable(v);
8348 }
8349 }
8350
8351 // Remove the old ARP entries
RefreshArpTable(VH * v)8352 void RefreshArpTable(VH *v)
8353 {
8354 UINT i;
8355 LIST *o;
8356 // Validate arguments
8357 if (v == NULL)
8358 {
8359 return;
8360 }
8361
8362 o = NewListFast(NULL);
8363 for (i = 0; i < LIST_NUM(v->ArpTable); i++)
8364 {
8365 ARP_ENTRY *e = LIST_DATA(v->ArpTable, i);
8366
8367 // Check for expired
8368 if (e->Expire < v->Now)
8369 {
8370 // Expired
8371 Add(o, e);
8372 }
8373 }
8374
8375 // Remove expired entries at once
8376 for (i = 0; i < LIST_NUM(o); i++)
8377 {
8378 ARP_ENTRY *e = LIST_DATA(o, i);
8379
8380 Delete(v->ArpTable, e);
8381 Free(e);
8382 }
8383
8384 ReleaseList(o);
8385 }
8386
8387 // Search the ARP table
SearchArpTable(VH * v,UINT ip)8388 ARP_ENTRY *SearchArpTable(VH *v, UINT ip)
8389 {
8390 ARP_ENTRY *e, t;
8391 // Validate arguments
8392 if (v == NULL)
8393 {
8394 return NULL;
8395 }
8396
8397 t.IpAddress = ip;
8398 e = Search(v->ArpTable, &t);
8399
8400 return e;
8401 }
8402
8403 // Initialize the ARP table
InitArpTable(VH * v)8404 void InitArpTable(VH *v)
8405 {
8406 // Validate arguments
8407 if (v == NULL)
8408 {
8409 return;
8410 }
8411
8412 v->ArpTable = NewList(CompareArpTable);
8413 }
8414
8415 // Release the ARP table
FreeArpTable(VH * v)8416 void FreeArpTable(VH *v)
8417 {
8418 UINT i;
8419 // Validate arguments
8420 if (v == NULL)
8421 {
8422 return;
8423 }
8424
8425 // Delete all entries
8426 for (i = 0; i < LIST_NUM(v->ArpTable); i++)
8427 {
8428 ARP_ENTRY *e = LIST_DATA(v->ArpTable, i);
8429 Free(e);
8430 }
8431 ReleaseList(v->ArpTable);
8432 }
8433
8434 // Comparison of the ARP waiting table entry
CompareArpWaitTable(void * p1,void * p2)8435 int CompareArpWaitTable(void *p1, void *p2)
8436 {
8437 ARP_WAIT *e1, *e2;
8438 if (p1 == NULL || p2 == NULL)
8439 {
8440 return 0;
8441 }
8442 e1 = *(ARP_WAIT **)p1;
8443 e2 = *(ARP_WAIT **)p2;
8444 if (e1 == NULL || e2 == NULL)
8445 {
8446 return 0;
8447 }
8448
8449 if (e1->IpAddress > e2->IpAddress)
8450 {
8451 return 1;
8452 }
8453 else if (e1->IpAddress < e2->IpAddress)
8454 {
8455 return -1;
8456 }
8457 return 0;
8458 }
8459
8460 // Comparison of the ARP table entry
CompareArpTable(void * p1,void * p2)8461 int CompareArpTable(void *p1, void *p2)
8462 {
8463 ARP_ENTRY *e1, *e2;
8464 if (p1 == NULL || p2 == NULL)
8465 {
8466 return 0;
8467 }
8468 e1 = *(ARP_ENTRY **)p1;
8469 e2 = *(ARP_ENTRY **)p2;
8470 if (e1 == NULL || e2 == NULL)
8471 {
8472 return 0;
8473 }
8474
8475 if (e1->IpAddress > e2->IpAddress)
8476 {
8477 return 1;
8478 }
8479 else if (e1->IpAddress < e2->IpAddress)
8480 {
8481 return -1;
8482 }
8483 return 0;
8484 }
8485
8486 // Initialize the virtual host
VirtualInit(VH * v)8487 bool VirtualInit(VH *v)
8488 {
8489 // Initialize the log
8490 v->Logger = NULL;
8491
8492 LockVirtual(v);
8493 {
8494 // Initialize
8495 v->Cancel = NewCancel();
8496 v->SendQueue = NewQueue();
8497 }
8498 UnlockVirtual(v);
8499
8500 // Counter reset
8501 v->Counter->c = 0;
8502 v->DhcpId = 0;
8503
8504 // Initialize the ARP table
8505 InitArpTable(v);
8506
8507 // Initialize the ARP waiting table
8508 InitArpWaitTable(v);
8509
8510 // Initialize the IP waiting table
8511 InitIpWaitTable(v);
8512
8513 // Initialize the IP combining list
8514 InitIpCombineList(v);
8515
8516 // Initialize the NAT
8517 InitNat(v);
8518
8519 // Initialize the DHCP server
8520 InitDhcpServer(v);
8521
8522 // Other initialization
8523 v->flag1 = false;
8524 v->NextArpTablePolling = Tick64() + (UINT64)ARP_ENTRY_POLLING_TIME;
8525 v->CurrentIpQuota = 0;
8526 v->Active = true;
8527
8528 return true;
8529 }
VirtualPaInit(SESSION * s)8530 bool VirtualPaInit(SESSION *s)
8531 {
8532 VH *v;
8533 // Validate arguments
8534 if (s == NULL || (v = (VH *)s->PacketAdapter->Param) == NULL)
8535 {
8536 return false;
8537 }
8538
8539 return VirtualInit(v);
8540 }
8541
8542 // Get the cancel object of the virtual host
VirtualPaGetCancel(SESSION * s)8543 CANCEL *VirtualPaGetCancel(SESSION *s)
8544 {
8545 VH *v;
8546 // Validate arguments
8547 if (s == NULL || (v = (VH *)s->PacketAdapter->Param) == NULL)
8548 {
8549 return NULL;
8550 }
8551
8552 AddRef(v->Cancel->ref);
8553 return v->Cancel;
8554 }
8555
8556 // Get the next packet from the virtual host
VirtualGetNextPacket(VH * v,void ** data)8557 UINT VirtualGetNextPacket(VH *v, void **data)
8558 {
8559 UINT ret = 0;
8560
8561 START:
8562 // Examine the transmission queue
8563 LockQueue(v->SendQueue);
8564 {
8565 BLOCK *block = GetNext(v->SendQueue);
8566
8567 if (block != NULL)
8568 {
8569 // There is a packet
8570 ret = block->Size;
8571 *data = block->Buf;
8572 // Discard the structure
8573 Free(block);
8574 }
8575 }
8576 UnlockQueue(v->SendQueue);
8577
8578 if (ret == 0)
8579 {
8580 LockVirtual(v);
8581 {
8582 v->Now = Tick64();
8583 // Polling process
8584 VirtualPolling(v);
8585 }
8586 UnlockVirtual(v);
8587 if (v->SendQueue->num_item != 0)
8588 {
8589 goto START;
8590 }
8591 }
8592
8593 return ret;
8594 }
VirtualPaGetNextPacket(SESSION * s,void ** data)8595 UINT VirtualPaGetNextPacket(SESSION *s, void **data)
8596 {
8597 VH *v;
8598 // Validate arguments
8599 if (s == NULL || (v = (VH *)s->PacketAdapter->Param) == NULL)
8600 {
8601 return INFINITE;
8602 }
8603
8604 return VirtualGetNextPacket(v, data);
8605 }
8606
8607 // Polling process (Always called once in a SessionMain loop)
VirtualPolling(VH * v)8608 void VirtualPolling(VH *v)
8609 {
8610 // Validate arguments
8611 if (v == NULL)
8612 {
8613 return;
8614 }
8615
8616 // DHCP polling
8617 PollingDhcpServer(v);
8618
8619 // NAT polling
8620 PoolingNat(v);
8621
8622 // Clear the old ARP table entries
8623 PollingArpTable(v);
8624
8625 // Poll the ARP waiting list
8626 PollingArpWaitTable(v);
8627
8628 // Poll the IP waiting list
8629 PollingIpWaitTable(v);
8630
8631 // Poll the IP combining list
8632 PollingIpCombine(v);
8633
8634 // Beacon transmission procedure
8635 PollingBeacon(v);
8636 }
8637
8638 // Beacon transmission procedure
PollingBeacon(VH * v)8639 void PollingBeacon(VH *v)
8640 {
8641 // Validate arguments
8642 if (v == NULL)
8643 {
8644 return;
8645 }
8646
8647 if (v->LastSendBeacon == 0 ||
8648 ((v->LastSendBeacon + BEACON_SEND_INTERVAL) <= Tick64()))
8649 {
8650 v->LastSendBeacon = Tick64();
8651
8652 SendBeacon(v);
8653 }
8654 }
8655
8656 // Send a Layer-2 packet
VirtualLayer2Send(VH * v,UCHAR * dest_mac,UCHAR * src_mac,USHORT protocol,void * data,UINT size)8657 void VirtualLayer2Send(VH *v, UCHAR *dest_mac, UCHAR *src_mac, USHORT protocol, void *data, UINT size)
8658 {
8659 MAC_HEADER *mac_header;
8660 UCHAR *buf;
8661 BLOCK *block;
8662 // Validate arguments
8663 if (v == NULL || dest_mac == NULL || src_mac == NULL || data == NULL || size > (MAX_PACKET_SIZE - sizeof(MAC_HEADER)))
8664 {
8665 return;
8666 }
8667
8668 // Create buffer
8669 buf = Malloc(MAC_HEADER_SIZE + size);
8670
8671 // MAC header
8672 mac_header = (MAC_HEADER *)&buf[0];
8673 Copy(mac_header->DestAddress, dest_mac, 6);
8674 Copy(mac_header->SrcAddress, src_mac, 6);
8675 mac_header->Protocol = Endian16(protocol);
8676
8677 // Copy data
8678 Copy(&buf[sizeof(MAC_HEADER)], data, size);
8679
8680 // Size
8681 size += sizeof(MAC_HEADER);
8682
8683 // Generate the packet
8684 block = NewBlock(buf, size, 0);
8685
8686 // Insert into the queue
8687 LockQueue(v->SendQueue);
8688 {
8689 InsertQueue(v->SendQueue, block);
8690 }
8691 UnlockQueue(v->SendQueue);
8692
8693 // Cancel
8694 Cancel(v->Cancel);
8695 }
8696
8697 // Send an IP packet (with automatic fragmentation)
SendIp(VH * v,UINT dest_ip,UINT src_ip,UCHAR protocol,void * data,UINT size)8698 void SendIp(VH *v, UINT dest_ip, UINT src_ip, UCHAR protocol, void *data, UINT size)
8699 {
8700 SendIpEx(v, dest_ip, src_ip, protocol, data, size, 0);
8701 }
SendIpEx(VH * v,UINT dest_ip,UINT src_ip,UCHAR protocol,void * data,UINT size,UCHAR ttl)8702 void SendIpEx(VH *v, UINT dest_ip, UINT src_ip, UCHAR protocol, void *data, UINT size, UCHAR ttl)
8703 {
8704 UINT mss;
8705 UCHAR *buf;
8706 USHORT offset;
8707 USHORT id;
8708 USHORT total_size;
8709 UINT size_of_this_packet;
8710 // Validate arguments
8711 if (v == NULL || data == NULL || size == 0 || size > MAX_IP_DATA_SIZE_TOTAL)
8712 {
8713 return;
8714 }
8715
8716 // Maximum segment size
8717 mss = v->IpMss;
8718
8719 // Buffer
8720 buf = (UCHAR *)data;
8721
8722 // ID
8723 id = (v->NextId++);
8724
8725 // Total size
8726 total_size = (USHORT)size;
8727
8728 // Start to split
8729 offset = 0;
8730
8731 while (true)
8732 {
8733 bool last_packet = false;
8734 // Gets the size of this packet
8735 size_of_this_packet = MIN((USHORT)mss, (total_size - offset));
8736 if ((offset + (USHORT)size_of_this_packet) == total_size)
8737 {
8738 last_packet = true;
8739 }
8740
8741 // Transmit the fragmented packet
8742 SendFragmentedIp(v, dest_ip, src_ip, id,
8743 total_size, offset, protocol, buf + offset, size_of_this_packet, NULL, ttl);
8744 if (last_packet)
8745 {
8746 break;
8747 }
8748
8749 offset += (USHORT)size_of_this_packet;
8750 }
8751 }
8752
8753 // Reserve to send the fragmented IP packet
SendFragmentedIp(VH * v,UINT dest_ip,UINT src_ip,USHORT id,USHORT total_size,USHORT offset,UCHAR protocol,void * data,UINT size,UCHAR * dest_mac,UCHAR ttl)8754 void SendFragmentedIp(VH *v, UINT dest_ip, UINT src_ip, USHORT id, USHORT total_size, USHORT offset, UCHAR protocol, void *data, UINT size, UCHAR *dest_mac, UCHAR ttl)
8755 {
8756 UCHAR *buf;
8757 IPV4_HEADER *ip;
8758 ARP_ENTRY *arp;
8759 // Validate arguments
8760 if (v == NULL || data == NULL || size == 0)
8761 {
8762 return;
8763 }
8764
8765 // Memory allocation
8766 buf = Malloc(size + IP_HEADER_SIZE);
8767 ip = (IPV4_HEADER *)&buf[0];
8768
8769 // IP header construction
8770 ip->VersionAndHeaderLength = 0;
8771 IPV4_SET_VERSION(ip, 4);
8772 IPV4_SET_HEADER_LEN(ip, (IP_HEADER_SIZE / 4));
8773 ip->TypeOfService = DEFAULT_IP_TOS;
8774 ip->TotalLength = Endian16((USHORT)(size + IP_HEADER_SIZE));
8775 ip->Identification = Endian16(id);
8776 ip->FlagsAndFragmentOffset[0] = ip->FlagsAndFragmentOffset[1] = 0;
8777 IPV4_SET_OFFSET(ip, (offset / 8));
8778 if ((offset + size) >= total_size)
8779 {
8780 IPV4_SET_FLAGS(ip, 0x00);
8781 }
8782 else
8783 {
8784 IPV4_SET_FLAGS(ip, 0x01);
8785 }
8786 ip->TimeToLive = (ttl == 0 ? DEFAULT_IP_TTL : ttl);
8787 ip->Protocol = protocol;
8788 ip->Checksum = 0;
8789 ip->SrcIP = src_ip;
8790 ip->DstIP = dest_ip;
8791
8792 // Checksum calculation
8793 ip->Checksum = IpChecksum(ip, IP_HEADER_SIZE);
8794
8795 // Data copy
8796 Copy(buf + IP_HEADER_SIZE, data, size);
8797
8798 if (dest_mac == NULL)
8799 {
8800 if (ip->DstIP == 0xffffffff ||
8801 (IsInNetwork(ip->DstIP, v->HostIP, v->HostMask) && (ip->DstIP & (~v->HostMask)) == (~v->HostMask)))
8802 {
8803 // Broadcast address
8804 dest_mac = broadcast;
8805 }
8806 else
8807 {
8808 // Send an ARP query if the destination MAC address is unknown
8809 arp = SearchArpTable(v, dest_ip);
8810 if (arp != NULL)
8811 {
8812 dest_mac = arp->MacAddress;
8813 }
8814 }
8815 }
8816 if (dest_mac != NULL)
8817 {
8818 // Send the packet immediately
8819 VirtualIpSend(v, dest_mac, buf, size + IP_HEADER_SIZE);
8820
8821 // Packet data may be released
8822 Free(buf);
8823 }
8824 else
8825 {
8826 // Because this packet still can not be transferred, add it to the IP waiting table
8827 InsertIpWaitTable(v, dest_ip, src_ip, buf, size + IP_HEADER_SIZE);
8828
8829 // Issue an ARP
8830 SendArp(v, dest_ip);
8831 }
8832 }
8833
8834 // Send an IP packet (fragmented)
VirtualIpSend(VH * v,UCHAR * dest_mac,void * data,UINT size)8835 void VirtualIpSend(VH *v, UCHAR *dest_mac, void *data, UINT size)
8836 {
8837 // Validate arguments
8838 if (v == NULL || dest_mac == NULL || data == NULL || size == 0)
8839 {
8840 return;
8841 }
8842
8843 // Transmission
8844 VirtualLayer2Send(v, dest_mac, v->MacAddress, MAC_PROTO_IPV4, data, size);
8845 }
8846
8847 // Send an ARP request packet
VirtualArpSendRequest(VH * v,UINT dest_ip)8848 void VirtualArpSendRequest(VH *v, UINT dest_ip)
8849 {
8850 ARPV4_HEADER arp;
8851 // Validate arguments
8852 if (v == NULL)
8853 {
8854 return;
8855 }
8856
8857 // Build the ARP header
8858 arp.HardwareType = Endian16(ARP_HARDWARE_TYPE_ETHERNET);
8859 arp.ProtocolType = Endian16(MAC_PROTO_IPV4);
8860 arp.HardwareSize = 6;
8861 arp.ProtocolSize = 4;
8862 arp.Operation = Endian16(ARP_OPERATION_REQUEST);
8863 Copy(arp.SrcAddress, v->MacAddress, 6);
8864 arp.SrcIP = v->HostIP;
8865 Zero(&arp.TargetAddress, 6);
8866 arp.TargetIP = dest_ip;
8867
8868 // Transmission
8869 VirtualLayer2Send(v, broadcast, v->MacAddress, MAC_PROTO_ARPV4, &arp, sizeof(arp));
8870 }
8871
8872 // Send an ARP response packet
VirtualArpSendResponse(VH * v,UCHAR * dest_mac,UINT dest_ip,UINT src_ip)8873 void VirtualArpSendResponse(VH *v, UCHAR *dest_mac, UINT dest_ip, UINT src_ip)
8874 {
8875 ARPV4_HEADER arp;
8876 // Validate arguments
8877 if (v == NULL || dest_mac == NULL)
8878 {
8879 return;
8880 }
8881
8882 // Build the ARP header
8883 arp.HardwareType = Endian16(ARP_HARDWARE_TYPE_ETHERNET);
8884 arp.ProtocolType = Endian16(MAC_PROTO_IPV4);
8885 arp.HardwareSize = 6;
8886 arp.ProtocolSize = 4;
8887 arp.Operation = Endian16(ARP_OPERATION_RESPONSE);
8888 Copy(arp.SrcAddress, v->MacAddress, 6);
8889 Copy(arp.TargetAddress, dest_mac, 6);
8890 arp.SrcIP = src_ip;
8891 arp.TargetIP = dest_ip;
8892
8893 // Transmission
8894 VirtualLayer2Send(v, dest_mac, v->MacAddress, MAC_PROTO_ARPV4, &arp, sizeof(ARPV4_HEADER));
8895 }
8896
8897 // An ARP request packet was received
VirtualArpResponseRequest(VH * v,PKT * packet)8898 void VirtualArpResponseRequest(VH *v, PKT *packet)
8899 {
8900 ARPV4_HEADER *arp;
8901 // Validate arguments
8902 if (v == NULL || packet == NULL)
8903 {
8904 return;
8905 }
8906
8907 arp = packet->L3.ARPv4Header;
8908
8909 // Memory the information of the host IP address and the MAC address of the other party
8910 ArpIpWasKnown(v, arp->SrcIP, arp->SrcAddress);
8911
8912 // Search whether it matches with the IP address of this host
8913 if (v->HostIP == arp->TargetIP)
8914 {
8915 // Respond since the match
8916 VirtualArpSendResponse(v, arp->SrcAddress, arp->SrcIP, v->HostIP);
8917 return;
8918 }
8919 // Do nothing if it doesn't match
8920 }
8921
8922 // An ARP response packet is received
VirtualArpResponseReceived(VH * v,PKT * packet)8923 void VirtualArpResponseReceived(VH *v, PKT *packet)
8924 {
8925 ARPV4_HEADER *arp;
8926 // Validate arguments
8927 if (v == NULL || packet == NULL)
8928 {
8929 return;
8930 }
8931
8932 arp = packet->L3.ARPv4Header;
8933
8934 // Regard this information as known information
8935 ArpIpWasKnown(v, arp->SrcIP, arp->SrcAddress);
8936 }
8937
8938 // Received an ARP packet
VirtualArpReceived(VH * v,PKT * packet)8939 void VirtualArpReceived(VH *v, PKT *packet)
8940 {
8941 ARPV4_HEADER *arp;
8942 // Validate arguments
8943 if (v == NULL || packet == NULL)
8944 {
8945 return;
8946 }
8947
8948 arp = packet->L3.ARPv4Header;
8949
8950 if (Endian16(arp->HardwareType) != ARP_HARDWARE_TYPE_ETHERNET)
8951 {
8952 // Ignore if hardware type is other than Ethernet
8953 return;
8954 }
8955 if (Endian16(arp->ProtocolType) != MAC_PROTO_IPV4)
8956 {
8957 // Ignore if the protocol type is a non-IPv4
8958 return;
8959 }
8960 if (arp->HardwareSize != 6 || arp->ProtocolSize != 4)
8961 {
8962 // Ignore because the size of protocol address or hardware address is invalid
8963 return;
8964 }
8965 // Check the source MAC address
8966 if (Cmp(arp->SrcAddress, packet->MacAddressSrc, 6) != 0)
8967 {
8968 // MAC address in the MAC header and the MAC address of the ARP packet are different
8969 return;
8970 }
8971
8972 switch (Endian16(arp->Operation))
8973 {
8974 case ARP_OPERATION_REQUEST: // ARP request
8975 VirtualArpResponseRequest(v, packet);
8976 break;
8977
8978 case ARP_OPERATION_RESPONSE: // ARP response
8979 VirtualArpResponseReceived(v, packet);
8980 break;
8981 }
8982 }
8983
8984 // Release the DHCP server
FreeDhcpServer(VH * v)8985 void FreeDhcpServer(VH *v)
8986 {
8987 UINT i;
8988 // Validate arguments
8989 if (v == NULL)
8990 {
8991 return;
8992 }
8993
8994 // Empty the leases lists
8995 for (i = 0; i < LIST_NUM(v->DhcpLeaseList); ++i)
8996 {
8997 DHCP_LEASE *d = LIST_DATA(v->DhcpLeaseList, i);
8998 FreeDhcpLease(d);
8999 }
9000
9001 ReleaseList(v->DhcpLeaseList);
9002 v->DhcpLeaseList = NULL;
9003
9004 for (i = 0; i < LIST_NUM(v->DhcpPendingLeaseList); ++i)
9005 {
9006 DHCP_LEASE *d = LIST_DATA(v->DhcpPendingLeaseList, i);
9007 FreeDhcpLease(d);
9008 }
9009
9010 ReleaseList(v->DhcpPendingLeaseList);
9011 v->DhcpPendingLeaseList = NULL;
9012 }
9013
9014 // Initialize the DHCP server
InitDhcpServer(VH * v)9015 void InitDhcpServer(VH *v)
9016 {
9017 // Validate arguments
9018 if (v == NULL)
9019 {
9020 return;
9021 }
9022
9023 // Create a list
9024 v->DhcpLeaseList = NewList(CompareDhcpLeaseList);
9025 v->DhcpPendingLeaseList = NewList(CompareDhcpLeaseList);
9026 }
9027
9028 // Search for a pending DHCP lease item by the IP address
SearchDhcpPendingLeaseByIp(VH * v,UINT ip)9029 DHCP_LEASE *SearchDhcpPendingLeaseByIp(VH *v, UINT ip)
9030 {
9031 UINT i;
9032 // Validate arguments
9033 if (v == NULL)
9034 {
9035 return NULL;
9036 }
9037
9038 for (i = 0; i < LIST_NUM(v->DhcpPendingLeaseList); ++i)
9039 {
9040 DHCP_LEASE *d = LIST_DATA(v->DhcpPendingLeaseList, i);
9041 if (d->IpAddress == ip)
9042 {
9043 return d;
9044 }
9045 }
9046
9047 return NULL;
9048 }
9049
9050 // Search for a DHCP lease item by the IP address
SearchDhcpLeaseByIp(VH * v,UINT ip)9051 DHCP_LEASE *SearchDhcpLeaseByIp(VH *v, UINT ip)
9052 {
9053 UINT i;
9054 // Validate arguments
9055 if (v == NULL)
9056 {
9057 return NULL;
9058 }
9059
9060 for (i = 0; i < LIST_NUM(v->DhcpLeaseList); ++i)
9061 {
9062 DHCP_LEASE *d = LIST_DATA(v->DhcpLeaseList, i);
9063 if (d->IpAddress == ip)
9064 {
9065 return d;
9066 }
9067 }
9068
9069 return NULL;
9070 }
9071
9072 // Search for a pending DHCP lease item by the MAC address
SearchDhcpPendingLeaseByMac(VH * v,UCHAR * mac)9073 DHCP_LEASE *SearchDhcpPendingLeaseByMac(VH *v, UCHAR *mac)
9074 {
9075 DHCP_LEASE *d, t;
9076 // Validate arguments
9077 if (v == NULL || mac == NULL)
9078 {
9079 return NULL;
9080 }
9081
9082 Copy(&t.MacAddress, mac, 6);
9083 d = Search(v->DhcpPendingLeaseList, &t);
9084
9085 return d;
9086 }
9087
9088 // Search for a DHCP lease item by the MAC address
SearchDhcpLeaseByMac(VH * v,UCHAR * mac)9089 DHCP_LEASE *SearchDhcpLeaseByMac(VH *v, UCHAR *mac)
9090 {
9091 DHCP_LEASE *d, t;
9092 // Validate arguments
9093 if (v == NULL || mac == NULL)
9094 {
9095 return NULL;
9096 }
9097
9098 Copy(&t.MacAddress, mac, 6);
9099 d = Search(v->DhcpLeaseList, &t);
9100
9101 return d;
9102 }
9103
9104 // Release the DHCP lease item
FreeDhcpLease(DHCP_LEASE * d)9105 void FreeDhcpLease(DHCP_LEASE *d)
9106 {
9107 // Validate arguments
9108 if (d == NULL)
9109 {
9110 return;
9111 }
9112
9113 Free(d->Hostname);
9114 Free(d);
9115 }
9116
9117 // Create a DHCP lease item
NewDhcpLease(UINT expire,UCHAR * mac_address,UINT ip,UINT mask,char * hostname)9118 DHCP_LEASE *NewDhcpLease(UINT expire, UCHAR *mac_address, UINT ip, UINT mask, char *hostname)
9119 {
9120 DHCP_LEASE *d;
9121 // Validate arguments
9122 if (mac_address == NULL || hostname == NULL)
9123 {
9124 return NULL;
9125 }
9126
9127 d = ZeroMalloc(sizeof(DHCP_LEASE));
9128 d->LeasedTime = (UINT64)Tick64();
9129 if (expire == INFINITE)
9130 {
9131 d->ExpireTime = INFINITE;
9132 }
9133 else
9134 {
9135 d->ExpireTime = d->LeasedTime + (UINT64)expire;
9136 }
9137 d->IpAddress = ip;
9138 d->Mask = mask;
9139 d->Hostname = CopyStr(hostname);
9140 Copy(d->MacAddress, mac_address, 6);
9141
9142
9143 return d;
9144 }
9145
9146 // Comparison of the items in the DHCP list
CompareDhcpLeaseList(void * p1,void * p2)9147 int CompareDhcpLeaseList(void *p1, void *p2)
9148 {
9149 DHCP_LEASE *d1, *d2;
9150 // Validate arguments
9151 if (p1 == NULL || p2 == NULL)
9152 {
9153 return 0;
9154 }
9155 d1 = *(DHCP_LEASE **)p1;
9156 d2 = *(DHCP_LEASE **)p2;
9157 if (d1 == NULL || d2 == NULL)
9158 {
9159 return 0;
9160 }
9161
9162 return Cmp(d1->MacAddress, d2->MacAddress, 6);
9163 }
9164
9165 // Poll the DHCP server
PollingDhcpServer(VH * v)9166 void PollingDhcpServer(VH *v)
9167 {
9168 UINT i;
9169 // Validate arguments
9170 if (v == NULL)
9171 {
9172 return;
9173 }
9174
9175 if (v->LastDhcpPolling != 0)
9176 {
9177 if ((v->LastDhcpPolling + (UINT64)DHCP_POLLING_INTERVAL) > v->Now &&
9178 v->LastDhcpPolling < v->Now)
9179 {
9180 return;
9181 }
9182 }
9183 v->LastDhcpPolling = v->Now;
9184
9185 LIST_CLEANUP:
9186 for (i = 0; i < LIST_NUM(v->DhcpLeaseList); ++i)
9187 {
9188 DHCP_LEASE *d = LIST_DATA(v->DhcpLeaseList, i);
9189
9190 if (d->ExpireTime < v->Now)
9191 {
9192 FreeDhcpLease(d);
9193 Delete(v->DhcpLeaseList, d);
9194 goto LIST_CLEANUP;
9195 }
9196 }
9197
9198 PENDING_LIST_CLEANUP:
9199 // Remove expired entries
9200 for (i = 0; i < LIST_NUM(v->DhcpPendingLeaseList); ++i)
9201 {
9202 DHCP_LEASE *d = LIST_DATA(v->DhcpPendingLeaseList, i);
9203
9204 if (d->ExpireTime < v->Now)
9205 {
9206 FreeDhcpLease(d);
9207 Delete(v->DhcpPendingLeaseList, d);
9208 goto PENDING_LIST_CLEANUP;
9209 }
9210 }
9211 }
9212
9213 // Correspond to the DHCP REQUEST
ServeDhcpRequest(VH * v,UCHAR * mac,UINT request_ip)9214 UINT ServeDhcpRequest(VH *v, UCHAR *mac, UINT request_ip)
9215 {
9216 return ServeDhcpRequestEx(v, mac, request_ip, false);
9217 }
9218
ServeDhcpRequestEx(VH * v,UCHAR * mac,UINT request_ip,bool is_static_ip)9219 UINT ServeDhcpRequestEx(VH *v, UCHAR *mac, UINT request_ip, bool is_static_ip)
9220 {
9221 UINT ret;
9222 // Validate arguments
9223 if (v == NULL || mac == NULL)
9224 {
9225 return 0;
9226 }
9227
9228 ret = ServeDhcpDiscoverEx(v, mac, request_ip, is_static_ip);
9229 if (ret != request_ip)
9230 {
9231 if (request_ip != 0)
9232 {
9233 // Raise an error if the requested IP address cannot to be assigned
9234 return 0;
9235 }
9236 }
9237
9238 return ret;
9239 }
9240
9241 // Correspond to the DHCP DISCOVER
ServeDhcpDiscover(VH * v,UCHAR * mac,UINT request_ip)9242 UINT ServeDhcpDiscover(VH *v, UCHAR *mac, UINT request_ip)
9243 {
9244 UINT ret = 0;
9245 // Validate arguments
9246 if (v == NULL || mac == NULL)
9247 {
9248 return 0;
9249 }
9250
9251 if (request_ip != 0)
9252 {
9253 // IP address is specified
9254 DHCP_LEASE *d = SearchDhcpLeaseByIp(v, request_ip);
9255 if (d == NULL)
9256 {
9257 d = SearchDhcpPendingLeaseByIp(v, request_ip);
9258 }
9259
9260 if (d != NULL)
9261 {
9262 // If an entry for the same IP address already exists,
9263 // check whether it is a request from the same MAC address
9264 if (Cmp(mac, d->MacAddress, 6) == 0)
9265 {
9266 // Examine whether the specified IP address is within the range of assignment
9267 if (Endian32(v->DhcpIpStart) <= Endian32(request_ip) &&
9268 Endian32(request_ip) <= Endian32(v->DhcpIpEnd))
9269 {
9270 // Accept if within the range
9271 ret = request_ip;
9272 }
9273 }
9274 }
9275 else
9276 {
9277 // Examine whether the specified IP address is within the range of assignment
9278 if (Endian32(v->DhcpIpStart) <= Endian32(request_ip) &&
9279 Endian32(request_ip) <= Endian32(v->DhcpIpEnd))
9280 {
9281 // Accept if within the range
9282 ret = request_ip;
9283 }
9284 else
9285 {
9286 // Propose an IP in the range since it's a Discover although It is out of range
9287 }
9288 }
9289 }
9290
9291 if (ret == 0)
9292 {
9293 // If there is any entry with the same MAC address
9294 // that are already registered, use it with priority
9295 DHCP_LEASE *d = SearchDhcpLeaseByMac(v, mac);
9296 if (d == NULL)
9297 {
9298 d = SearchDhcpPendingLeaseByMac(v, mac);
9299 }
9300
9301 if (d != NULL)
9302 {
9303 // Examine whether the found IP address is in the allocation region
9304 if (Endian32(v->DhcpIpStart) <= Endian32(d->IpAddress) &&
9305 Endian32(d->IpAddress) <= Endian32(v->DhcpIpEnd))
9306 {
9307 // Use the IP address if it's found within the range
9308 ret = d->IpAddress;
9309 }
9310 }
9311 }
9312
9313 if (ret == 0)
9314 {
9315 // Take an appropriate IP addresses that can be assigned newly
9316 HUB_OPTION *opt = NatGetHubOption(v);
9317
9318 if (opt != NULL && opt->SecureNAT_RandomizeAssignIp)
9319 {
9320 ret = GetFreeDhcpIpAddressByRandom(v, mac);
9321 }
9322 else
9323 {
9324 ret = GetFreeDhcpIpAddress(v);
9325 }
9326 }
9327
9328 return ret;
9329 }
9330
ServeDhcpDiscoverEx(VH * v,UCHAR * mac,UINT request_ip,bool is_static_ip)9331 UINT ServeDhcpDiscoverEx(VH *v, UCHAR *mac, UINT request_ip, bool is_static_ip)
9332 {
9333 if (is_static_ip == false)
9334 {
9335 return ServeDhcpDiscover(v, mac, request_ip );
9336 }
9337
9338 if (v == NULL || mac == NULL || request_ip == 0)
9339 {
9340 return 0;
9341 }
9342
9343 DHCP_LEASE *d = SearchDhcpLeaseByIp(v, request_ip);
9344 if (d != NULL)
9345 {
9346 // The requested IP address is used already
9347 return 0;
9348 }
9349
9350 // For static IP, the requested IP address must NOT be within the range of the DHCP pool
9351 if (Endian32(request_ip) < Endian32(v->DhcpIpStart) || Endian32(request_ip) > Endian32(v->DhcpIpEnd))
9352 {
9353 return request_ip;
9354 }
9355
9356 return 0;
9357 }
9358
9359 // Take an appropriate IP addresses that can be assigned newly
GetFreeDhcpIpAddress(VH * v)9360 UINT GetFreeDhcpIpAddress(VH *v)
9361 {
9362 UINT ip_start, ip_end;
9363 UINT i;
9364 // Validate arguments
9365 if (v == NULL)
9366 {
9367 return 0;
9368 }
9369
9370 ip_start = Endian32(v->DhcpIpStart);
9371 ip_end = Endian32(v->DhcpIpEnd);
9372
9373 for (i = ip_start; i <= ip_end; i++)
9374 {
9375 UINT ip = Endian32(i);
9376 if (SearchDhcpLeaseByIp(v, ip) == NULL && SearchDhcpPendingLeaseByIp(v, ip) == NULL)
9377 {
9378 // A free IP address is found
9379 return ip;
9380 }
9381 }
9382
9383 // There is no free address
9384 return 0;
9385 }
9386
9387 // Take an appropriate IP addresses that can be assigned newly (random)
GetFreeDhcpIpAddressByRandom(VH * v,UCHAR * mac)9388 UINT GetFreeDhcpIpAddressByRandom(VH *v, UCHAR *mac)
9389 {
9390 UINT ip_start, ip_end;
9391 UINT i;
9392 UINT num_retry;
9393 // Validate arguments
9394 if (v == NULL || mac == NULL)
9395 {
9396 return 0;
9397 }
9398
9399 ip_start = Endian32(v->DhcpIpStart);
9400 ip_end = Endian32(v->DhcpIpEnd);
9401
9402 if (ip_start > ip_end)
9403 {
9404 return 0;
9405 }
9406
9407 num_retry = (ip_end - ip_start + 1) * 2;
9408 num_retry = MIN(num_retry, 65536 * 2);
9409
9410 for (i = 0; i < num_retry; i++)
9411 {
9412 UCHAR rand_seed[sizeof(UINT) + 6];
9413 UCHAR hash[16];
9414 UINT rand_int;
9415 UINT new_ip;
9416
9417 WRITE_UINT(&rand_seed[0], i);
9418 Copy(rand_seed + sizeof(UINT), mac, 6);
9419
9420 Md5(hash, rand_seed, sizeof(rand_seed));
9421
9422 rand_int = READ_UINT(hash);
9423
9424 new_ip = Endian32(ip_start + (rand_int % (ip_end - ip_start + 1)));
9425
9426 if (SearchDhcpLeaseByIp(v, new_ip) == NULL && SearchDhcpPendingLeaseByIp(v, new_ip) == NULL)
9427 {
9428 // A free IP address is found
9429 return new_ip;
9430 }
9431 }
9432
9433 // There is no free address
9434 return 0;
9435 }
9436
9437 // Virtual DHCP Server
VirtualDhcpServer(VH * v,PKT * p)9438 void VirtualDhcpServer(VH *v, PKT *p)
9439 {
9440 DHCPV4_HEADER *dhcp;
9441 UCHAR *data;
9442 UINT size;
9443 UINT dhcp_header_size;
9444 UINT dhcp_data_offset;
9445 UINT tran_id;
9446 UINT magic_cookie = Endian32(DHCP_MAGIC_COOKIE);
9447 bool ok;
9448 DHCP_OPTION_LIST *opt;
9449 // Validate arguments
9450 if (v == NULL || p == NULL)
9451 {
9452 return;
9453 }
9454
9455 if (v->NativeNat != NULL)
9456 {
9457 if (Cmp(p->MacAddressSrc, v->NativeNat->CurrentMacAddress, 6) == 0)
9458 {
9459 // DHCP server is kept from responding for the native NAT interface
9460 // ** Not be needed to return yet **
9461 //return;
9462 }
9463 }
9464
9465 dhcp = p->L7.DHCPv4Header;
9466
9467 tran_id = Endian32(dhcp->TransactionId);
9468
9469 // Get the DHCP data and size
9470 dhcp_header_size = sizeof(DHCPV4_HEADER);
9471 dhcp_data_offset = (UINT)(((UCHAR *)p->L7.DHCPv4Header) - ((UCHAR *)p->MacHeader) + dhcp_header_size);
9472 data = ((UCHAR *)dhcp) + dhcp_header_size;
9473 size = p->PacketSize - dhcp_data_offset;
9474 if (dhcp_header_size < 5)
9475 {
9476 // Data size is invalid
9477 return;
9478 }
9479
9480 // Search for Magic Cookie
9481 ok = false;
9482 while (size >= 5)
9483 {
9484 if (Cmp(data, &magic_cookie, sizeof(magic_cookie)) == 0)
9485 {
9486 // Found
9487 data += 4;
9488 size -= 4;
9489 ok = true;
9490 break;
9491 }
9492 data++;
9493 size--;
9494 }
9495
9496 if (ok == false)
9497 {
9498 // The packet is invalid
9499 return;
9500 }
9501
9502 // Parse DHCP options list
9503 opt = ParseDhcpOptionList(data, size);
9504 if (opt == NULL)
9505 {
9506 // The packet is invalid
9507 return;
9508 }
9509
9510 if (StartWith(opt->Hostname, NN_HOSTNAME_STARTWITH) || StartWith(opt->Hostname, NN_HOSTNAME_STARTWITH2))
9511 {
9512 Free(opt);
9513 return;
9514 }
9515
9516 if (dhcp->OpCode == 1 && (opt->Opcode == DHCP_DISCOVER || opt->Opcode == DHCP_REQUEST || opt->Opcode == DHCP_INFORM))
9517 {
9518 // Operate as the server
9519 UINT ip = 0, ip_static = dhcp->ServerIP;
9520 dhcp->ServerIP = 0;
9521
9522 if (opt->RequestedIp == 0)
9523 {
9524 opt->RequestedIp = (ip_static ? ip_static : p->L3.IPv4Header->SrcIP);
9525 }
9526 if (opt->Opcode == DHCP_DISCOVER)
9527 {
9528 // Return an IP address that can be used
9529 ip = ServeDhcpDiscoverEx(v, p->MacAddressSrc, opt->RequestedIp, ip_static);
9530 }
9531 else if (opt->Opcode == DHCP_REQUEST)
9532 {
9533 // Determine the IP address
9534 if (ip_static && opt->RequestedIp != ip_static)
9535 {
9536 // Don't allow opt->RequestedIp other than the IP written in user's note
9537 ip = 0;
9538 }
9539 else
9540 {
9541 ip = ServeDhcpRequestEx(v, p->MacAddressSrc, opt->RequestedIp, ip_static);
9542 }
9543 }
9544
9545 if (ip != 0 || opt->Opcode == DHCP_INFORM)
9546 {
9547 // Respond if there is providable IP address
9548
9549 if (opt->Opcode == DHCP_REQUEST)
9550 {
9551 DHCP_LEASE *d;
9552 char client_mac[MAX_SIZE];
9553 char client_ip[MAX_SIZE];
9554
9555 // Remove old records with the same IP address
9556 d = SearchDhcpLeaseByIp(v, ip);
9557 if (d != NULL)
9558 {
9559 FreeDhcpLease(d);
9560 Delete(v->DhcpLeaseList, d);
9561 }
9562
9563 d = SearchDhcpPendingLeaseByIp(v, ip);
9564 if (d != NULL)
9565 {
9566 FreeDhcpLease(d);
9567 Delete(v->DhcpPendingLeaseList, d);
9568 }
9569
9570 // Create a new entry
9571 d = NewDhcpLease(v->DhcpExpire, p->MacAddressSrc, ip, v->DhcpMask, opt->Hostname);
9572 d->Id = ++v->DhcpId;
9573 Add(v->DhcpLeaseList, d);
9574
9575 MacToStr(client_mac, sizeof(client_mac), d->MacAddress);
9576 IPToStr32(client_ip, sizeof(client_ip), d->IpAddress);
9577
9578 NLog(v, "LH_NAT_DHCP_CREATED", d->Id, client_mac, client_ip, d->Hostname, v->DhcpExpire / 1000);
9579 }
9580
9581 // Respond
9582 if (true)
9583 {
9584 DHCP_OPTION_LIST ret;
9585 LIST *o;
9586 Zero(&ret, sizeof(ret));
9587
9588 ret.Opcode = (opt->Opcode == DHCP_DISCOVER ? DHCP_OFFER : DHCP_ACK);
9589 ret.ServerAddress = v->HostIP;
9590 if (v->DhcpExpire == INFINITE)
9591 {
9592 ret.LeaseTime = INFINITE;
9593 }
9594 else
9595 {
9596 ret.LeaseTime = Endian32(v->DhcpExpire / 1000);
9597 }
9598
9599 if (opt->Opcode == DHCP_INFORM)
9600 {
9601 ret.LeaseTime = 0;
9602 }
9603
9604 StrCpy(ret.DomainName, sizeof(ret.DomainName), v->DhcpDomain);
9605 ret.SubnetMask = v->DhcpMask;
9606 ret.DnsServer = v->DhcpDns;
9607 ret.DnsServer2 = v->DhcpDns2;
9608 ret.Gateway = v->DhcpGateway;
9609
9610 if (GetGlobalServerFlag(GSF_DISABLE_PUSH_ROUTE) == 0)
9611 {
9612 Copy(&ret.ClasslessRoute, &v->PushRoute, sizeof(DHCP_CLASSLESS_ROUTE_TABLE));
9613
9614 if (IsIpcMacAddress(p->MacAddressSrc))
9615 {
9616 if (ret.Gateway == 0)
9617 {
9618 // If the default gateway is not specified, add the static routing table
9619 // entry for the local IP subnet
9620 // (for PPP clients)
9621 IP dhcp_ip;
9622 IP dhcp_mask;
9623 IP dhcp_network;
9624
9625 UINTToIP(&dhcp_ip, ip);
9626
9627 if (ip == 0)
9628 {
9629 UINTToIP(&dhcp_ip, p->L3.IPv4Header->SrcIP);
9630 }
9631
9632 UINTToIP(&dhcp_mask, v->DhcpMask);
9633
9634 IPAnd4(&dhcp_network, &dhcp_ip, &dhcp_mask);
9635
9636 if (GetBestClasslessRoute(&ret.ClasslessRoute, &dhcp_ip) == NULL)
9637 {
9638 if (ret.ClasslessRoute.NumExistingRoutes < MAX_DHCP_CLASSLESS_ROUTE_ENTRIES)
9639 {
9640 DHCP_CLASSLESS_ROUTE *cr = &ret.ClasslessRoute.Entries[ret.ClasslessRoute.NumExistingRoutes];
9641
9642 cr->Exists = true;
9643
9644 UINTToIP(&cr->Gateway, v->HostIP);
9645
9646 if (v->UseNat == false && ret.ClasslessRoute.NumExistingRoutes >= 1)
9647 {
9648 Copy(&cr->Gateway, &ret.ClasslessRoute.Entries[0].Gateway, sizeof(IP));
9649 }
9650
9651 Copy(&cr->Network, &dhcp_network, sizeof(IP));
9652 Copy(&cr->SubnetMask, &dhcp_mask, sizeof(IP));
9653 cr->SubnetMaskLen = SubnetMaskToInt(&dhcp_mask);
9654
9655 ret.ClasslessRoute.NumExistingRoutes++;
9656 }
9657 }
9658 }
9659 }
9660 }
9661
9662 if (opt->Opcode != DHCP_INFORM)
9663 {
9664 char client_mac[MAX_SIZE];
9665 char client_ip[64];
9666 IP ips;
9667
9668 BinToStr(client_mac, sizeof(client_mac), p->MacAddressSrc, 6);
9669 UINTToIP(&ips, ip);
9670 IPToStr(client_ip, sizeof(client_ip), &ips);
9671
9672 if (ret.Opcode == DHCP_OFFER)
9673 {
9674 // DHCP_OFFER
9675 DHCP_LEASE *d = NewDhcpLease(5000, p->MacAddressSrc, ip, v->DhcpMask, opt->Hostname);
9676 d->Id = LIST_NUM(v->DhcpPendingLeaseList);
9677 Add(v->DhcpPendingLeaseList, d);
9678
9679 Debug("VirtualDhcpServer(): %s has been marked as pending for %s\n", client_ip, client_mac);
9680 }
9681 else
9682 {
9683 // DHCP_ACK
9684 Debug("VirtualDhcpServer(): %s has been assigned to %s\n", client_ip, client_mac);
9685 }
9686 }
9687
9688 // Build a DHCP option
9689 o = BuildDhcpOption(&ret);
9690 if (o != NULL)
9691 {
9692 BUF *b = BuildDhcpOptionsBuf(o);
9693 if (b != NULL)
9694 {
9695 UINT dest_ip = p->L3.IPv4Header->SrcIP;
9696 if (dest_ip == 0)
9697 {
9698 dest_ip = 0xffffffff;
9699 }
9700 // Transmission
9701 VirtualDhcpSend(v, tran_id, dest_ip, Endian16(p->L4.UDPHeader->SrcPort),
9702 ip, dhcp->ClientMacAddress, b, dhcp->HardwareType, dhcp->HardwareAddressSize);
9703
9704 // Release the memory
9705 FreeBuf(b);
9706 }
9707 FreeDhcpOptions(o);
9708 }
9709 }
9710 }
9711 else
9712 {
9713 // There is no IP address that can be provided
9714 DHCP_OPTION_LIST ret;
9715 LIST *o;
9716 Zero(&ret, sizeof(ret));
9717
9718 ret.Opcode = DHCP_NACK;
9719 ret.ServerAddress = v->HostIP;
9720 StrCpy(ret.DomainName, sizeof(ret.DomainName), v->DhcpDomain);
9721 ret.SubnetMask = v->DhcpMask;
9722
9723 // Build the DHCP option
9724 o = BuildDhcpOption(&ret);
9725 if (o != NULL)
9726 {
9727 BUF *b = BuildDhcpOptionsBuf(o);
9728 if (b != NULL)
9729 {
9730 UINT dest_ip = p->L3.IPv4Header->SrcIP;
9731 if (dest_ip == 0)
9732 {
9733 dest_ip = 0xffffffff;
9734 }
9735 // Transmission
9736 VirtualDhcpSend(v, tran_id, dest_ip, Endian16(p->L4.UDPHeader->SrcPort),
9737 ip, dhcp->ClientMacAddress, b, dhcp->HardwareType, dhcp->HardwareAddressSize);
9738
9739 // Release the memory
9740 FreeBuf(b);
9741 }
9742 FreeDhcpOptions(o);
9743 }
9744 }
9745 }
9746
9747 // Release the memory
9748 Free(opt);
9749 }
9750
9751 // Submit the DHCP response packet
VirtualDhcpSend(VH * v,UINT tran_id,UINT dest_ip,UINT dest_port,UINT new_ip,UCHAR * client_mac,BUF * b,UINT hw_type,UINT hw_addr_size)9752 void VirtualDhcpSend(VH *v, UINT tran_id, UINT dest_ip, UINT dest_port,
9753 UINT new_ip, UCHAR *client_mac, BUF *b, UINT hw_type, UINT hw_addr_size)
9754 {
9755 UINT blank_size = 128 + 64;
9756 UINT dhcp_packet_size;
9757 UINT magic = Endian32(DHCP_MAGIC_COOKIE);
9758 DHCPV4_HEADER *dhcp;
9759 void *magic_cookie_addr;
9760 void *buffer_addr;
9761 // Validate arguments
9762 if (v == NULL || b == NULL)
9763 {
9764 return;
9765 }
9766
9767 // Calculate the DHCP packet size
9768 dhcp_packet_size = blank_size + sizeof(DHCPV4_HEADER) + sizeof(magic) + b->Size;
9769
9770 if (dhcp_packet_size < DHCP_MIN_SIZE)
9771 {
9772 // Padding
9773 dhcp_packet_size = DHCP_MIN_SIZE;
9774 }
9775
9776 // Create a header
9777 dhcp = ZeroMalloc(dhcp_packet_size);
9778
9779 dhcp->OpCode = 2;
9780 dhcp->HardwareType = hw_type;
9781 dhcp->HardwareAddressSize = hw_addr_size;
9782 dhcp->Hops = 0;
9783 dhcp->TransactionId = Endian32(tran_id);
9784 dhcp->Seconds = 0;
9785 dhcp->Flags = 0;
9786 dhcp->YourIP = new_ip;
9787 dhcp->ServerIP = v->HostIP;
9788 Copy(dhcp->ClientMacAddress, client_mac, 6);
9789
9790 // Calculate the address
9791 magic_cookie_addr = (((UCHAR *)dhcp) + sizeof(DHCPV4_HEADER) + blank_size);
9792 buffer_addr = ((UCHAR *)magic_cookie_addr) + sizeof(magic);
9793
9794 // Magic Cookie
9795 Copy(magic_cookie_addr, &magic, sizeof(magic));
9796
9797 // Buffer
9798 Copy(buffer_addr, b->Buf, b->Size);
9799
9800 // Transmission
9801 SendUdp(v, dest_ip, dest_port, v->HostIP, NAT_DHCP_SERVER_PORT, dhcp, dhcp_packet_size);
9802
9803 Free(dhcp);
9804 }
9805
9806 // Virtual host: Process the Layer2
VirtualLayer2(VH * v,PKT * packet)9807 void VirtualLayer2(VH *v, PKT *packet)
9808 {
9809 bool ok;
9810 // Validate arguments
9811 if (packet == NULL || v == NULL)
9812 {
9813 return;
9814 }
9815
9816 // Packet filter
9817 if (VirtualLayer2Filter(v, packet) == false)
9818 {
9819 // Packet was ignored
9820 return;
9821 }
9822
9823 ok = false;
9824 if (packet->TypeL3 == L3_IPV4 && packet->TypeL4 == L4_UDP && packet->TypeL7 == L7_DHCPV4)
9825 {
9826 if (v->UseDhcp)
9827 {
9828 // A special treatment on the DHCP packet
9829 if (packet->BroadcastPacket || Cmp(packet->MacAddressDest, v->MacAddress, 6) == 0)
9830 {
9831 // Virtual DHCP server processing
9832 VirtualDhcpServer(v, packet);
9833 ok = true;
9834 }
9835 }
9836 }
9837
9838 if (ok == false)
9839 {
9840 // The process for each supported protocol
9841 switch (packet->TypeL3)
9842 {
9843 case L3_ARPV4: // ARPv4
9844 VirtualArpReceived(v, packet);
9845 break;
9846
9847 case L3_IPV4: // IPv4
9848 VirtualIpReceived(v, packet);
9849 break;
9850 }
9851 }
9852 }
9853
9854 // Packet filter (Blocking packets to other than me)
VirtualLayer2Filter(VH * v,PKT * packet)9855 bool VirtualLayer2Filter(VH *v, PKT *packet)
9856 {
9857 // Validate arguments
9858 if (v == NULL || packet == NULL)
9859 {
9860 return false;
9861 }
9862
9863 // Pass through if broadcast packet
9864 if (packet->BroadcastPacket)
9865 {
9866 return true;
9867 }
9868
9869 // Ignore if the sender of the packet is myself
9870 if (Cmp(packet->MacAddressSrc, v->MacAddress, 6) == 0)
9871 {
9872 return false;
9873 }
9874 // Pass through in the case of a packet addressed to me
9875 if (Cmp(packet->MacAddressDest, v->MacAddress, 6) == 0)
9876 {
9877 return true;
9878 }
9879
9880 // Discard if the other packets
9881 return false;
9882 }
9883
9884 // The virtual host is made to receive a packet
VirtualPutPacket(VH * v,void * data,UINT size)9885 bool VirtualPutPacket(VH *v, void *data, UINT size)
9886 {
9887 if (data == NULL)
9888 {
9889 // Flush
9890 v->flag1 = false;
9891
9892 if (v->NativeNat != NULL)
9893 {
9894 if (v->NativeNat->SendStateChanged)
9895 {
9896 TUBE *halt_tube = NULL;
9897
9898 Lock(v->NativeNat->Lock);
9899 {
9900 if (v->NativeNat->HaltTube != NULL)
9901 {
9902 halt_tube = v->NativeNat->HaltTube;
9903
9904 AddRef(halt_tube->Ref);
9905 }
9906 }
9907 Unlock(v->NativeNat->Lock);
9908
9909 if (halt_tube != NULL)
9910 {
9911 TubeFlushEx(halt_tube, true);
9912
9913 v->NativeNat->SendStateChanged = false;
9914
9915 ReleaseTube(halt_tube);
9916 }
9917 }
9918 }
9919 }
9920 else
9921 {
9922 // Interpret the received packet
9923 PKT *packet = ParsePacket(data, size);
9924
9925 if (v->flag1 == false)
9926 {
9927 v->flag1 = true;
9928 v->Now = Tick64();
9929 }
9930
9931 // Lock the entire virtual machine in here
9932 LockVirtual(v);
9933 {
9934 if (packet != NULL)
9935 {
9936 // Process the Layer-2
9937 VirtualLayer2(v, packet);
9938
9939 // Release the packet structure
9940 FreePacket(packet);
9941 }
9942 }
9943 UnlockVirtual(v);
9944
9945 Free(data);
9946 }
9947
9948 return true;
9949 }
VirtualPaPutPacket(SESSION * s,void * data,UINT size)9950 bool VirtualPaPutPacket(SESSION *s, void *data, UINT size)
9951 {
9952 VH *v;
9953 // Validate arguments
9954 if (s == NULL || (v = (VH *)s->PacketAdapter->Param) == NULL)
9955 {
9956 return false;
9957 }
9958
9959 return VirtualPutPacket(v, data, size);
9960 }
9961
9962 // Get the options for the virtual host
GetVirtualHostOption(VH * v,VH_OPTION * o)9963 void GetVirtualHostOption(VH *v, VH_OPTION *o)
9964 {
9965 // Validate arguments
9966 if (v == NULL)
9967 {
9968 return;
9969 }
9970
9971 LockVirtual(v);
9972 {
9973 Zero(o, sizeof(VH_OPTION));
9974
9975 // MAC address
9976 Copy(o->MacAddress, v->MacAddress, 6);
9977
9978 // Host information
9979 UINTToIP(&o->Ip, v->HostIP);
9980 UINTToIP(&o->Mask, v->HostMask);
9981
9982 o->Mtu = v->Mtu;
9983
9984 // NAT timeout information
9985 o->NatTcpTimeout = v->NatTcpTimeout / 1000;
9986 o->NatUdpTimeout = v->NatUdpTimeout / 1000;
9987
9988 // NAT using flag
9989 o->UseNat = v->UseNat;
9990
9991 // DHCP using flag
9992 o->UseDhcp = v->UseDhcp;
9993
9994 // IP address range for DHCP distribution
9995 UINTToIP(&o->DhcpLeaseIPStart, v->DhcpIpStart);
9996 UINTToIP(&o->DhcpLeaseIPEnd, v->DhcpIpEnd);
9997
9998 // Subnet mask
9999 UINTToIP(&o->DhcpSubnetMask, v->DhcpMask);
10000
10001 // Expiration date
10002 if (v->DhcpExpire != INFINITE)
10003 {
10004 o->DhcpExpireTimeSpan = v->DhcpExpire / 1000;
10005 }
10006 else
10007 {
10008 o->DhcpExpireTimeSpan = INFINITE;
10009 }
10010
10011 // Gateway address
10012 UINTToIP(&o->DhcpGatewayAddress, v->DhcpGateway);
10013
10014 // DNS server address
10015 UINTToIP(&o->DhcpDnsServerAddress, v->DhcpDns);
10016 UINTToIP(&o->DhcpDnsServerAddress2, v->DhcpDns2);
10017
10018 // Domain name
10019 StrCpy(o->DhcpDomainName, sizeof(o->DhcpDomainName), v->DhcpDomain);
10020
10021 // Save a log
10022 o->SaveLog = v->SaveLog;
10023
10024 // Pushing route option
10025 BuildClasslessRouteTableStr(o->DhcpPushRoutes, sizeof(o->DhcpPushRoutes), &v->PushRoute);
10026 o->ApplyDhcpPushRoutes = true;
10027 }
10028 UnlockVirtual(v);
10029 }
10030
10031 // Set the option to the virtual host
SetVirtualHostOption(VH * v,VH_OPTION * vo)10032 void SetVirtualHostOption(VH *v, VH_OPTION *vo)
10033 {
10034 UINT i;
10035 // Validate arguments
10036 if (v == NULL || vo == NULL)
10037 {
10038 return;
10039 }
10040
10041 LockVirtual(v);
10042 {
10043 // Set the MAC address
10044 for (i = 0; i < 6; i++)
10045 {
10046 if (vo->MacAddress[i] != 0)
10047 {
10048 Copy(v->MacAddress, vo->MacAddress, 6);
10049 break;
10050 }
10051 }
10052
10053 // Set the host information list
10054 v->HostIP = IPToUINT(&vo->Ip);
10055 v->HostMask = IPToUINT(&vo->Mask);
10056
10057 // Set the MTU, MMS
10058 v->Mtu = MIN(vo->Mtu, MAX_L3_DATA_SIZE);
10059 if (v->Mtu == 0)
10060 {
10061 v->Mtu = MAX_L3_DATA_SIZE;
10062 }
10063 v->Mtu = MAX(v->Mtu, TCP_HEADER_SIZE + IP_HEADER_SIZE + MAC_HEADER_SIZE + 8);
10064 v->IpMss = ((v->Mtu - IP_HEADER_SIZE) / 8) * 8;
10065 v->TcpMss = ((v->IpMss - TCP_HEADER_SIZE) / 8) * 8;
10066 v->UdpMss = ((v->IpMss - UDP_HEADER_SIZE) / 8) * 8;
10067
10068 if (vo->NatTcpTimeout != 0)
10069 {
10070 v->NatTcpTimeout = MIN(vo->NatTcpTimeout, 4000000) * 1000;
10071 }
10072 if (vo->NatUdpTimeout != 0)
10073 {
10074 v->NatUdpTimeout = MIN(vo->NatUdpTimeout, 4000000) * 1000;
10075 }
10076 v->NatTcpTimeout = MAKESURE(v->NatTcpTimeout, NAT_TCP_MIN_TIMEOUT, NAT_TCP_MAX_TIMEOUT);
10077 v->NatUdpTimeout = MAKESURE(v->NatUdpTimeout, NAT_UDP_MIN_TIMEOUT, NAT_UDP_MAX_TIMEOUT);
10078 Debug("Timeout: %d , %d\n", v->NatTcpTimeout, v->NatUdpTimeout);
10079
10080 // NAT using flag
10081 v->UseNat = vo->UseNat;
10082
10083 // DHCP using flag
10084 v->UseDhcp = vo->UseDhcp;
10085
10086 // Expiration date
10087 if (vo->DhcpExpireTimeSpan == 0 || vo->DhcpExpireTimeSpan == INFINITE)
10088 {
10089 v->DhcpExpire = INFINITE;
10090 }
10091 else
10092 {
10093 v->DhcpExpire = MAKESURE(DHCP_MIN_EXPIRE_TIMESPAN,
10094 MIN(vo->DhcpExpireTimeSpan * 1000, 2000000000),
10095 INFINITE);
10096 }
10097
10098 // Address range to be distributed
10099 v->DhcpIpStart = IPToUINT(&vo->DhcpLeaseIPStart);
10100 v->DhcpIpEnd = IPToUINT(&vo->DhcpLeaseIPEnd);
10101 if (Endian32(v->DhcpIpEnd) < Endian32(v->DhcpIpStart))
10102 {
10103 v->DhcpIpEnd = v->DhcpIpStart;
10104 }
10105
10106 // Subnet mask
10107 v->DhcpMask = IPToUINT(&vo->DhcpSubnetMask);
10108
10109 // Gateway address
10110 v->DhcpGateway = IPToUINT(&vo->DhcpGatewayAddress);
10111
10112 // DNS server address
10113 v->DhcpDns = IPToUINT(&vo->DhcpDnsServerAddress);
10114 v->DhcpDns2 = IPToUINT(&vo->DhcpDnsServerAddress2);
10115
10116 // Domain name
10117 StrCpy(v->DhcpDomain, sizeof(v->DhcpDomain), vo->DhcpDomainName);
10118
10119 // Save a log
10120 v->SaveLog = vo->SaveLog;
10121
10122 // DHCP routing table pushing setting
10123 if (vo->ApplyDhcpPushRoutes)
10124 {
10125 DHCP_CLASSLESS_ROUTE_TABLE rt;
10126
10127 Zero(&rt, sizeof(rt));
10128
10129 if (ParseClasslessRouteTableStr(&rt, vo->DhcpPushRoutes))
10130 {
10131 Copy(&v->PushRoute, &rt, sizeof(DHCP_CLASSLESS_ROUTE_TABLE));
10132 }
10133 }
10134 }
10135 UnlockVirtual(v);
10136 }
10137
10138 // Release the virtual host
Virtual_Free(VH * v)10139 void Virtual_Free(VH *v)
10140 {
10141 // Release the DHCP server
10142 FreeDhcpServer(v);
10143
10144 // NAT release
10145 FreeNat(v);
10146
10147 LockVirtual(v);
10148 {
10149 // Release the IP combining list
10150 FreeIpCombineList(v);
10151
10152 // Release the IP waiting table
10153 FreeIpWaitTable(v);
10154
10155 // Release the ARP waiting table
10156 FreeArpWaitTable(v);
10157
10158 // Release the ARP table
10159 FreeArpTable(v);
10160
10161 // Release the transmission queue
10162 LockQueue(v->SendQueue);
10163 {
10164 BLOCK *block;
10165
10166 // Release all queues
10167 while (block = GetNext(v->SendQueue))
10168 {
10169 FreeBlock(block);
10170 }
10171 }
10172 UnlockQueue(v->SendQueue);
10173 ReleaseQueue(v->SendQueue);
10174 v->SendQueue = NULL;
10175
10176 // Release the cancel object
10177 ReleaseCancel(v->Cancel);
10178
10179 v->Active = false;
10180 }
10181 UnlockVirtual(v);
10182
10183 // Release the logger
10184 FreeLog(v->Logger);
10185 }
VirtualPaFree(SESSION * s)10186 void VirtualPaFree(SESSION *s)
10187 {
10188 VH *v;
10189 // Validate arguments
10190 if (s == NULL || (v = (VH *)s->PacketAdapter->Param) == NULL)
10191 {
10192 return;
10193 }
10194
10195 Virtual_Free(v);
10196 }
10197
10198 // Release the virtual host
ReleaseVirtual(VH * v)10199 void ReleaseVirtual(VH *v)
10200 {
10201 // Validate arguments
10202 if (v == NULL)
10203 {
10204 return;
10205 }
10206
10207 if (Release(v->ref) == 0)
10208 {
10209 CleanupVirtual(v);
10210 }
10211 }
10212
10213 // Lock the virtual host
LockVirtual(VH * v)10214 void LockVirtual(VH *v)
10215 {
10216 // Validate arguments
10217 if (v == NULL)
10218 {
10219 return;
10220 }
10221
10222 Lock(v->lock);
10223 }
10224
10225 // Unlock the virtual host
UnlockVirtual(VH * v)10226 void UnlockVirtual(VH *v)
10227 {
10228 // Validate arguments
10229 if (v == NULL)
10230 {
10231 return;
10232 }
10233
10234 Unlock(v->lock);
10235 }
10236
10237 // Cleanup the virtual host
CleanupVirtual(VH * v)10238 void CleanupVirtual(VH *v)
10239 {
10240 // Validate arguments
10241 if (v == NULL)
10242 {
10243 return;
10244 }
10245
10246 if (v->Session != NULL)
10247 {
10248 ReleaseSession(v->Session);
10249 }
10250
10251 DeleteCounter(v->Counter);
10252 DeleteLock(v->lock);
10253
10254 Free(v);
10255 }
10256
10257 // Stop the virtual host
StopVirtualHost(VH * v)10258 void StopVirtualHost(VH *v)
10259 {
10260 SESSION *s;
10261 // Validate arguments
10262 if (v == NULL)
10263 {
10264 return;
10265 }
10266
10267 // Get the session corresponding to the virtual host
10268 LockVirtual(v);
10269 {
10270 s = v->Session;
10271 if (s != NULL)
10272 {
10273 AddRef(s->ref);
10274 }
10275 }
10276 UnlockVirtual(v);
10277
10278 if (s == NULL)
10279 {
10280 // This session is already stopped
10281 return;
10282 }
10283
10284 // Stop Session
10285 StopSession(s);
10286
10287 ReleaseSession(s);
10288 }
10289
10290 // Create a new virtual host
NewVirtualHost(CEDAR * cedar,CLIENT_OPTION * option,CLIENT_AUTH * auth,VH_OPTION * vh_option)10291 VH *NewVirtualHost(CEDAR *cedar, CLIENT_OPTION *option, CLIENT_AUTH *auth, VH_OPTION *vh_option)
10292 {
10293 return NewVirtualHostEx(cedar, option, auth, vh_option, NULL);
10294 }
NewVirtualHostEx(CEDAR * cedar,CLIENT_OPTION * option,CLIENT_AUTH * auth,VH_OPTION * vh_option,NAT * nat)10295 VH *NewVirtualHostEx(CEDAR *cedar, CLIENT_OPTION *option, CLIENT_AUTH *auth, VH_OPTION *vh_option, NAT *nat)
10296 {
10297 VH *v;
10298 SOCK *s;
10299 // Validate arguments
10300 if (vh_option == NULL)
10301 {
10302 return NULL;
10303 }
10304
10305 // Create a VH
10306 v = ZeroMalloc(sizeof(VH));
10307 v->ref = NewRef();
10308 v->lock = NewLock();
10309 v->Counter = NewCounter();
10310
10311 v->nat = nat;
10312
10313 // Examine whether ICMP Raw Socket can be created
10314 s = NewUDP4(MAKE_SPECIAL_PORT(IP_PROTO_ICMPV4), NULL);
10315 if (s != NULL)
10316 {
10317 if (s->IsTtlSupported)
10318 {
10319 v->IcmpRawSocketOk = true;
10320 }
10321
10322 ReleaseSock(s);
10323 }
10324
10325 if (v->IcmpRawSocketOk == false)
10326 {
10327 v->IcmpApiOk = true;
10328 }
10329
10330 // Set the options
10331 SetVirtualHostOption(v, vh_option);
10332
10333 return v;
10334 }
10335
10336 // Generate a random MAC address
GenMacAddress(UCHAR * mac)10337 void GenMacAddress(UCHAR *mac)
10338 {
10339 UCHAR rand_data[32];
10340 UINT64 now;
10341 BUF *b;
10342 UCHAR hash[SHA1_SIZE];
10343 // Validate arguments
10344 if (mac == NULL)
10345 {
10346 return;
10347 }
10348
10349 // Get the current time
10350 now = SystemTime64();
10351
10352 // Generate a random number
10353 Rand(rand_data, sizeof(rand_data));
10354
10355 // Add to the buffer
10356 b = NewBuf();
10357 WriteBuf(b, &now, sizeof(now));
10358 WriteBuf(b, rand_data, sizeof(rand_data));
10359
10360 // Hash
10361 Sha0(hash, b->Buf, b->Size);
10362
10363 // Generate a MAC address
10364 mac[0] = 0x5E;
10365 mac[1] = hash[0];
10366 mac[2] = hash[1];
10367 mac[3] = hash[2];
10368 mac[4] = hash[3];
10369 mac[5] = hash[4];
10370
10371 FreeBuf(b);
10372 }
10373
10374 // Get a packet of virtual host adapter
VirtualGetPacketAdapter()10375 PACKET_ADAPTER *VirtualGetPacketAdapter()
10376 {
10377 return NewPacketAdapter(VirtualPaInit, VirtualPaGetCancel,
10378 VirtualPaGetNextPacket, VirtualPaPutPacket, VirtualPaFree);
10379 }
10380
10381
10382