* copy vendor drop to trunk
[lab.git] / Dev / utvpn / utvpn-unix-v101-7101-public / src / Cedar / Listener.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 // Listener.c\r
79 // リスナー モジュール\r
80 \r
81 #include "CedarPch.h"\r
82 \r
83 // UDP パケットを 1 つ受信した\r
84 void UDPReceivedPacket(CEDAR *cedar, SOCK *s, IP *ip, UINT port, void *data, UINT size)\r
85 {\r
86         SESSION *session;\r
87         UINT *key32;\r
88         UCHAR *buf;\r
89         CONNECTION *c;\r
90         // 引数チェック\r
91         if (s == NULL || ip == NULL || data == NULL || size == 0 || cedar == NULL)\r
92         {\r
93                 return;\r
94         }\r
95 \r
96         if (size < 16)\r
97         {\r
98                 // パケットサイズが足らないので無視\r
99                 return;\r
100         }\r
101         buf = (UCHAR *)data;\r
102         key32 = (UINT *)(buf + 4);\r
103 \r
104 \r
105         // Key32 の値からセッションを取得\r
106         session = GetSessionFromUDPEntry(cedar, Endian32(*key32));\r
107         if (session == NULL)\r
108         {\r
109                 Debug("Invalid UDP Session Key 32: 0x%X\n", *key32);\r
110                 return;\r
111         }\r
112 \r
113         c = session->Connection;\r
114 \r
115         // データを書き込む\r
116         PutUDPPacketData(c, buf, size);\r
117 \r
118         // コネクションに関連付けられている UDP ソケットを書き換える\r
119         Lock(c->lock);\r
120         {\r
121                 if (c->Protocol == CONNECTION_UDP)\r
122                 {\r
123                         if (c->Udp->s != s)\r
124                         {\r
125                                 if (c->Udp->s != NULL)\r
126                                 {\r
127                                         ReleaseSock(c->Udp->s);\r
128                                 }\r
129                                 AddRef(s->ref);\r
130                                 c->Udp->s = s;\r
131                         }\r
132                         Copy(&c->Udp->ip, ip, sizeof(UINT));\r
133                         c->Udp->port = port;\r
134                 }\r
135         }\r
136         Unlock(c->lock);\r
137 \r
138         // キャンセル発動\r
139         Cancel(session->Cancel1);\r
140 \r
141         // セッションを解放\r
142         ReleaseSession(session);\r
143 }\r
144 \r
145 // Accept された TCP コネクションを処理するスレッド\r
146 void TCPAcceptedThread(THREAD *t, void *param)\r
147 {\r
148         TCP_ACCEPTED_PARAM *data;\r
149         LISTENER *r;\r
150         SOCK *s;\r
151         CONNECTION *c;\r
152         bool flag1;\r
153         char tmp[128];\r
154         // 引数チェック\r
155         if (t == NULL || param == NULL)\r
156         {\r
157                 return;\r
158         }\r
159 \r
160         // 初期化\r
161         data = (TCP_ACCEPTED_PARAM *)param;\r
162         r = data->r;\r
163         s = data->s;\r
164         AddRef(r->ref);\r
165         AddRef(s->ref);\r
166 \r
167         // コネクションの作成\r
168         c = NewServerConnection(r->Cedar, s, t);\r
169 \r
170         // Cedar に一時コネクションとして登録する\r
171         AddConnection(c->Cedar, c);\r
172 \r
173         NoticeThreadInit(t);\r
174 \r
175         AcceptInit(s);\r
176         StrCpy(c->ClientHostname, sizeof(c->ClientHostname), s->RemoteHostname);\r
177         IPToStr(tmp, sizeof(tmp), &s->RemoteIP);\r
178         SLog(r->Cedar, "LS_LISTENER_ACCEPT", r->Port, tmp, s->RemoteHostname, s->RemotePort);\r
179 \r
180         // 受付\r
181         ConnectionAccept(c);\r
182         flag1 = c->flag1;\r
183 \r
184         // 解放\r
185         SLog(r->Cedar, "LS_CONNECTION_END_1", c->Name);\r
186         ReleaseConnection(c);\r
187 \r
188         // 解放\r
189         if (flag1 == false)\r
190         {\r
191                 Debug("%s %u flag1 == false\n", __FILE__, __LINE__);\r
192                 IPToStr(tmp, sizeof(tmp), &s->RemoteIP);\r
193                 SLog(r->Cedar, "LS_LISTENER_DISCONNECT", tmp, s->RemotePort);\r
194                 Disconnect(s);\r
195         }\r
196         ReleaseSock(s);\r
197         ReleaseListener(r);\r
198 }\r
199 \r
200 // TCP で Accept されたコネクションがある場合はここに飛ぶ\r
201 void TCPAccepted(LISTENER *r, SOCK *s)\r
202 {\r
203         TCP_ACCEPTED_PARAM *data;\r
204         THREAD *t;\r
205         char tmp[MAX_SIZE];\r
206         UINT num_clients_from_this_ip = 0;\r
207         CEDAR *cedar;\r
208         // 引数チェック\r
209         if (r == NULL || s == NULL)\r
210         {\r
211                 return;\r
212         }\r
213 \r
214         cedar = r->Cedar;\r
215 \r
216         num_clients_from_this_ip = GetNumIpClient(&s->RemoteIP);\r
217 \r
218         IPToStr(tmp, sizeof(tmp), &s->RemoteIP);\r
219 \r
220         data = ZeroMalloc(sizeof(TCP_ACCEPTED_PARAM));\r
221         data->r = r;\r
222         data->s = s;\r
223 \r
224         if (r->ThreadProc == TCPAcceptedThread)\r
225         {\r
226                 Inc(cedar->AcceptingSockets);\r
227         }\r
228 \r
229         t = NewThread(r->ThreadProc, data);\r
230         WaitThreadInit(t);\r
231         Free(data);\r
232         ReleaseThread(t);\r
233 }\r
234 \r
235 // UDP リスナーメインループ\r
236 void ListenerUDPMainLoop(LISTENER *r)\r
237 {\r
238         UCHAR *data;\r
239         // 引数チェック\r
240         if (r == NULL)\r
241         {\r
242                 return;\r
243         }\r
244 \r
245         Debug("ListenerUDPMainLoop Starts.\n");\r
246         r->Status = LISTENER_STATUS_TRYING;\r
247 \r
248         while (true)\r
249         {\r
250                 // UDP ポートでの待機を試みる\r
251                 while (true)\r
252                 {\r
253                         // 停止フラグ検査\r
254                         if (r->Halt)\r
255                         {\r
256                                 // 停止\r
257                                 return;\r
258                         }\r
259 \r
260                         Debug("NewUDP()\n");\r
261                         r->Sock = NewUDP(r->Port);\r
262                         if (r->Sock != NULL)\r
263                         {\r
264                                 // 待機成功\r
265                                 break;\r
266                         }\r
267 \r
268                         // 待機失敗\r
269                         Debug("Failed to NewUDP.\n");\r
270                         Wait(r->Event, LISTEN_RETRY_TIME);\r
271 \r
272                         // 停止フラグ検査\r
273                         if (r->Halt)\r
274                         {\r
275                                 Debug("UDP Halt.\n");\r
276                                 return;\r
277                         }\r
278                 }\r
279 \r
280                 r->Status = LISTENER_STATUS_LISTENING;\r
281                 Debug("Start Listening at UDP Port %u.\n", r->Sock->LocalPort);\r
282 \r
283                 // 停止フラグ検査\r
284                 if (r->Halt)\r
285                 {\r
286                         // 停止\r
287                         goto STOP;\r
288                 }\r
289 \r
290                 // バッファ領域の確保\r
291                 data = Malloc(UDP_PACKET_SIZE);\r
292 \r
293                 // 次のパケットを読み込む\r
294                 while (true)\r
295                 {\r
296                         IP src_ip;\r
297                         UINT src_port;\r
298                         UINT size;\r
299                         SOCKSET set;\r
300 \r
301                         InitSockSet(&set);\r
302                         AddSockSet(&set, r->Sock);\r
303                         Select(&set, SELECT_TIME, NULL, NULL);\r
304 \r
305                         size = RecvFrom(r->Sock, &src_ip, &src_port, data, UDP_PACKET_SIZE);\r
306                         if (((size == 0) && (r->Sock->IgnoreRecvErr == false)) || r->Halt)\r
307                         {\r
308                                 // エラーが発生した\r
309 STOP:\r
310                                 Disconnect(r->Sock);\r
311                                 ReleaseSock(r->Sock);\r
312                                 r->Sock = NULL;\r
313                                 Debug("UDP Listen Stopped.\n");\r
314                                 Free(data);\r
315                                 break;\r
316                         }\r
317 \r
318                         // UDP パケットを 1 つ受信した\r
319                         if (size != SOCK_LATER)\r
320                         {\r
321                                 UDPReceivedPacket(r->Cedar, r->Sock, &src_ip, src_port, data, size);\r
322                         }\r
323                 }\r
324         }\r
325 }\r
326 \r
327 // TCP リスナーメインループ\r
328 void ListenerTCPMainLoop(LISTENER *r)\r
329 {\r
330         SOCK *new_sock;\r
331         SOCK *s;\r
332         UINT num_failed;\r
333         // 引数チェック\r
334         if (r == NULL)\r
335         {\r
336                 return;\r
337         }\r
338 \r
339         Debug("ListenerTCPMainLoop Starts.\n");\r
340         r->Status = LISTENER_STATUS_TRYING;\r
341 \r
342         while (true)\r
343         {\r
344                 bool first_failed = true;\r
345                 Debug("Status = LISTENER_STATUS_TRYING\n");\r
346                 r->Status = LISTENER_STATUS_TRYING;\r
347 \r
348                 // Listen を試みる\r
349                 while (true)\r
350                 {\r
351                         UINT interval;\r
352                         // 停止フラグ検査\r
353                         if (r->Halt)\r
354                         {\r
355                                 // 停止\r
356                                 return;\r
357                         }\r
358 \r
359                         if (r->ShadowIPv6 == false)\r
360                         {\r
361                                 s = ListenEx(r->Port, r->LocalOnly);\r
362                         }\r
363                         else\r
364                         {\r
365                                 s = ListenEx6(r->Port, r->LocalOnly);\r
366                         }\r
367 \r
368                         if (s != NULL)\r
369                         {\r
370                                 // Listen 成功\r
371                                 AddRef(s->ref);\r
372                                 r->Sock = s;\r
373                                 if (r->ShadowIPv6 == false)\r
374                                 {\r
375                                         SLog(r->Cedar, "LS_LISTENER_START_2", r->Port);\r
376                                 }\r
377                                 break;\r
378                         }\r
379 \r
380                         // Listen 失敗\r
381                         if (first_failed)\r
382                         {\r
383                                 first_failed = false;\r
384                                 if (r->ShadowIPv6 == false)\r
385                                 {\r
386                                         SLog(r->Cedar, "LS_LISTENER_START_3", r->Port, LISTEN_RETRY_TIME / 1000);\r
387                                 }\r
388                         }\r
389 \r
390                         interval = LISTEN_RETRY_TIME;\r
391 \r
392                         if (r->ShadowIPv6)\r
393                         {\r
394                                 if (IsIPv6Supported() == false)\r
395                                 {\r
396                                         interval = LISTEN_RETRY_TIME_NOIPV6;\r
397 \r
398                                         Debug("IPv6 is not supported.\n");\r
399                                 }\r
400                         }\r
401 \r
402                         Wait(r->Event, interval);\r
403 \r
404                         // 停止フラグ検査\r
405                         if (r->Halt)\r
406                         {\r
407                                 // 停止\r
408                                 Debug("Listener Halt.\n");\r
409                                 return;\r
410                         }\r
411                 }\r
412 \r
413                 r->Status = LISTENER_STATUS_LISTENING;\r
414                 Debug("Status = LISTENER_STATUS_LISTENING\n");\r
415 \r
416                 // 停止フラグ検査\r
417                 if (r->Halt)\r
418                 {\r
419                         // 停止\r
420                         goto STOP;\r
421                 }\r
422 \r
423                 num_failed = 0;\r
424 \r
425                 // Accpet ループ\r
426                 while (true)\r
427                 {\r
428                         // Accept を行う\r
429                         Debug("Accept()\n");\r
430                         new_sock = Accept(r->Sock);\r
431                         if (new_sock != NULL)\r
432                         {\r
433                                 // Accept 成功\r
434                                 Debug("Accepted.\n");\r
435                                 TCPAccepted(r, new_sock);\r
436                                 ReleaseSock(new_sock);\r
437                         }\r
438                         else\r
439                         {\r
440                                 if (r->Halt == false)\r
441                                 {\r
442                                         if ((++num_failed) <= 5)\r
443                                         {\r
444                                                 continue;\r
445                                         }\r
446                                 }\r
447 STOP:\r
448                                 Debug("Accept Canceled.\n");\r
449                                 // Accept に失敗した (ソケットが破壊された)\r
450                                 // Listen しているソケットを閉じる\r
451                                 Disconnect(s);\r
452                                 ReleaseSock(s);\r
453                                 break;\r
454                         }\r
455                 }\r
456 \r
457                 // 停止フラグ検査\r
458                 if (r->Halt)\r
459                 {\r
460                         // 停止\r
461                         Debug("Listener Halt.\n");\r
462                         return;\r
463                 }\r
464         }\r
465 }\r
466 \r
467 // リスナーのスレッド\r
468 void ListenerThread(THREAD *thread, void *param)\r
469 {\r
470         LISTENER *r;\r
471         // 引数チェック\r
472         if (thread == NULL || param == NULL)\r
473         {\r
474                 return;\r
475         }\r
476 \r
477         // 初期化\r
478         r = (LISTENER *)param;\r
479         AddRef(r->ref);\r
480         r->Thread = thread;\r
481         AddRef(thread->ref);\r
482         NoticeThreadInit(thread);\r
483 \r
484         // メインループ\r
485         switch (r->Protocol)\r
486         {\r
487         case LISTENER_TCP:\r
488                 // TCP プロトコル\r
489                 ListenerTCPMainLoop(r);\r
490                 break;\r
491 \r
492         case LISTENER_UDP:\r
493                 // UDP プロトコル\r
494                 ListenerUDPMainLoop(r);\r
495                 break;\r
496         }\r
497 \r
498         // 解放\r
499         ReleaseListener(r);\r
500 }\r
501 \r
502 // リスナーの停止\r
503 void StopListener(LISTENER *r)\r
504 {\r
505         UINT port;\r
506         // 引数チェック\r
507         if (r == NULL)\r
508         {\r
509                 return;\r
510         }\r
511 \r
512         if (r->Halt)\r
513         {\r
514                 return;\r
515         }\r
516 \r
517         port = r->Port;\r
518 \r
519         // 停止フラグセット\r
520         r->Halt = true;\r
521 \r
522         if (r->ShadowIPv6 == false)\r
523         {\r
524                 SLog(r->Cedar, "LS_LISTENER_STOP_1", port);\r
525         }\r
526 \r
527         // ソケットを閉じる\r
528         Disconnect(r->Sock);\r
529 \r
530         // イベントのセット\r
531         Set(r->Event);\r
532 \r
533         // スレッドが停止するまで待機\r
534         WaitThread(r->Thread, INFINITE);\r
535 \r
536         // 影のリスナーを停止させる\r
537         if (r->ShadowIPv6 == false)\r
538         {\r
539                 if (r->ShadowListener != NULL)\r
540                 {\r
541                         StopListener(r->ShadowListener);\r
542 \r
543                         ReleaseListener(r->ShadowListener);\r
544 \r
545                         r->ShadowListener = NULL;\r
546                 }\r
547         }\r
548 \r
549         if (r->ShadowIPv6 == false)\r
550         {\r
551                 SLog(r->Cedar, "LS_LISTENER_STOP_2", port);\r
552         }\r
553 }\r
554 \r
555 // リスナーのクリーンアップ\r
556 void CleanupListener(LISTENER *r)\r
557 {\r
558         // 引数チェック\r
559         if (r == NULL)\r
560         {\r
561                 return;\r
562         }\r
563 \r
564         if (r->Sock != NULL)\r
565         {\r
566                 ReleaseSock(r->Sock);\r
567         }\r
568 \r
569         DeleteLock(r->lock);\r
570         ReleaseThread(r->Thread);\r
571         ReleaseEvent(r->Event);\r
572 \r
573         ReleaseCedar(r->Cedar);\r
574 \r
575         Free(r);\r
576 }\r
577 \r
578 // リスナーの解放\r
579 void ReleaseListener(LISTENER *r)\r
580 {\r
581         // 引数チェック\r
582         if (r == NULL)\r
583         {\r
584                 return;\r
585         }\r
586 \r
587         if (Release(r->ref) == 0)\r
588         {\r
589                 CleanupListener(r);\r
590         }\r
591 }\r
592 \r
593 // UDP エントリリストの比較関数\r
594 int CompareUDPEntry(void *p1, void *p2)\r
595 {\r
596         UDP_ENTRY *e1, *e2;\r
597         if (p1 == NULL || p2 == NULL)\r
598         {\r
599                 return 0;\r
600         }\r
601         e1 = *(UDP_ENTRY **)p1;\r
602         e2 = *(UDP_ENTRY **)p2;\r
603         if (e1 == NULL || e2 == NULL)\r
604         {\r
605                 return 0;\r
606         }\r
607 \r
608         if (e1->SessionKey32 > e2->SessionKey32)\r
609         {\r
610                 return 1;\r
611         }\r
612         else if (e1->SessionKey32 == e2->SessionKey32)\r
613         {\r
614                 return 0;\r
615         }\r
616         else\r
617         {\r
618                 return -1;\r
619         }\r
620 }\r
621 \r
622 // リスナーの比較関数\r
623 int CompareListener(void *p1, void *p2)\r
624 {\r
625         LISTENER *r1, *r2;\r
626         if (p1 == NULL || p2 == NULL)\r
627         {\r
628                 return 0;\r
629         }\r
630         r1 = *(LISTENER **)p1;\r
631         r2 = *(LISTENER **)p2;\r
632         if (r1 == NULL || r2 == NULL)\r
633         {\r
634                 return 0;\r
635         }\r
636 \r
637         if (r1->Protocol > r2->Protocol)\r
638         {\r
639                 return 1;\r
640         }\r
641         else if (r1->Protocol < r2->Protocol)\r
642         {\r
643                 return -1;\r
644         }\r
645         else if (r1->Port > r2->Port)\r
646         {\r
647                 return 1;\r
648         }\r
649         else if (r1->Port < r2->Port)\r
650         {\r
651                 return -1;\r
652         }\r
653         else\r
654         {\r
655                 return 0;\r
656         }\r
657 }\r
658 \r
659 // 新しいリスナーの作成\r
660 LISTENER *NewListener(CEDAR *cedar, UINT proto, UINT port)\r
661 {\r
662         return NewListenerEx(cedar, proto, port, TCPAcceptedThread, NULL);\r
663 }\r
664 LISTENER *NewListenerEx(CEDAR *cedar, UINT proto, UINT port, THREAD_PROC *proc, void *thread_param)\r
665 {\r
666         return NewListenerEx2(cedar, proto, port, proc, thread_param, false);\r
667 }\r
668 LISTENER *NewListenerEx2(CEDAR *cedar, UINT proto, UINT port, THREAD_PROC *proc, void *thread_param, bool local_only)\r
669 {\r
670         return NewListenerEx3(cedar, proto, port, proc, thread_param, local_only, false);\r
671 }\r
672 LISTENER *NewListenerEx3(CEDAR *cedar, UINT proto, UINT port, THREAD_PROC *proc, void *thread_param, bool local_only, bool shadow_ipv6)\r
673 {\r
674         LISTENER *r;\r
675         THREAD *t;\r
676         // 引数チェック\r
677         if (port == 0 || cedar == NULL)\r
678         {\r
679                 return NULL;\r
680         }\r
681         // プロトコル番号のチェック\r
682         if (proto != LISTENER_TCP && proto != LISTENER_UDP)\r
683         {\r
684                 return NULL;\r
685         }\r
686 \r
687         r = ZeroMalloc(sizeof(LISTENER));\r
688 \r
689         r->ThreadProc = proc;\r
690         r->ThreadParam = thread_param;\r
691         r->Cedar = cedar;\r
692         AddRef(r->Cedar->ref);\r
693         r->lock = NewLock();\r
694         r->ref = NewRef();\r
695         r->Protocol = proto;\r
696         r->Port = port;\r
697         r->Event = NewEvent();\r
698         r->LocalOnly = local_only;\r
699         r->ShadowIPv6 = shadow_ipv6;\r
700 \r
701         if (r->ShadowIPv6 == false)\r
702         {\r
703                 SLog(cedar, "LS_LISTENER_START_1", port);\r
704         }\r
705 \r
706         // スレッドの作成\r
707         t = NewThread(ListenerThread, r);\r
708         WaitThreadInit(t);\r
709         ReleaseThread(t);\r
710 \r
711         if (r->ShadowIPv6 == false)\r
712         {\r
713                 if (r->Cedar->DisableIPv6Listener == false)\r
714                 {\r
715                         // 影のリスナーを追加する\r
716                         r->ShadowListener = NewListenerEx3(cedar, proto, port, proc, thread_param,\r
717                                 local_only, true);\r
718                 }\r
719         }\r
720 \r
721         if (r->ShadowIPv6 == false)\r
722         {\r
723                 // Cedar に追加\r
724                 AddListener(cedar, r);\r
725         }\r
726 \r
727         return r;\r
728 }\r
729 \r
730 // セッションキーからセッションを取得する\r
731 SESSION *GetSessionFromUDPEntry(CEDAR *cedar, UINT key32)\r
732 {\r
733         UDP_ENTRY *e, t;\r
734         SESSION *s;\r
735         // 引数チェック\r
736         if (cedar == NULL)\r
737         {\r
738                 return NULL;\r
739         }\r
740 \r
741         t.SessionKey32 = key32;\r
742 \r
743         LockList(cedar->UDPEntryList);\r
744         {\r
745                 e = Search(cedar->UDPEntryList, &t);\r
746                 if (e == NULL)\r
747                 {\r
748                         UnlockList(cedar->UDPEntryList);\r
749                         return NULL;\r
750                 }\r
751                 s = e->Session;\r
752                 AddRef(s->ref);\r
753         }\r
754         UnlockList(cedar->UDPEntryList);\r
755 \r
756         return s;\r
757 }\r
758 \r
759 // UDP セッションを UDP エントリから削除する\r
760 void DelUDPEntry(CEDAR *cedar, SESSION *session)\r
761 {\r
762         UINT num, i;\r
763         // 引数チェック\r
764         if (cedar == NULL || session == NULL)\r
765         {\r
766                 return;\r
767         }\r
768 \r
769         LockList(cedar->UDPEntryList);\r
770         {\r
771                 num = LIST_NUM(cedar->UDPEntryList);\r
772                 for (i = 0;i < num;i++)\r
773                 {\r
774                         UDP_ENTRY *e = LIST_DATA(cedar->UDPEntryList, i);\r
775                         if (e->Session == session)\r
776                         {\r
777                                 ReleaseSession(e->Session);\r
778                                 Delete(cedar->UDPEntryList, e);\r
779                                 Free(e);\r
780                                 UnlockList(cedar->UDPEntryList);\r
781                                 Debug("UDP_Entry Deleted.\n");\r
782                                 return;\r
783                         }\r
784                 }\r
785         }\r
786         UnlockList(cedar->UDPEntryList);\r
787 }\r
788 \r
789 // UDP セッションを UDP エントリに追加する\r
790 void AddUDPEntry(CEDAR *cedar, SESSION *session)\r
791 {\r
792         UDP_ENTRY *e;\r
793         // 引数チェック\r
794         if (cedar == NULL || session == NULL)\r
795         {\r
796                 return;\r
797         }\r
798 \r
799         e = ZeroMalloc(sizeof(UDP_ENTRY));\r
800         e->Session = session;\r
801         e->SessionKey32 = session->SessionKey32;\r
802         AddRef(session->ref);\r
803 \r
804         LockList(cedar->UDPEntryList);\r
805         {\r
806                 Add(cedar->UDPEntryList, e);\r
807         }\r
808         UnlockList(cedar->UDPEntryList);\r
809 \r
810         Debug("UDP_Entry Added.\n");\r
811 }\r
812 \r
813 // UDP エントリのクリア\r
814 void CleanupUDPEntry(CEDAR *cedar)\r
815 {\r
816         // 引数チェック\r
817         if (cedar == NULL)\r
818         {\r
819                 return;\r
820         }\r
821 }\r
822 \r
823 \r