source: asp3_tinet_ecnl_rx/trunk/asp3_dcre/tinet/net/ppp.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: 11.5 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 * Copyright (c) 1989 Carnegie Mellon University.
36 * All rights reserved.
37 *
38 * Redistribution and use in source and binary forms are permitted
39 * provided that the above copyright notice and this paragraph are
40 * duplicated in all such forms and that any documentation,
41 * advertising materials, and other materials related to such
42 * distribution and use acknowledge that the software was developed
43 * by Carnegie Mellon University. The name of the
44 * University may not be used to endorse or promote products derived
45 * from this software without specific prior written permission.
46 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
47 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
48 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
49 */
50
51/*
52 * Written by Toshiharu OHNO (tony-o@iij.ad.jp)
53 *
54 * Copyright (C) 1993, Internet Initiative Japan, Inc. All rights reserverd.
55 *
56 * Redistribution and use in source and binary forms are permitted
57 * provided that the above copyright notice and this paragraph are
58 * duplicated in all such forms and that any documentation,
59 * advertising materials, and other materials related to such
60 * distribution and use acknowledge that the software was developed
61 * by the Internet Initiative Japan. The name of the
62 * IIJ may not be used to endorse or promote products derived
63 * from this software without specific prior written permission.
64 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
65 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
66 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
67 */
68
69/*
70 * PPP 処理タスクの本体
71 */
72
73#include <s_services.h>
74#include <t_services.h>
75#include "kernel_id.h"
76
77#include <tinet_defs.h>
78#include <tinet_config.h>
79
80#include <net/if.h>
81#include <net/if_ppp.h>
82#include <net/net.h>
83#include <net/net_endian.h>
84#include <net/net_var.h>
85#include <net/net_buf.h>
86#include <net/net_timer.h>
87#include <net/net_count.h>
88#include <net/ppp.h>
89#include <net/ppp_var.h>
90#include <net/ppp_hdlc.h>
91#include <net/ppp_fsm.h>
92#include <net/ppp_lcp.h>
93#include <net/ppp_ipv6cp.h>
94#include <net/ppp_ipcp.h>
95#include <net/ppp_ccp.h>
96#include <net/ppp_upap.h>
97#include <net/ppp_modem.h>
98
99#ifdef SUPPORT_PPP
100
101/*
102 * 全域変数
103 */
104
105uint8_t ppp_phase = PPP_PHASE_INITIALIZE; /* リンクの状態 */
106
107/*
108 * プロトコル表
109 */
110
111T_PPP_PROTENT *protocols[] = {
112 &lcp_protent,
113
114#ifdef _IP6_CFG
115 &ipv6cp_protent,
116#endif /* of #ifdef _IP6_CFG */
117
118#ifdef _IP4_CFG
119 &ipcp_protent,
120#endif /* of #ifdef _IP4_CFG */
121
122#ifdef SUPPORT_CCP
123 &ccp_protent,
124#endif /* of #ifdef SUPPORT_CCP */
125
126#ifdef LCP_CFG_PAP
127 &pap_protent,
128#endif /* of #ifdef LCP_CFG_PAP */
129
130#ifdef LCP_CFG_CHAP
131 &chap_protent,
132#endif /* of #ifdef LCP_CFG_CHAP */
133
134 NULL
135 };
136
137/*
138 * 変数
139 */
140
141#ifdef PPP_IDLE_TIMEOUT
142
143static bool_t idle = false;
144
145#endif /* of #ifdef PPP_IDLE_TIMEOUT */
146
147/*
148 * 関数
149 */
150
151static void parse_input (T_NET_BUF *input);
152
153#ifdef PPP_IDLE_TIMEOUT
154
155static void idle_timeout (void *arg);
156
157#endif /* of #ifdef PPP_IDLE_TIMEOUT */
158
159/*
160 * PPP 入力の解析
161 */
162
163static void
164parse_input(T_NET_BUF *input)
165{
166 T_PPP_PROTENT *entry;
167 int_t ix;
168 uint16_t proto;
169
170 NET_COUNT_PPP(net_count_ppp.in_octets, input->len);
171 NET_COUNT_PPP(net_count_ppp.in_packets, 1);
172
173 /* フレーム長をチェックする */
174 if (input->len < sizeof(T_PPP_HDR)) { /* FreeBSD では PPP_HDRLEN は 4 */
175 syslog(LOG_NOTICE, "[PPP] recv short frame.");
176 goto buf_rel;
177 }
178
179 proto = ntohs(*GET_PPP_HDR(input));
180
181 /* プロトコルが LCP 以外で、LCP がオープンされていなければエラー */
182 if (proto != PPP_LCP && lcp_fsm.state != PPP_FSM_OPENED) {
183 syslog(LOG_NOTICE, "[PPP] LCP not open.");
184 goto buf_rel;
185 }
186
187 /* リンクが認証状態以前は、LCP、LQR、PAP、CHAP のみ受け付ける */
188 if (ppp_phase <= PPP_PHASE_AUTHENTICATE &&
189 !(proto == PPP_LCP || proto == PPP_LQR ||
190 proto == PPP_PAP || proto == PPP_CHAP)) {
191 syslog(LOG_NOTICE, "[PPP] disc proto: 0x%04x, phase: %d.", proto, ppp_phase);
192 goto buf_rel;
193 }
194
195 /* 上位プロトコルの入力関数を呼出す */
196 for (ix = 0; (entry = protocols[ix]) != NULL; ix ++) {
197 if (entry->proto == proto && entry->input != NULL) {
198 (*entry->input)(input);
199 syscall(rel_net_buf(input));
200 return;
201 }
202 if ((entry->proto & ~0x8000) == proto && entry->datainput != NULL) {
203 (*entry->datainput)(input);
204 return;
205 }
206 }
207
208 syslog(LOG_INFO, "[PPP] unexp proto: 0x%04x.", proto);
209 lcp_sprotrej(input);
210
211buf_rel:
212 NET_COUNT_PPP(net_count_ppp.in_err_packets, 1);
213 syscall(rel_net_buf(input));
214 }
215
216/*
217 * ppp_output -- PPP インタフェースの出力関数
218 */
219
220ER
221ppp_output (T_NET_BUF *output, TMO tmout)
222{
223 ER error = E_OK;
224
225#ifdef PPP_CFG_MODEM
226
227#if 0 /* 保留 */
228 /* モデムの接続完了まで待つ。*/
229 if ((error = wait_modem()) != E_OK)
230 goto buf_ret;
231#endif
232
233#endif /* of #ifdef PPP_CFG_MODEM */
234
235#ifdef _IP6_CFG
236 /* IPV6CP の接続完了まで待つ。*/
237 if ((error = wait_ipv6cp()) != E_OK)
238 goto buf_ret;
239#endif /* of #ifdef _IP6_CFG */
240
241#ifdef _IP4_CFG
242 /* IPCP の接続完了まで待つ。*/
243 if ((error = wait_ipcp()) != E_OK)
244 goto buf_ret;
245#endif /* of #ifdef _IP4_CFG */
246
247#ifdef _IP4_CFG
248 /* IPCP の接続完了まで待つ。*/
249 if ((error = wait_ipcp()) != E_OK)
250 goto buf_ret;
251#endif /* of #ifdef _IP4_CFG */
252
253#ifdef PPP_IDLE_TIMEOUT
254 wai_sem(SEM_IDLE_TIMEOUT);
255 if (idle) {
256 untimeout((FP)idle_timeout, NULL);
257 idle = false;
258 }
259 sig_sem(SEM_IDLE_TIMEOUT);
260#endif /* of #ifdef PPP_IDLE_TIMEOUT */
261
262 /* PPP 出力キューに投入する。*/
263 if ((error = tsnd_dtq(DTQ_PPP_OUTPUT, output, tmout)) != E_OK)
264 goto buf_ret;
265
266#ifdef PPP_IDLE_TIMEOUT
267 wai_sem(SEM_IDLE_TIMEOUT);
268 if (!idle && ppp_phase == PPP_PHASE_NETWORK) {
269 timeout((FP)idle_timeout, NULL, PPP_IDLE_TIMEOUT);
270 idle = true;
271 }
272 sig_sem(SEM_IDLE_TIMEOUT);
273#endif /* of #ifdef PPP_IDLE_TIMEOUT */
274
275 return error;
276
277buf_ret:
278 syscall(rel_net_buf(output));
279 NET_COUNT_PPP(net_count_ppp.out_err_packets, 1);
280 return error;
281 }
282
283/*
284 * ppp_cp_output -- CP フレームの送信
285 */
286
287void
288ppp_cp_output (uint8_t code, uint8_t id, T_NET_BUF *output)
289{
290 T_PPP_CP_HDR *cph;
291
292 /* CP ヘッダを設定する */
293 cph = GET_PPP_CP_HDR(output);
294 cph->code = code;
295 cph->id = id;
296 cph->len = htons(output->len - sizeof(T_PPP_HDR));
297
298 /* PPP 出力キューに投入する。*/
299 if (snd_dtq(DTQ_PPP_OUTPUT, output) != E_OK) {
300 syscall(rel_net_buf(output));
301 NET_COUNT_PPP(net_count_ppp.out_err_packets, 1);
302 }
303 }
304
305/*
306 * PPP 入力タスク
307 */
308
309void
310ppp_input_task(intptr_t exinf)
311{
312 T_NET_BUF *input;
313 T_PPP_PROTENT *proto;
314 ID tskid;
315 int_t ix;
316 uint8_t rcount = 0;
317
318 /* ポートを初期設定する */
319 syscall(serial_opn_por(HDLC_PORTID));
320 syscall(serial_ctl_por(HDLC_PORTID, IOCTL_FCSND | IOCTL_FCRCV));
321
322 get_tid(&tskid);
323
324#ifdef PPP_CFG_MODEM
325
326 init_modem();
327 syslog(LOG_NOTICE, "[PPP INPUT:%d] started with modem on port %d.", tskid, HDLC_PORTID);
328
329#else /* of #ifdef PPP_CFG_MODEM */
330
331 syslog(LOG_NOTICE, "[PPP INPUT:%d] started on port %d.", tskid, HDLC_PORTID);
332
333#endif /* of #ifdef PPP_CFG_MODEM */
334
335 /* ネットワークタイマタスクを起動する */
336 syscall(act_tsk(NET_TIMER_TASK));
337
338 /* 上位プロトコルを初期化する */
339 for (ix = 0; (proto = protocols[ix]) != NULL; ix ++)
340 if (proto->init != NULL)
341 (*proto->init)();
342
343 lcp_lowerup();
344 lcp_open(PPP_OPEN_PASSIVE);
345
346 /* PPP 出力タスクを起動する */
347 syscall(act_tsk(PPP_OUTPUT_TASK));
348
349 /* 乱数生成を初期化する。*/
350 net_srand(0);
351
352 while (true) {
353 if (tget_net_buf(&input, IF_PDU_SIZE, TMO_PPP_GET_NET_BUF) == E_OK) {
354 while (HDLC_read(input, IF_PDU_SIZE) != E_OK)
355 ;
356 if (input->len > 0) {
357
358 /* 乱数生成を初期化する。*/
359 if (rcount == 0)
360 net_srand(input->len);
361 rcount ++;
362
363#ifdef PPP_IDLE_TIMEOUT
364 wai_sem(SEM_IDLE_TIMEOUT);
365 if (idle && ntohs(*GET_PPP_HDR(input)) != PPP_LCP) {
366 untimeout((FP)idle_timeout, NULL);
367 idle = false;
368 }
369 sig_sem(SEM_IDLE_TIMEOUT);
370#endif /* of #ifdef PPP_IDLE_TIMEOUT */
371
372 parse_input(input);
373 }
374 else
375 syscall(rel_net_buf(input));
376
377#ifdef PPP_IDLE_TIMEOUT
378 wai_sem(SEM_IDLE_TIMEOUT);
379 if (!idle && ppp_phase == PPP_PHASE_NETWORK) {
380 timeout((FP)idle_timeout, NULL, PPP_IDLE_TIMEOUT);
381 idle = true;
382 }
383 else if (idle && ppp_phase != PPP_PHASE_NETWORK) {
384 untimeout((FP)idle_timeout, NULL);
385 idle = false;
386 }
387 sig_sem(SEM_IDLE_TIMEOUT);
388#endif /* of #ifdef PPP_IDLE_TIMEOUT */
389
390 }
391 else {
392 HDLC_dummy_read();
393 NET_COUNT_PPP(net_count_ppp.in_err_packets, 1);
394 NET_COUNT_PPP(net_count_ppp_no_bufs, 1);
395 }
396 }
397 }
398
399/*
400 * PPP 出力タスク
401 */
402
403void
404ppp_output_task(intptr_t exinf)
405{
406 T_NET_BUF *output;
407 ID tskid;
408
409 get_tid(&tskid);
410 syslog(LOG_NOTICE, "[PPP OUTPUT:%d] started.", tskid);
411
412 while (true) {
413 while (rcv_dtq(DTQ_PPP_OUTPUT, (intptr_t*)&output) == E_OK) {
414 NET_COUNT_PPP(net_count_ppp.out_octets, output->len);
415 NET_COUNT_PPP(net_count_ppp.out_packets, 1);
416 syscall(HDLC_write(output));
417 syscall(rel_net_buf(output));
418 }
419 }
420 }
421
422#ifdef PPP_IDLE_TIMEOUT
423
424/*
425 * アイドルタイムアウト処理
426 */
427
428static void
429idle_timeout (void *arg)
430{
431 syslog(LOG_NOTICE, "[PPP] idel %d [s], disconnecting.", (uint16_t)(PPP_IDLE_TIMEOUT / NET_TIMER_HZ));
432 lcp_close();
433 }
434
435#endif /* of #ifdef PPP_IDLE_TIMEOUT */
436
437#endif /* fo #ifdef SUPPORT_PPP */
Note: See TracBrowser for help on using the repository browser.