source: azure_iot_hub/trunk/asp3_dcre/tinet/netinet/if_ether.c@ 388

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

Azure IoT Hub Device C SDK を使ったサンプルの追加

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