source: asp3_tinet_ecnl_rx/trunk/asp3_dcre/tinet/net/ppp_fsm.c@ 337

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

ASP3版ECNLを追加

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