/** * Try to send 'data' to the * IP 'dst_ipv4' at port 'dport' via UDP. * * @param dst_ipv4 target IP * @param dport target port * @param data data to send */ static void try_send_udp (uint32_t dst_ipv4, uint16_t dport, uint16_t data) { struct GNUNET_NETWORK_Handle *s; struct sockaddr_in sa; s = GNUNET_NETWORK_socket_create (AF_INET, SOCK_DGRAM, 0); if (NULL == s) { GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "socket"); return; } memset (&sa, 0, sizeof (sa)); sa.sin_family = AF_INET; #if HAVE_SOCKADDR_IN_SIN_LEN sa.sin_len = sizeof (sa); #endif sa.sin_addr.s_addr = dst_ipv4; sa.sin_port = htons (dport); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending UDP packet to `%s'\n", GNUNET_a2s ((struct sockaddr *) &sa, sizeof (sa))); if (-1 == GNUNET_NETWORK_socket_sendto (s, &data, sizeof (data), (const struct sockaddr *) &sa, sizeof (sa))) GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "sendto"); GNUNET_NETWORK_socket_close (s); }
static void udp_ipv4_broadcast_send (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct Plugin *plugin = cls; int sent; uint16_t msg_size; char buf[65536] GNUNET_ALIGN; struct BroadcastAddress *baddr; plugin->send_ipv4_broadcast_task = GNUNET_SCHEDULER_NO_TASK; msg_size = prepare_beacon(plugin, (struct UDP_Beacon_Message *) &buf); sent = 0; baddr = plugin->ipv4_broadcast_head; /* just IPv4 */ while ((msg_size > 0) && (baddr != NULL) && (baddr->addrlen == sizeof (struct sockaddr_in))) { struct sockaddr_in *addr = (struct sockaddr_in *) baddr->addr; addr->sin_port = htons (plugin->port); sent = GNUNET_NETWORK_socket_sendto (plugin->sockv4, &buf, msg_size, (const struct sockaddr *) addr, baddr->addrlen); if (sent == GNUNET_SYSERR) { if ((ENETUNREACH == errno) || (ENETDOWN == errno)) { /* "Network unreachable" or "Network down" * * This indicates that we just do not have network connectivity */ GNUNET_log (GNUNET_ERROR_TYPE_BULK | GNUNET_ERROR_TYPE_WARNING, "Network connectivity is down, cannot send beacon!\n"); } else GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "sendto"); } else { LOG (GNUNET_ERROR_TYPE_DEBUG, "Sent HELLO beacon broadcast with %i bytes to address %s\n", sent, GNUNET_a2s (baddr->addr, baddr->addrlen)); } baddr = baddr->next; } plugin->send_ipv4_broadcast_task = GNUNET_SCHEDULER_add_delayed (plugin->broadcast_interval, &udp_ipv4_broadcast_send, plugin); }
static void udp_ipv6_broadcast_send (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct Plugin *plugin = cls; int sent; uint16_t msg_size; char buf[65536] GNUNET_ALIGN; plugin->send_ipv6_broadcast_task = GNUNET_SCHEDULER_NO_TASK; msg_size = prepare_beacon(plugin, (struct UDP_Beacon_Message *) &buf); sent = 0; sent = GNUNET_NETWORK_socket_sendto (plugin->sockv6, &buf, msg_size, (const struct sockaddr *) &plugin->ipv6_multicast_address, sizeof (struct sockaddr_in6)); if (sent == GNUNET_SYSERR) { if ((ENETUNREACH == errno) || (ENETDOWN == errno)) { /* "Network unreachable" or "Network down" * * This indicates that this system is IPv6 enabled, but does not * have a valid global IPv6 address assigned */ GNUNET_log (GNUNET_ERROR_TYPE_BULK | GNUNET_ERROR_TYPE_WARNING, "Network connectivity is down, cannot send beacon!\n"); } else GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "sendto"); } else { LOG (GNUNET_ERROR_TYPE_DEBUG, "Sending IPv6 HELLO beacon broadcast with %i bytes to address %s\n", sent, GNUNET_a2s ((const struct sockaddr *) &plugin->ipv6_multicast_address, sizeof (struct sockaddr_in6))); } plugin->send_ipv6_broadcast_task = GNUNET_SCHEDULER_add_delayed (plugin->broadcast_interval, &udp_ipv6_broadcast_send, plugin); }
/** * Perform DNS resolution. * * @param ctx stub resolver to use * @param sa the socket address * @param sa_len the socket length * @param request DNS request to transmit * @param request_len number of bytes in msg * @param rc function to call with result * @param rc_cls closure for 'rc' * @return socket used for the request, NULL on error */ struct GNUNET_DNSSTUB_RequestSocket * GNUNET_DNSSTUB_resolve (struct GNUNET_DNSSTUB_Context *ctx, const struct sockaddr *sa, socklen_t sa_len, const void *request, size_t request_len, GNUNET_DNSSTUB_ResultCallback rc, void *rc_cls) { struct GNUNET_DNSSTUB_RequestSocket *rs; struct GNUNET_NETWORK_Handle *ret; int af; af = sa->sa_family; if (NULL == (rs = get_request_socket (ctx, af))) return NULL; if (NULL != rs->dnsout4) ret = rs->dnsout4; else ret = rs->dnsout6; GNUNET_assert (NULL != ret); memcpy (&rs->addr, sa, sa_len); rs->addrlen = sa_len; rs->rc = rc; rs->rc_cls = rc_cls; if (GNUNET_SYSERR == GNUNET_NETWORK_socket_sendto (ret, request, request_len, sa, sa_len)) GNUNET_log (GNUNET_ERROR_TYPE_WARNING, _("Failed to send DNS request to %s\n"), GNUNET_a2s (sa, sa_len)); else GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, _("Sent DNS request to %s\n"), GNUNET_a2s (sa, sa_len)); return rs; }
static void udp_ipv6_broadcast_send (void *cls) { struct BroadcastAddress *baddr = cls; struct Plugin *plugin = baddr->plugin; ssize_t sent; uint16_t msg_size; char buf[65536] GNUNET_ALIGN; const struct sockaddr_in6 *s6 = (const struct sockaddr_in6 *) baddr->addr; 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 the specified interface as we're not (necessarily) using a link-local multicast group and the kernel suggests that the scope ID is only respected for link-local addresses; however, if the scope ID is ignored, the kernel should just multicast on ALL interfaces, which is merely slightly less efficient; in that case, we might want to revert to only doing this once, and not per interface (hard to test...) */ plugin->ipv6_multicast_address.sin6_scope_id = s6->sin6_scope_id; sent = GNUNET_NETWORK_socket_sendto (plugin->sockv6, &buf, msg_size, (const struct sockaddr *) &plugin->ipv6_multicast_address, sizeof (struct sockaddr_in6)); plugin->ipv6_multicast_address.sin6_scope_id = 0; if (sent == GNUNET_SYSERR) { if ((ENETUNREACH == errno) || (ENETDOWN == errno)) { /* "Network unreachable" or "Network down" * * This indicates that this system is IPv6 enabled, but does not * have a valid global IPv6 address assigned */ GNUNET_log (GNUNET_ERROR_TYPE_BULK | GNUNET_ERROR_TYPE_WARNING, "Network connectivity is down, cannot send beacon!\n"); } else GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "sendto"); } else { LOG (GNUNET_ERROR_TYPE_DEBUG, "Sending IPv6 HELLO beacon broadcast with %d bytes to address %s\n", (int) sent, GNUNET_a2s ((const struct sockaddr *) &plugin->ipv6_multicast_address, sizeof (struct sockaddr_in6))); } #if LINUX /* * Cryogenic */ if (NULL != baddr->cryogenic_fd) { 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) { GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "ioctl"); baddr->broadcast_task = GNUNET_SCHEDULER_add_delayed (plugin->broadcast_interval, &udp_ipv6_broadcast_send, baddr); } else GNUNET_SCHEDULER_add_write_file (GNUNET_TIME_UNIT_FOREVER_REL, baddr->cryogenic_fd, &udp_ipv6_broadcast_send, baddr); } else #endif baddr->broadcast_task = GNUNET_SCHEDULER_add_delayed (plugin->broadcast_interval, &udp_ipv6_broadcast_send, baddr); }
static void udp_ipv4_broadcast_send (void *cls) { struct BroadcastAddress *baddr = cls; struct Plugin *plugin = baddr->plugin; int sent; uint16_t msg_size; char buf[65536] GNUNET_ALIGN; baddr->broadcast_task = NULL; msg_size = prepare_beacon(plugin, (struct UDP_Beacon_Message *) &buf); if (0 != msg_size) { struct sockaddr_in *addr = (struct sockaddr_in *) baddr->addr; addr->sin_port = htons (plugin->port); sent = GNUNET_NETWORK_socket_sendto (plugin->sockv4, &buf, msg_size, (const struct sockaddr *) addr, baddr->addrlen); if (sent == GNUNET_SYSERR) { if ((ENETUNREACH == errno) || (ENETDOWN == errno)) { /* "Network unreachable" or "Network down" * * This indicates that we just do not have network connectivity */ GNUNET_log (GNUNET_ERROR_TYPE_BULK | GNUNET_ERROR_TYPE_WARNING, "Network connectivity is down, cannot send beacon!\n"); } else GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "sendto"); } else { LOG (GNUNET_ERROR_TYPE_DEBUG, "Sent HELLO beacon broadcast with %i bytes to address %s\n", sent, GNUNET_a2s (baddr->addr, baddr->addrlen)); } } #if LINUX /* * Cryogenic */ if (NULL != baddr->cryogenic_fd) { 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) { GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "ioctl"); baddr->broadcast_task = GNUNET_SCHEDULER_add_delayed (plugin->broadcast_interval, &udp_ipv4_broadcast_send, baddr); } else GNUNET_SCHEDULER_add_write_file (GNUNET_TIME_UNIT_FOREVER_REL, 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); }
/** * Perform DNS resolution using our default IP from init. * * @param ctx stub resolver to use * @param request DNS request to transmit * @param request_len number of bytes in msg * @param rc function to call with result * @param rc_cls closure for 'rc' * @return socket used for the request, NULL on error */ struct GNUNET_DNSSTUB_RequestSocket * GNUNET_DNSSTUB_resolve2 (struct GNUNET_DNSSTUB_Context *ctx, const void *request, size_t request_len, GNUNET_DNSSTUB_ResultCallback rc, void *rc_cls) { int af; struct sockaddr_in v4; struct sockaddr_in6 v6; struct sockaddr *sa; socklen_t salen; struct GNUNET_NETWORK_Handle *dnsout; struct GNUNET_DNSSTUB_RequestSocket *rs; memset (&v4, 0, sizeof (v4)); memset (&v6, 0, sizeof (v6)); if (1 == inet_pton (AF_INET, ctx->dns_exit, &v4.sin_addr)) { salen = sizeof (v4); v4.sin_family = AF_INET; v4.sin_port = htons (53); #if HAVE_SOCKADDR_IN_SIN_LEN v4.sin_len = (u_char) salen; #endif sa = (struct sockaddr *) &v4; af = AF_INET; } else if (1 == inet_pton (AF_INET6, ctx->dns_exit, &v6.sin6_addr)) { salen = sizeof (v6); v6.sin6_family = AF_INET6; v6.sin6_port = htons (53); #if HAVE_SOCKADDR_IN_SIN_LEN v6.sin6_len = (u_char) salen; #endif sa = (struct sockaddr *) &v6; af = AF_INET6; } else { GNUNET_break (0); return NULL; } if (NULL == (rs = get_request_socket (ctx, af))) return NULL; if (NULL != rs->dnsout4) dnsout = rs->dnsout4; else dnsout = rs->dnsout6; if (NULL == dnsout) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Configured DNS exit `%s' is not working / valid.\n"), ctx->dns_exit); return NULL; } memcpy (&rs->addr, sa, salen); rs->addrlen = salen; rs->rc = rc; rs->rc_cls = rc_cls; if (GNUNET_SYSERR == GNUNET_NETWORK_socket_sendto (dnsout, request, request_len, sa, salen)) GNUNET_log (GNUNET_ERROR_TYPE_WARNING, _("Failed to send DNS request to %s\n"), GNUNET_a2s (sa, salen)); rs->timeout = GNUNET_TIME_relative_to_absolute (REQUEST_TIMEOUT); return rs; }