- struct Plugin *plugin = cls;
- struct IPv4UdpAddress *v4;
- struct IPv6UdpAddress *v6;
-
- if ((addrlen != sizeof (struct IPv4UdpAddress)) &&
- (addrlen != sizeof (struct IPv6UdpAddress)))
- {
- GNUNET_break_op (0);
- return GNUNET_SYSERR;
- }
- if (addrlen == sizeof (struct IPv4UdpAddress))
- {
- v4 = (struct IPv4UdpAddress *) addr;
- if (GNUNET_OK != check_port (plugin, ntohs (v4->u4_port)))
- return GNUNET_SYSERR;
- if (GNUNET_OK !=
- GNUNET_NAT_test_address (plugin->nat, &v4->ipv4_addr,
- sizeof (struct in_addr)))
- return GNUNET_SYSERR;
- }
- else
- {
- v6 = (struct IPv6UdpAddress *) addr;
- if (IN6_IS_ADDR_LINKLOCAL (&v6->ipv6_addr))
- {
- GNUNET_break_op (0);
- return GNUNET_SYSERR;
- }
- if (GNUNET_OK != check_port (plugin, ntohs (v6->u6_port)))
- return GNUNET_SYSERR;
- if (GNUNET_OK !=
- GNUNET_NAT_test_address (plugin->nat, &v6->ipv6_addr,
- sizeof (struct in6_addr)))
- return GNUNET_SYSERR;
- }
- return GNUNET_OK;
-}
-
-
-/**
- * Function called for a quick conversion of the binary address to
- * a numeric address. Note that the caller must not free the
- * address and that the next call to this function is allowed
- * to override the address again.
- *
- * @param cls closure
- * @param addr binary address
- * @param addrlen length of the address
- * @return string representing the same address
- */
-static const char *
-udp_address_to_string (void *cls, const void *addr, size_t addrlen)
-{
- static char rbuf[INET6_ADDRSTRLEN + 10];
- char buf[INET6_ADDRSTRLEN];
- const void *sb;
- struct in_addr a4;
- struct in6_addr a6;
- const struct IPv4UdpAddress *t4;
- const struct IPv6UdpAddress *t6;
- int af;
- uint16_t port;
-
- if (addrlen == sizeof (struct IPv6UdpAddress))
- {
- t6 = addr;
- af = AF_INET6;
- port = ntohs (t6->u6_port);
- memcpy (&a6, &t6->ipv6_addr, sizeof (a6));
- sb = &a6;
- }
- else if (addrlen == sizeof (struct IPv4UdpAddress))
- {
- t4 = addr;
- af = AF_INET;
- port = ntohs (t4->u4_port);
- memcpy (&a4, &t4->ipv4_addr, sizeof (a4));
- sb = &a4;
- }
- else
- {
- GNUNET_break_op (0);
- return NULL;
- }
- inet_ntop (af, sb, buf, INET6_ADDRSTRLEN);
- GNUNET_snprintf (rbuf, sizeof (rbuf), (af == AF_INET6) ? "[%s]:%u" : "%s:%u",
- buf, port);
- return rbuf;
-}
-
-
-/**
- * Closure for 'append_port'.
- */
-struct PrettyPrinterContext
-{
- /**
- * Function to call with the result.
- */
- GNUNET_TRANSPORT_AddressStringCallback asc;
-
- /**
- * Clsoure for 'asc'.
- */
- void *asc_cls;
-
- /**
- * Port to add after the IP address.
- */
- uint16_t port;
-};
-
-
-/**
- * Append our port and forward the result.
- *
- * @param cls a 'struct PrettyPrinterContext'
- * @param hostname result from DNS resolver
- */
-static void
-append_port (void *cls, const char *hostname)
-{
- struct PrettyPrinterContext *ppc = cls;
- char *ret;
-
- if (hostname == NULL)
- {
- ppc->asc (ppc->asc_cls, NULL);
- GNUNET_free (ppc);
- return;
- }
- GNUNET_asprintf (&ret, "%s:%d", hostname, ppc->port);
- ppc->asc (ppc->asc_cls, ret);
- GNUNET_free (ret);
-}
-
-
-/**
- * Convert the transports address to a nice, human-readable
- * format.
- *
- * @param cls closure
- * @param type name of the transport that generated the address
- * @param addr one of the addresses of the host, NULL for the last address
- * the specific address format depends on the transport
- * @param addrlen length of the address
- * @param numeric should (IP) addresses be displayed in numeric form?
- * @param timeout after how long should we give up?
- * @param asc function to call on each string
- * @param asc_cls closure for asc
- */
-static void
-udp_plugin_address_pretty_printer (void *cls, const char *type,
- const void *addr, size_t addrlen,
- int numeric,
- struct GNUNET_TIME_Relative timeout,
- GNUNET_TRANSPORT_AddressStringCallback asc,
- void *asc_cls)
-{
- struct PrettyPrinterContext *ppc;
- const void *sb;
- size_t sbs;
- struct sockaddr_in a4;
- struct sockaddr_in6 a6;
- const struct IPv4UdpAddress *u4;
- const struct IPv6UdpAddress *u6;
- uint16_t port;
-
- if (addrlen == sizeof (struct IPv6UdpAddress))
- {
- u6 = addr;
- memset (&a6, 0, sizeof (a6));
- a6.sin6_family = AF_INET6;
-#if HAVE_SOCKADDR_IN_SIN_LEN
- a6.sin6_len = sizeof (a6);
-#endif
- a6.sin6_port = u6->u6_port;
- memcpy (&a6.sin6_addr, &u6->ipv6_addr, sizeof (struct in6_addr));
- port = ntohs (u6->u6_port);
- sb = &a6;
- sbs = sizeof (a6);
- }
- else if (addrlen == sizeof (struct IPv4UdpAddress))
- {
- u4 = addr;
- memset (&a4, 0, sizeof (a4));
- a4.sin_family = AF_INET;
-#if HAVE_SOCKADDR_IN_SIN_LEN
- a4.sin_len = sizeof (a4);
-#endif
- a4.sin_port = u4->u4_port;
- a4.sin_addr.s_addr = u4->ipv4_addr;
- port = ntohs (u4->u4_port);
- sb = &a4;
- sbs = sizeof (a4);
- }
- else
- {
- /* invalid address */
- GNUNET_break_op (0);
- asc (asc_cls, NULL);
- return;
- }
- ppc = GNUNET_malloc (sizeof (struct PrettyPrinterContext));
- ppc->asc = asc;
- ppc->asc_cls = asc_cls;
- ppc->port = port;
- GNUNET_RESOLVER_hostname_get (sb, sbs, !numeric, timeout, &append_port, ppc);
-}
-
-
-/**
- * Our external IP address/port mapping has changed.
- *
- * @param cls closure, the 'struct LocalAddrList'
- * @param add_remove GNUNET_YES to mean the new public IP address, GNUNET_NO to mean
- * the previous (now invalid) one
- * @param addr either the previous or the new public IP address
- * @param addrlen actual lenght of the address
- */
-static void
-udp_nat_port_map_callback (void *cls, int add_remove,
- const struct sockaddr *addr, socklen_t addrlen)
-{
- struct Plugin *plugin = cls;
- struct IPv4UdpAddress u4;
- struct IPv6UdpAddress u6;
- void *arg;
- size_t args;
-
- /* convert 'addr' to our internal format */
- switch (addr->sa_family)
- {
- case AF_INET:
- GNUNET_assert (addrlen == sizeof (struct sockaddr_in));
- u4.ipv4_addr = ((struct sockaddr_in *) addr)->sin_addr.s_addr;
- u4.u4_port = ((struct sockaddr_in *) addr)->sin_port;
- arg = &u4;
- args = sizeof (u4);
- break;
- case AF_INET6:
- GNUNET_assert (addrlen == sizeof (struct sockaddr_in6));
- memcpy (&u6.ipv6_addr, &((struct sockaddr_in6 *) addr)->sin6_addr,
- sizeof (struct in6_addr));
- u6.u6_port = ((struct sockaddr_in6 *) addr)->sin6_port;
- arg = &u6;
- args = sizeof (u6);
- break;
- default:
- GNUNET_break (0);
- return;
- }
- /* modify our published address list */
- plugin->env->notify_address (plugin->env->cls, add_remove, arg, args);
-}
-
-
-static int
-iface_proc (void *cls, const char *name,
- int isDefault,
- const struct sockaddr * addr,
- const struct sockaddr * broadcast_addr,
- const struct sockaddr * netmask,
- socklen_t addrlen)
-{
- struct Plugin *plugin = cls;
-
- if (addr != NULL)
- {
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "address %s for interface %s %p\n ",
- GNUNET_a2s(addr,addrlen), name, addr);
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "broadcast address %s for interface %s %p\n ",
- GNUNET_a2s(broadcast_addr,addrlen), name, broadcast_addr);
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "netmask %s for interface %s %p\n ",
- GNUNET_a2s(netmask,addrlen), name, netmask);
-
- if (broadcast_addr != NULL)
- {
- struct BroadcastAddress * ba = GNUNET_malloc(sizeof (struct BroadcastAddress));
- ba->addr = GNUNET_malloc(addrlen);
- memcpy(ba->addr, broadcast_addr, addrlen);
- ba->addrlen = addrlen;
- GNUNET_CONTAINER_DLL_insert(plugin->head, plugin->tail, ba);
- }
- }
- return GNUNET_OK;
-}
-
-
-/**
- * The exported method. Makes the core api available via a global and
- * returns the udp transport API.
- *
- * @param cls our 'struct GNUNET_TRANSPORT_PluginEnvironment'
- * @return our 'struct GNUNET_TRANSPORT_PluginFunctions'
- */
-void *
-libgnunet_plugin_transport_udp_init (void *cls)
-{
- struct GNUNET_TRANSPORT_PluginEnvironment *env = cls;
- unsigned long long port;
- unsigned long long aport;
- unsigned long long bport;
- struct GNUNET_TRANSPORT_PluginFunctions *api;
- struct Plugin *plugin;
- int sockets_created;
- int broadcast;
- struct GNUNET_TIME_Relative interval;
- struct sockaddr_in serverAddrv4;
- struct sockaddr_in6 serverAddrv6;
- struct sockaddr *serverAddr;
- struct sockaddr *addrs[2];
- socklen_t addrlens[2];
- socklen_t addrlen;
- unsigned int tries;
- unsigned long long udp_max_bps;
-
- if (GNUNET_OK !=
- GNUNET_CONFIGURATION_get_value_number (env->cfg, "transport-udp", "PORT",
- &port))
- port = 2086;
-
- broadcast =
- GNUNET_CONFIGURATION_get_value_yesno (env->cfg, "transport-udp",
- "BROADCAST");
- if (broadcast == GNUNET_SYSERR)
- broadcast = GNUNET_NO;
-
- if (GNUNET_SYSERR ==
- GNUNET_CONFIGURATION_get_value_time (env->cfg, "transport-udp",
- "BROADCAST_INTERVAL", &interval))
- interval = GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 10);
-
- if (GNUNET_OK !=
- GNUNET_CONFIGURATION_get_value_number (env->cfg, "transport-udp",
- "BROADCAST_PORT", &bport))
- bport = 20086;
-
- if (GNUNET_OK !=
- GNUNET_CONFIGURATION_get_value_number (env->cfg, "transport-udp",
- "MAX_BPS", &udp_max_bps))
- udp_max_bps = 1024 * 1024 * 50; /* 50 MB/s == infinity for practical purposes */
- if (GNUNET_OK !=
- GNUNET_CONFIGURATION_get_value_number (env->cfg, "transport-udp",
- "ADVERTISED_PORT", &aport))
- aport = port;
- if (port > 65535)
- {
- LOG (GNUNET_ERROR_TYPE_WARNING,
- _("Given `%s' option is out of range: %llu > %u\n"), "PORT", port,
- 65535);
- return NULL;
- }
- memset (&serverAddrv6, 0, sizeof (serverAddrv6));
- memset (&serverAddrv4, 0, sizeof (serverAddrv4));
-
- plugin = GNUNET_malloc (sizeof (struct Plugin));
- GNUNET_BANDWIDTH_tracker_init (&plugin->tracker,
- GNUNET_BANDWIDTH_value_init ((uint32_t)
- udp_max_bps), 30);
- plugin->last_expected_delay = GNUNET_TIME_UNIT_SECONDS;
- plugin->port = port;
- plugin->aport = aport;
- plugin->broadcast_port = bport;
- plugin->broadcast_ipv4 = broadcast;
- plugin->env = env;
- plugin->broadcast_interval = interval;
- api = GNUNET_malloc (sizeof (struct GNUNET_TRANSPORT_PluginFunctions));
- api->cls = plugin;