source: EcnlProtoTool/trunk/asp3_dcre/tinet/net/ppp_lcp.c@ 270

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

mruby版ECNLプロトタイピング・ツールを追加

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