diff options
Diffstat (limited to 'src/transport/plugin_transport_udp_broadcasting.c')
-rw-r--r-- | src/transport/plugin_transport_udp_broadcasting.c | 324 |
1 files changed, 179 insertions, 145 deletions
diff --git a/src/transport/plugin_transport_udp_broadcasting.c b/src/transport/plugin_transport_udp_broadcasting.c index 8c42e374f..c53665f10 100644 --- a/src/transport/plugin_transport_udp_broadcasting.c +++ b/src/transport/plugin_transport_udp_broadcasting.c | |||
@@ -59,9 +59,18 @@ struct UDP_Beacon_Message | |||
59 | struct BroadcastAddress | 59 | struct BroadcastAddress |
60 | { | 60 | { |
61 | struct BroadcastAddress *next; | 61 | struct BroadcastAddress *next; |
62 | |||
62 | struct BroadcastAddress *prev; | 63 | struct BroadcastAddress *prev; |
63 | 64 | ||
65 | /** | ||
66 | * ID of select broadcast task | ||
67 | */ | ||
68 | GNUNET_SCHEDULER_TaskIdentifier broadcast_task; | ||
69 | |||
70 | struct Plugin *plugin; | ||
71 | |||
64 | void *addr; | 72 | void *addr; |
73 | |||
65 | socklen_t addrlen; | 74 | socklen_t addrlen; |
66 | }; | 75 | }; |
67 | 76 | ||
@@ -89,11 +98,10 @@ struct Mstv6Context | |||
89 | }; | 98 | }; |
90 | 99 | ||
91 | 100 | ||
92 | int | 101 | static int |
93 | broadcast_ipv6_mst_cb (void *cls, void *client, | 102 | broadcast_ipv6_mst_cb (void *cls, void *client, |
94 | const struct GNUNET_MessageHeader *message) | 103 | const struct GNUNET_MessageHeader *message) |
95 | { | 104 | { |
96 | |||
97 | struct Plugin *plugin = cls; | 105 | struct Plugin *plugin = cls; |
98 | struct Mstv6Context *mc = client; | 106 | struct Mstv6Context *mc = client; |
99 | const struct GNUNET_MessageHeader *hello; | 107 | const struct GNUNET_MessageHeader *hello; |
@@ -138,7 +146,7 @@ broadcast_ipv6_mst_cb (void *cls, void *client, | |||
138 | } | 146 | } |
139 | 147 | ||
140 | 148 | ||
141 | int | 149 | static int |
142 | broadcast_ipv4_mst_cb (void *cls, void *client, | 150 | broadcast_ipv4_mst_cb (void *cls, void *client, |
143 | const struct GNUNET_MessageHeader *message) | 151 | const struct GNUNET_MessageHeader *message) |
144 | { | 152 | { |
@@ -180,8 +188,7 @@ broadcast_ipv4_mst_cb (void *cls, void *client, | |||
180 | &atsi, 1); | 188 | &atsi, 1); |
181 | 189 | ||
182 | GNUNET_STATISTICS_update (plugin->env->stats, | 190 | GNUNET_STATISTICS_update (plugin->env->stats, |
183 | _ | 191 | _("# IPv4 broadcast HELLO beacons received via udp"), |
184 | ("# IPv4 broadcast HELLO beacons received via udp"), | ||
185 | 1, GNUNET_NO); | 192 | 1, GNUNET_NO); |
186 | GNUNET_free (mc); | 193 | GNUNET_free (mc); |
187 | return GNUNET_OK; | 194 | return GNUNET_OK; |
@@ -197,7 +204,7 @@ udp_broadcast_receive (struct Plugin *plugin, | |||
197 | { | 204 | { |
198 | struct GNUNET_ATS_Information ats; | 205 | struct GNUNET_ATS_Information ats; |
199 | 206 | ||
200 | if ((GNUNET_YES == plugin->broadcast_ipv4) && (addrlen == sizeof (struct sockaddr_in))) | 207 | if (addrlen == sizeof (struct sockaddr_in)) |
201 | { | 208 | { |
202 | LOG (GNUNET_ERROR_TYPE_DEBUG, | 209 | LOG (GNUNET_ERROR_TYPE_DEBUG, |
203 | "Received IPv4 HELLO beacon broadcast with %i bytes from address %s\n", | 210 | "Received IPv4 HELLO beacon broadcast with %i bytes from address %s\n", |
@@ -218,7 +225,7 @@ udp_broadcast_receive (struct Plugin *plugin, | |||
218 | GNUNET_NO, GNUNET_NO)) | 225 | GNUNET_NO, GNUNET_NO)) |
219 | GNUNET_free (mc); | 226 | GNUNET_free (mc); |
220 | } | 227 | } |
221 | else if ((GNUNET_YES == plugin->broadcast_ipv4) && (addrlen == sizeof (struct sockaddr_in6))) | 228 | if (addrlen == sizeof (struct sockaddr_in6)) |
222 | { | 229 | { |
223 | LOG (GNUNET_ERROR_TYPE_DEBUG, | 230 | LOG (GNUNET_ERROR_TYPE_DEBUG, |
224 | "Received IPv6 HELLO beacon broadcast with %i bytes from address %s\n", | 231 | "Received IPv6 HELLO beacon broadcast with %i bytes from address %s\n", |
@@ -270,24 +277,20 @@ static void | |||
270 | udp_ipv4_broadcast_send (void *cls, | 277 | udp_ipv4_broadcast_send (void *cls, |
271 | const struct GNUNET_SCHEDULER_TaskContext *tc) | 278 | const struct GNUNET_SCHEDULER_TaskContext *tc) |
272 | { | 279 | { |
273 | struct Plugin *plugin = cls; | 280 | struct BroadcastAddress *baddr = cls; |
281 | struct Plugin *plugin = baddr->plugin; | ||
274 | int sent; | 282 | int sent; |
275 | uint16_t msg_size; | 283 | uint16_t msg_size; |
276 | char buf[65536] GNUNET_ALIGN; | 284 | char buf[65536] GNUNET_ALIGN; |
277 | struct BroadcastAddress *baddr; | ||
278 | 285 | ||
279 | plugin->send_ipv4_broadcast_task = GNUNET_SCHEDULER_NO_TASK; | 286 | baddr->broadcast_task = GNUNET_SCHEDULER_NO_TASK; |
280 | 287 | ||
281 | msg_size = prepare_beacon(plugin, (struct UDP_Beacon_Message *) &buf); | 288 | msg_size = prepare_beacon(plugin, (struct UDP_Beacon_Message *) &buf); |
282 | 289 | if (0 != msg_size) | |
283 | baddr = plugin->ipv4_broadcast_head; | ||
284 | /* just IPv4 */ | ||
285 | while ((msg_size > 0) && (baddr != NULL) && (baddr->addrlen == sizeof (struct sockaddr_in))) | ||
286 | { | 290 | { |
287 | struct sockaddr_in *addr = (struct sockaddr_in *) baddr->addr; | 291 | struct sockaddr_in *addr = (struct sockaddr_in *) baddr->addr; |
288 | 292 | ||
289 | addr->sin_port = htons (plugin->port); | 293 | addr->sin_port = htons (plugin->port); |
290 | |||
291 | sent = GNUNET_NETWORK_socket_sendto (plugin->sockv4, &buf, msg_size, | 294 | sent = GNUNET_NETWORK_socket_sendto (plugin->sockv4, &buf, msg_size, |
292 | (const struct sockaddr *) addr, | 295 | (const struct sockaddr *) addr, |
293 | baddr->addrlen); | 296 | baddr->addrlen); |
@@ -311,12 +314,14 @@ udp_ipv4_broadcast_send (void *cls, | |||
311 | "Sent HELLO beacon broadcast with %i bytes to address %s\n", sent, | 314 | "Sent HELLO beacon broadcast with %i bytes to address %s\n", sent, |
312 | GNUNET_a2s (baddr->addr, baddr->addrlen)); | 315 | GNUNET_a2s (baddr->addr, baddr->addrlen)); |
313 | } | 316 | } |
314 | baddr = baddr->next; | ||
315 | } | 317 | } |
316 | 318 | // if (-1 != baddr->cryogenic_fd) { | |
317 | plugin->send_ipv4_broadcast_task = | 319 | // ioctl (baddr->cryogenic_fd, broadcast_interval +/- X) |
318 | GNUNET_SCHEDULER_add_delayed (plugin->broadcast_interval, | 320 | // GNUNET_SCHEDULER_add_write_file (baddr->cryogenic_fd, &udp_ipv4_broadcast_send, baddr); |
319 | &udp_ipv4_broadcast_send, plugin); | 321 | // } else |
322 | baddr->broadcast_task = | ||
323 | GNUNET_SCHEDULER_add_delayed (plugin->broadcast_interval, | ||
324 | &udp_ipv4_broadcast_send, baddr); | ||
320 | } | 325 | } |
321 | 326 | ||
322 | 327 | ||
@@ -324,18 +329,30 @@ static void | |||
324 | udp_ipv6_broadcast_send (void *cls, | 329 | udp_ipv6_broadcast_send (void *cls, |
325 | const struct GNUNET_SCHEDULER_TaskContext *tc) | 330 | const struct GNUNET_SCHEDULER_TaskContext *tc) |
326 | { | 331 | { |
327 | struct Plugin *plugin = cls; | 332 | struct BroadcastAddress *baddr = cls; |
328 | int sent; | 333 | struct Plugin *plugin = baddr->plugin; |
334 | ssize_t sent; | ||
329 | uint16_t msg_size; | 335 | uint16_t msg_size; |
330 | char buf[65536] GNUNET_ALIGN; | 336 | char buf[65536] GNUNET_ALIGN; |
337 | const struct sockaddr_in6 *s6 = (const struct sockaddr_in6 *) baddr->addr; | ||
331 | 338 | ||
332 | plugin->send_ipv6_broadcast_task = GNUNET_SCHEDULER_NO_TASK; | 339 | baddr->broadcast_task = GNUNET_SCHEDULER_NO_TASK; |
333 | 340 | ||
334 | msg_size = prepare_beacon(plugin, (struct UDP_Beacon_Message *) &buf); | 341 | msg_size = prepare_beacon(plugin, (struct UDP_Beacon_Message *) &buf); |
342 | /* Note: unclear if this actually works to limit the multicast to | ||
343 | the specified interface as we're not (necessarily) using a | ||
344 | link-local multicast group and the kernel suggests that the | ||
345 | scope ID is only respected for link-local addresses; however, | ||
346 | if the scope ID is ignored, the kernel should just multicast | ||
347 | on ALL interfaces, which is merely slightly less efficient; | ||
348 | in that case, we might want to revert to only doing this | ||
349 | once, and not per interface (hard to test...) */ | ||
350 | plugin->ipv6_multicast_address.sin6_scope_id = s6->sin6_scope_id; | ||
335 | sent = GNUNET_NETWORK_socket_sendto (plugin->sockv6, &buf, msg_size, | 351 | sent = GNUNET_NETWORK_socket_sendto (plugin->sockv6, &buf, msg_size, |
336 | (const struct sockaddr *) | 352 | (const struct sockaddr *) |
337 | &plugin->ipv6_multicast_address, | 353 | &plugin->ipv6_multicast_address, |
338 | sizeof (struct sockaddr_in6)); | 354 | sizeof (struct sockaddr_in6)); |
355 | plugin->ipv6_multicast_address.sin6_scope_id = 0; | ||
339 | if (sent == GNUNET_SYSERR) | 356 | if (sent == GNUNET_SYSERR) |
340 | { | 357 | { |
341 | if ((ENETUNREACH == errno) || (ENETDOWN == errno)) | 358 | if ((ENETUNREACH == errno) || (ENETDOWN == errno)) |
@@ -354,56 +371,128 @@ udp_ipv6_broadcast_send (void *cls, | |||
354 | else | 371 | else |
355 | { | 372 | { |
356 | LOG (GNUNET_ERROR_TYPE_DEBUG, | 373 | LOG (GNUNET_ERROR_TYPE_DEBUG, |
357 | "Sending IPv6 HELLO beacon broadcast with %i bytes to address %s\n", | 374 | "Sending IPv6 HELLO beacon broadcast with %d bytes to address %s\n", |
358 | sent, | 375 | (int) sent, |
359 | GNUNET_a2s ((const struct sockaddr *) &plugin->ipv6_multicast_address, | 376 | GNUNET_a2s ((const struct sockaddr *) &plugin->ipv6_multicast_address, |
360 | sizeof (struct sockaddr_in6))); | 377 | sizeof (struct sockaddr_in6))); |
361 | } | 378 | } |
362 | plugin->send_ipv6_broadcast_task = | 379 | // cryogenic... |
363 | GNUNET_SCHEDULER_add_delayed (plugin->broadcast_interval, | 380 | baddr->broadcast_task = |
364 | &udp_ipv6_broadcast_send, plugin); | 381 | GNUNET_SCHEDULER_add_delayed (plugin->broadcast_interval, |
382 | &udp_ipv6_broadcast_send, baddr); | ||
365 | } | 383 | } |
366 | 384 | ||
367 | 385 | ||
386 | /** | ||
387 | * Callback function invoked for each interface found. | ||
388 | * | ||
389 | * @param cls closure with the `struct Plugin` | ||
390 | * @param name name of the interface (can be NULL for unknown) | ||
391 | * @param isDefault is this presumably the default interface | ||
392 | * @param addr address of this interface (can be NULL for unknown or unassigned) | ||
393 | * @param broadcast_addr the broadcast address (can be NULL for unknown or unassigned) | ||
394 | * @param netmask the network mask (can be NULL for unknown or unassigned) | ||
395 | * @param addrlen length of the address | ||
396 | * @return #GNUNET_OK to continue iteration, #GNUNET_SYSERR to abort | ||
397 | */ | ||
368 | static int | 398 | static int |
369 | iface_proc (void *cls, const char *name, int isDefault, | 399 | iface_proc (void *cls, |
370 | const struct sockaddr *addr, const struct sockaddr *broadcast_addr, | 400 | const char *name, |
401 | int isDefault, | ||
402 | const struct sockaddr *addr, | ||
403 | const struct sockaddr *broadcast_addr, | ||
371 | const struct sockaddr *netmask, socklen_t addrlen) | 404 | const struct sockaddr *netmask, socklen_t addrlen) |
372 | { | 405 | { |
373 | struct Plugin *plugin = cls; | 406 | struct Plugin *plugin = cls; |
407 | struct BroadcastAddress *ba; | ||
374 | 408 | ||
375 | if (addr != NULL) | 409 | if (NULL == addr) |
410 | return GNUNET_OK; | ||
411 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
412 | "address %s for interface %s %p\n ", | ||
413 | GNUNET_a2s (addr, addrlen), name, addr); | ||
414 | if (NULL == broadcast_addr) | ||
415 | return GNUNET_OK; | ||
416 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
417 | "broadcast address %s for interface %s %p\n ", | ||
418 | GNUNET_a2s (broadcast_addr, addrlen), name, broadcast_addr); | ||
419 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "netmask %s for interface %s %p\n ", | ||
420 | GNUNET_a2s (netmask, addrlen), name, netmask); | ||
421 | |||
422 | ba = GNUNET_new (struct BroadcastAddress); | ||
423 | ba->plugin = plugin; | ||
424 | ba->addr = GNUNET_malloc (addrlen); | ||
425 | memcpy (ba->addr, broadcast_addr, addrlen); | ||
426 | ba->addrlen = addrlen; | ||
427 | if ( (GNUNET_YES == plugin->enable_ipv4) && | ||
428 | (NULL != plugin->sockv4) && | ||
429 | (addrlen == sizeof (struct sockaddr_in)) ) | ||
430 | { | ||
431 | char *filename; | ||
432 | |||
433 | GNUNET_asprintf (&filename, | ||
434 | "/dev/power/net-%s", | ||
435 | name); | ||
436 | // ba->cryogenic_fd = GNUNET_DISK_file_open (filename, ...); | ||
437 | GNUNET_free (filename); | ||
438 | ba->broadcast_task = | ||
439 | GNUNET_SCHEDULER_add_now (&udp_ipv4_broadcast_send, ba); | ||
440 | } | ||
441 | if ((GNUNET_YES == plugin->enable_ipv6) && | ||
442 | (NULL != plugin->sockv6) && | ||
443 | (addrlen == sizeof (struct sockaddr_in6))) | ||
376 | { | 444 | { |
377 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "address %s for interface %s %p\n ", | 445 | /* Create IPv6 multicast request */ |
378 | GNUNET_a2s (addr, addrlen), name, addr); | 446 | struct ipv6_mreq multicastRequest; |
379 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | 447 | const struct sockaddr_in6 *s6 = (const struct sockaddr_in6 *) broadcast_addr; |
380 | "broadcast address %s for interface %s %p\n ", | 448 | |
381 | GNUNET_a2s (broadcast_addr, addrlen), name, broadcast_addr); | 449 | multicastRequest.ipv6mr_multiaddr = |
382 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "netmask %s for interface %s %p\n ", | 450 | plugin->ipv6_multicast_address.sin6_addr; |
383 | GNUNET_a2s (netmask, addrlen), name, netmask); | 451 | /* http://tools.ietf.org/html/rfc2553#section-5.2: |
384 | 452 | * | |
385 | /* Collecting broadcast addresses */ | 453 | * IPV6_JOIN_GROUP |
386 | if (broadcast_addr != NULL) | 454 | * |
455 | * Join a multicast group on a specified local interface. If the | ||
456 | * interface index is specified as 0, the kernel chooses the local | ||
457 | * interface. For example, some kernels look up the multicast | ||
458 | * group in the normal IPv6 routing table and using the resulting | ||
459 | * interface; we do this for each interface, so no need to use | ||
460 | * zero (anymore...). | ||
461 | */ | ||
462 | multicastRequest.ipv6mr_interface = s6->sin6_scope_id; | ||
463 | |||
464 | /* Join the multicast group */ | ||
465 | if (GNUNET_OK != | ||
466 | GNUNET_NETWORK_socket_setsockopt | ||
467 | (plugin->sockv6, IPPROTO_IPV6, IPV6_JOIN_GROUP, | ||
468 | &multicastRequest, sizeof (multicastRequest))) | ||
387 | { | 469 | { |
388 | struct BroadcastAddress *ba = | 470 | LOG (GNUNET_ERROR_TYPE_WARNING, |
389 | GNUNET_malloc (sizeof (struct BroadcastAddress)); | 471 | "Failed to join IPv6 multicast group: IPv6 broadcasting not running\n"); |
390 | ba->addr = GNUNET_malloc (addrlen); | 472 | } |
391 | memcpy (ba->addr, broadcast_addr, addrlen); | 473 | else |
392 | ba->addrlen = addrlen; | 474 | { |
393 | GNUNET_CONTAINER_DLL_insert (plugin->ipv4_broadcast_head, | 475 | LOG (GNUNET_ERROR_TYPE_DEBUG, |
394 | plugin->ipv4_broadcast_tail, ba); | 476 | "IPv6 multicasting running\n"); |
477 | // setup cryogenic FD... | ||
478 | ba->broadcast_task = | ||
479 | GNUNET_SCHEDULER_add_now (&udp_ipv6_broadcast_send, ba); | ||
395 | } | 480 | } |
396 | } | 481 | } |
482 | GNUNET_CONTAINER_DLL_insert (plugin->broadcast_head, | ||
483 | plugin->broadcast_tail, ba); | ||
397 | return GNUNET_OK; | 484 | return GNUNET_OK; |
398 | } | 485 | } |
399 | 486 | ||
400 | 487 | ||
401 | void | 488 | void |
402 | setup_broadcast (struct Plugin *plugin, struct sockaddr_in6 *server_addrv6, struct sockaddr_in *server_addrv4) | 489 | setup_broadcast (struct Plugin *plugin, |
490 | struct sockaddr_in6 *server_addrv6, | ||
491 | struct sockaddr_in *server_addrv4) | ||
403 | { | 492 | { |
404 | const struct GNUNET_MessageHeader *hello; | 493 | const struct GNUNET_MessageHeader *hello; |
405 | hello = plugin->env->get_our_hello (); | ||
406 | 494 | ||
495 | hello = plugin->env->get_our_hello (); | ||
407 | if (GNUNET_YES == GNUNET_HELLO_is_friend_only((const struct GNUNET_HELLO_Message *) hello)) | 496 | if (GNUNET_YES == GNUNET_HELLO_is_friend_only((const struct GNUNET_HELLO_Message *) hello)) |
408 | { | 497 | { |
409 | LOG (GNUNET_ERROR_TYPE_WARNING, | 498 | LOG (GNUNET_ERROR_TYPE_WARNING, |
@@ -411,143 +500,88 @@ setup_broadcast (struct Plugin *plugin, struct sockaddr_in6 *server_addrv6, stru | |||
411 | return; | 500 | return; |
412 | } | 501 | } |
413 | 502 | ||
414 | |||
415 | /* create IPv4 broadcast socket */ | 503 | /* create IPv4 broadcast socket */ |
416 | plugin->broadcast_ipv4 = GNUNET_NO; | 504 | if ((GNUNET_YES == plugin->enable_ipv4) && (NULL != plugin->sockv4)) |
417 | if ((GNUNET_YES == plugin->enable_ipv4) && (plugin->sockv4 != NULL)) | ||
418 | { | 505 | { |
419 | int yes = 1; | 506 | static int yes = 1; |
420 | 507 | ||
421 | if (GNUNET_NETWORK_socket_setsockopt | 508 | if (GNUNET_NETWORK_socket_setsockopt |
422 | (plugin->sockv4, SOL_SOCKET, SO_BROADCAST, &yes, | 509 | (plugin->sockv4, SOL_SOCKET, SO_BROADCAST, &yes, |
423 | sizeof (int)) != GNUNET_OK) | 510 | sizeof (int)) != GNUNET_OK) |
424 | { | 511 | { |
425 | LOG (GNUNET_ERROR_TYPE_WARNING, | 512 | LOG (GNUNET_ERROR_TYPE_WARNING, |
426 | _ | 513 | _("Failed to set IPv4 broadcast option for broadcast socket on port %d\n"), |
427 | ("Failed to set IPv4 broadcast option for broadcast socket on port %d\n"), | ||
428 | ntohs (server_addrv4->sin_port)); | 514 | ntohs (server_addrv4->sin_port)); |
429 | } | 515 | } |
430 | else | 516 | else |
431 | { | 517 | { |
432 | GNUNET_OS_network_interfaces_list (&iface_proc, plugin); | ||
433 | plugin->send_ipv4_broadcast_task = | ||
434 | GNUNET_SCHEDULER_add_now (&udp_ipv4_broadcast_send, plugin); | ||
435 | |||
436 | plugin->broadcast_ipv4_mst = | 518 | plugin->broadcast_ipv4_mst = |
437 | GNUNET_SERVER_mst_create (broadcast_ipv4_mst_cb, plugin); | 519 | GNUNET_SERVER_mst_create (broadcast_ipv4_mst_cb, plugin); |
438 | |||
439 | LOG (GNUNET_ERROR_TYPE_DEBUG, "IPv4 Broadcasting running\n"); | 520 | LOG (GNUNET_ERROR_TYPE_DEBUG, "IPv4 Broadcasting running\n"); |
440 | plugin->broadcast_ipv4 = GNUNET_YES; | ||
441 | } | 521 | } |
442 | } | 522 | } |
443 | |||
444 | plugin->broadcast_ipv6 = GNUNET_NO; | ||
445 | if ((GNUNET_YES == plugin->enable_ipv6) && (plugin->sockv6 != NULL)) | 523 | if ((GNUNET_YES == plugin->enable_ipv6) && (plugin->sockv6 != NULL)) |
446 | { | 524 | { |
447 | memset (&plugin->ipv6_multicast_address, 0, sizeof (struct sockaddr_in6)); | 525 | memset (&plugin->ipv6_multicast_address, 0, sizeof (struct sockaddr_in6)); |
448 | GNUNET_assert (1 == | 526 | GNUNET_assert (1 == |
449 | inet_pton (AF_INET6, "FF05::13B", | 527 | inet_pton (AF_INET6, "FF05::13B", |
450 | &plugin->ipv6_multicast_address.sin6_addr)); | 528 | &plugin->ipv6_multicast_address.sin6_addr)); |
451 | |||
452 | plugin->ipv6_multicast_address.sin6_family = AF_INET6; | 529 | plugin->ipv6_multicast_address.sin6_family = AF_INET6; |
453 | plugin->ipv6_multicast_address.sin6_port = htons (plugin->port); | 530 | plugin->ipv6_multicast_address.sin6_port = htons (plugin->port); |
454 | |||
455 | plugin->broadcast_ipv6_mst = | 531 | plugin->broadcast_ipv6_mst = |
456 | GNUNET_SERVER_mst_create (broadcast_ipv6_mst_cb, plugin); | 532 | GNUNET_SERVER_mst_create (broadcast_ipv6_mst_cb, plugin); |
457 | |||
458 | /* Create IPv6 multicast request */ | ||
459 | struct ipv6_mreq multicastRequest; | ||
460 | |||
461 | multicastRequest.ipv6mr_multiaddr = | ||
462 | plugin->ipv6_multicast_address.sin6_addr; | ||
463 | /* TODO: 0 selects the "best" interface, tweak to use all interfaces | ||
464 | * | ||
465 | * http://tools.ietf.org/html/rfc2553#section-5.2: | ||
466 | * | ||
467 | * IPV6_JOIN_GROUP | ||
468 | * | ||
469 | * Join a multicast group on a specified local interface. If the | ||
470 | * interface index is specified as 0, the kernel chooses the local | ||
471 | * interface. For example, some kernels look up the multicast | ||
472 | * group in the normal IPv6 routing table and using the resulting | ||
473 | * interface. | ||
474 | * */ | ||
475 | multicastRequest.ipv6mr_interface = 0; | ||
476 | |||
477 | /* Join the multicast group */ | ||
478 | if (GNUNET_NETWORK_socket_setsockopt | ||
479 | (plugin->sockv6, IPPROTO_IPV6, IPV6_JOIN_GROUP, | ||
480 | (char *) &multicastRequest, sizeof (multicastRequest)) != GNUNET_OK) | ||
481 | { | ||
482 | LOG (GNUNET_ERROR_TYPE_WARNING, | ||
483 | "Failed to join IPv6 multicast group: IPv6 broadcasting not running\n"); | ||
484 | } | ||
485 | else | ||
486 | { | ||
487 | LOG (GNUNET_ERROR_TYPE_DEBUG, "IPv6 broadcasting running\n"); | ||
488 | plugin->send_ipv6_broadcast_task = | ||
489 | GNUNET_SCHEDULER_add_now (&udp_ipv6_broadcast_send, plugin); | ||
490 | plugin->broadcast_ipv6 = GNUNET_YES; | ||
491 | } | ||
492 | } | 533 | } |
534 | GNUNET_OS_network_interfaces_list (&iface_proc, plugin); | ||
493 | } | 535 | } |
494 | 536 | ||
495 | 537 | ||
496 | void | 538 | void |
497 | stop_broadcast (struct Plugin *plugin) | 539 | stop_broadcast (struct Plugin *plugin) |
498 | { | 540 | { |
499 | if (plugin->broadcast_ipv4) | 541 | while (plugin->broadcast_head != NULL) |
500 | { | 542 | { |
501 | if (plugin->send_ipv4_broadcast_task != GNUNET_SCHEDULER_NO_TASK) | 543 | struct BroadcastAddress *p = plugin->broadcast_head; |
502 | { | ||
503 | GNUNET_SCHEDULER_cancel (plugin->send_ipv4_broadcast_task); | ||
504 | plugin->send_ipv4_broadcast_task = GNUNET_SCHEDULER_NO_TASK; | ||
505 | } | ||
506 | 544 | ||
507 | if (plugin->broadcast_ipv4_mst != NULL) | 545 | if (p->broadcast_task != GNUNET_SCHEDULER_NO_TASK) |
508 | GNUNET_SERVER_mst_destroy (plugin->broadcast_ipv4_mst); | ||
509 | |||
510 | while (plugin->ipv4_broadcast_head != NULL) | ||
511 | { | 546 | { |
512 | struct BroadcastAddress *p = plugin->ipv4_broadcast_head; | 547 | GNUNET_SCHEDULER_cancel (p->broadcast_task); |
513 | 548 | p->broadcast_task = GNUNET_SCHEDULER_NO_TASK; | |
514 | GNUNET_CONTAINER_DLL_remove (plugin->ipv4_broadcast_head, | ||
515 | plugin->ipv4_broadcast_tail, p); | ||
516 | GNUNET_free (p->addr); | ||
517 | GNUNET_free (p); | ||
518 | } | 549 | } |
519 | } | 550 | if ((GNUNET_YES == plugin->enable_ipv6) && |
520 | 551 | (NULL != plugin->sockv6) && | |
521 | if (plugin->broadcast_ipv6) | 552 | (p->addrlen == sizeof (struct sockaddr_in6))) |
522 | { | 553 | { |
523 | /* Create IPv6 multicast request */ | 554 | /* Create IPv6 multicast request */ |
524 | struct ipv6_mreq multicastRequest; | 555 | struct ipv6_mreq multicastRequest; |
556 | const struct sockaddr_in6 *s6 = (const struct sockaddr_in6 *) p->addr; | ||
525 | 557 | ||
526 | multicastRequest.ipv6mr_multiaddr = | 558 | multicastRequest.ipv6mr_multiaddr = |
527 | plugin->ipv6_multicast_address.sin6_addr; | 559 | plugin->ipv6_multicast_address.sin6_addr; |
528 | multicastRequest.ipv6mr_interface = 0; | 560 | multicastRequest.ipv6mr_interface = s6->sin6_scope_id; |
529 | 561 | ||
530 | /* Join the multicast address */ | 562 | /* Leave the multicast group */ |
531 | if (GNUNET_NETWORK_socket_setsockopt | 563 | if (GNUNET_OK == |
532 | (plugin->sockv6, IPPROTO_IPV6, IPV6_LEAVE_GROUP, | 564 | GNUNET_NETWORK_socket_setsockopt |
533 | (char *) &multicastRequest, sizeof (multicastRequest)) != GNUNET_OK) | 565 | (plugin->sockv6, IPPROTO_IPV6, IPV6_LEAVE_GROUP, |
534 | { | 566 | &multicastRequest, sizeof (multicastRequest))) |
535 | GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, setsockopt); | 567 | { |
536 | } | 568 | GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, setsockopt); |
537 | else | 569 | } |
538 | { | 570 | else |
539 | LOG (GNUNET_ERROR_TYPE_DEBUG, "IPv6 Broadcasting stopped\n"); | 571 | { |
540 | } | 572 | LOG (GNUNET_ERROR_TYPE_DEBUG, "IPv6 multicasting stopped\n"); |
541 | 573 | } | |
542 | if (plugin->send_ipv6_broadcast_task != GNUNET_SCHEDULER_NO_TASK) | ||
543 | { | ||
544 | GNUNET_SCHEDULER_cancel (plugin->send_ipv6_broadcast_task); | ||
545 | plugin->send_ipv6_broadcast_task = GNUNET_SCHEDULER_NO_TASK; | ||
546 | } | 574 | } |
547 | if (plugin->broadcast_ipv6_mst != NULL) | 575 | // close cryogenic FD... |
548 | GNUNET_SERVER_mst_destroy (plugin->broadcast_ipv6_mst); | 576 | GNUNET_CONTAINER_DLL_remove (plugin->broadcast_head, |
577 | plugin->broadcast_tail, p); | ||
578 | GNUNET_free (p->addr); | ||
579 | GNUNET_free (p); | ||
549 | } | 580 | } |
550 | 581 | if (plugin->broadcast_ipv4_mst != NULL) | |
582 | GNUNET_SERVER_mst_destroy (plugin->broadcast_ipv4_mst); | ||
583 | if (plugin->broadcast_ipv6_mst != NULL) | ||
584 | GNUNET_SERVER_mst_destroy (plugin->broadcast_ipv6_mst); | ||
551 | } | 585 | } |
552 | 586 | ||
553 | /* end of plugin_transport_udp_broadcasting.c */ | 587 | /* end of plugin_transport_udp_broadcasting.c */ |