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

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

文字コードを設定

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