source: azure_iot_hub/trunk/asp3_dcre/tinet/netapp/dhcp4_cli.c@ 388

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

Azure IoT Hub Device C SDK を使ったサンプルの追加

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