1 // SoftEther UT-VPN SourceCode
\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
8 // http://utvpn.tsukuba.ac.jp/
\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
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
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
23 // このファイルは GPL バージョン 2 ライセンスで公開されています。
\r
24 // 誰でもこのファイルの内容を複製、改変したり、改変したバージョンを再配布
\r
25 // することができます。ただし、原著作物を改変した場合は、原著作物の著作権表示
\r
26 // を除去することはできません。改変した著作物を配布する場合は、改変実施者の
\r
27 // 著作権表示を原著作物の著作権表示に付随して記載するようにしてください。
\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
33 // 本プログラムの配布者は、本プログラムを、業としての利用以外のため、
\r
34 // および、試験または研究のために利用が行われることを想定して配布
\r
36 // SoftEther UT-VPN プロジェクトの Web サイトは http://utvpn.tsukuba.ac.jp/ に
\r
38 // 本ソフトウェアの不具合の修正、機能改良、セキュリティホールの修復などのコード
\r
39 // の改変を行った場合で、その成果物を SoftEther UT-VPN プロジェクトに提出して
\r
40 // いただける場合は、 http://utvpn.tsukuba.ac.jp/ までソースコードを送付して
\r
41 // ください。SoftEther UT-VPN プロジェクトの本体リリースまたはブランチリリース
\r
44 // GPL に基づいて原著作物が提供される本ソフトウェアの改良版を配布、販売する
\r
45 // 場合は、そのソースコードを GPL に基づいて誰にでも開示する義務が生じます。
\r
47 // 本ソフトウェアに関連する著作権、特許権、商標権はソフトイーサ株式会社
\r
48 // (SoftEther Corporation) およびその他の著作権保持者が保有しています。
\r
49 // ソフトイーサ株式会社等はこれらの権利を放棄していません。本ソフトウェアの
\r
50 // 二次著作物を配布、販売する場合は、これらの権利を侵害しないようにご注意
\r
53 // お願い: どのような通信ソフトウェアにも通常は必ず未発見の
\r
54 // セキュリティホールが潜んでいます。本ソースコードをご覧いただいた結果、
\r
55 // UT-VPN にセキュリティホールを発見された場合は、当該セキュリティホールの
\r
56 // 情報を不特定多数に開示される前に、必ず、ソフトイーサ株式会社
\r
57 // および脆弱性情報の届出を受け付ける公的機関まで通報いただき、
\r
58 // 公益保護にご協力いただきますようお願い申し上げます。
\r
60 // ソフトイーサ株式会社は、当該セキュリティホールについて迅速に対処を
\r
61 // 行い、UT-VPN および UT-VPN に関連するソフトウェアのユーザー・顧客
\r
64 // ソフトイーサへの届出先: http://www.softether.co.jp/jp/contact/
\r
65 // 日本国内の脆弱性情報届出受付公的機関:
\r
67 // http://www.ipa.go.jp/security/vuln/report/
\r
69 // 上記各事項について不明な点は、ソフトイーサ株式会社までご連絡ください。
\r
70 // 連絡先: http://www.softether.co.jp/jp/contact/
\r
72 // -----------------------------------------------
\r
75 // 新規リリース by SoftEther
\r
76 // -----------------------------------------------
\r
79 // UNIX 用仮想デバイスドライバライブラリ
\r
90 #include <Mayaqua/Mayaqua.h>
\r
91 #include <Cedar/Cedar.h>
\r
95 static LIST *unix_vlan = NULL;
\r
99 // PACKET_ADAPTER の取得
\r
100 PACKET_ADAPTER *VLanGetPacketAdapter()
\r
102 PACKET_ADAPTER *pa;
\r
104 pa = NewPacketAdapter(VLanPaInit, VLanPaGetCancel,
\r
105 VLanPaGetNextPacket, VLanPaPutPacket, VLanPaFree);
\r
115 bool VLanPaInit(SESSION *s)
\r
125 v = NewVLan(s->ClientOption->DeviceName, NULL);
\r
132 s->PacketAdapter->Param = v;
\r
138 CANCEL *VLanPaGetCancel(SESSION *s)
\r
142 if ((s == NULL) || ((v = s->PacketAdapter->Param) == NULL))
\r
147 return VLanGetCancel(v);
\r
151 void VLanPaFree(SESSION *s)
\r
155 if ((s == NULL) || ((v = s->PacketAdapter->Param) == NULL))
\r
163 s->PacketAdapter->Param = NULL;
\r
167 bool VLanPaPutPacket(SESSION *s, void *data, UINT size)
\r
171 if ((s == NULL) || ((v = s->PacketAdapter->Param) == NULL))
\r
176 return VLanPutPacket(v, data, size);
\r
180 UINT VLanPaGetNextPacket(SESSION *s, void **data)
\r
185 if (data == NULL || (s == NULL) || ((v = s->PacketAdapter->Param) == NULL))
\r
190 if (VLanGetNextPacket(v, data, &size) == false)
\r
198 // パケットを仮想 LAN カードに書き込む
\r
199 bool VLanPutPacket(VLAN *v, void *buf, UINT size)
\r
211 if (size > MAX_PACKET_SIZE)
\r
215 if (buf == NULL || size == 0)
\r
224 ret = write(v->fd, buf, size);
\r
232 if (errno == EAGAIN || ret == 0)
\r
241 // 仮想 LAN カードから次のパケットを取得する
\r
242 bool VLanGetNextPacket(VLAN *v, void **buf, UINT *size)
\r
244 UCHAR tmp[TAP_READ_BUF_SIZE];
\r
247 if (v == NULL || buf == NULL || size == 0)
\r
257 ret = read(v->fd, tmp, sizeof(tmp));
\r
260 (ret == -1 && errno == EAGAIN))
\r
267 else if (ret == -1 || ret > TAP_READ_BUF_SIZE)
\r
275 *buf = Malloc(ret);
\r
276 Copy(*buf, tmp, ret);
\r
283 CANCEL *VLanGetCancel(VLAN *v)
\r
295 UnixDeletePipe(c->pipe_read, c->pipe_write);
\r
296 c->pipe_read = c->pipe_write = -1;
\r
301 UnixSetSocketNonBlockingMode(fd, true);
\r
302 #else // UNIX_MACOS
\r
303 UnixSetSocketNonBlockingMode(fd, false);
\r
304 #endif // UNIX_MACOS
\r
306 c->SpecialFlag = true;
\r
313 void FreeVLan(VLAN *v)
\r
321 Free(v->InstanceName);
\r
327 VLAN *NewTap(char *name, char *mac_address)
\r
332 if (name == NULL || mac_address == NULL)
\r
337 fd = UnixCreateTapDeviceEx(name, "tap", mac_address);
\r
343 v = ZeroMalloc(sizeof(VLAN));
\r
345 v->InstanceName = CopyStr(name);
\r
352 void FreeTap(VLAN *v)
\r
365 VLAN *NewVLan(char *instance_name, VLAN_PARAM *param)
\r
370 if (instance_name == NULL)
\r
376 fd = UnixVLanGet(instance_name);
\r
382 v = ZeroMalloc(sizeof(VLAN));
\r
384 v->InstanceName = CopyStr(instance_name);
\r
391 int UnixCreateTapDeviceEx(char *name, char *prefix, UCHAR *mac_address)
\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
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
416 if (GetOsInfo()->OsType == OSTYPE_LINUX)
\r
419 if (IsFile(TAP_FILENAME_1) == false)
\r
421 char tmp[MAX_SIZE];
\r
423 Format(tmp, sizeof(tmp), "%s c 10 200", TAP_FILENAME_1);
\r
424 Run("mknod", tmp, true, true);
\r
426 Format(tmp, sizeof(tmp), "600 %s", TAP_FILENAME_1);
\r
427 Run("chmod", tmp, true, true);
\r
431 fd = open(TAP_FILENAME_1, O_RDWR);
\r
435 fd = open(TAP_FILENAME_2, O_RDWR);
\r
440 tap_name = TAP_FILENAME_2;
\r
442 #else // UNIX_MACOS
\r
444 fd = open(TAP_MACOS_FILENAME, O_RDWR);
\r
449 tap_name = TAP_MACOS_FILENAME;
\r
450 #endif // UNIX_MACOS
\r
456 Zero(&ifr, sizeof(ifr));
\r
458 ifr.ifr_flags = IFF_TAP | IFF_NO_PI;
\r
459 StrCpy(ifr.ifr_name, sizeof(ifr.ifr_name), eth_name);
\r
461 if (ioctl(fd, TUNSETIFF, &ifr) == -1)
\r
469 s = socket(AF_INET, SOCK_DGRAM, 0);
\r
472 if (mac_address != NULL)
\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
481 Zero(&ifr, sizeof(ifr));
\r
482 StrCpy(ifr.ifr_name, sizeof(ifr.ifr_name), eth_name);
\r
483 ioctl(s, SIOCGIFFLAGS, &ifr);
\r
485 ifr.ifr_flags |= IFF_UP;
\r
486 ioctl(s, SIOCSIFFLAGS, &ifr);
\r
491 #else // UNIX_LINUX
\r
492 #ifdef UNIX_SOLARIS
\r
493 // Solaris 用 tap の作成
\r
499 tun_fd = open(tap_name, O_RDWR);
\r
507 ip_fd = open("/dev/ip", O_RDWR);
\r
517 ppa = ioctl(tun_fd, TUNNEWPPA, ppa);
\r
527 if (ioctl(fd, I_PUSH, "ip") < 0)
\r
536 if (ioctl(fd, IF_UNITSEL, (char *)&ppa) < 0)
\r
545 if (ioctl(ip_fd, I_LINK, fd) < 0)
\r
558 #endif // UNIX_SOLARIS
\r
559 #endif // UNIX_LINUX
\r
563 int UnixCreateTapDevice(char *name, UCHAR *mac_address)
\r
565 return UnixCreateTapDeviceEx(name, "utvpn", mac_address);
\r
569 void UnixCloseTapDevice(int fd)
\r
582 void UnixCloseTapDevice(int fd)
\r
586 int UnixCreateTapDeviceEx(char *name, char *prefix, UCHAR *mac_address)
\r
590 int UnixCreateTapDevice(char *name, UCHAR *mac_address)
\r
598 int UnixCompareVLan(void *p1, void *p2)
\r
600 UNIX_VLAN_LIST *v1, *v2;
\r
601 if (p1 == NULL || p2 == NULL)
\r
605 v1 = *(UNIX_VLAN_LIST **)p1;
\r
606 v2 = *(UNIX_VLAN_LIST **)p2;
\r
607 if (v1 == NULL || v2 == NULL)
\r
612 return StrCmpi(v1->Name, v2->Name);
\r
616 void UnixVLanInit()
\r
618 unix_vlan = NewList(UnixCompareVLan);
\r
622 bool UnixVLanCreateEx(char *name, char *prefix, UCHAR *mac_address)
\r
625 char tmp[MAX_SIZE];
\r
631 StrCpy(tmp, sizeof(tmp), name);
\r
635 LockList(unix_vlan);
\r
637 UNIX_VLAN_LIST *t, tt;
\r
640 // 同一名のデバイスが存在していないかどうかチェック
\r
641 Zero(&tt, sizeof(tt));
\r
642 StrCpy(tt.Name, sizeof(tt.Name), name);
\r
644 t = Search(unix_vlan, &tt);
\r
648 UnlockList(unix_vlan);
\r
653 fd = UnixCreateTapDeviceEx(name, prefix, mac_address);
\r
657 UnlockList(unix_vlan);
\r
661 t = ZeroMalloc(sizeof(UNIX_VLAN_LIST));
\r
663 StrCpy(t->Name, sizeof(t->Name), name);
\r
665 Insert(unix_vlan, t);
\r
667 UnlockList(unix_vlan);
\r
671 bool UnixVLanCreate(char *name, UCHAR *mac_address)
\r
673 return UnixVLanCreateEx(name, "utvpn", mac_address);
\r
677 TOKEN_LIST *UnixVLanEnum()
\r
681 if (unix_vlan == NULL)
\r
683 return NullToken();
\r
686 ret = ZeroMalloc(sizeof(TOKEN_LIST));
\r
688 LockList(unix_vlan);
\r
690 ret->NumTokens = LIST_NUM(unix_vlan);
\r
691 ret->Token = ZeroMalloc(sizeof(char *) * ret->NumTokens);
\r
693 for (i = 0;i < ret->NumTokens;i++)
\r
695 UNIX_VLAN_LIST *t = LIST_DATA(unix_vlan, i);
\r
697 ret->Token[i] = CopyStr(t->Name);
\r
700 UnlockList(unix_vlan);
\r
706 void UnixVLanDelete(char *name)
\r
709 if (name == NULL || unix_vlan == NULL)
\r
714 LockList(unix_vlan);
\r
717 UNIX_VLAN_LIST *t, tt;
\r
719 Zero(&tt, sizeof(tt));
\r
720 StrCpy(tt.Name, sizeof(tt.Name), name);
\r
722 t = Search(unix_vlan, &tt);
\r
725 UnixCloseTapDevice(t->fd);
\r
726 Delete(unix_vlan, t);
\r
730 UnlockList(unix_vlan);
\r
734 int UnixVLanGet(char *name)
\r
738 if (name == NULL || unix_vlan == NULL)
\r
743 LockList(unix_vlan);
\r
746 UNIX_VLAN_LIST *t, tt;
\r
748 Zero(&tt, sizeof(tt));
\r
749 StrCpy(tt.Name, sizeof(tt.Name), name);
\r
751 t = Search(unix_vlan, &tt);
\r
757 UnlockList(unix_vlan);
\r
763 void UnixVLanFree()
\r
767 for (i = 0;i < LIST_NUM(unix_vlan);i++)
\r
769 UNIX_VLAN_LIST *t = LIST_DATA(unix_vlan, i);
\r
771 UnixCloseTapDevice(t->fd);
\r
775 ReleaseList(unix_vlan);
\r