source: rubycfg_asp/trunk/asp_dcre/tinet/netinet/tcp_subr.c@ 313

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

ソースを追加

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
  • Property svn:mime-type set to text/x-csrc
File size: 51.2 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 * 上記著作権者
8は,以下の (1)~(4) の条件か,Free Software Foundation
9 * によってå…
10¬è¡¨ã•ã‚Œã¦ã„ã‚‹ GNU General Public License の Version 2 に記
11 * 述されている条件を満たす場合に限り,本ソフトウェア(本ソフトウェア
12 * を改変したものを含む.以下同じ)を使用・複製・改変・再é…
13å¸ƒï¼ˆä»¥ä¸‹ï¼Œ
14 * 利用と呼ぶ)することを無償で許諾する.
15 * (1) 本ソフトウェアをソースコードの形で利用する場合には,上記の著作
16 * 権表示,この利用条件および下記の無保証規定が,そのままの形でソー
17 * スコード中に含まれていること.
18 * (2) 本ソフトウェアを,ライブラリ形式など,他のソフトウェア開発に使
19 * 用できる形で再é…
20å¸ƒã™ã‚‹å ´åˆã«ã¯ï¼Œå†é…
21å¸ƒã«ä¼´ã†ãƒ‰ã‚­ãƒ¥ãƒ¡ãƒ³ãƒˆï¼ˆåˆ©ç”¨
22 * 者
23マニュアルなど)に,上記の著作権表示,この利用条件および下記
24 * の無保証規定を掲載すること.
25 * (3) 本ソフトウェアを,機器に組み込むなど,他のソフトウェア開発に使
26 * 用できない形で再é…
27å¸ƒã™ã‚‹å ´åˆã«ã¯ï¼Œæ¬¡ã®æ¡ä»¶ã‚’満たすこと.
28 * (a) 再é…
29å¸ƒã«ä¼´ã†ãƒ‰ã‚­ãƒ¥ãƒ¡ãƒ³ãƒˆï¼ˆåˆ©ç”¨è€…
30マニュアルなど)に,上記の著
31 * 作権表示,この利用条件および下記の無保証規定を掲載すること.
32 * (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
33 * 害からも,上記著作権者
34およびTOPPERSプロジェクトをå…
35è²¬ã™ã‚‹ã“と.
36 *
37 * 本ソフトウェアは,無保証で提供されているものである.上記著作権者
38お
39 * よびTOPPERSプロジェクトは,本ソフトウェアに関して,その適用可能性も
40 * 含めて,いかなる保証も行わない.また,本ソフトウェアの利用により直
41 * 接的または間接的に生じたいかなる損害に関しても,その責任を負わない.
42 *
43 * @(#) $Id: tcp_subr.c 313 2017-07-23 04:50:32Z coas-nagasima $
44 */
45
46/*
47 * Copyright (c) 1982, 1986, 1988, 1990, 1993, 1995
48 * The Regents of the University of California. All rights reserved.
49 *
50 * Redistribution and use in source and binary forms, with or without
51 * modification, are permitted provided that the following conditions
52 * are met:
53 * 1. Redistributions of source code must retain the above copyright
54 * notice, this list of conditions and the following disclaimer.
55 * 2. Redistributions in binary form must reproduce the above copyright
56 * notice, this list of conditions and the following disclaimer in the
57 * documentation and/or other materials provided with the distribution.
58 * 3. All advertising materials mentioning features or use of this software
59 * must display the following acknowledgement:
60 * This product includes software developed by the University of
61 * California, Berkeley and its contributors.
62 * 4. Neither the name of the University nor the names of its contributors
63 * may be used to endorse or promote products derived from this software
64 * without specific prior written permission.
65 *
66 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
67 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
68 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
69 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
70 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
71 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
72 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
73 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
74 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
75 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
76 * SUCH DAMAGE.
77 *
78 * @(#)tcp_subr.c 8.2 (Berkeley) 5/24/95
79 * $FreeBSD: src/sys/netinet/tcp_subr.c,v 1.49.2.4 1999/08/29 16:29:55 peter Exp $
80 */
81
82#include <stdarg.h>
83#include <string.h>
84
85#ifdef TARGET_KERNEL_ASP
86
87#include <kernel.h>
88#include <sil.h>
89#include <syssvc/serial.h>
90#include <syssvc/logtask.h>
91#include <t_syslog.h>
92#include "kernel_cfg.h"
93
94#endif /* of #ifdef TARGET_KERNEL_ASP */
95
96#ifdef TARGET_KERNEL_JSP
97
98#include <s_services.h>
99#include <t_services.h>
100#include "kernel_id.h"
101
102#endif /* of #ifdef TARGET_KERNEL_JSP */
103
104#include <tinet_defs.h>
105#include <tinet_config.h>
106
107#include <net/if.h>
108#include <net/if_ppp.h>
109#include <net/if_loop.h>
110#include <net/ethernet.h>
111#include <net/net.h>
112#include <net/net_endian.h>
113#include <net/net_var.h>
114#include <net/net_buf.h>
115#include <net/net_timer.h>
116#include <net/net_count.h>
117
118#include <netinet/in.h>
119#include <netinet/in_var.h>
120#include <netinet/in_itron.h>
121#include <netinet/ip.h>
122#include <netinet/ip_var.h>
123#include <netinet/tcp.h>
124#include <netinet/tcp_var.h>
125#include <netinet/tcp_fsm.h>
126#include <netinet/tcp_seq.h>
127#include <netinet/tcp_timer.h>
128
129#ifdef SUPPORT_TCP
130
131/*
132 * å…
133¨åŸŸå¤‰æ•°
134 */
135
136/*
137 * TCP の SEQ の初期値、プログラムが起動して、最初に TCP セグメントを
138 * 送受信するときに、get_tim() により初期化する。
139 */
140T_TCP_SEQ tcp_iss = 0;
141
142#ifdef SUPPORT_MIB
143
144/*
145 * SNMP の 管理情
146報ベース (MIB)
147 */
148
149T_TCP_STATS tcp_stats;
150
151#endif /* of #ifdef SUPPORT_MIB */
152
153/*
154 * 局所変数
155 */
156
157static uint16_t tcp_port_auto = TCP_PORT_FIRST_AUTO; /* 自動割り当て番号 */
158
159#if defined(NUM_TCP_TW_CEP_ENTRY) && NUM_TCP_TW_CEP_ENTRY > 0
160
161/*
162 * タスクからの Time Wait 状æ…
163‹ CEP 分離機能
164 */
165
166/*
167 * 変数
168 */
169
170T_TCP_TWCEP tcp_twcep[NUM_TCP_TW_CEP_ENTRY];
171
172/*
173 * tcp_move_twcep -- 必
174要な情
175報を Time Wait 用 TCP 通信端点に移して、
176 * 標準の TCP 通信端点を開放する。
177 */
178
179void
180tcp_move_twcep (T_TCP_CEP *cep)
181{
182 T_TCP_TWCEP* twcep;
183
184 /* 空きの Time Wait 用 TCP 通信端点を探索する。*/
185 for (twcep = &tcp_twcep[NUM_TCP_TW_CEP_ENTRY]; twcep -- != tcp_twcep; ) {
186 if (twcep->fsm_state != TCP_FSM_TIME_WAIT) {
187
188 /*
189 * 通信端点をロックし、
190 * 必
191要な情
192報を Time Wait 用 TCP 通信端点に移す。
193 */
194 syscall(wai_sem(cep->semid_lock));
195 twcep->flags = (uint8_t)cep->flags;
196 twcep->rbufsz = cep->rbufsz;
197 twcep->dstaddr = cep->dstaddr;
198 twcep->myaddr = cep->myaddr;
199 twcep->snd_una = cep->snd_una;
200 twcep->rcv_nxt = cep->rcv_nxt;
201 twcep->rwbuf_count = cep->rwbuf_count;
202 twcep->fsm_state = cep->fsm_state;
203 twcep->timer_2msl = cep->timer[TCP_TIM_2MSL];
204
205 /* 通信端点をロックを解除する。*/
206 syscall(sig_sem(cep->semid_lock));
207
208 /* 標準 TCP 通信端点を開放する。*/
209 tcp_close(cep);
210
211 break;
212 }
213 }
214 }
215
216/*
217 * tcp_find_twcep -- ポート番号から Time Wait 用 TCP 通信端点を得る。
218 */
219
220T_TCP_TWCEP*
221tcp_find_twcep (T_NET_BUF *input, uint_t off)
222{
223 T_TCP_TWCEP* twcep;
224 T_TCP_HDR *tcph;
225
226 tcph = GET_TCP_HDR(input, off);
227
228 /*
229 * 状æ…
230‹ãŒ TIME WAIT で、
231 * IP アドレスとポート番号が一致する通信端点を探索する。
232 */
233 for (twcep = &tcp_twcep[NUM_TCP_TW_CEP_ENTRY]; twcep -- != tcp_twcep; ) {
234 if (twcep->fsm_state == TCP_FSM_TIME_WAIT &&
235 IN_IS_DSTADDR_ACCEPT (&twcep->myaddr.ipaddr, input) &&
236 IN_ARE_NET_SRCADDR_EQUAL(&twcep->dstaddr.ipaddr, input) &&
237 tcph->dport == twcep->myaddr.portno &&
238 tcph->sport == twcep->dstaddr.portno)
239 return twcep;
240 }
241
242 return NULL;
243 }
244
245#endif /* of #if defined(NUM_TCP_TW_CEP_ENTRY) && NUM_TCP_TW_CEP_ENTRY > 0 */
246
247/*
248 * tcp_find_cep -- ポート番号から TCP 通信端点を得る。
249 */
250
251T_TCP_CEP*
252tcp_find_cep (T_NET_BUF *input, uint_t off)
253{
254 T_TCP_CEP* cep;
255 T_TCP_HDR *tcph;
256
257 tcph = GET_TCP_HDR(input, off);
258
259 /*
260 * 状æ…
261‹ãŒ SYN 送信済み以後は、
262 * IP アドレスとポート番号が一致する TCP 通信端点を探索する。
263 */
264 for (cep = &tcp_cep[tmax_tcp_cepid]; cep -- != tcp_cep; ) {
265 if (cep->fsm_state >= TCP_FSM_SYN_SENT &&
266 IN_IS_DSTADDR_ACCEPT (&cep->myaddr.ipaddr, input) &&
267 IN_ARE_NET_SRCADDR_EQUAL(&cep->dstaddr.ipaddr, input) &&
268 tcph->dport == cep->myaddr.portno &&
269 tcph->sport == cep->dstaddr.portno)
270 return cep;
271 }
272
273 /* IPv4 で受動オープン中の TCP 通信端点をå…
274ˆã«æŽ¢ç´¢ã™ã‚‹ã€‚*/
275 for (cep = &tcp_cep[tmax_tcp_cepid]; cep -- != tcp_cep; ) {
276 if ((cep->flags & TCP_CEP_FLG_IPV4) &&
277 cep->fsm_state == TCP_FSM_LISTEN &&
278 GET_IP_VER(input) == IPV4_VERSION &&
279 IN_IS_DSTADDR_ACCEPT(&cep->myaddr.ipaddr, input) &&
280 tcph->dport == cep->myaddr.portno)
281 return cep;
282 }
283
284 /* 受動オープン中の TCP 通信端点を探索する。*/
285 for (cep = &tcp_cep[tmax_tcp_cepid]; cep -- != tcp_cep; ) {
286
287#if defined(_IP6_CFG) && defined(_IP4_CFG)
288
289 if (cep->flags & TCP_CEP_FLG_IPV4) {
290 if (cep->fsm_state == TCP_FSM_LISTEN &&
291 GET_IP_VER(input) == IPV4_VERSION &&
292 IN_IS_DSTADDR_ACCEPT(&cep->myaddr.ipaddr, input) &&
293 tcph->dport == cep->myaddr.portno)
294 return cep;
295 }
296 else {
297
298#if defined(API_CFG_IP4MAPPED_ADDR)
299
300 if (cep->fsm_state == TCP_FSM_LISTEN &&
301 IN_IS_DSTADDR_ACCEPT(&cep->myaddr.ipaddr, input) &&
302 tcph->dport == cep->myaddr.portno)
303 return cep;
304
305#else /* of #if defined(API_CFG_IP4MAPPED_ADDR) */
306
307 if (cep->fsm_state == TCP_FSM_LISTEN &&
308 INN6_IS_DSTADDR_ACCEPT(&cep->myaddr.ipaddr, input) &&
309 tcph->dport == cep->myaddr.portno)
310 return cep;
311
312#endif /* of #if defined(API_CFG_IP4MAPPED_ADDR) */
313
314 }
315
316#else /* of #if defined(_IP6_CFG) && defined(_IP4_CFG) */
317
318 if (cep->fsm_state == TCP_FSM_LISTEN &&
319 IN_IS_DSTADDR_ACCEPT(&cep->myaddr.ipaddr, input) &&
320 tcph->dport == cep->myaddr.portno)
321 return cep;
322
323#endif /* of #if defined(_IP6_CFG) && defined(_IP4_CFG) */
324 }
325
326 return NULL;
327 }
328
329/*
330 * tcp_is_addr_accept -- 受信可能な IP アドレスとポート番号であることを確認する。
331 */
332
333bool_t
334tcp_is_addr_accept (T_NET_BUF *input, uint_t off)
335{
336 T_TCP_HDR *tcph;
337
338 tcph = GET_TCP_HDR(input, off);
339
340#if !defined(_IP6_CFG) && defined(_IP4_CFG) && defined(SUPPORT_LOOP)
341
342 /*
343 * 次のときは破棄する。
344 * ・ポート番号が同一で、送受信 IP アドレス が同一。
345 * ただし、送信å…
346ƒ IP アドレスがローカルループバックなら良い。
347 * ・マルチキャストアドレス
348 */
349
350 if (tcph->dport == tcph->sport &&
351 (IN4_ARE_HDR_ADDR_EQUAL(input) && !IN4_ARE_NET_ADDR_EQUAL(&GET_IP4_HDR(input)->dst, &IPV4_ADDR_LOOPBACK)))
352 return RET_DROP;
353
354#else /* of #if !defined(_IP6_CFG) && defined(_IP4_CFG) && defined(SUPPORT_LOOP) */
355
356 /*
357 * 次のときは、受信可能ではない。
358 * ・ポート番号が同一で、送受信 IP アドレス が同一。
359 * ・マルチキャストアドレス
360 */
361 if (tcph->dport == tcph->sport && IN_ARE_HDR_ADDR_EQUAL(input))
362 return false;
363
364#endif /* of #if !defined(_IP6_CFG) && defined(_IP4_CFG) && defined(SUPPORT_LOOP) */
365
366 if (IN_IS_NET_ADDR_MULTICAST(input))
367 return false;
368 else
369 return true;
370 }
371
372/*
373 * tcp_free_reassq -- 受信再構成キューのネットワークバッファを解放する。
374 *
375 * 注意:
376 * 必
377要であれば、この関数を呼び出す前に、通信端点をロックし、
378 * 戻った後、解除する必
379要がある。
380 */
381
382void
383tcp_free_reassq (T_TCP_CEP *cep)
384{
385 T_NET_BUF *q, *nq;
386
387 for (q = cep->reassq; q != NULL; q = nq) {
388 nq = GET_TCP_Q_HDR(q, GET_IP_TCP_Q_HDR_OFFSET(q))->next;
389 syscall(rel_net_buf(q));
390 }
391 cep->reassq = NULL;
392 NET_COUNT_TCP(net_count_tcp[NC_TCP_FREE_RCV_QUEUE], 1);
393 }
394
395/*
396 * tcp_alloc_auto_port -- 自動割り当てポート番号を設定する。
397 */
398
399void
400tcp_alloc_auto_port (T_TCP_CEP *cep)
401{
402 int_t ix;
403 uint16_t portno;
404
405 while (true) {
406 portno = tcp_port_auto ++;
407 if (tcp_port_auto > TCP_PORT_LAST_AUTO)
408 tcp_port_auto = TCP_PORT_FIRST_AUTO;
409
410#if defined(TNUM_TCP6_REPID)
411#if TNUM_TCP6_REPID > 0
412
413 for (ix = tmax_tcp6_repid; ix -- > 0; ) {
414
415#ifdef TCP_CFG_EXTENTIONS
416
417 if (VALID_TCP_REP(&tcp6_rep[ix]) && tcp6_rep[ix].myaddr.portno == portno) {
418 portno = TCP_PORTANY;
419 break;
420 }
421
422#else /* of #ifdef TCP_CFG_EXTENTIONS */
423
424 if (tcp6_rep[ix].myaddr.portno == portno) {
425 portno = TCP_PORTANY;
426 break;
427 }
428
429#endif /* of #ifdef TCP_CFG_EXTENTIONS */
430
431 }
432
433#endif /* of #if TNUM_TCP6_REPID > 0 */
434#endif /* of #if defined(TNUM_TCP6_REPID) */
435
436#if defined(TNUM_TCP4_REPID)
437#if TNUM_TCP4_REPID > 0
438
439 for (ix = tmax_tcp4_repid; ix -- > 0; ) {
440
441#ifdef TCP_CFG_EXTENTIONS
442
443 if (VALID_TCP_REP(&tcp4_rep[ix]) && tcp4_rep[ix].myaddr.portno == portno) {
444 portno = TCP_PORTANY;
445 break;
446 }
447
448#else /* of #ifdef TCP_CFG_EXTENTIONS */
449
450 if (tcp4_rep[ix].myaddr.portno == portno) {
451 portno = TCP_PORTANY;
452 break;
453 }
454
455#endif /* of #ifdef TCP_CFG_EXTENTIONS */
456
457 }
458
459#endif /* of #if TNUM_TCP4_REPID > 0 */
460#endif /* of #if defined(TNUM_TCP4_REPID) */
461
462 if (portno != TCP_PORTANY) {
463
464 syscall(wai_sem(SEM_TCP_CEP));
465 for (ix = tmax_tcp_cepid; ix -- > 0; ) {
466 if (VALID_TCP_CEP(&tcp_cep[ix]) && tcp_cep[ix].myaddr.portno == portno) {
467 portno = TCP_PORTANY;
468 break;
469 }
470 }
471
472 if (portno != TCP_PORTANY) {
473 cep->myaddr.portno = portno;
474 syscall(sig_sem(SEM_TCP_CEP));
475 return;
476 }
477 syscall(sig_sem(SEM_TCP_CEP));
478 }
479 }
480 }
481
482/*
483 * tcp_alloc_port -- 指定されたポート番号を設定する。
484 */
485
486ER
487tcp_alloc_port (T_TCP_CEP *cep, uint16_t portno)
488{
489 int_t ix;
490
491 syscall(wai_sem(SEM_TCP_CEP));
492 for (ix = tmax_tcp_cepid; ix -- > 0; )
493 if (VALID_TCP_CEP(cep) && tcp_cep[ix].myaddr.portno == portno) {
494 syscall(sig_sem(SEM_TCP_CEP));
495 return E_PAR;
496 }
497 cep->myaddr.portno = portno;
498 syscall(sig_sem(SEM_TCP_CEP));
499 return E_OK;
500 }
501
502/*
503 * tcp_init -- TCP モジュールの初期化
504 */
505
506void
507tcp_init (void)
508{
509 timeout(tcp_slow_timo, NULL, TCP_SLOW_TMO);
510
511#ifdef TCP_CFG_DELAY_ACK
512
513 timeout(tcp_fast_timo, NULL, TCP_FAST_TMO);
514
515#endif/* of #ifdef TCP_CFG_DELAY_ACK */
516 }
517
518/*
519 * tcp_init_iss シーケンス番号を初期化する。
520 */
521
522void
523tcp_init_iss (void)
524{
525 SYSTIM now;
526
527 syscall(get_tim(&now));
528 net_srand(now);
529 tcp_iss = net_rand();
530 }
531
532/*
533 * tcp_close -- コネクションを開放する。
534 */
535
536T_TCP_CEP *
537tcp_close (T_TCP_CEP *cep)
538{
539 /* タイマーを停止する。*/
540 tcp_cancel_timers(cep);
541
542 /*
543 * 通信端点をロックし、
544 * 受信再構成キューのネットワークバッファを解放する。
545 */
546 syscall(wai_sem(cep->semid_lock));
547 tcp_free_reassq(cep);
548 syscall(sig_sem(cep->semid_lock));
549
550 /* 状æ…
551‹ã‚’未使用にする。*/
552 cep->fsm_state = TCP_FSM_CLOSED;
553
554 /*
555 * 以下に関係しないフラグをクリアーする。
556 * ・送受信ウィンドバッファの省コピー機能
557 * ・動的な通信端点の生成・削除機能
558 * ・通信端点のネットワーク層プロトコル
559 */
560 cep->flags &= TCP_CEP_FLG_NOT_CLEAR;
561
562#ifdef TCP_CFG_NON_BLOCKING
563
564 if (cep->snd_nblk_tfn != TFN_TCP_UNDEF || cep->rcv_nblk_tfn != TFN_TCP_UNDEF) {
565 /* ノンブロッキングコール */
566
567#ifdef TCP_CFG_NON_BLOCKING_COMPAT14
568
569 if (!IS_PTR_DEFINED(cep->callback))
570 syslog(LOG_WARNING, "[TCP] no call back, CEP: %d.", GET_TCP_CEPID(cep));
571 else {
572 if (cep->rcv_nblk_tfn != TFN_TCP_UNDEF) {
573 ER_UINT len;
574
575 switch (cep->rcv_nblk_tfn) {
576
577 case TFN_TCP_ACP_CEP:
578 /* TCP 通信端点からTCP 受付口を解放する。*/
579 cep->rep = NULL;
580
581#if defined(_IP6_CFG) && defined(_IP4_CFG)
582 cep->rep4 = NULL;
583#endif
584
585 (*cep->callback)(GET_TCP_CEPID(cep), cep->rcv_nblk_tfn, (void*)E_CLS);
586 break;
587
588 case TFN_TCP_RCV_BUF:
589
590 /* 受信ウィンドバッファの空アドレスを獲得する。*/
591 len = TCP_GET_RWBUF_ADDR(cep, cep->rcv_p_buf);
592
593 /* 異常切断等のエラーを設定する。*/
594 if (cep->error == E_TMOUT)
595 len = E_CLS;
596 else if (cep->error < 0)
597 len = cep->error;
598
599 (*cep->callback)(GET_TCP_CEPID(cep), cep->rcv_nblk_tfn, (void*)(uint32_t)len);
600 break;
601
602 case TFN_TCP_RCV_DAT:
603
604 /* 受信ウィンドバッファからデータを取り出す。*/
605 len = TCP_READ_RWBUF(cep, cep->rcv_data, (uint_t)cep->rcv_len);
606
607 /* 異常切断等のエラーを設定する。*/
608 if (cep->error == E_TMOUT)
609 len = E_CLS;
610 else if (cep->error != E_OK)
611 len = cep->error;
612
613 (*cep->callback)(GET_TCP_CEPID(cep), cep->rcv_nblk_tfn, (void*)(uint32_t)len);
614 break;
615
616 case TFN_TCP_CLS_CEP:
617
618 if (cep->error == E_TMOUT)
619 (*cep->callback)(GET_TCP_CEPID(cep), cep->rcv_nblk_tfn, (void*)E_CLS);
620 else
621 (*cep->callback)(GET_TCP_CEPID(cep), cep->rcv_nblk_tfn, (void*)cep->error);
622 break;
623
624 default:
625 syslog(LOG_WARNING, "[TCP] unexp TFN: %s.", in_strtfn((FN)cep->rcv_nblk_tfn));
626 break;
627 }
628
629 /* 記憶されているタスク ID と API 機能コードをクリアーする。*/
630 cep->rcv_tskid = TA_NULL;
631 cep->rcv_tfn = cep->rcv_nblk_tfn = TFN_TCP_UNDEF;
632 }
633
634 if (cep->snd_nblk_tfn != TFN_TCP_UNDEF) {
635
636 switch (cep->snd_nblk_tfn) {
637
638 case TFN_TCP_CON_CEP:
639 /* TCP 通信端点から TCP 受付口を解放する。*/
640 cep->rep = NULL;
641
642#if defined(_IP6_CFG) && defined(_IP4_CFG)
643 cep->rep4 = NULL;
644#endif
645
646 (*cep->callback)(GET_TCP_CEPID(cep), cep->snd_nblk_tfn, (void*)E_CLS);
647 break;
648
649 case TFN_TCP_SND_DAT:
650 case TFN_TCP_GET_BUF:
651 if (cep->error == E_TMOUT)
652 (*cep->callback)(GET_TCP_CEPID(cep), cep->snd_nblk_tfn, (void*)E_CLS);
653 else
654 (*cep->callback)(GET_TCP_CEPID(cep), cep->snd_nblk_tfn, (void*)cep->error);
655 break;
656
657 default:
658 syslog(LOG_WARNING, "[TCP] unexp TFN: %s.", in_strtfn((FN)cep->snd_nblk_tfn));
659 break;
660 }
661
662 /* 記憶されているタスク ID と API 機能コードをクリアーする。*/
663 cep->snd_tskid = TA_NULL;
664 cep->snd_tfn = cep->snd_nblk_tfn = TFN_TCP_UNDEF;
665 }
666
667 }
668
669#else /* of #ifdef TCP_CFG_NON_BLOCKING_COMPAT14 */
670
671 if (!IS_PTR_DEFINED(cep->callback))
672 syslog(LOG_WARNING, "[TCP] no call back, CEP: %d.", GET_TCP_CEPID(cep));
673 else {
674 if (cep->rcv_nblk_tfn != TFN_TCP_UNDEF) {
675 ER_UINT len;
676
677 switch (cep->rcv_nblk_tfn) {
678
679 case TFN_TCP_ACP_CEP:
680
681 /* TCP 通信端点からTCP 受付口を解放する。*/
682 cep->rep = NULL;
683
684#if defined(_IP6_CFG) && defined(_IP4_CFG)
685 cep->rep4 = NULL;
686#endif
687
688 /* 接続エラーを設定する。*/
689 len = E_CLS;
690 (*cep->callback)(GET_TCP_CEPID(cep), cep->rcv_nblk_tfn, (void*)&len);
691 break;
692
693 case TFN_TCP_RCV_BUF:
694
695 /* 受信ウィンドバッファの空アドレスを獲得する。*/
696 len = TCP_GET_RWBUF_ADDR(cep, cep->rcv_p_buf);
697
698 /* 異常切断等のエラーを設定する。*/
699 if (cep->error == E_TMOUT)
700 len = E_CLS;
701 else if (cep->error < 0)
702 len = cep->error;
703
704 (*cep->callback)(GET_TCP_CEPID(cep), cep->rcv_nblk_tfn, (void*)&len);
705 break;
706
707 case TFN_TCP_RCV_DAT:
708
709 /* 受信ウィンドバッファからデータを取り出す。*/
710 len = TCP_READ_RWBUF(cep, cep->rcv_data, (uint_t)cep->rcv_len);
711
712 /* 異常切断等のエラーを設定する。*/
713 if (cep->error == E_TMOUT)
714 len = E_CLS;
715 else if (cep->error != E_OK)
716 len = cep->error;
717
718 (*cep->callback)(GET_TCP_CEPID(cep), cep->rcv_nblk_tfn, (void*)&len);
719 break;
720
721 case TFN_TCP_CLS_CEP:
722 if (cep->error == E_TMOUT)
723 len = E_CLS;
724 else
725 len = cep->error;
726 (*cep->callback)(GET_TCP_CEPID(cep), cep->rcv_nblk_tfn, (void*)&len);
727 break;
728
729 default:
730 syslog(LOG_WARNING, "[TCP] unexp TFN: %s.", in_strtfn((FN)cep->rcv_nblk_tfn));
731 break;
732 }
733
734 /* 記憶されているタスク ID と API 機能コードをクリアーする。*/
735 cep->rcv_tskid = TA_NULL;
736 cep->rcv_tfn = cep->rcv_nblk_tfn = TFN_TCP_UNDEF;
737 }
738
739 if (cep->snd_nblk_tfn != TFN_TCP_UNDEF) {
740 ER_UINT len;
741
742 switch (cep->snd_nblk_tfn) {
743
744 case TFN_TCP_CON_CEP:
745
746 /* TCP 通信端点からTCP 受付口を解放する。*/
747 cep->rep = NULL;
748
749#if defined(_IP6_CFG) && defined(_IP4_CFG)
750 cep->rep4 = NULL;
751#endif
752
753 /* 接続エラーを設定する。*/
754 len = E_CLS;
755 (*cep->callback)(GET_TCP_CEPID(cep), cep->snd_nblk_tfn, (void*)&len);
756 break;
757
758 case TFN_TCP_SND_DAT:
759 case TFN_TCP_GET_BUF:
760 if (cep->error == E_TMOUT)
761 len = E_CLS;
762 else
763 len = cep->error;
764 (*cep->callback)(GET_TCP_CEPID(cep), cep->rcv_nblk_tfn, (void*)&len);
765 break;
766
767 default:
768 syslog(LOG_WARNING, "[TCP] unexp TFN: %s.", in_strtfn((FN)cep->snd_nblk_tfn));
769 break;
770 }
771
772 /* 記憶されているタスク ID と API 機能コードをクリアーする。*/
773 cep->snd_tskid = TA_NULL;
774 cep->snd_tfn = cep->snd_nblk_tfn = TFN_TCP_UNDEF;
775 }
776
777 }
778
779#endif /* of #ifdef TCP_CFG_NON_BLOCKING_COMPAT14 */
780
781 /*
782 * 通信端点をロックし、
783 * 送受信ウィンドバッファキューのネットワークバッファを解放する。
784 */
785 syscall(wai_sem(cep->semid_lock));
786 TCP_FREE_RWBUFQ(cep);
787 TCP_FREE_SWBUFQ(cep);
788 syscall(sig_sem(cep->semid_lock));
789
790 /* 未使用になったことを知らせる。*/
791 syscall(set_flg(cep->est_flgid, TCP_CEP_EVT_CLOSED));
792 }
793 else { /* 非ノンブロッキングコール */
794
795#endif /* of #ifdef TCP_CFG_NON_BLOCKING */
796
797 /* 記憶されているタスク ID と API 機能コードをクリアーする。*/
798 cep->snd_tskid = cep->rcv_tskid = TA_NULL;
799 cep->snd_tfn = cep->rcv_tfn = TFN_TCP_UNDEF;
800
801 /*
802 * 通信端点をロックし、
803 * 送受信ウィンドバッファキューのネットワークバッファを解放する。
804 */
805 syscall(wai_sem(cep->semid_lock));
806 TCP_FREE_RWBUFQ(cep);
807 TCP_FREE_SWBUFQ(cep);
808 syscall(sig_sem(cep->semid_lock));
809
810 /* 未使用になったことを知らせる。*/
811 syscall(set_flg(cep->est_flgid, TCP_CEP_EVT_CLOSED));
812
813 /*
814 * å…
815¥å‡ºåŠ›ã‚¿ã‚¹ã‚¯ã‚’起床して、
816 * 送受信不可になったことを知らせる。
817 */
818 syscall(set_flg(cep->snd_flgid, TCP_CEP_EVT_SWBUF_READY));
819 syscall(set_flg(cep->rcv_flgid, TCP_CEP_EVT_RWBUF_READY));
820
821#ifdef TCP_CFG_NON_BLOCKING
822
823 }
824
825#endif /* of #ifdef TCP_CFG_NON_BLOCKING */
826
827 return NULL;
828 }
829
830/*
831 * tcp_drop -- TCP 接続を破棄する。
832 */
833
834T_TCP_CEP *
835tcp_drop (T_TCP_CEP *cep, ER errno)
836{
837#ifdef SUPPORT_MIB
838
839 if ((cep->fsm_state == TCP_FSM_SYN_SENT) || (cep->fsm_state == TCP_FSM_SYN_RECVD)) {
840 NET_COUNT_MIB(tcp_stats.tcpAttemptFails, 1);
841 }
842
843#endif /* of #ifdef SUPPORT_MIB */
844
845 cep->error = errno;
846 if (TCP_FSM_HAVE_RCVD_SYN(cep->fsm_state)) {
847 cep->fsm_state = TCP_FSM_CLOSED;
848
849 /* 送信と、送信後コネクションの切断を指示する。*/
850 cep->flags |= TCP_CEP_FLG_POST_OUTPUT | TCP_CEP_FLG_CLOSE_AFTER_OUTPUT;
851 sig_sem(SEM_TCP_POST_OUTPUT);
852 }
853 else {
854 cep = tcp_close(cep);
855 }
856 return cep;
857 }
858
859/*
860 * tcp_respond -- TCP の単一メッセージを送信する。
861 */
862
863void
864tcp_respond (T_NET_BUF *output, T_TCP_CEP *cep,
865 T_TCP_SEQ ack, T_TCP_SEQ seq, uint_t rbfree, uint8_t flags)
866{
867 T_TCP_HDR *tcph;
868 uint_t win = 0;
869 uint_t hdr_offset;
870
871 if ((flags & TCP_FLG_RST) == 0)
872 win = rbfree;
873
874 /*
875 * output が NULL でなければ、これはå…
876¥åŠ›ã—たセグメントの
877 * net_buf で、そのまま再利用する。
878 */
879 if (output != NULL) {
880 uint16_t portno;
881
882 /*
883 * IPv4 では、IP ヘッダのオプションを削除する。
884 * IPv6 では、拡張ヘッダを削除する。
885 */
886 if (IP_REMOVE_OPTIONS(output) != E_OK) {
887 syscall(rel_net_buf(output));
888 return;
889 }
890
891 ip_exchg_addr(output);
892
893#if defined(_IP6_CFG)
894
895 /* トラヒッククラスとフローラベルをクリアする。*/
896 SET_IP_CF(output, 0);
897
898#endif /* of #if defined(_IP6_CFG) */
899
900 /* TCP SDU 長を 0 にする。*/
901 SET_IP_SDU_SIZE(output, TCP_HDR_SIZE);
902
903 tcph = GET_TCP_HDR(output, IF_IP_TCP_HDR_OFFSET(output));
904
905 /* ポート番号を交換する。*/
906 portno = tcph->sport;
907 tcph->sport = tcph->dport;
908 tcph->dport = portno;
909
910 /* TCP ヘッダに情
911報を設定する。*/
912 tcph->doff = TCP_MAKE_DATA_OFF(TCP_HDR_SIZE);
913 }
914
915 /* cep が NULL であれば、何もしないで終了する。*/
916 else if (cep == NULL)
917 return;
918 else {
919 if (tcpn_get_segment(&output, cep, 0,
920 0, (uint_t)net_buf_max_siz(),
921 NBA_SEARCH_ASCENT, TMO_TCP_GET_NET_BUF) != E_OK)
922 return;
923 tcph = GET_TCP_HDR(output, IF_IP_TCP_HDR_OFFSET(output));
924 flags |= TCP_FLG_ACK;
925 }
926
927 tcph->seq = htonl(seq);
928 tcph->ack = htonl(ack);
929 tcph->win = htons(win);
930 tcph->flags = flags;
931 tcph->urp = tcph->sum = 0;
932
933 /*
934 * チェックサムを設定する。
935 */
936 hdr_offset = IF_IP_TCP_HDR_OFFSET(output);
937 tcph->sum = IN_CKSUM(output, IPPROTO_TCP, hdr_offset,
938 (uint_t)GET_TCP_HDR_SIZE(output, hdr_offset));
939
940 /* ネットワークバッファ長を調整する。*/
941 output->len = (uint16_t)GET_IF_IP_TCP_HDR_SIZE(output, hdr_offset);
942
943#ifdef TCP_CFG_TRACE
944
945 tcp_output_trace(output, cep);
946
947#endif /* of #ifdef TCP_CFG_TRACE */
948
949 /* ネットワーク層 (IP) の出力関数を呼び出す。*/
950 IP_OUTPUT(output, TMO_TCP_OUTPUT);
951 }
952#if 0
953/*
954 * tcp_get_segment -- TCP セグメントを獲得し、ヘッダを設定する。
955 *
956 * 戻り値 エラーコード
957 * optlen オプションサイズ、4 オクテット単位
958 * maxlen 最大セグメントサイズ(IF/IP/TCP ヘッダサイズを含まない)
959 * len TCP SDU サイズ
960 */
961
962ER
963tcp_get_segment (T_NET_BUF **nbuf, T_TCP_CEP *cep,
964 uint_t optlen, uint_t len, uint_t maxlen, ATR nbatr, TMO tmout)
965{
966 T_TCP_HDR *tcph;
967 ER error;
968
969 /* IP データグラムを獲得する。*/
970 if ((error = IN_GET_DATAGRAM(nbuf,
971 (uint_t)(TCP_HDR_SIZE + optlen + len),
972 (uint_t)(TCP_HDR_SIZE + maxlen),
973 &cep->dstaddr.ipaddr,
974 &cep->myaddr.ipaddr,
975 IPPROTO_TCP, IP_DEFTTL, nbatr, tmout)) != E_OK) {
976 syslog(LOG_WARNING, "[TCP] NET BUF busy, len: %d, CEP: %d.",
977 (uint16_t)(TCP_HDR_SIZE + optlen + len), GET_TCP_CEPID(cep));
978 return error;
979 }
980
981 /* TCP ヘッダに情
982報を設定する。*/
983
984 /* TCP ヘッダに情
985報を設定する。*/
986 tcph = GET_TCP_HDR(*nbuf, IF_IP_TCP_HDR_OFFSET(*nbuf));
987 tcph->sport = htons(cep->myaddr.portno);
988 tcph->dport = htons(cep->dstaddr.portno);
989 tcph->doff = TCP_MAKE_DATA_OFF(TCP_HDR_SIZE + optlen);
990 tcph->sum = tcph->flags = 0;
991
992 return E_OK;
993 }
994#endif
995/*
996 * tcpn_get_segment -- TCP セグメントを獲得し、ヘッダを設定する。
997 *
998 * 戻り値 エラーコード
999 * optlen オプションサイズ、4 オクテット単位
1000 * maxlen 最大セグメントサイズ(IF/IP/TCP ヘッダサイズを含む)
1001 * len TCP SDU サイズ
1002 */
1003
1004ER
1005tcpn_get_segment (T_NET_BUF **nbuf, T_TCP_CEP *cep,
1006 uint_t optlen, uint_t len, uint_t maxlen, ATR nbatr, TMO tmout)
1007{
1008 T_TCP_HDR *tcph;
1009 ER error;
1010
1011 /* IP データグラムを獲得する。*/
1012 if ((error = IN_GET_DATAGRAM(nbuf,
1013 (uint_t)(TCP_HDR_SIZE + optlen + len),
1014 (uint_t)(maxlen - IF_IP_NET_HDR_SIZE(&cep->dstaddr.ipaddr)),
1015 &cep->dstaddr.ipaddr,
1016 &cep->myaddr.ipaddr,
1017 IPPROTO_TCP, IP_DEFTTL, nbatr, tmout)) != E_OK) {
1018 syslog(LOG_WARNING, "[TCP] NET BUF busy, len:%4d, CEP: %d.",
1019 (uint16_t)(TCP_HDR_SIZE + optlen + len), GET_TCP_CEPID(cep));
1020 return error;
1021 }
1022
1023 /* TCP ヘッダに情
1024報を設定する。*/
1025
1026 /* TCP ヘッダに情
1027報を設定する。*/
1028 tcph = GET_TCP_HDR(*nbuf, IF_IP_TCP_HDR_OFFSET(*nbuf));
1029 tcph->sport = htons(cep->myaddr.portno);
1030 tcph->dport = htons(cep->dstaddr.portno);
1031 tcph->doff = TCP_MAKE_DATA_OFF(TCP_HDR_SIZE + optlen);
1032 tcph->sum = tcph->flags = 0;
1033
1034 return E_OK;
1035 }
1036
1037/*
1038 * tcp_can_send_more -- 送信できるか、通信端点の状æ…
1039‹ã‚’見る。
1040 */
1041
1042ER
1043tcp_can_send_more (T_TCP_CEP *cep, FN fncd, TMO tmout)
1044{
1045 ER error;
1046
1047 /* 送信できるか、CEP の FSM 状æ…
1048‹ã‚’見る。*/
1049 if (!TCP_FSM_CAN_SEND_MORE(cep->fsm_state)) {
1050 if ((error = cep->error) == E_OK)
1051 error = E_OBJ;
1052
1053#ifdef TCP_CFG_NON_BLOCKING
1054
1055 /* タイムアウトをチェックする。*/
1056 if (tmout == TMO_NBLK) { /* ノンブロッキングコール */
1057
1058 if (!IS_PTR_DEFINED(cep->callback))
1059 error = E_OBJ;
1060 else {
1061 /* コールバック関数を呼び出す。*/
1062#ifdef TCP_CFG_NON_BLOCKING_COMPAT14
1063 (*cep->callback)(GET_TCP_CEPID(cep), fncd, (void*)error);
1064#else
1065 (*cep->callback)(GET_TCP_CEPID(cep), fncd, (void*)&error);
1066#endif
1067 error = E_WBLK;
1068 }
1069 }
1070
1071#endif /* of #ifdef TCP_CFG_NON_BLOCKING */
1072
1073 }
1074 else {
1075
1076#ifdef TCP_CFG_SWBUF_CSAVE
1077
1078 error = E_OK;
1079
1080#else /* of #ifdef TCP_CFG_SWBUF_CSAVE */
1081
1082 if (!IS_PTR_DEFINED(cep->sbuf)) {
1083
1084#ifdef TCP_CFG_NON_BLOCKING
1085
1086 /* タイムアウトをチェックする。*/
1087 if (tmout == TMO_NBLK) { /* ノンブロッキングコール */
1088 if (!IS_PTR_DEFINED(cep->callback))
1089 error = E_OBJ;
1090 else {
1091 error = E_OBJ;
1092
1093 /* コールバック関数を呼び出す。*/
1094#ifdef TCP_CFG_NON_BLOCKING_COMPAT14
1095 (*cep->callback)(GET_TCP_CEPID(cep), fncd, (void*)error);
1096#else
1097 (*cep->callback)(GET_TCP_CEPID(cep), fncd, (void*)&error);
1098#endif
1099 error = E_WBLK;
1100 }
1101 }
1102 else
1103
1104#endif /* of #ifdef TCP_CFG_NON_BLOCKING */
1105
1106 error = E_OBJ;
1107 }
1108 else
1109 error = E_OK;
1110
1111#endif /* of #ifdef TCP_CFG_SWBUF_CSAVE */
1112
1113 }
1114
1115 return error;
1116 }
1117
1118/*
1119 * tcp_can_recv_more -- 受信できるか、通信端点の状æ…
1120‹ã‚’見る。
1121 *
1122 * 注意: 戻り値
1123 *
1124 * E_OK 受信可能
1125 * E_OBJ 相手から切断されたか、エラーが発生した。
1126 */
1127
1128ER
1129tcp_can_recv_more (ER *error, T_TCP_CEP *cep, FN fncd, TMO tmout)
1130{
1131 /*
1132 * 受信できるか、fsm_state を見る。受信できない場合は
1133 * 長さ 0、またはエラーを返す。
1134 */
1135 if (!TCP_FSM_CAN_RECV_MORE(cep->fsm_state) &&
1136 cep->rwbuf_count == 0 && cep->reassq == NULL) {
1137 *error = cep->error;
1138
1139#ifdef TCP_CFG_NON_BLOCKING
1140
1141 /* タイムアウトをチェックする。*/
1142 if (tmout == TMO_NBLK) { /* ノンブロッキングコール */
1143
1144 if (!IS_PTR_DEFINED(cep->callback))
1145 *error = E_OBJ;
1146 else {
1147 /* コールバック関数を呼び出す。*/
1148#ifdef TCP_CFG_NON_BLOCKING_COMPAT14
1149 (*cep->callback)(GET_TCP_CEPID(cep), fncd, (void*)*error);
1150#else
1151 (*cep->callback)(GET_TCP_CEPID(cep), fncd, (void*)error);
1152#endif
1153 *error = E_WBLK;
1154 }
1155 }
1156
1157#endif /* of #ifdef TCP_CFG_NON_BLOCKING */
1158
1159 /*
1160 * 通信端点をロックして、
1161 * 受信ウィンドバッファキューのネットワークバッファを解放する。
1162 */
1163 syscall(wai_sem(cep->semid_lock));
1164 TCP_FREE_RWBUFQ(cep);
1165 syscall(sig_sem(cep->semid_lock));
1166
1167 return E_OBJ;
1168 }
1169 else {
1170
1171#ifndef TCP_CFG_RWBUF_CSAVE
1172
1173 if (!IS_PTR_DEFINED(cep->rbuf)) {
1174
1175#ifdef TCP_CFG_NON_BLOCKING
1176
1177 /* タイムアウトをチェックする。*/
1178 if (tmout == TMO_NBLK) { /* ノンブロッキングコール */
1179 if (!IS_PTR_DEFINED(cep->callback))
1180 *error = E_OBJ;
1181 else {
1182 *error = E_OBJ;
1183
1184 /* コールバック関数を呼び出す。*/
1185#ifdef TCP_CFG_NON_BLOCKING_COMPAT14
1186 (*cep->callback)(GET_TCP_CEPID(cep), fncd, (void*)*error);
1187#else
1188 (*cep->callback)(GET_TCP_CEPID(cep), fncd, (void*)error);
1189#endif
1190 *error = E_WBLK;
1191 }
1192 }
1193 else
1194
1195#endif /* of #ifdef TCP_CFG_NON_BLOCKING */
1196
1197 *error = E_OBJ;
1198
1199 return E_OBJ;
1200 }
1201
1202#endif /* of #ifndef TCP_CFG_RWBUF_CSAVE */
1203
1204 return E_OK;
1205 }
1206 }
1207
1208/*
1209 * tcp_wait_rwbuf -- 受信ウィンドバッファにデータがå…
1210¥ã‚‹ã®ã‚’å¾…
1211つ。
1212 */
1213
1214ER
1215tcp_wait_rwbuf (T_TCP_CEP *cep, TMO tmout)
1216{
1217 ER error;
1218 FLGPTN flag;
1219
1220 if (cep->rwbuf_count == 0) {
1221 /* 受信ウィンドバッファにデータがなければ、å…
1222¥åŠ›ãŒã‚るまで待
1223つ。*/
1224 while (cep->rwbuf_count == 0) {
1225 if ((error = twai_flg(cep->rcv_flgid, TCP_CEP_EVT_RWBUF_READY, TWF_ORW, &flag, tmout)) != E_OK) {
1226 return error;
1227 }
1228 syscall(clr_flg(cep->rcv_flgid, (FLGPTN)(~TCP_CEP_EVT_RWBUF_READY)));
1229
1230 /*
1231 * 受信できるか、fsm_state を見る。受信できない状æ…
1232‹ã§ã€
1233 * 受信ウィンドバッファに文字がない場合は終了する。
1234 */
1235 if (!TCP_FSM_CAN_RECV_MORE(cep->fsm_state) &&
1236 cep->rwbuf_count == 0 && cep->reassq == NULL) {
1237
1238 /*
1239 * 通信端点をロックして、
1240 * 受信ウィンドバッファキューのネットワークバッファを解放する。
1241 */
1242 syscall(wai_sem(cep->semid_lock));
1243 TCP_FREE_RWBUFQ(cep);
1244 syscall(sig_sem(cep->semid_lock));
1245
1246 return cep->error;
1247 }
1248 }
1249 }
1250 else {
1251 syscall(clr_flg(cep->rcv_flgid, (FLGPTN)(~TCP_CEP_EVT_RWBUF_READY)));
1252 }
1253
1254 return E_OK;
1255 }
1256
1257/*
1258 * tcp_move_ra2rw -- 受信再構成キューで再構成したセグメントを受信ウィンドバッファに書き込む。
1259 */
1260
1261uint8_t
1262tcp_move_ra2rw (T_TCP_CEP *cep, uint8_t flags)
1263{
1264 T_NET_BUF *q;
1265 T_TCP_Q_HDR *qhdr;
1266
1267 /*
1268 * 受信データを受信ウィンドバッファに書き込み、
1269 * rcv_nxt を完了した SEQ だけ進める。
1270 */
1271 if (TCP_FSM_HAVE_ESTABLISHED(cep->fsm_state)) {
1272 while (cep->reassq != NULL) {
1273 q = cep->reassq;
1274 qhdr = GET_TCP_Q_HDR(q, GET_IP_TCP_Q_HDR_OFFSET(q));
1275 if (qhdr->seq != cep->rcv_nxt)
1276 break;
1277
1278 /* 次のセグメントに進む。*/
1279 cep->reassq = qhdr->next;
1280
1281 /* FIN フラグのみ残す。*/
1282 flags &= TCP_FLG_FIN;
1283
1284 /* データを受信ウィンドバッファに書き込む。*/
1285 TCP_WRITE_RWBUF(cep, q, (uint_t)(GET_IP_TCP_Q_HDR_OFFSET(q)));
1286 }
1287 }
1288 if (cep->reassq != NULL) {
1289 cep->flags |= TCP_CEP_FLG_ACK_NOW;
1290 flags &= ~TCP_FLG_FIN;
1291 }
1292 return flags;
1293 }
1294
1295/*
1296 * tcp_write_raque -- 受信セグメントを再構成して、受信再構成キューに繋ぐ。
1297 */
1298
1299uint8_t
1300tcp_write_raque (T_NET_BUF *input, T_TCP_CEP *cep, uint_t thoff, uint8_t flags)
1301{
1302 T_NET_BUF *new;
1303 T_NET_BUF *p, *q, *nq;
1304 T_TCP_Q_HDR *qhdr, *inqhdr = GET_TCP_Q_HDR(input, thoff);
1305 int32_t len;
1306
1307 /* TCP ヘッダの位置を保存する。*/
1308 SET_IP_TCP_Q_HDR_OFFSET(input, thoff);
1309
1310 /*
1311 * MAX_TCP_REALLOC_SIZE 以下の場合は、新たにネットワークバッファを
1312 * 割当てて、データをコピーする。
1313 * このとき、IP のオプション(拡張ヘッダ)と TCP のオプションは削除する。
1314 */
1315 len = IF_IP_TCP_HDR_SIZE(input) + inqhdr->slen;
1316
1317 if (len <= MAX_TCP_REALLOC_SIZE) {
1318
1319 /*
1320 * ネットワークバッファが確保できないときは割当てない。
1321 */
1322 if (tget_net_buf(&new, (uint_t)len, TMO_TCP_GET_NET_BUF) != E_OK)
1323 new = NULL;
1324 }
1325 else
1326 new = NULL;
1327
1328 /*
1329 * inqhdr->seq
1330 * |
1331 * |<------- inqhdr->slen ------->|
1332 * v v
1333 * +------------------------------+
1334 * | input |
1335 * +------------------------------+
1336 * ^ ^
1337 * |<----- slen ----->|
1338 * |
1339 * soff
1340 *
1341 */
1342 inqhdr->soff = 0;
1343
1344 /*
1345 * 今回追加するセグメントより前(p)と後(q)のセグメントを探す。
1346 *
1347 * +-------------------------+
1348 * | p |
1349 * +-------------------------+
1350 * ^ +---------------------------+
1351 * p->seq | input |
1352 * +---------------------------+
1353 * ^ +-------------------------+
1354 * inqhdr->seq | q |
1355 * +-------------------------+
1356 * ^
1357 * q->seq
1358 */
1359 for (q = cep->reassq, p = NULL; q != NULL; ) {
1360 qhdr = GET_TCP_Q_HDR(q, GET_IP_TCP_Q_HDR_OFFSET(q));
1361 if (SEQ_GT(qhdr->seq, inqhdr->seq))
1362 break;
1363 p = q;
1364 q = qhdr->next;
1365 }
1366
1367 /*
1368 * 前(p)のセグメントがあれば、既に、今回と同じセグメントが
1369 * あることもある。その場合は、その部分またはå…
1370¨ã¦ã‚’破棄する。
1371 *
1372 * qhdr->seq
1373 * |
1374 * |<----- qhdr->slen ------>|
1375 * v v
1376 * +-------------------------+
1377 * | p |
1378 * +-------------------------+
1379 * <--len -->
1380 * +---------------------------+
1381 * | input |
1382 * +---------------------------+
1383 * ^
1384 * inqhdr->seq
1385 */
1386 if (p != NULL) {
1387 qhdr = GET_TCP_Q_HDR(p, GET_IP_TCP_Q_HDR_OFFSET(p));
1388 len = qhdr->seq + qhdr->slen - inqhdr->seq;
1389 if (len > 0) {
1390
1391 /*
1392 * len が正であれば、前(p) のセグメントと今回の
1393 * セグメントが重なっている。
1394 */
1395 if (len >= inqhdr->slen) {
1396
1397 /*
1398 * len が今回のセグメントと同じなら
1399 * まったく同じセグメントなので何もしない。
1400 */
1401 if (new != NULL) {
1402 syscall(rel_net_buf(new));
1403 }
1404
1405 syscall(rel_net_buf(input));
1406 return flags;
1407 }
1408
1409 /*
1410 * 追加するセグメントの SDU を len 分前に詰める。
1411 */
1412 inqhdr->seq += len;
1413 inqhdr->soff += (uint16_t)len;
1414 inqhdr->slen -= (uint16_t)len;
1415 }
1416 }
1417
1418 /*
1419 * キューにつなぐ前に、新しいネットワークバッファにデータを移す。
1420 * TCP のオプションは削除する。
1421 */
1422 if (new != NULL) {
1423 memcpy(new->buf, input->buf, (size_t)(thoff + TCP_HDR_SIZE));
1424 memcpy((uint8_t*)GET_TCP_HDR(new, thoff) + TCP_HDR_SIZE,
1425 GET_TCP_SDU(input, thoff), (size_t)(inqhdr->slen));
1426 syscall(rel_net_buf(input));
1427 input = new;
1428 inqhdr = GET_TCP_Q_HDR(input, thoff);
1429 inqhdr->doff = (uint8_t)TCP_MAKE_DATA_OFF(TCP_HDR_SIZE);
1430 }
1431
1432 /*
1433 * 重なる後(q)のセグメントを調整する。
1434 *
1435 * inqhdr->seq
1436 * |
1437 * |<----- inqhdr->slen ---->|
1438 * v v
1439 * +-------------------------+
1440 * | input |
1441 * +-------------------------+
1442 * <--len -->
1443 * +---------------------------+
1444 * | q |
1445 * +---------------------------+
1446 * ^
1447 * qhdr->seq
1448 */
1449 while (q != NULL) {
1450 qhdr = GET_TCP_Q_HDR(q, GET_IP_TCP_Q_HDR_OFFSET(q));
1451 len = inqhdr->seq + inqhdr->slen - qhdr->seq;
1452 if (len <= 0)
1453 /* len が負なら重なっていない。*/
1454 break;
1455 else if (len < qhdr->slen) {
1456
1457 /*
1458 * 後ろで重なっているセグメントの SDU を len 分前に詰める。
1459 *
1460 * inqhdr->seq
1461 * |
1462 * |<----- inqhdr->slen ---->|
1463 * v v
1464 * +-------------------------+
1465 * | input |
1466 * +-------------------------+
1467 * <--len -->
1468 * +------+---------------------------+
1469 * | | q |
1470 * +------+---------------------------+
1471 * ^--------->
1472 * qhdr->seq
1473 * qhdr->soff
1474 */
1475 qhdr->seq += len;
1476 qhdr->soff += (uint16_t)len;
1477 qhdr->slen -= (uint16_t)len;
1478 break;
1479 }
1480 nq = qhdr->next;
1481 if (p)
1482 GET_TCP_Q_HDR(p, GET_IP_TCP_Q_HDR_OFFSET(p))->next = nq;
1483 else
1484 cep->reassq = nq;
1485 syscall(rel_net_buf(q));
1486 q = nq;
1487 }
1488
1489 if (p == NULL) {
1490 inqhdr->next = cep->reassq;
1491 cep->reassq = input;
1492 }
1493 else {
1494 inqhdr->next = GET_TCP_Q_HDR(p, GET_IP_TCP_Q_HDR_OFFSET(p))->next;
1495 GET_TCP_Q_HDR(p, GET_IP_TCP_Q_HDR_OFFSET(p))->next = input;
1496 }
1497
1498 return tcp_move_ra2rw(cep, flags);
1499 }
1500
1501/*
1502 * tcp_rexmt_val -- 再送タイムアウト値を返す。
1503 */
1504
1505T_TCP_TIME
1506tcp_rexmt_val (T_TCP_CEP *cep)
1507{
1508 T_TCP_TIME val;
1509
1510 val = ((cep->srtt >> (TCP_SRTT_SHIFT - TCP_DELTA_SHIFT)) + cep->rttvar) >> TCP_DELTA_SHIFT;
1511 if (val < TCP_TVAL_MIN)
1512 return TCP_TVAL_MIN;
1513 else
1514 return val;
1515 }
1516
1517/*
1518 * tcp_init_cep -- 通信端点を初期化する。
1519 */
1520
1521void
1522tcp_init_cep (T_TCP_CEP *cep)
1523{
1524
1525#ifdef TCP_CFG_RWBUF_CSAVE
1526 /*
1527 * 受信ウィンドバッファの省コピー機能を有効にした場合、
1528 * 受信ウィンドバッファがå…
1529¨ã¦è§£æ”¾ã•ã‚Œãªã„ことがあるので、
1530 * ここで解放する。
1531 */
1532 if (cep->rwbufq != NULL) {
1533 cep->rwbuf_count = 0;
1534 TCP_FREE_RWBUFQ(cep);
1535 }
1536#endif /* of #ifdef TCP_CFG_RWBUF_CSAVE */
1537
1538
1539 memset((uint8_t*)cep + offsetof(T_TCP_CEP, timer), 0,
1540 sizeof(T_TCP_CEP) - offsetof(T_TCP_CEP, timer));
1541
1542 cep->sbuf_rptr = cep->sbuf_wptr = cep->sbuf;
1543 cep->rbuf_rptr = cep->rbuf_wptr = cep->rbuf;
1544
1545 cep->maxseg = DEF_TCP_SND_SEG; /* 送信最大セグメントサイズ */
1546 cep->srtt = TCP_TVAL_SRTT_BASE; /* 滑らかな移動平均 */
1547 cep->rttvar = ((TCP_TVAL_RTO_BASE - TCP_TVAL_SRTT_BASE) << TCP_RTTVAR_SHIFT) / 4;
1548 /* 滑らかな分散 */
1549 cep->rxtcur = TCP_TVAL_RTO_BASE; /* 現在の再送値 */
1550 cep->snd_cwnd = MAX_TCP_WIN_SIZE; /* 輻輳ウィンドサイズ */
1551 cep->snd_ssthresh= MAX_TCP_WIN_SIZE; /* 輻輳ウィンドサイズ(snd_cwnd)の 制限値 */
1552
1553 /*
1554 * 以下に関係しないフラグをクリアーする。
1555 * ・送受信ウィンドバッファの省コピー機能
1556 * ・動的な通信端点の生成・削除機能
1557 * ・通信端点のネットワーク層プロトコル
1558 */
1559 cep->flags &= TCP_CEP_FLG_NOT_CLEAR;
1560
1561 /* セマフォを初期化する。*/
1562 sig_sem(cep->semid_lock);
1563
1564 /* フラグを初期化する。*/
1565 syscall(set_flg(cep->snd_flgid, TCP_CEP_EVT_SWBUF_READY));
1566 syscall(clr_flg(cep->rcv_flgid, TCP_CEP_EVT_RWBUF_READY));
1567 }
1568
1569/*
1570 * tcp_notify -- ICMP エラーの処理
1571 */
1572
1573void
1574tcp_notify (T_NET_BUF *input, ER error)
1575{
1576 T_TCP_CEP *cep;
1577
1578 if ((cep = tcp_find_cep(input, GET_TCP_HDR_OFFSET(input))) != NULL) {
1579
1580 /*
1581 * コネクション開設済で、ホスト到達不能エラーの場合は、
1582 * 再送により処理する。
1583 */
1584 if (cep->fsm_state == TCP_FSM_ESTABLISHED &&
1585 (error == EV_NURCH || error == EV_HURCH || error == EV_HDOWN))
1586 return;
1587
1588 /*
1589 * コネクション開設中、同じエラーを何度か受信した場合は、
1590 * 待
1591ち状æ…
1592‹ã‚’解除し、対応する関数にエラーを返させる。
1593 */
1594 if (cep->fsm_state < TCP_FSM_ESTABLISHED && cep->rxtshift > 3 && cep->net_error != E_OK) {
1595 cep->error = E_CLS;
1596 tcp_close(cep);
1597 }
1598 else {
1599 cep->net_error = error;
1600
1601 /* 送信を指示する。*/
1602 cep->flags |= TCP_CEP_FLG_POST_OUTPUT;
1603 sig_sem(SEM_TCP_POST_OUTPUT);
1604 }
1605 }
1606 }
1607
1608/*
1609 * tcp_lock_cep -- TCP 通信端点をロックする。
1610 */
1611
1612ER
1613tcp_lock_cep (ID cepid, T_TCP_CEP **p_cep, FN tfn)
1614{
1615 T_TCP_CEP *cep;
1616 ER error = E_OK;
1617
1618 *p_cep = NULL;
1619
1620 /* TCP 通信端点 ID をチェックする。*/
1621 if (!VALID_TCP_CEPID(cepid))
1622 return E_ID;
1623
1624 /* TCP 通信端点を得る。*/
1625 cep = GET_TCP_CEP(cepid);
1626
1627 /* TCP 通信端点をロックする。*/
1628 syscall(wai_sem(cep->semid_lock));
1629
1630 /* TCP 通信端点をチェックする。*/
1631 if (!VALID_TCP_CEP(cep)) {
1632 syscall(sig_sem(cep->semid_lock));
1633 return E_NOEXS;
1634 }
1635
1636 /*
1637 * API 機能コードとタスク識別子を記録する。
1638 * すでに記録されていれば、ペンディング中なのでエラー
1639 */
1640 if (IS_TFN_TCP_RCV(tfn)) {
1641 if (cep->rcv_tfn != TFN_TCP_UNDEF ||
1642 (tfn == TFN_TCP_ACP_CEP && cep->snd_tfn == TFN_TCP_CON_CEP))
1643 error = E_OBJ;
1644 else {
1645 get_tid(&(cep->rcv_tskid));
1646 cep->rcv_tfn = tfn;
1647 }
1648 }
1649 else {
1650 if (cep->snd_tfn != TFN_TCP_UNDEF ||
1651 (tfn == TFN_TCP_CON_CEP && cep->rcv_tfn == TFN_TCP_ACP_CEP) ||
1652 (tfn == TFN_TCP_CON_CEP && cep->rcv_tfn == TFN_TCP_CLS_CEP))
1653 error = E_OBJ;
1654 else {
1655 get_tid(&(cep->snd_tskid));
1656 cep->snd_tfn = tfn;
1657 }
1658 }
1659
1660 /* 通信端点のロックを解除する。*/
1661 syscall(sig_sem(cep->semid_lock));
1662
1663 *p_cep = cep;
1664 return error;
1665 }
1666
1667#ifdef TCP_CFG_TRACE
1668
1669/*
1670 * トレース出力に用いるシリアルポート番号
1671 */
1672
1673#ifndef CONSOLE_PORTID
1674#define CONSOLE_PORTID LOGTASK_PORTID
1675#endif
1676
1677/*
1678 * コネクションの状æ…
1679‹
1680 */
1681
1682static const char tcp_strfsm[][3] = {
1683 { 'C', 'D', '\0' },
1684 { 'L', 'I', '\0' },
1685 { 'S', 'S', '\0' },
1686 { 'S', 'R', '\0' },
1687 { 'E', 'S', '\0' },
1688 { 'C', 'W', '\0' },
1689 { 'F', '1', '\0' },
1690 { 'C', 'G', '\0' },
1691 { 'L', 'A', '\0' },
1692 { 'F', '2', '\0' },
1693 { 'T', 'W', '\0' },
1694 };
1695
1696/*
1697 * trace_putchar -- シリアルポートへの文字出力
1698 */
1699
1700static void
1701trace_putchar (ID portid, char ch)
1702{
1703 serial_wri_dat(portid, &ch, 1);
1704 /*cpu_putc(ch);*/
1705 }
1706
1707/*
1708 * シリアルポートへの書式付文字列出力ライブラリ
1709 */
1710
1711/*
1712 * 数値変換のための変換表
1713 */
1714
1715static const char radhex[] = "0123456789abcdef";
1716static const char radHEX[] = "0123456789ABCDEF";
1717
1718/*
1719 * convert -- trace_printf の数値変換
1720 */
1721
1722static int_t
1723convert (ID portid, long_t val, int_t radix,
1724 const char *radchar, int_t width, bool_t minus, char padchar)
1725{
1726 char digits[24];
1727 int_t ix, pad, pchars;
1728
1729 ix = 0;
1730 do {
1731 if (minus)
1732 digits[ix ++] = radchar[val % radix];
1733 else
1734 digits[ix ++] = radchar[(ulong_t)val % radix];
1735 val /= radix;
1736 } while (val != 0);
1737
1738 if (minus)
1739 digits[ix ++] = '-';
1740
1741 if (width > ix)
1742 pchars = width;
1743 else
1744 pchars = ix;
1745
1746 for (pad = ix; pad < width; pad ++)
1747 trace_putchar(portid, padchar);
1748
1749 while (ix -- > 0)
1750 trace_putchar(portid, digits[ix]);
1751
1752 return pchars;
1753 }
1754
1755/*
1756 * trace_printf -- シリアルポートへの書式付文字列出力
1757 */
1758
1759static void
1760trace_printf (ID portid, const char *fmt, ...)
1761{
1762 va_list ap;
1763 ulong_t val;
1764 char padchar, *str;
1765 int_t ch, width, longflag;
1766
1767 va_start(ap, fmt);
1768 while ((ch = *fmt ++) != '\0') {
1769 if (ch != '%') { /* 書式指定以外 */
1770 trace_putchar(portid, (char)ch);
1771 continue;
1772 }
1773
1774 width = longflag = 0;
1775 padchar = ' ';
1776 if ((ch = *fmt ++) == '0') { /* 上位桁の 0 */
1777 padchar = '0';
1778 ch = *fmt ++;
1779 }
1780
1781 while ('0' <= ch && ch <= '9') { /* 出力幅
1782 */
1783 width = width * 10 + ch - '0';
1784 ch = *fmt ++;
1785 }
1786
1787 while (ch == 'l') { /* long (long) の指定 */
1788 longflag ++;
1789 ch = *fmt ++;
1790 }
1791
1792 switch (ch) {
1793 case 'd':
1794 val = longflag ? (ulong_t)va_arg(ap, long_t)
1795 : (ulong_t)va_arg(ap, int_t);
1796 if (val >= 0)
1797 convert(portid, val, 10, radhex, width, false, padchar);
1798 else
1799 convert(portid, -val, 10, radhex, width, true, padchar);
1800 break;
1801
1802 case 'u':
1803 val = longflag ? (ulong_t)va_arg(ap, ulong_t)
1804 : (ulong_t)va_arg(ap, uint_t);
1805 convert(portid, val, 10, radhex, width, false, padchar);
1806 break;
1807
1808 case 'x':
1809 val = longflag ? (ulong_t)va_arg(ap, ulong_t)
1810 : (ulong_t)va_arg(ap, uint_t);
1811 convert(portid, val, 16, radhex, width, false, padchar);
1812 break;
1813
1814 case 'X':
1815 val = longflag ? (ulong_t)va_arg(ap, ulong_t)
1816 : (ulong_t)va_arg(ap, uint_t);
1817 convert(portid, val, 16, radHEX, width, false, padchar);
1818 break;
1819
1820 case 'c':
1821 ch = va_arg(ap, int_t);
1822 trace_putchar(portid, (char)ch);
1823 break;
1824
1825 case 's':
1826 str = va_arg(ap, char*);
1827 while ((ch = *str ++) != '\0')
1828 trace_putchar(portid, (char)ch);
1829 break;
1830
1831 case '%':
1832 trace_putchar(portid, '%');
1833 break;
1834
1835 case '0':
1836 fmt --;
1837 break;
1838
1839 default:
1840 break;
1841 }
1842
1843 }
1844 va_end(ap);
1845 }
1846
1847/*
1848 * TCP フラグ文字列
1849 */
1850
1851static char *
1852get_tcp_flag_str (char *buf, uint8_t flags)
1853{
1854 static char tcp_flag_str[] = "FSRPAU";
1855
1856 int_t bit, mask = 1;
1857
1858 for (bit = 0; bit < sizeof(tcp_flag_str); bit ++) {
1859 buf[sizeof(tcp_flag_str) - bit - 1] = (char)((flags & mask) ? tcp_flag_str[bit] : '-');
1860 mask <<= 1;
1861 }
1862 buf[sizeof(tcp_flag_str)] = '\0';
1863 return buf;
1864 }
1865
1866/*
1867 * 送信 TCP ヘッダのトレース出力
1868 */
1869
1870void
1871tcp_output_trace (T_NET_BUF *output, T_TCP_CEP *cep)
1872{
1873 SYSTIM time;
1874 T_TCP_HDR *tcph;
1875 char buf[9];
1876
1877 if (!(TCP_CFG_TRACE_LPORTNO == TCP_PORTANY || cep->myaddr.portno == TCP_CFG_TRACE_LPORTNO) ||
1878 !(TCP_CFG_TRACE_RPORTNO == TCP_PORTANY || cep->dstaddr.portno == TCP_CFG_TRACE_RPORTNO))
1879 return;
1880
1881#if defined(_IP4_CFG)
1882
1883#if defined(_IP6_CFG)
1884
1885 if (!((TCP_CFG_TRACE_IPV4_RADDR == IPV4_ADDRANY) ||
1886 ((cep->flags & TCP_CEP_FLG_IPV4) &&
1887 IN6_IS_ADDR_V4MAPPED(&cep->dstaddr.ipaddr) &&
1888 (ntohl(cep->dstaddr.ipaddr.s6_addr32[3]) == TCP_CFG_TRACE_IPV4_RADDR))))
1889 return;
1890
1891#else /* of #if defined(_IP6_CFG) */
1892
1893 if (!(TCP_CFG_TRACE_IPV4_RADDR == IPV4_ADDRANY || cep->dstaddr.ipaddr == TCP_CFG_TRACE_IPV4_RADDR))
1894 return;
1895
1896#endif /* of #if defined(_IP6_CFG) */
1897
1898#endif /* of #if defined(_IP4_CFG) */
1899
1900 syscall(wai_sem(SEM_TCP_TRACE));
1901 syscall(get_tim(&time));
1902 tcph = GET_TCP_HDR(output, GET_TCP_HDR_OFFSET(output));
1903 if (time > 99999999)
1904 trace_printf(CONSOLE_PORTID, "=O%10d", time / 1000);
1905 else
1906 trace_printf(CONSOLE_PORTID, "=O%6d.%03d", time / 1000, time % 1000);
1907 if (cep == NULL)
1908 trace_printf(CONSOLE_PORTID, "=c:-- s:-- f:--------");
1909 else
1910 trace_printf(CONSOLE_PORTID, "=c:%2d s:%s f:%08x",
1911 GET_TCP_CEPID(cep),
1912 tcp_strfsm[cep->fsm_state], cep->flags);
1913 trace_printf(CONSOLE_PORTID, ":%s", get_tcp_flag_str(buf, tcph->flags));
1914 if (cep->fsm_state >= TCP_FSM_ESTABLISHED)
1915 trace_printf(CONSOLE_PORTID, " s:%10u a:%10u",
1916 ntohl(tcph->seq) - cep->iss,
1917 ntohl(tcph->ack) - cep->irs);
1918 else
1919 trace_printf(CONSOLE_PORTID, " s:%10u a:%10u",
1920 ntohl(tcph->seq), ntohl(tcph->ack));
1921 trace_printf(CONSOLE_PORTID, " w:%5d l:%4d>\n",
1922 ntohs(tcph->win),
1923 GET_IP_SDU_SIZE(output) - TCP_HDR_LEN(tcph->doff));
1924 syscall(sig_sem(SEM_TCP_TRACE));
1925 }
1926
1927/*
1928 * 受信 TCP ヘッダのトレース出力
1929 *
1930 * 注意: TCP ヘッダ内
1931は、すでにホストバイトオーダ
1932 */
1933
1934void
1935tcp_input_trace (T_NET_BUF *input, T_TCP_CEP *cep)
1936{
1937 SYSTIM time;
1938 T_TCP_HDR *tcph;
1939 char buf[9];
1940
1941 if (!(TCP_CFG_TRACE_LPORTNO == TCP_PORTANY || cep->myaddr.portno == TCP_CFG_TRACE_LPORTNO) ||
1942 !(TCP_CFG_TRACE_RPORTNO == TCP_PORTANY || cep->dstaddr.portno == TCP_CFG_TRACE_RPORTNO))
1943 return;
1944
1945#if defined(_IP4_CFG)
1946
1947#if defined(_IP6_CFG)
1948
1949 if (!((TCP_CFG_TRACE_IPV4_RADDR == IPV4_ADDRANY) ||
1950 ((cep->flags & TCP_CEP_FLG_IPV4) &&
1951 IN6_IS_ADDR_V4MAPPED(&cep->dstaddr.ipaddr) &&
1952 (ntohl(cep->dstaddr.ipaddr.s6_addr32[3]) == TCP_CFG_TRACE_IPV4_RADDR))))
1953 return;
1954
1955#else /* of #if defined(_IP6_CFG) */
1956
1957 if (!(TCP_CFG_TRACE_IPV4_RADDR == IPV4_ADDRANY || cep->dstaddr.ipaddr == TCP_CFG_TRACE_IPV4_RADDR))
1958 return;
1959
1960#endif /* of #if defined(_IP6_CFG) */
1961
1962#endif /* of #if defined(_IP4_CFG) */
1963
1964 syscall(wai_sem(SEM_TCP_TRACE));
1965 syscall(get_tim(&time));
1966 tcph = GET_TCP_HDR(input, GET_TCP_HDR_OFFSET(input));
1967 if (time > 99999999)
1968 trace_printf(CONSOLE_PORTID, "<I%10d", time / 1000);
1969 else
1970 trace_printf(CONSOLE_PORTID, "<I%6d.%03d", time / 1000, time % 1000);
1971 if (cep == NULL)
1972 trace_printf(CONSOLE_PORTID, "=c:-- s:-- f:--------");
1973 else
1974 trace_printf(CONSOLE_PORTID, "=c:%2d s:%s f:%08x",
1975 GET_TCP_CEPID(cep),
1976 tcp_strfsm[cep->fsm_state], cep->flags);
1977 trace_printf(CONSOLE_PORTID, ":%s", get_tcp_flag_str(buf, tcph->flags));
1978 if (cep->fsm_state >= TCP_FSM_SYN_RECVD)
1979 trace_printf(CONSOLE_PORTID, " a:%10u s:%10u", tcph->ack - cep->iss, tcph->seq - cep->irs);
1980 else
1981 trace_printf(CONSOLE_PORTID, " a:%10u s:%10u", tcph->ack, tcph->seq);
1982 trace_printf(CONSOLE_PORTID, " w:%5d l:%4d=\n",
1983 tcph->win, GET_IP_SDU_SIZE(input) - TCP_HDR_LEN(tcph->doff));
1984 syscall(sig_sem(SEM_TCP_TRACE));
1985 }
1986
1987#endif /* of #ifdef TCP_CFG_TRACE */
1988
1989#endif /* of #ifdef SUPPORT_TCP */
Note: See TracBrowser for help on using the repository browser.