source: EcnlProtoTool/trunk/asp3_dcre/tinet/netapp/dhcp4_cli.c@ 331

Last change on this file since 331 was 331, checked in by coas-nagasima, 6 years ago

prototoolに関連するプロジェクトをnewlibからmuslを使うよう変更・更新
ntshellをnewlibの下位の実装から、muslのsyscallの実装に変更・更新
以下のOSSをアップデート
・mruby-1.3.0
・musl-1.1.18
・onigmo-6.1.3
・tcc-0.9.27
以下のOSSを追加
・openssl-1.1.0e
・curl-7.57.0
・zlib-1.2.11
以下のmrbgemsを追加
・iij/mruby-digest
・iij/mruby-env
・iij/mruby-errno
・iij/mruby-iijson
・iij/mruby-ipaddr
・iij/mruby-mock
・iij/mruby-require
・iij/mruby-tls-openssl

  • Property svn:eol-style set to native
  • Property svn:mime-type set to text/x-csrc
File size: 56.1 KB
Line 
1/*
2 * Copyright 2004 Henning Brauer <henning@openbsd.org>
3 * Copyright (c) 1995, 1996, 1997, 1998, 1999
4 * The Internet Software Consortium. All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 *
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of The Internet Software Consortium nor the names
16 * of its contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE INTERNET SOFTWARE CONSORTIUM AND
20 * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
21 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
22 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
23 * DISCLAIMED. IN NO EVENT SHALL THE INTERNET SOFTWARE CONSORTIUM OR
24 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
27 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
28 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
29 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
30 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 *
33 * This software has been written for the Internet Software Consortium
34 * by Ted Lemon <mellon@fugue.com> in cooperation with Vixie
35 * Enterprises. To learn more about the Internet Software Consortium,
36 * see ``http://www.vix.com/isc''. To learn more about Vixie
37 * Enterprises, see ``http://www.vix.com''.
38 *
39 * This client was substantially modified and enhanced by Elliot Poger
40 * for use on Linux while he was working on the MosquitoNet project at
41 * Stanford.
42 *
43 * The current version owes much to Elliot's Linux enhancements, but
44 * was substantially reorganized and partially rewritten by Ted Lemon
45 * so as to use the same networking framework that the Internet Software
46 * Consortium DHCP server uses. Much system-specific configuration code
47 * was moved into a shell script so that as support for more operating
48 * systems is added, it will not be necessary to port and maintain
49 * system-specific configuration code to these operating systems - instead,
50 * the shell script can invoke the native tools to accomplish the same
51 * purpose.
52 */
53/*
54 * WIDE Project DHCP Implementation
55 * Copyright (c) 1995-1997 Akihiro Tominaga
56 * Copyright (c) 1995-1997 WIDE Project
57 * All rights reserved.
58 *
59 * Permission to use, copy, modify and distribute this software and its
60 * documentation is hereby granted, provided the following conditions
61 * are satisfied,
62 *
63 * 1. Both the copyright notice and this permission notice appear in
64 * all copies of the software, derivative works or modified versions,
65 * and any portions thereof, and that both notices appear in
66 * supporting documentation.
67 * 2. All advertising materials mentioning features or use of this software
68 * must display the following acknowledgement:
69 * This product includes software developed by WIDE Project and
70 * its contributors.
71 * 3. Neither the name of WIDE Project nor the names of its contributors
72 * may be used to endorse or promote products derived from this software
73 * without specific prior written permission.
74 *
75 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPER ``AS IS'' AND WIDE
76 * PROJECT DISCLAIMS ANY LIABILITY OF ANY KIND FOR ANY DAMAGES
77 * WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. ALSO, THERE
78 * IS NO WARRANTY IMPLIED OR OTHERWISE, NOR IS SUPPORT PROVIDED.
79 *
80 * Feedback of the results generated from any improvements or
81 * extensions made to this software would be much appreciated.
82 * Any such feedback should be sent to:
83 *
84 * Akihiro Tominaga
85 * WIDE Project
86 * Keio University, Endo 5322, Kanagawa, Japan
87 * (E-mail: dhcp-dist@wide.ad.jp)
88 *
89 * WIDE project has the rights to redistribute these changes.
90 */
91/*
92 * TINET (TCP/IP Protocol Stack)
93 *
94 * Copyright (C) 2011 by Dep. of Computer Science and Engineering
95 * Tomakomai National College of Technology, JAPAN
96 *
97 * 上記著作権者
98は,以下の (1)~(4) の条件か,Free Software Foundation
99 * によってå…
100¬è¡¨ã•ã‚Œã¦ã„ã‚‹ GNU General Public License の Version 2 に記
101 * 述されている条件を満たす場合に限り,本ソフトウェア(本ソフトウェア
102 * を改変したものを含む.以下同じ)を使用・複製・改変・再é…
103å¸ƒï¼ˆä»¥ä¸‹ï¼Œ
104 * 利用と呼ぶ)することを無償で許諾する.
105 * (1) 本ソフトウェアをソースコードの形で利用する場合には,上記の著作
106 * 権表示,この利用条件および下記の無保証規定が,そのままの形でソー
107 * スコード中に含まれていること.
108 * (2) 本ソフトウェアを,ライブラリ形式など,他のソフトウェア開発に使
109 * 用できる形で再é…
110å¸ƒã™ã‚‹å ´åˆã«ã¯ï¼Œå†é…
111å¸ƒã«ä¼´ã†ãƒ‰ã‚­ãƒ¥ãƒ¡ãƒ³ãƒˆï¼ˆåˆ©ç”¨
112 * 者
113マニュアルなど)に,上記の著作権表示,この利用条件および下記
114 * の無保証規定を掲載すること.
115 * (3) 本ソフトウェアを,機器に組み込むなど,他のソフトウェア開発に使
116 * 用できない形で再é…
117å¸ƒã™ã‚‹å ´åˆã«ã¯ï¼Œæ¬¡ã®ã„ずれかの条件を満たすこ
118 * と.
119 * (a) 再é…
120å¸ƒã«ä¼´ã†ãƒ‰ã‚­ãƒ¥ãƒ¡ãƒ³ãƒˆï¼ˆåˆ©ç”¨è€…
121マニュアルなど)に,上記の著
122 * 作権表示,この利用条件および下記の無保証規定を掲載すること.
123 * (b) 再é…
124å¸ƒã®å½¢æ…
125‹ã‚’,別に定める方法によって,TOPPERSプロジェクトに
126 * 報告すること.
127 * (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
128 * 害からも,上記著作権者
129およびTOPPERSプロジェクトをå…
130è²¬ã™ã‚‹ã“と.
131 *
132 * 本ソフトウェアは,無保証で提供されているものである.上記著作権者
133お
134 * よびTOPPERSプロジェクトは,本ソフトウェアに関して,その適用可能性も
135 * 含めて,いかなる保証も行わない.また,本ソフトウェアの利用により直
136 * 接的または間接的に生じたいかなる損害に関しても,その責任を負わない.
137 *
138 * @(#) $Id$
139 */
140
141#include <string.h>
142
143#ifdef TARGET_KERNEL_ASP
144
145#include <kernel.h>
146#include <sil.h>
147#include <t_syslog.h>
148#include "kernel_cfg.h"
149
150#endif /* of #ifdef TARGET_KERNEL_ASP */
151
152#ifdef TARGET_KERNEL_JSP
153
154#include <s_services.h>
155#include <t_services.h>
156#include "kernel_id.h"
157
158#endif /* of #ifdef TARGET_KERNEL_JSP */
159
160#include <tinet_defs.h>
161#include <tinet_config.h>
162
163#include <net/if.h>
164#include <net/ethernet.h>
165#include <net/net.h>
166#include <net/net_endian.h>
167#include <net/net_var.h>
168#include <net/net_timer.h>
169
170#include <netinet/in.h>
171#include <netinet/in_var.h>
172#include <netinet/in_itron.h>
173#include <netinet/if_ether.h>
174
175#include <net/if_var.h>
176
177#include <netapp/netapp.h>
178#include <netapp/netapp_var.h>
179#include <netapp/dhcp4_cli.h>
180#include <netapp/dhcp4_cli_var.h>
181#include <netapp/resolver.h>
182#include "lcd.h"
183
184/*
185 * DHCP クライアントタスク
186 */
187
188#ifdef DHCP4_CLI_CFG
189
190/*
191 * 変数
192 */
193
194static T_DHCP4_CLI_CONTEXT context; /* クライアントコンテキスト */
195static uint8_t magicno[DHCP4_MAGIC_LEN] = DHCP4_RFC1048_MAGIC; /* magic 番号(RFC1048)*/
196
197/* 必
198須オプションリスト */
199#ifdef DHCP4_CLI_CFG_REQUIRED_OLIST
200static uint8_t required_plist[] = DHCP4_CLI_CFG_REQUIRED_OLIST;
201#endif
202
203/* 要求オプションリスト */
204#ifdef DHCP4_CLI_CFG_REQUEST_OLIST
205static uint8_t request_plist[] = DHCP4_CLI_CFG_REQUEST_OLIST;
206#endif
207
208/*
209 * dhcp4_cksum -- チェックサムの計算関数
210 */
211
212static uint32_t
213dhcp4_cksum (void *data, uint_t len /*オクテット単位*/)
214{
215 uint32_t carry, sum = 0;
216
217 for ( ; len > 0; len -= 2) {
218 sum += (*(uint8_t*)data << 8) + *((uint8_t*)data + 1);
219 data = (uint8_t*)data + 2;
220 }
221
222 while (sum >= 0x00010000) {
223 carry = sum >> 16;
224 sum = (sum & 0xffff) + carry;
225 }
226
227 return sum;
228 }
229
230/*
231 * create_xid -- トランザクション ID を生成する。
232 */
233
234static uint32_t
235create_xid (void)
236{
237 T_IF_SOFTC *ic;
238 SYSTIM time;
239
240 ic = IF_ETHER_NIC_GET_SOFTC();
241 get_tim(&time);
242 return (dhcp4_cksum((void*)&ic->ifaddr.lladdr, ETHER_ADDR_LEN) << 16)
243 + dhcp4_cksum((void*)&time, sizeof(time));
244 }
245
246/*
247 * find_option_sub -- 指定したオプションを探索する。
248 *
249 * 注意: 引数 size が 0 の時はオプションサイズを検証しない。
250 */
251
252static uint8_t *
253find_option_sub (T_DHCP4_CLI_MSG *msg, uint_t off, uint_t len,
254 uint_t tag, uint_t size, bool_t overload)
255{
256 uint8_t *opt, *tmp;
257
258 opt = (uint8_t*)&msg->msg + off;
259 while (opt < (uint8_t*)&msg->msg + off + len && *opt != DHCP4_OPT_END) {
260 if (*opt == DHCP4_OPT_PAD)
261 opt ++;
262 else if ((*opt == DHCP4_OPT_OPT_OVERLOAD) && overload) {
263 if (*(opt + 2) & DHCP4_OPTOL_FILE) {
264 tmp = find_option_sub(msg, DHCP4_FILE_OFFSET, DHCP4_FILE_LEN, tag, len, false);
265 if (tmp != NULL)
266 return tmp;
267 }
268 if (*(opt + 2) & DHCP4_OPTOL_SNAME) {
269 tmp = find_option_sub(msg, DHCP4_SNAME_OFFSET, DHCP4_SNAME_LEN, tag, len, false);
270 if (tmp != NULL)
271 return tmp;
272 }
273 opt += *(opt + 1) + 2;
274 }
275 else if (*opt == tag && (size == 0 || *(opt + 1) == size))
276 return opt;
277 else
278 opt += *(opt + 1) + 2;
279 }
280 return NULL;
281 }
282
283/*
284 * find_option -- 指定したオプションを探索する。
285 *
286 * 注意: 引数 size が 0 の時はオプションサイズを検証しない。
287 */
288
289static uint8_t *
290find_option (T_DHCP4_CLI_MSG *msg, uint_t tag, uint_t size)
291{
292 return find_option_sub(msg, DHCP4_OPTION_OFFSET + DHCP4_MAGIC_LEN,
293 msg->len - (DHCP4_OPTION_OFFSET + DHCP4_MAGIC_LEN),
294 tag, size, true);
295 }
296
297/*
298 * is_equal_sid -- メッセージ内
299の SERVER ID を比較する。
300 */
301
302static bool_t
303is_equal_sid (T_DHCP4_CLI_MSG *msg1, T_DHCP4_CLI_MSG *msg2)
304{
305 uint8_t *opt1, *opt2;
306
307 if ((opt1 = find_option(msg1, DHCP4_OPT_SERVER_ID, sizeof(T_IN4_ADDR))) == NULL)
308 return false;
309 if ((opt2 = find_option(msg2, DHCP4_OPT_SERVER_ID, sizeof(T_IN4_ADDR))) == NULL)
310 return false;
311
312 return msg2host32(opt1) == msg2host32(opt2);
313 }
314
315/*
316 * timer_value -- メッセージから時間情
317報を取り出す。
318 */
319
320static uint32_t
321timer_value (T_DHCP4_CLI_MSG *msg, uint_t tag, uint32_t def_value)
322{
323 uint8_t *opt;
324 uint32_t seconds;
325
326 if ((opt = find_option(msg, tag, sizeof(uint32_t))) == NULL)
327 return def_value;
328 else {
329
330 /* サーバからのリース時間は[s]。*/
331 seconds = msg2host32(opt + 2);
332
333 /* コンテキスト内
334のリース時間は SYSTIM_HZ。*/
335 if (seconds == DHCP4_TIME_INFINITY)
336 return DHCP4_TIME_INFINITY;
337 else if (seconds > SYSTIM2SEC(DHCP4_TIME_INFINITY))
338 return DHCP4_TIME_INFINITY;
339 else
340 return SEC2SYSTIM(seconds);
341 }
342 }
343
344/*
345 * rel_addr -- IPv4 アドレス、サブネットマスク、静的経路表を解放する。
346 */
347
348static void
349rel_addr (void)
350{
351 ER error;
352 uint_t count = 0;
353
354 if ((error = in4_add_ifaddr(IPV4_ADDRANY, IPV4_ADDRANY)) != E_OK) {
355 syslog(LOG_NOTICE, "[DHCP4C] error, IPv4 addr: %s", itron_strerror(error));
356 count ++;
357 }
358
359 if ((error = in4_add_route(0, IPV4_ADDRANY, IPV4_ADDRANY, IPV4_ADDRANY)) != E_OK) {
360 syslog(LOG_NOTICE, "[DHCP4C] error, release routing table: %s", itron_strerror(error));
361 count ++;
362 }
363
364 if ((error = in4_add_route(1, IPV4_ADDRANY, IPV4_ADDRANY, IPV4_ADDRANY)) != E_OK) {
365 syslog(LOG_NOTICE, "[DHCP4C] error, release routing table: %s", itron_strerror(error));
366 count ++;
367 }
368
369 if ((error = in4_add_route(2, 0xffffffff, 0xffffffff, IPV4_ADDRANY)) != E_OK) {
370 syslog(LOG_NOTICE, "[DHCP4C] error, release routing table: %s", itron_strerror(error));
371 count ++;
372 }
373
374 if (count == 0) {
375 syslog(LOG_NOTICE, "[DHCP4C] release IPv4 addr.");
376
377#if 0
378#ifdef USE_LCD
379 dly_tsk(1 * 1000);
380 lcd_puts(LCD_PORTID, "0.0.0.0\n");
381#endif /* of #ifdef USE_LCD */
382#endif
383
384 }
385 }
386
387/*
388 * rel_options -- リースされたオプションを解析して値を解放する。
389 */
390
391static void
392rel_options (T_DHCP4_CLI_CONTEXT *ct, uint_t off, uint_t len, bool_t overload)
393{
394#if defined(USE_RESOLVER)
395 T_IN4_ADDR addr;
396#endif
397
398 uint8_t *opt;
399
400 opt = (uint8_t*)&ct->act_msg->msg + off;
401 while (opt < (uint8_t*)&ct->act_msg->msg + off + len && *opt != DHCP4_OPT_END) {
402 if (*opt == DHCP4_OPT_PAD)
403 opt ++;
404 else if ((*opt == DHCP4_OPT_OPT_OVERLOAD) && overload) {
405 if (*(opt + 2) & DHCP4_OPTOL_FILE)
406 rel_options(ct, DHCP4_FILE_OFFSET, DHCP4_FILE_LEN, false);
407 if (*(opt + 2) & DHCP4_OPTOL_SNAME)
408 rel_options(ct, DHCP4_SNAME_OFFSET, DHCP4_SNAME_LEN, false);
409 opt += *(opt + 1) + 2;
410 }
411 else {
412
413 switch (*opt) {
414
415#if defined(USE_RESOLVER)
416
417 case DHCP4_OPT_DNS_SERVER:
418 addr = IPV4_ADDRANY;
419 dns_in4_set_addr(&addr);
420 break;
421
422 case DHCP4_OPT_HOST_NAME:
423 break;
424
425 case DHCP4_OPT_DOMAIN_NAME:
426 dns_in4_set_dname("", 0);
427 break;
428
429#else /* of #if defined(USE_RESOLVER) */
430
431 case DHCP4_OPT_DNS_SERVER:
432 case DHCP4_OPT_HOST_NAME:
433 case DHCP4_OPT_DOMAIN_NAME:
434
435#endif /* of #if defined(USE_RESOLVER) */
436
437 case DHCP4_OPT_SUBNET_MASK:
438 case DHCP4_OPT_ROUTER:
439 case DHCP4_OPT_LEASE_TIME:
440 case DHCP4_OPT_RENEWAL_T1:
441 case DHCP4_OPT_REBINDING_T2:
442 break;
443
444 default:
445 break;
446 }
447
448 opt += *(opt + 1) + 2;
449 }
450 }
451 }
452
453/*
454 * rel_lease -- リースされた情
455報を解放する。
456 */
457
458static void
459rel_lease (T_DHCP4_CLI_CONTEXT *ct)
460{
461 /* 有効なリース・メッセージ構造体が無ければ何もしない。*/
462 if (ct->act_msg == NULL)
463 return;
464
465 /* リースされたオプションを解析して値を解放する。*/
466 rel_options(ct, DHCP4_OPTION_OFFSET + DHCP4_MAGIC_LEN,
467 ct->act_msg->len - (DHCP4_OPTION_OFFSET + DHCP4_MAGIC_LEN), true);
468 rel_addr();
469
470 /* 有効なリース・メッセージ構造体を解放する。*/
471 syscall(rel_mpf(MPF_DHCP4_CLI_MSG, (void*)ct->act_msg));
472 ct->act_msg = NULL;
473 }
474
475/*
476 * set_addr -- IPv4 アドレス、サブネットマスク、静的経路表を設定する。
477 */
478
479static void
480set_addr (T_DHCP4_CLI_CONTEXT *ct, uint8_t *mopt, uint8_t *ropt)
481{
482 ER error;
483 T_IN4_ADDR addr, mask, router, net_addr;
484
485 addr = ntohl(ct->act_msg->msg.yiaddr);
486 mask = msg2host32(mopt + 2);
487 net_addr = addr & mask;
488 router = msg2host32(ropt + 2);
489
490 if ((error = in4_add_ifaddr(addr, mask)) != E_OK)
491 syslog(LOG_NOTICE, "[DHCP4C] error, set IPv4 addr: %s", itron_strerror(error));
492
493 if ((error = in4_add_route(0, IPV4_ADDRANY, IPV4_ADDRANY, router)) != E_OK)
494 syslog(LOG_NOTICE, "[DHCP4C] error, set routing table: %s", itron_strerror(error));
495
496 if ((error = in4_add_route(1, net_addr, mask, IPV4_ADDRANY)) != E_OK)
497 syslog(LOG_NOTICE, "[DHCP4C] error, set routing table: %s", itron_strerror(error));
498
499 if ((error = in4_add_route(2, 0xffffffff, 0xffffffff, IPV4_ADDRANY)) != E_OK)
500 syslog(LOG_NOTICE, "[DHCP4C] error, set routing table: %s", itron_strerror(error));
501
502 if (error == E_OK) {
503 syslog(LOG_NOTICE, "[DHCP4C] set IPv4 addr: %s.", ip2str(NULL, &addr));
504
505#ifdef USE_LCD
506 dly_tsk(1 * 1000);
507 lcd_puts(LCD_PORTID, ip2str(NULL, &addr));
508 lcd_putc(LCD_PORTID, '\n');
509#endif /* of #ifdef USE_LCD */
510 if (ct->set_addr_callback != NULL)
511 ct->set_addr_callback();
512
513 }
514 }
515
516/*
517 * set_options -- リースされたオプションを解析して値を設定する。
518 */
519
520static void
521set_options (T_DHCP4_CLI_CONTEXT *ct, uint_t off, uint_t len, bool_t overload)
522{
523#if defined(USE_RESOLVER)
524 T_IN4_ADDR addr;
525#endif
526
527 uint8_t *opt, *mopt = NULL, *ropt = NULL;
528
529 opt = (uint8_t*)&ct->act_msg->msg + off;
530 while (opt < (uint8_t*)&ct->act_msg->msg + off + len && *opt != DHCP4_OPT_END) {
531 if (*opt == DHCP4_OPT_PAD)
532 opt ++;
533 else if ((*opt == DHCP4_OPT_OPT_OVERLOAD) && overload) {
534 if (*(opt + 2) & DHCP4_OPTOL_FILE)
535 set_options(ct, DHCP4_FILE_OFFSET, DHCP4_FILE_LEN, false);
536 if (*(opt + 2) & DHCP4_OPTOL_SNAME)
537 set_options(ct, DHCP4_SNAME_OFFSET, DHCP4_SNAME_LEN, false);
538 opt += *(opt + 1) + 2;
539 }
540 else {
541
542 switch (*opt) {
543 case DHCP4_OPT_SUBNET_MASK:
544 mopt = opt;
545 break;
546
547 case DHCP4_OPT_ROUTER:
548 ropt = opt;
549 break;
550
551#if defined(USE_RESOLVER)
552
553 case DHCP4_OPT_DNS_SERVER:
554 addr = msg2host32(opt + 2);
555 dns_in4_set_addr(&addr);
556 break;
557
558 case DHCP4_OPT_HOST_NAME:
559 break;
560
561 case DHCP4_OPT_DOMAIN_NAME:
562 dns_in4_set_dname(opt + 2, *(opt + 1));
563 break;
564
565#else /* of #if defined(USE_RESOLVER) */
566
567 case DHCP4_OPT_DNS_SERVER:
568 case DHCP4_OPT_HOST_NAME:
569 case DHCP4_OPT_DOMAIN_NAME:
570
571#endif /* of #if defined(USE_RESOLVER) */
572
573 case DHCP4_OPT_LEASE_TIME:
574 case DHCP4_OPT_RENEWAL_T1:
575 case DHCP4_OPT_REBINDING_T2:
576 break;
577
578 default:
579 break;
580 }
581
582 opt += *(opt + 1) + 2;
583 }
584 }
585 if (!(mopt == NULL || ropt == NULL))
586 set_addr(ct, mopt, ropt);
587 }
588
589/*
590 * set_lease -- リースされた情
591報を設定する。
592 */
593
594static void
595set_lease (T_DHCP4_CLI_CONTEXT *ct)
596{
597 /* リースされたオプションを解析して値を設定する。*/
598 set_options(ct, DHCP4_OPTION_OFFSET + DHCP4_MAGIC_LEN,
599 ct->act_msg->len - (DHCP4_OPTION_OFFSET + DHCP4_MAGIC_LEN), true);
600 }
601
602/*
603 * validate_duplicate -- 指定された IPv4 アドレスが使われていないか検証する。
604 *
605 * 使われていない時は true を返す。
606 */
607
608static bool_t
609validate_duplicate (T_DHCP4_CLI_MSG *msg)
610{
611 T_IN4_ADDR yiaddr;
612
613 /* 指定された IPv4 アドレスが ADDR ANY なら使われていないと判断する。*/
614 yiaddr = ntohl(msg->msg.yiaddr);
615 if (yiaddr == IPV4_ADDRANY)
616 return true;
617
618 /* ARP キャッシュにあれば使われていると判断する。*/
619 if (arp_lookup(yiaddr, false) != NULL)
620 return false;
621
622 /*
623 * ARP 要求を出力して TMO_DHCP4C_ARP_WAIT 待
624ち、
625 * ARP キャッシュになければ使われていないと判断する。
626 */
627 arp_request(&IF_ETHER_NIC_GET_SOFTC()->ifaddr, yiaddr);
628 dly_tsk(TMO_DHCP4C_ARP_WAIT);
629 return arp_lookup(yiaddr, false) == NULL;
630 }
631
632/*
633 * validate_rcv_msg -- 受信メッセージを検証する。
634 */
635
636static ER
637validate_rcv_msg (T_DHCP4_CLI_CONTEXT *ct, T_DHCP4_CLI_MSG *msg)
638{
639 uint8_t *opt;
640
641 /* packet type が DHCP4_REPLY であることを確認する。*/
642 if (!(msg->msg.op == DHCP4_REPLY))
643 return false;
644
645 /* メッセージタイプオプションがあることを確認する。*/
646 if ((opt = find_option(msg, DHCP4_OPT_MSG_TYPE, 1)) == NULL)
647 return E_PAR;
648
649 /* メッセージのタイプが一致していることを検証する。*/
650 msg->type = *(opt + 2);
651 switch (ct->fsm) {
652
653 case DHCP4_FSM_SELECT:
654 if (!(msg->type == DHCP4_MTYPE_OFFER))
655 return E_PAR;
656 break;
657
658 case DHCP4_FSM_REQUEST:
659 case DHCP4_FSM_REBOOT:
660 case DHCP4_FSM_RENEW:
661 case DHCP4_FSM_REBIND:
662 case DHCP4_FSM_REL_INFO:
663 if (!((msg->type == DHCP4_MTYPE_ACK) || (msg->type == DHCP4_MTYPE_NAK)))
664 return E_PAR;
665 break;
666
667 case DHCP4_FSM_INIT:
668 case DHCP4_FSM_BOUND:
669 case DHCP4_FSM_INIT_REBOOT:
670 return E_PAR;
671 break;
672
673 default:
674 syslog(LOG_NOTICE, "[DHCP4C] error, unknown state: %d.", ct->fsm);
675 return E_PAR;
676 break;
677 }
678
679 /* マジック番号を検証する。*/
680 if (memcmp((uint8_t*)&msg->msg.options, magicno, DHCP4_MAGIC_LEN))
681 return E_PAR;
682
683 /* トランザクション ID が異なっていればエラー */
684 if (ntohl(msg->msg.xid) != ct->xid)
685 return E_PAR;
686
687 /* ハードウェアアドレス長が 6(MAC アドレス長)でなければエラー */
688 if (msg->msg.hlen != ETHER_ADDR_LEN)
689 return E_PAR;
690
691 /* ハードウェアアドレスが異なっていればエラー */
692 if (memcmp(&msg->msg.chaddr, &ct->sc->ifaddr.lladdr, sizeof(ct->sc->ifaddr.lladdr)))
693 return E_PAR;
694
695 /*
696 * メッセージタイプが OFFER の場合は、
697 * ARP を使用して、指定された IPv4 アドレスが使われていないか検証する。
698 * 使われている時は、他の IPv4 アドレスの提供を待
699つ。
700 */
701 if (msg->type == DHCP4_MTYPE_OFFER) {
702 if (!validate_duplicate(msg))
703 return E_PAR;
704 }
705
706 return E_OK;
707 }
708
709/*
710 * eval_prefer -- 受信メッセージの推奨度を評価する。
711 */
712
713static void
714eval_prefer (T_DHCP4_CLI_MSG *msg)
715{
716 int ix;
717
718 /* 無効の場合は終了する。*/
719 if (msg == NULL)
720 return;
721
722 /* 指定された IPv4 アドレスが ADDR ANY なら推奨度を 0に設定する。*/
723 if (ntohl(msg->msg.yiaddr) == IPV4_ADDRANY)
724 msg->prefer = 0;
725 else
726 msg->prefer = DHCP4_CLI_CFG_PREFER_ADDR;
727
728#if defined(DHCP4_CLI_CFG_REQUEST_OLIST)
729
730 /* 要求オプションを検証する。*/
731 for (ix = sizeof(request_plist); ix -- > 0; ) {
732 if (find_option(msg, request_plist[ix], 0) != NULL)
733 msg->prefer ++;
734 }
735
736#endif /* of #if defined(DHCP4_CLI_CFG_REQUEST_OLIST) */
737
738#if defined(DHCP4_CLI_CFG_REQUIRED_OLIST)
739
740 /* 必
741須オプションを検証する。*/
742 for (ix = sizeof(required_plist); ix -- > 0; ) {
743 if (find_option(msg, required_plist[ix], 0) == NULL)
744 msg->prefer = 0;
745 }
746
747#endif /* of #if defined(DHCP4_CLI_CFG_REQUIRED_OLIST) */
748 }
749
750/*
751 * eval_rcv_msg -- 受信メッセージを評価する。
752 */
753
754static ER
755eval_rcv_msg (T_DHCP4_CLI_CONTEXT *ct)
756{
757 T_DHCP4_CLI_MSG *evl, *msg;
758
759 /* メッセージを受信していなければ中止する。*/
760 syscall(wai_sem(SEM_DHCP4_CLI_LOCK));
761 if (ct->val_lst == NULL) {
762 syscall(sig_sem(SEM_DHCP4_CLI_LOCK));
763 return E_OK;
764 }
765
766 /* 検証メッセージリストから評価メッセージを取り出す。*/
767 evl = ct->val_lst;
768 ct->val_lst = ct->val_lst->next;
769 evl->next = NULL;
770 syscall(sig_sem(SEM_DHCP4_CLI_LOCK));
771
772 /* 評価メッセージを検証する。*/
773 if (validate_rcv_msg(ct, evl) != E_OK) {
774
775 /* エラーが発生した評価メッセージを受信メッセージ構造体リストに戻す。*/
776 goto rcv_ret;
777 }
778
779 /* 受信したメッセージが NAK の時の処理 */
780 if (evl->type == DHCP4_MTYPE_NAK) {
781
782 /* リースされた情
783報を解放する。*/
784 rel_lease(ct);
785
786 /* 内
787部エラーを設定して終了する。*/
788 return E_PAR;
789 }
790
791 /* REL_INFO 状æ…
792‹ã®æ™‚の処理 */
793 //cons_printf(CONSOLE_PORTID, "evl_rcv_msg3[s=%d]\n", ct->fsm);
794 if (ct->fsm == DHCP4_FSM_REL_INFO) {
795 syscall(wai_sem(SEM_DHCP4_CLI_LOCK));
796 evl->next = ct->prf_lst;
797 ct->prf_lst = evl;
798 syscall(sig_sem(SEM_DHCP4_CLI_LOCK));
799 return E_OK;
800 }
801
802 /* 評価メッセージの推奨度を評価する。*/
803 eval_prefer(evl);
804
805 /* 推奨メッセージリストが空なら評価メッセージを移して終了する。*/
806 if (ct->prf_lst == NULL) {
807 ct->max_prefer = evl->prefer;
808 ct->prf_lst = evl;
809 return E_OK;
810 }
811
812 /* 評価メッセージの推奨度と推奨メッセージリストの最大推奨度を比較する。*/
813 if (evl->prefer > ct->max_prefer) {
814
815 /*
816 * 評価メッセージの推奨度が推奨メッセージリストの最大推奨度より高ければ、
817 * 推奨メッセージリストを受信メッセージ構造体リストに戻し、
818 * 評価メッセージを推奨メッセージリストに移す。
819 */
820 ct->max_prefer = evl->prefer;
821 syscall(wai_sem(SEM_DHCP4_CLI_LOCK));
822 if (ct->rcv_lst == NULL)
823 ct->rcv_lst = ct->prf_lst;
824 else {
825 for (msg = ct->rcv_lst; msg->next != NULL; msg = msg->next)
826 ;
827 msg->next = ct->prf_lst;
828 }
829 syscall(sig_sem(SEM_DHCP4_CLI_LOCK));
830 ct->prf_lst = evl;
831 return E_OK;
832 }
833
834 else if (evl->prefer == ct->max_prefer) {
835 for (msg = ct->prf_lst; msg != NULL; msg = msg->next) {
836 if (is_equal_sid(evl, msg)) {
837
838 /*
839 * 推奨メッセージリストに同じ DHCP4_OPT_SERVER_ID のメッセージがあれば、
840 * 評価メッセージを受信メッセージ構造体リストに戻す。
841 */
842 goto rcv_ret;
843 }
844 }
845
846 /*
847 * 評価メッセージを推奨メッセージリストに移す。
848 */
849 evl->next = ct->prf_lst;
850 ct->prf_lst = evl;
851 return E_OK;
852 }
853
854 /*else */
855 /*
856 * 評価メッセージの推奨度が推奨メッセージリストの最大推奨度より低ければ、
857 * 評価メッセージを受信メッセージ構造体リストに戻す。
858 */
859
860rcv_ret:
861 syscall(wai_sem(SEM_DHCP4_CLI_LOCK));
862 evl->next = ct->rcv_lst;
863 ct->rcv_lst = evl;
864 syscall(sig_sem(SEM_DHCP4_CLI_LOCK));
865 return E_OK;
866 }
867
868/*
869 * select_msg -- 推奨メッセージを選択する。
870 */
871
872static T_DHCP4_CLI_MSG*
873select_msg (T_DHCP4_CLI_CONTEXT *ct)
874{
875 T_DHCP4_CLI_MSG *msg, *select;
876
877 syscall(wai_sem(SEM_DHCP4_CLI_LOCK));
878 if (ct->prf_lst == NULL) {
879 /* メッセージを受信していなければ中止する。*/
880 syscall(sig_sem(SEM_DHCP4_CLI_LOCK));
881 return NULL;
882 }
883
884 /* 推奨メッセージリストのå…
885ˆé ­ã®ãƒ¡ãƒƒã‚»ãƒ¼ã‚¸ã‚’選択する。*/
886 select = ct->prf_lst;
887 ct->prf_lst = ct->prf_lst->next;
888 select->next = NULL;
889
890 /* 選択されなかった検証メッセージを受信メッセージ構造体リストに戻す。*/
891 if (ct->rcv_lst == NULL)
892 ct->rcv_lst = ct->prf_lst;
893 else {
894 for (msg = ct->rcv_lst; msg->next != NULL; msg = msg->next)
895 ;
896 msg->next = ct->prf_lst;
897 }
898 syscall(sig_sem(SEM_DHCP4_CLI_LOCK));
899 return select;
900 }
901
902/*
903 * select_ack -- ACK メッセージを検証する。
904 *
905 * 受けå…
906¥ã‚Œã‚‹ã“とが可能の時は true を返す。
907 */
908
909static bool_t
910select_ack (T_DHCP4_CLI_CONTEXT *ct)
911{
912 T_DHCP4_CLI_MSG *msg;
913
914 if ((msg = select_msg(ct)) == NULL)
915 return false;
916
917 /* 有効なリース・メッセージが残っていれば、受信メッセージ構造体リストに戻す。*/
918 if (ct->act_msg != NULL) {
919 syscall(wai_sem(SEM_DHCP4_CLI_LOCK));
920 ct->act_msg->next = ct->rcv_lst;
921 ct->rcv_lst = ct->act_msg;
922 syscall(sig_sem(SEM_DHCP4_CLI_LOCK));
923 }
924
925 /* 有効なリース・メッセージに設定する。*/
926 ct->act_msg = msg;
927 return true;
928 }
929
930/*
931 * select_offer -- OFFER メッセージを検証する。
932 *
933 * 受けå…
934¥ã‚Œã‚‹ã“とが可能の時は true を返す。
935 */
936
937static bool_t
938select_offer (T_DHCP4_CLI_CONTEXT *ct)
939{
940 return (ct->off_msg = select_msg(ct)) != NULL;
941 }
942
943/*
944 * cancel_all_timers -- å…
945¨ã¦ã® TIMER をキャンセルする。
946 */
947
948static void
949cancel_all_timers (T_DHCP4_CLI_CONTEXT *ct)
950{
951 int ix;
952
953 syscall(wai_sem(SEM_DHCP4_CLI_TIMER));
954 for (ix = NUM_DHCP4C_TIMERS; ix -- > 0; )
955 ct->timers[ix] = 0;
956 syscall(sig_sem(SEM_DHCP4_CLI_TIMER));
957 }
958
959
960/*
961 * start_select -- DISCOVER メッセージを送信して SELECT 状æ…
962‹ã«é·ç§»ã™ã‚‹ã€‚
963 */
964
965static void
966start_select (T_DHCP4_CLI_CONTEXT *ct)
967{
968 /* 送信を開始した時間を記録する。*/
969 get_tim(&ct->snd_start);
970
971 /* OFFER メッセージ受信タイムアウトを設定する。*/
972 syscall(wai_sem(SEM_DHCP4_CLI_TIMER));
973 ct->timers[DHCP4C_TIMER_RCV_OFFER] = SYSTIM2TIMER(TMO_DHCP4C_OFFER);
974 syscall(sig_sem(SEM_DHCP4_CLI_TIMER));
975
976 /* 送信å…
977ˆã‚¢ãƒ‰ãƒ¬ã‚¹ã«ãƒ­ãƒ¼ã‚«ãƒ«ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯ã¸ã®ãƒ–ロードキャストを設定する。*/
978 ct->dst.ipaddr = IPV4_ADDRBROADCAST;
979
980 /* 送信間隔をリセットする。*/
981 ct->interval = 0;
982
983 /* SELECT 状æ…
984‹ã«é·ç§»ã™ã‚‹ã€‚*/
985 ct->fsm = DHCP4_FSM_SELECT;
986
987 /* DISCOVER メッセージを送信する。*/
988 ct->flags |= DHCP4C_FLAG_TMOUT_SND_DISC;
989 syscall(sig_sem(SEM_DHCP4_CLI_READY));
990 }
991
992/*
993 * start_bound -- BOUND 状æ…
994‹ã«é·ç§»ã™ã‚‹ã€‚
995 */
996
997static void
998start_bound (T_DHCP4_CLI_CONTEXT *ct)
999{
1000 /* リースされた情
1001報を設定する。*/
1002 set_lease(ct);
1003
1004 /* リースの有効時間を設定する。*/
1005 ct->expire = timer_value(ct->act_msg, DHCP4_OPT_LEASE_TIME, TMO_DHCP4C_DEF_LEASE);
1006
1007 /* リース時間が TMO_DHCP4C_MIN_LEASE 以下の時は、TMO_DHCP4C_MIN_LEASE に設定する。*/
1008 if (ct->expire < TMO_DHCP4C_MIN_LEASE)
1009 ct->expire = TMO_DHCP4C_MIN_LEASE;
1010
1011 /* RENEW 状æ…
1012‹ã¾ã§ã®æ™‚間を設定する。*/
1013 ct->renew = timer_value(ct->act_msg, DHCP4_OPT_RENEWAL_T1, ct->expire / 2);
1014
1015 /* REBIND 状æ…
1016‹ã¾ã§ã®æ™‚間を設定する。*/
1017 ct->rebind = timer_value(ct->act_msg, DHCP4_OPT_REBINDING_T2, ct->renew + ct->renew / 2 + ct->renew / 4);
1018
1019 /* EXPIRE、RENEW、REBIND タイマーを設定する。*/
1020 syscall(wai_sem(SEM_DHCP4_CLI_TIMER));
1021 ct->timers[DHCP4C_TIMER_EXPIRE] = SYSTIM2TIMER(ct->expire); /* EXPIRE までの時間 */
1022 ct->timers[DHCP4C_TIMER_REBIND] = SYSTIM2TIMER(ct->rebind); /* REBIND(T2)までの時間 */
1023 ct->timers[DHCP4C_TIMER_RENEW] = SYSTIM2TIMER(ct->renew); /* RENEW (T1)までの時間 */
1024 syscall(sig_sem(SEM_DHCP4_CLI_TIMER));
1025
1026 /* BOUND 状æ…
1027‹ã«é·ç§»ã™ã‚‹ã€‚*/
1028 ct->fsm = DHCP4_FSM_BOUND;
1029
1030 /* BIND を開始した時間を記録する。*/
1031 get_tim(&ct->bind_start);
1032 }
1033
1034/*
1035 * start_send_request -- REQUEST メッセージを送信して、指定された状æ…
1036‹ã«é·ç§»ã™ã‚‹ã€‚
1037 */
1038
1039static void
1040start_send_request (T_DHCP4_CLI_CONTEXT *ct, uint_t fsm)
1041{
1042 T_IFNET *ifp = IF_GET_IFNET();
1043
1044 /* 送信を開始した時間を記録する。*/
1045 get_tim(&ct->snd_start);
1046
1047 /* 遷移する状æ…
1048‹ãŒ RENEW 以外では ACK/NAK メッセージ受信タイムアウトを設定する。*/
1049 if (fsm != DHCP4_FSM_RENEW) {
1050 syscall(wai_sem(SEM_DHCP4_CLI_TIMER));
1051 ct->timers[DHCP4C_TIMER_RCV_ACK] = SYSTIM2TIMER(TMO_DHCP4C_ACK);
1052 syscall(sig_sem(SEM_DHCP4_CLI_TIMER));
1053 }
1054
1055 /*
1056 * 遷移する状æ…
1057‹ãŒ RENEW で、
1058 * SERVER ID オプションがあればローカルネットワークへのブロードキャストを送信する。
1059 */
1060 if ((fsm == DHCP4_FSM_RENEW) &&
1061 (find_option(ct->act_msg, DHCP4_OPT_SERVER_ID, sizeof(T_IN4_ADDR)) != NULL))
1062 ct->dst.ipaddr = (ifp->in4_ifaddr.addr & ifp->in4_ifaddr.mask) | ~ifp->in4_ifaddr.mask;
1063 else
1064 ct->dst.ipaddr = IPV4_ADDRBROADCAST;
1065
1066 /* 送信間隔をリセットする。*/
1067 ct->interval = 0;
1068
1069 /* 指定された状æ…
1070‹ã«é·ç§»ã™ã‚‹ã€‚*/
1071 ct->fsm = fsm;
1072
1073 /* REQUEST メッセージを送信する。*/
1074 ct->flags |= DHCP4C_FLAG_TMOUT_SND_REQ;
1075 syscall(sig_sem(SEM_DHCP4_CLI_READY));
1076 }
1077
1078/*
1079 * start_rel_info -- アドレス情
1080報を解放する。
1081 *
1082 * 注意: DHCPv4 の RFC2131 には無い
1083 */
1084
1085static void
1086start_rel_info (T_DHCP4_CLI_CONTEXT *ct)
1087{
1088 /* å…
1089¨ã¦ã® TIMER をキャンセルする。*/
1090 cancel_all_timers(ct);
1091
1092 /* 有効なリース情
1093報が無ければ SLEEP に遷移する。*/
1094 if (ct->act_msg == NULL) {
1095 ct->fsm = DHCP4_FSM_SLEEP;
1096 return;
1097 }
1098
1099 /* 送信å…
1100ˆã‚¢ãƒ‰ãƒ¬ã‚¹ã«ãƒ­ãƒ¼ã‚«ãƒ«ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯ã¸ã®ãƒ–ロードキャストを設定する。*/
1101 ct->dst.ipaddr = IPV4_ADDRBROADCAST;
1102
1103 /* RELEASE メッセージを送信する。*/
1104 ct->flags |= DHCP4C_FLAG_TMOUT_SND_REL;
1105 syscall(sig_sem(SEM_DHCP4_CLI_READY));
1106 }
1107
1108/*
1109 * setup_dhcp_com_msg -- DHCP メッセージのå…
1110±é€šéƒ¨åˆ†ã‚’作成する。
1111 */
1112
1113static uint8_t *
1114setup_dhcp_com_msg (T_DHCP4_CLI_CONTEXT *ct, uint_t op, uint_t type)
1115{
1116 uint8_t *option;
1117
1118 memset((void*)&ct->snd_msg->msg, sizeof(ct->snd_msg->msg), 0);
1119 ct->snd_msg->len = sizeof(ct->snd_msg->msg);
1120
1121 /* ヘッダ部を設定する。*/
1122 ct->snd_msg->msg.op = op;
1123 ct->snd_msg->msg.htype = DHCP4_HWA_TYPE_ETHER;
1124 ct->snd_msg->msg.hlen = ETHER_ADDR_LEN;
1125 HOST2MSG32(ct->snd_msg->msg.xid, ct->xid);
1126
1127 /* MAC アドレスを設定する。*/
1128 memcpy(&ct->snd_msg->msg.chaddr, &ct->sc->ifaddr.lladdr, ETHER_ADDR_LEN);
1129
1130 /*
1131 * オプション部を設定する。
1132 */
1133
1134 /* RFC1048 に定義されているマジック番号を設定する。*/
1135 memcpy(&ct->snd_msg->msg.options, magicno, DHCP4_MAGIC_LEN);
1136 option = ct->snd_msg->msg.options + DHCP4_MAGIC_LEN;
1137
1138 /* DHCP メッセージタイプを設定する。*/
1139 *(option ++) = DHCP4_OPT_MSG_TYPE;
1140 *(option ++) = 1;
1141 *(option ++) = type;
1142
1143 return option;
1144 }
1145
1146/*
1147 * setup_release_msg -- RELEASE メッセージを作成する。
1148 */
1149
1150static ER
1151setup_release_msg (T_DHCP4_CLI_CONTEXT *ct, T_DHCP4_CLI_MSG *ref)
1152{
1153 uint8_t *opt, *ref_opt;
1154
1155 /* 有効なリース・メッセージがなければエラー */
1156 if (ref == NULL)
1157 return E_PAR;
1158
1159 ct->xid = create_xid();
1160 if ((opt = setup_dhcp_com_msg(ct, DHCP4_REQUEST, DHCP4_MTYPE_RELEASE)) == NULL)
1161 return E_PAR;
1162
1163 /*
1164 * サーバ ID(server-ip)を設定する。
1165 * RFC2131 4.4.1 Initialization and allocation of network address 参ç…
1166§
1167 */
1168 if ((ref_opt = find_option(ref, DHCP4_OPT_SERVER_ID, sizeof(T_IN4_ADDR))) == NULL)
1169 return E_PAR;
1170 *(opt ++) = *(ref_opt ++);
1171 *(opt ++) = *(ref_opt ++);
1172 memcpy(opt, ref_opt, *(ref_opt - 1));
1173 opt += *(ref_opt - 1);
1174
1175 /*
1176 * クライアント ID(MAC アドレス)を設定する。
1177 * RFC2131 4.4.1 Initialization and allocation of network address 参ç…
1178§
1179 */
1180 *(opt ++) = DHCP4_OPT_CLIENT_ID;
1181 *(opt ++) = ETHER_ADDR_LEN + 1;
1182 *(opt ++) = DHCP4_HWA_TYPE_ETHER;
1183 memcpy(opt, &ct->sc->ifaddr.lladdr, ETHER_ADDR_LEN);
1184 opt += ETHER_ADDR_LEN;
1185
1186 /* オプションの終了を設定する。*/
1187 *(opt ++) = DHCP4_OPT_END;
1188
1189 /*
1190 * クライアント IP アドレス(ciaddr)を設定する。
1191 * RFC2131 4.4.1 Initialization and allocation of network address 参ç…
1192§
1193 */
1194 HOST2MSG32(ct->snd_msg->msg.ciaddr, IF_GET_IFNET()->in4_ifaddr.addr);
1195
1196 /* メッセージ長を設定する。*/
1197 ct->snd_msg->len = sizeof(ct->snd_msg->msg) - DHCP4_DFLT_OPT_LEN
1198 + (opt - (uint8_t*)&ct->snd_msg->msg.options);
1199 return E_OK;
1200 }
1201
1202
1203/*
1204 * setup_request_msg -- REQUEST メッセージを作成する。
1205 */
1206
1207static ER
1208setup_request_msg (T_DHCP4_CLI_CONTEXT *ct, T_DHCP4_CLI_MSG *ref)
1209{
1210 uint8_t *opt, *ref_opt;
1211
1212#if defined(DHCP4_CLI_CFG_REQUIRED_OLIST) || defined(DHCP4_CLI_CFG_REQUEST_OLIST)
1213 uint_t len = 0;
1214#endif
1215
1216 /* 参ç…
1217§ã™ã‚‹ãƒ¡ãƒƒã‚»ãƒ¼ã‚¸ãŒãªã‘ればエラー */
1218 if (ref == NULL)
1219 return E_PAR;
1220
1221 ct->xid = create_xid();
1222 if ((opt = setup_dhcp_com_msg(ct, DHCP4_REQUEST, DHCP4_MTYPE_REQUEST)) == NULL)
1223 return E_PAR;
1224
1225#if defined(DHCP4_CLI_CFG_REQUIRED_OLIST) || defined(DHCP4_CLI_CFG_REQUEST_OLIST)
1226
1227 /* 追加のオプションを設定する。*/
1228
1229 *opt = DHCP4_OPT_REQ_PARAM;
1230 opt += 2;
1231
1232#if defined(DHCP4_CLI_CFG_REQUIRED_OLIST)
1233
1234 /* 要求オプションリストを設定する。*/
1235 if (sizeof(required_plist) > 0) {
1236 memcpy(opt, required_plist, sizeof(required_plist));
1237 opt += sizeof(required_plist);
1238 len += sizeof(required_plist);
1239 }
1240
1241#endif /* of #if defined(DHCP4_CLI_CFG_REQUIRED_OLIST) */
1242
1243#if defined(DHCP4_CLI_CFG_REQUEST_OLIST)
1244
1245 /* 要求オプションリストを設定する。*/
1246 if (sizeof(request_plist) > 0) {
1247 memcpy(opt, request_plist, sizeof(request_plist));
1248 opt += sizeof(request_plist);
1249 len += sizeof(request_plist);
1250 }
1251
1252#endif /* of #if defined(DHCP4_CLI_CFG_REQUEST_OLIST) */
1253
1254 *(opt - len - 1) = len;
1255
1256#endif /* of #if defined(DHCP4_CLI_CFG_REQUIRED_OLIST) || defined(DHCP4_CLI_CFG_REQUEST_OLIST) */
1257
1258 /*
1259 * サーバ ID(server-ip)を設定する。
1260 * RFC2131 4.4.1 Initialization and allocation of network address 参ç…
1261§
1262 */
1263 if (ct->fsm == DHCP4_FSM_REQUEST) {
1264 if ((ref_opt = find_option(ref, DHCP4_OPT_SERVER_ID, sizeof(T_IN4_ADDR))) == NULL)
1265 return E_PAR;
1266 *(opt ++) = *(ref_opt ++);
1267 *(opt ++) = *(ref_opt ++);
1268 memcpy(opt, ref_opt, *(ref_opt - 1));
1269 opt += *(ref_opt - 1);
1270 }
1271
1272 /*
1273 * 要求 IP アドレス(requested-ip)を設定する。
1274 * RFC2131 4.4.1 Initialization and allocation of network address 参ç…
1275§
1276 * RFC2131 では、DHCP4_FSM_RENEW の時 MUST NOT になっているが、
1277 * MUST のようである。
1278 */
1279 *(opt ++) = DHCP4_OPT_REQ_IPV4;
1280 *(opt ++) = sizeof(ref->msg.yiaddr);
1281 if (ct->fsm == DHCP4_FSM_REQUEST || ct->fsm == DHCP4_FSM_INIT_REBOOT ||
1282 ct->fsm == DHCP4_FSM_RENEW || ct->fsm == DHCP4_FSM_REBIND)
1283 /* 参ç…
1284§ãƒ¡ãƒƒã‚»ãƒ¼ã‚¸ã¨åŒã˜ IP アドレス(requested-ip)を要求する。*/
1285 memcpy(opt, (uint8_t*)&ref->msg.yiaddr, sizeof(ref->msg.yiaddr));
1286 else
1287 host2msg32(opt, IPV4_ADDRANY);
1288 opt += sizeof(ref->msg.yiaddr);
1289
1290 /*
1291 * クライアント ID(MAC アドレス)を設定する。
1292 * RFC2131 4.4.1 Initialization and allocation of network address 参ç…
1293§
1294 */
1295 *(opt ++) = DHCP4_OPT_CLIENT_ID;
1296 *(opt ++) = ETHER_ADDR_LEN + 1;
1297 *(opt ++) = DHCP4_HWA_TYPE_ETHER;
1298 memcpy(opt, &ct->sc->ifaddr.lladdr, ETHER_ADDR_LEN);
1299 opt += ETHER_ADDR_LEN;
1300
1301 /* オプションの終了を設定する。*/
1302 *(opt ++) = DHCP4_OPT_END;
1303
1304 /*
1305 * クライアント IP アドレス(ciaddr)を設定する。
1306 * RFC2131 4.4.1 Initialization and allocation of network address 参ç…
1307§
1308 */
1309 if (ct->fsm == DHCP4_FSM_RENEW || ct->fsm == DHCP4_FSM_REBIND)
1310 HOST2MSG32(ct->snd_msg->msg.ciaddr, IF_GET_IFNET()->in4_ifaddr.addr);
1311 else
1312 HOST2MSG32(ct->snd_msg->msg.ciaddr, IPV4_ADDRANY);
1313
1314 /* メッセージ長を設定する。*/
1315 ct->snd_msg->len = sizeof(ct->snd_msg->msg) - DHCP4_DFLT_OPT_LEN
1316 + (opt - (uint8_t*)&ct->snd_msg->msg.options);
1317 return E_OK;
1318 }
1319
1320/*
1321 * setup_discover_msg -- DISCOVER メッセージを作成する。
1322 */
1323
1324static ER
1325setup_discover_msg (T_DHCP4_CLI_CONTEXT *ct)
1326{
1327 uint8_t *opt;
1328
1329#if defined(DHCP4_CLI_CFG_REQUIRED_OLIST) || defined(DHCP4_CLI_CFG_REQUEST_OLIST)
1330 uint_t len = 0;
1331#endif
1332
1333 ct->xid = create_xid();
1334 if ((opt = setup_dhcp_com_msg(ct, DHCP4_REQUEST, DHCP4_MTYPE_DISCOVER)) == NULL)
1335 return E_PAR;
1336
1337#if defined(DHCP4_CLI_CFG_REQUIRED_OLIST) || defined(DHCP4_CLI_CFG_REQUEST_OLIST)
1338
1339 /* 追加のオプションを設定する。*/
1340
1341 *opt = DHCP4_OPT_REQ_PARAM;
1342 opt += 2;
1343
1344#if defined(DHCP4_CLI_CFG_REQUIRED_OLIST)
1345
1346 /* 要求オプションリストを設定する。*/
1347 if (sizeof(required_plist) > 0) {
1348 memcpy(opt, required_plist, sizeof(required_plist));
1349 opt += sizeof(required_plist);
1350 len += sizeof(required_plist);
1351 }
1352
1353#endif /* of #if defined(DHCP4_CLI_CFG_REQUIRED_OLIST) */
1354
1355#if defined(DHCP4_CLI_CFG_REQUEST_OLIST)
1356
1357 /* 要求オプションリストを設定する。*/
1358 if (sizeof(request_plist) > 0) {
1359 memcpy(opt, request_plist, sizeof(request_plist));
1360 opt += sizeof(request_plist);
1361 len += sizeof(request_plist);
1362 }
1363
1364#endif /* of #if defined(DHCP4_CLI_CFG_REQUEST_OLIST) */
1365
1366 *(opt - len - 1) = len;
1367
1368#endif /* of #if defined(DHCP4_CLI_CFG_REQUIRED_OLIST) || defined(DHCP4_CLI_CFG_REQUEST_OLIST) */
1369
1370 /* 既にアドレス情
1371報がリースされていれば、同じ IP アドレスを要求する。*/
1372 if (ct->act_msg != NULL) {
1373 *(opt ++) = DHCP4_OPT_REQ_IPV4;
1374 *(opt ++) = sizeof(ct->act_msg->msg.yiaddr);
1375 memcpy(opt, (uint8_t*)&ct->act_msg->msg.yiaddr, sizeof(ct->act_msg->msg.yiaddr));
1376 opt += sizeof(ct->act_msg->msg.yiaddr);
1377 }
1378
1379 /* クライアント ID(MAC アドレス)を設定する。*/
1380 *(opt ++) = DHCP4_OPT_CLIENT_ID;
1381 *(opt ++) = ETHER_ADDR_LEN + 1;
1382 *(opt ++) = DHCP4_HWA_TYPE_ETHER;
1383 memcpy(opt, &ct->sc->ifaddr.lladdr, ETHER_ADDR_LEN);
1384 opt += ETHER_ADDR_LEN;
1385
1386 /* オプションの終了を設定する。*/
1387 *(opt ++) = DHCP4_OPT_END;
1388
1389 /* 送信å…
1390ˆã‚¢ãƒ‰ãƒ¬ã‚¹ã‚’設定する。*/
1391 ct->dst.ipaddr = IPV4_ADDRBROADCAST;
1392
1393 /* メッセージ長を設定する。*/
1394 ct->snd_msg->len = sizeof(ct->snd_msg->msg) - DHCP4_DFLT_OPT_LEN
1395 + (opt - (uint8_t*)&ct->snd_msg->msg.options);
1396 return E_OK;
1397 }
1398
1399/*
1400 * ack_msg_timeout -- ACK/NAK メッセージ受信タイムアウト処理
1401 */
1402
1403static void
1404ack_msg_timeout (T_DHCP4_CLI_CONTEXT *ct)
1405{
1406 /* ACK メッセージを受信していれば。BOUND 状æ…
1407‹ã«é·ç§»ã™ã‚‹ã€‚*/
1408 ct->flags &= ~DHCP4C_FLAG_TMOUT_MASK;
1409 if (select_ack(ct)) {
1410
1411 /* REQUEST メッセージ送信タイマーを停止する。*/
1412 syscall(wai_sem(SEM_DHCP4_CLI_TIMER));
1413 ct->timers[DHCP4C_TIMER_SND_REQ] = 0;
1414 syscall(sig_sem(SEM_DHCP4_CLI_TIMER));
1415
1416 /*
1417 * 状æ…
1418‹ãŒ REQUEST の時は、
1419 * OFFER メッセージを受信メッセージ構造体リストに戻す。
1420 */
1421 if (ct->fsm == DHCP4_FSM_REQUEST && ct->off_msg != NULL) {
1422 syscall(wai_sem(SEM_DHCP4_CLI_LOCK));
1423 ct->off_msg->next = ct->rcv_lst;
1424 ct->rcv_lst = ct->off_msg;
1425 syscall(sig_sem(SEM_DHCP4_CLI_LOCK));
1426 ct->off_msg = NULL;
1427 }
1428
1429 /* BOUND 状æ…
1430‹ã«é·ç§»ã™ã‚‹ã€‚*/
1431 start_bound(ct);
1432 return;
1433 }
1434 else {
1435
1436 /* リース情
1437報を解放する。*/
1438 rel_lease(ct);
1439
1440 ct->error = E_TMOUT;
1441 }
1442 }
1443
1444/*
1445 * send_request_msg -- REQUEST メッセージを送信する。
1446 */
1447
1448static void
1449send_request_msg (T_DHCP4_CLI_CONTEXT *ct)
1450{
1451 T_DHCP4_CLI_MSG *ref;
1452 ER error;
1453 SYSTIM time;
1454 RELTIM interval;
1455 uint16_t secs;
1456
1457 /* タイムアウトフラグをクリアーする。*/
1458 ct->flags &= ~DHCP4C_FLAG_TMOUT_MASK;
1459
1460 /* ACK メッセージを受信していれば。BOUND 状æ…
1461‹ã«é·ç§»ã™ã‚‹ã€‚*/
1462 ct->flags &= ~DHCP4C_FLAG_TMOUT_MASK;
1463 if (select_ack(ct)) {
1464
1465 /* ACK/NAK メッセージ受信タイマーを停止する。*/
1466 syscall(wai_sem(SEM_DHCP4_CLI_TIMER));
1467 ct->timers[DHCP4C_TIMER_RCV_ACK] = 0;
1468 syscall(sig_sem(SEM_DHCP4_CLI_TIMER));
1469
1470 /*
1471 * 状æ…
1472‹ãŒ REQUEST の時は、
1473 * OFFER メッセージを受信メッセージ構造体リストに戻す。
1474 */
1475 if (ct->fsm == DHCP4_FSM_REQUEST && ct->off_msg != NULL) {
1476 syscall(wai_sem(SEM_DHCP4_CLI_LOCK));
1477 ct->off_msg->next = ct->rcv_lst;
1478 ct->rcv_lst = ct->off_msg;
1479 syscall(sig_sem(SEM_DHCP4_CLI_LOCK));
1480 ct->off_msg = NULL;
1481 }
1482
1483 /* BOUND 状æ…
1484‹ã«é·ç§»ã™ã‚‹ã€‚*/
1485 start_bound(ct);
1486 return;
1487 }
1488
1489 /* REQUEST メッセージを作成する。*/
1490 if (ct->fsm == DHCP4_FSM_REQUEST)
1491 ref = ct->off_msg;
1492 else
1493 ref = ct->act_msg;
1494 if ((error = setup_request_msg(ct, ref)) != E_OK) {
1495 syslog(LOG_NOTICE, "[DHCP4C] error, setup request message: %s", itron_strerror(error));
1496 ct->error = error;
1497 return;
1498 }
1499
1500 /* 送信を開始してからの時間を得る。*/
1501 get_tim(&time);
1502 interval = time - ct->snd_start;
1503
1504 /*
1505 * 送信を開始してからの時間(秒)をメッセージに設定する。
1506 * 最大値は 65535。
1507 */
1508 if (ct->fsm == DHCP4_FSM_REQUEST)
1509 secs = ct->secs;
1510 else {
1511 if (SYSTIM2SEC(interval) < 65536)
1512 secs = SYSTIM2SEC(interval);
1513 else
1514 secs = 65535;
1515 }
1516 HOST2MSG16(ct->snd_msg->msg.secs, secs);
1517
1518 /* ノンブロッキングコールでメッセージを送信する。*/
1519 error = udp_snd_dat(ct->cepid, &ct->dst, &ct->snd_msg->msg, ct->snd_msg->len, TMO_NBLK);
1520 if (error != E_WBLK) {
1521 syslog(LOG_NOTICE, "[DHCP4C] error, send request message: %s", itron_strerror(error));
1522 ct->error = error;
1523 return;
1524 }
1525
1526 /* 送信間隔を設定する。*/
1527 if (ct->interval == 0)
1528 /* 未設定 */
1529 ct->interval = TMO_DHCP4C_INIT_INTVL;
1530 else
1531 /* バックオフアルゴリズムで 2倍にした(乱数使用)送信間隔を加算する。*/
1532 ct->interval += (netapp_rand() >> 2) % (ct->interval << 1);
1533
1534 /* 送信周期の制限値を超
1535えないようにする。*/
1536 if (ct->interval > TMO_DHCP4C_MAX_BACKOFF)
1537 ct->interval = (TMO_DHCP4C_MAX_BACKOFF >> 1) + ((netapp_rand() >> 2) % TMO_DHCP4C_MAX_BACKOFF);
1538
1539 /* リース時間のタイムアウト【å…
1540ˆé€ã‚Šã€‘ */
1541 if (ct->fsm != DHCP4_FSM_REQUEST &&
1542 TIMEC_GT(ct->interval + time, ct->expire + ct->bind_start))
1543 ct->interval = ct->expire + ct->bind_start - time + SYSTIM_HZ;
1544
1545 /* 再送信タイムアウトを設定する。*/
1546 syscall(wai_sem(SEM_DHCP4_CLI_TIMER));
1547 ct->timers[DHCP4C_TIMER_SND_REQ] = SYSTIM2TIMER(ct->interval);
1548 syscall(sig_sem(SEM_DHCP4_CLI_TIMER));
1549 }
1550
1551/*
1552 * send_release_msg -- RELEASE メッセージを送信する。
1553 */
1554
1555static void
1556send_release_msg (T_DHCP4_CLI_CONTEXT *ct)
1557{
1558 ER error;
1559
1560 /* タイムアウトフラグをクリアーする。*/
1561 ct->flags &= ~DHCP4C_FLAG_TMOUT_MASK;
1562
1563 /* RELEASE メッセージを作成する。*/
1564 if ((error = setup_release_msg(ct, ct->act_msg)) != E_OK) {
1565 syslog(LOG_NOTICE, "[DHCP4C] error, setup release message: %s", itron_strerror(error));
1566 ct->error = error;
1567 return;
1568 }
1569
1570 /* リース情
1571報を解放する。*/
1572 rel_lease(ct);
1573
1574 /* ノンブロッキングコールでメッセージを送信する。*/
1575 error = udp_snd_dat(ct->cepid, &ct->dst, &ct->snd_msg->msg, ct->snd_msg->len, TMO_NBLK);
1576 if (error != E_WBLK) {
1577 syslog(LOG_NOTICE, "[DHCP4C] error, send release message: %s", itron_strerror(error));
1578 ct->error = error;
1579 return;
1580 }
1581
1582 /* メッセージ送信待
1583ちを行う。*/
1584 syscall(wai_sem(SEM_DHCP4_CLI_READY));
1585
1586 /* SLEEP 状æ…
1587‹ã«é·ç§»ã™ã‚‹ã€‚*/
1588 ct->fsm = DHCP4_FSM_SLEEP;
1589 }
1590
1591/*
1592 * offer_msg_timeout -- OFFER メッセージ受信タイムアウト処理
1593 */
1594
1595static void
1596offer_msg_timeout (T_DHCP4_CLI_CONTEXT *ct)
1597{
1598 /* OFFER メッセージを受信していれば。REQUEST 状æ…
1599‹ã«é·ç§»ã™ã‚‹ã€‚*/
1600 ct->flags &= ~DHCP4C_FLAG_TMOUT_MASK;
1601 if (select_offer(ct)) {
1602
1603 /* DISCOVER メッセージ送信タイマーを停止する。*/
1604 syscall(wai_sem(SEM_DHCP4_CLI_TIMER));
1605 ct->timers[DHCP4C_TIMER_SND_DISC] = 0;
1606 syscall(sig_sem(SEM_DHCP4_CLI_TIMER));
1607
1608 /* REQUEST メッセージを送信して REQUEST 状æ…
1609‹ã«é·ç§»ã™ã‚‹ã€‚*/
1610 start_send_request(ct, DHCP4_FSM_REQUEST);
1611 }
1612 else
1613 ct->error = E_TMOUT;
1614 }
1615
1616/*
1617 * send_discover_msg -- DISCOVERメッセージを送信する。
1618 */
1619
1620static void
1621send_discover_msg (T_DHCP4_CLI_CONTEXT *ct)
1622{
1623 ER error;
1624 SYSTIM time;
1625 RELTIM interval;
1626
1627 /* タイムアウトフラグをクリアーする。*/
1628 ct->flags &= ~DHCP4C_FLAG_TMOUT_MASK;
1629
1630 /* OFFER メッセージを受信していれば。REQUEST 状æ…
1631‹ã«é·ç§»ã™ã‚‹ã€‚*/
1632 ct->flags &= ~DHCP4C_FLAG_TMOUT_MASK;
1633 if (select_offer(ct)) {
1634
1635 /* OFFER メッセージ受信タイマーを停止する。*/
1636 syscall(wai_sem(SEM_DHCP4_CLI_TIMER));
1637 ct->timers[DHCP4C_TIMER_RCV_OFFER] = 0;
1638 syscall(sig_sem(SEM_DHCP4_CLI_TIMER));
1639
1640 /* REQUEST メッセージを送信して REQUEST 状æ…
1641‹ã«é·ç§»ã™ã‚‹ã€‚*/
1642 start_send_request(ct, DHCP4_FSM_REQUEST);
1643 return;
1644 }
1645
1646 /* DISCOVER メッセージを作成する。*/
1647 if ((error = setup_discover_msg(ct)) != E_OK) {
1648 syslog(LOG_NOTICE, "[DHCP4C] error, setup discover message: %s", itron_strerror(error));
1649 ct->error = error;
1650 return;
1651 }
1652
1653 /* 送信を開始してからの時間を得る。*/
1654 get_tim(&time);
1655 interval = time - ct->snd_start;
1656
1657 /*
1658 * 送信を開始してからの時間(秒)をメッセージに設定する。
1659 * 最大値は 65535。
1660 */
1661 if (SYSTIM2SEC(interval) < 65536)
1662 ct->secs = SYSTIM2SEC(interval);
1663 else
1664 ct->secs = 65535;
1665 HOST2MSG16(ct->snd_msg->msg.secs, ct->secs);
1666
1667 /* ノンブロッキングコールでメッセージを送信する。*/
1668 error = udp_snd_dat(ct->cepid, &ct->dst, &ct->snd_msg->msg, ct->snd_msg->len, TMO_NBLK);
1669 if (error != E_WBLK) {
1670 syslog(LOG_NOTICE, "[DHCP4C] error, send discover message: %s", itron_strerror(error));
1671 ct->error = error;
1672 return;
1673 }
1674
1675 /* 送信間隔を設定する。*/
1676 if (ct->interval == 0)
1677 /* 未設定 */
1678 ct->interval = TMO_DHCP4C_INIT_INTVL;
1679 else
1680 /* バックオフアルゴリズムで 2倍にした(乱数使用)送信間隔を加算する。*/
1681 ct->interval += (netapp_rand() >> 2) % (ct->interval << 1);
1682
1683 /* 送信周期の制限値を超
1684えないようにする。*/
1685 if (ct->interval > TMO_DHCP4C_MAX_BACKOFF)
1686 ct->interval = (TMO_DHCP4C_MAX_BACKOFF >> 1) + ((netapp_rand() >> 2) % TMO_DHCP4C_MAX_BACKOFF);
1687
1688 /* OFFER メッセージの受信タイムアウトを超
1689えないように調整する。*/
1690 if (TIMEC_GT(time + ct->interval, ct->snd_start + TMO_DHCP4C_OFFER))
1691 ct->interval = (TMO_DHCP4C_INIT_INTVL + TMO_DHCP4C_OFFER) - time + 1;
1692
1693 /* 再送信タイムアウトを設定する。*/
1694 syscall(wai_sem(SEM_DHCP4_CLI_TIMER));
1695 ct->timers[DHCP4C_TIMER_SND_DISC] = SYSTIM2TIMER(ct->interval);
1696 syscall(sig_sem(SEM_DHCP4_CLI_TIMER));
1697 }
1698
1699/*
1700 * dhcpc_timer -- TIMER 管理
1701 */
1702
1703static void
1704dhcpc_timer (T_DHCP4_CLI_CONTEXT *ct)
1705{
1706 int ix;
1707
1708 syscall(wai_sem(SEM_DHCP4_CLI_TIMER));
1709 for (ix = NUM_DHCP4C_TIMERS; ix -- > 0; ) {
1710 if (ct->timers[ix] != 0) {
1711 ct->timers[ix] --;
1712 if (ct->timers[ix] == 0) {
1713 ct->flags = (ct->flags & ~DHCP4C_FLAG_TMOUT_MASK) | DHCP4C_FLAG_TMOUT_TIMER | ix;
1714 syscall(sig_sem(SEM_DHCP4_CLI_READY));
1715 }
1716 }
1717 }
1718 syscall(sig_sem(SEM_DHCP4_CLI_TIMER));
1719
1720 /* 1秒毎にタイムアウトする。*/
1721 timeout((callout_func)dhcpc_timer, ct, NET_TIMER_HZ);
1722 }
1723
1724/*
1725 * expire_timeout -- EXPIRE タイムアウト処理
1726 */
1727
1728static void
1729expire_timeout (T_DHCP4_CLI_CONTEXT *ct)
1730{
1731 //ER error;
1732
1733 /* タイムアウトフラグをクリアーする。*/
1734 ct->flags &= ~DHCP4C_FLAG_TMOUT_MASK;
1735
1736 /* 状æ…
1737‹ãŒ REQUEST の時は何もしない。*/
1738 if (ct->fsm == DHCP4_FSM_REQUEST)
1739 return;
1740
1741 /* å…
1742¨ã¦ã® TIMER をキャンセルする。*/
1743 cancel_all_timers(ct);
1744
1745 /* リースされた情
1746報を解放する。*/
1747 rel_lease(ct);
1748
1749 ct->error = E_TMOUT;
1750 }
1751
1752/*
1753 * rebind_timeout -- REBIND タイムアウト処理
1754 */
1755
1756static void
1757rebind_timeout (T_DHCP4_CLI_CONTEXT *ct)
1758{
1759 /* タイムアウトフラグをクリアーする。*/
1760 ct->flags &= ~DHCP4C_FLAG_TMOUT_MASK;
1761
1762 /* å…
1763¨ã¦ã® TIMER をキャンセルする。*/
1764 cancel_all_timers(ct);
1765
1766 /* REQUEST メッセージを送信して REBIND 状æ…
1767‹ã«é·ç§»ã™ã‚‹ã€‚*/
1768 start_send_request(ct, DHCP4_FSM_REBIND);
1769 }
1770
1771/*
1772 * renew_timeout -- RENEW タイムアウト処理
1773 */
1774
1775static void
1776renew_timeout (T_DHCP4_CLI_CONTEXT *ct)
1777{
1778 /* タイムアウトフラグをクリアーする。*/
1779 ct->flags &= ~DHCP4C_FLAG_TMOUT_MASK;
1780
1781 /* REQUEST メッセージを送信して RENEW 状æ…
1782‹ã«é·ç§»ã™ã‚‹ã€‚*/
1783 start_send_request(ct, DHCP4_FSM_RENEW);
1784 }
1785
1786/*
1787 * dispatch_timeout -- タイムアウトした時の処理
1788 */
1789
1790static ER
1791dispatch_timeout (T_DHCP4_CLI_CONTEXT *ct)
1792{
1793 switch (ct->flags & DHCP4C_FLAG_TMOUT_TIMER_MASK) {
1794
1795 case DHCP4C_TIMER_SND_DISC:
1796 send_discover_msg(ct);
1797 break;
1798
1799 case DHCP4C_TIMER_SND_REQ:
1800 send_request_msg(ct);
1801 break;
1802
1803 case DHCP4C_TIMER_RCV_OFFER:
1804 offer_msg_timeout(ct);
1805 break;
1806
1807 case DHCP4C_TIMER_RCV_ACK:
1808 ack_msg_timeout(ct);
1809 break;
1810
1811 case DHCP4C_TIMER_RENEW:
1812 renew_timeout(ct);
1813 break;
1814
1815 case DHCP4C_TIMER_REBIND:
1816 rebind_timeout(ct);
1817 break;
1818
1819 case DHCP4C_TIMER_EXPIRE:
1820 expire_timeout(ct);
1821 break;
1822
1823 case DHCP4C_TIMER_SND_REL:
1824 send_release_msg(ct);
1825 break;
1826
1827 default:
1828 break;
1829 }
1830
1831 return ct->error;
1832 }
1833
1834/*
1835 * dispatch_event -- イベント毎の処理
1836 */
1837
1838static ER
1839dispatch_event (T_DHCP4_CLI_CONTEXT *ct)
1840{
1841 ER error = E_OK;
1842
1843 while (ct->fsm != DHCP4_FSM_SLEEP && error == E_OK) {
1844
1845 /* メッセージの受信とタイムアウトを待
1846つ。*/
1847 syscall(wai_sem(SEM_DHCP4_CLI_READY));
1848
1849 if (ct->flags & DHCP4C_FLAG_RCV_MSG) {
1850 while (ct->val_lst != NULL) {
1851 error = eval_rcv_msg(ct);
1852 }
1853 ct->flags &= ~DHCP4C_FLAG_RCV_MSG;
1854 }
1855 if (ct->flags & DHCP4C_FLAG_TMOUT_MASK)
1856 error = dispatch_timeout(ct);
1857
1858 if (ct->error != E_OK)
1859 error = ct->error;
1860 }
1861
1862 return error;
1863 }
1864
1865/*
1866 * init_context -- DHCP クライアントコンテキスト構造体を初期化する。
1867 */
1868
1869static void
1870init_context (T_DHCP4_CLI_CONTEXT *ct, ID cepid)
1871{
1872 memset(ct, 0, sizeof(*ct));
1873 ct->cepid = cepid;
1874 ct->sc = IF_ETHER_NIC_GET_SOFTC();
1875 ct->dst.portno = DHCP4_SRV_CFG_PORTNO;
1876 ct->dst.ipaddr = IPV4_ADDRANY;
1877 ct->set_addr_callback = DHCP4_CLI_SET_ADDR_CALLBACK;
1878 }
1879
1880/*
1881 * rel_cli_msg -- メッセージ構造体を解放する。
1882 */
1883
1884static void
1885rel_cli_msg (T_DHCP4_CLI_CONTEXT *ct)
1886{
1887 T_DHCP4_CLI_MSG *ptr, *cell;
1888
1889 for (ptr = ct->rcv_lst; ptr != NULL; ) {
1890 cell = ptr;
1891 ptr = ptr->next;
1892 syscall(rel_mpf(MPF_DHCP4_CLI_MSG, (void*)cell));
1893 }
1894
1895 for (ptr = ct->val_lst; ptr != NULL; ) {
1896 cell = ptr;
1897 ptr = ptr->next;
1898 syscall(rel_mpf(MPF_DHCP4_CLI_MSG, (void*)cell));
1899 }
1900
1901 for (ptr = ct->prf_lst; ptr != NULL; ) {
1902 cell = ptr;
1903 ptr = ptr->next;
1904 syscall(rel_mpf(MPF_DHCP4_CLI_MSG, (void*)cell));
1905 }
1906
1907 if (ct->snd_msg != NULL)
1908 syscall(rel_mpf(MPF_DHCP4_CLI_MSG, (void*)ct->snd_msg));
1909 ct->rcv_lst = ct->prf_lst = ct->val_lst = ct->snd_msg = NULL;
1910 }
1911
1912/*
1913 * init_cli_msg -- 各メッセージ構造体を初期化する。
1914 */
1915
1916static ER
1917init_cli_msg (T_DHCP4_CLI_CONTEXT *ct)
1918{
1919 T_DHCP4_CLI_MSG *cell;
1920 ER error;
1921 int count;
1922
1923 /* 送信メッセージ構造体を獲得する。*/
1924 if ((error = tget_mpf(MPF_DHCP4_CLI_MSG, (void*)&ct->snd_msg, TMO_DHCP4C_MPF_GET)) != E_OK) {
1925 syslog(LOG_NOTICE, "[DHCP4C] error, tget_mpf() for send: %s.", itron_strerror(error));
1926 return error;
1927 }
1928
1929 /*
1930 * 有効なリース・メッセージ構造体がある場合は、
1931 * 獲得する受信メッセージ構造体リストの構造体を 1減らす。
1932 */
1933 if (ct->act_msg == NULL)
1934 count = NUM_DHCP4_MSG_LIST;
1935 else
1936 count = NUM_DHCP4_MSG_LIST - 1;
1937
1938 /* 受信メッセージ構造体を獲得する。*/
1939 while (count --> 0) {
1940 if ((error = tget_mpf(MPF_DHCP4_CLI_MSG, (void*)&cell, TMO_DHCP4C_MPF_GET)) != E_OK) {
1941 syslog(LOG_NOTICE, "[DHCP4C] error, tget_mpf() for receive: %s.", itron_strerror(error));
1942 break;
1943 }
1944 cell->next = ct->rcv_lst;
1945 ct->rcv_lst = cell;
1946 }
1947
1948 return E_OK;
1949 }
1950
1951/*
1952 * dhcp4c_renew_info -- ネットワーク情
1953報を再取得する。
1954 */
1955
1956ER
1957dhcp4c_renew_info (void)
1958{
1959 if (context.fsm == DHCP4_FSM_BOUND) {
1960
1961 /* REL_INFO 状æ…
1962‹ã«é·ç§»ã—た後に SLEEP を解除するように設定する。*/
1963 context.flags |= DHCP4C_FLAG_RENEW;
1964 start_rel_info(&context);
1965 return E_OK;
1966 }
1967 else if (context.fsm == DHCP4_FSM_SLEEP) {
1968
1969 /* SLEEP を解除する。*/
1970 wup_tsk(DHCP4_CLI_TASK);
1971 return E_OK;
1972 }
1973 else
1974 return E_OBJ;
1975 }
1976
1977/*
1978 * dhcp4c_rel_info -- DHCP で設定されたネットワーク情
1979報を解放する。
1980 */
1981
1982ER
1983dhcp4c_rel_info (void)
1984{
1985 /* REL_INFO 状æ…
1986‹ã«é·ç§»ã™ã‚‹ã€‚*/
1987 start_rel_info(&context);
1988 return E_OK;
1989 }
1990
1991/*
1992 * dhcp4c_get_info -- DHCP で設定されたネットワーク情
1993報を返す。
1994 */
1995
1996ER
1997dhcp4c_get_info (T_IN4_ADDR *addr, uint32_t *expire, uint32_t *renew,
1998 uint32_t *rebind, SYSTIM *bind_start)
1999{
2000 if (addr == NULL || expire == NULL ||
2001 renew == NULL || rebind == NULL || bind_start == NULL)
2002 return E_PAR;
2003 else if (context.act_msg == NULL)
2004 return E_OBJ;
2005 else {
2006 *addr = context.act_msg->srv.ipaddr;
2007 *expire = context.timers[DHCP4C_TIMER_EXPIRE];
2008 *renew = context.timers[DHCP4C_TIMER_RENEW];
2009 *rebind = context.timers[DHCP4C_TIMER_REBIND];
2010 *bind_start = context.bind_start;
2011 return E_OK;
2012 }
2013 }
2014
2015/*
2016 * コールバック関数
2017 */
2018
2019ER
2020callback_nblk_dhcp4_cli (ID cepid, FN fncd, void *p_parblk)
2021{
2022 T_DHCP4_CLI_MSG *msg;
2023 ER_UINT len;
2024
2025 len = *(ER_UINT*)p_parblk;
2026 if (len < 0 && len != E_RLWAI) {
2027 /* E_RLWAI 以外で、0 以下の場合は、エラーを意味している。*/
2028 syslog(LOG_NOTICE, "[DHCPC(CBR)] error: %s, fncd: %s", itron_strerror(len), in_strtfn(fncd));
2029 }
2030 else {
2031 if (fncd == TEV_UDP_RCV_DAT) {
2032
2033 /* 受信メッセージリストが空の時は、受信しないでデータグラムを捨てる。*/
2034 if (context.rcv_lst == NULL)
2035 syslog(LOG_NOTICE, "[DHCP4C(CBR)] receive buffer all busy.");
2036 else {
2037 /* メッセージを受信するメッセージ構造体を準備する。*/
2038 syscall(wai_sem(SEM_DHCP4_CLI_LOCK));
2039 msg = context.rcv_lst;
2040 context.rcv_lst = context.rcv_lst->next;
2041 syscall(sig_sem(SEM_DHCP4_CLI_LOCK));
2042
2043 /* メッセージを受信する。*/
2044 len = udp_rcv_dat(context.cepid, &msg->srv, &msg->msg, sizeof(msg->msg), TMO_POL);
2045
2046 syscall(wai_sem(SEM_DHCP4_CLI_LOCK));
2047 msg->len = len;
2048 if (len >= 0) {
2049 /* 受信したメッセージを検証メッセージリストに移す。*/
2050 msg->next = context.val_lst;
2051 context.val_lst = msg;
2052 context.flags |= DHCP4C_FLAG_RCV_MSG;
2053 }
2054 else {
2055 /* メッセージ構造体を受信メッセージリストに戻す。*/
2056 context.error = len;
2057 msg->next = context.rcv_lst;
2058 context.rcv_lst = msg;
2059 }
2060 syscall(sig_sem(SEM_DHCP4_CLI_LOCK));
2061 }
2062 }
2063 syscall(sig_sem(SEM_DHCP4_CLI_READY));
2064 }
2065 return E_OK;
2066 }
2067
2068/*
2069 * dhcp4_cli_task -- DHCP クライアントタスク
2070 */
2071
2072void
2073dhcp4_cli_task (intptr_t exinf)
2074{
2075 T_DHCP4_CLI_CONTEXT *ct;
2076 ID tskid;
2077 ER error;
2078
2079 dly_tsk(1000);
2080 get_tid(&tskid);
2081 syslog(LOG_NOTICE, "[DHCP4C:%d,%d] started.", tskid, (ID)exinf);
2082 dly_tsk(500);
2083 ct = &context;
2084
2085 /* DHCP クライアントコンテキスト構造体を初期化する。*/
2086 init_context(ct, (ID)exinf);
2087
2088 while (true) {
2089
2090 /* 1秒毎にタイムアウトするようにタイマーを設定する。*/
2091 timeout((callout_func)dhcpc_timer, ct, NET_TIMER_HZ / DHCP4C_TIMER_HZ);
2092
2093 /* メッセージ構造体を初期化する。*/
2094 if ((error = init_cli_msg(ct)) == E_OK) {
2095
2096 /* SELECT 状æ…
2097‹ã«é·ç§»ã™ã‚‹ã€‚*/
2098 start_select(ct);
2099
2100 /* メインループ */
2101 error = dispatch_event(ct);
2102 }
2103
2104 /* å…
2105¨ã¦ã® TIMER をキャンセルする。*/
2106 cancel_all_timers(ct);
2107
2108 /* タイマーを停止する。*/
2109 untimeout((callout_func)dhcpc_timer, ct);
2110
2111 /* メッセージ構造体を解放する。*/
2112 rel_cli_msg (ct);
2113
2114 /* リースを解放後、再取得が指定されていなければ休止する。*/
2115 if (!(ct->flags & DHCP4C_FLAG_RENEW)) {
2116
2117 /* 休止する。*/
2118 if (error == E_OK)
2119 syslog(LOG_NOTICE, "[DHCP4C] lease released, go to sleep.");
2120 else {
2121 syslog(LOG_NOTICE, "[DHCP4C] server not available, go to sleep, error: %s.", itron_strerror(error));
2122 ct->fsm = DHCP4_FSM_SLEEP;
2123 }
2124 slp_tsk();
2125 }
2126 ct->flags = 0;
2127 ct->error = E_OK;
2128 }
2129 }
2130
2131#endif /* of #ifdef DHCP4_CLI_CFG */
Note: See TracBrowser for help on using the repository browser.