* tar xzf utvpn-src-unix-v101-7101-public-2010.06.27.tar.gz
[lab.git] / utvpn / utvpn-unix-v101-7101-public / src / Cedar / VLanUnix.c
1 // SoftEther UT-VPN SourceCode\r
2 // \r
3 // Copyright (C) 2004-2010 SoftEther Corporation.\r
4 // Copyright (C) 2004-2010 University of Tsukuba, Japan.\r
5 // Copyright (C) 2003-2010 Daiyuu Nobori.\r
6 // All Rights Reserved.\r
7 // \r
8 // http://utvpn.tsukuba.ac.jp/\r
9 // \r
10 // This program is free software; you can redistribute it and/or\r
11 // modify it under the terms of the GNU General Public License\r
12 // version 2 as published by the Free Software Foundation.\r
13 // \r
14 // This program is distributed in the hope that it will be useful,\r
15 // but WITHOUT ANY WARRANTY; without even the implied warranty of\r
16 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r
17 // GNU General Public License for more details.\r
18 // \r
19 // You should have received a copy of the GNU General Public License version 2\r
20 // along with this program; if not, write to the Free Software\r
21 // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.\r
22 // \r
23 // このファイルは GPL バージョン 2 ライセンスで公開されています。\r
24 // 誰でもこのファイルの内容を複製、改変したり、改変したバージョンを再配布\r
25 // することができます。ただし、原著作物を改変した場合は、原著作物の著作権表示\r
26 // を除去することはできません。改変した著作物を配布する場合は、改変実施者の\r
27 // 著作権表示を原著作物の著作権表示に付随して記載するようにしてください。\r
28 // \r
29 // この SoftEther UT-VPN オープンソース・プロジェクトは、日本国の\r
30 // ソフトイーサ株式会社 (SoftEther Corporation, http://www.softether.co.jp/ )\r
31 // および筑波大学 (University of Tsukuba, http://www.tsukuba.ac.jp/ ) によって\r
32 // ホストされています。\r
33 // 本プログラムの配布者は、本プログラムを、業としての利用以外のため、\r
34 // および、試験または研究のために利用が行われることを想定して配布\r
35 // しています。\r
36 // SoftEther UT-VPN プロジェクトの Web サイトは http://utvpn.tsukuba.ac.jp/ に\r
37 // あります。\r
38 // 本ソフトウェアの不具合の修正、機能改良、セキュリティホールの修復などのコード\r
39 // の改変を行った場合で、その成果物を SoftEther UT-VPN プロジェクトに提出して\r
40 // いただける場合は、 http://utvpn.tsukuba.ac.jp/ までソースコードを送付して\r
41 // ください。SoftEther UT-VPN プロジェクトの本体リリースまたはブランチリリース\r
42 // に組み込みさせていただきます。\r
43 // \r
44 // GPL に基づいて原著作物が提供される本ソフトウェアの改良版を配布、販売する\r
45 // 場合は、そのソースコードを GPL に基づいて誰にでも開示する義務が生じます。\r
46 // \r
47 // 本ソフトウェアに関連する著作権、特許権、商標権はソフトイーサ株式会社\r
48 // (SoftEther Corporation) およびその他の著作権保持者が保有しています。\r
49 // ソフトイーサ株式会社等はこれらの権利を放棄していません。本ソフトウェアの\r
50 // 二次著作物を配布、販売する場合は、これらの権利を侵害しないようにご注意\r
51 // ください。\r
52 // \r
53 // お願い: どのような通信ソフトウェアにも通常は必ず未発見の\r
54 // セキュリティホールが潜んでいます。本ソースコードをご覧いただいた結果、\r
55 // UT-VPN にセキュリティホールを発見された場合は、当該セキュリティホールの\r
56 // 情報を不特定多数に開示される前に、必ず、ソフトイーサ株式会社\r
57 // および脆弱性情報の届出を受け付ける公的機関まで通報いただき、\r
58 // 公益保護にご協力いただきますようお願い申し上げます。\r
59 // \r
60 // ソフトイーサ株式会社は、当該セキュリティホールについて迅速に対処を\r
61 // 行い、UT-VPN および UT-VPN に関連するソフトウェアのユーザー・顧客\r
62 // を保護するための努力を行います。\r
63 // \r
64 // ソフトイーサへの届出先: http://www.softether.co.jp/jp/contact/\r
65 // 日本国内の脆弱性情報届出受付公的機関:\r
66 //         独立行政法人 情報処理推進機構\r
67 //         http://www.ipa.go.jp/security/vuln/report/\r
68 // \r
69 // 上記各事項について不明な点は、ソフトイーサ株式会社までご連絡ください。\r
70 // 連絡先: http://www.softether.co.jp/jp/contact/\r
71 \r
72 // -----------------------------------------------\r
73 // [ChangeLog]\r
74 // 2010.05.20\r
75 //  新規リリース by SoftEther\r
76 // -----------------------------------------------\r
77 \r
78 // VLanUnix.c\r
79 // UNIX 用仮想デバイスドライバライブラリ\r
80 \r
81 #ifdef  VLAN_C\r
82 \r
83 #include <stdio.h>\r
84 #include <stdlib.h>\r
85 #include <string.h>\r
86 #include <wchar.h>\r
87 #include <stdarg.h>\r
88 #include <time.h>\r
89 #include <errno.h>\r
90 #include <Mayaqua/Mayaqua.h>\r
91 #include <Cedar/Cedar.h>\r
92 \r
93 #ifdef  OS_UNIX\r
94 \r
95 static LIST *unix_vlan = NULL;\r
96 \r
97 #ifndef NO_VLAN\r
98 \r
99 // PACKET_ADAPTER の取得\r
100 PACKET_ADAPTER *VLanGetPacketAdapter()\r
101 {\r
102         PACKET_ADAPTER *pa;\r
103 \r
104         pa = NewPacketAdapter(VLanPaInit, VLanPaGetCancel,\r
105                 VLanPaGetNextPacket, VLanPaPutPacket, VLanPaFree);\r
106         if (pa == NULL)\r
107         {\r
108                 return NULL;\r
109         }\r
110 \r
111         return pa;\r
112 }\r
113 \r
114 // PA 初期化\r
115 bool VLanPaInit(SESSION *s)\r
116 {\r
117         VLAN *v;\r
118         // 引数チェック\r
119         if (s == NULL)\r
120         {\r
121                 return false;\r
122         }\r
123 \r
124         // ドライバに接続\r
125         v = NewVLan(s->ClientOption->DeviceName, NULL);\r
126         if (v == NULL)\r
127         {\r
128                 // 失敗\r
129                 return false;\r
130         }\r
131 \r
132         s->PacketAdapter->Param = v;\r
133 \r
134         return true;\r
135 }\r
136 \r
137 // キャンセルオブジェクトの取得\r
138 CANCEL *VLanPaGetCancel(SESSION *s)\r
139 {\r
140         VLAN *v;\r
141         // 引数チェック\r
142         if ((s == NULL) || ((v = s->PacketAdapter->Param) == NULL))\r
143         {\r
144                 return NULL;\r
145         }\r
146 \r
147         return VLanGetCancel(v);\r
148 }\r
149 \r
150 // パケットアダプタの解放\r
151 void VLanPaFree(SESSION *s)\r
152 {\r
153         VLAN *v;\r
154         // 引数チェック\r
155         if ((s == NULL) || ((v = s->PacketAdapter->Param) == NULL))\r
156         {\r
157                 return;\r
158         }\r
159 \r
160         // 仮想 LAN カードの終了\r
161         FreeVLan(v);\r
162 \r
163         s->PacketAdapter->Param = NULL;\r
164 }\r
165 \r
166 // パケットの書き込み\r
167 bool VLanPaPutPacket(SESSION *s, void *data, UINT size)\r
168 {\r
169         VLAN *v;\r
170         // 引数チェック\r
171         if ((s == NULL) || ((v = s->PacketAdapter->Param) == NULL))\r
172         {\r
173                 return false;\r
174         }\r
175 \r
176         return VLanPutPacket(v, data, size);\r
177 }\r
178 \r
179 // 次のパケットを取得\r
180 UINT VLanPaGetNextPacket(SESSION *s, void **data)\r
181 {\r
182         VLAN *v;\r
183         UINT size;\r
184         // 引数チェック\r
185         if (data == NULL || (s == NULL) || ((v = s->PacketAdapter->Param) == NULL))\r
186         {\r
187                 return INFINITE;\r
188         }\r
189 \r
190         if (VLanGetNextPacket(v, data, &size) == false)\r
191         {\r
192                 return INFINITE;\r
193         }\r
194 \r
195         return size;\r
196 }\r
197 \r
198 // パケットを仮想 LAN カードに書き込む\r
199 bool VLanPutPacket(VLAN *v, void *buf, UINT size)\r
200 {\r
201         UINT ret;\r
202         // 引数チェック\r
203         if (v == NULL)\r
204         {\r
205                 return false;\r
206         }\r
207         if (v->Halt)\r
208         {\r
209                 return false;\r
210         }\r
211         if (size > MAX_PACKET_SIZE)\r
212         {\r
213                 return false;\r
214         }\r
215         if (buf == NULL || size == 0)\r
216         {\r
217                 if (buf != NULL)\r
218                 {\r
219                         Free(buf);\r
220                 }\r
221                 return true;\r
222         }\r
223 \r
224         ret = write(v->fd, buf, size);\r
225 \r
226         if (ret >= 1)\r
227         {\r
228                 Free(buf);\r
229                 return true;\r
230         }\r
231 \r
232         if (errno == EAGAIN || ret == 0)\r
233         {\r
234                 Free(buf);\r
235                 return true;\r
236         }\r
237 \r
238         return false;\r
239 }\r
240 \r
241 // 仮想 LAN カードから次のパケットを取得する\r
242 bool VLanGetNextPacket(VLAN *v, void **buf, UINT *size)\r
243 {\r
244         UCHAR tmp[TAP_READ_BUF_SIZE];\r
245         int ret;\r
246         // 引数チェック\r
247         if (v == NULL || buf == NULL || size == 0)\r
248         {\r
249                 return false;\r
250         }\r
251         if (v->Halt)\r
252         {\r
253                 return false;\r
254         }\r
255 \r
256         // 読み込み\r
257         ret = read(v->fd, tmp, sizeof(tmp));\r
258 \r
259         if (ret == 0 ||\r
260                 (ret == -1 && errno == EAGAIN))\r
261         {\r
262                 // パケット無し\r
263                 *buf = NULL;\r
264                 *size = 0;\r
265                 return true;\r
266         }\r
267         else if (ret == -1 || ret > TAP_READ_BUF_SIZE)\r
268         {\r
269                 // エラー\r
270                 return false;\r
271         }\r
272         else\r
273         {\r
274                 // パケット読み込み成功\r
275                 *buf = Malloc(ret);\r
276                 Copy(*buf, tmp, ret);\r
277                 *size = ret;\r
278                 return true;\r
279         }\r
280 }\r
281 \r
282 // キャンセルオブジェクトの取得\r
283 CANCEL *VLanGetCancel(VLAN *v)\r
284 {\r
285         CANCEL *c;\r
286         int fd;\r
287         int yes = 0;\r
288         // 引数チェック\r
289         if (v == NULL)\r
290         {\r
291                 return NULL;\r
292         }\r
293 \r
294         c = NewCancel();\r
295         UnixDeletePipe(c->pipe_read, c->pipe_write);\r
296         c->pipe_read = c->pipe_write = -1;\r
297 \r
298         fd = v->fd;\r
299 \r
300 #ifndef UNIX_MACOS\r
301         UnixSetSocketNonBlockingMode(fd, true);\r
302 #else   // UNIX_MACOS\r
303         UnixSetSocketNonBlockingMode(fd, false);\r
304 #endif  // UNIX_MACOS\r
305 \r
306         c->SpecialFlag = true;\r
307         c->pipe_read = fd;\r
308 \r
309         return c;\r
310 }\r
311 \r
312 // 仮想 LAN カードを閉じる\r
313 void FreeVLan(VLAN *v)\r
314 {\r
315         // 引数チェック\r
316         if (v == NULL)\r
317         {\r
318                 return;\r
319         }\r
320 \r
321         Free(v->InstanceName);\r
322 \r
323         Free(v);\r
324 }\r
325 \r
326 // tap の作成\r
327 VLAN *NewTap(char *name, char *mac_address)\r
328 {\r
329         int fd;\r
330         VLAN *v;\r
331         // 引数チェック\r
332         if (name == NULL || mac_address == NULL)\r
333         {\r
334                 return NULL;\r
335         }\r
336 \r
337         fd = UnixCreateTapDeviceEx(name, "tap", mac_address);\r
338         if (fd == -1)\r
339         {\r
340                 return NULL;\r
341         }\r
342 \r
343         v = ZeroMalloc(sizeof(VLAN));\r
344         v->Halt = false;\r
345         v->InstanceName = CopyStr(name);\r
346         v->fd = fd;\r
347 \r
348         return v;\r
349 }\r
350 \r
351 // tap を閉じる\r
352 void FreeTap(VLAN *v)\r
353 {\r
354         // 引数チェック\r
355         if (v == NULL)\r
356         {\r
357                 return;\r
358         }\r
359 \r
360         close(v->fd);\r
361         FreeVLan(v);\r
362 }\r
363 \r
364 // 仮想 LAN カードの取得\r
365 VLAN *NewVLan(char *instance_name, VLAN_PARAM *param)\r
366 {\r
367         int fd;\r
368         VLAN *v;\r
369         // 引数チェック\r
370         if (instance_name == NULL)\r
371         {\r
372                 return NULL;\r
373         }\r
374 \r
375         // tap を開く\r
376         fd = UnixVLanGet(instance_name);\r
377         if (fd == -1)\r
378         {\r
379                 return NULL;\r
380         }\r
381 \r
382         v = ZeroMalloc(sizeof(VLAN));\r
383         v->Halt = false;\r
384         v->InstanceName = CopyStr(instance_name);\r
385         v->fd = fd;\r
386 \r
387         return v;\r
388 }\r
389 \r
390 // tap デバイスの作成\r
391 int UnixCreateTapDeviceEx(char *name, char *prefix, UCHAR *mac_address)\r
392 {\r
393         int fd;\r
394         struct ifreq ifr;\r
395         char eth_name[MAX_SIZE];\r
396         char instance_name_lower[MAX_SIZE];\r
397         struct sockaddr sa;\r
398         char *tap_name = TAP_FILENAME_1;\r
399         int s;\r
400         // 引数チェック\r
401         if (name == NULL)\r
402         {\r
403                 return -1;\r
404         }\r
405 \r
406         // デバイス名を生成\r
407         StrCpy(instance_name_lower, sizeof(instance_name_lower), name);\r
408         Trim(instance_name_lower);\r
409         StrLower(instance_name_lower);\r
410         Format(eth_name, sizeof(eth_name), "%s_%s", prefix, instance_name_lower);\r
411 \r
412         eth_name[15] = 0;\r
413 \r
414         // tun/tap を開く\r
415 #ifndef UNIX_MACOS\r
416         if (GetOsInfo()->OsType == OSTYPE_LINUX)\r
417         {\r
418                 // Linux\r
419                 if (IsFile(TAP_FILENAME_1) == false)\r
420                 {\r
421                         char tmp[MAX_SIZE];\r
422 \r
423                         Format(tmp, sizeof(tmp), "%s c 10 200", TAP_FILENAME_1);\r
424                         Run("mknod", tmp, true, true);\r
425 \r
426                         Format(tmp, sizeof(tmp), "600 %s", TAP_FILENAME_1);\r
427                         Run("chmod", tmp, true, true);\r
428                 }\r
429         }\r
430         // MacOS X 以外\r
431         fd = open(TAP_FILENAME_1, O_RDWR);\r
432         if (fd == -1)\r
433         {\r
434                 // 失敗\r
435                 fd = open(TAP_FILENAME_2, O_RDWR);\r
436                 if (fd == -1)\r
437                 {\r
438                         return -1;\r
439                 }\r
440                 tap_name = TAP_FILENAME_2;\r
441         }\r
442 #else   // UNIX_MACOS\r
443         // MacOS X\r
444         fd = open(TAP_MACOS_FILENAME, O_RDWR);\r
445         if (fd == -1)\r
446         {\r
447                 return -1;\r
448         }\r
449         tap_name = TAP_MACOS_FILENAME;\r
450 #endif  // UNIX_MACOS\r
451 \r
452 #ifdef  UNIX_LINUX\r
453         // Linux 用 tap の作成\r
454 \r
455         // デバイス名設定\r
456         Zero(&ifr, sizeof(ifr));\r
457 \r
458         ifr.ifr_flags = IFF_TAP | IFF_NO_PI;\r
459         StrCpy(ifr.ifr_name, sizeof(ifr.ifr_name), eth_name);\r
460 \r
461         if (ioctl(fd, TUNSETIFF, &ifr) == -1)\r
462         {\r
463                 // 失敗\r
464                 close(fd);\r
465                 return -1;\r
466         }\r
467 \r
468         // MAC アドレス設定\r
469         s = socket(AF_INET, SOCK_DGRAM, 0);\r
470         if (s != -1)\r
471         {\r
472                 if (mac_address != NULL)\r
473                 {\r
474                         Zero(&ifr, sizeof(ifr));\r
475                         StrCpy(ifr.ifr_name, sizeof(ifr.ifr_name), eth_name);\r
476                         ifr.ifr_hwaddr.sa_family = ARPHRD_ETHER;\r
477                         Copy(&ifr.ifr_hwaddr.sa_data, mac_address, 6);\r
478                         ioctl(s, SIOCSIFHWADDR, &ifr);\r
479                 }\r
480 \r
481                 Zero(&ifr, sizeof(ifr));\r
482                 StrCpy(ifr.ifr_name, sizeof(ifr.ifr_name), eth_name);\r
483                 ioctl(s, SIOCGIFFLAGS, &ifr);\r
484 \r
485                 ifr.ifr_flags |= IFF_UP;\r
486                 ioctl(s, SIOCSIFFLAGS, &ifr);\r
487 \r
488                 close(s);\r
489         }\r
490 \r
491 #else   // UNIX_LINUX\r
492 #ifdef  UNIX_SOLARIS\r
493         // Solaris 用 tap の作成\r
494         {\r
495                 int ip_fd;\r
496                 int tun_fd;\r
497                 int ppa;\r
498 \r
499                 tun_fd = open(tap_name, O_RDWR);\r
500                 if (tun_fd == -1)\r
501                 {\r
502                         // 失敗\r
503                         close(fd);\r
504                         return -1;\r
505                 }\r
506 \r
507                 ip_fd = open("/dev/ip", O_RDWR);\r
508                 if (ip_fd == -1)\r
509                 {\r
510                         // 失敗\r
511                         close(tun_fd);\r
512                         close(fd);\r
513                         return -1;\r
514                 }\r
515 \r
516                 ppa = -1;\r
517                 ppa = ioctl(tun_fd, TUNNEWPPA, ppa);\r
518                 if (ppa == -1)\r
519                 {\r
520                         // 失敗\r
521                         close(tun_fd);\r
522                         close(fd);\r
523                         close(ip_fd);\r
524                         return -1;\r
525                 }\r
526 \r
527                 if (ioctl(fd, I_PUSH, "ip") < 0)\r
528                 {\r
529                         // 失敗\r
530                         close(tun_fd);\r
531                         close(fd);\r
532                         close(ip_fd);\r
533                         return -1;\r
534                 }\r
535 \r
536                 if (ioctl(fd, IF_UNITSEL, (char *)&ppa) < 0)\r
537                 {\r
538                         // 失敗\r
539                         close(tun_fd);\r
540                         close(fd);\r
541                         close(ip_fd);\r
542                         return -1;\r
543                 }\r
544 \r
545                 if (ioctl(ip_fd, I_LINK, fd) < 0)\r
546                 {\r
547                         // 失敗\r
548                         close(tun_fd);\r
549                         close(fd);\r
550                         close(ip_fd);\r
551                         return -1;\r
552                 }\r
553 \r
554                 close(tun_fd);\r
555                 close(ip_fd);\r
556         }\r
557 \r
558 #endif  // UNIX_SOLARIS\r
559 #endif  // UNIX_LINUX\r
560 \r
561         return fd;\r
562 }\r
563 int UnixCreateTapDevice(char *name, UCHAR *mac_address)\r
564 {\r
565         return UnixCreateTapDeviceEx(name, "utvpn", mac_address);\r
566 }\r
567 \r
568 // tap デバイスを閉じる\r
569 void UnixCloseTapDevice(int fd)\r
570 {\r
571         // 引数チェック\r
572         if (fd == -1)\r
573         {\r
574                 return;\r
575         }\r
576 \r
577         close(fd);\r
578 }\r
579 \r
580 #else   // NO_VLAN\r
581 \r
582 void UnixCloseTapDevice(int fd)\r
583 {\r
584 }\r
585 \r
586 int UnixCreateTapDeviceEx(char *name, char *prefix, UCHAR *mac_address)\r
587 {\r
588         return -1;\r
589 }\r
590 int UnixCreateTapDevice(char *name, UCHAR *mac_address)\r
591 {\r
592         return -1;\r
593 }\r
594 \r
595 #endif  // NO_VLAN\r
596 \r
597 // VLAN リストの比較\r
598 int UnixCompareVLan(void *p1, void *p2)\r
599 {\r
600         UNIX_VLAN_LIST *v1, *v2;\r
601         if (p1 == NULL || p2 == NULL)\r
602         {\r
603                 return 0;\r
604         }\r
605         v1 = *(UNIX_VLAN_LIST **)p1;\r
606         v2 = *(UNIX_VLAN_LIST **)p2;\r
607         if (v1 == NULL || v2 == NULL)\r
608         {\r
609                 return 0;\r
610         }\r
611 \r
612         return StrCmpi(v1->Name, v2->Name);\r
613 }\r
614 \r
615 // VLAN リストの初期化\r
616 void UnixVLanInit()\r
617 {\r
618         unix_vlan = NewList(UnixCompareVLan);\r
619 }\r
620 \r
621 // VLAN の作成\r
622 bool UnixVLanCreateEx(char *name, char *prefix, UCHAR *mac_address)\r
623 {\r
624         // 引数チェック\r
625         char tmp[MAX_SIZE];\r
626         if (name == NULL)\r
627         {\r
628                 return false;\r
629         }\r
630 \r
631         StrCpy(tmp, sizeof(tmp), name);\r
632         Trim(tmp);\r
633         name = tmp;\r
634 \r
635         LockList(unix_vlan);\r
636         {\r
637                 UNIX_VLAN_LIST *t, tt;\r
638                 int fd;\r
639 \r
640                 // 同一名のデバイスが存在していないかどうかチェック\r
641                 Zero(&tt, sizeof(tt));\r
642                 StrCpy(tt.Name, sizeof(tt.Name), name);\r
643 \r
644                 t = Search(unix_vlan, &tt);\r
645                 if (t != NULL)\r
646                 {\r
647                         // すでに存在する\r
648                         UnlockList(unix_vlan);\r
649                         return false;\r
650                 }\r
651 \r
652                 // tap デバイスを作成\r
653                 fd = UnixCreateTapDeviceEx(name, prefix, mac_address);\r
654                 if (fd == -1)\r
655                 {\r
656                         // 作成失敗\r
657                         UnlockList(unix_vlan);\r
658                         return false;\r
659                 }\r
660 \r
661                 t = ZeroMalloc(sizeof(UNIX_VLAN_LIST));\r
662                 t->fd = fd;\r
663                 StrCpy(t->Name, sizeof(t->Name), name);\r
664 \r
665                 Insert(unix_vlan, t);\r
666         }\r
667         UnlockList(unix_vlan);\r
668 \r
669         return true;\r
670 }\r
671 bool UnixVLanCreate(char *name, UCHAR *mac_address)\r
672 {\r
673         return UnixVLanCreateEx(name, "utvpn", mac_address);\r
674 }\r
675 \r
676 // VLAN の列挙\r
677 TOKEN_LIST *UnixVLanEnum()\r
678 {\r
679         TOKEN_LIST *ret;\r
680         UINT i;\r
681         if (unix_vlan == NULL)\r
682         {\r
683                 return NullToken();\r
684         }\r
685 \r
686         ret = ZeroMalloc(sizeof(TOKEN_LIST));\r
687 \r
688         LockList(unix_vlan);\r
689         {\r
690                 ret->NumTokens = LIST_NUM(unix_vlan);\r
691                 ret->Token = ZeroMalloc(sizeof(char *) * ret->NumTokens);\r
692 \r
693                 for (i = 0;i < ret->NumTokens;i++)\r
694                 {\r
695                         UNIX_VLAN_LIST *t = LIST_DATA(unix_vlan, i);\r
696 \r
697                         ret->Token[i] = CopyStr(t->Name);\r
698                 }\r
699         }\r
700         UnlockList(unix_vlan);\r
701 \r
702         return ret;\r
703 }\r
704 \r
705 // VLAN の削除\r
706 void UnixVLanDelete(char *name)\r
707 {\r
708         // 引数チェック\r
709         if (name == NULL || unix_vlan == NULL)\r
710         {\r
711                 return;\r
712         }\r
713 \r
714         LockList(unix_vlan);\r
715         {\r
716                 UINT i;\r
717                 UNIX_VLAN_LIST *t, tt;\r
718 \r
719                 Zero(&tt, sizeof(tt));\r
720                 StrCpy(tt.Name, sizeof(tt.Name), name);\r
721 \r
722                 t = Search(unix_vlan, &tt);\r
723                 if (t != NULL)\r
724                 {\r
725                         UnixCloseTapDevice(t->fd);\r
726                         Delete(unix_vlan, t);\r
727                         Free(t);\r
728                 }\r
729         }\r
730         UnlockList(unix_vlan);\r
731 }\r
732 \r
733 // VLAN の取得\r
734 int UnixVLanGet(char *name)\r
735 {\r
736         int fd = -1;\r
737         // 引数チェック\r
738         if (name == NULL || unix_vlan == NULL)\r
739         {\r
740                 return -1;\r
741         }\r
742 \r
743         LockList(unix_vlan);\r
744         {\r
745                 UINT i;\r
746                 UNIX_VLAN_LIST *t, tt;\r
747 \r
748                 Zero(&tt, sizeof(tt));\r
749                 StrCpy(tt.Name, sizeof(tt.Name), name);\r
750 \r
751                 t = Search(unix_vlan, &tt);\r
752                 if (t != NULL)\r
753                 {\r
754                         fd = t->fd;\r
755                 }\r
756         }\r
757         UnlockList(unix_vlan);\r
758 \r
759         return fd;\r
760 }\r
761 \r
762 // VLAN リストの解放\r
763 void UnixVLanFree()\r
764 {\r
765         UINT i;\r
766 \r
767         for (i = 0;i < LIST_NUM(unix_vlan);i++)\r
768         {\r
769                 UNIX_VLAN_LIST *t = LIST_DATA(unix_vlan, i);\r
770 \r
771                 UnixCloseTapDevice(t->fd);\r
772                 Free(t);\r
773         }\r
774 \r
775         ReleaseList(unix_vlan);\r
776         unix_vlan = NULL;\r
777 }\r
778 \r
779 #endif  // OS_UNIX\r
780 \r
781 #endif  // VLAN_C\r
782 \r