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

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

SVNプロパティを設定

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