1 // SoftEther VPN Source Code - Developer Edition Master Branch
2 // Cedar Communication Module
3
4
5 // Layer3.c
6 // Layer-3 switch module
7
8 #include "Layer3.h"
9
10 #include "Connection.h"
11 #include "Hub.h"
12 #include "Server.h"
13 #include "Session.h"
14 #include "Virtual.h"
15
16 #include "Mayaqua/FileIO.h"
17 #include "Mayaqua/Kernel.h"
18 #include "Mayaqua/Memory.h"
19 #include "Mayaqua/Object.h"
20 #include "Mayaqua/Str.h"
21 #include "Mayaqua/TcpIp.h"
22 #include "Mayaqua/Tick64.h"
23
24 static UCHAR broadcast[6] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
25
26 // Process the IP queue
L3PollingIpQueue(L3IF * f)27 void L3PollingIpQueue(L3IF *f)
28 {
29 L3PACKET *p;
30 // Validate arguments
31 if (f == NULL)
32 {
33 return;
34 }
35
36 // Process the packet came from another session
37 while (p = GetNext(f->IpPacketQueue))
38 {
39 PKT *pkt = p->Packet;
40
41 // Send as an IP packet
42 L3SendIp(f, p);
43 }
44 }
45
46 // Process IP packets
L3RecvIp(L3IF * f,PKT * p,bool self)47 void L3RecvIp(L3IF *f, PKT *p, bool self)
48 {
49 IPV4_HEADER *ip;
50 UINT header_size;
51 UINT next_hop = 0;
52 L3IF *dst;
53 L3PACKET *packet;
54 UINT new_ttl = 0;
55 // Validate arguments
56 if (f == NULL || p == NULL)
57 {
58 return;
59 }
60
61 ip = p->L3.IPv4Header;
62 header_size = IPV4_GET_HEADER_LEN(p->L3.IPv4Header) * 4;
63
64 // Calculate the checksum
65 if (IpCheckChecksum(ip) == false)
66 {
67 // The checksum does not match
68 goto FREE_PACKET;
69 }
70
71 // Register in the ARP table
72 L3KnownArp(f, ip->SrcIP, p->MacAddressSrc);
73
74 if (p->BroadcastPacket)
75 {
76 // Not to route in the case of broadcast packet
77 goto FREE_PACKET;
78 }
79
80 // Calculate the TTL
81 if (ip->TimeToLive >= 1)
82 {
83 new_ttl = ip->TimeToLive - 1;
84 }
85 else
86 {
87 new_ttl = 0;
88 }
89
90 if (new_ttl == 0)
91 {
92 if (ip->DstIP != f->IpAddress)
93 {
94 UINT src_packet_size = p->PacketSize - sizeof(MAC_HEADER);
95 UINT icmp_packet_total_size = sizeof(MAC_HEADER) + sizeof(IPV4_HEADER) + sizeof(ICMP_HEADER) + 4 + header_size + 8;
96 UCHAR *buf;
97 IPV4_HEADER *ipv4;
98 ICMP_HEADER *icmpv4;
99 UCHAR *data;
100 PKT *pkt;
101 UINT data_size = MIN(p->PacketSize - header_size, header_size + 8);
102
103 // Generate an ICMP message that means that the TTL has expired
104 buf = ZeroMalloc(icmp_packet_total_size);
105 ipv4 = (IPV4_HEADER *)(buf + sizeof(MAC_HEADER));
106 icmpv4 = (ICMP_HEADER *)(buf + sizeof(MAC_HEADER) + sizeof(IPV4_HEADER));
107 data = buf + sizeof(MAC_HEADER) + sizeof(IPV4_HEADER) + sizeof(ICMP_HEADER) + 4;
108
109 IPV4_SET_VERSION(ipv4, 4);
110 IPV4_SET_HEADER_LEN(ipv4, sizeof(IPV4_HEADER) / 4);
111 ipv4->TotalLength = Endian16((USHORT)(icmp_packet_total_size - sizeof(MAC_HEADER)));
112 ipv4->TimeToLive = 0xff;
113 ipv4->Protocol = IP_PROTO_ICMPV4;
114 ipv4->SrcIP = f->IpAddress;
115 ipv4->DstIP = ip->SrcIP;
116 ipv4->Checksum = IpChecksum(ipv4, sizeof(IPV4_HEADER));
117
118 icmpv4->Type = 11;
119 Copy(data, ip, data_size);
120 icmpv4->Checksum = IpChecksum(icmpv4, sizeof(ICMP_HEADER) + data_size + 4);
121
122 buf[12] = 0x08;
123 buf[13] = 0x00;
124
125 pkt = ParsePacket(buf, icmp_packet_total_size);
126 if (pkt == NULL)
127 {
128 Free(buf);
129 }
130 else
131 {
132 L3RecvIp(f, pkt, true);
133 }
134
135 // Discard the packet body whose the TTL has expired
136 goto FREE_PACKET;
137 }
138 }
139
140 // Rewrite the TTL
141 p->L3.IPv4Header->TimeToLive = (UCHAR)new_ttl;
142
143 // Get the interface corresponding to the destination IP address
144 dst = L3GetNextIf(f->Switch, ip->DstIP, &next_hop);
145
146 if (dst == NULL && self == false)
147 {
148 UINT src_packet_size = p->PacketSize - sizeof(MAC_HEADER);
149 UINT icmp_packet_total_size = sizeof(MAC_HEADER) + sizeof(IPV4_HEADER) + sizeof(ICMP_HEADER) + 4 + header_size + 8;
150 UCHAR *buf;
151 IPV4_HEADER *ipv4;
152 ICMP_HEADER *icmpv4;
153 UCHAR *data;
154 PKT *pkt;
155 UINT data_size = MIN(p->PacketSize - header_size, header_size + 8);
156
157 // Respond with ICMP that indicates that no route can be found
158 buf = ZeroMalloc(icmp_packet_total_size);
159 ipv4 = (IPV4_HEADER *)(buf + sizeof(MAC_HEADER));
160 icmpv4 = (ICMP_HEADER *)(buf + sizeof(MAC_HEADER) + sizeof(IPV4_HEADER));
161 data = buf + sizeof(MAC_HEADER) + sizeof(IPV4_HEADER) + sizeof(ICMP_HEADER) + 4;
162
163 IPV4_SET_VERSION(ipv4, 4);
164 IPV4_SET_HEADER_LEN(ipv4, sizeof(IPV4_HEADER) / 4);
165 ipv4->TotalLength = Endian16((USHORT)(icmp_packet_total_size - sizeof(MAC_HEADER)));
166 ipv4->TimeToLive = 0xff;
167 ipv4->Protocol = IP_PROTO_ICMPV4;
168 ipv4->SrcIP = f->IpAddress;
169 ipv4->DstIP = ip->SrcIP;
170 ipv4->Checksum = IpChecksum(ipv4, sizeof(IPV4_HEADER));
171
172 icmpv4->Type = 3;
173 Copy(data, ip, data_size);
174 icmpv4->Checksum = IpChecksum(icmpv4, sizeof(ICMP_HEADER) + data_size + 4);
175
176 buf[12] = 0x08;
177 buf[13] = 0x00;
178
179 pkt = ParsePacket(buf, icmp_packet_total_size);
180 if (pkt == NULL)
181 {
182 Free(buf);
183 }
184 else
185 {
186 L3RecvIp(f, pkt, true);
187 }
188
189 // Discard the packet body whose route can not be found
190 goto FREE_PACKET;
191 }
192
193 if (dst != NULL && ip->DstIP == dst->IpAddress)
194 {
195 bool free_packet = true;
196 // IP packet addressed to myself has arrived
197 if (p->TypeL4 == L4_ICMPV4)
198 {
199 ICMP_HEADER *icmp = p->L4.ICMPHeader;
200 if (icmp->Type == ICMP_TYPE_ECHO_REQUEST)
201 {
202 // Reply by rewriting the source and destination of the IP packet
203 UINT src_ip, dst_ip;
204 src_ip = p->L3.IPv4Header->DstIP;
205 dst_ip = p->L3.IPv4Header->SrcIP;
206
207 p->L3.IPv4Header->DstIP = dst_ip;
208 p->L3.IPv4Header->SrcIP = src_ip;
209
210 ip->TimeToLive = 0xff;
211
212 // Recalculates the checksum
213 ip->FlagsAndFragmentOffset[0] = ip->FlagsAndFragmentOffset[1] = 0;
214 icmp->Checksum = 0;
215 icmp->Type = ICMP_TYPE_ECHO_RESPONSE;
216 icmp->Checksum = IpChecksum(icmp, p->PacketSize - sizeof(MAC_HEADER) - header_size);
217
218 dst = L3GetNextIf(f->Switch, ip->DstIP, &next_hop);
219
220 free_packet = false;
221 }
222 }
223
224 if (free_packet)
225 {
226 goto FREE_PACKET;
227 }
228 }
229
230 if (dst == NULL)
231 {
232 // The destination does not exist
233 goto FREE_PACKET;
234 }
235
236 // Recalculate the IP checksum
237 ip->Checksum = 0;
238 ip->Checksum = IpChecksum(ip, header_size);
239
240 // Treat as a Layer-3 packet
241 packet = ZeroMalloc(sizeof(L3PACKET));
242 packet->Expire = Tick64() + IP_WAIT_FOR_ARP_TIMEOUT;
243 packet->NextHopIp = next_hop;
244 packet->Packet = p;
245
246 // Store to the destination session
247 L3StoreIpPacketToIf(f, dst, packet);
248
249 return;
250
251 FREE_PACKET:
252 // Release the packet
253 Free(p->PacketData);
254 FreePacket(p);
255 return;
256 }
257
258 // Process the Layer 2 packet
L3RecvL2(L3IF * f,PKT * p)259 void L3RecvL2(L3IF *f, PKT *p)
260 {
261 // Validate arguments
262 if (f == NULL || p == NULL)
263 {
264 return;
265 }
266
267 // Ignore any packets except a unicast packet which is at destination
268 // or a packet which I sent
269 if (Cmp(p->MacAddressSrc, f->MacAddress, 6) == 0 ||
270 (p->BroadcastPacket == false && Cmp(p->MacAddressDest, f->MacAddress, 6) != 0))
271 {
272 // Release the packet
273 Free(p->PacketData);
274 FreePacket(p);
275 return;
276 }
277
278 if (p->TypeL3 == L3_ARPV4)
279 {
280 // Received an ARP packet
281 L3RecvArp(f, p);
282
283 // Release the packet
284 Free(p->PacketData);
285 FreePacket(p);
286 }
287 else if (p->TypeL3 == L3_IPV4)
288 {
289 // Received an IP packet
290 L3RecvIp(f, p, false);
291 }
292 else
293 {
294 // Release the packet
295 Free(p->PacketData);
296 FreePacket(p);
297 }
298 }
299
300 // Store the IP packet to a different interface
L3StoreIpPacketToIf(L3IF * src_if,L3IF * dst_if,L3PACKET * p)301 void L3StoreIpPacketToIf(L3IF *src_if, L3IF *dst_if, L3PACKET *p)
302 {
303 // Validate arguments
304 if (src_if == NULL || p == NULL || dst_if == NULL)
305 {
306 return;
307 }
308
309 // Add to the queue of store-destination session
310 InsertQueue(dst_if->IpPacketQueue, p);
311
312 // Hit the Cancel object of the store-destination session
313 AddCancelList(src_if->CancelList, dst_if->Session->Cancel1);
314 }
315
316 // Write the packet (Process because the packet was received)
L3PutPacket(L3IF * f,void * data,UINT size)317 void L3PutPacket(L3IF *f, void *data, UINT size)
318 {
319 PKT *p;
320 L3SW *s;
321 if (f == NULL)
322 {
323 return;
324 }
325
326 s = f->Switch;
327
328 if (data != NULL)
329 {
330 // Handle the next packet
331 if (f->CancelList == NULL)
332 {
333 f->CancelList = NewCancelList();
334 }
335
336 // Packet analysis
337 p = ParsePacket(data, size);
338
339 if (p == NULL)
340 {
341 // Packet analysis failure
342 Free(data);
343 }
344 else
345 {
346 // Packet analysis success
347 Lock(s->lock);
348 {
349 L3RecvL2(f, p);
350 }
351 Unlock(s->lock);
352 }
353 }
354 else
355 {
356 // Cancel for the cancellation list after all packet processing has been finished
357 if (f->CancelList != NULL)
358 {
359 CancelList(f->CancelList);
360 ReleaseCancelList(f->CancelList);
361 f->CancelList = NULL;
362 }
363 }
364 }
365
366 // Send the waiting IP packets whose destination MAC address has been resolved
L3SendWaitingIp(L3IF * f,UCHAR * mac,UINT ip,L3ARPENTRY * a)367 void L3SendWaitingIp(L3IF *f, UCHAR *mac, UINT ip, L3ARPENTRY *a)
368 {
369 UINT i;
370 LIST *o = NULL;
371 // Validate arguments
372 if (f == NULL || mac == NULL || a == NULL)
373 {
374 return;
375 }
376
377 for (i = 0;i < LIST_NUM(f->IpWaitList);i++)
378 {
379 L3PACKET *p = LIST_DATA(f->IpWaitList, i);
380
381 if (p->NextHopIp == ip)
382 {
383 if (o == NULL)
384 {
385 o = NewListFast(NULL);
386 }
387 Add(o, p);
388 }
389 }
390
391 if (o != NULL)
392 {
393 for (i = 0;i < LIST_NUM(o);i++)
394 {
395 L3PACKET *p = LIST_DATA(o, i);
396
397 // Transmission
398 L3SendIpNow(f, a, p);
399
400 Delete(f->IpWaitList, p);
401 Free(p->Packet->PacketData);
402 FreePacket(p->Packet);
403 Free(p);
404 }
405
406 ReleaseList(o);
407 }
408 }
409
410 // Register in the ARP table
L3InsertArpTable(L3IF * f,UINT ip,UCHAR * mac)411 void L3InsertArpTable(L3IF *f, UINT ip, UCHAR *mac)
412 {
413 L3ARPENTRY *a, t;
414 // Validate arguments
415 if (f == NULL || ip == 0 || ip == 0xffffffff || mac == NULL)
416 {
417 return;
418 }
419
420 Zero(&t, sizeof(t));
421 t.IpAddress = ip;
422
423 a = Search(f->ArpTable, &t);
424
425 if (a == NULL)
426 {
427 // Since this is not registered, register this
428 a = ZeroMalloc(sizeof(L3ARPENTRY));
429 a->IpAddress = ip;
430 Copy(a->MacAddress, mac, 6);
431 Insert(f->ArpTable, a);
432 }
433
434 // Extend the expiration date
435 a->Expire = Tick64() + ARP_ENTRY_EXPIRES;
436
437 // Send waiting IP packets
438 L3SendWaitingIp(f, mac, ip, a);
439 }
440
441 // Function to be called when the ARP resolved
L3KnownArp(L3IF * f,UINT ip,UCHAR * mac)442 void L3KnownArp(L3IF *f, UINT ip, UCHAR *mac)
443 {
444 L3ARPWAIT t, *w;
445 // Validate arguments
446 if (f == NULL || ip == 0 || ip == 0xffffffff || mac == NULL)
447 {
448 return;
449 }
450
451 if (!((f->IpAddress & f->SubnetMask) == (ip & f->SubnetMask)))
452 {
453 // Outside the subnet
454 return;
455 }
456
457 // Delete an ARP query entry to this IP address
458 Zero(&t, sizeof(t));
459 t.IpAddress = ip;
460 w = Search(f->IpWaitList, &t);
461 if (w != NULL)
462 {
463 Delete(f->IpWaitList, w);
464 Free(w);
465 }
466
467 // Register in the ARP table
468 L3InsertArpTable(f, ip, mac);
469 }
470
471 // Issue an ARP query
L3SendArp(L3IF * f,UINT ip)472 void L3SendArp(L3IF *f, UINT ip)
473 {
474 L3ARPWAIT t, *w;
475 // Validate arguments
476 if (f == NULL || ip == 0 || ip == 0xffffffff)
477 {
478 return;
479 }
480
481 // Examine whether it has not already registered
482 Zero(&t, sizeof(t));
483 t.IpAddress = ip;
484 w = Search(f->ArpWaitTable, &t);
485
486 if (w != NULL)
487 {
488 // Do not do anything because it is already registered in the waiting list
489 return;
490 }
491 else
492 {
493 // Register in the waiting list newly
494 w = ZeroMalloc(sizeof(L3ARPWAIT));
495 w->Expire = Tick64() + ARP_REQUEST_GIVEUP;
496 w->IpAddress = ip;
497 Insert(f->ArpWaitTable, w);
498 }
499 }
500
501 // Received an ARP request
L3RecvArpRequest(L3IF * f,PKT * p)502 void L3RecvArpRequest(L3IF *f, PKT *p)
503 {
504 ARPV4_HEADER *a;
505 // Validate arguments
506 if (f == NULL || p == NULL)
507 {
508 return;
509 }
510
511 a = p->L3.ARPv4Header;
512
513 L3KnownArp(f, a->SrcIP, a->SrcAddress);
514
515 if (a->TargetIP == f->IpAddress)
516 {
517 // Respond only if the ARP packet addressed to myself
518 L3SendArpResponseNow(f, a->SrcAddress, a->SrcIP, f->IpAddress);
519 }
520 }
521
522 // Received an ARP response
L3RecvArpResponse(L3IF * f,PKT * p)523 void L3RecvArpResponse(L3IF *f, PKT *p)
524 {
525 ARPV4_HEADER *a;
526 // Validate arguments
527 if (f == NULL || p == NULL)
528 {
529 return;
530 }
531
532 a = p->L3.ARPv4Header;
533
534 L3KnownArp(f, a->SrcIP, a->SrcAddress);
535 }
536
537 // Received an ARP packet
L3RecvArp(L3IF * f,PKT * p)538 void L3RecvArp(L3IF *f, PKT *p)
539 {
540 ARPV4_HEADER *a;
541 // Validate arguments
542 if (f == NULL || p == NULL)
543 {
544 return;
545 }
546
547 a = p->L3.ARPv4Header;
548
549 if (Endian16(a->HardwareType) != ARP_HARDWARE_TYPE_ETHERNET ||
550 Endian16(a->ProtocolType) != MAC_PROTO_IPV4 ||
551 a->HardwareSize != 6 || a->ProtocolSize != 4)
552 {
553 return;
554 }
555 if (Cmp(a->SrcAddress, p->MacAddressSrc, 6) != 0)
556 {
557 return;
558 }
559
560 switch (Endian16(a->Operation))
561 {
562 case ARP_OPERATION_REQUEST:
563 // ARP request arrives
564 L3RecvArpRequest(f, p);
565 break;
566
567 case ARP_OPERATION_RESPONSE:
568 // ARP response arrives
569 L3RecvArpResponse(f, p);
570 break;
571 }
572 }
573
574 // Send an IP packet
L3SendIp(L3IF * f,L3PACKET * p)575 void L3SendIp(L3IF *f, L3PACKET *p)
576 {
577 L3ARPENTRY *a = NULL;
578 bool broadcast = false;
579 IPV4_HEADER *ip;
580 bool for_me = false;
581 // Validate arguments
582 if (f == NULL || p == NULL)
583 {
584 return;
585 }
586 if (p->Packet->TypeL3 != L3_IPV4)
587 {
588 return;
589 }
590
591 ip = p->Packet->L3.IPv4Header;
592
593 // Determining whether it's a broadcast
594 if (p->NextHopIp == 0xffffffff ||
595 ((p->NextHopIp & f->SubnetMask) == (f->IpAddress & f->SubnetMask)) &&
596 ((p->NextHopIp & (~f->SubnetMask)) == (~f->SubnetMask)))
597 {
598 broadcast = true;
599 }
600
601 if (broadcast == false && ip->DstIP == f->IpAddress)
602 {
603 // me?
604 }
605 else if (broadcast == false)
606 {
607 // Examine whether the ARP entry contains this in the case of unicast
608 a = L3SearchArpTable(f, p->NextHopIp);
609
610 if (a == NULL)
611 {
612 // Since It is not in the ARP table,
613 // insert it into the IP waiting list without sending immediately
614 p->Expire = Tick64() + IP_WAIT_FOR_ARP_TIMEOUT;
615
616 Insert(f->IpWaitList, p);
617
618 // Issue an ARP query
619 L3SendArp(f, p->NextHopIp);
620 return;
621 }
622 }
623
624 if (for_me == false)
625 {
626 // Send the IP packet
627 L3SendIpNow(f, a, p);
628 }
629
630 // Release the packet
631 Free(p->Packet->PacketData);
632 FreePacket(p->Packet);
633 Free(p);
634 }
635
636 // Send the IP packet immediately
L3SendIpNow(L3IF * f,L3ARPENTRY * a,L3PACKET * p)637 void L3SendIpNow(L3IF *f, L3ARPENTRY *a, L3PACKET *p)
638 {
639 // Validate arguments
640 if (f == NULL || p == NULL)
641 {
642 return;
643 }
644
645 L3SendL2Now(f, a != NULL ? a->MacAddress : broadcast, f->MacAddress, Endian16(p->Packet->MacHeader->Protocol),
646 p->Packet->L3.PointerL3, p->Packet->PacketSize - sizeof(MAC_HEADER));
647 }
648
649 // Search in the ARP table
L3SearchArpTable(L3IF * f,UINT ip)650 L3ARPENTRY *L3SearchArpTable(L3IF *f, UINT ip)
651 {
652 L3ARPENTRY *e, t;
653 // Validate arguments
654 if (f == NULL || ip == 0 || ip == 0xffffffff)
655 {
656 return NULL;
657 }
658
659 Zero(&t, sizeof(t));
660 t.IpAddress = ip;
661
662 e = Search(f->ArpTable, &t);
663
664 return e;
665 }
666
667 // Send an ARP request packet
L3SendArpRequestNow(L3IF * f,UINT dest_ip)668 void L3SendArpRequestNow(L3IF *f, UINT dest_ip)
669 {
670 ARPV4_HEADER arp;
671 // Validate arguments
672 if (f == NULL)
673 {
674 return;
675 }
676
677 // Build an ARP header
678 arp.HardwareType = Endian16(ARP_HARDWARE_TYPE_ETHERNET);
679 arp.ProtocolType = Endian16(MAC_PROTO_IPV4);
680 arp.HardwareSize = 6;
681 arp.ProtocolSize = 4;
682 arp.Operation = Endian16(ARP_OPERATION_REQUEST);
683 Copy(arp.SrcAddress, f->MacAddress, 6);
684 arp.SrcIP = f->IpAddress;
685 Zero(&arp.TargetAddress, 6);
686 arp.TargetIP = dest_ip;
687
688 // Transmission
689 L3SendL2Now(f, broadcast, f->MacAddress, MAC_PROTO_ARPV4, &arp, sizeof(arp));
690 }
691
692 // Send an ARP response packet
L3SendArpResponseNow(L3IF * f,UCHAR * dest_mac,UINT dest_ip,UINT src_ip)693 void L3SendArpResponseNow(L3IF *f, UCHAR *dest_mac, UINT dest_ip, UINT src_ip)
694 {
695 ARPV4_HEADER arp;
696 // Validate arguments
697 if (f == NULL || dest_mac == NULL)
698 {
699 return;
700 }
701
702 // Build a header
703 arp.HardwareType = Endian16(ARP_HARDWARE_TYPE_ETHERNET);
704 arp.ProtocolType = Endian16(MAC_PROTO_IPV4);
705 arp.HardwareSize = 6;
706 arp.ProtocolSize = 4;
707 arp.Operation = Endian16(ARP_OPERATION_RESPONSE);
708 Copy(arp.SrcAddress, f->MacAddress, 6);
709 Copy(arp.TargetAddress, dest_mac, 6);
710 arp.SrcIP = src_ip;
711 arp.TargetIP = dest_ip;
712
713 // Transmission
714 L3SendL2Now(f, dest_mac, f->MacAddress, MAC_PROTO_ARPV4, &arp, sizeof(arp));
715 }
716
717 // Generate a MAC address of the interface
L3GenerateMacAddress(L3IF * f)718 void L3GenerateMacAddress(L3IF *f)
719 {
720 BUF *b;
721 UCHAR hash[SHA1_SIZE];
722 // Validate arguments
723 if (f == NULL)
724 {
725 return;
726 }
727
728 b = NewBuf();
729 WriteBuf(b, f->Switch->Name, StrLen(f->Switch->Name));
730 WriteBuf(b, f->HubName, StrLen(f->HubName));
731 WriteBuf(b, &f->IpAddress, sizeof(f->IpAddress));
732
733 GenMacAddress(f->MacAddress);
734 Sha0(hash, b->Buf, b->Size);
735 Copy(f->MacAddress + 2, hash, 4);
736 f->MacAddress[1] = 0xA3;
737 FreeBuf(b);
738 }
739
740 // Send an L2 packet immediately
L3SendL2Now(L3IF * f,UCHAR * dest_mac,UCHAR * src_mac,USHORT protocol,void * data,UINT size)741 void L3SendL2Now(L3IF *f, UCHAR *dest_mac, UCHAR *src_mac, USHORT protocol, void *data, UINT size)
742 {
743 UCHAR *buf;
744 MAC_HEADER *mac_header;
745 PKT *p;
746 // Validate arguments
747 if (f == NULL || dest_mac == NULL || src_mac == NULL || data == NULL)
748 {
749 return;
750 }
751
752 // Buffer creation
753 buf = Malloc(MAC_HEADER_SIZE + size);
754
755 // MAC header
756 mac_header = (MAC_HEADER *)&buf[0];
757 Copy(mac_header->DestAddress, dest_mac, 6);
758 Copy(mac_header->SrcAddress, src_mac, 6);
759 mac_header->Protocol = Endian16(protocol);
760
761 // Copy data
762 Copy(&buf[sizeof(MAC_HEADER)], data, size);
763
764 // Size
765 size += sizeof(MAC_HEADER);
766
767 // Packet generation
768 p = ZeroMalloc(sizeof(PKT));
769 p->PacketData = buf;
770 p->PacketSize = size;
771
772 // Add to the queue
773 InsertQueue(f->SendQueue, p);
774 }
775
776 // Polling for the ARP resolution waiting list
L3PollingArpWaitTable(L3IF * f)777 void L3PollingArpWaitTable(L3IF *f)
778 {
779 UINT i;
780 LIST *o = NULL;
781 // Validate arguments
782 if (f == NULL)
783 {
784 return;
785 }
786
787 for (i = 0;i < LIST_NUM(f->ArpWaitTable);i++)
788 {
789 L3ARPWAIT *w = LIST_DATA(f->ArpWaitTable, i);
790
791 if (w->Expire <= Tick64())
792 {
793 // The ARP request entry is expired
794 if (o == NULL)
795 {
796 o = NewListFast(NULL);
797 }
798
799 Insert(o, w);
800 }
801 else if ((w->LastSentTime + ARP_REQUEST_TIMEOUT) <= Tick64())
802 {
803 // Send a next ARP request packet
804 w->LastSentTime = Tick64();
805
806 L3SendArpRequestNow(f, w->IpAddress);
807 }
808 }
809
810 if (o != NULL)
811 {
812 for (i = 0;i < LIST_NUM(o);i++)
813 {
814 L3ARPWAIT *w = LIST_DATA(o, i);
815
816 Delete(f->ArpWaitTable, w);
817 Free(w);
818 }
819
820 ReleaseList(o);
821 }
822 }
823
824 // Clear old ARP table entries
L3DeleteOldArpTable(L3IF * f)825 void L3DeleteOldArpTable(L3IF *f)
826 {
827 UINT i;
828 LIST *o = NULL;
829 // Validate arguments
830 if (f == NULL)
831 {
832 return;
833 }
834
835 if ((f->LastDeleteOldArpTable + ARP_ENTRY_POLLING_TIME) > Tick64())
836 {
837 return;
838 }
839 f->LastDeleteOldArpTable = Tick64();
840
841 for (i = 0;i < LIST_NUM(f->ArpTable);i++)
842 {
843 L3ARPENTRY *a = LIST_DATA(f->ArpTable, i);
844
845 if (a->Expire <= Tick64())
846 {
847 // Expired
848 if (o == NULL)
849 {
850 o = NewListFast(NULL);
851 }
852
853 Insert(o, a);
854 }
855 }
856
857 if (o != NULL)
858 {
859 for (i = 0;i < LIST_NUM(o);i++)
860 {
861 L3ARPENTRY *a = LIST_DATA(o, i);
862
863 Delete(f->ArpTable, a);
864 Free(a);
865 }
866
867 ReleaseList(o);
868 }
869 }
870
871 // Clear the IP waiting list
L3DeleteOldIpWaitList(L3IF * f)872 void L3DeleteOldIpWaitList(L3IF *f)
873 {
874 UINT i;
875 LIST *o = NULL;
876 // Validate arguments
877 if (f == NULL)
878 {
879 return;
880 }
881
882 for (i = 0;i < LIST_NUM(f->IpWaitList);i++)
883 {
884 L3PACKET *p = LIST_DATA(f->IpWaitList, i);
885
886 if (p->Expire <= Tick64())
887 {
888 if (o == NULL)
889 {
890 o = NewListFast(NULL);
891 }
892
893 Insert(o, p);
894 }
895 }
896
897 if (o != NULL)
898 {
899 for (i = 0;i < LIST_NUM(o);i++)
900 {
901 L3PACKET *p = LIST_DATA(o, i);
902
903 Delete(f->IpWaitList, p);
904
905 Free(p->Packet->PacketData);
906 FreePacket(p->Packet);
907 Free(p);
908 }
909
910 ReleaseList(o);
911 }
912 }
913
914 // Beacon transmission
L3PollingBeacon(L3IF * f)915 void L3PollingBeacon(L3IF *f)
916 {
917 // Validate arguments
918 if (f == NULL)
919 {
920 return;
921 }
922
923 if (f->LastBeaconSent == 0 ||
924 (f->LastBeaconSent + BEACON_SEND_INTERVAL) <= Tick64())
925 {
926 UINT dest_ip;
927 UCHAR *udp_buf;
928 UINT udp_buf_size;
929 ARPV4_HEADER arp;
930 IPV4_HEADER *ip;
931 UDP_HEADER *udp;
932 static char beacon_str[] =
933 "PacketiX VPN Virtual Layer-3 Switch Beacon";
934
935 // Send an UDP
936 dest_ip = (f->IpAddress & f->SubnetMask) | (~f->SubnetMask);
937 udp_buf_size = sizeof(IPV4_HEADER) + sizeof(UDP_HEADER) + sizeof(beacon_str);
938 udp_buf = ZeroMalloc(udp_buf_size);
939
940 ip = (IPV4_HEADER *)udp_buf;
941 udp = (UDP_HEADER *)(udp_buf + sizeof(IPV4_HEADER));
942 udp->DstPort = Endian16(7);
943 udp->SrcPort = Endian16(7);
944 udp->PacketLength = Endian16(sizeof(UDP_HEADER) + sizeof(beacon_str));
945
946 Copy(udp_buf + sizeof(IPV4_HEADER) + sizeof(UDP_HEADER), beacon_str, sizeof(beacon_str));
947
948 udp->Checksum = CalcChecksumForIPv4(f->IpAddress, dest_ip, 0x11, udp, sizeof(UDP_HEADER) + sizeof(beacon_str), 0);
949
950 ip->DstIP = dest_ip;
951 IPV4_SET_VERSION(ip, 4);
952 IPV4_SET_HEADER_LEN(ip, (IP_HEADER_SIZE / 4));
953 ip->TypeOfService = DEFAULT_IP_TOS;
954 ip->TotalLength = Endian16((USHORT)(udp_buf_size));
955 ip->TimeToLive = DEFAULT_IP_TTL;
956 ip->Protocol = IP_PROTO_UDP;
957 ip->SrcIP = f->IpAddress;
958 ip->Checksum = IpChecksum(ip, IP_HEADER_SIZE);
959
960 L3SendL2Now(f, broadcast, f->MacAddress, MAC_PROTO_IPV4, udp_buf, udp_buf_size);
961
962 Free(udp_buf);
963
964 // Build the ARP header
965 arp.HardwareType = Endian16(ARP_HARDWARE_TYPE_ETHERNET);
966 arp.ProtocolType = Endian16(MAC_PROTO_IPV4);
967 arp.HardwareSize = 6;
968 arp.ProtocolSize = 4;
969 arp.Operation = Endian16(ARP_OPERATION_RESPONSE);
970 Copy(arp.SrcAddress, f->MacAddress, 6);
971 arp.SrcIP = f->IpAddress;
972 arp.TargetAddress[0] =
973 arp.TargetAddress[1] =
974 arp.TargetAddress[2] =
975 arp.TargetAddress[3] =
976 arp.TargetAddress[4] =
977 arp.TargetAddress[5] = 0xff;
978 arp.TargetIP = dest_ip;
979
980 // Transmission
981 L3SendL2Now(f, broadcast, f->MacAddress, MAC_PROTO_ARPV4, &arp, sizeof(arp));
982
983 f->LastBeaconSent = Tick64();
984 }
985 }
986
987 // Polling process
L3Polling(L3IF * f)988 void L3Polling(L3IF *f)
989 {
990 L3SW *s;
991 // Validate arguments
992 if (f == NULL)
993 {
994 return;
995 }
996
997 s = f->Switch;
998
999 // Lock the entire switch in the middle of the polling process
1000 Lock(s->lock);
1001 {
1002 // Beacon transmission
1003 L3PollingBeacon(f);
1004
1005 // Process the IP queue
1006 L3PollingIpQueue(f);
1007
1008 // Clear old ARP table entries
1009 L3DeleteOldArpTable(f);
1010
1011 // Polling ARP resolution waiting list
1012 L3PollingArpWaitTable(f);
1013
1014 // Clear the IP waiting list
1015 L3DeleteOldIpWaitList(f);
1016 }
1017 Unlock(s->lock);
1018 }
1019
1020 // Get the next packet
L3GetNextPacket(L3IF * f,void ** data)1021 UINT L3GetNextPacket(L3IF *f, void **data)
1022 {
1023 UINT ret = 0;
1024 // Validate arguments
1025 if (f == NULL || data == NULL)
1026 {
1027 return 0;
1028 }
1029
1030 START:
1031 // Examine the send queue
1032 LockQueue(f->SendQueue);
1033 {
1034 PKT *p = GetNext(f->SendQueue);
1035
1036 if (p != NULL)
1037 {
1038 // There is a packet
1039 ret = p->PacketSize;
1040 *data = p->PacketData;
1041 // Packet structure may be discarded
1042 Free(p);
1043 }
1044 }
1045 UnlockQueue(f->SendQueue);
1046
1047 if (ret == 0)
1048 {
1049 // Polling process
1050 L3Polling(f);
1051
1052 // Examine whether a new packet is queued for results of the polling process
1053 if (f->SendQueue->num_item != 0)
1054 {
1055 // Get the packet immediately if it's in the queue
1056 goto START;
1057 }
1058 }
1059
1060 return ret;
1061 }
1062
1063 // Determine the packet destined for the specified IP address should be sent to which interface
L3GetNextIf(L3SW * s,UINT ip,UINT * next_hop)1064 L3IF *L3GetNextIf(L3SW *s, UINT ip, UINT *next_hop)
1065 {
1066 UINT i;
1067 L3IF *f;
1068 UINT next_hop_ip = 0;
1069 // Validate arguments
1070 if (s == NULL || ip == 0 || ip == 0xffffffff)
1071 {
1072 return NULL;
1073 }
1074
1075 f = NULL;
1076
1077 // Examine whether the specified IP address is contained
1078 // in the networks which each interfaces belong to
1079 for (i = 0;i < LIST_NUM(s->IfList);i++)
1080 {
1081 L3IF *ff = LIST_DATA(s->IfList, i);
1082
1083 if ((ff->IpAddress & ff->SubnetMask) == (ip & ff->SubnetMask))
1084 {
1085 f = ff;
1086 next_hop_ip = ip;
1087 break;
1088 }
1089 }
1090
1091 if (f == NULL)
1092 {
1093 // Find the routing table if it's not found
1094 L3TABLE *t = L3GetBestRoute(s, ip);
1095
1096 if (t == NULL)
1097 {
1098 // Still not found
1099 return NULL;
1100 }
1101 else
1102 {
1103 // Find the interface with the IP address of the router of
1104 // NextHop of the found route
1105 for (i = 0;i < LIST_NUM(s->IfList);i++)
1106 {
1107 L3IF *ff = LIST_DATA(s->IfList, i);
1108
1109 if ((ff->IpAddress & ff->SubnetMask) == (t->GatewayAddress & ff->SubnetMask))
1110 {
1111 f = ff;
1112 next_hop_ip = t->GatewayAddress;
1113 break;
1114 }
1115 }
1116 }
1117 }
1118
1119 if (f == NULL)
1120 {
1121 // Destination interface was unknown after all
1122 return NULL;
1123 }
1124
1125 if (next_hop != NULL)
1126 {
1127 *next_hop = next_hop_ip;
1128 }
1129
1130 return f;
1131 }
1132
1133 // Get the best routing table entry for the specified IP address
L3GetBestRoute(L3SW * s,UINT ip)1134 L3TABLE *L3GetBestRoute(L3SW *s, UINT ip)
1135 {
1136 UINT i;
1137 UINT max_mask = 0;
1138 UINT min_metric = INFINITE;
1139 L3TABLE *ret = NULL;
1140 // Validate arguments
1141 if (s == NULL || ip == 0)
1142 {
1143 return NULL;
1144 }
1145
1146 // 1st condition: Choose the one which have the largest subnet mask
1147 // 2nd condition: Choose the one which have the smallest metric
1148 for (i = 0;i < LIST_NUM(s->TableList);i++)
1149 {
1150 L3TABLE *t = LIST_DATA(s->TableList, i);
1151
1152 if ((t->NetworkAddress & t->SubnetMask) == (ip & t->SubnetMask))
1153 {
1154 if (t->SubnetMask >= max_mask)
1155 {
1156 max_mask = t->SubnetMask;
1157 if (min_metric >= t->Metric)
1158 {
1159 min_metric = t->Metric;
1160 ret = t;
1161 }
1162 }
1163 }
1164 }
1165
1166 return ret;
1167 }
1168
1169 // Initialize the Layer-3 interface
L3InitInterface(L3IF * f)1170 void L3InitInterface(L3IF *f)
1171 {
1172 // Validate arguments
1173 if (f == NULL)
1174 {
1175 return;
1176 }
1177
1178 // MAC address generation
1179 L3GenerateMacAddress(f);
1180
1181 // List generation
1182 f->ArpTable = NewList(CmpL3ArpEntry);
1183 f->ArpWaitTable = NewList(CmpL3ArpWaitTable);
1184 f->IpPacketQueue = NewQueue();
1185 f->IpWaitList = NewList(NULL);
1186 f->SendQueue = NewQueue();
1187 }
1188
1189 // Release the Layer-3 interface
L3FreeInterface(L3IF * f)1190 void L3FreeInterface(L3IF *f)
1191 {
1192 UINT i;
1193 L3PACKET *p;
1194 PKT *pkt;
1195 // Validate arguments
1196 if (f == NULL)
1197 {
1198 return;
1199 }
1200
1201 for (i = 0;i < LIST_NUM(f->ArpTable);i++)
1202 {
1203 L3ARPENTRY *a = LIST_DATA(f->ArpTable, i);
1204 Free(a);
1205 }
1206 ReleaseList(f->ArpTable);
1207 f->ArpTable = NULL;
1208
1209 for (i = 0;i < LIST_NUM(f->ArpWaitTable);i++)
1210 {
1211 L3ARPWAIT *w = LIST_DATA(f->ArpWaitTable, i);
1212 Free(w);
1213 }
1214 ReleaseList(f->ArpWaitTable);
1215 f->ArpWaitTable = NULL;
1216
1217 while (p = GetNext(f->IpPacketQueue))
1218 {
1219 Free(p->Packet->PacketData);
1220 FreePacket(p->Packet);
1221 Free(p);
1222 }
1223 ReleaseQueue(f->IpPacketQueue);
1224 f->IpPacketQueue = NULL;
1225
1226 for (i = 0;i < LIST_NUM(f->IpWaitList);i++)
1227 {
1228 L3PACKET *p = LIST_DATA(f->IpWaitList, i);
1229 Free(p->Packet->PacketData);
1230 FreePacket(p->Packet);
1231 Free(p);
1232 }
1233 ReleaseList(f->IpWaitList);
1234 f->IpWaitList = NULL;
1235
1236 while (pkt = GetNext(f->SendQueue))
1237 {
1238 Free(pkt->PacketData);
1239 FreePacket(pkt);
1240 }
1241 ReleaseQueue(f->SendQueue);
1242 f->SendQueue = NULL;
1243 }
1244
1245 // Layer-3 interface thread
L3IfThread(THREAD * t,void * param)1246 void L3IfThread(THREAD *t, void *param)
1247 {
1248 L3IF *f;
1249 CONNECTION *c;
1250 SESSION *s;
1251 POLICY *policy;
1252 char tmp[MAX_SIZE];
1253 char name[MAX_SIZE];
1254 char username[MAX_SIZE];
1255 // Validate arguments
1256 if (t == NULL || param == NULL)
1257 {
1258 return;
1259 }
1260
1261 f = (L3IF *)param;
1262
1263 StrCpy(username, sizeof(username), L3_USERNAME);
1264 if (f->Switch != NULL)
1265 {
1266 StrCat(username, sizeof(username), f->Switch->Name);
1267 }
1268
1269 // Create a connection
1270 c = NewServerConnection(f->Switch->Cedar, NULL, t);
1271 c->Protocol = CONNECTION_HUB_LAYER3;
1272
1273 // Create a Session
1274 policy = ClonePolicy(GetDefaultPolicy());
1275 // Not to limit the number of broadcast by policy
1276 policy->NoBroadcastLimiter = true;
1277 s = NewServerSession(f->Switch->Cedar, c, f->Hub, username, policy);
1278 c->Session = s;
1279
1280 ReleaseConnection(c);
1281
1282 // Determine the name of the session
1283 GetMachineHostName(tmp, sizeof(tmp));
1284 if (f->Switch->Cedar->Server->ServerType == SERVER_TYPE_STANDALONE)
1285 {
1286 Format(name, sizeof(name), "SID-L3-%s-%u", f->Switch->Name, Inc(f->Hub->SessionCounter));
1287 }
1288 else
1289 {
1290 Format(name, sizeof(name), "SID-L3-%s-%s-%u", tmp, f->Switch->Name, Inc(f->Hub->SessionCounter));
1291 }
1292 ConvertSafeFileName(name, sizeof(name), name);
1293 StrUpper(name);
1294
1295 Free(s->Name);
1296 s->Name = CopyStr(name);
1297
1298 s->L3SwitchMode = true;
1299 s->L3If = f;
1300
1301 if (s->Username != NULL)
1302 {
1303 Free(s->Username);
1304 }
1305 s->Username = CopyStr(username);
1306
1307 StrCpy(s->UserNameReal, sizeof(s->UserNameReal), username);
1308
1309 f->Session = s;
1310 AddRef(s->ref);
1311
1312 // Notify the initialization completion
1313 NoticeThreadInit(t);
1314
1315 // Session main process
1316 SessionMain(s);
1317
1318 // Release the session
1319 ReleaseSession(s);
1320 }
1321
1322 // Initialize all Layer-3 interfaces
L3InitAllInterfaces(L3SW * s)1323 void L3InitAllInterfaces(L3SW *s)
1324 {
1325 UINT i;
1326 // Validate arguments
1327 if (s == NULL)
1328 {
1329 return;
1330 }
1331
1332 for (i = 0;i < LIST_NUM(s->IfList);i++)
1333 {
1334 L3IF *f = LIST_DATA(s->IfList, i);
1335 THREAD *t;
1336
1337 L3InitInterface(f);
1338
1339 f->Hub = GetHub(s->Cedar, f->HubName);
1340 t = NewThread(L3IfThread, f);
1341 WaitThreadInit(t);
1342 ReleaseThread(t);
1343 }
1344 }
1345
1346 // Release all Layer-3 interfaces
L3FreeAllInterfaces(L3SW * s)1347 void L3FreeAllInterfaces(L3SW *s)
1348 {
1349 UINT i;
1350 // Validate arguments
1351 if (s == NULL)
1352 {
1353 return;
1354 }
1355
1356 for (i = 0;i < LIST_NUM(s->IfList);i++)
1357 {
1358 L3IF *f = LIST_DATA(s->IfList, i);
1359
1360 ReleaseHub(f->Hub);
1361 f->Hub = NULL;
1362 ReleaseSession(f->Session);
1363 f->Session = NULL;
1364
1365 L3FreeInterface(f);
1366 }
1367 }
1368
1369 // Layer-3 test
L3Test(SERVER * s)1370 void L3Test(SERVER *s)
1371 {
1372 L3SW *ss = L3AddSw(s->Cedar, "TEST");
1373 L3AddIf(ss, "DEFAULT", 0x0101a8c0, 0x00ffffff);
1374 L3AddIf(ss, "DEFAULT2", 0x0102a8c0, 0x00ffffff);
1375 L3SwStart(ss);
1376 ReleaseL3Sw(ss);
1377 }
1378
1379 // Layer-3 switch thread
L3SwThread(THREAD * t,void * param)1380 void L3SwThread(THREAD *t, void *param)
1381 {
1382 L3SW *s;
1383 bool shutdown_now = false;
1384 // Validate arguments
1385 if (t == NULL || param == NULL)
1386 {
1387 return;
1388 }
1389
1390 s = (L3SW *)param;
1391
1392 s->Active = true;
1393
1394 NoticeThreadInit(t);
1395
1396 // Operation start
1397 SLog(s->Cedar, "L3_SWITCH_START", s->Name);
1398
1399 while (s->Halt == false)
1400 {
1401 if (s->Online == false)
1402 {
1403 // Because the L3 switch is off-line now,
1404 // attempt to make it on-line periodically
1405 LockList(s->Cedar->HubList);
1406 {
1407 Lock(s->lock);
1408 {
1409 UINT i;
1410 UINT n = 0;
1411 bool all_exists = true;
1412 if (LIST_NUM(s->IfList) == 0)
1413 {
1414 // Don't operate if there is no interface
1415 all_exists = false;
1416 }
1417 for (i = 0;i < LIST_NUM(s->IfList);i++)
1418 {
1419 L3IF *f = LIST_DATA(s->IfList, i);
1420 HUB *h = GetHub(s->Cedar, f->HubName);
1421
1422 if (h != NULL)
1423 {
1424 if (h->Offline || h->Type == HUB_TYPE_FARM_DYNAMIC)
1425 {
1426 all_exists = false;
1427 }
1428 else
1429 {
1430 n++;
1431 }
1432 ReleaseHub(h);
1433 }
1434 else
1435 {
1436 all_exists = false;
1437 }
1438 }
1439
1440 if (all_exists && n >= 1)
1441 {
1442 // Start the operation because all Virtual HUBs for
1443 // interfaces are enabled
1444 SLog(s->Cedar, "L3_SWITCH_ONLINE", s->Name);
1445 L3InitAllInterfaces(s);
1446 s->Online = true;
1447 }
1448 }
1449 Unlock(s->lock);
1450 }
1451 UnlockList(s->Cedar->HubList);
1452 }
1453 else
1454 {
1455 // Examine periodically whether all sessions terminated
1456 UINT i;
1457 bool any_halted = false;
1458 LIST *o = NULL;
1459
1460 SHUTDOWN:
1461
1462 Lock(s->lock);
1463 {
1464 for (i = 0;i < LIST_NUM(s->IfList);i++)
1465 {
1466 L3IF *f = LIST_DATA(s->IfList, i);
1467 if (f->Session->Halt || f->Hub->Offline != false)
1468 {
1469 any_halted = true;
1470 break;
1471 }
1472 }
1473
1474 if (shutdown_now)
1475 {
1476 any_halted = true;
1477 }
1478
1479 if (any_halted)
1480 {
1481 SLog(s->Cedar, "L3_SWITCH_OFFLINE", s->Name);
1482 o = NewListFast(NULL);
1483 // If there is any terminated session, terminate all sessions
1484 for (i = 0;i < LIST_NUM(s->IfList);i++)
1485 {
1486 L3IF *f = LIST_DATA(s->IfList, i);
1487 Insert(o, f->Session);
1488 }
1489
1490 // Restore to the offline
1491 s->Online = false;
1492 }
1493 }
1494 Unlock(s->lock);
1495
1496 if (o != NULL)
1497 {
1498 UINT i;
1499 for (i = 0;i < LIST_NUM(o);i++)
1500 {
1501 SESSION *s = LIST_DATA(o, i);
1502 StopSession(s);
1503 }
1504 L3FreeAllInterfaces(s);
1505 ReleaseList(o);
1506 o = NULL;
1507 }
1508 }
1509
1510 SleepThread(50);
1511 }
1512
1513 if (s->Online != false)
1514 {
1515 shutdown_now = true;
1516 goto SHUTDOWN;
1517 }
1518
1519 // Stop the operation
1520 SLog(s->Cedar, "L3_SWITCH_STOP", s->Name);
1521 }
1522
1523 // Start a Layer-3 switch
L3SwStart(L3SW * s)1524 void L3SwStart(L3SW *s)
1525 {
1526 // Validate arguments
1527 if (s == NULL)
1528 {
1529 return;
1530 }
1531
1532 Lock(s->lock);
1533 {
1534 if (s->Active == false)
1535 {
1536 // Start if there is registered interface
1537 if (LIST_NUM(s->IfList) >= 1)
1538 {
1539 s->Halt = false;
1540
1541 // Create a thread
1542 s->Thread = NewThread(L3SwThread, s);
1543 WaitThreadInit(s->Thread);
1544 }
1545 }
1546 }
1547 Unlock(s->lock);
1548 }
1549
1550 // Stop the Layer-3 switch
L3SwStop(L3SW * s)1551 void L3SwStop(L3SW *s)
1552 {
1553 THREAD *t = NULL;
1554 // Validate arguments
1555 if (s == NULL)
1556 {
1557 return;
1558 }
1559
1560 Lock(s->lock);
1561 {
1562 if (s->Active == false)
1563 {
1564 Unlock(s->lock);
1565 return;
1566 }
1567
1568 s->Halt = true;
1569
1570 t = s->Thread;
1571
1572 s->Active = false;
1573 }
1574 Unlock(s->lock);
1575
1576 WaitThread(t, INFINITE);
1577 ReleaseThread(t);
1578 }
1579
1580 // Add a Layer-3 switch
L3AddSw(CEDAR * c,char * name)1581 L3SW *L3AddSw(CEDAR *c, char *name)
1582 {
1583 L3SW *s = NULL;
1584 // Validate arguments
1585 if (c == NULL || name == NULL)
1586 {
1587 return NULL;
1588 }
1589
1590 LockList(c->L3SwList);
1591 {
1592 s = L3GetSw(c, name);
1593
1594 if (s == NULL)
1595 {
1596 s = NewL3Sw(c, name);
1597
1598 Insert(c->L3SwList, s);
1599
1600 AddRef(s->ref);
1601 }
1602 else
1603 {
1604 ReleaseL3Sw(s);
1605 s = NULL;
1606 }
1607 }
1608 UnlockList(c->L3SwList);
1609
1610 return s;
1611 }
1612
1613 // Delete the Layer-3 switch
L3DelSw(CEDAR * c,char * name)1614 bool L3DelSw(CEDAR *c, char *name)
1615 {
1616 L3SW *s;
1617 bool ret = false;
1618 // Validate arguments
1619 if (c == NULL || name == NULL)
1620 {
1621 return false;
1622 }
1623
1624 LockList(c->L3SwList);
1625 {
1626 s = L3GetSw(c, name);
1627
1628 if (s != NULL)
1629 {
1630 // Stop and delete
1631 L3SwStop(s);
1632 Delete(c->L3SwList, s);
1633 ReleaseL3Sw(s);
1634 ReleaseL3Sw(s);
1635
1636 ret = true;
1637 }
1638 }
1639 UnlockList(c->L3SwList);
1640
1641 return ret;
1642 }
1643
1644
1645 // Delete the routing table
L3DelTable(L3SW * s,L3TABLE * tbl)1646 bool L3DelTable(L3SW *s, L3TABLE *tbl)
1647 {
1648 bool ret = false;
1649 // Validate arguments
1650 if (s == NULL || tbl == NULL)
1651 {
1652 return false;
1653 }
1654
1655 Lock(s->lock);
1656 {
1657 if (s->Active == false)
1658 {
1659 L3TABLE *t = Search(s->TableList, tbl);
1660
1661 if (t != NULL)
1662 {
1663 Delete(s->TableList, t);
1664 Free(t);
1665
1666 ret = true;
1667 }
1668 }
1669 }
1670 Unlock(s->lock);
1671
1672 return ret;
1673 }
1674
1675 // Add to the routing table
L3AddTable(L3SW * s,L3TABLE * tbl)1676 bool L3AddTable(L3SW *s, L3TABLE *tbl)
1677 {
1678 bool ret = false;
1679 // Validate arguments
1680 if (s == NULL || tbl == NULL)
1681 {
1682 return false;
1683 }
1684
1685 if (tbl->Metric == 0 || tbl->GatewayAddress == 0 || tbl->GatewayAddress == 0xffffffff)
1686 {
1687 return false;
1688 }
1689
1690 Lock(s->lock);
1691 {
1692 if (LIST_NUM(s->TableList) >= GetServerCapsInt(s->Cedar->Server, "i_max_l3_table"))
1693 {
1694 // Too many
1695 }
1696 else
1697 {
1698 // Create
1699 if (s->Active == false)
1700 {
1701 if (Search(s->TableList, tbl) == NULL)
1702 {
1703 L3TABLE *t = ZeroMalloc(sizeof(L3TABLE));
1704
1705 Copy(t, tbl, sizeof(L3TABLE));
1706
1707 Insert(s->TableList, t);
1708
1709 ret = true;
1710 }
1711 }
1712 }
1713 }
1714 Unlock(s->lock);
1715
1716 return ret;
1717 }
1718
1719 // Get the L3 switch
L3GetSw(CEDAR * c,char * name)1720 L3SW *L3GetSw(CEDAR *c, char *name)
1721 {
1722 L3SW t, *s;
1723 // Validate arguments
1724 if (c == NULL || name == NULL)
1725 {
1726 return NULL;
1727 }
1728
1729 Zero(&t, sizeof(t));
1730 StrCpy(t.Name, sizeof(t.Name), name);
1731
1732 LockList(c->L3SwList);
1733 {
1734 s = Search(c->L3SwList, &t);
1735 }
1736 UnlockList(c->L3SwList);
1737
1738 if (s != NULL)
1739 {
1740 AddRef(s->ref);
1741 }
1742
1743 return s;
1744 }
1745
1746 // Get the interface that is connected to the specified Virtual HUB from the L3 switch
L3SearchIf(L3SW * s,char * hubname)1747 L3IF *L3SearchIf(L3SW *s, char *hubname)
1748 {
1749 L3IF t, *f;
1750 // Validate arguments
1751 if (s == NULL || hubname == NULL)
1752 {
1753 return NULL;
1754 }
1755
1756 Zero(&t, sizeof(t));
1757 StrCpy(t.HubName, sizeof(t.HubName), hubname);
1758
1759 f = Search(s->IfList, &t);
1760
1761 return f;
1762 }
1763
1764 // Delete the interface
L3DelIf(L3SW * s,char * hubname)1765 bool L3DelIf(L3SW *s, char *hubname)
1766 {
1767 L3IF *f;
1768 bool ret = false;
1769 // Validate arguments
1770 if (s == NULL || hubname == NULL)
1771 {
1772 return false;
1773 }
1774
1775 Lock(s->lock);
1776 {
1777 if (s->Active == false)
1778 {
1779 f = L3SearchIf(s, hubname);
1780
1781 if (f != NULL)
1782 {
1783 // Remove
1784 Delete(s->IfList, f);
1785 Free(f);
1786
1787 ret = true;
1788 }
1789 }
1790 }
1791 Unlock(s->lock);
1792
1793 return ret;
1794 }
1795
1796 // Add an interface
L3AddIf(L3SW * s,char * hubname,UINT ip,UINT subnet)1797 bool L3AddIf(L3SW *s, char *hubname, UINT ip, UINT subnet)
1798 {
1799 L3IF *f;
1800 bool ret = false;
1801 // Validate arguments
1802 if (s == NULL || hubname == NULL || IsSafeStr(hubname) == false ||
1803 ip == 0 || ip == 0xffffffff)
1804 {
1805 return false;
1806 }
1807
1808 Lock(s->lock);
1809 {
1810 if (LIST_NUM(s->TableList) >= GetServerCapsInt(s->Cedar->Server, "i_max_l3_if"))
1811 {
1812 // Too many
1813 }
1814 else
1815 {
1816 if (s->Active == false)
1817 {
1818 // Examine whether the interface is already in the same Virtual HUB
1819 if (L3SearchIf(s, hubname) == NULL)
1820 {
1821 // Add
1822 f = ZeroMalloc(sizeof(L3IF));
1823
1824 f->Switch = s;
1825 StrCpy(f->HubName, sizeof(f->HubName), hubname);
1826 f->IpAddress = ip;
1827 f->SubnetMask = subnet;
1828
1829 Insert(s->IfList, f);
1830
1831 ret = true;
1832 }
1833 }
1834 }
1835 }
1836 Unlock(s->lock);
1837
1838 return ret;
1839 }
1840
1841 // Clean-up the L3 switch
CleanupL3Sw(L3SW * s)1842 void CleanupL3Sw(L3SW *s)
1843 {
1844 UINT i;
1845 // Validate arguments
1846 if (s == NULL)
1847 {
1848 return;
1849 }
1850
1851 for (i = 0;i < LIST_NUM(s->IfList);i++)
1852 {
1853 L3IF *f = LIST_DATA(s->IfList, i);
1854 Free(f);
1855 }
1856 ReleaseList(s->IfList);
1857
1858 for (i = 0;i < LIST_NUM(s->TableList);i++)
1859 {
1860 L3TABLE *t = LIST_DATA(s->TableList, i);
1861 Free(t);
1862 }
1863 ReleaseList(s->TableList);
1864
1865 DeleteLock(s->lock);
1866 Free(s);
1867 }
1868
1869 // Release the L3 switch
ReleaseL3Sw(L3SW * s)1870 void ReleaseL3Sw(L3SW *s)
1871 {
1872 // Validate arguments
1873 if (s == NULL)
1874 {
1875 return;
1876 }
1877
1878 if (Release(s->ref) == 0)
1879 {
1880 CleanupL3Sw(s);
1881 }
1882 }
1883
1884 // Create a new L3 switch
NewL3Sw(CEDAR * c,char * name)1885 L3SW *NewL3Sw(CEDAR *c, char *name)
1886 {
1887 L3SW *o;
1888 // Validate arguments
1889 if (c == NULL || name == NULL)
1890 {
1891 return NULL;
1892 }
1893
1894 o = ZeroMalloc(sizeof(L3SW));
1895
1896 StrCpy(o->Name, sizeof(o->Name), name);
1897
1898 o->lock = NewLock();
1899 o->ref = NewRef();
1900 o->Cedar = c;
1901 o->Active = false;
1902
1903 o->IfList = NewList(CmpL3If);
1904 o->TableList = NewList(CmpL3Table);
1905
1906 return o;
1907 }
1908
1909 // Stop all L3 switches in the Cedar
L3FreeAllSw(CEDAR * c)1910 void L3FreeAllSw(CEDAR *c)
1911 {
1912 LIST *o;
1913 UINT i;
1914 // Validate arguments
1915 if (c == NULL)
1916 {
1917 return;
1918 }
1919
1920 o = NewListFast(NULL);
1921
1922 LockList(c->L3SwList);
1923 {
1924 for (i = 0;i < LIST_NUM(c->L3SwList);i++)
1925 {
1926 L3SW *s = LIST_DATA(c->L3SwList, i);
1927 Insert(o, CopyStr(s->Name));
1928 }
1929
1930 for (i = 0;i < LIST_NUM(o);i++)
1931 {
1932 char *name = LIST_DATA(o, i);
1933
1934 L3DelSw(c, name);
1935
1936 Free(name);
1937 }
1938
1939 ReleaseList(o);
1940 }
1941 UnlockList(c->L3SwList);
1942 }
1943
1944 // Stop the L3 switch function of the Cedar
FreeCedarLayer3(CEDAR * c)1945 void FreeCedarLayer3(CEDAR *c)
1946 {
1947 // Validate arguments
1948 if (c == NULL)
1949 {
1950 return;
1951 }
1952
1953 ReleaseList(c->L3SwList);
1954 c->L3SwList = NULL;
1955 }
1956
1957 // Start the L3 switch function of the Cedar
InitCedarLayer3(CEDAR * c)1958 void InitCedarLayer3(CEDAR *c)
1959 {
1960 // Validate arguments
1961 if (c == NULL)
1962 {
1963 return;
1964 }
1965
1966 c->L3SwList = NewList(CmpL3Sw);
1967 }
1968
1969 // Interface comparison function
CmpL3If(void * p1,void * p2)1970 int CmpL3If(void *p1, void *p2)
1971 {
1972 L3IF *f1, *f2;
1973 if (p1 == NULL || p2 == NULL)
1974 {
1975 return 0;
1976 }
1977 f1 = *(L3IF **)p1;
1978 f2 = *(L3IF **)p2;
1979 if (f1 == NULL || f2 == NULL)
1980 {
1981 return 0;
1982 }
1983
1984 return StrCmpi(f1->HubName, f2->HubName);
1985 }
1986
1987 // Routing table entry comparison function
CmpL3Table(void * p1,void * p2)1988 int CmpL3Table(void *p1, void *p2)
1989 {
1990 L3TABLE *t1, *t2;
1991 if (p1 == NULL || p2 == NULL)
1992 {
1993 return 0;
1994 }
1995 t1 = *(L3TABLE **)p1;
1996 t2 = *(L3TABLE **)p2;
1997 if (t1 == NULL || t2 == NULL)
1998 {
1999 return 0;
2000 }
2001
2002 if (t1->NetworkAddress > t2->NetworkAddress)
2003 {
2004 return 1;
2005 }
2006 else if (t1->NetworkAddress < t2->NetworkAddress)
2007 {
2008 return -1;
2009 }
2010 else if (t1->SubnetMask > t2->SubnetMask)
2011 {
2012 return 1;
2013 }
2014 else if (t1->SubnetMask < t2->SubnetMask)
2015 {
2016 return -1;
2017 }
2018 else if (t1->GatewayAddress > t2->GatewayAddress)
2019 {
2020 return 1;
2021 }
2022 else if (t1->GatewayAddress < t2->GatewayAddress)
2023 {
2024 return -1;
2025 }
2026 else if (t1->Metric > t2->Metric)
2027 {
2028 return 1;
2029 }
2030 else if (t1->Metric < t2->Metric)
2031 {
2032 return -1;
2033 }
2034 else
2035 {
2036 return 0;
2037 }
2038 }
2039
2040 // L3SW comparison function
CmpL3Sw(void * p1,void * p2)2041 int CmpL3Sw(void *p1, void *p2)
2042 {
2043 L3SW *s1, *s2;
2044 if (p1 == NULL || p2 == NULL)
2045 {
2046 return 0;
2047 }
2048 s1 = *(L3SW **)p1;
2049 s2 = *(L3SW **)p2;
2050 if (s1 == NULL || s2 == NULL)
2051 {
2052 return 0;
2053 }
2054
2055 return StrCmpi(s1->Name, s2->Name);
2056 }
2057
2058 // ARP waiting entry comparison function
CmpL3ArpWaitTable(void * p1,void * p2)2059 int CmpL3ArpWaitTable(void *p1, void *p2)
2060 {
2061 L3ARPWAIT *w1, *w2;
2062 if (p1 == NULL || p2 == NULL)
2063 {
2064 return 0;
2065 }
2066 w1 = *(L3ARPWAIT **)p1;
2067 w2 = *(L3ARPWAIT **)p2;
2068 if (w1 == NULL || w2 == NULL)
2069 {
2070 return 0;
2071 }
2072 if (w1->IpAddress > w2->IpAddress)
2073 {
2074 return 1;
2075 }
2076 else if (w1->IpAddress < w2->IpAddress)
2077 {
2078 return -1;
2079 }
2080 else
2081 {
2082 return 0;
2083 }
2084 }
2085
2086 // ARP entries comparison function
CmpL3ArpEntry(void * p1,void * p2)2087 int CmpL3ArpEntry(void *p1, void *p2)
2088 {
2089 L3ARPENTRY *e1, *e2;
2090 if (p1 == NULL || p2 == NULL)
2091 {
2092 return 0;
2093 }
2094 e1 = *(L3ARPENTRY **)p1;
2095 e2 = *(L3ARPENTRY **)p2;
2096 if (e1 == NULL || e2 == NULL)
2097 {
2098 return 0;
2099 }
2100 if (e1->IpAddress > e2->IpAddress)
2101 {
2102 return 1;
2103 }
2104 else if (e1->IpAddress < e2->IpAddress)
2105 {
2106 return -1;
2107 }
2108 else
2109 {
2110 return 0;
2111 }
2112 }
2113
2114