source: EcnlProtoTool/trunk/asp3_dcre/tinet/net/ppp_hdlc.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: 15.6 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 * PPP High Level Link Control (HDLC) Module
36 *
37 * Written by Toshiharu OHNO (tony-o@iij.ad.jp)
38 *
39 * Copyright (C) 1993, Internet Initiative Japan, Inc. All rights reserverd.
40 *
41 * Redistribution and use in source and binary forms are permitted
42 * provided that the above copyright notice and this paragraph are
43 * duplicated in all such forms and that any documentation,
44 * advertising materials, and other materials related to such
45 * distribution and use acknowledge that the software was developed
46 * by the Internet Initiative Japan, Inc. The name of the
47 * IIJ may not be used to endorse or promote products derived
48 * from this software without specific prior written permission.
49 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
50 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
51 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
52 *
53 * $FreeBSD: src/usr.sbin/ppp/hdlc.c,v 1.46 1999/12/20 20:29:42 brian Exp $
54 *
55 * TODO:
56 */
57
58#include <s_services.h>
59#include <t_services.h>
60
61#include <tinet_defs.h>
62#include <tinet_config.h>
63
64#include <net/if.h>
65#include <net/if_ppp.h>
66#include <net/net.h>
67#include <net/net_buf.h>
68#include <net/net_count.h>
69#include <net/ppp.h>
70#include <net/ppp_var.h>
71#include <net/ppp_hdlc.h>
72#include <net/ppp_fsm.h>
73#include <net/ppp_lcp.h>
74#include <net/ppp_modem.h>
75
76#ifdef SUPPORT_PPP
77
78/*
79 * RFC1171 (PPP) の HDLC 部の定義
80 */
81
82/*
83 * 変数
84 */
85
86uint32_t remote_ACCM = DEF_REMOTE_ACCM;
87
88/*
89 * 関数
90 */
91
92static ER HDLC_putoctet (uint8_t octet);
93static ER HDLC_getoctet (uint8_t *octet);
94
95/*
96 * genfcstab.c により作成した FCS のルックアップ表
97 * RFC1171 参照
98 */
99
100static uint16_t fcstab[256] = {
101 UINT_C(0x0000), UINT_C(0x1189), UINT_C(0x2312), UINT_C(0x329b),
102 UINT_C(0x4624), UINT_C(0x57ad), UINT_C(0x6536), UINT_C(0x74bf),
103 UINT_C(0x8c48), UINT_C(0x9dc1), UINT_C(0xaf5a), UINT_C(0xbed3),
104 UINT_C(0xca6c), UINT_C(0xdbe5), UINT_C(0xe97e), UINT_C(0xf8f7),
105 UINT_C(0x1081), UINT_C(0x0108), UINT_C(0x3393), UINT_C(0x221a),
106 UINT_C(0x56a5), UINT_C(0x472c), UINT_C(0x75b7), UINT_C(0x643e),
107 UINT_C(0x9cc9), UINT_C(0x8d40), UINT_C(0xbfdb), UINT_C(0xae52),
108 UINT_C(0xdaed), UINT_C(0xcb64), UINT_C(0xf9ff), UINT_C(0xe876),
109 UINT_C(0x2102), UINT_C(0x308b), UINT_C(0x0210), UINT_C(0x1399),
110 UINT_C(0x6726), UINT_C(0x76af), UINT_C(0x4434), UINT_C(0x55bd),
111 UINT_C(0xad4a), UINT_C(0xbcc3), UINT_C(0x8e58), UINT_C(0x9fd1),
112 UINT_C(0xeb6e), UINT_C(0xfae7), UINT_C(0xc87c), UINT_C(0xd9f5),
113 UINT_C(0x3183), UINT_C(0x200a), UINT_C(0x1291), UINT_C(0x0318),
114 UINT_C(0x77a7), UINT_C(0x662e), UINT_C(0x54b5), UINT_C(0x453c),
115 UINT_C(0xbdcb), UINT_C(0xac42), UINT_C(0x9ed9), UINT_C(0x8f50),
116 UINT_C(0xfbef), UINT_C(0xea66), UINT_C(0xd8fd), UINT_C(0xc974),
117 UINT_C(0x4204), UINT_C(0x538d), UINT_C(0x6116), UINT_C(0x709f),
118 UINT_C(0x0420), UINT_C(0x15a9), UINT_C(0x2732), UINT_C(0x36bb),
119 UINT_C(0xce4c), UINT_C(0xdfc5), UINT_C(0xed5e), UINT_C(0xfcd7),
120 UINT_C(0x8868), UINT_C(0x99e1), UINT_C(0xab7a), UINT_C(0xbaf3),
121 UINT_C(0x5285), UINT_C(0x430c), UINT_C(0x7197), UINT_C(0x601e),
122 UINT_C(0x14a1), UINT_C(0x0528), UINT_C(0x37b3), UINT_C(0x263a),
123 UINT_C(0xdecd), UINT_C(0xcf44), UINT_C(0xfddf), UINT_C(0xec56),
124 UINT_C(0x98e9), UINT_C(0x8960), UINT_C(0xbbfb), UINT_C(0xaa72),
125 UINT_C(0x6306), UINT_C(0x728f), UINT_C(0x4014), UINT_C(0x519d),
126 UINT_C(0x2522), UINT_C(0x34ab), UINT_C(0x0630), UINT_C(0x17b9),
127 UINT_C(0xef4e), UINT_C(0xfec7), UINT_C(0xcc5c), UINT_C(0xddd5),
128 UINT_C(0xa96a), UINT_C(0xb8e3), UINT_C(0x8a78), UINT_C(0x9bf1),
129 UINT_C(0x7387), UINT_C(0x620e), UINT_C(0x5095), UINT_C(0x411c),
130 UINT_C(0x35a3), UINT_C(0x242a), UINT_C(0x16b1), UINT_C(0x0738),
131 UINT_C(0xffcf), UINT_C(0xee46), UINT_C(0xdcdd), UINT_C(0xcd54),
132 UINT_C(0xb9eb), UINT_C(0xa862), UINT_C(0x9af9), UINT_C(0x8b70),
133 UINT_C(0x8408), UINT_C(0x9581), UINT_C(0xa71a), UINT_C(0xb693),
134 UINT_C(0xc22c), UINT_C(0xd3a5), UINT_C(0xe13e), UINT_C(0xf0b7),
135 UINT_C(0x0840), UINT_C(0x19c9), UINT_C(0x2b52), UINT_C(0x3adb),
136 UINT_C(0x4e64), UINT_C(0x5fed), UINT_C(0x6d76), UINT_C(0x7cff),
137 UINT_C(0x9489), UINT_C(0x8500), UINT_C(0xb79b), UINT_C(0xa612),
138 UINT_C(0xd2ad), UINT_C(0xc324), UINT_C(0xf1bf), UINT_C(0xe036),
139 UINT_C(0x18c1), UINT_C(0x0948), UINT_C(0x3bd3), UINT_C(0x2a5a),
140 UINT_C(0x5ee5), UINT_C(0x4f6c), UINT_C(0x7df7), UINT_C(0x6c7e),
141 UINT_C(0xa50a), UINT_C(0xb483), UINT_C(0x8618), UINT_C(0x9791),
142 UINT_C(0xe32e), UINT_C(0xf2a7), UINT_C(0xc03c), UINT_C(0xd1b5),
143 UINT_C(0x2942), UINT_C(0x38cb), UINT_C(0x0a50), UINT_C(0x1bd9),
144 UINT_C(0x6f66), UINT_C(0x7eef), UINT_C(0x4c74), UINT_C(0x5dfd),
145 UINT_C(0xb58b), UINT_C(0xa402), UINT_C(0x9699), UINT_C(0x8710),
146 UINT_C(0xf3af), UINT_C(0xe226), UINT_C(0xd0bd), UINT_C(0xc134),
147 UINT_C(0x39c3), UINT_C(0x284a), UINT_C(0x1ad1), UINT_C(0x0b58),
148 UINT_C(0x7fe7), UINT_C(0x6e6e), UINT_C(0x5cf5), UINT_C(0x4d7c),
149 UINT_C(0xc60c), UINT_C(0xd785), UINT_C(0xe51e), UINT_C(0xf497),
150 UINT_C(0x8028), UINT_C(0x91a1), UINT_C(0xa33a), UINT_C(0xb2b3),
151 UINT_C(0x4a44), UINT_C(0x5bcd), UINT_C(0x6956), UINT_C(0x78df),
152 UINT_C(0x0c60), UINT_C(0x1de9), UINT_C(0x2f72), UINT_C(0x3efb),
153 UINT_C(0xd68d), UINT_C(0xc704), UINT_C(0xf59f), UINT_C(0xe416),
154 UINT_C(0x90a9), UINT_C(0x8120), UINT_C(0xb3bb), UINT_C(0xa232),
155 UINT_C(0x5ac5), UINT_C(0x4b4c), UINT_C(0x79d7), UINT_C(0x685e),
156 UINT_C(0x1ce1), UINT_C(0x0d68), UINT_C(0x3ff3), UINT_C(0x2e7a),
157 UINT_C(0xe70e), UINT_C(0xf687), UINT_C(0xc41c), UINT_C(0xd595),
158 UINT_C(0xa12a), UINT_C(0xb0a3), UINT_C(0x8238), UINT_C(0x93b1),
159 UINT_C(0x6b46), UINT_C(0x7acf), UINT_C(0x4854), UINT_C(0x59dd),
160 UINT_C(0x2d62), UINT_C(0x3ceb), UINT_C(0x0e70), UINT_C(0x1ff9),
161 UINT_C(0xf78f), UINT_C(0xe606), UINT_C(0xd49d), UINT_C(0xc514),
162 UINT_C(0xb1ab), UINT_C(0xa022), UINT_C(0x92b9), UINT_C(0x8330),
163 UINT_C(0x7bc7), UINT_C(0x6a4e), UINT_C(0x58d5), UINT_C(0x495c),
164 UINT_C(0x3de3), UINT_C(0x2c6a), UINT_C(0x1ef1), UINT_C(0x0f78),
165 };
166
167/*
168 * インライン関数
169 */
170
171Inline uint16_t Next_FCS (uint16_t FCS, uint8_t Octet) {
172 return (FCS >> 8) ^ fcstab[(FCS ^ Octet) & 0xff];
173 };
174
175/*
176 * HDLC_putoctet -- HDLC オクテット出力
177 */
178
179static
180ER HDLC_putoctet (uint8_t octet)
181{
182 static uint8_t escape[2] = { HDLC_CNTL_ESC };
183
184 ER error;
185
186 NET_COUNT_PPP_HDLC(net_count_hdlc.out_octets, 1);
187
188 if ((octet < 0x20 && ((1 << octet) & lcp_remote_ack_cfg.ACCM)) ||
189 octet == HDLC_CNTL_ESC || octet == HDLC_FLAG_SEQ) {
190 escape[1] = octet ^ HDLC_ESC_MASK;
191 error = serial_wri_dat(HDLC_PORTID, escape, sizeof(escape));
192 }
193 else
194 error = serial_wri_dat(HDLC_PORTID, &octet, sizeof(octet));
195
196 return error > 0 ? E_OK : error;
197 }
198
199/*
200 * HDLC_wirte -- HDLC 出力
201 */
202
203ER HDLC_write (T_NET_BUF *nbuf)
204{
205 static char flag_seq_ac[4] = {
206 HDLC_FLAG_SEQ,
207 HDLC_ADDR_ALL,
208 HDLC_CNTL_ESC,
209 HDLC_CNTL_UI ^ HDLC_ESC_MASK,
210 };
211
212#ifdef LCP_CFG_ACCOMP
213
214 static char flag_seq = HDLC_FLAG_SEQ;
215
216#endif /* of #ifdef LCP_CFG_ACCOMP */
217
218 ER error;
219 uint32_t fcs;
220 uint16_t len;
221 uint8_t *buf;
222
223 NET_COUNT_PPP_HDLC(net_count_hdlc.out_packets, 1);
224
225#ifdef LCP_CFG_ACCOMP
226
227 if (lcp_local_ack_cfg.options & LCP_CFG_ACCOMP) {
228 NET_COUNT_PPP_HDLC(net_count_hdlc.out_octets, sizeof(flag_seq));
229 /* フレーム開始フラグシーケンス を送信する */
230 if ((error = serial_wri_dat(HDLC_PORTID, &flag_seq, sizeof(flag_seq))) < 0) {
231 goto err_ret;
232 }
233 fcs = HDLC_INIT_FCS;
234 }
235 else {
236
237 NET_COUNT_PPP_HDLC(net_count_hdlc.out_octets, sizeof(flag_seq_ac));
238 /* フレーム開始フラグシーケンス、Address と Control を送信する */
239 if ((error = serial_wri_dat(HDLC_PORTID, flag_seq_ac, sizeof(flag_seq_ac))) < 0) {
240 goto err_ret;
241 }
242 /* Address と Control の FCS の計算は HDLC_INIT_FCS_AC に含めている */
243 fcs = HDLC_INIT_FCS_AC;
244 }
245
246#else /* of #ifdef LCP_CFG_ACCOMP */
247
248 NET_COUNT_PPP_HDLC(net_count_hdlc.out_octets, sizeof(flag_seq_ac));
249 /* フレーム開始フラグシーケンス、Address と Control を送信する */
250 if ((error = serial_wri_dat(HDLC_PORTID, flag_seq_ac, sizeof(flag_seq_ac))) < 0) {
251 goto err_ret;
252 }
253 /* Address と Control の FCS の計算は HDLC_INIT_FCS_AC に含めている */
254 fcs = HDLC_INIT_FCS_AC;
255
256#endif /* of #ifdef LCP_CFG_ACCOMP */
257
258 buf = nbuf->buf;
259 len = nbuf->len;
260
261#ifdef LCP_CFG_PCOMP
262
263 if ((lcp_local_ack_cfg.options & LCP_CFG_ACCOMP) && *buf == 0 && *(buf + 1) < 0xff) {
264 buf ++;
265 len --;
266 }
267
268#endif /* of #ifdef LCP_CFG_PCOMP */
269
270 /* データを送信する */
271 while (len -- > 0) {
272
273 if ((error = HDLC_putoctet(*buf)) != E_OK)
274 goto err_ret;
275 fcs = Next_FCS(fcs, *buf);
276 buf ++;
277 }
278
279 /* FCS を送信する */
280 fcs = ~fcs;
281 if ((error = HDLC_putoctet(fcs & 0xff)) != E_OK)
282 goto err_ret;
283 if ((error = HDLC_putoctet(fcs >> 8)) != E_OK)
284 goto err_ret;
285
286 /* フレーム終了フラグシーケンスを送信する */
287 if ((error = serial_wri_dat(HDLC_PORTID, &flag_seq_ac[0], sizeof(char))) < 0)
288 goto err_ret;
289
290 return E_OK;
291
292err_ret:
293 NET_COUNT_PPP_HDLC(net_count_hdlc.out_err_packets, 1);
294 return error;
295 }
296
297/*
298 * HDLC_getoctet -- HDLC オクテット入力
299 *
300 * 戻り値が true ならフラグシーケンス
301 */
302
303static
304ER_BOOL HDLC_getoctet (uint8_t *octet)
305{
306 ER error;
307
308 /* 1オクテット入力する */
309 if ((error = serial_rea_dat(HDLC_PORTID, octet, sizeof(uint8_t))) <= 0) {
310 return error;
311 }
312
313 /* 入力したオクテットがフラグシーケンスなら true を返す */
314 if (*octet == HDLC_FLAG_SEQ)
315 return true;
316
317 /* 入力したオクテットがエスケープなら、もう1オクテット入力しマスクを解除する */
318 if (*octet == HDLC_CNTL_ESC) {
319 if ((error = serial_rea_dat(HDLC_PORTID, octet, sizeof(uint8_t))) <= 0)
320 return error;
321 *octet ^= HDLC_ESC_MASK;
322 }
323
324 NET_COUNT_PPP_HDLC(net_count_hdlc.in_octets, 1);
325 return E_OK;
326 }
327
328/*
329 * HDLC_read -- HDLC 入力
330 *
331 * HDLC フレームを入力する。
332 */
333
334ER HDLC_read (T_NET_BUF *nbuf, uint16_t size)
335{
336 ER error;
337 uint32_t fcs = 0;
338 uint16_t olen = 0;
339 uint8_t *buf, octet;
340
341 buf = nbuf->buf;
342
343 /* フレーム開始フラグシーケンスまで入力を読み飛ばす */
344 while ((error = HDLC_getoctet(&octet)) != true) {
345
346 if (error != E_OK)
347 goto err_ret;
348
349#ifdef PPP_CFG_MODEM
350
351 else if (octet == '\n') {
352 /* モデム制御を呼び出す。*/
353 modem_cntl(modem_getline(nbuf, size));
354 /* 一度、この関数を終了する。*/
355 nbuf->len = 0;
356 return E_OK;
357 }
358
359#endif/* of #ifdef PPP_CFG_MODEM */
360
361 }
362
363 /* フレーム開始フラグシーケンスの間は入力を読み飛ばす */
364 while (1) {
365 if ((error = HDLC_getoctet(&octet)) == E_OK)
366 break;
367 else if (error != true)
368 goto err_ret;
369 }
370
371 NET_COUNT_PPP_HDLC(net_count_hdlc.in_packets, 1);
372
373 /* 入力したオクテットは Address: All-Stations か */
374 if (octet == HDLC_ADDR_ALL) {
375
376 /* 次は Control: UI */
377 if ((error = HDLC_getoctet(&octet)) != E_OK || octet != HDLC_CNTL_UI) {
378 error = E_SYS;
379 goto err_ret;
380 }
381 if ((error = HDLC_getoctet(&octet)) != E_OK)
382 goto err_ret;
383 /* Address と Control の FCS の計算は HDLC_INIT_FCS_AC に含めている */
384 fcs = HDLC_INIT_FCS_AC;
385 }
386
387#ifdef LCP_CFG_ACCOMP
388
389 else if (lcp_remote_ack_cfg.options & LCP_CFG_ACCOMP) {
390 fcs = HDLC_INIT_FCS;
391 }
392
393#endif/* of #ifdef LCP_CFG_ACCOMP */
394
395 else {
396 error = E_SYS;
397 goto err_ret;
398 }
399
400 nbuf->len = 0;
401
402#ifdef LCP_CFG_PCOMP
403
404 if ((lcp_remote_ack_cfg.options & LCP_CFG_PCOMP) && (octet & 0x01) != 0) {
405 *buf ++ = 0x00;
406 size --;
407 nbuf->len ++;
408 }
409
410#endif /* of #ifdef LCP_CFG_PCOMP */
411
412 fcs = Next_FCS(fcs, octet);
413 *buf ++ = octet;
414 size --;
415 nbuf->len ++;
416
417 /* SUD + FCS を入力する */
418 while ((error = HDLC_getoctet(&octet)) == E_OK) {
419 fcs = Next_FCS(fcs, octet);
420 if (size > 0) {
421 *buf ++ = octet;
422 size --;
423 }
424 else
425 olen ++;
426 nbuf->len ++;
427 }
428
429 if (error == true) {
430 if (size > 0)
431 nbuf->len -= 2;
432 else if (olen <= 2)
433 nbuf->len -= olen;
434 else {
435 error = E_BOVR;
436 goto err_ret;
437 }
438 }
439 else
440 goto err_ret;
441
442 /* FCS をチェックする */
443 if (fcs != HDLC_GOOD_FCS) {
444 error = E_SYS;
445 goto err_ret;
446 }
447
448 return E_OK;
449
450err_ret:
451 NET_COUNT_PPP_HDLC(net_count_hdlc.in_err_packets, 1);
452 return error;
453 }
454
455/*
456 * HDLC_dummy_read -- HDLC 入力 (空読み)
457 *
458 * HDLC フレームを空読みする。
459 */
460
461void
462HDLC_dummy_read (void)
463{
464 uint8_t octet;
465 ER error;
466
467 /* フレーム開始フラグシーケンスまで入力を読み飛ばす */
468 while ((error = HDLC_getoctet(&octet)) != true) {
469 if (error != E_OK)
470 return;
471 }
472
473 /* フレーム開始フラグシーケンスの間は入力を読み飛ばす */
474 while (octet == HDLC_FLAG_SEQ)
475 if (HDLC_getoctet(&octet) != E_OK)
476 return;
477
478 /* 入力したオクテットは Address: All-Stations か */
479 if (octet == HDLC_ADDR_ALL) {
480
481 /* 次は Control: UI */
482 if (HDLC_getoctet(&octet) != E_OK || octet != HDLC_CNTL_UI)
483 return;
484 if (HDLC_getoctet(&octet) != E_OK)
485 return;
486 }
487
488#ifdef LCP_CFG_ACCOMP
489
490 else if (lcp_remote_ack_cfg.options & LCP_CFG_ACCOMP)
491 ;
492
493#endif/* of #ifdef LCP_CFG_ACCOMP */
494
495 else
496 return;
497
498 while (HDLC_getoctet(&octet) == E_OK)
499 ;
500 }
501
502#ifdef PPP_CFG_MODEM
503
504/*
505 * HDLC_raw_getoctet -- HDLC オクテット (Raw) 入力
506 */
507
508int HDLC_raw_getoctet (void)
509{
510 uint8_t ch;
511
512 /* 1オクテット入力する */
513 if (serial_rea_dat(HDLC_PORTID, &ch, sizeof(ch)) <= 0)
514 return '\0';
515
516 NET_COUNT_PPP_HDLC(net_count_hdlc.in_octets, 1);
517 return ch;
518 }
519
520/*
521 * HDLC_raw_putoctet -- HDLC オクテット (Raw) 出力
522 */
523
524void HDLC_raw_putoctet (uint8_t ch)
525{
526 NET_COUNT_PPP_HDLC(net_count_hdlc.out_octets, 1);
527 /* 1オクテット出力する */
528 serial_wri_dat(HDLC_PORTID, &ch, sizeof(ch));
529 }
530
531#endif /* of #ifdef PPP_CFG_MODEM */
532
533#endif /* fo #ifdef SUPPORT_PPP */
Note: See TracBrowser for help on using the repository browser.