source: EcnlProtoTool/trunk/asp3_dcre/tinet/netinet/udp_input.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: 12.0 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, 1990, 1993, 1995
36 * The Regents of the University of California. All rights reserved.
37 *
38 * Redistribution and use in source and binary forms, with or without
39 * modification, are permitted provided that the following conditions
40 * are met:
41 * 1. Redistributions of source code must retain the above copyright
42 * notice, this list of conditions and the following disclaimer.
43 * 2. Redistributions in binary form must reproduce the above copyright
44 * notice, this list of conditions and the following disclaimer in the
45 * documentation and/or other materials provided with the distribution.
46 * 3. All advertising materials mentioning features or use of this software
47 * must display the following acknowledgement:
48 * This product includes software developed by the University of
49 * California, Berkeley and its contributors.
50 * 4. Neither the name of the University nor the names of its contributors
51 * may be used to endorse or promote products derived from this software
52 * without specific prior written permission.
53 *
54 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
55 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
56 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
57 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
58 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
59 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
60 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
61 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
62 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
63 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
64 * SUCH DAMAGE.
65 */
66
67#include <string.h>
68
69#ifdef TARGET_KERNEL_ASP
70
71#include <kernel.h>
72#include <sil.h>
73#include <t_syslog.h>
74
75#endif /* of #ifdef TARGET_KERNEL_ASP */
76
77#ifdef TARGET_KERNEL_JSP
78
79#include <s_services.h>
80#include <t_services.h>
81#include "kernel_id.h"
82
83#endif /* of #ifdef TARGET_KERNEL_JSP */
84
85#include <tinet_defs.h>
86#include <tinet_config.h>
87
88#include <net/if.h>
89#include <net/if_loop.h>
90#include <net/if_ppp.h>
91#include <net/ethernet.h>
92#include <net/ppp_ipcp.h>
93#include <net/net.h>
94#include <net/net_buf.h>
95#include <net/net_count.h>
96
97#include <netinet/in.h>
98#include <netinet/in_var.h>
99#include <netinet6/in6.h>
100#include <netinet6/in6_var.h>
101#include <netinet/in_itron.h>
102#include <netinet/ip.h>
103#include <netinet/ip_var.h>
104#include <netinet/ip6.h>
105#include <netinet6/ip6_var.h>
106#include <netinet/ip_icmp.h>
107#include <netinet/icmp6.h>
108
109#include <netinet/udp.h>
110#include <netinet/udp_var.h>
111
112#include <net/if_var.h>
113
114#ifdef SUPPORT_UDP
115
116#ifdef SUPPORT_MIB
117
118/*
119 * SNMP の 管理情報ベース (MIB)
120 */
121
122T_UDP_STATS udp_stats;
123
124#endif /* of #ifdef SUPPORT_MIB */
125
126#if defined(SUPPORT_INET4)
127
128#ifdef DHCP_CFG
129
130/*
131 * udp_dstaddr_accept -- UDP のあて先アドレスが正しいかチェックする。
132 *
133 * DHCP_CFG が定義されているときは、以下のデータグラムを受信する。
134 *
135 * ・あて先アドレスがブロードキャスト
136 * ・ローカルアドレスが未定義
137 */
138
139static bool_t
140udp_is_dstaddr_accept (T_IN4_ADDR *myaddr, T_IN4_ADDR *dstaddr)
141{
142 T_IFNET *ifp = IF_GET_IFNET();
143
144 if (ifp->in_ifaddr.addr == IPV4_ADDRANY ||
145 ntohl(*dstaddr) == IPV4_ADDR_BROADCAST ||
146 ntohl(*dstaddr) == ((ifp->in_ifaddr.addr & ifp->in_ifaddr.mask) | ~ifp->in_ifaddr.mask))
147 return true;
148 else
149 return IN_IS_DSTADDR_ACCEPT(myaddr, dstaddr);
150 }
151
152#elif defined(ETHER_CFG_MULTICAST)
153
154/*
155 * udp_dstaddr_accept -- UDP のあて先アドレスが正しいかチェックする。
156 *
157 * 以下の場合もデータグラムを受信する。
158 *
159 * ・あて先アドレスがブロードキャスト
160 */
161
162static bool_t
163udp_is_dstaddr_accept (T_IN4_ADDR *myaddr, T_IN4_ADDR *dstaddr)
164{
165 T_IFNET *ifp = IF_GET_IFNET();
166 T_IN4_ADDR dst = ntohl(*dstaddr);
167
168 if (dst == IPV4_ADDR_BROADCAST ||
169 dst == ((ifp->in_ifaddr.addr & ifp->in_ifaddr.mask) | ~ifp->in_ifaddr.mask) ||
170 IN4_IS_ADDR_MULTICAST(dst))
171 return true;
172 else
173 return IN_IS_DSTADDR_ACCEPT(myaddr, dstaddr);
174 }
175
176#else /* of #ifdef DHCP_CFG */
177
178/*
179 * udp_dstaddr_accept -- UDP のあて先アドレスが正しいかチェックする。
180 *
181 * 以下の場合もデータグラムを受信する。
182 *
183 * ・あて先アドレスがブロードキャスト
184 */
185
186static bool_t
187udp_is_dstaddr_accept (T_IN4_ADDR *myaddr, T_IN4_ADDR *dstaddr)
188{
189 T_IFNET *ifp = IF_GET_IFNET();
190
191 if (ntohl(*dstaddr) == IPV4_ADDR_BROADCAST ||
192 ntohl(*dstaddr) == ((ifp->in_ifaddr.addr & ifp->in_ifaddr.mask) | ~ifp->in_ifaddr.mask))
193 return true;
194 else
195 return IN_IS_DSTADDR_ACCEPT(myaddr, dstaddr);
196 }
197
198#endif /* of #ifdef DHCP_CFG */
199
200#endif /* of #if defined(SUPPORT_INET4) */
201
202#if defined(SUPPORT_INET6)
203
204/*
205 * udp_dstaddr_accept -- UDP のあて先アドレスが正しいかチェックする。
206 *
207 * 以下の場合もデータグラムを受信する。
208 *
209 * ・あて先アドレスがマルチキャスト
210 */
211
212static bool_t
213udp_is_dstaddr_accept (T_IN6_ADDR *myaddr, T_IN6_ADDR *dstaddr)
214{
215 if (IN6_IS_ADDR_MULTICAST(dstaddr))
216 return true;
217 else
218 return IN_IS_DSTADDR_ACCEPT(myaddr, dstaddr);
219 }
220
221#endif /* of #if defined(SUPPORT_INET6) */
222
223/*
224 * udp_input -- UDP の入力関数
225 */
226
227uint_t
228udp_input (T_NET_BUF **inputp, uint_t *offp, uint_t *nextp)
229{
230 T_NET_BUF *input = *inputp;
231 T_UDP_CEP *cep;
232 T_UDP_HDR *udph;
233 T_IP_HDR *iph;
234 int_t ix;
235 uint_t len, hlen, ulen;
236
237 hlen = (uint_t)GET_IF_IP_HDR_SIZE(input);
238
239 NET_COUNT_UDP(net_count_udp.in_octets, input->len - hlen);
240 NET_COUNT_UDP(net_count_udp.in_packets, 1);
241 NET_COUNT_MIB(udp_stats.udpInDatagrams, 1);
242
243 /* ヘッダ長をチェックする。*/
244 if (input->len < hlen + UDP_HDR_SIZE)
245 goto buf_rel;
246
247 udph = (T_UDP_HDR *)(input->buf + *offp);
248
249 /* データグラム長をチェックする */
250 ulen = ntohs(udph->ulen);
251 if (ulen != input->len - hlen)
252 goto buf_rel;
253
254 /* 宛先ポートが 0 のデータグラムは破棄する。RFC768 */
255 if (udph->dport == 0)
256 goto buf_rel;
257
258#ifdef UDP_CFG_IN_CHECKSUM
259
260 /* チェックサムをチェックする */
261 if (udph->sum && IN_CKSUM(input, IPPROTO_UDP, *offp, ulen) != 0)
262 goto buf_rel;
263
264#endif /* of #ifdef UDP_CFG_IN_CHECKSUM */
265
266 iph = GET_IP_HDR(input);
267
268 /* 宛先アドレスとポートをチェックする */
269 for (ix = tmax_udp_ccepid; ix -- > 0; ) {
270 cep = &udp_cep[ix];
271 if (VALID_UDP_CEP(cep) &&
272 udp_is_dstaddr_accept(&cep->myaddr.ipaddr, &iph->dst) &&
273 ntohs(udph->dport) == cep->myaddr.portno) {
274 len = (uint_t)(ntohs(udph->ulen) - UDP_HDR_SIZE);
275
276 if (cep->rcv_tskid != TA_NULL) { /* 非ノンブロッキングコールでペンディング中 */
277 if (psnd_dtq(cep->rcvqid, (intptr_t)input) != E_OK)
278 goto buf_rel;
279 }
280
281#ifdef UDP_CFG_NON_BLOCKING
282
283 else if (cep->rcv_p_dstaddr != NULL) { /* ノンブロッキングコールでペンディング中 */
284
285 /* p_dstaddr を設定する。*/
286 cep->rcv_p_dstaddr->portno = ntohs(udph->sport);
287 IN_COPY_TO_HOST(&cep->rcv_p_dstaddr->ipaddr, &GET_IP_HDR(input)->src);
288
289 /* データをバッファに移す。*/
290 memcpy(cep->rcv_data, GET_UDP_SDU(input, *offp),
291 (size_t)(len < cep->rcv_len ? len : cep->rcv_len));
292 syscall(rel_net_buf(input));
293
294 if (IS_PTR_DEFINED(cep->callback))
295
296#ifdef TCP_CFG_NON_BLOCKING_COMPAT14
297
298 (*cep->callback)(GET_UDP_CEPID(cep), TFN_UDP_RCV_DAT, (void*)(uint32_t)len);
299
300#else /* of #ifdef TCP_CFG_NON_BLOCKING_COMPAT14 */
301
302 (*cep->callback)(GET_UDP_CEPID(cep), TFN_UDP_RCV_DAT, (void*)&len);
303
304#endif /* of #ifdef TCP_CFG_NON_BLOCKING_COMPAT14 */
305
306 else
307 syslog(LOG_WARNING, "[UDP] no call back, CEP: %d.", GET_UDP_CEPID(cep));
308 cep->rcv_p_dstaddr = NULL;
309 }
310
311#endif /* of #ifdef UDP_CFG_NON_BLOCKING */
312
313 else if (IS_PTR_DEFINED(cep->callback)) {
314
315 /* コールバック関数を呼び出す。*/
316 cep->cb_netbuf = input;
317
318#ifdef TCP_CFG_NON_BLOCKING_COMPAT14
319
320 (*cep->callback)(GET_UDP_CEPID(cep), TEV_UDP_RCV_DAT, (void*)(uint32_t)len);
321
322#else /* of #ifdef TCP_CFG_NON_BLOCKING_COMPAT14 */
323
324 (*cep->callback)(GET_UDP_CEPID(cep), TEV_UDP_RCV_DAT, (void*)&len);
325
326#endif /* of #ifdef TCP_CFG_NON_BLOCKING_COMPAT14 */
327
328 /*
329 * ネットワークバッファがそのままであれば、コールバック関数内で
330 * データを読み出さなかったことになるので、捨てる。
331 */
332 if (cep->cb_netbuf != NULL)
333 syscall(rel_net_buf(cep->cb_netbuf));
334 }
335 else
336 goto buf_rel;
337
338 return IPPROTO_DONE;
339 }
340 }
341
342 NET_COUNT_MIB(udp_stats.udpNoPorts, 1);
343
344#if defined(SUPPORT_INET4)
345
346 /* ローカル IP アドレスに届いたデータグラムのみ ICMP エラーを通知する。*/
347 if (ntohl(iph->dst) == IF_GET_IFNET()->in_ifaddr.addr) {
348 syslog(LOG_INFO, "[UDP] unexp port: %d.", ntohs(udph->dport));
349
350 icmp_error(ICMP4_UNREACH_PORT, input);
351 /* icmp_error では、ネットワークバッファ input を返却しないので下へ抜ける。*/
352 }
353
354#endif /* of #if defined(SUPPORT_INET4) */
355
356#if defined(SUPPORT_INET6)
357
358 /* マルチキャストアドレスに届いたデータグラムは ICMP エラーを通知しない。*/
359 if (!IN6_IS_ADDR_MULTICAST(&iph->dst)) {
360 syslog(LOG_INFO, "[UDP] unexp port: %d.", ntohs(udph->dport));
361
362 /* icmp6_error で、ネットワークバッファ input を返却する。*/
363 icmp6_error(input, ICMP6_DST_UNREACH, ICMP6_DST_UNREACH_NOPORT, 0);
364
365 NET_COUNT_UDP(net_count_udp.in_err_packets, 1);
366 NET_COUNT_MIB(udp_stats.udpInErrors, 1);
367 return IPPROTO_DONE;
368 }
369
370#endif /* of #if defined(SUPPORT_INET6) */
371
372buf_rel:
373 NET_COUNT_UDP(net_count_udp.in_err_packets, 1);
374 NET_COUNT_MIB(udp_stats.udpInErrors, 1);
375 syscall(rel_net_buf(input));
376 return IPPROTO_DONE;
377 }
378
379#endif /* of #ifdef SUPPORT_UDP */
Note: See TracBrowser for help on using the repository browser.