* tar xzf utvpn-src-unix-v101-7101-public-2010.06.27.tar.gz
[lab.git] / utvpn / utvpn-unix-v101-7101-public / src / Cedar / Remote.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 // Remote.c\r
79 // リモートプロシージャーコール\r
80 \r
81 #include "CedarPch.h"\r
82 \r
83 // RPC の終了\r
84 void EndRpc(RPC *rpc)\r
85 {\r
86         RpcFree(rpc);\r
87 }\r
88 \r
89 // RPC の解放\r
90 void RpcFree(RPC *rpc)\r
91 {\r
92         // 引数チェック\r
93         if (rpc == NULL)\r
94         {\r
95                 return;\r
96         }\r
97 \r
98         Disconnect(rpc->Sock);\r
99         ReleaseSock(rpc->Sock);\r
100 \r
101         DeleteLock(rpc->Lock);\r
102 \r
103         Free(rpc);\r
104 }\r
105 \r
106 // エラーの取得\r
107 UINT RpcGetError(PACK *p)\r
108 {\r
109         // 引数チェック\r
110         if (p == NULL)\r
111         {\r
112                 return ERR_DISCONNECTED;\r
113         }\r
114 \r
115         return PackGetInt(p, "error_code");\r
116 }\r
117 \r
118 // エラーチェック\r
119 bool RpcIsOk(PACK *p)\r
120 {\r
121         // 引数チェック\r
122         if (p == NULL)\r
123         {\r
124                 return false;\r
125         }\r
126 \r
127         if (PackGetInt(p, "error") == 0)\r
128         {\r
129                 return true;\r
130         }\r
131         else\r
132         {\r
133                 return false;\r
134         }\r
135 }\r
136 \r
137 // エラーコード設定\r
138 void RpcError(PACK *p, UINT err)\r
139 {\r
140         // 引数チェック\r
141         if (p == NULL)\r
142         {\r
143                 return;\r
144         }\r
145 \r
146         PackAddInt(p, "error", 1);\r
147         PackAddInt(p, "error_code", err);\r
148 }\r
149 \r
150 // RPC ディスパッチャを起動する\r
151 PACK *CallRpcDispatcher(RPC *r, PACK *p)\r
152 {\r
153         char func_name[MAX_SIZE];\r
154         // 引数チェック\r
155         if (r == NULL || p == NULL)\r
156         {\r
157                 return NULL;\r
158         }\r
159 \r
160         if (PackGetStr(p, "function_name", func_name, sizeof(func_name)) == false)\r
161         {\r
162                 return NULL;\r
163         }\r
164 \r
165         return r->Dispatch(r, func_name, p);\r
166 }\r
167 \r
168 // 次の RPC 呼び出しを待機する\r
169 bool RpcRecvNextCall(RPC *r)\r
170 {\r
171         UINT size;\r
172         void *tmp;\r
173         SOCK *s;\r
174         BUF *b;\r
175         PACK *p;\r
176         PACK *ret;\r
177         // 引数チェック\r
178         if (r == NULL)\r
179         {\r
180                 return false;\r
181         }\r
182 \r
183         s = r->Sock;\r
184 \r
185         if (RecvAll(s, &size, sizeof(UINT), s->SecureMode) == false)\r
186         {\r
187                 return false;\r
188         }\r
189 \r
190         size = Endian32(size);\r
191 \r
192         if (size > MAX_PACK_SIZE)\r
193         {\r
194                 return false;\r
195         }\r
196 \r
197         tmp = MallocEx(size, true);\r
198 \r
199         if (RecvAll(s, tmp, size, s->SecureMode) == false)\r
200         {\r
201                 Free(tmp);\r
202                 return false;\r
203         }\r
204 \r
205         b = NewBuf();\r
206         WriteBuf(b, tmp, size);\r
207         SeekBuf(b, 0, 0);\r
208         Free(tmp);\r
209 \r
210         p = BufToPack(b);\r
211         FreeBuf(b);\r
212 \r
213         if (p == NULL)\r
214         {\r
215                 return false;\r
216         }\r
217 \r
218         ret = CallRpcDispatcher(r, p);\r
219         FreePack(p);\r
220 \r
221         if (ret == NULL)\r
222         {\r
223                 ret = PackError(ERR_NOT_SUPPORTED);\r
224         }\r
225 \r
226         b = PackToBuf(ret);\r
227         FreePack(ret);\r
228 \r
229         size = Endian32(b->Size);\r
230         SendAdd(s, &size, sizeof(UINT));\r
231         SendAdd(s, b->Buf, b->Size);\r
232 \r
233         if (SendNow(s, s->SecureMode) == false)\r
234         {\r
235                 FreeBuf(b);\r
236                 return false;\r
237         }\r
238 \r
239         FreeBuf(b);\r
240 \r
241         return true;\r
242 }\r
243 \r
244 // RPC サーバー動作\r
245 void RpcServer(RPC *r)\r
246 {\r
247         SOCK *s;\r
248         // 引数チェック\r
249         if (r == NULL)\r
250         {\r
251                 return;\r
252         }\r
253 \r
254         s = r->Sock;\r
255 \r
256         while (true)\r
257         {\r
258                 // 次の RPC 呼び出しを待機する\r
259                 if (RpcRecvNextCall(r) == false)\r
260                 {\r
261                         // 通信エラー\r
262                         break;\r
263                 }\r
264         }\r
265 }\r
266 \r
267 // RPC 呼び出し\r
268 PACK *RpcCall(RPC *r, char *function_name, PACK *p)\r
269 {\r
270         PACK *ret;\r
271         UINT num_retry = 0;\r
272         UINT err = 0;\r
273         // 引数チェック\r
274         if (r == NULL || function_name == NULL)\r
275         {\r
276                 return NULL;\r
277         }\r
278 \r
279 //      Debug("RpcCall: %s\n", function_name);\r
280 \r
281         Lock(r->Lock);\r
282         {\r
283                 if (p == NULL)\r
284                 {\r
285                         p = NewPack();\r
286                 }\r
287 \r
288                 PackAddStr(p, "function_name", function_name);\r
289 \r
290 RETRY:\r
291                 err = 0;\r
292                 ret = RpcCallInternal(r, p);\r
293 \r
294                 if (ret == NULL)\r
295                 {\r
296                         if (r->IsVpnServer && r->Sock != NULL)\r
297                         {\r
298                                 if (num_retry < 1)\r
299                                 {\r
300                                         num_retry++;\r
301 \r
302                                         // VPN Server に RPC 再接続を試みる\r
303                                         err = AdminReconnect(r);\r
304 \r
305                                         if (err == ERR_NO_ERROR)\r
306                                         {\r
307                                                 goto RETRY;\r
308                                         }\r
309                                 }\r
310                         }\r
311                 }\r
312 \r
313                 FreePack(p);\r
314 \r
315                 if (ret == NULL)\r
316                 {\r
317                         if (err == 0)\r
318                         {\r
319                                 err = ERR_DISCONNECTED;\r
320                         }\r
321 \r
322                         ret = PackError(err);\r
323                         PackAddInt(ret, "error_code", err);\r
324                 }\r
325         }\r
326         Unlock(r->Lock);\r
327 \r
328         return ret;\r
329 }\r
330 \r
331 // RPC 内部呼び出し\r
332 PACK *RpcCallInternal(RPC *r, PACK *p)\r
333 {\r
334         BUF *b;\r
335         UINT size;\r
336         PACK *ret;\r
337         void *tmp;\r
338         // 引数チェック\r
339         if (r == NULL || p == NULL)\r
340         {\r
341                 return NULL;\r
342         }\r
343 \r
344         if (r->Sock == NULL)\r
345         {\r
346                 return NULL;\r
347         }\r
348 \r
349         b = PackToBuf(p);\r
350 \r
351         size = Endian32(b->Size);\r
352         SendAdd(r->Sock, &size, sizeof(UINT));\r
353         SendAdd(r->Sock, b->Buf, b->Size);\r
354         FreeBuf(b);\r
355 \r
356         if (SendNow(r->Sock, r->Sock->SecureMode) == false)\r
357         {\r
358                 return NULL;\r
359         }\r
360 \r
361         if (RecvAll(r->Sock, &size, sizeof(UINT), r->Sock->SecureMode) == false)\r
362         {\r
363                 return NULL;\r
364         }\r
365 \r
366         size = Endian32(size);\r
367         if (size > MAX_PACK_SIZE)\r
368         {\r
369                 return NULL;\r
370         }\r
371 \r
372         tmp = MallocEx(size, true);\r
373         if (RecvAll(r->Sock, tmp, size, r->Sock->SecureMode) == false)\r
374         {\r
375                 Free(tmp);\r
376                 return NULL;\r
377         }\r
378 \r
379         b = NewBuf();\r
380         WriteBuf(b, tmp, size);\r
381         SeekBuf(b, 0, 0);\r
382         Free(tmp);\r
383 \r
384         ret = BufToPack(b);\r
385         if (ret == NULL)\r
386         {\r
387                 FreeBuf(b);\r
388                 return NULL;\r
389         }\r
390 \r
391         FreeBuf(b);\r
392 \r
393         return ret;\r
394 }\r
395 \r
396 // RPC サーバーの開始\r
397 RPC *StartRpcServer(SOCK *s, RPC_DISPATCHER *dispatch, void *param)\r
398 {\r
399         RPC *r;\r
400         // 引数チェック\r
401         if (s == NULL)\r
402         {\r
403                 return NULL;\r
404         }\r
405 \r
406         r = ZeroMallocEx(sizeof(RPC), true);\r
407         r->Sock = s;\r
408         r->Param = param;\r
409         r->Lock = NewLock();\r
410         AddRef(s->ref);\r
411 \r
412         r->ServerMode = true;\r
413         r->Dispatch = dispatch;\r
414 \r
415         // 名前の生成\r
416         Format(r->Name, sizeof(r->Name), "RPC-%u", s->socket);\r
417 \r
418         return r;\r
419 }\r
420 \r
421 // RPC クライアントの開始\r
422 RPC *StartRpcClient(SOCK *s, void *param)\r
423 {\r
424         RPC *r;\r
425         // 引数チェック\r
426         if (s == NULL)\r
427         {\r
428                 return NULL;\r
429         }\r
430 \r
431         r = ZeroMalloc(sizeof(RPC));\r
432         r->Sock = s;\r
433         r->Param = param;\r
434         r->Lock = NewLock();\r
435         AddRef(s->ref);\r
436 \r
437         r->ServerMode = false;\r
438 \r
439         return r;\r
440 }\r
441 \r