1 // SoftEther VPN Source Code - Stable Edition Repository
2 // Cedar Communication Module
3 //
4 // SoftEther VPN Server, Client and Bridge are free software under the Apache License, Version 2.0.
5 //
6 // Copyright (c) Daiyuu Nobori.
7 // Copyright (c) SoftEther VPN Project, University of Tsukuba, Japan.
8 // Copyright (c) SoftEther Corporation.
9 // Copyright (c) all contributors on SoftEther VPN project in GitHub.
10 //
11 // All Rights Reserved.
12 //
13 // http://www.softether.org/
14 //
15 // This stable branch is officially managed by Daiyuu Nobori, the owner of SoftEther VPN Project.
16 // Pull requests should be sent to the Developer Edition Master Repository on https://github.com/SoftEtherVPN/SoftEtherVPN
17 // Contributors:
18 // - nattoheaven (https://github.com/nattoheaven)
19 //
20 // License: The Apache License, Version 2.0
21 // https://www.apache.org/licenses/LICENSE-2.0
22 //
23 // DISCLAIMER
24 // ==========
25 //
26 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
27 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
28 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
29 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
30 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
31 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
32 // SOFTWARE.
33 //
34 // THIS SOFTWARE IS DEVELOPED IN JAPAN, AND DISTRIBUTED FROM JAPAN, UNDER
35 // JAPANESE LAWS. YOU MUST AGREE IN ADVANCE TO USE, COPY, MODIFY, MERGE, PUBLISH,
36 // DISTRIBUTE, SUBLICENSE, AND/OR SELL COPIES OF THIS SOFTWARE, THAT ANY
37 // JURIDICAL DISPUTES WHICH ARE CONCERNED TO THIS SOFTWARE OR ITS CONTENTS,
38 // AGAINST US (SOFTETHER PROJECT, SOFTETHER CORPORATION, DAIYUU NOBORI OR OTHER
39 // SUPPLIERS), OR ANY JURIDICAL DISPUTES AGAINST US WHICH ARE CAUSED BY ANY KIND
40 // OF USING, COPYING, MODIFYING, MERGING, PUBLISHING, DISTRIBUTING, SUBLICENSING,
41 // AND/OR SELLING COPIES OF THIS SOFTWARE SHALL BE REGARDED AS BE CONSTRUED AND
42 // CONTROLLED BY JAPANESE LAWS, AND YOU MUST FURTHER CONSENT TO EXCLUSIVE
43 // JURISDICTION AND VENUE IN THE COURTS SITTING IN TOKYO, JAPAN. YOU MUST WAIVE
44 // ALL DEFENSES OF LACK OF PERSONAL JURISDICTION AND FORUM NON CONVENIENS.
45 // PROCESS MAY BE SERVED ON EITHER PARTY IN THE MANNER AUTHORIZED BY APPLICABLE
46 // LAW OR COURT RULE.
47 //
48 // USE ONLY IN JAPAN. DO NOT USE THIS SOFTWARE IN ANOTHER COUNTRY UNLESS YOU HAVE
49 // A CONFIRMATION THAT THIS SOFTWARE DOES NOT VIOLATE ANY CRIMINAL LAWS OR CIVIL
50 // RIGHTS IN THAT PARTICULAR COUNTRY. USING THIS SOFTWARE IN OTHER COUNTRIES IS
51 // COMPLETELY AT YOUR OWN RISK. THE SOFTETHER VPN PROJECT HAS DEVELOPED AND
52 // DISTRIBUTED THIS SOFTWARE TO COMPLY ONLY WITH THE JAPANESE LAWS AND EXISTING
53 // CIVIL RIGHTS INCLUDING PATENTS WHICH ARE SUBJECTS APPLY IN JAPAN. OTHER
54 // COUNTRIES' LAWS OR CIVIL RIGHTS ARE NONE OF OUR CONCERNS NOR RESPONSIBILITIES.
55 // WE HAVE NEVER INVESTIGATED ANY CRIMINAL REGULATIONS, CIVIL LAWS OR
56 // INTELLECTUAL PROPERTY RIGHTS INCLUDING PATENTS IN ANY OF OTHER 200+ COUNTRIES
57 // AND TERRITORIES. BY NATURE, THERE ARE 200+ REGIONS IN THE WORLD, WITH
58 // DIFFERENT LAWS. IT IS IMPOSSIBLE TO VERIFY EVERY COUNTRIES' LAWS, REGULATIONS
59 // AND CIVIL RIGHTS TO MAKE THE SOFTWARE COMPLY WITH ALL COUNTRIES' LAWS BY THE
60 // PROJECT. EVEN IF YOU WILL BE SUED BY A PRIVATE ENTITY OR BE DAMAGED BY A
61 // PUBLIC SERVANT IN YOUR COUNTRY, THE DEVELOPERS OF THIS SOFTWARE WILL NEVER BE
62 // LIABLE TO RECOVER OR COMPENSATE SUCH DAMAGES, CRIMINAL OR CIVIL
63 // RESPONSIBILITIES. NOTE THAT THIS LINE IS NOT LICENSE RESTRICTION BUT JUST A
64 // STATEMENT FOR WARNING AND DISCLAIMER.
65 //
66 // READ AND UNDERSTAND THE 'WARNING.TXT' FILE BEFORE USING THIS SOFTWARE.
67 // SOME SOFTWARE PROGRAMS FROM THIRD PARTIES ARE INCLUDED ON THIS SOFTWARE WITH
68 // LICENSE CONDITIONS WHICH ARE DESCRIBED ON THE 'THIRD_PARTY.TXT' FILE.
69 //
70 //
71 // SOURCE CODE CONTRIBUTION
72 // ------------------------
73 //
74 // Your contribution to SoftEther VPN Project is much appreciated.
75 // Please send patches to us through GitHub.
76 // Read the SoftEther VPN Patch Acceptance Policy in advance:
77 // http://www.softether.org/5-download/src/9.patch
78 //
79 //
80 // DEAR SECURITY EXPERTS
81 // ---------------------
82 //
83 // If you find a bug or a security vulnerability please kindly inform us
84 // about the problem immediately so that we can fix the security problem
85 // to protect a lot of users around the world as soon as possible.
86 //
87 // Our e-mail address for security reports is:
88 // softether-vpn-security [at] softether.org
89 //
90 // Please note that the above e-mail address is not a technical support
91 // inquiry address. If you need technical assistance, please visit
92 // http://www.softether.org/ and ask your question on the users forum.
93 //
94 // Thank you for your cooperation.
95 //
96 //
97 // NO MEMORY OR RESOURCE LEAKS
98 // ---------------------------
99 //
100 // The memory-leaks and resource-leaks verification under the stress
101 // test has been passed before release this source code.
102 
103 
104 // VLanUnix.c
105 // Virtual device driver library for UNIX
106 
107 #include <GlobalConst.h>
108 
109 #ifdef	VLAN_C
110 
111 #include <stdio.h>
112 #include <stdlib.h>
113 #include <string.h>
114 #include <wchar.h>
115 #include <stdarg.h>
116 #include <time.h>
117 #include <errno.h>
118 #include <Mayaqua/Mayaqua.h>
119 #include <Cedar/Cedar.h>
120 #ifdef	UNIX_MACOS
121 #include <net/ethernet.h>
122 #endif
123 
124 #ifdef	OS_UNIX
125 
126 static LIST *unix_vlan = NULL;
127 
128 #ifndef	NO_VLAN
129 
130 // Get the PACKET_ADAPTER
VLanGetPacketAdapter()131 PACKET_ADAPTER *VLanGetPacketAdapter()
132 {
133 	PACKET_ADAPTER *pa;
134 
135 	pa = NewPacketAdapter(VLanPaInit, VLanPaGetCancel,
136 		VLanPaGetNextPacket, VLanPaPutPacket, VLanPaFree);
137 	if (pa == NULL)
138 	{
139 		return NULL;
140 	}
141 
142 	return pa;
143 }
144 
145 // PA initialization
VLanPaInit(SESSION * s)146 bool VLanPaInit(SESSION *s)
147 {
148 	VLAN *v;
149 	// Validate arguments
150 	if (s == NULL)
151 	{
152 		return false;
153 	}
154 
155 	// Connect to the driver
156 	v = NewVLan(s->ClientOption->DeviceName, NULL);
157 	if (v == NULL)
158 	{
159 		// Failure
160 		return false;
161 	}
162 
163 	s->PacketAdapter->Param = v;
164 
165 	return true;
166 }
167 
168 // Get the cancel object
VLanPaGetCancel(SESSION * s)169 CANCEL *VLanPaGetCancel(SESSION *s)
170 {
171 	VLAN *v;
172 	// Validate arguments
173 	if ((s == NULL) || ((v = s->PacketAdapter->Param) == NULL))
174 	{
175 		return NULL;
176 	}
177 
178 	return VLanGetCancel(v);
179 }
180 
181 // Release the packet adapter
VLanPaFree(SESSION * s)182 void VLanPaFree(SESSION *s)
183 {
184 	VLAN *v;
185 	// Validate arguments
186 	if ((s == NULL) || ((v = s->PacketAdapter->Param) == NULL))
187 	{
188 		return;
189 	}
190 
191 	// End the virtual LAN card
192 	FreeVLan(v);
193 
194 	s->PacketAdapter->Param = NULL;
195 }
196 
197 // Write a packet
VLanPaPutPacket(SESSION * s,void * data,UINT size)198 bool VLanPaPutPacket(SESSION *s, void *data, UINT size)
199 {
200 	VLAN *v;
201 	// Validate arguments
202 	if ((s == NULL) || ((v = s->PacketAdapter->Param) == NULL))
203 	{
204 		return false;
205 	}
206 
207 	return VLanPutPacket(v, data, size);
208 }
209 
210 // Get the next packet
VLanPaGetNextPacket(SESSION * s,void ** data)211 UINT VLanPaGetNextPacket(SESSION *s, void **data)
212 {
213 	VLAN *v;
214 	UINT size;
215 	// Validate arguments
216 	if (data == NULL || (s == NULL) || ((v = s->PacketAdapter->Param) == NULL))
217 	{
218 		return INFINITE;
219 	}
220 
221 	if (VLanGetNextPacket(v, data, &size) == false)
222 	{
223 		return INFINITE;
224 	}
225 
226 	return size;
227 }
228 
229 // Write a packet to the virtual LAN card
VLanPutPacket(VLAN * v,void * buf,UINT size)230 bool VLanPutPacket(VLAN *v, void *buf, UINT size)
231 {
232 	UINT ret;
233 	// Validate arguments
234 	if (v == NULL)
235 	{
236 		return false;
237 	}
238 	if (v->Halt)
239 	{
240 		return false;
241 	}
242 	if (size > MAX_PACKET_SIZE)
243 	{
244 		return false;
245 	}
246 	if (buf == NULL || size == 0)
247 	{
248 		if (buf != NULL)
249 		{
250 			Free(buf);
251 		}
252 		return true;
253 	}
254 
255 	ret = write(v->fd, buf, size);
256 
257 	if (ret >= 1)
258 	{
259 		Free(buf);
260 		return true;
261 	}
262 
263 	if (errno == EAGAIN || ret == 0)
264 	{
265 		Free(buf);
266 		return true;
267 	}
268 
269 	return false;
270 }
271 
272 // Get the next packet from the virtual LAN card
VLanGetNextPacket(VLAN * v,void ** buf,UINT * size)273 bool VLanGetNextPacket(VLAN *v, void **buf, UINT *size)
274 {
275 	UCHAR tmp[TAP_READ_BUF_SIZE];
276 	int ret;
277 	// Validate arguments
278 	if (v == NULL || buf == NULL || size == 0)
279 	{
280 		return false;
281 	}
282 	if (v->Halt)
283 	{
284 		return false;
285 	}
286 
287 	// Read
288 	ret = read(v->fd, tmp, sizeof(tmp));
289 
290 	if (ret == 0 ||
291 		(ret == -1 && errno == EAGAIN))
292 	{
293 		// No packet
294 		*buf = NULL;
295 		*size = 0;
296 		return true;
297 	}
298 	else if (ret == -1 || ret > TAP_READ_BUF_SIZE)
299 	{
300 		// Error
301 		return false;
302 	}
303 	else
304 	{
305 		// Reading packet success
306 		*buf = Malloc(ret);
307 		Copy(*buf, tmp, ret);
308 		*size = ret;
309 		return true;
310 	}
311 }
312 
313 // Get the cancel object
VLanGetCancel(VLAN * v)314 CANCEL *VLanGetCancel(VLAN *v)
315 {
316 	CANCEL *c;
317 	int fd;
318 	int yes = 0;
319 	// Validate arguments
320 	if (v == NULL)
321 	{
322 		return NULL;
323 	}
324 
325 	c = NewCancel();
326 	UnixDeletePipe(c->pipe_read, c->pipe_write);
327 	c->pipe_read = c->pipe_write = -1;
328 
329 	fd = v->fd;
330 
331 	UnixSetSocketNonBlockingMode(fd, true);
332 
333 	c->SpecialFlag = true;
334 	c->pipe_read = fd;
335 
336 	return c;
337 }
338 
339 // Close the Virtual LAN card
FreeVLan(VLAN * v)340 void FreeVLan(VLAN *v)
341 {
342 	// Validate arguments
343 	if (v == NULL)
344 	{
345 		return;
346 	}
347 
348 	Free(v->InstanceName);
349 
350 	Free(v);
351 }
352 
353 // Create a tap
NewTap(char * name,char * mac_address)354 VLAN *NewTap(char *name, char *mac_address)
355 {
356 	int fd;
357 	VLAN *v;
358 	// Validate arguments
359 	if (name == NULL || mac_address == NULL)
360 	{
361 		return NULL;
362 	}
363 
364 	fd = UnixCreateTapDeviceEx(name, "tap", mac_address);
365 	if (fd == -1)
366 	{
367 		return NULL;
368 	}
369 
370 	v = ZeroMalloc(sizeof(VLAN));
371 	v->Halt = false;
372 	v->InstanceName = CopyStr(name);
373 	v->fd = fd;
374 
375 	return v;
376 }
377 
378 // Close the tap
FreeTap(VLAN * v)379 void FreeTap(VLAN *v)
380 {
381 	// Validate arguments
382 	if (v == NULL)
383 	{
384 		return;
385 	}
386 
387 	close(v->fd);
388 	FreeVLan(v);
389 }
390 
391 // Get the Virtual LAN card list
NewVLan(char * instance_name,VLAN_PARAM * param)392 VLAN *NewVLan(char *instance_name, VLAN_PARAM *param)
393 {
394 	int fd;
395 	VLAN *v;
396 	// Validate arguments
397 	if (instance_name == NULL)
398 	{
399 		return NULL;
400 	}
401 
402 	// Open the tap
403 	fd = UnixVLanGet(instance_name);
404 	if (fd == -1)
405 	{
406 		return NULL;
407 	}
408 
409 	v = ZeroMalloc(sizeof(VLAN));
410 	v->Halt = false;
411 	v->InstanceName = CopyStr(instance_name);
412 	v->fd = fd;
413 
414 	return v;
415 }
416 
417 // Create a tap device
UnixCreateTapDeviceEx(char * name,char * prefix,UCHAR * mac_address)418 int UnixCreateTapDeviceEx(char *name, char *prefix, UCHAR *mac_address)
419 {
420 	int fd;
421 	struct ifreq ifr;
422 	char eth_name[MAX_SIZE];
423 	char instance_name_lower[MAX_SIZE];
424 	struct sockaddr sa;
425 	char *tap_name = TAP_FILENAME_1;
426 	int s;
427 #ifdef	UNIX_MACOS
428 	char tap_macos_name[256] = TAP_MACOS_DIR TAP_MACOS_FILENAME;
429 #endif
430 	// Validate arguments
431 	if (name == NULL)
432 	{
433 		return -1;
434 	}
435 
436 	// Generate the device name
437 	StrCpy(instance_name_lower, sizeof(instance_name_lower), name);
438 	Trim(instance_name_lower);
439 	StrLower(instance_name_lower);
440 	Format(eth_name, sizeof(eth_name), "%s_%s", prefix, instance_name_lower);
441 
442 	eth_name[15] = 0;
443 
444 	// Open the tun / tap
445 #ifndef	UNIX_MACOS
446 	if (GetOsInfo()->OsType == OSTYPE_LINUX)
447 	{
448 		// Linux
449 		if (IsFile(TAP_FILENAME_1) == false)
450 		{
451 			char tmp[MAX_SIZE];
452 
453 			Format(tmp, sizeof(tmp), "%s c 10 200", TAP_FILENAME_1);
454 			Run("mknod", tmp, true, true);
455 
456 			Format(tmp, sizeof(tmp), "600 %s", TAP_FILENAME_1);
457 			Run("chmod", tmp, true, true);
458 		}
459 	}
460 	// Other than MacOS X
461 	fd = open(TAP_FILENAME_1, O_RDWR);
462 	if (fd == -1)
463 	{
464 		// Failure
465 		fd = open(TAP_FILENAME_2, O_RDWR);
466 		if (fd == -1)
467 		{
468 			return -1;
469 		}
470 		tap_name = TAP_FILENAME_2;
471 	}
472 #else	// UNIX_MACOS
473 	{
474 		int i;
475 		fd = -1;
476 		for (i = 0; i < TAP_MACOS_NUMBER; i++) {
477 			sprintf(tap_macos_name + strlen(TAP_MACOS_DIR TAP_MACOS_FILENAME), "%d", i);
478 			fd = open(tap_macos_name, O_RDWR);
479 			if (fd != -1)
480 			{
481 				tap_name = tap_macos_name;
482 				break;
483 			}
484 		}
485 		if (fd == -1)
486 		{
487 			return -1;
488 		}
489 	}
490 #endif	// UNIX_MACOS
491 
492 #ifdef	UNIX_LINUX
493 	// Create a tap for Linux
494 
495 	// Set the device name
496 	Zero(&ifr, sizeof(ifr));
497 
498 	ifr.ifr_flags = IFF_TAP | IFF_NO_PI;
499 	StrCpy(ifr.ifr_name, sizeof(ifr.ifr_name), eth_name);
500 
501 	if (ioctl(fd, TUNSETIFF, &ifr) == -1)
502 	{
503 		// Failure
504 		close(fd);
505 		return -1;
506 	}
507 
508 	// MAC address setting
509 	s = socket(AF_INET, SOCK_DGRAM, 0);
510 	if (s != -1)
511 	{
512 		if (mac_address != NULL)
513 		{
514 			Zero(&ifr, sizeof(ifr));
515 			StrCpy(ifr.ifr_name, sizeof(ifr.ifr_name), eth_name);
516 			ifr.ifr_hwaddr.sa_family = ARPHRD_ETHER;
517 			Copy(&ifr.ifr_addr.sa_data, mac_address, 6);
518 			ioctl(s, SIOCSIFHWADDR, &ifr);
519 		}
520 
521 		Zero(&ifr, sizeof(ifr));
522 		StrCpy(ifr.ifr_name, sizeof(ifr.ifr_name), eth_name);
523 		ioctl(s, SIOCGIFFLAGS, &ifr);
524 
525 		ifr.ifr_flags |= IFF_UP;
526 		ioctl(s, SIOCSIFFLAGS, &ifr);
527 
528 		close(s);
529 	}
530 
531 #else	// UNIX_LINUX
532 #ifdef	UNIX_MACOS
533 	// MAC address setting
534 	s = socket(AF_INET, SOCK_DGRAM, 0);
535 	if (s != -1)
536 	{
537 		char *macos_eth_name;
538 		macos_eth_name = tap_macos_name + strlen(TAP_MACOS_DIR);
539 
540 		if (mac_address != NULL)
541 		{
542 			Zero(&ifr, sizeof(ifr));
543 			StrCpy(ifr.ifr_name, sizeof(ifr.ifr_name), macos_eth_name);
544 			ifr.ifr_addr.sa_len = ETHER_ADDR_LEN;
545 			ifr.ifr_addr.sa_family = AF_LINK;
546 			Copy(&ifr.ifr_addr.sa_data, mac_address, ETHER_ADDR_LEN);
547 			ioctl(s, SIOCSIFLLADDR, &ifr);
548 		}
549 
550 		Zero(&ifr, sizeof(ifr));
551 		StrCpy(ifr.ifr_name, sizeof(ifr.ifr_name), macos_eth_name);
552 		ioctl(s, SIOCGIFFLAGS, &ifr);
553 
554 		ifr.ifr_flags |= IFF_UP;
555 		ioctl(s, SIOCSIFFLAGS, &ifr);
556 
557 		close(s);
558 	}
559 #endif	// UNIX_MACOS
560 #ifdef	UNIX_SOLARIS
561 	// Create a tap for Solaris
562 	{
563 		int ip_fd;
564 		int tun_fd;
565 		int ppa;
566 
567 		tun_fd = open(tap_name, O_RDWR);
568 		if (tun_fd == -1)
569 		{
570 			// Failure
571 			close(fd);
572 			return -1;
573 		}
574 
575 		ip_fd = open("/dev/ip", O_RDWR);
576 		if (ip_fd == -1)
577 		{
578 			// Failure
579 			close(tun_fd);
580 			close(fd);
581 			return -1;
582 		}
583 
584 		ppa = -1;
585 		ppa = ioctl(tun_fd, TUNNEWPPA, ppa);
586 		if (ppa == -1)
587 		{
588 			// Failure
589 			close(tun_fd);
590 			close(fd);
591 			close(ip_fd);
592 			return -1;
593 		}
594 
595 		if (ioctl(fd, I_PUSH, "ip") < 0)
596 		{
597 			// Failure
598 			close(tun_fd);
599 			close(fd);
600 			close(ip_fd);
601 			return -1;
602 		}
603 
604 		if (ioctl(fd, IF_UNITSEL, (char *)&ppa) < 0)
605 		{
606 			// Failure
607 			close(tun_fd);
608 			close(fd);
609 			close(ip_fd);
610 			return -1;
611 		}
612 
613 		if (ioctl(ip_fd, I_LINK, fd) < 0)
614 		{
615 			// Failure
616 			close(tun_fd);
617 			close(fd);
618 			close(ip_fd);
619 			return -1;
620 		}
621 
622 		close(tun_fd);
623 		close(ip_fd);
624 	}
625 
626 #endif	// UNIX_SOLARIS
627 #endif	// UNIX_LINUX
628 
629 	return fd;
630 }
UnixCreateTapDevice(char * name,UCHAR * mac_address)631 int UnixCreateTapDevice(char *name, UCHAR *mac_address)
632 {
633 	return UnixCreateTapDeviceEx(name, "vpn", mac_address);
634 }
635 
636 // Close the tap device
UnixCloseTapDevice(int fd)637 void UnixCloseTapDevice(int fd)
638 {
639 	// Validate arguments
640 	if (fd == -1)
641 	{
642 		return;
643 	}
644 
645 	close(fd);
646 }
647 
648 #else	// NO_VLAN
649 
UnixCloseTapDevice(int fd)650 void UnixCloseTapDevice(int fd)
651 {
652 }
653 
UnixCreateTapDeviceEx(char * name,char * prefix,UCHAR * mac_address)654 int UnixCreateTapDeviceEx(char *name, char *prefix, UCHAR *mac_address)
655 {
656 	return -1;
657 }
UnixCreateTapDevice(char * name,UCHAR * mac_address)658 int UnixCreateTapDevice(char *name, UCHAR *mac_address)
659 {
660 	return -1;
661 }
662 
663 #endif	// NO_VLAN
664 
665 // Comparison of the VLAN list entries
UnixCompareVLan(void * p1,void * p2)666 int UnixCompareVLan(void *p1, void *p2)
667 {
668 	UNIX_VLAN_LIST *v1, *v2;
669 	if (p1 == NULL || p2 == NULL)
670 	{
671 		return 0;
672 	}
673 	v1 = *(UNIX_VLAN_LIST **)p1;
674 	v2 = *(UNIX_VLAN_LIST **)p2;
675 	if (v1 == NULL || v2 == NULL)
676 	{
677 		return 0;
678 	}
679 
680 	return StrCmpi(v1->Name, v2->Name);
681 }
682 
683 // Initialize the VLAN list
UnixVLanInit()684 void UnixVLanInit()
685 {
686 	unix_vlan = NewList(UnixCompareVLan);
687 }
688 
689 // Create a VLAN
UnixVLanCreateEx(char * name,char * prefix,UCHAR * mac_address)690 bool UnixVLanCreateEx(char *name, char *prefix, UCHAR *mac_address)
691 {
692 	// Validate arguments
693 	char tmp[MAX_SIZE];
694 	if (name == NULL)
695 	{
696 		return false;
697 	}
698 
699 	StrCpy(tmp, sizeof(tmp), name);
700 	Trim(tmp);
701 	name = tmp;
702 
703 	LockList(unix_vlan);
704 	{
705 		UNIX_VLAN_LIST *t, tt;
706 		int fd;
707 
708 		// Check whether a device with the same name exists
709 		Zero(&tt, sizeof(tt));
710 		StrCpy(tt.Name, sizeof(tt.Name), name);
711 
712 		t = Search(unix_vlan, &tt);
713 		if (t != NULL)
714 		{
715 			// Already exist
716 			UnlockList(unix_vlan);
717 			return false;
718 		}
719 
720 		// Create a tap device
721 		fd = UnixCreateTapDeviceEx(name, prefix, mac_address);
722 		if (fd == -1)
723 		{
724 			// Failure to create
725 			UnlockList(unix_vlan);
726 			return false;
727 		}
728 
729 		t = ZeroMalloc(sizeof(UNIX_VLAN_LIST));
730 		t->fd = fd;
731 		StrCpy(t->Name, sizeof(t->Name), name);
732 
733 		Insert(unix_vlan, t);
734 	}
735 	UnlockList(unix_vlan);
736 
737 	return true;
738 }
UnixVLanCreate(char * name,UCHAR * mac_address)739 bool UnixVLanCreate(char *name, UCHAR *mac_address)
740 {
741 	return UnixVLanCreateEx(name, "vpn", mac_address);
742 }
743 
744 // Enumerate VLANs
UnixVLanEnum()745 TOKEN_LIST *UnixVLanEnum()
746 {
747 	TOKEN_LIST *ret;
748 	UINT i;
749 	if (unix_vlan == NULL)
750 	{
751 		return NullToken();
752 	}
753 
754 	ret = ZeroMalloc(sizeof(TOKEN_LIST));
755 
756 	LockList(unix_vlan);
757 	{
758 		ret->NumTokens = LIST_NUM(unix_vlan);
759 		ret->Token = ZeroMalloc(sizeof(char *) * ret->NumTokens);
760 
761 		for (i = 0;i < ret->NumTokens;i++)
762 		{
763 			UNIX_VLAN_LIST *t = LIST_DATA(unix_vlan, i);
764 
765 			ret->Token[i] = CopyStr(t->Name);
766 		}
767 	}
768 	UnlockList(unix_vlan);
769 
770 	return ret;
771 }
772 
773 // Delete the VLAN
UnixVLanDelete(char * name)774 void UnixVLanDelete(char *name)
775 {
776 	// Validate arguments
777 	if (name == NULL || unix_vlan == NULL)
778 	{
779 		return;
780 	}
781 
782 	LockList(unix_vlan);
783 	{
784 		UINT i;
785 		UNIX_VLAN_LIST *t, tt;
786 
787 		Zero(&tt, sizeof(tt));
788 		StrCpy(tt.Name, sizeof(tt.Name), name);
789 
790 		t = Search(unix_vlan, &tt);
791 		if (t != NULL)
792 		{
793 			UnixCloseTapDevice(t->fd);
794 			Delete(unix_vlan, t);
795 			Free(t);
796 		}
797 	}
798 	UnlockList(unix_vlan);
799 }
800 
801 // Get the VLAN
UnixVLanGet(char * name)802 int UnixVLanGet(char *name)
803 {
804 	int fd = -1;
805 	// Validate arguments
806 	if (name == NULL || unix_vlan == NULL)
807 	{
808 		return -1;
809 	}
810 
811 	LockList(unix_vlan);
812 	{
813 		UINT i;
814 		UNIX_VLAN_LIST *t, tt;
815 
816 		Zero(&tt, sizeof(tt));
817 		StrCpy(tt.Name, sizeof(tt.Name), name);
818 
819 		t = Search(unix_vlan, &tt);
820 		if (t != NULL)
821 		{
822 			fd = t->fd;
823 		}
824 	}
825 	UnlockList(unix_vlan);
826 
827 	return fd;
828 }
829 
830 // Release the VLAN list
UnixVLanFree()831 void UnixVLanFree()
832 {
833 	UINT i;
834 
835 	for (i = 0;i < LIST_NUM(unix_vlan);i++)
836 	{
837 		UNIX_VLAN_LIST *t = LIST_DATA(unix_vlan, i);
838 
839 		UnixCloseTapDevice(t->fd);
840 		Free(t);
841 	}
842 
843 	ReleaseList(unix_vlan);
844 	unix_vlan = NULL;
845 }
846 
847 #endif	// OS_UNIX
848 
849 #endif	// VLAN_C
850 
851