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