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