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
84 #define __WINCRYPT_H__
\r
87 // Socket API のために windows.h をインクルード
\r
88 #define _WIN32_WINNT 0x0502
\r
89 #define WINVER 0x0502
\r
90 #include <Ws2tcpip.h>
\r
91 #include <Wspiapi.h>
\r
92 #include <winsock2.h>
\r
93 #include <Ws2tcpip.h>
\r
94 #include <windows.h>
\r
95 #include <Iphlpapi.h>
\r
100 #include <string.h>
\r
102 #include <stdarg.h>
\r
104 #include <openssl/ssl.h>
\r
105 #include <openssl/err.h>
\r
106 #include <openssl/rand.h>
\r
107 #include <openssl/engine.h>
\r
108 #include <openssl/bio.h>
\r
109 #include <openssl/x509.h>
\r
110 #include <openssl/pkcs7.h>
\r
111 #include <openssl/pkcs12.h>
\r
112 #include <openssl/rc4.h>
\r
113 #include <openssl/md5.h>
\r
114 #include <openssl/sha.h>
\r
115 #include <Mayaqua/Mayaqua.h>
\r
118 NETWORK_WIN32_FUNCTIONS *w32net;
\r
119 struct ROUTE_CHANGE_DATA
\r
121 OVERLAPPED Overlapped;
\r
127 // SSL でブロッキングするかどうか
\r
128 #if defined(UNIX_BSD)
\r
129 #define FIX_SSL_BLOCKING
\r
134 #ifndef IPV6_V6ONLY
\r
135 #define IPV6_V6ONLY 26
\r
136 #endif // IPV6_V6ONLY
\r
137 #endif // UNIX_LINUX
\r
139 #ifdef UNIX_SOLARIS
\r
140 #ifndef IPV6_V6ONLY
\r
141 #define IPV6_V6ONLY 0x27
\r
142 #endif // IPV6_V6ONLY
\r
143 #endif // UNIX_SOLARIS
\r
146 static SSL_CTX *ssl_ctx = NULL;
\r
149 static LIST *DnsCache;
\r
152 static LOCK *machine_name_lock = NULL;
\r
153 static LOCK *disconnect_function_lock = NULL;
\r
154 static LOCK *aho = NULL;
\r
155 static LOCK *socket_library_lock = NULL;
\r
156 extern LOCK *openssl_lock;
\r
157 static LOCK *ssl_accept_lock = NULL;
\r
158 static LOCK *ssl_connect_lock = NULL;
\r
159 static TOKEN_LIST *cipher_list_token = NULL;
\r
160 static COUNTER *num_tcp_connections = NULL;
\r
161 static LOCK *dns_lock = NULL;
\r
162 static LOCK *unix_dns_server_addr_lock = NULL;
\r
163 static IP unix_dns_server;
\r
164 static LIST *HostCacheList = NULL;
\r
165 static LIST *WaitThreadList = NULL;
\r
166 static bool disable_cache = false;
\r
167 static bool NetworkReleaseMode = false; // ネットワークリリースモード
\r
169 static char *cipher_list = "RC4-MD5 RC4-SHA AES128-SHA AES256-SHA DES-CBC-SHA DES-CBC3-SHA";
\r
170 static LIST *ip_clients = NULL;
\r
172 // ルーティングテーブル変更検出を初期化
\r
173 ROUTE_CHANGE *NewRouteChange()
\r
176 return Win32NewRouteChange();
\r
182 // ルーティングテーブル変更検出を解放
\r
183 void FreeRouteChange(ROUTE_CHANGE *r)
\r
186 Win32FreeRouteChange(r);
\r
190 // ルーティングテーブルが変更されたかどうか取得
\r
191 bool IsRouteChanged(ROUTE_CHANGE *r)
\r
194 return Win32IsRouteChanged(r);
\r
200 // ルーティングテーブル変更検出機能 (Win32)
\r
202 ROUTE_CHANGE *Win32NewRouteChange()
\r
207 if (MsIsNt() == false)
\r
212 if (w32net->CancelIPChangeNotify == NULL ||
\r
213 w32net->NotifyRouteChange == NULL)
\r
218 r = ZeroMalloc(sizeof(ROUTE_CHANGE));
\r
220 r->Data = ZeroMalloc(sizeof(ROUTE_CHANGE_DATA));
\r
222 r->Data->Overlapped.hEvent = CreateEventA(NULL, false, true, NULL);
\r
224 ret = w32net->NotifyRouteChange(&r->Data->Handle, &r->Data->Overlapped);
\r
225 if (!(ret == NO_ERROR || ret == WSA_IO_PENDING || WSAGetLastError() == WSA_IO_PENDING))
\r
236 void Win32FreeRouteChange(ROUTE_CHANGE *r)
\r
244 w32net->CancelIPChangeNotify(&r->Data->Overlapped);
\r
245 CloseHandle(r->Data->Overlapped.hEvent);
\r
251 bool Win32IsRouteChanged(ROUTE_CHANGE *r)
\r
259 if ((r->Data->NumCalled++) == 0)
\r
264 if (WaitForSingleObject(r->Data->Overlapped.hEvent, 0) == WAIT_OBJECT_0)
\r
266 w32net->NotifyRouteChange(&r->Data->Handle, &r->Data->Overlapped);
\r
276 // TCP コネクションのプロセス ID の取得が成功するかどうかを取得
\r
277 bool CanGetTcpProcessId()
\r
281 LIST *o = GetTcpTableList();
\r
288 for (i = 0;i < LIST_NUM(o);i++)
\r
290 TCPTABLE *t = LIST_DATA(o, i);
\r
292 if (t->ProcessId != 0)
\r
299 FreeTcpTableList(o);
\r
307 #define USE_OLD_GETIP
\r
309 // Linux における arp_filter を設定する
\r
310 void SetLinuxArpFilter()
\r
312 char *filename = "/proc/sys/net/ipv4/conf/all/arp_filter";
\r
313 char *data = "1\n";
\r
316 o = FileCreate(filename);
\r
322 FileWrite(o, data, StrLen(data));
\r
328 // 指定された文字列が IPv6 マスクかどうか判定する
\r
329 bool IsIpMask6(char *str)
\r
338 return StrToMask6(&mask, str);
\r
341 // 指定された文字列が IPv6 アドレスかどうか判定する
\r
342 bool IsStrIPv6Address(char *str)
\r
351 if (StrToIP6(&ip, str) == false)
\r
359 // サブネットマスクを整数に変換する
\r
360 UINT SubnetMaskToInt6(IP *a)
\r
364 if (IsIP6(a) == false)
\r
369 for (i = 0;i <= 128;i++)
\r
373 IntToSubnetMask6(&tmp, i);
\r
375 if (CmpIpAddr(a, &tmp) == 0)
\r
383 UINT SubnetMaskToInt4(IP *a)
\r
387 if (IsIP4(a) == false)
\r
392 for (i = 0;i <= 32;i++)
\r
396 IntToSubnetMask4(&tmp, i);
\r
398 if (CmpIpAddr(a, &tmp) == 0)
\r
406 UINT SubnetMaskToInt(IP *a)
\r
410 return SubnetMaskToInt6(a);
\r
414 return SubnetMaskToInt4(a);
\r
418 // 指定した IP アドレスがサブネットマスクかどうか調べる
\r
419 bool IsSubnetMask6(IP *a)
\r
423 if (IsIP6(a) == false)
\r
428 for (i = 0;i <= 128;i++)
\r
432 IntToSubnetMask6(&tmp, i);
\r
434 if (CmpIpAddr(a, &tmp) == 0)
\r
443 // MAC アドレスからグローバルアドレスを生成する
\r
444 void GenerateEui64GlobalAddress(IP *ip, IP *prefix, IP *subnet, UCHAR *mac)
\r
451 if (ip == NULL || prefix == NULL || subnet == NULL || mac == NULL)
\r
456 GenerateEui64Address6(tmp, mac);
\r
460 Copy(&a.ipv6_addr[8], tmp, 8);
\r
462 IPNot6(&subnet_not, subnet);
\r
463 IPAnd6(&or1, &a, &subnet_not);
\r
464 IPAnd6(&or2, prefix, subnet);
\r
466 IPOr6(ip, &or1, &or2);
\r
469 // MAC アドレスからローカルアドレスを生成する
\r
470 void GenerateEui64LocalAddress(IP *a, UCHAR *mac)
\r
474 if (a == NULL || mac == NULL)
\r
479 GenerateEui64Address6(tmp, mac);
\r
482 a->ipv6_addr[0] = 0xfe;
\r
483 a->ipv6_addr[1] = 0x80;
\r
485 Copy(&a->ipv6_addr[8], tmp, 8);
\r
488 // MAC アドレスから EUI-64 アドレスを生成する
\r
489 void GenerateEui64Address6(UCHAR *dst, UCHAR *mac)
\r
492 if (dst == NULL || mac == NULL)
\r
498 Copy(dst + 5, mac, 3);
\r
502 dst[0] = ((~(dst[0] & 0x02)) & 0x02) | (dst[0] & 0xfd);
\r
505 // 同一のネットワークかどうか調べる
\r
506 bool IsInSameNetwork6(IP *a1, IP *a2, IP *subnet)
\r
508 IP prefix1, prefix2;
\r
510 if (IsIP6(a1) == false || IsIP6(a2) == false || IsIP6(subnet) == false)
\r
515 if (a1->ipv6_scope_id != a2->ipv6_scope_id)
\r
520 GetPrefixAddress6(&prefix1, a1, subnet);
\r
521 GetPrefixAddress6(&prefix2, a2, subnet);
\r
523 if (CmpIpAddr(&prefix1, &prefix2) == 0)
\r
531 // ネットワークプレフィックスアドレスかどうかチェックする
\r
532 bool IsNetworkAddress6(IP *ip, IP *subnet)
\r
534 return IsNetworkPrefixAddress6(ip, subnet);
\r
536 bool IsNetworkPrefixAddress6(IP *ip, IP *subnet)
\r
540 if (ip == NULL || subnet == NULL)
\r
545 if (IsIP6(ip) == false || IsIP6(subnet) == false)
\r
550 GetHostAddress6(&host, ip, subnet);
\r
552 if (IsZeroIp(&host))
\r
560 // ユニキャストアドレスが有効かどうかチェックする
\r
561 bool CheckUnicastAddress(IP *ip)
\r
569 if ((GetIPAddrType6(ip) & IPV6_ADDR_UNICAST) == 0)
\r
578 void GetHostAddress6(IP *dst, IP *ip, IP *subnet)
\r
582 if (dst == NULL || ip == NULL || subnet == NULL)
\r
587 IPNot6(¬, subnet);
\r
589 IPAnd6(dst, ip, ¬);
\r
591 dst->ipv6_scope_id = ip->ipv6_scope_id;
\r
595 void GetPrefixAddress6(IP *dst, IP *ip, IP *subnet)
\r
598 if (dst == NULL || ip == NULL || subnet == NULL)
\r
603 IPAnd6(dst, ip, subnet);
\r
605 dst->ipv6_scope_id = ip->ipv6_scope_id;
\r
608 // 要請ノードマルチキャストアドレスを取得
\r
609 void GetSoliciationMulticastAddr6(IP *dst, IP *src)
\r
616 if (dst == NULL || src == NULL)
\r
622 prefix.ipv6_addr[0] = 0xff;
\r
623 prefix.ipv6_addr[1] = 0x02;
\r
624 prefix.ipv6_addr[11] = 0x01;
\r
625 prefix.ipv6_addr[12] = 0xff;
\r
627 IntToSubnetMask6(&mask104, 104);
\r
629 IPAnd6(&or1, &prefix, &mask104);
\r
630 IPAnd6(&or2, src, &mask104);
\r
632 IPOr6(dst, &or1, &or2);
\r
634 dst->ipv6_scope_id = src->ipv6_scope_id;
\r
637 // マルチキャストアドレスに対応した MAC アドレスの生成
\r
638 void GenerateMulticastMacAddress6(UCHAR *mac, IP *ip)
\r
648 mac[2] = ip->ipv6_addr[12];
\r
649 mac[3] = ip->ipv6_addr[13];
\r
650 mac[4] = ip->ipv6_addr[14];
\r
651 mac[5] = ip->ipv6_addr[15];
\r
654 // IPv6 アドレスのタイプの取得
\r
655 UINT GetIPv6AddrType(IPV6_ADDR *addr)
\r
664 IPv6AddrToIP(&ip, addr);
\r
666 return GetIPAddrType6(&ip);
\r
668 UINT GetIPAddrType6(IP *ip)
\r
672 if (IsIP6(ip) == false)
\r
677 if (ip->ipv6_addr[0] == 0xff)
\r
679 IP all_node, all_router;
\r
681 GetAllNodeMulticaseAddress6(&all_node);
\r
683 GetAllRouterMulticastAddress6(&all_router);
\r
685 ret |= IPV6_ADDR_MULTICAST;
\r
687 if (Cmp(ip->ipv6_addr, all_node.ipv6_addr, 16) == 0)
\r
689 ret |= IPV6_ADDR_ALL_NODE_MULTICAST;
\r
691 else if (Cmp(ip->ipv6_addr, all_router.ipv6_addr, 16) == 0)
\r
693 ret |= IPV6_ADDR_ALL_ROUTER_MULTICAST;
\r
697 if (ip->ipv6_addr[1] == 0x02 && ip->ipv6_addr[2] == 0 && ip->ipv6_addr[3] == 0 &&
\r
698 ip->ipv6_addr[4] == 0 && ip->ipv6_addr[5] == 0 && ip->ipv6_addr[6] == 0 &&
\r
699 ip->ipv6_addr[7] == 0 && ip->ipv6_addr[8] == 0 && ip->ipv6_addr[9] == 0 &&
\r
700 ip->ipv6_addr[10] == 0 && ip->ipv6_addr[11] == 0x01 && ip->ipv6_addr[12] == 0xff)
\r
702 ret |= IPV6_ADDR_SOLICIATION_MULTICAST;
\r
708 ret |= IPV6_ADDR_UNICAST;
\r
710 if (ip->ipv6_addr[0] == 0xfe && (ip->ipv6_addr[1] & 0xc0) == 0x80)
\r
712 ret |= IPV6_ADDR_LOCAL_UNICAST;
\r
716 ret |= IPV6_ADDR_GLOBAL_UNICAST;
\r
718 if (IsZero(&ip->ipv6_addr, 16))
\r
720 ret |= IPV6_ADDR_ZERO;
\r
726 GetLoopbackAddress6(&loopback);
\r
728 if (Cmp(ip->ipv6_addr, loopback.ipv6_addr, 16) == 0)
\r
730 ret |= IPV6_ADDR_LOOPBACK;
\r
739 // すべてのビットが立っているアドレス
\r
740 void GetAllFilledAddress6(IP *ip)
\r
751 for (i = 0;i < 15;i++)
\r
753 ip->ipv6_addr[i] = 0xff;
\r
758 void GetLoopbackAddress6(IP *ip)
\r
768 ip->ipv6_addr[15] = 0x01;
\r
772 void GetAllNodeMulticaseAddress6(IP *ip)
\r
782 ip->ipv6_addr[0] = 0xff;
\r
783 ip->ipv6_addr[1] = 0x02;
\r
784 ip->ipv6_addr[15] = 0x01;
\r
788 void GetAllRouterMulticastAddress6(IP *ip)
\r
798 ip->ipv6_addr[0] = 0xff;
\r
799 ip->ipv6_addr[1] = 0x02;
\r
800 ip->ipv6_addr[15] = 0x02;
\r
804 void IPAnd6(IP *dst, IP *a, IP *b)
\r
808 if (dst == NULL || IsIP6(a) == false || IsIP6(b) == false)
\r
814 for (i = 0;i < 16;i++)
\r
816 dst->ipv6_addr[i] = a->ipv6_addr[i] & b->ipv6_addr[i];
\r
819 void IPOr6(IP *dst, IP *a, IP *b)
\r
823 if (dst == NULL || IsIP6(a) == false || IsIP6(b) == false)
\r
829 for (i = 0;i < 16;i++)
\r
831 dst->ipv6_addr[i] = a->ipv6_addr[i] | b->ipv6_addr[i];
\r
834 void IPNot6(IP *dst, IP *a)
\r
838 if (dst == NULL || IsIP6(a) == false)
\r
844 for (i = 0;i < 16;i++)
\r
846 dst->ipv6_addr[i] = ~(a->ipv6_addr[i]);
\r
851 void IntToSubnetMask6(IP *ip, UINT i)
\r
860 for (z = 0;z < 16;z++)
\r
864 a.ipv6_addr[z] = 0xff;
\r
868 a.ipv6_addr[z] = ~(0xff >> k);
\r
872 Copy(ip, &a, sizeof(IP));
\r
876 void IP6AddrToStr(char *str, UINT size, IPV6_ADDR *addr)
\r
879 if (str == NULL || addr == NULL)
\r
884 IPToStr6Array(str, size, addr->Value);
\r
886 void IPToStr6Array(char *str, UINT size, UCHAR *bytes)
\r
890 if (str == NULL || bytes == NULL)
\r
895 SetIP6(&ip, bytes);
\r
897 IPToStr6(str, size, &ip);
\r
899 void IPToStr6(char *str, UINT size, IP *ip)
\r
901 char tmp[MAX_SIZE];
\r
903 IPToStr6Inner(tmp, ip);
\r
905 StrCpy(str, size, tmp);
\r
907 void IPToStr6Inner(char *str, IP *ip)
\r
911 UINT zero_started_index;
\r
913 UINT max_zero_start;
\r
916 if (str == NULL || ip == NULL)
\r
921 Copy(&a, ip, sizeof(IP));
\r
923 for (i = 0;i < 8;i++)
\r
925 Copy(&values[i], &a.ipv6_addr[i * 2], sizeof(USHORT));
\r
926 values[i] = Endian16(values[i]);
\r
929 // 省略できる場所があるかどうか検索
\r
930 zero_started_index = INFINITE;
\r
932 max_zero_start = INFINITE;
\r
933 for (i = 0;i < 9;i++)
\r
935 USHORT v = (i != 8 ? values[i] : 1);
\r
937 if (values[i] == 0)
\r
939 if (zero_started_index == INFINITE)
\r
941 zero_started_index = i;
\r
948 if (zero_started_index != INFINITE)
\r
950 zero_len = i - zero_started_index;
\r
953 if (max_zero_len < zero_len)
\r
955 max_zero_start = zero_started_index;
\r
956 max_zero_len = zero_len;
\r
960 zero_started_index = INFINITE;
\r
966 StrCpy(str, 0, "");
\r
967 for (i = 0;i < 8;i++)
\r
971 ToHex(tmp, values[i]);
\r
974 if (i == max_zero_start)
\r
978 StrCat(str, 0, "::");
\r
982 StrCat(str, 0, ":");
\r
984 i += max_zero_len - 1;
\r
988 StrCat(str, 0, tmp);
\r
991 StrCat(str, 0, ":");
\r
997 if (ip->ipv6_scope_id != 0)
\r
1001 StrCat(str, 0, "%");
\r
1002 ToStr(tmp, ip->ipv6_scope_id);
\r
1004 StrCat(str, 0, tmp);
\r
1008 // 文字列を IP アドレスに変換
\r
1009 bool StrToIP6(IP *ip, char *str)
\r
1012 char tmp[MAX_PATH];
\r
1015 UINT scope_id = 0;
\r
1017 if (str == NULL || ip == NULL)
\r
1024 StrCpy(tmp, sizeof(tmp), str);
\r
1027 if (StartWith(tmp, "[") && EndWith(tmp, "]"))
\r
1029 // かぎかっこで囲まれている場合はそれを除去
\r
1030 StrCpy(tmp, sizeof(tmp), &tmp[1]);
\r
1032 if (StrLen(tmp) >= 1)
\r
1034 tmp[StrLen(tmp) - 1] = 0;
\r
1038 // スコープ ID がある場合はそれを解析して除去
\r
1039 i = SearchStrEx(tmp, "%", 0, false);
\r
1040 if (i != INFINITE)
\r
1042 char ss[MAX_PATH];
\r
1044 StrCpy(ss, sizeof(ss), &tmp[i + 1]);
\r
1052 scope_id = ToInt(ss);
\r
1056 t = ParseTokenWithNullStr(tmp, ":");
\r
1057 if (t->NumTokens >= 3 && t->NumTokens <= 8)
\r
1065 for (i = 0;i < t->NumTokens;i++)
\r
1067 char *str = t->Token[i];
\r
1069 if (i != 0 && i != (t->NumTokens - 1) && StrLen(str) == 0)
\r
1074 k += 2 * (8 - t->NumTokens + 1);
\r
1086 if (CheckIPItemStr6(str) == false)
\r
1092 IPItemStrToChars6(chars, str);
\r
1094 a.ipv6_addr[k++] = chars[0];
\r
1095 a.ipv6_addr[k++] = chars[1];
\r
1099 if (n != 0 && n != 1)
\r
1103 else if (n == 0 && t->NumTokens != 8)
\r
1122 Copy(ip, &a, sizeof(IP));
\r
1124 ip->ipv6_scope_id = scope_id;
\r
1128 bool StrToIP6Addr(IPV6_ADDR *ip, char *str)
\r
1132 if (ip == NULL || str == NULL)
\r
1134 Zero(ip, sizeof(IPV6_ADDR));
\r
1138 if (StrToIP6(&ip2, str) == false)
\r
1143 if (IPToIPv6Addr(ip, &ip2) == false)
\r
1151 // IP アドレスの文字から UCHAR 型に変換
\r
1152 void IPItemStrToChars6(UCHAR *chars, char *str)
\r
1158 if (chars == NULL)
\r
1163 Zero(tmp, sizeof(tmp));
\r
1165 len = StrLen(str);
\r
1169 tmp[0] = tmp[1] = tmp[2] = tmp[3] = '0';
\r
1173 tmp[0] = tmp[1] = tmp[2] = '0';
\r
1178 tmp[0] = tmp[1] = '0';
\r
1198 b = StrToBin(tmp);
\r
1200 chars[0] = ((UCHAR *)b->Buf)[0];
\r
1201 chars[1] = ((UCHAR *)b->Buf)[1];
\r
1206 // IP アドレスの要素文字列の中に不正な文字が含まれていないかどうかチェックする
\r
1207 bool CheckIPItemStr6(char *str)
\r
1216 len = StrLen(str);
\r
1223 for (i = 0;i < len;i++)
\r
1227 if ((c >= 'a' && c <= 'f') ||
\r
1228 (c >= 'A' && c <= 'F') ||
\r
1229 (c >= '0' && c <= '9'))
\r
1241 // ゼロの IPv4 アドレスを作成する
\r
1242 void ZeroIP4(IP *ip)
\r
1250 Zero(ip, sizeof(IP));
\r
1253 // ゼロの IPv6 アドレスを作成する
\r
1254 void ZeroIP6(IP *ip)
\r
1265 // localhost の IP アドレスを取得する
\r
1266 void GetLocalHostIP6(IP *ip)
\r
1270 ip->ipv6_addr[15] = 1;
\r
1273 // IPV6_ADDR を IP に変換
\r
1274 void IPv6AddrToIP(IP *ip, IPV6_ADDR *addr)
\r
1277 if (ip == NULL || addr == NULL)
\r
1282 SetIP6(ip, addr->Value);
\r
1285 // IP を IPV6_ADDR に変換
\r
1286 bool IPToIPv6Addr(IPV6_ADDR *addr, IP *ip)
\r
1290 if (addr == NULL || ip == NULL)
\r
1292 Zero(addr, sizeof(IPV6_ADDR));
\r
1296 if (IsIP6(ip) == false)
\r
1298 Zero(addr, sizeof(IPV6_ADDR));
\r
1302 for (i = 0;i < 16;i++)
\r
1304 addr->Value[i] = ip->ipv6_addr[i];
\r
1310 // IPv6 アドレスをセットする
\r
1311 void SetIP6(IP *ip, UCHAR *value)
\r
1319 Zero(ip, sizeof(IP));
\r
1321 ip->addr[0] = 223;
\r
1322 ip->addr[1] = 255;
\r
1323 ip->addr[2] = 255;
\r
1324 ip->addr[3] = 254;
\r
1326 if (value != NULL)
\r
1330 for (i = 0;i < 16;i++)
\r
1332 ip->ipv6_addr[i] = value[i];
\r
1337 // 指定されたアドレスが IPv6 アドレスかどうかチェックする
\r
1338 bool IsIP6(IP *ip)
\r
1346 if (ip->addr[0] == 223 && ip->addr[1] == 255 && ip->addr[2] == 255 && ip->addr[3] == 254)
\r
1353 bool IsIP4(IP *ip)
\r
1361 return (IsIP6(ip) ? false : true);
\r
1364 // IPv6 のサブネット長をチェック
\r
1365 bool CheckSubnetLength6(UINT i)
\r
1367 if (i >= 1 && i <= 127)
\r
1375 // ソケットから対応する TCP コネクションのプロセス ID を取得
\r
1376 UINT GetTcpProcessIdFromSocket(SOCK *s)
\r
1387 o = GetTcpTableList();
\r
1393 t = GetTcpTableFromEndPoint(o, &s->LocalIP, s->LocalPort,
\r
1394 &s->RemoteIP, s->RemotePort);
\r
1398 pid = t->ProcessId;
\r
1401 FreeTcpTableList(o);
\r
1405 UINT GetTcpProcessIdFromSocketReverse(SOCK *s)
\r
1416 o = GetTcpTableList();
\r
1422 t = GetTcpTableFromEndPoint(o, &s->RemoteIP, s->RemotePort,
\r
1423 &s->LocalIP, s->LocalPort);
\r
1427 pid = t->ProcessId;
\r
1430 FreeTcpTableList(o);
\r
1435 // エンドポイントから TCP テーブルを検索
\r
1436 TCPTABLE *GetTcpTableFromEndPoint(LIST *o, IP *local_ip, UINT local_port, IP *remote_ip, UINT remote_port)
\r
1446 SetIP(&local, 127, 0, 0, 1);
\r
1448 if (local_ip == NULL)
\r
1450 local_ip = &local;
\r
1453 if (remote_ip == NULL)
\r
1455 remote_ip = &local;
\r
1458 for (i = 0;i < LIST_NUM(o);i++)
\r
1460 TCPTABLE *t = LIST_DATA(o, i);
\r
1462 if (t->Status == TCP_STATE_SYN_SENT || t->Status == TCP_STATE_SYN_RCVD ||
\r
1463 t->Status == TCP_STATE_ESTAB)
\r
1465 if (CmpIpAddr(&t->LocalIP, local_ip) == 0)
\r
1467 if (CmpIpAddr(&t->RemoteIP, remote_ip) == 0)
\r
1469 if (t->LocalPort == local_port)
\r
1471 if (t->RemotePort == remote_port)
\r
1484 // TCP テーブルリストを取得 (Win32)
\r
1486 LIST *Win32GetTcpTableList()
\r
1490 // Windows XP SP2 以降用
\r
1491 o = Win32GetTcpTableListByGetExtendedTcpTable();
\r
1498 o = Win32GetTcpTableListByAllocateAndGetTcpExTableFromStack();
\r
1505 return Win32GetTcpTableListByGetTcpTable();
\r
1508 // TCP テーブルリストを取得: Windows XP SP2 以降用
\r
1509 LIST *Win32GetTcpTableListByGetExtendedTcpTable()
\r
1513 MIB_TCPTABLE_OWNER_PID *table;
\r
1516 if (w32net->GetExtendedTcpTable == NULL)
\r
1521 for (i = 0;i < 128;i++)
\r
1524 table = MallocFast(sizeof(MIB_TCPTABLE_OWNER_PID));
\r
1525 need_size = sizeof(MIB_TCPTABLE_OWNER_PID);
\r
1526 ret = w32net->GetExtendedTcpTable(table, &need_size, true, AF_INET, _TCP_TABLE_OWNER_PID_ALL, 0);
\r
1527 if (ret == NO_ERROR)
\r
1535 if (ret != ERROR_INSUFFICIENT_BUFFER)
\r
1541 table = MallocFast(need_size);
\r
1543 ret = w32net->GetExtendedTcpTable(table, &need_size, true, AF_INET, _TCP_TABLE_OWNER_PID_ALL, 0);
\r
1544 if (ret == NO_ERROR)
\r
1553 if (ret != ERROR_INSUFFICIENT_BUFFER)
\r
1565 o = NewListEx(NULL, true);
\r
1567 for (i = 0;i < table->dwNumEntries;i++)
\r
1569 MIB_TCPROW_OWNER_PID *r = &table->table[i];
\r
1570 TCPTABLE *t = ZeroMallocFast(sizeof(TCPTABLE));
\r
1572 UINTToIP(&t->LocalIP, r->dwLocalAddr);
\r
1573 t->LocalPort = Endian16((USHORT)r->dwLocalPort);
\r
1575 if (r->dwState != TCP_STATE_LISTEN)
\r
1577 UINTToIP(&t->RemoteIP, r->dwRemoteAddr);
\r
1578 t->RemotePort = Endian16((USHORT)r->dwRemotePort);
\r
1581 t->Status = r->dwState;
\r
1582 t->ProcessId = r->dwOwningPid;
\r
1592 // TCP テーブルリストを取得: Windows XP 以降用
\r
1593 LIST *Win32GetTcpTableListByAllocateAndGetTcpExTableFromStack()
\r
1597 MIB_TCPTABLE_OWNER_PID *table;
\r
1600 if (w32net->AllocateAndGetTcpExTableFromStack == NULL)
\r
1605 heap = GetProcessHeap();
\r
1607 if (w32net->AllocateAndGetTcpExTableFromStack(&table, true, heap, HEAP_GROWABLE, AF_INET) != ERROR_SUCCESS)
\r
1612 o = NewListEx(NULL, true);
\r
1614 for (i = 0;i < table->dwNumEntries;i++)
\r
1616 MIB_TCPROW_OWNER_PID *r = &table->table[i];
\r
1617 TCPTABLE *t = ZeroMallocFast(sizeof(TCPTABLE));
\r
1619 UINTToIP(&t->LocalIP, r->dwLocalAddr);
\r
1620 t->LocalPort = Endian16((USHORT)r->dwLocalPort);
\r
1622 if (r->dwState != TCP_STATE_LISTEN)
\r
1624 UINTToIP(&t->RemoteIP, r->dwRemoteAddr);
\r
1625 t->RemotePort = Endian16((USHORT)r->dwRemotePort);
\r
1628 t->ProcessId = r->dwOwningPid;
\r
1629 t->Status = r->dwState;
\r
1634 HeapFree(heap, 0, table);
\r
1639 // TCP テーブルリストを取得: 古い Windows 用
\r
1640 LIST *Win32GetTcpTableListByGetTcpTable()
\r
1644 MIB_TCPTABLE *table;
\r
1647 if (w32net->GetTcpTable == NULL)
\r
1652 for (i = 0;i < 128;i++)
\r
1655 table = MallocFast(sizeof(MIB_TCPTABLE));
\r
1656 need_size = sizeof(MIB_TCPTABLE);
\r
1657 ret = w32net->GetTcpTable(table, &need_size, true);
\r
1658 if (ret == NO_ERROR)
\r
1666 if (ret != ERROR_INSUFFICIENT_BUFFER)
\r
1672 table = MallocFast(need_size);
\r
1674 ret = w32net->GetTcpTable(table, &need_size, true);
\r
1675 if (ret == NO_ERROR)
\r
1684 if (ret != ERROR_INSUFFICIENT_BUFFER)
\r
1696 o = NewListEx(NULL, true);
\r
1698 for (i = 0;i < table->dwNumEntries;i++)
\r
1700 MIB_TCPROW *r = &table->table[i];
\r
1701 TCPTABLE *t = ZeroMallocFast(sizeof(TCPTABLE));
\r
1703 UINTToIP(&t->LocalIP, r->dwLocalAddr);
\r
1704 t->LocalPort = Endian16((USHORT)r->dwLocalPort);
\r
1706 if (r->dwState != TCP_STATE_LISTEN)
\r
1708 UINTToIP(&t->RemoteIP, r->dwRemoteAddr);
\r
1709 t->RemotePort = Endian16((USHORT)r->dwRemotePort);
\r
1712 t->Status = r->dwState;
\r
1722 #endif // OS_WIN32
\r
1725 void PrintTcpTableList(LIST *o)
\r
1731 Print("o == NULL\n\n");
\r
1735 Print("--- TCPTABLE: %u Entries ---\n", LIST_NUM(o));
\r
1736 for (i = 0;i < LIST_NUM(o);i++)
\r
1738 char tmp1[MAX_PATH], tmp2[MAX_PATH];
\r
1739 TCPTABLE *t = LIST_DATA(o, i);
\r
1741 IPToStr(tmp1, sizeof(tmp1), &t->LocalIP);
\r
1742 IPToStr(tmp2, sizeof(tmp2), &t->RemoteIP);
\r
1744 Print("%s:%u <--> %s:%u state=%u pid=%u\n",
\r
1745 tmp1, t->LocalPort,
\r
1746 tmp2, t->RemotePort,
\r
1750 Print("------\n\n");
\r
1754 int CompareTcpTable(void *p1, void *p2)
\r
1756 TCPTABLE *t1, *t2;
\r
1757 if (p1 == NULL || p2 == NULL)
\r
1761 t1 = *(TCPTABLE **)p1;
\r
1762 t2 = *(TCPTABLE **)p2;
\r
1763 if (t1 == NULL || t2 == NULL)
\r
1768 return Cmp(t1, t2, sizeof(TCPTABLE));
\r
1772 LIST *GetTcpTableList()
\r
1775 return Win32GetTcpTableList();
\r
1778 #endif // OS_WIN32
\r
1782 void FreeTcpTableList(LIST *o)
\r
1791 for (i = 0;i < LIST_NUM(o);i++)
\r
1793 TCPTABLE *t = LIST_DATA(o, i);
\r
1801 // 指定された IP アドレスから接続中のクライアント数の取得
\r
1802 UINT GetNumIpClient(IP *ip)
\r
1812 LockList(ip_clients);
\r
1814 c = SearchIpClient(ip);
\r
1818 ret = c->NumConnections;
\r
1821 UnlockList(ip_clients);
\r
1826 // IP クライアントエントリに追加
\r
1827 void AddIpClient(IP *ip)
\r
1836 LockList(ip_clients);
\r
1838 c = SearchIpClient(ip);
\r
1842 c = ZeroMallocFast(sizeof(IP_CLIENT));
\r
1843 Copy(&c->IpAddress, ip, sizeof(IP));
\r
1844 c->NumConnections = 0;
\r
1846 Add(ip_clients, c);
\r
1849 c->NumConnections++;
\r
1851 UnlockList(ip_clients);
\r
1854 // IP クライアントリストから削除
\r
1855 void DelIpClient(IP *ip)
\r
1864 LockList(ip_clients);
\r
1866 c = SearchIpClient(ip);
\r
1870 c->NumConnections--;
\r
1872 if (c->NumConnections == 0)
\r
1874 Delete(ip_clients, c);
\r
1879 UnlockList(ip_clients);
\r
1882 // IP クライアントエントリの検索
\r
1883 IP_CLIENT *SearchIpClient(IP *ip)
\r
1892 Zero(&t, sizeof(t));
\r
1893 Copy(&t.IpAddress, ip, sizeof(IP));
\r
1895 return Search(ip_clients, &t);
\r
1899 void InitIpClientList()
\r
1901 ip_clients = NewList(CompareIpClientList);
\r
1905 void FreeIpClientList()
\r
1909 for (i = 0;i < LIST_NUM(ip_clients);i++)
\r
1911 IP_CLIENT *c = LIST_DATA(ip_clients, i);
\r
1916 ReleaseList(ip_clients);
\r
1917 ip_clients = NULL;
\r
1920 // クライアントリストエントリの比較
\r
1921 int CompareIpClientList(void *p1, void *p2)
\r
1923 IP_CLIENT *c1, *c2;
\r
1924 if (p1 == NULL || p2 == NULL)
\r
1928 c1 = *(IP_CLIENT **)p1;
\r
1929 c2 = *(IP_CLIENT **)p2;
\r
1930 if (c1 == NULL || c2 == NULL)
\r
1935 return CmpIpAddr(&c1->IpAddress, &c2->IpAddress);
\r
1939 bool NormalizeMacAddress(char *dst, UINT size, char *src)
\r
1944 if (dst == NULL || src == NULL)
\r
1949 b = StrToBin(src);
\r
1951 if (b != NULL && b->Size == 6)
\r
1955 BinToStr(dst, size, b->Buf, b->Size);
\r
1963 // IP アドレスが空かどうか識別する
\r
1964 bool IsZeroIP(IP *ip)
\r
1966 return IsZeroIp(ip);
\r
1968 bool IsZeroIp(IP *ip)
\r
1976 if (IsIP6(ip) == false)
\r
1978 return IsZero(ip->addr, sizeof(ip->addr));
\r
1982 return IsZero(ip->ipv6_addr, sizeof(ip->ipv6_addr));
\r
1985 bool IsZeroIP6Addr(IPV6_ADDR *addr)
\r
1993 return IsZero(addr, sizeof(IPV6_ADDR));
\r
1996 // 指定された IP アドレスがホストとして意味があるかどうかを調べる
\r
1997 bool IsHostIPAddress4(IP *ip)
\r
2008 if (a == 0 || a == 0xffffffff)
\r
2015 bool IsHostIPAddress32(UINT ip)
\r
2021 return IsHostIPAddress4(&p);
\r
2024 // 指定された IP アドレスとサブネットマスクが正しくネットワークを示すかどうか調べる
\r
2025 bool IsNetworkAddress(IP *ip, IP *mask)
\r
2029 return IsNetworkAddress4(ip, mask);
\r
2033 return IsNetworkAddress6(ip, mask);
\r
2036 bool IsNetworkAddress4(IP *ip, IP *mask)
\r
2040 if (ip == NULL || mask == NULL)
\r
2045 if (IsIP4(ip) == false || IsIP4(mask) == false)
\r
2050 if (IsSubnetMask4(mask) == false)
\r
2056 b = IPToUINT(mask);
\r
2065 bool IsNetworkAddress32(UINT ip, UINT mask)
\r
2070 UINTToIP(&b, mask);
\r
2072 return IsNetworkAddress4(&a, &b);
\r
2075 // 整数をサブネットマスクに変換する
\r
2076 UINT IntToSubnetMask32(UINT i)
\r
2078 UINT ret = 0xFFFFFFFF;
\r
2083 case 0: ret = 0x00000000; break;
\r
2084 case 1: ret = 0x80000000; break;
\r
2085 case 2: ret = 0xC0000000; break;
\r
2086 case 3: ret = 0xE0000000; break;
\r
2087 case 4: ret = 0xF0000000; break;
\r
2088 case 5: ret = 0xF8000000; break;
\r
2089 case 6: ret = 0xFC000000; break;
\r
2090 case 7: ret = 0xFE000000; break;
\r
2091 case 8: ret = 0xFF000000; break;
\r
2092 case 9: ret = 0xFF800000; break;
\r
2093 case 10: ret = 0xFFC00000; break;
\r
2094 case 11: ret = 0xFFE00000; break;
\r
2095 case 12: ret = 0xFFF00000; break;
\r
2096 case 13: ret = 0xFFF80000; break;
\r
2097 case 14: ret = 0xFFFC0000; break;
\r
2098 case 15: ret = 0xFFFE0000; break;
\r
2099 case 16: ret = 0xFFFF0000; break;
\r
2100 case 17: ret = 0xFFFF8000; break;
\r
2101 case 18: ret = 0xFFFFC000; break;
\r
2102 case 19: ret = 0xFFFFE000; break;
\r
2103 case 20: ret = 0xFFFFF000; break;
\r
2104 case 21: ret = 0xFFFFF800; break;
\r
2105 case 22: ret = 0xFFFFFC00; break;
\r
2106 case 23: ret = 0xFFFFFE00; break;
\r
2107 case 24: ret = 0xFFFFFF00; break;
\r
2108 case 25: ret = 0xFFFFFF80; break;
\r
2109 case 26: ret = 0xFFFFFFC0; break;
\r
2110 case 27: ret = 0xFFFFFFE0; break;
\r
2111 case 28: ret = 0xFFFFFFF0; break;
\r
2112 case 29: ret = 0xFFFFFFF8; break;
\r
2113 case 30: ret = 0xFFFFFFFC; break;
\r
2114 case 31: ret = 0xFFFFFFFE; break;
\r
2115 case 32: ret = 0xFFFFFFFF; break;
\r
2118 if (IsLittleEndian())
\r
2120 ret = Swap32(ret);
\r
2125 void IntToSubnetMask4(IP *ip, UINT i)
\r
2134 m = IntToSubnetMask32(i);
\r
2139 // 指定された IP アドレスがサブネットマスクかどうか調べる
\r
2140 bool IsSubnetMask(IP *ip)
\r
2144 return IsSubnetMask6(ip);
\r
2148 return IsSubnetMask4(ip);
\r
2151 bool IsSubnetMask4(IP *ip)
\r
2167 if (IsLittleEndian())
\r
2213 bool IsSubnetMask32(UINT ip)
\r
2219 return IsSubnetMask4(&p);
\r
2223 void SetNetworkReleaseMode()
\r
2225 NetworkReleaseMode = true;
\r
2228 #ifdef OS_UNIX // UNIX 用コード
\r
2230 // ソケットをノンブロッキングモードにしたり解除したりする
\r
2231 void UnixSetSocketNonBlockingMode(int fd, bool nonblock)
\r
2235 if (fd == INVALID_SOCKET)
\r
2246 ioctl(fd, FIONBIO, &flag);
\r
2249 int flag = fcntl(fd, F_GETFL, 0);
\r
2254 flag |= O_NONBLOCK;
\r
2258 flag = flag & ~O_NONBLOCK;
\r
2260 fcntl(fd, F_SETFL, flag);
\r
2268 void UnixIpForwardRowToRouteEntry(ROUTE_ENTRY *entry, void *ip_forward_row)
\r
2273 void UnixRouteEntryToIpForwardRow(void *ip_forward_row, ROUTE_ENTRY *entry)
\r
2278 int UnixCompareRouteEntryByMetric(void *p1, void *p2)
\r
2284 ROUTE_TABLE *UnixGetRouteTable()
\r
2286 ROUTE_TABLE *ret = ZeroMalloc(sizeof(ROUTE_TABLE));
\r
2287 ret->NumEntry = 0;
\r
2288 ret->Entry = ZeroMalloc(0);
\r
2294 bool UnixAddRouteEntry(ROUTE_ENTRY *e, bool *already_exists)
\r
2300 void UnixDeleteRouteEntry(ROUTE_ENTRY *e)
\r
2306 UINT UnixGetVLanInterfaceID(char *instance_name)
\r
2312 char **UnixEnumVLan(char *tag_name)
\r
2316 list = ZeroMalloc(sizeof(char *));
\r
2322 void UnixRenewDhcp()
\r
2326 // デフォルトの DNS サーバーの IP アドレスを取得
\r
2327 bool UnixGetDefaultDns(IP *ip)
\r
2336 Lock(unix_dns_server_addr_lock);
\r
2338 if (IsZero(&unix_dns_server, sizeof(IP)) == false)
\r
2340 Copy(ip, &unix_dns_server, sizeof(IP));
\r
2341 Unlock(unix_dns_server_addr_lock);
\r
2345 ip->addr[0] = 127;
\r
2350 b = ReadDump("/etc/resolv.conf");
\r
2355 while ((s = CfgReadNextLine(b)) != NULL)
\r
2357 TOKEN_LIST *t = ParseToken(s, "\" \t,");
\r
2358 if (t->NumTokens == 2)
\r
2360 if (StrCmpi(t->Token[0], "nameserver") == 0)
\r
2362 StrToIP(ip, t->Token[1]);
\r
2377 Copy(&unix_dns_server, ip, sizeof(IP));
\r
2379 Unlock(unix_dns_server_addr_lock);
\r
2386 void UnixSelect(SOCKSET *set, UINT timeout, CANCEL *c1, CANCEL *c2)
\r
2388 UINT reads[MAXIMUM_WAIT_OBJECTS];
\r
2389 UINT writes[MAXIMUM_WAIT_OBJECTS];
\r
2390 UINT num_read, num_write, i;
\r
2393 UCHAR tmp[MAX_SIZE];
\r
2401 Zero(reads, sizeof(reads));
\r
2402 Zero(writes, sizeof(writes));
\r
2403 num_read = num_write = 0;
\r
2408 for (i = 0;i < set->NumSocket;i++)
\r
2413 UnixInitAsyncSocket(s);
\r
2414 reads[num_read++] = s->socket;
\r
2415 if (s->WriteBlocked)
\r
2417 writes[num_write++] = s->socket;
\r
2427 reads[num_read++] = p1 = c1->pipe_read;
\r
2431 reads[num_read++] = p2 = c2->pipe_read;
\r
2435 UnixSelectInner(num_read, reads, num_write, writes, timeout);
\r
2438 if (c1 != NULL && c1->SpecialFlag == false && p1 != -1)
\r
2440 read(p1, tmp, sizeof(tmp));
\r
2442 if (c2 != NULL && c2->SpecialFlag == false && p2 != -1)
\r
2444 read(p2, tmp, sizeof(tmp));
\r
2449 void UnixCancel(CANCEL *c)
\r
2457 UnixWritePipe(c->pipe_write);
\r
2461 void UnixCleanupCancel(CANCEL *c)
\r
2469 if (c->SpecialFlag == false)
\r
2471 UnixDeletePipe(c->pipe_read, c->pipe_write);
\r
2477 // 新しいキャンセルオブジェクトの作成
\r
2478 CANCEL *UnixNewCancel()
\r
2480 CANCEL *c = ZeroMallocFast(sizeof(CANCEL));
\r
2482 c->ref = NewRef();
\r
2483 c->SpecialFlag = false;
\r
2485 UnixNewPipe(&c->pipe_read, &c->pipe_write);
\r
2490 // ソケットをソケットイベントに追加する
\r
2491 void UnixJoinSockToSockEvent(SOCK *sock, SOCK_EVENT *event)
\r
2494 if (sock == NULL || event == NULL || sock->AsyncMode)
\r
2498 if (sock->ListenMode != false || (sock->Type == SOCK_TCP && sock->Connected == false))
\r
2503 sock->AsyncMode = true;
\r
2505 LockList(event->SockList);
\r
2507 Add(event->SockList, sock);
\r
2508 AddRef(sock->ref);
\r
2510 UnlockList(event->SockList);
\r
2513 UnixSetSocketNonBlockingMode(sock->socket, true);
\r
2515 // SOCK_EVENT の参照カウンタを増加
\r
2516 AddRef(event->ref);
\r
2517 sock->SockEvent = event;
\r
2520 SetSockEvent(event);
\r
2524 bool UnixWaitSockEvent(SOCK_EVENT *event, UINT timeout)
\r
2526 UINT num_read, num_write;
\r
2527 UINT *reads, *writes;
\r
2529 char tmp[MAX_SIZE];
\r
2531 if (event == NULL)
\r
2536 LockList(event->SockList);
\r
2539 num_read = LIST_NUM(event->SockList) + 1;
\r
2540 reads = ZeroMallocFast(sizeof(SOCK *) * num_read);
\r
2544 for (i = 0;i < (num_read - 1);i++)
\r
2546 SOCK *s = LIST_DATA(event->SockList, i);
\r
2547 reads[i] = s->socket;
\r
2548 if (s->WriteBlocked)
\r
2554 reads[num_read - 1] = event->pipe_read;
\r
2556 writes = ZeroMallocFast(sizeof(SOCK *) * num_write);
\r
2560 for (i = 0;i < (num_read - 1);i++)
\r
2562 SOCK *s = LIST_DATA(event->SockList, i);
\r
2563 if (s->WriteBlocked)
\r
2565 writes[n++] = s->socket;
\r
2569 UnlockList(event->SockList);
\r
2574 Print("UnixSelectInner: ");
\r
2575 for (i = 0;i < num_read;i++)
\r
2577 Print("%u ", reads[i]);
\r
2582 UnixSelectInner(num_read, reads, num_write, writes, timeout);
\r
2584 read(event->pipe_read, tmp, sizeof(tmp));
\r
2593 void UnixSetSockEvent(SOCK_EVENT *event)
\r
2596 if (event == NULL)
\r
2601 UnixWritePipe(event->pipe_write);
\r
2604 // ソケットの select の実行
\r
2605 void UnixSelectInner(UINT num_read, UINT *reads, UINT num_write, UINT *writes, UINT timeout)
\r
2611 UINT num_read_total, num_write_total;
\r
2613 if (num_read != 0 && reads == NULL)
\r
2617 if (num_write != 0 && writes == NULL)
\r
2627 num_read_total = num_write_total = 0;
\r
2628 for (i = 0;i < num_read;i++)
\r
2630 if (reads[i] != INVALID_SOCKET)
\r
2635 for (i = 0;i < num_write;i++)
\r
2637 if (writes[i] != INVALID_SOCKET)
\r
2639 num_write_total++;
\r
2643 num = num_read_total + num_write_total;
\r
2644 p = ZeroMallocFast(sizeof(struct pollfd) * num);
\r
2648 for (i = 0;i < num_read;i++)
\r
2650 if (reads[i] != INVALID_SOCKET)
\r
2652 struct pollfd *pfd = &p[n++];
\r
2653 pfd->fd = reads[i];
\r
2654 pfd->events = POLLIN | POLLPRI | POLLERR | POLLHUP;
\r
2658 for (i = 0;i < num_write;i++)
\r
2660 if (writes[i] != INVALID_SOCKET)
\r
2662 struct pollfd *pfd = &p[n++];
\r
2663 pfd->fd = writes[i];
\r
2664 pfd->events = POLLIN | POLLPRI | POLLERR | POLLHUP | POLLOUT;
\r
2670 poll(p, num, timeout == INFINITE ? -1 : (int)timeout);
\r
2674 SleepThread(timeout);
\r
2680 // ソケットイベントのクリーンアップ
\r
2681 void UnixCleanupSockEvent(SOCK_EVENT *event)
\r
2685 if (event == NULL)
\r
2690 for (i = 0;i < LIST_NUM(event->SockList);i++)
\r
2692 SOCK *s = LIST_DATA(event->SockList, i);
\r
2697 ReleaseList(event->SockList);
\r
2699 UnixDeletePipe(event->pipe_read, event->pipe_write);
\r
2705 SOCK_EVENT *UnixNewSockEvent()
\r
2707 SOCK_EVENT *e = ZeroMallocFast(sizeof(SOCK_EVENT));
\r
2709 e->SockList = NewList(NULL);
\r
2710 e->ref = NewRef();
\r
2712 UnixNewPipe(&e->pipe_read, &e->pipe_write);
\r
2718 void UnixDeletePipe(int p1, int p2)
\r
2732 void UnixWritePipe(int pipe_write)
\r
2735 write(pipe_write, &c, 1);
\r
2739 void UnixNewPipe(int *pipe_read, int *pipe_write)
\r
2743 if (pipe_read == NULL || pipe_write == NULL)
\r
2748 fd[0] = fd[1] = 0;
\r
2752 *pipe_read = fd[0];
\r
2753 *pipe_write = fd[1];
\r
2755 UnixSetSocketNonBlockingMode(*pipe_write, true);
\r
2756 UnixSetSocketNonBlockingMode(*pipe_read, true);
\r
2760 void UnixFreeAsyncSocket(SOCK *sock)
\r
2771 if (sock->AsyncMode == false)
\r
2773 Unlock(sock->lock);
\r
2777 sock->AsyncMode = false;
\r
2779 // このソケットが SockEvent に関連付けられているかどうか調べる
\r
2780 if (sock->SockEvent != NULL)
\r
2782 SOCK_EVENT *e = sock->SockEvent;
\r
2786 p = e->pipe_write;
\r
2787 LockList(e->SockList);
\r
2789 if (Delete(e->SockList, sock))
\r
2791 ReleaseSock(sock);
\r
2794 UnlockList(e->SockList);
\r
2797 ReleaseSockEvent(sock->SockEvent);
\r
2798 sock->SockEvent = NULL;
\r
2802 ReleaseSockEvent(e);
\r
2805 Unlock(sock->lock);
\r
2809 void UnixInitAsyncSocket(SOCK *sock)
\r
2816 if (sock->AsyncMode)
\r
2818 // すでに非同期ソケットになっている
\r
2821 if (sock->ListenMode != false || (sock->Type == SOCK_TCP && sock->Connected == false))
\r
2826 sock->AsyncMode = true;
\r
2828 UnixSetSocketNonBlockingMode(sock->socket, true);
\r
2832 void UnixInitSocketLibrary()
\r
2838 void UnixFreeSocketLibrary()
\r
2845 #ifdef OS_WIN32 // Windows 用コード
\r
2847 NETWORK_WIN32_FUNCTIONS *w32net;
\r
2849 // IP_ADAPTER_INDEX_MAP の比較
\r
2850 int CompareIpAdapterIndexMap(void *p1, void *p2)
\r
2852 IP_ADAPTER_INDEX_MAP *a1, *a2;
\r
2853 if (p1 == NULL || p2 == NULL)
\r
2857 a1 = *(IP_ADAPTER_INDEX_MAP **)p1;
\r
2858 a2 = *(IP_ADAPTER_INDEX_MAP **)p2;
\r
2859 if (a1 == NULL || a2 == NULL)
\r
2864 if (a1->Index > a2->Index)
\r
2868 else if (a1->Index < a2->Index)
\r
2878 // アダプタの IP アドレスを更新
\r
2879 bool Win32RenewAddressByGuid(char *guid)
\r
2881 IP_ADAPTER_INDEX_MAP a;
\r
2888 Zero(&a, sizeof(a));
\r
2889 if (Win32GetAdapterFromGuid(&a, guid) == false)
\r
2894 return Win32RenewAddress(&a);
\r
2896 bool Win32RenewAddress(void *a)
\r
2904 if (w32net->IpRenewAddress == NULL)
\r
2909 ret = w32net->IpRenewAddress(a);
\r
2911 if (ret == NO_ERROR)
\r
2917 Debug("IpRenewAddress: Error: %u\n", ret);
\r
2922 // アダプタの IP アドレスを解放
\r
2923 bool Win32ReleaseAddress(void *a)
\r
2931 if (w32net->IpReleaseAddress == NULL)
\r
2936 ret = w32net->IpReleaseAddress(a);
\r
2938 if (ret == NO_ERROR)
\r
2944 Debug("IpReleaseAddress: Error: %u\n", ret);
\r
2948 bool Win32ReleaseAddressByGuid(char *guid)
\r
2950 IP_ADAPTER_INDEX_MAP a;
\r
2957 Zero(&a, sizeof(a));
\r
2958 if (Win32GetAdapterFromGuid(&a, guid) == false)
\r
2963 return Win32ReleaseAddress(&a);
\r
2965 void Win32ReleaseAddressByGuidExThread(THREAD *t, void *param)
\r
2967 WIN32_RELEASEADDRESS_THREAD_PARAM *p;
\r
2969 if (t == NULL || param == NULL)
\r
2974 p = (WIN32_RELEASEADDRESS_THREAD_PARAM *)param;
\r
2978 NoticeThreadInit(t);
\r
2982 if (p->Renew == false)
\r
2984 p->Ok = Win32ReleaseAddressByGuid(p->Guid);
\r
2988 p->Ok = Win32RenewAddressByGuid(p->Guid);
\r
2991 ReleaseWin32ReleaseAddressByGuidThreadParam(p);
\r
2995 bool Win32RenewAddressByGuidEx(char *guid, UINT timeout)
\r
2997 return Win32ReleaseOrRenewAddressByGuidEx(guid, timeout, true);
\r
2999 bool Win32ReleaseAddressByGuidEx(char *guid, UINT timeout)
\r
3001 return Win32ReleaseOrRenewAddressByGuidEx(guid, timeout, false);
\r
3003 bool Win32ReleaseOrRenewAddressByGuidEx(char *guid, UINT timeout, bool renew)
\r
3006 WIN32_RELEASEADDRESS_THREAD_PARAM *p;
\r
3008 UINT64 start_tick = 0;
\r
3009 UINT64 end_tick = 0;
\r
3017 timeout = INFINITE;
\r
3020 p = ZeroMalloc(sizeof(WIN32_RELEASEADDRESS_THREAD_PARAM));
\r
3021 p->Ref = NewRef();
\r
3022 StrCpy(p->Guid, sizeof(p->Guid), guid);
\r
3023 p->Timeout = timeout;
\r
3026 t = NewThread(Win32ReleaseAddressByGuidExThread, p);
\r
3027 WaitThreadInit(t);
\r
3028 start_tick = Tick64();
\r
3029 end_tick = start_tick + (UINT64)timeout;
\r
3033 UINT64 now = Tick64();
\r
3037 if (now >= end_tick)
\r
3042 remain = end_tick - now;
\r
3043 remain32 = MIN((UINT)remain, 100);
\r
3045 if (WaitThread(t, remain32))
\r
3058 ReleaseWin32ReleaseAddressByGuidThreadParam(p);
\r
3062 void ReleaseWin32ReleaseAddressByGuidThreadParam(WIN32_RELEASEADDRESS_THREAD_PARAM *p)
\r
3070 if (Release(p->Ref) == 0)
\r
3076 // アダプタを GUID から取得
\r
3077 bool Win32GetAdapterFromGuid(void *a, char *guid)
\r
3080 IP_INTERFACE_INFO *info;
\r
3084 wchar_t tmp[MAX_SIZE];
\r
3087 if (a == NULL || guid == NULL)
\r
3091 if (w32net->GetInterfaceInfo == NULL)
\r
3096 UniFormat(tmp, sizeof(tmp), L"\\DEVICE\\TCPIP_%S", guid);
\r
3098 size = sizeof(IP_INTERFACE_INFO);
\r
3099 info = ZeroMallocFast(size);
\r
3101 if (w32net->GetInterfaceInfo(info, &size) == ERROR_INSUFFICIENT_BUFFER)
\r
3104 info = ZeroMallocFast(size);
\r
3107 if (w32net->GetInterfaceInfo(info, &size) != NO_ERROR)
\r
3113 o = NewListFast(CompareIpAdapterIndexMap);
\r
3115 for (i = 0;i < info->NumAdapters;i++)
\r
3117 IP_ADAPTER_INDEX_MAP *a = &info->Adapter[i];
\r
3124 for (i = 0;i < (int)(LIST_NUM(o));i++)
\r
3126 IP_ADAPTER_INDEX_MAP *e = LIST_DATA(o, i);
\r
3128 if (UniStrCmpi(e->Name, tmp) == 0)
\r
3130 Copy(a, e, sizeof(IP_ADAPTER_INDEX_MAP));
\r
3144 void Win32NetworkTest()
\r
3146 IP_INTERFACE_INFO *info;
\r
3151 size = sizeof(IP_INTERFACE_INFO);
\r
3152 info = ZeroMallocFast(size);
\r
3154 if (w32net->GetInterfaceInfo(info, &size) == ERROR_INSUFFICIENT_BUFFER)
\r
3157 info = ZeroMallocFast(size);
\r
3160 if (w32net->GetInterfaceInfo(info, &size) != NO_ERROR)
\r
3166 o = NewListFast(CompareIpAdapterIndexMap);
\r
3168 for (i = 0;i < info->NumAdapters;i++)
\r
3170 IP_ADAPTER_INDEX_MAP *a = &info->Adapter[i];
\r
3177 for (i = 0;i < (int)(LIST_NUM(o));i++)
\r
3179 IP_ADAPTER_INDEX_MAP *a = LIST_DATA(o, i);
\r
3189 // 指定された LAN カードの DHCP アドレスを更新する
\r
3190 void Win32RenewDhcp9x(UINT if_id)
\r
3192 IP_INTERFACE_INFO *info;
\r
3202 size = sizeof(IP_INTERFACE_INFO);
\r
3203 info = ZeroMallocFast(size);
\r
3205 if (w32net->GetInterfaceInfo(info, &size) == ERROR_INSUFFICIENT_BUFFER)
\r
3208 info = ZeroMallocFast(size);
\r
3211 if (w32net->GetInterfaceInfo(info, &size) != NO_ERROR)
\r
3217 o = NewListFast(CompareIpAdapterIndexMap);
\r
3219 for (i = 0;i < info->NumAdapters;i++)
\r
3221 IP_ADAPTER_INDEX_MAP *a = &info->Adapter[i];
\r
3228 for (i = 0;i < (int)(LIST_NUM(o));i++)
\r
3230 IP_ADAPTER_INDEX_MAP *a = LIST_DATA(o, i);
\r
3232 if (a->Index == if_id)
\r
3234 char arg[MAX_PATH];
\r
3235 Format(arg, sizeof(arg), "/renew %u", i);
\r
3236 Run("ipconfig.exe", arg, true, false);
\r
3245 // 指定された LAN カードの DHCP アドレスを解放する
\r
3246 void Win32ReleaseDhcp9x(UINT if_id, bool wait)
\r
3248 IP_INTERFACE_INFO *info;
\r
3258 size = sizeof(IP_INTERFACE_INFO);
\r
3259 info = ZeroMallocFast(size);
\r
3261 if (w32net->GetInterfaceInfo(info, &size) == ERROR_INSUFFICIENT_BUFFER)
\r
3264 info = ZeroMallocFast(size);
\r
3267 if (w32net->GetInterfaceInfo(info, &size) != NO_ERROR)
\r
3273 o = NewListFast(CompareIpAdapterIndexMap);
\r
3275 for (i = 0;i < info->NumAdapters;i++)
\r
3277 IP_ADAPTER_INDEX_MAP *a = &info->Adapter[i];
\r
3284 for (i = 0;i < (int)(LIST_NUM(o));i++)
\r
3286 IP_ADAPTER_INDEX_MAP *a = LIST_DATA(o, i);
\r
3288 if (a->Index == if_id)
\r
3290 char arg[MAX_PATH];
\r
3291 Format(arg, sizeof(arg), "/release %u", i);
\r
3292 Run("ipconfig.exe", arg, true, wait);
\r
3301 // DHCP サーバーから IP アドレスを再取得する
\r
3302 void Win32RenewDhcp()
\r
3304 if (OS_IS_WINDOWS_NT(GetOsInfo()->OsType))
\r
3306 Run("ipconfig.exe", "/renew", true, false);
\r
3309 Run("ipconfig.exe", "/renew6", true, false);
\r
3313 Run("netsh.exe", "int ipv6 renew", true, false);
\r
3318 Run("ipconfig.exe", "/renew_all", true, false);
\r
3322 // 指定された文字列を含む仮想 LAN カードの一覧を列挙する
\r
3323 char **Win32EnumVLan(char *tag_name)
\r
3328 UINT num_retry = 0;
\r
3333 if (tag_name == 0)
\r
3339 p = ZeroMallocFast(sizeof(MIB_IFTABLE));
\r
3343 ret = w32net->GetIfTable(p, &size_needed, 0);
\r
3344 if (ret == ERROR_INSUFFICIENT_BUFFER)
\r
3346 // 必要なサイズ分のメモリブロックを再確保
\r
3348 p = ZeroMallocFast(size_needed);
\r
3350 else if (ret != NO_ERROR)
\r
3359 ret = w32net->GetIfTable(p, &size_needed, FALSE);
\r
3360 if (ret != NO_ERROR)
\r
3363 if ((++num_retry) >= 5)
\r
3373 o = NewListFast(CompareStr);
\r
3374 for (i = 0;i < p->dwNumEntries;i++)
\r
3376 MIB_IFROW *r = &p->table[i];
\r
3377 if (SearchStrEx(r->bDescr, tag_name, 0, false) != INFINITE)
\r
3379 char *s = CopyStr(r->bDescr);
\r
3390 ss = ZeroMallocFast(sizeof(char *) * (LIST_NUM(o) + 1));
\r
3391 for (i = 0;i < LIST_NUM(o);i++)
\r
3393 ss[i] = LIST_DATA(o, i);
\r
3395 ss[LIST_NUM(o)] = NULL;
\r
3402 // 仮想 LAN カードのインスタンス名から仮想 LAN カードの ID を取得する
\r
3403 UINT Win32GetVLanInterfaceID(char *instance_name)
\r
3408 UINT num_retry = 0;
\r
3410 char ps_miniport_str[MAX_SIZE];
\r
3411 char ps_miniport_str2[MAX_SIZE];
\r
3413 if (instance_name == 0)
\r
3419 p = ZeroMallocFast(sizeof(MIB_IFTABLE));
\r
3423 ret = w32net->GetIfTable(p, &size_needed, 0);
\r
3424 if (ret == ERROR_INSUFFICIENT_BUFFER)
\r
3426 // 必要なサイズ分のメモリブロックを再確保
\r
3428 p = ZeroMallocFast(size_needed);
\r
3430 else if (ret != NO_ERROR)
\r
3435 Debug("******** GetIfTable Failed 1. Err = %u\n", ret);
\r
3440 ret = w32net->GetIfTable(p, &size_needed, FALSE);
\r
3441 if (ret != NO_ERROR)
\r
3444 if ((++num_retry) >= 5)
\r
3449 Debug("******** GetIfTable Failed 2. Err = %u\n", ret);
\r
3453 // "%s - パケット スケジューラ ミニポート"
\r
3454 Format(ps_miniport_str, sizeof(ps_miniport_str), "%s - ", instance_name);
\r
3455 Format(ps_miniport_str2, sizeof(ps_miniport_str2), "%s (Microsoft", instance_name);
\r
3459 for (i = 0;i < p->dwNumEntries;i++)
\r
3461 MIB_IFROW *r = &p->table[i];
\r
3462 if (instance_name[0] != '@')
\r
3464 if (StrCmpi(r->bDescr, instance_name) == 0 || StartWith(r->bDescr, ps_miniport_str) || StartWith(r->bDescr, ps_miniport_str2))
\r
3471 if (SearchStrEx(r->bDescr, &instance_name[1], 0, false) != INFINITE)
\r
3477 Debug("if[%u] (0x%x): %s\n", i, r->dwIndex, r->bDescr);
\r
3485 // デフォルトの DNS サーバーアドレスを取得する
\r
3486 bool Win32GetDefaultDns(IP *ip, char *domain, UINT size)
\r
3496 Zero(ip, sizeof(IP));
\r
3498 info = ZeroMallocFast(sizeof(FIXED_INFO));
\r
3499 if (w32net->GetNetworkParams(info, &info_size) == ERROR_BUFFER_OVERFLOW)
\r
3502 info = ZeroMallocFast(info_size);
\r
3504 if (w32net->GetNetworkParams(info, &info_size) != NO_ERROR)
\r
3510 if (info->DnsServerList.IpAddress.String == NULL)
\r
3516 dns_name = info->DnsServerList.IpAddress.String;
\r
3517 StrToIP(ip, dns_name);
\r
3519 if (domain != NULL)
\r
3521 StrCpy(domain, size, info->DomainName);
\r
3530 // Win32 用 IP 変換関数
\r
3531 void Win32UINTToIP(IP *ip, UINT i)
\r
3536 // Win32 用 IP 変換関数
\r
3537 UINT Win32IPToUINT(IP *ip)
\r
3539 return IPToUINT(ip);
\r
3542 // ルーティングテーブルからルーティングエントリを削除
\r
3543 void Win32DeleteRouteEntry(ROUTE_ENTRY *e)
\r
3545 MIB_IPFORWARDROW *p;
\r
3552 p = ZeroMallocFast(sizeof(MIB_IPFORWARDROW));
\r
3553 Win32RouteEntryToIpForwardRow(p, e);
\r
3556 w32net->DeleteIpForwardEntry(p);
\r
3561 // ルーティングテーブルにルーティングエントリを追加
\r
3562 bool Win32AddRouteEntry(ROUTE_ENTRY *e, bool *already_exists)
\r
3565 bool dummy = false;
\r
3566 MIB_IPFORWARDROW *p;
\r
3573 if (already_exists == NULL)
\r
3575 already_exists = &dummy;
\r
3578 *already_exists = false;
\r
3580 p = ZeroMallocFast(sizeof(MIB_IPFORWARDROW));
\r
3581 Win32RouteEntryToIpForwardRow(p, e);
\r
3584 err = w32net->CreateIpForwardEntry(p);
\r
3587 if (err == ERROR_OBJECT_ALREADY_EXISTS)
\r
3589 Debug("CreateIpForwardEntry: Already Exists\n");
\r
3590 *already_exists = true;
\r
3595 Debug("CreateIpForwardEntry Error: %u\n", err);
\r
3610 ROUTE_TABLE *Win32GetRouteTable()
\r
3612 ROUTE_TABLE *t = ZeroMallocFast(sizeof(ROUTE_TABLE));
\r
3613 MIB_IPFORWARDTABLE *p;
\r
3616 UINT num_retry = 0;
\r
3622 p = ZeroMallocFast(sizeof(MIB_IFTABLE));
\r
3626 ret = w32net->GetIpForwardTable(p, &size_needed, 0);
\r
3627 if (ret == ERROR_INSUFFICIENT_BUFFER)
\r
3629 // 必要なサイズ分のメモリブロックを再確保
\r
3631 p = ZeroMallocFast(size_needed);
\r
3633 else if (ret != NO_ERROR)
\r
3638 t->Entry = MallocFast(0);
\r
3643 ret = w32net->GetIpForwardTable(p, &size_needed, FALSE);
\r
3644 if (ret != NO_ERROR)
\r
3647 if ((++num_retry) >= 5)
\r
3656 o = NewListFast(Win32CompareRouteEntryByMetric);
\r
3657 for (i = 0;i < p->dwNumEntries;i++)
\r
3659 e = ZeroMallocFast(sizeof(ROUTE_ENTRY));
\r
3660 Win32IpForwardRowToRouteEntry(e, &p->table[i]);
\r
3669 t->NumEntry = LIST_NUM(o);
\r
3670 t->Entry = ToArrayEx(o, true);
\r
3676 // ルーティングエントリをメトリックによってソートする
\r
3677 int Win32CompareRouteEntryByMetric(void *p1, void *p2)
\r
3679 ROUTE_ENTRY *e1, *e2;
\r
3681 if (p1 == NULL || p2 == NULL)
\r
3686 e1 = *(ROUTE_ENTRY **)p1;
\r
3687 e2 = *(ROUTE_ENTRY **)p2;
\r
3688 if (e1 == NULL || e2 == NULL)
\r
3693 if (e1->Metric > e2->Metric)
\r
3697 else if (e1->Metric == e2->Metric)
\r
3707 // ROUTE_ENTRY を MIB_IPFORWARDROW に変換
\r
3708 void Win32RouteEntryToIpForwardRow(void *ip_forward_row, ROUTE_ENTRY *entry)
\r
3710 MIB_IPFORWARDROW *r;
\r
3712 if (entry == NULL || ip_forward_row == NULL)
\r
3717 r = (MIB_IPFORWARDROW *)ip_forward_row;
\r
3718 Zero(r, sizeof(MIB_IPFORWARDROW));
\r
3721 r->dwForwardDest = Win32IPToUINT(&entry->DestIP);
\r
3723 r->dwForwardMask = Win32IPToUINT(&entry->DestMask);
\r
3725 r->dwForwardNextHop = Win32IPToUINT(&entry->GatewayIP);
\r
3727 if (entry->LocalRouting)
\r
3730 r->dwForwardType = 3;
\r
3735 r->dwForwardType = 4;
\r
3738 r->dwForwardProto = r->dwForwardType - 1; // 大抵の場合 1 引けば良い
\r
3739 if (entry->PPPConnection)
\r
3742 r->dwForwardProto++;
\r
3745 r->dwForwardMetric1 = entry->Metric;
\r
3747 if (MsIsVista() == false)
\r
3749 r->dwForwardMetric2 = r->dwForwardMetric3 = r->dwForwardMetric4 = r->dwForwardMetric5 = INFINITE;
\r
3753 r->dwForwardMetric2 = r->dwForwardMetric3 = r->dwForwardMetric4 = r->dwForwardMetric5 = 0;
\r
3754 r->dwForwardAge = 163240;
\r
3758 r->dwForwardIfIndex = entry->InterfaceID;
\r
3760 Debug("Win32RouteEntryToIpForwardRow()\n");
\r
3761 Debug(" r->dwForwardDest=%X\n", r->dwForwardDest);
\r
3762 Debug(" r->dwForwardMask=%X\n", r->dwForwardMask);
\r
3763 Debug(" r->dwForwardNextHop=%X\n", r->dwForwardNextHop);
\r
3764 Debug(" r->dwForwardType=%u\n", r->dwForwardType);
\r
3765 Debug(" r->dwForwardProto=%u\n", r->dwForwardProto);
\r
3766 Debug(" r->dwForwardMetric1=%u\n", r->dwForwardMetric1);
\r
3767 Debug(" r->dwForwardMetric2=%u\n", r->dwForwardMetric2);
\r
3768 Debug(" r->dwForwardIfIndex=%u\n", r->dwForwardIfIndex);
\r
3771 // MIB_IPFORWARDROW を ROUTE_ENTRY に変換
\r
3772 void Win32IpForwardRowToRouteEntry(ROUTE_ENTRY *entry, void *ip_forward_row)
\r
3774 MIB_IPFORWARDROW *r;
\r
3776 if (entry == NULL || ip_forward_row == NULL)
\r
3781 r = (MIB_IPFORWARDROW *)ip_forward_row;
\r
3783 Zero(entry, sizeof(ROUTE_ENTRY));
\r
3785 Win32UINTToIP(&entry->DestIP, r->dwForwardDest);
\r
3787 Win32UINTToIP(&entry->DestMask, r->dwForwardMask);
\r
3789 Win32UINTToIP(&entry->GatewayIP, r->dwForwardNextHop);
\r
3791 if (r->dwForwardType == 3)
\r
3793 entry->LocalRouting = true;
\r
3797 entry->LocalRouting = false;
\r
3799 if (entry->LocalRouting && r->dwForwardProto == 3)
\r
3802 entry->PPPConnection = true;
\r
3805 entry->Metric = r->dwForwardMetric1;
\r
3807 entry->InterfaceID = r->dwForwardIfIndex;
\r
3811 void Win32InitSocketLibrary()
\r
3814 Zero(&data, sizeof(data));
\r
3815 WSAStartup(MAKEWORD(2, 2), &data);
\r
3818 w32net = ZeroMalloc(sizeof(NETWORK_WIN32_FUNCTIONS));
\r
3819 w32net->hIpHlpApi32 = LoadLibrary("iphlpapi.dll");
\r
3821 if (w32net->hIpHlpApi32 != NULL)
\r
3823 w32net->CreateIpForwardEntry =
\r
3824 (DWORD (__stdcall *)(PMIB_IPFORWARDROW))
\r
3825 GetProcAddress(w32net->hIpHlpApi32, "CreateIpForwardEntry");
\r
3827 w32net->DeleteIpForwardEntry =
\r
3828 (DWORD (__stdcall *)(PMIB_IPFORWARDROW))
\r
3829 GetProcAddress(w32net->hIpHlpApi32, "DeleteIpForwardEntry");
\r
3831 w32net->GetIfTable =
\r
3832 (DWORD (__stdcall *)(PMIB_IFTABLE, PULONG, BOOL))
\r
3833 GetProcAddress(w32net->hIpHlpApi32, "GetIfTable");
\r
3835 w32net->GetIpForwardTable =
\r
3836 (DWORD (__stdcall *)(PMIB_IPFORWARDTABLE, PULONG, BOOL))
\r
3837 GetProcAddress(w32net->hIpHlpApi32, "GetIpForwardTable");
\r
3839 w32net->GetNetworkParams =
\r
3840 (DWORD (__stdcall *)(PFIXED_INFO,PULONG))
\r
3841 GetProcAddress(w32net->hIpHlpApi32, "GetNetworkParams");
\r
3843 w32net->IpRenewAddress =
\r
3844 (DWORD (__stdcall *)(PIP_ADAPTER_INDEX_MAP))
\r
3845 GetProcAddress(w32net->hIpHlpApi32, "IpRenewAddress");
\r
3847 w32net->IpReleaseAddress =
\r
3848 (DWORD (__stdcall *)(PIP_ADAPTER_INDEX_MAP))
\r
3849 GetProcAddress(w32net->hIpHlpApi32, "IpReleaseAddress");
\r
3851 w32net->GetInterfaceInfo =
\r
3852 (DWORD (__stdcall *)(PIP_INTERFACE_INFO, PULONG))
\r
3853 GetProcAddress(w32net->hIpHlpApi32, "GetInterfaceInfo");
\r
3855 w32net->GetAdaptersInfo =
\r
3856 (DWORD (__stdcall *)(PIP_ADAPTER_INFO, PULONG))
\r
3857 GetProcAddress(w32net->hIpHlpApi32, "GetAdaptersInfo");
\r
3859 w32net->GetExtendedTcpTable =
\r
3860 (DWORD (__stdcall *)(PVOID,PDWORD,BOOL,ULONG,_TCP_TABLE_CLASS,ULONG))
\r
3861 GetProcAddress(w32net->hIpHlpApi32, "GetExtendedTcpTable");
\r
3863 w32net->AllocateAndGetTcpExTableFromStack =
\r
3864 (DWORD (__stdcall *)(PVOID *,BOOL,HANDLE,DWORD,DWORD))
\r
3865 GetProcAddress(w32net->hIpHlpApi32, "AllocateAndGetTcpExTableFromStack");
\r
3867 w32net->GetTcpTable =
\r
3868 (DWORD (__stdcall *)(PMIB_TCPTABLE,PDWORD,BOOL))
\r
3869 GetProcAddress(w32net->hIpHlpApi32, "GetTcpTable");
\r
3871 w32net->NotifyRouteChange =
\r
3872 (DWORD (__stdcall *)(PHANDLE,LPOVERLAPPED))
\r
3873 GetProcAddress(w32net->hIpHlpApi32, "NotifyRouteChange");
\r
3875 w32net->CancelIPChangeNotify =
\r
3876 (BOOL (__stdcall *)(LPOVERLAPPED))
\r
3877 GetProcAddress(w32net->hIpHlpApi32, "CancelIPChangeNotify");
\r
3879 w32net->NhpAllocateAndGetInterfaceInfoFromStack =
\r
3880 (DWORD (__stdcall *)(IP_INTERFACE_NAME_INFO **,PDWORD,BOOL,HANDLE,DWORD))
\r
3881 GetProcAddress(w32net->hIpHlpApi32, "NhpAllocateAndGetInterfaceInfoFromStack");
\r
3886 void Win32FreeSocketLibrary()
\r
3888 if (w32net != NULL)
\r
3890 FreeLibrary(w32net->hIpHlpApi32);
\r
3900 void Win32Cancel(CANCEL *c)
\r
3908 SetEvent((HANDLE)c->hEvent);
\r
3912 void Win32CleanupCancel(CANCEL *c)
\r
3920 if (c->SpecialFlag == false)
\r
3922 CloseHandle(c->hEvent);
\r
3929 CANCEL *Win32NewCancel()
\r
3931 CANCEL *c = ZeroMallocFast(sizeof(CANCEL));
\r
3932 c->ref = NewRef();
\r
3933 c->SpecialFlag = false;
\r
3934 c->hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
\r
3940 bool Win32WaitSockEvent(SOCK_EVENT *event, UINT timeout)
\r
3943 if (event == NULL || timeout == 0)
\r
3948 if (WaitForSingleObject((HANDLE)event->hEvent, timeout) == WAIT_OBJECT_0)
\r
3958 // ソケットイベントのクリーンアップ
\r
3959 void Win32CleanupSockEvent(SOCK_EVENT *event)
\r
3962 if (event == NULL)
\r
3967 CloseHandle((HANDLE)event->hEvent);
\r
3973 void Win32SetSockEvent(SOCK_EVENT *event)
\r
3976 if (event == NULL)
\r
3981 SetEvent((HANDLE)event->hEvent);
\r
3985 SOCK_EVENT *Win32NewSockEvent()
\r
3987 SOCK_EVENT *e = ZeroMallocFast(sizeof(SOCK_EVENT));
\r
3989 e->ref = NewRef();
\r
3990 e->hEvent = (void *)CreateEvent(NULL, FALSE, FALSE, NULL);
\r
3995 // ソケットをソケットイベントに関連付けして非同期に設定する
\r
3996 void Win32JoinSockToSockEvent(SOCK *sock, SOCK_EVENT *event)
\r
4000 if (sock == NULL || event == NULL || sock->AsyncMode)
\r
4004 if (sock->ListenMode != false || (sock->Type != SOCK_UDP && sock->Connected == false))
\r
4009 sock->AsyncMode = true;
\r
4011 hEvent = event->hEvent;
\r
4014 WSAEventSelect(sock->socket, hEvent, FD_READ | FD_WRITE | FD_CLOSE);
\r
4016 // SOCK_EVENT の参照カウンタを増加
\r
4017 AddRef(event->ref);
\r
4018 sock->SockEvent = event;
\r
4022 void Win32InitAsyncSocket(SOCK *sock)
\r
4029 if (sock->AsyncMode)
\r
4031 // すでに非同期ソケットになっている
\r
4034 if (sock->ListenMode != false || (sock->Type == SOCK_TCP && sock->Connected == false))
\r
4039 sock->AsyncMode = true;
\r
4042 sock->hEvent = (void *)CreateEvent(NULL, FALSE, FALSE, NULL);
\r
4045 WSAEventSelect(sock->socket, sock->hEvent, FD_READ | FD_WRITE | FD_CLOSE);
\r
4049 void Win32FreeAsyncSocket(SOCK *sock)
\r
4058 if (sock->hEvent != NULL)
\r
4060 CloseHandle((HANDLE)sock->hEvent);
\r
4062 sock->hEvent = NULL;
\r
4063 sock->AsyncMode = false;
\r
4066 if (sock->SockEvent != NULL)
\r
4068 ReleaseSockEvent(sock->SockEvent);
\r
4069 sock->SockEvent = NULL;
\r
4073 // Win32 版 Select 関数
\r
4074 void Win32Select(SOCKSET *set, UINT timeout, CANCEL *c1, CANCEL *c2)
\r
4076 HANDLE array[MAXIMUM_WAIT_OBJECTS];
\r
4086 Zero(array, sizeof(array));
\r
4092 for (i = 0;i < set->NumSocket;i++)
\r
4097 Win32InitAsyncSocket(s);
\r
4098 if (s->hEvent != NULL)
\r
4100 array[n++] = (HANDLE)s->hEvent;
\r
4105 if (c1 != NULL && c1->hEvent != NULL)
\r
4107 array[n++] = c1->hEvent;
\r
4109 if (c2 != NULL && c2->hEvent != NULL)
\r
4111 array[n++] = c2->hEvent;
\r
4116 // 待つイベントが 1 つも登録されていない場合は
\r
4118 SleepThread(timeout);
\r
4122 // イベントが 1 つ以上登録されている場合はイベントを待つ
\r
4125 // イベントが 1 つの場合は軽量版を呼び出す
\r
4126 WaitForSingleObject(array[0], timeout);
\r
4131 WaitForMultipleObjects(n, array, false, timeout);
\r
4136 #endif // OS_WIN32
\r
4138 // IPv6 がサポートされているかどうか調べる
\r
4139 bool IsIPv6Supported()
\r
4146 s = socket(AF_INET6, SOCK_STREAM, 0);
\r
4147 if (s == INVALID_SOCKET)
\r
4158 // ホストキャッシュからホスト名の取得
\r
4159 bool GetHostCache(char *hostname, UINT size, IP *ip)
\r
4163 if (hostname == NULL || ip == NULL)
\r
4170 LockList(HostCacheList);
\r
4173 Zero(&t, sizeof(t));
\r
4174 Copy(&t.IpAddress, ip, sizeof(IP));
\r
4176 c = Search(HostCacheList, &t);
\r
4179 if (IsEmptyStr(c->HostName) == false)
\r
4182 StrCpy(hostname, size, c->HostName);
\r
4187 StrCpy(hostname, size, "");
\r
4191 UnlockList(HostCacheList);
\r
4197 void AddHostCache(IP *ip, char *hostname)
\r
4200 if (ip == NULL || hostname == NULL)
\r
4204 if (IsNetworkNameCacheEnabled() == false)
\r
4209 LockList(HostCacheList);
\r
4215 Zero(&t, sizeof(t));
\r
4216 Copy(&t.IpAddress, ip, sizeof(IP));
\r
4218 c = Search(HostCacheList, &t);
\r
4221 c = ZeroMalloc(sizeof(HOSTCACHE));
\r
4222 Copy(&c->IpAddress, ip, sizeof(IP));
\r
4223 Add(HostCacheList, c);
\r
4226 StrCpy(c->HostName, sizeof(c->HostName), hostname);
\r
4227 c->Expires = Tick64() + (UINT64)EXPIRES_HOSTNAME;
\r
4229 o = NewListFast(NULL);
\r
4231 for (i = 0;i < LIST_NUM(HostCacheList);i++)
\r
4233 HOSTCACHE *c = LIST_DATA(HostCacheList, i);
\r
4235 if (c->Expires <= Tick64())
\r
4241 for (i = 0;i < LIST_NUM(o);i++)
\r
4243 HOSTCACHE *c = LIST_DATA(o, i);
\r
4245 if (Delete(HostCacheList, c))
\r
4253 UnlockList(HostCacheList);
\r
4257 int CompareHostCache(void *p1, void *p2)
\r
4259 HOSTCACHE *c1, *c2;
\r
4260 if (p1 == NULL || p2 == NULL)
\r
4264 c1 = *(HOSTCACHE **)p1;
\r
4265 c2 = *(HOSTCACHE **)p2;
\r
4266 if (c1 == NULL || c2 == NULL)
\r
4271 return CmpIpAddr(&c1->IpAddress, &c2->IpAddress);
\r
4275 void FreeHostCache()
\r
4279 for (i = 0;i < LIST_NUM(HostCacheList);i++)
\r
4281 HOSTCACHE *c = LIST_DATA(HostCacheList, i);
\r
4286 ReleaseList(HostCacheList);
\r
4287 HostCacheList = NULL;
\r
4291 void InitHostCache()
\r
4293 HostCacheList = NewList(CompareHostCache);
\r
4296 // スレッドをスレッド待機リストに追加する
\r
4297 void AddWaitThread(THREAD *t)
\r
4307 LockList(WaitThreadList);
\r
4309 Add(WaitThreadList, t);
\r
4311 UnlockList(WaitThreadList);
\r
4314 // スレッドを待機リストから削除する
\r
4315 void DelWaitThread(THREAD *t)
\r
4323 LockList(WaitThreadList);
\r
4325 if (Delete(WaitThreadList, t))
\r
4330 UnlockList(WaitThreadList);
\r
4334 void InitWaitThread()
\r
4336 WaitThreadList = NewList(NULL);
\r
4340 void FreeWaitThread()
\r
4345 LockList(WaitThreadList);
\r
4347 num = LIST_NUM(WaitThreadList);
\r
4348 threads = ToArray(WaitThreadList);
\r
4349 DeleteAll(WaitThreadList);
\r
4351 UnlockList(WaitThreadList);
\r
4353 for (i = 0;i < num;i++)
\r
4355 THREAD *t = threads[i];
\r
4356 WaitThread(t, INFINITE);
\r
4362 ReleaseList(WaitThreadList);
\r
4363 WaitThreadList = NULL;
\r
4367 bool CheckCipherListName(char *name)
\r
4376 for (i = 0;i < cipher_list_token->NumTokens;i++)
\r
4378 if (StrCmpi(cipher_list_token->Token[i], name) == 0)
\r
4387 // DHCP サーバーの IP アドレス更新
\r
4398 bool UnixGetDomainName(char *name, UINT size)
\r
4401 BUF *b = ReadDump("/etc/resolv.conf");
\r
4410 char *s = CfgReadNextLine(b);
\r
4420 t = ParseToken(s, " \t");
\r
4423 if (t->NumTokens == 2)
\r
4425 if (StrCmpi(t->Token[0], "domain") == 0)
\r
4427 StrCpy(name, size, t->Token[1]);
\r
4443 bool GetDomainName(char *name, UINT size)
\r
4454 ret = Win32GetDefaultDns(&ip, name, size);
\r
4456 ret = UnixGetDomainName(name, size);
\r
4457 #endif // OS_WIN32
\r
4462 // デフォルトの DNS サーバーの取得
\r
4463 bool GetDefaultDns(IP *ip)
\r
4467 ret = Win32GetDefaultDns(ip, NULL, 0);
\r
4469 ret = UnixGetDefaultDns(ip);
\r
4470 #endif // OS_WIN32
\r
4475 SOCK_EVENT *NewSockEvent()
\r
4477 SOCK_EVENT *e = NULL;
\r
4479 e = Win32NewSockEvent();
\r
4481 e = UnixNewSockEvent();
\r
4482 #endif // OS_WIN32
\r
4487 void SetSockEvent(SOCK_EVENT *event)
\r
4490 Win32SetSockEvent(event);
\r
4492 UnixSetSockEvent(event);
\r
4493 #endif // OS_WIN32
\r
4496 // ソケットイベントのクリーンアップ
\r
4497 void CleanupSockEvent(SOCK_EVENT *event)
\r
4500 Win32CleanupSockEvent(event);
\r
4502 UnixCleanupSockEvent(event);
\r
4503 #endif // OS_WIN32
\r
4507 bool WaitSockEvent(SOCK_EVENT *event, UINT timeout)
\r
4511 ret = Win32WaitSockEvent(event, timeout);
\r
4513 ret = UnixWaitSockEvent(event, timeout);
\r
4514 #endif // OS_WIN32
\r
4519 void ReleaseSockEvent(SOCK_EVENT *event)
\r
4522 if (event == NULL)
\r
4527 if (Release(event->ref) == 0)
\r
4529 CleanupSockEvent(event);
\r
4533 // ソケットをソケットイベントに所属させる
\r
4534 void JoinSockToSockEvent(SOCK *sock, SOCK_EVENT *event)
\r
4537 Win32JoinSockToSockEvent(sock, event);
\r
4539 UnixJoinSockToSockEvent(sock, event);
\r
4540 #endif // OS_WIN32
\r
4543 // 新しい特殊キャンセルオブジェクト
\r
4544 CANCEL *NewCancelSpecial(void *hEvent)
\r
4548 if (hEvent == NULL)
\r
4553 c = ZeroMalloc(sizeof(CANCEL));
\r
4554 c->ref = NewRef();
\r
4555 c->SpecialFlag = true;
\r
4558 c->hEvent = (HANDLE)hEvent;
\r
4560 c->pipe_read = (int)hEvent;
\r
4561 c->pipe_write = -1;
\r
4562 #endif // OS_WIN32
\r
4568 CANCEL *NewCancel()
\r
4572 c = Win32NewCancel();
\r
4574 c = UnixNewCancel();
\r
4575 #endif // OS_WIN32
\r
4580 void ReleaseCancel(CANCEL *c)
\r
4588 if (Release(c->ref) == 0)
\r
4594 // キャンセルオブジェクトのクリーンアップ
\r
4595 void CleanupCancel(CANCEL *c)
\r
4598 Win32CleanupCancel(c);
\r
4600 UnixCleanupCancel(c);
\r
4605 void Cancel(CANCEL *c)
\r
4614 // 指定されたルーティングテーブルから最適なルートを計算する
\r
4615 ROUTE_ENTRY *GetBestRouteEntryFromRouteTable(ROUTE_TABLE *table, IP *ip)
\r
4617 return GetBestRouteEntryFromRouteTableEx(table, ip, 0);
\r
4619 ROUTE_ENTRY *GetBestRouteEntryFromRouteTableEx(ROUTE_TABLE *table, IP *ip, UINT exclude_if_id)
\r
4622 UINT max_mask = 0;
\r
4623 UINT min_metric = INFINITE;
\r
4624 ROUTE_ENTRY *ret = NULL;
\r
4625 ROUTE_ENTRY *tmp = NULL;
\r
4627 if (ip == NULL || table == NULL)
\r
4638 // 対象となるルーティングテーブルのうち、
\r
4639 // 第一条件: サブネットマスクが最も大きい
\r
4640 // 第二条件: メトリック値が最も小さい
\r
4642 for (i = 0;i < table->NumEntry;i++)
\r
4644 ROUTE_ENTRY *e = table->Entry[i];
\r
4645 UINT dest, net, mask;
\r
4647 dest = IPToUINT(ip);
\r
4648 net = IPToUINT(&e->DestIP);
\r
4649 mask = IPToUINT(&e->DestMask);
\r
4651 if (exclude_if_id != 0)
\r
4653 if (e->InterfaceID == exclude_if_id)
\r
4660 if ((dest & mask) == (net & mask))
\r
4662 // これはルーティングの対象となり得る
\r
4663 if (mask >= max_mask)
\r
4666 if (min_metric >= e->Metric)
\r
4668 min_metric = e->Metric;
\r
4677 UINT dest, gateway, mask;
\r
4680 ret = ZeroMallocFast(sizeof(ROUTE_ENTRY));
\r
4682 Copy(&ret->DestIP, ip, sizeof(IP));
\r
4683 ret->DestMask.addr[0] = 255;
\r
4684 ret->DestMask.addr[1] = 255;
\r
4685 ret->DestMask.addr[2] = 255;
\r
4686 ret->DestMask.addr[3] = 255;
\r
4687 Copy(&ret->GatewayIP, &tmp->GatewayIP, sizeof(IP));
\r
4688 ret->InterfaceID = tmp->InterfaceID;
\r
4689 ret->LocalRouting = tmp->LocalRouting;
\r
4690 ret->OldIfMetric = tmp->Metric;
\r
4692 ret->PPPConnection = tmp->PPPConnection;
\r
4695 dest = IPToUINT(&tmp->DestIP);
\r
4696 gateway = IPToUINT(&tmp->GatewayIP);
\r
4697 mask = IPToUINT(&tmp->DestMask);
\r
4698 if ((dest & mask) == (gateway & mask))
\r
4701 if (MsIsVista() == false)
\r
4704 ret->PPPConnection = true;
\r
4706 #endif // OS_WIN32
\r
4713 // ルーティングエントリを解放する
\r
4714 void FreeRouteEntry(ROUTE_ENTRY *e)
\r
4725 // 現在のルーティングテーブルを解析して最適なルートエントリを取得する
\r
4726 ROUTE_ENTRY *GetBestRouteEntry(IP *ip)
\r
4728 return GetBestRouteEntryEx(ip, 0);
\r
4730 ROUTE_ENTRY *GetBestRouteEntryEx(IP *ip, UINT exclude_if_id)
\r
4732 ROUTE_TABLE *table;
\r
4733 ROUTE_ENTRY *e = NULL;
\r
4740 table = GetRouteTable();
\r
4741 if (table == NULL)
\r
4746 e = GetBestRouteEntryFromRouteTableEx(table, ip, exclude_if_id);
\r
4747 FreeRouteTable(table);
\r
4752 // 仮想 LAN カードのインターフェース ID の取得
\r
4753 UINT GetVLanInterfaceID(char *tag_name)
\r
4757 ret = Win32GetVLanInterfaceID(tag_name);
\r
4759 ret = UnixGetVLanInterfaceID(tag_name);
\r
4760 #endif // OS_WIN32
\r
4764 // 仮想 LAN カードの列挙変数の解放
\r
4765 void FreeEnumVLan(char **s)
\r
4790 char **EnumVLan(char *tag_name)
\r
4792 char **ret = NULL;
\r
4794 ret = Win32EnumVLan(tag_name);
\r
4796 ret = UnixEnumVLan(tag_name);
\r
4797 #endif // OS_WIN32
\r
4801 // ルーティングテーブルを表示する
\r
4802 void DebugPrintRouteTable(ROUTE_TABLE *r)
\r
4811 if (IsDebug() == false)
\r
4816 Debug("---- Routing Table (%u Entries) ----\n", r->NumEntry);
\r
4818 for (i = 0;i < r->NumEntry;i++)
\r
4822 DebugPrintRoute(r->Entry[i]);
\r
4825 Debug("------------------------------------\n");
\r
4828 // ルーティングテーブルエントリを表示する
\r
4829 void DebugPrintRoute(ROUTE_ENTRY *e)
\r
4831 char tmp[MAX_SIZE];
\r
4838 if (IsDebug() == false)
\r
4843 RouteToStr(tmp, sizeof(tmp), e);
\r
4845 Debug("%s\n", tmp);
\r
4848 // ルーティングテーブルエントリを文字列にする
\r
4849 void RouteToStr(char *str, UINT str_size, ROUTE_ENTRY *e)
\r
4851 char dest_ip[MAX_PATH];
\r
4852 char dest_mask[MAX_PATH];
\r
4853 char gateway_ip[MAX_PATH];
\r
4855 if (str == NULL || e == NULL)
\r
4860 IPToStr(dest_ip, sizeof(dest_ip), &e->DestIP);
\r
4861 IPToStr(dest_mask, sizeof(dest_mask), &e->DestMask);
\r
4862 IPToStr(gateway_ip, sizeof(gateway_ip), &e->GatewayIP);
\r
4864 Format(str, str_size, "%s/%s %s m=%u oif=%u if=%u lo=%u p=%u",
\r
4865 dest_ip, dest_mask, gateway_ip,
\r
4866 e->Metric, e->OldIfMetric, e->InterfaceID,
\r
4867 e->LocalRouting, e->PPPConnection);
\r
4871 void DeleteRouteEntry(ROUTE_ENTRY *e)
\r
4873 Debug("DeleteRouteEntry();\n");
\r
4875 Win32DeleteRouteEntry(e);
\r
4877 UnixDeleteRouteEntry(e);
\r
4882 bool AddRouteEntry(ROUTE_ENTRY *e)
\r
4884 bool dummy = false;
\r
4885 return AddRouteEntryEx(e, &dummy);
\r
4887 bool AddRouteEntryEx(ROUTE_ENTRY *e, bool *already_exists)
\r
4890 Debug("AddRouteEntryEx();\n");
\r
4892 ret = Win32AddRouteEntry(e, already_exists);
\r
4894 ret = UnixAddRouteEntry(e, already_exists);
\r
4900 ROUTE_TABLE *GetRouteTable()
\r
4902 ROUTE_TABLE *t = NULL;
\r
4904 BUF *buf = NewBuf();
\r
4905 UCHAR hash[MD5_SIZE];
\r
4908 t = Win32GetRouteTable();
\r
4910 t = UnixGetRouteTable();
\r
4911 #endif // OS_WIN32
\r
4913 WriteBuf(buf, &t->NumEntry, sizeof(t->NumEntry));
\r
4915 for (i = 0;i < t->NumEntry;i++)
\r
4917 ROUTE_ENTRY *e = t->Entry[i];
\r
4919 WriteBuf(buf, e, sizeof(ROUTE_ENTRY));
\r
4922 Hash(hash, buf->Buf, buf->Size, false);
\r
4926 Copy(&t->HashedValue, hash, sizeof(t->HashedValue));
\r
4932 void FreeRouteTable(ROUTE_TABLE *t)
\r
4941 for (i = 0;i < t->NumEntry;i++)
\r
4943 Free(t->Entry[i]);
\r
4950 UINT RecvFrom(SOCK *sock, IP *src_addr, UINT *src_port, void *data, UINT size)
\r
4954 struct sockaddr_in addr;
\r
4956 if (sock == NULL || src_addr == NULL || src_port == NULL || data == NULL)
\r
4960 if (sock->Type != SOCK_UDP || sock->socket == INVALID_SOCKET)
\r
4971 return RecvFrom6(sock, src_addr, src_port, data, size);
\r
4976 sz = sizeof(addr);
\r
4977 ret = recvfrom(s, data, size, 0, (struct sockaddr *)&addr, (int *)&sz);
\r
4980 InAddrToIP(src_addr, &addr.sin_addr);
\r
4981 *src_port = (UINT)ntohs(addr.sin_port);
\r
4986 sock->RecvSize += (UINT64)ret;
\r
4988 Unlock(sock->lock);
\r
4990 // Debug("UDP RecvFrom: %u\n", ret);
\r
4996 sock->IgnoreRecvErr = false;
\r
4999 if (WSAGetLastError() == WSAECONNRESET)
\r
5001 sock->IgnoreRecvErr = true;
\r
5003 else if (WSAGetLastError() == WSAEWOULDBLOCK)
\r
5005 return SOCK_LATER;
\r
5009 UINT e = WSAGetLastError();
\r
5010 // Debug("RecvFrom Error: %u\n", e);
\r
5013 if (errno == ECONNREFUSED || errno == ECONNRESET)
\r
5015 sock->IgnoreRecvErr = true;
\r
5017 else if (errno == EAGAIN)
\r
5019 return SOCK_LATER;
\r
5021 #endif // OS_WIN32
\r
5025 UINT RecvFrom6(SOCK *sock, IP *src_addr, UINT *src_port, void *data, UINT size)
\r
5029 struct sockaddr_in6 addr;
\r
5031 if (sock == NULL || src_addr == NULL || src_port == NULL || data == NULL)
\r
5035 if (sock->Type != SOCK_UDP || sock->socket == INVALID_SOCKET)
\r
5046 sz = sizeof(addr);
\r
5047 ret = recvfrom(s, data, size, 0, (struct sockaddr *)&addr, (int *)&sz);
\r
5050 InAddrToIP6(src_addr, &addr.sin6_addr);
\r
5051 src_addr->ipv6_scope_id = addr.sin6_scope_id;
\r
5052 *src_port = (UINT)ntohs(addr.sin6_port);
\r
5057 sock->RecvSize += (UINT64)ret;
\r
5059 Unlock(sock->lock);
\r
5061 // Debug("UDP RecvFrom: %u\n", ret);
\r
5067 sock->IgnoreRecvErr = false;
\r
5070 if (WSAGetLastError() == WSAECONNRESET)
\r
5072 sock->IgnoreRecvErr = true;
\r
5074 else if (WSAGetLastError() == WSAEWOULDBLOCK)
\r
5076 return SOCK_LATER;
\r
5080 UINT e = WSAGetLastError();
\r
5081 // Debug("RecvFrom Error: %u\n", e);
\r
5084 if (errno == ECONNREFUSED || errno == ECONNRESET)
\r
5086 sock->IgnoreRecvErr = true;
\r
5088 else if (errno == EAGAIN)
\r
5090 return SOCK_LATER;
\r
5092 #endif // OS_WIN32
\r
5098 void LockOpenSSL()
\r
5100 Lock(openssl_lock);
\r
5104 void UnlockOpenSSL()
\r
5106 Unlock(openssl_lock);
\r
5111 UINT SendTo(SOCK *sock, IP *dest_addr, UINT dest_port, void *data, UINT size)
\r
5115 struct sockaddr_in addr;
\r
5117 if (sock == NULL || dest_addr == NULL || dest_port == 0 || data == NULL)
\r
5121 if (dest_port >= 65536)
\r
5125 if (sock->Type != SOCK_UDP || sock->socket == INVALID_SOCKET)
\r
5136 return SendTo6(sock, dest_addr, dest_port, data, size);
\r
5139 if (IsIP4(dest_addr) == false)
\r
5145 Zero(&addr, sizeof(addr));
\r
5146 addr.sin_family = AF_INET;
\r
5147 addr.sin_port = htons((USHORT)dest_port);
\r
5148 IPToInAddr(&addr.sin_addr, dest_addr);
\r
5150 if (dest_addr->addr[0] == 255 && dest_addr->addr[1] == 255 &&
\r
5151 dest_addr->addr[2] == 255 && dest_addr->addr[3] == 255)
\r
5153 if (sock->UdpBroadcast == false)
\r
5157 sock->UdpBroadcast = true;
\r
5159 setsockopt(s, SOL_SOCKET, SO_BROADCAST, (char *)&yes, sizeof(yes));
\r
5163 ret = sendto(s, data, size, 0, (struct sockaddr *)&addr, sizeof(addr));
\r
5164 if (ret != (int)size)
\r
5166 sock->IgnoreSendErr = false;
\r
5169 if (WSAGetLastError() == WSAECONNRESET)
\r
5171 sock->IgnoreSendErr = true;
\r
5173 else if (WSAGetLastError() == WSAEWOULDBLOCK)
\r
5175 return SOCK_LATER;
\r
5179 UINT e = WSAGetLastError();
\r
5182 if (errno == ECONNREFUSED || errno == ECONNRESET)
\r
5184 sock->IgnoreRecvErr = true;
\r
5186 else if (errno == EAGAIN)
\r
5188 return SOCK_LATER;
\r
5190 #endif // OS_WIN32
\r
5196 sock->SendSize += (UINT64)size;
\r
5199 Unlock(sock->lock);
\r
5203 UINT SendTo6(SOCK *sock, IP *dest_addr, UINT dest_port, void *data, UINT size)
\r
5207 struct sockaddr_in6 addr;
\r
5210 if (sock == NULL || dest_addr == NULL || dest_port == 0 || data == NULL)
\r
5214 if (dest_port >= 65536)
\r
5218 if (sock->Type != SOCK_UDP || sock->socket == INVALID_SOCKET)
\r
5227 if (IsIP6(dest_addr) == false)
\r
5233 Zero(&addr, sizeof(addr));
\r
5234 addr.sin6_family = AF_INET6;
\r
5235 addr.sin6_port = htons((USHORT)dest_port);
\r
5236 IPToInAddr6(&addr.sin6_addr, dest_addr);
\r
5237 addr.sin6_scope_id = dest_addr->ipv6_scope_id;
\r
5239 type = GetIPAddrType6(dest_addr);
\r
5241 if (type & IPV6_ADDR_MULTICAST)
\r
5243 if (sock->UdpBroadcast == false)
\r
5247 sock->UdpBroadcast = true;
\r
5249 setsockopt(s, SOL_SOCKET, SO_BROADCAST, (char *)&yes, sizeof(yes));
\r
5253 ret = sendto(s, data, size, 0, (struct sockaddr *)&addr, sizeof(addr));
\r
5254 if (ret != (int)size)
\r
5256 sock->IgnoreSendErr = false;
\r
5259 if (WSAGetLastError() == WSAECONNRESET)
\r
5261 sock->IgnoreSendErr = true;
\r
5263 else if (WSAGetLastError() == WSAEWOULDBLOCK)
\r
5265 return SOCK_LATER;
\r
5269 UINT e = WSAGetLastError();
\r
5272 if (errno == ECONNREFUSED || errno == ECONNRESET)
\r
5274 sock->IgnoreRecvErr = true;
\r
5276 else if (errno == EAGAIN)
\r
5278 return SOCK_LATER;
\r
5280 #endif // OS_WIN32
\r
5286 sock->SendSize += (UINT64)size;
\r
5289 Unlock(sock->lock);
\r
5294 // UDP ソケットの作成と初期化
\r
5295 // port が 0 の場合は OS がランダムに割り当てる
\r
5296 SOCK *NewUDP(UINT port)
\r
5298 return NewUDPEx(port, false);
\r
5300 SOCK *NewUDPEx(UINT port, bool ipv6)
\r
5302 if (ipv6 == false)
\r
5304 return NewUDP4(port);
\r
5308 return NewUDP6(port);
\r
5311 SOCK *NewUDP4(UINT port)
\r
5315 struct sockaddr_in addr;
\r
5317 s = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
\r
5318 if (s == INVALID_SOCKET)
\r
5323 Zero(&addr, sizeof(addr));
\r
5324 addr.sin_family = AF_INET;
\r
5325 addr.sin_addr.s_addr = htonl(INADDR_ANY);
\r
5328 addr.sin_port = 0;
\r
5332 addr.sin_port = htons((USHORT)port);
\r
5335 if (bind(s, (struct sockaddr *)&addr, sizeof(addr)) != 0)
\r
5344 sock->Type = SOCK_UDP;
\r
5345 sock->Connected = false;
\r
5346 sock->AsyncMode = false;
\r
5347 sock->ServerMode = false;
\r
5350 sock->ServerMode = true;
\r
5355 QuerySocketInformation(sock);
\r
5359 SOCK *NewUDP6(UINT port)
\r
5363 struct sockaddr_in6 addr;
\r
5365 s = socket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP);
\r
5366 if (s == INVALID_SOCKET)
\r
5371 Zero(&addr, sizeof(addr));
\r
5372 addr.sin6_family = AF_INET6;
\r
5375 addr.sin6_port = 0;
\r
5379 addr.sin6_port = htons((USHORT)port);
\r
5382 if (bind(s, (struct sockaddr *)&addr, sizeof(addr)) != 0)
\r
5391 sock->Type = SOCK_UDP;
\r
5392 sock->Connected = false;
\r
5393 sock->AsyncMode = false;
\r
5394 sock->ServerMode = false;
\r
5395 sock->IPv6 = true;
\r
5398 sock->ServerMode = true;
\r
5403 QuerySocketInformation(sock);
\r
5409 void Select(SOCKSET *set, UINT timeout, CANCEL *c1, CANCEL *c2)
\r
5412 Win32Select(set, timeout, c1, c2);
\r
5414 UnixSelect(set, timeout, c1, c2);
\r
5415 #endif // OS_WIN32
\r
5418 // ソケットセットにソケットを追加
\r
5419 void AddSockSet(SOCKSET *set, SOCK *sock)
\r
5422 if (set == NULL || sock == NULL)
\r
5426 if (sock->Type == SOCK_TCP && sock->Connected == false)
\r
5431 if (set->NumSocket >= MAX_SOCKSET_NUM)
\r
5436 set->Sock[set->NumSocket++] = sock;
\r
5440 void InitSockSet(SOCKSET *set)
\r
5448 Zero(set, sizeof(SOCKSET));
\r
5452 bool RecvAll(SOCK *sock, void *data, UINT size, bool secure)
\r
5454 UINT recv_size, sz, ret;
\r
5456 if (sock == NULL || data == NULL)
\r
5464 if (sock->AsyncMode)
\r
5473 sz = size - recv_size;
\r
5474 ret = Recv(sock, (UCHAR *)data + recv_size, sz, secure);
\r
5480 if (recv_size >= size)
\r
5487 // TCP 送信バッファを送信する
\r
5488 bool SendNow(SOCK *sock, int secure)
\r
5492 if (sock == NULL || sock->AsyncMode != false)
\r
5496 if (sock->SendBuf->Size == 0)
\r
5501 ret = SendAll(sock, sock->SendBuf->Buf, sock->SendBuf->Size, secure);
\r
5502 ClearBuf(sock->SendBuf);
\r
5508 void SendAdd(SOCK *sock, void *data, UINT size)
\r
5511 if (sock == NULL || data == NULL || size == 0 || sock->AsyncMode != false)
\r
5516 WriteBuf(sock->SendBuf, data, size);
\r
5520 bool SendAll(SOCK *sock, void *data, UINT size, bool secure)
\r
5526 if (sock == NULL || data == NULL)
\r
5530 if (sock->AsyncMode)
\r
5539 buf = (UCHAR *)data;
\r
5544 ret = Send(sock, buf, size - sent_size, secure);
\r
5551 if (sent_size >= size)
\r
5558 // 使用したい暗号化アルゴリズム名を設定する
\r
5559 void SetWantToUseCipher(SOCK *sock, char *name)
\r
5562 if (sock == NULL || name == NULL)
\r
5567 if (sock->WaitToUseCipher)
\r
5569 Free(sock->WaitToUseCipher);
\r
5571 sock->WaitToUseCipher = CopyStr(name);
\r
5574 // TCP-SSL 通信を開始する
\r
5575 bool StartSSL(SOCK *sock, X *x, K *priv)
\r
5577 return StartSSLEx(sock, x, priv, false);
\r
5579 bool StartSSLEx(SOCK *sock, X *x, K *priv, bool client_tls)
\r
5583 UINT prev_timeout = 1024;
\r
5585 #ifdef UNIX_SOLARIS
\r
5586 SOCKET_TIMEOUT_PARAM *ttparam;
\r
5587 #endif //UNIX_SOLARIS
\r
5592 Debug("StartSSL Error: #0\n");
\r
5595 if (sock->Connected == false || sock->socket == INVALID_SOCKET ||
\r
5596 sock->ListenMode != false)
\r
5598 Debug("StartSSL Error: #1\n");
\r
5601 if (x != NULL && priv == NULL)
\r
5603 Debug("StartSSL Error: #2\n");
\r
5607 if (sock->SecureMode)
\r
5609 Debug("StartSSL Error: #3\n");
\r
5610 // すでに SSL 通信が開始されている
\r
5614 Lock(sock->ssl_lock);
\r
5615 if (sock->SecureMode)
\r
5617 Debug("StartSSL Error: #4\n");
\r
5618 // すでに SSL 通信が開始されている
\r
5619 Unlock(sock->ssl_lock);
\r
5623 Lock(openssl_lock);
\r
5625 if (sock->ServerMode)
\r
5627 SSL_CTX_set_ssl_version(ssl_ctx, SSLv23_method());
\r
5631 if (client_tls == false)
\r
5633 SSL_CTX_set_ssl_version(ssl_ctx, SSLv3_method());
\r
5637 SSL_CTX_set_ssl_version(ssl_ctx, TLSv1_client_method());
\r
5640 sock->ssl = SSL_new(ssl_ctx);
\r
5641 SSL_set_fd(sock->ssl, (int)sock->socket);
\r
5643 Unlock(openssl_lock);
\r
5648 if (CheckXandK(x, priv))
\r
5654 Lock(openssl_lock);
\r
5656 SSL_use_certificate(sock->ssl, x509);
\r
5657 SSL_use_PrivateKey(sock->ssl, key);
\r
5659 Unlock(openssl_lock);
\r
5663 if (sock->WaitToUseCipher != NULL)
\r
5665 // 使用したい暗号化アルゴリズム名を設定する
\r
5666 Lock(openssl_lock);
\r
5668 SSL_set_cipher_list(sock->ssl, sock->WaitToUseCipher);
\r
5670 Unlock(openssl_lock);
\r
5673 if (sock->ServerMode)
\r
5675 // Lock(ssl_connect_lock);
\r
5677 // SOLARIS用タイムアウトスレッドの起動
\r
5678 #ifdef UNIX_SOLARIS
\r
5679 ttparam = NewSocketTimeout(sock);
\r
5680 #endif // UNIX_SOLARIS
\r
5683 if (SSL_accept(sock->ssl) <= 0)
\r
5687 #ifdef UNIX_SOLARIS
\r
5688 FreeSocketTimeout(ttparam);
\r
5689 #endif // UNIX_SOLARIS
\r
5691 // Unlock(ssl_connect_lock);
\r
5693 Lock(openssl_lock);
\r
5695 SSL_free(sock->ssl);
\r
5697 Unlock(openssl_lock);
\r
5699 Unlock(sock->ssl_lock);
\r
5700 Debug("StartSSL Error: #5\n");
\r
5705 #ifdef UNIX_SOLARIS
\r
5706 FreeSocketTimeout(ttparam);
\r
5707 #endif // UNIX_SOLARIS
\r
5709 // Unlock(ssl_connect_lock);
\r
5713 prev_timeout = GetTimeout(sock);
\r
5714 SetTimeout(sock, TIMEOUT_SSL_CONNECT);
\r
5715 Lock(ssl_connect_lock);
\r
5717 if (SSL_connect(sock->ssl) <= 0)
\r
5719 Unlock(ssl_connect_lock);
\r
5721 Lock(openssl_lock);
\r
5723 SSL_free(sock->ssl);
\r
5725 Unlock(openssl_lock);
\r
5727 Unlock(sock->ssl_lock);
\r
5728 Debug("StartSSL Error: #5\n");
\r
5729 SetTimeout(sock, prev_timeout);
\r
5732 Unlock(ssl_connect_lock);
\r
5733 SetTimeout(sock, prev_timeout);
\r
5737 sock->SecureMode = true;
\r
5739 // リモートホストの証明書を取得する
\r
5740 Lock(openssl_lock);
\r
5742 x509 = SSL_get_peer_certificate(sock->ssl);
\r
5744 Unlock(openssl_lock);
\r
5748 // リモートホストに証明書は存在しない
\r
5749 sock->RemoteX = NULL;
\r
5754 sock->RemoteX = X509ToX(x509);
\r
5757 // ローカルホストの証明書を取得する
\r
5758 Lock(openssl_lock);
\r
5760 x509 = SSL_get_certificate(sock->ssl);
\r
5762 Unlock(openssl_lock);
\r
5766 // リモートホストに証明書は存在しない
\r
5767 sock->LocalX = NULL;
\r
5773 local_x = X509ToX(x509);
\r
5774 local_x->do_not_free = true;
\r
5775 sock->LocalX = CloneX(local_x);
\r
5780 SSL_set_mode(sock->ssl, SSL_MODE_AUTO_RETRY);
\r
5783 SSL_set_mode(sock->ssl, SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER);
\r
5785 // 暗号化に使用しているアルゴリズム名を取得
\r
5786 Lock(openssl_lock);
\r
5788 sock->CipherName = CopyStr((char *)SSL_get_cipher(sock->ssl));
\r
5790 Unlock(openssl_lock);
\r
5792 Unlock(sock->ssl_lock);
\r
5798 UINT SecureRecv(SOCK *sock, void *data, UINT size)
\r
5804 #ifdef UNIX_SOLARIS
\r
5805 SOCKET_TIMEOUT_PARAM *ttparam;
\r
5806 #endif //UNIX_SOLARIS
\r
5811 if (sock->AsyncMode)
\r
5813 // 非同期モードの場合はデータが 1 バイトでも読み出し可能かどうか確認する。
\r
5814 // 読み出し可能なデータが無い場合に read をしてしまうとブロッキングするため
\r
5817 Lock(sock->ssl_lock);
\r
5819 if (sock->Connected == false)
\r
5821 Unlock(sock->ssl_lock);
\r
5822 Debug("%s %u SecureRecv() Disconnect\n", __FILE__, __LINE__);
\r
5825 ret = SSL_peek(ssl, &c, sizeof(c));
\r
5827 Unlock(sock->ssl_lock);
\r
5832 Debug("%s %u SecureRecv() Disconnect\n", __FILE__, __LINE__);
\r
5838 e = SSL_get_error(ssl, ret);
\r
5839 if (e == SSL_ERROR_WANT_READ || e == SSL_ERROR_WANT_WRITE || e == SSL_ERROR_SSL)
\r
5841 // パケットがまだ届いていない、つまり read してはいけない
\r
5842 return SOCK_LATER;
\r
5848 Lock(sock->ssl_lock);
\r
5850 if (sock->Connected == false)
\r
5852 Unlock(sock->ssl_lock);
\r
5853 Debug("%s %u SecureRecv() Disconnect\n", __FILE__, __LINE__);
\r
5858 if (sock->AsyncMode == false)
\r
5860 sock->CallingThread = pthread_self();
\r
5864 // SOLARIS用タイムアウトスレッドの起動
\r
5865 #ifdef UNIX_SOLARIS
\r
5866 ttparam = NewSocketTimeout(sock);
\r
5867 #endif // UNIX_SOLARIS
\r
5869 ret = SSL_read(ssl, data, size);
\r
5872 #ifdef UNIX_SOLARIS
\r
5873 FreeSocketTimeout(ttparam);
\r
5874 #endif // UNIX_SOLARIS
\r
5878 if (sock->AsyncMode == false)
\r
5880 sock->CallingThread = 0;
\r
5886 e = SSL_get_error(ssl, ret);
\r
5890 Unlock(sock->ssl_lock);
\r
5894 sock->RecvSize += (UINT64)ret;
\r
5902 Debug("%s %u SecureRecv() Disconnect\n", __FILE__, __LINE__);
\r
5905 if (sock->AsyncMode)
\r
5907 if (e == SSL_ERROR_WANT_READ || e == SSL_ERROR_WANT_WRITE || e == SSL_ERROR_SSL)
\r
5910 return SOCK_LATER;
\r
5914 Debug("%s %u SecureRecv() Disconnect\n", __FILE__, __LINE__);
\r
5919 UINT SecureSend(SOCK *sock, void *data, UINT size)
\r
5927 if (sock->AsyncMode)
\r
5930 SSL_set_mode(ssl, SSL_MODE_ENABLE_PARTIAL_WRITE);
\r
5934 Lock(sock->ssl_lock);
\r
5936 if (sock->Connected == false)
\r
5938 Unlock(sock->ssl_lock);
\r
5939 Debug("%s %u SecureRecv() Disconnect\n", __FILE__, __LINE__);
\r
5943 ret = SSL_write(ssl, data, size);
\r
5946 e = SSL_get_error(ssl, ret);
\r
5949 Unlock(sock->ssl_lock);
\r
5954 sock->SendSize += (UINT64)ret;
\r
5956 sock->WriteBlocked = false;
\r
5962 Debug("%s %u SecureRecv() Disconnect\n", __FILE__, __LINE__);
\r
5967 if (sock->AsyncMode)
\r
5970 if (e == SSL_ERROR_WANT_READ || e == SSL_ERROR_WANT_WRITE || e == SSL_ERROR_SSL)
\r
5972 sock->WriteBlocked = true;
\r
5973 return SOCK_LATER;
\r
5975 Debug("%s %u e=%u\n", __FILE__, __LINE__, e);
\r
5977 //Debug("%s %u SecureRecv() Disconnect\n", __FILE__, __LINE__);
\r
5983 UINT Recv(SOCK *sock, void *data, UINT size, bool secure)
\r
5988 #ifdef UNIX_SOLARIS
\r
5989 SOCKET_TIMEOUT_PARAM *ttparam;
\r
5990 #endif //UNIX_SOLARIS
\r
5993 if (sock == NULL || data == NULL || size == 0)
\r
5997 if (sock->Type != SOCK_TCP || sock->Connected == false || sock->ListenMode != false ||
\r
5998 sock->socket == INVALID_SOCKET)
\r
6002 if (secure != false && sock->SecureMode == false)
\r
6009 return SecureRecv(sock, data, size);
\r
6017 if (sock->AsyncMode == false)
\r
6019 sock->CallingThread = pthread_self();
\r
6023 // SOLARIS用タイムアウトスレッドの開始
\r
6024 #ifdef UNIX_SOLARIS
\r
6025 ttparam = NewSocketTimeout(sock);
\r
6026 #endif // UNIX_SOLARIS
\r
6028 ret = recv(s, data, size, 0);
\r
6031 #ifdef UNIX_SOLARIS
\r
6032 FreeSocketTimeout(ttparam);
\r
6033 #endif // UNIX_SOLARIS
\r
6036 if (sock->AsyncMode == false)
\r
6038 sock->CallingThread = 0;
\r
6047 sock->RecvSize += (UINT64)ret;
\r
6050 Unlock(sock->lock);
\r
6055 if (sock->AsyncMode)
\r
6057 // 非同期モードの場合、エラーを調べる
\r
6058 if (ret == SOCKET_ERROR)
\r
6061 if (WSAGetLastError() == WSAEWOULDBLOCK)
\r
6064 return SOCK_LATER;
\r
6068 Debug("Socket Error: %u\n", WSAGetLastError());
\r
6071 if (errno == EAGAIN)
\r
6074 return SOCK_LATER;
\r
6076 #endif // OS_WIN32
\r
6086 UINT Send(SOCK *sock, void *data, UINT size, bool secure)
\r
6091 if (sock == NULL || data == NULL || size == 0)
\r
6095 size = MIN(size, MAX_SEND_BUF_MEM_SIZE);
\r
6096 if (sock->Type != SOCK_TCP || sock->Connected == false || sock->ListenMode != false ||
\r
6097 sock->socket == INVALID_SOCKET)
\r
6101 if (secure != false && sock->SecureMode == false)
\r
6108 return SecureSend(sock, data, size);
\r
6113 ret = send(s, data, size, 0);
\r
6119 sock->SendSize += (UINT64)ret;
\r
6122 Unlock(sock->lock);
\r
6123 sock->WriteBlocked = false;
\r
6128 if (sock->AsyncMode)
\r
6130 // 非同期モードの場合、エラーを調べる
\r
6131 if (ret == SOCKET_ERROR)
\r
6134 if (WSAGetLastError() == WSAEWOULDBLOCK)
\r
6137 sock->WriteBlocked = true;
\r
6138 return SOCK_LATER;
\r
6142 Debug("Socket Error: %u\n", WSAGetLastError());
\r
6145 if (errno == EAGAIN)
\r
6148 sock->WriteBlocked = true;
\r
6149 return SOCK_LATER;
\r
6151 #endif // OS_WIN32
\r
6160 // タイムアウトの取得 (ミリ秒)
\r
6161 UINT GetTimeout(SOCK *sock)
\r
6168 if (sock->Type != SOCK_TCP)
\r
6173 return sock->TimeOut;
\r
6176 // タイムアウト時間の設定 (ミリ秒)
\r
6177 void SetTimeout(SOCK *sock, UINT timeout)
\r
6184 if (sock->Type != SOCK_TCP)
\r
6189 if (timeout == INFINITE)
\r
6191 timeout = TIMEOUT_INFINITE;
\r
6194 sock->TimeOut = timeout;
\r
6196 // Debug("SetTimeout(%u)\n",timeout);
\r
6199 setsockopt(sock->socket, SOL_SOCKET, SO_SNDTIMEO, (char *)&timeout, sizeof(UINT));
\r
6200 setsockopt(sock->socket, SOL_SOCKET, SO_RCVTIMEO, (char *)&timeout, sizeof(UINT));
\r
6204 #ifndef UNIX_SOLARIS
\r
6206 struct timeval tv_timeout;
\r
6208 tv_timeout.tv_sec = timeout / 1000; // miliseconds to seconds
\r
6209 tv_timeout.tv_usec = (timeout % 1000) * 1000; // miliseconds to microseconds
\r
6211 setsockopt(sock->socket, SOL_SOCKET, SO_SNDTIMEO, (char *)&tv_timeout, sizeof(tv_timeout));
\r
6212 setsockopt(sock->socket, SOL_SOCKET, SO_RCVTIMEO, (char *)&tv_timeout, sizeof(tv_timeout));
\r
6214 #endif // UNIX_SOLARIS
\r
6219 void AcceptInit(SOCK *s)
\r
6221 char tmp[MAX_SIZE];
\r
6228 Zero(tmp, sizeof(tmp));
\r
6229 if (GetHostName(tmp, sizeof(tmp), &s->RemoteIP) == false ||
\r
6232 IPToStr(tmp, sizeof(tmp), &s->RemoteIP);
\r
6235 s->RemoteHostname = CopyStr(tmp);
\r
6239 SOCK *Accept(SOCK *sock)
\r
6242 SOCKET s, new_socket;
\r
6244 struct sockaddr_in addr;
\r
6245 bool true_flag = true;
\r
6251 if (sock->ListenMode == false || sock->Type != SOCK_TCP || sock->ServerMode == false)
\r
6255 if (sock->CancelAccept)
\r
6261 return Accept6(sock);
\r
6265 if (s == INVALID_SOCKET)
\r
6269 Zero(&addr, sizeof(addr));
\r
6270 size = sizeof(addr);
\r
6273 sock->CallingThread = pthread_self();
\r
6276 new_socket = accept(s, (struct sockaddr *)&addr,(int *)&size);
\r
6279 sock->CallingThread = 0;
\r
6282 if (new_socket == INVALID_SOCKET)
\r
6286 if (sock->CancelAccept)
\r
6288 closesocket(new_socket);
\r
6293 ret->socket = new_socket;
\r
6294 ret->Connected = true;
\r
6295 ret->AsyncMode = false;
\r
6296 ret->Type = SOCK_TCP;
\r
6297 ret->ServerMode = true;
\r
6298 ret->SecureMode = false;
\r
6301 setsockopt(ret->socket, IPPROTO_TCP, TCP_NODELAY, (char *)&true_flag, sizeof(bool));
\r
6303 SetSockPriorityHigh(ret);
\r
6306 SetTimeout(ret, TIMEOUT_INFINITE);
\r
6309 QuerySocketInformation(ret);
\r
6311 AddIpClient(&ret->RemoteIP);
\r
6315 SOCK *Accept6(SOCK *sock)
\r
6318 SOCKET s, new_socket;
\r
6320 struct sockaddr_in6 addr;
\r
6321 bool true_flag = true;
\r
6327 if (sock->ListenMode == false || sock->Type != SOCK_TCP || sock->ServerMode == false)
\r
6331 if (sock->CancelAccept)
\r
6335 if (sock->IPv6 == false)
\r
6341 if (s == INVALID_SOCKET)
\r
6345 Zero(&addr, sizeof(addr));
\r
6346 size = sizeof(addr);
\r
6349 sock->CallingThread = pthread_self();
\r
6352 new_socket = accept(s, (struct sockaddr *)&addr,(int *)&size);
\r
6355 sock->CallingThread = 0;
\r
6358 if (new_socket == INVALID_SOCKET)
\r
6362 if (sock->CancelAccept)
\r
6364 closesocket(new_socket);
\r
6369 ret->socket = new_socket;
\r
6370 ret->Connected = true;
\r
6371 ret->AsyncMode = false;
\r
6372 ret->Type = SOCK_TCP;
\r
6373 ret->ServerMode = true;
\r
6374 ret->SecureMode = false;
\r
6377 setsockopt(ret->socket, IPPROTO_TCP, TCP_NODELAY, (char *)&true_flag, sizeof(bool));
\r
6379 SetSockPriorityHigh(ret);
\r
6382 SetTimeout(ret, TIMEOUT_INFINITE);
\r
6385 QuerySocketInformation(ret);
\r
6387 AddIpClient(&ret->RemoteIP);
\r
6392 // TCP 待ち受け (IPv6)
\r
6393 SOCK *Listen6(UINT port)
\r
6395 return ListenEx6(port, false);
\r
6397 SOCK *ListenEx6(UINT port, bool local_only)
\r
6401 struct sockaddr_in6 addr;
\r
6402 struct in6_addr in;
\r
6403 bool true_flag = true;
\r
6406 if (port == 0 || port >= 65536)
\r
6412 Zero(&addr, sizeof(addr));
\r
6413 Zero(&in, sizeof(in));
\r
6414 GetLocalHostIP6(&localhost);
\r
6416 addr.sin6_port = htons((UINT)port);
\r
6417 addr.sin6_family = AF_INET6;
\r
6421 IPToInAddr6(&addr.sin6_addr, &localhost);
\r
6425 s = socket(AF_INET6, SOCK_STREAM, 0);
\r
6426 if (s == INVALID_SOCKET)
\r
6432 // UNIX 系では IPv6 Only フラグを立てる必要がある
\r
6433 setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY, &true_flag, sizeof(true_flag));
\r
6436 //SetSocketSendRecvBufferSize(s, SOCKET_BUFFER_SIZE);
\r
6439 // Windows 系 OS は REUSEADDR の実装にバグがあるっぽいので
\r
6441 setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (char *)&true_flag, sizeof(bool));
\r
6444 if (bind(s, (struct sockaddr *)&addr, sizeof(struct sockaddr_in6)) != 0)
\r
6450 if (listen(s, SOMAXCONN))
\r
6459 sock->Connected = false;
\r
6460 sock->AsyncMode = false;
\r
6461 sock->ServerMode = true;
\r
6462 sock->Type = SOCK_TCP;
\r
6464 sock->ListenMode = true;
\r
6465 sock->SecureMode = false;
\r
6466 sock->LocalPort = port;
\r
6467 sock->IPv6 = true;
\r
6473 SOCK *Listen(UINT port)
\r
6475 return ListenEx(port, false);
\r
6477 SOCK *ListenEx(UINT port, bool local_only)
\r
6481 struct sockaddr_in addr;
\r
6482 struct in_addr in;
\r
6483 bool true_flag = true;
\r
6486 if (port == 0 || port >= 65536)
\r
6492 Zero(&addr, sizeof(addr));
\r
6493 Zero(&in, sizeof(in));
\r
6494 SetIP(&localhost, 127, 0, 0, 1);
\r
6496 addr.sin_port = htons((UINT)port);
\r
6497 *((UINT *)&addr.sin_addr) = htonl(INADDR_ANY);
\r
6498 addr.sin_family = AF_INET;
\r
6502 IPToInAddr(&addr.sin_addr, &localhost);
\r
6506 s = socket(AF_INET, SOCK_STREAM, 0);
\r
6507 if (s == INVALID_SOCKET)
\r
6512 //SetSocketSendRecvBufferSize(s, SOCKET_BUFFER_SIZE);
\r
6515 // Windows 系 OS は REUSEADDR の実装にバグがあるっぽいので
\r
6517 setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (char *)&true_flag, sizeof(bool));
\r
6520 if (bind(s, (struct sockaddr *)&addr, sizeof(struct sockaddr_in)) != 0)
\r
6526 if (listen(s, SOMAXCONN))
\r
6535 sock->Connected = false;
\r
6536 sock->AsyncMode = false;
\r
6537 sock->ServerMode = true;
\r
6538 sock->Type = SOCK_TCP;
\r
6540 sock->ListenMode = true;
\r
6541 sock->SecureMode = false;
\r
6542 sock->LocalPort = port;
\r
6548 void Disconnect(SOCK *sock)
\r
6551 bool true_flag = true;
\r
6552 bool false_flag = false;
\r
6559 sock->Disconnecting = true;
\r
6562 UnixFreeAsyncSocket(sock);
\r
6563 #endif // UnixFreeAsyncSocket
\r
6565 if (sock->Type == SOCK_TCP && sock->ListenMode)
\r
6567 // Listen 中のソケットの場合は localhost に対して接続する
\r
6568 sock->CancelAccept = true;
\r
6570 if (sock->IPv6 == false)
\r
6572 CheckTCPPort("127.0.0.1", sock->LocalPort);
\r
6576 CheckTCPPort("::1", sock->LocalPort);
\r
6580 Lock(disconnect_function_lock);
\r
6582 Lock(sock->disconnect_lock);
\r
6584 if (sock->Type == SOCK_TCP)
\r
6586 if (sock->socket != INVALID_SOCKET)
\r
6589 #ifdef SO_DONTLINGER
\r
6590 setsockopt(sock->socket, SOL_SOCKET, SO_DONTLINGER, (char *)&true_flag, sizeof(bool));
\r
6591 #else // SO_DONTLINGER
\r
6592 setsockopt(sock->socket, SOL_SOCKET, SO_LINGER, (char *)&false_flag, sizeof(bool));
\r
6593 #endif // SO_DONTLINGER
\r
6594 // setsockopt(sock->socket, SOL_SOCKET, SO_REUSEADDR, (char *)&true_flag, sizeof(bool));
\r
6600 if (sock->socket == INVALID_SOCKET)
\r
6602 Unlock(sock->lock);
\r
6603 Unlock(sock->disconnect_lock);
\r
6604 Unlock(disconnect_function_lock);
\r
6609 if (sock->Connected)
\r
6611 struct linger ling;
\r
6612 Zero(&ling, sizeof(ling));
\r
6617 Lock(sock->ssl_lock);
\r
6619 if (sock->SecureMode)
\r
6621 SSL_shutdown(sock->ssl);
\r
6624 Unlock(sock->ssl_lock);
\r
6634 #ifdef FIX_SSL_BLOCKING
\r
6635 if (sock->CallingThread != NULL)
\r
6637 pthread_kill(sock->CallingThread, 64);
\r
6639 #endif // FIX_SSL_BLOCKING
\r
6643 Lock(sock->ssl_lock);
\r
6645 if (sock->SecureMode)
\r
6647 if (sock->ssl != NULL)
\r
6649 Lock(openssl_lock);
\r
6651 SSL_free(sock->ssl);
\r
6653 Unlock(openssl_lock);
\r
6656 sock->Connected = false;
\r
6658 if (sock->RemoteX != NULL)
\r
6660 FreeX(sock->RemoteX);
\r
6661 sock->RemoteX = NULL;
\r
6663 if (sock->LocalX != NULL)
\r
6665 FreeX(sock->LocalX);
\r
6666 sock->LocalX = NULL;
\r
6670 if (sock->CipherName != NULL)
\r
6672 Free(sock->CipherName);
\r
6673 sock->CipherName = NULL;
\r
6675 sock->SecureMode = false;
\r
6678 Unlock(sock->ssl_lock);
\r
6681 sock->socket = INVALID_SOCKET;
\r
6683 sock->AsyncMode = false;
\r
6684 sock->Connected = false;
\r
6685 sock->ListenMode = false;
\r
6686 sock->SecureMode = false;
\r
6688 if (sock->ServerMode && sock->ListenMode == false)
\r
6690 DelIpClient(&sock->RemoteIP);
\r
6693 Unlock(sock->lock);
\r
6695 else if (sock->Type == SOCK_UDP)
\r
6700 if (sock->socket == INVALID_SOCKET)
\r
6702 Unlock(sock->lock);
\r
6703 Unlock(sock->disconnect_lock);
\r
6704 Unlock(disconnect_function_lock);
\r
6714 sock->socket = INVALID_SOCKET;
\r
6716 sock->AsyncMode = false;
\r
6717 sock->Connected = false;
\r
6718 sock->ListenMode = false;
\r
6719 sock->SecureMode = false;
\r
6721 Unlock(sock->lock);
\r
6723 Unlock(sock->disconnect_lock);
\r
6725 Unlock(disconnect_function_lock);
\r
6728 typedef struct TCP_PORT_CHECK
\r
6731 char hostname[MAX_SIZE];
\r
6736 // TCP ポートチェック用スレッド
\r
6737 void CheckTCPPortThread(THREAD *thread, void *param)
\r
6739 TCP_PORT_CHECK *c;
\r
6742 if (thread == NULL || param == NULL)
\r
6747 c = (TCP_PORT_CHECK *)param;
\r
6749 NoticeThreadInit(thread);
\r
6751 AddWaitThread(thread);
\r
6753 s = Connect(c->hostname, c->port);
\r
6761 if (Release(c->ref) == 0)
\r
6766 DelWaitThread(thread);
\r
6769 // TCP ポートに接続可能かどうかチェックする
\r
6770 bool CheckTCPPortEx(char *hostname, UINT port, UINT timeout)
\r
6774 if (hostname == NULL || port == 0 || port >= 65536)
\r
6781 timeout = TIMEOUT_TCP_PORT_CHECK;
\r
6784 s = ConnectEx(hostname, port, timeout);
\r
6796 bool CheckTCPPort(char *hostname, UINT port)
\r
6798 return CheckTCPPortEx(hostname, port, TIMEOUT_TCP_PORT_CHECK);
\r
6802 // タイムアウト付き接続 (UNIX 版)
\r
6803 int connect_timeout(SOCKET s, struct sockaddr *addr, int size, int timeout, bool *cancel_flag)
\r
6807 UINT64 start_time;
\r
6809 if (s == INVALID_SOCKET || addr == NULL)
\r
6815 timeout = TIMEOUT_TCP_PORT_CHECK;
\r
6818 UnixSetSocketNonBlockingMode(s, true);
\r
6820 start_time = Tick64();
\r
6825 ret = connect(s, addr, size);
\r
6826 if (ret == 0 || errno == EISCONN)
\r
6833 if (((start_time + (UINT64)timeout) <= Tick64()) || (errno != EAGAIN && errno != EINPROGRESS && errno != EALREADY))
\r
6838 else if (*cancel_flag)
\r
6847 UnixSelectInner(1, (UINT *)&s, 1, (UINT *)&s, 100);
\r
6852 UnixSetSocketNonBlockingMode(s, false);
\r
6864 // タイムアウト付き接続 (Win32 版)
\r
6865 int connect_timeout(SOCKET s, struct sockaddr *addr, int size, int timeout, bool *cancel_flag)
\r
6867 UINT64 start_time;
\r
6869 bool timeouted = false;
\r
6873 UINT ret_size = 0;
\r
6874 bool is_nt = false;
\r
6876 if (s == INVALID_SOCKET || addr == NULL)
\r
6882 timeout = TIMEOUT_TCP_PORT_CHECK;
\r
6885 is_nt = OS_IS_WINDOWS_NT(GetOsInfo()->OsType);
\r
6888 hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
\r
6890 // ソケットをイベントに関連付ける
\r
6891 WSAEventSelect(s, hEvent, FD_CONNECT);
\r
6893 start_time = Tick64();
\r
6899 ret = connect(s, addr, size);
\r
6908 int err = WSAGetLastError();
\r
6909 //Debug("err=%u\n", err);
\r
6910 //Debug("cancel_flag=%u\n", *cancel_flag);
\r
6911 if (timeouted && ((err == WSAEALREADY) || (err == WSAEWOULDBLOCK && !is_nt)))
\r
6923 if (err == WSAEISCONN || (err == WSAEINVAL && is_nt))
\r
6928 if (((start_time + (UINT64)timeout) <= Tick64()) || (err != WSAEWOULDBLOCK && err != WSAEALREADY && (is_nt || err != WSAEINVAL)))
\r
6937 if (WaitForSingleObject(hEvent, 100) == WAIT_OBJECT_0)
\r
6946 WSAEventSelect(s, hEvent, 0);
\r
6949 WSAIoctl(s, FIONBIO, &zero, sizeof(zero), &tmp, sizeof(tmp), &ret_size, NULL, NULL);
\r
6952 CloseHandle(hEvent);
\r
6965 // ソケットのパケットの優先順位を向上させる (未使用)
\r
6966 void SetSockPriorityHigh(SOCK *s)
\r
6978 //setsockopt(s->socket, IPPROTO_IP, IP_TOS, (char *)&value, sizeof(int));
\r
6983 SOCK *Connect(char *hostname, UINT port)
\r
6985 return ConnectEx(hostname, port, 0);
\r
6987 SOCK *ConnectEx(char *hostname, UINT port, UINT timeout)
\r
6989 return ConnectEx2(hostname, port, timeout, NULL);
\r
6991 SOCK *ConnectEx2(char *hostname, UINT port, UINT timeout, bool *cancel_flag)
\r
6995 struct linger ling;
\r
6996 struct sockaddr_in sockaddr4;
\r
6997 struct in_addr addr4;
\r
6999 struct sockaddr_in6 sockaddr6;
\r
7000 struct in6_addr addr6;
\r
7002 bool true_flag = true;
\r
7003 bool false_flag = false;
\r
7004 char tmp[MAX_SIZE];
\r
7006 bool is_ipv6 = false;
\r
7007 bool dummy = false;
\r
7009 if (hostname == NULL || port == 0 || port >= 65536)
\r
7015 timeout = TIMEOUT_TCP_PORT_CHECK;
\r
7017 if (cancel_flag == NULL)
\r
7019 cancel_flag = &dummy;
\r
7022 Zero(¤t_ip, sizeof(current_ip));
\r
7024 Zero(&sockaddr4, sizeof(sockaddr4));
\r
7025 Zero(&addr4, sizeof(addr4));
\r
7026 Zero(&ip4, sizeof(ip4));
\r
7028 Zero(&sockaddr6, sizeof(sockaddr6));
\r
7029 Zero(&addr6, sizeof(addr6));
\r
7030 Zero(&ip6, sizeof(ip6));
\r
7033 if (GetIP46Ex(&ip4, &ip6, hostname, 0, cancel_flag) == false)
\r
7038 s = INVALID_SOCKET;
\r
7041 if (IsZeroIp(&ip4) == false)
\r
7043 // sockaddr_in の生成
\r
7044 IPToInAddr(&addr4, &ip4);
\r
7045 sockaddr4.sin_port = htons((USHORT)port);
\r
7046 sockaddr4.sin_family = AF_INET;
\r
7047 sockaddr4.sin_addr.s_addr = addr4.s_addr;
\r
7050 s = socket(AF_INET, SOCK_STREAM, 0);
\r
7051 if (s != INVALID_SOCKET)
\r
7054 if (connect_timeout(s, (struct sockaddr *)&sockaddr4, sizeof(struct sockaddr_in), timeout, cancel_flag) != 0)
\r
7058 s = INVALID_SOCKET;
\r
7062 Copy(¤t_ip, &ip4, sizeof(IP));
\r
7068 if (s == INVALID_SOCKET && IsZeroIp(&ip6) == false)
\r
7070 // sockaddr_in6 の生成
\r
7071 IPToInAddr6(&addr6, &ip6);
\r
7072 sockaddr6.sin6_port = htons((USHORT)port);
\r
7073 sockaddr6.sin6_family = AF_INET6;
\r
7074 sockaddr6.sin6_scope_id = ip6.ipv6_scope_id;
\r
7075 Copy(&sockaddr6.sin6_addr, &addr6, sizeof(addr6));
\r
7078 s = socket(AF_INET6, SOCK_STREAM, 0);
\r
7079 if (s != INVALID_SOCKET)
\r
7082 if (connect_timeout(s, (struct sockaddr *)&sockaddr6, sizeof(struct sockaddr_in6), timeout, cancel_flag) != 0)
\r
7086 s = INVALID_SOCKET;
\r
7090 Copy(¤t_ip, &ip6, sizeof(IP));
\r
7097 if (s == INVALID_SOCKET)
\r
7099 // IPv4, IPv6 の両方で接続失敗
\r
7106 sock->Type = SOCK_TCP;
\r
7107 sock->ServerMode = false;
\r
7109 SetSockPriorityHigh(sock);
\r
7112 if (GetHostName(tmp, sizeof(tmp), ¤t_ip) == false)
\r
7114 StrCpy(tmp, sizeof(tmp), hostname);
\r
7117 //Debug("PTR: %s\n", tmp);
\r
7119 sock->RemoteHostname = CopyStr(tmp);
\r
7121 // Debug("new socket: %u\n", s);
\r
7123 Zero(&ling, sizeof(ling));
\r
7125 #ifdef SO_DONTLINGER
\r
7126 setsockopt(sock->socket, SOL_SOCKET, SO_DONTLINGER, (char *)&true_flag, sizeof(bool));
\r
7127 #else // SO_DONTLINGER
\r
7128 setsockopt(sock->socket, SOL_SOCKET, SO_LINGER, (char *)&false_flag, sizeof(bool));
\r
7129 #endif // SO_DONTLINGER
\r
7130 // setsockopt(sock->socket, SOL_SOCKET, SO_REUSEADDR, (char *)&true_flag, sizeof(bool));
\r
7133 setsockopt(sock->socket, IPPROTO_TCP, TCP_NODELAY, (char *)&true_flag, sizeof(bool));
\r
7136 SetTimeout(sock, TIMEOUT_INFINITE);
\r
7139 QuerySocketInformation(sock);
\r
7141 sock->Connected = true;
\r
7142 sock->AsyncMode = false;
\r
7143 sock->SecureMode = false;
\r
7144 sock->IPv6 = is_ipv6;
\r
7149 // ソケットの送受信バッファサイズを最大にする
\r
7150 void SetSocketSendRecvBufferSize(int s, UINT size)
\r
7152 int value = (int)size;
\r
7154 if (s == INVALID_SOCKET)
\r
7159 setsockopt(s, SOL_SOCKET, SO_RCVBUF, (char *)&value, sizeof(int));
\r
7160 setsockopt(s, SOL_SOCKET, SO_SNDBUF, (char *)&value, sizeof(int));
\r
7164 void QuerySocketInformation(SOCK *sock)
\r
7174 struct sockaddr_in6 sockaddr6;
\r
7175 struct in6_addr *addr6;
\r
7178 if (sock->Type == SOCK_TCP)
\r
7181 size = sizeof(sockaddr6);
\r
7182 if (getpeername(sock->socket, (struct sockaddr *)&sockaddr6, (int *)&size) == 0)
\r
7184 if (size >= sizeof(struct sockaddr_in6))
\r
7186 sock->RemotePort = (UINT)ntohs(sockaddr6.sin6_port);
\r
7187 addr6 = &sockaddr6.sin6_addr;
\r
7188 InAddrToIP6(&sock->RemoteIP, addr6);
\r
7189 sock->RemoteIP.ipv6_scope_id = sockaddr6.sin6_scope_id;
\r
7193 struct sockaddr_in *sockaddr;
\r
7194 struct in_addr *addr;
\r
7196 sockaddr = (struct sockaddr_in *)&sockaddr6;
\r
7197 sock->RemotePort = (UINT)ntohs(sockaddr->sin_port);
\r
7198 addr = &sockaddr->sin_addr;
\r
7199 InAddrToIP(&sock->RemoteIP, addr);
\r
7205 size = sizeof(sockaddr6);
\r
7206 if (getsockname(sock->socket, (struct sockaddr *)&sockaddr6, (int *)&size) == 0)
\r
7208 if (size >= sizeof(struct sockaddr_in6))
\r
7210 sock->LocalPort = (UINT)ntohs(sockaddr6.sin6_port);
\r
7211 addr6 = &sockaddr6.sin6_addr;
\r
7212 InAddrToIP6(&sock->LocalIP, addr6);
\r
7213 sock->LocalIP.ipv6_scope_id = sockaddr6.sin6_scope_id;
\r
7217 struct sockaddr_in *sockaddr;
\r
7218 struct in_addr *addr;
\r
7220 sockaddr = (struct sockaddr_in *)&sockaddr6;
\r
7221 sock->LocalPort = (UINT)ntohs(sockaddr->sin_port);
\r
7222 addr = &sockaddr->sin_addr;
\r
7223 InAddrToIP(&sock->LocalIP, addr);
\r
7227 Unlock(sock->lock);
\r
7231 void ReleaseSock(SOCK *s)
\r
7239 if (Release(s->ref) == 0)
\r
7241 if (s->ListenMode == false && s->ServerMode)
\r
7250 void CleanupSock(SOCK *s)
\r
7258 // {Debug("CleanupSock: Disconnect() Called: %s %u\n", __FILE__, __LINE__);Disconnect(s);}
\r
7262 Win32FreeAsyncSocket(s);
\r
7264 UnixFreeAsyncSocket(s);
\r
7265 #endif // OS_WIN32
\r
7267 FreeBuf(s->SendBuf);
\r
7268 if (s->socket != INVALID_SOCKET)
\r
7271 closesocket(s->socket);
\r
7274 #endif // OS_WIN32
\r
7276 Free(s->RemoteHostname);
\r
7278 Free(s->WaitToUseCipher);
\r
7279 DeleteLock(s->lock);
\r
7280 DeleteLock(s->ssl_lock);
\r
7281 DeleteLock(s->disconnect_lock);
\r
7283 Dec(num_tcp_connections);
\r
7291 SOCK *s = ZeroMallocFast(sizeof(SOCK));
\r
7293 s->ref = NewRef();
\r
7294 s->lock = NewLock();
\r
7295 s->SendBuf = NewBuf();
\r
7296 s->socket = INVALID_SOCKET;
\r
7297 s->ssl_lock = NewLock();
\r
7298 s->disconnect_lock = NewLock();
\r
7300 Inc(num_tcp_connections);
\r
7305 // IP を UINT に変換する
\r
7306 UINT IPToUINT(IP *ip)
\r
7309 UINT i, value = 0;
\r
7316 b = (UCHAR *)&value;
\r
7317 for (i = 0;i < 4;i++)
\r
7319 b[i] = ip->addr[i];
\r
7325 // UNIT を IP に変換する
\r
7326 void UINTToIP(IP *ip, UINT value)
\r
7338 b = (UCHAR *)&value;
\r
7339 for (i = 0;i < 4;i++)
\r
7341 ip->addr[i] = b[i];
\r
7346 void GetMachineHostName(char *name, UINT size)
\r
7348 char tmp[MAX_SIZE];
\r
7356 GetMachineName(tmp, sizeof(tmp));
\r
7358 len = StrLen(tmp);
\r
7359 for (i = 0;i < len;i++)
\r
7361 if (tmp[i] == '.')
\r
7367 ConvertSafeFileName(name, size, tmp);
\r
7370 // このコンピュータの IP アドレスを取得
\r
7371 void GetMachineIp(IP *ip)
\r
7373 char tmp[MAX_SIZE];
\r
7380 Zero(ip, sizeof(IP));
\r
7381 SetIP(ip, 127, 0, 0, 1);
\r
7383 GetMachineName(tmp, sizeof(tmp));
\r
7387 // コンピュータ名を hosts から取得
\r
7388 bool GetMachineNameFromHosts(char *name, UINT size)
\r
7399 b = ReadDump("/etc/hosts");
\r
7407 s = CfgReadNextLine(b);
\r
7414 TOKEN_LIST *t = ParseToken(s, " \t");
\r
7418 if (t->NumTokens >= 2)
\r
7420 if (StrCmpi(t->Token[0], "127.0.0.1") == 0)
\r
7424 for (i = 1;i < t->NumTokens;i++)
\r
7426 if (StartWith(t->Token[i], "localhost") == false)
\r
7428 StrCpy(name, size, t->Token[i]);
\r
7446 // このコンピュータのコンピュータ名を取得
\r
7447 void GetMachineName(char *name, UINT size)
\r
7449 GetMachineNameEx(name, size, false);
\r
7451 void GetMachineNameEx(char *name, UINT size, bool no_load_hosts)
\r
7453 static char name_cache[MAX_SIZE];
\r
7454 static bool name_cached = false;
\r
7455 char tmp[MAX_SIZE];
\r
7456 char tmp2[MAX_SIZE];
\r
7464 Lock(machine_name_lock);
\r
7466 if (name_cached != false)
\r
7468 StrCpy(name, size, name_cache);
\r
7469 Unlock(machine_name_lock);
\r
7472 if (gethostname(tmp, MAX_SIZE) != 0)
\r
7474 StrCpy(name, size, "Unknown");
\r
7475 Unlock(machine_name_lock);
\r
7478 if (GetIP(&ip, tmp) == false)
\r
7480 StrCpy(name, size, tmp);
\r
7481 Unlock(machine_name_lock);
\r
7484 if (GetHostNameInner(name, size, &ip) == false || StartWith(name, "localhost"))
\r
7486 StrCpy(name, size, tmp);
\r
7488 if (StartWith(name, "localhost"))
\r
7490 if (no_load_hosts == false && OS_IS_UNIX(GetOsInfo()->OsType))
\r
7492 if (GetMachineNameFromHosts(tmp2, sizeof(tmp2)))
\r
7494 StrCpy(name, sizeof(name), tmp2);
\r
7499 StrCpy(name_cache, sizeof(name_cache), name);
\r
7500 name_cached = true;
\r
7502 Unlock(machine_name_lock);
\r
7506 void GetHostNameThread(THREAD *t, void *p)
\r
7509 char hostname[256];
\r
7511 if (t == NULL || p == NULL)
\r
7520 NoticeThreadInit(t);
\r
7522 if (GetHostNameInner(hostname, sizeof(hostname), ip))
\r
7524 AddHostCache(ip, hostname);
\r
7533 bool GetHostName(char *hostname, UINT size, IP *ip)
\r
7539 if (hostname == NULL || ip == NULL)
\r
7544 if (GetHostCache(hostname, size, ip))
\r
7546 if (IsEmptyStr(hostname) == false)
\r
7556 p_ip = ZeroMalloc(sizeof(IP));
\r
7557 Copy(p_ip, ip, sizeof(IP));
\r
7559 t = NewThread(GetHostNameThread, p_ip);
\r
7561 WaitThreadInit(t);
\r
7563 WaitThread(t, TIMEOUT_HOSTNAME);
\r
7567 ret = GetHostCache(hostname, size, ip);
\r
7572 ret = GetNetBiosName(hostname, size, ip);
\r
7575 AddHostCache(ip, hostname);
\r
7581 if (IsEmptyStr(hostname))
\r
7588 AddHostCache(ip, "");
\r
7589 StrCpy(hostname, size, "");
\r
7596 bool GetHostNameInner(char *hostname, UINT size, IP *ip)
\r
7598 struct in_addr addr;
\r
7599 struct sockaddr_in sa;
\r
7600 char tmp[MAX_SIZE];
\r
7603 if (hostname == NULL || ip == NULL)
\r
7610 return GetHostNameInner6(hostname, size, ip);
\r
7614 IPToInAddr(&addr, ip);
\r
7615 Zero(&sa, sizeof(sa));
\r
7616 sa.sin_family = AF_INET;
\r
7618 #if defined(UNIX_BSD) || defined(UNIX_MACOS)
\r
7619 sa.sin_len = INET_ADDRSTRLEN;
\r
7620 #endif // UNIX_BSD || UNIX_MACOS
\r
7622 Copy(&sa.sin_addr, &addr, sizeof(struct in_addr));
\r
7625 if (getnameinfo((struct sockaddr *)&sa, sizeof(sa), tmp, sizeof(tmp), NULL, 0, 0) != 0)
\r
7630 IPToStr(ip_str, sizeof(ip_str), ip);
\r
7632 if (StrCmpi(tmp, ip_str) == 0)
\r
7637 if (IsEmptyStr(tmp))
\r
7642 StrCpy(hostname, size, tmp);
\r
7646 bool GetHostNameInner6(char *hostname, UINT size, IP *ip)
\r
7648 struct in6_addr addr;
\r
7649 struct sockaddr_in6 sa;
\r
7650 char tmp[MAX_SIZE];
\r
7653 if (hostname == NULL || ip == NULL)
\r
7659 IPToInAddr6(&addr, ip);
\r
7660 Zero(&sa, sizeof(sa));
\r
7661 sa.sin6_family = AF_INET6;
\r
7663 #if defined(UNIX_BSD) || defined(UNIX_MACOS)
\r
7664 sa.sin6_len = INET6_ADDRSTRLEN;
\r
7665 #endif // UNIX_BSD || UNIX_MACOS
\r
7667 Copy(&sa.sin6_addr, &addr, sizeof(struct in6_addr));
\r
7670 if (getnameinfo((struct sockaddr *)&sa, sizeof(sa), tmp, sizeof(tmp), NULL, 0, 0) != 0)
\r
7675 IPToStr(ip_str, sizeof(ip_str), ip);
\r
7677 if (StrCmpi(tmp, ip_str) == 0)
\r
7682 if (IsEmptyStr(tmp))
\r
7687 StrCpy(hostname, size, tmp);
\r
7692 #define NUM_NBT_QUERYS_SEND 3
\r
7694 // IP アドレスからそのマシンの NetBIOS 名を取得する
\r
7695 bool GetNetBiosName(char *name, UINT size, IP *ip)
\r
7699 bool flag = false;
\r
7703 USHORT tran_id[NUM_NBT_QUERYS_SEND];
\r
7704 UINT64 timeout_tick;
\r
7706 if (name == NULL || ip == NULL)
\r
7711 IPToStr(name, size, ip);
\r
7713 for (i = 0;i < NUM_NBT_QUERYS_SEND;i++)
\r
7715 tran_id[i] = Rand16();
\r
7724 for (j = 0;j < NUM_NBT_QUERYS_SEND;j++)
\r
7726 Zero(&req, sizeof(req));
\r
7727 req.TransactionId = Endian16(tran_id[j]);
\r
7728 req.NumQuestions = Endian16(1);
\r
7729 req.Query[0] = 0x20;
\r
7730 req.Query[1] = 0x43;
\r
7731 req.Query[2] = 0x4b;
\r
7732 for (i = 3;i <= 32;i++)
\r
7734 req.Query[i] = 0x41;
\r
7736 req.Query[35] = 0x21;
\r
7737 req.Query[37] = 0x01;
\r
7739 if (SendTo(s, ip, 137, &req, sizeof(req)) == 0)
\r
7746 timeout_tick = Tick() + (UINT64)TIMEOUT_NETBIOS_HOSTNAME;
\r
7754 if (Tick() >= timeout_tick)
\r
7758 InitSockSet(&set);
\r
7759 AddSockSet(&set, s);
\r
7760 Select(&set, 100, NULL, NULL);
\r
7762 if (flag == false)
\r
7771 ret = RecvFrom(s, &src_ip, &src_port, buf, sizeof(buf));
\r
7773 if (ret == SOCK_LATER)
\r
7777 else if (ret == 0)
\r
7783 if (ret >= sizeof(NBTRESPONSE))
\r
7785 NBTRESPONSE *r = (NBTRESPONSE *)buf;
\r
7788 USHORT id = Endian16(r->TransactionId);
\r
7789 for (i = 0;i < NUM_NBT_QUERYS_SEND;i++)
\r
7791 if (id == tran_id[i])
\r
7799 if (r->Flags != 0 && r->NumQuestions == 0 && r->AnswerRRs >= 1)
\r
7801 if (r->Response[0] == 0x20 && r->Response[1] == 0x43 &&
\r
7802 r->Response[2] == 0x4b)
\r
7804 if (r->Response[34] == 0x00 && r->Response[35] == 0x21 &&
\r
7805 r->Response[36] == 0x00 && r->Response[37] == 0x01)
\r
7807 char *a = (char *)(&r->Response[45]);
\r
7808 if (StrCheckLen(a, 15))
\r
7810 if (IsEmptyStr(a) == false)
\r
7812 StrCpy(name, size, a);
\r
7835 void SetIP(IP *ip, UCHAR a1, UCHAR a2, UCHAR a3, UCHAR a4)
\r
7843 Zero(ip, sizeof(IP));
\r
7850 // DNS 正引きを行って結果を v4 と v6 のどちらかで得る (両方の場合は IPv4 優先)
\r
7851 bool GetIP46Any4(IP *ip, char *hostname)
\r
7856 if (ip == NULL || hostname == NULL)
\r
7861 if (GetIP46(&ip4, &ip6, hostname) == false)
\r
7866 if (IsZeroIp(&ip6) == false)
\r
7868 Copy(ip, &ip6, sizeof(IP));
\r
7873 if (IsZeroIp(&ip4) == false)
\r
7875 Copy(ip, &ip4, sizeof(IP));
\r
7883 // DNS 正引きを行って結果を v4 と v6 のどちらかで得る (両方の場合は IPv6 優先)
\r
7884 bool GetIP46Any6(IP *ip, char *hostname)
\r
7889 if (ip == NULL || hostname == NULL)
\r
7894 if (GetIP46(&ip4, &ip6, hostname) == false)
\r
7899 if (IsZeroIp(&ip4) == false)
\r
7901 Copy(ip, &ip4, sizeof(IP));
\r
7906 if (IsZeroIp(&ip6) == false)
\r
7908 Copy(ip, &ip6, sizeof(IP));
\r
7916 // DNS 正引きを行って結果を v4 と v6 の両方で得る
\r
7917 bool GetIP46(IP *ip4, IP *ip6, char *hostname)
\r
7919 return GetIP46Ex(ip4, ip6, hostname, 0, NULL);
\r
7921 bool GetIP46Ex(IP *ip4, IP *ip6, char *hostname, UINT timeout, bool *cancel)
\r
7926 if (ip4 == NULL || ip6 == NULL || hostname == NULL)
\r
7934 ok_a = ok_b = false;
\r
7936 if (GetIP6Ex(&a, hostname, timeout, cancel))
\r
7941 if (GetIP4Ex(&b, hostname, timeout, cancel))
\r
7950 Copy(ip4, &a, sizeof(IP));
\r
7957 Copy(ip4, &b, sizeof(IP));
\r
7962 Copy(ip6, &b, sizeof(IP));
\r
7969 Copy(ip6, &a, sizeof(IP));
\r
7973 if (IsZeroIp(ip4) && IsZeroIp(ip6))
\r
7981 // GetIP 用スレッドのパラメータのクリーンアップ
\r
7982 void CleanupGetIPThreadParam(GETIP_THREAD_PARAM *p)
\r
7993 // GetIP 用スレッドのパラメータの解放
\r
7994 void ReleaseGetIPThreadParam(GETIP_THREAD_PARAM *p)
\r
8002 if (Release(p->Ref) == 0)
\r
8004 CleanupGetIPThreadParam(p);
\r
8008 // DNS 正引きクエリ (タイムアウト付き) を行うスレッド
\r
8009 void GetIP4Ex6ExThread(THREAD *t, void *param)
\r
8011 GETIP_THREAD_PARAM *p;
\r
8013 if (t == NULL || param == NULL)
\r
8018 p = (GETIP_THREAD_PARAM *)param;
\r
8022 NoticeThreadInit(t);
\r
8027 if (p->IPv6 == false)
\r
8030 p->Ok = GetIP4Inner(&p->Ip, p->HostName);
\r
8035 p->Ok = GetIP6Inner(&p->Ip, p->HostName);
\r
8038 ReleaseGetIPThreadParam(p);
\r
8043 // DNS 正引きクエリ (タイムアウト付き) を行う
\r
8044 bool GetIP4Ex6Ex(IP *ip, char *hostname, UINT timeout, bool ipv6, bool *cancel)
\r
8046 GETIP_THREAD_PARAM *p;
\r
8049 UINT64 start_tick = 0;
\r
8050 UINT64 end_tick = 0;
\r
8052 if (ip == NULL || hostname == NULL)
\r
8058 timeout = TIMEOUT_GETIP;
\r
8061 p = ZeroMalloc(sizeof(GETIP_THREAD_PARAM));
\r
8062 p->Ref = NewRef();
\r
8063 StrCpy(p->HostName, sizeof(p->HostName), hostname);
\r
8065 p->Timeout = timeout;
\r
8068 t = NewThread(GetIP4Ex6ExThread, p);
\r
8069 WaitThreadInit(t);
\r
8071 if (cancel == NULL)
\r
8073 WaitThread(t, timeout);
\r
8077 start_tick = Tick64();
\r
8078 end_tick = start_tick + (UINT64)timeout;
\r
8082 UINT64 now = Tick64();
\r
8091 if (now >= end_tick)
\r
8096 remain = end_tick - now;
\r
8097 remain32 = MIN((UINT)remain, 100);
\r
8099 if (WaitThread(t, remain32))
\r
8111 Copy(ip, &p->Ip, sizeof(IP));
\r
8114 ReleaseGetIPThreadParam(p);
\r
8118 bool GetIP4Ex(IP *ip, char *hostname, UINT timeout, bool *cancel)
\r
8120 return GetIP4Ex6Ex(ip, hostname, timeout, false, cancel);
\r
8122 bool GetIP6Ex(IP *ip, char *hostname, UINT timeout, bool *cancel)
\r
8124 return GetIP4Ex6Ex(ip, hostname, timeout, true, cancel);
\r
8126 bool GetIP4(IP *ip, char *hostname)
\r
8128 return GetIP4Ex(ip, hostname, 0, NULL);
\r
8130 bool GetIP6(IP *ip, char *hostname)
\r
8132 return GetIP6Ex(ip, hostname, 0, NULL);
\r
8136 bool GetIP(IP *ip, char *hostname)
\r
8138 return GetIPEx(ip, hostname, false);
\r
8140 bool GetIPEx(IP *ip, char *hostname, bool ipv6)
\r
8142 if (ipv6 == false)
\r
8144 return GetIP4(ip, hostname);
\r
8148 return GetIP6(ip, hostname);
\r
8151 bool GetIP6Inner(IP *ip, char *hostname)
\r
8153 struct sockaddr_in6 in;
\r
8154 struct in6_addr addr;
\r
8155 struct addrinfo hint;
\r
8156 struct addrinfo *info;
\r
8158 if (ip == NULL || hostname == NULL)
\r
8163 if (IsEmptyStr(hostname))
\r
8168 if (StrCmpi(hostname, "localhost") == 0)
\r
8170 GetLocalHostIP6(ip);
\r
8174 if (StrToIP6(ip, hostname) == false && StrToIP(ip, hostname) == false)
\r
8177 Zero(&hint, sizeof(hint));
\r
8178 hint.ai_family = AF_INET6;
\r
8179 hint.ai_socktype = SOCK_STREAM;
\r
8180 hint.ai_protocol = IPPROTO_TCP;
\r
8183 if (getaddrinfo(hostname, NULL, &hint, &info) != 0 ||
\r
8184 info->ai_family != AF_INET6)
\r
8188 freeaddrinfo(info);
\r
8190 return QueryDnsCacheEx(ip, hostname, true);
\r
8193 Copy(&in, info->ai_addr, sizeof(struct sockaddr_in6));
\r
8194 freeaddrinfo(info);
\r
8196 Copy(&addr, &in.sin6_addr, sizeof(addr));
\r
8197 InAddrToIP6(ip, &addr);
\r
8201 NewDnsCache(hostname, ip);
\r
8205 bool GetIP4Inner(IP *ip, char *hostname)
\r
8207 struct sockaddr_in in;
\r
8208 struct in_addr addr;
\r
8209 struct addrinfo hint;
\r
8210 struct addrinfo *info;
\r
8212 if (ip == NULL || hostname == NULL)
\r
8217 if (IsEmptyStr(hostname))
\r
8222 if (StrCmpi(hostname, "localhost") == 0)
\r
8224 SetIP(ip, 127, 0, 0, 1);
\r
8228 if (StrToIP6(ip, hostname) == false && StrToIP(ip, hostname) == false)
\r
8231 Zero(&hint, sizeof(hint));
\r
8232 hint.ai_family = AF_INET;
\r
8233 hint.ai_socktype = SOCK_STREAM;
\r
8234 hint.ai_protocol = IPPROTO_TCP;
\r
8237 if (getaddrinfo(hostname, NULL, &hint, &info) != 0 ||
\r
8238 info->ai_family != AF_INET)
\r
8242 freeaddrinfo(info);
\r
8244 return QueryDnsCache(ip, hostname);
\r
8247 Copy(&in, info->ai_addr, sizeof(struct sockaddr_in));
\r
8248 freeaddrinfo(info);
\r
8249 Copy(&addr, &in.sin_addr, sizeof(addr));
\r
8250 InAddrToIP(ip, &addr);
\r
8254 NewDnsCache(hostname, ip);
\r
8260 bool QueryDnsCache(IP *ip, char *hostname)
\r
8262 return QueryDnsCacheEx(ip, hostname, false);
\r
8264 bool QueryDnsCacheEx(IP *ip, char *hostname, bool ipv6)
\r
8267 char tmp[MAX_SIZE];
\r
8269 if (ip == NULL || hostname == NULL)
\r
8274 GenDnsCacheKeyName(tmp, sizeof(tmp), hostname, ipv6);
\r
8276 c = FindDnsCache(tmp);
\r
8282 Copy(ip, &c->IpAddress, sizeof(IP));
\r
8288 void IPToUniStr(wchar_t *str, UINT size, IP *ip)
\r
8292 IPToStr(tmp, sizeof(tmp), ip);
\r
8293 StrToUni(str, size, tmp);
\r
8296 // IP を文字列に変換 (32bit UINT)
\r
8297 void IPToUniStr32(wchar_t *str, UINT size, UINT ip)
\r
8301 IPToStr32(tmp, sizeof(tmp), ip);
\r
8302 StrToUni(str, size, tmp);
\r
8305 // IP を文字列に変換 (128bit byte array)
\r
8306 void IPToStr128(char *str, UINT size, UCHAR *ip_bytes)
\r
8315 SetIP6(&ip_st, ip_bytes);
\r
8316 IPToStr(str, size, &ip_st);
\r
8319 // IP を文字列に変換 (32bit UINT)
\r
8320 void IPToStr32(char *str, UINT size, UINT ip)
\r
8329 UINTToIP(&ip_st, ip);
\r
8330 IPToStr(str, size, &ip_st);
\r
8333 // IPv4 または IPv6 を文字列に変換
\r
8334 void IPToStr4or6(char *str, UINT size, UINT ip_4_uint, UCHAR *ip_6_bytes)
\r
8345 Zero(&ip, sizeof(ip));
\r
8347 UINTToIP(&ip4, ip_4_uint);
\r
8348 SetIP6(&ip6, ip_6_bytes);
\r
8350 if (IsIP6(&ip4) || (IsZeroIp(&ip4) && (IsZeroIp(&ip6) == false)))
\r
8352 Copy(&ip, &ip6, sizeof(IP));
\r
8356 Copy(&ip, &ip4, sizeof(IP));
\r
8359 IPToStr(str, size, &ip);
\r
8363 void IPToStr(char *str, UINT size, IP *ip)
\r
8366 if (str == NULL || ip == NULL)
\r
8373 IPToStr6(str, size, ip);
\r
8377 IPToStr4(str, size, ip);
\r
8382 void IPToStr4(char *str, UINT size, IP *ip)
\r
8385 if (str == NULL || ip == NULL)
\r
8391 snprintf(str, size != 0 ? size : 64, "%u.%u.%u.%u", ip->addr[0], ip->addr[1], ip->addr[2], ip->addr[3]);
\r
8395 bool StrToIP(IP *ip, char *str)
\r
8397 TOKEN_LIST *token;
\r
8401 if (ip == NULL || str == NULL)
\r
8406 if (StrToIP6(ip, str))
\r
8411 Zero(ip, sizeof(IP));
\r
8413 tmp = CopyStr(str);
\r
8415 token = ParseToken(tmp, ".");
\r
8418 if (token->NumTokens != 4)
\r
8423 for (i = 0;i < 4;i++)
\r
8425 char *s = token->Token[i];
\r
8426 if (s[0] < '0' || s[0] > '9' ||
\r
8427 (ToInt(s) >= 256))
\r
8433 Zero(ip, sizeof(IP));
\r
8434 for (i = 0;i < 4;i++)
\r
8436 ip->addr[i] = (UCHAR)ToInt(token->Token[i]);
\r
8443 UINT StrToIP32(char *str)
\r
8452 if (StrToIP(&ip, str) == false)
\r
8457 return IPToUINT(&ip);
\r
8459 bool UniStrToIP(IP *ip, wchar_t *str)
\r
8464 tmp = CopyUniToStr(str);
\r
8465 ret = StrToIP(ip, tmp);
\r
8470 UINT UniStrToIP32(wchar_t *str)
\r
8475 tmp = CopyUniToStr(str);
\r
8476 ret = StrToIP32(tmp);
\r
8482 // IP を in_addr に変換
\r
8483 void IPToInAddr(struct in_addr *addr, IP *ip)
\r
8487 if (addr == NULL || ip == NULL)
\r
8492 Zero(addr, sizeof(struct in_addr));
\r
8494 if (IsIP6(ip) == false)
\r
8496 for (i = 0;i < 4;i++)
\r
8498 ((UCHAR *)addr)[i] = ip->addr[i];
\r
8503 // IP を in6_addr に変換
\r
8504 void IPToInAddr6(struct in6_addr *addr, IP *ip)
\r
8508 if (addr == NULL || ip == NULL)
\r
8513 Zero(addr, sizeof(struct in_addr));
\r
8517 for (i = 0;i < 16;i++)
\r
8519 ((UCHAR *)addr)[i] = ip->ipv6_addr[i];
\r
8524 // in_addr を IP に変換
\r
8525 void InAddrToIP(IP *ip, struct in_addr *addr)
\r
8529 if (ip == NULL || addr == NULL)
\r
8534 Zero(ip, sizeof(IP));
\r
8536 for (i = 0;i < 4;i++)
\r
8538 ip->addr[i] = ((UCHAR *)addr)[i];
\r
8542 // in6_addr を IP に変換
\r
8543 void InAddrToIP6(IP *ip, struct in6_addr *addr)
\r
8547 if (ip == NULL || addr == NULL)
\r
8553 for (i = 0;i < 16;i++)
\r
8555 ip->ipv6_addr[i] = ((UCHAR *)addr)[i];
\r
8560 DNSCACHE *FindDnsCache(char *hostname)
\r
8562 return FindDnsCacheEx(hostname, false);
\r
8564 DNSCACHE *FindDnsCacheEx(char *hostname, bool ipv6)
\r
8567 char tmp[MAX_SIZE];
\r
8568 if (hostname == NULL)
\r
8573 GenDnsCacheKeyName(tmp, sizeof(tmp), hostname, ipv6);
\r
8579 c = Search(DnsCache, &t);
\r
8586 // DNS キャッシュ用の IPv4 / IPv6 キー名を生成
\r
8587 void GenDnsCacheKeyName(char *dst, UINT size, char *src, bool ipv6)
\r
8590 if (dst == NULL || src == NULL)
\r
8595 if (ipv6 == false)
\r
8597 StrCpy(dst, size, src);
\r
8601 Format(dst, size, "%s@ipv6", src);
\r
8605 // 新しい DNS キャッシュの登録
\r
8606 void NewDnsCache(char *hostname, IP *ip)
\r
8608 NewDnsCacheEx(hostname, ip, IsIP6(ip));
\r
8610 void NewDnsCacheEx(char *hostname, IP *ip, bool ipv6)
\r
8613 char tmp[MAX_PATH];
\r
8615 if (hostname == NULL || ip == NULL)
\r
8620 if (IsNetworkNameCacheEnabled() == false)
\r
8625 GenDnsCacheKeyName(tmp, sizeof(tmp), hostname, ipv6);
\r
8631 // まず hostname に該当するものがあるかどうか検索してみる
\r
8633 c = Search(DnsCache, &t);
\r
8638 c = ZeroMalloc(sizeof(DNSCACHE));
\r
8639 c->HostName = CopyStr(tmp);
\r
8641 Copy(&c->IpAddress, ip, sizeof(IP));
\r
8648 Copy(&c->IpAddress, ip, sizeof(IP));
\r
8655 int CompareDnsCache(void *p1, void *p2)
\r
8657 DNSCACHE *c1, *c2;
\r
8658 if (p1 == NULL || p2 == NULL)
\r
8662 c1 = *(DNSCACHE **)p1;
\r
8663 c2 = *(DNSCACHE **)p2;
\r
8664 if (c1 == NULL || c2 == NULL)
\r
8669 return StrCmpi(c1->HostName, c2->HostName);
\r
8673 void InitDnsCache()
\r
8676 DnsCache = NewList(CompareDnsCache);
\r
8680 void FreeDnsCache()
\r
8686 for (i = 0;i < LIST_NUM(DnsCache);i++)
\r
8689 c = LIST_DATA(DnsCache, i);
\r
8690 Free(c->HostName);
\r
8697 ReleaseList(DnsCache);
\r
8702 void LockDnsCache()
\r
8704 LockList(DnsCache);
\r
8707 // DNS キャッシュのロック解除
\r
8708 void UnlockDnsCache()
\r
8710 UnlockList(DnsCache);
\r
8713 // ネットワーク通信モジュールの初期化
\r
8714 void InitNetwork()
\r
8716 num_tcp_connections = NewCounter();
\r
8719 InitIpClientList();
\r
8729 Win32InitSocketLibrary();
\r
8731 UnixInitSocketLibrary();
\r
8732 #endif // OS_WIN32
\r
8738 ssl_ctx = SSL_CTX_new(SSLv23_method());
\r
8741 machine_name_lock = NewLock();
\r
8742 disconnect_function_lock = NewLock();
\r
8744 socket_library_lock = NewLock();
\r
8745 ssl_connect_lock = NewLock();
\r
8746 // ssl_accept_lock = NewLock();
\r
8747 dns_lock = NewLock();
\r
8748 unix_dns_server_addr_lock = NewLock();
\r
8749 Zero(&unix_dns_server, sizeof(unix_dns_server));
\r
8751 cipher_list_token = ParseToken(cipher_list, " ");
\r
8753 disable_cache = false;
\r
8756 // ネットワーク名キャッシュの有効化
\r
8757 void EnableNetworkNameCache()
\r
8759 disable_cache = false;
\r
8762 // ネットワーク名キャッシュの無効化
\r
8763 void DisableNetworkNameCache()
\r
8765 disable_cache = true;
\r
8768 // ネットワーク名キャッシュが有効かどうか取得
\r
8769 bool IsNetworkNameCacheEnabled()
\r
8771 return !disable_cache;
\r
8774 // 暗号化アルゴリズムリストを取得
\r
8775 TOKEN_LIST *GetCipherList()
\r
8777 return cipher_list_token;
\r
8780 // TCP コネクション数カウンタを取得
\r
8781 COUNTER *GetNumTcpConnectionsCounter()
\r
8783 return num_tcp_connections;
\r
8786 // ネットワーク通信モジュールの解放
\r
8787 void FreeNetwork()
\r
8789 FreeToken(cipher_list_token);
\r
8790 cipher_list_token = NULL;
\r
8792 Zero(&unix_dns_server, sizeof(unix_dns_server));
\r
8795 DeleteLock(unix_dns_server_addr_lock);
\r
8796 DeleteLock(dns_lock);
\r
8797 DeleteLock(ssl_accept_lock);
\r
8798 DeleteLock(machine_name_lock);
\r
8799 DeleteLock(disconnect_function_lock);
\r
8801 DeleteLock(socket_library_lock);
\r
8802 DeleteLock(ssl_connect_lock);
\r
8803 machine_name_lock = NULL;
\r
8804 ssl_accept_lock = machine_name_lock = disconnect_function_lock =
\r
8805 aho = socket_library_lock = ssl_connect_lock = NULL;
\r
8808 SSL_CTX_free(ssl_ctx);
\r
8822 Win32FreeSocketLibrary();
\r
8824 UnixFreeSocketLibrary();
\r
8825 #endif // OS_WIN32
\r
8827 DeleteCounter(num_tcp_connections);
\r
8828 num_tcp_connections = NULL;
\r
8831 FreeIpClientList();
\r
8834 // ソケットリストにソケットを追加する
\r
8835 void AddSockList(SOCKLIST *sl, SOCK *s)
\r
8838 if (sl == NULL || s == NULL)
\r
8843 LockList(sl->SockList);
\r
8845 if (IsInList(sl->SockList, s) == false)
\r
8849 Insert(sl->SockList, s);
\r
8852 UnlockList(sl->SockList);
\r
8855 // ソケットリストからソケットを削除する
\r
8856 void DelSockList(SOCKLIST *sl, SOCK *s)
\r
8859 if (sl == NULL || s == NULL)
\r
8864 LockList(sl->SockList);
\r
8866 if (Delete(sl->SockList, s))
\r
8871 UnlockList(sl->SockList);
\r
8874 // ソケットリストのソケットをすべて停止させて削除する
\r
8875 void StopSockList(SOCKLIST *sl)
\r
8885 LockList(sl->SockList);
\r
8887 num = LIST_NUM(sl->SockList);
\r
8888 ss = ToArray(sl->SockList);
\r
8890 DeleteAll(sl->SockList);
\r
8892 UnlockList(sl->SockList);
\r
8894 for (i = 0;i < num;i++)
\r
8906 void FreeSockList(SOCKLIST *sl)
\r
8916 ReleaseList(sl->SockList);
\r
8922 SOCKLIST *NewSockList()
\r
8924 SOCKLIST *sl = ZeroMallocFast(sizeof(SOCKLIST));
\r
8926 sl->SockList = NewList(NULL);
\r
8931 // Solarisでのソケットのタイムアウト用スレッド
\r
8932 void SocketTimeoutThread(THREAD *t, void *param)
\r
8934 SOCKET_TIMEOUT_PARAM *ttparam;
\r
8935 ttparam = (SOCKET_TIMEOUT_PARAM *)param;
\r
8938 Select(NULL, ttparam->sock->TimeOut, ttparam->cancel, NULL);
\r
8940 // ブロック中ならディスコネクトする
\r
8941 if(! ttparam->unblocked)
\r
8943 // Debug("Socket timeouted\n");
\r
8944 closesocket(ttparam->sock->socket);
\r
8948 // Debug("Socket timeout cancelled\n");
\r
8952 // タイムアウト用スレッドの初期化と開始
\r
8953 SOCKET_TIMEOUT_PARAM *NewSocketTimeout(SOCK *sock)
\r
8955 SOCKET_TIMEOUT_PARAM *ttp;
\r
8956 if(! sock->AsyncMode && sock->TimeOut != TIMEOUT_INFINITE)
\r
8958 // Debug("NewSockTimeout(%u)\n",sock->TimeOut);
\r
8960 ttp = (SOCKET_TIMEOUT_PARAM*)Malloc(sizeof(SOCKET_TIMEOUT_PARAM));
\r
8962 // タイムアウトスレッド用のパラメータをセット
\r
8963 ttp->cancel = NewCancel();
\r
8965 ttp->unblocked = false;
\r
8966 ttp->thread = NewThread(SocketTimeoutThread, ttp);
\r
8972 // タイムアウト用スレッドの停止と開放
\r
8973 void FreeSocketTimeout(SOCKET_TIMEOUT_PARAM *ttp)
\r
8980 ttp->unblocked = true;
\r
8981 Cancel(ttp->cancel);
\r
8982 WaitThread(ttp->thread, INFINITE);
\r
8983 ReleaseCancel(ttp->cancel);
\r
8984 ReleaseThread(ttp->thread);
\r
8986 // Debug("FreeSocketTimeout succeed\n");
\r
8990 // IP アドレスとサブネット マスクのパース
\r
8991 bool ParseIpAndSubnetMask46(char *src, IP *ip, IP *mask)
\r
8994 if (src == NULL || ip == NULL || mask == NULL)
\r
8999 if (ParseIpAndMask46(src, ip, mask) == false)
\r
9006 return IsSubnetMask4(mask);
\r
9010 return IsSubnetMask6(mask);
\r
9013 bool ParseIpAndSubnetMask6(char *src, IP *ip, IP *mask)
\r
9015 if (ParseIpAndSubnetMask46(src, ip, mask) == false)
\r
9020 if (IsIP6(ip) == false)
\r
9027 bool ParseIpAndSubnetMask4(char *src, UINT *ip, UINT *mask)
\r
9036 if (ParseIpAndSubnetMask46(src, &ip2, &mask2) == false)
\r
9041 if (IsIP4(&ip2) == false)
\r
9048 *ip = IPToUINT(&ip2);
\r
9053 *mask = IPToUINT(&mask2);
\r
9060 // IP アドレスとマスクのパース
\r
9061 bool ParseIpAndMask46(char *src, IP *ip, IP *mask)
\r
9070 if (src == NULL || ip == NULL || mask == NULL)
\r
9075 Zero(&ip2, sizeof(IP));
\r
9076 Zero(&mask2, sizeof(IP));
\r
9078 t = ParseToken(src, "/");
\r
9079 if (t->NumTokens != 2)
\r
9085 ipstr = t->Token[0];
\r
9086 subnetstr = t->Token[1];
\r
9090 if (StrToIP(&ip2, ipstr))
\r
9092 if (StrToIP(&mask2, subnetstr))
\r
9094 // IP アドレス部とマスク部が同一の種類かどうか比較する
\r
9095 if (IsIP6(&ip2) && IsIP6(&mask2))
\r
9099 Copy(ip, &ip2, sizeof(IP));
\r
9100 Copy(mask, &mask2, sizeof(IP));
\r
9102 else if (IsIP4(&ip2) && IsIP4(&mask2))
\r
9106 Copy(ip, &ip2, sizeof(IP));
\r
9107 Copy(mask, &mask2, sizeof(IP));
\r
9112 if (IsNum(subnetstr))
\r
9114 UINT i = ToInt(subnetstr);
\r
9116 if (IsIP6(&ip2) && i <= 128)
\r
9119 Copy(ip, &ip2, sizeof(IP));
\r
9120 IntToSubnetMask6(mask, i);
\r
9125 Copy(ip, &ip2, sizeof(IP));
\r
9126 IntToSubnetMask4(mask, i);
\r
9136 bool ParseIpAndMask4(char *src, UINT *ip, UINT *mask)
\r
9138 IP ip_ip, ip_mask;
\r
9139 if (ParseIpAndMask46(src, &ip_ip, &ip_mask) == false)
\r
9144 if (IsIP4(&ip_ip) == false)
\r
9151 *ip = IPToUINT(&ip_ip);
\r
9156 *mask = IPToUINT(&ip_mask);
\r
9161 bool ParseIpAndMask6(char *src, IP *ip, IP *mask)
\r
9163 if (ParseIpAndMask46(src, ip, mask) == false)
\r
9168 if (IsIP6(ip) == false)
\r
9177 // IPv4 アドレスの指定が正しいかどうかチェックする
\r
9178 bool IsIpStr4(char *str)
\r
9186 if (StrToIP32(str) == 0 && StrCmpi(str, "0.0.0.0") != 0)
\r
9194 // IPv6 アドレスの指定が正しいかどうかチェックする
\r
9195 bool IsIpStr6(char *str)
\r
9204 if (StrToIP6(&ip, str) == false)
\r
9212 // IP アドレスの指定が正しいかどうかチェックする
\r
9213 bool IsIpStr46(char *str)
\r
9215 if (IsIpStr4(str) || IsIpStr6(str))
\r
9224 // 文字列を IPv4 マスクに変換
\r
9225 bool StrToMask4(IP *mask, char *str)
\r
9228 if (mask == NULL || str == NULL)
\r
9233 if (str[0] == '/')
\r
9240 UINT n = ToInt(str);
\r
9244 IntToSubnetMask4(mask, n);
\r
9254 if (StrToIP(mask, str) == false)
\r
9260 return IsIP4(mask);
\r
9265 // 文字列を IPv6 マスクに変換
\r
9266 bool StrToMask6(IP *mask, char *str)
\r
9269 if (mask == NULL || str == NULL)
\r
9274 if (str[0] == '/')
\r
9281 UINT n = ToInt(str);
\r
9285 IntToSubnetMask6(mask, n);
\r
9295 if (StrToIP(mask, str) == false)
\r
9301 return IsIP6(mask);
\r
9305 bool StrToMask6Addr(IPV6_ADDR *mask, char *str)
\r
9309 if (StrToMask6(&ip, str) == false)
\r
9314 if (IPToIPv6Addr(mask, &ip) == false)
\r
9322 // 文字列を IPv4 / IPv6 マスクに変換
\r
9323 bool StrToMask46(IP *mask, char *str, bool ipv6)
\r
9327 return StrToMask6(mask, str);
\r
9331 return StrToMask4(mask, str);
\r
9336 // IPv4 / IPv6 マスクを文字列に変換
\r
9337 void MaskToStr(char *str, UINT size, IP *mask)
\r
9339 MaskToStrEx(str, size, mask, false);
\r
9341 void MaskToStrEx(char *str, UINT size, IP *mask, bool always_full_address)
\r
9344 if (str == NULL || mask == NULL)
\r
9349 if (always_full_address == false && IsSubnetMask(mask))
\r
9351 ToStr(str, SubnetMaskToInt(mask));
\r
9355 IPToStr(str, size, mask);
\r
9358 void MaskToStr32(char *str, UINT size, UINT mask)
\r
9360 MaskToStr32Ex(str, size, mask, false);
\r
9362 void MaskToStr32Ex(char *str, UINT size, UINT mask, bool always_full_address)
\r
9366 UINTToIP(&ip, mask);
\r
9368 MaskToStrEx(str, size, &ip, always_full_address);
\r
9370 void Mask6AddrToStrEx(char *str, UINT size, IPV6_ADDR *mask, bool always_full_address)
\r
9375 if (str == NULL || mask == NULL)
\r
9377 StrCpy(str, size, "");
\r
9381 IPv6AddrToIP(&ip, mask);
\r
9383 MaskToStrEx(str, size, &ip, always_full_address);
\r
9385 void Mask6AddrToStr(char *str, UINT size, IPV6_ADDR *mask)
\r
9387 Mask6AddrToStrEx(str, size, mask, false);
\r