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