source: EcnlProtoTool/trunk/asp3_dcre/tinet/netinet/tcp_usrreq.c@ 321

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

文字コードを設定

  • Property svn:eol-style set to native
  • Property svn:mime-type set to text/x-csrc;charset=UTF-8
File size: 50.3 KB
Line 
1/*
2 * TINET (TCP/IP Protocol Stack)
3 *
4 * Copyright (C) 2001-2009 by Dep. of Computer Science and Engineering
5 * Tomakomai National College of Technology, JAPAN
6 *
7 * 上記著作権者は,以下の (1)~(4) の条件か,Free Software Foundation
8 * によって公表されている GNU General Public License の Version 2 に記
9 * 述されている条件を満たす場合に限り,本ソフトウェア(本ソフトウェア
10 * を改変したものを含む.以下同じ)を使用・複製・改変・再配布(以下,
11 * 利用と呼ぶ)することを無償で許諾する.
12 * (1) 本ソフトウェアをソースコードの形で利用する場合には,上記の著作
13 * 権表示,この利用条件および下記の無保証規定が,そのままの形でソー
14 * スコード中に含まれていること.
15 * (2) 本ソフトウェアを,ライブラリ形式など,他のソフトウェア開発に使
16 * 用できる形で再配布する場合には,再配布に伴うドキュメント(利用
17 * 者マニュアルなど)に,上記の著作権表示,この利用条件および下記
18 * の無保証規定を掲載すること.
19 * (3) 本ソフトウェアを,機器に組み込むなど,他のソフトウェア開発に使
20 * 用できない形で再配布する場合には,次の条件を満たすこと.
21 * (a) 再配布に伴うドキュメント(利用者マニュアルなど)に,上記の著
22 * 作権表示,この利用条件および下記の無保証規定を掲載すること.
23 * (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
24 * 害からも,上記著作権者およびTOPPERSプロジェクトを免責すること.
25 *
26 * 本ソフトウェアは,無保証で提供されているものである.上記著作権者お
27 * よびTOPPERSプロジェクトは,本ソフトウェアに関して,その適用可能性も
28 * 含めて,いかなる保証も行わない.また,本ソフトウェアの利用により直
29 * 接的または間接的に生じたいかなる損害に関しても,その責任を負わない.
30 *
31 * @(#) $Id$
32 */
33
34/*
35 * Copyright (c) 1982, 1986, 1988, 1993
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 * From: @(#)tcp_usrreq.c 8.2 (Berkeley) 1/3/94
67 * $FreeBSD: src/sys/netinet/tcp_usrreq.c,v 1.40.2.3 1999/08/29 16:29:57 peter Exp $
68 */
69
70#include <string.h>
71
72#ifdef TARGET_KERNEL_ASP
73
74#include <kernel.h>
75#include <sil.h>
76#include "kernel_cfg.h"
77
78#endif /* of #ifdef TARGET_KERNEL_ASP */
79
80#ifdef TARGET_KERNEL_JSP
81
82#include <s_services.h>
83#include <t_services.h>
84#include "kernel_id.h"
85
86#endif /* of #ifdef TARGET_KERNEL_JSP */
87
88#include <tinet_defs.h>
89#include <tinet_config.h>
90
91#include <net/if.h>
92#include <net/if_ppp.h>
93#include <net/if_loop.h>
94#include <net/ethernet.h>
95#include <net/ppp_ipcp.h>
96#include <net/net.h>
97#include <net/net_var.h>
98#include <net/net_buf.h>
99#include <net/net_timer.h>
100#include <net/net_count.h>
101
102#include <netinet/in.h>
103#include <netinet/in_var.h>
104#include <netinet6/in6.h>
105#include <netinet6/in6_var.h>
106#include <netinet/in_itron.h>
107#include <netinet/ip.h>
108#include <netinet/ip_var.h>
109#include <netinet/ip6.h>
110#include <netinet6/ip6_var.h>
111#include <netinet/tcp.h>
112#include <netinet/tcp_timer.h>
113#include <netinet/tcp_var.h>
114#include <netinet/tcp_fsm.h>
115#include <netinet/tcp_seq.h>
116
117#include <net/if_var.h>
118
119#ifdef SUPPORT_TCP
120
121/*
122 * IPv4 と IPv6 の切り替えマクロ
123 */
124
125#if defined(SUPPORT_INET4)
126
127#define TCP_CRE_REP tcp_cre_rep
128#define TCP_ACP_CEP tcp_acp_cep
129#define TCP_CON_CEP tcp_con_cep
130
131#endif /* of #if defined(SUPPORT_INET4) */
132
133#if defined(SUPPORT_INET6)
134
135#define TCP_CRE_REP tcp6_cre_rep
136#define TCP_ACP_CEP tcp6_acp_cep
137#define TCP_CON_CEP tcp6_con_cep
138
139#endif /* of #if defined(SUPPORT_INET6) */
140
141/*
142 * TINET をライブラリ化しない場合は、全ての機能を
143 * オブジェクトファイルに出力するため、マクロを有効にする。
144 */
145
146#ifndef TCP_CFG_LIBRARY
147
148#define __tcp_cre_rep
149#define __tcp_del_rep
150#define __tcp_cre_cep
151#define __tcp_del_cep
152#define __tcp_acp_cep
153#define __tcp_con_cep
154#define __tcp_sht_cep
155#define __tcp_cls_cep
156#define __tcp_snd_dat
157#define __tcp_rcv_dat
158#define __tcp_snd_oob
159#define __tcp_rcv_oob
160#define __tcp_get_buf
161#define __tcp_snd_buf
162#define __tcp_rcv_buf
163#define __tcp_rel_buf
164#define __tcp_can_cep
165#define __tcp_set_opt
166#define __tcp_get_opt
167
168#endif /* of #ifndef TCP_CFG_LIBRARY */
169
170/*
171 * tcp_cre_rep -- TCP 受付口の生成【拡張機能】
172 */
173
174#ifdef __tcp_cre_rep
175
176#ifdef TCP_CFG_EXTENTIONS
177
178ER
179TCP_CRE_REP (ID repid, T_TCP_CREP *pk_crep)
180{
181 T_TCP_REP *rep;
182 ER error;
183
184 /* TCP 受付口 ID をチェックする。*/
185 if (!VAID_TCP_REPID(repid))
186 return E_ID;
187
188 /* pk_crep が NULL ならエラー */
189 if (pk_crep == NULL)
190 return E_PAR;
191
192 /* TCP 受付口を得る。*/
193 rep = GET_TCP_REP(repid);
194
195 /* TCP 受付口が、動的生成用でなければエラー */
196 if (!DYNAMIC_TCP_REP(rep))
197 return E_ID;
198
199 /* 受付口をロックする。*/
200 syscall(wai_sem(rep->semid_lock));
201
202 /*
203 * TCP 受付口をチェックする。生成済みであればエラー
204 */
205 if (VALID_TCP_REP(rep))
206 error = E_OBJ;
207 else {
208
209 /* TCP 受付口生成情報をコピーする。*/
210 rep->repatr = pk_crep->repatr; /* 受付口属性 */
211 rep->myaddr = pk_crep->myaddr; /* 自分のアドレス */
212
213 /* TCP 受付口を生成済みにする。*/
214 rep->flags |= TCP_REP_FLG_VALID;
215 error = E_OK;
216 }
217
218 /* 受付口のロックを解除する。*/
219 syscall(sig_sem(rep->semid_lock));
220
221 return error;
222 }
223
224#endif /* of #ifdef TCP_CFG_EXTENTIONS */
225
226#endif /* of #ifdef __tcp_cre_cep */
227
228#ifdef __tcp_del_rep
229
230#ifdef TCP_CFG_EXTENTIONS
231
232/*
233 * tcp_find_cep_rep -- TCP 受付口をリンクしている TCP 通信端点を得る。
234 */
235
236static T_TCP_CEP*
237tcp_find_cep_rep (T_TCP_REP* rep)
238{
239 T_TCP_CEP* cep;
240
241 for (cep = &tcp_cep[tmax_tcp_cepid]; cep -- != tcp_cep; ) {
242 if (cep->rep == rep)
243 return cep;
244 }
245
246 return NULL;
247 }
248
249/*
250 * tcp_del_rep -- TCP 受付口の削除【拡張機能】
251 */
252
253
254ER
255tcp_del_rep (ID repid)
256{
257 T_TCP_CEP *cep;
258 T_TCP_REP *rep;
259 ER error = E_OK;
260
261 /* TCP 受付口 ID をチェックする。*/
262 if (!VAID_TCP_REPID(repid))
263 return E_ID;
264
265 /* TCP 受付口を得る。*/
266 rep = GET_TCP_REP(repid);
267
268 /* TCP 受付口が、動的生成用でなければエラー */
269 if (!DYNAMIC_TCP_REP(rep))
270 return E_ID;
271
272 /* 受付口をロックする。*/
273 syscall(wai_sem(rep->semid_lock));
274
275 /* TCP 受付口をチェックする。未生成の場合はエラー */
276 if (!VALID_TCP_REP(rep))
277 error = E_NOEXS;
278 else {
279 if ((cep = tcp_find_cep_rep(rep)) != NULL) {
280 /*
281 * すでに受動オープンしているとき
282 *(tcp_acp_cep が呼ばれているとき)は、
283 * tcp_acp_cep を終了させる。
284 */
285
286 /* 通信端点をロックする。*/
287 syscall(wai_sem(cep->semid_lock));
288
289 /*
290 * 通信端点から受付口を解放し、
291 * イベントフラグをクローズに設定する。
292 */
293 cep->rep = NULL;
294 cep->fsm_state = TCP_FSM_CLOSED;
295 cep->error = E_DLT;
296 syscall(set_flg(cep->est_flgid, TCP_CEP_EVT_CLOSED));
297
298#ifdef TCP_CFG_NON_BLOCKING
299
300 if (cep->rcv_nblk_tfn != TFN_TCP_UNDEF) {
301 if (IS_PTR_DEFINED(cep->callback)) {
302
303#ifdef TCP_CFG_NON_BLOCKING_COMPAT14
304
305 (*cep->callback)(GET_TCP_CEPID(cep), cep->rcv_nblk_tfn, (void*)E_DLT);
306
307#else /* of #ifdef TCP_CFG_NON_BLOCKING_COMPAT14 */
308
309 ER error = E_DLT;
310
311 (*cep->callback)(GET_TCP_CEPID(cep), cep->rcv_nblk_tfn, (void*)&error);
312
313#endif /* of #ifdef TCP_CFG_NON_BLOCKING_COMPAT14 */
314
315 }
316 else
317 error = E_OBJ;
318 cep->rcv_nblk_tfn = TFN_TCP_UNDEF;
319 }
320
321#endif /* of #ifdef TCP_CFG_NON_BLOCKING */
322
323 cep->rcv_tskid = TA_NULL;
324 cep->rcv_tfn = TFN_TCP_UNDEF;
325
326 /* 通信端点のロックを解除する。*/
327 syscall(sig_sem(cep->semid_lock));
328
329 }
330 else
331 error = E_OK;
332
333 /* TCP 受付口を未生成にする。*/
334 rep->flags &= ~TCP_REP_FLG_VALID;
335 }
336
337 /* 受付口のロックを解除する。*/
338 syscall(sig_sem(rep->semid_lock));
339
340 return error;
341 }
342
343#endif /* of #ifdef TCP_CFG_EXTENTIONS */
344
345#endif /* of #ifdef __tcp_del_rep */
346
347/*
348 * tcp_cre_cep -- TCP 通信端点の生成【拡張機能】
349 */
350
351#ifdef __tcp_cre_cep
352
353#ifdef TCP_CFG_EXTENTIONS
354
355ER
356tcp_cre_cep (ID cepid, T_TCP_CCEP *pk_ccep)
357{
358 T_TCP_CEP *cep;
359 ER error;
360
361 /* TCP 通信端点 ID をチェックする。*/
362 if (!VAID_TCP_CEPID(cepid))
363 return E_ID;
364
365 /* pk_ccep が NULL ならエラー */
366 if (pk_ccep == NULL)
367 return E_PAR;
368
369 /* TCP 通信端点を得る。*/
370 cep = GET_TCP_CEP(cepid);
371
372 /* TCP 通信端点が、動的生成用でなければエラー */
373 if (!DYNAMIC_TCP_CEP(cep))
374 return E_ID;
375
376 /* 通信端点をロックする。*/
377 syscall(wai_sem(cep->semid_lock));
378
379 /*
380 * TCP 通信端点をチェックする。生成済みであればエラー
381 */
382 if (VALID_TCP_CEP(cep))
383 error = E_OBJ;
384 else {
385
386 /* TCP 通信端点生成情報をコピーする。*/
387 cep->cepatr = pk_ccep->cepatr; /* 通信端点属性 */
388 cep->sbuf = pk_ccep->sbuf; /* 送信用ウィンドバッファ */
389 cep->sbufsz = pk_ccep->sbufsz; /* 送信用ウィンドバッファサイズ */
390 cep->rbuf = pk_ccep->rbuf; /* 受信用ウィンドバッファ */
391 cep->rbufsz = pk_ccep->rbufsz; /* 受信用ウィンドバッファサイズ */
392 cep->callback = (void*)pk_ccep->callback; /* コールバック */
393
394 /* TCP 通信端点を生成済みにする。*/
395 cep->flags |= TCP_CEP_FLG_VALID;
396 error = E_OK;
397 }
398
399 /* 通信端点のロックを解除する。*/
400 syscall(sig_sem(cep->semid_lock));
401
402 return error;
403 }
404
405#endif /* of #ifdef TCP_CFG_EXTENTIONS */
406
407#endif /* of #ifdef __tcp_cre_cep */
408
409/*
410 * tcp_del_cep -- TCP 通信端点の削除【拡張機能】
411 */
412
413#ifdef __tcp_del_cep
414
415#ifdef TCP_CFG_EXTENTIONS
416
417ER
418tcp_del_cep (ID cepid)
419{
420 T_TCP_CEP *cep;
421 ER error;
422
423 /* TCP 通信端点 ID をチェックする。*/
424 if (!VAID_TCP_CEPID(cepid))
425 return E_ID;
426
427 /* TCP 通信端点を得る。*/
428 cep = GET_TCP_CEP(cepid);
429
430 /* TCP 通信端点が、動的生成用でなければエラー */
431 if (!DYNAMIC_TCP_CEP(cep))
432 return E_ID;
433
434 /* 通信端点をロックする。*/
435 syscall(wai_sem(cep->semid_lock));
436
437 /*
438 * TCP 通信端点をチェックする。以下の場合はエラー
439 * ・未生成。
440 * ・使用中。
441 */
442 if (!VALID_TCP_CEP(cep))
443 error = E_NOEXS;
444 else if (cep->fsm_state != TCP_FSM_CLOSED)
445 error = E_OBJ;
446 else {
447
448 /* TCP 通信端点を未生成にする。*/
449 cep->flags &= ~TCP_CEP_FLG_VALID;
450 error = E_OK;
451 }
452
453 /* 通信端点のロックを解除する。*/
454 syscall(sig_sem(cep->semid_lock));
455
456 return error;
457 }
458
459#endif /* of #ifdef TCP_CFG_EXTENTIONS */
460
461#endif /* of #ifdef __tcp_del_cep */
462
463#ifdef TCP_CFG_PASSIVE_OPEN
464
465/*
466 * tcp_acp_cep -- 接続要求待ち (受動オープン)【標準機能】
467 */
468
469#ifdef __tcp_acp_cep
470
471ER
472TCP_ACP_CEP (ID cepid, ID repid, T_IPEP *p_dstaddr, TMO tmout)
473{
474 T_TCP_REP *rep;
475 T_TCP_CEP *cep;
476 ER error;
477 FLGPTN flag;
478
479 /* TCP 受付口をチェックする。*/
480 if (!VAID_TCP_REPID(repid))
481 return E_ID;
482
483#ifdef TCP_CFG_NON_BLOCKING
484
485 /* p_dstaddr が NULL ならエラー */
486 if (p_dstaddr == NULL)
487 return E_PAR;
488
489#else /* of #ifdef TCP_CFG_NON_BLOCKING */
490
491 /* p_dstaddr が NULL か、tmout が TMO_NBLK ならエラー */
492 if (p_dstaddr == NULL || tmout == TMO_NBLK)
493 return E_PAR;
494
495#endif /* of #ifdef TCP_CFG_NON_BLOCKING */
496
497 /*
498 * CEP をロックし、API 機能コードとタスク識別子を記録する。
499 * すでに記録されていれば、ペンディング中なのでエラー
500 */
501 if ((error = tcp_lock_cep(cepid, &cep, TFN_TCP_ACP_CEP)) != E_OK)
502 return error;
503
504 /* CEP の FSM がクローズ状態でなければエラー。*/
505 if (cep->fsm_state != TCP_FSM_CLOSED) {
506 error = E_OBJ;
507 goto err_ret;
508 }
509 syscall(clr_flg(cep->est_flgid, (FLGPTN)(~TCP_CEP_EVT_CLOSED)));
510
511 /* TCP 通信端点を初期化する。*/
512 tcp_init_cep(cep);
513
514 /* TCP 受付口を得る。*/
515 rep = GET_TCP_REP(repid);
516
517#ifdef TCP_CFG_EXTENTIONS
518
519 /* TCP 受付口をロックする。*/
520 syscall(wai_sem(rep->semid_lock));
521
522 /* TCP 受付口をチェックする。*/
523 if (!VALID_TCP_REP(rep)) {
524 syscall(sig_sem(rep->semid_lock));
525 error = E_NOEXS;
526 goto err_ret;
527 }
528
529#endif /* of #ifdef TCP_CFG_EXTENTIONS */
530
531 /* TCP 通信端点にTCP受付口を記録する。*/
532 cep->rep = rep;
533
534#ifdef TCP_CFG_EXTENTIONS
535
536 /* TCP 受付口のロックを解除する。*/
537 syscall(sig_sem(rep->semid_lock));
538
539#endif /* of #ifdef TCP_CFG_EXTENTIONS */
540
541 /* TCP 受付口のアドレスをコピーする。*/
542 cep->myaddr = rep->myaddr;
543
544 /* 通信端点を設定する。*/
545 cep->fsm_state = TCP_FSM_LISTEN;
546
547#ifdef TCP_CFG_NON_BLOCKING
548
549 /* タイムアウトをチェックする。*/
550 if (tmout == TMO_NBLK) {
551 /* ノンブロッキングコール */
552 cep->p_dstaddr = p_dstaddr;
553 cep->rcv_nblk_tfn = TFN_TCP_ACP_CEP;
554 return E_WBLK;
555 }
556 else {
557
558#endif /* of #ifdef TCP_CFG_NON_BLOCKING */
559
560 /*
561 * FSM が ESTABLISHED になるまで待つ。
562 * FSM が CLOSED になった場合は、エラーが発生したことを意味している。
563 */
564 error = twai_flg(cep->est_flgid, (TCP_CEP_EVT_CLOSED |
565 TCP_CEP_EVT_ESTABLISHED), TWF_ORW, &flag, tmout);
566 if (error == E_OK) {
567 if (cep->error != E_OK)
568 error = cep->error;
569 else if (cep->fsm_state == TCP_FSM_CLOSED)
570 error = E_TMOUT;
571 }
572
573 syscall(clr_flg(cep->est_flgid, (FLGPTN)(~TCP_CEP_EVT_ESTABLISHED)));
574
575 if (error == E_OK) {
576 /* 相手のアドレスをコピーする。*/
577 *p_dstaddr = cep->dstaddr;
578 }
579 else {
580 /*
581 * 通信端点から受付口を解放し、
582 * イベントフラグをクローズに設定する。
583 */
584 cep->rep = NULL;
585 cep->fsm_state = TCP_FSM_CLOSED;
586 syscall(set_flg(cep->est_flgid, TCP_CEP_EVT_CLOSED));
587 }
588
589#ifdef TCP_CFG_NON_BLOCKING
590
591 }
592
593#endif /* of #ifdef TCP_CFG_NON_BLOCKING */
594
595err_ret:
596 cep->rcv_tskid = TA_NULL;
597 cep->rcv_tfn = TFN_TCP_UNDEF;
598 return error;
599 }
600
601#endif /* of #ifdef __tcp_acp_cep */
602
603#endif /* of #ifdef TCP_CFG_PASSIVE_OPEN */
604
605/*
606 * tcp_con_cep -- 接続要求 (能動オープン)【標準機能】
607 */
608
609#ifdef __tcp_con_cep
610
611ER
612TCP_CON_CEP (ID cepid, T_IPEP *p_myaddr, T_IPEP *p_dstaddr, TMO tmout)
613{
614 T_TCP_CEP *cep;
615 ER error;
616 FLGPTN flag;
617
618#ifdef TCP_CFG_NON_BLOCKING
619
620 /*
621 * p_dstaddr または p_myaddr が NULL か、
622 * あて先がマルチキャストアドレスならエラー
623 */
624 if (p_myaddr == NULL || p_dstaddr == NULL || IN_IS_ADDR_MULTICAST(&p_dstaddr->ipaddr))
625 return E_PAR;
626
627#else /* of #ifdef TCP_CFG_NON_BLOCKING */
628
629 /*
630 * p_dstaddr または p_myaddr が NULL 、
631 * あて先がマルチキャストアドレスか、
632 * tmout が TMO_NBLK ならエラー
633 */
634 if (p_myaddr == NULL || p_dstaddr == NULL ||
635 IN_IS_ADDR_MULTICAST(&p_dstaddr->ipaddr) || tmout == TMO_NBLK)
636 return E_PAR;
637
638#endif /* of #ifdef TCP_CFG_NON_BLOCKING */
639
640 /*
641 * CEP をロックし、API 機能コードとタスク識別子を記録する。
642 * すでに記録されていれば、ペンディング中なのでエラー
643 */
644 if ((error = tcp_lock_cep(cepid, &cep, TFN_TCP_CON_CEP)) != E_OK)
645 return error;
646
647 /* CEP の FSM がクローズ状態でなければエラー。*/
648 if (cep->fsm_state != TCP_FSM_CLOSED) {
649 error = E_OBJ;
650 goto err_ret;
651 }
652 syscall(clr_flg(cep->est_flgid, (FLGPTN)(~TCP_CEP_EVT_CLOSED)));
653
654 /* シーケンス番号を初期化する。*/
655 if (tcp_iss == 0)
656 tcp_init_iss();
657
658 /* 通信端点を初期化する。*/
659 tcp_init_cep(cep);
660
661 /*
662 * p_myaddr が NADR (-1) ではなく、自 IP アドレスが ANY でなければ、
663 * 指定された IP アドレスを割り当てる。
664 */
665 if (p_myaddr != NADR && !IN_IS_ADDR_ANY(&p_myaddr->ipaddr))
666 cep->myaddr.ipaddr = p_myaddr->ipaddr;
667 else {
668 T_IN_IFADDR *ia;
669
670 if ((ia = IN_IFAWITHIFP(IF_GET_IFNET(), &p_dstaddr->ipaddr)) == NULL) {
671 error = E_PAR;
672 goto err_ret;
673 }
674 cep->myaddr.ipaddr = ia->addr;
675 }
676
677 /* 通信端点を設定する。*/
678 cep->fsm_state = TCP_FSM_SYN_SENT;
679 cep->dstaddr = *p_dstaddr;
680 cep->iss = tcp_iss;
681 cep->timer[TCP_TIM_KEEP] = TCP_TVAL_KEEP_INIT;
682 tcp_iss += TCP_ISS_INCR() / 2;
683 init_send_seq(cep);
684
685#ifdef TCP_CFG_NON_BLOCKING
686
687 /* タイムアウトをチェックする。*/
688 if (tmout == TMO_NBLK) {
689 /* ノンブロッキングコール */
690 cep->p_dstaddr = p_dstaddr;
691 cep->p_myaddr = p_myaddr;
692 cep->snd_nblk_tfn = TFN_TCP_CON_CEP;
693
694 /* コネクションの開設をポストする。*/
695 cep->flags |= TCP_CEP_FLG_POST_OUTPUT;
696 sig_sem(SEM_TCP_POST_OUTPUT);
697 return E_WBLK;
698 }
699 else {
700
701#endif /* of #ifdef TCP_CFG_NON_BLOCKING */
702
703 /*
704 * p_myaddr が NADR (-1) か、
705 * 自ポート番号が TCP_PORTANY なら、自動で割り当てる。
706 */
707 if (p_myaddr == NADR || p_myaddr->portno == TCP_PORTANY)
708 tcp_alloc_auto_port(cep);
709 else if ((error = tcp_alloc_port(cep, p_myaddr->portno)) != E_OK)
710 goto err_ret;
711
712 /* コネクションの開設をポストする。*/
713 cep->flags |= TCP_CEP_FLG_POST_OUTPUT;
714 sig_sem(SEM_TCP_POST_OUTPUT);
715
716 /*
717 * イベントが ESTABLISHED になるまで待つ。
718 * イベントが CLOSED になった場合は、何らかのエラーが発生したか、
719 * 接続要求が拒否されたことを意味している。
720 */
721 error = twai_flg(cep->est_flgid, (TCP_CEP_EVT_CLOSED |
722 TCP_CEP_EVT_ESTABLISHED), TWF_ORW, &flag, tmout);
723 if (error == E_OK) {
724 if (cep->error != E_OK)
725 error = cep->error;
726 else if (cep->fsm_state == TCP_FSM_CLOSED)
727 error = E_CLS;
728 }
729
730 syscall(clr_flg(cep->est_flgid, (FLGPTN)(~TCP_CEP_EVT_ESTABLISHED)));
731
732 if (error != E_OK) {
733 /*
734 * 通信端点から受付口を解放し、
735 * イベントフラグをクローズに設定する。
736 */
737 cep->rep = NULL;
738 cep->fsm_state = TCP_FSM_CLOSED;
739 syscall(set_flg(cep->est_flgid, TCP_CEP_EVT_CLOSED));
740 }
741
742#ifdef TCP_CFG_NON_BLOCKING
743
744 }
745
746#endif /* of #ifdef TCP_CFG_NON_BLOCKING */
747
748err_ret:
749 cep->snd_tskid = TA_NULL;
750 cep->snd_tfn = TFN_TCP_UNDEF;
751 return error;
752 }
753
754#endif /* of #ifdef __tcp_con_cep */
755
756#ifdef __tcp_cls_cep
757
758/*
759 * tcp_user_closed -- ユーザからのコネクションの開放
760 */
761
762T_TCP_CEP *
763tcp_user_closed (T_TCP_CEP *cep)
764{
765 switch (cep->fsm_state) {
766
767 case TCP_FSM_CLOSED: /* クローズ */
768 case TCP_FSM_LISTEN: /* 受動オープン */
769 cep->fsm_state = TCP_FSM_CLOSED;
770 cep = tcp_close(cep);
771 break;
772
773 case TCP_FSM_SYN_SENT: /* 能動オープン、SYN 送信済み */
774 case TCP_FSM_SYN_RECVD: /* SYN を受信し、SYN 送信済み */
775 cep->flags |= TCP_CEP_FLG_NEED_FIN;
776 break;
777
778 case TCP_FSM_ESTABLISHED: /* コネクション開設完了 */
779 cep->fsm_state = TCP_FSM_FIN_WAIT_1;
780 break;
781
782 case TCP_FSM_CLOSE_WAIT: /* 相手から FIN 受信、APP の終了待ち */
783 cep->fsm_state = TCP_FSM_LAST_ACK;
784 break;
785 }
786
787 if (cep != NULL && cep->fsm_state == TCP_FSM_FIN_WAIT_2)
788 cep->timer[TCP_TIM_2MSL] = TCP_TVAL_KEEP_COUNT * TCP_TVAL_KEEP_INTERVAL;
789 return cep;
790 }
791
792/*
793 * tcp_cls_cep -- 通信端点のクローズ【標準機能】
794 */
795
796ER
797tcp_cls_cep (ID cepid, TMO tmout)
798{
799 T_TCP_CEP *cep;
800 ER error = E_OK;
801 FLGPTN flag;
802
803#ifndef TCP_CFG_NON_BLOCKING
804
805 /* tmout が TMO_NBLK ならエラー */
806 if (tmout == TMO_NBLK)
807 return E_PAR;
808
809#endif /* of #ifndef TCP_CFG_NON_BLOCKING */
810
811 /*
812 * CEP をロックし、API 機能コードとタスク識別子を記録する。
813 * すでに記録されていれば、ペンディング中なのでエラー
814 */
815 if ((error = tcp_lock_cep(cepid, &cep, TFN_TCP_CLS_CEP)) != E_OK)
816 return error;
817
818#ifdef TCP_CFG_NON_BLOCKING
819
820 /* タイムアウトをチェックする。*/
821 if (tmout == TMO_NBLK) { /* ノンブロッキングコール */
822
823 if (!IS_PTR_DEFINED(cep->callback))
824 error = E_OBJ;
825 else if (cep->fsm_state == TCP_FSM_CLOSED) { /* すでにクローズされているとき */
826
827#ifdef TCP_CFG_NON_BLOCKING_COMPAT14
828
829 (*cep->callback)(GET_TCP_CEPID(cep), TFN_TCP_CLS_CEP, E_OK);
830 error = E_WBLK;
831
832#else /* of #ifdef TCP_CFG_NON_BLOCKING_COMPAT14 */
833
834 ER error = E_OK;
835
836 (*cep->callback)(GET_TCP_CEPID(cep), TFN_TCP_CLS_CEP, (void*)&error);
837 error = E_WBLK;
838
839#endif /* of #ifdef TCP_CFG_NON_BLOCKING_COMPAT14 */
840
841 }
842 else {
843 /* NBLK のAPI 機能コードを設定する。*/
844 cep->rcv_nblk_tfn = TFN_TCP_CLS_CEP;
845
846 if ((cep = tcp_user_closed(cep)) != NULL) { /* コネクションを切断する。*/
847 /* 切断セグメント出力をポストする。*/
848 cep->flags |= TCP_CEP_FLG_POST_OUTPUT;
849 sig_sem(SEM_TCP_POST_OUTPUT);
850 }
851
852 /* cep が NULL で戻ってきた場合は、
853 * 既にコネクションが切断されていることを意味している。
854 * また、この場合コールバック関数が呼び出されている。
855 */
856 return E_WBLK;
857 }
858 }
859 else { /* 非ノンブロッキングコール */
860
861#endif /* of #ifdef TCP_CFG_NON_BLOCKING */
862
863 if ((cep = tcp_user_closed(cep)) == NULL) { /* コネクションを切断する。*/
864
865 /* cep が NULL で戻ってきた場合は、
866 * 既にコネクションが切断されていることを意味している。
867 */
868 return error;
869 }
870 else {
871 /* 切断セグメント出力をポストする。*/
872 cep->flags |= TCP_CEP_FLG_POST_OUTPUT;
873 sig_sem(SEM_TCP_POST_OUTPUT);
874
875 /* イベントフラグが CLOSED になるまで待つ。*/
876 error = twai_flg(cep->est_flgid, TCP_CEP_EVT_CLOSED, TWF_ORW, &flag, tmout);
877 if (error == E_OK && cep->error != E_OK)
878 error = cep->error;
879
880 if (error != E_OK) {
881 if (error == E_RLWAI) {
882 /* tcp_cls_cep がキャンセルされたときは、RST を送信する。*/
883 tcp_respond(NULL, cep, cep->rcv_nxt, cep->snd_una - 1,
884 cep->rbufsz - cep->rwbuf_count, TCP_FLG_RST);
885 }
886
887 /* タイマーを停止する。*/
888 tcp_cancel_timers(cep);
889
890 /*
891 * 通信端点をロックし、
892 * 受信再構成キューのネットワークバッファを解放する。
893 */
894 syscall(wai_sem(cep->semid_lock));
895 tcp_free_reassq(cep);
896 syscall(sig_sem(cep->semid_lock));
897
898 /* 状態を未使用にする。*/
899 cep->fsm_state = TCP_FSM_CLOSED;
900
901 /*
902 * 以下に関係しないフラグをクリアーする。
903 * ・送受信ウィンドバッファの省コピー機能
904 * ・動的な通信端点の生成・削除機能
905 */
906 cep->flags &= (TCP_CEP_FLG_WBCS_NBUF_REQ | TCP_CEP_FLG_WBCS_MASK |
907 TCP_CEP_FLG_DYNAMIC | TCP_CEP_FLG_VALID);
908
909 /*
910 * 通信端点をロックし、
911 * 送受信ウィンドバッファキューのネットワークバッファを解放する。
912 */
913 cep->rwbuf_count = 0;
914 syscall(wai_sem(cep->semid_lock));
915 TCP_FREE_RWBUFQ(cep);
916 TCP_FREE_SWBUFQ(cep);
917 syscall(sig_sem(cep->semid_lock));
918
919 syscall(set_flg(cep->est_flgid, TCP_CEP_EVT_CLOSED));
920 }
921 }
922
923#ifdef TCP_CFG_NON_BLOCKING
924
925 }
926
927#endif /* of #ifdef TCP_CFG_NON_BLOCKING */
928
929 cep->rcv_tskid = TA_NULL;
930 cep->rcv_tfn = TFN_TCP_UNDEF;
931 return error;
932 }
933
934#endif /* of #ifdef __tcp_cls_cep */
935
936#ifdef __tcp_sht_cep
937
938/*
939 * tcp_sht_cep -- データ送信の終了【標準機能】
940 */
941
942ER
943tcp_sht_cep (ID cepid)
944{
945 T_TCP_CEP *cep;
946 ER error = E_OK;
947
948 /*
949 * CEP をロックし、API 機能コードとタスク識別子を記録する。
950 * すでに記録されていれば、ペンディング中なのでエラー
951 */
952 if ((error = tcp_lock_cep(cepid, &cep, TFN_TCP_SHT_CEP)) != E_OK)
953 return error;
954
955 /* TCP 通信端点のコネクションが確立状態でなければエラー */
956 if (!TCP_FSM_HAVE_ESTABLISHED(cep->fsm_state)) {
957 if ((error = cep->error) == E_OK)
958 error = E_OBJ;
959 }
960
961 else if ((cep = tcp_user_closed(cep)) != NULL) { /* コネクションを切断する。*/
962
963 /* 切断セグメント出力をポストする。*/
964 cep->flags |= TCP_CEP_FLG_POST_OUTPUT;
965 sig_sem(SEM_TCP_POST_OUTPUT);
966 }
967
968 cep->snd_tskid = TA_NULL;
969 cep->snd_tfn = TFN_TCP_UNDEF;
970 return error;
971 }
972
973#endif /* of #ifdef __tcp_sht_cep */
974
975#ifdef __tcp_snd_dat
976
977/*
978 * tcp_snd_dat -- パケットの送信【標準機能】
979 */
980
981ER_UINT
982tcp_snd_dat (ID cepid, void *data, int_t len, TMO tmout)
983{
984 T_TCP_CEP *cep;
985 ER_UINT error;
986
987#ifdef TCP_CFG_NON_BLOCKING
988
989 /* data が NULL か、len < 0 ならエラー */
990 if (data == NULL || len < 0)
991 return E_PAR;
992
993#else /* of #ifdef TCP_CFG_NON_BLOCKING */
994
995 /* data が NULL、len < 0 か、tmout が TMO_NBLK ならエラー */
996 if (data == NULL || len < 0 || tmout == TMO_NBLK)
997 return E_PAR;
998
999#endif /* of #ifdef TCP_CFG_NON_BLOCKING */
1000
1001 /*
1002 * CEP をロックし、API 機能コードとタスク識別子を記録する。
1003 * すでに記録されていれば、ペンディング中なのでエラー
1004 */
1005 if ((error = tcp_lock_cep(cepid, &cep, TFN_TCP_SND_DAT)) != E_OK)
1006 return error;
1007
1008 /* 送信できるか、通信端点の状態を見る。*/
1009 if ((error = tcp_can_send_more(cep, TFN_TCP_SND_DAT, tmout)) != E_OK)
1010 goto err_ret;
1011
1012#ifdef TCP_CFG_NON_BLOCKING
1013
1014 /* タイムアウトをチェックする。*/
1015 if (tmout == TMO_NBLK) { /* ノンブロッキングコール */
1016
1017 /* 送信ウィンドバッファに空きがあればコールバック関数を呼び出す。*/
1018 if (!TCP_IS_SWBUF_FULL(cep)) {
1019
1020 /* 送信ウィンドバッファにデータを書き込む。*/
1021 error = TCP_WRITE_SWBUF(cep, data, (uint_t)len);
1022
1023 /* 出力をポストする。*/
1024 cep->flags |= TCP_CEP_FLG_POST_OUTPUT;
1025 sig_sem(SEM_TCP_POST_OUTPUT);
1026
1027#ifdef TCP_CFG_NON_BLOCKING_COMPAT14
1028
1029 /* コールバック関数を呼び出す。*/
1030 (*cep->callback)(GET_TCP_CEPID(cep), TFN_TCP_SND_DAT, (void*)error);
1031
1032#else /* of #ifdef TCP_CFG_NON_BLOCKING_COMPAT14 */
1033
1034 /* コールバック関数を呼び出す。*/
1035 (*cep->callback)(GET_TCP_CEPID(cep), TFN_TCP_SND_DAT, (void*)&error);
1036
1037#endif /* of #ifdef TCP_CFG_NON_BLOCKING_COMPAT14 */
1038
1039 error = E_WBLK;
1040 goto err_ret;
1041 }
1042 else {
1043 cep->snd_data = data;
1044 cep->snd_len = len;
1045 cep->snd_nblk_tfn = TFN_TCP_SND_DAT;
1046 TCP_ALLOC_SWBUF(cep);
1047
1048 return E_WBLK;
1049 }
1050 }
1051 else { /* 非ノンブロッキングコール */
1052
1053#endif /* of #ifdef TCP_CFG_NON_BLOCKING */
1054
1055 /* 送信ウィンドバッファが空くのを待つ。*/
1056 if ((error = TCP_WAIT_SWBUF(cep, tmout)) != E_OK)
1057 goto err_ret;
1058
1059 /* 送信ウィンドバッファにデータを書き込む。*/
1060 if ((error = TCP_WRITE_SWBUF(cep, data, (uint_t)len)) > 0) {
1061
1062 /* データを送信する。送信ウィンドバッファがフルのときは強制的に送信する。*/
1063 if (TCP_IS_SWBUF_FULL(cep))
1064 cep->flags |= TCP_CEP_FLG_FORCE | TCP_CEP_FLG_FORCE_CLEAR;
1065
1066 /* 出力をポストする。*/
1067 cep->flags |= TCP_CEP_FLG_POST_OUTPUT;
1068 sig_sem(SEM_TCP_POST_OUTPUT);
1069 }
1070
1071#ifdef TCP_CFG_NON_BLOCKING
1072
1073 }
1074
1075#endif /* of #ifdef TCP_CFG_NON_BLOCKING */
1076
1077err_ret:
1078 cep->snd_tskid = TA_NULL;
1079 cep->snd_tfn = TFN_TCP_UNDEF;
1080 return error;
1081 }
1082
1083#endif /* of #ifdef __tcp_snd_dat */
1084
1085#ifdef __tcp_snd_oob
1086
1087#ifdef TCP_CFG_EXTENTIONS
1088
1089/*
1090 * tcp_snd_oob -- 緊急データの送信【拡張機能】
1091 */
1092
1093ER_UINT
1094tcp_snd_oob (ID cepid, void *data, int_t len, TMO tmout)
1095{
1096 T_TCP_CEP *cep;
1097 ER_UINT error;
1098
1099#ifdef TCP_CFG_NON_BLOCKING
1100
1101 /* data が NULL か、len < 0 ならエラー */
1102 if (data == NULL || len < 0)
1103 return E_PAR;
1104
1105#else /* of #ifdef TCP_CFG_NON_BLOCKING */
1106
1107 /* data が NULL、len < 0 か、tmout が TMO_NBLK ならエラー */
1108 if (data == NULL || len < 0 || tmout == TMO_NBLK)
1109 return E_PAR;
1110
1111#endif /* of #ifdef TCP_CFG_NON_BLOCKING */
1112
1113 /*
1114 * CEP をロックし、API 機能コードとタスク識別子を記録する。
1115 * すでに記録されていれば、ペンディング中なのでエラー
1116 */
1117 if ((error = tcp_lock_cep(cepid, &cep, TFN_TCP_SND_OOB)) != E_OK)
1118 return error;
1119
1120 /* 送信できるか、通信端点の状態を見る。*/
1121 if ((error = tcp_can_send_more(cep, TFN_TCP_SND_OOB, tmout)) != E_OK)
1122 goto err_ret;
1123
1124#ifdef TCP_CFG_NON_BLOCKING
1125
1126 /* タイムアウトをチェックする。*/
1127 if (tmout == TMO_NBLK) { /* ノンブロッキングコール */
1128
1129 /* 送信ウィンドバッファに空きがあればコールバック関数を呼び出す。*/
1130 if (!TCP_IS_SWBUF_FULL(cep)) {
1131
1132 /* 送信ウィンドバッファにデータを書き込む。*/
1133 error = TCP_WRITE_SWBUF(cep, data, (uint_t)len);
1134
1135 /* 送信緊急ポインタを設定する。*/
1136 cep->snd_up = cep->snd_una + cep->swbuf_count;
1137
1138 /* 出力をポストする。*/
1139 cep->flags |= TCP_CEP_FLG_POST_OUTPUT;
1140 sig_sem(SEM_TCP_POST_OUTPUT);
1141
1142#ifdef TCP_CFG_NON_BLOCKING_COMPAT14
1143
1144 /* コールバック関数を呼び出す。*/
1145 (*cep->callback)(GET_TCP_CEPID(cep), TFN_TCP_SND_OOB, (void*)error);
1146
1147#else /* of #ifdef TCP_CFG_NON_BLOCKING_COMPAT14 */
1148
1149 /* コールバック関数を呼び出す。*/
1150 (*cep->callback)(GET_TCP_CEPID(cep), TFN_TCP_SND_OOB, (void*)&error);
1151
1152#endif /* of #ifdef TCP_CFG_NON_BLOCKING_COMPAT14 */
1153
1154 error = E_WBLK;
1155 goto err_ret;
1156 }
1157 else {
1158 cep->snd_data = data;
1159 cep->snd_len = len;
1160 cep->snd_nblk_tfn = TFN_TCP_SND_OOB;
1161 TCP_ALLOC_SWBUF(cep);
1162
1163 return E_WBLK;
1164 }
1165 }
1166 else { /* 非ノンブロッキングコール */
1167
1168#endif /* of #ifdef TCP_CFG_NON_BLOCKING */
1169
1170 /* 送信ウィンドバッファが空くのを待つ。*/
1171 if ((error = TCP_WAIT_SWBUF(cep, tmout)) != E_OK)
1172 goto err_ret;
1173
1174 /* 送信ウィンドバッファにデータを書き込む。*/
1175 if ((error = TCP_WRITE_SWBUF(cep, data, (uint_t)len)) > 0) {
1176
1177 /* 送信緊急ポインタを設定する。*/
1178 cep->snd_up = cep->snd_una + cep->swbuf_count;
1179
1180 /* データを送信する。送信ウィンドバッファがフルのときは強制的に送信する。*/
1181 if (TCP_IS_SWBUF_FULL(cep))
1182 cep->flags |= TCP_CEP_FLG_FORCE | TCP_CEP_FLG_FORCE_CLEAR;
1183
1184 /* 出力をポストする。*/
1185 cep->flags |= TCP_CEP_FLG_POST_OUTPUT;
1186 sig_sem(SEM_TCP_POST_OUTPUT);
1187 }
1188
1189#ifdef TCP_CFG_NON_BLOCKING
1190
1191 }
1192
1193#endif /* of #ifdef TCP_CFG_NON_BLOCKING */
1194
1195err_ret:
1196 cep->snd_tskid = TA_NULL;
1197 cep->snd_tfn = TFN_TCP_UNDEF;
1198 return error;
1199 }
1200
1201#endif /* of #ifdef TCP_CFG_EXTENTIONS */
1202
1203#endif /* of #ifdef __tcp_snd_oob */
1204
1205#ifdef __tcp_get_buf
1206
1207/*
1208 * tcp_get_buf -- 送信用バッファの獲得【標準機能】
1209 */
1210
1211ER_UINT
1212tcp_get_buf (ID cepid, void **p_buf, TMO tmout)
1213{
1214 T_TCP_CEP *cep;
1215 ER_UINT error;
1216
1217#ifdef TCP_CFG_NON_BLOCKING
1218
1219 /* p_buf が NULL ならエラー */
1220 if (p_buf == NULL)
1221 return E_PAR;
1222
1223#else /* of #ifdef TCP_CFG_NON_BLOCKING */
1224
1225 /* p_buf が NULL か、tmout が TMO_NBLK ならエラー */
1226 if (p_buf == NULL || tmout == TMO_NBLK)
1227 return E_PAR;
1228
1229#endif /* of #ifdef TCP_CFG_NON_BLOCKING */
1230
1231 /*
1232 * CEP をロックし、API 機能コードとタスク識別子を記録する。
1233 * すでに記録されていれば、ペンディング中なのでエラー
1234 */
1235 if ((error = tcp_lock_cep(cepid, &cep, TFN_TCP_GET_BUF)) != E_OK)
1236 return error;
1237
1238 /* 送信できるか、通信端点の状態を見る。*/
1239 if ((error = tcp_can_send_more(cep, TFN_TCP_GET_BUF, tmout)) != E_OK)
1240 goto err_ret;
1241
1242#ifdef TCP_CFG_NON_BLOCKING
1243
1244 /* タイムアウトをチェックする。*/
1245 if (tmout == TMO_NBLK) { /* ノンブロッキングコール */
1246
1247 if (!TCP_IS_SWBUF_FULL(cep)) {
1248
1249 /* 送信ウィンドバッファに空きがあればコールバック関数を呼び出す。*/
1250 error = TCP_GET_SWBUF_ADDR(cep, p_buf);
1251
1252#ifdef TCP_CFG_NON_BLOCKING_COMPAT14
1253
1254 /* コールバック関数を呼び出す。*/
1255 (*cep->callback)(GET_TCP_CEPID(cep), TFN_TCP_GET_BUF, (void*)error);
1256
1257#else /* of #ifdef TCP_CFG_NON_BLOCKING_COMPAT14 */
1258
1259 /* コールバック関数を呼び出す。*/
1260 (*cep->callback)(GET_TCP_CEPID(cep), TFN_TCP_GET_BUF, (void*)&error);
1261
1262#endif /* of #ifdef TCP_CFG_NON_BLOCKING_COMPAT14 */
1263
1264 error = E_WBLK;
1265 goto err_ret;
1266 }
1267 else {
1268 cep->snd_p_buf = p_buf;
1269 cep->snd_nblk_tfn = TFN_TCP_GET_BUF;
1270 TCP_ALLOC_SWBUF(cep);
1271 return E_WBLK;
1272 }
1273 }
1274
1275 else { /* 非ノンブロッキングコール */
1276
1277#endif /* of #ifdef TCP_CFG_NON_BLOCKING */
1278
1279 /* 送信ウィンドバッファが空くのを待つ。*/
1280 if ((error = TCP_WAIT_SWBUF(cep, tmout)) != E_OK)
1281 goto err_ret;
1282
1283 /* 送信ウィンドバッファの空アドレスを獲得する。*/
1284 error = TCP_GET_SWBUF_ADDR(cep, p_buf);
1285
1286#ifdef TCP_CFG_NON_BLOCKING
1287
1288 }
1289
1290#endif /* of #ifdef TCP_CFG_NON_BLOCKING */
1291
1292err_ret:
1293 cep->snd_tskid = TA_NULL;
1294 cep->snd_tfn = TFN_TCP_UNDEF;
1295 return error;
1296 }
1297
1298#endif /* of #ifdef __tcp_get_buf */
1299
1300#ifdef __tcp_snd_buf
1301
1302/*
1303 * tcp_snd_buf -- バッファ内のデータの送信【標準機能】
1304 */
1305
1306ER
1307tcp_snd_buf (ID cepid, int_t len)
1308{
1309 T_TCP_CEP *cep;
1310 ER error;
1311
1312 /* 送信する長さ len をチェックする。*/
1313 if (len < 0)
1314 return E_PAR;
1315
1316 /* 送信する長さlen が 0 であれば、何もしないで戻る。*/
1317 if (len == 0)
1318 return E_OK;
1319
1320 /*
1321 * CEP をロックし、API 機能コードとタスク識別子を記録する。
1322 * すでに記録されていれば、ペンディング中なのでエラー
1323 */
1324 if ((error = tcp_lock_cep(cepid, &cep, TFN_TCP_SND_BUF)) != E_OK)
1325 return error;
1326
1327 /* 送信する長さ len をチェックする。*/
1328 if (len > cep->get_buf_len) {
1329 error = E_OBJ;
1330 goto err_ret;
1331 }
1332
1333 /* 送信できるか、CEP の FSM 状態を見る。*/
1334 if (!TCP_FSM_CAN_SEND_MORE(cep->fsm_state)) {
1335 if ((error = cep->error) == E_OK)
1336 error = E_OBJ;
1337 goto err_ret;
1338 }
1339
1340 /* 送信ウィンドバッファのデータを送信可能にする。*/
1341 TCP_SEND_SWBUF(cep, (uint_t)len);
1342
1343 /* 出力をポストする。*/
1344 cep->flags |= TCP_CEP_FLG_POST_OUTPUT;
1345 sig_sem(SEM_TCP_POST_OUTPUT);
1346
1347err_ret:
1348 cep->snd_tskid = TA_NULL;
1349 cep->snd_tfn = TFN_TCP_UNDEF;
1350 return error;
1351 }
1352
1353#endif /* of #ifdef __tcp_snd_buf */
1354
1355#ifdef __tcp_rcv_dat
1356
1357/*
1358 * tcp_rcv_dat -- パケットの受信【標準機能】
1359 */
1360
1361ER_UINT
1362tcp_rcv_dat (ID cepid, void *data, int_t len, TMO tmout)
1363{
1364 T_TCP_CEP *cep;
1365 ER_UINT error;
1366
1367#ifdef TCP_CFG_NON_BLOCKING
1368
1369 /* data が NULL か、len < 0 ならエラー */
1370 if (data == NULL || len < 0)
1371 return E_PAR;
1372
1373#else /* of #ifdef TCP_CFG_NON_BLOCKING */
1374
1375 /* data が NULL、len < 0 か、tmout が TMO_NBLK ならエラー */
1376 if (data == NULL || len < 0 || tmout == TMO_NBLK)
1377 return E_PAR;
1378
1379#endif /* of #ifdef TCP_CFG_NON_BLOCKING */
1380
1381 /*
1382 * CEP をロックし、API 機能コードとタスク識別子を記録する。
1383 * すでに記録されていれば、ペンディング中なのでエラー
1384 */
1385 if ((error = tcp_lock_cep(cepid, &cep, TFN_TCP_RCV_DAT)) != E_OK)
1386 return error;
1387
1388 /* 受信できるか、通信端点の状態を見る。*/
1389 if (tcp_can_recv_more(&error, cep, TFN_TCP_RCV_DAT, tmout) != E_OK)
1390 goto err_ret;
1391
1392#ifdef TCP_CFG_NON_BLOCKING
1393
1394 /* タイムアウトをチェックする。*/
1395 if (tmout == TMO_NBLK) { /* ノンブロッキングコール */
1396
1397 /* 受信ウィンドバッファにデータがあればコールバック関数を呼び出す。*/
1398 if (cep->rwbuf_count > 0) {
1399
1400 /* 受信ウィンドバッファからデータを取り出す。*/
1401 len = TCP_READ_RWBUF(cep, data, (uint_t)len);
1402
1403#ifdef TCP_CFG_NON_BLOCKING_COMPAT14
1404
1405 (*cep->callback)(GET_TCP_CEPID(cep), TFN_TCP_RCV_DAT, (void*)(uint32_t)len);
1406
1407#else /* of #ifdef TCP_CFG_NON_BLOCKING_COMPAT14 */
1408
1409 (*cep->callback)(GET_TCP_CEPID(cep), TFN_TCP_RCV_DAT, (void*)&len);
1410
1411#endif /* of #ifdef TCP_CFG_NON_BLOCKING_COMPAT14 */
1412
1413 error = E_WBLK;
1414 goto err_ret;
1415 }
1416 else {
1417 cep->rcv_data = data;
1418 cep->rcv_len = len;
1419 cep->rcv_nblk_tfn = TFN_TCP_RCV_DAT;
1420 return E_WBLK;
1421 }
1422 }
1423 else { /* 非ノンブロッキングコール */
1424
1425#endif /* of #ifdef TCP_CFG_NON_BLOCKING */
1426
1427 /* 受信ウィンドバッファにデータがなければ、入力があるまで待つ。*/
1428 if ((error = tcp_wait_rwbuf(cep, tmout)) != E_OK)
1429 goto err_ret;
1430
1431 /* 受信ウィンドバッファからデータを取り出す。*/
1432 error = TCP_READ_RWBUF(cep, data, (uint_t)len);
1433
1434 /* 相手にウィンドウサイズが変わったことを知らせるため出力をポストする。*/
1435 cep->flags |= TCP_CEP_FLG_POST_OUTPUT;
1436 sig_sem(SEM_TCP_POST_OUTPUT);
1437
1438#ifdef TCP_CFG_NON_BLOCKING
1439
1440 }
1441
1442#endif /* of #ifdef TCP_CFG_NON_BLOCKING */
1443
1444err_ret:
1445 cep->rcv_tskid = TA_NULL;
1446 cep->rcv_tfn = TFN_TCP_UNDEF;
1447 return error;
1448 }
1449
1450#endif /* of #ifdef __tcp_rcv_dat */
1451
1452#ifdef __tcp_rcv_oob
1453
1454#ifdef TCP_CFG_EXTENTIONS
1455
1456/*
1457 * tcp_rcv_oob -- 緊急データの受信【拡張機能】
1458 *
1459 * 注意: 送信側が複数オクテットのデータを送信しても、
1460 * 緊急ポインタが指す 1 オクテットのデータのみ受信する。
1461 */
1462
1463ER_UINT
1464tcp_rcv_oob (ID cepid, void *data, int_t len)
1465{
1466 T_TCP_CEP *cep;
1467 uint8_t *urg;
1468
1469 /* TCP 通信端点 ID をチェックする。*/
1470 if (!VAID_TCP_CEPID(cepid))
1471 return E_ID;
1472
1473 /* data が NULL か、len < 0 ならエラー */
1474 if (data == NULL || len < 0)
1475 return E_PAR;
1476
1477 /* TCP 通信端点を得る。*/
1478 cep = GET_TCP_CEP(cepid);
1479
1480 /* 受信できるか、通信端点の状態を見る。*/
1481 /* 受信できるか、fsm_state を見る。*/
1482 if (!TCP_FSM_CAN_RECV_MORE(cep->fsm_state))
1483 return E_OBJ;
1484
1485 /*
1486 * 緊急データ入りのセグメントの TCP ヘッダが
1487 * 設定されていなければ、緊急データを受信していない。
1488 */
1489 if (cep->urg_tcph == NULL)
1490 return E_OBJ;
1491
1492 /* len == 0 ならバッファオーバーフロー */
1493 if (len == 0)
1494 return E_BOVR;
1495
1496 /* 緊急ポインタが指す 1 オクテットのデータを読み取る。*/
1497 urg = (uint8_t*)cep->urg_tcph + TCP_DATA_OFF(cep->urg_tcph->doff) + cep->urg_tcph->urp + TCP_CFG_URG_OFFSET;
1498 *(uint8_t*)data = *urg;
1499
1500 /* 読み取ったデータから後ろの SDU を前に詰める。*/
1501 memcpy(urg, urg + 1, cep->urg_tcph->sum - (cep->urg_tcph->urp + TCP_CFG_URG_OFFSET) - 1);
1502
1503 /* tcp_rcv_oob() が呼出されたこと知らせるために、NULL を設定する。*/
1504 cep->urg_tcph = NULL;
1505
1506 return 1;
1507 }
1508
1509#endif /* of #ifdef TCP_CFG_EXTENTIONS */
1510
1511#endif /* of #ifdef __tcp_rcv_oob */
1512
1513#ifdef __tcp_rcv_buf
1514
1515/*
1516 * tcp_rcv_buf -- 受信したデータの入ったバッファの獲得【標準機能】
1517 */
1518
1519ER_UINT
1520tcp_rcv_buf (ID cepid, void **p_buf, TMO tmout)
1521{
1522 T_TCP_CEP *cep;
1523 ER_UINT error;
1524
1525#ifdef TCP_CFG_NON_BLOCKING
1526
1527 /* p_buf が NULL ならエラー */
1528 if (p_buf == NULL)
1529 return E_PAR;
1530
1531#else /* of #ifdef TCP_CFG_NON_BLOCKING */
1532
1533 /* p_buf が NULL か、tmout が TMO_NBLK ならエラー */
1534 if (p_buf == NULL || tmout == TMO_NBLK)
1535 return E_PAR;
1536
1537#endif /* of #ifdef TCP_CFG_NON_BLOCKING */
1538
1539 /*
1540 * CEP をロックし、API 機能コードとタスク識別子を記録する。
1541 * すでに記録されていれば、ペンディング中なのでエラー
1542 */
1543 if ((error = tcp_lock_cep(cepid, &cep, TFN_TCP_RCV_BUF)) != E_OK)
1544 return error;
1545
1546 /* 受信できるか、通信端点の状態を見る。*/
1547 if (tcp_can_recv_more(&error, cep, TFN_TCP_RCV_DAT, tmout) != E_OK)
1548 goto err_ret;
1549
1550#ifdef TCP_CFG_NON_BLOCKING
1551
1552 /* タイムアウトをチェックする。*/
1553 if (tmout == TMO_NBLK) { /* ノンブロッキングコール */
1554
1555 /* 受信ウィンドバッファにデータがあればコールバック関数を呼び出す。*/
1556 if (cep->rwbuf_count > 0) {
1557
1558 /* 受信ウィンドバッファの空アドレスを獲得する。*/
1559 error = TCP_GET_RWBUF_ADDR(cep, p_buf);
1560
1561#ifdef TCP_CFG_NON_BLOCKING_COMPAT14
1562
1563 /* コールバック関数を呼び出す。*/
1564 (*cep->callback)(GET_TCP_CEPID(cep), TFN_TCP_RCV_BUF, (void*)error);
1565
1566#else /* of #ifdef TCP_CFG_NON_BLOCKING_COMPAT14 */
1567
1568 /* コールバック関数を呼び出す。*/
1569 (*cep->callback)(GET_TCP_CEPID(cep), TFN_TCP_RCV_BUF, (void*)&error);
1570
1571#endif /* of #ifdef TCP_CFG_NON_BLOCKING_COMPAT14 */
1572
1573 error = E_WBLK;
1574 goto err_ret;
1575 }
1576 else {
1577 cep->rcv_p_buf = p_buf;
1578 cep->rcv_nblk_tfn = TFN_TCP_RCV_BUF;
1579 return E_WBLK;
1580 }
1581 }
1582 else { /* 非ノンブロッキングコール */
1583
1584#endif /* of #ifdef TCP_CFG_NON_BLOCKING */
1585
1586 /* 受信ウィンドバッファにデータがなければ、入力があるまで待つ。*/
1587 if ((error = tcp_wait_rwbuf(cep, tmout)) != E_OK) {
1588 cep->rwbuf_count = 0;
1589 goto err_ret;
1590 }
1591
1592 /* 受信ウィンドバッファのアドレスを獲得する。*/
1593 error = TCP_GET_RWBUF_ADDR(cep, p_buf);
1594
1595#ifdef TCP_CFG_NON_BLOCKING
1596
1597 }
1598
1599#endif /* of #ifdef TCP_CFG_NON_BLOCKING */
1600
1601err_ret:
1602 cep->rcv_tskid = TA_NULL;
1603 cep->rcv_tfn = TFN_TCP_UNDEF;
1604 return error;
1605 }
1606
1607#endif /* of #ifdef __tcp_rcv_buf */
1608
1609#ifdef __tcp_rel_buf
1610
1611/*
1612 * tcp_rel_buf -- 受信用バッファの解放【標準機能】
1613 */
1614
1615ER
1616tcp_rel_buf (ID cepid, int_t len)
1617{
1618 T_TCP_CEP *cep;
1619 ER error;
1620
1621 /* 解放する長さ len をチェックする。*/
1622 if (len < 0)
1623 return E_PAR;
1624
1625 /*
1626 * CEP をロックし、API 機能コードとタスク識別子を記録する。
1627 * すでに記録されていれば、ペンディング中なのでエラー
1628 */
1629 if ((error = tcp_lock_cep(cepid, &cep, TFN_TCP_REL_BUF)) != E_OK)
1630 return error;
1631
1632 /* 解放する長さ len をチェックする。*/
1633 if (len > cep->rcv_buf_len) {
1634 error = E_OBJ;
1635 goto err_ret;
1636 }
1637
1638 /* 通信端点をロックする。*/
1639 syscall(wai_sem(cep->semid_lock));
1640
1641 /* 受信ウィンドバッファから受信したオクテットを削除する。*/
1642 TCP_DROP_RWBUF(cep, (uint_t)len);
1643
1644 /* tcp_rcv_buf の割当て長をリセットする。*/
1645 cep->rcv_buf_len = 0;
1646
1647 /* 通信端点のロックを解除する。*/
1648 syscall(sig_sem(cep->semid_lock));
1649
1650 /* 相手にウィンドウサイズが変わったことを知らせるため出力をポストする。*/
1651 cep->flags |= TCP_CEP_FLG_POST_OUTPUT;
1652 sig_sem(SEM_TCP_POST_OUTPUT);
1653
1654err_ret:
1655 cep->rcv_tskid = TA_NULL;
1656 cep->rcv_tfn = TFN_TCP_UNDEF;
1657 return error;
1658 }
1659
1660#endif /* of #ifdef __tcp_rel_buf */
1661
1662#ifdef __tcp_can_cep
1663
1664/*
1665 * tcp_can_snd -- ペンディングしている送信のキャンセル
1666 */
1667
1668static ER
1669tcp_can_snd (T_TCP_CEP *cep, FN fncd)
1670{
1671 ER error = E_OK;
1672
1673 /* 通信端点をロックする。*/
1674 syscall(wai_sem(cep->semid_lock));
1675
1676 /*
1677 * snd_tskid が TA_NULL なら、
1678 * ペンディングしていないのでエラー
1679 */
1680 if (cep->snd_tskid == TA_NULL)
1681 error = EV_NOPND;
1682
1683 /* ペンディング中の API 機能コードと一致しなければエラー */
1684 else if (fncd != TFN_TCP_ALL && fncd != cep->snd_tfn)
1685 error = E_OBJ;
1686
1687 /* 処理をキャンセルする。*/
1688 else {
1689
1690 /* 受信再構成キューのネットワークバッファを解放する。*/
1691 tcp_free_reassq(cep);
1692
1693 /* 受信ウィンドバッファキューのネットワークバッファを解放する。*/
1694 cep->rwbuf_count = 0;
1695 TCP_FREE_RWBUFQ(cep);
1696
1697 /* 送信ウィンドバッファキューのネットワークバッファを解放する。*/
1698 TCP_FREE_SWBUFQ(cep);
1699
1700#ifdef TCP_CFG_NON_BLOCKING
1701
1702 if (cep->snd_nblk_tfn != TFN_TCP_UNDEF) { /* ノンブロッキングコール */
1703
1704 switch (cep->snd_nblk_tfn) {
1705
1706 case TFN_TCP_CON_CEP:
1707 /* 通信端点から受付口を解放する。*/
1708 cep->rep = NULL;
1709 cep->fsm_state = TCP_FSM_CLOSED;
1710 syscall(set_flg(cep->est_flgid, TCP_CEP_EVT_CLOSED));
1711 break;
1712
1713 case TFN_TCP_SND_DAT:
1714 case TFN_TCP_GET_BUF:
1715 case TFN_TCP_SND_OOB:
1716 break;
1717 }
1718
1719 if (IS_PTR_DEFINED(cep->callback)) {
1720
1721#ifdef TCP_CFG_NON_BLOCKING_COMPAT14
1722
1723 (*cep->callback)(GET_TCP_CEPID(cep), cep->snd_nblk_tfn, (void*)E_RLWAI);
1724
1725#else /* of #ifdef TCP_CFG_NON_BLOCKING_COMPAT14 */
1726
1727 ER error = E_RLWAI;
1728
1729 (*cep->callback)(GET_TCP_CEPID(cep), cep->snd_nblk_tfn, (void*)&error);
1730
1731#endif /* of #ifdef TCP_CFG_NON_BLOCKING_COMPAT14 */
1732
1733 }
1734 else
1735 error = E_OBJ;
1736 cep->snd_nblk_tfn = TFN_TCP_UNDEF;
1737 }
1738 else
1739
1740#endif /* of #ifdef TCP_CFG_NON_BLOCKING */
1741
1742 error = rel_wai(cep->snd_tskid);
1743
1744 cep->snd_tskid = TA_NULL;
1745 cep->snd_tfn = TFN_TCP_UNDEF;
1746 }
1747
1748 /* 通信端点のロックを解除する。*/
1749 syscall(sig_sem(cep->semid_lock));
1750
1751 return error;
1752 }
1753
1754/*
1755 * tcp_can_rcv -- ペンディングしている受信のキャンセル
1756 */
1757
1758static ER
1759tcp_can_rcv (T_TCP_CEP *cep, FN fncd)
1760{
1761 ER error = E_OK;
1762
1763 /* 通信端点をロックする。*/
1764 syscall(wai_sem(cep->semid_lock));
1765
1766 /*
1767 * rcv_tskid が TA_NULL なら、
1768 * ペンディングしていないのでエラー
1769 */
1770 if (cep->rcv_tskid == TA_NULL)
1771 error = EV_NOPND;
1772
1773 /* ペンディング中の API 機能コードと一致しなければエラー */
1774 else if (fncd != TFN_TCP_ALL && fncd != cep->rcv_tfn)
1775 error = E_OBJ;
1776
1777 /* 処理をキャンセルする。*/
1778 else {
1779
1780 /* 受信再構成キューのネットワークバッファを解放する。*/
1781 tcp_free_reassq(cep);
1782
1783 /* 受信ウィンドバッファキューのネットワークバッファを解放する。*/
1784 cep->rwbuf_count = 0;
1785 TCP_FREE_RWBUFQ(cep);
1786
1787 /* 送信ウィンドバッファキューのネットワークバッファを解放する。*/
1788 TCP_FREE_SWBUFQ(cep);
1789
1790#ifdef TCP_CFG_NON_BLOCKING
1791
1792 if (cep->rcv_nblk_tfn != TFN_TCP_UNDEF) { /* ノンブロッキングコール */
1793
1794 switch (cep->rcv_nblk_tfn) {
1795
1796 case TFN_TCP_ACP_CEP:
1797 /*
1798 * 通信端点から受付口を解放し、
1799 * イベントフラグをクローズに設定する。
1800 */
1801 cep->rep = NULL;
1802 cep->fsm_state = TCP_FSM_CLOSED;
1803 syscall(set_flg(cep->est_flgid, TCP_CEP_EVT_CLOSED));
1804 break;
1805
1806 case TFN_TCP_RCV_DAT:
1807 case TFN_TCP_RCV_BUF:
1808 break;
1809
1810 case TFN_TCP_CLS_CEP:
1811 cep->fsm_state = TCP_FSM_CLOSED;
1812 tcp_respond(NULL, cep, cep->rcv_nxt, cep->snd_una - 1,
1813 cep->rbufsz - cep->rwbuf_count, TCP_FLG_RST);
1814 syscall(set_flg(cep->est_flgid, TCP_CEP_EVT_CLOSED));
1815 break;
1816 }
1817
1818 if (IS_PTR_DEFINED(cep->callback)) {
1819
1820#ifdef TCP_CFG_NON_BLOCKING_COMPAT14
1821
1822 (*cep->callback)(GET_TCP_CEPID(cep), cep->rcv_nblk_tfn, (void*)E_RLWAI);
1823
1824#else /* of #ifdef TCP_CFG_NON_BLOCKING_COMPAT14 */
1825
1826 ER error = E_RLWAI;
1827
1828 (*cep->callback)(GET_TCP_CEPID(cep), cep->rcv_nblk_tfn, (void*)&error);
1829
1830#endif /* of #ifdef TCP_CFG_NON_BLOCKING_COMPAT14 */
1831
1832 }
1833 else
1834 error = E_OBJ;
1835 cep->rcv_nblk_tfn = TFN_TCP_UNDEF;
1836 }
1837 else
1838
1839#endif /* of #ifdef TCP_CFG_NON_BLOCKING */
1840
1841 error = rel_wai(cep->rcv_tskid);
1842
1843 cep->rcv_tskid = TA_NULL;
1844 cep->rcv_tfn = TFN_TCP_UNDEF;
1845 }
1846
1847 /* 通信端点のロックを解除する。*/
1848 syscall(sig_sem(cep->semid_lock));
1849
1850 return error;
1851 }
1852
1853/*
1854 * tcp_can_cep -- ペンディングしている処理のキャンセル【標準機能】
1855 */
1856
1857ER
1858tcp_can_cep (ID cepid, FN fncd)
1859{
1860 T_TCP_CEP *cep;
1861 ER error = E_OK, snd_err, rcv_err;
1862
1863 /* API 機能コードをチェックする。*/
1864 if (!VALID_TFN_TCP_CAN(fncd))
1865 return E_PAR;
1866
1867 /* TCP 通信端点 ID をチェックする。*/
1868 if (!VAID_TCP_CEPID(cepid))
1869 return E_ID;
1870
1871 /* TCP 通信端点を得る。*/
1872 cep = GET_TCP_CEP(cepid);
1873
1874 /* TCP 通信端点をチェックする。*/
1875 if (!VALID_TCP_CEP(cep))
1876 return E_NOEXS;
1877
1878 if (fncd == TFN_TCP_ALL) { /* TFN_TCP_ALL の処理 */
1879 snd_err = tcp_can_snd(cep, fncd);
1880 rcv_err = tcp_can_rcv(cep, fncd);
1881
1882 /*
1883 * snd_err と rcv_err のどちらも EV_NOPND
1884 * なら、ペンディングしていないのでエラー
1885 */
1886 if (snd_err == EV_NOPND && rcv_err == EV_NOPND)
1887 error = E_OBJ;
1888 else {
1889 if (snd_err == EV_NOPND)
1890 snd_err = E_OK;
1891 if (rcv_err == EV_NOPND)
1892 rcv_err = E_OK;
1893
1894 if (snd_err != E_OK)
1895 error = snd_err;
1896 else if (rcv_err != E_OK)
1897 error = rcv_err;
1898 }
1899 }
1900
1901 else if (IS_TFN_TCP_RCV(fncd)) { /* 受信処理のキャンセル */
1902 if ((error = tcp_can_rcv(cep, fncd)) == EV_NOPND)
1903 error = E_OBJ;
1904 }
1905
1906 else { /* 送信処理のキャンセル */
1907 if ((error = tcp_can_snd(cep, fncd)) == EV_NOPND)
1908 error = E_OBJ;
1909 }
1910
1911 return error;
1912 }
1913
1914#endif /* of #ifdef __tcp_can_cep */
1915
1916/*
1917 * tcp_set_opt -- TCP 通信端点オプションの設定【拡張機能】
1918 *
1919 * 注意: 設定可能な TCP 通信端点オプションは無いため、E_PAR が返される。
1920 */
1921
1922#ifdef __tcp_set_opt
1923
1924#ifdef TCP_CFG_EXTENTIONS
1925
1926ER
1927tcp_set_opt (ID cepid, int_t optname, void *optval, int_t optlen)
1928{
1929 T_TCP_CEP *cep;
1930
1931 /* TCP 通信端点 ID をチェックする。*/
1932 if (!VAID_TCP_CEPID(cepid))
1933 return E_ID;
1934
1935 /* TCP 通信端点を得る。*/
1936 cep = GET_TCP_CEP(cepid);
1937
1938 /* TCP 通信端点をチェックする。*/
1939 if (!VALID_TCP_CEP(cep))
1940 return E_NOEXS;
1941
1942 return E_PAR;
1943 }
1944
1945#endif /* of #ifdef TCP_CFG_EXTENTIONS */
1946
1947#endif /* of #ifdef __tcp_set_opt */
1948
1949/*
1950 * tcp_get_opt -- TCP 通信端点オプションの設定【拡張機能】
1951 *
1952 * 注意: 設定可能な TCP 通信端点オプションは無いため、E_PAR が返される。
1953 */
1954
1955#ifdef __tcp_get_opt
1956
1957#ifdef TCP_CFG_EXTENTIONS
1958
1959ER
1960tcp_get_opt (ID cepid, int_t optname, void *optval, int_t optlen)
1961{
1962 T_TCP_CEP *cep;
1963
1964 /* TCP 通信端点 ID をチェックする。*/
1965 if (!VAID_TCP_CEPID(cepid))
1966 return E_ID;
1967
1968 /* TCP 通信端点を得る。*/
1969 cep = GET_TCP_CEP(cepid);
1970
1971 /* TCP 通信端点をチェックする。*/
1972 if (!VALID_TCP_CEP(cep))
1973 return E_NOEXS;
1974
1975 return E_PAR;
1976 }
1977
1978#endif /* of #ifdef TCP_CFG_EXTENTIONS */
1979
1980#endif /* of #ifdef __tcp_get_opt */
1981
1982#endif /* of #ifdef SUPPORT_TCP */
Note: See TracBrowser for help on using the repository browser.