source: rubycfg_asp/trunk/asp_dcre/tinet/netapp/dhcp4_cli.c@ 313

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

ソースを追加

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
  • Property svn:mime-type set to text/x-csrc
File size: 56.0 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: dhcp4_cli.c 313 2017-07-23 04:50:32Z coas-nagasima $
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
511 }
512 }
513
514/*
515 * set_options -- リースされたオプションを解析して値を設定する。
516 */
517
518static void
519set_options (T_DHCP4_CLI_CONTEXT *ct, uint_t off, uint_t len, bool_t overload)
520{
521#if defined(USE_RESOLVER)
522 T_IN4_ADDR addr;
523#endif
524
525 uint8_t *opt, *mopt = NULL, *ropt = NULL;
526
527 opt = (uint8_t*)&ct->act_msg->msg + off;
528 while (opt < (uint8_t*)&ct->act_msg->msg + off + len && *opt != DHCP4_OPT_END) {
529 if (*opt == DHCP4_OPT_PAD)
530 opt ++;
531 else if ((*opt == DHCP4_OPT_OPT_OVERLOAD) && overload) {
532 if (*(opt + 2) & DHCP4_OPTOL_FILE)
533 set_options(ct, DHCP4_FILE_OFFSET, DHCP4_FILE_LEN, false);
534 if (*(opt + 2) & DHCP4_OPTOL_SNAME)
535 set_options(ct, DHCP4_SNAME_OFFSET, DHCP4_SNAME_LEN, false);
536 opt += *(opt + 1) + 2;
537 }
538 else {
539
540 switch (*opt) {
541 case DHCP4_OPT_SUBNET_MASK:
542 mopt = opt;
543 break;
544
545 case DHCP4_OPT_ROUTER:
546 ropt = opt;
547 break;
548
549#if defined(USE_RESOLVER)
550
551 case DHCP4_OPT_DNS_SERVER:
552 addr = msg2host32(opt + 2);
553 dns_in4_set_addr(&addr);
554 break;
555
556 case DHCP4_OPT_HOST_NAME:
557 break;
558
559 case DHCP4_OPT_DOMAIN_NAME:
560 dns_in4_set_dname(opt + 2, *(opt + 1));
561 break;
562
563#else /* of #if defined(USE_RESOLVER) */
564
565 case DHCP4_OPT_DNS_SERVER:
566 case DHCP4_OPT_HOST_NAME:
567 case DHCP4_OPT_DOMAIN_NAME:
568
569#endif /* of #if defined(USE_RESOLVER) */
570
571 case DHCP4_OPT_LEASE_TIME:
572 case DHCP4_OPT_RENEWAL_T1:
573 case DHCP4_OPT_REBINDING_T2:
574 break;
575
576 default:
577 break;
578 }
579
580 opt += *(opt + 1) + 2;
581 }
582 }
583 if (!(mopt == NULL || ropt == NULL))
584 set_addr(ct, mopt, ropt);
585 }
586
587/*
588 * set_lease -- リースされた情
589報を設定する。
590 */
591
592static void
593set_lease (T_DHCP4_CLI_CONTEXT *ct)
594{
595 /* リースされたオプションを解析して値を設定する。*/
596 set_options(ct, DHCP4_OPTION_OFFSET + DHCP4_MAGIC_LEN,
597 ct->act_msg->len - (DHCP4_OPTION_OFFSET + DHCP4_MAGIC_LEN), true);
598 }
599
600/*
601 * validate_duplicate -- 指定された IPv4 アドレスが使われていないか検証する。
602 *
603 * 使われていない時は true を返す。
604 */
605
606static bool_t
607validate_duplicate (T_DHCP4_CLI_MSG *msg)
608{
609 T_IN4_ADDR yiaddr;
610
611 /* 指定された IPv4 アドレスが ADDR ANY なら使われていないと判断する。*/
612 yiaddr = ntohl(msg->msg.yiaddr);
613 if (yiaddr == IPV4_ADDRANY)
614 return true;
615
616 /* ARP キャッシュにあれば使われていると判断する。*/
617 if (arp_lookup(yiaddr, false) != NULL)
618 return false;
619
620 /*
621 * ARP 要求を出力して TMO_DHCP4C_ARP_WAIT 待
622ち、
623 * ARP キャッシュになければ使われていないと判断する。
624 */
625 arp_request(&IF_ETHER_NIC_GET_SOFTC()->ifaddr, yiaddr);
626 dly_tsk(TMO_DHCP4C_ARP_WAIT);
627 return arp_lookup(yiaddr, false) == NULL;
628 }
629
630/*
631 * validate_rcv_msg -- 受信メッセージを検証する。
632 */
633
634static ER
635validate_rcv_msg (T_DHCP4_CLI_CONTEXT *ct, T_DHCP4_CLI_MSG *msg)
636{
637 uint8_t *opt;
638
639 /* packet type が DHCP4_REPLY であることを確認する。*/
640 if (!(msg->msg.op == DHCP4_REPLY))
641 return false;
642
643 /* メッセージタイプオプションがあることを確認する。*/
644 if ((opt = find_option(msg, DHCP4_OPT_MSG_TYPE, 1)) == NULL)
645 return E_PAR;
646
647 /* メッセージのタイプが一致していることを検証する。*/
648 msg->type = *(opt + 2);
649 switch (ct->fsm) {
650
651 case DHCP4_FSM_SELECT:
652 if (!(msg->type == DHCP4_MTYPE_OFFER))
653 return E_PAR;
654 break;
655
656 case DHCP4_FSM_REQUEST:
657 case DHCP4_FSM_REBOOT:
658 case DHCP4_FSM_RENEW:
659 case DHCP4_FSM_REBIND:
660 case DHCP4_FSM_REL_INFO:
661 if (!((msg->type == DHCP4_MTYPE_ACK) || (msg->type == DHCP4_MTYPE_NAK)))
662 return E_PAR;
663 break;
664
665 case DHCP4_FSM_INIT:
666 case DHCP4_FSM_BOUND:
667 case DHCP4_FSM_INIT_REBOOT:
668 return E_PAR;
669 break;
670
671 default:
672 syslog(LOG_NOTICE, "[DHCP4C] error, unknown state: %d.", ct->fsm);
673 return E_PAR;
674 break;
675 }
676
677 /* マジック番号を検証する。*/
678 if (memcmp((uint8_t*)&msg->msg.options, magicno, DHCP4_MAGIC_LEN))
679 return E_PAR;
680
681 /* トランザクション ID が異なっていればエラー */
682 if (ntohl(msg->msg.xid) != ct->xid)
683 return E_PAR;
684
685 /* ハードウェアアドレス長が 6(MAC アドレス長)でなければエラー */
686 if (msg->msg.hlen != ETHER_ADDR_LEN)
687 return E_PAR;
688
689 /* ハードウェアアドレスが異なっていればエラー */
690 if (memcmp(&msg->msg.chaddr, &ct->sc->ifaddr.lladdr, sizeof(ct->sc->ifaddr.lladdr)))
691 return E_PAR;
692
693 /*
694 * メッセージタイプが OFFER の場合は、
695 * ARP を使用して、指定された IPv4 アドレスが使われていないか検証する。
696 * 使われている時は、他の IPv4 アドレスの提供を待
697つ。
698 */
699 if (msg->type == DHCP4_MTYPE_OFFER) {
700 if (!validate_duplicate(msg))
701 return E_PAR;
702 }
703
704 return E_OK;
705 }
706
707/*
708 * eval_prefer -- 受信メッセージの推奨度を評価する。
709 */
710
711static void
712eval_prefer (T_DHCP4_CLI_MSG *msg)
713{
714 int ix;
715
716 /* 無効の場合は終了する。*/
717 if (msg == NULL)
718 return;
719
720 /* 指定された IPv4 アドレスが ADDR ANY なら推奨度を 0に設定する。*/
721 if (ntohl(msg->msg.yiaddr) == IPV4_ADDRANY)
722 msg->prefer = 0;
723 else
724 msg->prefer = DHCP4_CLI_CFG_PREFER_ADDR;
725
726#if defined(DHCP4_CLI_CFG_REQUEST_OLIST)
727
728 /* 要求オプションを検証する。*/
729 for (ix = sizeof(request_plist); ix -- > 0; ) {
730 if (find_option(msg, request_plist[ix], 0) != NULL)
731 msg->prefer ++;
732 }
733
734#endif /* of #if defined(DHCP4_CLI_CFG_REQUEST_OLIST) */
735
736#if defined(DHCP4_CLI_CFG_REQUIRED_OLIST)
737
738 /* 必
739須オプションを検証する。*/
740 for (ix = sizeof(required_plist); ix -- > 0; ) {
741 if (find_option(msg, required_plist[ix], 0) == NULL)
742 msg->prefer = 0;
743 }
744
745#endif /* of #if defined(DHCP4_CLI_CFG_REQUIRED_OLIST) */
746 }
747
748/*
749 * eval_rcv_msg -- 受信メッセージを評価する。
750 */
751
752static ER
753eval_rcv_msg (T_DHCP4_CLI_CONTEXT *ct)
754{
755 T_DHCP4_CLI_MSG *evl, *msg;
756
757 /* メッセージを受信していなければ中止する。*/
758 syscall(wai_sem(SEM_DHCP4_CLI_LOCK));
759 if (ct->val_lst == NULL) {
760 syscall(sig_sem(SEM_DHCP4_CLI_LOCK));
761 return E_OK;
762 }
763
764 /* 検証メッセージリストから評価メッセージを取り出す。*/
765 evl = ct->val_lst;
766 ct->val_lst = ct->val_lst->next;
767 evl->next = NULL;
768 syscall(sig_sem(SEM_DHCP4_CLI_LOCK));
769
770 /* 評価メッセージを検証する。*/
771 if (validate_rcv_msg(ct, evl) != E_OK) {
772
773 /* エラーが発生した評価メッセージを受信メッセージ構造体リストに戻す。*/
774 goto rcv_ret;
775 }
776
777 /* 受信したメッセージが NAK の時の処理 */
778 if (evl->type == DHCP4_MTYPE_NAK) {
779
780 /* リースされた情
781報を解放する。*/
782 rel_lease(ct);
783
784 /* 内
785部エラーを設定して終了する。*/
786 return E_PAR;
787 }
788
789 /* REL_INFO 状æ…
790‹ã®æ™‚の処理 */
791 //cons_printf(CONSOLE_PORTID, "evl_rcv_msg3[s=%d]\n", ct->fsm);
792 if (ct->fsm == DHCP4_FSM_REL_INFO) {
793 syscall(wai_sem(SEM_DHCP4_CLI_LOCK));
794 evl->next = ct->prf_lst;
795 ct->prf_lst = evl;
796 syscall(sig_sem(SEM_DHCP4_CLI_LOCK));
797 return E_OK;
798 }
799
800 /* 評価メッセージの推奨度を評価する。*/
801 eval_prefer(evl);
802
803 /* 推奨メッセージリストが空なら評価メッセージを移して終了する。*/
804 if (ct->prf_lst == NULL) {
805 ct->max_prefer = evl->prefer;
806 ct->prf_lst = evl;
807 return E_OK;
808 }
809
810 /* 評価メッセージの推奨度と推奨メッセージリストの最大推奨度を比較する。*/
811 if (evl->prefer > ct->max_prefer) {
812
813 /*
814 * 評価メッセージの推奨度が推奨メッセージリストの最大推奨度より高ければ、
815 * 推奨メッセージリストを受信メッセージ構造体リストに戻し、
816 * 評価メッセージを推奨メッセージリストに移す。
817 */
818 ct->max_prefer = evl->prefer;
819 syscall(wai_sem(SEM_DHCP4_CLI_LOCK));
820 if (ct->rcv_lst == NULL)
821 ct->rcv_lst = ct->prf_lst;
822 else {
823 for (msg = ct->rcv_lst; msg->next != NULL; msg = msg->next)
824 ;
825 msg->next = ct->prf_lst;
826 }
827 syscall(sig_sem(SEM_DHCP4_CLI_LOCK));
828 ct->prf_lst = evl;
829 return E_OK;
830 }
831
832 else if (evl->prefer == ct->max_prefer) {
833 for (msg = ct->prf_lst; msg != NULL; msg = msg->next) {
834 if (is_equal_sid(evl, msg)) {
835
836 /*
837 * 推奨メッセージリストに同じ DHCP4_OPT_SERVER_ID のメッセージがあれば、
838 * 評価メッセージを受信メッセージ構造体リストに戻す。
839 */
840 goto rcv_ret;
841 }
842 }
843
844 /*
845 * 評価メッセージを推奨メッセージリストに移す。
846 */
847 evl->next = ct->prf_lst;
848 ct->prf_lst = evl;
849 return E_OK;
850 }
851
852 /*else */
853 /*
854 * 評価メッセージの推奨度が推奨メッセージリストの最大推奨度より低ければ、
855 * 評価メッセージを受信メッセージ構造体リストに戻す。
856 */
857
858rcv_ret:
859 syscall(wai_sem(SEM_DHCP4_CLI_LOCK));
860 evl->next = ct->rcv_lst;
861 ct->rcv_lst = evl;
862 syscall(sig_sem(SEM_DHCP4_CLI_LOCK));
863 return E_OK;
864 }
865
866/*
867 * select_msg -- 推奨メッセージを選択する。
868 */
869
870static T_DHCP4_CLI_MSG*
871select_msg (T_DHCP4_CLI_CONTEXT *ct)
872{
873 T_DHCP4_CLI_MSG *msg, *select;
874
875 syscall(wai_sem(SEM_DHCP4_CLI_LOCK));
876 if (ct->prf_lst == NULL) {
877 /* メッセージを受信していなければ中止する。*/
878 syscall(sig_sem(SEM_DHCP4_CLI_LOCK));
879 return NULL;
880 }
881
882 /* 推奨メッセージリストのå…
883ˆé ­ã®ãƒ¡ãƒƒã‚»ãƒ¼ã‚¸ã‚’選択する。*/
884 select = ct->prf_lst;
885 ct->prf_lst = ct->prf_lst->next;
886 select->next = NULL;
887
888 /* 選択されなかった検証メッセージを受信メッセージ構造体リストに戻す。*/
889 if (ct->rcv_lst == NULL)
890 ct->rcv_lst = ct->prf_lst;
891 else {
892 for (msg = ct->rcv_lst; msg->next != NULL; msg = msg->next)
893 ;
894 msg->next = ct->prf_lst;
895 }
896 syscall(sig_sem(SEM_DHCP4_CLI_LOCK));
897 return select;
898 }
899
900/*
901 * select_ack -- ACK メッセージを検証する。
902 *
903 * 受けå…
904¥ã‚Œã‚‹ã“とが可能の時は true を返す。
905 */
906
907static bool_t
908select_ack (T_DHCP4_CLI_CONTEXT *ct)
909{
910 T_DHCP4_CLI_MSG *msg;
911
912 if ((msg = select_msg(ct)) == NULL)
913 return false;
914
915 /* 有効なリース・メッセージが残っていれば、受信メッセージ構造体リストに戻す。*/
916 if (ct->act_msg != NULL) {
917 syscall(wai_sem(SEM_DHCP4_CLI_LOCK));
918 ct->act_msg->next = ct->rcv_lst;
919 ct->rcv_lst = ct->act_msg;
920 syscall(sig_sem(SEM_DHCP4_CLI_LOCK));
921 }
922
923 /* 有効なリース・メッセージに設定する。*/
924 ct->act_msg = msg;
925 return true;
926 }
927
928/*
929 * select_offer -- OFFER メッセージを検証する。
930 *
931 * 受けå…
932¥ã‚Œã‚‹ã“とが可能の時は true を返す。
933 */
934
935static bool_t
936select_offer (T_DHCP4_CLI_CONTEXT *ct)
937{
938 return (ct->off_msg = select_msg(ct)) != NULL;
939 }
940
941/*
942 * cancel_all_timers -- å…
943¨ã¦ã® TIMER をキャンセルする。
944 */
945
946static void
947cancel_all_timers (T_DHCP4_CLI_CONTEXT *ct)
948{
949 int ix;
950
951 syscall(wai_sem(SEM_DHCP4_CLI_TIMER));
952 for (ix = NUM_DHCP4C_TIMERS; ix -- > 0; )
953 ct->timers[ix] = 0;
954 syscall(sig_sem(SEM_DHCP4_CLI_TIMER));
955 }
956
957
958/*
959 * start_select -- DISCOVER メッセージを送信して SELECT 状æ…
960‹ã«é·ç§»ã™ã‚‹ã€‚
961 */
962
963static void
964start_select (T_DHCP4_CLI_CONTEXT *ct)
965{
966 /* 送信を開始した時間を記録する。*/
967 get_tim(&ct->snd_start);
968
969 /* OFFER メッセージ受信タイムアウトを設定する。*/
970 syscall(wai_sem(SEM_DHCP4_CLI_TIMER));
971 ct->timers[DHCP4C_TIMER_RCV_OFFER] = SYSTIM2TIMER(TMO_DHCP4C_OFFER);
972 syscall(sig_sem(SEM_DHCP4_CLI_TIMER));
973
974 /* 送信å…
975ˆã‚¢ãƒ‰ãƒ¬ã‚¹ã«ãƒ­ãƒ¼ã‚«ãƒ«ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯ã¸ã®ãƒ–ロードキャストを設定する。*/
976 ct->dst.ipaddr = IPV4_ADDRBROADCAST;
977
978 /* 送信間隔をリセットする。*/
979 ct->interval = 0;
980
981 /* SELECT 状æ…
982‹ã«é·ç§»ã™ã‚‹ã€‚*/
983 ct->fsm = DHCP4_FSM_SELECT;
984
985 /* DISCOVER メッセージを送信する。*/
986 ct->flags |= DHCP4C_FLAG_TMOUT_SND_DISC;
987 syscall(sig_sem(SEM_DHCP4_CLI_READY));
988 }
989
990/*
991 * start_bound -- BOUND 状æ…
992‹ã«é·ç§»ã™ã‚‹ã€‚
993 */
994
995static void
996start_bound (T_DHCP4_CLI_CONTEXT *ct)
997{
998 /* リースされた情
999報を設定する。*/
1000 set_lease(ct);
1001
1002 /* リースの有効時間を設定する。*/
1003 ct->expire = timer_value(ct->act_msg, DHCP4_OPT_LEASE_TIME, TMO_DHCP4C_DEF_LEASE);
1004
1005 /* リース時間が TMO_DHCP4C_MIN_LEASE 以下の時は、TMO_DHCP4C_MIN_LEASE に設定する。*/
1006 if (ct->expire < TMO_DHCP4C_MIN_LEASE)
1007 ct->expire = TMO_DHCP4C_MIN_LEASE;
1008
1009 /* RENEW 状æ…
1010‹ã¾ã§ã®æ™‚間を設定する。*/
1011 ct->renew = timer_value(ct->act_msg, DHCP4_OPT_RENEWAL_T1, ct->expire / 2);
1012
1013 /* REBIND 状æ…
1014‹ã¾ã§ã®æ™‚間を設定する。*/
1015 ct->rebind = timer_value(ct->act_msg, DHCP4_OPT_REBINDING_T2, ct->renew + ct->renew / 2 + ct->renew / 4);
1016
1017 /* EXPIRE、RENEW、REBIND タイマーを設定する。*/
1018 syscall(wai_sem(SEM_DHCP4_CLI_TIMER));
1019 ct->timers[DHCP4C_TIMER_EXPIRE] = SYSTIM2TIMER(ct->expire); /* EXPIRE までの時間 */
1020 ct->timers[DHCP4C_TIMER_REBIND] = SYSTIM2TIMER(ct->rebind); /* REBIND(T2)までの時間 */
1021 ct->timers[DHCP4C_TIMER_RENEW] = SYSTIM2TIMER(ct->renew); /* RENEW (T1)までの時間 */
1022 syscall(sig_sem(SEM_DHCP4_CLI_TIMER));
1023
1024 /* BOUND 状æ…
1025‹ã«é·ç§»ã™ã‚‹ã€‚*/
1026 ct->fsm = DHCP4_FSM_BOUND;
1027
1028 /* BIND を開始した時間を記録する。*/
1029 get_tim(&ct->bind_start);
1030 }
1031
1032/*
1033 * start_send_request -- REQUEST メッセージを送信して、指定された状æ…
1034‹ã«é·ç§»ã™ã‚‹ã€‚
1035 */
1036
1037static void
1038start_send_request (T_DHCP4_CLI_CONTEXT *ct, uint_t fsm)
1039{
1040 T_IFNET *ifp = IF_GET_IFNET();
1041
1042 /* 送信を開始した時間を記録する。*/
1043 get_tim(&ct->snd_start);
1044
1045 /* 遷移する状æ…
1046‹ãŒ RENEW 以外では ACK/NAK メッセージ受信タイムアウトを設定する。*/
1047 if (fsm != DHCP4_FSM_RENEW) {
1048 syscall(wai_sem(SEM_DHCP4_CLI_TIMER));
1049 ct->timers[DHCP4C_TIMER_RCV_ACK] = SYSTIM2TIMER(TMO_DHCP4C_ACK);
1050 syscall(sig_sem(SEM_DHCP4_CLI_TIMER));
1051 }
1052
1053 /*
1054 * 遷移する状æ…
1055‹ãŒ RENEW で、
1056 * SERVER ID オプションがあればローカルネットワークへのブロードキャストを送信する。
1057 */
1058 if ((fsm == DHCP4_FSM_RENEW) &&
1059 (find_option(ct->act_msg, DHCP4_OPT_SERVER_ID, sizeof(T_IN4_ADDR)) != NULL))
1060 ct->dst.ipaddr = (ifp->in4_ifaddr.addr & ifp->in4_ifaddr.mask) | ~ifp->in4_ifaddr.mask;
1061 else
1062 ct->dst.ipaddr = IPV4_ADDRBROADCAST;
1063
1064 /* 送信間隔をリセットする。*/
1065 ct->interval = 0;
1066
1067 /* 指定された状æ…
1068‹ã«é·ç§»ã™ã‚‹ã€‚*/
1069 ct->fsm = fsm;
1070
1071 /* REQUEST メッセージを送信する。*/
1072 ct->flags |= DHCP4C_FLAG_TMOUT_SND_REQ;
1073 syscall(sig_sem(SEM_DHCP4_CLI_READY));
1074 }
1075
1076/*
1077 * start_rel_info -- アドレス情
1078報を解放する。
1079 *
1080 * 注意: DHCPv4 の RFC2131 には無い
1081 */
1082
1083static void
1084start_rel_info (T_DHCP4_CLI_CONTEXT *ct)
1085{
1086 /* å…
1087¨ã¦ã® TIMER をキャンセルする。*/
1088 cancel_all_timers(ct);
1089
1090 /* 有効なリース情
1091報が無ければ SLEEP に遷移する。*/
1092 if (ct->act_msg == NULL) {
1093 ct->fsm = DHCP4_FSM_SLEEP;
1094 return;
1095 }
1096
1097 /* 送信å…
1098ˆã‚¢ãƒ‰ãƒ¬ã‚¹ã«ãƒ­ãƒ¼ã‚«ãƒ«ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯ã¸ã®ãƒ–ロードキャストを設定する。*/
1099 ct->dst.ipaddr = IPV4_ADDRBROADCAST;
1100
1101 /* RELEASE メッセージを送信する。*/
1102 ct->flags |= DHCP4C_FLAG_TMOUT_SND_REL;
1103 syscall(sig_sem(SEM_DHCP4_CLI_READY));
1104 }
1105
1106/*
1107 * setup_dhcp_com_msg -- DHCP メッセージのå…
1108±é€šéƒ¨åˆ†ã‚’作成する。
1109 */
1110
1111static uint8_t *
1112setup_dhcp_com_msg (T_DHCP4_CLI_CONTEXT *ct, uint_t op, uint_t type)
1113{
1114 uint8_t *option;
1115
1116 memset((void*)&ct->snd_msg->msg, sizeof(ct->snd_msg->msg), 0);
1117 ct->snd_msg->len = sizeof(ct->snd_msg->msg);
1118
1119 /* ヘッダ部を設定する。*/
1120 ct->snd_msg->msg.op = op;
1121 ct->snd_msg->msg.htype = DHCP4_HWA_TYPE_ETHER;
1122 ct->snd_msg->msg.hlen = ETHER_ADDR_LEN;
1123 HOST2MSG32(ct->snd_msg->msg.xid, ct->xid);
1124
1125 /* MAC アドレスを設定する。*/
1126 memcpy(&ct->snd_msg->msg.chaddr, &ct->sc->ifaddr.lladdr, ETHER_ADDR_LEN);
1127
1128 /*
1129 * オプション部を設定する。
1130 */
1131
1132 /* RFC1048 に定義されているマジック番号を設定する。*/
1133 memcpy(&ct->snd_msg->msg.options, magicno, DHCP4_MAGIC_LEN);
1134 option = ct->snd_msg->msg.options + DHCP4_MAGIC_LEN;
1135
1136 /* DHCP メッセージタイプを設定する。*/
1137 *(option ++) = DHCP4_OPT_MSG_TYPE;
1138 *(option ++) = 1;
1139 *(option ++) = type;
1140
1141 return option;
1142 }
1143
1144/*
1145 * setup_release_msg -- RELEASE メッセージを作成する。
1146 */
1147
1148static ER
1149setup_release_msg (T_DHCP4_CLI_CONTEXT *ct, T_DHCP4_CLI_MSG *ref)
1150{
1151 uint8_t *opt, *ref_opt;
1152
1153 /* 有効なリース・メッセージがなければエラー */
1154 if (ref == NULL)
1155 return E_PAR;
1156
1157 ct->xid = create_xid();
1158 if ((opt = setup_dhcp_com_msg(ct, DHCP4_REQUEST, DHCP4_MTYPE_RELEASE)) == NULL)
1159 return E_PAR;
1160
1161 /*
1162 * サーバ ID(server-ip)を設定する。
1163 * RFC2131 4.4.1 Initialization and allocation of network address 参ç…
1164§
1165 */
1166 if ((ref_opt = find_option(ref, DHCP4_OPT_SERVER_ID, sizeof(T_IN4_ADDR))) == NULL)
1167 return E_PAR;
1168 *(opt ++) = *(ref_opt ++);
1169 *(opt ++) = *(ref_opt ++);
1170 memcpy(opt, ref_opt, *(ref_opt - 1));
1171 opt += *(ref_opt - 1);
1172
1173 /*
1174 * クライアント ID(MAC アドレス)を設定する。
1175 * RFC2131 4.4.1 Initialization and allocation of network address 参ç…
1176§
1177 */
1178 *(opt ++) = DHCP4_OPT_CLIENT_ID;
1179 *(opt ++) = ETHER_ADDR_LEN + 1;
1180 *(opt ++) = DHCP4_HWA_TYPE_ETHER;
1181 memcpy(opt, &ct->sc->ifaddr.lladdr, ETHER_ADDR_LEN);
1182 opt += ETHER_ADDR_LEN;
1183
1184 /* オプションの終了を設定する。*/
1185 *(opt ++) = DHCP4_OPT_END;
1186
1187 /*
1188 * クライアント IP アドレス(ciaddr)を設定する。
1189 * RFC2131 4.4.1 Initialization and allocation of network address 参ç…
1190§
1191 */
1192 HOST2MSG32(ct->snd_msg->msg.ciaddr, IF_GET_IFNET()->in4_ifaddr.addr);
1193
1194 /* メッセージ長を設定する。*/
1195 ct->snd_msg->len = sizeof(ct->snd_msg->msg) - DHCP4_DFLT_OPT_LEN
1196 + (opt - (uint8_t*)&ct->snd_msg->msg.options);
1197 return E_OK;
1198 }
1199
1200
1201/*
1202 * setup_request_msg -- REQUEST メッセージを作成する。
1203 */
1204
1205static ER
1206setup_request_msg (T_DHCP4_CLI_CONTEXT *ct, T_DHCP4_CLI_MSG *ref)
1207{
1208 uint8_t *opt, *ref_opt;
1209
1210#if defined(DHCP4_CLI_CFG_REQUIRED_OLIST) || defined(DHCP4_CLI_CFG_REQUEST_OLIST)
1211 uint_t len = 0;
1212#endif
1213
1214 /* 参ç…
1215§ã™ã‚‹ãƒ¡ãƒƒã‚»ãƒ¼ã‚¸ãŒãªã‘ればエラー */
1216 if (ref == NULL)
1217 return E_PAR;
1218
1219 ct->xid = create_xid();
1220 if ((opt = setup_dhcp_com_msg(ct, DHCP4_REQUEST, DHCP4_MTYPE_REQUEST)) == NULL)
1221 return E_PAR;
1222
1223#if defined(DHCP4_CLI_CFG_REQUIRED_OLIST) || defined(DHCP4_CLI_CFG_REQUEST_OLIST)
1224
1225 /* 追加のオプションを設定する。*/
1226
1227 *opt = DHCP4_OPT_REQ_PARAM;
1228 opt += 2;
1229
1230#if defined(DHCP4_CLI_CFG_REQUIRED_OLIST)
1231
1232 /* 要求オプションリストを設定する。*/
1233 if (sizeof(required_plist) > 0) {
1234 memcpy(opt, required_plist, sizeof(required_plist));
1235 opt += sizeof(required_plist);
1236 len += sizeof(required_plist);
1237 }
1238
1239#endif /* of #if defined(DHCP4_CLI_CFG_REQUIRED_OLIST) */
1240
1241#if defined(DHCP4_CLI_CFG_REQUEST_OLIST)
1242
1243 /* 要求オプションリストを設定する。*/
1244 if (sizeof(request_plist) > 0) {
1245 memcpy(opt, request_plist, sizeof(request_plist));
1246 opt += sizeof(request_plist);
1247 len += sizeof(request_plist);
1248 }
1249
1250#endif /* of #if defined(DHCP4_CLI_CFG_REQUEST_OLIST) */
1251
1252 *(opt - len - 1) = len;
1253
1254#endif /* of #if defined(DHCP4_CLI_CFG_REQUIRED_OLIST) || defined(DHCP4_CLI_CFG_REQUEST_OLIST) */
1255
1256 /*
1257 * サーバ ID(server-ip)を設定する。
1258 * RFC2131 4.4.1 Initialization and allocation of network address 参ç…
1259§
1260 */
1261 if (ct->fsm == DHCP4_FSM_REQUEST) {
1262 if ((ref_opt = find_option(ref, DHCP4_OPT_SERVER_ID, sizeof(T_IN4_ADDR))) == NULL)
1263 return E_PAR;
1264 *(opt ++) = *(ref_opt ++);
1265 *(opt ++) = *(ref_opt ++);
1266 memcpy(opt, ref_opt, *(ref_opt - 1));
1267 opt += *(ref_opt - 1);
1268 }
1269
1270 /*
1271 * 要求 IP アドレス(requested-ip)を設定する。
1272 * RFC2131 4.4.1 Initialization and allocation of network address 参ç…
1273§
1274 * RFC2131 では、DHCP4_FSM_RENEW の時 MUST NOT になっているが、
1275 * MUST のようである。
1276 */
1277 *(opt ++) = DHCP4_OPT_REQ_IPV4;
1278 *(opt ++) = sizeof(ref->msg.yiaddr);
1279 if (ct->fsm == DHCP4_FSM_REQUEST || ct->fsm == DHCP4_FSM_INIT_REBOOT ||
1280 ct->fsm == DHCP4_FSM_RENEW || ct->fsm == DHCP4_FSM_REBIND)
1281 /* 参ç…
1282§ãƒ¡ãƒƒã‚»ãƒ¼ã‚¸ã¨åŒã˜ IP アドレス(requested-ip)を要求する。*/
1283 memcpy(opt, (uint8_t*)&ref->msg.yiaddr, sizeof(ref->msg.yiaddr));
1284 else
1285 host2msg32(opt, IPV4_ADDRANY);
1286 opt += sizeof(ref->msg.yiaddr);
1287
1288 /*
1289 * クライアント ID(MAC アドレス)を設定する。
1290 * RFC2131 4.4.1 Initialization and allocation of network address 参ç…
1291§
1292 */
1293 *(opt ++) = DHCP4_OPT_CLIENT_ID;
1294 *(opt ++) = ETHER_ADDR_LEN + 1;
1295 *(opt ++) = DHCP4_HWA_TYPE_ETHER;
1296 memcpy(opt, &ct->sc->ifaddr.lladdr, ETHER_ADDR_LEN);
1297 opt += ETHER_ADDR_LEN;
1298
1299 /* オプションの終了を設定する。*/
1300 *(opt ++) = DHCP4_OPT_END;
1301
1302 /*
1303 * クライアント IP アドレス(ciaddr)を設定する。
1304 * RFC2131 4.4.1 Initialization and allocation of network address 参ç…
1305§
1306 */
1307 if (ct->fsm == DHCP4_FSM_RENEW || ct->fsm == DHCP4_FSM_REBIND)
1308 HOST2MSG32(ct->snd_msg->msg.ciaddr, IF_GET_IFNET()->in4_ifaddr.addr);
1309 else
1310 HOST2MSG32(ct->snd_msg->msg.ciaddr, IPV4_ADDRANY);
1311
1312 /* メッセージ長を設定する。*/
1313 ct->snd_msg->len = sizeof(ct->snd_msg->msg) - DHCP4_DFLT_OPT_LEN
1314 + (opt - (uint8_t*)&ct->snd_msg->msg.options);
1315 return E_OK;
1316 }
1317
1318/*
1319 * setup_discover_msg -- DISCOVER メッセージを作成する。
1320 */
1321
1322static ER
1323setup_discover_msg (T_DHCP4_CLI_CONTEXT *ct)
1324{
1325 uint8_t *opt;
1326
1327#if defined(DHCP4_CLI_CFG_REQUIRED_OLIST) || defined(DHCP4_CLI_CFG_REQUEST_OLIST)
1328 uint_t len = 0;
1329#endif
1330
1331 ct->xid = create_xid();
1332 if ((opt = setup_dhcp_com_msg(ct, DHCP4_REQUEST, DHCP4_MTYPE_DISCOVER)) == NULL)
1333 return E_PAR;
1334
1335#if defined(DHCP4_CLI_CFG_REQUIRED_OLIST) || defined(DHCP4_CLI_CFG_REQUEST_OLIST)
1336
1337 /* 追加のオプションを設定する。*/
1338
1339 *opt = DHCP4_OPT_REQ_PARAM;
1340 opt += 2;
1341
1342#if defined(DHCP4_CLI_CFG_REQUIRED_OLIST)
1343
1344 /* 要求オプションリストを設定する。*/
1345 if (sizeof(required_plist) > 0) {
1346 memcpy(opt, required_plist, sizeof(required_plist));
1347 opt += sizeof(required_plist);
1348 len += sizeof(required_plist);
1349 }
1350
1351#endif /* of #if defined(DHCP4_CLI_CFG_REQUIRED_OLIST) */
1352
1353#if defined(DHCP4_CLI_CFG_REQUEST_OLIST)
1354
1355 /* 要求オプションリストを設定する。*/
1356 if (sizeof(request_plist) > 0) {
1357 memcpy(opt, request_plist, sizeof(request_plist));
1358 opt += sizeof(request_plist);
1359 len += sizeof(request_plist);
1360 }
1361
1362#endif /* of #if defined(DHCP4_CLI_CFG_REQUEST_OLIST) */
1363
1364 *(opt - len - 1) = len;
1365
1366#endif /* of #if defined(DHCP4_CLI_CFG_REQUIRED_OLIST) || defined(DHCP4_CLI_CFG_REQUEST_OLIST) */
1367
1368 /* 既にアドレス情
1369報がリースされていれば、同じ IP アドレスを要求する。*/
1370 if (ct->act_msg != NULL) {
1371 *(opt ++) = DHCP4_OPT_REQ_IPV4;
1372 *(opt ++) = sizeof(ct->act_msg->msg.yiaddr);
1373 memcpy(opt, (uint8_t*)&ct->act_msg->msg.yiaddr, sizeof(ct->act_msg->msg.yiaddr));
1374 opt += sizeof(ct->act_msg->msg.yiaddr);
1375 }
1376
1377 /* クライアント ID(MAC アドレス)を設定する。*/
1378 *(opt ++) = DHCP4_OPT_CLIENT_ID;
1379 *(opt ++) = ETHER_ADDR_LEN + 1;
1380 *(opt ++) = DHCP4_HWA_TYPE_ETHER;
1381 memcpy(opt, &ct->sc->ifaddr.lladdr, ETHER_ADDR_LEN);
1382 opt += ETHER_ADDR_LEN;
1383
1384 /* オプションの終了を設定する。*/
1385 *(opt ++) = DHCP4_OPT_END;
1386
1387 /* 送信å…
1388ˆã‚¢ãƒ‰ãƒ¬ã‚¹ã‚’設定する。*/
1389 ct->dst.ipaddr = IPV4_ADDRBROADCAST;
1390
1391 /* メッセージ長を設定する。*/
1392 ct->snd_msg->len = sizeof(ct->snd_msg->msg) - DHCP4_DFLT_OPT_LEN
1393 + (opt - (uint8_t*)&ct->snd_msg->msg.options);
1394 return E_OK;
1395 }
1396
1397/*
1398 * ack_msg_timeout -- ACK/NAK メッセージ受信タイムアウト処理
1399 */
1400
1401static void
1402ack_msg_timeout (T_DHCP4_CLI_CONTEXT *ct)
1403{
1404 /* ACK メッセージを受信していれば。BOUND 状æ…
1405‹ã«é·ç§»ã™ã‚‹ã€‚*/
1406 ct->flags &= ~DHCP4C_FLAG_TMOUT_MASK;
1407 if (select_ack(ct)) {
1408
1409 /* REQUEST メッセージ送信タイマーを停止する。*/
1410 syscall(wai_sem(SEM_DHCP4_CLI_TIMER));
1411 ct->timers[DHCP4C_TIMER_SND_REQ] = 0;
1412 syscall(sig_sem(SEM_DHCP4_CLI_TIMER));
1413
1414 /*
1415 * 状æ…
1416‹ãŒ REQUEST の時は、
1417 * OFFER メッセージを受信メッセージ構造体リストに戻す。
1418 */
1419 if (ct->fsm == DHCP4_FSM_REQUEST && ct->off_msg != NULL) {
1420 syscall(wai_sem(SEM_DHCP4_CLI_LOCK));
1421 ct->off_msg->next = ct->rcv_lst;
1422 ct->rcv_lst = ct->off_msg;
1423 syscall(sig_sem(SEM_DHCP4_CLI_LOCK));
1424 ct->off_msg = NULL;
1425 }
1426
1427 /* BOUND 状æ…
1428‹ã«é·ç§»ã™ã‚‹ã€‚*/
1429 start_bound(ct);
1430 return;
1431 }
1432 else {
1433
1434 /* リース情
1435報を解放する。*/
1436 rel_lease(ct);
1437
1438 ct->error = E_TMOUT;
1439 }
1440 }
1441
1442/*
1443 * send_request_msg -- REQUEST メッセージを送信する。
1444 */
1445
1446static void
1447send_request_msg (T_DHCP4_CLI_CONTEXT *ct)
1448{
1449 T_DHCP4_CLI_MSG *ref;
1450 ER error;
1451 SYSTIM time;
1452 RELTIM interval;
1453 uint16_t secs;
1454
1455 /* タイムアウトフラグをクリアーする。*/
1456 ct->flags &= ~DHCP4C_FLAG_TMOUT_MASK;
1457
1458 /* ACK メッセージを受信していれば。BOUND 状æ…
1459‹ã«é·ç§»ã™ã‚‹ã€‚*/
1460 ct->flags &= ~DHCP4C_FLAG_TMOUT_MASK;
1461 if (select_ack(ct)) {
1462
1463 /* ACK/NAK メッセージ受信タイマーを停止する。*/
1464 syscall(wai_sem(SEM_DHCP4_CLI_TIMER));
1465 ct->timers[DHCP4C_TIMER_RCV_ACK] = 0;
1466 syscall(sig_sem(SEM_DHCP4_CLI_TIMER));
1467
1468 /*
1469 * 状æ…
1470‹ãŒ REQUEST の時は、
1471 * OFFER メッセージを受信メッセージ構造体リストに戻す。
1472 */
1473 if (ct->fsm == DHCP4_FSM_REQUEST && ct->off_msg != NULL) {
1474 syscall(wai_sem(SEM_DHCP4_CLI_LOCK));
1475 ct->off_msg->next = ct->rcv_lst;
1476 ct->rcv_lst = ct->off_msg;
1477 syscall(sig_sem(SEM_DHCP4_CLI_LOCK));
1478 ct->off_msg = NULL;
1479 }
1480
1481 /* BOUND 状æ…
1482‹ã«é·ç§»ã™ã‚‹ã€‚*/
1483 start_bound(ct);
1484 return;
1485 }
1486
1487 /* REQUEST メッセージを作成する。*/
1488 if (ct->fsm == DHCP4_FSM_REQUEST)
1489 ref = ct->off_msg;
1490 else
1491 ref = ct->act_msg;
1492 if ((error = setup_request_msg(ct, ref)) != E_OK) {
1493 syslog(LOG_NOTICE, "[DHCP4C] error, setup request message: %s", itron_strerror(error));
1494 ct->error = error;
1495 return;
1496 }
1497
1498 /* 送信を開始してからの時間を得る。*/
1499 get_tim(&time);
1500 interval = time - ct->snd_start;
1501
1502 /*
1503 * 送信を開始してからの時間(秒)をメッセージに設定する。
1504 * 最大値は 65535。
1505 */
1506 if (ct->fsm == DHCP4_FSM_REQUEST)
1507 secs = ct->secs;
1508 else {
1509 if (SYSTIM2SEC(interval) < 65536)
1510 secs = SYSTIM2SEC(interval);
1511 else
1512 secs = 65535;
1513 }
1514 HOST2MSG16(ct->snd_msg->msg.secs, secs);
1515
1516 /* ノンブロッキングコールでメッセージを送信する。*/
1517 error = udp_snd_dat(ct->cepid, &ct->dst, &ct->snd_msg->msg, ct->snd_msg->len, TMO_NBLK);
1518 if (error != E_WBLK) {
1519 syslog(LOG_NOTICE, "[DHCP4C] error, send request message: %s", itron_strerror(error));
1520 ct->error = error;
1521 return;
1522 }
1523
1524 /* 送信間隔を設定する。*/
1525 if (ct->interval == 0)
1526 /* 未設定 */
1527 ct->interval = TMO_DHCP4C_INIT_INTVL;
1528 else
1529 /* バックオフアルゴリズムで 2倍にした(乱数使用)送信間隔を加算する。*/
1530 ct->interval += (netapp_rand() >> 2) % (ct->interval << 1);
1531
1532 /* 送信周期の制限値を超
1533えないようにする。*/
1534 if (ct->interval > TMO_DHCP4C_MAX_BACKOFF)
1535 ct->interval = (TMO_DHCP4C_MAX_BACKOFF >> 1) + ((netapp_rand() >> 2) % TMO_DHCP4C_MAX_BACKOFF);
1536
1537 /* リース時間のタイムアウト【å…
1538ˆé€ã‚Šã€‘ */
1539 if (ct->fsm != DHCP4_FSM_REQUEST &&
1540 TIMEC_GT(ct->interval + time, ct->expire + ct->bind_start))
1541 ct->interval = ct->expire + ct->bind_start - time + SYSTIM_HZ;
1542
1543 /* 再送信タイムアウトを設定する。*/
1544 syscall(wai_sem(SEM_DHCP4_CLI_TIMER));
1545 ct->timers[DHCP4C_TIMER_SND_REQ] = SYSTIM2TIMER(ct->interval);
1546 syscall(sig_sem(SEM_DHCP4_CLI_TIMER));
1547 }
1548
1549/*
1550 * send_release_msg -- RELEASE メッセージを送信する。
1551 */
1552
1553static void
1554send_release_msg (T_DHCP4_CLI_CONTEXT *ct)
1555{
1556 ER error;
1557
1558 /* タイムアウトフラグをクリアーする。*/
1559 ct->flags &= ~DHCP4C_FLAG_TMOUT_MASK;
1560
1561 /* RELEASE メッセージを作成する。*/
1562 if ((error = setup_release_msg(ct, ct->act_msg)) != E_OK) {
1563 syslog(LOG_NOTICE, "[DHCP4C] error, setup release message: %s", itron_strerror(error));
1564 ct->error = error;
1565 return;
1566 }
1567
1568 /* リース情
1569報を解放する。*/
1570 rel_lease(ct);
1571
1572 /* ノンブロッキングコールでメッセージを送信する。*/
1573 error = udp_snd_dat(ct->cepid, &ct->dst, &ct->snd_msg->msg, ct->snd_msg->len, TMO_NBLK);
1574 if (error != E_WBLK) {
1575 syslog(LOG_NOTICE, "[DHCP4C] error, send release message: %s", itron_strerror(error));
1576 ct->error = error;
1577 return;
1578 }
1579
1580 /* メッセージ送信待
1581ちを行う。*/
1582 syscall(wai_sem(SEM_DHCP4_CLI_READY));
1583
1584 /* SLEEP 状æ…
1585‹ã«é·ç§»ã™ã‚‹ã€‚*/
1586 ct->fsm = DHCP4_FSM_SLEEP;
1587 }
1588
1589/*
1590 * offer_msg_timeout -- OFFER メッセージ受信タイムアウト処理
1591 */
1592
1593static void
1594offer_msg_timeout (T_DHCP4_CLI_CONTEXT *ct)
1595{
1596 /* OFFER メッセージを受信していれば。REQUEST 状æ…
1597‹ã«é·ç§»ã™ã‚‹ã€‚*/
1598 ct->flags &= ~DHCP4C_FLAG_TMOUT_MASK;
1599 if (select_offer(ct)) {
1600
1601 /* DISCOVER メッセージ送信タイマーを停止する。*/
1602 syscall(wai_sem(SEM_DHCP4_CLI_TIMER));
1603 ct->timers[DHCP4C_TIMER_SND_DISC] = 0;
1604 syscall(sig_sem(SEM_DHCP4_CLI_TIMER));
1605
1606 /* REQUEST メッセージを送信して REQUEST 状æ…
1607‹ã«é·ç§»ã™ã‚‹ã€‚*/
1608 start_send_request(ct, DHCP4_FSM_REQUEST);
1609 }
1610 else
1611 ct->error = E_TMOUT;
1612 }
1613
1614/*
1615 * send_discover_msg -- DISCOVERメッセージを送信する。
1616 */
1617
1618static void
1619send_discover_msg (T_DHCP4_CLI_CONTEXT *ct)
1620{
1621 ER error;
1622 SYSTIM time;
1623 RELTIM interval;
1624
1625 /* タイムアウトフラグをクリアーする。*/
1626 ct->flags &= ~DHCP4C_FLAG_TMOUT_MASK;
1627
1628 /* OFFER メッセージを受信していれば。REQUEST 状æ…
1629‹ã«é·ç§»ã™ã‚‹ã€‚*/
1630 ct->flags &= ~DHCP4C_FLAG_TMOUT_MASK;
1631 if (select_offer(ct)) {
1632
1633 /* OFFER メッセージ受信タイマーを停止する。*/
1634 syscall(wai_sem(SEM_DHCP4_CLI_TIMER));
1635 ct->timers[DHCP4C_TIMER_RCV_OFFER] = 0;
1636 syscall(sig_sem(SEM_DHCP4_CLI_TIMER));
1637
1638 /* REQUEST メッセージを送信して REQUEST 状æ…
1639‹ã«é·ç§»ã™ã‚‹ã€‚*/
1640 start_send_request(ct, DHCP4_FSM_REQUEST);
1641 return;
1642 }
1643
1644 /* DISCOVER メッセージを作成する。*/
1645 if ((error = setup_discover_msg(ct)) != E_OK) {
1646 syslog(LOG_NOTICE, "[DHCP4C] error, setup discover message: %s", itron_strerror(error));
1647 ct->error = error;
1648 return;
1649 }
1650
1651 /* 送信を開始してからの時間を得る。*/
1652 get_tim(&time);
1653 interval = time - ct->snd_start;
1654
1655 /*
1656 * 送信を開始してからの時間(秒)をメッセージに設定する。
1657 * 最大値は 65535。
1658 */
1659 if (SYSTIM2SEC(interval) < 65536)
1660 ct->secs = SYSTIM2SEC(interval);
1661 else
1662 ct->secs = 65535;
1663 HOST2MSG16(ct->snd_msg->msg.secs, ct->secs);
1664
1665 /* ノンブロッキングコールでメッセージを送信する。*/
1666 error = udp_snd_dat(ct->cepid, &ct->dst, &ct->snd_msg->msg, ct->snd_msg->len, TMO_NBLK);
1667 if (error != E_WBLK) {
1668 syslog(LOG_NOTICE, "[DHCP4C] error, send discover message: %s", itron_strerror(error));
1669 ct->error = error;
1670 return;
1671 }
1672
1673 /* 送信間隔を設定する。*/
1674 if (ct->interval == 0)
1675 /* 未設定 */
1676 ct->interval = TMO_DHCP4C_INIT_INTVL;
1677 else
1678 /* バックオフアルゴリズムで 2倍にした(乱数使用)送信間隔を加算する。*/
1679 ct->interval += (netapp_rand() >> 2) % (ct->interval << 1);
1680
1681 /* 送信周期の制限値を超
1682えないようにする。*/
1683 if (ct->interval > TMO_DHCP4C_MAX_BACKOFF)
1684 ct->interval = (TMO_DHCP4C_MAX_BACKOFF >> 1) + ((netapp_rand() >> 2) % TMO_DHCP4C_MAX_BACKOFF);
1685
1686 /* OFFER メッセージの受信タイムアウトを超
1687えないように調整する。*/
1688 if (TIMEC_GT(time + ct->interval, ct->snd_start + TMO_DHCP4C_OFFER))
1689 ct->interval = (TMO_DHCP4C_INIT_INTVL + TMO_DHCP4C_OFFER) - time + 1;
1690
1691 /* 再送信タイムアウトを設定する。*/
1692 syscall(wai_sem(SEM_DHCP4_CLI_TIMER));
1693 ct->timers[DHCP4C_TIMER_SND_DISC] = SYSTIM2TIMER(ct->interval);
1694 syscall(sig_sem(SEM_DHCP4_CLI_TIMER));
1695 }
1696
1697/*
1698 * dhcpc_timer -- TIMER 管理
1699 */
1700
1701static void
1702dhcpc_timer (T_DHCP4_CLI_CONTEXT *ct)
1703{
1704 int ix;
1705
1706 syscall(wai_sem(SEM_DHCP4_CLI_TIMER));
1707 for (ix = NUM_DHCP4C_TIMERS; ix -- > 0; ) {
1708 if (ct->timers[ix] != 0) {
1709 ct->timers[ix] --;
1710 if (ct->timers[ix] == 0) {
1711 ct->flags = (ct->flags & ~DHCP4C_FLAG_TMOUT_MASK) | DHCP4C_FLAG_TMOUT_TIMER | ix;
1712 syscall(sig_sem(SEM_DHCP4_CLI_READY));
1713 }
1714 }
1715 }
1716 syscall(sig_sem(SEM_DHCP4_CLI_TIMER));
1717
1718 /* 1秒毎にタイムアウトする。*/
1719 timeout((callout_func)dhcpc_timer, ct, NET_TIMER_HZ);
1720 }
1721
1722/*
1723 * expire_timeout -- EXPIRE タイムアウト処理
1724 */
1725
1726static void
1727expire_timeout (T_DHCP4_CLI_CONTEXT *ct)
1728{
1729 //ER error;
1730
1731 /* タイムアウトフラグをクリアーする。*/
1732 ct->flags &= ~DHCP4C_FLAG_TMOUT_MASK;
1733
1734 /* 状æ…
1735‹ãŒ REQUEST の時は何もしない。*/
1736 if (ct->fsm == DHCP4_FSM_REQUEST)
1737 return;
1738
1739 /* å…
1740¨ã¦ã® TIMER をキャンセルする。*/
1741 cancel_all_timers(ct);
1742
1743 /* リースされた情
1744報を解放する。*/
1745 rel_lease(ct);
1746
1747 ct->error = E_TMOUT;
1748 }
1749
1750/*
1751 * rebind_timeout -- REBIND タイムアウト処理
1752 */
1753
1754static void
1755rebind_timeout (T_DHCP4_CLI_CONTEXT *ct)
1756{
1757 /* タイムアウトフラグをクリアーする。*/
1758 ct->flags &= ~DHCP4C_FLAG_TMOUT_MASK;
1759
1760 /* å…
1761¨ã¦ã® TIMER をキャンセルする。*/
1762 cancel_all_timers(ct);
1763
1764 /* REQUEST メッセージを送信して REBIND 状æ…
1765‹ã«é·ç§»ã™ã‚‹ã€‚*/
1766 start_send_request(ct, DHCP4_FSM_REBIND);
1767 }
1768
1769/*
1770 * renew_timeout -- RENEW タイムアウト処理
1771 */
1772
1773static void
1774renew_timeout (T_DHCP4_CLI_CONTEXT *ct)
1775{
1776 /* タイムアウトフラグをクリアーする。*/
1777 ct->flags &= ~DHCP4C_FLAG_TMOUT_MASK;
1778
1779 /* REQUEST メッセージを送信して RENEW 状æ…
1780‹ã«é·ç§»ã™ã‚‹ã€‚*/
1781 start_send_request(ct, DHCP4_FSM_RENEW);
1782 }
1783
1784/*
1785 * dispatch_timeout -- タイムアウトした時の処理
1786 */
1787
1788static ER
1789dispatch_timeout (T_DHCP4_CLI_CONTEXT *ct)
1790{
1791 switch (ct->flags & DHCP4C_FLAG_TMOUT_TIMER_MASK) {
1792
1793 case DHCP4C_TIMER_SND_DISC:
1794 send_discover_msg(ct);
1795 break;
1796
1797 case DHCP4C_TIMER_SND_REQ:
1798 send_request_msg(ct);
1799 break;
1800
1801 case DHCP4C_TIMER_RCV_OFFER:
1802 offer_msg_timeout(ct);
1803 break;
1804
1805 case DHCP4C_TIMER_RCV_ACK:
1806 ack_msg_timeout(ct);
1807 break;
1808
1809 case DHCP4C_TIMER_RENEW:
1810 renew_timeout(ct);
1811 break;
1812
1813 case DHCP4C_TIMER_REBIND:
1814 rebind_timeout(ct);
1815 break;
1816
1817 case DHCP4C_TIMER_EXPIRE:
1818 expire_timeout(ct);
1819 break;
1820
1821 case DHCP4C_TIMER_SND_REL:
1822 send_release_msg(ct);
1823 break;
1824
1825 default:
1826 break;
1827 }
1828
1829 return ct->error;
1830 }
1831
1832/*
1833 * dispatch_event -- イベント毎の処理
1834 */
1835
1836static ER
1837dispatch_event (T_DHCP4_CLI_CONTEXT *ct)
1838{
1839 ER error = E_OK;
1840
1841 while (ct->fsm != DHCP4_FSM_SLEEP && error == E_OK) {
1842
1843 /* メッセージの受信とタイムアウトを待
1844つ。*/
1845 syscall(wai_sem(SEM_DHCP4_CLI_READY));
1846
1847 if (ct->flags & DHCP4C_FLAG_RCV_MSG) {
1848 while (ct->val_lst != NULL) {
1849 error = eval_rcv_msg(ct);
1850 }
1851 ct->flags &= ~DHCP4C_FLAG_RCV_MSG;
1852 }
1853 if (ct->flags & DHCP4C_FLAG_TMOUT_MASK)
1854 error = dispatch_timeout(ct);
1855
1856 if (ct->error != E_OK)
1857 error = ct->error;
1858 }
1859
1860 return error;
1861 }
1862
1863/*
1864 * init_context -- DHCP クライアントコンテキスト構造体を初期化する。
1865 */
1866
1867static void
1868init_context (T_DHCP4_CLI_CONTEXT *ct, ID cepid)
1869{
1870 memset(ct, 0, sizeof(*ct));
1871 ct->cepid = cepid;
1872 ct->sc = IF_ETHER_NIC_GET_SOFTC();
1873 ct->dst.portno = DHCP4_SRV_CFG_PORTNO;
1874 ct->dst.ipaddr = IPV4_ADDRANY;
1875 }
1876
1877/*
1878 * rel_cli_msg -- メッセージ構造体を解放する。
1879 */
1880
1881static void
1882rel_cli_msg (T_DHCP4_CLI_CONTEXT *ct)
1883{
1884 T_DHCP4_CLI_MSG *ptr, *cell;
1885
1886 for (ptr = ct->rcv_lst; ptr != NULL; ) {
1887 cell = ptr;
1888 ptr = ptr->next;
1889 syscall(rel_mpf(MPF_DHCP4_CLI_MSG, (void*)cell));
1890 }
1891
1892 for (ptr = ct->val_lst; ptr != NULL; ) {
1893 cell = ptr;
1894 ptr = ptr->next;
1895 syscall(rel_mpf(MPF_DHCP4_CLI_MSG, (void*)cell));
1896 }
1897
1898 for (ptr = ct->prf_lst; ptr != NULL; ) {
1899 cell = ptr;
1900 ptr = ptr->next;
1901 syscall(rel_mpf(MPF_DHCP4_CLI_MSG, (void*)cell));
1902 }
1903
1904 if (ct->snd_msg != NULL)
1905 syscall(rel_mpf(MPF_DHCP4_CLI_MSG, (void*)ct->snd_msg));
1906 ct->rcv_lst = ct->prf_lst = ct->val_lst = ct->snd_msg = NULL;
1907 }
1908
1909/*
1910 * init_cli_msg -- 各メッセージ構造体を初期化する。
1911 */
1912
1913static ER
1914init_cli_msg (T_DHCP4_CLI_CONTEXT *ct)
1915{
1916 T_DHCP4_CLI_MSG *cell;
1917 ER error;
1918 int count;
1919
1920 /* 送信メッセージ構造体を獲得する。*/
1921 if ((error = tget_mpf(MPF_DHCP4_CLI_MSG, (void*)&ct->snd_msg, TMO_DHCP4C_MPF_GET)) != E_OK) {
1922 syslog(LOG_NOTICE, "[DHCP4C] error, tget_mpf() for send: %s.", itron_strerror(error));
1923 return error;
1924 }
1925
1926 /*
1927 * 有効なリース・メッセージ構造体がある場合は、
1928 * 獲得する受信メッセージ構造体リストの構造体を 1減らす。
1929 */
1930 if (ct->act_msg == NULL)
1931 count = NUM_DHCP4_MSG_LIST;
1932 else
1933 count = NUM_DHCP4_MSG_LIST - 1;
1934
1935 /* 受信メッセージ構造体を獲得する。*/
1936 while (count --> 0) {
1937 if ((error = tget_mpf(MPF_DHCP4_CLI_MSG, (void*)&cell, TMO_DHCP4C_MPF_GET)) != E_OK) {
1938 syslog(LOG_NOTICE, "[DHCP4C] error, tget_mpf() for receive: %s.", itron_strerror(error));
1939 break;
1940 }
1941 cell->next = ct->rcv_lst;
1942 ct->rcv_lst = cell;
1943 }
1944
1945 return E_OK;
1946 }
1947
1948/*
1949 * dhcp4c_renew_info -- ネットワーク情
1950報を再取得する。
1951 */
1952
1953ER
1954dhcp4c_renew_info (void)
1955{
1956 if (context.fsm == DHCP4_FSM_BOUND) {
1957
1958 /* REL_INFO 状æ…
1959‹ã«é·ç§»ã—た後に SLEEP を解除するように設定する。*/
1960 context.flags |= DHCP4C_FLAG_RENEW;
1961 start_rel_info(&context);
1962 return E_OK;
1963 }
1964 else if (context.fsm == DHCP4_FSM_SLEEP) {
1965
1966 /* SLEEP を解除する。*/
1967 wup_tsk(DHCP4_CLI_TASK);
1968 return E_OK;
1969 }
1970 else
1971 return E_OBJ;
1972 }
1973
1974/*
1975 * dhcp4c_rel_info -- DHCP で設定されたネットワーク情
1976報を解放する。
1977 */
1978
1979ER
1980dhcp4c_rel_info (void)
1981{
1982 /* REL_INFO 状æ…
1983‹ã«é·ç§»ã™ã‚‹ã€‚*/
1984 start_rel_info(&context);
1985 return E_OK;
1986 }
1987
1988/*
1989 * dhcp4c_get_info -- DHCP で設定されたネットワーク情
1990報を返す。
1991 */
1992
1993ER
1994dhcp4c_get_info (T_IN4_ADDR *addr, uint32_t *expire, uint32_t *renew,
1995 uint32_t *rebind, SYSTIM *bind_start)
1996{
1997 if (addr == NULL || expire == NULL ||
1998 renew == NULL || rebind == NULL || bind_start == NULL)
1999 return E_PAR;
2000 else if (context.act_msg == NULL)
2001 return E_OBJ;
2002 else {
2003 *addr = context.act_msg->srv.ipaddr;
2004 *expire = context.timers[DHCP4C_TIMER_EXPIRE];
2005 *renew = context.timers[DHCP4C_TIMER_RENEW];
2006 *rebind = context.timers[DHCP4C_TIMER_REBIND];
2007 *bind_start = context.bind_start;
2008 return E_OK;
2009 }
2010 }
2011
2012/*
2013 * コールバック関数
2014 */
2015
2016ER
2017callback_nblk_dhcp4_cli (ID cepid, FN fncd, void *p_parblk)
2018{
2019 T_DHCP4_CLI_MSG *msg;
2020 ER_UINT len;
2021
2022 len = *(ER_UINT*)p_parblk;
2023 if (len < 0 && len != E_RLWAI) {
2024 /* E_RLWAI 以外で、0 以下の場合は、エラーを意味している。*/
2025 syslog(LOG_NOTICE, "[DHCPC(CBR)] error: %s, fncd: %s", itron_strerror(len), in_strtfn(fncd));
2026 }
2027 else {
2028 if (fncd == TEV_UDP_RCV_DAT) {
2029
2030 /* 受信メッセージリストが空の時は、受信しないでデータグラムを捨てる。*/
2031 if (context.rcv_lst == NULL)
2032 syslog(LOG_NOTICE, "[DHCP4C(CBR)] receive buffer all busy.");
2033 else {
2034 /* メッセージを受信するメッセージ構造体を準備する。*/
2035 syscall(wai_sem(SEM_DHCP4_CLI_LOCK));
2036 msg = context.rcv_lst;
2037 context.rcv_lst = context.rcv_lst->next;
2038 syscall(sig_sem(SEM_DHCP4_CLI_LOCK));
2039
2040 /* メッセージを受信する。*/
2041 len = udp_rcv_dat(context.cepid, &msg->srv, &msg->msg, sizeof(msg->msg), TMO_POL);
2042
2043 syscall(wai_sem(SEM_DHCP4_CLI_LOCK));
2044 msg->len = len;
2045 if (len >= 0) {
2046 /* 受信したメッセージを検証メッセージリストに移す。*/
2047 msg->next = context.val_lst;
2048 context.val_lst = msg;
2049 context.flags |= DHCP4C_FLAG_RCV_MSG;
2050 }
2051 else {
2052 /* メッセージ構造体を受信メッセージリストに戻す。*/
2053 context.error = len;
2054 msg->next = context.rcv_lst;
2055 context.rcv_lst = msg;
2056 }
2057 syscall(sig_sem(SEM_DHCP4_CLI_LOCK));
2058 }
2059 }
2060 syscall(sig_sem(SEM_DHCP4_CLI_READY));
2061 }
2062 return E_OK;
2063 }
2064
2065/*
2066 * dhcp4_cli_task -- DHCP クライアントタスク
2067 */
2068
2069void
2070dhcp4_cli_task (intptr_t exinf)
2071{
2072 T_DHCP4_CLI_CONTEXT *ct;
2073 ID tskid;
2074 ER error;
2075
2076 dly_tsk(1000);
2077 get_tid(&tskid);
2078 syslog(LOG_NOTICE, "[DHCP4C:%d,%d] started.", tskid, (ID)exinf);
2079 dly_tsk(500);
2080 ct = &context;
2081
2082 /* DHCP クライアントコンテキスト構造体を初期化する。*/
2083 init_context(ct, (ID)exinf);
2084
2085 while (true) {
2086
2087 /* 1秒毎にタイムアウトするようにタイマーを設定する。*/
2088 timeout((callout_func)dhcpc_timer, ct, NET_TIMER_HZ / DHCP4C_TIMER_HZ);
2089
2090 /* メッセージ構造体を初期化する。*/
2091 if ((error = init_cli_msg(ct)) == E_OK) {
2092
2093 /* SELECT 状æ…
2094‹ã«é·ç§»ã™ã‚‹ã€‚*/
2095 start_select(ct);
2096
2097 /* メインループ */
2098 error = dispatch_event(ct);
2099 }
2100
2101 /* å…
2102¨ã¦ã® TIMER をキャンセルする。*/
2103 cancel_all_timers(ct);
2104
2105 /* タイマーを停止する。*/
2106 untimeout((callout_func)dhcpc_timer, ct);
2107
2108 /* メッセージ構造体を解放する。*/
2109 rel_cli_msg (ct);
2110
2111 /* リースを解放後、再取得が指定されていなければ休止する。*/
2112 if (!(ct->flags & DHCP4C_FLAG_RENEW)) {
2113
2114 /* 休止する。*/
2115 if (error == E_OK)
2116 syslog(LOG_NOTICE, "[DHCP4C] lease released, go to sleep.");
2117 else {
2118 syslog(LOG_NOTICE, "[DHCP4C] server not available, go to sleep, error: %s.", itron_strerror(error));
2119 ct->fsm = DHCP4_FSM_SLEEP;
2120 }
2121 slp_tsk();
2122 }
2123 ct->flags = 0;
2124 ct->error = E_OK;
2125 }
2126 }
2127
2128#endif /* of #ifdef DHCP4_CLI_CFG */
Note: See TracBrowser for help on using the repository browser.