source: azure_iot_hub/trunk/asp3_dcre/tinet/netinet/tcp_subr.c@ 388

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

Azure IoT Hub Device C SDK を使ったサンプルの追加

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