source: azure_iot_hub/trunk/asp3_dcre/tinet/netinet/ip_igmp.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: 9.6 KB
RevLine 
[388]1/*
2* TINET (TCP/IP Protocol Stack)
3*
4* Copyright (C) 2001-2012 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: ip_igmp.c 388 2019-05-22 11:25:18Z coas-nagasima $
44*/
45
46#include <string.h>
47
48#ifdef TARGET_KERNEL_ASP
49
50#include <kernel.h>
51#include <sil.h>
52#include <t_syslog.h>
53#include "kernel_cfg.h"
54#include "tinet_cfg.h"
55
56#endif /* of #ifdef TARGET_KERNEL_ASP */
57
58#ifdef TARGET_KERNEL_JSP
59
60#include <s_services.h>
61#include <t_services.h>
62#include "tinet_id.h"
63
64#endif /* of #ifdef TARGET_KERNEL_JSP */
65
66#include <tinet_defs.h>
67#include <tinet_config.h>
68
69#include <net/if.h>
70#include <net/if_loop.h>
71#include <net/if_ppp.h>
72#include <net/ethernet.h>
73#include <net/ppp_ipcp.h>
74#include <net/net.h>
75#include <net/net_endian.h>
76#include <net/net_buf.h>
77#include <net/net_timer.h>
78#include <net/net_count.h>
79
80#include <netinet/in.h>
81#include <netinet/in_var.h>
82#include <netinet/ip.h>
83#include <netinet/ip_var.h>
84#include <netinet/tcp.h>
85#include <netinet/tcp_var.h>
86#include <netinet/udp_var.h>
87#include <netinet/ip_igmp.h>
88
89#include <net/if_var.h>
90#include <net/net_var.h>
91
92#ifdef SUPPORT_IGMP
93
94static T_IGMP_ENTRY igmp_groups[NUM_IGMP_ENTRY];
95static T_IN4_ADDR igmp_send_addrs[NUM_IGMP_ENTRY];
96
97static bool_t igmp_send_report_v2(T_IN4_ADDR dst);
98static int16_t igmp_get_timer(T_IGMP_ENTRY *entry);
99
100ER igmp_set_loop(T_UDP_CEP *cep, uint8_t optval)
101{
102 switch (optval) {
103 case 0:
104 cep->igmp_loopback = false;
105 return E_OK;
106 case 1:
107 cep->igmp_loopback = true;
108 return E_OK;
109 }
110
111 return E_PAR;
112}
113
114ER igmp_get_loop(T_UDP_CEP *cep, uint8_t *optval)
115{
116 if (optval == NULL)
117 return E_PAR;
118
119 *optval = cep->igmp_loopback ? 1 : 0;
120
121 return E_OK;
122}
123
124ER igmp_set_ttl(T_UDP_CEP *cep, uint8_t optval)
125{
126 cep->igmp_ttl = optval;
127
128 return E_OK;
129}
130
131ER igmp_get_ttl(T_UDP_CEP *cep, uint8_t *optval)
132{
133 if (optval == NULL)
134 return E_PAR;
135
136 *optval = cep->igmp_ttl;
137
138 return E_OK;
139}
140
141ER igmp_set_if(T_UDP_CEP *cep, T_IN4_ADDR *optval)
142{
143 if (optval == NULL)
144 return E_PAR;
145
146 cep->igmp_mcaddr = *optval;
147
148 return E_OK;
149}
150
151ER igmp_get_if(T_UDP_CEP *cep, T_IN4_ADDR *optval)
152{
153 if (optval == NULL)
154 return E_PAR;
155
156 *optval = cep->igmp_mcaddr;
157
158 return E_OK;
159}
160
161ER igmp_add_membership(T_UDP_CEP *cep, T_IP_MREQ *optval)
162{
163 T_IGMP_ENTRY *entry = NULL;
164 int i;
165 T_IFNET *ifp = IF_GET_IFNET();
166 ER ret = E_NOMEM;
167
168 if ((optval->imr_interface != IPV4_ADDRANY)
169 && (optval->imr_interface != ifp->in4_ifaddr.addr))
170 return E_PAR;
171
172 syscall(wai_sem(SEM_IGMP_GROUP_LOCK));
173
174 for (i = 0; i < NUM_IGMP_ENTRY; i++) {
175 entry = &igmp_groups[i];
176 if (entry->timer == -1) {
177 entry->timer = 0;
178 entry->ip_addr = optval->imr_multiaddr;
179 ret = E_OK;
180 break;
181 }
182 }
183
184 syscall(sig_sem(SEM_IGMP_GROUP_LOCK));
185
186 return ret;
187}
188
189ER igmp_drop_membership(T_UDP_CEP *cep, T_IP_MREQ *optval)
190{
191 T_IGMP_ENTRY *entry = NULL;
192 int i;
193 ER ret = E_PAR;
194 T_IFNET *ifp = IF_GET_IFNET();
195
196 if ((optval->imr_interface != IPV4_ADDRANY)
197 && (optval->imr_interface != ifp->in4_ifaddr.addr))
198 return E_PAR;
199
200 syscall(wai_sem(SEM_IGMP_GROUP_LOCK));
201
202 for (i = 0; i < NUM_IGMP_ENTRY; i++) {
203 entry = &igmp_groups[i];
204 if ((entry->timer >= 0) && (entry->ip_addr == optval->imr_multiaddr)) {
205 entry->timer = -1;
206 entry->ip_addr = 0;
207 ret = E_OK;
208 break;
209 }
210 }
211
212 syscall(sig_sem(SEM_IGMP_GROUP_LOCK));
213
214 return ret;
215}
216
217ER igmp_set_ip_msfilter(T_UDP_CEP *cep, const T_IP_MSFILTER *optval)
218{
219 return E_PAR;
220}
221
222ER igmp_get_ip_msfilter(T_UDP_CEP *cep, T_IP_MSFILTER *optval)
223{
224 return E_PAR;
225}
226
227uint_t igmp_input(T_NET_BUF **inputp, uint_t *offp, uint_t *nextp)
228{
229 T_NET_BUF *input = *inputp;
230 T_IGMPV2_HDR *igmph;
231 uint_t len, align;
232 T_IP4_HDR *ip4h;
233 int i;
234 T_IGMP_ENTRY *entry;
235 bool_t ret;
236
237 NET_COUNT_IGMP(net_count_igmp.in_octets,
238 input->len - GET_IF_IP4_HDR_SIZE(input));
239 NET_COUNT_IGMP(net_count_igmp.in_packets, 1);
240
241 /* ICMP ヘッダの長さをチェックする。*/
242 if (input->len < IF_IP4_IGMP_HDR_SIZE) {
243 NET_COUNT_IGMP(net_count_igmp.in_err_packets, 1);
244 NET_COUNT_MIB(igmp_stats.igmpInErrors, 1);
245 goto buf_rel;
246 }
247
248 igmph = (T_IGMPV2_HDR *)(input->buf + *offp);
249
250 /* 4 オクテット境界のデータ長 */
251 len = input->len - *offp;
252 align = (len + 3) >> 2 << 2;
253
254 /* 4 オクテット境界までパディングで埋める。*/
255 if (align > len)
256 memset((uint8_t*)input->buf + input->len, 0, (size_t)(align - len));
257
258 /* チェックサムを計算する。*/
259 if (in_cksum(igmph, align) != 0) {
260 NET_COUNT_IGMP(net_count_igmp.in_err_packets, 1);
261 goto buf_rel;
262 }
263
264 /* メッセージの型により分岐する。*/
265 switch (igmph->type) {
266 case IGMP_MEMBERSHIP_QUERY:
267 ip4h = GET_IP4_HDR(input);
268 ret = false;
269
270 /* 参加中のグループアドレスからのクエリーの場合 */
271 syscall(wai_sem(SEM_IGMP_GROUP_LOCK));
272
273 for (i = 0; i < NUM_IGMP_ENTRY; i++) {
274 entry = &igmp_groups[i];
275 if ((entry->timer >= 0) && (entry->ip_addr == igmph->addr)) {
276 entry->resptime = igmph->time;
277 ret = true;
278 break;
279 }
280 }
281
282 syscall(sig_sem(SEM_IGMP_GROUP_LOCK));
283
284 if (ret) {
285 /* メンバーシップリポートを送信 */
286 igmp_send_report_v2(ip4h->src);
287 }
288 break;
289 }
290
291buf_rel:
292 syscall(rel_net_buf(input));
293 return IPPROTO_DONE;
294}
295
296static bool_t igmp_send_report_v2(T_IN4_ADDR dst)
297{
298 T_IGMPV2_HDR *igmph;
299 T_NET_BUF *output;
300 uint_t len = 0, align;
301
302 if (in4_get_datagram(&output, (uint_t)(IF_IP4_IGMP_HDR_SIZE + len), 0,
303 &dst, NULL, IPPROTO_IGMP, IP4_DEFTTL,
304 NBA_SEARCH_ASCENT, TMO_IGMP_OUTPUT) != E_OK)
305 return false;
306
307 /* IGMP ヘッダを設定する。*/
308 igmph = GET_IGMPV2_HDR(output, IF_IP4_IGMP_HDR_OFFSET);
309 igmph->type = IGMP_MEMBERSHIP_REPORT_V2;
310 igmph->time = 0;
311 igmph->addr = htonl(dst);
312
313 /* 4 オクテット境界のデータ長 */
314 align = (len + 3) >> 2 << 2;
315
316 /* 4 オクテット境界までパディングで埋める。*/
317 if (align > len)
318 memset((uint8_t*)GET_IGMP_SDU(output, IF_IP4_IGMP_HDR_OFFSET) + len,
319 0, (size_t)(align - len));
320
321 /* チェックサムを計算する。*/
322 igmph->sum = 0;
323 igmph->sum = in_cksum(igmph, (uint_t)(IGMP_HDR_SIZE + align));
324
325 /* 送信する。*/
326 NET_COUNT_IGMP(net_count_igmp.out_octets,
327 output->len - GET_IF_IP4_HDR_SIZE(output));
328 NET_COUNT_IGMP(net_count_igmp.out_packets, 1);
329 NET_COUNT_MIB(icmp_stats.icmpOutMsgs, 1);
330 NET_COUNT_MIB(icmp_stats.icmpOutDestUnreachs, 1);
331 ip_output(output, TMO_IGMP_OUTPUT);
332
333 return true;
334}
335
336/*
337* igmp_timer -- IGMP å…
338±é€šã‚¿ã‚¤ãƒžãƒ¼
339*/
340static void igmp_timer(void *ignore)
341{
342 T_IGMP_ENTRY *entry = NULL;
343 int i, j = 0;
344
345 /* memset(igmp_send_addrs, 0, sizeof(igmp_send_addrs)); */
346
347 syscall(wai_sem(SEM_IGMP_GROUP_LOCK));
348
349 for (i = 0; i < NUM_IGMP_ENTRY; i++) {
350 entry = &igmp_groups[i];
351 if (entry->timer > 0)
352 entry->timer--;
353 if (entry->timer == 0) {
354 entry->timer = igmp_get_timer(entry);
355 igmp_send_addrs[j++] = entry->ip_addr;
356 }
357 }
358
359 syscall(sig_sem(SEM_IGMP_GROUP_LOCK));
360
361 for (i = 0; i < j; i++) {
362 igmp_send_report_v2(igmp_send_addrs[i]);
363 }
364
365 timeout(igmp_timer, NULL, NET_TIMER_HZ / 1);
366}
367
368/*
369* igmp_init -- IGMP 機能を初期化する。
370*/
371
372void igmp_init(void)
373{
374 int i;
375
376 for (i = 0; i < NUM_IGMP_ENTRY; i++) {
377 igmp_groups[i].timer = -1;
378 }
379
380 timeout(igmp_timer, NULL, NET_TIMER_HZ / 1);
381}
382
383bool_t igmp_is_joined_group(T_IN4_ADDR addr)
384{
385 T_IGMP_ENTRY *entry = NULL;
386 int i;
387 bool_t ret = false;
388
389 syscall(wai_sem(SEM_IGMP_GROUP_LOCK));
390
391 for (i = 0; i < NUM_IGMP_ENTRY; i++) {
392 entry = &igmp_groups[i];
393 if ((entry->timer >= 0) && (entry->ip_addr == addr)) {
394 ret = true;
395 break;
396 }
397 }
398
399 syscall(sig_sem(SEM_IGMP_GROUP_LOCK));
400
401 return ret;
402}
403
404int16_t igmp_get_timer(T_IGMP_ENTRY *entry)
405{
406 int16_t time = entry->resptime;
407
408 if (time == 0)
409 time = 590;
410
411 return (int16_t)(net_rand() % time) + 10;
412}
413
414#endif /* of #ifdef SUPPORT_IGMP */
Note: See TracBrowser for help on using the repository browser.