source: azure_iot_hub/trunk/asp3_dcre/tinet/net/ppp_lcp.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: 34.7 KB
Line 
1/*
2 * TINET (TCP/IP Protocol Stack)
3 *
4 * Copyright (C) 2001-2017 by Dep. of Computer Science and Engineering
5 * Tomakomai National College of Technology, JAPAN
6 *
7 * 上記著作権者
8は,以下の (1)~(4) の条件か,Free Software Foundation
9 * によってå…
10¬è¡¨ã•ã‚Œã¦ã„ã‚‹ GNU General Public License の Version 2 に記
11 * 述されている条件を満たす場合に限り,本ソフトウェア(本ソフトウェア
12 * を改変したものを含む.以下同じ)を使用・複製・改変・再é…
13å¸ƒï¼ˆä»¥ä¸‹ï¼Œ
14 * 利用と呼ぶ)することを無償で許諾する.
15 * (1) 本ソフトウェアをソースコードの形で利用する場合には,上記の著作
16 * 権表示,この利用条件および下記の無保証規定が,そのままの形でソー
17 * スコード中に含まれていること.
18 * (2) 本ソフトウェアを,ライブラリ形式など,他のソフトウェア開発に使
19 * 用できる形で再é…
20å¸ƒã™ã‚‹å ´åˆã«ã¯ï¼Œå†é…
21å¸ƒã«ä¼´ã†ãƒ‰ã‚­ãƒ¥ãƒ¡ãƒ³ãƒˆï¼ˆåˆ©ç”¨
22 * 者
23マニュアルなど)に,上記の著作権表示,この利用条件および下記
24 * の無保証規定を掲載すること.
25 * (3) 本ソフトウェアを,機器に組み込むなど,他のソフトウェア開発に使
26 * 用できない形で再é…
27å¸ƒã™ã‚‹å ´åˆã«ã¯ï¼Œæ¬¡ã®æ¡ä»¶ã‚’満たすこと.
28 * (a) 再é…
29å¸ƒã«ä¼´ã†ãƒ‰ã‚­ãƒ¥ãƒ¡ãƒ³ãƒˆï¼ˆåˆ©ç”¨è€…
30マニュアルなど)に,上記の著
31 * 作権表示,この利用条件および下記の無保証規定を掲載すること.
32 * (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
33 * 害からも,上記著作権者
34およびTOPPERSプロジェクトをå…
35è²¬ã™ã‚‹ã“と.
36 *
37 * 本ソフトウェアは,無保証で提供されているものである.上記著作権者
38お
39 * よびTOPPERSプロジェクトは,本ソフトウェアに関して,その適用可能性も
40 * 含めて,いかなる保証も行わない.また,本ソフトウェアの利用により直
41 * 接的または間接的に生じたいかなる損害に関しても,その責任を負わない.
42 *
43 * @(#) $Id: ppp_lcp.c 388 2019-05-22 11:25:18Z coas-nagasima $
44 */
45
46/*
47 * lcp.c - PPP Link Control Protocol.
48 *
49 * Copyright (c) 1989 Carnegie Mellon University.
50 * All rights reserved.
51 *
52 * Redistribution and use in source and binary forms are permitted
53 * provided that the above copyright notice and this paragraph are
54 * duplicated in all such forms and that any documentation,
55 * advertising materials, and other materials related to such
56 * distribution and use acknowledge that the software was developed
57 * by Carnegie Mellon University. The name of the
58 * University may not be used to endorse or promote products derived
59 * from this software without specific prior written permission.
60 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
61 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
62 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
63 */
64
65/*
66 * PPP Link Control Protocol (LCP) Module
67 *
68 * Written by Toshiharu OHNO (tony-o@iij.ad.jp)
69 *
70 * Copyright (C) 1993, Internet Initiative Japan, Inc. All rights reserverd.
71 *
72 * Redistribution and use in source and binary forms are permitted
73 * provided that the above copyright notice and this paragraph are
74 * duplicated in all such forms and that any documentation,
75 * advertising materials, and other materials related to such
76 * distribution and use acknowledge that the software was developed
77 * by the Internet Initiative Japan, Inc. The name of the
78 * IIJ may not be used to endorse or promote products derived
79 * from this software without specific prior written permission.
80 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
81 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
82 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
83 *
84 * $FreeBSD: src/usr.sbin/ppp/lcp.c,v 1.81.2.3 2000/08/19 09:30:04 brian Exp $
85 *
86 */
87
88#include <string.h>
89
90#include <s_services.h>
91#include <t_services.h>
92#include "kernel_id.h"
93
94#include <tinet_defs.h>
95#include <tinet_config.h>
96
97#include <net/if.h>
98#include <net/if_ppp.h>
99#include <net/net.h>
100#include <net/net_endian.h>
101#include <net/net_var.h>
102#include <net/net_buf.h>
103#include <net/net_timer.h>
104#include <net/net_count.h>
105#include <net/ppp.h>
106#include <net/ppp_var.h>
107#include <net/ppp_hdlc.h>
108#include <net/ppp_auth.h>
109#include <net/ppp_fsm.h>
110#include <net/ppp_lcp.h>
111
112#ifdef SUPPORT_PPP
113
114/*
115 * 関数
116 */
117
118static void lcp_init (void);
119static void lcp_protrej (void);
120static void lcp_input (T_NET_BUF *input);
121
122#if DEF_LCP_LOCAL_CFGS & LCP_CFG_MAGIC
123
124static void send_echo_req (T_PPP_FSM *fsm);
125static void recv_echo_rep (T_PPP_FSM *fsm, uint8_t id, T_NET_BUF *input);
126static void echo_timeout (void *arg);
127static void echo_lowerup (void);
128static void echo_lowerdown (void);
129
130#endif /* of #if DEF_LCP_LOCAL_CFGS & LCP_CFG_MAGIC */
131
132/*
133 * FSM から呼出されるコールバック関数
134 */
135
136static void lcp_resetci(T_PPP_FSM *fsm); /* 自構成情
137報をリセットする。 */
138static int_t lcp_cilen (T_PPP_FSM *fsm); /* 構成情
139報の長さを返す。 */
140static void lcp_addci (T_PPP_FSM *fsm, T_NET_BUF *output);
141 /* 自構成情
142報を追加する。 */
143static bool_t lcp_ackci (T_PPP_FSM *fsm, T_NET_BUF *input);
144 /* ACK を受信したときの処理 */
145static bool_t lcp_nakci (T_PPP_FSM *fsm, T_NET_BUF *input);
146 /* NAK を受信したときの処理 */
147static bool_t lcp_rejci (T_PPP_FSM *fsm, T_NET_BUF *input);
148 /* REJ を受信したときの処理 */
149static int_t lcp_reqci (T_PPP_FSM *fsm, T_NET_BUF *input, T_NET_BUF *output);
150 /* 相手の構成情
151報を確認する。 */
152static void lcp_up (T_PPP_FSM *fsm); /* リンク接続を確立する。 */
153static void lcp_starting(T_PPP_FSM *fsm); /* 下位層を開始する。 */
154static bool_t lcp_extcode (T_PPP_FSM *fsm, uint8_t code, uint8_t id, T_NET_BUF *input);
155 /* 不明な CP を受信したときの処理 */
156static void lcp_rprotrej(T_PPP_FSM *fsm, T_NET_BUF *input);
157 /* Proto-REJ を受信したときの処理 */
158/*
159 * 変数
160 */
161
162static T_LCP_CONFIGS lcp_def_cfg = { /* 構成情
163報の初期設定値 */
164 DEF_REMOTE_ACCM, /* ACCM */
165
166#ifdef LCP_CFG_MAGIC
167
168 ULONG_C(0), /* マジック番号 */
169
170#endif /* of #ifdef LCP_CFG_MAGIC */
171
172 DEF_PPP_MTU, /* MRU */
173 UINT_C(0), /* オプションフラグ */
174 };
175
176static T_LCP_CONFIGS lcp_local_def_cfg = { /* 自構成情
177報の規定値 */
178 DEF_LOCAL_ACCM, /* ACCM */
179
180#ifdef LCP_CFG_MAGIC
181
182 ULONG_C(0), /* マジック番号 */
183
184#endif /* of #ifdef LCP_CFG_MAGIC */
185
186 DEF_PPP_MTU, /* MRU */
187 DEF_LCP_LOCAL_CFGS, /* オプションフラグ */
188 };
189
190static T_LCP_CONFIGS lcp_local_neg_cfg; /* ネゴ中の自構成情
191å ± */
192
193static T_LCP_CONFIGS lcp_remote_neg_cfg; /* ネゴ中の相手の構成情
194å ± */
195
196#if DEF_LCP_LOCAL_CFGS & LCP_CFG_MAGIC
197
198static uint8_t echo_pending = UINT_C(0);
199static uint8_t echo_number = UINT_C(0);
200static uint8_t timer_running = false;
201
202#endif /* of #if DEF_LCP_LOCAL_CFGS & LCP_CFG_MAGIC */
203
204/*
205 * å…
206¨åŸŸå¤‰æ•°
207 */
208
209T_PPP_FSM_CALLBACKS lcp_callbacks = {
210 lcp_resetci, /* 自構成情
211報をリセットする。 */
212 lcp_cilen, /* 構成情
213報の長さを返す。 */
214 lcp_addci, /* 自構成情
215報を追加する。 */
216 lcp_ackci, /* ACK を受信したときの処理 */
217 lcp_nakci, /* NAK を受信したときの処理 */
218 lcp_rejci, /* REJ を受信したときの処理 */
219 lcp_reqci, /* 相手の構成情
220報を確認する。 */
221 lcp_up, /* リンク接続を確立する。 */
222 lcp_down, /* リンク接続を解放する。 */
223 lcp_starting, /* 下位層を開始する。 */
224 lcp_finished, /* 下位層を終了する。 */
225 NULL, /* 再送する。 */
226 lcp_extcode, /* 不明な CP を受信したときの処理 */
227 };
228
229T_PPP_FSM lcp_fsm = {
230 &lcp_callbacks, /* コールバック関数 */
231 PPP_LCP, /* プロトコル */
232 };
233
234T_PPP_PROTENT lcp_protent = {
235 PPP_LCP,
236 lcp_init, /* 初期化 */
237 lcp_input, /* å…
238¥åŠ› */
239 lcp_protrej, /* Proto-REJ 受信処理 */
240 NULL, /* 下位層を起動する */
241 lcp_lowerdown, /* 下位層を停止する */
242 NULL, /* オープンする */
243 lcp_close, /* クローズする */
244 NULL, /* データå…
245¥åŠ› */
246 };
247
248T_LCP_CONFIGS lcp_local_ack_cfg; /* 相手に許可されたの自構成情
249å ± */
250T_LCP_CONFIGS lcp_remote_ack_cfg; /* 相手に許可した構成情
251å ± */
252
253/*
254 * lcp_init -- LCP モジュールの初期化
255 */
256
257static void
258lcp_init (void)
259{
260 fsm_init(&lcp_fsm);
261 }
262
263/*
264 * lcp_input -- LCP å…
265¥åŠ›
266 */
267
268static void
269lcp_input (T_NET_BUF *input)
270{
271 NET_COUNT_PPP_LCP(net_count_ppp_lcp_in_octets, input->len);
272 NET_COUNT_PPP_LCP(net_count_ppp_lcp_in_packets, 1);
273 fsm_input(&lcp_fsm, input);
274 }
275
276/*
277 * lcp_resetci -- LCPの構成情
278報をリセットする。
279 */
280
281static void
282lcp_resetci (T_PPP_FSM *fsm)
283{
284#ifdef LCP_CFG_MAGIC
285
286 SYSTIM time;
287
288#endif /* of #ifdef LCP_CFG_MAGIC */
289
290 /* 自構成情
291報の初期設定 */
292 lcp_local_neg_cfg = lcp_local_def_cfg;
293 lcp_local_ack_cfg = lcp_def_cfg;
294
295 /* 相手の構成情
296報の初期設定 */
297 lcp_remote_neg_cfg = lcp_def_cfg;
298 lcp_remote_ack_cfg = lcp_def_cfg;
299
300#ifdef LCP_CFG_MAGIC
301
302 syscall(get_tim(&time));
303 net_srand((unsigned int)time);
304 lcp_local_neg_cfg.magic = net_rand();
305
306#endif /* of #ifdef LCP_CFG_MAGIC */
307
308 auth_reset();
309 }
310
311/*
312 * lcp_cilen -- 構成情
313報の長さを返す。
314 */
315
316static int_t
317lcp_cilen (T_PPP_FSM *fsm)
318{
319 int_t cilen = 0;
320
321 if (lcp_local_neg_cfg.options & LCP_CFG_MRU)
322 cilen += sizeof(T_PPP_CI_HDR) + sizeof(uint16_t); /* MRU */
323
324 if (lcp_local_neg_cfg.options & LCP_CFG_ACCM)
325 cilen += sizeof(T_PPP_CI_HDR) + sizeof(uint32_t); /* ACCM */
326
327#ifdef LCP_CFG_MAGIC
328
329 if (lcp_local_neg_cfg.options & LCP_CFG_MAGIC)
330 cilen += sizeof(T_PPP_CI_HDR) + sizeof(uint32_t); /* Magic */
331
332#endif /* of #ifdef LCP_CFG_MAGIC */
333
334#ifdef LCP_CFG_PAP
335
336 if (lcp_local_neg_cfg.options & LCP_CFG_PAP)
337 cilen += sizeof(T_PPP_CI_HDR) + sizeof(uint16_t); /* PAP */
338
339#endif /* of #ifdef LCP_CFG_PAP */
340
341#ifdef LCP_CFG_PCOMP
342
343 if (lcp_local_neg_cfg.options & LCP_CFG_PCOMP)
344 cilen += sizeof(T_PPP_CI_HDR); /* プロトコル圧縮 */
345
346#endif /* of #ifdef LCP_CFG_PCOMP */
347
348#ifdef LCP_CFG_ACCOMP
349
350 if (lcp_local_neg_cfg.options & LCP_CFG_ACCOMP)
351 cilen += sizeof(T_PPP_CI_HDR); /* アドレス・制御圧縮 */
352
353#endif /* of #ifdef LCP_CFG_ACCOMP */
354
355 return cilen;
356 }
357
358/*
359 * lcp_addci -- LCPの構成情
360報を追加する。
361 */
362
363static void
364lcp_addci (T_PPP_FSM *fsm, T_NET_BUF *output)
365{
366 uint8_t *buf;
367
368 buf = output->buf + sizeof(T_PPP_HDR) + sizeof(T_PPP_CP_HDR);
369
370 /* MRU オプションを追加する。 */
371 if (lcp_local_neg_cfg.options & LCP_CFG_MRU) {
372 *buf ++ = LCP_CIT_MRU;
373 *buf ++ = sizeof(T_PPP_CI_HDR) + sizeof(uint16_t);
374 *((uint16_t*)buf) = htons(lcp_local_neg_cfg.MRU);
375 buf += sizeof(uint16_t);
376 }
377
378 /* ACCM オプションを追加する。 */
379 if (lcp_local_neg_cfg.options & LCP_CFG_ACCM) {
380 *buf ++ = LCP_CIT_ACCM;
381 *buf ++ = sizeof(T_PPP_CI_HDR) + sizeof(uint32_t);
382 ahtonl(buf, lcp_local_neg_cfg.ACCM);
383 buf += sizeof(uint32_t);
384 }
385
386#ifdef LCP_CFG_MAGIC
387
388 /* Magic Number オプションを追加する。 */
389 if (lcp_local_neg_cfg.options & LCP_CFG_MAGIC) {
390 *buf ++ = LCP_CIT_MAGIC;
391 *buf ++ = sizeof(T_PPP_CI_HDR) + sizeof(uint32_t);
392 ahtonl(buf, lcp_local_neg_cfg.magic);
393 buf += sizeof(uint32_t);
394 }
395
396#endif /* of #ifdef LCP_CFG_MAGIC */
397
398#ifdef LCP_CFG_PAP
399
400 /* 認証プロトコルオプションを追加する。 */
401 if (lcp_local_neg_cfg.options & LCP_CFG_PAP) {
402 *buf ++ = LCP_CIT_AUTH;
403 *buf ++ = sizeof(T_PPP_CI_HDR) + sizeof(uint16_t);
404 *((uint16_t*)buf) = htons(PPP_PAP);
405 buf += sizeof(uint16_t);
406 }
407
408#endif /* of #ifdef LCP_CFG_PAP */
409
410#ifdef LCP_CFG_PCOMP
411
412 /* プロトコル圧縮オプションを追加する。 */
413 if (lcp_local_neg_cfg.options & LCP_CFG_PCOMP) {
414 *buf ++ = LCP_CIT_PCOMP;
415 *buf ++ = sizeof(T_PPP_CI_HDR);
416 }
417
418#endif /* of #ifdef LCP_CFG_PCOMP */
419
420#ifdef LCP_CFG_ACCOMP
421
422 /* アドレス・制御圧縮オプションを追加する。 */
423 if (lcp_local_neg_cfg.options & LCP_CFG_ACCOMP) {
424 *buf ++ = LCP_CIT_ACCOMP;
425 *buf ++ = sizeof(T_PPP_CI_HDR);
426 }
427
428#endif /* of #ifdef LCP_CFG_ACCOMP */
429 }
430
431/*
432 * lcp_ackci -- ACK を受信したときの処理
433 *
434 * 戻り値: TURE ACK は正常
435 * false ACK は異常
436 */
437
438static bool_t
439lcp_ackci (T_PPP_FSM *fsm, T_NET_BUF *input)
440{
441 uint8_t *buf;
442 uint16_t len;
443
444 buf = input->buf + sizeof(T_PPP_HDR) + sizeof(T_PPP_CP_HDR);
445 len = input->len - (sizeof(T_PPP_HDR) + sizeof(T_PPP_CP_HDR));
446
447 /*
448 * 構成情
449報は送信した順に完å…
450¨ã«ä¸€è‡´ã—なければならない。
451 * 従って、lcp_addci で作成した順に解析する。
452 */
453
454 /* MRU オプションを解析する。 */
455 if (lcp_local_neg_cfg.options & LCP_CFG_MRU) {
456 if (len < sizeof(T_PPP_CI_HDR) + sizeof(uint16_t) ||
457 *buf ++ != LCP_CIT_MRU ||
458 *buf ++ != sizeof(T_PPP_CI_HDR) + sizeof(uint16_t)||
459 *((uint16_t*)buf) != htons(lcp_local_neg_cfg.MRU) )
460 return false;
461 buf += sizeof(uint16_t);
462 len -= sizeof(T_PPP_CI_HDR) + sizeof(uint16_t);
463 }
464
465 /* ACCM オプションを解析する。 */
466 if (lcp_local_neg_cfg.options & LCP_CFG_ACCM) {
467 if (len < sizeof(T_PPP_CI_HDR) + sizeof(uint32_t) ||
468 *buf ++ != LCP_CIT_ACCM ||
469 *buf ++ != sizeof(T_PPP_CI_HDR) + sizeof(uint32_t)||
470 nahcmpl(buf, lcp_local_neg_cfg.ACCM) )
471 return false;
472 buf += sizeof(uint32_t);
473 len -= sizeof(T_PPP_CI_HDR) + sizeof(uint32_t);
474 }
475
476#ifdef LCP_CFG_MAGIC
477
478 /* Magic Number オプションを解析する。 */
479 if (lcp_local_neg_cfg.options & LCP_CFG_MAGIC) {
480 if (len < sizeof(T_PPP_CI_HDR) + sizeof(uint32_t) ||
481 *buf ++ != LCP_CIT_MAGIC ||
482 *buf ++ != sizeof(T_PPP_CI_HDR) + sizeof(uint32_t)||
483 nahcmpl(buf, lcp_local_neg_cfg.magic) )
484 return false;
485 buf += sizeof(uint32_t);
486 len -= sizeof(T_PPP_CI_HDR) + sizeof(uint32_t);
487 }
488
489#endif /* of #ifdef LCP_CFG_MAGIC */
490
491#ifdef LCP_CFG_PAP
492
493 /* 認証プロトコルオプションを解析する。 */
494 if (lcp_local_neg_cfg.options & LCP_CFG_PAP) {
495 if (len < sizeof(T_PPP_CI_HDR) + sizeof(uint16_t) ||
496 *buf ++ != LCP_CIT_AUTH ||
497 *buf ++ != sizeof(T_PPP_CI_HDR) + sizeof(uint16_t)||
498 *((uint16_t*)buf) != htons(PPP_PAP) )
499 return false;
500 buf += sizeof(uint16_t);
501 len -= sizeof(T_PPP_CI_HDR) + sizeof(uint16_t);
502 }
503
504#endif /* of #ifdef LCP_CFG_PAP */
505
506#ifdef LCP_CFG_PCOMP
507
508 /* プロトコル圧縮オプションを解析する。 */
509 if (lcp_local_neg_cfg.options & LCP_CFG_PCOMP) {
510 if (len < sizeof(T_PPP_CI_HDR) ||
511 *buf ++ != LCP_CIT_PCOMP ||
512 *buf ++ != sizeof(T_PPP_CI_HDR))
513 return false;
514 len -= sizeof(T_PPP_CI_HDR);
515 }
516
517#endif /* of #ifdef LCP_CFG_PCOMP */
518
519#ifdef LCP_CFG_ACCOMP
520
521 /* アドレス・制御圧縮オプションを解析する。 */
522 if (lcp_local_neg_cfg.options & LCP_CFG_ACCOMP) {
523 if (len < sizeof(T_PPP_CI_HDR) ||
524 *buf ++ != LCP_CIT_ACCOMP ||
525 *buf ++ != sizeof(T_PPP_CI_HDR))
526 return false;
527 len -= sizeof(T_PPP_CI_HDR);
528 }
529
530#endif /* of #ifdef LCP_CFG_ACCOMP */
531 return true;
532 }
533
534/*
535 * lcp_nakci -- NAK を受信したときの処理
536 *
537 * 戻り値: 1 NAK は正常
538 * 0 NAK は異常
539 */
540
541static int_t
542lcp_nakci (T_PPP_FSM *fsm, T_NET_BUF *input)
543{
544 T_LCP_CONFIGS new_cfg;
545 bool_t loop = false; /* ループバックをチェック */
546 uint32_t cilong;
547 uint16_t cishort, len;
548 uint8_t *buf, cilen;
549
550 buf = input->buf + sizeof(T_PPP_HDR) + sizeof(T_PPP_CP_HDR);
551 len = input->len - (sizeof(T_PPP_HDR) + sizeof(T_PPP_CP_HDR));
552
553 new_cfg = lcp_local_neg_cfg;
554
555 /* MRU オプションを解析する。 */
556 if (len >= sizeof(T_PPP_CI_HDR) + sizeof(uint16_t) &&
557 * buf == LCP_CIT_MRU &&
558 *(buf + 1) == sizeof(T_PPP_CI_HDR) + sizeof(uint16_t) &&
559 (lcp_local_neg_cfg.options & LCP_CFG_MRU)) {
560 cishort = ntohs(*((uint16_t*)(buf + 2)));
561 buf += sizeof(T_PPP_CI_HDR) + sizeof(uint16_t);
562 len -= sizeof(T_PPP_CI_HDR) + sizeof(uint16_t);
563 if (cishort <= lcp_local_neg_cfg.MRU || cishort <= DEF_PPP_MTU)
564 new_cfg.MRU = cishort;
565 }
566
567 /* ACCM オプションを解析する。 */
568 if (len >= sizeof(T_PPP_CI_HDR) + sizeof(uint32_t) &&
569 * buf == LCP_CIT_ACCM &&
570 *(buf + 1) == sizeof(T_PPP_CI_HDR) + sizeof(uint32_t) &&
571 (lcp_local_neg_cfg.options & LCP_CFG_ACCM)) {
572 ntoahl(cilong, buf + 2);
573 buf += sizeof(T_PPP_CI_HDR) + sizeof(uint32_t);
574 len -= sizeof(T_PPP_CI_HDR) + sizeof(uint32_t);
575 new_cfg.ACCM |= cilong;
576 }
577
578#ifdef LCP_CFG_MAGIC
579
580 /* Magic Number オプションを解析する。 */
581 if (len >= sizeof(T_PPP_CI_HDR) + sizeof(uint32_t) &&
582 * buf == LCP_CIT_MAGIC &&
583 *(buf + 1) == sizeof(T_PPP_CI_HDR) + sizeof(uint32_t) &&
584 (lcp_local_neg_cfg.options & LCP_CFG_MAGIC)) {
585 ntoahl(cilong, buf + 2);
586 buf += sizeof(T_PPP_CI_HDR) + sizeof(uint32_t);
587 len -= sizeof(T_PPP_CI_HDR) + sizeof(uint32_t);
588 new_cfg.magic = cilong;
589 loop = true;
590 }
591
592#endif /* of #ifdef LCP_CFG_MAGIC */
593
594#ifdef LCP_CFG_PAP
595
596 /* 認証プロトコルオプションを解析する。 */
597 if (len >= sizeof(T_PPP_CI_HDR) + sizeof(uint16_t) &&
598 * buf == LCP_CIT_AUTH &&
599 *(buf + 1) == sizeof(T_PPP_CI_HDR) + sizeof(uint16_t) &&
600 (lcp_local_neg_cfg.options & LCP_CFG_PAP)) {
601 cishort = ntohs(*((uint16_t*)(buf + 2)));
602 buf += sizeof(T_PPP_CI_HDR) + sizeof(uint16_t);
603 len -= sizeof(T_PPP_CI_HDR) + sizeof(uint16_t);
604 if (cishort == PPP_PAP)
605 new_cfg.options &= ~LCP_CFG_PAP;
606 else
607 return 0;
608 }
609
610#endif /* of #ifdef LCP_CFG_PAP */
611
612#ifdef LCP_CFG_PCOMP
613
614 /* プロトコル圧縮オプションを解析する。 */
615 if (len >= sizeof(T_PPP_CI_HDR) &&
616 * buf == LCP_CIT_PCOMP &&
617 *(buf + 1) == sizeof(T_PPP_CI_HDR) &&
618 (lcp_local_neg_cfg.options & LCP_CFG_PCOMP)) {
619 buf += sizeof(T_PPP_CI_HDR);
620 len -= sizeof(T_PPP_CI_HDR);
621 new_cfg.options &= ~LCP_CFG_PCOMP;
622 }
623
624#endif /* of #ifdef LCP_CFG_PCOMP */
625
626#ifdef LCP_CFG_ACCOMP
627
628 /* アドレス・制御圧縮オプションを解析する。 */
629 if (len >= sizeof(T_PPP_CI_HDR) &&
630 * buf == LCP_CIT_ACCOMP &&
631 *(buf + 1) == sizeof(T_PPP_CI_HDR) &&
632 (lcp_local_neg_cfg.options & LCP_CFG_ACCOMP)) {
633 buf += sizeof(T_PPP_CI_HDR);
634 len -= sizeof(T_PPP_CI_HDR);
635 new_cfg.options &= ~LCP_CFG_ACCOMP;
636 }
637
638#endif /* of #ifdef LCP_CFG_ACCOMP */
639
640 /* 後は無視する。*/
641 while (len > sizeof(T_PPP_CI_HDR)) {
642 cilen = *(buf + 1);
643 if (len < cilen)
644 return 0;
645 buf += cilen;
646 len -= cilen;
647 }
648
649 /* 長さが 0 でなければエラー */
650 if (len != 0)
651 return 0;
652
653 /* 新しいオプションを設定する。*/
654 if (fsm->state != PPP_FSM_OPENED) {
655 if (loop) {
656 syslog(LOG_WARNING, "[PPP/LCP] line looped.");
657 lcp_close();
658 }
659 lcp_local_neg_cfg = new_cfg;
660 }
661 return 1;
662 }
663
664/*
665 * lcp_rejci -- REJ を受信したときの処理
666 *
667 * 戻り値: 1 REJ は正常
668 * 0 REJ は異常
669 */
670
671static int_t
672lcp_rejci (T_PPP_FSM *fsm, T_NET_BUF *input)
673{
674 T_LCP_CONFIGS new_cfg;
675 uint32_t cilong;
676 uint16_t cishort, len;
677 uint8_t *buf;
678
679 buf = input->buf + sizeof(T_PPP_HDR) + sizeof(T_PPP_CP_HDR);
680 len = input->len - (sizeof(T_PPP_HDR) + sizeof(T_PPP_CP_HDR));
681
682 new_cfg = lcp_local_neg_cfg;
683
684 /* MRU オプションを解析する。 */
685 if (len >= sizeof(T_PPP_CI_HDR) + sizeof(uint16_t) &&
686 * buf == LCP_CIT_MRU &&
687 *(buf + 1) == sizeof(T_PPP_CI_HDR) + sizeof(uint16_t) &&
688 (lcp_local_neg_cfg.options & LCP_CFG_MRU)) {
689 cishort = ntohs(*((uint16_t*)(buf + 2)));
690 buf += sizeof(T_PPP_CI_HDR) + sizeof(uint16_t);
691 len -= sizeof(T_PPP_CI_HDR) + sizeof(uint16_t);
692 if (cishort != lcp_local_neg_cfg.MRU)
693 return 0;
694 else
695 new_cfg.options &= ~LCP_CFG_MRU;
696 }
697
698 /* ACCM オプションを解析する。 */
699 if (len >= sizeof(T_PPP_CI_HDR) + sizeof(uint32_t) &&
700 * buf == LCP_CIT_ACCM &&
701 *(buf + 1) == sizeof(T_PPP_CI_HDR) + sizeof(uint32_t) &&
702 (lcp_local_neg_cfg.options & LCP_CFG_ACCM)) {
703 ntoahl(cilong, buf + 2);
704 buf += sizeof(T_PPP_CI_HDR) + sizeof(uint32_t);
705 len -= sizeof(T_PPP_CI_HDR) + sizeof(uint32_t);
706 if (cilong != lcp_local_neg_cfg.ACCM)
707 return 0;
708 else
709 new_cfg.options &= ~LCP_CFG_ACCM;
710 }
711
712#ifdef LCP_CFG_MAGIC
713
714 /* Magic Number オプションを解析する。 */
715 if (len >= sizeof(T_PPP_CI_HDR) + sizeof(uint32_t) &&
716 * buf == LCP_CIT_MAGIC &&
717 *(buf + 1) == sizeof(T_PPP_CI_HDR) + sizeof(uint32_t) &&
718 (lcp_local_neg_cfg.options & LCP_CFG_MAGIC)) {
719 ntoahl(cilong, buf + 2);
720 buf += sizeof(T_PPP_CI_HDR) + sizeof(uint32_t);
721 len -= sizeof(T_PPP_CI_HDR) + sizeof(uint32_t);
722 if (cilong != lcp_local_neg_cfg.magic)
723 return 0;
724 else
725 new_cfg.options &= ~LCP_CFG_MAGIC;
726 }
727
728#endif /* of #ifdef LCP_CFG_MAGIC */
729
730#ifdef LCP_CFG_PAP
731
732 /* 認証プロトコルオプションを解析する。 */
733 if (len >= sizeof(T_PPP_CI_HDR) + sizeof(uint16_t) &&
734 * buf == LCP_CIT_AUTH &&
735 *(buf + 1) == sizeof(T_PPP_CI_HDR) + sizeof(uint16_t) &&
736 (lcp_local_neg_cfg.options & LCP_CFG_PAP)) {
737 cishort = ntohs(*((uint16_t*)(buf + 2)));
738 buf += sizeof(T_PPP_CI_HDR) + sizeof(uint16_t);
739 len -= sizeof(T_PPP_CI_HDR) + sizeof(uint16_t);
740 if (cishort != PPP_PAP)
741 return 0;
742 else
743 new_cfg.options &= ~LCP_CFG_PAP;
744 }
745
746#endif /* of #ifdef LCP_CFG_PAP */
747
748#ifdef LCP_CFG_PCOMP
749
750 /* プロトコル圧縮オプションを解析する。 */
751 if (len >= sizeof(T_PPP_CI_HDR) &&
752 * buf == LCP_CIT_PCOMP &&
753 *(buf + 1) == sizeof(T_PPP_CI_HDR) &&
754 (lcp_local_neg_cfg.options & LCP_CFG_PCOMP)) {
755 buf += sizeof(T_PPP_CI_HDR);
756 len -= sizeof(T_PPP_CI_HDR);
757 new_cfg.options &= ~LCP_CFG_PCOMP;
758 }
759
760#endif /* of #ifdef LCP_CFG_PCOMP */
761
762#ifdef LCP_CFG_ACCOMP
763
764 /* アドレス・制御圧縮オプションを解析する。 */
765 if (len >= sizeof(T_PPP_CI_HDR) &&
766 * buf == LCP_CIT_ACCOMP &&
767 *(buf + 1) == sizeof(T_PPP_CI_HDR) &&
768 (lcp_local_neg_cfg.options & LCP_CFG_ACCOMP)) {
769 buf += sizeof(T_PPP_CI_HDR);
770 len -= sizeof(T_PPP_CI_HDR);
771 new_cfg.options &= ~LCP_CFG_ACCOMP;
772 }
773
774#endif /* of #ifdef LCP_CFG_ACCOMP */
775
776 /* 長さが 0 でなければエラー */
777 if (len != 0)
778 return 0;
779
780 /* 新しいオプションを設定する。*/
781 if (fsm->state != PPP_FSM_OPENED)
782 lcp_local_neg_cfg = new_cfg;
783
784 return 1;
785 }
786
787/*
788 * lcp_reqci -- 相手の構成情
789報を解析する。
790 */
791
792static int_t
793lcp_reqci (T_PPP_FSM *fsm, T_NET_BUF *input, T_NET_BUF *output)
794{
795#if DEF_LCP_REMOTE_CFGS & LCP_CFG_MAGIC
796
797 uint32_t cilong;
798
799#endif /* of #if DEF_LCP_REMOTE_CFGS & LCP_CFG_MAGIC */
800
801 uint16_t code, final, len, cilen, cishort;
802 uint8_t *np, *rp, *ap, *cp, type = 0;
803
804 rp = ap = input->buf + sizeof(T_PPP_HDR) + sizeof(T_PPP_CP_HDR);
805 /* rp: REJ、ap: ACK する CI のポインタ */
806 /* 拒否する場合は、引数 input に上書きする。 */
807 len = input->len - (sizeof(T_PPP_HDR) + sizeof(T_PPP_CP_HDR));
808 np = output->buf + sizeof(T_PPP_HDR) + sizeof(T_PPP_CP_HDR);
809 final = PPP_CONFACK; /* 最終的に送信するコード */
810 while (len > 0) {
811 code = PPP_CONFACK;
812 cp = ap; /* cp: 現在処理中の CI */
813
814 if (len < sizeof(T_PPP_CI_HDR)) {
815
816 /* 残りが CI ヘッダより短い */
817 syslog(LOG_WARNING, "[PPP/LCP] bad CI len: %d.", len);
818 cilen = len; /* データ長が異常の場合の処置 */
819 len = 0; /* ループから抜ける。 */
820 code = PPP_CONFREJ;
821 goto endswitch;
822 }
823
824 type = *ap ++; /* CI の型 */
825 cilen = *ap ++; /* CI の長さ */
826 if (len < cilen) {
827
828 /* 残りが CI 長より短い */
829 syslog(LOG_WARNING, "[PPP/LCP] bad CI len: %d.", cilen);
830 cilen = len; /* データ長が異常の場合の処置 */
831 len = 0; /* ループから抜ける。 */
832 code = PPP_CONFREJ;
833 goto endswitch;
834 }
835 len -= sizeof(T_PPP_CI_HDR);
836
837 /* CI の型により分岐する。*/
838 switch (type) {
839
840 case LCP_CIT_MRU: /* 最大受信量 (Maximum Receive Unit) */
841
842#if (DEF_LCP_REMOTE_CFGS & LCP_CFG_MRU) == 0
843
844 code = PPP_CONFREJ;
845
846#else /* of #if (DEF_LCP_REMOTE_CFGS & LCP_CFG_MRU) == 0 */
847
848 /* CI 長が、ヘッダ + 2 オクテットでなければ REJ */
849 if (cilen != sizeof(T_PPP_CI_HDR) + sizeof(uint16_t))
850 code = PPP_CONFREJ;
851 {
852 cishort = ntohs(*(uint16_t*)ap);
853
854 /* 最小受信量より小さければ NAK */
855 if (cishort < MIN_PPP_MTU) {
856 *np ++ = LCP_CIT_MRU;
857 *np ++ = sizeof(T_PPP_CI_HDR) + sizeof(uint16_t);
858 *((uint16_t*)np) = htons(MIN_PPP_MTU);
859 np += sizeof(uint16_t);
860 code = PPP_CONFNAK;
861 }
862 else {
863 lcp_remote_neg_cfg.MRU = cishort;
864 lcp_remote_neg_cfg.options |= LCP_CFG_MRU;
865 }
866 }
867
868#endif /* of #if (DEF_LCP_REMOTE_CFGS & LCP_CFG_MRU) == 0 */
869
870 break;
871
872 case LCP_CIT_ACCM: /* Async Control Character Map */
873
874#if (DEF_LCP_REMOTE_CFGS & LCP_CFG_ACCM) == 0
875
876 code = PPP_CONFREJ;
877
878#else /* of #if (DEF_LCP_REMOTE_CFGS & LCP_CFG_ACCM) == 0 */
879
880 /* CI 長が、ヘッダ + 4 オクテットでなければ REJ */
881 if (cilen != sizeof(T_PPP_CI_HDR) + sizeof(uint32_t))
882 code = PPP_CONFREJ;
883 else {
884 ntoahl(lcp_remote_neg_cfg.ACCM, ap);
885 lcp_remote_neg_cfg.options |= LCP_CFG_ACCM;
886 }
887
888#endif /* of #if (DEF_LCP_REMOTE_CFGS & LCP_CFG_ACCM) == 0 */
889
890 break;
891
892 case LCP_CIT_MAGIC: /* マジック番号 */
893
894#if (DEF_LCP_REMOTE_CFGS & LCP_CFG_MAGIC) == 0
895
896 code = PPP_CONFREJ;
897
898#else /* of #if (DEF_LCP_REMOTE_CFGS & LCP_CFG_MAGIC) == 0 */
899
900 /* CI 長が、ヘッダ + 4 オクテットでなければ REJ */
901 if (cilen != sizeof(T_PPP_CI_HDR) + sizeof(uint32_t))
902 code = PPP_CONFREJ;
903 else {
904 ntoahl(cilong, ap);
905
906 /* 番号が自分と同じなら NAK */
907 if (cilong == lcp_local_neg_cfg.magic) {
908 cilong = net_rand();
909 *np ++ = LCP_CIT_MAGIC;
910 *np ++ = sizeof(T_PPP_CI_HDR) + sizeof(uint32_t);
911 ahtonl(np, cilong);
912 np += sizeof(uint32_t);
913 code = PPP_CONFNAK;
914 }
915 else {
916 lcp_remote_neg_cfg.magic = cilong;
917 lcp_remote_neg_cfg.options |= LCP_CFG_MAGIC;
918 }
919 }
920
921#endif /* of #if (DEF_LCP_REMOTE_CFGS & LCP_CFG_MAGIC) == 0 */
922
923 break;
924
925#ifdef LCP_CFG_PAP
926 /* CHAP は実装
927予定 */
928
929 case LCP_CIT_AUTH: /* 認証プロトコル */
930
931 /* CI 長が、ヘッダ + 2 オクテットより短いときはエラー */
932 if (cilen < sizeof(T_PPP_CI_HDR) + sizeof(uint16_t))
933 code = PPP_CONFREJ;
934 else {
935 cishort = ntohs(*(uint16_t*)ap);
936
937 /* 認証プロトコルにより分岐する */
938 if (cishort == PPP_PAP &&
939 cilen == sizeof(T_PPP_CI_HDR) + sizeof(uint16_t) &&
940 (DEF_LCP_REMOTE_CFGS & LCP_CFG_PAP) != 0)
941 lcp_remote_neg_cfg.options |= LCP_CFG_PAP;
942 else
943 code = PPP_CONFREJ;
944 }
945 break;
946
947#endif /* of #ifdef LCP_CFG_PAP */
948
949#ifdef LCP_CFG_PCOMP
950
951 case LCP_CIT_PCOMP: /* プロトコル部圧縮は実装
952予定 */
953
954#if (DEF_LCP_REMOTE_CFGS & LCP_CFG_PCOMP) == 0
955
956 code = PPP_CONFREJ;
957
958#else /* of #if (DEF_LCP_REMOTE_CFGS & LCP_CFG_PCOMP) == 0 */
959
960 /* CI 長が、ヘッダ長だけでなければ REJ */
961 if (cilen != sizeof(T_PPP_CI_HDR))
962 code = PPP_CONFREJ;
963 else
964 lcp_remote_neg_cfg.options |= LCP_CFG_PCOMP;
965
966#endif /* of #if (DEF_LCP_REMOTE_CFGS & LCP_CFG_PCOMP) == 0 */
967
968 break;
969
970#endif /* of #ifdef LCP_CFG_PCOMP */
971
972#ifdef LCP_CFG_ACCOMP
973
974 case LCP_CIT_ACCOMP: /* アドレス・制御部圧縮 */
975
976#if (DEF_LCP_REMOTE_CFGS & LCP_CFG_ACCOMP) == 0
977
978 code = PPP_CONFREJ;
979
980#else /* of #if (DEF_LCP_REMOTE_CFGS & LCP_CFG_ACCOMP) == 0 */
981
982 /* CI 長が、ヘッダ長だけでなければ REJ */
983 if (cilen != sizeof(T_PPP_CI_HDR))
984 code = PPP_CONFREJ;
985 else
986 lcp_remote_neg_cfg.options |= LCP_CFG_ACCOMP;
987
988#endif /* of #if (DEF_LCP_REMOTE_CFGS & LCP_CFG_ACCOMP) == 0 */
989
990 break;
991
992#endif /* of #ifdef LCP_CFG_ACCOMP */
993
994 default:
995 syslog(LOG_WARNING, "[PPP/LCP] unexp opt: %d.", type);
996 code = PPP_CONFREJ;
997 break;
998 }
999endswitch:
1000 if (code == PPP_CONFNAK) {
1001 /* CI の型が Magic Number の場合を除いて、NAK の回数が */
1002 /* 最大値 MAX_PPP_FAILURES を超
1003えたら拒否する。 */
1004 if (fsm->failures >= MAX_PPP_FAILURES && type != LCP_CIT_MAGIC)
1005 code = PPP_CONFREJ;
1006 else if (final != PPP_CONFREJ)
1007 final = PPP_CONFNAK;
1008 }
1009
1010 /* この CI を拒否する */
1011 if (code == PPP_CONFREJ) {
1012 if (rp < cp) /* 前に詰める。*/
1013 memcpy(rp, cp, cilen);
1014 rp += cilen;
1015 final = PPP_CONFREJ;
1016 }
1017
1018 ap += cilen - sizeof(T_PPP_CI_HDR);
1019 len -= cilen - sizeof(T_PPP_CI_HDR);
1020 }
1021
1022 /* 最終的な長さを調整する。*/
1023 switch (final) {
1024 case PPP_CONFNAK:
1025 output->len = np - output->buf;
1026 memcpy(output->buf, input->buf, sizeof(T_PPP_HDR) + sizeof(T_PPP_CP_HDR));
1027 break;
1028 case PPP_CONFREJ:
1029 memcpy(output->buf, input->buf, output->len = rp - input->buf);
1030 break;
1031 case PPP_CONFACK:
1032 memcpy(output->buf, input->buf, input->len);
1033 break;
1034 }
1035 return final;
1036 }
1037
1038/*
1039 * lcp_up -- リンク接続を確立する (Phase: Establish に移行する)。
1040 */
1041
1042static void
1043lcp_up (T_PPP_FSM *fsm)
1044{
1045 /* 自構成情
1046報の設定 */
1047 lcp_local_ack_cfg = lcp_local_neg_cfg;
1048
1049 /* 相手の構成情
1050報の設定 */
1051 lcp_remote_ack_cfg = lcp_remote_neg_cfg;
1052
1053#if DEF_LCP_LOCAL_CFGS & LCP_CFG_MAGIC
1054
1055 echo_lowerup();
1056
1057#endif /* of #if DEF_LCP_LOCAL_CFGS & LCP_CFG_MAGIC */
1058
1059 link_established();
1060 }
1061
1062/*
1063 * lcp_starting -- 下位層を開始する。
1064 */
1065
1066static void
1067lcp_starting (T_PPP_FSM *fsm)
1068{
1069 link_required();
1070 }
1071
1072/*
1073 * lcp_extcode -- LCP 特有の CP を受信したときの処理
1074 */
1075
1076static bool_t
1077lcp_extcode (T_PPP_FSM *fsm, uint8_t code, uint8_t id, T_NET_BUF *input)
1078{
1079#if DEF_LCP_REMOTE_CFGS & LCP_CFG_MAGIC
1080
1081 T_NET_BUF *output;
1082
1083#endif /* of #if DEF_LCP_REMOTE_CFGS & LCP_CFG_MAGIC */
1084
1085 switch (code) {
1086 case PPP_PROTREJ:
1087 lcp_rprotrej(fsm, input);
1088 break;
1089
1090 case PPP_ECHOREQ:
1091
1092#if DEF_LCP_REMOTE_CFGS & LCP_CFG_MAGIC
1093
1094 if (fsm->state == PPP_FSM_OPENED) {
1095 syscall(get_net_buf(&output, sizeof(T_PPP_HDR)
1096 + sizeof(T_PPP_CP_HDR)
1097 + sizeof(uint32_t)));
1098 *(uint32_t*)(output->buf + sizeof(T_PPP_HDR)
1099 + sizeof(T_PPP_CP_HDR)) = lcp_local_ack_cfg.magic;
1100 IF_SET_PROTO(output, PPP_LCP);
1101 ppp_cp_output(PPP_ECHOREP, id, output);
1102 }
1103
1104#endif /* of #if DEF_LCP_REMOTE_CFGS & LCP_CFG_MAGIC */
1105
1106 break;
1107
1108 case PPP_ECHOREP:
1109
1110#if DEF_LCP_LOCAL_CFGS & LCP_CFG_MAGIC
1111
1112 recv_echo_rep(fsm, id, input);
1113
1114#endif /* of #if DEF_LCP_LOCAL_CFGS & LCP_CFG_MAGIC */
1115
1116 break;
1117
1118 case PPP_DISCREQ:
1119 break;
1120
1121 default:
1122 return false;
1123 break;
1124
1125 }
1126 return true;
1127 }
1128
1129/*
1130 * lcp_rprotrej -- Proto-REJ を受信したときの処理
1131 */
1132
1133static void
1134lcp_rprotrej (T_PPP_FSM *fsm, T_NET_BUF *input)
1135{
1136 T_PPP_PROTENT *entry;
1137 int_t ix;
1138 uint16_t proto;
1139
1140 if (input->len < sizeof(uint16_t)) {
1141 syslog(LOG_WARNING, "[PPP/LCP] bad len: %d in recv Proto-REJ.");
1142 return;
1143 }
1144
1145 proto = ntohs(*GET_PPP_HDR(input));
1146
1147 if (fsm->state != PPP_FSM_OPENED) {
1148 return;
1149 }
1150
1151 /* 上位プロトコルを初期化する */
1152 for (ix = 0; (entry = protocols[ix]) != NULL; ix ++)
1153 if (entry->proto == proto) {
1154 (*entry->protrej)();
1155 return;
1156 }
1157
1158 syslog(LOG_WARNING, "[PPP/LCP] unexp proto: %d in recv Proto-REJ.", proto);
1159 }
1160
1161/*
1162 * lcp_protrej -- Proto-REJ を受信したときの処理
1163 */
1164
1165static void
1166lcp_protrej (void)
1167{
1168 fsm_protreject(&lcp_fsm);
1169 }
1170
1171/*
1172 * lcp_lowerup -- LCP 下位層を起動する。
1173 */
1174
1175void
1176lcp_lowerup (void)
1177{
1178 fsm_lowerup(&lcp_fsm);
1179 }
1180
1181/*
1182 * lcp_lowerdown -- LCP 下位層を停止する。
1183 */
1184
1185void
1186lcp_lowerdown (void)
1187{
1188 fsm_lowerdown(&lcp_fsm);
1189 }
1190
1191/*
1192 * lcp_open -- LCP のオープ
1193 */
1194
1195void
1196lcp_open (uint8_t open_mode)
1197{
1198 ppp_open_mode = open_mode; /* オープン時の動作モード */
1199 fsm_open(&lcp_fsm);
1200 }
1201
1202/*
1203 * lcp_close -- LCP のクローズ
1204 */
1205
1206void
1207lcp_close (void)
1208{
1209 if (ppp_phase != PPP_PHASE_DEAD)
1210 ppp_phase = PPP_PHASE_TERMINATE;
1211
1212 if (ppp_open_mode == PPP_OPEN_PASSIVE && lcp_fsm.state == PPP_FSM_STOPPED) {
1213 lcp_fsm.state = PPP_FSM_CLOSED;
1214 lcp_finished(&lcp_fsm);
1215 }
1216 else
1217 fsm_close(&lcp_fsm);
1218 }
1219
1220/*
1221 * lcp_sprotrej -- 認識できないプロトコルが送られてきたときの処理
1222 */
1223
1224void
1225lcp_sprotrej (T_NET_BUF *input)
1226{
1227 T_NET_BUF *output;
1228 /*
1229 * Protocol-Reject を送り返す。
1230 */
1231
1232 syscall(get_net_buf(&output, input->len + sizeof(T_PPP_HDR) + sizeof(T_PPP_CP_HDR)));
1233
1234 memcpy(output->buf, input->buf, sizeof(T_PPP_HDR) + sizeof(T_PPP_CP_HDR));
1235 memcpy(output->buf + sizeof(T_PPP_HDR) + sizeof(T_PPP_CP_HDR), input->buf, input->len);
1236
1237 IF_SET_PROTO(output, PPP_LCP);
1238 ppp_cp_output(PPP_PROTREJ, ++ lcp_fsm.id, output);
1239 }
1240
1241/*
1242 * lcp_down -- リンク接続を解放する (Phase: Dead に移行する)。
1243 */
1244
1245void
1246lcp_down (T_PPP_FSM *fsm)
1247{
1248
1249#if DEF_LCP_LOCAL_CFGS & LCP_CFG_MAGIC
1250
1251 echo_lowerdown();
1252
1253#endif /* of #if DEF_LCP_LOCAL_CFGS & LCP_CFG_MAGIC */
1254
1255 link_down();
1256 }
1257
1258/*
1259 * lcp_finished -- 下位層を終了する。
1260 */
1261
1262void
1263lcp_finished (T_PPP_FSM *fsm)
1264{
1265 link_terminated();
1266 }
1267
1268#if DEF_LCP_LOCAL_CFGS & LCP_CFG_MAGIC
1269
1270/*
1271 * recv_echo_rep -- ECHOREP を受信したときの処理
1272 */
1273
1274static void
1275recv_echo_rep(T_PPP_FSM *fsm, uint8_t id, T_NET_BUF *input)
1276{
1277 T_PPP_CP_HDR *hdr;
1278 uint32_t magic;
1279
1280 hdr = GET_PPP_CP_HDR(input);
1281
1282 /* Magic Number の長さ以下ならエラー */
1283 if (hdr->len < sizeof(T_PPP_CP_HDR) + sizeof(uint32_t)) {
1284 syslog(LOG_WARNING, "[PPP/LCP] bad ECHOREP len: %d.", hdr->len);
1285 return;
1286 }
1287
1288 ntoahl(magic, input->buf + sizeof(T_PPP_HDR) + sizeof(T_PPP_CP_HDR));
1289
1290 /* 受信した Magic Number が自分と同じならループしている。*/
1291 if ((lcp_local_ack_cfg.options & LCP_CFG_MAGIC) && magic == lcp_local_ack_cfg.magic) {
1292 syslog(LOG_WARNING, "[PPP/LCP] ECHOREP looped.");
1293 return;
1294 }
1295
1296 echo_pending = 0;
1297 }
1298
1299/*
1300 * echo_timeout -- ECHO REQ/REP のタイムアウト処理
1301 */
1302
1303static void
1304echo_timeout (void *arg)
1305{
1306 if (timer_running) {
1307 timer_running = false;
1308 send_echo_req((T_PPP_FSM *)arg);
1309 }
1310 }
1311
1312/*
1313 * send_echo_req -- ECHO REQ を送信する。
1314 */
1315
1316static void
1317send_echo_req (T_PPP_FSM *fsm)
1318{
1319 T_NET_BUF *input;
1320
1321#if LCP_ECHO_FAILS > 0
1322
1323 if (echo_pending >= LCP_ECHO_FAILS) {
1324 syslog(LOG_WARNING, "[PPP/LCP] no reply to ECHOREQ.");
1325 lcp_close();
1326 echo_pending = 0;
1327 }
1328
1329#endif /* of #if LCP_ECHO_FAILS > 0 */
1330
1331 if (fsm->state == PPP_FSM_OPENED) {
1332
1333 /* ECHOREQ を送信する。*/
1334 syscall(get_net_buf(&input, sizeof(T_PPP_HDR) + sizeof(T_PPP_CP_HDR) + sizeof(uint32_t)));
1335 *(uint32_t*)(input->buf + sizeof(T_PPP_HDR) + sizeof(T_PPP_CP_HDR)) = lcp_local_ack_cfg.magic;
1336 IF_SET_PROTO(input, PPP_LCP);
1337 ppp_cp_output(PPP_ECHOREQ, echo_number ++, input);
1338 echo_pending ++;
1339
1340 /* タイマーをスタートする。*/
1341 timeout((FP)echo_timeout, fsm, LCP_ECHO_INTERVAL);
1342 timer_running = true;
1343 }
1344 }
1345
1346/*
1347 * echo_lowerup -- ECHO REQ/REP の起動
1348 */
1349
1350static void
1351echo_lowerup (void)
1352{
1353 echo_pending = 0;
1354 echo_number = 0;
1355 timer_running = false;
1356
1357 send_echo_req(&lcp_fsm);
1358 }
1359
1360/*
1361 * echo_lowerdown -- ECHO REQ/REP の停止
1362 */
1363
1364static void
1365echo_lowerdown (void)
1366{
1367 if (timer_running) {
1368 untimeout((FP)echo_timeout, &lcp_fsm);
1369 timer_running = false;
1370 }
1371 }
1372
1373#endif /* of #if DEF_LCP_LOCAL_CFGS & LCP_CFG_MAGIC */
1374
1375#endif /* fo #ifdef SUPPORT_PPP */
Note: See TracBrowser for help on using the repository browser.