source: EcnlProtoTool/trunk/asp3_dcre/tinet/netinet/if_ether.c@ 270

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

mruby版ECNLプロトタイピング・ツールを追加

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
  • Property svn:mime-type set to text/x-csrc
File size: 15.2 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 * 上記著作権者
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: if_ether.c 270 2017-02-09 04:03:47Z coas-nagasima $
44 */
45
46/*
47 * Copyright (c) 1982, 1986, 1988, 1993
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 * @(#)if_ether.c 8.1 (Berkeley) 6/10/93
79 * $FreeBSD: src/sys/netinet/if_ether.c,v 1.52.2.6 1999/10/18 11:59:31 sheldonh Exp $
80 */
81
82#include <string.h>
83
84#ifdef TARGET_KERNEL_ASP
85
86#include <kernel.h>
87#include <sil.h>
88#include <t_syslog.h>
89#include "kernel_cfg.h"
90
91#endif /* of #ifdef TARGET_KERNEL_ASP */
92
93#ifdef TARGET_KERNEL_JSP
94
95#include <s_services.h>
96#include <t_services.h>
97#include "kernel_id.h"
98
99#endif /* of #ifdef TARGET_KERNEL_JSP */
100
101#include <tinet_defs.h>
102#include <tinet_config.h>
103
104#include <net/if.h>
105#include <net/ethernet.h>
106#include <net/if_arp.h>
107#include <net/net.h>
108#include <net/net_buf.h>
109#include <net/net_var.h>
110#include <net/net_timer.h>
111#include <net/net_count.h>
112
113#include <netinet/in.h>
114#include <netinet/in_var.h>
115#include <netinet/ip.h>
116#include <netinet/if_ether.h>
117
118#include <net/if_var.h>
119
120#if defined(SUPPORT_INET4) && defined(SUPPORT_ETHER)
121
122/*
123 * ARP キャッシュエントリ
124 */
125
126static T_ARP_ENTRY arp_cache[NUM_ARP_ENTRY];
127
128/*
129 * 関数
130 */
131
132static T_ARP_ENTRY *arp_lookup (T_IN4_ADDR addr, bool_t create);
133static void in_arpinput (T_IF_ADDR *ifaddr, T_NET_BUF *input);
134static void arp_timer (void *ignore);
135
136/*
137 * arp_lookup -- ARP キャッシュの探索と登録
138 *
139 * 注意: SEM_ARP_CACHE_LOCK を獲得した状æ…
140‹ã§å‘¼å‡ºã™ã“と
141 */
142
143static T_ARP_ENTRY *
144arp_lookup (T_IN4_ADDR addr, bool_t create)
145{
146 int_t ix, six;
147 uint16_t min;
148
149 for (ix = NUM_ARP_ENTRY; ix -- > 0; ) {
150 if (arp_cache[ix].expire && arp_cache[ix].ip_addr == addr)
151 return &arp_cache[ix];
152 }
153
154 /* create が真なら、新たなエントリを登録する。*/
155 if (create) {
156
157 /* まず、空きがあれば、その空きを利用する。*/
158 for (ix = NUM_ARP_ENTRY; ix -- > 0; ) {
159 if (arp_cache[ix].expire == 0) {
160 arp_cache[ix].ip_addr = addr;
161 return &arp_cache[ix];
162 }
163 }
164
165 /*
166 * 空きがなければ、タイムアウトまで時間が最短の
167 * エントリーを破棄して利用する。
168 */
169 syslog(LOG_NOTICE, "[ARP] cache busy, size=%d", NUM_ARP_ENTRY);
170 min = 0xffff;
171 for (six = ix = NUM_ARP_ENTRY; ix -- > 0; )
172 if (arp_cache[ix].expire < min) {
173 six = ix;
174 min = arp_cache[ix].expire;
175 }
176 arp_cache[six].expire = 0;
177 arp_cache[six].ip_addr = addr;
178 return &arp_cache[six];
179 }
180 else
181 return NULL;
182 }
183
184/*
185 * in_arpinput -- TCP/IP 用 ARP のå…
186¥åŠ›é–¢æ•°
187 */
188
189static void
190in_arpinput (T_IF_ADDR *ifaddr, T_NET_BUF *input)
191{
192 T_NET_BUF *pending;
193 T_ETHER_HDR *eth;
194 T_ARP_HDR *arph;
195 T_ETHER_ARP_HDR *et_arph;
196 T_ARP_ENTRY *ent;
197 T_IFNET *ifp = IF_GET_IFNET();
198 T_IN4_ADDR saddr, taddr;
199
200 et_arph = GET_ETHER_ARP_HDR(input);
201
202 ntoahl(saddr, et_arph->sproto); /* 送信å…
203ƒ IP アドレス */
204 ntoahl(taddr, et_arph->tproto); /* 解決対象 IP アドレス */
205
206 /*
207 * 以下の場合はエラー
208 * ・送信ホストの物理アドレスが自分
209 * ・送信ホストの物理アドレスがブロードキャスト
210 */
211 if (memcmp(et_arph->shost, ifaddr->lladdr, ETHER_ADDR_LEN) == 0 ||
212 memcmp(et_arph->shost, ether_broad_cast_addr, ETHER_ADDR_LEN) == 0)
213 goto err_ret;
214
215 /*
216 * 送信ホストの IP アドレスが自分の場合は、重複しているので
217 * 相手にも知らせる。
218 */
219 if (saddr == ifp->in_ifaddr.addr) {
220
221#ifdef ARP_CFG_CALLBACK_DUPLICATED
222
223 if (arp_callback_duplicated(et_arph->shost)) {
224 syslog(LOG_ERROR, "[ARP] IP address duplicated: %s", mac2str(NULL, et_arph->shost));
225 taddr = saddr;
226 goto reply;
227 }
228 else
229 goto buf_rel;
230
231#else /* of #ifdef ARP_CFG_CALLBACK_DUPLICATED */
232
233 syslog(LOG_ERROR, "[ARP] IP address duplicated: %s", mac2str(NULL, et_arph->shost));
234 taddr = saddr;
235 goto reply;
236
237#endif /* of #ifdef ARP_CFG_CALLBACK_DUPLICATED */
238
239 }
240
241 /*
242 * 以下の場合は何もしない。
243 * ・解決対象 IP アドレスが自分ではない、注: å…
244ƒã® FreeBSD の
245 * 実装
246では、ARP PROXY 等のため、自分以外の IP アドレスの
247 * 解決も行っているが、本実装
248では、自分以外の IP
249 * アドレスの解決は行わない。
250 */
251 if (taddr != ifp->in_ifaddr.addr)
252 goto buf_rel;
253
254 /*
255 * 送信å…
256ƒ IP アドレスが ARP キャッシュにあるか調べる。
257 * キャッシュになければ、新たにエントリを登録する。
258 */
259 syscall(wai_sem(SEM_ARP_CACHE_LOCK));
260 ent = arp_lookup(saddr, true);
261
262 memcpy(ent->mac_addr, et_arph->shost, ETHER_ADDR_LEN);
263 ent->expire = ARP_CACHE_KEEP;
264
265 /*
266 * 送信がペンデングされているフレームがあれば送信する。
267 */
268 if (ent->hold) {
269
270 /* フレームの Ethernet ヘッダを設定する。*/
271 memcpy(GET_ETHER_HDR(ent->hold)->dhost, ent->mac_addr, ETHER_ADDR_LEN);
272
273 pending = ent->hold;
274 ent->hold = NULL;
275 syscall(sig_sem(SEM_ARP_CACHE_LOCK));
276
277 /* ペンディングされているフレームを送信する。*/
278 IF_RAW_OUTPUT(pending, TMO_FEVR);
279
280 }
281 else
282 syscall(sig_sem(SEM_ARP_CACHE_LOCK));
283
284reply:
285
286 arph = GET_ARP_HDR(input);
287
288 /* アドレス解決要求でなければ終了 */
289 if (ntohs(arph->opcode) != ARPOP_REQUEST)
290 goto buf_rel;
291
292 /* Ethernet ARP ヘッダを設定する。*/
293 memcpy(et_arph->thost, et_arph->shost, ETHER_ADDR_LEN);
294 memcpy(et_arph->shost, ifaddr->lladdr, ETHER_ADDR_LEN);
295 memcpy(et_arph->tproto, (uint8_t*)&et_arph->sproto, sizeof(T_IN_ADDR));
296 ahtonl(et_arph->sproto, taddr);
297
298 /* Ethernet ARP ヘッダを設定する。*/
299 arph->opcode = htons(ARPOP_REPLY);
300
301 /* Ethernet ヘッダを設定する。*/
302 eth = GET_ETHER_HDR(input);
303 memcpy(eth->dhost, eth->shost, ETHER_ADDR_LEN);
304 memcpy(eth->shost, ifaddr->lladdr, ETHER_ADDR_LEN);
305
306 /* ARP 応答を送信する。*/
307 IF_RAW_OUTPUT(input, TMO_FEVR);
308 return;
309
310err_ret:
311 NET_COUNT_ARP(net_count_arp.in_err_packets, 1);
312buf_rel:
313 syscall(rel_net_buf(input));
314 }
315
316/*
317 * arp_timer -- ARP キャッシュの更新
318 */
319
320static void
321arp_timer (void *ignore)
322{
323 int_t ix;
324
325 syscall(wai_sem(SEM_ARP_CACHE_LOCK));
326
327 for (ix = NUM_ARP_ENTRY; ix -- > 0; ) {
328 if (arp_cache[ix].expire) {
329 arp_cache[ix].expire -= ARP_TIMER_TMO;
330 if (arp_cache[ix].expire == 0) {
331 /* 送信がペンデングされているフレームがあれば捨てる。*/
332 if (arp_cache[ix].hold) {
333 NET_COUNT_IP4(net_count_ip4[NC_IP4_OUT_ERR_PACKETS], 1);
334 syscall(rel_net_buf(arp_cache[ix].hold));
335 }
336 memset(&arp_cache[ix], 0, sizeof(T_ARP_ENTRY));
337 }
338 }
339 }
340
341 syscall(sig_sem(SEM_ARP_CACHE_LOCK));
342 timeout(arp_timer, NULL, ARP_TIMER_TMO);
343 }
344
345/*
346 * arp_request -- MAC アドレス解決要求
347 */
348
349ER
350arp_request (T_IF_ADDR *ifaddr, T_IN4_ADDR dst)
351{
352 ER error;
353 T_IN4_ADDR src;
354 T_ETHER_HDR *eth;
355 T_ARP_HDR *arph;
356 T_ETHER_ARP_HDR *et_arph;
357 T_NET_BUF *arp_req;
358
359 NET_COUNT_ARP(net_count_arp.out_octets , IF_ARP_ETHER_HDR_SIZE - IF_HDR_SIZE);
360 NET_COUNT_ARP(net_count_arp.out_packets, 1);
361
362 if ((error = tget_net_buf(&arp_req, IF_ARP_ETHER_HDR_SIZE, TMO_ARP_GET_NET_BUF)) == E_OK) {
363
364 /* イーサネットヘッダを設定する。*/
365 eth = GET_ETHER_HDR(arp_req);
366 memcpy(eth->dhost, ether_broad_cast_addr, ETHER_ADDR_LEN);
367 memcpy(eth->shost, ifaddr->lladdr, ETHER_ADDR_LEN);
368 eth->type = htons(ETHER_TYPE_ARP);
369
370 /* ARP ヘッダを設定する。*/
371 arph = GET_ARP_HDR(arp_req);
372 arph->hrd_addr = htons(ARPHRD_ETHER);
373 arph->proto = htons(ETHER_TYPE_IP);
374 arph->hdr_len = sizeof(et_arph->shost);
375 arph->proto_len = sizeof(et_arph->sproto);
376 arph->opcode = htons(ARPOP_REQUEST);
377
378 /* イーサネット ARP ヘッダを設定する。*/
379 et_arph = GET_ETHER_ARP_HDR(arp_req);
380 src = IF_GET_IFNET()->in_ifaddr.addr;
381 memcpy(et_arph->shost, ifaddr->lladdr, ETHER_ADDR_LEN);
382 memset(et_arph->thost, 0, ETHER_ADDR_LEN);
383 ahtonl(et_arph->sproto, src);
384 ahtonl(et_arph->tproto, dst);
385
386 /* 送信する。*/
387 error = IF_RAW_OUTPUT(arp_req, TMO_ARP_OUTPUT);
388 }
389 if (error != E_OK)
390 NET_COUNT_ARP(net_count_arp.out_err_packets, 1);
391 return error;
392 }
393
394/*
395 * arp_get_cache -- ARP キャッシュを獲得する。
396 */
397
398const T_ARP_ENTRY *
399arp_get_cache (void)
400{
401 return arp_cache;
402 }
403
404/*
405 * arp_input -- ARP のå…
406¥åŠ›é–¢æ•°
407 */
408
409void
410arp_input (T_IF_ADDR *ifaddr, T_NET_BUF *input)
411{
412 T_ARP_HDR *arph;
413
414 NET_COUNT_ARP(net_count_arp.in_octets , input->len - IF_HDR_SIZE);
415 NET_COUNT_ARP(net_count_arp.in_packets, 1);
416
417 /* ARP ヘッダの長さをチェックする。*/
418 if (input->len < IF_ARP_HDR_SIZE)
419 goto buf_rel;
420
421 arph = GET_ARP_HDR(input);
422
423 /*
424 * 物理アドレスフォーマットが Ehternet 以外
425 * または、プロトコルが IP 以外はエラー。
426 */
427 if (ntohs(arph->hrd_addr) != ARPHRD_ETHER ||
428 ntohs(arph->proto) != ETHER_TYPE_IP)
429 goto buf_rel;
430
431 /* ARP ヘッダ + Ether ARP ヘッダの長さをチェックする。*/
432 if (input->len < IF_ARP_ETHER_HDR_SIZE)
433 goto buf_rel;
434
435 in_arpinput(ifaddr, input);
436 return;
437
438buf_rel:
439 NET_COUNT_ARP(net_count_arp.in_err_packets, 1);
440 syscall(rel_net_buf(input));
441 }
442
443/*
444 * arp_resolve -- MAC アドレス解決
445 *
446 * アドレス解決ができれば、戻り値は true を返し、できなければ
447 * 送信をペンディングして、戻り値は false を返す。
448 */
449
450bool_t
451arp_resolve (T_IF_ADDR *ifaddr, T_NET_BUF *output, T_IN4_ADDR gw)
452{
453 T_ARP_ENTRY *ent;
454 T_ETHER_HDR *eth;
455 T_IFNET *ifp = IF_GET_IFNET();
456
457 eth = GET_ETHER_HDR(output);
458
459 /*
460 * 次の場合は、イーサネットのブロードキャストアドレスを返す。
461 *
462 * ・å…
463¨ãƒ“ットが 1
464 * ・ホスト部のå…
465¨ãƒ“ットが 1 で、ネットワーク部がローカルアドレス
466 */
467 if (gw == IPV4_ADDR_BROADCAST ||
468 gw == ((ifp->in_ifaddr.addr & ifp->in_ifaddr.mask) | ~ifp->in_ifaddr.mask)) {
469 memcpy(eth->dhost, ether_broad_cast_addr, ETHER_ADDR_LEN);
470 return true;
471 }
472
473 /* 送信å…
474ˆ GW の IP アドレスが ARP キャッシュにあるか調べる。*/
475 syscall(wai_sem(SEM_ARP_CACHE_LOCK));
476 ent = arp_lookup(gw, true);
477 if (ent->expire) {
478 memcpy(eth->dhost, ent->mac_addr, ETHER_ADDR_LEN);
479 syscall(sig_sem(SEM_ARP_CACHE_LOCK));
480 return true;
481 }
482 else {
483 /* 送信がペンデングされているフレームがあれば捨てる。*/
484 if (ent->hold) {
485 NET_COUNT_IP4(net_count_ip4[NC_IP4_OUT_ERR_PACKETS], 1);
486 syscall(rel_net_buf(ent->hold));
487 }
488
489 /*
490 * 送信をペンディングする。
491 * IF でネットワークバッファを開放しないフラグが設定されているときは、
492 * 送信をペンディングしない。
493 */
494 if ((output->flags & NB_FLG_NOREL_IFOUT) == 0)
495 ent->hold = output;
496 else {
497 output->flags &= (uint8_t)~NB_FLG_NOREL_IFOUT;
498 ent->hold = NULL;
499 }
500 syscall(sig_sem(SEM_ARP_CACHE_LOCK));
501
502 /* アドレス解決要求を送信する。*/
503 arp_request(ifaddr, gw);
504 return false;
505 }
506 }
507
508/*
509 * arp_init -- ARP 初期化
510 */
511
512void
513arp_init (void)
514{
515 timeout(arp_timer, NULL, ARP_TIMER_TMO);
516 }
517
518#ifdef ETHER_CFG_MULTICAST
519/*
520 * ether_map_ipv4_multicast -- IPv4 マルチキャストアドレスからイーサネット・マルチキャストアドレスへの変換
521 */
522
523void
524ether_map_ipv4_multicast (T_ETHER_ADDR *eaddr, T_IN4_ADDR maddr)
525{
526 eaddr->lladdr[0] = UINT_C(0x01);
527 eaddr->lladdr[1] = UINT_C(0x00);
528 eaddr->lladdr[2] = UINT_C(0x5E);
529 eaddr->lladdr[3] = (maddr & 0x7F0000) >> 16;
530 eaddr->lladdr[4] = (maddr & 0xFF00) >> 8;
531 eaddr->lladdr[5] = maddr & 0xFF;
532 }
533#endif /* ETHER_CFG_MULTICAST */
534
535#endif /* of #if defined(SUPPORT_INET4) && defined(SUPPORT_ETHER) */
Note: See TracBrowser for help on using the repository browser.