source: EcnlProtoTool/trunk/asp3_dcre/tinet/netapp/net_cons.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: 14.0 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 * ネットワーク経由コンソール入出力
36 */
37
38#include <stdarg.h>
39#include <string.h>
40
41#ifdef TARGET_KERNEL_ASP
42
43#include <kernel.h>
44#include <sil.h>
45#include <syssvc/serial.h>
46#include <syssvc/logtask.h>
47#include <t_syslog.h>
48#include "kernel_cfg.h"
49#include "tinet_cfg.h"
50
51#endif /* of #ifdef TARGET_KERNEL_ASP */
52
53#ifdef TARGET_KERNEL_JSP
54
55#include <s_services.h>
56#include <t_services.h>
57#include "kernel_id.h"
58#include "tinet_id.h"
59
60#endif /* of #ifdef TARGET_KERNEL_JSP */
61
62#include <tinet_defs.h>
63
64#include <net/if.h>
65#include <net/if_ppp.h>
66#include <net/if_loop.h>
67#include <net/ethernet.h>
68#include <net/net.h>
69#include <net/net_timer.h>
70
71#include <netinet/in.h>
72#include <netinet/in_itron.h>
73
74#include <netapp/netapp.h>
75#include <netapp/netapp_var.h>
76#include <netapp/net_cons.h>
77
78#ifdef USE_NET_CONS
79
80/*
81 * マクロ定義
82 */
83
84/* リネームの解除 */
85
86#undef syslog
87#undef serial_rea_dat
88#undef serial_ctl_por
89
90#define EOF (-1)
91
92/* TELNET オプション */
93
94#define TELNET_OPT_SE (240)
95#define TELNET_OPT_NOP (241)
96#define TELNET_OPT_DM (242)
97#define TELNET_OPT_BRK (243)
98#define TELNET_OPT_IP (244)
99#define TELNET_OPT_AO (245)
100#define TELNET_OPT_AYT (246)
101#define TELNET_OPT_EC (247)
102#define TELNET_OPT_EL (248)
103#define TELNET_OPT_GA (249)
104#define TELNET_OPT_SB (250)
105#define TELNET_OPT_WILL (251)
106#define TELNET_OPT_WONT (252)
107#define TELNET_OPT_DO (253)
108#define TELNET_OPT_DONT (254)
109#define TELNET_OPT_IAC (255)
110
111/*
112 * 変数
113 */
114
115/* TCP 送受信ウィンドバッファ */
116
117uint8_t net_cons_swbuf[NET_CONS_SWBUF_SIZE];
118uint8_t net_cons_rwbuf[NET_CONS_RWBUF_SIZE];
119
120bool_t connected = false; /* コネクションの状態 */
121bool_t wait_accept = false; /* 接続要求待ち中 */
122
123#if defined(SUPPORT_INET4)
124
125T_IPV4EP dst;
126
127#endif /* of #if defined(SUPPORT_INET4) */
128
129#if defined(SUPPORT_INET6)
130
131T_IPV6EP dst;
132
133#endif /* of #if defined(SUPPORT_INET6) */
134
135uint8_t *snd_buff = NULL;
136uint8_t *rcv_buff = NULL;
137uint_t snd_off = 0;
138uint_t rcv_off = 0;
139uint_t net_ioctl = IOCTL_NULL;
140ER_UINT snd_len = 0;
141ER_UINT rcv_len = 0;
142
143/*
144 * ノンブロッキングコールのコールバック関数
145 */
146
147ER
148callback_nblk_net_cons (ID cepid, FN fncd, void *p_parblk)
149{
150 ER error = E_OK;
151 SYSTIM now;
152
153 switch (fncd) {
154
155 case TFN_TCP_ACP_CEP:
156 get_tim(&now);
157 if (*(ER*)p_parblk == E_OK) {
158 syslog(LOG_NOTICE, "[NCS:%02u CBN] connected: %6lu, from: %s.%u",
159 cepid, now / SYSTIM_HZ, IP2STR(NULL, &dst.ipaddr), dst.portno);
160 connected = true;
161 }
162 else
163 syslog(LOG_NOTICE, "[NCS:%02d CBN] error: %s", itron_strerror(*(ER*)p_parblk));
164 snd_len = snd_off = rcv_len = rcv_off = 0;
165 wait_accept = false;
166 break;
167
168 case TFN_TCP_CLS_CEP:
169 case TFN_TCP_RCV_BUF:
170 case TFN_TCP_GET_BUF:
171 case TFN_TCP_RCV_DAT:
172 case TFN_TCP_SND_DAT:
173 case TFN_TCP_CON_CEP:
174 case TFN_TCP_SND_OOB:
175 default:
176 error = E_PAR;
177 break;
178 }
179 return error;
180 }
181
182/*
183 * 送信バッファのフラッシュ
184 */
185
186void
187flush_snd_buff (void)
188{
189 ER_UINT error;
190
191 if (connected) {
192 syscall(wai_sem(SEM_NET_CONS_SEND));
193 if (snd_off > 0) {
194 if ((error = tcp_snd_buf(NET_CONS_CEPID, snd_off)) != E_OK && error != E_CLS)
195 syslog(LOG_NOTICE, "[NCS:%02d SND] flush send error: %s",
196 NET_CONS_CEPID, itron_strerror(error));
197 snd_len = snd_off = 0;
198 }
199 syscall(sig_sem(SEM_NET_CONS_SEND));
200 }
201 return;
202 }
203
204/*
205 * 文字送信
206 */
207
208void
209cons_putchar (ID portid, char ch)
210{
211 ER_UINT error;
212
213 if (connected) {
214 if (ch == '\n' && (net_ioctl & IOCTL_CRLF) != 0)
215 cons_putchar(portid, '\r');
216 syscall(wai_sem(SEM_NET_CONS_SEND));
217 if (snd_off >= snd_len) {
218 if ((error = tcp_snd_buf(NET_CONS_CEPID, snd_off)) != E_OK) {
219 if (error != E_CLS)
220 syslog(LOG_NOTICE, "[NCS:%02d SND] send buff error: %s",
221 NET_CONS_CEPID, itron_strerror(error));
222 syscall(sig_sem(SEM_NET_CONS_SEND));
223 return;
224 }
225 snd_off = 0;
226 if ((snd_len = tcp_get_buf(NET_CONS_CEPID, (void*)&snd_buff, TMO_FEVR)) <= 0) {
227 if (snd_len != E_CLS)
228 syslog(LOG_NOTICE, "[NCS:%02d SND] get buff error: %s",
229 NET_CONS_CEPID, itron_strerror(snd_len));
230 syscall(sig_sem(SEM_NET_CONS_SEND));
231 return;
232 }
233 }
234 snd_buff[snd_off ++] = ch;
235 syscall(sig_sem(SEM_NET_CONS_SEND));
236 }
237 else
238 serial_wri_dat(portid, &ch, sizeof(ch));
239 }
240
241/*
242 * 文字受信(変換なし)
243 */
244
245static int_t
246cons_getchar_raw (void)
247{
248 ER error = E_OK;
249
250 if (connected) {
251 if (rcv_off >= rcv_len) {
252 rcv_off = 0;
253 if ((error = tcp_rel_buf(NET_CONS_CEPID, rcv_len)) != E_OK) {
254 if (error != E_CLS)
255 syslog(LOG_NOTICE, "[NCS:%02d RCV] release buff error: %s",
256 NET_CONS_CEPID, itron_strerror(error));
257 discon_net_cons();
258 return EOF;
259 }
260 if ((rcv_len = tcp_rcv_buf(NET_CONS_CEPID, (void*)&rcv_buff, TMO_FEVR)) == 0) {
261 discon_net_cons();
262 return EOF;
263 }
264 else if (rcv_len < 0) {
265 if (rcv_len != E_CLS)
266 syslog(LOG_NOTICE, "[NCS:%02d RCV] recieve buff error: %s",
267 NET_CONS_CEPID, itron_strerror(rcv_len));
268 discon_net_cons();
269 return EOF;
270 }
271 }
272 return rcv_buff[rcv_off ++];
273 }
274 else
275 return EOF;
276 }
277
278/*
279 * 文字受信(TELNET オプションをスキップ)
280 */
281
282int_t
283cons_getchar (ID portid)
284{
285 T_SERIAL_RPOR rpor;
286 int_t ch, req;
287 char uch;
288 ER error;
289
290 if (!wait_accept && !connected) {
291 wait_accept = true;
292 error = TCP_ACP_CEP(NET_CONS_CEPID, NET_CONS_REPID, &dst, TMO_NBLK);
293#if 0
294 syslog(LOG_NOTICE, "[NCS:%02d ACP] status: %s",NET_CONS_CEPID, itron_strerror(error));
295#endif
296 if (error != E_WBLK)
297 return EOF;
298 }
299
300 while (true) {
301 if (connected) {
302 while ((ch = cons_getchar_raw()) == TELNET_OPT_IAC || ch == '\0') {
303 if (ch != '\0') {
304 switch (ch = cons_getchar_raw()) {
305 case TELNET_OPT_WILL:
306 case TELNET_OPT_WONT:
307 case TELNET_OPT_DO:
308 case TELNET_OPT_DONT:
309 req = cons_getchar_raw();
310 break;
311 case TELNET_OPT_SB:
312 while ((ch = cons_getchar_raw()) != EOF && ch != TELNET_OPT_IAC) {
313 if ((ch = cons_getchar_raw()) == EOF || ch == TELNET_OPT_SE)
314 break;
315 }
316 break;
317 default:
318 break;
319 }
320 }
321 }
322 if (ch != '\n') {
323 if ((net_ioctl & IOCTL_ECHO) != 0 && ch != EOF) {
324 cons_putchar(portid, ch);
325 flush_snd_buff();
326 }
327 return ch;
328 }
329 }
330
331 else if (serial_ref_por(portid, &rpor) == E_OK && rpor.reacnt > 0) {
332 if (serial_rea_dat(portid, &uch, sizeof(uch)) > 0)
333 return uch;
334 else
335 return EOF;
336 }
337 dly_tsk(100);
338 }
339 return EOF;
340 }
341
342/*
343 * コネクションを切断
344 */
345
346ER
347discon_net_cons (void)
348{
349 ER error = E_OK;
350 SYSTIM now;
351
352 if (connected) {
353 syscall(wai_sem(SEM_NET_CONS_SEND));
354 if (snd_off > 0) {
355 if ((error = tcp_snd_buf(NET_CONS_CEPID, snd_off)) != E_OK && error != E_CLS)
356 syslog(LOG_NOTICE, "[NCS:%02d SND] send buff error: %s",
357 NET_CONS_CEPID, itron_strerror(error));
358 }
359 if ((error = tcp_sht_cep(NET_CONS_CEPID)) != E_OK)
360 syslog(LOG_NOTICE, "[NCS:%02d SHT] shutdown error: %s",
361 NET_CONS_CEPID, itron_strerror(error));
362 if ((error = tcp_cls_cep(NET_CONS_CEPID, TMO_FEVR)) != E_OK)
363 syslog(LOG_NOTICE, "[NCS:%02d CLS] close error: %s",
364 NET_CONS_CEPID, itron_strerror(error));
365 connected = false;
366 syscall(sig_sem(SEM_NET_CONS_SEND));
367 get_tim(&now);
368 syslog(LOG_NOTICE, "[NCS:%02u SND] disconnected:%5lu, from: %s.%u",
369 NET_CONS_CEPID, now / SYSTIM_HZ, IP2STR(NULL, &dst.ipaddr), dst.portno);
370 }
371 return error;
372 }
373
374/*
375 * シリアルポートの制御
376 */
377
378ER
379net_serial_ctl_por (ID portid, uint_t ioctl)
380{
381 net_ioctl = ioctl;
382 return serial_ctl_por(portid, ioctl);
383 }
384
385/*
386 * ログ出力
387 */
388
389ER
390net_syslog (uint_t prio, const char *format, ...)
391{
392#if defined(SUPPORT_INET4)
393 T_IN4_ADDR *addr;
394#endif /* of #if defined(SUPPORT_INET4) */
395
396 ulong_t val;
397 SYSLOG log;
398 va_list ap;
399 char padchar, *str;
400 int_t ch, width, left, i;
401 bool_t longflag;
402
403 if (connected) {
404 syscall(wai_sem(SEM_NET_CONS_PRINTF));
405 va_start(ap, format);
406 while ((ch = *format ++) != '\0') {
407 if (ch != '%') { /* 書式指定以外 */
408 cons_putchar(CONSOLE_PORTID, (char)ch);
409 continue;
410 }
411
412 width = 0;
413 longflag = false;
414 padchar = ' ';
415
416 if (ch == '-') { /* 左詰め */
417 format ++;
418 left = -1;
419 }
420 else
421 left = 1;
422
423 if ((ch = *format ++) == '0') { /* 上位桁の 0 */
424 padchar = '0';
425 ch = *format ++;
426 }
427
428 while ('0' <= ch && ch <= '9') { /* 出力幅 */
429 width = width * 10 + ch - '0';
430 ch = *format ++;
431 }
432
433 while (ch == 'l') { /* long (long) の指定 */
434 longflag = true;
435 ch = *format ++;
436 }
437
438 switch (ch) {
439 case 'd':
440 val = longflag ? (ulong_t)va_arg(ap, long_t)
441 : (ulong_t)va_arg(ap, int_t);
442 if ((long_t)val >= 0)
443 cons_putnumber(CONSOLE_PORTID, val, 10, radhex, width * left, false, padchar);
444 else
445 cons_putnumber(CONSOLE_PORTID, -val, 10, radhex, width * left, true, padchar);
446 break;
447
448 case 'u':
449 val = longflag ? (ulong_t)va_arg(ap, ulong_t)
450 : (ulong_t)va_arg(ap, uint_t);
451 cons_putnumber(CONSOLE_PORTID, val, 10, radhex, width * left, false, padchar);
452 break;
453
454 case 'x':
455 val = longflag ? (ulong_t)va_arg(ap, ulong_t)
456 : (ulong_t)va_arg(ap, uint_t);
457 cons_putnumber(CONSOLE_PORTID, val, 16, radhex, width * left, false, padchar);
458 break;
459
460 case 'X':
461 val = longflag ? (ulong_t)va_arg(ap, ulong_t)
462 : (ulong_t)va_arg(ap, uint_t);
463 cons_putnumber(CONSOLE_PORTID, val, 16, radHEX, width * left, false, padchar);
464 break;
465
466 case 'c':
467 ch = va_arg(ap, int_t);
468 cons_putchar(CONSOLE_PORTID, (char)ch);
469 break;
470
471 case 's':
472 str = va_arg(ap, char*);
473 while ((ch = *str ++) != '\0') {
474 cons_putchar(CONSOLE_PORTID, (char)ch);
475 width --;
476 }
477 while (width -- > 0)
478 cons_putchar(CONSOLE_PORTID, ' ');
479 break;
480
481 case 'I':
482
483#if defined(SUPPORT_INET4)
484
485 addr = va_arg(ap, T_IN4_ADDR*);
486 put_ipv4addr(CONSOLE_PORTID, addr, width);
487
488#endif /* of #if defined(SUPPORT_INET4) */
489
490#if defined(SUPPORT_INET6)
491
492 str = va_arg(ap, char*);
493 put_ipv6addr(CONSOLE_PORTID, (T_IN6_ADDR *)str, width);
494
495#endif /* of #if defined(SUPPORT_INET6) */
496
497 break;
498
499 case 'M':
500 str = va_arg(ap, char*);
501 put_macaddr(CONSOLE_PORTID, str, width);
502 break;
503
504 case '%':
505 cons_putchar(CONSOLE_PORTID, '%');
506 break;
507
508 case '0':
509 format --;
510 break;
511
512 default:
513 break;
514 }
515
516 }
517 va_end(ap);
518 cons_putchar(CONSOLE_PORTID, '\n');
519 flush_snd_buff();
520 syscall(sig_sem(SEM_NET_CONS_PRINTF));
521 return E_OK;
522 }
523 else {
524 log.logtype = LOG_TYPE_COMMENT;
525 log.loginfo[0] = (intptr_t)format;
526 i = 1;
527 va_start(ap, format);
528
529 while ((ch = *format++) != '\0' && i < TMAX_LOGINFO) {
530 if (ch != '%') {
531 continue;
532 }
533
534 longflag = false;
535
536 ch = *format++;
537 while ('0' <= ch && ch <= '9') {
538 ch = *format++;
539 }
540
541 while (ch == 'l') { /* long (long) の指定 */
542 longflag = true;
543 ch = *format ++;
544 }
545
546 switch (ch) {
547 case 'd':
548 log.loginfo[i++] = longflag
549 ? (intptr_t)va_arg(ap, long_t)
550 : (intptr_t)va_arg(ap, int_t);
551 break;
552 case 'u':
553 case 'x':
554 case 'X':
555 log.loginfo[i++] = longflag
556 ? (intptr_t)va_arg(ap, ulong_t)
557 : (intptr_t)va_arg(ap, uint_t);
558 break;
559 case 'p':
560 log.loginfo[i++] = (intptr_t)va_arg(ap, void *);
561 break;
562 case 'c':
563 log.loginfo[i++] = (intptr_t)va_arg(ap, int_t);
564 break;
565 case 's':
566 log.loginfo[i++] = (intptr_t)va_arg(ap, const char *);
567 break;
568 case '\0':
569 format--;
570 break;
571 default:
572 break;
573 }
574 }
575 va_end(ap);
576
577#ifdef TARGET_KERNEL_ASP
578
579 return(syslog_wri_log(prio, &log));
580
581#endif /* of #ifdef TARGET_KERNEL_ASP */
582
583#ifdef TARGET_KERNEL_JSP
584
585 return(vwri_log(prio, &log));
586
587#endif /* of #ifdef TARGET_KERNEL_JSP */
588
589 }
590 }
591
592#endif /* of #ifdef USE_NET_CONS */
Note: See TracBrowser for help on using the repository browser.