source: EcnlProtoTool/trunk/asp3_dcre/tinet/netinet/ip_igmp.c@ 331

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

prototoolに関連するプロジェクトをnewlibからmuslを使うよう変更・更新
ntshellをnewlibの下位の実装から、muslのsyscallの実装に変更・更新
以下のOSSをアップデート
・mruby-1.3.0
・musl-1.1.18
・onigmo-6.1.3
・tcc-0.9.27
以下のOSSを追加
・openssl-1.1.0e
・curl-7.57.0
・zlib-1.2.11
以下のmrbgemsを追加
・iij/mruby-digest
・iij/mruby-env
・iij/mruby-errno
・iij/mruby-iijson
・iij/mruby-ipaddr
・iij/mruby-mock
・iij/mruby-require
・iij/mruby-tls-openssl

  • Property svn:eol-style set to native
  • Property svn:mime-type set to text/x-csrc
File size: 8.9 KB
Line 
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* ã‹L’˜ìŒ ŽÒ‚́CˆÈ‰º‚Ì (1)`(4) ‚ÌðŒ‚©CFree Software Foundation
8* ‚É‚æ‚Á‚ÄŒö•\‚³‚ê‚Ä‚¢‚é GNU General Public License ‚Ì Version 2 ‚É‹L
9* q‚³‚ê‚Ä‚¢‚éðŒ‚ð–ž‚½‚·ê‡‚ÉŒÀ‚èC–{ƒ\ƒtƒgƒEƒFƒAi–{ƒ\ƒtƒgƒEƒFƒA
10* ‚ð‰ü•Ï‚µ‚½‚à‚Ì‚ðŠÜ‚ށDˆÈ‰º“¯‚¶j‚ðŽg—pE•¡»E‰ü•ÏEÄ”z•ziˆÈ‰ºC
11* —˜—p‚ƌĂԁj‚·‚邱‚Ƃ𖳏ž‚Å‹–‘ø‚·‚éD
12* (1) –{ƒ\ƒtƒgƒEƒFƒA‚ðƒ\[ƒXƒR[ƒh‚ÌŒ`‚Å—˜—p‚·‚éê‡‚ɂ́Cã‹L‚Ì’˜ì
13* Œ •\Ž¦C‚±‚Ì—˜—pðŒ‚¨‚æ‚щº‹L‚Ì–³•ÛØ‹K’肪C‚»‚Ì‚Ü‚Ü‚ÌŒ`‚Ń\[
14* ƒXƒR[ƒh’†‚ÉŠÜ‚Ü‚ê‚Ä‚¢‚邱‚ƁD
15* (2) –{ƒ\ƒtƒgƒEƒFƒA‚ðCƒ‰ƒCƒuƒ‰ƒŠŒ`Ž®‚ȂǁC‘¼‚̃\ƒtƒgƒEƒFƒAŠJ”­‚ÉŽg
16* —p‚Å‚«‚éŒ`‚ōĔz•z‚·‚éê‡‚ɂ́CÄ”z•z‚É”º‚¤ƒhƒLƒ…
17ƒƒ“ƒgi—˜—p
18* ŽÒƒ}ƒjƒ…
19ƒAƒ‹‚Ȃǁj‚ɁCã‹L‚Ì’˜ìŒ •\Ž¦C‚±‚Ì—˜—pðŒ‚¨‚æ‚щº‹L
20* ‚Ì–³•ÛØ‹K’è‚ðŒfÚ‚·‚邱‚ƁD
21* (3) –{ƒ\ƒtƒgƒEƒFƒA‚ðC‹@Ší‚É‘g‚ݍž‚ނȂǁC‘¼‚̃\ƒtƒgƒEƒFƒAŠJ”­‚ÉŽg
22* —p‚Å‚«‚È‚¢Œ`‚ōĔz•z‚·‚éê‡‚ɂ́CŽŸ‚ÌðŒ‚ð–ž‚½‚·‚±‚ƁD
23* (a) Ä”z•z‚É”º‚¤ƒhƒLƒ…
24ƒƒ“ƒgi—˜—pŽÒƒ}ƒjƒ…
25ƒAƒ‹‚Ȃǁj‚ɁCã‹L‚Ì’˜
26* ìŒ •\Ž¦C‚±‚Ì—˜—pðŒ‚¨‚æ‚щº‹L‚Ì–³•ÛØ‹K’è‚ðŒfÚ‚·‚邱‚ƁD
27* (4) –{ƒ\ƒtƒgƒEƒFƒA‚Ì—˜—p‚É‚æ‚è’¼Ú“I‚Ü‚½‚͊ԐړI‚ɐ¶‚¶‚é‚¢‚©‚Ȃ鑹
28* ŠQ‚©‚ç‚àCã‹L’˜ìŒ ŽÒ‚¨‚æ‚ÑTOPPERSƒvƒƒWƒFƒNƒg‚ð–Ɛӂ·‚邱‚ƁD
29*
30* –{ƒ\ƒtƒgƒEƒFƒA‚́C–³•ÛØ‚Å’ñ‹Ÿ‚³‚ê‚Ä‚¢‚é‚à‚Ì‚Å‚ ‚éDã‹L’˜ìŒ ŽÒ‚¨
31* ‚æ‚ÑTOPPERSƒvƒƒWƒFƒNƒg‚́C–{ƒ\ƒtƒgƒEƒFƒA‚ÉŠÖ‚µ‚āC‚»‚Ì“K—p‰Â”\«‚à
32* ŠÜ‚߂āC‚¢‚©‚È‚é•ÛØ‚às‚í‚È‚¢D‚Ü‚½C–{ƒ\ƒtƒgƒEƒFƒA‚Ì—˜—p‚É‚æ‚è’¼
33* Ú“I‚Ü‚½‚͊ԐړI‚ɐ¶‚¶‚½‚¢‚©‚Ȃ鑹ŠQ‚ÉŠÖ‚µ‚Ä‚àC‚»‚̐ӔC‚𕉂í‚È‚¢D
34*
35* @(#) $Id$
36*/
37
38#include <string.h>
39
40#ifdef TARGET_KERNEL_ASP
41
42#include <kernel.h>
43#include <sil.h>
44#include <t_syslog.h>
45#include "kernel_cfg.h"
46#include "tinet_cfg.h"
47
48#endif /* of #ifdef TARGET_KERNEL_ASP */
49
50#ifdef TARGET_KERNEL_JSP
51
52#include <s_services.h>
53#include <t_services.h>
54#include "tinet_id.h"
55
56#endif /* of #ifdef TARGET_KERNEL_JSP */
57
58#include <tinet_defs.h>
59#include <tinet_config.h>
60
61#include <net/if.h>
62#include <net/if_loop.h>
63#include <net/if_ppp.h>
64#include <net/ethernet.h>
65#include <net/ppp_ipcp.h>
66#include <net/net.h>
67#include <net/net_endian.h>
68#include <net/net_buf.h>
69#include <net/net_timer.h>
70#include <net/net_count.h>
71
72#include <netinet/in.h>
73#include <netinet/in_var.h>
74#include <netinet/ip.h>
75#include <netinet/ip_var.h>
76#include <netinet/tcp.h>
77#include <netinet/tcp_var.h>
78#include <netinet/udp_var.h>
79#include <netinet/ip_igmp.h>
80
81#include <net/if_var.h>
82#include <net/net_var.h>
83
84#ifdef SUPPORT_IGMP
85
86static T_IGMP_ENTRY igmp_groups[NUM_IGMP_ENTRY];
87static T_IN4_ADDR igmp_send_addrs[NUM_IGMP_ENTRY];
88
89static bool_t igmp_send_report_v2(T_IN4_ADDR dst);
90static uint16_t igmp_get_timer(T_IGMP_ENTRY *entry);
91
92ER igmp_set_loop(T_UDP_CEP *cep, uint8_t optval)
93{
94 switch (optval) {
95 case 0:
96 cep->igmp_loopback = false;
97 return E_OK;
98 case 1:
99 cep->igmp_loopback = true;
100 return E_OK;
101 }
102
103 return E_PAR;
104}
105
106ER igmp_get_loop(T_UDP_CEP *cep, uint8_t *optval)
107{
108 if (optval == NULL)
109 return E_PAR;
110
111 *optval = cep->igmp_loopback ? 1 : 0;
112
113 return E_OK;
114}
115
116ER igmp_set_ttl(T_UDP_CEP *cep, uint8_t optval)
117{
118 cep->igmp_ttl = optval;
119
120 return E_OK;
121}
122
123ER igmp_get_ttl(T_UDP_CEP *cep, uint8_t *optval)
124{
125 if (optval == NULL)
126 return E_PAR;
127
128 *optval = cep->igmp_ttl;
129
130 return E_OK;
131}
132
133ER igmp_set_if(T_UDP_CEP *cep, T_IN4_ADDR *optval)
134{
135 if (optval == NULL)
136 return E_PAR;
137
138 cep->igmp_mcaddr = *optval;
139
140 return E_OK;
141}
142
143ER igmp_get_if(T_UDP_CEP *cep, T_IN4_ADDR *optval)
144{
145 if (optval == NULL)
146 return E_PAR;
147
148 *optval = cep->igmp_mcaddr;
149
150 return E_OK;
151}
152
153ER igmp_add_membership(T_UDP_CEP *cep, T_IP_MREQ *optval)
154{
155 T_IGMP_ENTRY *entry = NULL;
156 int i;
157 uint16_t min;
158 T_IFNET *ifp = IF_GET_IFNET();
159 ER ret = E_NOMEM;
160
161 if ((optval->imr_interface != IPV4_ADDRANY)
162 && (optval->imr_interface != ifp->in4_ifaddr.addr))
163 return E_PAR;
164
165 syscall(wai_sem(SEM_IGMP_GROUP_LOCK));
166
167 for (i = 0; i < NUM_IGMP_ENTRY; i++) {
168 entry = &igmp_groups[i];
169 if (entry->timer == -1) {
170 entry->timer = igmp_get_timer(entry);
171 entry->ip_addr = optval->imr_multiaddr;
172 ret = E_OK;
173 break;
174 }
175 }
176
177 syscall(sig_sem(SEM_IGMP_GROUP_LOCK));
178
179 return ret;
180}
181
182ER igmp_drop_membership(T_UDP_CEP *cep, T_IP_MREQ *optval)
183{
184 T_IGMP_ENTRY *entry = NULL;
185 int i;
186 uint16_t min;
187 ER ret = E_PAR;
188 T_IFNET *ifp = IF_GET_IFNET();
189
190 if ((optval->imr_interface != IPV4_ADDRANY)
191 && (optval->imr_interface != ifp->in4_ifaddr.addr))
192 return E_PAR;
193
194 syscall(wai_sem(SEM_IGMP_GROUP_LOCK));
195
196 for (i = 0; i < NUM_IGMP_ENTRY; i++) {
197 entry = &igmp_groups[i];
198 if ((entry->timer >= 0) && (entry->ip_addr == optval->imr_multiaddr)) {
199 entry->timer = -1;
200 entry->ip_addr = 0;
201 ret = E_OK;
202 break;
203 }
204 }
205
206 syscall(sig_sem(SEM_IGMP_GROUP_LOCK));
207
208 return ret;
209}
210
211ER igmp_set_ip_msfilter(T_UDP_CEP *cep, const T_IP_MSFILTER *optval)
212{
213 return E_PAR;
214}
215
216ER igmp_get_ip_msfilter(T_UDP_CEP *cep, T_IP_MSFILTER *optval)
217{
218 return E_PAR;
219}
220
221uint_t igmp_input(T_NET_BUF **inputp, uint_t *offp, uint_t *nextp)
222{
223 T_NET_BUF *input = *inputp;
224 T_IGMPV2_HDR *igmph;
225 T_IN4_ADDR addr;
226 uint_t len, align;
227 T_IP4_HDR *ip4h;
228 int i;
229 T_IGMP_ENTRY *entry;
230 bool_t ret;
231
232 NET_COUNT_IGMP(net_count_igmp.in_octets,
233 input->len - GET_IF_IP4_HDR_SIZE(input));
234 NET_COUNT_IGMP(net_count_igmp.in_packets, 1);
235
236 /* ICMP ƒwƒbƒ_‚Ì’·‚³‚ðƒ`ƒFƒbƒN‚·‚éB*/
237 if (input->len < IF_IP4_IGMP_HDR_SIZE) {
238 NET_COUNT_IGMP(net_count_igmp.in_err_packets, 1);
239 NET_COUNT_MIB(igmp_stats.igmpInErrors, 1);
240 goto buf_rel;
241 }
242
243 igmph = (T_IGMPV2_HDR *)(input->buf + *offp);
244
245 /* 4 ƒIƒNƒeƒbƒg‹«ŠE‚̃f[ƒ^’· */
246 len = input->len - *offp;
247 align = (len + 3) >> 2 << 2;
248
249 /* 4 ƒIƒNƒeƒbƒg‹«ŠE‚܂ŃpƒfƒBƒ“ƒO‚Å–„‚ß‚éB*/
250 if (align > len)
251 memset((uint8_t*)input->buf + input->len, 0, (size_t)(align - len));
252
253 /* ƒ`ƒFƒbƒNƒTƒ€‚ðŒvŽZ‚·‚éB*/
254 if (in_cksum(igmph, align) != 0) {
255 NET_COUNT_IGMP(net_count_igmp.in_err_packets, 1);
256 goto buf_rel;
257 }
258
259 /* ƒƒbƒZ[ƒW‚ÌŒ^‚É‚æ‚蕪Šò‚·‚éB*/
260 switch (igmph->type) {
261 case IGMP_MEMBERSHIP_QUERY:
262 ip4h = GET_IP4_HDR(input);
263 ret = false;
264
265 /* ŽQ‰Á’†‚̃Oƒ‹[ƒvƒAƒhƒŒƒX‚©‚ç‚̃NƒGƒŠ[‚̏ꍇ */
266 syscall(wai_sem(SEM_IGMP_GROUP_LOCK));
267
268 for (i = 0; i < NUM_IGMP_ENTRY; i++) {
269 entry = &igmp_groups[i];
270 if ((entry->timer >= 0) && (entry->ip_addr == addr)) {
271 entry->resptime = igmph->time;
272 ret = true;
273 break;
274 }
275 }
276
277 syscall(sig_sem(SEM_IGMP_GROUP_LOCK));
278
279 if (ret) {
280 /* ƒƒ“ƒo[ƒVƒbƒvƒŠƒ|[ƒg‚𑗐M */
281 igmp_send_report_v2(ip4h->src);
282 }
283 break;
284 }
285
286buf_rel:
287 syscall(rel_net_buf(input));
288 return IPPROTO_DONE;
289}
290
291static bool_t igmp_send_report_v2(T_IN4_ADDR dst)
292{
293 T_IGMPV2_HDR *igmph;
294 T_NET_BUF *output;
295 uint_t len, align;
296
297 if (in4_get_datagram(&output, (uint_t)(IF_IP4_IGMP_HDR_SIZE + len), 0,
298 &dst, NULL, IPPROTO_IGMP, IP4_DEFTTL,
299 NBA_SEARCH_ASCENT, TMO_IGMP_OUTPUT) != E_OK)
300 return false;
301
302 /* IGMP ƒwƒbƒ_‚ðÝ’è‚·‚éB*/
303 igmph = GET_IGMPV2_HDR(output, IF_IP4_IGMP_HDR_OFFSET);
304 igmph->type = IGMP_MEMBERSHIP_REPORT_V2;
305 igmph->time = 0;
306 igmph->addr = dst;
307
308 /* 4 ƒIƒNƒeƒbƒg‹«ŠE‚̃f[ƒ^’· */
309 align = (len + 3) >> 2 << 2;
310
311 /* 4 ƒIƒNƒeƒbƒg‹«ŠE‚܂ŃpƒfƒBƒ“ƒO‚Å–„‚ß‚éB*/
312 if (align > len)
313 memset((uint8_t*)GET_IGMP_SDU(output, IF_IP4_IGMP_HDR_OFFSET) + IP4_HDR_SIZE + len,
314 0, (size_t)(align - len));
315
316 /* ƒ`ƒFƒbƒNƒTƒ€‚ðŒvŽZ‚·‚éB*/
317 igmph->sum = 0;
318 igmph->sum = in_cksum(igmph, (uint_t)(IF_IP4_IGMP_HDR_SIZE + align));
319
320 /* ‘—M‚·‚éB*/
321 NET_COUNT_IGMP(net_count_igmp.out_octets,
322 output->len - GET_IF_IP4_HDR_SIZE(output));
323 NET_COUNT_IGMP(net_count_igmp.out_packets, 1);
324 NET_COUNT_MIB(icmp_stats.icmpOutMsgs, 1);
325 NET_COUNT_MIB(icmp_stats.icmpOutDestUnreachs, 1);
326 ip_output(output, TMO_IGMP_OUTPUT);
327
328 return true;
329}
330
331/*
332* igmp_timer -- IGMP ‹¤’ʃ^ƒCƒ}[
333*/
334static void igmp_timer(void *ignore)
335{
336 T_IGMP_ENTRY *entry = NULL;
337 int i, j = 0;
338
339 /* memset(igmp_send_addrs, 0, sizeof(igmp_send_addrs)); */
340
341 syscall(wai_sem(SEM_IGMP_GROUP_LOCK));
342
343 for (i = 0; i < NUM_IGMP_ENTRY; i++) {
344 entry = &igmp_groups[i];
345 if (entry->timer > 0)
346 entry->timer--;
347 if (entry->timer == 0) {
348 entry->timer = igmp_get_timer(entry);
349 igmp_send_addrs[j++] = entry->ip_addr;
350 }
351 }
352
353 syscall(sig_sem(SEM_IGMP_GROUP_LOCK));
354
355 for (i = 0; i < j; i++) {
356 igmp_send_report_v2(igmp_send_addrs[i]);
357 }
358
359 timeout(igmp_timer, NULL, NET_TIMER_HZ / 1);
360}
361
362/*
363* igmp_init -- IGMP ‹@”\‚ð‰Šú‰»‚·‚éB
364*/
365
366void igmp_init(void)
367{
368 T_IGMP_ENTRY *entry = NULL;
369 int i;
370
371 for (i = 0; i < NUM_IGMP_ENTRY; i++) {
372 igmp_groups[i].timer = -1;
373 }
374
375 timeout(igmp_timer, NULL, NET_TIMER_HZ / 1);
376}
377
378bool_t igmp_is_joined_group(T_IN4_ADDR addr)
379{
380 T_IGMP_ENTRY *entry = NULL;
381 int i;
382 bool_t ret = false;
383
384 syscall(wai_sem(SEM_IGMP_GROUP_LOCK));
385
386 for (i = 0; i < NUM_IGMP_ENTRY; i++) {
387 entry = &igmp_groups[i];
388 if ((entry->timer >= 0) && (entry->ip_addr == addr)) {
389 ret = true;
390 break;
391 }
392 }
393
394 syscall(sig_sem(SEM_IGMP_GROUP_LOCK));
395
396 return ret;
397}
398
399uint16_t igmp_get_timer(T_IGMP_ENTRY *entry)
400{
401 uint16_t time = entry->resptime;
402
403 if (time == 0)
404 time = 10;
405
406 return net_rand() / (0x7fffffff / time);
407}
408
409#endif /* of #ifdef SUPPORT_IGMP */
Note: See TracBrowser for help on using the repository browser.