source: asp3_tinet_ecnl_arm/trunk/asp3_dcre/tinet/netinet/in4_subr.c@ 364

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

TINETとSocket APIなどを更新

  • Property svn:eol-style set to native
  • Property svn:mime-type set to text/x-csrc;charset=UTF-8
File size: 14.5 KB
Line 
1/*
2 * TINET (TCP/IP Protocol Stack)
3 *
4 * Copyright (C) 2001-2017 by Dep. of Computer Science and Engineering
5 * Tomakomai National College of Technology, JAPAN
6 *
7 * 上記著作権者は,以下の (1)~(4) の条件か,Free Software Foundation
8 * によって公表されている GNU General Public License の Version 2 に記
9 * 述されている条件を満たす場合に限り,本ソフトウェア(本ソフトウェア
10 * を改変したものを含む.以下同じ)を使用・複製・改変・再配布(以下,
11 * 利用と呼ぶ)することを無償で許諾する.
12 * (1) 本ソフトウェアをソースコードの形で利用する場合には,上記の著作
13 * 権表示,この利用条件および下記の無保証規定が,そのままの形でソー
14 * スコード中に含まれていること.
15 * (2) 本ソフトウェアを,ライブラリ形式など,他のソフトウェア開発に使
16 * 用できる形で再配布する場合には,再配布に伴うドキュメント(利用
17 * 者マニュアルなど)に,上記の著作権表示,この利用条件および下記
18 * の無保証規定を掲載すること.
19 * (3) 本ソフトウェアを,機器に組み込むなど,他のソフトウェア開発に使
20 * 用できない形で再配布する場合には,次の条件を満たすこと.
21 * (a) 再配布に伴うドキュメント(利用者マニュアルなど)に,上記の著
22 * 作権表示,この利用条件および下記の無保証規定を掲載すること.
23 * (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
24 * 害からも,上記著作権者およびTOPPERSプロジェクトを免責すること.
25 *
26 * 本ソフトウェアは,無保証で提供されているものである.上記著作権者お
27 * よびTOPPERSプロジェクトは,本ソフトウェアに関して,その適用可能性も
28 * 含めて,いかなる保証も行わない.また,本ソフトウェアの利用により直
29 * 接的または間接的に生じたいかなる損害に関しても,その責任を負わない.
30 *
31 * @(#) $Id$
32 */
33
34/*
35 * Copyright (c) 1982, 1986, 1988, 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
67#include <string.h>
68
69#ifdef TARGET_KERNEL_ASP
70
71#include <kernel.h>
72#include <sil.h>
73#include "kernel_cfg.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_endian.h>
95#include <net/net_buf.h>
96#include <net/net_timer.h>
97
98#include <netinet/in.h>
99#include <netinet/in_var.h>
100#include <netinet/ip.h>
101#include <netinet/ip_var.h>
102
103#include <net/if_var.h>
104
105#ifdef SUPPORT_IGMP
106#include <netinet/udp_var.h>
107#include <netinet/ip_igmp.h>
108#endif /* of #ifdef SUPPORT_IGMP */
109
110#if defined(_IP4_CFG)
111
112#if NUM_IN4_REDIRECT_ROUTE_ENTRY > 0
113
114/*
115 * in_rtinit -- ルーティング表を初期化する。
116 */
117
118void
119in_rtinit (void)
120{
121 int_t ix;
122
123 for (ix = 0; ix < NUM_IN4_STATIC_ROUTE_ENTRY; ix ++)
124 routing4_tbl[ix].flags = IN_RTF_DEFINED;
125
126 for ( ; ix < NUM_IN4_ROUTE_ENTRY; ix ++)
127 routing4_tbl[ix].flags = 0;
128 }
129
130/*
131 * in_rtnewentry -- 新しいエントリを獲得する。
132 */
133
134T_IN4_RTENTRY *
135in_rtnewentry (uint8_t flags, uint32_t tmo)
136{
137 SYSTIM now;
138 T_IN4_RTENTRY *rt, *frt = NULL;
139 int_t ix;
140
141 /* 空きエントリを探す。*/
142 for (ix = NUM_IN4_STATIC_ROUTE_ENTRY; ix < NUM_IN4_ROUTE_ENTRY; ix ++) {
143 rt = &routing4_tbl[ix];
144 if ((routing4_tbl[ix].flags & IN_RTF_DEFINED) == 0) {
145 frt = rt;
146 break;
147 }
148 }
149
150 /* expire の単位は [s]。*/
151 syscall(get_tim(&now));
152 now /= SYSTIM_HZ;
153
154 if (frt == NULL) {
155 /* 空きがなければ、有効時間がもっとも短いエントリを空きにする。*/
156 T_IN4_RTENTRY *srt = NULL;
157 int_t diff, sdiff = INT_MAX;
158
159 syscall(wai_sem(SEM_IN4_ROUTING_TBL));
160 for (ix = NUM_IN4_STATIC_ROUTE_ENTRY; ix < NUM_IN4_ROUTE_ENTRY; ix ++) {
161 rt = &routing4_tbl[ix];
162 diff = (int_t)(rt->expire - now);
163 if (diff <= 0) { /* rt->expire <= now */
164 /* 既に、有効時間が過ぎている。*/
165 frt = rt;
166 break;
167 }
168 else if (diff < sdiff) {
169 srt = rt;
170 sdiff = diff;
171 }
172 }
173 if (frt == NULL)
174 frt = srt;
175 frt->flags = 0;
176 syscall(sig_sem(SEM_IN4_ROUTING_TBL));
177 }
178
179 frt->flags = (uint8_t)(flags | IN_RTF_DEFINED);
180 frt->expire = now + tmo / SYSTIM_HZ;
181 return frt;
182 }
183
184/*
185 * in_rttimer -- ルーティング表の管理タイマー
186 */
187
188void
189in_rttimer (void)
190{
191 SYSTIM now;
192 int_t ix;
193
194 /* expire の単位は [s]。*/
195 syscall(get_tim(&now));
196 now /= SYSTIM_HZ;
197
198 syscall(wai_sem(SEM_IN4_ROUTING_TBL));
199 for (ix = NUM_IN4_STATIC_ROUTE_ENTRY; ix < NUM_IN4_ROUTE_ENTRY; ix ++)
200 if ((routing4_tbl[ix].flags & IN_RTF_DEFINED) &&
201 (int_t)(routing4_tbl[ix].expire - now) <= 0)
202 routing4_tbl[ix].flags = 0;
203 syscall(sig_sem(SEM_IN4_ROUTING_TBL));
204 }
205
206#endif /* of #if NUM_IN4_REDIRECT_ROUTE_ENTRY > 0 */
207
208/*
209 * in4_get_maxnum_ifaddr -- インタフェースに設定可能な最大アドレス数を返す。
210 */
211
212uint_t
213in4_get_maxnum_ifaddr (void)
214{
215 return 1;
216 }
217
218/*
219 * in4_get_ifaddr -- インタフェースに設定されているアドレスを返す。
220 */
221
222const T_IN4_ADDR *
223in4_get_ifaddr (int_t index)
224{
225 T_IFNET *ifp = IF_GET_IFNET();
226
227 return &ifp->in4_ifaddr.addr;
228 }
229
230/*
231 * in4_set_header -- IPv4 ヘッダを設定する。
232 */
233
234ER
235in4_set_header (T_NET_BUF *nbuf, uint_t len,
236 T_IN4_ADDR *dstaddr, T_IN4_ADDR *srcaddr, uint8_t proto, uint8_t ttl)
237{
238 T_IP4_HDR *ip4h = GET_IP4_HDR(nbuf);
239 T_IFNET *ifp = IF_GET_IFNET();
240
241 /* IP ヘッダを設定する。*/
242 ip4h->vhl = IP4_MAKE_VHL(IPV4_VERSION, IP4_HDR_SIZE >> 2);
243 ip4h->len = htons(IP4_HDR_SIZE + len);
244 ip4h->proto = proto;
245 ip4h->ttl = ttl;
246 ip4h->type = 0;
247 ip4h->id = ip4h->flg_off = ip4h->sum = 0;
248
249 /* IP アドレスを設定する。*/
250 ip4h->dst = htonl(*dstaddr);
251
252 if (srcaddr == NULL || *srcaddr == IPV4_ADDRANY)
253 ip4h->src = htonl(ifp->in4_ifaddr.addr);
254 else
255 ip4h->src = htonl(*srcaddr);
256
257 return E_OK;
258 }
259
260/*
261 * in4_get_datagram -- IPv4 データグラムを獲得し、ヘッダを設定する。
262 */
263
264ER
265in4_get_datagram (T_NET_BUF **nbuf, uint_t len, uint_t maxlen,
266 T_IN4_ADDR *dstaddr, T_IN4_ADDR *srcaddr,
267 uint8_t proto, uint8_t ttl, ATR nbatr, TMO tmout)
268{
269 ER error;
270 uint_t align;
271
272 /* データ長を 4 オクテット境界に調整する。*/
273 align = (len + 3) >> 2 << 2;
274
275 /* ネットワークバッファを獲得する。*/
276 if ((error = tget_net_buf_ex(nbuf, (uint_t)(IF_IP4_HDR_SIZE + align),
277 (uint_t)(IF_IP4_HDR_SIZE + maxlen), nbatr, tmout)) != E_OK)
278 return error;
279
280 /*
281 * より大きなサイズのネットワークバッファを獲得する場合のみ長さを調整する。
282 * より小さなサイズのネットワークバッファの獲得は、送信ウィンドバッファの
283 * 省コピー機能で使用され、実際に送信するまで、データサイズは決定できない。
284 */
285 if ((nbatr & NBA_SEARCH_ASCENT) != 0)
286 (*nbuf)->len = (uint16_t)(IF_IP4_HDR_SIZE + len);
287
288 /* IP ヘッダを設定する。*/
289 if ((error = in4_set_header(*nbuf, len, dstaddr, srcaddr, proto, ttl)) != E_OK) {
290 syscall(rel_net_buf(*nbuf));
291 *nbuf = NULL;
292 return error;
293 }
294
295 /* 4 オクテット境界までパディングで埋める。*/
296 if (align > len)
297 memset((GET_IP4_SDU(*nbuf) + len), 0, (size_t)(align - len));
298
299 return E_OK;
300 }
301
302/*
303 * in4_cksum -- IPv4 のトランスポート層ヘッダのチェックサムを計算する。
304 *
305 * 注意: 戻り値はネットワークバイトオーダ
306 */
307
308uint16_t
309in4_cksum (T_NET_BUF *nbuf, uint8_t proto, uint_t off, uint_t len)
310{
311 uint32_t sum;
312 uint_t align;
313
314 /* 4 オクテット境界のデータ長 */
315 align = (len + 3) >> 2 << 2;
316
317 /* 4 オクテット境界までパディングで埋める。*/
318 if (align > len)
319 memset((uint8_t*)nbuf->buf + off + len, 0, (size_t)(align - len));
320
321 sum = in_cksum_sum(nbuf->buf + off, align)
322 + in_cksum_sum(&GET_IP4_HDR(nbuf)->src, sizeof(T_IN4_ADDR) * 2)
323 + len + proto;
324 sum = in_cksum_carry(sum);
325
326 return (uint16_t)(~htons((uint16_t)sum));
327 }
328
329/*
330 * in_cksum -- チェックサム計算関数、IPv4、ICMPv4 用
331 *
332 * 注意: data は 4 オクテット単位でパディングすること。
333 * data が 2 オクテット単位にアラインされていないと
334 * 例外が発生する可能性がある。
335 * len は 4 オクテット単位にアラインされていること。
336 *
337 * 戻り値はネットワークバイトオーダ
338 */
339
340uint16_t
341in_cksum (void *data, uint_t len /*オクテット単位*/)
342{
343 uint16_t sum;
344
345 sum = (uint16_t)in_cksum_carry(in_cksum_sum(data, len));
346 return (uint16_t)(~htons(sum));
347 }
348
349/*
350 * in4_is_dstaddr_accept -- 宛先アドレスとして正しいかチェックする。
351 *
352 * 注意: dstaddr は、
353 * TINET-1.2 からネットワークバイトオーダ、
354 * TINET-1.1 までは、ホストバイトオーダ
355 */
356
357bool_t
358in4_is_dstaddr_accept (T_IN4_ADDR *myaddr, T_IN4_ADDR *dstaddr)
359{
360 if (*myaddr == IPV4_ADDRANY)
361 return ntohl(*dstaddr) == IF_GET_IFNET()->in4_ifaddr.addr;
362 else
363 return ntohl(*dstaddr) == *myaddr;
364 }
365
366/*
367 * inn4_is_dstaddr_accept -- 宛先アドレスとして正しいかチェックする。
368 *
369 * 注意: dstaddr は、
370 * TINET-1.2 からネットワークバイトオーダ、
371 * TINET-1.1 までは、ホストバイトオーダ
372 */
373
374bool_t
375inn4_is_dstaddr_accept (T_IN4_ADDR *myaddr, T_NET_BUF *nbuf)
376{
377 T_IP4_HDR *iph;
378
379 iph = GET_IP4_HDR(nbuf);
380 if (*myaddr == IPV4_ADDRANY)
381 return ntohl(iph->dst) == IF_GET_IFNET()->in4_ifaddr.addr;
382 else
383 return ntohl(iph->dst) == *myaddr;
384 }
385
386/*
387 * in4_addrwithifp -- 宛先アドレスにふさわしい送信元アドレスを、
388 * ネットワークインタフェースから探索する。
389 * in6_addrwithifp をシミュレートするだけで、
390 * エラーを返すことはない。
391 */
392
393T_IN4_ADDR *
394in4_addrwithifp (T_IFNET *ifp, T_IN4_ADDR *src, T_IN4_ADDR *dst)
395{
396 *src = ifp->in4_ifaddr.addr;
397 return src;
398 }
399
400/*
401 * in4_add_ifaddr -- インタフェースに IPv4 アドレスを設定する。
402 */
403
404ER
405in4_add_ifaddr (T_IN4_ADDR addr, T_IN4_ADDR mask)
406{
407 T_IFNET *ifp = IF_GET_IFNET();
408
409 ifp->in4_ifaddr.addr = addr;
410 ifp->in4_ifaddr.mask = mask;
411 return E_OK;
412 }
413
414#if NUM_IN4_ROUTE_ENTRY > 0
415
416/*
417 * in4_add_route -- 経路表にエントリを設定する。
418 */
419
420ER
421in4_add_route (int_t index, T_IN4_ADDR target, T_IN4_ADDR mask, T_IN4_ADDR gateway)
422{
423
424 if (0 <= index && index < NUM_IN4_STATIC_ROUTE_ENTRY) {
425 routing4_tbl[index].target = target;
426 routing4_tbl[index].mask = mask;
427 routing4_tbl[index].gateway = gateway;
428 return E_OK;
429 }
430 else
431 return E_PAR;
432 }
433
434#endif /* of #if NUM_IN4_ROUTE_ENTRY > 0 */
435
436/*
437 * in4_rtalloc -- ルーティング表を探索する。
438 */
439
440T_IN4_ADDR
441in4_rtalloc (T_IN4_ADDR dst)
442{
443 int_t ix;
444#ifdef ETHER_CFG_MULTICAST
445 if(IN4_IS_ADDR_MULTICAST(dst))
446 return dst;
447#endif /* of #ifdef ETHER_CFG_MULTICAST */
448 for (ix = NUM_IN4_ROUTE_ENTRY; ix --; )
449 if ((routing4_tbl[ix].flags & IN_RTF_DEFINED) &&
450 (dst & routing4_tbl[ix].mask) == routing4_tbl[ix].target) {
451 if (routing4_tbl[ix].gateway == 0)
452 return dst;
453 else {
454 return routing4_tbl[ix].gateway;
455 }
456 }
457 return dst;
458 }
459
460#if NUM_IN4_REDIRECT_ROUTE_ENTRY > 0
461
462/*
463 * in4_rtredirect -- ルーティング表にエントリを登録する。
464 *
465 * 注意: 引数 tmo の単位は [ms]。
466 */
467
468void
469in4_rtredirect (T_IN4_ADDR gateway, T_IN4_ADDR target, uint8_t flags, uint32_t tmo)
470{
471 T_IN4_RTENTRY *frt;
472
473 frt = in_rtnewentry(flags, tmo);
474 frt->gateway = gateway;
475 frt->target = target;
476 frt->mask = 0xffffffff;
477 }
478
479#endif /* of #if NUM_IN4_REDIRECT_ROUTE_ENTRY > 0 */
480
481/*
482 * in4_timer -- IPv4 共通タイマー
483 *
484 * 1秒周期で起動される。
485 */
486
487static void
488in4_timer (void *ignore)
489{
490#if NUM_IN4_REDIRECT_ROUTE_ENTRY > 0
491
492 in_rttimer();
493
494#endif /* of #if NUM_IN4_REDIRECT_ROUTE_ENTRY > 0 */
495
496#ifdef IP4_CFG_FRAGMENT
497
498 ip_frag_timer();
499
500#endif /* of #ifdef IP4_CFG_FRAGMENT */
501
502 timeout(in4_timer, NULL, IN_TIMER_TMO);
503 }
504
505/*
506 * in4_init -- IPv4 共通機能を初期化する。
507 */
508
509void
510in4_init (void)
511{
512#if NUM_IN4_REDIRECT_ROUTE_ENTRY > 0
513
514 in_rtinit();
515
516#endif /* of #if NUM_IN4_REDIRECT_ROUTE_ENTRY > 0 */
517
518#ifdef SUPPORT_IGMP
519 igmp_init();
520#endif /* of #ifdef SUPPORT_IGMP */
521
522 timeout(in4_timer, NULL, IN_TIMER_TMO);
523 }
524
525#endif /* of #if defined(_IP4_CFG) */
Note: See TracBrowser for help on using the repository browser.