source: EcnlProtoTool/trunk/asp3_dcre/tinet/netinet/udp_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: 19.8 KB
Line 
1/*
2 * TINET (UDP/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, 1990, 1993, 1995
36 * The Regents of the University of California. All rights reserved.
37 *
38 * Redistribution and use in source and binary forms, with or without
39 * modification, are permitted provided that the following conditions
40 * are met:
41 * 1. Redistributions of source code must retain the above copyright
42 * notice, this list of conditions and the following disclaimer.
43 * 2. Redistributions in binary form must ceproduce 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 * @(#)udp_usrreq.c 8.6 (Berkeley) 5/23/95
67 * $FreeBSD: src/sys/netinet/udp_usrreq.c,v 1.49.2.2 1999/08/29 16:29:58 peter Exp $
68 */
69
70/*
71 * ノンブロッキングコールを組込まない場合にリンクされる関数の定義
72 */
73
74#include <string.h>
75
76#ifdef TARGET_KERNEL_ASP
77
78#include <kernel.h>
79#include <sil.h>
80
81#endif /* of #ifdef TARGET_KERNEL_ASP */
82
83#ifdef TARGET_KERNEL_JSP
84
85#include <s_services.h>
86#include <t_services.h>
87#include "kernel_id.h"
88
89#endif /* of #ifdef TARGET_KERNEL_JSP */
90
91#include <tinet_defs.h>
92#include <tinet_config.h>
93
94#include <net/if.h>
95#include <net/if_ppp.h>
96#include <net/if_loop.h>
97#include <net/ethernet.h>
98#include <net/net.h>
99#include <net/net_buf.h>
100#include <net/net_count.h>
101#include <net/ppp_ipcp.h>
102
103#include <netinet/in.h>
104#include <netinet6/in6.h>
105#include <netinet/in_var.h>
106#include <netinet/in_itron.h>
107#include <netinet/ip.h>
108#include <netinet/ip_var.h>
109#include <netinet/ip_icmp.h>
110#include <netinet6/in6_var.h>
111#include <netinet/ip6.h>
112#include <netinet6/ip6_var.h>
113#include <netinet6/nd6.h>
114#include <netinet/icmp6.h>
115#include <netinet/udp.h>
116#include <netinet/udp_var.h>
117
118#ifdef SUPPORT_UDP
119
120/*
121 * IPv4 と IPv6 の切り替えマクロ
122 */
123
124#if defined(SUPPORT_INET4)
125
126#define UDP_CRE_CEP udp_cre_cep
127#define UDP_SND_DAT udp_snd_dat
128#define UDP_RCV_DAT udp_rcv_dat
129
130#endif /* of #if defined(SUPPORT_INET4) */
131
132#if defined(SUPPORT_INET6)
133
134#define UDP_CRE_CEP udp6_cre_cep
135#define UDP_SND_DAT udp6_snd_dat
136#define UDP_RCV_DAT udp6_rcv_dat
137
138#endif /* of #if defined(SUPPORT_INET6) */
139
140/*
141 * TINET をライブラリ化しない場合は、全ての機能を
142 * オブジェクトファイルに出力するため、マクロを有効にする。
143 */
144
145#ifndef UDP_CFG_LIBRARY
146
147#define __udp_send_data
148#define __udp_cre_cep
149#define __udp_del_cep
150#define __udp_can_cep
151#define __udp_set_opt
152#define __udp_get_opt
153#define __udp_can_snd
154#define __udp_can_rcv
155#define __udp_snd_dat
156#define __udp_rcv_dat
157
158#endif /* of #ifndef UDP_CFG_LIBRARY */
159
160#ifdef __udp_send_data
161
162/*
163 * udp_send_data -- パケット送信の主要部
164 */
165
166ER_UINT
167udp_send_data (T_UDP_CEP *cep, T_IPEP *p_dstaddr, void *data, int_t len, TMO tmout)
168{
169 T_NET_BUF *output;
170 T_UDP_HDR *udph;
171 SYSTIM before, after;
172 ER error = E_OK;
173
174#ifdef UDP_CFG_OUT_CHECKSUM
175 uint16_t sum;
176#endif /* of #ifdef UDP_CFG_OUT_CHECKSUM */
177
178 NET_COUNT_UDP(net_count_udp.out_octets, len);
179 NET_COUNT_UDP(net_count_udp.out_packets, 1);
180
181 /* IP データグラム割り当ての時間を tmout から減ずる。*/
182 if (!(tmout == TMO_POL || tmout == TMO_FEVR))
183 syscall(get_tim(&before));
184
185 /* IP データグラムを割り当てる。*/
186 if ((error = IN_GET_DATAGRAM(&output, (uint_t)(UDP_HDR_SIZE + len), 0,
187 &p_dstaddr->ipaddr,
188 &cep->myaddr.ipaddr,
189 IPPROTO_UDP, IP_DEFTTL,
190 NBA_SEARCH_ASCENT, tmout)) != E_OK)
191 goto err_ret;
192
193 /* IP データグラム割り当ての時間を tmout から減ずる。*/
194 if (!(tmout == TMO_POL || tmout == TMO_FEVR)) {
195 syscall(get_tim(&after));
196 if (after - before > tmout) {
197 syscall(rel_net_buf(output));
198 error = E_TMOUT;
199 goto err_ret;
200 }
201 tmout -= (TMO)(after - before);
202 }
203
204 /* UDP ヘッダに情報を設定する。*/
205 udph = GET_UDP_HDR(output, IF_IP_UDP_HDR_OFFSET);
206 udph->sport = htons(cep->myaddr.portno);
207 udph->dport = htons(p_dstaddr->portno);
208 udph->ulen = htons(UDP_HDR_SIZE + len);
209 udph->sum = 0;
210
211 /* データをコピーする。*/
212 memcpy((void*)GET_UDP_SDU(output, IF_IP_UDP_HDR_OFFSET), data, (size_t)len);
213
214#ifdef UDP_CFG_OUT_CHECKSUM
215
216 sum = IN_CKSUM(output, IPPROTO_UDP, IF_IP_UDP_HDR_OFFSET, (uint_t)(UDP_HDR_SIZE + len));
217
218 /* 計算したチェックサムの値が 0 なら 0xffff を入れる。*/
219 if (sum == 0)
220 sum = 0xffff;
221 udph->sum = sum;
222
223#endif /* of #ifdef UDP_CFG_OUT_CHECKSUM */
224
225 /* ネットワークバッファ長を調整する。*/
226 output->len = (uint16_t)(IF_IP_UDP_HDR_SIZE + len);
227
228 /* ネットワーク層 (IP) の出力関数を呼び出す。*/
229 if ((error = IP_OUTPUT(output, tmout)) == E_OK) {
230 NET_COUNT_MIB(udp_stats.udpOutDatagrams, 1);
231 cep->snd_tskid = TA_NULL;
232 return len;
233 }
234
235err_ret:
236 NET_COUNT_UDP(net_count_udp.out_err_packets, 1);
237 cep->snd_tskid = TA_NULL;
238 return error;
239 }
240
241#endif /* of #ifdef __udp_send_data */
242
243/*
244 * udp_cre_cep -- UDP 通信端点の生成【拡張機能】
245 */
246
247#ifdef __udp_cre_cep
248
249#ifdef UDP_CFG_EXTENTIONS
250
251ER
252UDP_CRE_CEP (ID cepid, T_UDP_CCEP *pk_ccep)
253{
254 T_UDP_CEP *cep;
255 ER error;
256
257 /* UDP 通信端点 ID をチェックする。*/
258 if (!VALID_UDP_CEPID(cepid))
259 return E_ID;
260
261 /* pk_ccep が NULL ならエラー */
262 if (pk_ccep == NULL)
263 return E_PAR;
264
265 /* UDP 通信端点を得る。*/
266 cep = GET_UDP_CEP(cepid);
267
268 /* UDP 通信端点をチェックする。*/
269 if (VALID_UDP_CEP(cep))
270 return E_OBJ;
271
272 /* UDP 通信端点が、動的生成用でなければエラー */
273 if (!DYNAMIC_UDP_CEP(cep))
274 return E_ID;
275
276 /* 通信端点をロックする。*/
277 syscall(wai_sem(cep->semid_lock));
278
279 /*
280 * UDP 通信端点をチェックする。生成済みであればエラー
281 */
282 if (VALID_UDP_CEP(cep))
283 error = E_OBJ;
284 else {
285
286 /*
287 * 自ポート番号が UDP_PORTANY なら、自動で割り当てる。
288 */
289 if (pk_ccep->myaddr.portno == UDP_PORTANY)
290 error = udp_alloc_auto_port(cep);
291 else
292 error = udp_alloc_port(cep, pk_ccep->myaddr.portno);
293
294 if (error == E_OK) {
295
296 /* UDP 通信端点生成情報をコピーする。*/
297 cep->cepatr = pk_ccep->cepatr; /* 通信端点属性 */
298 cep->myaddr.ipaddr = pk_ccep->myaddr.ipaddr; /* 自分のアドレス */
299 cep->callback = (void*)pk_ccep->callback; /* コールバック */
300
301 /* UDP 通信端点を生成済みにする。*/
302 cep->flags |= UDP_CEP_FLG_VALID;
303 }
304 }
305
306 /* 通信端点のロックを解除する。*/
307 syscall(sig_sem(cep->semid_lock));
308
309 return error;
310 }
311
312#endif /* of #ifdef UDP_CFG_EXTENTIONS */
313
314#endif /* of #ifdef __udp_cre_cep */
315
316/*
317 * udp_del_cep -- UDP 通信端点の削除【拡張機能】
318 */
319
320#ifdef __udp_del_cep
321
322#ifdef UDP_CFG_EXTENTIONS
323
324ER
325udp_del_cep (ID cepid)
326{
327 T_UDP_CEP *cep;
328 ER error;
329
330 /* UDP 通信端点 ID をチェックする。*/
331 if (!VALID_UDP_CEPID(cepid))
332 return E_ID;
333
334 /* UDP 通信端点を得る。*/
335 cep = GET_UDP_CEP(cepid);
336
337 /* UDP 通信端点をチェックする。*/
338 if (!VALID_UDP_CEP(cep))
339 return E_NOEXS;
340
341 /* UDP 通信端点が、動的生成用でなければエラー */
342 if (!DYNAMIC_UDP_CEP(cep))
343 return E_ID;
344
345 /* 通信端点をロックする。*/
346 syscall(wai_sem(cep->semid_lock));
347
348 /*
349 * UDP 通信端点をチェックする。未生成の場合はエラー
350 * ・未生成。
351 */
352 if (!VALID_UDP_CEP(cep))
353 error = E_NOEXS;
354 else {
355 udp_can_snd(cep, E_DLT);
356 udp_can_rcv(cep, E_DLT);
357
358 /* UDP 通信端点を未生成にする。*/
359 cep->flags &= ~UDP_CEP_FLG_VALID;
360 error = E_OK;
361 }
362
363 /* 通信端点のロックを解除する。*/
364 syscall(sig_sem(cep->semid_lock));
365
366 return error;
367 }
368
369#endif /* of #ifdef UDP_CFG_EXTENTIONS */
370
371#endif /* of #ifdef __udp_del_cep */
372
373#ifdef __udp_can_cep
374
375/*
376 * udp_can_cep -- ペンディングしている処理のキャンセル【標準機能】
377 */
378
379ER
380udp_can_cep (ID cepid, FN fncd)
381{
382 T_UDP_CEP *cep;
383 ER error = E_OK, snd_err, rcv_err;
384
385 /* API 機能コードをチェックする。*/
386 if (!VALID_TFN_UDP_CAN(fncd))
387 return E_PAR;
388
389 /* UDP 通信端点 ID をチェックする。*/
390 if (!VALID_UDP_CEPID(cepid))
391 return E_ID;
392
393 /* UDP 通信端点を得る。*/
394 cep = GET_UDP_CEP(cepid);
395
396 /* UDP 通信端点をチェックする。*/
397 if (!VALID_UDP_CEP(cep))
398 return E_NOEXS;
399
400 /* 通信端点をロックする。*/
401 syscall(wai_sem(cep->semid_lock));
402
403 if (fncd == TFN_UDP_ALL) { /* TFN_UDP_ALL の処理 */
404
405 snd_err = udp_can_snd(cep, E_RLWAI);
406 rcv_err = udp_can_rcv(cep, E_RLWAI);
407
408 /*
409 * snd_err と rcv_err のどちらも EV_NOPND
410 * なら、ペンディングしていないのでエラー
411 */
412 if (snd_err == EV_NOPND && rcv_err == EV_NOPND)
413 error = E_OBJ;
414 else {
415 if (snd_err == EV_NOPND)
416 snd_err = E_OK;
417 if (rcv_err == EV_NOPND)
418 rcv_err = E_OK;
419
420 if (snd_err != E_OK)
421 error = snd_err;
422 else if (rcv_err != E_OK)
423 error = rcv_err;
424 }
425 }
426 else if (fncd == TFN_UDP_SND_DAT) { /* 送信処理のキャンセル */
427 if ((error = udp_can_snd(cep, E_RLWAI)) == EV_NOPND)
428 error = E_OBJ;
429 }
430 else if (fncd == TFN_UDP_RCV_DAT) { /* 受信処理のキャンセル */
431 if ((error = udp_can_rcv(cep, E_RLWAI)) == EV_NOPND)
432 error = E_OBJ;
433 }
434 else
435 error = E_PAR;
436
437 /* 通信端点をロックを解除する。*/
438 syscall(sig_sem(cep->semid_lock));
439
440 return error;
441 }
442
443#endif /* of #ifdef __udp_can_cep */
444
445/*
446 * udp_set_opt -- UDP 通信端点オプションの設定【拡張機能】
447 *
448 * 注意: 設定可能な UDP 通信端点オプションは無いため、E_PAR が返される。
449 */
450
451#ifdef __udp_set_opt
452
453#ifdef UDP_CFG_EXTENTIONS
454
455ER
456udp_set_opt (ID cepid, int_t optname, void *optval, int_t optlen)
457{
458 T_UDP_CEP *cep;
459
460 /* UDP 通信端点 ID をチェックする。*/
461 if (!VALID_UDP_CEPID(cepid))
462 return E_ID;
463
464 /* UDP 通信端点を得る。*/
465 cep = GET_UDP_CEP(cepid);
466
467 /* UDP 通信端点をチェックする。*/
468 if (!VALID_UDP_CEP(cep))
469 return E_NOEXS;
470
471 return E_OK/*E_PAR*/;
472 }
473
474#endif /* of #ifdef UDP_CFG_EXTENTIONS */
475
476#endif /* of #ifdef __udp_set_opt */
477
478/*
479 * udp_get_opt -- UDP 通信端点オプションの設定【拡張機能】
480 *
481 * 注意: 設定可能な UDP 通信端点オプションは無いため、E_PAR が返される。
482 */
483
484#ifdef __udp_get_opt
485
486#ifdef UDP_CFG_EXTENTIONS
487
488ER
489udp_get_opt (ID cepid, int_t optname, void *optval, int_t optlen)
490{
491 T_UDP_CEP *cep;
492
493 /* UDP 通信端点 ID をチェックする。*/
494 if (!VALID_UDP_CEPID(cepid))
495 return E_ID;
496
497 /* UDP 通信端点を得る。*/
498 cep = GET_UDP_CEP(cepid);
499
500 /* UDP 通信端点をチェックする。*/
501 if (!VALID_UDP_CEP(cep))
502 return E_NOEXS;
503
504 return E_OK/*E_PAR*/;
505 }
506
507#endif /* of #ifdef UDP_CFG_EXTENTIONS */
508
509#endif /* of #ifdef __udp_get_opt */
510
511#ifdef UDP_CFG_NON_BLOCKING
512
513#include "udp_usrreq_nblk.c"
514
515#else /* of #ifdef UDP_CFG_NON_BLOCKING */
516
517#ifdef __udp_can_snd
518
519/*
520 * udp_can_snd -- ペンディングしている送信のキャンセル
521 */
522
523ER
524udp_can_snd (T_UDP_CEP *cep, ER error)
525{
526 if (cep->snd_tskid != TA_NULL) { /* 非ノンブロッキングコールでペンディング中 */
527
528#ifdef UDP_CFG_EXTENTIONS
529
530 /* 待ち中に発生したエラー情報を設定する。*/
531 cep->error = error;
532
533#endif /* of #ifdef UDP_CFG_EXTENTIONS */
534
535 error = rel_wai(cep->snd_tskid);
536 cep->snd_tskid = TA_NULL;
537 }
538 else /* どちらでもないならペンディングしていない */
539 error = EV_NOPND;
540
541 return error;
542 }
543
544#endif /* of #ifdef __udp_can_snd */
545
546#ifdef __udp_can_rcv
547
548/*
549 * udp_can_rcv -- ペンディングしている受信のキャンセル
550 */
551
552ER
553udp_can_rcv (T_UDP_CEP *cep, ER error)
554{
555 if (cep->rcv_tskid != TA_NULL) { /* 非ノンブロッキングコールでペンディング中 */
556
557#ifdef UDP_CFG_EXTENTIONS
558
559 /* 待ち中に発生したエラー情報を設定する。*/
560 cep->error = error;
561
562#endif /* of #ifdef UDP_CFG_EXTENTIONS */
563
564 error = rel_wai(cep->rcv_tskid);
565 cep->rcv_tskid = TA_NULL;
566 }
567 else /* どちらでもないならペンディングしていない */
568 error = EV_NOPND;
569
570 return error;
571 }
572
573#endif /* of #ifdef __udp_can_rcv */
574
575#ifdef __udp_snd_dat
576
577/*
578 * udp_snd_dat -- パケットの送信【標準機能】
579 */
580
581ER_UINT
582UDP_SND_DAT (ID cepid, T_IPEP *p_dstaddr, void *data, int_t len, TMO tmout)
583{
584 T_UDP_CEP *cep;
585 ER error;
586
587 /* p_dstaddr または data が NULL か、tmout が TMO_NBLK ならエラー */
588 if (p_dstaddr == NULL || data == NULL || tmout == TMO_NBLK)
589 return E_PAR;
590
591 /* データ長をチェックする。*/
592 if (len < 0 || len + IP_HDR_SIZE + UDP_HDR_SIZE > IF_MTU)
593 return E_PAR;
594
595 /* UDP 通信端点 ID をチェックする。*/
596 if (!VALID_UDP_CEPID(cepid))
597 return E_ID;
598
599 /* UDP 通信端点を得る。*/
600 cep = GET_UDP_CEP(cepid);
601
602 /* UDP 通信端点をチェックする。*/
603 if (!VALID_UDP_CEP(cep))
604 return E_NOEXS;
605
606 /*
607 * 自ポート番号が UDP_PORTANY なら、自動で割り当てる。
608 */
609 if (cep->myaddr.portno == UDP_PORTANY) {
610 if ((error = udp_alloc_auto_port(cep)) != E_OK)
611 return error;
612 }
613
614 /* 通信端点をロックする。*/
615 syscall(wai_sem(cep->semid_lock));
616
617 if (cep->snd_tskid != TA_NULL) {
618
619 /* 非ノンブロッキングコールでペンディング中 */
620 error = E_QOVR;
621
622 /* 通信端点をロックを解除する。*/
623 syscall(sig_sem(cep->semid_lock));
624 }
625 else {
626 /* 現在のタスク識別子を記録する。*/
627 get_tid(&(cep->snd_tskid));
628
629#ifdef UDP_CFG_EXTENTIONS
630
631 /* 待ち中に発生したエラー情報をリセットする。*/
632 cep->error = E_OK;
633
634#endif /* of #ifdef UDP_CFG_EXTENTIONS */
635
636 /* 通信端点をロックを解除する。*/
637 syscall(sig_sem(cep->semid_lock));
638
639 /* パケットを送信する。*/
640 error = udp_send_data(cep, p_dstaddr, data, len, tmout);
641
642#ifdef UDP_CFG_EXTENTIONS
643
644 /* 待ち中に発生したエラー情報を返す。*/
645 if (error == E_RLWAI)
646 error = cep->error;
647
648#endif /* of #ifdef UDP_CFG_EXTENTIONS */
649 }
650
651 return error;
652 }
653
654#endif /* of #ifdef __udp_snd_dat */
655
656#ifdef __udp_rcv_dat
657
658/*
659 * udp_rcv_dat -- パケットの受信【標準機能】
660 */
661
662ER_UINT
663UDP_RCV_DAT (ID cepid, T_IPEP *p_dstaddr, void *data, int_t len, TMO tmout)
664{
665 T_NET_BUF *input;
666 T_UDP_CEP *cep;
667 T_UDP_HDR *udph;
668 ER_UINT error;
669 uint_t ulen, uhoff;
670
671 /* p_dstaddr または data が NULL 、len < 0 か、tmout が TMO_NBLK ならエラー */
672 if (p_dstaddr == NULL || data == NULL || len < 0 || tmout == TMO_NBLK)
673 return E_PAR;
674
675 /* UDP 通信端点 ID をチェックする。*/
676 if (!VALID_UDP_CEPID(cepid))
677 return E_ID;
678
679 /* UDP 通信端点を得る。*/
680 cep = GET_UDP_CEP(cepid);
681
682 /* UDP 通信端点をチェックする。*/
683 if (!VALID_UDP_CEP(cep))
684 return E_NOEXS;
685
686 /* 通信端点をロックする。*/
687 syscall(wai_sem(cep->semid_lock));
688
689 if (cep->rcv_tskid != TA_NULL) {
690
691 /* 非ノンブロッキングコールでペンディング中 */
692 error = E_QOVR;
693
694 /* 通信端点をロックを解除する。*/
695 syscall(sig_sem(cep->semid_lock));
696 }
697 else {
698
699 /* 現在のタスク識別子を記録する。*/
700 get_tid(&(cep->rcv_tskid));
701
702#ifdef UDP_CFG_EXTENTIONS
703
704 /* 待ち中に発生したエラー情報をリセットする。*/
705 cep->error = E_OK;
706
707#endif /* of #ifdef UDP_CFG_EXTENTIONS */
708
709 /* 通信端点をロックを解除する。*/
710 syscall(sig_sem(cep->semid_lock));
711
712 /* 入力があるまで待つ。*/
713 if (cep->cb_netbuf != NULL) {
714
715 /*
716 * ここにくる場合は、コールバック関数の中から
717 * udp_rcv_dat を呼び出していることになり、
718 * すでに入力済みである。
719 */
720 input = cep->cb_netbuf;
721 cep->cb_netbuf = NULL;
722 }
723 else if ((error = trcv_dtq(cep->rcvqid, (intptr_t*)&input, tmout)) != E_OK) {
724
725#ifdef UDP_CFG_EXTENTIONS
726
727 /* 待ち中に発生したエラー情報を返す。*/
728 if (error == E_RLWAI)
729 error = cep->error;
730
731#endif /* of #ifdef UDP_CFG_EXTENTIONS */
732
733 cep->rcv_tskid = TA_NULL;
734 return error;
735 }
736
737 /* p_dstaddr を設定する。*/
738 uhoff = (uint_t)GET_UDP_HDR_OFFSET(input);
739 udph = GET_UDP_HDR(input, uhoff);
740 p_dstaddr->portno = ntohs(udph->sport);
741 IN_COPY_TO_HOST(&p_dstaddr->ipaddr, &GET_IP_HDR(input)->src);
742
743 /* データをバッファに移す。*/
744 ulen = ntohs(udph->ulen);
745 if (ulen - UDP_HDR_SIZE > len)
746 error = E_BOVR;
747 else {
748 len = (uint_t)(ulen - UDP_HDR_SIZE);
749 error = (ER_UINT)(ulen - UDP_HDR_SIZE);
750 }
751
752 memcpy(data, GET_UDP_SDU(input, uhoff), (size_t)len);
753
754 syscall(rel_net_buf(input));
755
756 cep->rcv_tskid = TA_NULL;
757 }
758
759 return error;
760 }
761
762#endif /* of #ifdef __udp_rcv_dat */
763
764#endif /* of #ifdef UDP_CFG_NON_BLOCKING */
765
766#endif /* of #ifdef SUPPORT_UDP */
Note: See TracBrowser for help on using the repository browser.