source: azure_iot_hub/trunk/asp3_dcre/tinet/net/ppp_lcp.c@ 389

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