source: EcnlProtoTool/trunk/asp3_dcre/tinet/net/ppp_fsm.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: 20.8 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 * fsm->c - {Link, IP} Control Protocol Finite State Machine.
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 Finite State Machine for LCP/IPCP
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/fsm->c,v 1.52.2.3 2000/08/19 09:30:03 brian Exp $
73 *
74 * TODO:
75 */
76
77#include <string.h>
78
79#include <s_services.h>
80#include <t_services.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_timer.h>
89#include <net/net_buf.h>
90#include <net/net_count.h>
91#include <net/ppp.h>
92#include <net/ppp_var.h>
93#include <net/ppp_hdlc.h>
94#include <net/ppp_fsm.h>
95
96#include <netinet/in.h>
97
98#ifdef SUPPORT_PPP
99
100/*
101 * 全域変数
102 */
103
104uint8_t ppp_open_mode = PPP_OPEN_PASSIVE; /* オープン時の動作モード */
105
106/*
107 * 関数
108 */
109
110static void fsm_sconfreq (T_PPP_FSM *fsm, int_t retansmit);
111static void fsm_rconfreq (T_PPP_FSM *fsm, uint8_t id, T_NET_BUF *input);
112static void fsm_rconfack (T_PPP_FSM *fsm, uint8_t id, T_NET_BUF *input);
113static void fsm_rconfnakrej (T_PPP_FSM *fsm, uint8_t code, uint8_t id, T_NET_BUF *input);
114static void fsm_rtermreq (T_PPP_FSM *fsm, uint8_t id, T_NET_BUF *input);
115static void fsm_rtermack (T_PPP_FSM *fsm, T_NET_BUF *input);
116static void fsm_rcoderej (T_PPP_FSM *fsm, T_NET_BUF *input);
117static void fsm_stermreq (T_PPP_FSM *fsm, uint8_t id);
118static void fsm_timeout (void *arg);
119
120/*
121 * fsm_sconfreq -- Configure-Request を送信する。
122 */
123
124static void
125fsm_sconfreq (T_PPP_FSM *fsm, int_t retransmit)
126{
127 T_NET_BUF *output;
128 uint16_t len;
129
130 if (!(fsm->state == PPP_FSM_REQSENT ||
131 fsm->state == PPP_FSM_ACKRCVD ||
132 fsm->state == PPP_FSM_ACKSENT)) {
133 /* まだネゴをしていない。オプションをリセットする。 */
134 if (fsm->callbacks->resetci)
135 (*fsm->callbacks->resetci)(fsm);
136 fsm->failures = 0;
137 }
138 if (retransmit == 0) {
139 /* 新しいリクエスト。再送カウンタをリセットし、新しい ID を設定する。 */
140 fsm->retrans = MAX_PPP_CONFIGURES;
141 fsm->reqid = ++ fsm->id;
142 }
143
144 fsm->seen_ack = 0;
145
146 if (fsm->callbacks->cilen && fsm->callbacks->addci) {
147 /* 構成情報パケットを作る。 */
148 len = (*fsm->callbacks->cilen)(fsm);
149
150 syscall(get_net_buf(&output, len + sizeof(T_PPP_HDR) + sizeof(T_PPP_CP_HDR)));
151 (*fsm->callbacks->addci)(fsm, output);
152
153 /* 構成情報パケットを送信する。 */
154 IF_SET_PROTO(output, fsm->proto);
155 ppp_cp_output(PPP_CONFREQ, fsm->reqid, output);
156
157 -- fsm->retrans;
158 timeout((FP)fsm_timeout, fsm, DEF_PPP_TIMEOUT);
159 }
160 }
161
162/*
163 * fsm_rconfreq -- Configure-Request を受信したときの処理
164 */
165
166static void
167fsm_rconfreq (T_PPP_FSM *fsm, uint8_t id, T_NET_BUF *input)
168{
169 T_NET_BUF *output;
170 uint16_t code;
171
172 switch (fsm->state) {
173 case PPP_FSM_CLOSED:
174 syscall(get_net_buf(&output, sizeof(T_PPP_HDR) + sizeof(T_PPP_CP_HDR)));
175 memcpy(output->buf, input->buf, sizeof(T_PPP_HDR) + sizeof(T_PPP_CP_HDR));
176 ppp_cp_output(PPP_TERMACK, id, output);
177 return;
178 break;
179
180 case PPP_FSM_CLOSING:
181 case PPP_FSM_STOPPING:
182 return;
183 break;
184
185 case PPP_FSM_OPENED:
186 /* 上位層を停止して、ネゴに移る。 */
187 if (fsm->callbacks->down != NULL)
188 (*fsm->callbacks->down)(fsm);
189 fsm_sconfreq(fsm, 0); /* 最初の Configure-Request を送る。 */
190 break;
191
192 case PPP_FSM_STOPPED:
193 /* 相手からネゴが開始された */
194 fsm_sconfreq(fsm, 0); /* 最初の Configure-Request を送る。 */
195 fsm->state = PPP_FSM_REQSENT;
196 break;
197
198 }
199
200 syscall(get_net_buf(&output, input->len));
201
202 /* 上位プロトコルに要求された Configure-Request を送る。 */
203 if (fsm->callbacks->reqci != NULL) /* 構成情報をチェックする。 */
204 code = (*fsm->callbacks->reqci)(fsm, input, output);
205 else if (output->len > sizeof(T_PPP_HDR) + sizeof(T_PPP_CP_HDR))
206 code = PPP_CONFREJ;
207 else
208 code = PPP_CONFACK;
209
210 /* 相手に ACK, NAK または REJ を送信する。 */
211 ppp_cp_output(code, id, output);
212
213 if (code == PPP_CONFACK) {
214 if (fsm->state == PPP_FSM_ACKRCVD) {
215 untimeout((FP)fsm_timeout, fsm);
216 fsm->state = PPP_FSM_OPENED;
217 if (fsm->callbacks->up != NULL)
218 (*fsm->callbacks->up)(fsm);
219 }
220 else
221 fsm->state = PPP_FSM_ACKSENT;
222 fsm->failures = 0;
223 }
224 else {
225 /* ACK か REJ を送る */
226 if (fsm->state != PPP_FSM_ACKRCVD)
227 fsm->state = PPP_FSM_REQSENT;
228 if (code == PPP_CONFNAK)
229 fsm->failures ++;
230 }
231 }
232
233/*
234 * fsm_rconfnakrej -- Configure-NAK/REJ を受信したときの処理
235 */
236
237static void
238fsm_rconfnakrej (T_PPP_FSM *fsm, uint8_t code, uint8_t id, T_NET_BUF *input)
239{
240 int_t ret = 0;
241 T_NET_BUF *output;
242
243 /* 予期した ID でないか、NAK/REJ を予期していないときは終了する。*/
244 if (id != fsm->reqid || fsm->seen_ack) {
245 syslog(LOG_WARNING, "[PPP/FSM] bad ID or unexp NAK/REJ.");
246 return;
247 }
248
249 if (code == PPP_CONFNAK) {
250 if (fsm->callbacks->nakci != NULL && (ret = (*fsm->callbacks->nakci)(fsm, input)) == 0) {
251 syslog(LOG_WARNING, "[PPP/FSM] bad NAK.");
252 return;
253 }
254 }
255 else {
256 if (fsm->callbacks->rejci != NULL && (ret = (*fsm->callbacks->rejci)(fsm, input)) == 0) {
257 syslog(LOG_WARNING, "[PPP/FSM] bad REJ.");
258 return;
259 }
260 }
261
262 fsm->seen_ack = 1;
263
264 switch (fsm->state) {
265 case PPP_FSM_CLOSED:
266 case PPP_FSM_STOPPED:
267 syscall(get_net_buf(&output, sizeof(T_PPP_HDR) + sizeof(T_PPP_CP_HDR)));
268 memcpy(output->buf, input->buf, sizeof(T_PPP_HDR) + sizeof(T_PPP_CP_HDR));
269 ppp_cp_output(PPP_TERMACK, id, output);
270 return;
271 break;
272
273 case PPP_FSM_REQSENT:
274 case PPP_FSM_ACKSENT:
275 untimeout((FP)fsm_timeout, fsm);
276 if (ret < 0) /* 送信した Conf-Req が破損し空の NAK/REJ が届いた。*/
277 fsm->state = PPP_FSM_STOPPED;
278 else
279 fsm_sconfreq(fsm, 0);
280 break;
281
282 case PPP_FSM_ACKRCVD:
283 untimeout((FP)fsm_timeout, fsm);
284 fsm_sconfreq(fsm, 0);
285 fsm->state = PPP_FSM_REQSENT;
286 break;
287
288 case PPP_FSM_OPENED:
289 /* 再起動し、ネゴをやり直す。*/
290 if (fsm->callbacks->down != NULL)
291 (*fsm->callbacks->down)(fsm);
292 fsm_sconfreq(fsm, 0);
293 fsm->state = PPP_FSM_REQSENT;
294 break;
295 }
296 }
297
298/*
299 * fsm_rconfack -- Configure-ACK を受信したときの処理
300 */
301
302static void
303fsm_rconfack (T_PPP_FSM *fsm, uint8_t id, T_NET_BUF *input)
304{
305 T_NET_BUF *output;
306
307 /* 予期した ID でないか、ACK を予期していないときは終了する。*/
308 if (id != fsm->reqid || fsm->seen_ack) {
309 syslog(LOG_WARNING, "[PPP/FSM] bad ID or unexp ACK.");
310 return;
311 }
312
313 if (fsm->callbacks->ackci != NULL) {
314 if ((*fsm->callbacks->ackci)(fsm, input) != true) {
315 syslog(LOG_WARNING, "[PPP/FSM] bad ACK.");
316 return;
317 }
318 }
319 else if (input->len - (sizeof(T_PPP_HDR) + sizeof(T_PPP_CP_HDR)) != 0) {
320 syslog(LOG_WARNING, "[PPP/FSM] bad ACK.");
321 return;
322 }
323
324 fsm->seen_ack = 1;
325
326 switch (fsm->state) {
327 case PPP_FSM_CLOSED:
328 case PPP_FSM_STOPPED:
329 syscall(get_net_buf(&output, sizeof(T_PPP_HDR) + sizeof(T_PPP_CP_HDR)));
330 memcpy(output->buf, input->buf, sizeof(T_PPP_HDR) + sizeof(T_PPP_CP_HDR));
331 ppp_cp_output(PPP_TERMACK, id, output);
332 break;
333
334 case PPP_FSM_REQSENT:
335 fsm->state = PPP_FSM_ACKRCVD;
336 fsm->retrans = MAX_PPP_CONFIGURES;
337 break;
338
339 case PPP_FSM_ACKRCVD:
340 untimeout((FP)fsm_timeout, fsm);
341 fsm_sconfreq(fsm, 0);
342 fsm->state = PPP_FSM_REQSENT;
343 break;
344
345 case PPP_FSM_ACKSENT:
346 untimeout((FP)fsm_timeout, fsm);
347 fsm->state = PPP_FSM_OPENED;
348 fsm->retrans = MAX_PPP_CONFIGURES;
349 if (fsm->callbacks->up != NULL)
350 (*fsm->callbacks->up)(fsm);
351 break;
352
353 case PPP_FSM_OPENED:
354 /* 再起動し、ネゴをやり直す。*/
355 if (fsm->callbacks->down != NULL)
356 (*fsm->callbacks->down)(fsm);
357 fsm_sconfreq(fsm, 0);
358 fsm->state = PPP_FSM_REQSENT;
359 break;
360
361 default :
362 syslog(LOG_WARNING, "[PPP/FSM] unexp state: %d in recv Conf-ACK.", fsm->state);
363 break;
364 }
365
366 }
367
368/*
369 * fsm_rtermreq -- Terminate-Request を受信したときの処理
370 */
371
372static void
373fsm_rtermreq (T_PPP_FSM *fsm, uint8_t id, T_NET_BUF *input)
374{
375 T_NET_BUF *output;
376
377 switch (fsm->state) {
378 case PPP_FSM_ACKRCVD:
379 case PPP_FSM_ACKSENT:
380 fsm->state = PPP_FSM_REQSENT;
381 break;
382
383 case PPP_FSM_OPENED:
384 if (fsm->callbacks->down != NULL)
385 (*fsm->callbacks->down)(fsm);
386 fsm->retrans = 0;
387 fsm->state = PPP_FSM_STOPPING;
388 timeout((FP)fsm_timeout, fsm, DEF_PPP_TIMEOUT);
389 break;
390 }
391 syscall(get_net_buf(&output, sizeof(T_PPP_HDR) + sizeof(T_PPP_CP_HDR)));
392 memcpy(output->buf, input->buf, sizeof(T_PPP_HDR) + sizeof(T_PPP_CP_HDR));
393 ppp_cp_output(PPP_TERMACK, id, output);
394 }
395
396/*
397 * fsm_rtermack -- Terminate-ACK を受信したときの処理
398 */
399
400static void
401fsm_rtermack (T_PPP_FSM *fsm, T_NET_BUF *input)
402{
403 switch (fsm->state) {
404 case PPP_FSM_CLOSING:
405 untimeout((FP)fsm_timeout, fsm);
406#if 0 /* 本来の動作は CLOSED に遷移する。*/
407 fsm->state = PPP_FSM_CLOSED;
408#else /* of #if 0 */
409 fsm->state = PPP_FSM_STOPPED;
410#endif /* of #if 0 */
411 if (fsm->callbacks->finished != NULL)
412 (*fsm->callbacks->finished)(fsm);
413 break;
414
415 case PPP_FSM_STOPPING:
416 untimeout((FP)fsm_timeout, fsm);
417 fsm->state = PPP_FSM_STOPPED;
418 if (fsm->callbacks->finished != NULL)
419 (*fsm->callbacks->finished)(fsm);
420 break;
421
422 case PPP_FSM_ACKRCVD:
423 fsm->state = PPP_FSM_REQSENT;
424 break;
425
426 case PPP_FSM_OPENED:
427 if (fsm->callbacks->down != NULL)
428 (*fsm->callbacks->down)(fsm);
429 fsm_sconfreq(fsm, 0);
430 break;
431 }
432 }
433
434/*
435 * fsm_rcoderej -- Code-REJ を受信したときの処理
436 */
437
438static void
439fsm_rcoderej (T_PPP_FSM *fsm, T_NET_BUF *input)
440{
441 T_PPP_CP_HDR *hdr;
442
443 /* PPP リンク制御 (CP) ヘッダより短ければエラー */
444 if (input->len < sizeof(T_PPP_HDR) + sizeof(T_PPP_CP_HDR)) {
445 syslog(LOG_WARNING, "[PPP/FSM] bad len: %d in recv Code-REJ.", input->len);
446 return;
447 }
448
449 hdr = GET_PPP_CP_HDR(input);
450
451 syslog(LOG_WARNING, "[PPP/FSM] recv Code-REJ, code=%d, id=%d.", hdr->code, hdr->id);
452
453 if (fsm->state == PPP_FSM_ACKRCVD)
454 fsm->state = PPP_FSM_REQSENT;
455 }
456
457/*
458 * fsm_timeout -- タイムアウト処理
459 */
460
461static void
462fsm_timeout (void *arg)
463{
464 T_PPP_FSM *fsm = (T_PPP_FSM*)arg;
465
466 switch (fsm->state) {
467 case PPP_FSM_CLOSING:
468 case PPP_FSM_STOPPING:
469 if (fsm->retrans <= 0) {
470 /* 最大再送回数を超えたときの処理 */
471#if 0 /* 本来の動作は CLOSED に遷移する。*/
472 fsm->state = (fsm->state == PPP_FSM_CLOSING) ? PPP_FSM_CLOSED : PPP_FSM_STOPPED;
473#else /* of #if 0 */
474 fsm->state = PPP_FSM_STOPPED;
475#endif /* of #if 0 */
476 if (fsm->callbacks->finished != NULL)
477 (*fsm->callbacks->finished)(fsm);
478 }
479 else {
480 /* Terminate-Request を送信する。*/
481 fsm_stermreq(fsm, ++ fsm->id);
482 }
483 break;
484 case PPP_FSM_REQSENT:
485 case PPP_FSM_ACKRCVD:
486 case PPP_FSM_ACKSENT:
487 if (fsm->retrans <= 0) {
488 /* 最大再送回数を超えたときの処理 */
489 syslog(LOG_WARNING, "[PPP/FSM] retrans Conf-Req.");
490 fsm->state = PPP_FSM_STOPPED;
491 if (ppp_open_mode != PPP_OPEN_PASSIVE && fsm->callbacks->finished)
492 (*fsm->callbacks->finished)(fsm);
493 }
494 else {
495 /* Configure-Request を再送する。*/
496 if (fsm->callbacks->retrans != NULL)
497 (*fsm->callbacks->retrans)(fsm);
498 fsm_sconfreq(fsm, 1);
499 if (fsm->state == PPP_FSM_ACKRCVD)
500 fsm->state = PPP_FSM_REQSENT;
501 }
502
503 break;
504
505 default :
506 syslog(LOG_WARNING, "[PPP/FSM] unexp state: %d in timeout.", fsm->state);
507 break;
508 }
509 }
510
511/*
512 * fsm_stermreq -- Terminate-Request を送信する。
513 */
514
515static void
516fsm_stermreq (T_PPP_FSM *fsm, uint8_t id)
517{
518 T_NET_BUF *input;
519
520 syscall(get_net_buf(&input, sizeof(T_PPP_HDR) + sizeof(T_PPP_CP_HDR)));
521 IF_SET_PROTO(input, fsm->proto);
522 ppp_cp_output(PPP_TERMREQ, id, input);
523
524 timeout((FP)fsm_timeout, fsm, DEF_PPP_TIMEOUT);
525 fsm->retrans --;
526 }
527
528/*
529 * fsm_init -- FSM モジュールの初期化
530 */
531
532void
533fsm_init (T_PPP_FSM *fsm)
534{
535 fsm->state = PPP_FSM_INITIAL;
536 fsm->id = 0;
537 }
538
539/*
540 * fsm_lowerup -- FSM 下位層を起動する。
541 */
542
543void
544fsm_lowerup (T_PPP_FSM *fsm)
545{
546 switch (fsm->state) {
547 case PPP_FSM_INITIAL:
548 fsm->state = PPP_FSM_CLOSED;
549 break;
550
551 case PPP_FSM_STARTING:
552 if (ppp_open_mode == PPP_OPEN_PASSIVE)
553 fsm->state = PPP_FSM_STOPPED;
554 else {
555 fsm_sconfreq(fsm, 0);
556 fsm->state = PPP_FSM_REQSENT;
557 }
558 break;
559
560 default :
561 syslog(LOG_WARNING, "[PPP/FSM] unexp state: %d in lowerup", fsm->state);
562 break;
563 }
564 }
565
566/*
567 * fsm_lowerdown -- FSM 下位層を停止する。
568 */
569
570void
571fsm_lowerdown (T_PPP_FSM *fsm)
572{
573 switch (fsm->state) {
574 case PPP_FSM_CLOSED:
575 fsm->state = PPP_FSM_INITIAL;
576 break;
577
578 case PPP_FSM_STOPPED:
579 fsm->state = PPP_FSM_STARTING;
580 if (fsm->callbacks->starting != NULL)
581 (*fsm->callbacks->starting)(fsm);
582 break;
583
584 case PPP_FSM_CLOSING:
585 fsm->state = PPP_FSM_INITIAL;
586 untimeout((FP)fsm_timeout, fsm);
587 break;
588
589 case PPP_FSM_STOPPING:
590 case PPP_FSM_REQSENT:
591 case PPP_FSM_ACKRCVD:
592 case PPP_FSM_ACKSENT:
593 fsm->state = PPP_FSM_STARTING;
594 untimeout((FP)fsm_timeout, fsm);
595 break;
596
597 case PPP_FSM_OPENED:
598 if (fsm->callbacks->down != NULL)
599 (*fsm->callbacks->down)(fsm);
600 fsm->state = PPP_FSM_STARTING;
601 break;
602
603 default :
604 syslog(LOG_WARNING, "[PPP/FSM] unexp state: %d in lowerdown", fsm->state);
605 break;
606 }
607 }
608
609/*
610 * fsm_open -- FSM のオープン
611 */
612
613void
614fsm_open (T_PPP_FSM *fsm)
615{
616 switch (fsm->state) {
617 case PPP_FSM_INITIAL:
618 fsm->state = PPP_FSM_STARTING;
619 if (fsm->callbacks->starting != NULL)
620 (*fsm->callbacks->starting)(fsm);
621 break;
622
623 case PPP_FSM_CLOSED:
624 if (ppp_open_mode == PPP_OPEN_PASSIVE)
625 fsm->state = PPP_FSM_STOPPED;
626 else {
627 fsm_sconfreq(fsm, 0);
628 fsm->state = PPP_FSM_REQSENT;
629 }
630 break;
631
632 case PPP_FSM_CLOSING:
633 fsm->state = PPP_FSM_STOPPING;
634 /* nobreak; 下に落ちる */
635
636 case PPP_FSM_STOPPED:
637 case PPP_FSM_OPENED:
638 fsm_lowerdown(fsm);
639 fsm_lowerup(fsm);
640 break;
641 }
642 }
643
644/*
645 * fsm_close -- リンクの切断を開始する。
646 */
647
648void
649fsm_close (T_PPP_FSM *fsm)
650{
651 switch (fsm->state) {
652 case PPP_FSM_STARTING:
653 fsm->state = PPP_FSM_INITIAL;
654 break;
655
656#if 0 /* 本来の動作は CLOSED に遷移する。*/
657 case PPP_FSM_STOPPED:
658 fsm->state = PPP_FSM_CLOSED;
659 break;
660#endif /* of #if 0 */
661
662 case PPP_FSM_STOPPING:
663 fsm->state = PPP_FSM_CLOSING;
664 break;
665
666 case PPP_FSM_REQSENT:
667 case PPP_FSM_ACKRCVD:
668 case PPP_FSM_ACKSENT:
669 case PPP_FSM_OPENED:
670 if (fsm->state != PPP_FSM_OPENED)
671 untimeout((FP)fsm_timeout, fsm);
672 else if (fsm->callbacks->down != NULL)
673 (*fsm->callbacks->down)(fsm);
674
675 /* タイムアウトを設定し、Terminate-Request を送信する。*/
676 fsm->retrans = MAX_PPP_TERMINATES;
677 fsm_stermreq(fsm, fsm->reqid = ++ fsm->id);
678 fsm->state = PPP_FSM_CLOSING;
679 break;
680 }
681 }
682
683/*
684 * fsm_input -- 入力、PPP リンク制御 (CP) の制御コードにより適当な関数を呼出す
685 */
686
687void
688fsm_input (T_PPP_FSM *fsm, T_NET_BUF *input)
689{
690 T_PPP_CP_HDR *hdr;
691 T_NET_BUF *output;
692
693 /* PPP リンク制御 (CP) ヘッダより短ければエラー */
694 if (input->len < (sizeof(T_PPP_HDR) + sizeof(T_PPP_CP_HDR))) {
695 syslog(LOG_WARNING, "[PPP/FSM] short hdr: %d.", input->len);
696 return;
697 }
698
699 hdr = GET_PPP_CP_HDR(input);
700
701 /* ヘッダの長さと入力データサイズが一致しなければエラー */
702 if (hdr->len != input->len - sizeof(T_PPP_HDR)) {
703 syslog(LOG_WARNING, "[PPP/FSM] bad len: %d.", hdr->len);
704 return;
705 }
706
707 /* 状態が INITIAL か STARTING ならエラー */
708 if (fsm->state == PPP_FSM_INITIAL || fsm->state == PPP_FSM_STARTING) {
709 syslog(LOG_WARNING, "[PPP/FSM] unexp state: %d in input.", fsm->state);
710 return;
711 }
712
713 /*
714 * 制御コードにより適当な関数を呼出す
715 */
716
717 switch (hdr->code) {
718 case PPP_CONFREQ:
719 fsm_rconfreq(fsm, hdr->id, input);
720 break;
721
722 case PPP_CONFACK:
723 fsm_rconfack(fsm, hdr->id, input);
724 break;
725
726 case PPP_CONFNAK:
727 case PPP_CONFREJ:
728 fsm_rconfnakrej(fsm, hdr->code, hdr->id, input);
729 break;
730
731 case PPP_TERMREQ:
732 fsm_rtermreq(fsm, hdr->id, input);
733 break;
734
735 case PPP_TERMACK:
736 fsm_rtermack(fsm, input);
737 break;
738
739 case PPP_CODEREJ:
740 fsm_rcoderej(fsm, input);
741 break;
742
743 default:
744 if (fsm->callbacks->extcode == NULL ||
745 (*fsm->callbacks->extcode)(fsm, hdr->code, hdr->id, input) != true) {
746 syscall(get_net_buf(&output, sizeof(T_PPP_HDR) + sizeof(T_PPP_CP_HDR)));
747 memcpy(output->buf, input->buf, sizeof(T_PPP_HDR) + sizeof(T_PPP_CP_HDR));
748 ppp_cp_output(PPP_CODEREJ, ++ fsm->id, output);
749 }
750 break;
751 }
752 }
753
754/*
755 * fsm_protoreject -- Proto-REJ を受信したときの処理
756 */
757
758void
759fsm_protreject (T_PPP_FSM *fsm)
760{
761 switch (fsm->state) {
762 case PPP_FSM_CLOSING:
763 untimeout((FP)fsm_timeout, fsm);
764
765#if 0 /* 本来の動作は CLOSED に遷移する。*/
766 /* 下に落ちる */
767#else /* of #if 0 */
768 fsm->state = PPP_FSM_STOPPED;
769 if (fsm->callbacks->finished != NULL)
770 (*fsm->callbacks->finished)(fsm);
771 break;
772#endif /* of #if 0 */
773
774 case PPP_FSM_CLOSED:
775 fsm->state = PPP_FSM_CLOSED;
776 if (fsm->callbacks->finished != NULL)
777 (*fsm->callbacks->finished)(fsm);
778 break;
779
780 case PPP_FSM_STOPPING:
781 case PPP_FSM_REQSENT:
782 case PPP_FSM_ACKRCVD:
783 case PPP_FSM_ACKSENT:
784 untimeout((FP)fsm_timeout, fsm);
785 /* 下に落ちる */
786
787 case PPP_FSM_STOPPED:
788 fsm->state = PPP_FSM_STOPPED;
789 if (fsm->callbacks->finished != NULL)
790 (*fsm->callbacks->finished)(fsm);
791 break;
792
793 case PPP_FSM_OPENED:
794 if (fsm->callbacks->down != NULL)
795 (*fsm->callbacks->down)(fsm);
796
797 /* タイムアウトを設定し、Terminate-Request を送信する。*/
798 fsm->retrans = MAX_PPP_TERMINATES;
799 fsm_stermreq(fsm, fsm->reqid = ++ fsm->id);
800 fsm->state = PPP_FSM_STOPPING;
801 break;
802
803 }
804 }
805
806#endif /* fo #ifdef SUPPORT_PPP */
Note: See TracBrowser for help on using the repository browser.