* tar xzf utvpn-src-unix-v101-7101-public-2010.06.27.tar.gz
[lab.git] / utvpn / utvpn-unix-v101-7101-public / src / Mayaqua / Network.c
1 // SoftEther UT-VPN SourceCode\r
2 // \r
3 // Copyright (C) 2004-2010 SoftEther Corporation.\r
4 // Copyright (C) 2004-2010 University of Tsukuba, Japan.\r
5 // Copyright (C) 2003-2010 Daiyuu Nobori.\r
6 // All Rights Reserved.\r
7 // \r
8 // http://utvpn.tsukuba.ac.jp/\r
9 // \r
10 // This program is free software; you can redistribute it and/or\r
11 // modify it under the terms of the GNU General Public License\r
12 // version 2 as published by the Free Software Foundation.\r
13 // \r
14 // This program is distributed in the hope that it will be useful,\r
15 // but WITHOUT ANY WARRANTY; without even the implied warranty of\r
16 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r
17 // GNU General Public License for more details.\r
18 // \r
19 // You should have received a copy of the GNU General Public License version 2\r
20 // along with this program; if not, write to the Free Software\r
21 // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.\r
22 // \r
23 // このファイルは GPL バージョン 2 ライセンスで公開されています。\r
24 // 誰でもこのファイルの内容を複製、改変したり、改変したバージョンを再配布\r
25 // することができます。ただし、原著作物を改変した場合は、原著作物の著作権表示\r
26 // を除去することはできません。改変した著作物を配布する場合は、改変実施者の\r
27 // 著作権表示を原著作物の著作権表示に付随して記載するようにしてください。\r
28 // \r
29 // この SoftEther UT-VPN オープンソース・プロジェクトは、日本国の\r
30 // ソフトイーサ株式会社 (SoftEther Corporation, http://www.softether.co.jp/ )\r
31 // および筑波大学 (University of Tsukuba, http://www.tsukuba.ac.jp/ ) によって\r
32 // ホストされています。\r
33 // 本プログラムの配布者は、本プログラムを、業としての利用以外のため、\r
34 // および、試験または研究のために利用が行われることを想定して配布\r
35 // しています。\r
36 // SoftEther UT-VPN プロジェクトの Web サイトは http://utvpn.tsukuba.ac.jp/ に\r
37 // あります。\r
38 // 本ソフトウェアの不具合の修正、機能改良、セキュリティホールの修復などのコード\r
39 // の改変を行った場合で、その成果物を SoftEther UT-VPN プロジェクトに提出して\r
40 // いただける場合は、 http://utvpn.tsukuba.ac.jp/ までソースコードを送付して\r
41 // ください。SoftEther UT-VPN プロジェクトの本体リリースまたはブランチリリース\r
42 // に組み込みさせていただきます。\r
43 // \r
44 // GPL に基づいて原著作物が提供される本ソフトウェアの改良版を配布、販売する\r
45 // 場合は、そのソースコードを GPL に基づいて誰にでも開示する義務が生じます。\r
46 // \r
47 // 本ソフトウェアに関連する著作権、特許権、商標権はソフトイーサ株式会社\r
48 // (SoftEther Corporation) およびその他の著作権保持者が保有しています。\r
49 // ソフトイーサ株式会社等はこれらの権利を放棄していません。本ソフトウェアの\r
50 // 二次著作物を配布、販売する場合は、これらの権利を侵害しないようにご注意\r
51 // ください。\r
52 // \r
53 // お願い: どのような通信ソフトウェアにも通常は必ず未発見の\r
54 // セキュリティホールが潜んでいます。本ソースコードをご覧いただいた結果、\r
55 // UT-VPN にセキュリティホールを発見された場合は、当該セキュリティホールの\r
56 // 情報を不特定多数に開示される前に、必ず、ソフトイーサ株式会社\r
57 // および脆弱性情報の届出を受け付ける公的機関まで通報いただき、\r
58 // 公益保護にご協力いただきますようお願い申し上げます。\r
59 // \r
60 // ソフトイーサ株式会社は、当該セキュリティホールについて迅速に対処を\r
61 // 行い、UT-VPN および UT-VPN に関連するソフトウェアのユーザー・顧客\r
62 // を保護するための努力を行います。\r
63 // \r
64 // ソフトイーサへの届出先: http://www.softether.co.jp/jp/contact/\r
65 // 日本国内の脆弱性情報届出受付公的機関:\r
66 //         独立行政法人 情報処理推進機構\r
67 //         http://www.ipa.go.jp/security/vuln/report/\r
68 // \r
69 // 上記各事項について不明な点は、ソフトイーサ株式会社までご連絡ください。\r
70 // 連絡先: http://www.softether.co.jp/jp/contact/\r
71 \r
72 // -----------------------------------------------\r
73 // [ChangeLog]\r
74 // 2010.05.20\r
75 //  新規リリース by SoftEther\r
76 // -----------------------------------------------\r
77 \r
78 // Network.c\r
79 // ネットワーク通信モジュール\r
80 \r
81 #define ENCRYPT_C\r
82 #define NETWORK_C\r
83 \r
84 #define __WINCRYPT_H__\r
85 \r
86 #ifdef  WIN32\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
96 #endif  // WIN32\r
97 \r
98 #include <stdio.h>\r
99 #include <stdlib.h>\r
100 #include <string.h>\r
101 #include <wchar.h>\r
102 #include <stdarg.h>\r
103 #include <time.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
116 \r
117 #ifdef  OS_WIN32\r
118 NETWORK_WIN32_FUNCTIONS *w32net;\r
119 struct ROUTE_CHANGE_DATA\r
120 {\r
121         OVERLAPPED Overlapped;\r
122         HANDLE Handle;\r
123         UINT NumCalled;\r
124 };\r
125 #endif  // OS_WIN32\r
126 \r
127 // SSL でブロッキングするかどうか\r
128 #if     defined(UNIX_BSD)\r
129 #define FIX_SSL_BLOCKING\r
130 #endif\r
131 \r
132 // IPV6_V6ONLY 定数\r
133 #ifdef  UNIX_LINUX\r
134 #ifndef IPV6_V6ONLY\r
135 #define IPV6_V6ONLY     26\r
136 #endif  // IPV6_V6ONLY\r
137 #endif  // UNIX_LINUX\r
138 \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
144 \r
145 // SSL_CTX\r
146 static SSL_CTX *ssl_ctx = NULL;\r
147 \r
148 // DNS キャッシュリスト\r
149 static LIST *DnsCache;\r
150 \r
151 // ロック関係\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
168 \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
171 \r
172 // ルーティングテーブル変更検出を初期化\r
173 ROUTE_CHANGE *NewRouteChange()\r
174 {\r
175 #ifdef  OS_WIN32\r
176         return Win32NewRouteChange();\r
177 #else   // OS_WIN32\r
178         return NULL;\r
179 #endif  // OS_WIN32\r
180 }\r
181 \r
182 // ルーティングテーブル変更検出を解放\r
183 void FreeRouteChange(ROUTE_CHANGE *r)\r
184 {\r
185 #ifdef  OS_WIN32\r
186         Win32FreeRouteChange(r);\r
187 #endif  // OS_WIN32\r
188 }\r
189 \r
190 // ルーティングテーブルが変更されたかどうか取得\r
191 bool IsRouteChanged(ROUTE_CHANGE *r)\r
192 {\r
193 #ifdef  OS_WIN32\r
194         return Win32IsRouteChanged(r);\r
195 #else   // OS_WIN32\r
196         return false;\r
197 #endif  // OS_WIN32\r
198 }\r
199 \r
200 // ルーティングテーブル変更検出機能 (Win32)\r
201 #ifdef  OS_WIN32\r
202 ROUTE_CHANGE *Win32NewRouteChange()\r
203 {\r
204         ROUTE_CHANGE *r;\r
205         bool ret;\r
206 \r
207         if (MsIsNt() == false)\r
208         {\r
209                 return NULL;\r
210         }\r
211 \r
212         if (w32net->CancelIPChangeNotify == NULL ||\r
213                 w32net->NotifyRouteChange == NULL)\r
214         {\r
215                 return NULL;\r
216         }\r
217 \r
218         r = ZeroMalloc(sizeof(ROUTE_CHANGE));\r
219 \r
220         r->Data = ZeroMalloc(sizeof(ROUTE_CHANGE_DATA));\r
221 \r
222         r->Data->Overlapped.hEvent = CreateEventA(NULL, false, true, NULL);\r
223 \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
226         {\r
227                 Free(r->Data);\r
228                 Free(r);\r
229 \r
230                 return NULL;\r
231         }\r
232 \r
233         return r;\r
234 }\r
235 \r
236 void Win32FreeRouteChange(ROUTE_CHANGE *r)\r
237 {\r
238         // 引数チェック\r
239         if (r == NULL)\r
240         {\r
241                 return;\r
242         }\r
243 \r
244         w32net->CancelIPChangeNotify(&r->Data->Overlapped);\r
245         CloseHandle(r->Data->Overlapped.hEvent);\r
246 \r
247         Free(r->Data);\r
248         Free(r);\r
249 }\r
250 \r
251 bool Win32IsRouteChanged(ROUTE_CHANGE *r)\r
252 {\r
253         // 引数チェック\r
254         if (r == NULL)\r
255         {\r
256                 return false;\r
257         }\r
258 \r
259         if ((r->Data->NumCalled++) == 0)\r
260         {\r
261                 return true;\r
262         }\r
263 \r
264         if (WaitForSingleObject(r->Data->Overlapped.hEvent, 0) == WAIT_OBJECT_0)\r
265         {\r
266                 w32net->NotifyRouteChange(&r->Data->Handle, &r->Data->Overlapped);\r
267                 return true;\r
268         }\r
269 \r
270         return false;\r
271 }\r
272 \r
273 #endif  // OS_WIN32\r
274 \r
275 \r
276 // TCP コネクションのプロセス ID の取得が成功するかどうかを取得\r
277 bool CanGetTcpProcessId()\r
278 {\r
279         UINT i;\r
280         bool ret = false;\r
281         LIST *o = GetTcpTableList();\r
282 \r
283         if (o == NULL)\r
284         {\r
285                 return false;\r
286         }\r
287 \r
288         for (i = 0;i < LIST_NUM(o);i++)\r
289         {\r
290                 TCPTABLE *t = LIST_DATA(o, i);\r
291 \r
292                 if (t->ProcessId != 0)\r
293                 {\r
294                         ret = true;\r
295                         break;\r
296                 }\r
297         }\r
298 \r
299         FreeTcpTableList(o);\r
300 \r
301         return ret;\r
302 }\r
303 \r
304 \r
305 \r
306 \r
307 #define USE_OLD_GETIP\r
308 \r
309 // Linux における arp_filter を設定する\r
310 void SetLinuxArpFilter()\r
311 {\r
312         char *filename = "/proc/sys/net/ipv4/conf/all/arp_filter";\r
313         char *data = "1\n";\r
314         IO *o;\r
315 \r
316         o = FileCreate(filename);\r
317         if (o == NULL)\r
318         {\r
319                 return;\r
320         }\r
321 \r
322         FileWrite(o, data, StrLen(data));\r
323         FileFlush(o);\r
324 \r
325         FileClose(o);\r
326 }\r
327 \r
328 // 指定された文字列が IPv6 マスクかどうか判定する\r
329 bool IsIpMask6(char *str)\r
330 {\r
331         IP mask;\r
332         // 引数チェック\r
333         if (str == NULL)\r
334         {\r
335                 return false;\r
336         }\r
337 \r
338         return StrToMask6(&mask, str);\r
339 }\r
340 \r
341 // 指定された文字列が IPv6 アドレスかどうか判定する\r
342 bool IsStrIPv6Address(char *str)\r
343 {\r
344         IP ip;\r
345         // 引数チェック\r
346         if (str == NULL)\r
347         {\r
348                 return false;\r
349         }\r
350 \r
351         if (StrToIP6(&ip, str) == false)\r
352         {\r
353                 return false;\r
354         }\r
355 \r
356         return true;\r
357 }\r
358 \r
359 // サブネットマスクを整数に変換する\r
360 UINT SubnetMaskToInt6(IP *a)\r
361 {\r
362         UINT i;\r
363         // 引数チェック\r
364         if (IsIP6(a) == false)\r
365         {\r
366                 return 0;\r
367         }\r
368 \r
369         for (i = 0;i <= 128;i++)\r
370         {\r
371                 IP tmp;\r
372 \r
373                 IntToSubnetMask6(&tmp, i);\r
374 \r
375                 if (CmpIpAddr(a, &tmp) == 0)\r
376                 {\r
377                         return i;\r
378                 }\r
379         }\r
380 \r
381         return 0;\r
382 }\r
383 UINT SubnetMaskToInt4(IP *a)\r
384 {\r
385         UINT i;\r
386         // 引数チェック\r
387         if (IsIP4(a) == false)\r
388         {\r
389                 return 0;\r
390         }\r
391 \r
392         for (i = 0;i <= 32;i++)\r
393         {\r
394                 IP tmp;\r
395 \r
396                 IntToSubnetMask4(&tmp, i);\r
397 \r
398                 if (CmpIpAddr(a, &tmp) == 0)\r
399                 {\r
400                         return i;\r
401                 }\r
402         }\r
403 \r
404         return 0;\r
405 }\r
406 UINT SubnetMaskToInt(IP *a)\r
407 {\r
408         if (IsIP6(a))\r
409         {\r
410                 return SubnetMaskToInt6(a);\r
411         }\r
412         else\r
413         {\r
414                 return SubnetMaskToInt4(a);\r
415         }\r
416 }\r
417 \r
418 // 指定した IP アドレスがサブネットマスクかどうか調べる\r
419 bool IsSubnetMask6(IP *a)\r
420 {\r
421         UINT i;\r
422         // 引数チェック\r
423         if (IsIP6(a) == false)\r
424         {\r
425                 return false;\r
426         }\r
427 \r
428         for (i = 0;i <= 128;i++)\r
429         {\r
430                 IP tmp;\r
431 \r
432                 IntToSubnetMask6(&tmp, i);\r
433 \r
434                 if (CmpIpAddr(a, &tmp) == 0)\r
435                 {\r
436                         return true;\r
437                 }\r
438         }\r
439 \r
440         return false;\r
441 }\r
442 \r
443 // MAC アドレスからグローバルアドレスを生成する\r
444 void GenerateEui64GlobalAddress(IP *ip, IP *prefix, IP *subnet, UCHAR *mac)\r
445 {\r
446         UCHAR tmp[8];\r
447         IP a;\r
448         IP subnet_not;\r
449         IP or1, or2;\r
450         // 引数チェック\r
451         if (ip == NULL || prefix == NULL || subnet == NULL || mac == NULL)\r
452         {\r
453                 return;\r
454         }\r
455 \r
456         GenerateEui64Address6(tmp, mac);\r
457 \r
458         ZeroIP6(&a);\r
459 \r
460         Copy(&a.ipv6_addr[8], tmp, 8);\r
461 \r
462         IPNot6(&subnet_not, subnet);\r
463         IPAnd6(&or1, &a, &subnet_not);\r
464         IPAnd6(&or2, prefix, subnet);\r
465 \r
466         IPOr6(ip, &or1, &or2);\r
467 }\r
468 \r
469 // MAC アドレスからローカルアドレスを生成する\r
470 void GenerateEui64LocalAddress(IP *a, UCHAR *mac)\r
471 {\r
472         UCHAR tmp[8];\r
473         // 引数チェック\r
474         if (a == NULL || mac == NULL)\r
475         {\r
476                 return;\r
477         }\r
478 \r
479         GenerateEui64Address6(tmp, mac);\r
480 \r
481         ZeroIP6(a);\r
482         a->ipv6_addr[0] = 0xfe;\r
483         a->ipv6_addr[1] = 0x80;\r
484 \r
485         Copy(&a->ipv6_addr[8], tmp, 8);\r
486 }\r
487 \r
488 // MAC アドレスから EUI-64 アドレスを生成する\r
489 void GenerateEui64Address6(UCHAR *dst, UCHAR *mac)\r
490 {\r
491         // 引数チェック\r
492         if (dst == NULL || mac == NULL)\r
493         {\r
494                 return;\r
495         }\r
496 \r
497         Copy(dst, mac, 3);\r
498         Copy(dst + 5, mac, 3);\r
499 \r
500         dst[3] = 0xff;\r
501         dst[4] = 0xfe;\r
502         dst[0] = ((~(dst[0] & 0x02)) & 0x02) | (dst[0] & 0xfd);\r
503 }\r
504 \r
505 // 同一のネットワークかどうか調べる\r
506 bool IsInSameNetwork6(IP *a1, IP *a2, IP *subnet)\r
507 {\r
508         IP prefix1, prefix2;\r
509         // 引数チェック\r
510         if (IsIP6(a1) == false || IsIP6(a2) == false || IsIP6(subnet) == false)\r
511         {\r
512                 return false;\r
513         }\r
514 \r
515         if (a1->ipv6_scope_id != a2->ipv6_scope_id)\r
516         {\r
517                 return false;\r
518         }\r
519 \r
520         GetPrefixAddress6(&prefix1, a1, subnet);\r
521         GetPrefixAddress6(&prefix2, a2, subnet);\r
522 \r
523         if (CmpIpAddr(&prefix1, &prefix2) == 0)\r
524         {\r
525                 return true;\r
526         }\r
527 \r
528         return false;\r
529 }\r
530 \r
531 // ネットワークプレフィックスアドレスかどうかチェックする\r
532 bool IsNetworkAddress6(IP *ip, IP *subnet)\r
533 {\r
534         return IsNetworkPrefixAddress6(ip, subnet);\r
535 }\r
536 bool IsNetworkPrefixAddress6(IP *ip, IP *subnet)\r
537 {\r
538         IP host;\r
539         // 引数チェック\r
540         if (ip == NULL || subnet == NULL)\r
541         {\r
542                 return false;\r
543         }\r
544 \r
545         if (IsIP6(ip) == false || IsIP6(subnet) == false)\r
546         {\r
547                 return false;\r
548         }\r
549 \r
550         GetHostAddress6(&host, ip, subnet);\r
551 \r
552         if (IsZeroIp(&host))\r
553         {\r
554                 return true;\r
555         }\r
556 \r
557         return false;\r
558 }\r
559 \r
560 // ユニキャストアドレスが有効かどうかチェックする\r
561 bool CheckUnicastAddress(IP *ip)\r
562 {\r
563         // 引数チェック\r
564         if (ip == NULL)\r
565         {\r
566                 return false;\r
567         }\r
568 \r
569         if ((GetIPAddrType6(ip) & IPV6_ADDR_UNICAST) == 0)\r
570         {\r
571                 return false;\r
572         }\r
573 \r
574         return true;\r
575 }\r
576 \r
577 // ホストアドレスの取得\r
578 void GetHostAddress6(IP *dst, IP *ip, IP *subnet)\r
579 {\r
580         IP not;\r
581         // 引数チェック\r
582         if (dst == NULL || ip == NULL || subnet == NULL)\r
583         {\r
584                 return;\r
585         }\r
586 \r
587         IPNot6(&not, subnet);\r
588 \r
589         IPAnd6(dst, ip, &not);\r
590 \r
591         dst->ipv6_scope_id = ip->ipv6_scope_id;\r
592 }\r
593 \r
594 // プレフィックスアドレスの取得\r
595 void GetPrefixAddress6(IP *dst, IP *ip, IP *subnet)\r
596 {\r
597         // 引数チェック\r
598         if (dst == NULL || ip == NULL || subnet == NULL)\r
599         {\r
600                 return;\r
601         }\r
602 \r
603         IPAnd6(dst, ip, subnet);\r
604 \r
605         dst->ipv6_scope_id = ip->ipv6_scope_id;\r
606 }\r
607 \r
608 // 要請ノードマルチキャストアドレスを取得\r
609 void GetSoliciationMulticastAddr6(IP *dst, IP *src)\r
610 {\r
611         IP prefix;\r
612         IP mask104;\r
613         IP or1, or2;\r
614 \r
615         // 引数チェック\r
616         if (dst == NULL || src == NULL)\r
617         {\r
618                 return;\r
619         }\r
620 \r
621         ZeroIP6(&prefix);\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
626 \r
627         IntToSubnetMask6(&mask104, 104);\r
628 \r
629         IPAnd6(&or1, &prefix, &mask104);\r
630         IPAnd6(&or2, src, &mask104);\r
631 \r
632         IPOr6(dst, &or1, &or2);\r
633 \r
634         dst->ipv6_scope_id = src->ipv6_scope_id;\r
635 }\r
636 \r
637 // マルチキャストアドレスに対応した MAC アドレスの生成\r
638 void GenerateMulticastMacAddress6(UCHAR *mac, IP *ip)\r
639 {\r
640         // 引数チェック\r
641         if (mac == NULL)\r
642         {\r
643                 return;\r
644         }\r
645 \r
646         mac[0] = 0x33;\r
647         mac[1] = 0x33;\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
652 }\r
653 \r
654 // IPv6 アドレスのタイプの取得\r
655 UINT GetIPv6AddrType(IPV6_ADDR *addr)\r
656 {\r
657         IP ip;\r
658         // 引数チェック\r
659         if (addr == NULL)\r
660         {\r
661                 return 0;\r
662         }\r
663 \r
664         IPv6AddrToIP(&ip, addr);\r
665 \r
666         return GetIPAddrType6(&ip);\r
667 }\r
668 UINT GetIPAddrType6(IP *ip)\r
669 {\r
670         UINT ret = 0;\r
671         // 引数チェック\r
672         if (IsIP6(ip) == false)\r
673         {\r
674                 return 0;\r
675         }\r
676 \r
677         if (ip->ipv6_addr[0] == 0xff)\r
678         {\r
679                 IP all_node, all_router;\r
680 \r
681                 GetAllNodeMulticaseAddress6(&all_node);\r
682 \r
683                 GetAllRouterMulticastAddress6(&all_router);\r
684 \r
685                 ret |= IPV6_ADDR_MULTICAST;\r
686 \r
687                 if (Cmp(ip->ipv6_addr, all_node.ipv6_addr, 16) == 0)\r
688                 {\r
689                         ret |= IPV6_ADDR_ALL_NODE_MULTICAST;\r
690                 }\r
691                 else if (Cmp(ip->ipv6_addr, all_router.ipv6_addr, 16) == 0)\r
692                 {\r
693                         ret |= IPV6_ADDR_ALL_ROUTER_MULTICAST;\r
694                 }\r
695                 else\r
696                 {\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
701                         {\r
702                                 ret |= IPV6_ADDR_SOLICIATION_MULTICAST;\r
703                         }\r
704                 }\r
705         }\r
706         else\r
707         {\r
708                 ret |= IPV6_ADDR_UNICAST;\r
709 \r
710                 if (ip->ipv6_addr[0] == 0xfe && (ip->ipv6_addr[1] & 0xc0) == 0x80)\r
711                 {\r
712                         ret |= IPV6_ADDR_LOCAL_UNICAST;\r
713                 }\r
714                 else\r
715                 {\r
716                         ret |= IPV6_ADDR_GLOBAL_UNICAST;\r
717 \r
718                         if (IsZero(&ip->ipv6_addr, 16))\r
719                         {\r
720                                 ret |= IPV6_ADDR_ZERO;\r
721                         }\r
722                         else\r
723                         {\r
724                                 IP loopback;\r
725 \r
726                                 GetLoopbackAddress6(&loopback);\r
727 \r
728                                 if (Cmp(ip->ipv6_addr, loopback.ipv6_addr, 16) == 0)\r
729                                 {\r
730                                         ret |= IPV6_ADDR_LOOPBACK;\r
731                                 }\r
732                         }\r
733                 }\r
734         }\r
735 \r
736         return ret;\r
737 }\r
738 \r
739 // すべてのビットが立っているアドレス\r
740 void GetAllFilledAddress6(IP *ip)\r
741 {\r
742         UINT i;\r
743         // 引数チェック\r
744         if (ip == NULL)\r
745         {\r
746                 return;\r
747         }\r
748 \r
749         ZeroIP6(ip);\r
750 \r
751         for (i = 0;i < 15;i++)\r
752         {\r
753                 ip->ipv6_addr[i] = 0xff;\r
754         }\r
755 }\r
756 \r
757 // ループバックアドレス\r
758 void GetLoopbackAddress6(IP *ip)\r
759 {\r
760         // 引数チェック\r
761         if (ip == NULL)\r
762         {\r
763                 return;\r
764         }\r
765 \r
766         ZeroIP6(ip);\r
767 \r
768         ip->ipv6_addr[15] = 0x01;\r
769 }\r
770 \r
771 // 全ノードマルチキャストアドレス\r
772 void GetAllNodeMulticaseAddress6(IP *ip)\r
773 {\r
774         // 引数チェック\r
775         if (ip == NULL)\r
776         {\r
777                 return;\r
778         }\r
779 \r
780         ZeroIP6(ip);\r
781 \r
782         ip->ipv6_addr[0] = 0xff;\r
783         ip->ipv6_addr[1] = 0x02;\r
784         ip->ipv6_addr[15] = 0x01;\r
785 }\r
786 \r
787 // 全ルータマルチキャストアドレス\r
788 void GetAllRouterMulticastAddress6(IP *ip)\r
789 {\r
790         // 引数チェック\r
791         if (ip == NULL)\r
792         {\r
793                 return;\r
794         }\r
795 \r
796         ZeroIP6(ip);\r
797 \r
798         ip->ipv6_addr[0] = 0xff;\r
799         ip->ipv6_addr[1] = 0x02;\r
800         ip->ipv6_addr[15] = 0x02;\r
801 }\r
802 \r
803 // IPv6 アドレスの論理演算\r
804 void IPAnd6(IP *dst, IP *a, IP *b)\r
805 {\r
806         UINT i;\r
807         // 引数チェック\r
808         if (dst == NULL || IsIP6(a) == false || IsIP6(b) == false)\r
809         {\r
810                 return;\r
811         }\r
812 \r
813         ZeroIP6(dst);\r
814         for (i = 0;i < 16;i++)\r
815         {\r
816                 dst->ipv6_addr[i] = a->ipv6_addr[i] & b->ipv6_addr[i];\r
817         }\r
818 }\r
819 void IPOr6(IP *dst, IP *a, IP *b)\r
820 {\r
821         UINT i;\r
822         // 引数チェック\r
823         if (dst == NULL || IsIP6(a) == false || IsIP6(b) == false)\r
824         {\r
825                 return;\r
826         }\r
827 \r
828         ZeroIP6(dst);\r
829         for (i = 0;i < 16;i++)\r
830         {\r
831                 dst->ipv6_addr[i] = a->ipv6_addr[i] | b->ipv6_addr[i];\r
832         }\r
833 }\r
834 void IPNot6(IP *dst, IP *a)\r
835 {\r
836         UINT i;\r
837         // 引数チェック\r
838         if (dst == NULL || IsIP6(a) == false)\r
839         {\r
840                 return;\r
841         }\r
842 \r
843         ZeroIP6(dst);\r
844         for (i = 0;i < 16;i++)\r
845         {\r
846                 dst->ipv6_addr[i] = ~(a->ipv6_addr[i]);\r
847         }\r
848 }\r
849 \r
850 // サブネットマスクの作成\r
851 void IntToSubnetMask6(IP *ip, UINT i)\r
852 {\r
853         UINT j = i / 8;\r
854         UINT k = i % 8;\r
855         UINT z;\r
856         IP a;\r
857 \r
858         ZeroIP6(&a);\r
859 \r
860         for (z = 0;z < 16;z++)\r
861         {\r
862                 if (z < j)\r
863                 {\r
864                         a.ipv6_addr[z] = 0xff;\r
865                 }\r
866                 else if (z == j)\r
867                 {\r
868                         a.ipv6_addr[z] = ~(0xff >> k);\r
869                 }\r
870         }\r
871 \r
872         Copy(ip, &a, sizeof(IP));\r
873 }\r
874 \r
875 // IP アドレスを文字列に変換\r
876 void IP6AddrToStr(char *str, UINT size, IPV6_ADDR *addr)\r
877 {\r
878         // 引数チェック\r
879         if (str == NULL || addr == NULL)\r
880         {\r
881                 return;\r
882         }\r
883 \r
884         IPToStr6Array(str, size, addr->Value);\r
885 }\r
886 void IPToStr6Array(char *str, UINT size, UCHAR *bytes)\r
887 {\r
888         IP ip;\r
889         // 引数チェック\r
890         if (str == NULL || bytes == NULL)\r
891         {\r
892                 return;\r
893         }\r
894 \r
895         SetIP6(&ip, bytes);\r
896 \r
897         IPToStr6(str, size, &ip);\r
898 }\r
899 void IPToStr6(char *str, UINT size, IP *ip)\r
900 {\r
901         char tmp[MAX_SIZE];\r
902 \r
903         IPToStr6Inner(tmp, ip);\r
904 \r
905         StrCpy(str, size, tmp);\r
906 }\r
907 void IPToStr6Inner(char *str, IP *ip)\r
908 {\r
909         UINT i;\r
910         USHORT values[8];\r
911         UINT zero_started_index;\r
912         UINT max_zero_len;\r
913         UINT max_zero_start;\r
914         IP a;\r
915         // 引数チェック\r
916         if (str == NULL || ip == NULL)\r
917         {\r
918                 return;\r
919         }\r
920 \r
921         Copy(&a, ip, sizeof(IP));\r
922 \r
923         for (i = 0;i < 8;i++)\r
924         {\r
925                 Copy(&values[i], &a.ipv6_addr[i * 2], sizeof(USHORT));\r
926                 values[i] = Endian16(values[i]);\r
927         }\r
928 \r
929         // 省略できる場所があるかどうか検索\r
930         zero_started_index = INFINITE;\r
931         max_zero_len = 0;\r
932         max_zero_start = INFINITE;\r
933         for (i = 0;i < 9;i++)\r
934         {\r
935                 USHORT v = (i != 8 ? values[i] : 1);\r
936 \r
937                 if (values[i] == 0)\r
938                 {\r
939                         if (zero_started_index == INFINITE)\r
940                         {\r
941                                 zero_started_index = i;\r
942                         }\r
943                 }\r
944                 else\r
945                 {\r
946                         UINT zero_len;\r
947 \r
948                         if (zero_started_index != INFINITE)\r
949                         {\r
950                                 zero_len = i - zero_started_index;\r
951                                 if (zero_len >= 2)\r
952                                 {\r
953                                         if (max_zero_len < zero_len)\r
954                                         {\r
955                                                 max_zero_start = zero_started_index;\r
956                                                 max_zero_len = zero_len;\r
957                                         }\r
958                                 }\r
959 \r
960                                 zero_started_index = INFINITE;\r
961                         }\r
962                 }\r
963         }\r
964 \r
965         // 文字列を形成\r
966         StrCpy(str, 0, "");\r
967         for (i = 0;i < 8;i++)\r
968         {\r
969                 char tmp[16];\r
970 \r
971                 ToHex(tmp, values[i]);\r
972                 StrLower(tmp);\r
973 \r
974                 if (i == max_zero_start)\r
975                 {\r
976                         if (i == 0)\r
977                         {\r
978                                 StrCat(str, 0, "::");\r
979                         }\r
980                         else\r
981                         {\r
982                                 StrCat(str, 0, ":");\r
983                         }\r
984                         i += max_zero_len - 1;\r
985                 }\r
986                 else\r
987                 {\r
988                         StrCat(str, 0, tmp);\r
989                         if (i != 7)\r
990                         {\r
991                                 StrCat(str, 0, ":");\r
992                         }\r
993                 }\r
994         }\r
995 \r
996         // スコープ ID\r
997         if (ip->ipv6_scope_id != 0)\r
998         {\r
999                 char tmp[64];\r
1000 \r
1001                 StrCat(str, 0, "%");\r
1002                 ToStr(tmp, ip->ipv6_scope_id);\r
1003 \r
1004                 StrCat(str, 0, tmp);\r
1005         }\r
1006 }\r
1007 \r
1008 // 文字列を IP アドレスに変換\r
1009 bool StrToIP6(IP *ip, char *str)\r
1010 {\r
1011         TOKEN_LIST *t;\r
1012         char tmp[MAX_PATH];\r
1013         IP a;\r
1014         UINT i;\r
1015         UINT scope_id = 0;\r
1016         // 引数チェック\r
1017         if (str == NULL || ip == NULL)\r
1018         {\r
1019                 return false;\r
1020         }\r
1021 \r
1022         ZeroIP6(&a);\r
1023 \r
1024         StrCpy(tmp, sizeof(tmp), str);\r
1025         Trim(tmp);\r
1026 \r
1027         if (StartWith(tmp, "[") && EndWith(tmp, "]"))\r
1028         {\r
1029                 // かぎかっこで囲まれている場合はそれを除去\r
1030                 StrCpy(tmp, sizeof(tmp), &tmp[1]);\r
1031 \r
1032                 if (StrLen(tmp) >= 1)\r
1033                 {\r
1034                         tmp[StrLen(tmp) - 1] = 0;\r
1035                 }\r
1036         }\r
1037 \r
1038         // スコープ ID がある場合はそれを解析して除去\r
1039         i = SearchStrEx(tmp, "%", 0, false);\r
1040         if (i != INFINITE)\r
1041         {\r
1042                 char ss[MAX_PATH];\r
1043 \r
1044                 StrCpy(ss, sizeof(ss), &tmp[i + 1]);\r
1045 \r
1046                 tmp[i] = 0;\r
1047 \r
1048                 Trim(tmp);\r
1049 \r
1050                 Trim(ss);\r
1051 \r
1052                 scope_id = ToInt(ss);\r
1053         }\r
1054 \r
1055         // トークン分割\r
1056         t = ParseTokenWithNullStr(tmp, ":");\r
1057         if (t->NumTokens >= 3 && t->NumTokens <= 8)\r
1058         {\r
1059                 UINT i, n;\r
1060                 bool b = true;\r
1061                 UINT k = 0;\r
1062 \r
1063                 n = 0;\r
1064 \r
1065                 for (i = 0;i < t->NumTokens;i++)\r
1066                 {\r
1067                         char *str = t->Token[i];\r
1068 \r
1069                         if (i != 0 && i != (t->NumTokens - 1) && StrLen(str) == 0)\r
1070                         {\r
1071                                 n++;\r
1072                                 if (n == 1)\r
1073                                 {\r
1074                                         k += 2 * (8 - t->NumTokens + 1);\r
1075                                 }\r
1076                                 else\r
1077                                 {\r
1078                                         b = false;\r
1079                                         break;\r
1080                                 }\r
1081                         }\r
1082                         else\r
1083                         {\r
1084                                 UCHAR chars[2];\r
1085 \r
1086                                 if (CheckIPItemStr6(str) == false)\r
1087                                 {\r
1088                                         b = false;\r
1089                                         break;\r
1090                                 }\r
1091 \r
1092                                 IPItemStrToChars6(chars, str);\r
1093 \r
1094                                 a.ipv6_addr[k++] = chars[0];\r
1095                                 a.ipv6_addr[k++] = chars[1];\r
1096                         }\r
1097                 }\r
1098 \r
1099                 if (n != 0 && n != 1)\r
1100                 {\r
1101                         b = false;\r
1102                 }\r
1103                 else if (n == 0 && t->NumTokens != 8)\r
1104                 {\r
1105                         b = false;\r
1106                 }\r
1107 \r
1108                 if (b == false)\r
1109                 {\r
1110                         FreeToken(t);\r
1111                         return false;\r
1112                 }\r
1113         }\r
1114         else\r
1115         {\r
1116                 FreeToken(t);\r
1117                 return false;\r
1118         }\r
1119 \r
1120         FreeToken(t);\r
1121 \r
1122         Copy(ip, &a, sizeof(IP));\r
1123 \r
1124         ip->ipv6_scope_id = scope_id;\r
1125 \r
1126         return true;\r
1127 }\r
1128 bool StrToIP6Addr(IPV6_ADDR *ip, char *str)\r
1129 {\r
1130         IP ip2;\r
1131         // 引数チェック\r
1132         if (ip == NULL || str == NULL)\r
1133         {\r
1134                 Zero(ip, sizeof(IPV6_ADDR));\r
1135                 return false;\r
1136         }\r
1137 \r
1138         if (StrToIP6(&ip2, str) == false)\r
1139         {\r
1140                 return false;\r
1141         }\r
1142 \r
1143         if (IPToIPv6Addr(ip, &ip2) == false)\r
1144         {\r
1145                 return false;\r
1146         }\r
1147 \r
1148         return true;\r
1149 }\r
1150 \r
1151 // IP アドレスの文字から UCHAR 型に変換\r
1152 void IPItemStrToChars6(UCHAR *chars, char *str)\r
1153 {\r
1154         char tmp[5];\r
1155         BUF *b;\r
1156         UINT len;\r
1157         // 引数チェック\r
1158         if (chars == NULL)\r
1159         {\r
1160                 return;\r
1161         }\r
1162 \r
1163         Zero(tmp, sizeof(tmp));\r
1164 \r
1165         len = StrLen(str);\r
1166         switch (len)\r
1167         {\r
1168         case 0:\r
1169                 tmp[0] = tmp[1] = tmp[2] = tmp[3] = '0';\r
1170                 break;\r
1171 \r
1172         case 1:\r
1173                 tmp[0] = tmp[1] = tmp[2] = '0';\r
1174                 tmp[3] = str[0];\r
1175                 break;\r
1176 \r
1177         case 2:\r
1178                 tmp[0] = tmp[1] = '0';\r
1179                 tmp[2] = str[0];\r
1180                 tmp[3] = str[1];\r
1181                 break;\r
1182 \r
1183         case 3:\r
1184                 tmp[0] = '0';\r
1185                 tmp[1] = str[0];\r
1186                 tmp[2] = str[1];\r
1187                 tmp[3] = str[2];\r
1188                 break;\r
1189 \r
1190         case 4:\r
1191                 tmp[0] = str[0];\r
1192                 tmp[1] = str[1];\r
1193                 tmp[2] = str[2];\r
1194                 tmp[3] = str[3];\r
1195                 break;\r
1196         }\r
1197 \r
1198         b = StrToBin(tmp);\r
1199 \r
1200         chars[0] = ((UCHAR *)b->Buf)[0];\r
1201         chars[1] = ((UCHAR *)b->Buf)[1];\r
1202 \r
1203         FreeBuf(b);\r
1204 }\r
1205 \r
1206 // IP アドレスの要素文字列の中に不正な文字が含まれていないかどうかチェックする\r
1207 bool CheckIPItemStr6(char *str)\r
1208 {\r
1209         UINT i, len;\r
1210         // 引数チェック\r
1211         if (str == NULL)\r
1212         {\r
1213                 return false;\r
1214         }\r
1215 \r
1216         len = StrLen(str);\r
1217         if (len >= 5)\r
1218         {\r
1219                 // 長さ不正\r
1220                 return false;\r
1221         }\r
1222 \r
1223         for (i = 0;i < len;i++)\r
1224         {\r
1225                 char c = str[i];\r
1226 \r
1227                 if ((c >= 'a' && c <= 'f') ||\r
1228                         (c >= 'A' && c <= 'F') ||\r
1229                         (c >= '0' && c <= '9'))\r
1230                 {\r
1231                 }\r
1232                 else\r
1233                 {\r
1234                         return false;\r
1235                 }\r
1236         }\r
1237 \r
1238         return true;\r
1239 }\r
1240 \r
1241 // ゼロの IPv4 アドレスを作成する\r
1242 void ZeroIP4(IP *ip)\r
1243 {\r
1244         // 引数チェック\r
1245         if (ip == NULL)\r
1246         {\r
1247                 return;\r
1248         }\r
1249 \r
1250         Zero(ip, sizeof(IP));\r
1251 }\r
1252 \r
1253 // ゼロの IPv6 アドレスを作成する\r
1254 void ZeroIP6(IP *ip)\r
1255 {\r
1256         // 引数チェック\r
1257         if (ip == NULL)\r
1258         {\r
1259                 return;\r
1260         }\r
1261 \r
1262         SetIP6(ip, NULL);\r
1263 }\r
1264 \r
1265 // localhost の IP アドレスを取得する\r
1266 void GetLocalHostIP6(IP *ip)\r
1267 {\r
1268         ZeroIP6(ip);\r
1269 \r
1270         ip->ipv6_addr[15] = 1;\r
1271 }\r
1272 \r
1273 // IPV6_ADDR を IP に変換\r
1274 void IPv6AddrToIP(IP *ip, IPV6_ADDR *addr)\r
1275 {\r
1276         // 引数チェック\r
1277         if (ip == NULL || addr == NULL)\r
1278         {\r
1279                 return;\r
1280         }\r
1281 \r
1282         SetIP6(ip, addr->Value);\r
1283 }\r
1284 \r
1285 // IP を IPV6_ADDR に変換\r
1286 bool IPToIPv6Addr(IPV6_ADDR *addr, IP *ip)\r
1287 {\r
1288         UINT i;\r
1289         // 引数チェック\r
1290         if (addr == NULL || ip == NULL)\r
1291         {\r
1292                 Zero(addr, sizeof(IPV6_ADDR));\r
1293                 return false;\r
1294         }\r
1295 \r
1296         if (IsIP6(ip) == false)\r
1297         {\r
1298                 Zero(addr, sizeof(IPV6_ADDR));\r
1299                 return false;\r
1300         }\r
1301 \r
1302         for (i = 0;i < 16;i++)\r
1303         {\r
1304                 addr->Value[i] = ip->ipv6_addr[i];\r
1305         }\r
1306 \r
1307         return true;\r
1308 }\r
1309 \r
1310 // IPv6 アドレスをセットする\r
1311 void SetIP6(IP *ip, UCHAR *value)\r
1312 {\r
1313         // 引数チェック\r
1314         if (ip == NULL)\r
1315         {\r
1316                 return;\r
1317         }\r
1318 \r
1319         Zero(ip, sizeof(IP));\r
1320 \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
1325 \r
1326         if (value != NULL)\r
1327         {\r
1328                 UINT i;\r
1329 \r
1330                 for (i = 0;i < 16;i++)\r
1331                 {\r
1332                         ip->ipv6_addr[i] = value[i];\r
1333                 }\r
1334         }\r
1335 }\r
1336 \r
1337 // 指定されたアドレスが IPv6 アドレスかどうかチェックする\r
1338 bool IsIP6(IP *ip)\r
1339 {\r
1340         // 引数チェック\r
1341         if (ip == NULL)\r
1342         {\r
1343                 return false;\r
1344         }\r
1345 \r
1346         if (ip->addr[0] == 223 && ip->addr[1] == 255 && ip->addr[2] == 255 && ip->addr[3] == 254)\r
1347         {\r
1348                 return true;\r
1349         }\r
1350 \r
1351         return false;\r
1352 }\r
1353 bool IsIP4(IP *ip)\r
1354 {\r
1355         // 引数チェック\r
1356         if (ip == NULL)\r
1357         {\r
1358                 return false;\r
1359         }\r
1360 \r
1361         return (IsIP6(ip) ? false : true);\r
1362 }\r
1363 \r
1364 // IPv6 のサブネット長をチェック\r
1365 bool CheckSubnetLength6(UINT i)\r
1366 {\r
1367         if (i >= 1 && i <= 127)\r
1368         {\r
1369                 return true;\r
1370         }\r
1371 \r
1372         return false;\r
1373 }\r
1374 \r
1375 // ソケットから対応する TCP コネクションのプロセス ID を取得\r
1376 UINT GetTcpProcessIdFromSocket(SOCK *s)\r
1377 {\r
1378         LIST *o;\r
1379         TCPTABLE *t;\r
1380         UINT pid = 0;\r
1381         // 引数チェック\r
1382         if (s == NULL)\r
1383         {\r
1384                 return 0;\r
1385         }\r
1386 \r
1387         o = GetTcpTableList();\r
1388         if (o == NULL)\r
1389         {\r
1390                 return 0;\r
1391         }\r
1392 \r
1393         t = GetTcpTableFromEndPoint(o, &s->LocalIP, s->LocalPort,\r
1394                 &s->RemoteIP, s->RemotePort);\r
1395 \r
1396         if (t != NULL)\r
1397         {\r
1398                 pid = t->ProcessId;\r
1399         }\r
1400 \r
1401         FreeTcpTableList(o);\r
1402 \r
1403         return pid;\r
1404 }\r
1405 UINT GetTcpProcessIdFromSocketReverse(SOCK *s)\r
1406 {\r
1407         LIST *o;\r
1408         TCPTABLE *t;\r
1409         UINT pid = 0;\r
1410         // 引数チェック\r
1411         if (s == NULL)\r
1412         {\r
1413                 return 0;\r
1414         }\r
1415 \r
1416         o = GetTcpTableList();\r
1417         if (o == NULL)\r
1418         {\r
1419                 return 0;\r
1420         }\r
1421 \r
1422         t = GetTcpTableFromEndPoint(o, &s->RemoteIP, s->RemotePort,\r
1423                 &s->LocalIP, s->LocalPort);\r
1424 \r
1425         if (t != NULL)\r
1426         {\r
1427                 pid = t->ProcessId;\r
1428         }\r
1429 \r
1430         FreeTcpTableList(o);\r
1431 \r
1432         return pid;\r
1433 }\r
1434 \r
1435 // エンドポイントから TCP テーブルを検索\r
1436 TCPTABLE *GetTcpTableFromEndPoint(LIST *o, IP *local_ip, UINT local_port, IP *remote_ip, UINT remote_port)\r
1437 {\r
1438         IP local;\r
1439         UINT i;\r
1440         // 引数チェック\r
1441         if (o == NULL)\r
1442         {\r
1443                 return NULL;\r
1444         }\r
1445 \r
1446         SetIP(&local, 127, 0, 0, 1);\r
1447 \r
1448         if (local_ip == NULL)\r
1449         {\r
1450                 local_ip = &local;\r
1451         }\r
1452 \r
1453         if (remote_ip == NULL)\r
1454         {\r
1455                 remote_ip = &local;\r
1456         }\r
1457 \r
1458         for (i = 0;i < LIST_NUM(o);i++)\r
1459         {\r
1460                 TCPTABLE *t = LIST_DATA(o, i);\r
1461 \r
1462                 if (t->Status == TCP_STATE_SYN_SENT || t->Status == TCP_STATE_SYN_RCVD ||\r
1463                         t->Status == TCP_STATE_ESTAB)\r
1464                 {\r
1465                         if (CmpIpAddr(&t->LocalIP, local_ip) == 0)\r
1466                         {\r
1467                                 if (CmpIpAddr(&t->RemoteIP, remote_ip) == 0)\r
1468                                 {\r
1469                                         if (t->LocalPort == local_port)\r
1470                                         {\r
1471                                                 if (t->RemotePort == remote_port)\r
1472                                                 {\r
1473                                                         return t;\r
1474                                                 }\r
1475                                         }\r
1476                                 }\r
1477                         }\r
1478                 }\r
1479         }\r
1480 \r
1481         return NULL;\r
1482 }\r
1483 \r
1484 // TCP テーブルリストを取得 (Win32)\r
1485 #ifdef  OS_WIN32\r
1486 LIST *Win32GetTcpTableList()\r
1487 {\r
1488         LIST *o;\r
1489 \r
1490         // Windows XP SP2 以降用\r
1491         o = Win32GetTcpTableListByGetExtendedTcpTable();\r
1492         if (o != NULL)\r
1493         {\r
1494                 return o;\r
1495         }\r
1496 \r
1497         // Windows XP 以降用\r
1498         o = Win32GetTcpTableListByAllocateAndGetTcpExTableFromStack();\r
1499         if (o != NULL)\r
1500         {\r
1501                 return o;\r
1502         }\r
1503 \r
1504         // 古い Windows 用\r
1505         return Win32GetTcpTableListByGetTcpTable();\r
1506 }\r
1507 \r
1508 // TCP テーブルリストを取得: Windows XP SP2 以降用\r
1509 LIST *Win32GetTcpTableListByGetExtendedTcpTable()\r
1510 {\r
1511         UINT need_size;\r
1512         UINT i;\r
1513         MIB_TCPTABLE_OWNER_PID *table;\r
1514         bool ok = false;\r
1515         LIST *o;\r
1516         if (w32net->GetExtendedTcpTable == NULL)\r
1517         {\r
1518                 return NULL;\r
1519         }\r
1520 \r
1521         for (i = 0;i < 128;i++)\r
1522         {\r
1523                 UINT ret;\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
1528                 {\r
1529                         ok = true;\r
1530                         break;\r
1531                 }\r
1532                 else\r
1533                 {\r
1534                         Free(table);\r
1535                         if (ret != ERROR_INSUFFICIENT_BUFFER)\r
1536                         {\r
1537                                 return NULL;\r
1538                         }\r
1539                 }\r
1540 \r
1541                 table = MallocFast(need_size);\r
1542 \r
1543                 ret = w32net->GetExtendedTcpTable(table, &need_size, true, AF_INET, _TCP_TABLE_OWNER_PID_ALL, 0);\r
1544                 if (ret == NO_ERROR)\r
1545                 {\r
1546                         ok = true;\r
1547                         break;\r
1548                 }\r
1549                 else\r
1550                 {\r
1551                         Free(table);\r
1552 \r
1553                         if (ret != ERROR_INSUFFICIENT_BUFFER)\r
1554                         {\r
1555                                 return NULL;\r
1556                         }\r
1557                 }\r
1558         }\r
1559 \r
1560         if (ok == false)\r
1561         {\r
1562                 return NULL;\r
1563         }\r
1564 \r
1565         o = NewListEx(NULL, true);\r
1566 \r
1567         for (i = 0;i < table->dwNumEntries;i++)\r
1568         {\r
1569                 MIB_TCPROW_OWNER_PID *r = &table->table[i];\r
1570                 TCPTABLE *t = ZeroMallocFast(sizeof(TCPTABLE));\r
1571 \r
1572                 UINTToIP(&t->LocalIP, r->dwLocalAddr);\r
1573                 t->LocalPort = Endian16((USHORT)r->dwLocalPort);\r
1574 \r
1575                 if (r->dwState != TCP_STATE_LISTEN)\r
1576                 {\r
1577                         UINTToIP(&t->RemoteIP, r->dwRemoteAddr);\r
1578                         t->RemotePort = Endian16((USHORT)r->dwRemotePort);\r
1579                 }\r
1580 \r
1581                 t->Status = r->dwState;\r
1582                 t->ProcessId = r->dwOwningPid;\r
1583 \r
1584                 Add(o, t);\r
1585         }\r
1586 \r
1587         Free(table);\r
1588 \r
1589         return o;\r
1590 }\r
1591 \r
1592 // TCP テーブルリストを取得: Windows XP 以降用\r
1593 LIST *Win32GetTcpTableListByAllocateAndGetTcpExTableFromStack()\r
1594 {\r
1595         HANDLE heap;\r
1596         UINT i;\r
1597         MIB_TCPTABLE_OWNER_PID *table;\r
1598         bool ok = false;\r
1599         LIST *o;\r
1600         if (w32net->AllocateAndGetTcpExTableFromStack == NULL)\r
1601         {\r
1602                 return NULL;\r
1603         }\r
1604 \r
1605         heap = GetProcessHeap();\r
1606 \r
1607         if (w32net->AllocateAndGetTcpExTableFromStack(&table, true, heap, HEAP_GROWABLE, AF_INET) != ERROR_SUCCESS)\r
1608         {\r
1609                 return NULL;\r
1610         }\r
1611 \r
1612         o = NewListEx(NULL, true);\r
1613 \r
1614         for (i = 0;i < table->dwNumEntries;i++)\r
1615         {\r
1616                 MIB_TCPROW_OWNER_PID *r = &table->table[i];\r
1617                 TCPTABLE *t = ZeroMallocFast(sizeof(TCPTABLE));\r
1618 \r
1619                 UINTToIP(&t->LocalIP, r->dwLocalAddr);\r
1620                 t->LocalPort = Endian16((USHORT)r->dwLocalPort);\r
1621 \r
1622                 if (r->dwState != TCP_STATE_LISTEN)\r
1623                 {\r
1624                         UINTToIP(&t->RemoteIP, r->dwRemoteAddr);\r
1625                         t->RemotePort = Endian16((USHORT)r->dwRemotePort);\r
1626                 }\r
1627 \r
1628                 t->ProcessId = r->dwOwningPid;\r
1629                 t->Status = r->dwState;\r
1630 \r
1631                 Add(o, t);\r
1632         }\r
1633 \r
1634         HeapFree(heap, 0, table);\r
1635 \r
1636         return o;\r
1637 }\r
1638 \r
1639 // TCP テーブルリストを取得: 古い Windows 用\r
1640 LIST *Win32GetTcpTableListByGetTcpTable()\r
1641 {\r
1642         UINT need_size;\r
1643         UINT i;\r
1644         MIB_TCPTABLE *table;\r
1645         bool ok = false;\r
1646         LIST *o;\r
1647         if (w32net->GetTcpTable == NULL)\r
1648         {\r
1649                 return NULL;\r
1650         }\r
1651 \r
1652         for (i = 0;i < 128;i++)\r
1653         {\r
1654                 UINT ret;\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
1659                 {\r
1660                         ok = true;\r
1661                         break;\r
1662                 }\r
1663                 else\r
1664                 {\r
1665                         Free(table);\r
1666                         if (ret != ERROR_INSUFFICIENT_BUFFER)\r
1667                         {\r
1668                                 return NULL;\r
1669                         }\r
1670                 }\r
1671 \r
1672                 table = MallocFast(need_size);\r
1673 \r
1674                 ret = w32net->GetTcpTable(table, &need_size, true);\r
1675                 if (ret == NO_ERROR)\r
1676                 {\r
1677                         ok = true;\r
1678                         break;\r
1679                 }\r
1680                 else\r
1681                 {\r
1682                         Free(table);\r
1683 \r
1684                         if (ret != ERROR_INSUFFICIENT_BUFFER)\r
1685                         {\r
1686                                 return NULL;\r
1687                         }\r
1688                 }\r
1689         }\r
1690 \r
1691         if (ok == false)\r
1692         {\r
1693                 return NULL;\r
1694         }\r
1695 \r
1696         o = NewListEx(NULL, true);\r
1697 \r
1698         for (i = 0;i < table->dwNumEntries;i++)\r
1699         {\r
1700                 MIB_TCPROW *r = &table->table[i];\r
1701                 TCPTABLE *t = ZeroMallocFast(sizeof(TCPTABLE));\r
1702 \r
1703                 UINTToIP(&t->LocalIP, r->dwLocalAddr);\r
1704                 t->LocalPort = Endian16((USHORT)r->dwLocalPort);\r
1705 \r
1706                 if (r->dwState != TCP_STATE_LISTEN)\r
1707                 {\r
1708                         UINTToIP(&t->RemoteIP, r->dwRemoteAddr);\r
1709                         t->RemotePort = Endian16((USHORT)r->dwRemotePort);\r
1710                 }\r
1711 \r
1712                 t->Status = r->dwState;\r
1713 \r
1714                 Add(o, t);\r
1715         }\r
1716 \r
1717         Free(table);\r
1718 \r
1719         return o;\r
1720 }\r
1721 \r
1722 #endif  // OS_WIN32\r
1723 \r
1724 // TCP テーブルの表示\r
1725 void PrintTcpTableList(LIST *o)\r
1726 {\r
1727         UINT i;\r
1728         // 引数チェック\r
1729         if (o == NULL)\r
1730         {\r
1731                 Print("o == NULL\n\n");\r
1732                 return;\r
1733         }\r
1734 \r
1735         Print("--- TCPTABLE: %u Entries ---\n", LIST_NUM(o));\r
1736         for (i = 0;i < LIST_NUM(o);i++)\r
1737         {\r
1738                 char tmp1[MAX_PATH], tmp2[MAX_PATH];\r
1739                 TCPTABLE *t = LIST_DATA(o, i);\r
1740 \r
1741                 IPToStr(tmp1, sizeof(tmp1), &t->LocalIP);\r
1742                 IPToStr(tmp2, sizeof(tmp2), &t->RemoteIP);\r
1743 \r
1744                 Print("%s:%u <--> %s:%u  state=%u  pid=%u\n",\r
1745                         tmp1, t->LocalPort,\r
1746                         tmp2, t->RemotePort,\r
1747                         t->Status,\r
1748                         t->ProcessId);\r
1749         }\r
1750         Print("------\n\n");\r
1751 }\r
1752 \r
1753 // TCP テーブルの比較\r
1754 int CompareTcpTable(void *p1, void *p2)\r
1755 {\r
1756         TCPTABLE *t1, *t2;\r
1757         if (p1 == NULL || p2 == NULL)\r
1758         {\r
1759                 return 0;\r
1760         }\r
1761         t1 = *(TCPTABLE **)p1;\r
1762         t2 = *(TCPTABLE **)p2;\r
1763         if (t1 == NULL || t2 == NULL)\r
1764         {\r
1765                 return 0;\r
1766         }\r
1767 \r
1768         return Cmp(t1, t2, sizeof(TCPTABLE));\r
1769 }\r
1770 \r
1771 // TCP テーブルリストを取得\r
1772 LIST *GetTcpTableList()\r
1773 {\r
1774 #ifdef  OS_WIN32\r
1775         return Win32GetTcpTableList();\r
1776 #else   // OS_WIN32\r
1777         return NULL;\r
1778 #endif  // OS_WIN32\r
1779 }\r
1780 \r
1781 // TCP テーブルリストを解放\r
1782 void FreeTcpTableList(LIST *o)\r
1783 {\r
1784         UINT i;\r
1785         // 引数チェック\r
1786         if (o == NULL)\r
1787         {\r
1788                 return;\r
1789         }\r
1790 \r
1791         for (i = 0;i < LIST_NUM(o);i++)\r
1792         {\r
1793                 TCPTABLE *t = LIST_DATA(o, i);\r
1794 \r
1795                 Free(t);\r
1796         }\r
1797 \r
1798         ReleaseList(o);\r
1799 }\r
1800 \r
1801 // 指定された IP アドレスから接続中のクライアント数の取得\r
1802 UINT GetNumIpClient(IP *ip)\r
1803 {\r
1804         IP_CLIENT *c;\r
1805         UINT ret = 0;\r
1806         // 引数チェック\r
1807         if (ip == NULL)\r
1808         {\r
1809                 return 0;\r
1810         }\r
1811 \r
1812         LockList(ip_clients);\r
1813         {\r
1814                 c = SearchIpClient(ip);\r
1815 \r
1816                 if (c != NULL)\r
1817                 {\r
1818                         ret = c->NumConnections;\r
1819                 }\r
1820         }\r
1821         UnlockList(ip_clients);\r
1822 \r
1823         return ret;\r
1824 }\r
1825 \r
1826 // IP クライアントエントリに追加\r
1827 void AddIpClient(IP *ip)\r
1828 {\r
1829         IP_CLIENT *c;\r
1830         // 引数チェック\r
1831         if (ip == NULL)\r
1832         {\r
1833                 return;\r
1834         }\r
1835 \r
1836         LockList(ip_clients);\r
1837         {\r
1838                 c = SearchIpClient(ip);\r
1839 \r
1840                 if (c == NULL)\r
1841                 {\r
1842                         c = ZeroMallocFast(sizeof(IP_CLIENT));\r
1843                         Copy(&c->IpAddress, ip, sizeof(IP));\r
1844                         c->NumConnections = 0;\r
1845 \r
1846                         Add(ip_clients, c);\r
1847                 }\r
1848 \r
1849                 c->NumConnections++;\r
1850         }\r
1851         UnlockList(ip_clients);\r
1852 }\r
1853 \r
1854 // IP クライアントリストから削除\r
1855 void DelIpClient(IP *ip)\r
1856 {\r
1857         IP_CLIENT *c;\r
1858         // 引数チェック\r
1859         if (ip == NULL)\r
1860         {\r
1861                 return;\r
1862         }\r
1863 \r
1864         LockList(ip_clients);\r
1865         {\r
1866                 c = SearchIpClient(ip);\r
1867 \r
1868                 if (c != NULL)\r
1869                 {\r
1870                         c->NumConnections--;\r
1871 \r
1872                         if (c->NumConnections == 0)\r
1873                         {\r
1874                                 Delete(ip_clients, c);\r
1875                                 Free(c);\r
1876                         }\r
1877                 }\r
1878         }\r
1879         UnlockList(ip_clients);\r
1880 }\r
1881 \r
1882 // IP クライアントエントリの検索\r
1883 IP_CLIENT *SearchIpClient(IP *ip)\r
1884 {\r
1885         IP_CLIENT t;\r
1886         // 引数チェック\r
1887         if (ip == NULL)\r
1888         {\r
1889                 return NULL;\r
1890         }\r
1891 \r
1892         Zero(&t, sizeof(t));\r
1893         Copy(&t.IpAddress, ip, sizeof(IP));\r
1894 \r
1895         return Search(ip_clients, &t);\r
1896 }\r
1897 \r
1898 // クライアントリストの初期化\r
1899 void InitIpClientList()\r
1900 {\r
1901         ip_clients = NewList(CompareIpClientList);\r
1902 }\r
1903 \r
1904 // クライアントリストの解放\r
1905 void FreeIpClientList()\r
1906 {\r
1907         UINT i;\r
1908 \r
1909         for (i = 0;i < LIST_NUM(ip_clients);i++)\r
1910         {\r
1911                 IP_CLIENT *c = LIST_DATA(ip_clients, i);\r
1912 \r
1913                 Free(c);\r
1914         }\r
1915 \r
1916         ReleaseList(ip_clients);\r
1917         ip_clients = NULL;\r
1918 }\r
1919 \r
1920 // クライアントリストエントリの比較\r
1921 int CompareIpClientList(void *p1, void *p2)\r
1922 {\r
1923         IP_CLIENT *c1, *c2;\r
1924         if (p1 == NULL || p2 == NULL)\r
1925         {\r
1926                 return 0;\r
1927         }\r
1928         c1 = *(IP_CLIENT **)p1;\r
1929         c2 = *(IP_CLIENT **)p2;\r
1930         if (c1 == NULL || c2 == NULL)\r
1931         {\r
1932                 return 0;\r
1933         }\r
1934 \r
1935         return CmpIpAddr(&c1->IpAddress, &c2->IpAddress);\r
1936 }\r
1937 \r
1938 // MAC アドレスの正規化\r
1939 bool NormalizeMacAddress(char *dst, UINT size, char *src)\r
1940 {\r
1941         BUF *b;\r
1942         bool ret = false;\r
1943         // 引数チェック\r
1944         if (dst == NULL || src == NULL)\r
1945         {\r
1946                 return false;\r
1947         }\r
1948 \r
1949         b = StrToBin(src);\r
1950 \r
1951         if (b != NULL && b->Size == 6)\r
1952         {\r
1953                 ret = true;\r
1954 \r
1955                 BinToStr(dst, size, b->Buf, b->Size);\r
1956         }\r
1957 \r
1958         FreeBuf(b);\r
1959 \r
1960         return ret;\r
1961 }\r
1962 \r
1963 // IP アドレスが空かどうか識別する\r
1964 bool IsZeroIP(IP *ip)\r
1965 {\r
1966         return IsZeroIp(ip);\r
1967 }\r
1968 bool IsZeroIp(IP *ip)\r
1969 {\r
1970         // 引数チェック\r
1971         if (ip == NULL)\r
1972         {\r
1973                 return true;\r
1974         }\r
1975 \r
1976         if (IsIP6(ip) == false)\r
1977         {\r
1978                 return IsZero(ip->addr, sizeof(ip->addr));\r
1979         }\r
1980         else\r
1981         {\r
1982                 return IsZero(ip->ipv6_addr, sizeof(ip->ipv6_addr));\r
1983         }\r
1984 }\r
1985 bool IsZeroIP6Addr(IPV6_ADDR *addr)\r
1986 {\r
1987         // 引数チェック\r
1988         if (addr == NULL)\r
1989         {\r
1990                 return true;\r
1991         }\r
1992 \r
1993         return IsZero(addr, sizeof(IPV6_ADDR));\r
1994 }\r
1995 \r
1996 // 指定された IP アドレスがホストとして意味があるかどうかを調べる\r
1997 bool IsHostIPAddress4(IP *ip)\r
1998 {\r
1999         UINT a;\r
2000         // 引数チェック\r
2001         if (ip == NULL)\r
2002         {\r
2003                 return false;\r
2004         }\r
2005 \r
2006         a = IPToUINT(ip);\r
2007 \r
2008         if (a == 0 || a == 0xffffffff)\r
2009         {\r
2010                 return false;\r
2011         }\r
2012 \r
2013         return true;\r
2014 }\r
2015 bool IsHostIPAddress32(UINT ip)\r
2016 {\r
2017         IP p;\r
2018 \r
2019         UINTToIP(&p, ip);\r
2020 \r
2021         return IsHostIPAddress4(&p);\r
2022 }\r
2023 \r
2024 // 指定された IP アドレスとサブネットマスクが正しくネットワークを示すかどうか調べる\r
2025 bool IsNetworkAddress(IP *ip, IP *mask)\r
2026 {\r
2027         if (IsIP4(ip))\r
2028         {\r
2029                 return IsNetworkAddress4(ip, mask);\r
2030         }\r
2031         else\r
2032         {\r
2033                 return IsNetworkAddress6(ip, mask);\r
2034         }\r
2035 }\r
2036 bool IsNetworkAddress4(IP *ip, IP *mask)\r
2037 {\r
2038         UINT a, b;\r
2039         // 引数チェック\r
2040         if (ip == NULL || mask == NULL)\r
2041         {\r
2042                 return false;\r
2043         }\r
2044 \r
2045         if (IsIP4(ip) == false || IsIP4(mask) == false)\r
2046         {\r
2047                 return false;\r
2048         }\r
2049 \r
2050         if (IsSubnetMask4(mask) == false)\r
2051         {\r
2052                 return false;\r
2053         }\r
2054 \r
2055         a = IPToUINT(ip);\r
2056         b = IPToUINT(mask);\r
2057 \r
2058         if ((a & b) == a)\r
2059         {\r
2060                 return true;\r
2061         }\r
2062 \r
2063         return false;\r
2064 }\r
2065 bool IsNetworkAddress32(UINT ip, UINT mask)\r
2066 {\r
2067         IP a, b;\r
2068 \r
2069         UINTToIP(&a, ip);\r
2070         UINTToIP(&b, mask);\r
2071 \r
2072         return IsNetworkAddress4(&a, &b);\r
2073 }\r
2074 \r
2075 // 整数をサブネットマスクに変換する\r
2076 UINT IntToSubnetMask32(UINT i)\r
2077 {\r
2078         UINT ret = 0xFFFFFFFF;\r
2079 \r
2080         // 汚いコード\r
2081         switch (i)\r
2082         {\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
2116         }\r
2117 \r
2118         if (IsLittleEndian())\r
2119         {\r
2120                 ret = Swap32(ret);\r
2121         }\r
2122 \r
2123         return ret;\r
2124 }\r
2125 void IntToSubnetMask4(IP *ip, UINT i)\r
2126 {\r
2127         UINT m;\r
2128         // 引数チェック\r
2129         if (ip == NULL)\r
2130         {\r
2131                 return;\r
2132         }\r
2133 \r
2134         m = IntToSubnetMask32(i);\r
2135 \r
2136         UINTToIP(ip, m);\r
2137 }\r
2138 \r
2139 // 指定された IP アドレスがサブネットマスクかどうか調べる\r
2140 bool IsSubnetMask(IP *ip)\r
2141 {\r
2142         if (IsIP6(ip))\r
2143         {\r
2144                 return IsSubnetMask6(ip);\r
2145         }\r
2146         else\r
2147         {\r
2148                 return IsSubnetMask4(ip);\r
2149         }\r
2150 }\r
2151 bool IsSubnetMask4(IP *ip)\r
2152 {\r
2153         UINT i;\r
2154         // 引数チェック\r
2155         if (ip == NULL)\r
2156         {\r
2157                 return false;\r
2158         }\r
2159 \r
2160         if (IsIP6(ip))\r
2161         {\r
2162                 return false;\r
2163         }\r
2164 \r
2165         i = IPToUINT(ip);\r
2166 \r
2167         if (IsLittleEndian())\r
2168         {\r
2169                 i = Swap32(i);\r
2170         }\r
2171 \r
2172         // 汚いコード\r
2173         switch (i)\r
2174         {\r
2175         case 0x00000000:\r
2176         case 0x80000000:\r
2177         case 0xC0000000:\r
2178         case 0xE0000000:\r
2179         case 0xF0000000:\r
2180         case 0xF8000000:\r
2181         case 0xFC000000:\r
2182         case 0xFE000000:\r
2183         case 0xFF000000:\r
2184         case 0xFF800000:\r
2185         case 0xFFC00000:\r
2186         case 0xFFE00000:\r
2187         case 0xFFF00000:\r
2188         case 0xFFF80000:\r
2189         case 0xFFFC0000:\r
2190         case 0xFFFE0000:\r
2191         case 0xFFFF0000:\r
2192         case 0xFFFF8000:\r
2193         case 0xFFFFC000:\r
2194         case 0xFFFFE000:\r
2195         case 0xFFFFF000:\r
2196         case 0xFFFFF800:\r
2197         case 0xFFFFFC00:\r
2198         case 0xFFFFFE00:\r
2199         case 0xFFFFFF00:\r
2200         case 0xFFFFFF80:\r
2201         case 0xFFFFFFC0:\r
2202         case 0xFFFFFFE0:\r
2203         case 0xFFFFFFF0:\r
2204         case 0xFFFFFFF8:\r
2205         case 0xFFFFFFFC:\r
2206         case 0xFFFFFFFE:\r
2207         case 0xFFFFFFFF:\r
2208                 return true;\r
2209         }\r
2210 \r
2211         return false;\r
2212 }\r
2213 bool IsSubnetMask32(UINT ip)\r
2214 {\r
2215         IP p;\r
2216 \r
2217         UINTToIP(&p, ip);\r
2218 \r
2219         return IsSubnetMask4(&p);\r
2220 }\r
2221 \r
2222 // ネットワークリリースモード\r
2223 void SetNetworkReleaseMode()\r
2224 {\r
2225         NetworkReleaseMode = true;\r
2226 }\r
2227 \r
2228 #ifdef  OS_UNIX                 // UNIX 用コード\r
2229 \r
2230 // ソケットをノンブロッキングモードにしたり解除したりする\r
2231 void UnixSetSocketNonBlockingMode(int fd, bool nonblock)\r
2232 {\r
2233         UINT flag = 0;\r
2234         // 引数チェック\r
2235         if (fd == INVALID_SOCKET)\r
2236         {\r
2237                 return;\r
2238         }\r
2239 \r
2240         if (nonblock)\r
2241         {\r
2242                 flag = 1;\r
2243         }\r
2244 \r
2245 #ifdef  FIONBIO\r
2246         ioctl(fd, FIONBIO, &flag);\r
2247 #else   // FIONBIO\r
2248         {\r
2249                 int flag = fcntl(fd, F_GETFL, 0);\r
2250                 if (flag != -1)\r
2251                 {\r
2252                         if (nonblock)\r
2253                         {\r
2254                                 flag |= O_NONBLOCK;\r
2255                         }\r
2256                         else\r
2257                         {\r
2258                                 flag = flag & ~O_NONBLOCK;\r
2259 \r
2260                                 fcntl(fd, F_SETFL, flag);\r
2261                         }\r
2262                 }\r
2263         }\r
2264 #endif  // FIONBIO\r
2265 }\r
2266 \r
2267 // 何もしない\r
2268 void UnixIpForwardRowToRouteEntry(ROUTE_ENTRY *entry, void *ip_forward_row)\r
2269 {\r
2270 }\r
2271 \r
2272 // 何もしない\r
2273 void UnixRouteEntryToIpForwardRow(void *ip_forward_row, ROUTE_ENTRY *entry)\r
2274 {\r
2275 }\r
2276 \r
2277 // 何もしない\r
2278 int UnixCompareRouteEntryByMetric(void *p1, void *p2)\r
2279 {\r
2280         return 1;\r
2281 }\r
2282 \r
2283 // 何もしない\r
2284 ROUTE_TABLE *UnixGetRouteTable()\r
2285 {\r
2286         ROUTE_TABLE *ret = ZeroMalloc(sizeof(ROUTE_TABLE));\r
2287         ret->NumEntry = 0;\r
2288         ret->Entry = ZeroMalloc(0);\r
2289 \r
2290         return ret;\r
2291 }\r
2292 \r
2293 // 何もしない\r
2294 bool UnixAddRouteEntry(ROUTE_ENTRY *e, bool *already_exists)\r
2295 {\r
2296         return true;\r
2297 }\r
2298 \r
2299 // 何もしない\r
2300 void UnixDeleteRouteEntry(ROUTE_ENTRY *e)\r
2301 {\r
2302         return;\r
2303 }\r
2304 \r
2305 // 何もしない\r
2306 UINT UnixGetVLanInterfaceID(char *instance_name)\r
2307 {\r
2308         return 1;\r
2309 }\r
2310 \r
2311 // 何もしない\r
2312 char **UnixEnumVLan(char *tag_name)\r
2313 {\r
2314         char **list;\r
2315 \r
2316         list = ZeroMalloc(sizeof(char *));\r
2317 \r
2318         return list;\r
2319 }\r
2320 \r
2321 // 何もしない\r
2322 void UnixRenewDhcp()\r
2323 {\r
2324 }\r
2325 \r
2326 // デフォルトの DNS サーバーの IP アドレスを取得\r
2327 bool UnixGetDefaultDns(IP *ip)\r
2328 {\r
2329         BUF *b;\r
2330         // 引数チェック\r
2331         if (ip == NULL)\r
2332         {\r
2333                 return false;\r
2334         }\r
2335 \r
2336         Lock(unix_dns_server_addr_lock);\r
2337         {\r
2338                 if (IsZero(&unix_dns_server, sizeof(IP)) == false)\r
2339                 {\r
2340                         Copy(ip, &unix_dns_server, sizeof(IP));\r
2341                         Unlock(unix_dns_server_addr_lock);\r
2342                         return true;\r
2343                 }\r
2344 \r
2345                 ip->addr[0] = 127;\r
2346                 ip->addr[1] = 0;\r
2347                 ip->addr[2] = 0;\r
2348                 ip->addr[3] = 1;\r
2349 \r
2350                 b = ReadDump("/etc/resolv.conf");\r
2351                 if (b != NULL)\r
2352                 {\r
2353                         char *s;\r
2354                         bool f = false;\r
2355                         while ((s = CfgReadNextLine(b)) != NULL)\r
2356                         {\r
2357                                 TOKEN_LIST *t = ParseToken(s, "\" \t,");\r
2358                                 if (t->NumTokens == 2)\r
2359                                 {\r
2360                                         if (StrCmpi(t->Token[0], "nameserver") == 0)\r
2361                                         {\r
2362                                                 StrToIP(ip, t->Token[1]);\r
2363                                                 f = true;\r
2364                                         }\r
2365                                 }\r
2366                                 FreeToken(t);\r
2367 \r
2368                                 Free(s);\r
2369 \r
2370                                 if (f)\r
2371                                 {\r
2372                                         break;\r
2373                                 }\r
2374                         }\r
2375                         FreeBuf(b);\r
2376                 }\r
2377                 Copy(&unix_dns_server, ip, sizeof(IP));\r
2378         }\r
2379         Unlock(unix_dns_server_addr_lock);\r
2380 \r
2381         return true;\r
2382 }\r
2383 \r
2384 \r
2385 // Select 処理\r
2386 void UnixSelect(SOCKSET *set, UINT timeout, CANCEL *c1, CANCEL *c2)\r
2387 {\r
2388         UINT reads[MAXIMUM_WAIT_OBJECTS];\r
2389         UINT writes[MAXIMUM_WAIT_OBJECTS];\r
2390         UINT num_read, num_write, i;\r
2391         UINT p1, p2;\r
2392         SOCK *s;\r
2393         UCHAR tmp[MAX_SIZE];\r
2394         // 引数チェック\r
2395         if (timeout == 0)\r
2396         {\r
2397                 return;\r
2398         }\r
2399 \r
2400         // 配列の初期化\r
2401         Zero(reads, sizeof(reads));\r
2402         Zero(writes, sizeof(writes));\r
2403         num_read = num_write = 0;\r
2404 \r
2405         // イベント配列の設定\r
2406         if (set != NULL)\r
2407         {\r
2408                 for (i = 0;i < set->NumSocket;i++)\r
2409                 {\r
2410                         s = set->Sock[i];\r
2411                         if (s != NULL)\r
2412                         {\r
2413                                 UnixInitAsyncSocket(s);\r
2414                                 reads[num_read++] = s->socket;\r
2415                                 if (s->WriteBlocked)\r
2416                                 {\r
2417                                         writes[num_write++] = s->socket;\r
2418                                 }\r
2419                         }\r
2420                 }\r
2421         }\r
2422 \r
2423         p1 = p2 = -1;\r
2424 \r
2425         if (c1 != NULL)\r
2426         {\r
2427                 reads[num_read++] = p1 = c1->pipe_read;\r
2428         }\r
2429         if (c2 != NULL)\r
2430         {\r
2431                 reads[num_read++] = p2 = c2->pipe_read;\r
2432         }\r
2433 \r
2434         // select を呼び出す\r
2435         UnixSelectInner(num_read, reads, num_write, writes, timeout);\r
2436 \r
2437         // pipe から読んでおく\r
2438         if (c1 != NULL && c1->SpecialFlag == false && p1 != -1)\r
2439         {\r
2440                 read(p1, tmp, sizeof(tmp));\r
2441         }\r
2442         if (c2 != NULL && c2->SpecialFlag == false && p2 != -1)\r
2443         {\r
2444                 read(p2, tmp, sizeof(tmp));\r
2445         }\r
2446 }\r
2447 \r
2448 // キャンセル\r
2449 void UnixCancel(CANCEL *c)\r
2450 {\r
2451         // 引数チェック\r
2452         if (c == NULL)\r
2453         {\r
2454                 return;\r
2455         }\r
2456 \r
2457         UnixWritePipe(c->pipe_write);\r
2458 }\r
2459 \r
2460 // キャンセルオブジェクトの解放\r
2461 void UnixCleanupCancel(CANCEL *c)\r
2462 {\r
2463         // 引数チェック\r
2464         if (c == NULL)\r
2465         {\r
2466                 return;\r
2467         }\r
2468 \r
2469         if (c->SpecialFlag == false)\r
2470         {\r
2471                 UnixDeletePipe(c->pipe_read, c->pipe_write);\r
2472         }\r
2473 \r
2474         Free(c);\r
2475 }\r
2476 \r
2477 // 新しいキャンセルオブジェクトの作成\r
2478 CANCEL *UnixNewCancel()\r
2479 {\r
2480         CANCEL *c = ZeroMallocFast(sizeof(CANCEL));\r
2481 \r
2482         c->ref = NewRef();\r
2483         c->SpecialFlag = false;\r
2484 \r
2485         UnixNewPipe(&c->pipe_read, &c->pipe_write);\r
2486 \r
2487         return c;\r
2488 }\r
2489 \r
2490 // ソケットをソケットイベントに追加する\r
2491 void UnixJoinSockToSockEvent(SOCK *sock, SOCK_EVENT *event)\r
2492 {\r
2493         // 引数チェック\r
2494         if (sock == NULL || event == NULL || sock->AsyncMode)\r
2495         {\r
2496                 return;\r
2497         }\r
2498         if (sock->ListenMode != false || (sock->Type == SOCK_TCP && sock->Connected == false))\r
2499         {\r
2500                 return;\r
2501         }\r
2502 \r
2503         sock->AsyncMode = true;\r
2504 \r
2505         LockList(event->SockList);\r
2506         {\r
2507                 Add(event->SockList, sock);\r
2508                 AddRef(sock->ref);\r
2509         }\r
2510         UnlockList(event->SockList);\r
2511 \r
2512         // ソケットを非同期にする\r
2513         UnixSetSocketNonBlockingMode(sock->socket, true);\r
2514 \r
2515         // SOCK_EVENT の参照カウンタを増加\r
2516         AddRef(event->ref);\r
2517         sock->SockEvent = event;\r
2518 \r
2519         // ソケットイベントを叩く\r
2520         SetSockEvent(event);\r
2521 }\r
2522 \r
2523 // ソケットイベントを待機する\r
2524 bool UnixWaitSockEvent(SOCK_EVENT *event, UINT timeout)\r
2525 {\r
2526         UINT num_read, num_write;\r
2527         UINT *reads, *writes;\r
2528         UINT n;\r
2529         char tmp[MAX_SIZE];\r
2530         // 引数チェック\r
2531         if (event == NULL)\r
2532         {\r
2533                 return false;\r
2534         }\r
2535 \r
2536         LockList(event->SockList);\r
2537         {\r
2538                 UINT i;\r
2539                 num_read = LIST_NUM(event->SockList) + 1;\r
2540                 reads = ZeroMallocFast(sizeof(SOCK *) * num_read);\r
2541 \r
2542                 num_write = 0;\r
2543 \r
2544                 for (i = 0;i < (num_read - 1);i++)\r
2545                 {\r
2546                         SOCK *s = LIST_DATA(event->SockList, i);\r
2547                         reads[i] = s->socket;\r
2548                         if (s->WriteBlocked)\r
2549                         {\r
2550                                 num_write++;\r
2551                         }\r
2552                 }\r
2553 \r
2554                 reads[num_read - 1] = event->pipe_read;\r
2555 \r
2556                 writes = ZeroMallocFast(sizeof(SOCK *) * num_write);\r
2557 \r
2558                 n = 0;\r
2559 \r
2560                 for (i = 0;i < (num_read - 1);i++)\r
2561                 {\r
2562                         SOCK *s = LIST_DATA(event->SockList, i);\r
2563                         if (s->WriteBlocked)\r
2564                         {\r
2565                                 writes[n++] = s->socket;\r
2566                         }\r
2567                 }\r
2568         }\r
2569         UnlockList(event->SockList);\r
2570 \r
2571         if (0)\r
2572         {\r
2573                 UINT i;\r
2574                 Print("UnixSelectInner: ");\r
2575                 for (i = 0;i < num_read;i++)\r
2576                 {\r
2577                         Print("%u ", reads[i]);\r
2578                 }\r
2579                 Print("\n");\r
2580         }\r
2581 \r
2582         UnixSelectInner(num_read, reads, num_write, writes, timeout);\r
2583 \r
2584         read(event->pipe_read, tmp, sizeof(tmp));\r
2585 \r
2586         Free(reads);\r
2587         Free(writes);\r
2588 \r
2589         return true;\r
2590 }\r
2591 \r
2592 // ソケットイベントをセットする\r
2593 void UnixSetSockEvent(SOCK_EVENT *event)\r
2594 {\r
2595         // 引数チェック\r
2596         if (event == NULL)\r
2597         {\r
2598                 return;\r
2599         }\r
2600 \r
2601         UnixWritePipe(event->pipe_write);\r
2602 }\r
2603 \r
2604 // ソケットの select の実行\r
2605 void UnixSelectInner(UINT num_read, UINT *reads, UINT num_write, UINT *writes, UINT timeout)\r
2606 {\r
2607         struct pollfd *p;\r
2608         UINT num;\r
2609         UINT i;\r
2610         UINT n;\r
2611         UINT num_read_total, num_write_total;\r
2612 \r
2613         if (num_read != 0 && reads == NULL)\r
2614         {\r
2615                 num_read = 0;\r
2616         }\r
2617         if (num_write != 0 && writes == NULL)\r
2618         {\r
2619                 num_write = 0;\r
2620         }\r
2621 \r
2622         if (timeout == 0)\r
2623         {\r
2624                 return;\r
2625         }\r
2626 \r
2627         num_read_total = num_write_total = 0;\r
2628         for (i = 0;i < num_read;i++)\r
2629         {\r
2630                 if (reads[i] != INVALID_SOCKET)\r
2631                 {\r
2632                         num_read_total++;\r
2633                 }\r
2634         }\r
2635         for (i = 0;i < num_write;i++)\r
2636         {\r
2637                 if (writes[i] != INVALID_SOCKET)\r
2638                 {\r
2639                         num_write_total++;\r
2640                 }\r
2641         }\r
2642 \r
2643         num = num_read_total + num_write_total;\r
2644         p = ZeroMallocFast(sizeof(struct pollfd) * num);\r
2645 \r
2646         n = 0;\r
2647 \r
2648         for (i = 0;i < num_read;i++)\r
2649         {\r
2650                 if (reads[i] != INVALID_SOCKET)\r
2651                 {\r
2652                         struct pollfd *pfd = &p[n++];\r
2653                         pfd->fd = reads[i];\r
2654                         pfd->events = POLLIN | POLLPRI | POLLERR | POLLHUP;\r
2655                 }\r
2656         }\r
2657 \r
2658         for (i = 0;i < num_write;i++)\r
2659         {\r
2660                 if (writes[i] != INVALID_SOCKET)\r
2661                 {\r
2662                         struct pollfd *pfd = &p[n++];\r
2663                         pfd->fd = writes[i];\r
2664                         pfd->events = POLLIN | POLLPRI | POLLERR | POLLHUP | POLLOUT;\r
2665                 }\r
2666         }\r
2667 \r
2668         if (num != 0)\r
2669         {\r
2670                 poll(p, num, timeout == INFINITE ? -1 : (int)timeout);\r
2671         }\r
2672         else\r
2673         {\r
2674                 SleepThread(timeout);\r
2675         }\r
2676 \r
2677         Free(p);\r
2678 }\r
2679 \r
2680 // ソケットイベントのクリーンアップ\r
2681 void UnixCleanupSockEvent(SOCK_EVENT *event)\r
2682 {\r
2683         UINT i;\r
2684         // 引数チェック\r
2685         if (event == NULL)\r
2686         {\r
2687                 return;\r
2688         }\r
2689 \r
2690         for (i = 0;i < LIST_NUM(event->SockList);i++)\r
2691         {\r
2692                 SOCK *s = LIST_DATA(event->SockList, i);\r
2693 \r
2694                 ReleaseSock(s);\r
2695         }\r
2696 \r
2697         ReleaseList(event->SockList);\r
2698 \r
2699         UnixDeletePipe(event->pipe_read, event->pipe_write);\r
2700 \r
2701         Free(event);\r
2702 }\r
2703 \r
2704 // ソケットイベントを作成する\r
2705 SOCK_EVENT *UnixNewSockEvent()\r
2706 {\r
2707         SOCK_EVENT *e = ZeroMallocFast(sizeof(SOCK_EVENT));\r
2708 \r
2709         e->SockList = NewList(NULL);\r
2710         e->ref = NewRef();\r
2711 \r
2712         UnixNewPipe(&e->pipe_read, &e->pipe_write);\r
2713 \r
2714         return e;\r
2715 }\r
2716 \r
2717 // パイプを閉じる\r
2718 void UnixDeletePipe(int p1, int p2)\r
2719 {\r
2720         if (p1 != -1)\r
2721         {\r
2722                 close(p1);\r
2723         }\r
2724 \r
2725         if (p2 != -1)\r
2726         {\r
2727                 close(p2);\r
2728         }\r
2729 }\r
2730 \r
2731 // パイプに書き込む\r
2732 void UnixWritePipe(int pipe_write)\r
2733 {\r
2734         char c = 1;\r
2735         write(pipe_write, &c, 1);\r
2736 }\r
2737 \r
2738 // 新しいパイプを作成する\r
2739 void UnixNewPipe(int *pipe_read, int *pipe_write)\r
2740 {\r
2741         int fd[2];\r
2742         // 引数チェック\r
2743         if (pipe_read == NULL || pipe_write == NULL)\r
2744         {\r
2745                 return;\r
2746         }\r
2747 \r
2748         fd[0] = fd[1] = 0;\r
2749 \r
2750         pipe(fd);\r
2751 \r
2752         *pipe_read = fd[0];\r
2753         *pipe_write = fd[1];\r
2754 \r
2755         UnixSetSocketNonBlockingMode(*pipe_write, true);\r
2756         UnixSetSocketNonBlockingMode(*pipe_read, true);\r
2757 }\r
2758 \r
2759 // 非同期ソケットの解放\r
2760 void UnixFreeAsyncSocket(SOCK *sock)\r
2761 {\r
2762         UINT p;\r
2763         // 引数チェック\r
2764         if (sock == NULL)\r
2765         {\r
2766                 return;\r
2767         }\r
2768 \r
2769         Lock(sock->lock);\r
2770         {\r
2771                 if (sock->AsyncMode == false)\r
2772                 {\r
2773                         Unlock(sock->lock);\r
2774                         return;\r
2775                 }\r
2776 \r
2777                 sock->AsyncMode = false;\r
2778 \r
2779                 // このソケットが SockEvent に関連付けられているかどうか調べる\r
2780                 if (sock->SockEvent != NULL)\r
2781                 {\r
2782                         SOCK_EVENT *e = sock->SockEvent;\r
2783 \r
2784                         AddRef(e->ref);\r
2785 \r
2786                         p = e->pipe_write;\r
2787                         LockList(e->SockList);\r
2788                         {\r
2789                                 if (Delete(e->SockList, sock))\r
2790                                 {\r
2791                                         ReleaseSock(sock);\r
2792                                 }\r
2793                         }\r
2794                         UnlockList(e->SockList);\r
2795 \r
2796                         // ソケットイベントを解放する\r
2797                         ReleaseSockEvent(sock->SockEvent);\r
2798                         sock->SockEvent = NULL;\r
2799 \r
2800                         SetSockEvent(e);\r
2801 \r
2802                         ReleaseSockEvent(e);\r
2803                 }\r
2804         }\r
2805         Unlock(sock->lock);\r
2806 }\r
2807 \r
2808 // ソケットを非同期に設定する\r
2809 void UnixInitAsyncSocket(SOCK *sock)\r
2810 {\r
2811         // 引数チェック\r
2812         if (sock == NULL)\r
2813         {\r
2814                 return;\r
2815         }\r
2816         if (sock->AsyncMode)\r
2817         {\r
2818                 // すでに非同期ソケットになっている\r
2819                 return;\r
2820         }\r
2821         if (sock->ListenMode != false || (sock->Type == SOCK_TCP && sock->Connected == false))\r
2822         {\r
2823                 return;\r
2824         }\r
2825 \r
2826         sock->AsyncMode = true;\r
2827 \r
2828         UnixSetSocketNonBlockingMode(sock->socket, true);\r
2829 }\r
2830 \r
2831 // ソケットライブラリの初期化\r
2832 void UnixInitSocketLibrary()\r
2833 {\r
2834         // 特に何もしない\r
2835 }\r
2836 \r
2837 // ソケットライブラリの解放\r
2838 void UnixFreeSocketLibrary()\r
2839 {\r
2840         // 特に何もしない\r
2841 }\r
2842 \r
2843 #endif  // OS_UNIX\r
2844 \r
2845 #ifdef  OS_WIN32                // Windows 用コード\r
2846 \r
2847 NETWORK_WIN32_FUNCTIONS *w32net;\r
2848 \r
2849 // IP_ADAPTER_INDEX_MAP の比較\r
2850 int CompareIpAdapterIndexMap(void *p1, void *p2)\r
2851 {\r
2852         IP_ADAPTER_INDEX_MAP *a1, *a2;\r
2853         if (p1 == NULL || p2 == NULL)\r
2854         {\r
2855                 return 0;\r
2856         }\r
2857         a1 = *(IP_ADAPTER_INDEX_MAP **)p1;\r
2858         a2 = *(IP_ADAPTER_INDEX_MAP **)p2;\r
2859         if (a1 == NULL || a2 == NULL)\r
2860         {\r
2861                 return 0;\r
2862         }\r
2863 \r
2864         if (a1->Index > a2->Index)\r
2865         {\r
2866                 return 1;\r
2867         }\r
2868         else if (a1->Index < a2->Index)\r
2869         {\r
2870                 return -1;\r
2871         }\r
2872         else\r
2873         {\r
2874                 return 0;\r
2875         }\r
2876 }\r
2877 \r
2878 // アダプタの IP アドレスを更新\r
2879 bool Win32RenewAddressByGuid(char *guid)\r
2880 {\r
2881         IP_ADAPTER_INDEX_MAP a;\r
2882         // 引数チェック\r
2883         if (guid == NULL)\r
2884         {\r
2885                 return false;\r
2886         }\r
2887 \r
2888         Zero(&a, sizeof(a));\r
2889         if (Win32GetAdapterFromGuid(&a, guid) == false)\r
2890         {\r
2891                 return false;\r
2892         }\r
2893 \r
2894         return Win32RenewAddress(&a);\r
2895 }\r
2896 bool Win32RenewAddress(void *a)\r
2897 {\r
2898         DWORD ret;\r
2899         // 引数チェック\r
2900         if (a == NULL)\r
2901         {\r
2902                 return false;\r
2903         }\r
2904         if (w32net->IpRenewAddress == NULL)\r
2905         {\r
2906                 return false;\r
2907         }\r
2908 \r
2909         ret = w32net->IpRenewAddress(a);\r
2910 \r
2911         if (ret == NO_ERROR)\r
2912         {\r
2913                 return true;\r
2914         }\r
2915         else\r
2916         {\r
2917                 Debug("IpRenewAddress: Error: %u\n", ret);\r
2918                 return false;\r
2919         }\r
2920 }\r
2921 \r
2922 // アダプタの IP アドレスを解放\r
2923 bool Win32ReleaseAddress(void *a)\r
2924 {\r
2925         DWORD ret;\r
2926         // 引数チェック\r
2927         if (a == NULL)\r
2928         {\r
2929                 return false;\r
2930         }\r
2931         if (w32net->IpReleaseAddress == NULL)\r
2932         {\r
2933                 return false;\r
2934         }\r
2935 \r
2936         ret = w32net->IpReleaseAddress(a);\r
2937 \r
2938         if (ret == NO_ERROR)\r
2939         {\r
2940                 return true;\r
2941         }\r
2942         else\r
2943         {\r
2944                 Debug("IpReleaseAddress: Error: %u\n", ret);\r
2945                 return false;\r
2946         }\r
2947 }\r
2948 bool Win32ReleaseAddressByGuid(char *guid)\r
2949 {\r
2950         IP_ADAPTER_INDEX_MAP a;\r
2951         // 引数チェック\r
2952         if (guid == NULL)\r
2953         {\r
2954                 return false;\r
2955         }\r
2956 \r
2957         Zero(&a, sizeof(a));\r
2958         if (Win32GetAdapterFromGuid(&a, guid) == false)\r
2959         {\r
2960                 return false;\r
2961         }\r
2962 \r
2963         return Win32ReleaseAddress(&a);\r
2964 }\r
2965 void Win32ReleaseAddressByGuidExThread(THREAD *t, void *param)\r
2966 {\r
2967         WIN32_RELEASEADDRESS_THREAD_PARAM *p;\r
2968         // 引数チェック\r
2969         if (t == NULL || param == NULL)\r
2970         {\r
2971                 return;\r
2972         }\r
2973 \r
2974         p = (WIN32_RELEASEADDRESS_THREAD_PARAM *)param;\r
2975 \r
2976         AddRef(p->Ref);\r
2977 \r
2978         NoticeThreadInit(t);\r
2979 \r
2980         AddWaitThread(t);\r
2981 \r
2982         if (p->Renew == false)\r
2983         {\r
2984                 p->Ok = Win32ReleaseAddressByGuid(p->Guid);\r
2985         }\r
2986         else\r
2987         {\r
2988                 p->Ok = Win32RenewAddressByGuid(p->Guid);\r
2989         }\r
2990 \r
2991         ReleaseWin32ReleaseAddressByGuidThreadParam(p);\r
2992 \r
2993         DelWaitThread(t);\r
2994 }\r
2995 bool Win32RenewAddressByGuidEx(char *guid, UINT timeout)\r
2996 {\r
2997         return Win32ReleaseOrRenewAddressByGuidEx(guid, timeout, true);\r
2998 }\r
2999 bool Win32ReleaseAddressByGuidEx(char *guid, UINT timeout)\r
3000 {\r
3001         return Win32ReleaseOrRenewAddressByGuidEx(guid, timeout, false);\r
3002 }\r
3003 bool Win32ReleaseOrRenewAddressByGuidEx(char *guid, UINT timeout, bool renew)\r
3004 {\r
3005         THREAD *t;\r
3006         WIN32_RELEASEADDRESS_THREAD_PARAM *p;\r
3007         bool ret = false;\r
3008         UINT64 start_tick = 0;\r
3009         UINT64 end_tick = 0;\r
3010         // 引数チェック\r
3011         if (guid == NULL)\r
3012         {\r
3013                 return false;\r
3014         }\r
3015         if (timeout == 0)\r
3016         {\r
3017                 timeout = INFINITE;\r
3018         }\r
3019 \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
3024         p->Renew = renew;\r
3025 \r
3026         t = NewThread(Win32ReleaseAddressByGuidExThread, p);\r
3027         WaitThreadInit(t);\r
3028         start_tick = Tick64();\r
3029         end_tick = start_tick + (UINT64)timeout;\r
3030 \r
3031         while (true)\r
3032         {\r
3033                 UINT64 now = Tick64();\r
3034                 UINT64 remain;\r
3035                 UINT remain32;\r
3036 \r
3037                 if (now >= end_tick)\r
3038                 {\r
3039                         break;\r
3040                 }\r
3041 \r
3042                 remain = end_tick - now;\r
3043                 remain32 = MIN((UINT)remain, 100);\r
3044 \r
3045                 if (WaitThread(t, remain32))\r
3046                 {\r
3047                         break;\r
3048                 }\r
3049         }\r
3050 \r
3051         ReleaseThread(t);\r
3052 \r
3053         if (p->Ok)\r
3054         {\r
3055                 ret = true;\r
3056         }\r
3057 \r
3058         ReleaseWin32ReleaseAddressByGuidThreadParam(p);\r
3059 \r
3060         return ret;\r
3061 }\r
3062 void ReleaseWin32ReleaseAddressByGuidThreadParam(WIN32_RELEASEADDRESS_THREAD_PARAM *p)\r
3063 {\r
3064         // 引数チェック\r
3065         if (p == NULL)\r
3066         {\r
3067                 return;\r
3068         }\r
3069 \r
3070         if (Release(p->Ref) == 0)\r
3071         {\r
3072                 Free(p);\r
3073         }\r
3074 }\r
3075 \r
3076 // アダプタを GUID から取得\r
3077 bool Win32GetAdapterFromGuid(void *a, char *guid)\r
3078 {\r
3079         bool ret = false;\r
3080         IP_INTERFACE_INFO *info;\r
3081         UINT size;\r
3082         int i;\r
3083         LIST *o;\r
3084         wchar_t tmp[MAX_SIZE];\r
3085 \r
3086         // 引数チェック\r
3087         if (a == NULL || guid == NULL)\r
3088         {\r
3089                 return false;\r
3090         }\r
3091         if (w32net->GetInterfaceInfo == NULL)\r
3092         {\r
3093                 return false;\r
3094         }\r
3095 \r
3096         UniFormat(tmp, sizeof(tmp), L"\\DEVICE\\TCPIP_%S", guid);\r
3097 \r
3098         size = sizeof(IP_INTERFACE_INFO);\r
3099         info = ZeroMallocFast(size);\r
3100 \r
3101         if (w32net->GetInterfaceInfo(info, &size) == ERROR_INSUFFICIENT_BUFFER)\r
3102         {\r
3103                 Free(info);\r
3104                 info = ZeroMallocFast(size);\r
3105         }\r
3106 \r
3107         if (w32net->GetInterfaceInfo(info, &size) != NO_ERROR)\r
3108         {\r
3109                 Free(info);\r
3110                 return false;\r
3111         }\r
3112 \r
3113         o = NewListFast(CompareIpAdapterIndexMap);\r
3114 \r
3115         for (i = 0;i < info->NumAdapters;i++)\r
3116         {\r
3117                 IP_ADAPTER_INDEX_MAP *a = &info->Adapter[i];\r
3118 \r
3119                 Add(o, a);\r
3120         }\r
3121 \r
3122         Sort(o);\r
3123 \r
3124         for (i = 0;i < (int)(LIST_NUM(o));i++)\r
3125         {\r
3126                 IP_ADAPTER_INDEX_MAP *e = LIST_DATA(o, i);\r
3127 \r
3128                 if (UniStrCmpi(e->Name, tmp) == 0)\r
3129                 {\r
3130                         Copy(a, e, sizeof(IP_ADAPTER_INDEX_MAP));\r
3131                         ret = true;\r
3132                         break;\r
3133                 }\r
3134         }\r
3135 \r
3136         ReleaseList(o);\r
3137 \r
3138         Free(info);\r
3139 \r
3140         return ret;\r
3141 }\r
3142 \r
3143 // テスト\r
3144 void Win32NetworkTest()\r
3145 {\r
3146         IP_INTERFACE_INFO *info;\r
3147         UINT size;\r
3148         int i;\r
3149         LIST *o;\r
3150 \r
3151         size = sizeof(IP_INTERFACE_INFO);\r
3152         info = ZeroMallocFast(size);\r
3153 \r
3154         if (w32net->GetInterfaceInfo(info, &size) == ERROR_INSUFFICIENT_BUFFER)\r
3155         {\r
3156                 Free(info);\r
3157                 info = ZeroMallocFast(size);\r
3158         }\r
3159 \r
3160         if (w32net->GetInterfaceInfo(info, &size) != NO_ERROR)\r
3161         {\r
3162                 Free(info);\r
3163                 return;\r
3164         }\r
3165 \r
3166         o = NewListFast(CompareIpAdapterIndexMap);\r
3167 \r
3168         for (i = 0;i < info->NumAdapters;i++)\r
3169         {\r
3170                 IP_ADAPTER_INDEX_MAP *a = &info->Adapter[i];\r
3171 \r
3172                 Add(o, a);\r
3173         }\r
3174 \r
3175         Sort(o);\r
3176 \r
3177         for (i = 0;i < (int)(LIST_NUM(o));i++)\r
3178         {\r
3179                 IP_ADAPTER_INDEX_MAP *a = LIST_DATA(o, i);\r
3180 \r
3181                 DoNothing();\r
3182         }\r
3183 \r
3184         ReleaseList(o);\r
3185 \r
3186         Free(info);\r
3187 }\r
3188 \r
3189 // 指定された LAN カードの DHCP アドレスを更新する\r
3190 void Win32RenewDhcp9x(UINT if_id)\r
3191 {\r
3192         IP_INTERFACE_INFO *info;\r
3193         UINT size;\r
3194         int i;\r
3195         LIST *o;\r
3196         // 引数チェック\r
3197         if (if_id == 0)\r
3198         {\r
3199                 return;\r
3200         }\r
3201 \r
3202         size = sizeof(IP_INTERFACE_INFO);\r
3203         info = ZeroMallocFast(size);\r
3204 \r
3205         if (w32net->GetInterfaceInfo(info, &size) == ERROR_INSUFFICIENT_BUFFER)\r
3206         {\r
3207                 Free(info);\r
3208                 info = ZeroMallocFast(size);\r
3209         }\r
3210 \r
3211         if (w32net->GetInterfaceInfo(info, &size) != NO_ERROR)\r
3212         {\r
3213                 Free(info);\r
3214                 return;\r
3215         }\r
3216 \r
3217         o = NewListFast(CompareIpAdapterIndexMap);\r
3218 \r
3219         for (i = 0;i < info->NumAdapters;i++)\r
3220         {\r
3221                 IP_ADAPTER_INDEX_MAP *a = &info->Adapter[i];\r
3222 \r
3223                 Add(o, a);\r
3224         }\r
3225 \r
3226         Sort(o);\r
3227 \r
3228         for (i = 0;i < (int)(LIST_NUM(o));i++)\r
3229         {\r
3230                 IP_ADAPTER_INDEX_MAP *a = LIST_DATA(o, i);\r
3231 \r
3232                 if (a->Index == if_id)\r
3233                 {\r
3234                         char arg[MAX_PATH];\r
3235                         Format(arg, sizeof(arg), "/renew %u", i);\r
3236                         Run("ipconfig.exe", arg, true, false);\r
3237                 }\r
3238         }\r
3239 \r
3240         ReleaseList(o);\r
3241 \r
3242         Free(info);\r
3243 }\r
3244 \r
3245 // 指定された LAN カードの DHCP アドレスを解放する\r
3246 void Win32ReleaseDhcp9x(UINT if_id, bool wait)\r
3247 {\r
3248         IP_INTERFACE_INFO *info;\r
3249         UINT size;\r
3250         int i;\r
3251         LIST *o;\r
3252         // 引数チェック\r
3253         if (if_id == 0)\r
3254         {\r
3255                 return;\r
3256         }\r
3257 \r
3258         size = sizeof(IP_INTERFACE_INFO);\r
3259         info = ZeroMallocFast(size);\r
3260 \r
3261         if (w32net->GetInterfaceInfo(info, &size) == ERROR_INSUFFICIENT_BUFFER)\r
3262         {\r
3263                 Free(info);\r
3264                 info = ZeroMallocFast(size);\r
3265         }\r
3266 \r
3267         if (w32net->GetInterfaceInfo(info, &size) != NO_ERROR)\r
3268         {\r
3269                 Free(info);\r
3270                 return;\r
3271         }\r
3272 \r
3273         o = NewListFast(CompareIpAdapterIndexMap);\r
3274 \r
3275         for (i = 0;i < info->NumAdapters;i++)\r
3276         {\r
3277                 IP_ADAPTER_INDEX_MAP *a = &info->Adapter[i];\r
3278 \r
3279                 Add(o, a);\r
3280         }\r
3281 \r
3282         Sort(o);\r
3283 \r
3284         for (i = 0;i < (int)(LIST_NUM(o));i++)\r
3285         {\r
3286                 IP_ADAPTER_INDEX_MAP *a = LIST_DATA(o, i);\r
3287 \r
3288                 if (a->Index == if_id)\r
3289                 {\r
3290                         char arg[MAX_PATH];\r
3291                         Format(arg, sizeof(arg), "/release %u", i);\r
3292                         Run("ipconfig.exe", arg, true, wait);\r
3293                 }\r
3294         }\r
3295 \r
3296         ReleaseList(o);\r
3297 \r
3298         Free(info);\r
3299 }\r
3300 \r
3301 // DHCP サーバーから IP アドレスを再取得する\r
3302 void Win32RenewDhcp()\r
3303 {\r
3304         if (OS_IS_WINDOWS_NT(GetOsInfo()->OsType))\r
3305         {\r
3306                 Run("ipconfig.exe", "/renew", true, false);\r
3307                 if (MsIsVista())\r
3308                 {\r
3309                         Run("ipconfig.exe", "/renew6", true, false);\r
3310                 }\r
3311                 else\r
3312                 {\r
3313                         Run("netsh.exe", "int ipv6 renew", true, false);\r
3314                 }\r
3315         }\r
3316         else\r
3317         {\r
3318                 Run("ipconfig.exe", "/renew_all", true, false);\r
3319         }\r
3320 }\r
3321 \r
3322 // 指定された文字列を含む仮想 LAN カードの一覧を列挙する\r
3323 char **Win32EnumVLan(char *tag_name)\r
3324 {\r
3325         MIB_IFTABLE *p;\r
3326         UINT ret;\r
3327         UINT size_needed;\r
3328         UINT num_retry = 0;\r
3329         UINT i;\r
3330         LIST *o;\r
3331         char **ss;\r
3332         // 引数チェック\r
3333         if (tag_name == 0)\r
3334         {\r
3335                 return NULL;\r
3336         }\r
3337 \r
3338 RETRY:\r
3339         p = ZeroMallocFast(sizeof(MIB_IFTABLE));\r
3340         size_needed = 0;\r
3341 \r
3342         // 必要なサイズを調べる\r
3343         ret = w32net->GetIfTable(p, &size_needed, 0);\r
3344         if (ret == ERROR_INSUFFICIENT_BUFFER)\r
3345         {\r
3346                 // 必要なサイズ分のメモリブロックを再確保\r
3347                 Free(p);\r
3348                 p = ZeroMallocFast(size_needed);\r
3349         }\r
3350         else if (ret != NO_ERROR)\r
3351         {\r
3352                 // 取得失敗\r
3353 FAILED:\r
3354                 Free(p);\r
3355                 return NULL;\r
3356         }\r
3357 \r
3358         // 実際に取得する\r
3359         ret = w32net->GetIfTable(p, &size_needed, FALSE);\r
3360         if (ret != NO_ERROR)\r
3361         {\r
3362                 // 取得失敗\r
3363                 if ((++num_retry) >= 5)\r
3364                 {\r
3365                         goto FAILED;\r
3366                 }\r
3367                 Free(p);\r
3368                 goto RETRY;\r
3369         }\r
3370 \r
3371         // 検索\r
3372         ret = 0;\r
3373         o = NewListFast(CompareStr);\r
3374         for (i = 0;i < p->dwNumEntries;i++)\r
3375         {\r
3376                 MIB_IFROW *r = &p->table[i];\r
3377                 if (SearchStrEx(r->bDescr, tag_name, 0, false) != INFINITE)\r
3378                 {\r
3379                         char *s = CopyStr(r->bDescr);\r
3380                         Add(o, s);\r
3381                 }\r
3382         }\r
3383 \r
3384         Free(p);\r
3385 \r
3386         // ソート\r
3387         Sort(o);\r
3388 \r
3389         // 文字列に変換\r
3390         ss = ZeroMallocFast(sizeof(char *) * (LIST_NUM(o) + 1));\r
3391         for (i = 0;i < LIST_NUM(o);i++)\r
3392         {\r
3393                 ss[i] = LIST_DATA(o, i);\r
3394         }\r
3395         ss[LIST_NUM(o)] = NULL;\r
3396 \r
3397         ReleaseList(o);\r
3398 \r
3399         return ss;\r
3400 }\r
3401 \r
3402 // 仮想 LAN カードのインスタンス名から仮想 LAN カードの ID を取得する\r
3403 UINT Win32GetVLanInterfaceID(char *instance_name)\r
3404 {\r
3405         MIB_IFTABLE *p;\r
3406         UINT ret;\r
3407         UINT size_needed;\r
3408         UINT num_retry = 0;\r
3409         UINT i;\r
3410         char ps_miniport_str[MAX_SIZE];\r
3411         char ps_miniport_str2[MAX_SIZE];\r
3412         // 引数チェック\r
3413         if (instance_name == 0)\r
3414         {\r
3415                 return 0;\r
3416         }\r
3417 \r
3418 RETRY:\r
3419         p = ZeroMallocFast(sizeof(MIB_IFTABLE));\r
3420         size_needed = 0;\r
3421 \r
3422         // 必要なサイズを調べる\r
3423         ret = w32net->GetIfTable(p, &size_needed, 0);\r
3424         if (ret == ERROR_INSUFFICIENT_BUFFER)\r
3425         {\r
3426                 // 必要なサイズ分のメモリブロックを再確保\r
3427                 Free(p);\r
3428                 p = ZeroMallocFast(size_needed);\r
3429         }\r
3430         else if (ret != NO_ERROR)\r
3431         {\r
3432                 // 取得失敗\r
3433 FAILED:\r
3434                 Free(p);\r
3435                 Debug("******** GetIfTable Failed 1. Err = %u\n", ret);\r
3436                 return 0;\r
3437         }\r
3438 \r
3439         // 実際に取得する\r
3440         ret = w32net->GetIfTable(p, &size_needed, FALSE);\r
3441         if (ret != NO_ERROR)\r
3442         {\r
3443                 // 取得失敗\r
3444                 if ((++num_retry) >= 5)\r
3445                 {\r
3446                         goto FAILED;\r
3447                 }\r
3448                 Free(p);\r
3449                 Debug("******** GetIfTable Failed 2. Err = %u\n", ret);\r
3450                 goto RETRY;\r
3451         }\r
3452 \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
3456 \r
3457         // 検索\r
3458         ret = 0;\r
3459         for (i = 0;i < p->dwNumEntries;i++)\r
3460         {\r
3461                 MIB_IFROW *r = &p->table[i];\r
3462                 if (instance_name[0] != '@')\r
3463                 {\r
3464                         if (StrCmpi(r->bDescr, instance_name) == 0 || StartWith(r->bDescr, ps_miniport_str) || StartWith(r->bDescr, ps_miniport_str2))\r
3465                         {\r
3466                                 ret = r->dwIndex;\r
3467                         }\r
3468                 }\r
3469                 else\r
3470                 {\r
3471                         if (SearchStrEx(r->bDescr, &instance_name[1], 0, false) != INFINITE)\r
3472                         {\r
3473                                 ret = r->dwIndex;\r
3474                         }\r
3475                 }\r
3476 \r
3477                 Debug("if[%u] (0x%x): %s\n", i, r->dwIndex, r->bDescr);\r
3478         }\r
3479 \r
3480         Free(p);\r
3481 \r
3482         return ret;\r
3483 }\r
3484 \r
3485 // デフォルトの DNS サーバーアドレスを取得する\r
3486 bool Win32GetDefaultDns(IP *ip, char *domain, UINT size)\r
3487 {\r
3488         FIXED_INFO *info;\r
3489         UINT info_size;\r
3490         char *dns_name;\r
3491         // 引数チェック\r
3492         if (ip == NULL)\r
3493         {\r
3494                 return false;\r
3495         }\r
3496         Zero(ip, sizeof(IP));\r
3497         info_size = 0;\r
3498         info = ZeroMallocFast(sizeof(FIXED_INFO));\r
3499         if (w32net->GetNetworkParams(info, &info_size) == ERROR_BUFFER_OVERFLOW)\r
3500         {\r
3501                 Free(info);\r
3502                 info = ZeroMallocFast(info_size);\r
3503         }\r
3504         if (w32net->GetNetworkParams(info, &info_size) != NO_ERROR)\r
3505         {\r
3506                 Free(info);\r
3507                 return false;\r
3508         }\r
3509 \r
3510         if (info->DnsServerList.IpAddress.String == NULL)\r
3511         {\r
3512                 Free(info);\r
3513                 return false;\r
3514         }\r
3515 \r
3516         dns_name = info->DnsServerList.IpAddress.String;\r
3517         StrToIP(ip, dns_name);\r
3518 \r
3519         if (domain != NULL)\r
3520         {\r
3521                 StrCpy(domain, size, info->DomainName);\r
3522                 Trim(domain);\r
3523         }\r
3524 \r
3525         Free(info);\r
3526 \r
3527         return true;\r
3528 }\r
3529 \r
3530 // Win32 用 IP 変換関数\r
3531 void Win32UINTToIP(IP *ip, UINT i)\r
3532 {\r
3533         UINTToIP(ip, i);\r
3534 }\r
3535 \r
3536 // Win32 用 IP 変換関数\r
3537 UINT Win32IPToUINT(IP *ip)\r
3538 {\r
3539         return IPToUINT(ip);\r
3540 }\r
3541 \r
3542 // ルーティングテーブルからルーティングエントリを削除\r
3543 void Win32DeleteRouteEntry(ROUTE_ENTRY *e)\r
3544 {\r
3545         MIB_IPFORWARDROW *p;\r
3546         // 引数チェック\r
3547         if (e == NULL)\r
3548         {\r
3549                 return;\r
3550         }\r
3551 \r
3552         p = ZeroMallocFast(sizeof(MIB_IPFORWARDROW));\r
3553         Win32RouteEntryToIpForwardRow(p, e);\r
3554 \r
3555         // 削除\r
3556         w32net->DeleteIpForwardEntry(p);\r
3557 \r
3558         Free(p);\r
3559 }\r
3560 \r
3561 // ルーティングテーブルにルーティングエントリを追加\r
3562 bool Win32AddRouteEntry(ROUTE_ENTRY *e, bool *already_exists)\r
3563 {\r
3564         bool ret = false;\r
3565         bool dummy = false;\r
3566         MIB_IPFORWARDROW *p;\r
3567         UINT err = 0;\r
3568         // 引数チェック\r
3569         if (e == NULL)\r
3570         {\r
3571                 return false;\r
3572         }\r
3573         if (already_exists == NULL)\r
3574         {\r
3575                 already_exists = &dummy;\r
3576         }\r
3577 \r
3578         *already_exists = false;\r
3579 \r
3580         p = ZeroMallocFast(sizeof(MIB_IPFORWARDROW));\r
3581         Win32RouteEntryToIpForwardRow(p, e);\r
3582 \r
3583         // 追加\r
3584         err = w32net->CreateIpForwardEntry(p);\r
3585         if (err != 0)\r
3586         {\r
3587                 if (err == ERROR_OBJECT_ALREADY_EXISTS)\r
3588                 {\r
3589                         Debug("CreateIpForwardEntry: Already Exists\n");\r
3590                         *already_exists = true;\r
3591                         ret = true;\r
3592                 }\r
3593                 else\r
3594                 {\r
3595                         Debug("CreateIpForwardEntry Error: %u\n", err);\r
3596                         ret = false;\r
3597                 }\r
3598         }\r
3599         else\r
3600         {\r
3601                 ret = true;\r
3602         }\r
3603 \r
3604         Free(p);\r
3605 \r
3606         return ret;\r
3607 }\r
3608 \r
3609 // ルーティングテーブルの取得\r
3610 ROUTE_TABLE *Win32GetRouteTable()\r
3611 {\r
3612         ROUTE_TABLE *t = ZeroMallocFast(sizeof(ROUTE_TABLE));\r
3613         MIB_IPFORWARDTABLE *p;\r
3614         UINT ret;\r
3615         UINT size_needed;\r
3616         UINT num_retry = 0;\r
3617         LIST *o;\r
3618         UINT i;\r
3619         ROUTE_ENTRY *e;\r
3620 \r
3621 RETRY:\r
3622         p = ZeroMallocFast(sizeof(MIB_IFTABLE));\r
3623         size_needed = 0;\r
3624 \r
3625         // 必要なサイズを調べる\r
3626         ret = w32net->GetIpForwardTable(p, &size_needed, 0);\r
3627         if (ret == ERROR_INSUFFICIENT_BUFFER)\r
3628         {\r
3629                 // 必要なサイズ分のメモリブロックを再確保\r
3630                 Free(p);\r
3631                 p = ZeroMallocFast(size_needed);\r
3632         }\r
3633         else if (ret != NO_ERROR)\r
3634         {\r
3635                 // 取得失敗\r
3636 FAILED:\r
3637                 Free(p);\r
3638                 t->Entry = MallocFast(0);\r
3639                 return t;\r
3640         }\r
3641 \r
3642         // 実際に取得する\r
3643         ret = w32net->GetIpForwardTable(p, &size_needed, FALSE);\r
3644         if (ret != NO_ERROR)\r
3645         {\r
3646                 // 取得失敗\r
3647                 if ((++num_retry) >= 5)\r
3648                 {\r
3649                         goto FAILED;\r
3650                 }\r
3651                 Free(p);\r
3652                 goto RETRY;\r
3653         }\r
3654 \r
3655         // リストに追加していく\r
3656         o = NewListFast(Win32CompareRouteEntryByMetric);\r
3657         for (i = 0;i < p->dwNumEntries;i++)\r
3658         {\r
3659                 e = ZeroMallocFast(sizeof(ROUTE_ENTRY));\r
3660                 Win32IpForwardRowToRouteEntry(e, &p->table[i]);\r
3661                 Add(o, e);\r
3662         }\r
3663         Free(p);\r
3664 \r
3665         // メトリック順にソート\r
3666         Sort(o);\r
3667 \r
3668         // 結果を結合\r
3669         t->NumEntry = LIST_NUM(o);\r
3670         t->Entry = ToArrayEx(o, true);\r
3671         ReleaseList(o);\r
3672 \r
3673         return t;\r
3674 }\r
3675 \r
3676 // ルーティングエントリをメトリックによってソートする\r
3677 int Win32CompareRouteEntryByMetric(void *p1, void *p2)\r
3678 {\r
3679         ROUTE_ENTRY *e1, *e2;\r
3680         // 引数チェック\r
3681         if (p1 == NULL || p2 == NULL)\r
3682         {\r
3683                 return 0;\r
3684         }\r
3685 \r
3686         e1 = *(ROUTE_ENTRY **)p1;\r
3687         e2 = *(ROUTE_ENTRY **)p2;\r
3688         if (e1 == NULL || e2 == NULL)\r
3689         {\r
3690                 return 0;\r
3691         }\r
3692 \r
3693         if (e1->Metric > e2->Metric)\r
3694         {\r
3695                 return 1;\r
3696         }\r
3697         else if (e1->Metric == e2->Metric)\r
3698         {\r
3699                 return 0;\r
3700         }\r
3701         else\r
3702         {\r
3703                 return -1;\r
3704         }\r
3705 }\r
3706 \r
3707 // ROUTE_ENTRY を MIB_IPFORWARDROW に変換\r
3708 void Win32RouteEntryToIpForwardRow(void *ip_forward_row, ROUTE_ENTRY *entry)\r
3709 {\r
3710         MIB_IPFORWARDROW *r;\r
3711         // 引数チェック\r
3712         if (entry == NULL || ip_forward_row == NULL)\r
3713         {\r
3714                 return;\r
3715         }\r
3716 \r
3717         r = (MIB_IPFORWARDROW *)ip_forward_row;\r
3718         Zero(r, sizeof(MIB_IPFORWARDROW));\r
3719 \r
3720         // IP アドレス\r
3721         r->dwForwardDest = Win32IPToUINT(&entry->DestIP);\r
3722         // サブネットマスク\r
3723         r->dwForwardMask = Win32IPToUINT(&entry->DestMask);\r
3724         // ゲートウェイ IP アドレス\r
3725         r->dwForwardNextHop = Win32IPToUINT(&entry->GatewayIP);\r
3726         // ローカルルーティングフラグ\r
3727         if (entry->LocalRouting)\r
3728         {\r
3729                 // ローカル\r
3730                 r->dwForwardType = 3;\r
3731         }\r
3732         else\r
3733         {\r
3734                 // リモートルータ\r
3735                 r->dwForwardType = 4;\r
3736         }\r
3737         // プロトコル\r
3738         r->dwForwardProto = r->dwForwardType - 1;       // 大抵の場合 1 引けば良い\r
3739         if (entry->PPPConnection)\r
3740         {\r
3741                 // PPP ちゃうかな? 危険!\r
3742                 r->dwForwardProto++;\r
3743         }\r
3744         // メトリック\r
3745         r->dwForwardMetric1 = entry->Metric;\r
3746 \r
3747         if (MsIsVista() == false)\r
3748         {\r
3749                 r->dwForwardMetric2 = r->dwForwardMetric3 = r->dwForwardMetric4 = r->dwForwardMetric5 = INFINITE;\r
3750         }\r
3751         else\r
3752         {\r
3753                 r->dwForwardMetric2 = r->dwForwardMetric3 = r->dwForwardMetric4 = r->dwForwardMetric5 = 0;\r
3754                 r->dwForwardAge = 163240;\r
3755         }\r
3756 \r
3757         // インターフェイス ID\r
3758         r->dwForwardIfIndex = entry->InterfaceID;\r
3759 \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
3769 }\r
3770 \r
3771 // MIB_IPFORWARDROW を ROUTE_ENTRY に変換\r
3772 void Win32IpForwardRowToRouteEntry(ROUTE_ENTRY *entry, void *ip_forward_row)\r
3773 {\r
3774         MIB_IPFORWARDROW *r;\r
3775         // 引数チェック\r
3776         if (entry == NULL || ip_forward_row == NULL)\r
3777         {\r
3778                 return;\r
3779         }\r
3780 \r
3781         r = (MIB_IPFORWARDROW *)ip_forward_row;\r
3782 \r
3783         Zero(entry, sizeof(ROUTE_ENTRY));\r
3784         // IP アドレス\r
3785         Win32UINTToIP(&entry->DestIP, r->dwForwardDest);\r
3786         // サブネットマスク\r
3787         Win32UINTToIP(&entry->DestMask, r->dwForwardMask);\r
3788         // ゲートウェイ IP アドレス\r
3789         Win32UINTToIP(&entry->GatewayIP, r->dwForwardNextHop);\r
3790         // ローカルルーティングフラグ\r
3791         if (r->dwForwardType == 3)\r
3792         {\r
3793                 entry->LocalRouting = true;\r
3794         }\r
3795         else\r
3796         {\r
3797                 entry->LocalRouting = false;\r
3798         }\r
3799         if (entry->LocalRouting && r->dwForwardProto == 3)\r
3800         {\r
3801                 // PPP。危険!\r
3802                 entry->PPPConnection = true;\r
3803         }\r
3804         // メトリック\r
3805         entry->Metric = r->dwForwardMetric1;\r
3806         // インターフェイス ID\r
3807         entry->InterfaceID = r->dwForwardIfIndex;\r
3808 }\r
3809 \r
3810 // ソケットライブラリの初期化\r
3811 void Win32InitSocketLibrary()\r
3812 {\r
3813         WSADATA data;\r
3814         Zero(&data, sizeof(data));\r
3815         WSAStartup(MAKEWORD(2, 2), &data);\r
3816 \r
3817         // DLL 関数の読み込み\r
3818         w32net = ZeroMalloc(sizeof(NETWORK_WIN32_FUNCTIONS));\r
3819         w32net->hIpHlpApi32 = LoadLibrary("iphlpapi.dll");\r
3820 \r
3821         if (w32net->hIpHlpApi32 != NULL)\r
3822         {\r
3823                 w32net->CreateIpForwardEntry =\r
3824                         (DWORD (__stdcall *)(PMIB_IPFORWARDROW))\r
3825                         GetProcAddress(w32net->hIpHlpApi32, "CreateIpForwardEntry");\r
3826 \r
3827                 w32net->DeleteIpForwardEntry =\r
3828                         (DWORD (__stdcall *)(PMIB_IPFORWARDROW))\r
3829                         GetProcAddress(w32net->hIpHlpApi32, "DeleteIpForwardEntry");\r
3830 \r
3831                 w32net->GetIfTable =\r
3832                         (DWORD (__stdcall *)(PMIB_IFTABLE, PULONG, BOOL))\r
3833                         GetProcAddress(w32net->hIpHlpApi32, "GetIfTable");\r
3834 \r
3835                 w32net->GetIpForwardTable =\r
3836                         (DWORD (__stdcall *)(PMIB_IPFORWARDTABLE, PULONG, BOOL))\r
3837                         GetProcAddress(w32net->hIpHlpApi32, "GetIpForwardTable");\r
3838 \r
3839                 w32net->GetNetworkParams =\r
3840                         (DWORD (__stdcall *)(PFIXED_INFO,PULONG))\r
3841                         GetProcAddress(w32net->hIpHlpApi32, "GetNetworkParams");\r
3842 \r
3843                 w32net->IpRenewAddress =\r
3844                         (DWORD (__stdcall *)(PIP_ADAPTER_INDEX_MAP))\r
3845                         GetProcAddress(w32net->hIpHlpApi32, "IpRenewAddress");\r
3846 \r
3847                 w32net->IpReleaseAddress =\r
3848                         (DWORD (__stdcall *)(PIP_ADAPTER_INDEX_MAP))\r
3849                         GetProcAddress(w32net->hIpHlpApi32, "IpReleaseAddress");\r
3850 \r
3851                 w32net->GetInterfaceInfo =\r
3852                         (DWORD (__stdcall *)(PIP_INTERFACE_INFO, PULONG))\r
3853                         GetProcAddress(w32net->hIpHlpApi32, "GetInterfaceInfo");\r
3854 \r
3855                 w32net->GetAdaptersInfo =\r
3856                         (DWORD (__stdcall *)(PIP_ADAPTER_INFO, PULONG))\r
3857                         GetProcAddress(w32net->hIpHlpApi32, "GetAdaptersInfo");\r
3858 \r
3859                 w32net->GetExtendedTcpTable =\r
3860                         (DWORD (__stdcall *)(PVOID,PDWORD,BOOL,ULONG,_TCP_TABLE_CLASS,ULONG))\r
3861                         GetProcAddress(w32net->hIpHlpApi32, "GetExtendedTcpTable");\r
3862 \r
3863                 w32net->AllocateAndGetTcpExTableFromStack =\r
3864                         (DWORD (__stdcall *)(PVOID *,BOOL,HANDLE,DWORD,DWORD))\r
3865                         GetProcAddress(w32net->hIpHlpApi32, "AllocateAndGetTcpExTableFromStack");\r
3866 \r
3867                 w32net->GetTcpTable =\r
3868                         (DWORD (__stdcall *)(PMIB_TCPTABLE,PDWORD,BOOL))\r
3869                         GetProcAddress(w32net->hIpHlpApi32, "GetTcpTable");\r
3870 \r
3871                 w32net->NotifyRouteChange =\r
3872                         (DWORD (__stdcall *)(PHANDLE,LPOVERLAPPED))\r
3873                         GetProcAddress(w32net->hIpHlpApi32, "NotifyRouteChange");\r
3874 \r
3875                 w32net->CancelIPChangeNotify =\r
3876                         (BOOL (__stdcall *)(LPOVERLAPPED))\r
3877                         GetProcAddress(w32net->hIpHlpApi32, "CancelIPChangeNotify");\r
3878 \r
3879                 w32net->NhpAllocateAndGetInterfaceInfoFromStack =\r
3880                         (DWORD (__stdcall *)(IP_INTERFACE_NAME_INFO **,PDWORD,BOOL,HANDLE,DWORD))\r
3881                         GetProcAddress(w32net->hIpHlpApi32, "NhpAllocateAndGetInterfaceInfoFromStack");\r
3882         }\r
3883 }\r
3884 \r
3885 // ソケットライブラリの解放\r
3886 void Win32FreeSocketLibrary()\r
3887 {\r
3888         if (w32net != NULL)\r
3889         {\r
3890                 FreeLibrary(w32net->hIpHlpApi32);\r
3891 \r
3892                 Free(w32net);\r
3893                 w32net = NULL;\r
3894         }\r
3895 \r
3896         WSACleanup();\r
3897 }\r
3898 \r
3899 // キャンセル\r
3900 void Win32Cancel(CANCEL *c)\r
3901 {\r
3902         // 引数チェック\r
3903         if (c == NULL)\r
3904         {\r
3905                 return;\r
3906         }\r
3907 \r
3908         SetEvent((HANDLE)c->hEvent);\r
3909 }\r
3910 \r
3911 // キャンセルのクリーンアップ\r
3912 void Win32CleanupCancel(CANCEL *c)\r
3913 {\r
3914         // 引数チェック\r
3915         if (c == NULL)\r
3916         {\r
3917                 return;\r
3918         }\r
3919 \r
3920         if (c->SpecialFlag == false)\r
3921         {\r
3922                 CloseHandle(c->hEvent);\r
3923         }\r
3924 \r
3925         Free(c);\r
3926 }\r
3927 \r
3928 // 新しいキャンセルオブジェクト\r
3929 CANCEL *Win32NewCancel()\r
3930 {\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
3935 \r
3936         return c;\r
3937 }\r
3938 \r
3939 // ソケットイベントの待機\r
3940 bool Win32WaitSockEvent(SOCK_EVENT *event, UINT timeout)\r
3941 {\r
3942         // 引数チェック\r
3943         if (event == NULL || timeout == 0)\r
3944         {\r
3945                 return false;\r
3946         }\r
3947 \r
3948         if (WaitForSingleObject((HANDLE)event->hEvent, timeout) == WAIT_OBJECT_0)\r
3949         {\r
3950                 return true;\r
3951         }\r
3952         else\r
3953         {\r
3954                 return false;\r
3955         }\r
3956 }\r
3957 \r
3958 // ソケットイベントのクリーンアップ\r
3959 void Win32CleanupSockEvent(SOCK_EVENT *event)\r
3960 {\r
3961         // 引数チェック\r
3962         if (event == NULL)\r
3963         {\r
3964                 return;\r
3965         }\r
3966 \r
3967         CloseHandle((HANDLE)event->hEvent);\r
3968 \r
3969         Free(event);\r
3970 }\r
3971 \r
3972 // ソケットイベントのセット\r
3973 void Win32SetSockEvent(SOCK_EVENT *event)\r
3974 {\r
3975         // 引数チェック\r
3976         if (event == NULL)\r
3977         {\r
3978                 return;\r
3979         }\r
3980 \r
3981         SetEvent((HANDLE)event->hEvent);\r
3982 }\r
3983 \r
3984 // ソケットイベントの作成\r
3985 SOCK_EVENT *Win32NewSockEvent()\r
3986 {\r
3987         SOCK_EVENT *e = ZeroMallocFast(sizeof(SOCK_EVENT));\r
3988 \r
3989         e->ref = NewRef();\r
3990         e->hEvent = (void *)CreateEvent(NULL, FALSE, FALSE, NULL);\r
3991 \r
3992         return e;\r
3993 }\r
3994 \r
3995 // ソケットをソケットイベントに関連付けして非同期に設定する\r
3996 void Win32JoinSockToSockEvent(SOCK *sock, SOCK_EVENT *event)\r
3997 {\r
3998         HANDLE hEvent;\r
3999         // 引数チェック\r
4000         if (sock == NULL || event == NULL || sock->AsyncMode)\r
4001         {\r
4002                 return;\r
4003         }\r
4004         if (sock->ListenMode != false || (sock->Type != SOCK_UDP && sock->Connected == false))\r
4005         {\r
4006                 return;\r
4007         }\r
4008 \r
4009         sock->AsyncMode = true;\r
4010 \r
4011         hEvent = event->hEvent;\r
4012 \r
4013         // 関連付け\r
4014         WSAEventSelect(sock->socket, hEvent, FD_READ | FD_WRITE | FD_CLOSE);\r
4015 \r
4016         // SOCK_EVENT の参照カウンタを増加\r
4017         AddRef(event->ref);\r
4018         sock->SockEvent = event;\r
4019 }\r
4020 \r
4021 // ソケットを非同期に設定する\r
4022 void Win32InitAsyncSocket(SOCK *sock)\r
4023 {\r
4024         // 引数チェック\r
4025         if (sock == NULL)\r
4026         {\r
4027                 return;\r
4028         }\r
4029         if (sock->AsyncMode)\r
4030         {\r
4031                 // すでに非同期ソケットになっている\r
4032                 return;\r
4033         }\r
4034         if (sock->ListenMode != false || (sock->Type == SOCK_TCP && sock->Connected == false))\r
4035         {\r
4036                 return;\r
4037         }\r
4038 \r
4039         sock->AsyncMode = true;\r
4040 \r
4041         // イベントの作成\r
4042         sock->hEvent = (void *)CreateEvent(NULL, FALSE, FALSE, NULL);\r
4043 \r
4044         // 関連付け\r
4045         WSAEventSelect(sock->socket, sock->hEvent, FD_READ | FD_WRITE | FD_CLOSE);\r
4046 }\r
4047 \r
4048 // 非同期ソケットを解放\r
4049 void Win32FreeAsyncSocket(SOCK *sock)\r
4050 {\r
4051         // 引数チェック\r
4052         if (sock == NULL)\r
4053         {\r
4054                 return;\r
4055         }\r
4056 \r
4057         // 非同期ソケット\r
4058         if (sock->hEvent != NULL)\r
4059         {\r
4060                 CloseHandle((HANDLE)sock->hEvent);\r
4061         }\r
4062         sock->hEvent = NULL;\r
4063         sock->AsyncMode = false;\r
4064 \r
4065         // ソケットイベント\r
4066         if (sock->SockEvent != NULL)\r
4067         {\r
4068                 ReleaseSockEvent(sock->SockEvent);\r
4069                 sock->SockEvent = NULL;\r
4070         }\r
4071 }\r
4072 \r
4073 // Win32 版 Select 関数\r
4074 void Win32Select(SOCKSET *set, UINT timeout, CANCEL *c1, CANCEL *c2)\r
4075 {\r
4076         HANDLE array[MAXIMUM_WAIT_OBJECTS];\r
4077         UINT n, i;\r
4078         SOCK *s;\r
4079         // 引数チェック\r
4080         if (timeout == 0)\r
4081         {\r
4082                 return;\r
4083         }\r
4084 \r
4085         // 配列の初期化\r
4086         Zero(array, sizeof(array));\r
4087         n = 0;\r
4088 \r
4089         // イベント配列の設定\r
4090         if (set != NULL)\r
4091         {\r
4092                 for (i = 0;i < set->NumSocket;i++)\r
4093                 {\r
4094                         s = set->Sock[i];\r
4095                         if (s != NULL)\r
4096                         {\r
4097                                 Win32InitAsyncSocket(s);\r
4098                                 if (s->hEvent != NULL)\r
4099                                 {\r
4100                                         array[n++] = (HANDLE)s->hEvent;\r
4101                                 }\r
4102                         }\r
4103                 }\r
4104         }\r
4105         if (c1 != NULL && c1->hEvent != NULL)\r
4106         {\r
4107                 array[n++] = c1->hEvent;\r
4108         }\r
4109         if (c2 != NULL && c2->hEvent != NULL)\r
4110         {\r
4111                 array[n++] = c2->hEvent;\r
4112         }\r
4113 \r
4114         if (n == 0)\r
4115         {\r
4116                 // 待つイベントが 1 つも登録されていない場合は\r
4117                 // 通常の待ち関数を呼ぶ\r
4118                 SleepThread(timeout);\r
4119         }\r
4120         else\r
4121         {\r
4122                 // イベントが 1 つ以上登録されている場合はイベントを待つ\r
4123                 if (n == 1)\r
4124                 {\r
4125                         // イベントが 1 つの場合は軽量版を呼び出す\r
4126                         WaitForSingleObject(array[0], timeout);\r
4127                 }\r
4128                 else\r
4129                 {\r
4130                         // イベントが複数の場合\r
4131                         WaitForMultipleObjects(n, array, false, timeout);\r
4132                 }\r
4133         }\r
4134 }\r
4135 \r
4136 #endif  // OS_WIN32\r
4137 \r
4138 // IPv6 がサポートされているかどうか調べる\r
4139 bool IsIPv6Supported()\r
4140 {\r
4141 #ifdef  NO_IPV6\r
4142         return false;\r
4143 #else   // NO_IPV6\r
4144         SOCKET s;\r
4145 \r
4146         s = socket(AF_INET6, SOCK_STREAM, 0);\r
4147         if (s == INVALID_SOCKET)\r
4148         {\r
4149                 return false;\r
4150         }\r
4151 \r
4152         closesocket(s);\r
4153 \r
4154         return true;\r
4155 #endif  // NO_IPV6\r
4156 }\r
4157 \r
4158 // ホストキャッシュからホスト名の取得\r
4159 bool GetHostCache(char *hostname, UINT size, IP *ip)\r
4160 {\r
4161         bool ret;\r
4162         // 引数チェック\r
4163         if (hostname == NULL || ip == NULL)\r
4164         {\r
4165                 return false;\r
4166         }\r
4167 \r
4168         ret = false;\r
4169 \r
4170         LockList(HostCacheList);\r
4171         {\r
4172                 HOSTCACHE t, *c;\r
4173                 Zero(&t, sizeof(t));\r
4174                 Copy(&t.IpAddress, ip, sizeof(IP));\r
4175 \r
4176                 c = Search(HostCacheList, &t);\r
4177                 if (c != NULL)\r
4178                 {\r
4179                         if (IsEmptyStr(c->HostName) == false)\r
4180                         {\r
4181                                 ret = true;\r
4182                                 StrCpy(hostname, size, c->HostName);\r
4183                         }\r
4184                         else\r
4185                         {\r
4186                                 ret = true;\r
4187                                 StrCpy(hostname, size, "");\r
4188                         }\r
4189                 }\r
4190         }\r
4191         UnlockList(HostCacheList);\r
4192 \r
4193         return ret;\r
4194 }\r
4195 \r
4196 // ホスト名キャッシュへ追加\r
4197 void AddHostCache(IP *ip, char *hostname)\r
4198 {\r
4199         // 引数チェック\r
4200         if (ip == NULL || hostname == NULL)\r
4201         {\r
4202                 return;\r
4203         }\r
4204         if (IsNetworkNameCacheEnabled() == false)\r
4205         {\r
4206                 return;\r
4207         }\r
4208 \r
4209         LockList(HostCacheList);\r
4210         {\r
4211                 HOSTCACHE t, *c;\r
4212                 UINT i;\r
4213                 LIST *o;\r
4214 \r
4215                 Zero(&t, sizeof(t));\r
4216                 Copy(&t.IpAddress, ip, sizeof(IP));\r
4217 \r
4218                 c = Search(HostCacheList, &t);\r
4219                 if (c == NULL)\r
4220                 {\r
4221                         c = ZeroMalloc(sizeof(HOSTCACHE));\r
4222                         Copy(&c->IpAddress, ip, sizeof(IP));\r
4223                         Add(HostCacheList, c);\r
4224                 }\r
4225 \r
4226                 StrCpy(c->HostName, sizeof(c->HostName), hostname);\r
4227                 c->Expires = Tick64() + (UINT64)EXPIRES_HOSTNAME;\r
4228 \r
4229                 o = NewListFast(NULL);\r
4230 \r
4231                 for (i = 0;i < LIST_NUM(HostCacheList);i++)\r
4232                 {\r
4233                         HOSTCACHE *c = LIST_DATA(HostCacheList, i);\r
4234 \r
4235                         if (c->Expires <= Tick64())\r
4236                         {\r
4237                                 Add(o, c);\r
4238                         }\r
4239                 }\r
4240 \r
4241                 for (i = 0;i < LIST_NUM(o);i++)\r
4242                 {\r
4243                         HOSTCACHE *c = LIST_DATA(o, i);\r
4244 \r
4245                         if (Delete(HostCacheList, c))\r
4246                         {\r
4247                                 Free(c);\r
4248                         }\r
4249                 }\r
4250 \r
4251                 ReleaseList(o);\r
4252         }\r
4253         UnlockList(HostCacheList);\r
4254 }\r
4255 \r
4256 // ホスト名キャッシュの比較\r
4257 int CompareHostCache(void *p1, void *p2)\r
4258 {\r
4259         HOSTCACHE *c1, *c2;\r
4260         if (p1 == NULL || p2 == NULL)\r
4261         {\r
4262                 return 0;\r
4263         }\r
4264         c1 = *(HOSTCACHE **)p1;\r
4265         c2 = *(HOSTCACHE **)p2;\r
4266         if (c1 == NULL || c2 == NULL)\r
4267         {\r
4268                 return 0;\r
4269         }\r
4270 \r
4271         return CmpIpAddr(&c1->IpAddress, &c2->IpAddress);\r
4272 }\r
4273 \r
4274 // ホスト名キャッシュの解放\r
4275 void FreeHostCache()\r
4276 {\r
4277         UINT i;\r
4278 \r
4279         for (i = 0;i < LIST_NUM(HostCacheList);i++)\r
4280         {\r
4281                 HOSTCACHE *c = LIST_DATA(HostCacheList, i);\r
4282 \r
4283                 Free(c);\r
4284         }\r
4285 \r
4286         ReleaseList(HostCacheList);\r
4287         HostCacheList = NULL;\r
4288 }\r
4289 \r
4290 // ホスト名キャッシュの初期化\r
4291 void InitHostCache()\r
4292 {\r
4293         HostCacheList = NewList(CompareHostCache);\r
4294 }\r
4295 \r
4296 // スレッドをスレッド待機リストに追加する\r
4297 void AddWaitThread(THREAD *t)\r
4298 {\r
4299         // 引数チェック\r
4300         if (t == NULL)\r
4301         {\r
4302                 return;\r
4303         }\r
4304 \r
4305         AddRef(t->ref);\r
4306 \r
4307         LockList(WaitThreadList);\r
4308         {\r
4309                 Add(WaitThreadList, t);\r
4310         }\r
4311         UnlockList(WaitThreadList);\r
4312 }\r
4313 \r
4314 // スレッドを待機リストから削除する\r
4315 void DelWaitThread(THREAD *t)\r
4316 {\r
4317         // 引数チェック\r
4318         if (t == NULL)\r
4319         {\r
4320                 return;\r
4321         }\r
4322 \r
4323         LockList(WaitThreadList);\r
4324         {\r
4325                 if (Delete(WaitThreadList, t))\r
4326                 {\r
4327                         ReleaseThread(t);\r
4328                 }\r
4329         }\r
4330         UnlockList(WaitThreadList);\r
4331 }\r
4332 \r
4333 // スレッド待機リストの作成\r
4334 void InitWaitThread()\r
4335 {\r
4336         WaitThreadList = NewList(NULL);\r
4337 }\r
4338 \r
4339 // スレッド待機リストの解放\r
4340 void FreeWaitThread()\r
4341 {\r
4342         UINT i, num;\r
4343         THREAD **threads;\r
4344 \r
4345         LockList(WaitThreadList);\r
4346         {\r
4347                 num = LIST_NUM(WaitThreadList);\r
4348                 threads = ToArray(WaitThreadList);\r
4349                 DeleteAll(WaitThreadList);\r
4350         }\r
4351         UnlockList(WaitThreadList);\r
4352 \r
4353         for (i = 0;i < num;i++)\r
4354         {\r
4355                 THREAD *t = threads[i];\r
4356                 WaitThread(t, INFINITE);\r
4357                 ReleaseThread(t);\r
4358         }\r
4359 \r
4360         Free(threads);\r
4361 \r
4362         ReleaseList(WaitThreadList);\r
4363         WaitThreadList = NULL;\r
4364 }\r
4365 \r
4366 // 暗号リスト名をチェックする\r
4367 bool CheckCipherListName(char *name)\r
4368 {\r
4369         UINT i;\r
4370         // 引数チェック\r
4371         if (name == NULL)\r
4372         {\r
4373                 return false;\r
4374         }\r
4375 \r
4376         for (i = 0;i < cipher_list_token->NumTokens;i++)\r
4377         {\r
4378                 if (StrCmpi(cipher_list_token->Token[i], name) == 0)\r
4379                 {\r
4380                         return true;\r
4381                 }\r
4382         }\r
4383 \r
4384         return false;\r
4385 }\r
4386 \r
4387 // DHCP サーバーの IP アドレス更新\r
4388 void RenewDhcp()\r
4389 {\r
4390 #ifdef  OS_WIN32\r
4391         Win32RenewDhcp();\r
4392 #else\r
4393         UnixRenewDhcp();\r
4394 #endif\r
4395 }\r
4396 \r
4397 // UNIX 用ドメイン名を取得\r
4398 bool UnixGetDomainName(char *name, UINT size)\r
4399 {\r
4400         bool ret = false;\r
4401         BUF *b = ReadDump("/etc/resolv.conf");\r
4402 \r
4403         if (b == NULL)\r
4404         {\r
4405                 return false;\r
4406         }\r
4407 \r
4408         while (true)\r
4409         {\r
4410                 char *s = CfgReadNextLine(b);\r
4411                 TOKEN_LIST *t;\r
4412 \r
4413                 if (s == NULL)\r
4414                 {\r
4415                         break;\r
4416                 }\r
4417 \r
4418                 Trim(s);\r
4419 \r
4420                 t = ParseToken(s, " \t");\r
4421                 if (t != NULL)\r
4422                 {\r
4423                         if (t->NumTokens == 2)\r
4424                         {\r
4425                                 if (StrCmpi(t->Token[0], "domain") == 0)\r
4426                                 {\r
4427                                         StrCpy(name, size, t->Token[1]);\r
4428                                         ret = true;\r
4429                                 }\r
4430                         }\r
4431                         FreeToken(t);\r
4432                 }\r
4433 \r
4434                 Free(s);\r
4435         }\r
4436 \r
4437         FreeBuf(b);\r
4438 \r
4439         return ret;\r
4440 }\r
4441 \r
4442 // ドメイン名を取得\r
4443 bool GetDomainName(char *name, UINT size)\r
4444 {\r
4445         bool ret = false;\r
4446         IP ip;\r
4447         // 引数チェック\r
4448         if (name == NULL)\r
4449         {\r
4450                 return false;\r
4451         }\r
4452 \r
4453 #ifdef  OS_WIN32\r
4454         ret = Win32GetDefaultDns(&ip, name, size);\r
4455 #else   // OS_WIN32\r
4456         ret = UnixGetDomainName(name, size);\r
4457 #endif  // OS_WIN32\r
4458 \r
4459         return ret;\r
4460 }\r
4461 \r
4462 // デフォルトの DNS サーバーの取得\r
4463 bool GetDefaultDns(IP *ip)\r
4464 {\r
4465         bool ret = false;\r
4466 #ifdef  OS_WIN32\r
4467         ret = Win32GetDefaultDns(ip, NULL, 0);\r
4468 #else\r
4469         ret = UnixGetDefaultDns(ip);\r
4470 #endif  // OS_WIN32\r
4471         return ret;\r
4472 }\r
4473 \r
4474 // ソケットイベントの作成\r
4475 SOCK_EVENT *NewSockEvent()\r
4476 {\r
4477         SOCK_EVENT *e = NULL;\r
4478 #ifdef  OS_WIN32\r
4479         e = Win32NewSockEvent();\r
4480 #else\r
4481         e = UnixNewSockEvent();\r
4482 #endif  // OS_WIN32\r
4483         return e;\r
4484 }\r
4485 \r
4486 // ソケットイベントのセット\r
4487 void SetSockEvent(SOCK_EVENT *event)\r
4488 {\r
4489 #ifdef  OS_WIN32\r
4490         Win32SetSockEvent(event);\r
4491 #else\r
4492         UnixSetSockEvent(event);\r
4493 #endif  // OS_WIN32\r
4494 }\r
4495 \r
4496 // ソケットイベントのクリーンアップ\r
4497 void CleanupSockEvent(SOCK_EVENT *event)\r
4498 {\r
4499 #ifdef  OS_WIN32\r
4500         Win32CleanupSockEvent(event);\r
4501 #else\r
4502         UnixCleanupSockEvent(event);\r
4503 #endif  // OS_WIN32\r
4504 }\r
4505 \r
4506 // ソケットイベントの待機\r
4507 bool WaitSockEvent(SOCK_EVENT *event, UINT timeout)\r
4508 {\r
4509         bool ret = false;\r
4510 #ifdef  OS_WIN32\r
4511         ret = Win32WaitSockEvent(event, timeout);\r
4512 #else\r
4513         ret = UnixWaitSockEvent(event, timeout);\r
4514 #endif  // OS_WIN32\r
4515         return ret;\r
4516 }\r
4517 \r
4518 // ソケットイベントの解放\r
4519 void ReleaseSockEvent(SOCK_EVENT *event)\r
4520 {\r
4521         // 引数チェック\r
4522         if (event == NULL)\r
4523         {\r
4524                 return;\r
4525         }\r
4526 \r
4527         if (Release(event->ref) == 0)\r
4528         {\r
4529                 CleanupSockEvent(event);\r
4530         }\r
4531 }\r
4532 \r
4533 // ソケットをソケットイベントに所属させる\r
4534 void JoinSockToSockEvent(SOCK *sock, SOCK_EVENT *event)\r
4535 {\r
4536 #ifdef  OS_WIN32\r
4537         Win32JoinSockToSockEvent(sock, event);\r
4538 #else\r
4539         UnixJoinSockToSockEvent(sock, event);\r
4540 #endif  // OS_WIN32\r
4541 }\r
4542 \r
4543 // 新しい特殊キャンセルオブジェクト\r
4544 CANCEL *NewCancelSpecial(void *hEvent)\r
4545 {\r
4546         CANCEL *c;\r
4547         // 引数チェック\r
4548         if (hEvent == NULL)\r
4549         {\r
4550                 return NULL;\r
4551         }\r
4552 \r
4553         c = ZeroMalloc(sizeof(CANCEL));\r
4554         c->ref = NewRef();\r
4555         c->SpecialFlag = true;\r
4556 \r
4557 #ifdef  OS_WIN32\r
4558         c->hEvent = (HANDLE)hEvent;\r
4559 #else   // OS_WIN32\r
4560         c->pipe_read = (int)hEvent;\r
4561         c->pipe_write = -1;\r
4562 #endif  // OS_WIN32\r
4563 \r
4564         return c;\r
4565 }\r
4566 \r
4567 // キャンセルオブジェクトの作成\r
4568 CANCEL *NewCancel()\r
4569 {\r
4570         CANCEL *c = NULL;\r
4571 #ifdef  OS_WIN32\r
4572         c = Win32NewCancel();\r
4573 #else\r
4574         c = UnixNewCancel();\r
4575 #endif  // OS_WIN32\r
4576         return c;\r
4577 }\r
4578 \r
4579 // キャンセルオブジェクトの解放\r
4580 void ReleaseCancel(CANCEL *c)\r
4581 {\r
4582         // 引数チェック\r
4583         if (c == NULL)\r
4584         {\r
4585                 return;\r
4586         }\r
4587 \r
4588         if (Release(c->ref) == 0)\r
4589         {\r
4590                 CleanupCancel(c);\r
4591         }\r
4592 }\r
4593 \r
4594 // キャンセルオブジェクトのクリーンアップ\r
4595 void CleanupCancel(CANCEL *c)\r
4596 {\r
4597 #ifdef  OS_WIN32\r
4598         Win32CleanupCancel(c);\r
4599 #else\r
4600         UnixCleanupCancel(c);\r
4601 #endif\r
4602 }\r
4603 \r
4604 // キャンセル発動\r
4605 void Cancel(CANCEL *c)\r
4606 {\r
4607 #ifdef  OS_WIN32\r
4608         Win32Cancel(c);\r
4609 #else\r
4610         UnixCancel(c);\r
4611 #endif\r
4612 }\r
4613 \r
4614 // 指定されたルーティングテーブルから最適なルートを計算する\r
4615 ROUTE_ENTRY *GetBestRouteEntryFromRouteTable(ROUTE_TABLE *table, IP *ip)\r
4616 {\r
4617         return GetBestRouteEntryFromRouteTableEx(table, ip, 0);\r
4618 }\r
4619 ROUTE_ENTRY *GetBestRouteEntryFromRouteTableEx(ROUTE_TABLE *table, IP *ip, UINT exclude_if_id)\r
4620 {\r
4621         UINT i;\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
4626         // 引数チェック\r
4627         if (ip == NULL || table == NULL)\r
4628         {\r
4629                 return NULL;\r
4630         }\r
4631 \r
4632         if (IsIP6(ip))\r
4633         {\r
4634                 // IPv6 は非サポート\r
4635                 return NULL;\r
4636         }\r
4637 \r
4638         // 対象となるルーティングテーブルのうち、\r
4639         //  第一条件: サブネットマスクが最も大きい\r
4640         //  第二条件: メトリック値が最も小さい\r
4641         // ものを選択する\r
4642         for (i = 0;i < table->NumEntry;i++)\r
4643         {\r
4644                 ROUTE_ENTRY *e = table->Entry[i];\r
4645                 UINT dest, net, mask;\r
4646 \r
4647                 dest = IPToUINT(ip);\r
4648                 net = IPToUINT(&e->DestIP);\r
4649                 mask = IPToUINT(&e->DestMask);\r
4650 \r
4651                 if (exclude_if_id != 0)\r
4652                 {\r
4653                         if (e->InterfaceID == exclude_if_id)\r
4654                         {\r
4655                                 continue;\r
4656                         }\r
4657                 }\r
4658 \r
4659                 // マスクテスト\r
4660                 if ((dest & mask) == (net & mask))\r
4661                 {\r
4662                         // これはルーティングの対象となり得る\r
4663                         if (mask >= max_mask)\r
4664                         {\r
4665                                 max_mask = mask;\r
4666                                 if (min_metric >= e->Metric)\r
4667                                 {\r
4668                                         min_metric = e->Metric;\r
4669                                         tmp = e;\r
4670                                 }\r
4671                         }\r
4672                 }\r
4673         }\r
4674 \r
4675         if (tmp != NULL)\r
4676         {\r
4677                 UINT dest, gateway, mask;\r
4678 \r
4679                 // エントリを生成\r
4680                 ret = ZeroMallocFast(sizeof(ROUTE_ENTRY));\r
4681 \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
4691                 ret->Metric = 1;\r
4692                 ret->PPPConnection = tmp->PPPConnection;\r
4693 \r
4694                 // ルーティング制御関係の計算\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
4699                 {\r
4700 #ifdef  OS_WIN32\r
4701                         if (MsIsVista() == false)\r
4702                         {\r
4703                                 // Windows 用調整\r
4704                                 ret->PPPConnection = true;\r
4705                         }\r
4706 #endif  // OS_WIN32\r
4707                 }\r
4708         }\r
4709 \r
4710         return ret;\r
4711 }\r
4712 \r
4713 // ルーティングエントリを解放する\r
4714 void FreeRouteEntry(ROUTE_ENTRY *e)\r
4715 {\r
4716         // 引数チェック\r
4717         if (e == NULL)\r
4718         {\r
4719                 return;\r
4720         }\r
4721 \r
4722         Free(e);\r
4723 }\r
4724 \r
4725 // 現在のルーティングテーブルを解析して最適なルートエントリを取得する\r
4726 ROUTE_ENTRY *GetBestRouteEntry(IP *ip)\r
4727 {\r
4728         return GetBestRouteEntryEx(ip, 0);\r
4729 }\r
4730 ROUTE_ENTRY *GetBestRouteEntryEx(IP *ip, UINT exclude_if_id)\r
4731 {\r
4732         ROUTE_TABLE *table;\r
4733         ROUTE_ENTRY *e = NULL;\r
4734         // 引数チェック\r
4735         if (ip == NULL)\r
4736         {\r
4737                 return NULL;\r
4738         }\r
4739 \r
4740         table = GetRouteTable();\r
4741         if (table == NULL)\r
4742         {\r
4743                 return NULL;\r
4744         }\r
4745 \r
4746         e = GetBestRouteEntryFromRouteTableEx(table, ip, exclude_if_id);\r
4747         FreeRouteTable(table);\r
4748 \r
4749         return e;\r
4750 }\r
4751 \r
4752 // 仮想 LAN カードのインターフェース ID の取得\r
4753 UINT GetVLanInterfaceID(char *tag_name)\r
4754 {\r
4755         UINT ret = 0;\r
4756 #ifdef  OS_WIN32\r
4757         ret = Win32GetVLanInterfaceID(tag_name);\r
4758 #else   // OS_WIN32\r
4759         ret = UnixGetVLanInterfaceID(tag_name);\r
4760 #endif  // OS_WIN32\r
4761         return ret;\r
4762 }\r
4763 \r
4764 // 仮想 LAN カードの列挙変数の解放\r
4765 void FreeEnumVLan(char **s)\r
4766 {\r
4767         char *a;\r
4768         UINT i;\r
4769         // 引数チェック\r
4770         if (s == NULL)\r
4771         {\r
4772                 return;\r
4773         }\r
4774 \r
4775         i = 0;\r
4776         while (true)\r
4777         {\r
4778                 a = s[i++];\r
4779                 if (a == NULL)\r
4780                 {\r
4781                         break;\r
4782                 }\r
4783                 Free(a);\r
4784         }\r
4785 \r
4786         Free(s);\r
4787 }\r
4788 \r
4789 // 仮想 LAN カードの列挙\r
4790 char **EnumVLan(char *tag_name)\r
4791 {\r
4792         char **ret = NULL;\r
4793 #ifdef  OS_WIN32\r
4794         ret = Win32EnumVLan(tag_name);\r
4795 #else   // OS_WIN32\r
4796         ret = UnixEnumVLan(tag_name);\r
4797 #endif  // OS_WIN32\r
4798         return ret;\r
4799 }\r
4800 \r
4801 // ルーティングテーブルを表示する\r
4802 void DebugPrintRouteTable(ROUTE_TABLE *r)\r
4803 {\r
4804         UINT i;\r
4805         // 引数チェック\r
4806         if (r == NULL)\r
4807         {\r
4808                 return;\r
4809         }\r
4810 \r
4811         if (IsDebug() == false)\r
4812         {\r
4813                 return;\r
4814         }\r
4815 \r
4816         Debug("---- Routing Table (%u Entries) ----\n", r->NumEntry);\r
4817 \r
4818         for (i = 0;i < r->NumEntry;i++)\r
4819         {\r
4820                 Debug("   ");\r
4821 \r
4822                 DebugPrintRoute(r->Entry[i]);\r
4823         }\r
4824 \r
4825         Debug("------------------------------------\n");\r
4826 }\r
4827 \r
4828 // ルーティングテーブルエントリを表示する\r
4829 void DebugPrintRoute(ROUTE_ENTRY *e)\r
4830 {\r
4831         char tmp[MAX_SIZE];\r
4832         // 引数チェック\r
4833         if (e == NULL)\r
4834         {\r
4835                 return;\r
4836         }\r
4837 \r
4838         if (IsDebug() == false)\r
4839         {\r
4840                 return;\r
4841         }\r
4842 \r
4843         RouteToStr(tmp, sizeof(tmp), e);\r
4844 \r
4845         Debug("%s\n", tmp);\r
4846 }\r
4847 \r
4848 // ルーティングテーブルエントリを文字列にする\r
4849 void RouteToStr(char *str, UINT str_size, ROUTE_ENTRY *e)\r
4850 {\r
4851         char dest_ip[MAX_PATH];\r
4852         char dest_mask[MAX_PATH];\r
4853         char gateway_ip[MAX_PATH];\r
4854         // 引数チェック\r
4855         if (str == NULL || e == NULL)\r
4856         {\r
4857                 return;\r
4858         }\r
4859 \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
4863 \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
4868 }\r
4869 \r
4870 // ルーティングテーブルの削除\r
4871 void DeleteRouteEntry(ROUTE_ENTRY *e)\r
4872 {\r
4873         Debug("DeleteRouteEntry();\n");\r
4874 #ifdef  OS_WIN32\r
4875         Win32DeleteRouteEntry(e);\r
4876 #else   // OS_WIN32\r
4877         UnixDeleteRouteEntry(e);\r
4878 #endif\r
4879 }\r
4880 \r
4881 // ルーティングテーブルの追加\r
4882 bool AddRouteEntry(ROUTE_ENTRY *e)\r
4883 {\r
4884         bool dummy = false;\r
4885         return AddRouteEntryEx(e, &dummy);\r
4886 }\r
4887 bool AddRouteEntryEx(ROUTE_ENTRY *e, bool *already_exists)\r
4888 {\r
4889         bool ret = false;\r
4890         Debug("AddRouteEntryEx();\n");\r
4891 #ifdef  OS_WIN32\r
4892         ret = Win32AddRouteEntry(e, already_exists);\r
4893 #else   // OS_WIN32\r
4894         ret = UnixAddRouteEntry(e, already_exists);\r
4895 #endif\r
4896         return ret;\r
4897 }\r
4898 \r
4899 // ルーティングテーブルの取得\r
4900 ROUTE_TABLE *GetRouteTable()\r
4901 {\r
4902         ROUTE_TABLE *t = NULL;\r
4903         UINT i;\r
4904         BUF *buf = NewBuf();\r
4905         UCHAR hash[MD5_SIZE];\r
4906 \r
4907 #ifdef  OS_WIN32\r
4908         t = Win32GetRouteTable();\r
4909 #else   //OS_WIN32\r
4910         t = UnixGetRouteTable();\r
4911 #endif  // OS_WIN32\r
4912 \r
4913         WriteBuf(buf, &t->NumEntry, sizeof(t->NumEntry));\r
4914 \r
4915         for (i = 0;i < t->NumEntry;i++)\r
4916         {\r
4917                 ROUTE_ENTRY *e = t->Entry[i];\r
4918 \r
4919                 WriteBuf(buf, e, sizeof(ROUTE_ENTRY));\r
4920         }\r
4921 \r
4922         Hash(hash, buf->Buf, buf->Size, false);\r
4923 \r
4924         FreeBuf(buf);\r
4925 \r
4926         Copy(&t->HashedValue, hash, sizeof(t->HashedValue));\r
4927 \r
4928         return t;\r
4929 }\r
4930 \r
4931 // ルーティングテーブルの解放\r
4932 void FreeRouteTable(ROUTE_TABLE *t)\r
4933 {\r
4934         UINT i;\r
4935         // 引数チェック\r
4936         if (t == NULL)\r
4937         {\r
4938                 return;\r
4939         }\r
4940 \r
4941         for (i = 0;i < t->NumEntry;i++)\r
4942         {\r
4943                 Free(t->Entry[i]);\r
4944         }\r
4945         Free(t->Entry);\r
4946         Free(t);\r
4947 }\r
4948 \r
4949 // UDP 受信\r
4950 UINT RecvFrom(SOCK *sock, IP *src_addr, UINT *src_port, void *data, UINT size)\r
4951 {\r
4952         SOCKET s;\r
4953         int ret, sz;\r
4954         struct sockaddr_in addr;\r
4955         // 引数チェック\r
4956         if (sock == NULL || src_addr == NULL || src_port == NULL || data == NULL)\r
4957         {\r
4958                 return false;\r
4959         }\r
4960         if (sock->Type != SOCK_UDP || sock->socket == INVALID_SOCKET)\r
4961         {\r
4962                 return false;\r
4963         }\r
4964         if (size == 0)\r
4965         {\r
4966                 return false;\r
4967         }\r
4968 \r
4969         if (sock->IPv6)\r
4970         {\r
4971                 return RecvFrom6(sock, src_addr, src_port, data, size);\r
4972         }\r
4973 \r
4974         s = sock->socket;\r
4975 \r
4976         sz = sizeof(addr);\r
4977         ret = recvfrom(s, data, size, 0, (struct sockaddr *)&addr, (int *)&sz);\r
4978         if (ret > 0)\r
4979         {\r
4980                 InAddrToIP(src_addr, &addr.sin_addr);\r
4981                 *src_port = (UINT)ntohs(addr.sin_port);\r
4982 \r
4983                 Lock(sock->lock);\r
4984                 {\r
4985                         sock->RecvNum++;\r
4986                         sock->RecvSize += (UINT64)ret;\r
4987                 }\r
4988                 Unlock(sock->lock);\r
4989 \r
4990                 // Debug("UDP RecvFrom: %u\n", ret);\r
4991 \r
4992                 return (UINT)ret;\r
4993         }\r
4994         else\r
4995         {\r
4996                 sock->IgnoreRecvErr = false;\r
4997 \r
4998 #ifdef  OS_WIN32\r
4999                 if (WSAGetLastError() == WSAECONNRESET)\r
5000                 {\r
5001                         sock->IgnoreRecvErr = true;\r
5002                 }\r
5003                 else if (WSAGetLastError() == WSAEWOULDBLOCK)\r
5004                 {\r
5005                         return SOCK_LATER;\r
5006                 }\r
5007                 else\r
5008                 {\r
5009                         UINT e = WSAGetLastError();\r
5010 //                      Debug("RecvFrom Error: %u\n", e);\r
5011                 }\r
5012 #else   // OS_WIN32\r
5013                 if (errno == ECONNREFUSED || errno == ECONNRESET)\r
5014                 {\r
5015                         sock->IgnoreRecvErr = true;\r
5016                 }\r
5017                 else if (errno == EAGAIN)\r
5018                 {\r
5019                         return SOCK_LATER;\r
5020                 }\r
5021 #endif  // OS_WIN32\r
5022                 return 0;\r
5023         }\r
5024 }\r
5025 UINT RecvFrom6(SOCK *sock, IP *src_addr, UINT *src_port, void *data, UINT size)\r
5026 {\r
5027         SOCKET s;\r
5028         int ret, sz;\r
5029         struct sockaddr_in6 addr;\r
5030         // 引数チェック\r
5031         if (sock == NULL || src_addr == NULL || src_port == NULL || data == NULL)\r
5032         {\r
5033                 return false;\r
5034         }\r
5035         if (sock->Type != SOCK_UDP || sock->socket == INVALID_SOCKET)\r
5036         {\r
5037                 return false;\r
5038         }\r
5039         if (size == 0)\r
5040         {\r
5041                 return false;\r
5042         }\r
5043 \r
5044         s = sock->socket;\r
5045 \r
5046         sz = sizeof(addr);\r
5047         ret = recvfrom(s, data, size, 0, (struct sockaddr *)&addr, (int *)&sz);\r
5048         if (ret > 0)\r
5049         {\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
5053 \r
5054                 Lock(sock->lock);\r
5055                 {\r
5056                         sock->RecvNum++;\r
5057                         sock->RecvSize += (UINT64)ret;\r
5058                 }\r
5059                 Unlock(sock->lock);\r
5060 \r
5061                 // Debug("UDP RecvFrom: %u\n", ret);\r
5062 \r
5063                 return (UINT)ret;\r
5064         }\r
5065         else\r
5066         {\r
5067                 sock->IgnoreRecvErr = false;\r
5068 \r
5069 #ifdef  OS_WIN32\r
5070                 if (WSAGetLastError() == WSAECONNRESET)\r
5071                 {\r
5072                         sock->IgnoreRecvErr = true;\r
5073                 }\r
5074                 else if (WSAGetLastError() == WSAEWOULDBLOCK)\r
5075                 {\r
5076                         return SOCK_LATER;\r
5077                 }\r
5078                 else\r
5079                 {\r
5080                         UINT e = WSAGetLastError();\r
5081                         //                      Debug("RecvFrom Error: %u\n", e);\r
5082                 }\r
5083 #else   // OS_WIN32\r
5084                 if (errno == ECONNREFUSED || errno == ECONNRESET)\r
5085                 {\r
5086                         sock->IgnoreRecvErr = true;\r
5087                 }\r
5088                 else if (errno == EAGAIN)\r
5089                 {\r
5090                         return SOCK_LATER;\r
5091                 }\r
5092 #endif  // OS_WIN32\r
5093                 return 0;\r
5094         }\r
5095 }\r
5096 \r
5097 // OpenSSL のロック\r
5098 void LockOpenSSL()\r
5099 {\r
5100         Lock(openssl_lock);\r
5101 }\r
5102 \r
5103 // OpenSSL のロック解除\r
5104 void UnlockOpenSSL()\r
5105 {\r
5106         Unlock(openssl_lock);\r
5107 }\r
5108 \r
5109 \r
5110 // UDP 送信\r
5111 UINT SendTo(SOCK *sock, IP *dest_addr, UINT dest_port, void *data, UINT size)\r
5112 {\r
5113         SOCKET s;\r
5114         int ret;\r
5115         struct sockaddr_in addr;\r
5116         // 引数チェック\r
5117         if (sock == NULL || dest_addr == NULL || dest_port == 0 || data == NULL)\r
5118         {\r
5119                 return 0;\r
5120         }\r
5121         if (dest_port >= 65536)\r
5122         {\r
5123                 return 0;\r
5124         }\r
5125         if (sock->Type != SOCK_UDP || sock->socket == INVALID_SOCKET)\r
5126         {\r
5127                 return 0;\r
5128         }\r
5129         if (size == 0)\r
5130         {\r
5131                 return 0;\r
5132         }\r
5133 \r
5134         if (sock->IPv6)\r
5135         {\r
5136                 return SendTo6(sock, dest_addr, dest_port, data, size);\r
5137         }\r
5138 \r
5139         if (IsIP4(dest_addr) == false)\r
5140         {\r
5141                 return 0;\r
5142         }\r
5143 \r
5144         s = sock->socket;\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
5149 \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
5152         {\r
5153                 if (sock->UdpBroadcast == false)\r
5154                 {\r
5155                         bool yes = true;\r
5156 \r
5157                         sock->UdpBroadcast = true;\r
5158 \r
5159                         setsockopt(s, SOL_SOCKET, SO_BROADCAST, (char *)&yes, sizeof(yes));\r
5160                 }\r
5161         }\r
5162 \r
5163         ret = sendto(s, data, size, 0, (struct sockaddr *)&addr, sizeof(addr));\r
5164         if (ret != (int)size)\r
5165         {\r
5166                 sock->IgnoreSendErr = false;\r
5167 \r
5168 #ifdef  OS_WIN32\r
5169                 if (WSAGetLastError() == WSAECONNRESET)\r
5170                 {\r
5171                         sock->IgnoreSendErr = true;\r
5172                 }\r
5173                 else if (WSAGetLastError() == WSAEWOULDBLOCK)\r
5174                 {\r
5175                         return SOCK_LATER;\r
5176                 }\r
5177                 else\r
5178                 {\r
5179                         UINT e = WSAGetLastError();\r
5180                 }\r
5181 #else   // OS_WIN32\r
5182                 if (errno == ECONNREFUSED || errno == ECONNRESET)\r
5183                 {\r
5184                         sock->IgnoreRecvErr = true;\r
5185                 }\r
5186                 else if (errno == EAGAIN)\r
5187                 {\r
5188                         return SOCK_LATER;\r
5189                 }\r
5190 #endif  // OS_WIN32\r
5191                 return 0;\r
5192         }\r
5193 \r
5194         Lock(sock->lock);\r
5195         {\r
5196                 sock->SendSize += (UINT64)size;\r
5197                 sock->SendNum++;\r
5198         }\r
5199         Unlock(sock->lock);\r
5200 \r
5201         return ret;\r
5202 }\r
5203 UINT SendTo6(SOCK *sock, IP *dest_addr, UINT dest_port, void *data, UINT size)\r
5204 {\r
5205         SOCKET s;\r
5206         int ret;\r
5207         struct sockaddr_in6 addr;\r
5208         UINT type;\r
5209         // 引数チェック\r
5210         if (sock == NULL || dest_addr == NULL || dest_port == 0 || data == NULL)\r
5211         {\r
5212                 return 0;\r
5213         }\r
5214         if (dest_port >= 65536)\r
5215         {\r
5216                 return 0;\r
5217         }\r
5218         if (sock->Type != SOCK_UDP || sock->socket == INVALID_SOCKET)\r
5219         {\r
5220                 return 0;\r
5221         }\r
5222         if (size == 0)\r
5223         {\r
5224                 return 0;\r
5225         }\r
5226 \r
5227         if (IsIP6(dest_addr) == false)\r
5228         {\r
5229                 return 0;\r
5230         }\r
5231 \r
5232         s = sock->socket;\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
5238 \r
5239         type = GetIPAddrType6(dest_addr);\r
5240 \r
5241         if (type & IPV6_ADDR_MULTICAST)\r
5242         {\r
5243                 if (sock->UdpBroadcast == false)\r
5244                 {\r
5245                         bool yes = true;\r
5246 \r
5247                         sock->UdpBroadcast = true;\r
5248 \r
5249                         setsockopt(s, SOL_SOCKET, SO_BROADCAST, (char *)&yes, sizeof(yes));\r
5250                 }\r
5251         }\r
5252 \r
5253         ret = sendto(s, data, size, 0, (struct sockaddr *)&addr, sizeof(addr));\r
5254         if (ret != (int)size)\r
5255         {\r
5256                 sock->IgnoreSendErr = false;\r
5257 \r
5258 #ifdef  OS_WIN32\r
5259                 if (WSAGetLastError() == WSAECONNRESET)\r
5260                 {\r
5261                         sock->IgnoreSendErr = true;\r
5262                 }\r
5263                 else if (WSAGetLastError() == WSAEWOULDBLOCK)\r
5264                 {\r
5265                         return SOCK_LATER;\r
5266                 }\r
5267                 else\r
5268                 {\r
5269                         UINT e = WSAGetLastError();\r
5270                 }\r
5271 #else   // OS_WIN32\r
5272                 if (errno == ECONNREFUSED || errno == ECONNRESET)\r
5273                 {\r
5274                         sock->IgnoreRecvErr = true;\r
5275                 }\r
5276                 else if (errno == EAGAIN)\r
5277                 {\r
5278                         return SOCK_LATER;\r
5279                 }\r
5280 #endif  // OS_WIN32\r
5281                 return 0;\r
5282         }\r
5283 \r
5284         Lock(sock->lock);\r
5285         {\r
5286                 sock->SendSize += (UINT64)size;\r
5287                 sock->SendNum++;\r
5288         }\r
5289         Unlock(sock->lock);\r
5290 \r
5291         return ret;\r
5292 }\r
5293 \r
5294 // UDP ソケットの作成と初期化\r
5295 // port が 0 の場合は OS がランダムに割り当てる\r
5296 SOCK *NewUDP(UINT port)\r
5297 {\r
5298         return NewUDPEx(port, false);\r
5299 }\r
5300 SOCK *NewUDPEx(UINT port, bool ipv6)\r
5301 {\r
5302         if (ipv6 == false)\r
5303         {\r
5304                 return NewUDP4(port);\r
5305         }\r
5306         else\r
5307         {\r
5308                 return NewUDP6(port);\r
5309         }\r
5310 }\r
5311 SOCK *NewUDP4(UINT port)\r
5312 {\r
5313         SOCK *sock;\r
5314         SOCKET s;\r
5315         struct sockaddr_in addr;\r
5316 \r
5317         s = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);\r
5318         if (s == INVALID_SOCKET)\r
5319         {\r
5320                 return NULL;\r
5321         }\r
5322 \r
5323         Zero(&addr, sizeof(addr));\r
5324         addr.sin_family = AF_INET;\r
5325         addr.sin_addr.s_addr = htonl(INADDR_ANY);\r
5326         if (port == 0)\r
5327         {\r
5328                 addr.sin_port = 0;\r
5329         }\r
5330         else\r
5331         {\r
5332                 addr.sin_port = htons((USHORT)port);\r
5333         }\r
5334 \r
5335         if (bind(s, (struct sockaddr *)&addr, sizeof(addr)) != 0)\r
5336         {\r
5337                 // 失敗\r
5338                 closesocket(s);\r
5339                 return NULL;\r
5340         }\r
5341 \r
5342         sock = NewSock();\r
5343 \r
5344         sock->Type = SOCK_UDP;\r
5345         sock->Connected = false;\r
5346         sock->AsyncMode = false;\r
5347         sock->ServerMode = false;\r
5348         if (port != 0)\r
5349         {\r
5350                 sock->ServerMode = true;\r
5351         }\r
5352 \r
5353         sock->socket = s;\r
5354 \r
5355         QuerySocketInformation(sock);\r
5356 \r
5357         return sock;\r
5358 }\r
5359 SOCK *NewUDP6(UINT port)\r
5360 {\r
5361         SOCK *sock;\r
5362         SOCKET s;\r
5363         struct sockaddr_in6 addr;\r
5364 \r
5365         s = socket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP);\r
5366         if (s == INVALID_SOCKET)\r
5367         {\r
5368                 return NULL;\r
5369         }\r
5370 \r
5371         Zero(&addr, sizeof(addr));\r
5372         addr.sin6_family = AF_INET6;\r
5373         if (port == 0)\r
5374         {\r
5375                 addr.sin6_port = 0;\r
5376         }\r
5377         else\r
5378         {\r
5379                 addr.sin6_port = htons((USHORT)port);\r
5380         }\r
5381 \r
5382         if (bind(s, (struct sockaddr *)&addr, sizeof(addr)) != 0)\r
5383         {\r
5384                 // 失敗\r
5385                 closesocket(s);\r
5386                 return NULL;\r
5387         }\r
5388 \r
5389         sock = NewSock();\r
5390 \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
5396         if (port != 0)\r
5397         {\r
5398                 sock->ServerMode = true;\r
5399         }\r
5400 \r
5401         sock->socket = s;\r
5402 \r
5403         QuerySocketInformation(sock);\r
5404 \r
5405         return sock;\r
5406 }\r
5407 \r
5408 // Select 関数\r
5409 void Select(SOCKSET *set, UINT timeout, CANCEL *c1, CANCEL *c2)\r
5410 {\r
5411 #ifdef  OS_WIN32\r
5412         Win32Select(set, timeout, c1, c2);\r
5413 #else\r
5414         UnixSelect(set, timeout, c1, c2);\r
5415 #endif  // OS_WIN32\r
5416 }\r
5417 \r
5418 // ソケットセットにソケットを追加\r
5419 void AddSockSet(SOCKSET *set, SOCK *sock)\r
5420 {\r
5421         // 引数チェック\r
5422         if (set == NULL || sock == NULL)\r
5423         {\r
5424                 return;\r
5425         }\r
5426         if (sock->Type == SOCK_TCP && sock->Connected == false)\r
5427         {\r
5428                 return;\r
5429         }\r
5430 \r
5431         if (set->NumSocket >= MAX_SOCKSET_NUM)\r
5432         {\r
5433                 // 上限\r
5434                 return;\r
5435         }\r
5436         set->Sock[set->NumSocket++] = sock;\r
5437 }\r
5438 \r
5439 // ソケットセットの初期化\r
5440 void InitSockSet(SOCKSET *set)\r
5441 {\r
5442         // 引数チェック\r
5443         if (set == NULL)\r
5444         {\r
5445                 return;\r
5446         }\r
5447 \r
5448         Zero(set, sizeof(SOCKSET));\r
5449 }\r
5450 \r
5451 // TCP すべて受信\r
5452 bool RecvAll(SOCK *sock, void *data, UINT size, bool secure)\r
5453 {\r
5454         UINT recv_size, sz, ret;\r
5455         // 引数チェック\r
5456         if (sock == NULL || data == NULL)\r
5457         {\r
5458                 return false;\r
5459         }\r
5460         if (size == 0)\r
5461         {\r
5462                 return true;\r
5463         }\r
5464         if (sock->AsyncMode)\r
5465         {\r
5466                 return false;\r
5467         }\r
5468 \r
5469         recv_size = 0;\r
5470 \r
5471         while (true)\r
5472         {\r
5473                 sz = size - recv_size;\r
5474                 ret = Recv(sock, (UCHAR *)data + recv_size, sz, secure);\r
5475                 if (ret == 0)\r
5476                 {\r
5477                         return false;\r
5478                 }\r
5479                 recv_size += ret;\r
5480                 if (recv_size >= size)\r
5481                 {\r
5482                         return true;\r
5483                 }\r
5484         }\r
5485 }\r
5486 \r
5487 // TCP 送信バッファを送信する\r
5488 bool SendNow(SOCK *sock, int secure)\r
5489 {\r
5490         bool ret;\r
5491         // 引数チェック\r
5492         if (sock == NULL || sock->AsyncMode != false)\r
5493         {\r
5494                 return false;\r
5495         }\r
5496         if (sock->SendBuf->Size == 0)\r
5497         {\r
5498                 return true;\r
5499         }\r
5500 \r
5501         ret = SendAll(sock, sock->SendBuf->Buf, sock->SendBuf->Size, secure);\r
5502         ClearBuf(sock->SendBuf);\r
5503 \r
5504         return ret;\r
5505 }\r
5506 \r
5507 // TCP 送信バッファ追加\r
5508 void SendAdd(SOCK *sock, void *data, UINT size)\r
5509 {\r
5510         // 引数チェック\r
5511         if (sock == NULL || data == NULL || size == 0 || sock->AsyncMode != false)\r
5512         {\r
5513                 return;\r
5514         }\r
5515 \r
5516         WriteBuf(sock->SendBuf, data, size);\r
5517 }\r
5518 \r
5519 // TCP すべて送信\r
5520 bool SendAll(SOCK *sock, void *data, UINT size, bool secure)\r
5521 {\r
5522         UCHAR *buf;\r
5523         UINT sent_size;\r
5524         UINT ret;\r
5525         // 引数チェック\r
5526         if (sock == NULL || data == NULL)\r
5527         {\r
5528                 return false;\r
5529         }\r
5530         if (sock->AsyncMode)\r
5531         {\r
5532                 return false;\r
5533         }\r
5534         if (size == 0)\r
5535         {\r
5536                 return true;\r
5537         }\r
5538 \r
5539         buf = (UCHAR *)data;\r
5540         sent_size = 0;\r
5541 \r
5542         while (true)\r
5543         {\r
5544                 ret = Send(sock, buf, size - sent_size, secure);\r
5545                 if (ret == 0)\r
5546                 {\r
5547                         return false;\r
5548                 }\r
5549                 sent_size += ret;\r
5550                 buf += ret;\r
5551                 if (sent_size >= size)\r
5552                 {\r
5553                         return true;\r
5554                 }\r
5555         }\r
5556 }\r
5557 \r
5558 // 使用したい暗号化アルゴリズム名を設定する\r
5559 void SetWantToUseCipher(SOCK *sock, char *name)\r
5560 {\r
5561         // 引数チェック\r
5562         if (sock == NULL || name == NULL)\r
5563         {\r
5564                 return;\r
5565         }\r
5566 \r
5567         if (sock->WaitToUseCipher)\r
5568         {\r
5569                 Free(sock->WaitToUseCipher);\r
5570         }\r
5571         sock->WaitToUseCipher = CopyStr(name);\r
5572 }\r
5573 \r
5574 // TCP-SSL 通信を開始する\r
5575 bool StartSSL(SOCK *sock, X *x, K *priv)\r
5576 {\r
5577         return StartSSLEx(sock, x, priv, false);\r
5578 }\r
5579 bool StartSSLEx(SOCK *sock, X *x, K *priv, bool client_tls)\r
5580 {\r
5581         X509 *x509;\r
5582         EVP_PKEY *key;\r
5583         UINT prev_timeout = 1024;\r
5584 \r
5585 #ifdef UNIX_SOLARIS\r
5586         SOCKET_TIMEOUT_PARAM *ttparam;\r
5587 #endif //UNIX_SOLARIS\r
5588 \r
5589         // 引数チェック\r
5590         if (sock == NULL)\r
5591         {\r
5592                 Debug("StartSSL Error: #0\n");\r
5593                 return false;\r
5594         }\r
5595         if (sock->Connected == false || sock->socket == INVALID_SOCKET ||\r
5596                 sock->ListenMode != false)\r
5597         {\r
5598                 Debug("StartSSL Error: #1\n");\r
5599                 return false;\r
5600         }\r
5601         if (x != NULL && priv == NULL)\r
5602         {\r
5603                 Debug("StartSSL Error: #2\n");\r
5604                 return false;\r
5605         }\r
5606 \r
5607         if (sock->SecureMode)\r
5608         {\r
5609                 Debug("StartSSL Error: #3\n");\r
5610                 // すでに SSL 通信が開始されている\r
5611                 return true;\r
5612         }\r
5613 \r
5614         Lock(sock->ssl_lock);\r
5615         if (sock->SecureMode)\r
5616         {\r
5617                 Debug("StartSSL Error: #4\n");\r
5618                 // すでに SSL 通信が開始されている\r
5619                 Unlock(sock->ssl_lock);\r
5620                 return true;\r
5621         }\r
5622 \r
5623         Lock(openssl_lock);\r
5624         {\r
5625                 if (sock->ServerMode)\r
5626                 {\r
5627                         SSL_CTX_set_ssl_version(ssl_ctx, SSLv23_method());\r
5628                 }\r
5629                 else\r
5630                 {\r
5631                         if (client_tls == false)\r
5632                         {\r
5633                                 SSL_CTX_set_ssl_version(ssl_ctx, SSLv3_method());\r
5634                         }\r
5635                         else\r
5636                         {\r
5637                                 SSL_CTX_set_ssl_version(ssl_ctx, TLSv1_client_method());\r
5638                         }\r
5639                 }\r
5640                 sock->ssl = SSL_new(ssl_ctx);\r
5641                 SSL_set_fd(sock->ssl, (int)sock->socket);\r
5642         }\r
5643         Unlock(openssl_lock);\r
5644 \r
5645         if (x != NULL)\r
5646         {\r
5647                 // 証明書と秘密鍵のチェック\r
5648                 if (CheckXandK(x, priv))\r
5649                 {\r
5650                         // 証明書を使用する\r
5651                         x509 = x->x509;\r
5652                         key = priv->pkey;\r
5653 \r
5654                         Lock(openssl_lock);\r
5655                         {\r
5656                                 SSL_use_certificate(sock->ssl, x509);\r
5657                                 SSL_use_PrivateKey(sock->ssl, key);\r
5658                         }\r
5659                         Unlock(openssl_lock);\r
5660                 }\r
5661         }\r
5662 \r
5663         if (sock->WaitToUseCipher != NULL)\r
5664         {\r
5665                 // 使用したい暗号化アルゴリズム名を設定する\r
5666                 Lock(openssl_lock);\r
5667                 {\r
5668                         SSL_set_cipher_list(sock->ssl, sock->WaitToUseCipher);\r
5669                 }\r
5670                 Unlock(openssl_lock);\r
5671         }\r
5672 \r
5673         if (sock->ServerMode)\r
5674         {\r
5675 //              Lock(ssl_connect_lock);\r
5676 \r
5677 // SOLARIS用タイムアウトスレッドの起動\r
5678 #ifdef UNIX_SOLARIS\r
5679                 ttparam = NewSocketTimeout(sock);\r
5680 #endif // UNIX_SOLARIS\r
5681 \r
5682                 // サーバーモード\r
5683                 if (SSL_accept(sock->ssl) <= 0)\r
5684                 {\r
5685 \r
5686 // タイムアウトスレッドの停止\r
5687 #ifdef UNIX_SOLARIS\r
5688                         FreeSocketTimeout(ttparam);\r
5689 #endif // UNIX_SOLARIS\r
5690 \r
5691                         //                      Unlock(ssl_connect_lock);\r
5692                         // SSL-Accept 失敗\r
5693                         Lock(openssl_lock);\r
5694                         {\r
5695                                 SSL_free(sock->ssl);\r
5696                         }\r
5697                         Unlock(openssl_lock);\r
5698 \r
5699                         Unlock(sock->ssl_lock);\r
5700                         Debug("StartSSL Error: #5\n");\r
5701                         return false;\r
5702                 }\r
5703 \r
5704 // タイムアウトスレッドの停止\r
5705 #ifdef UNIX_SOLARIS\r
5706                 FreeSocketTimeout(ttparam);\r
5707 #endif // UNIX_SOLARIS\r
5708 \r
5709                 //              Unlock(ssl_connect_lock);\r
5710         }\r
5711         else\r
5712         {\r
5713                 prev_timeout = GetTimeout(sock);\r
5714                 SetTimeout(sock, TIMEOUT_SSL_CONNECT);\r
5715                 Lock(ssl_connect_lock);\r
5716                 // クライアントモード\r
5717                 if (SSL_connect(sock->ssl) <= 0)\r
5718                 {\r
5719                         Unlock(ssl_connect_lock);\r
5720                         // SSL-connect 失敗\r
5721                         Lock(openssl_lock);\r
5722                         {\r
5723                                 SSL_free(sock->ssl);\r
5724                         }\r
5725                         Unlock(openssl_lock);\r
5726 \r
5727                         Unlock(sock->ssl_lock);\r
5728                         Debug("StartSSL Error: #5\n");\r
5729                         SetTimeout(sock, prev_timeout);\r
5730                         return false;\r
5731                 }\r
5732                 Unlock(ssl_connect_lock);\r
5733                 SetTimeout(sock, prev_timeout);\r
5734         }\r
5735 \r
5736         // SSL 通信が開始された\r
5737         sock->SecureMode = true;\r
5738 \r
5739         // リモートホストの証明書を取得する\r
5740         Lock(openssl_lock);\r
5741         {\r
5742                 x509 = SSL_get_peer_certificate(sock->ssl);\r
5743         }\r
5744         Unlock(openssl_lock);\r
5745 \r
5746         if (x509 == NULL)\r
5747         {\r
5748                 // リモートホストに証明書は存在しない\r
5749                 sock->RemoteX = NULL;\r
5750         }\r
5751         else\r
5752         {\r
5753                 // 証明書を取得できた\r
5754                 sock->RemoteX = X509ToX(x509);\r
5755         }\r
5756 \r
5757         // ローカルホストの証明書を取得する\r
5758         Lock(openssl_lock);\r
5759         {\r
5760                 x509 = SSL_get_certificate(sock->ssl);\r
5761         }\r
5762         Unlock(openssl_lock);\r
5763 \r
5764         if (x509 == NULL)\r
5765         {\r
5766                 // リモートホストに証明書は存在しない\r
5767                 sock->LocalX = NULL;\r
5768         }\r
5769         else\r
5770         {\r
5771                 X *local_x;\r
5772                 // 証明書を取得できた\r
5773                 local_x = X509ToX(x509);\r
5774                 local_x->do_not_free = true;\r
5775                 sock->LocalX = CloneX(local_x);\r
5776                 FreeX(local_x);\r
5777         }\r
5778 \r
5779         // 自動再試行モード\r
5780         SSL_set_mode(sock->ssl, SSL_MODE_AUTO_RETRY);\r
5781 \r
5782         // へんなフラグ\r
5783         SSL_set_mode(sock->ssl, SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER);\r
5784 \r
5785         // 暗号化に使用しているアルゴリズム名を取得\r
5786         Lock(openssl_lock);\r
5787         {\r
5788                 sock->CipherName = CopyStr((char *)SSL_get_cipher(sock->ssl));\r
5789         }\r
5790         Unlock(openssl_lock);\r
5791 \r
5792         Unlock(sock->ssl_lock);\r
5793 \r
5794         return true;\r
5795 }\r
5796 \r
5797 // TCP-SSL 受信\r
5798 UINT SecureRecv(SOCK *sock, void *data, UINT size)\r
5799 {\r
5800         SOCKET s;\r
5801         int ret, e = 0;\r
5802         SSL *ssl;\r
5803 \r
5804 #ifdef UNIX_SOLARIS\r
5805         SOCKET_TIMEOUT_PARAM *ttparam;\r
5806 #endif //UNIX_SOLARIS\r
5807 \r
5808         s = sock->socket;\r
5809         ssl = sock->ssl;\r
5810 \r
5811         if (sock->AsyncMode)\r
5812         {\r
5813                 // 非同期モードの場合はデータが 1 バイトでも読み出し可能かどうか確認する。\r
5814                 // 読み出し可能なデータが無い場合に read をしてしまうとブロッキングするため\r
5815                 // それは避けなければならない。\r
5816                 char c;\r
5817                 Lock(sock->ssl_lock);\r
5818                 {\r
5819                         if (sock->Connected == false)\r
5820                         {\r
5821                                 Unlock(sock->ssl_lock);\r
5822                                 Debug("%s %u SecureRecv() Disconnect\n", __FILE__, __LINE__);\r
5823                                 return 0;\r
5824                         }\r
5825                         ret = SSL_peek(ssl, &c, sizeof(c));\r
5826                 }\r
5827                 Unlock(sock->ssl_lock);\r
5828                 if (ret == 0)\r
5829                 {\r
5830                         // 通信が切れておる\r
5831                         Disconnect(sock);\r
5832                         Debug("%s %u SecureRecv() Disconnect\n", __FILE__, __LINE__);\r
5833                         return 0;\r
5834                 }\r
5835                 if (ret < 0)\r
5836                 {\r
5837                         // エラーが発生した\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
5840                         {\r
5841                                 // パケットがまだ届いていない、つまり read してはいけない\r
5842                                 return SOCK_LATER;\r
5843                         }\r
5844                 }\r
5845         }\r
5846 \r
5847         // 受信する\r
5848         Lock(sock->ssl_lock);\r
5849         {\r
5850                 if (sock->Connected == false)\r
5851                 {\r
5852                         Unlock(sock->ssl_lock);\r
5853                         Debug("%s %u SecureRecv() Disconnect\n", __FILE__, __LINE__);\r
5854                         return 0;\r
5855                 }\r
5856 \r
5857 #ifdef  OS_UNIX\r
5858                 if (sock->AsyncMode == false)\r
5859                 {\r
5860                         sock->CallingThread = pthread_self();\r
5861                 }\r
5862 #endif  // OS_UNIX\r
5863 \r
5864 // SOLARIS用タイムアウトスレッドの起動\r
5865 #ifdef UNIX_SOLARIS\r
5866                 ttparam = NewSocketTimeout(sock);\r
5867 #endif // UNIX_SOLARIS\r
5868 \r
5869                 ret = SSL_read(ssl, data, size);\r
5870 \r
5871 // タイムアウトスレッドの停止\r
5872 #ifdef UNIX_SOLARIS\r
5873                 FreeSocketTimeout(ttparam);\r
5874 #endif // UNIX_SOLARIS\r
5875 \r
5876 \r
5877 #ifdef  OS_UNIX\r
5878                 if (sock->AsyncMode == false)\r
5879                 {\r
5880                         sock->CallingThread = 0;\r
5881                 }\r
5882 #endif  // OS_UNIX\r
5883 \r
5884                 if (ret < 0)\r
5885                 {\r
5886                         e = SSL_get_error(ssl, ret);\r
5887                 }\r
5888 \r
5889         }\r
5890         Unlock(sock->ssl_lock);\r
5891         if (ret > 0)\r
5892         {\r
5893                 // 受信成功\r
5894                 sock->RecvSize += (UINT64)ret;\r
5895                 sock->RecvNum++;\r
5896                 return (UINT)ret;\r
5897         }\r
5898         if (ret == 0)\r
5899         {\r
5900                 // 通信切断\r
5901                 Disconnect(sock);\r
5902                 Debug("%s %u SecureRecv() Disconnect\n", __FILE__, __LINE__);\r
5903                 return 0;\r
5904         }\r
5905         if (sock->AsyncMode)\r
5906         {\r
5907                 if (e == SSL_ERROR_WANT_READ || e == SSL_ERROR_WANT_WRITE || e == SSL_ERROR_SSL)\r
5908                 {\r
5909                         // パケットがまだ届いていない\r
5910                         return SOCK_LATER;\r
5911                 }\r
5912         }\r
5913         Disconnect(sock);\r
5914         Debug("%s %u SecureRecv() Disconnect\n", __FILE__, __LINE__);\r
5915         return 0;\r
5916 }\r
5917 \r
5918 // TCP-SSL 送信\r
5919 UINT SecureSend(SOCK *sock, void *data, UINT size)\r
5920 {\r
5921         SOCKET s;\r
5922         int ret, e;\r
5923         SSL *ssl;\r
5924         s = sock->socket;\r
5925         ssl = sock->ssl;\r
5926 \r
5927         if (sock->AsyncMode)\r
5928         {\r
5929                 // 非同期モード\r
5930                 SSL_set_mode(ssl, SSL_MODE_ENABLE_PARTIAL_WRITE);\r
5931         }\r
5932 \r
5933         // 送信\r
5934         Lock(sock->ssl_lock);\r
5935         {\r
5936                 if (sock->Connected == false)\r
5937                 {\r
5938                         Unlock(sock->ssl_lock);\r
5939                         Debug("%s %u SecureRecv() Disconnect\n", __FILE__, __LINE__);\r
5940                         return 0;\r
5941                 }\r
5942 \r
5943                 ret = SSL_write(ssl, data, size);\r
5944                 if (ret < 0)\r
5945                 {\r
5946                         e = SSL_get_error(ssl, ret);\r
5947                 }\r
5948         }\r
5949         Unlock(sock->ssl_lock);\r
5950 \r
5951         if (ret > 0)\r
5952         {\r
5953                 // 送信成功\r
5954                 sock->SendSize += (UINT64)ret;\r
5955                 sock->SendNum++;\r
5956                 sock->WriteBlocked = false;\r
5957                 return (UINT)ret;\r
5958         }\r
5959         if (ret == 0)\r
5960         {\r
5961                 // 切断\r
5962                 Debug("%s %u SecureRecv() Disconnect\n", __FILE__, __LINE__);\r
5963                 Disconnect(sock);\r
5964                 return 0;\r
5965         }\r
5966 \r
5967         if (sock->AsyncMode)\r
5968         {\r
5969                 // エラー値の確認\r
5970                 if (e == SSL_ERROR_WANT_READ || e == SSL_ERROR_WANT_WRITE || e == SSL_ERROR_SSL)\r
5971                 {\r
5972                         sock->WriteBlocked = true;\r
5973                         return SOCK_LATER;\r
5974                 }\r
5975                 Debug("%s %u e=%u\n", __FILE__, __LINE__, e);\r
5976         }\r
5977         //Debug("%s %u SecureRecv() Disconnect\n", __FILE__, __LINE__);\r
5978         Disconnect(sock);\r
5979         return 0;\r
5980 }\r
5981 \r
5982 // TCP 受信\r
5983 UINT Recv(SOCK *sock, void *data, UINT size, bool secure)\r
5984 {\r
5985         SOCKET s;\r
5986         int ret;\r
5987 \r
5988 #ifdef UNIX_SOLARIS\r
5989         SOCKET_TIMEOUT_PARAM *ttparam;\r
5990 #endif //UNIX_SOLARIS\r
5991 \r
5992         // 引数チェック\r
5993         if (sock == NULL || data == NULL || size == 0)\r
5994         {\r
5995                 return 0;\r
5996         }\r
5997         if (sock->Type != SOCK_TCP || sock->Connected == false || sock->ListenMode != false ||\r
5998                 sock->socket == INVALID_SOCKET)\r
5999         {\r
6000                 return 0;\r
6001         }\r
6002         if (secure != false && sock->SecureMode == false)\r
6003         {\r
6004                 return 0;\r
6005         }\r
6006 \r
6007         if (secure)\r
6008         {\r
6009                 return SecureRecv(sock, data, size);\r
6010         }\r
6011 \r
6012         // 受信\r
6013         s = sock->socket;\r
6014 \r
6015 \r
6016 #ifdef  OS_UNIX\r
6017         if (sock->AsyncMode == false)\r
6018         {\r
6019                 sock->CallingThread = pthread_self();\r
6020         }\r
6021 #endif  // OS_UNIX\r
6022 \r
6023 // SOLARIS用タイムアウトスレッドの開始\r
6024 #ifdef UNIX_SOLARIS\r
6025         ttparam = NewSocketTimeout(sock);\r
6026 #endif // UNIX_SOLARIS\r
6027 \r
6028         ret = recv(s, data, size, 0);\r
6029 \r
6030 // タイムアウトスレッドの停止\r
6031 #ifdef UNIX_SOLARIS\r
6032         FreeSocketTimeout(ttparam);\r
6033 #endif // UNIX_SOLARIS\r
6034 \r
6035 #ifdef  OS_UNIX\r
6036         if (sock->AsyncMode == false)\r
6037         {\r
6038                 sock->CallingThread = 0;\r
6039         }\r
6040 #endif  // OS_UNIX\r
6041 \r
6042         if (ret > 0)\r
6043         {\r
6044                 // 受信成功\r
6045                 Lock(sock->lock);\r
6046                 {\r
6047                         sock->RecvSize += (UINT64)ret;\r
6048                         sock->SendNum++;\r
6049                 }\r
6050                 Unlock(sock->lock);\r
6051                 return (UINT)ret;\r
6052         }\r
6053 \r
6054         // 送信失敗\r
6055         if (sock->AsyncMode)\r
6056         {\r
6057                 // 非同期モードの場合、エラーを調べる\r
6058                 if (ret == SOCKET_ERROR)\r
6059                 {\r
6060 #ifdef  OS_WIN32\r
6061                         if (WSAGetLastError() == WSAEWOULDBLOCK)\r
6062                         {\r
6063                                 // ブロッキングしている\r
6064                                 return SOCK_LATER;\r
6065                         }\r
6066                         else\r
6067                         {\r
6068                                 Debug("Socket Error: %u\n", WSAGetLastError());\r
6069                         }\r
6070 #else   // OS_WIN32\r
6071                         if (errno == EAGAIN)\r
6072                         {\r
6073                                 // ブロッキングしている\r
6074                                 return SOCK_LATER;\r
6075                         }\r
6076 #endif  // OS_WIN32\r
6077                 }\r
6078         }\r
6079 \r
6080         // 切断された\r
6081         Disconnect(sock);\r
6082         return 0;\r
6083 }\r
6084 \r
6085 // TCP 送信\r
6086 UINT Send(SOCK *sock, void *data, UINT size, bool secure)\r
6087 {\r
6088         SOCKET s;\r
6089         int ret;\r
6090         // 引数チェック\r
6091         if (sock == NULL || data == NULL || size == 0)\r
6092         {\r
6093                 return 0;\r
6094         }\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
6098         {\r
6099                 return 0;\r
6100         }\r
6101         if (secure != false && sock->SecureMode == false)\r
6102         {\r
6103                 return 0;\r
6104         }\r
6105 \r
6106         if (secure)\r
6107         {\r
6108                 return SecureSend(sock, data, size);\r
6109         }\r
6110 \r
6111         // 送信\r
6112         s = sock->socket;\r
6113         ret = send(s, data, size, 0);\r
6114         if (ret > 0)\r
6115         {\r
6116                 // 送信成功\r
6117                 Lock(sock->lock);\r
6118                 {\r
6119                         sock->SendSize += (UINT64)ret;\r
6120                         sock->SendNum++;\r
6121                 }\r
6122                 Unlock(sock->lock);\r
6123                 sock->WriteBlocked = false;\r
6124                 return (UINT)ret;\r
6125         }\r
6126 \r
6127         // 送信失敗\r
6128         if (sock->AsyncMode)\r
6129         {\r
6130                 // 非同期モードの場合、エラーを調べる\r
6131                 if (ret == SOCKET_ERROR)\r
6132                 {\r
6133 #ifdef  OS_WIN32\r
6134                         if (WSAGetLastError() == WSAEWOULDBLOCK)\r
6135                         {\r
6136                                 // ブロッキングしている\r
6137                                 sock->WriteBlocked = true;\r
6138                                 return SOCK_LATER;\r
6139                         }\r
6140                         else\r
6141                         {\r
6142                                 Debug("Socket Error: %u\n", WSAGetLastError());\r
6143                         }\r
6144 #else   // OS_WIN32\r
6145                         if (errno == EAGAIN)\r
6146                         {\r
6147                                 // ブロッキングしている\r
6148                                 sock->WriteBlocked = true;\r
6149                                 return SOCK_LATER;\r
6150                         }\r
6151 #endif  // OS_WIN32\r
6152                 }\r
6153         }\r
6154 \r
6155         // 切断された\r
6156         Disconnect(sock);\r
6157         return 0;\r
6158 }\r
6159 \r
6160 // タイムアウトの取得 (ミリ秒)\r
6161 UINT GetTimeout(SOCK *sock)\r
6162 {\r
6163         // 引数チェック\r
6164         if (sock == NULL)\r
6165         {\r
6166                 return INFINITE;\r
6167         }\r
6168         if (sock->Type != SOCK_TCP)\r
6169         {\r
6170                 return INFINITE;\r
6171         }\r
6172 \r
6173         return sock->TimeOut;\r
6174 }\r
6175 \r
6176 // タイムアウト時間の設定 (ミリ秒)\r
6177 void SetTimeout(SOCK *sock, UINT timeout)\r
6178 {\r
6179         // 引数チェック\r
6180         if (sock == NULL)\r
6181         {\r
6182                 return;\r
6183         }\r
6184         if (sock->Type != SOCK_TCP)\r
6185         {\r
6186                 return;\r
6187         }\r
6188 \r
6189         if (timeout == INFINITE)\r
6190         {\r
6191                 timeout = TIMEOUT_INFINITE;\r
6192         }\r
6193 \r
6194         sock->TimeOut = timeout;\r
6195 \r
6196 //      Debug("SetTimeout(%u)\n",timeout);\r
6197 \r
6198 #ifdef OS_WIN32\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
6201 #endif\r
6202 \r
6203 #ifdef OS_UNIX\r
6204 #ifndef UNIX_SOLARIS\r
6205         {\r
6206                 struct timeval tv_timeout;\r
6207 \r
6208                 tv_timeout.tv_sec = timeout / 1000; // miliseconds to seconds\r
6209                 tv_timeout.tv_usec = (timeout % 1000) * 1000; // miliseconds to microseconds\r
6210 \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
6213         }\r
6214 #endif // UNIX_SOLARIS\r
6215 #endif // OS_UNIX\r
6216 }\r
6217 \r
6218 // 接続受諾初期化\r
6219 void AcceptInit(SOCK *s)\r
6220 {\r
6221         char tmp[MAX_SIZE];\r
6222         // 引数チェック\r
6223         if (s == NULL)\r
6224         {\r
6225                 return;\r
6226         }\r
6227 \r
6228         Zero(tmp, sizeof(tmp));\r
6229         if (GetHostName(tmp, sizeof(tmp), &s->RemoteIP) == false ||\r
6230                 IsEmptyStr(tmp))\r
6231         {\r
6232                 IPToStr(tmp, sizeof(tmp), &s->RemoteIP);\r
6233         }\r
6234 \r
6235         s->RemoteHostname = CopyStr(tmp);\r
6236 }\r
6237 \r
6238 // TCP 接続受諾\r
6239 SOCK *Accept(SOCK *sock)\r
6240 {\r
6241         SOCK *ret;\r
6242         SOCKET s, new_socket;\r
6243         int size;\r
6244         struct sockaddr_in addr;\r
6245         bool true_flag = true;\r
6246         // 引数チェック\r
6247         if (sock == NULL)\r
6248         {\r
6249                 return NULL;\r
6250         }\r
6251         if (sock->ListenMode == false || sock->Type != SOCK_TCP || sock->ServerMode == false)\r
6252         {\r
6253                 return NULL;\r
6254         }\r
6255         if (sock->CancelAccept)\r
6256         {\r
6257                 return NULL;\r
6258         }\r
6259         if (sock->IPv6)\r
6260         {\r
6261                 return Accept6(sock);\r
6262         }\r
6263 \r
6264         s = sock->socket;\r
6265         if (s == INVALID_SOCKET)\r
6266         {\r
6267                 return NULL;\r
6268         }\r
6269         Zero(&addr, sizeof(addr));\r
6270         size = sizeof(addr);\r
6271 \r
6272 #ifdef  OS_UNIX\r
6273         sock->CallingThread = pthread_self();\r
6274 #endif  // OS_UNIX\r
6275 \r
6276         new_socket = accept(s, (struct sockaddr *)&addr,(int *)&size);\r
6277 \r
6278 #ifdef  OS_UNIX\r
6279         sock->CallingThread = 0;\r
6280 #endif  // OS_UNIX\r
6281 \r
6282         if (new_socket == INVALID_SOCKET)\r
6283         {\r
6284                 return NULL;\r
6285         }\r
6286         if (sock->CancelAccept)\r
6287         {\r
6288                 closesocket(new_socket);\r
6289                 return NULL;\r
6290         }\r
6291 \r
6292         ret = NewSock();\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
6299 \r
6300         // TCP オプションの設定\r
6301         setsockopt(ret->socket, IPPROTO_TCP, TCP_NODELAY, (char *)&true_flag, sizeof(bool));\r
6302 \r
6303         SetSockPriorityHigh(ret);\r
6304 \r
6305         // タイムアウト値の初期化\r
6306         SetTimeout(ret, TIMEOUT_INFINITE);\r
6307 \r
6308         // ソケット情報\r
6309         QuerySocketInformation(ret);\r
6310 \r
6311         AddIpClient(&ret->RemoteIP);\r
6312 \r
6313         return ret;\r
6314 }\r
6315 SOCK *Accept6(SOCK *sock)\r
6316 {\r
6317         SOCK *ret;\r
6318         SOCKET s, new_socket;\r
6319         int size;\r
6320         struct sockaddr_in6 addr;\r
6321         bool true_flag = true;\r
6322         // 引数チェック\r
6323         if (sock == NULL)\r
6324         {\r
6325                 return NULL;\r
6326         }\r
6327         if (sock->ListenMode == false || sock->Type != SOCK_TCP || sock->ServerMode == false)\r
6328         {\r
6329                 return NULL;\r
6330         }\r
6331         if (sock->CancelAccept)\r
6332         {\r
6333                 return NULL;\r
6334         }\r
6335         if (sock->IPv6 == false)\r
6336         {\r
6337                 return NULL;\r
6338         }\r
6339 \r
6340         s = sock->socket;\r
6341         if (s == INVALID_SOCKET)\r
6342         {\r
6343                 return NULL;\r
6344         }\r
6345         Zero(&addr, sizeof(addr));\r
6346         size = sizeof(addr);\r
6347 \r
6348 #ifdef  OS_UNIX\r
6349         sock->CallingThread = pthread_self();\r
6350 #endif  // OS_UNIX\r
6351 \r
6352         new_socket = accept(s, (struct sockaddr *)&addr,(int *)&size);\r
6353 \r
6354 #ifdef  OS_UNIX\r
6355         sock->CallingThread = 0;\r
6356 #endif  // OS_UNIX\r
6357 \r
6358         if (new_socket == INVALID_SOCKET)\r
6359         {\r
6360                 return NULL;\r
6361         }\r
6362         if (sock->CancelAccept)\r
6363         {\r
6364                 closesocket(new_socket);\r
6365                 return NULL;\r
6366         }\r
6367 \r
6368         ret = NewSock();\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
6375 \r
6376         // TCP オプションの設定\r
6377         setsockopt(ret->socket, IPPROTO_TCP, TCP_NODELAY, (char *)&true_flag, sizeof(bool));\r
6378 \r
6379         SetSockPriorityHigh(ret);\r
6380 \r
6381         // タイムアウト値の初期化\r
6382         SetTimeout(ret, TIMEOUT_INFINITE);\r
6383 \r
6384         // ソケット情報\r
6385         QuerySocketInformation(ret);\r
6386 \r
6387         AddIpClient(&ret->RemoteIP);\r
6388 \r
6389         return ret;\r
6390 }\r
6391 \r
6392 // TCP 待ち受け (IPv6)\r
6393 SOCK *Listen6(UINT port)\r
6394 {\r
6395         return ListenEx6(port, false);\r
6396 }\r
6397 SOCK *ListenEx6(UINT port, bool local_only)\r
6398 {\r
6399         SOCKET s;\r
6400         SOCK *sock;\r
6401         struct sockaddr_in6 addr;\r
6402         struct in6_addr in;\r
6403         bool true_flag = true;\r
6404         IP localhost;\r
6405         // 引数チェック\r
6406         if (port == 0 || port >= 65536)\r
6407         {\r
6408                 return NULL;\r
6409         }\r
6410 \r
6411         // 初期化\r
6412         Zero(&addr, sizeof(addr));\r
6413         Zero(&in, sizeof(in));\r
6414         GetLocalHostIP6(&localhost);\r
6415 \r
6416         addr.sin6_port = htons((UINT)port);\r
6417         addr.sin6_family = AF_INET6;\r
6418 \r
6419         if (local_only)\r
6420         {\r
6421                 IPToInAddr6(&addr.sin6_addr, &localhost);\r
6422         }\r
6423 \r
6424         // ソケットの作成\r
6425         s = socket(AF_INET6, SOCK_STREAM, 0);\r
6426         if (s == INVALID_SOCKET)\r
6427         {\r
6428                 return NULL;\r
6429         }\r
6430 \r
6431 #ifdef  OS_UNIX\r
6432         // UNIX 系では IPv6 Only フラグを立てる必要がある\r
6433         setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY, &true_flag, sizeof(true_flag));\r
6434 #endif  // OS_UNIX\r
6435 \r
6436         //SetSocketSendRecvBufferSize(s, SOCKET_BUFFER_SIZE);\r
6437 \r
6438 #ifdef  OS_UNIX\r
6439         // Windows 系 OS は REUSEADDR の実装にバグがあるっぽいので\r
6440         // UNIX 系のみ有効にした。\r
6441         setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (char *)&true_flag, sizeof(bool));\r
6442 #endif  // OS_UNIX\r
6443 \r
6444         if (bind(s, (struct sockaddr *)&addr, sizeof(struct sockaddr_in6)) != 0)\r
6445         {\r
6446                 // bind 失敗\r
6447                 closesocket(s);\r
6448                 return NULL;\r
6449         }\r
6450         if (listen(s, SOMAXCONN))\r
6451         {\r
6452                 // listen 失敗\r
6453                 closesocket(s);\r
6454                 return NULL;\r
6455         }\r
6456 \r
6457         // 成功\r
6458         sock = NewSock();\r
6459         sock->Connected = false;\r
6460         sock->AsyncMode = false;\r
6461         sock->ServerMode = true;\r
6462         sock->Type = SOCK_TCP;\r
6463         sock->socket = s;\r
6464         sock->ListenMode = true;\r
6465         sock->SecureMode = false;\r
6466         sock->LocalPort = port;\r
6467         sock->IPv6 = true;\r
6468 \r
6469         return sock;\r
6470 }\r
6471 \r
6472 // TCP 待ち受け\r
6473 SOCK *Listen(UINT port)\r
6474 {\r
6475         return ListenEx(port, false);\r
6476 }\r
6477 SOCK *ListenEx(UINT port, bool local_only)\r
6478 {\r
6479         SOCKET s;\r
6480         SOCK *sock;\r
6481         struct sockaddr_in addr;\r
6482         struct in_addr in;\r
6483         bool true_flag = true;\r
6484         IP localhost;\r
6485         // 引数チェック\r
6486         if (port == 0 || port >= 65536)\r
6487         {\r
6488                 return NULL;\r
6489         }\r
6490 \r
6491         // 初期化\r
6492         Zero(&addr, sizeof(addr));\r
6493         Zero(&in, sizeof(in));\r
6494         SetIP(&localhost, 127, 0, 0, 1);\r
6495 \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
6499 \r
6500         if (local_only)\r
6501         {\r
6502                 IPToInAddr(&addr.sin_addr, &localhost);\r
6503         }\r
6504 \r
6505         // ソケットの作成\r
6506         s = socket(AF_INET, SOCK_STREAM, 0);\r
6507         if (s == INVALID_SOCKET)\r
6508         {\r
6509                 return NULL;\r
6510         }\r
6511 \r
6512         //SetSocketSendRecvBufferSize(s, SOCKET_BUFFER_SIZE);\r
6513 \r
6514 #ifdef  OS_UNIX\r
6515         // Windows 系 OS は REUSEADDR の実装にバグがあるっぽいので\r
6516         // UNIX 系のみ有効にした。\r
6517         setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (char *)&true_flag, sizeof(bool));\r
6518 #endif  // OS_UNIX\r
6519 \r
6520         if (bind(s, (struct sockaddr *)&addr, sizeof(struct sockaddr_in)) != 0)\r
6521         {\r
6522                 // bind 失敗\r
6523                 closesocket(s);\r
6524                 return NULL;\r
6525         }\r
6526         if (listen(s, SOMAXCONN))\r
6527         {\r
6528                 // listen 失敗\r
6529                 closesocket(s);\r
6530                 return NULL;\r
6531         }\r
6532 \r
6533         // 成功\r
6534         sock = NewSock();\r
6535         sock->Connected = false;\r
6536         sock->AsyncMode = false;\r
6537         sock->ServerMode = true;\r
6538         sock->Type = SOCK_TCP;\r
6539         sock->socket = s;\r
6540         sock->ListenMode = true;\r
6541         sock->SecureMode = false;\r
6542         sock->LocalPort = port;\r
6543 \r
6544         return sock;\r
6545 }\r
6546 \r
6547 // TCP 切断\r
6548 void Disconnect(SOCK *sock)\r
6549 {\r
6550         SOCKET s;\r
6551         bool true_flag = true;\r
6552         bool false_flag = false;\r
6553         // 引数チェック\r
6554         if (sock == NULL)\r
6555         {\r
6556                 return;\r
6557         }\r
6558 \r
6559         sock->Disconnecting = true;\r
6560 \r
6561 #ifdef  OS_UNIX\r
6562         UnixFreeAsyncSocket(sock);\r
6563 #endif  // UnixFreeAsyncSocket\r
6564 \r
6565         if (sock->Type == SOCK_TCP && sock->ListenMode)\r
6566         {\r
6567                 // Listen 中のソケットの場合は localhost に対して接続する\r
6568                 sock->CancelAccept = true;\r
6569 \r
6570                 if (sock->IPv6 == false)\r
6571                 {\r
6572                         CheckTCPPort("127.0.0.1", sock->LocalPort);\r
6573                 }\r
6574                 else\r
6575                 {\r
6576                         CheckTCPPort("::1", sock->LocalPort);\r
6577                 }\r
6578         }\r
6579 \r
6580         Lock(disconnect_function_lock);\r
6581 \r
6582         Lock(sock->disconnect_lock);\r
6583 \r
6584         if (sock->Type == SOCK_TCP)\r
6585         {\r
6586                 if (sock->socket != INVALID_SOCKET)\r
6587                 {\r
6588                         // 強制切断フラグ\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
6595                 }\r
6596 \r
6597                 // TCP ソケット\r
6598                 Lock(sock->lock);\r
6599                 {\r
6600                         if (sock->socket == INVALID_SOCKET)\r
6601                         {\r
6602                                 Unlock(sock->lock);\r
6603                                 Unlock(sock->disconnect_lock);\r
6604                                 Unlock(disconnect_function_lock);\r
6605                                 return;\r
6606                         }\r
6607                         s = sock->socket;\r
6608 \r
6609                         if (sock->Connected)\r
6610                         {\r
6611                                 struct linger ling;\r
6612                                 Zero(&ling, sizeof(ling));\r
6613 \r
6614 \r
6615 #if     0\r
6616                                 // SSL 切断\r
6617                                 Lock(sock->ssl_lock);\r
6618                                 {\r
6619                                         if (sock->SecureMode)\r
6620                                         {\r
6621                                                 SSL_shutdown(sock->ssl);\r
6622                                         }\r
6623                                 }\r
6624                                 Unlock(sock->ssl_lock);\r
6625 #endif\r
6626                                 // 切断\r
6627                                 shutdown(s, 2);\r
6628                         }\r
6629 \r
6630                         // ソケットを閉じる\r
6631                         closesocket(s);\r
6632 \r
6633 #ifdef  OS_UNIX\r
6634 #ifdef  FIX_SSL_BLOCKING\r
6635                         if (sock->CallingThread != NULL)\r
6636                         {\r
6637                                 pthread_kill(sock->CallingThread, 64);\r
6638                         }\r
6639 #endif  // FIX_SSL_BLOCKING\r
6640 #endif  // OS_UNIX\r
6641 \r
6642                         // SSL を解放\r
6643                         Lock(sock->ssl_lock);\r
6644                         {\r
6645                                 if (sock->SecureMode)\r
6646                                 {\r
6647                                         if (sock->ssl != NULL)\r
6648                                         {\r
6649                                                 Lock(openssl_lock);\r
6650                                                 {\r
6651                                                         SSL_free(sock->ssl);\r
6652                                                 }\r
6653                                                 Unlock(openssl_lock);\r
6654                                                 sock->ssl = NULL;\r
6655                                         }\r
6656                                         sock->Connected = false;\r
6657                                         // 証明書を解放\r
6658                                         if (sock->RemoteX != NULL)\r
6659                                         {\r
6660                                                 FreeX(sock->RemoteX);\r
6661                                                 sock->RemoteX = NULL;\r
6662                                         }\r
6663                                         if (sock->LocalX != NULL)\r
6664                                         {\r
6665                                                 FreeX(sock->LocalX);\r
6666                                                 sock->LocalX = NULL;\r
6667                                         }\r
6668 \r
6669                                         // 暗号化アルゴリズム名\r
6670                                         if (sock->CipherName != NULL)\r
6671                                         {\r
6672                                                 Free(sock->CipherName);\r
6673                                                 sock->CipherName = NULL;\r
6674                                         }\r
6675                                         sock->SecureMode = false;\r
6676                                 }\r
6677                         }\r
6678                         Unlock(sock->ssl_lock);\r
6679 \r
6680                         // 初期化\r
6681                         sock->socket = INVALID_SOCKET;\r
6682                         sock->Type = 0;\r
6683                         sock->AsyncMode = false;\r
6684                         sock->Connected = false;\r
6685                         sock->ListenMode = false;\r
6686                         sock->SecureMode = false;\r
6687 \r
6688                         if (sock->ServerMode && sock->ListenMode == false)\r
6689                         {\r
6690                                 DelIpClient(&sock->RemoteIP);\r
6691                         }\r
6692                 }\r
6693                 Unlock(sock->lock);\r
6694         }\r
6695         else if (sock->Type == SOCK_UDP)\r
6696         {\r
6697                 // UDP ソケット\r
6698                 Lock(sock->lock);\r
6699                 {\r
6700                         if (sock->socket == INVALID_SOCKET)\r
6701                         {\r
6702                                 Unlock(sock->lock);\r
6703                                 Unlock(sock->disconnect_lock);\r
6704                                 Unlock(disconnect_function_lock);\r
6705                                 return;\r
6706                         }\r
6707 \r
6708                         s = sock->socket;\r
6709 \r
6710                         // ソケットを閉じる\r
6711                         closesocket(s);\r
6712 \r
6713                         // 初期化\r
6714                         sock->socket = INVALID_SOCKET;\r
6715                         sock->Type = 0;\r
6716                         sock->AsyncMode = false;\r
6717                         sock->Connected = false;\r
6718                         sock->ListenMode = false;\r
6719                         sock->SecureMode = false;\r
6720                 }\r
6721                 Unlock(sock->lock);\r
6722         }\r
6723         Unlock(sock->disconnect_lock);\r
6724 \r
6725         Unlock(disconnect_function_lock);\r
6726 }\r
6727 \r
6728 typedef struct TCP_PORT_CHECK\r
6729 {\r
6730         REF *ref;\r
6731         char hostname[MAX_SIZE];\r
6732         UINT port;\r
6733         bool ok;\r
6734 } TCP_PORT_CHECK;\r
6735 \r
6736 // TCP ポートチェック用スレッド\r
6737 void CheckTCPPortThread(THREAD *thread, void *param)\r
6738 {\r
6739         TCP_PORT_CHECK *c;\r
6740         SOCK *s;\r
6741         // 引数チェック\r
6742         if (thread == NULL || param == NULL)\r
6743         {\r
6744                 return;\r
6745         }\r
6746 \r
6747         c = (TCP_PORT_CHECK *)param;\r
6748         AddRef(c->ref);\r
6749         NoticeThreadInit(thread);\r
6750 \r
6751         AddWaitThread(thread);\r
6752 \r
6753         s = Connect(c->hostname, c->port);\r
6754         if (s != NULL)\r
6755         {\r
6756                 c->ok = true;\r
6757                 Disconnect(s);\r
6758                 ReleaseSock(s);\r
6759         }\r
6760 \r
6761         if (Release(c->ref) == 0)\r
6762         {\r
6763                 Free(c);\r
6764         }\r
6765 \r
6766         DelWaitThread(thread);\r
6767 }\r
6768 \r
6769 // TCP ポートに接続可能かどうかチェックする\r
6770 bool CheckTCPPortEx(char *hostname, UINT port, UINT timeout)\r
6771 {\r
6772         SOCK *s;\r
6773         // 引数チェック\r
6774         if (hostname == NULL || port == 0 || port >= 65536)\r
6775         {\r
6776                 return false;\r
6777         }\r
6778 \r
6779         if (timeout == 0)\r
6780         {\r
6781                 timeout = TIMEOUT_TCP_PORT_CHECK;\r
6782         }\r
6783 \r
6784         s = ConnectEx(hostname, port, timeout);\r
6785         if (s == NULL)\r
6786         {\r
6787                 return false;\r
6788         }\r
6789         else\r
6790         {\r
6791                 Disconnect(s);\r
6792                 ReleaseSock(s);\r
6793                 return true;\r
6794         }\r
6795 }\r
6796 bool CheckTCPPort(char *hostname, UINT port)\r
6797 {\r
6798         return CheckTCPPortEx(hostname, port, TIMEOUT_TCP_PORT_CHECK);\r
6799 }\r
6800 \r
6801 #ifdef  OS_UNIX\r
6802 // タイムアウト付き接続 (UNIX 版)\r
6803 int connect_timeout(SOCKET s, struct sockaddr *addr, int size, int timeout, bool *cancel_flag)\r
6804 {\r
6805         SOCKSET set;\r
6806         bool ok = false;\r
6807         UINT64 start_time;\r
6808         // 引数チェック\r
6809         if (s == INVALID_SOCKET || addr == NULL)\r
6810         {\r
6811                 return -1;\r
6812         }\r
6813         if (timeout == 0)\r
6814         {\r
6815                 timeout = TIMEOUT_TCP_PORT_CHECK;\r
6816         }\r
6817 \r
6818         UnixSetSocketNonBlockingMode(s, true);\r
6819 \r
6820         start_time = Tick64();\r
6821 \r
6822         while (true)\r
6823         {\r
6824                 int ret;\r
6825                 ret = connect(s, addr, size);\r
6826                 if (ret == 0 || errno == EISCONN)\r
6827                 {\r
6828                         ok = true;\r
6829                         break;\r
6830                 }\r
6831                 else\r
6832                 {\r
6833                         if (((start_time + (UINT64)timeout) <= Tick64()) || (errno != EAGAIN && errno != EINPROGRESS && errno != EALREADY))\r
6834                         {\r
6835                                 // 失敗\r
6836                                 break;\r
6837                         }\r
6838                         else if (*cancel_flag)\r
6839                         {\r
6840                                 // キャンセル\r
6841                                 break;\r
6842                         }\r
6843                         else\r
6844                         {\r
6845                                 // 接続中\r
6846                                 SleepThread(50);\r
6847                                 UnixSelectInner(1, (UINT *)&s, 1, (UINT *)&s, 100);\r
6848                         }\r
6849                 }\r
6850         }\r
6851 \r
6852         UnixSetSocketNonBlockingMode(s, false);\r
6853 \r
6854         if (ok)\r
6855         {\r
6856                 return 0;\r
6857         }\r
6858         else\r
6859         {\r
6860                 return -1;\r
6861         }\r
6862 }\r
6863 #else\r
6864 // タイムアウト付き接続 (Win32 版)\r
6865 int connect_timeout(SOCKET s, struct sockaddr *addr, int size, int timeout, bool *cancel_flag)\r
6866 {\r
6867         UINT64 start_time;\r
6868         bool ok = false;\r
6869         bool timeouted = false;\r
6870         WSAEVENT hEvent;\r
6871         UINT zero = 0;\r
6872         UINT tmp = 0;\r
6873         UINT ret_size = 0;\r
6874         bool is_nt = false;\r
6875         // 引数チェック\r
6876         if (s == INVALID_SOCKET || addr == NULL)\r
6877         {\r
6878                 return -1;\r
6879         }\r
6880         if (timeout == 0)\r
6881         {\r
6882                 timeout = TIMEOUT_TCP_PORT_CHECK;\r
6883         }\r
6884 \r
6885         is_nt = OS_IS_WINDOWS_NT(GetOsInfo()->OsType);\r
6886 \r
6887         // イベントを作成\r
6888         hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);\r
6889 \r
6890         // ソケットをイベントに関連付ける\r
6891         WSAEventSelect(s, hEvent, FD_CONNECT);\r
6892 \r
6893         start_time = Tick64();\r
6894 \r
6895         while (true)\r
6896         {\r
6897                 int ret;\r
6898                 \r
6899                 ret = connect(s, addr, size);\r
6900 \r
6901                 if (ret == 0)\r
6902                 {\r
6903                         ok = true;\r
6904                         break;\r
6905                 }\r
6906                 else\r
6907                 {\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
6912                         {\r
6913                                 // タイムアウト\r
6914                                 ok = false;\r
6915                                 break;\r
6916                         }\r
6917                         if (*cancel_flag)\r
6918                         {\r
6919                                 // キャンセル\r
6920                                 ok = false;\r
6921                                 break;\r
6922                         }\r
6923                         if (err == WSAEISCONN || (err == WSAEINVAL && is_nt))\r
6924                         {\r
6925                                 ok = true;\r
6926                                 break;\r
6927                         }\r
6928                         if (((start_time + (UINT64)timeout) <= Tick64()) || (err != WSAEWOULDBLOCK && err != WSAEALREADY && (is_nt || err != WSAEINVAL)))\r
6929                         {\r
6930                                 // 失敗 (タイムアウト)\r
6931                                 break;\r
6932                         }\r
6933                         else\r
6934                         {\r
6935                                 SleepThread(10);\r
6936                                 // 接続中\r
6937                                 if (WaitForSingleObject(hEvent, 100) == WAIT_OBJECT_0)\r
6938                                 {\r
6939                                         timeouted = true;\r
6940                                 }\r
6941                         }\r
6942                 }\r
6943         }\r
6944 \r
6945         // ソケットをイベントから外す\r
6946         WSAEventSelect(s, hEvent, 0);\r
6947 \r
6948         // 同期ソケットに戻す\r
6949         WSAIoctl(s, FIONBIO, &zero, sizeof(zero), &tmp, sizeof(tmp), &ret_size, NULL, NULL);\r
6950 \r
6951         // イベントを閉じる\r
6952         CloseHandle(hEvent);\r
6953 \r
6954         if (ok)\r
6955         {\r
6956                 return 0;\r
6957         }\r
6958         else\r
6959         {\r
6960                 return -1;\r
6961         }\r
6962 }\r
6963 #endif  // OS_UNIX\r
6964 \r
6965 // ソケットのパケットの優先順位を向上させる (未使用)\r
6966 void SetSockPriorityHigh(SOCK *s)\r
6967 {\r
6968         int value;\r
6969         // 引数チェック\r
6970         if (s == NULL)\r
6971         {\r
6972                 return;\r
6973         }\r
6974 \r
6975         value = 16;\r
6976 \r
6977 #ifdef  IP_TOS\r
6978         //setsockopt(s->socket, IPPROTO_IP, IP_TOS, (char *)&value, sizeof(int));\r
6979 #endif  // IP_TOS\r
6980 }\r
6981 \r
6982 // TCP 接続\r
6983 SOCK *Connect(char *hostname, UINT port)\r
6984 {\r
6985         return ConnectEx(hostname, port, 0);\r
6986 }\r
6987 SOCK *ConnectEx(char *hostname, UINT port, UINT timeout)\r
6988 {\r
6989         return ConnectEx2(hostname, port, timeout, NULL);\r
6990 }\r
6991 SOCK *ConnectEx2(char *hostname, UINT port, UINT timeout, bool *cancel_flag)\r
6992 {\r
6993         SOCK *sock;\r
6994         SOCKET s;\r
6995         struct linger ling;\r
6996         struct sockaddr_in sockaddr4;\r
6997         struct in_addr addr4;\r
6998         IP ip4;\r
6999         struct sockaddr_in6 sockaddr6;\r
7000         struct in6_addr addr6;\r
7001         IP ip6;\r
7002         bool true_flag = true;\r
7003         bool false_flag = false;\r
7004         char tmp[MAX_SIZE];\r
7005         IP current_ip;\r
7006         bool is_ipv6 = false;\r
7007         bool dummy = false;\r
7008         // 引数チェック\r
7009         if (hostname == NULL || port == 0 || port >= 65536)\r
7010         {\r
7011                 return NULL;\r
7012         }\r
7013         if (timeout == 0)\r
7014         {\r
7015                 timeout = TIMEOUT_TCP_PORT_CHECK;\r
7016         }\r
7017         if (cancel_flag == NULL)\r
7018         {\r
7019                 cancel_flag = &dummy;\r
7020         }\r
7021 \r
7022         Zero(&current_ip, sizeof(current_ip));\r
7023 \r
7024         Zero(&sockaddr4, sizeof(sockaddr4));\r
7025         Zero(&addr4, sizeof(addr4));\r
7026         Zero(&ip4, sizeof(ip4));\r
7027 \r
7028         Zero(&sockaddr6, sizeof(sockaddr6));\r
7029         Zero(&addr6, sizeof(addr6));\r
7030         Zero(&ip6, sizeof(ip6));\r
7031 \r
7032         // 正引き\r
7033         if (GetIP46Ex(&ip4, &ip6, hostname, 0, cancel_flag) == false)\r
7034         {\r
7035                 return NULL;\r
7036         }\r
7037 \r
7038         s = INVALID_SOCKET;\r
7039 \r
7040         // IPv4 で接続を試行する\r
7041         if (IsZeroIp(&ip4) == false)\r
7042         {\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
7048 \r
7049                 // ソケット作成\r
7050                 s = socket(AF_INET, SOCK_STREAM, 0);\r
7051                 if (s != INVALID_SOCKET)\r
7052                 {\r
7053                         // 接続\r
7054                         if (connect_timeout(s, (struct sockaddr *)&sockaddr4, sizeof(struct sockaddr_in), timeout, cancel_flag) != 0)\r
7055                         {\r
7056                                 // 接続失敗\r
7057                                 closesocket(s);\r
7058                                 s = INVALID_SOCKET;\r
7059                         }\r
7060                         else\r
7061                         {\r
7062                                 Copy(&current_ip, &ip4, sizeof(IP));\r
7063                         }\r
7064                 }\r
7065         }\r
7066 \r
7067         // IPv6 で接続を試行する\r
7068         if (s == INVALID_SOCKET && IsZeroIp(&ip6) == false)\r
7069         {\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
7076 \r
7077                 // ソケット作成\r
7078                 s = socket(AF_INET6, SOCK_STREAM, 0);\r
7079                 if (s != INVALID_SOCKET)\r
7080                 {\r
7081                         // 接続\r
7082                         if (connect_timeout(s, (struct sockaddr *)&sockaddr6, sizeof(struct sockaddr_in6), timeout, cancel_flag) != 0)\r
7083                         {\r
7084                                 // 接続失敗\r
7085                                 closesocket(s);\r
7086                                 s = INVALID_SOCKET;\r
7087                         }\r
7088                         else\r
7089                         {\r
7090                                 Copy(&current_ip, &ip6, sizeof(IP));\r
7091 \r
7092                                 is_ipv6 = true;\r
7093                         }\r
7094                 }\r
7095         }\r
7096 \r
7097         if (s == INVALID_SOCKET)\r
7098         {\r
7099                 // IPv4, IPv6 の両方で接続失敗\r
7100                 return NULL;\r
7101         }\r
7102 \r
7103         // SOCK の作成\r
7104         sock = NewSock();\r
7105         sock->socket = s;\r
7106         sock->Type = SOCK_TCP;\r
7107         sock->ServerMode = false;\r
7108 \r
7109         SetSockPriorityHigh(sock);\r
7110 \r
7111         // ホスト名解決\r
7112         if (GetHostName(tmp, sizeof(tmp), &current_ip) == false)\r
7113         {\r
7114                 StrCpy(tmp, sizeof(tmp), hostname);\r
7115         }\r
7116 \r
7117         //Debug("PTR: %s\n", tmp);\r
7118 \r
7119         sock->RemoteHostname = CopyStr(tmp);\r
7120 \r
7121 //      Debug("new socket: %u\n", s);\r
7122 \r
7123         Zero(&ling, sizeof(ling));\r
7124         // 強制切断フラグ\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
7131 \r
7132         // TCP オプションの設定\r
7133         setsockopt(sock->socket, IPPROTO_TCP, TCP_NODELAY, (char *)&true_flag, sizeof(bool));\r
7134 \r
7135         // タイムアウト値の初期化\r
7136         SetTimeout(sock, TIMEOUT_INFINITE);\r
7137 \r
7138         // ソケット情報の取得\r
7139         QuerySocketInformation(sock);\r
7140 \r
7141         sock->Connected = true;\r
7142         sock->AsyncMode = false;\r
7143         sock->SecureMode = false;\r
7144         sock->IPv6 = is_ipv6;\r
7145 \r
7146         return sock;\r
7147 }\r
7148 \r
7149 // ソケットの送受信バッファサイズを最大にする\r
7150 void SetSocketSendRecvBufferSize(int s, UINT size)\r
7151 {\r
7152         int value = (int)size;\r
7153         // 引数チェック\r
7154         if (s == INVALID_SOCKET)\r
7155         {\r
7156                 return;\r
7157         }\r
7158 \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
7161 }\r
7162 \r
7163 // ソケット情報の取得\r
7164 void QuerySocketInformation(SOCK *sock)\r
7165 {\r
7166         // 引数チェック\r
7167         if (sock == NULL)\r
7168         {\r
7169                 return;\r
7170         }\r
7171 \r
7172         Lock(sock->lock);\r
7173         {\r
7174                 struct sockaddr_in6 sockaddr6;\r
7175                 struct in6_addr *addr6;\r
7176                 int size;\r
7177 \r
7178                 if (sock->Type == SOCK_TCP)\r
7179                 {\r
7180                         // リモートホストの情報を取得\r
7181                         size = sizeof(sockaddr6);\r
7182                         if (getpeername(sock->socket, (struct sockaddr *)&sockaddr6, (int *)&size) == 0)\r
7183                         {\r
7184                                 if (size >= sizeof(struct sockaddr_in6))\r
7185                                 {\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
7190                                 }\r
7191                                 else\r
7192                                 {\r
7193                                         struct sockaddr_in *sockaddr;\r
7194                                         struct in_addr *addr;\r
7195 \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
7200                                 }\r
7201                         }\r
7202                 }\r
7203 \r
7204                 // ローカルホストの情報を取得\r
7205                 size = sizeof(sockaddr6);\r
7206                 if (getsockname(sock->socket, (struct sockaddr *)&sockaddr6, (int *)&size) == 0)\r
7207                 {\r
7208                         if (size >= sizeof(struct sockaddr_in6))\r
7209                         {\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
7214                         }\r
7215                         else\r
7216                         {\r
7217                                 struct sockaddr_in *sockaddr;\r
7218                                 struct in_addr *addr;\r
7219 \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
7224                         }\r
7225                 }\r
7226         }\r
7227         Unlock(sock->lock);\r
7228 }\r
7229 \r
7230 // ソケットの解放\r
7231 void ReleaseSock(SOCK *s)\r
7232 {\r
7233         // 引数チェック\r
7234         if (s == NULL)\r
7235         {\r
7236                 return;\r
7237         }\r
7238 \r
7239         if (Release(s->ref) == 0)\r
7240         {\r
7241                 if (s->ListenMode == false && s->ServerMode)\r
7242                 {\r
7243                         Print("");\r
7244                 }\r
7245                 CleanupSock(s);\r
7246         }\r
7247 }\r
7248 \r
7249 // ソケットのクリーンアップ\r
7250 void CleanupSock(SOCK *s)\r
7251 {\r
7252         // 引数チェック\r
7253         if (s == NULL)\r
7254         {\r
7255                 return;\r
7256         }\r
7257 \r
7258 //      {Debug("CleanupSock: Disconnect() Called: %s %u\n", __FILE__, __LINE__);Disconnect(s);}\r
7259         Disconnect(s);\r
7260 \r
7261 #ifdef  OS_WIN32\r
7262         Win32FreeAsyncSocket(s);\r
7263 #else   // OS_WIN32\r
7264         UnixFreeAsyncSocket(s);\r
7265 #endif  // OS_WIN32\r
7266 \r
7267         FreeBuf(s->SendBuf);\r
7268         if (s->socket != INVALID_SOCKET)\r
7269         {\r
7270 #ifdef  OS_WIN32\r
7271                 closesocket(s->socket);\r
7272 #else   // OS_WIN32\r
7273                 close(s->socket);\r
7274 #endif  // OS_WIN32\r
7275         }\r
7276         Free(s->RemoteHostname);\r
7277 \r
7278         Free(s->WaitToUseCipher);\r
7279         DeleteLock(s->lock);\r
7280         DeleteLock(s->ssl_lock);\r
7281         DeleteLock(s->disconnect_lock);\r
7282 \r
7283         Dec(num_tcp_connections);\r
7284 \r
7285         Free(s);\r
7286 }\r
7287 \r
7288 // 新しいソケットの作成\r
7289 SOCK *NewSock()\r
7290 {\r
7291         SOCK *s = ZeroMallocFast(sizeof(SOCK));\r
7292 \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
7299 \r
7300         Inc(num_tcp_connections);\r
7301 \r
7302         return s;\r
7303 }\r
7304 \r
7305 // IP を UINT に変換する\r
7306 UINT IPToUINT(IP *ip)\r
7307 {\r
7308         UCHAR *b;\r
7309         UINT i, value = 0;\r
7310         // 引数チェック\r
7311         if (ip == NULL)\r
7312         {\r
7313                 return 0;\r
7314         }\r
7315 \r
7316         b = (UCHAR *)&value;\r
7317         for (i = 0;i < 4;i++)\r
7318         {\r
7319                 b[i] = ip->addr[i];\r
7320         }\r
7321 \r
7322         return value;\r
7323 }\r
7324 \r
7325 // UNIT を IP に変換する\r
7326 void UINTToIP(IP *ip, UINT value)\r
7327 {\r
7328         UCHAR *b;\r
7329         UINT i;\r
7330         // 引数チェック\r
7331         if (ip == NULL)\r
7332         {\r
7333                 return;\r
7334         }\r
7335 \r
7336         ZeroIP4(ip);\r
7337 \r
7338         b = (UCHAR *)&value;\r
7339         for (i = 0;i < 4;i++)\r
7340         {\r
7341                 ip->addr[i] = b[i];\r
7342         }\r
7343 }\r
7344 \r
7345 // コンピュータのホスト名を取得\r
7346 void GetMachineHostName(char *name, UINT size)\r
7347 {\r
7348         char tmp[MAX_SIZE];\r
7349         UINT i, len;\r
7350         // 引数チェック\r
7351         if (name == NULL)\r
7352         {\r
7353                 return;\r
7354         }\r
7355 \r
7356         GetMachineName(tmp, sizeof(tmp));\r
7357 \r
7358         len = StrLen(tmp);\r
7359         for (i = 0;i < len;i++)\r
7360         {\r
7361                 if (tmp[i] == '.')\r
7362                 {\r
7363                         tmp[i] = 0;\r
7364                 }\r
7365         }\r
7366 \r
7367         ConvertSafeFileName(name, size, tmp);\r
7368 }\r
7369 \r
7370 // このコンピュータの IP アドレスを取得\r
7371 void GetMachineIp(IP *ip)\r
7372 {\r
7373         char tmp[MAX_SIZE];\r
7374         // 引数チェック\r
7375         if (ip == NULL)\r
7376         {\r
7377                 return;\r
7378         }\r
7379 \r
7380         Zero(ip, sizeof(IP));\r
7381         SetIP(ip, 127, 0, 0, 1);\r
7382 \r
7383         GetMachineName(tmp, sizeof(tmp));\r
7384         GetIP(ip, tmp);\r
7385 }\r
7386 \r
7387 // コンピュータ名を hosts から取得\r
7388 bool GetMachineNameFromHosts(char *name, UINT size)\r
7389 {\r
7390         bool ret = false;\r
7391         char *s;\r
7392         BUF *b;\r
7393         // 引数チェック\r
7394         if (name == NULL)\r
7395         {\r
7396                 return false;\r
7397         }\r
7398 \r
7399         b = ReadDump("/etc/hosts");\r
7400         if (b == NULL)\r
7401         {\r
7402                 return false;\r
7403         }\r
7404 \r
7405         while (true)\r
7406         {\r
7407                 s = CfgReadNextLine(b);\r
7408                 if (s == NULL)\r
7409                 {\r
7410                         break;\r
7411                 }\r
7412                 else\r
7413                 {\r
7414                         TOKEN_LIST *t = ParseToken(s, " \t");\r
7415 \r
7416                         if (t != NULL)\r
7417                         {\r
7418                                 if (t->NumTokens >= 2)\r
7419                                 {\r
7420                                         if (StrCmpi(t->Token[0], "127.0.0.1") == 0)\r
7421                                         {\r
7422                                                 UINT i;\r
7423 \r
7424                                                 for (i = 1;i < t->NumTokens;i++)\r
7425                                                 {\r
7426                                                         if (StartWith(t->Token[i], "localhost") == false)\r
7427                                                         {\r
7428                                                                 StrCpy(name, size, t->Token[i]);\r
7429                                                                 ret = true;\r
7430                                                         }\r
7431                                                 }\r
7432                                         }\r
7433                                 }\r
7434                         }\r
7435                         FreeToken(t);\r
7436                 }\r
7437 \r
7438                 Free(s);\r
7439         }\r
7440 \r
7441         FreeBuf(b);\r
7442 \r
7443         return ret;\r
7444 }\r
7445 \r
7446 // このコンピュータのコンピュータ名を取得\r
7447 void GetMachineName(char *name, UINT size)\r
7448 {\r
7449         GetMachineNameEx(name, size, false);\r
7450 }\r
7451 void GetMachineNameEx(char *name, UINT size, bool no_load_hosts)\r
7452 {\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
7457         IP ip;\r
7458         // 引数チェック\r
7459         if (name == NULL)\r
7460         {\r
7461                 return;\r
7462         }\r
7463 \r
7464         Lock(machine_name_lock);\r
7465         {\r
7466                 if (name_cached != false)\r
7467                 {\r
7468                         StrCpy(name, size, name_cache);\r
7469                         Unlock(machine_name_lock);\r
7470                         return;\r
7471                 }\r
7472                 if (gethostname(tmp, MAX_SIZE) != 0)\r
7473                 {\r
7474                         StrCpy(name, size, "Unknown");\r
7475                         Unlock(machine_name_lock);\r
7476                         return;\r
7477                 }\r
7478                 if (GetIP(&ip, tmp) == false)\r
7479                 {\r
7480                         StrCpy(name, size, tmp);\r
7481                         Unlock(machine_name_lock);\r
7482                         return;\r
7483                 }\r
7484                 if (GetHostNameInner(name, size, &ip) == false || StartWith(name, "localhost"))\r
7485                 {\r
7486                         StrCpy(name, size, tmp);\r
7487                 }\r
7488                 if (StartWith(name, "localhost"))\r
7489                 {\r
7490                         if (no_load_hosts == false && OS_IS_UNIX(GetOsInfo()->OsType))\r
7491                         {\r
7492                                 if (GetMachineNameFromHosts(tmp2, sizeof(tmp2)))\r
7493                                 {\r
7494                                         StrCpy(name, sizeof(name), tmp2);\r
7495                                 }\r
7496                         }\r
7497                 }\r
7498 \r
7499                 StrCpy(name_cache, sizeof(name_cache), name);\r
7500                 name_cached = true;\r
7501         }\r
7502         Unlock(machine_name_lock);\r
7503 }\r
7504 \r
7505 // ホスト名取得スレッド\r
7506 void GetHostNameThread(THREAD *t, void *p)\r
7507 {\r
7508         IP *ip;\r
7509         char hostname[256];\r
7510         // 引数チェック\r
7511         if (t == NULL || p == NULL)\r
7512         {\r
7513                 return;\r
7514         }\r
7515 \r
7516         ip = (IP *)p;\r
7517 \r
7518         AddWaitThread(t);\r
7519 \r
7520         NoticeThreadInit(t);\r
7521 \r
7522         if (GetHostNameInner(hostname, sizeof(hostname), ip))\r
7523         {\r
7524                 AddHostCache(ip, hostname);\r
7525         }\r
7526 \r
7527         Free(ip);\r
7528 \r
7529         DelWaitThread(t);\r
7530 }\r
7531 \r
7532 // ホスト名の取得\r
7533 bool GetHostName(char *hostname, UINT size, IP *ip)\r
7534 {\r
7535         THREAD *t;\r
7536         IP *p_ip;\r
7537         bool ret;\r
7538         // 引数チェック\r
7539         if (hostname == NULL || ip == NULL)\r
7540         {\r
7541                 return false;\r
7542         }\r
7543 \r
7544         if (GetHostCache(hostname, size, ip))\r
7545         {\r
7546                 if (IsEmptyStr(hostname) == false)\r
7547                 {\r
7548                         return true;\r
7549                 }\r
7550                 else\r
7551                 {\r
7552                         return false;\r
7553                 }\r
7554         }\r
7555 \r
7556         p_ip = ZeroMalloc(sizeof(IP));\r
7557         Copy(p_ip, ip, sizeof(IP));\r
7558 \r
7559         t = NewThread(GetHostNameThread, p_ip);\r
7560 \r
7561         WaitThreadInit(t);\r
7562 \r
7563         WaitThread(t, TIMEOUT_HOSTNAME);\r
7564 \r
7565         ReleaseThread(t);\r
7566 \r
7567         ret = GetHostCache(hostname, size, ip);\r
7568         if (ret == false)\r
7569         {\r
7570                 if (IsIP4(ip))\r
7571                 {\r
7572                         ret = GetNetBiosName(hostname, size, ip);\r
7573                         if (ret)\r
7574                         {\r
7575                                 AddHostCache(ip, hostname);\r
7576                         }\r
7577                 }\r
7578         }\r
7579         else\r
7580         {\r
7581                 if (IsEmptyStr(hostname))\r
7582                 {\r
7583                         ret = false;\r
7584                 }\r
7585         }\r
7586         if (ret == false)\r
7587         {\r
7588                 AddHostCache(ip, "");\r
7589                 StrCpy(hostname, size, "");\r
7590         }\r
7591 \r
7592         return ret;\r
7593 }\r
7594 \r
7595 // DNS 逆引きクエリを行う\r
7596 bool GetHostNameInner(char *hostname, UINT size, IP *ip)\r
7597 {\r
7598         struct in_addr addr;\r
7599         struct sockaddr_in sa;\r
7600         char tmp[MAX_SIZE];\r
7601         char ip_str[64];\r
7602         // 引数チェック\r
7603         if (hostname == NULL || ip == NULL)\r
7604         {\r
7605                 return false;\r
7606         }\r
7607 \r
7608         if (IsIP6(ip))\r
7609         {\r
7610                 return GetHostNameInner6(hostname, size, ip);\r
7611         }\r
7612 \r
7613         // 逆引き\r
7614         IPToInAddr(&addr, ip);\r
7615         Zero(&sa, sizeof(sa));\r
7616         sa.sin_family = AF_INET;\r
7617 \r
7618 #if     defined(UNIX_BSD) || defined(UNIX_MACOS)\r
7619         sa.sin_len = INET_ADDRSTRLEN;\r
7620 #endif  // UNIX_BSD || UNIX_MACOS\r
7621 \r
7622         Copy(&sa.sin_addr, &addr, sizeof(struct in_addr));\r
7623         sa.sin_port = 0;\r
7624 \r
7625         if (getnameinfo((struct sockaddr *)&sa, sizeof(sa), tmp, sizeof(tmp), NULL, 0, 0) != 0)\r
7626         {\r
7627                 return false;\r
7628         }\r
7629 \r
7630         IPToStr(ip_str, sizeof(ip_str), ip);\r
7631 \r
7632         if (StrCmpi(tmp, ip_str) == 0)\r
7633         {\r
7634                 return false;\r
7635         }\r
7636 \r
7637         if (IsEmptyStr(tmp))\r
7638         {\r
7639                 return false;\r
7640         }\r
7641 \r
7642         StrCpy(hostname, size, tmp);\r
7643 \r
7644         return true;\r
7645 }\r
7646 bool GetHostNameInner6(char *hostname, UINT size, IP *ip)\r
7647 {\r
7648         struct in6_addr addr;\r
7649         struct sockaddr_in6 sa;\r
7650         char tmp[MAX_SIZE];\r
7651         char ip_str[256];\r
7652         // 引数チェック\r
7653         if (hostname == NULL || ip == NULL)\r
7654         {\r
7655                 return false;\r
7656         }\r
7657 \r
7658         // 逆引き\r
7659         IPToInAddr6(&addr, ip);\r
7660         Zero(&sa, sizeof(sa));\r
7661         sa.sin6_family = AF_INET6;\r
7662 \r
7663 #if     defined(UNIX_BSD) || defined(UNIX_MACOS)\r
7664         sa.sin6_len = INET6_ADDRSTRLEN;\r
7665 #endif  // UNIX_BSD || UNIX_MACOS\r
7666 \r
7667         Copy(&sa.sin6_addr, &addr, sizeof(struct in6_addr));\r
7668         sa.sin6_port = 0;\r
7669 \r
7670         if (getnameinfo((struct sockaddr *)&sa, sizeof(sa), tmp, sizeof(tmp), NULL, 0, 0) != 0)\r
7671         {\r
7672                 return false;\r
7673         }\r
7674 \r
7675         IPToStr(ip_str, sizeof(ip_str), ip);\r
7676 \r
7677         if (StrCmpi(tmp, ip_str) == 0)\r
7678         {\r
7679                 return false;\r
7680         }\r
7681 \r
7682         if (IsEmptyStr(tmp))\r
7683         {\r
7684                 return false;\r
7685         }\r
7686 \r
7687         StrCpy(hostname, size, tmp);\r
7688 \r
7689         return true;\r
7690 }\r
7691 \r
7692 #define NUM_NBT_QUERYS_SEND                     3\r
7693 \r
7694 // IP アドレスからそのマシンの NetBIOS 名を取得する\r
7695 bool GetNetBiosName(char *name, UINT size, IP *ip)\r
7696 {\r
7697         SOCK *s;\r
7698         UINT i, j;\r
7699         bool flag = false;\r
7700         bool ok = false;\r
7701         NBTREQUEST req;\r
7702         UCHAR buf[1024];\r
7703         USHORT tran_id[NUM_NBT_QUERYS_SEND];\r
7704         UINT64 timeout_tick;\r
7705         // 引数チェック\r
7706         if (name == NULL || ip == NULL)\r
7707         {\r
7708                 return false;\r
7709         }\r
7710 \r
7711         IPToStr(name, size, ip);\r
7712 \r
7713         for (i = 0;i < NUM_NBT_QUERYS_SEND;i++)\r
7714         {\r
7715                 tran_id[i] = Rand16();\r
7716         }\r
7717 \r
7718         s = NewUDP(0);\r
7719         if (s == NULL)\r
7720         {\r
7721                 return false;\r
7722         }\r
7723 \r
7724         for (j = 0;j < NUM_NBT_QUERYS_SEND;j++)\r
7725         {\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
7733                 {\r
7734                         req.Query[i] = 0x41;\r
7735                 }\r
7736                 req.Query[35] = 0x21;\r
7737                 req.Query[37] = 0x01;\r
7738 \r
7739                 if (SendTo(s, ip, 137, &req, sizeof(req)) == 0)\r
7740                 {\r
7741                         ReleaseSock(s);\r
7742                         return false;\r
7743                 }\r
7744         }\r
7745 \r
7746         timeout_tick = Tick() + (UINT64)TIMEOUT_NETBIOS_HOSTNAME;\r
7747 \r
7748         while (1)\r
7749         {\r
7750                 UINT ret;\r
7751                 IP src_ip;\r
7752                 UINT src_port;\r
7753                 SOCKSET set;\r
7754                 if (Tick() >= timeout_tick)\r
7755                 {\r
7756                         break;\r
7757                 }\r
7758                 InitSockSet(&set);\r
7759                 AddSockSet(&set, s);\r
7760                 Select(&set, 100, NULL, NULL);\r
7761 \r
7762                 if (flag == false)\r
7763                 {\r
7764                         flag = true;\r
7765                 }\r
7766                 else\r
7767                 {\r
7768                         SleepThread(10);\r
7769                 }\r
7770 \r
7771                 ret = RecvFrom(s, &src_ip, &src_port, buf, sizeof(buf));\r
7772 \r
7773                 if (ret == SOCK_LATER)\r
7774                 {\r
7775                         continue;\r
7776                 }\r
7777                 else if (ret == 0)\r
7778                 {\r
7779                         break;\r
7780                 }\r
7781                 else\r
7782                 {\r
7783                         if (ret >= sizeof(NBTRESPONSE))\r
7784                         {\r
7785                                 NBTRESPONSE *r = (NBTRESPONSE *)buf;\r
7786                                 bool b = false;\r
7787                                 UINT i;\r
7788                                 USHORT id = Endian16(r->TransactionId);\r
7789                                 for (i = 0;i < NUM_NBT_QUERYS_SEND;i++)\r
7790                                 {\r
7791                                         if (id == tran_id[i])\r
7792                                         {\r
7793                                                 b = true;\r
7794                                                 break;\r
7795                                         }\r
7796                                 }\r
7797                                 if (b)\r
7798                                 {\r
7799                                         if (r->Flags != 0 && r->NumQuestions == 0 && r->AnswerRRs >= 1)\r
7800                                         {\r
7801                                                 if (r->Response[0] == 0x20 && r->Response[1] == 0x43 &&\r
7802                                                         r->Response[2] == 0x4b)\r
7803                                                 {\r
7804                                                         if (r->Response[34] == 0x00 && r->Response[35] == 0x21 &&\r
7805                                                                 r->Response[36] == 0x00 && r->Response[37] == 0x01)\r
7806                                                         {\r
7807                                                                 char *a = (char *)(&r->Response[45]);\r
7808                                                                 if (StrCheckLen(a, 15))\r
7809                                                                 {\r
7810                                                                         if (IsEmptyStr(a) == false)\r
7811                                                                         {\r
7812                                                                                 StrCpy(name, size, a);\r
7813                                                                                 Trim(name);\r
7814                                                                                 ok = true;\r
7815                                                                         }\r
7816                                                                         else\r
7817                                                                         {\r
7818                                                                                 ok = false;\r
7819                                                                                 break;\r
7820                                                                         }\r
7821                                                                 }\r
7822                                                         }\r
7823                                                 }\r
7824                                         }\r
7825                                 }\r
7826                         }\r
7827                 }\r
7828         }\r
7829 \r
7830         ReleaseSock(s);\r
7831         return ok;\r
7832 }\r
7833 \r
7834 // IP アドレスを設定する\r
7835 void SetIP(IP *ip, UCHAR a1, UCHAR a2, UCHAR a3, UCHAR a4)\r
7836 {\r
7837         // 引数チェック\r
7838         if (ip == NULL)\r
7839         {\r
7840                 return;\r
7841         }\r
7842 \r
7843         Zero(ip, sizeof(IP));\r
7844         ip->addr[0] = a1;\r
7845         ip->addr[1] = a2;\r
7846         ip->addr[2] = a3;\r
7847         ip->addr[3] = a4;\r
7848 }\r
7849 \r
7850 // DNS 正引きを行って結果を v4 と v6 のどちらかで得る (両方の場合は IPv4 優先)\r
7851 bool GetIP46Any4(IP *ip, char *hostname)\r
7852 {\r
7853         IP ip4, ip6;\r
7854         bool b = false;\r
7855         // 引数チェック\r
7856         if (ip == NULL || hostname == NULL)\r
7857         {\r
7858                 return false;\r
7859         }\r
7860 \r
7861         if (GetIP46(&ip4, &ip6, hostname) == false)\r
7862         {\r
7863                 return false;\r
7864         }\r
7865 \r
7866         if (IsZeroIp(&ip6) == false)\r
7867         {\r
7868                 Copy(ip, &ip6, sizeof(IP));\r
7869 \r
7870                 b = true;\r
7871         }\r
7872 \r
7873         if (IsZeroIp(&ip4) == false)\r
7874         {\r
7875                 Copy(ip, &ip4, sizeof(IP));\r
7876 \r
7877                 b = true;\r
7878         }\r
7879 \r
7880         return b;\r
7881 }\r
7882 \r
7883 // DNS 正引きを行って結果を v4 と v6 のどちらかで得る (両方の場合は IPv6 優先)\r
7884 bool GetIP46Any6(IP *ip, char *hostname)\r
7885 {\r
7886         IP ip4, ip6;\r
7887         bool b = false;\r
7888         // 引数チェック\r
7889         if (ip == NULL || hostname == NULL)\r
7890         {\r
7891                 return false;\r
7892         }\r
7893 \r
7894         if (GetIP46(&ip4, &ip6, hostname) == false)\r
7895         {\r
7896                 return false;\r
7897         }\r
7898 \r
7899         if (IsZeroIp(&ip4) == false)\r
7900         {\r
7901                 Copy(ip, &ip4, sizeof(IP));\r
7902 \r
7903                 b = true;\r
7904         }\r
7905 \r
7906         if (IsZeroIp(&ip6) == false)\r
7907         {\r
7908                 Copy(ip, &ip6, sizeof(IP));\r
7909 \r
7910                 b = true;\r
7911         }\r
7912 \r
7913         return b;\r
7914 }\r
7915 \r
7916 // DNS 正引きを行って結果を v4 と v6 の両方で得る\r
7917 bool GetIP46(IP *ip4, IP *ip6, char *hostname)\r
7918 {\r
7919         return GetIP46Ex(ip4, ip6, hostname, 0, NULL);\r
7920 }\r
7921 bool GetIP46Ex(IP *ip4, IP *ip6, char *hostname, UINT timeout, bool *cancel)\r
7922 {\r
7923         IP a, b;\r
7924         bool ok_a, ok_b;\r
7925         // 引数チェック\r
7926         if (ip4 == NULL || ip6 == NULL || hostname == NULL)\r
7927         {\r
7928                 return false;\r
7929         }\r
7930 \r
7931         ZeroIP4(ip4);\r
7932         ZeroIP6(ip6);\r
7933 \r
7934         ok_a = ok_b = false;\r
7935 \r
7936         if (GetIP6Ex(&a, hostname, timeout, cancel))\r
7937         {\r
7938                 ok_a = true;\r
7939         }\r
7940 \r
7941         if (GetIP4Ex(&b, hostname, timeout, cancel))\r
7942         {\r
7943                 ok_b = true;\r
7944         }\r
7945 \r
7946         if (ok_a)\r
7947         {\r
7948                 if (IsIP4(&a))\r
7949                 {\r
7950                         Copy(ip4, &a, sizeof(IP));\r
7951                 }\r
7952         }\r
7953         if (ok_b)\r
7954         {\r
7955                 if (IsIP4(&b))\r
7956                 {\r
7957                         Copy(ip4, &b, sizeof(IP));\r
7958                 }\r
7959 \r
7960                 if (IsIP6(&b))\r
7961                 {\r
7962                         Copy(ip6, &b, sizeof(IP));\r
7963                 }\r
7964         }\r
7965         if (ok_a)\r
7966         {\r
7967                 if (IsIP6(&a))\r
7968                 {\r
7969                         Copy(ip6, &a, sizeof(IP));\r
7970                 }\r
7971         }\r
7972 \r
7973         if (IsZeroIp(ip4) && IsZeroIp(ip6))\r
7974         {\r
7975                 return false;\r
7976         }\r
7977 \r
7978         return true;\r
7979 }\r
7980 \r
7981 // GetIP 用スレッドのパラメータのクリーンアップ\r
7982 void CleanupGetIPThreadParam(GETIP_THREAD_PARAM *p)\r
7983 {\r
7984         // 引数チェック\r
7985         if (p == NULL)\r
7986         {\r
7987                 return;\r
7988         }\r
7989 \r
7990         Free(p);\r
7991 }\r
7992 \r
7993 // GetIP 用スレッドのパラメータの解放\r
7994 void ReleaseGetIPThreadParam(GETIP_THREAD_PARAM *p)\r
7995 {\r
7996         // 引数チェック\r
7997         if (p == NULL)\r
7998         {\r
7999                 return;\r
8000         }\r
8001 \r
8002         if (Release(p->Ref) == 0)\r
8003         {\r
8004                 CleanupGetIPThreadParam(p);\r
8005         }\r
8006 }\r
8007 \r
8008 // DNS 正引きクエリ (タイムアウト付き) を行うスレッド\r
8009 void GetIP4Ex6ExThread(THREAD *t, void *param)\r
8010 {\r
8011         GETIP_THREAD_PARAM *p;\r
8012         // 引数チェック\r
8013         if (t == NULL || param == NULL)\r
8014         {\r
8015                 return;\r
8016         }\r
8017 \r
8018         p = (GETIP_THREAD_PARAM *)param;\r
8019 \r
8020         AddRef(p->Ref);\r
8021 \r
8022         NoticeThreadInit(t);\r
8023 \r
8024         AddWaitThread(t);\r
8025 \r
8026         // 解決の実行\r
8027         if (p->IPv6 == false)\r
8028         {\r
8029                 // IPv4\r
8030                 p->Ok = GetIP4Inner(&p->Ip, p->HostName);\r
8031         }\r
8032         else\r
8033         {\r
8034                 // IPv6\r
8035                 p->Ok = GetIP6Inner(&p->Ip, p->HostName);\r
8036         }\r
8037 \r
8038         ReleaseGetIPThreadParam(p);\r
8039 \r
8040         DelWaitThread(t);\r
8041 }\r
8042 \r
8043 // DNS 正引きクエリ (タイムアウト付き) を行う\r
8044 bool GetIP4Ex6Ex(IP *ip, char *hostname, UINT timeout, bool ipv6, bool *cancel)\r
8045 {\r
8046         GETIP_THREAD_PARAM *p;\r
8047         THREAD *t;\r
8048         bool ret = false;\r
8049         UINT64 start_tick = 0;\r
8050         UINT64 end_tick = 0;\r
8051         // 引数チェック\r
8052         if (ip == NULL || hostname == NULL)\r
8053         {\r
8054                 return false;\r
8055         }\r
8056         if (timeout == 0)\r
8057         {\r
8058                 timeout = TIMEOUT_GETIP;\r
8059         }\r
8060 \r
8061         p = ZeroMalloc(sizeof(GETIP_THREAD_PARAM));\r
8062         p->Ref = NewRef();\r
8063         StrCpy(p->HostName, sizeof(p->HostName), hostname);\r
8064         p->IPv6 = ipv6;\r
8065         p->Timeout = timeout;\r
8066         p->Ok = false;\r
8067 \r
8068         t = NewThread(GetIP4Ex6ExThread, p);\r
8069         WaitThreadInit(t);\r
8070 \r
8071         if (cancel == NULL)\r
8072         {\r
8073                 WaitThread(t, timeout);\r
8074         }\r
8075         else\r
8076         {\r
8077                 start_tick = Tick64();\r
8078                 end_tick = start_tick + (UINT64)timeout;\r
8079 \r
8080                 while (true)\r
8081                 {\r
8082                         UINT64 now = Tick64();\r
8083                         UINT64 remain;\r
8084                         UINT remain32;\r
8085 \r
8086                         if (*cancel)\r
8087                         {\r
8088                                 break;\r
8089                         }\r
8090 \r
8091                         if (now >= end_tick)\r
8092                         {\r
8093                                 break;\r
8094                         }\r
8095 \r
8096                         remain = end_tick - now;\r
8097                         remain32 = MIN((UINT)remain, 100);\r
8098 \r
8099                         if (WaitThread(t, remain32))\r
8100                         {\r
8101                                 break;\r
8102                         }\r
8103                 }\r
8104         }\r
8105 \r
8106         ReleaseThread(t);\r
8107 \r
8108         if (p->Ok)\r
8109         {\r
8110                 ret = true;\r
8111                 Copy(ip, &p->Ip, sizeof(IP));\r
8112         }\r
8113 \r
8114         ReleaseGetIPThreadParam(p);\r
8115 \r
8116         return ret;\r
8117 }\r
8118 bool GetIP4Ex(IP *ip, char *hostname, UINT timeout, bool *cancel)\r
8119 {\r
8120         return GetIP4Ex6Ex(ip, hostname, timeout, false, cancel);\r
8121 }\r
8122 bool GetIP6Ex(IP *ip, char *hostname, UINT timeout, bool *cancel)\r
8123 {\r
8124         return GetIP4Ex6Ex(ip, hostname, timeout, true, cancel);\r
8125 }\r
8126 bool GetIP4(IP *ip, char *hostname)\r
8127 {\r
8128         return GetIP4Ex(ip, hostname, 0, NULL);\r
8129 }\r
8130 bool GetIP6(IP *ip, char *hostname)\r
8131 {\r
8132         return GetIP6Ex(ip, hostname, 0, NULL);\r
8133 }\r
8134 \r
8135 // DNS 正引きクエリを行う\r
8136 bool GetIP(IP *ip, char *hostname)\r
8137 {\r
8138         return GetIPEx(ip, hostname, false);\r
8139 }\r
8140 bool GetIPEx(IP *ip, char *hostname, bool ipv6)\r
8141 {\r
8142         if (ipv6 == false)\r
8143         {\r
8144                 return GetIP4(ip, hostname);\r
8145         }\r
8146         else\r
8147         {\r
8148                 return GetIP6(ip, hostname);\r
8149         }\r
8150 }\r
8151 bool GetIP6Inner(IP *ip, char *hostname)\r
8152 {\r
8153         struct sockaddr_in6 in;\r
8154         struct in6_addr addr;\r
8155         struct addrinfo hint;\r
8156         struct addrinfo *info;\r
8157         // 引数チェック\r
8158         if (ip == NULL || hostname == NULL)\r
8159         {\r
8160                 return false;\r
8161         }\r
8162 \r
8163         if (IsEmptyStr(hostname))\r
8164         {\r
8165                 return false;\r
8166         }\r
8167 \r
8168         if (StrCmpi(hostname, "localhost") == 0)\r
8169         {\r
8170                 GetLocalHostIP6(ip);\r
8171                 return true;\r
8172         }\r
8173 \r
8174         if (StrToIP6(ip, hostname) == false && StrToIP(ip, hostname) == false)\r
8175         {\r
8176                 // 正引き\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
8181                 info = NULL;\r
8182 \r
8183                 if (getaddrinfo(hostname, NULL, &hint, &info) != 0 ||\r
8184                         info->ai_family != AF_INET6)\r
8185                 {\r
8186                         if (info)\r
8187                         {\r
8188                                 freeaddrinfo(info);\r
8189                         }\r
8190                         return QueryDnsCacheEx(ip, hostname, true);\r
8191                 }\r
8192                 // 正引き成功\r
8193                 Copy(&in, info->ai_addr, sizeof(struct sockaddr_in6));\r
8194                 freeaddrinfo(info);\r
8195 \r
8196                 Copy(&addr, &in.sin6_addr, sizeof(addr));\r
8197                 InAddrToIP6(ip, &addr);\r
8198         }\r
8199 \r
8200         // キャッシュ保存\r
8201         NewDnsCache(hostname, ip);\r
8202 \r
8203         return true;\r
8204 }\r
8205 bool GetIP4Inner(IP *ip, char *hostname)\r
8206 {\r
8207         struct sockaddr_in in;\r
8208         struct in_addr addr;\r
8209         struct addrinfo hint;\r
8210         struct addrinfo *info;\r
8211         // 引数チェック\r
8212         if (ip == NULL || hostname == NULL)\r
8213         {\r
8214                 return false;\r
8215         }\r
8216 \r
8217         if (IsEmptyStr(hostname))\r
8218         {\r
8219                 return false;\r
8220         }\r
8221 \r
8222         if (StrCmpi(hostname, "localhost") == 0)\r
8223         {\r
8224                 SetIP(ip, 127, 0, 0, 1);\r
8225                 return true;\r
8226         }\r
8227 \r
8228         if (StrToIP6(ip, hostname) == false && StrToIP(ip, hostname) == false)\r
8229         {\r
8230                 // 正引き\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
8235                 info = NULL;\r
8236 \r
8237                 if (getaddrinfo(hostname, NULL, &hint, &info) != 0 ||\r
8238                         info->ai_family != AF_INET)\r
8239                 {\r
8240                         if (info)\r
8241                         {\r
8242                                 freeaddrinfo(info);\r
8243                         }\r
8244                         return QueryDnsCache(ip, hostname);\r
8245                 }\r
8246                 // 正引き成功\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
8251         }\r
8252 \r
8253         // キャッシュ保存\r
8254         NewDnsCache(hostname, ip);\r
8255 \r
8256         return true;\r
8257 }\r
8258 \r
8259 // DNS キャッシュを検索する\r
8260 bool QueryDnsCache(IP *ip, char *hostname)\r
8261 {\r
8262         return QueryDnsCacheEx(ip, hostname, false);\r
8263 }\r
8264 bool QueryDnsCacheEx(IP *ip, char *hostname, bool ipv6)\r
8265 {\r
8266         DNSCACHE *c;\r
8267         char tmp[MAX_SIZE];\r
8268         // 引数チェック\r
8269         if (ip == NULL || hostname == NULL)\r
8270         {\r
8271                 return false;\r
8272         }\r
8273 \r
8274         GenDnsCacheKeyName(tmp, sizeof(tmp), hostname, ipv6);\r
8275 \r
8276         c = FindDnsCache(tmp);\r
8277         if (c == NULL)\r
8278         {\r
8279                 return false;\r
8280         }\r
8281 \r
8282         Copy(ip, &c->IpAddress, sizeof(IP));\r
8283 \r
8284         return true;\r
8285 }\r
8286 \r
8287 // IP を文字列に変換\r
8288 void IPToUniStr(wchar_t *str, UINT size, IP *ip)\r
8289 {\r
8290         char tmp[128];\r
8291 \r
8292         IPToStr(tmp, sizeof(tmp), ip);\r
8293         StrToUni(str, size, tmp);\r
8294 }\r
8295 \r
8296 // IP を文字列に変換 (32bit UINT)\r
8297 void IPToUniStr32(wchar_t *str, UINT size, UINT ip)\r
8298 {\r
8299         char tmp[128];\r
8300 \r
8301         IPToStr32(tmp, sizeof(tmp), ip);\r
8302         StrToUni(str, size, tmp);\r
8303 }\r
8304 \r
8305 // IP を文字列に変換 (128bit byte array)\r
8306 void IPToStr128(char *str, UINT size, UCHAR *ip_bytes)\r
8307 {\r
8308         IP ip_st;\r
8309         // 引数チェック\r
8310         if (str == NULL)\r
8311         {\r
8312                 return;\r
8313         }\r
8314 \r
8315         SetIP6(&ip_st, ip_bytes);\r
8316         IPToStr(str, size, &ip_st);\r
8317 }\r
8318 \r
8319 // IP を文字列に変換 (32bit UINT)\r
8320 void IPToStr32(char *str, UINT size, UINT ip)\r
8321 {\r
8322         IP ip_st;\r
8323         // 引数チェック\r
8324         if (str == NULL)\r
8325         {\r
8326                 return;\r
8327         }\r
8328 \r
8329         UINTToIP(&ip_st, ip);\r
8330         IPToStr(str, size, &ip_st);\r
8331 }\r
8332 \r
8333 // IPv4 または IPv6 を文字列に変換\r
8334 void IPToStr4or6(char *str, UINT size, UINT ip_4_uint, UCHAR *ip_6_bytes)\r
8335 {\r
8336         IP ip4;\r
8337         IP ip6;\r
8338         IP ip;\r
8339         // 引数チェック\r
8340         if (str == NULL)\r
8341         {\r
8342                 return;\r
8343         }\r
8344 \r
8345         Zero(&ip, sizeof(ip));\r
8346 \r
8347         UINTToIP(&ip4, ip_4_uint);\r
8348         SetIP6(&ip6, ip_6_bytes);\r
8349 \r
8350         if (IsIP6(&ip4) || (IsZeroIp(&ip4) && (IsZeroIp(&ip6) == false)))\r
8351         {\r
8352                 Copy(&ip, &ip6, sizeof(IP));\r
8353         }\r
8354         else\r
8355         {\r
8356                 Copy(&ip, &ip4, sizeof(IP));\r
8357         }\r
8358 \r
8359         IPToStr(str, size, &ip);\r
8360 }\r
8361 \r
8362 // IP を文字列に変換\r
8363 void IPToStr(char *str, UINT size, IP *ip)\r
8364 {\r
8365         // 引数チェック\r
8366         if (str == NULL || ip == NULL)\r
8367         {\r
8368                 return;\r
8369         }\r
8370 \r
8371         if (IsIP6(ip))\r
8372         {\r
8373                 IPToStr6(str, size, ip);\r
8374         }\r
8375         else\r
8376         {\r
8377                 IPToStr4(str, size, ip);\r
8378         }\r
8379 }\r
8380 \r
8381 // IPv4 を文字列に変換\r
8382 void IPToStr4(char *str, UINT size, IP *ip)\r
8383 {\r
8384         // 引数チェック\r
8385         if (str == NULL || ip == NULL)\r
8386         {\r
8387                 return;\r
8388         }\r
8389 \r
8390         // 変換\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
8392 }\r
8393 \r
8394 // 文字列を IP に変換\r
8395 bool StrToIP(IP *ip, char *str)\r
8396 {\r
8397         TOKEN_LIST *token;\r
8398         char *tmp;\r
8399         UINT i;\r
8400         // 引数チェック\r
8401         if (ip == NULL || str == NULL)\r
8402         {\r
8403                 return false;\r
8404         }\r
8405 \r
8406         if (StrToIP6(ip, str))\r
8407         {\r
8408                 return true;\r
8409         }\r
8410 \r
8411         Zero(ip, sizeof(IP));\r
8412 \r
8413         tmp = CopyStr(str);\r
8414         Trim(tmp);\r
8415         token = ParseToken(tmp, ".");\r
8416         Free(tmp);\r
8417 \r
8418         if (token->NumTokens != 4)\r
8419         {\r
8420                 FreeToken(token);\r
8421                 return false;\r
8422         }\r
8423         for (i = 0;i < 4;i++)\r
8424         {\r
8425                 char *s = token->Token[i];\r
8426                 if (s[0] < '0' || s[0] > '9' ||\r
8427                         (ToInt(s) >= 256))\r
8428                 {\r
8429                         FreeToken(token);\r
8430                         return false;\r
8431                 }\r
8432         }\r
8433         Zero(ip, sizeof(IP));\r
8434         for (i = 0;i < 4;i++)\r
8435         {\r
8436                 ip->addr[i] = (UCHAR)ToInt(token->Token[i]);\r
8437         }\r
8438 \r
8439         FreeToken(token);\r
8440 \r
8441         return true;\r
8442 }\r
8443 UINT StrToIP32(char *str)\r
8444 {\r
8445         IP ip;\r
8446         // 引数チェック\r
8447         if (str == NULL)\r
8448         {\r
8449                 return 0;\r
8450         }\r
8451 \r
8452         if (StrToIP(&ip, str) == false)\r
8453         {\r
8454                 return 0;\r
8455         }\r
8456 \r
8457         return IPToUINT(&ip);\r
8458 }\r
8459 bool UniStrToIP(IP *ip, wchar_t *str)\r
8460 {\r
8461         char *tmp;\r
8462         bool ret;\r
8463 \r
8464         tmp = CopyUniToStr(str);\r
8465         ret = StrToIP(ip, tmp);\r
8466         Free(tmp);\r
8467 \r
8468         return ret;\r
8469 }\r
8470 UINT UniStrToIP32(wchar_t *str)\r
8471 {\r
8472         UINT ret;\r
8473         char *tmp;\r
8474 \r
8475         tmp = CopyUniToStr(str);\r
8476         ret = StrToIP32(tmp);\r
8477         Free(tmp);\r
8478 \r
8479         return ret;\r
8480 }\r
8481 \r
8482 // IP を in_addr に変換\r
8483 void IPToInAddr(struct in_addr *addr, IP *ip)\r
8484 {\r
8485         UINT i;\r
8486         // 引数チェック\r
8487         if (addr == NULL || ip == NULL)\r
8488         {\r
8489                 return;\r
8490         }\r
8491 \r
8492         Zero(addr, sizeof(struct in_addr));\r
8493 \r
8494         if (IsIP6(ip) == false)\r
8495         {\r
8496                 for (i = 0;i < 4;i++)\r
8497                 {\r
8498                         ((UCHAR *)addr)[i] = ip->addr[i];\r
8499                 }\r
8500         }\r
8501 }\r
8502 \r
8503 // IP を in6_addr に変換\r
8504 void IPToInAddr6(struct in6_addr *addr, IP *ip)\r
8505 {\r
8506         UINT i;\r
8507         // 引数チェック\r
8508         if (addr == NULL || ip == NULL)\r
8509         {\r
8510                 return;\r
8511         }\r
8512 \r
8513         Zero(addr, sizeof(struct in_addr));\r
8514 \r
8515         if (IsIP6(ip))\r
8516         {\r
8517                 for (i = 0;i < 16;i++)\r
8518                 {\r
8519                         ((UCHAR *)addr)[i] = ip->ipv6_addr[i];\r
8520                 }\r
8521         }\r
8522 }\r
8523 \r
8524 // in_addr を IP に変換\r
8525 void InAddrToIP(IP *ip, struct in_addr *addr)\r
8526 {\r
8527         UINT i;\r
8528         // 引数チェック\r
8529         if (ip == NULL || addr == NULL)\r
8530         {\r
8531                 return;\r
8532         }\r
8533 \r
8534         Zero(ip, sizeof(IP));\r
8535 \r
8536         for (i = 0;i < 4;i++)\r
8537         {\r
8538                 ip->addr[i] = ((UCHAR *)addr)[i];\r
8539         }\r
8540 }\r
8541 \r
8542 // in6_addr を IP に変換\r
8543 void InAddrToIP6(IP *ip, struct in6_addr *addr)\r
8544 {\r
8545         UINT i;\r
8546         // 引数チェック\r
8547         if (ip == NULL || addr == NULL)\r
8548         {\r
8549                 return;\r
8550         }\r
8551 \r
8552         ZeroIP6(ip);\r
8553         for (i = 0;i < 16;i++)\r
8554         {\r
8555                 ip->ipv6_addr[i] = ((UCHAR *)addr)[i];\r
8556         }\r
8557 }\r
8558 \r
8559 // DNS キャッシュの検索\r
8560 DNSCACHE *FindDnsCache(char *hostname)\r
8561 {\r
8562         return FindDnsCacheEx(hostname, false);\r
8563 }\r
8564 DNSCACHE *FindDnsCacheEx(char *hostname, bool ipv6)\r
8565 {\r
8566         DNSCACHE *c;\r
8567         char tmp[MAX_SIZE];\r
8568         if (hostname == NULL)\r
8569         {\r
8570                 return NULL;\r
8571         }\r
8572 \r
8573         GenDnsCacheKeyName(tmp, sizeof(tmp), hostname, ipv6);\r
8574 \r
8575         LockDnsCache();\r
8576         {\r
8577                 DNSCACHE t;\r
8578                 t.HostName = tmp;\r
8579                 c = Search(DnsCache, &t);\r
8580         }\r
8581         UnlockDnsCache();\r
8582 \r
8583         return c;\r
8584 }\r
8585 \r
8586 // DNS キャッシュ用の IPv4 / IPv6 キー名を生成\r
8587 void GenDnsCacheKeyName(char *dst, UINT size, char *src, bool ipv6)\r
8588 {\r
8589         // 引数チェック\r
8590         if (dst == NULL || src == NULL)\r
8591         {\r
8592                 return;\r
8593         }\r
8594 \r
8595         if (ipv6 == false)\r
8596         {\r
8597                 StrCpy(dst, size, src);\r
8598         }\r
8599         else\r
8600         {\r
8601                 Format(dst, size, "%s@ipv6", src);\r
8602         }\r
8603 }\r
8604 \r
8605 // 新しい DNS キャッシュの登録\r
8606 void NewDnsCache(char *hostname, IP *ip)\r
8607 {\r
8608         NewDnsCacheEx(hostname, ip, IsIP6(ip));\r
8609 }\r
8610 void NewDnsCacheEx(char *hostname, IP *ip, bool ipv6)\r
8611 {\r
8612         DNSCACHE *c;\r
8613         char tmp[MAX_PATH];\r
8614         // 引数チェック\r
8615         if (hostname == NULL || ip == NULL)\r
8616         {\r
8617                 return;\r
8618         }\r
8619 \r
8620         if (IsNetworkNameCacheEnabled() == false)\r
8621         {\r
8622                 return;\r
8623         }\r
8624 \r
8625         GenDnsCacheKeyName(tmp, sizeof(tmp), hostname, ipv6);\r
8626 \r
8627         LockDnsCache();\r
8628         {\r
8629                 DNSCACHE t;\r
8630 \r
8631                 // まず hostname に該当するものがあるかどうか検索してみる\r
8632                 t.HostName = tmp;\r
8633                 c = Search(DnsCache, &t);\r
8634 \r
8635                 if (c == NULL)\r
8636                 {\r
8637                         // 新規登録\r
8638                         c = ZeroMalloc(sizeof(DNSCACHE));\r
8639                         c->HostName = CopyStr(tmp);\r
8640 \r
8641                         Copy(&c->IpAddress, ip, sizeof(IP));\r
8642 \r
8643                         Add(DnsCache, c);\r
8644                 }\r
8645                 else\r
8646                 {\r
8647                         // 更新\r
8648                         Copy(&c->IpAddress, ip, sizeof(IP));\r
8649                 }\r
8650         }\r
8651         UnlockDnsCache();\r
8652 }\r
8653 \r
8654 // DNS キャッシュの名前比較\r
8655 int CompareDnsCache(void *p1, void *p2)\r
8656 {\r
8657         DNSCACHE *c1, *c2;\r
8658         if (p1 == NULL || p2 == NULL)\r
8659         {\r
8660                 return 0;\r
8661         }\r
8662         c1 = *(DNSCACHE **)p1;\r
8663         c2 = *(DNSCACHE **)p2;\r
8664         if (c1 == NULL || c2 == NULL)\r
8665         {\r
8666                 return 0;\r
8667         }\r
8668 \r
8669         return StrCmpi(c1->HostName, c2->HostName);\r
8670 }\r
8671 \r
8672 // DNS キャッシュの初期化\r
8673 void InitDnsCache()\r
8674 {\r
8675         // リスト作成\r
8676         DnsCache = NewList(CompareDnsCache);\r
8677 }\r
8678 \r
8679 // DNS キャッシュの解放\r
8680 void FreeDnsCache()\r
8681 {\r
8682         LockDnsCache();\r
8683         {\r
8684                 DNSCACHE *c;\r
8685                 UINT i;\r
8686                 for (i = 0;i < LIST_NUM(DnsCache);i++)\r
8687                 {\r
8688                         // エントリのメモリ解放\r
8689                         c = LIST_DATA(DnsCache, i);\r
8690                         Free(c->HostName);\r
8691                         Free(c);\r
8692                 }\r
8693         }\r
8694         UnlockDnsCache();\r
8695 \r
8696         // リスト解放\r
8697         ReleaseList(DnsCache);\r
8698         DnsCache = NULL;\r
8699 }\r
8700 \r
8701 // DNS キャッシュのロック\r
8702 void LockDnsCache()\r
8703 {\r
8704         LockList(DnsCache);\r
8705 }\r
8706 \r
8707 // DNS キャッシュのロック解除\r
8708 void UnlockDnsCache()\r
8709 {\r
8710         UnlockList(DnsCache);\r
8711 }\r
8712 \r
8713 // ネットワーク通信モジュールの初期化\r
8714 void InitNetwork()\r
8715 {\r
8716         num_tcp_connections = NewCounter();\r
8717 \r
8718         // クライアントリストの初期化\r
8719         InitIpClientList();\r
8720 \r
8721         // スレッド関係の初期化\r
8722         InitWaitThread();\r
8723 \r
8724         // ホスト名キャッシュの初期化\r
8725         InitHostCache();\r
8726 \r
8727 #ifdef  OS_WIN32\r
8728         // ソケットライブラリの初期化\r
8729         Win32InitSocketLibrary();\r
8730 #else\r
8731         UnixInitSocketLibrary();\r
8732 #endif  // OS_WIN32\r
8733 \r
8734         // DNS キャッシュの初期化\r
8735         InitDnsCache();\r
8736 \r
8737         // OpenSSL の初期化\r
8738         ssl_ctx = SSL_CTX_new(SSLv23_method());\r
8739 \r
8740         // ロック初期化\r
8741         machine_name_lock = NewLock();\r
8742         disconnect_function_lock = NewLock();\r
8743         aho = 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
8750 \r
8751         cipher_list_token = ParseToken(cipher_list, " ");\r
8752 \r
8753         disable_cache = false;\r
8754 }\r
8755 \r
8756 // ネットワーク名キャッシュの有効化\r
8757 void EnableNetworkNameCache()\r
8758 {\r
8759         disable_cache = false;\r
8760 }\r
8761 \r
8762 // ネットワーク名キャッシュの無効化\r
8763 void DisableNetworkNameCache()\r
8764 {\r
8765         disable_cache = true;\r
8766 }\r
8767 \r
8768 // ネットワーク名キャッシュが有効かどうか取得\r
8769 bool IsNetworkNameCacheEnabled()\r
8770 {\r
8771         return !disable_cache;\r
8772 }\r
8773 \r
8774 // 暗号化アルゴリズムリストを取得\r
8775 TOKEN_LIST *GetCipherList()\r
8776 {\r
8777         return cipher_list_token;\r
8778 }\r
8779 \r
8780 // TCP コネクション数カウンタを取得\r
8781 COUNTER *GetNumTcpConnectionsCounter()\r
8782 {\r
8783         return num_tcp_connections;\r
8784 }\r
8785 \r
8786 // ネットワーク通信モジュールの解放\r
8787 void FreeNetwork()\r
8788 {\r
8789         FreeToken(cipher_list_token);\r
8790         cipher_list_token = NULL;\r
8791 \r
8792         Zero(&unix_dns_server, sizeof(unix_dns_server));\r
8793 \r
8794         // ロック解放\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
8800         DeleteLock(aho);\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
8806 \r
8807         // OpenSSL の解放\r
8808         SSL_CTX_free(ssl_ctx);\r
8809         ssl_ctx = NULL;\r
8810 \r
8811         // スレッド関係の解放\r
8812         FreeWaitThread();\r
8813 \r
8814         // DNS キャッシュの解放\r
8815         FreeDnsCache();\r
8816 \r
8817         // ホスト名キャッシュの解放\r
8818         FreeHostCache();\r
8819 \r
8820 #ifdef  OS_WIN32\r
8821         // ソケットライブラリの解放\r
8822         Win32FreeSocketLibrary();\r
8823 #else\r
8824         UnixFreeSocketLibrary();\r
8825 #endif  // OS_WIN32\r
8826 \r
8827         DeleteCounter(num_tcp_connections);\r
8828         num_tcp_connections = NULL;\r
8829 \r
8830         // クライアントリストの解放\r
8831         FreeIpClientList();\r
8832 }\r
8833 \r
8834 // ソケットリストにソケットを追加する\r
8835 void AddSockList(SOCKLIST *sl, SOCK *s)\r
8836 {\r
8837         // 引数チェック\r
8838         if (sl == NULL || s == NULL)\r
8839         {\r
8840                 return;\r
8841         }\r
8842 \r
8843         LockList(sl->SockList);\r
8844         {\r
8845                 if (IsInList(sl->SockList, s) == false)\r
8846                 {\r
8847                         AddRef(s->ref);\r
8848 \r
8849                         Insert(sl->SockList, s);\r
8850                 }\r
8851         }\r
8852         UnlockList(sl->SockList);\r
8853 }\r
8854 \r
8855 // ソケットリストからソケットを削除する\r
8856 void DelSockList(SOCKLIST *sl, SOCK *s)\r
8857 {\r
8858         // 引数チェック\r
8859         if (sl == NULL || s == NULL)\r
8860         {\r
8861                 return;\r
8862         }\r
8863 \r
8864         LockList(sl->SockList);\r
8865         {\r
8866                 if (Delete(sl->SockList, s))\r
8867                 {\r
8868                         ReleaseSock(s);\r
8869                 }\r
8870         }\r
8871         UnlockList(sl->SockList);\r
8872 }\r
8873 \r
8874 // ソケットリストのソケットをすべて停止させて削除する\r
8875 void StopSockList(SOCKLIST *sl)\r
8876 {\r
8877         SOCK **ss;\r
8878         UINT num, i;\r
8879         // 引数チェック\r
8880         if (sl == NULL)\r
8881         {\r
8882                 return;\r
8883         }\r
8884 \r
8885         LockList(sl->SockList);\r
8886         {\r
8887                 num = LIST_NUM(sl->SockList);\r
8888                 ss = ToArray(sl->SockList);\r
8889 \r
8890                 DeleteAll(sl->SockList);\r
8891         }\r
8892         UnlockList(sl->SockList);\r
8893 \r
8894         for (i = 0;i < num;i++)\r
8895         {\r
8896                 SOCK *s = ss[i];\r
8897 \r
8898                 Disconnect(s);\r
8899                 ReleaseSock(s);\r
8900         }\r
8901 \r
8902         Free(ss);\r
8903 }\r
8904 \r
8905 // ソケットリストの削除\r
8906 void FreeSockList(SOCKLIST *sl)\r
8907 {\r
8908         // 引数チェック\r
8909         if (sl == NULL)\r
8910         {\r
8911                 return;\r
8912         }\r
8913 \r
8914         StopSockList(sl);\r
8915 \r
8916         ReleaseList(sl->SockList);\r
8917 \r
8918         Free(sl);\r
8919 }\r
8920 \r
8921 // ソケットリストの作成\r
8922 SOCKLIST *NewSockList()\r
8923 {\r
8924         SOCKLIST *sl = ZeroMallocFast(sizeof(SOCKLIST));\r
8925 \r
8926         sl->SockList = NewList(NULL);\r
8927 \r
8928         return sl;\r
8929 }\r
8930 \r
8931 // Solarisでのソケットのタイムアウト用スレッド\r
8932 void SocketTimeoutThread(THREAD *t, void *param)\r
8933 {\r
8934         SOCKET_TIMEOUT_PARAM *ttparam;\r
8935         ttparam = (SOCKET_TIMEOUT_PARAM *)param;\r
8936 \r
8937         // タイムアウト時間だけ待つ\r
8938         Select(NULL, ttparam->sock->TimeOut, ttparam->cancel, NULL);\r
8939 \r
8940         // ブロック中ならディスコネクトする\r
8941         if(! ttparam->unblocked)\r
8942         {\r
8943 //              Debug("Socket timeouted\n");\r
8944                 closesocket(ttparam->sock->socket);\r
8945         }\r
8946         else\r
8947         {\r
8948 //              Debug("Socket timeout cancelled\n");\r
8949         }\r
8950 }\r
8951 \r
8952 // タイムアウト用スレッドの初期化と開始\r
8953 SOCKET_TIMEOUT_PARAM *NewSocketTimeout(SOCK *sock)\r
8954 {\r
8955         SOCKET_TIMEOUT_PARAM *ttp;\r
8956         if(! sock->AsyncMode && sock->TimeOut != TIMEOUT_INFINITE)\r
8957         {\r
8958 //              Debug("NewSockTimeout(%u)\n",sock->TimeOut);\r
8959 \r
8960                 ttp = (SOCKET_TIMEOUT_PARAM*)Malloc(sizeof(SOCKET_TIMEOUT_PARAM));\r
8961 \r
8962                 // タイムアウトスレッド用のパラメータをセット\r
8963                 ttp->cancel = NewCancel();\r
8964                 ttp->sock = sock;\r
8965                 ttp->unblocked = false;\r
8966                 ttp->thread = NewThread(SocketTimeoutThread, ttp);\r
8967                 return ttp;\r
8968         }\r
8969         return NULL;\r
8970 }\r
8971 \r
8972 // タイムアウト用スレッドの停止と開放\r
8973 void FreeSocketTimeout(SOCKET_TIMEOUT_PARAM *ttp)\r
8974 {\r
8975         if(ttp == NULL)\r
8976         {\r
8977                 return;\r
8978         }\r
8979 \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
8985         Free(ttp);\r
8986 //      Debug("FreeSocketTimeout succeed\n");\r
8987         return;\r
8988 }\r
8989 \r
8990 // IP アドレスとサブネット マスクのパース\r
8991 bool ParseIpAndSubnetMask46(char *src, IP *ip, IP *mask)\r
8992 {\r
8993         // 引数チェック\r
8994         if (src == NULL || ip == NULL || mask == NULL)\r
8995         {\r
8996                 return false;\r
8997         }\r
8998 \r
8999         if (ParseIpAndMask46(src, ip, mask) == false)\r
9000         {\r
9001                 return false;\r
9002         }\r
9003 \r
9004         if (IsIP4(ip))\r
9005         {\r
9006                 return IsSubnetMask4(mask);\r
9007         }\r
9008         else\r
9009         {\r
9010                 return IsSubnetMask6(mask);\r
9011         }\r
9012 }\r
9013 bool ParseIpAndSubnetMask6(char *src, IP *ip, IP *mask)\r
9014 {\r
9015         if (ParseIpAndSubnetMask46(src, ip, mask) == false)\r
9016         {\r
9017                 return false;\r
9018         }\r
9019 \r
9020         if (IsIP6(ip) == false)\r
9021         {\r
9022                 return false;\r
9023         }\r
9024 \r
9025         return true;\r
9026 }\r
9027 bool ParseIpAndSubnetMask4(char *src, UINT *ip, UINT *mask)\r
9028 {\r
9029         IP ip2, mask2;\r
9030         // 引数チェック\r
9031         if (src == NULL)\r
9032         {\r
9033                 return false;\r
9034         }\r
9035 \r
9036         if (ParseIpAndSubnetMask46(src, &ip2, &mask2) == false)\r
9037         {\r
9038                 return false;\r
9039         }\r
9040 \r
9041         if (IsIP4(&ip2) == false)\r
9042         {\r
9043                 return false;\r
9044         }\r
9045 \r
9046         if (ip != NULL)\r
9047         {\r
9048                 *ip = IPToUINT(&ip2);\r
9049         }\r
9050 \r
9051         if (mask != NULL)\r
9052         {\r
9053                 *mask = IPToUINT(&mask2);\r
9054         }\r
9055 \r
9056         return true;\r
9057 }\r
9058 \r
9059 \r
9060 // IP アドレスとマスクのパース\r
9061 bool ParseIpAndMask46(char *src, IP *ip, IP *mask)\r
9062 {\r
9063         TOKEN_LIST *t;\r
9064         char *ipstr;\r
9065         char *subnetstr;\r
9066         bool ret = false;\r
9067         IP ip2;\r
9068         IP mask2;\r
9069         // 引数チェック\r
9070         if (src == NULL || ip == NULL || mask == NULL)\r
9071         {\r
9072                 return false;\r
9073         }\r
9074 \r
9075         Zero(&ip2, sizeof(IP));\r
9076         Zero(&mask2, sizeof(IP));\r
9077 \r
9078         t = ParseToken(src, "/");\r
9079         if (t->NumTokens != 2)\r
9080         {\r
9081                 FreeToken(t);\r
9082                 return false;\r
9083         }\r
9084 \r
9085         ipstr = t->Token[0];\r
9086         subnetstr = t->Token[1];\r
9087         Trim(ipstr);\r
9088         Trim(subnetstr);\r
9089 \r
9090         if (StrToIP(&ip2, ipstr))\r
9091         {\r
9092                 if (StrToIP(&mask2, subnetstr))\r
9093                 {\r
9094                         // IP アドレス部とマスク部が同一の種類かどうか比較する\r
9095                         if (IsIP6(&ip2) && IsIP6(&mask2))\r
9096                         {\r
9097                                 // 両方とも IPv6\r
9098                                 ret = true;\r
9099                                 Copy(ip, &ip2, sizeof(IP));\r
9100                                 Copy(mask, &mask2, sizeof(IP));\r
9101                         }\r
9102                         else if (IsIP4(&ip2) && IsIP4(&mask2))\r
9103                         {\r
9104                                 // 両方とも IPv4\r
9105                                 ret = true;\r
9106                                 Copy(ip, &ip2, sizeof(IP));\r
9107                                 Copy(mask, &mask2, sizeof(IP));\r
9108                         }\r
9109                 }\r
9110                 else\r
9111                 {\r
9112                         if (IsNum(subnetstr))\r
9113                         {\r
9114                                 UINT i = ToInt(subnetstr);\r
9115                                 // マスク部が数値\r
9116                                 if (IsIP6(&ip2) && i <= 128)\r
9117                                 {\r
9118                                         ret = true;\r
9119                                         Copy(ip, &ip2, sizeof(IP));\r
9120                                         IntToSubnetMask6(mask, i);\r
9121                                 }\r
9122                                 else if (i <= 32)\r
9123                                 {\r
9124                                         ret = true;\r
9125                                         Copy(ip, &ip2, sizeof(IP));\r
9126                                         IntToSubnetMask4(mask, i);\r
9127                                 }\r
9128                         }\r
9129                 }\r
9130         }\r
9131 \r
9132         FreeToken(t);\r
9133 \r
9134         return ret;\r
9135 }\r
9136 bool ParseIpAndMask4(char *src, UINT *ip, UINT *mask)\r
9137 {\r
9138         IP ip_ip, ip_mask;\r
9139         if (ParseIpAndMask46(src, &ip_ip, &ip_mask) == false)\r
9140         {\r
9141                 return false;\r
9142         }\r
9143 \r
9144         if (IsIP4(&ip_ip) == false)\r
9145         {\r
9146                 return false;\r
9147         }\r
9148 \r
9149         if (ip != NULL)\r
9150         {\r
9151                 *ip = IPToUINT(&ip_ip);\r
9152         }\r
9153 \r
9154         if (mask != NULL)\r
9155         {\r
9156                 *mask = IPToUINT(&ip_mask);\r
9157         }\r
9158 \r
9159         return true;\r
9160 }\r
9161 bool ParseIpAndMask6(char *src, IP *ip, IP *mask)\r
9162 {\r
9163         if (ParseIpAndMask46(src, ip, mask) == false)\r
9164         {\r
9165                 return false;\r
9166         }\r
9167 \r
9168         if (IsIP6(ip) == false)\r
9169         {\r
9170                 return false;\r
9171         }\r
9172 \r
9173         return true;\r
9174 }\r
9175 \r
9176 \r
9177 // IPv4 アドレスの指定が正しいかどうかチェックする\r
9178 bool IsIpStr4(char *str)\r
9179 {\r
9180         // 引数チェック\r
9181         if (str == NULL)\r
9182         {\r
9183                 return false;\r
9184         }\r
9185 \r
9186         if (StrToIP32(str) == 0 && StrCmpi(str, "0.0.0.0") != 0)\r
9187         {\r
9188                 return false;\r
9189         }\r
9190 \r
9191         return true;\r
9192 }\r
9193 \r
9194 // IPv6 アドレスの指定が正しいかどうかチェックする\r
9195 bool IsIpStr6(char *str)\r
9196 {\r
9197         IP ip;\r
9198         // 引数チェック\r
9199         if (str == NULL)\r
9200         {\r
9201                 return false;\r
9202         }\r
9203 \r
9204         if (StrToIP6(&ip, str) == false)\r
9205         {\r
9206                 return false;\r
9207         }\r
9208 \r
9209         return true;\r
9210 }\r
9211 \r
9212 // IP アドレスの指定が正しいかどうかチェックする\r
9213 bool IsIpStr46(char *str)\r
9214 {\r
9215         if (IsIpStr4(str) || IsIpStr6(str))\r
9216         {\r
9217                 return true;\r
9218         }\r
9219 \r
9220         return false;\r
9221 }\r
9222 \r
9223 \r
9224 // 文字列を IPv4 マスクに変換\r
9225 bool StrToMask4(IP *mask, char *str)\r
9226 {\r
9227         // 引数チェック\r
9228         if (mask == NULL || str == NULL)\r
9229         {\r
9230                 return false;\r
9231         }\r
9232 \r
9233         if (str[0] == '/')\r
9234         {\r
9235                 str++;\r
9236         }\r
9237 \r
9238         if (IsNum(str))\r
9239         {\r
9240                 UINT n = ToInt(str);\r
9241 \r
9242                 if (n <= 32)\r
9243                 {\r
9244                         IntToSubnetMask4(mask, n);\r
9245                         return true;\r
9246                 }\r
9247                 else\r
9248                 {\r
9249                         return false;\r
9250                 }\r
9251         }\r
9252         else\r
9253         {\r
9254                 if (StrToIP(mask, str) == false)\r
9255                 {\r
9256                         return false;\r
9257                 }\r
9258                 else\r
9259                 {\r
9260                         return IsIP4(mask);\r
9261                 }\r
9262         }\r
9263 }\r
9264 \r
9265 // 文字列を IPv6 マスクに変換\r
9266 bool StrToMask6(IP *mask, char *str)\r
9267 {\r
9268         // 引数チェック\r
9269         if (mask == NULL || str == NULL)\r
9270         {\r
9271                 return false;\r
9272         }\r
9273 \r
9274         if (str[0] == '/')\r
9275         {\r
9276                 str++;\r
9277         }\r
9278 \r
9279         if (IsNum(str))\r
9280         {\r
9281                 UINT n = ToInt(str);\r
9282 \r
9283                 if (n <= 128)\r
9284                 {\r
9285                         IntToSubnetMask6(mask, n);\r
9286                         return true;\r
9287                 }\r
9288                 else\r
9289                 {\r
9290                         return false;\r
9291                 }\r
9292         }\r
9293         else\r
9294         {\r
9295                 if (StrToIP(mask, str) == false)\r
9296                 {\r
9297                         return false;\r
9298                 }\r
9299                 else\r
9300                 {\r
9301                         return IsIP6(mask);\r
9302                 }\r
9303         }\r
9304 }\r
9305 bool StrToMask6Addr(IPV6_ADDR *mask, char *str)\r
9306 {\r
9307         IP ip;\r
9308 \r
9309         if (StrToMask6(&ip, str) == false)\r
9310         {\r
9311                 return false;\r
9312         }\r
9313 \r
9314         if (IPToIPv6Addr(mask, &ip) == false)\r
9315         {\r
9316                 return false;\r
9317         }\r
9318 \r
9319         return true;\r
9320 }\r
9321 \r
9322 // 文字列を IPv4 / IPv6 マスクに変換\r
9323 bool StrToMask46(IP *mask, char *str, bool ipv6)\r
9324 {\r
9325         if (ipv6)\r
9326         {\r
9327                 return StrToMask6(mask, str);\r
9328         }\r
9329         else\r
9330         {\r
9331                 return StrToMask4(mask, str);\r
9332         }\r
9333 }\r
9334 \r
9335 \r
9336 // IPv4 / IPv6 マスクを文字列に変換\r
9337 void MaskToStr(char *str, UINT size, IP *mask)\r
9338 {\r
9339         MaskToStrEx(str, size, mask, false);\r
9340 }\r
9341 void MaskToStrEx(char *str, UINT size, IP *mask, bool always_full_address)\r
9342 {\r
9343         // 引数チェック\r
9344         if (str == NULL || mask == NULL)\r
9345         {\r
9346                 return;\r
9347         }\r
9348 \r
9349         if (always_full_address == false && IsSubnetMask(mask))\r
9350         {\r
9351                 ToStr(str, SubnetMaskToInt(mask));\r
9352         }\r
9353         else\r
9354         {\r
9355                 IPToStr(str, size, mask);\r
9356         }\r
9357 }\r
9358 void MaskToStr32(char *str, UINT size, UINT mask)\r
9359 {\r
9360         MaskToStr32Ex(str, size, mask, false);\r
9361 }\r
9362 void MaskToStr32Ex(char *str, UINT size, UINT mask, bool always_full_address)\r
9363 {\r
9364         IP ip;\r
9365 \r
9366         UINTToIP(&ip, mask);\r
9367 \r
9368         MaskToStrEx(str, size, &ip, always_full_address);\r
9369 }\r
9370 void Mask6AddrToStrEx(char *str, UINT size, IPV6_ADDR *mask, bool always_full_address)\r
9371 {\r
9372         IP ip;\r
9373 \r
9374         // 引数チェック\r
9375         if (str == NULL || mask == NULL)\r
9376         {\r
9377                 StrCpy(str, size, "");\r
9378                 return;\r
9379         }\r
9380 \r
9381         IPv6AddrToIP(&ip, mask);\r
9382 \r
9383         MaskToStrEx(str, size, &ip, always_full_address);\r
9384 }\r
9385 void Mask6AddrToStr(char *str, UINT size, IPV6_ADDR *mask)\r
9386 {\r
9387         Mask6AddrToStrEx(str, size, mask, false);\r
9388 }\r
9389 \r