2
0

plugin_transport_udp_broadcasting.c 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647
  1. /*
  2. This file is part of GNUnet
  3. Copyright (C) 2010, 2011 GNUnet e.V.
  4. GNUnet is free software: you can redistribute it and/or modify it
  5. under the terms of the GNU Affero General Public License as published
  6. by the Free Software Foundation, either version 3 of the License,
  7. or (at your option) any later version.
  8. GNUnet is distributed in the hope that it will be useful, but
  9. WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  11. Affero General Public License for more details.
  12. You should have received a copy of the GNU Affero General Public License
  13. along with this program. If not, see <http://www.gnu.org/licenses/>.
  14. SPDX-License-Identifier: AGPL3.0-or-later
  15. */
  16. /**
  17. * @file transport/plugin_transport_udp_broadcasting.c
  18. * @brief Neighbour discovery with UDP
  19. * @author Christian Grothoff
  20. * @author Matthias Wachs
  21. */
  22. #include "platform.h"
  23. #include "plugin_transport_udp.h"
  24. #include "gnunet_hello_lib.h"
  25. #include "gnunet_util_lib.h"
  26. #include "gnunet_fragmentation_lib.h"
  27. #include "gnunet_protocols.h"
  28. #include "gnunet_resolver_service.h"
  29. #include "gnunet_signatures.h"
  30. #include "gnunet_constants.h"
  31. #include "gnunet_statistics_service.h"
  32. #include "gnunet_transport_service.h"
  33. #include "gnunet_transport_plugin.h"
  34. #include "transport.h"
  35. #define LOG(kind, ...) GNUNET_log_from (kind, "transport-udp", __VA_ARGS__)
  36. /* *********** Cryogenic ********** */
  37. #ifdef __linux__
  38. #include <sys/stat.h>
  39. #include <fcntl.h>
  40. #include <sys/ioctl.h>
  41. #include <sys/select.h>
  42. #include <sys/time.h>
  43. #define PM_MAGIC 'k'
  44. #define PM_SET_DELAY_AND_TIMEOUT _IOW (PM_MAGIC, 1, struct pm_times)
  45. struct pm_times
  46. {
  47. unsigned long delay_msecs;
  48. unsigned long timeout_msecs;
  49. };
  50. #endif
  51. /************************************/
  52. struct UDP_Beacon_Message
  53. {
  54. /**
  55. * Message header.
  56. */
  57. struct GNUNET_MessageHeader header;
  58. /**
  59. * What is the identity of the sender
  60. */
  61. struct GNUNET_PeerIdentity sender;
  62. };
  63. struct BroadcastAddress
  64. {
  65. struct BroadcastAddress *next;
  66. struct BroadcastAddress *prev;
  67. /**
  68. * ID of select broadcast task
  69. */
  70. struct GNUNET_SCHEDULER_Task *broadcast_task;
  71. struct Plugin *plugin;
  72. struct sockaddr *addr;
  73. socklen_t addrlen;
  74. #ifdef __linux__
  75. /**
  76. * Cryogenic handle.
  77. */
  78. struct GNUNET_DISK_FileHandle *cryogenic_fd;
  79. /**
  80. * Time out for cryogenic.
  81. */
  82. struct pm_times cryogenic_times;
  83. #endif
  84. };
  85. /**
  86. * Client-specific context for #broadcast_mst_cb().
  87. */
  88. struct MstContext
  89. {
  90. struct Plugin *plugin;
  91. const union UdpAddress *udp_addr;
  92. size_t udp_addr_len;
  93. /**
  94. * ATS network type.
  95. */
  96. enum GNUNET_NetworkType ats_address_network_type;
  97. };
  98. /**
  99. * Parse broadcast message received.
  100. *
  101. * @param cls the `struct Plugin`
  102. * @param client the `struct MstContext` with sender address
  103. * @param message the message we received
  104. * @return #GNUNET_OK (always)
  105. */
  106. static int
  107. broadcast_mst_cb (void *cls,
  108. const struct GNUNET_MessageHeader *message)
  109. {
  110. struct MstContext *mc = cls;
  111. struct Plugin *plugin = mc->plugin;
  112. struct GNUNET_HELLO_Address *address;
  113. const struct GNUNET_MessageHeader *hello;
  114. const struct UDP_Beacon_Message *msg;
  115. msg = (const struct UDP_Beacon_Message *) message;
  116. if (GNUNET_MESSAGE_TYPE_TRANSPORT_BROADCAST_BEACON !=
  117. ntohs (msg->header.type))
  118. return GNUNET_OK;
  119. LOG (GNUNET_ERROR_TYPE_DEBUG,
  120. "Received beacon with %u bytes from peer `%s' via address `%s'\n",
  121. ntohs (msg->header.size),
  122. GNUNET_i2s (&msg->sender),
  123. udp_address_to_string (NULL,
  124. mc->udp_addr,
  125. mc->udp_addr_len));
  126. hello = (struct GNUNET_MessageHeader *) &msg[1];
  127. address = GNUNET_HELLO_address_allocate (&msg->sender,
  128. PLUGIN_NAME,
  129. mc->udp_addr,
  130. mc->udp_addr_len,
  131. GNUNET_HELLO_ADDRESS_INFO_NONE);
  132. plugin->env->receive (plugin->env->cls,
  133. address,
  134. NULL,
  135. hello);
  136. GNUNET_HELLO_address_free (address);
  137. GNUNET_STATISTICS_update (plugin->env->stats,
  138. _ ("# Multicast HELLO beacons received via UDP"),
  139. 1, GNUNET_NO);
  140. return GNUNET_OK;
  141. }
  142. /**
  143. * We received a broadcast message. Process it and all subsequent
  144. * messages in the same packet.
  145. *
  146. * @param plugin the UDP plugin
  147. * @param buf the buffer with the message(s)
  148. * @param size number of bytes in @a buf
  149. * @param udp_addr address of the sender
  150. * @param udp_addr_len number of bytes in @a udp_addr
  151. * @param network_type network type of the sender's address
  152. */
  153. void
  154. udp_broadcast_receive (struct Plugin *plugin,
  155. const char *buf,
  156. ssize_t size,
  157. const union UdpAddress *udp_addr,
  158. size_t udp_addr_len,
  159. enum GNUNET_NetworkType network_type)
  160. {
  161. struct GNUNET_MessageStreamTokenizer *broadcast_mst;
  162. struct MstContext mc;
  163. broadcast_mst = GNUNET_MST_create (&broadcast_mst_cb,
  164. &mc);
  165. mc.plugin = plugin;
  166. mc.udp_addr = udp_addr;
  167. mc.udp_addr_len = udp_addr_len;
  168. mc.ats_address_network_type = network_type;
  169. GNUNET_MST_from_buffer (broadcast_mst,
  170. buf, size,
  171. GNUNET_NO,
  172. GNUNET_NO);
  173. GNUNET_MST_destroy (broadcast_mst);
  174. }
  175. static unsigned int
  176. prepare_beacon (struct Plugin *plugin,
  177. struct UDP_Beacon_Message *msg)
  178. {
  179. uint16_t hello_size;
  180. uint16_t msg_size;
  181. const struct GNUNET_MessageHeader *hello;
  182. hello = plugin->env->get_our_hello ();
  183. if (NULL == hello)
  184. return 0;
  185. hello_size = GNUNET_HELLO_size ((struct GNUNET_HELLO_Message *) hello);
  186. msg_size = hello_size + sizeof(struct UDP_Beacon_Message);
  187. if ((hello_size < (sizeof(struct GNUNET_MessageHeader))) ||
  188. (msg_size > (UDP_MTU)))
  189. return 0;
  190. msg->sender = *(plugin->env->my_identity);
  191. msg->header.size = htons (msg_size);
  192. msg->header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_BROADCAST_BEACON);
  193. GNUNET_memcpy (&msg[1], hello, hello_size);
  194. return msg_size;
  195. }
  196. static void
  197. udp_ipv4_broadcast_send (void *cls)
  198. {
  199. struct BroadcastAddress *baddr = cls;
  200. struct Plugin *plugin = baddr->plugin;
  201. int sent;
  202. uint16_t msg_size;
  203. char buf[65536] GNUNET_ALIGN;
  204. baddr->broadcast_task = NULL;
  205. msg_size = prepare_beacon (plugin, (struct UDP_Beacon_Message *) &buf);
  206. if (0 != msg_size)
  207. {
  208. struct sockaddr_in *addr = (struct sockaddr_in *) baddr->addr;
  209. addr->sin_port = htons (plugin->port);
  210. sent = GNUNET_NETWORK_socket_sendto (plugin->sockv4, &buf, msg_size,
  211. (const struct sockaddr *) addr,
  212. baddr->addrlen);
  213. if (sent == GNUNET_SYSERR)
  214. {
  215. if ((ENETUNREACH == errno) || (ENETDOWN == errno))
  216. {
  217. /* "Network unreachable" or "Network down"
  218. *
  219. * This indicates that we just do not have network connectivity
  220. */
  221. GNUNET_log (GNUNET_ERROR_TYPE_BULK | GNUNET_ERROR_TYPE_WARNING,
  222. "Network connectivity is down, cannot send beacon!\n");
  223. }
  224. else
  225. GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "sendto");
  226. }
  227. else
  228. {
  229. LOG (GNUNET_ERROR_TYPE_DEBUG,
  230. "Sent HELLO beacon broadcast with %i bytes to address %s\n", sent,
  231. GNUNET_a2s (baddr->addr, baddr->addrlen));
  232. }
  233. }
  234. #ifdef __linux__
  235. /*
  236. * Cryogenic
  237. */
  238. if (NULL != baddr->cryogenic_fd)
  239. {
  240. baddr->cryogenic_times.delay_msecs =
  241. (plugin->broadcast_interval.rel_value_us / 1000.0) * 0.5;
  242. baddr->cryogenic_times.timeout_msecs =
  243. (plugin->broadcast_interval.rel_value_us / 1000.0) * 1.5;
  244. if (ioctl (baddr->cryogenic_fd->fd,
  245. PM_SET_DELAY_AND_TIMEOUT,
  246. &baddr->cryogenic_times) < 0)
  247. {
  248. GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "ioctl");
  249. baddr->broadcast_task =
  250. GNUNET_SCHEDULER_add_delayed (plugin->broadcast_interval,
  251. &udp_ipv4_broadcast_send, baddr);
  252. }
  253. else
  254. GNUNET_SCHEDULER_add_write_file (GNUNET_TIME_UNIT_FOREVER_REL,
  255. baddr->cryogenic_fd,
  256. &udp_ipv4_broadcast_send,
  257. baddr);
  258. }
  259. else
  260. #endif
  261. baddr->broadcast_task =
  262. GNUNET_SCHEDULER_add_delayed (plugin->broadcast_interval,
  263. &udp_ipv4_broadcast_send, baddr);
  264. }
  265. static void
  266. udp_ipv6_broadcast_send (void *cls)
  267. {
  268. struct BroadcastAddress *baddr = cls;
  269. struct Plugin *plugin = baddr->plugin;
  270. ssize_t sent;
  271. uint16_t msg_size;
  272. char buf[65536] GNUNET_ALIGN;
  273. const struct sockaddr_in6 *s6 = (const struct sockaddr_in6 *) baddr->addr;
  274. baddr->broadcast_task = NULL;
  275. msg_size = prepare_beacon (plugin, (struct UDP_Beacon_Message *) &buf);
  276. /* Note: unclear if this actually works to limit the multicast to
  277. the specified interface as we're not (necessarily) using a
  278. link-local multicast group and the kernel suggests that the
  279. scope ID is only respected for link-local addresses; however,
  280. if the scope ID is ignored, the kernel should just multicast
  281. on ALL interfaces, which is merely slightly less efficient;
  282. in that case, we might want to revert to only doing this
  283. once, and not per interface (hard to test...) */plugin->ipv6_multicast_address.sin6_scope_id = s6->sin6_scope_id;
  284. sent = GNUNET_NETWORK_socket_sendto (plugin->sockv6, &buf, msg_size,
  285. (const struct sockaddr *)
  286. &plugin->ipv6_multicast_address,
  287. sizeof(struct sockaddr_in6));
  288. plugin->ipv6_multicast_address.sin6_scope_id = 0;
  289. if (sent == GNUNET_SYSERR)
  290. {
  291. if ((ENETUNREACH == errno) || (ENETDOWN == errno))
  292. {
  293. /* "Network unreachable" or "Network down"
  294. *
  295. * This indicates that this system is IPv6 enabled, but does not
  296. * have a valid global IPv6 address assigned
  297. */GNUNET_log (GNUNET_ERROR_TYPE_BULK | GNUNET_ERROR_TYPE_WARNING,
  298. "Network connectivity is down, cannot send beacon!\n");
  299. }
  300. else
  301. GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "sendto");
  302. }
  303. else
  304. {
  305. LOG (GNUNET_ERROR_TYPE_DEBUG,
  306. "Sending IPv6 HELLO beacon broadcast with %d bytes to address %s\n",
  307. (int) sent,
  308. GNUNET_a2s ((const struct sockaddr *) &plugin->ipv6_multicast_address,
  309. sizeof(struct sockaddr_in6)));
  310. }
  311. #ifdef __linux__
  312. /*
  313. * Cryogenic
  314. */
  315. if (NULL != baddr->cryogenic_fd)
  316. {
  317. baddr->cryogenic_times.delay_msecs =
  318. (plugin->broadcast_interval.rel_value_us / 1000.0) * 0.5;
  319. baddr->cryogenic_times.timeout_msecs =
  320. (plugin->broadcast_interval.rel_value_us / 1000.0) * 1.5;
  321. if (ioctl (baddr->cryogenic_fd->fd,
  322. PM_SET_DELAY_AND_TIMEOUT,
  323. &baddr->cryogenic_times) < 0)
  324. {
  325. GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "ioctl");
  326. baddr->broadcast_task =
  327. GNUNET_SCHEDULER_add_delayed (plugin->broadcast_interval,
  328. &udp_ipv6_broadcast_send, baddr);
  329. }
  330. else
  331. GNUNET_SCHEDULER_add_write_file (GNUNET_TIME_UNIT_FOREVER_REL,
  332. baddr->cryogenic_fd,
  333. &udp_ipv6_broadcast_send,
  334. baddr);
  335. }
  336. else
  337. #endif
  338. baddr->broadcast_task =
  339. GNUNET_SCHEDULER_add_delayed (plugin->broadcast_interval,
  340. &udp_ipv6_broadcast_send, baddr);
  341. }
  342. /**
  343. * Callback function invoked for each interface found.
  344. *
  345. * @param cls closure with the `struct Plugin`
  346. * @param name name of the interface (can be NULL for unknown)
  347. * @param isDefault is this presumably the default interface
  348. * @param addr address of this interface (can be NULL for unknown or unassigned)
  349. * @param broadcast_addr the broadcast address (can be NULL for unknown or unassigned)
  350. * @param netmask the network mask (can be NULL for unknown or unassigned)
  351. * @param addrlen length of the address
  352. * @return #GNUNET_OK to continue iteration, #GNUNET_SYSERR to abort
  353. */
  354. static int
  355. iface_proc (void *cls,
  356. const char *name,
  357. int isDefault,
  358. const struct sockaddr *addr,
  359. const struct sockaddr *broadcast_addr,
  360. const struct sockaddr *netmask, socklen_t addrlen)
  361. {
  362. struct Plugin *plugin = cls;
  363. struct BroadcastAddress *ba;
  364. enum GNUNET_NetworkType network;
  365. if (NULL == addr)
  366. return GNUNET_OK;
  367. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  368. "address %s for interface %s %p\n ",
  369. GNUNET_a2s (addr, addrlen), name, addr);
  370. if (NULL == broadcast_addr)
  371. return GNUNET_OK;
  372. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  373. "broadcast address %s for interface %s %p\n ",
  374. GNUNET_a2s (broadcast_addr, addrlen), name, broadcast_addr);
  375. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "netmask %s for interface %s %p\n ",
  376. GNUNET_a2s (netmask, addrlen), name, netmask);
  377. network = plugin->env->get_address_type (plugin->env->cls, broadcast_addr,
  378. addrlen);
  379. if (GNUNET_NT_LOOPBACK == network)
  380. {
  381. /* Broadcasting on loopback does not make sense */
  382. return GNUNET_YES;
  383. }
  384. ba = GNUNET_new (struct BroadcastAddress);
  385. ba->plugin = plugin;
  386. ba->addr = GNUNET_malloc (addrlen);
  387. GNUNET_memcpy (ba->addr, broadcast_addr, addrlen);
  388. ba->addrlen = addrlen;
  389. if ((GNUNET_YES == plugin->enable_ipv4) &&
  390. (NULL != plugin->sockv4) &&
  391. (addrlen == sizeof(struct sockaddr_in)))
  392. {
  393. #ifdef __linux__
  394. /*
  395. * setup Cryogenic FD for ipv4 broadcasting
  396. */
  397. char *filename;
  398. GNUNET_asprintf (&filename,
  399. "/dev/cryogenic/%s",
  400. name);
  401. if (0 == access (name, R_OK))
  402. {
  403. ba->cryogenic_fd =
  404. GNUNET_DISK_file_open (filename,
  405. GNUNET_DISK_OPEN_WRITE,
  406. GNUNET_DISK_PERM_NONE);
  407. }
  408. GNUNET_free (filename);
  409. #endif
  410. ba->broadcast_task =
  411. GNUNET_SCHEDULER_add_now (&udp_ipv4_broadcast_send, ba);
  412. }
  413. if ((GNUNET_YES == plugin->enable_ipv6) &&
  414. (NULL != plugin->sockv6) &&
  415. (addrlen == sizeof(struct sockaddr_in6)))
  416. {
  417. /* Create IPv6 multicast request */
  418. struct ipv6_mreq multicastRequest;
  419. const struct sockaddr_in6 *s6 = (const struct
  420. sockaddr_in6 *) broadcast_addr;
  421. multicastRequest.ipv6mr_multiaddr =
  422. plugin->ipv6_multicast_address.sin6_addr;
  423. /* http://tools.ietf.org/html/rfc2553#section-5.2:
  424. *
  425. * IPV6_JOIN_GROUP
  426. *
  427. * Join a multicast group on a specified local interface. If the
  428. * interface index is specified as 0, the kernel chooses the local
  429. * interface. For example, some kernels look up the multicast
  430. * group in the normal IPv6 routing table and using the resulting
  431. * interface; we do this for each interface, so no need to use
  432. * zero (anymore...).
  433. */multicastRequest.ipv6mr_interface = s6->sin6_scope_id;
  434. /* Join the multicast group */
  435. if (GNUNET_OK !=
  436. GNUNET_NETWORK_socket_setsockopt
  437. (plugin->sockv6, IPPROTO_IPV6, IPV6_JOIN_GROUP,
  438. &multicastRequest, sizeof(multicastRequest)))
  439. {
  440. LOG (GNUNET_ERROR_TYPE_WARNING,
  441. "Failed to join IPv6 multicast group: IPv6 broadcasting not running\n");
  442. }
  443. else
  444. {
  445. #ifdef __linux__
  446. /*
  447. * setup Cryogenic FD for ipv6 broadcasting
  448. */
  449. char *filename;
  450. GNUNET_asprintf (&filename,
  451. "/dev/cryogenic/%s",
  452. name);
  453. if (0 == access (name, R_OK))
  454. {
  455. ba->cryogenic_fd =
  456. GNUNET_DISK_file_open (filename,
  457. GNUNET_DISK_OPEN_WRITE,
  458. GNUNET_DISK_PERM_NONE);
  459. }
  460. GNUNET_free (filename);
  461. #endif
  462. ba->broadcast_task =
  463. GNUNET_SCHEDULER_add_now (&udp_ipv6_broadcast_send, ba);
  464. }
  465. }
  466. GNUNET_CONTAINER_DLL_insert (plugin->broadcast_head,
  467. plugin->broadcast_tail, ba);
  468. return GNUNET_OK;
  469. }
  470. /**
  471. * Setup broadcasting subsystem.
  472. *
  473. * @param plugin
  474. * @param server_addrv6
  475. * @param server_addrv4
  476. */
  477. void
  478. setup_broadcast (struct Plugin *plugin,
  479. struct sockaddr_in6 *server_addrv6,
  480. struct sockaddr_in *server_addrv4)
  481. {
  482. if (GNUNET_YES ==
  483. GNUNET_CONFIGURATION_get_value_yesno (plugin->env->cfg,
  484. "topology",
  485. "FRIENDS-ONLY"))
  486. {
  487. LOG (GNUNET_ERROR_TYPE_WARNING,
  488. _ (
  489. "Disabling HELLO broadcasting due to friend-to-friend only configuration!\n"));
  490. return;
  491. }
  492. if (GNUNET_YES != plugin->enable_broadcasting)
  493. return; /* We do not send, just receive */
  494. /* create IPv4 broadcast socket */
  495. if ((GNUNET_YES == plugin->enable_ipv4) && (NULL != plugin->sockv4))
  496. {
  497. static int yes = 1;
  498. if (GNUNET_NETWORK_socket_setsockopt
  499. (plugin->sockv4, SOL_SOCKET, SO_BROADCAST, &yes,
  500. sizeof(int)) != GNUNET_OK)
  501. {
  502. LOG (GNUNET_ERROR_TYPE_WARNING,
  503. _ (
  504. "Failed to set IPv4 broadcast option for broadcast socket on port %d\n"),
  505. ntohs (server_addrv4->sin_port));
  506. }
  507. }
  508. /* create IPv6 multicast socket */
  509. if ((GNUNET_YES == plugin->enable_ipv6) && (plugin->sockv6 != NULL))
  510. {
  511. memset (&plugin->ipv6_multicast_address, 0, sizeof(struct sockaddr_in6));
  512. GNUNET_assert (1 ==
  513. inet_pton (AF_INET6, "FF05::13B",
  514. &plugin->ipv6_multicast_address.sin6_addr));
  515. plugin->ipv6_multicast_address.sin6_family = AF_INET6;
  516. plugin->ipv6_multicast_address.sin6_port = htons (plugin->port);
  517. }
  518. GNUNET_OS_network_interfaces_list (&iface_proc, plugin);
  519. }
  520. /**
  521. * Stop broadcasting subsystem.
  522. *
  523. * @param plugin
  524. */
  525. void
  526. stop_broadcast (struct Plugin *plugin)
  527. {
  528. if (GNUNET_YES == plugin->enable_broadcasting)
  529. {
  530. /* Disable broadcasting */
  531. while (plugin->broadcast_head != NULL)
  532. {
  533. struct BroadcastAddress *p = plugin->broadcast_head;
  534. if (p->broadcast_task != NULL)
  535. {
  536. GNUNET_SCHEDULER_cancel (p->broadcast_task);
  537. p->broadcast_task = NULL;
  538. }
  539. if ((GNUNET_YES == plugin->enable_ipv6) &&
  540. (NULL != plugin->sockv6) &&
  541. (p->addrlen == sizeof(struct sockaddr_in6)))
  542. {
  543. /* Create IPv6 multicast request */
  544. struct ipv6_mreq multicastRequest;
  545. const struct sockaddr_in6 *s6 = (const struct sockaddr_in6 *) p->addr;
  546. multicastRequest.ipv6mr_multiaddr =
  547. plugin->ipv6_multicast_address.sin6_addr;
  548. multicastRequest.ipv6mr_interface = s6->sin6_scope_id;
  549. /* Leave the multicast group */
  550. if (GNUNET_OK ==
  551. GNUNET_NETWORK_socket_setsockopt
  552. (plugin->sockv6, IPPROTO_IPV6, IPV6_LEAVE_GROUP,
  553. &multicastRequest, sizeof(multicastRequest)))
  554. {
  555. GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "setsockopt");
  556. }
  557. else
  558. {
  559. LOG (GNUNET_ERROR_TYPE_DEBUG, "IPv6 multicasting stopped\n");
  560. }
  561. }
  562. #ifdef __linux__
  563. GNUNET_DISK_file_close (p->cryogenic_fd);
  564. #endif
  565. GNUNET_CONTAINER_DLL_remove (plugin->broadcast_head,
  566. plugin->broadcast_tail, p);
  567. GNUNET_free (p->addr);
  568. GNUNET_free (p);
  569. }
  570. }
  571. }
  572. /* end of plugin_transport_udp_broadcasting.c */