source: lab.git/Dev/utvpn/utvpn-unix-v101-7101-public/src/Cedar/VLanUnix.c @ a1bae3e

trunk
Last change on this file since a1bae3e was a1bae3e, checked in by mitty <mitty@…>, 12 years ago
  • copy vendor drop to trunk

git-svn-id: https://lab.mitty.jp/svn/lab/trunk@147 7d2118f6-f56c-43e7-95a2-4bb3031d96e7

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