X-Git-Url: https://git.librecmc.org/?a=blobdiff_plain;f=src%2Ftransport%2Fplugin_transport_udp_broadcasting.c;h=0c26aa62493760f66ff0aee499e034bad462b5c2;hb=1b1edf92c24f91c36747458e880e0d6a5e559e95;hp=15325938251af7b6d3820f816d023a54abb2cc95;hpb=d8c56c79613f603765984a9a8fc2ed9036bdd2e6;p=oweals%2Fgnunet.git diff --git a/src/transport/plugin_transport_udp_broadcasting.c b/src/transport/plugin_transport_udp_broadcasting.c index 153259382..0c26aa624 100644 --- a/src/transport/plugin_transport_udp_broadcasting.c +++ b/src/transport/plugin_transport_udp_broadcasting.c @@ -1,21 +1,21 @@ /* This file is part of GNUnet - (C) 2010, 2011 Christian Grothoff (and other contributing authors) + Copyright (C) 2010, 2011 GNUnet e.V. - GNUnet is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published - by the Free Software Foundation; either version 3, or (at your - option) any later version. + GNUnet is free software: you can redistribute it and/or modify it + under the terms of the GNU Affero General Public License as published + by the Free Software Foundation, either version 3 of the License, + or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see . - You should have received a copy of the GNU General Public License - along with GNUnet; see the file COPYING. If not, write to the - Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. + SPDX-License-Identifier: AGPL3.0-or-later */ /** @@ -29,7 +29,6 @@ #include "gnunet_hello_lib.h" #include "gnunet_util_lib.h" #include "gnunet_fragmentation_lib.h" -#include "gnunet_nat_lib.h" #include "gnunet_protocols.h" #include "gnunet_resolver_service.h" #include "gnunet_signatures.h" @@ -42,7 +41,7 @@ #define LOG(kind,...) GNUNET_log_from (kind, "transport-udp", __VA_ARGS__) /* *********** Cryogenic ********** */ - +#if LINUX #include #include @@ -57,7 +56,8 @@ struct pm_times { unsigned long delay_msecs; unsigned long timeout_msecs; }; -/************************************/ +#endif +/************************************/ struct UDP_Beacon_Message @@ -83,103 +83,63 @@ struct BroadcastAddress /** * ID of select broadcast task */ - GNUNET_SCHEDULER_TaskIdentifier broadcast_task; + struct GNUNET_SCHEDULER_Task * broadcast_task; struct Plugin *plugin; - void *addr; + struct sockaddr *addr; socklen_t addrlen; - - /* - * Cryogenic fields + +#if LINUX + /** + * Cryogenic handle. */ struct GNUNET_DISK_FileHandle *cryogenic_fd; + /** + * Time out for cryogenic. + */ struct pm_times cryogenic_times; +#endif }; -struct Mstv4Context +/** + * Client-specific context for #broadcast_mst_cb(). + */ +struct MstContext { struct Plugin *plugin; - struct IPv4UdpAddress addr; - /** - * ATS network type in NBO - */ - uint32_t ats_address_network_type; -}; + const union UdpAddress *udp_addr; -struct Mstv6Context -{ - struct Plugin *plugin; + size_t udp_addr_len; - struct IPv6UdpAddress addr; /** - * ATS network type in NBO + * ATS network type. */ - uint32_t ats_address_network_type; + enum GNUNET_NetworkType ats_address_network_type; }; +/** + * Parse broadcast message received. + * + * @param cls the `struct Plugin` + * @param client the `struct MstContext` with sender address + * @param message the message we received + * @return #GNUNET_OK (always) + */ static int -broadcast_ipv6_mst_cb (void *cls, void *client, - const struct GNUNET_MessageHeader *message) -{ - struct Plugin *plugin = cls; - struct Mstv6Context *mc = client; - const struct GNUNET_MessageHeader *hello; - const struct UDP_Beacon_Message *msg; - struct GNUNET_ATS_Information atsi; - - msg = (const struct UDP_Beacon_Message *) message; - - if (GNUNET_MESSAGE_TYPE_TRANSPORT_BROADCAST_BEACON != - ntohs (msg->header.type)) - return GNUNET_OK; - LOG (GNUNET_ERROR_TYPE_DEBUG, - "Received beacon with %u bytes from peer `%s' via address `%s'\n", - ntohs (msg->header.size), GNUNET_i2s (&msg->sender), - udp_address_to_string (NULL, &mc->addr, sizeof (mc->addr))); - - /* setup ATS */ - atsi.type = htonl (GNUNET_ATS_NETWORK_TYPE); - atsi.value = mc->ats_address_network_type; - GNUNET_break (ntohl(mc->ats_address_network_type) != GNUNET_ATS_NET_UNSPECIFIED); - - hello = (struct GNUNET_MessageHeader *) &msg[1]; - plugin->env->receive (plugin->env->cls, - &msg->sender, - hello, - NULL, - (const char *) &mc->addr, - sizeof (mc->addr)); - plugin->env->update_address_metrics (plugin->env->cls, - &msg->sender, - (const char *) &mc->addr, - sizeof (mc->addr), - NULL, - &atsi, 1); - - GNUNET_STATISTICS_update (plugin->env->stats, - _ - ("# IPv6 multicast HELLO beacons received via udp"), - 1, GNUNET_NO); - GNUNET_free (mc); - return GNUNET_OK; -} - - -static int -broadcast_ipv4_mst_cb (void *cls, void *client, - const struct GNUNET_MessageHeader *message) +broadcast_mst_cb (void *cls, + const struct GNUNET_MessageHeader *message) { - struct Plugin *plugin = cls; - struct Mstv4Context *mc = client; + struct MstContext *mc = cls; + struct Plugin *plugin = mc->plugin; + struct GNUNET_HELLO_Address *address; const struct GNUNET_MessageHeader *hello; const struct UDP_Beacon_Message *msg; - struct GNUNET_ATS_Information atsi; msg = (const struct UDP_Beacon_Message *) message; @@ -188,93 +148,68 @@ broadcast_ipv4_mst_cb (void *cls, void *client, return GNUNET_OK; LOG (GNUNET_ERROR_TYPE_DEBUG, "Received beacon with %u bytes from peer `%s' via address `%s'\n", - ntohs (msg->header.size), GNUNET_i2s (&msg->sender), - udp_address_to_string (NULL, &mc->addr, sizeof (mc->addr))); - - - /* setup ATS */ - atsi.type = htonl (GNUNET_ATS_NETWORK_TYPE); - atsi.value = mc->ats_address_network_type; - GNUNET_break (ntohl(mc->ats_address_network_type) != GNUNET_ATS_NET_UNSPECIFIED); - + ntohs (msg->header.size), + GNUNET_i2s (&msg->sender), + udp_address_to_string (NULL, + mc->udp_addr, + mc->udp_addr_len)); hello = (struct GNUNET_MessageHeader *) &msg[1]; + address = GNUNET_HELLO_address_allocate (&msg->sender, + PLUGIN_NAME, + mc->udp_addr, + mc->udp_addr_len, + GNUNET_HELLO_ADDRESS_INFO_NONE); plugin->env->receive (plugin->env->cls, - &msg->sender, - hello, + address, NULL, - (const char *) &mc->addr, - sizeof (mc->addr)); - - plugin->env->update_address_metrics (plugin->env->cls, - &msg->sender, - (const char *) &mc->addr, - sizeof (mc->addr), - NULL, - &atsi, 1); - + hello); + GNUNET_HELLO_address_free (address); GNUNET_STATISTICS_update (plugin->env->stats, - _("# IPv4 broadcast HELLO beacons received via udp"), + _("# Multicast HELLO beacons received via UDP"), 1, GNUNET_NO); - GNUNET_free (mc); return GNUNET_OK; } +/** + * We received a broadcast message. Process it and all subsequent + * messages in the same packet. + * + * @param plugin the UDP plugin + * @param buf the buffer with the message(s) + * @param size number of bytes in @a buf + * @param udp_addr address of the sender + * @param udp_addr_len number of bytes in @a udp_addr + * @param network_type network type of the sender's address + */ void udp_broadcast_receive (struct Plugin *plugin, - const char * buf, + const char *buf, ssize_t size, - const struct sockaddr *addr, - size_t addrlen) + const union UdpAddress *udp_addr, + size_t udp_addr_len, + enum GNUNET_NetworkType network_type) { - struct GNUNET_ATS_Information ats; - - if (addrlen == sizeof (struct sockaddr_in)) - { - LOG (GNUNET_ERROR_TYPE_DEBUG, - "Received IPv4 HELLO beacon broadcast with %i bytes from address %s\n", - size, GNUNET_a2s ((const struct sockaddr *) addr, addrlen)); - struct Mstv4Context *mc; - - mc = GNUNET_malloc (sizeof (struct Mstv4Context)); - struct sockaddr_in *av4 = (struct sockaddr_in *) addr; - - mc->addr.ipv4_addr = av4->sin_addr.s_addr; - mc->addr.u4_port = av4->sin_port; - ats = plugin->env->get_address_type (plugin->env->cls, (const struct sockaddr *) addr, addrlen); - mc->ats_address_network_type = ats.value; - - GNUNET_assert (NULL != plugin->broadcast_ipv4_mst); - if (GNUNET_OK != - GNUNET_SERVER_mst_receive (plugin->broadcast_ipv4_mst, mc, buf, size, - GNUNET_NO, GNUNET_NO)) - GNUNET_free (mc); - } - if (addrlen == sizeof (struct sockaddr_in6)) - { - LOG (GNUNET_ERROR_TYPE_DEBUG, - "Received IPv6 HELLO beacon broadcast with %i bytes from address %s\n", - size, GNUNET_a2s ((const struct sockaddr *) &addr, addrlen)); - struct Mstv6Context *mc; - - mc = GNUNET_malloc (sizeof (struct Mstv6Context)); - struct sockaddr_in6 *av6 = (struct sockaddr_in6 *) addr; - - mc->addr.ipv6_addr = av6->sin6_addr; - mc->addr.u6_port = av6->sin6_port; - ats = plugin->env->get_address_type (plugin->env->cls, (const struct sockaddr *) addr, addrlen); - mc->ats_address_network_type = ats.value; - GNUNET_assert (NULL != plugin->broadcast_ipv4_mst); - if (GNUNET_OK != - GNUNET_SERVER_mst_receive (plugin->broadcast_ipv6_mst, mc, buf, size, - GNUNET_NO, GNUNET_NO)) - GNUNET_free (mc); - } + struct GNUNET_MessageStreamTokenizer *broadcast_mst; + struct MstContext mc; + + broadcast_mst = GNUNET_MST_create (&broadcast_mst_cb, + &mc); + mc.plugin = plugin; + mc.udp_addr = udp_addr; + mc.udp_addr_len = udp_addr_len; + mc.ats_address_network_type = network_type; + GNUNET_MST_from_buffer (broadcast_mst, + buf, size, + GNUNET_NO, + GNUNET_NO); + GNUNET_MST_destroy (broadcast_mst); } static unsigned int -prepare_beacon (struct Plugin *plugin, struct UDP_Beacon_Message *msg) +prepare_beacon (struct Plugin *plugin, + struct UDP_Beacon_Message *msg) { uint16_t hello_size; uint16_t msg_size; @@ -293,14 +228,13 @@ prepare_beacon (struct Plugin *plugin, struct UDP_Beacon_Message *msg) msg->sender = *(plugin->env->my_identity); msg->header.size = htons (msg_size); msg->header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_BROADCAST_BEACON); - memcpy (&msg[1], hello, hello_size); + GNUNET_memcpy (&msg[1], hello, hello_size); return msg_size; } static void -udp_ipv4_broadcast_send (void *cls, - const struct GNUNET_SCHEDULER_TaskContext *tc) +udp_ipv4_broadcast_send (void *cls) { struct BroadcastAddress *baddr = cls; struct Plugin *plugin = baddr->plugin; @@ -308,7 +242,7 @@ udp_ipv4_broadcast_send (void *cls, uint16_t msg_size; char buf[65536] GNUNET_ALIGN; - baddr->broadcast_task = GNUNET_SCHEDULER_NO_TASK; + baddr->broadcast_task = NULL; msg_size = prepare_beacon(plugin, (struct UDP_Beacon_Message *) &buf); if (0 != msg_size) @@ -340,7 +274,8 @@ udp_ipv4_broadcast_send (void *cls, GNUNET_a2s (baddr->addr, baddr->addrlen)); } } - + +#if LINUX /* * Cryogenic */ @@ -348,7 +283,7 @@ udp_ipv4_broadcast_send (void *cls, { baddr->cryogenic_times.delay_msecs = (plugin->broadcast_interval.rel_value_us/1000.0)*0.5; baddr->cryogenic_times.timeout_msecs = (plugin->broadcast_interval.rel_value_us/1000.0)*1.5; - + if (ioctl(baddr->cryogenic_fd->fd, PM_SET_DELAY_AND_TIMEOUT, &baddr->cryogenic_times) < 0) @@ -363,9 +298,10 @@ udp_ipv4_broadcast_send (void *cls, baddr->cryogenic_fd, &udp_ipv4_broadcast_send, baddr); - + } else +#endif baddr->broadcast_task = GNUNET_SCHEDULER_add_delayed (plugin->broadcast_interval, &udp_ipv4_broadcast_send, baddr); @@ -373,8 +309,7 @@ udp_ipv4_broadcast_send (void *cls, static void -udp_ipv6_broadcast_send (void *cls, - const struct GNUNET_SCHEDULER_TaskContext *tc) +udp_ipv6_broadcast_send (void *cls) { struct BroadcastAddress *baddr = cls; struct Plugin *plugin = baddr->plugin; @@ -383,7 +318,7 @@ udp_ipv6_broadcast_send (void *cls, char buf[65536] GNUNET_ALIGN; const struct sockaddr_in6 *s6 = (const struct sockaddr_in6 *) baddr->addr; - baddr->broadcast_task = GNUNET_SCHEDULER_NO_TASK; + baddr->broadcast_task = NULL; msg_size = prepare_beacon(plugin, (struct UDP_Beacon_Message *) &buf); /* Note: unclear if this actually works to limit the multicast to @@ -423,6 +358,7 @@ udp_ipv6_broadcast_send (void *cls, GNUNET_a2s ((const struct sockaddr *) &plugin->ipv6_multicast_address, sizeof (struct sockaddr_in6))); } +#if LINUX /* * Cryogenic */ @@ -430,7 +366,7 @@ udp_ipv6_broadcast_send (void *cls, { baddr->cryogenic_times.delay_msecs = (plugin->broadcast_interval.rel_value_us/1000.0)*0.5; baddr->cryogenic_times.timeout_msecs = (plugin->broadcast_interval.rel_value_us/1000.0)*1.5; - + if (ioctl(baddr->cryogenic_fd->fd, PM_SET_DELAY_AND_TIMEOUT, &baddr->cryogenic_times) < 0) @@ -443,10 +379,11 @@ udp_ipv6_broadcast_send (void *cls, else GNUNET_SCHEDULER_add_write_file (GNUNET_TIME_UNIT_FOREVER_REL, baddr->cryogenic_fd, - &udp_ipv4_broadcast_send, + &udp_ipv6_broadcast_send, baddr); } else +#endif baddr->broadcast_task = GNUNET_SCHEDULER_add_delayed (plugin->broadcast_interval, &udp_ipv6_broadcast_send, baddr); @@ -475,6 +412,7 @@ iface_proc (void *cls, { struct Plugin *plugin = cls; struct BroadcastAddress *ba; + enum GNUNET_NetworkType network; if (NULL == addr) return GNUNET_OK; @@ -489,29 +427,41 @@ iface_proc (void *cls, GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "netmask %s for interface %s %p\n ", GNUNET_a2s (netmask, addrlen), name, netmask); + network = plugin->env->get_address_type (plugin->env->cls, broadcast_addr, addrlen); + if (GNUNET_NT_LOOPBACK == network) + { + /* Broadcasting on loopback does not make sense */ + return GNUNET_YES; + } + ba = GNUNET_new (struct BroadcastAddress); ba->plugin = plugin; ba->addr = GNUNET_malloc (addrlen); - memcpy (ba->addr, broadcast_addr, addrlen); + GNUNET_memcpy (ba->addr, broadcast_addr, addrlen); ba->addrlen = addrlen; + if ( (GNUNET_YES == plugin->enable_ipv4) && (NULL != plugin->sockv4) && (addrlen == sizeof (struct sockaddr_in)) ) { - - /* - * setup Cryogenic FD for ipv4 broadcasting - */ +#if LINUX + /* + * setup Cryogenic FD for ipv4 broadcasting + */ char *filename; + GNUNET_asprintf (&filename, - "/dev/power/%s", + "/dev/cryogenic/%s", name); - ba->cryogenic_fd = + if (0 == ACCESS (name, R_OK)) + { + ba->cryogenic_fd = GNUNET_DISK_file_open (filename, - GNUNET_DISK_OPEN_WRITE, - GNUNET_DISK_PERM_NONE); + GNUNET_DISK_OPEN_WRITE, + GNUNET_DISK_PERM_NONE); + } GNUNET_free (filename); - +#endif ba->broadcast_task = GNUNET_SCHEDULER_add_now (&udp_ipv4_broadcast_send, ba); } @@ -549,23 +499,24 @@ iface_proc (void *cls, } else { - LOG (GNUNET_ERROR_TYPE_DEBUG, - "IPv6 multicasting running\n"); - +#if LINUX /* * setup Cryogenic FD for ipv6 broadcasting */ char *filename; + GNUNET_asprintf (&filename, - "/dev/power/%s", + "/dev/cryogenic/%s", name); - ba->cryogenic_fd = + if (0 == ACCESS (name, R_OK)) + { + ba->cryogenic_fd = GNUNET_DISK_file_open (filename, - GNUNET_DISK_OPEN_WRITE, - GNUNET_DISK_PERM_NONE); + GNUNET_DISK_OPEN_WRITE, + GNUNET_DISK_PERM_NONE); + } GNUNET_free (filename); - - +#endif ba->broadcast_task = GNUNET_SCHEDULER_add_now (&udp_ipv6_broadcast_send, ba); } @@ -576,21 +527,31 @@ iface_proc (void *cls, } +/** + * Setup broadcasting subsystem. + * + * @param plugin + * @param server_addrv6 + * @param server_addrv4 + */ void setup_broadcast (struct Plugin *plugin, struct sockaddr_in6 *server_addrv6, struct sockaddr_in *server_addrv4) { - const struct GNUNET_MessageHeader *hello; - - hello = plugin->env->get_our_hello (); - if (GNUNET_YES == GNUNET_HELLO_is_friend_only((const struct GNUNET_HELLO_Message *) hello)) + if (GNUNET_YES == + GNUNET_CONFIGURATION_get_value_yesno (plugin->env->cfg, + "topology", + "FRIENDS-ONLY")) { LOG (GNUNET_ERROR_TYPE_WARNING, _("Disabling HELLO broadcasting due to friend-to-friend only configuration!\n")); return; } + if (GNUNET_YES != plugin->enable_broadcasting) + return; /* We do not send, just receive */ + /* create IPv4 broadcast socket */ if ((GNUNET_YES == plugin->enable_ipv4) && (NULL != plugin->sockv4)) { @@ -604,13 +565,8 @@ setup_broadcast (struct Plugin *plugin, _("Failed to set IPv4 broadcast option for broadcast socket on port %d\n"), ntohs (server_addrv4->sin_port)); } - else - { - plugin->broadcast_ipv4_mst = - GNUNET_SERVER_mst_create (broadcast_ipv4_mst_cb, plugin); - LOG (GNUNET_ERROR_TYPE_DEBUG, "IPv4 Broadcasting running\n"); - } } + /* create IPv6 multicast socket */ if ((GNUNET_YES == plugin->enable_ipv6) && (plugin->sockv6 != NULL)) { memset (&plugin->ipv6_multicast_address, 0, sizeof (struct sockaddr_in6)); @@ -619,65 +575,66 @@ setup_broadcast (struct Plugin *plugin, &plugin->ipv6_multicast_address.sin6_addr)); plugin->ipv6_multicast_address.sin6_family = AF_INET6; plugin->ipv6_multicast_address.sin6_port = htons (plugin->port); - plugin->broadcast_ipv6_mst = - GNUNET_SERVER_mst_create (broadcast_ipv6_mst_cb, plugin); } GNUNET_OS_network_interfaces_list (&iface_proc, plugin); } +/** + * Stop broadcasting subsystem. + * + * @param plugin + */ void stop_broadcast (struct Plugin *plugin) { - while (plugin->broadcast_head != NULL) + if (GNUNET_YES == plugin->enable_broadcasting) { - struct BroadcastAddress *p = plugin->broadcast_head; - - if (p->broadcast_task != GNUNET_SCHEDULER_NO_TASK) + /* Disable broadcasting */ + while (plugin->broadcast_head != NULL) { - GNUNET_SCHEDULER_cancel (p->broadcast_task); - p->broadcast_task = GNUNET_SCHEDULER_NO_TASK; - } - if ((GNUNET_YES == plugin->enable_ipv6) && - (NULL != plugin->sockv6) && - (p->addrlen == sizeof (struct sockaddr_in6))) - { - /* Create IPv6 multicast request */ - struct ipv6_mreq multicastRequest; - const struct sockaddr_in6 *s6 = (const struct sockaddr_in6 *) p->addr; - - multicastRequest.ipv6mr_multiaddr = - plugin->ipv6_multicast_address.sin6_addr; - multicastRequest.ipv6mr_interface = s6->sin6_scope_id; + struct BroadcastAddress *p = plugin->broadcast_head; - /* Leave the multicast group */ - if (GNUNET_OK == - GNUNET_NETWORK_socket_setsockopt - (plugin->sockv6, IPPROTO_IPV6, IPV6_LEAVE_GROUP, - &multicastRequest, sizeof (multicastRequest))) + if (p->broadcast_task != NULL) { - GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, setsockopt); + GNUNET_SCHEDULER_cancel (p->broadcast_task); + p->broadcast_task = NULL; } - else + if ((GNUNET_YES == plugin->enable_ipv6) && + (NULL != plugin->sockv6) && + (p->addrlen == sizeof (struct sockaddr_in6))) { - LOG (GNUNET_ERROR_TYPE_DEBUG, "IPv6 multicasting stopped\n"); + /* Create IPv6 multicast request */ + struct ipv6_mreq multicastRequest; + const struct sockaddr_in6 *s6 = (const struct sockaddr_in6 *) p->addr; + + multicastRequest.ipv6mr_multiaddr = + plugin->ipv6_multicast_address.sin6_addr; + multicastRequest.ipv6mr_interface = s6->sin6_scope_id; + + /* Leave the multicast group */ + if (GNUNET_OK == + GNUNET_NETWORK_socket_setsockopt + (plugin->sockv6, IPPROTO_IPV6, IPV6_LEAVE_GROUP, + &multicastRequest, sizeof (multicastRequest))) + { + GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "setsockopt"); + } + else + { + LOG (GNUNET_ERROR_TYPE_DEBUG, "IPv6 multicasting stopped\n"); + } } - } - /* - * Close Cryogenic FD - */ +#if LINUX GNUNET_DISK_file_close(p->cryogenic_fd); - - GNUNET_CONTAINER_DLL_remove (plugin->broadcast_head, - plugin->broadcast_tail, p); - GNUNET_free (p->addr); - GNUNET_free (p); +#endif + GNUNET_CONTAINER_DLL_remove (plugin->broadcast_head, + plugin->broadcast_tail, p); + GNUNET_free (p->addr); + GNUNET_free (p); + } } - if (plugin->broadcast_ipv4_mst != NULL) - GNUNET_SERVER_mst_destroy (plugin->broadcast_ipv4_mst); - if (plugin->broadcast_ipv6_mst != NULL) - GNUNET_SERVER_mst_destroy (plugin->broadcast_ipv6_mst); } /* end of plugin_transport_udp_broadcasting.c */