source: asp3_tinet_ecnl_arm/trunk/asp3_dcre/tinet/netinet/tcp_subr.c@ 352

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

arm向けASP3版ECNLを追加

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