/** * Create and initialize a listen socket for the server. * * @return NULL on error, otherwise the listen socket */ static struct GNUNET_NETWORK_Handle * open_listen_socket () { const static int on = 1; struct sockaddr_in sa; struct GNUNET_NETWORK_Handle *desc; memset (&sa, 0, sizeof (sa)); #if HAVE_SOCKADDR_IN_SIN_LEN sa.sin_len = sizeof (sa); #endif sa.sin_family = AF_INET; sa.sin_port = htons (PORT); desc = GNUNET_NETWORK_socket_create (AF_INET, SOCK_STREAM, 0); GNUNET_assert (desc != 0); if (GNUNET_NETWORK_socket_setsockopt (desc, SOL_SOCKET, SO_REUSEADDR, &on, sizeof (on)) != GNUNET_OK) GNUNET_log (GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, "setsockopt"); if (GNUNET_OK != GNUNET_NETWORK_socket_bind (desc, (const struct sockaddr *) &sa, sizeof (sa))) { GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, "bind"); GNUNET_assert (0); } GNUNET_NETWORK_socket_listen (desc, 5); return desc; }
/** * Creating a listening socket for each of the service's addresses and * wait for the first incoming connection to it * * @param sa address associated with the service * @param addr_len length of sa * @param sl service entry for the service in question */ static void create_listen_socket (struct sockaddr *sa, socklen_t addr_len, struct ServiceList *sl) { static int on = 1; struct GNUNET_NETWORK_Handle *sock; struct ServiceListeningInfo *sli; switch (sa->sa_family) { case AF_INET: sock = GNUNET_NETWORK_socket_create (PF_INET, SOCK_STREAM, 0); break; case AF_INET6: sock = GNUNET_NETWORK_socket_create (PF_INET6, SOCK_STREAM, 0); break; case AF_UNIX: if (strcmp (GNUNET_a2s (sa, addr_len), "@") == 0) /* Do not bind to blank UNIX path! */ return; sock = GNUNET_NETWORK_socket_create (PF_UNIX, SOCK_STREAM, 0); break; default: GNUNET_break (0); sock = NULL; errno = EAFNOSUPPORT; break; } if (NULL == sock) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Unable to create socket for service `%s': %s\n"), sl->name, STRERROR (errno)); GNUNET_free (sa); return; } if (GNUNET_NETWORK_socket_setsockopt (sock, SOL_SOCKET, SO_REUSEADDR, &on, sizeof (on)) != GNUNET_OK) GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, "setsockopt"); #ifdef IPV6_V6ONLY if ((sa->sa_family == AF_INET6) && (GNUNET_NETWORK_socket_setsockopt (sock, IPPROTO_IPV6, IPV6_V6ONLY, &on, sizeof (on)) != GNUNET_OK)) GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, "setsockopt"); #endif if (GNUNET_NETWORK_socket_bind (sock, (const struct sockaddr *) sa, addr_len) != GNUNET_OK) { GNUNET_log (GNUNET_ERROR_TYPE_WARNING, _ ("Unable to bind listening socket for service `%s' to address `%s': %s\n"), sl->name, GNUNET_a2s (sa, addr_len), STRERROR (errno)); GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (sock)); GNUNET_free (sa); return; } if (GNUNET_NETWORK_socket_listen (sock, 5) != GNUNET_OK) { GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "listen"); GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (sock)); GNUNET_free (sa); return; } GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("ARM now monitors connections to service `%s' at `%s'\n"), sl->name, GNUNET_a2s (sa, addr_len)); sli = GNUNET_malloc (sizeof (struct ServiceListeningInfo)); sli->service_addr = sa; sli->service_addr_len = addr_len; sli->listen_socket = sock; sli->sl = sl; sli->accept_task = GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL, sock, &accept_connection, sli); GNUNET_CONTAINER_DLL_insert (sl->listen_head, sl->listen_tail, sli); }
/** * Start testing if NAT traversal works using the * given configuration (IPv4-only). * * ALL failures are reported directly to the report callback * * @param cfg configuration for the NAT traversal * @param is_tcp #GNUNET_YES to test TCP, #GNUNET_NO to test UDP * @param bnd_port port to bind to, 0 for connection reversal * @param adv_port externally advertised port to use * @param timeout delay after which the test should be aborted * @param report function to call with the result of the test * @param report_cls closure for @a report * @return handle to cancel NAT test or NULL. The error is always indicated via the report callback */ struct GNUNET_NAT_Test * GNUNET_NAT_test_start (const struct GNUNET_CONFIGURATION_Handle *cfg, int is_tcp, uint16_t bnd_port, uint16_t adv_port, struct GNUNET_TIME_Relative timeout, GNUNET_NAT_TestCallback report, void *report_cls) { struct GNUNET_NAT_Test *nh; struct sockaddr_in sa; const struct sockaddr *addrs[] = { (const struct sockaddr *) &sa }; const socklen_t addrlens[] = { sizeof (sa) }; memset (&sa, 0, sizeof (sa)); sa.sin_family = AF_INET; sa.sin_port = htons (bnd_port); #if HAVE_SOCKADDR_IN_SIN_LEN sa.sin_len = sizeof (sa); #endif nh = GNUNET_new (struct GNUNET_NAT_Test); nh->cfg = cfg; nh->is_tcp = is_tcp; nh->data = bnd_port; nh->adv_port = adv_port; nh->report = report; nh->report_cls = report_cls; nh->status = GNUNET_NAT_ERROR_SUCCESS; if (0 == bnd_port) { nh->nat = GNUNET_NAT_register (cfg, is_tcp, 0, 0, NULL, NULL, &addr_cb, &reversal_cb, nh, NULL); } else { nh->lsock = GNUNET_NETWORK_socket_create (AF_INET, (is_tcp == GNUNET_YES) ? SOCK_STREAM : SOCK_DGRAM, 0); if ((nh->lsock == NULL) || (GNUNET_OK != GNUNET_NETWORK_socket_bind (nh->lsock, (const struct sockaddr *) &sa, sizeof (sa)))) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Failed to create listen socket bound to `%s' for NAT test: %s\n"), GNUNET_a2s ((const struct sockaddr *) &sa, sizeof (sa)), STRERROR (errno)); if (NULL != nh->lsock) { GNUNET_NETWORK_socket_close (nh->lsock); nh->lsock = NULL; } nh->status = GNUNET_NAT_ERROR_INTERNAL_NETWORK_ERROR; nh->ttask = GNUNET_SCHEDULER_add_now (&do_timeout, nh); return nh; } if (GNUNET_YES == is_tcp) { GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_listen (nh->lsock, 5)); nh->ltask = GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL, nh->lsock, &do_accept, nh); } else { nh->ltask = GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL, nh->lsock, &do_udp_read, nh); } LOG (GNUNET_ERROR_TYPE_INFO, "NAT test listens on port %u (%s)\n", bnd_port, (GNUNET_YES == is_tcp) ? "tcp" : "udp"); nh->nat = GNUNET_NAT_register (cfg, is_tcp, adv_port, 1, addrs, addrlens, &addr_cb, NULL, nh, NULL); if (NULL == nh->nat) { LOG (GNUNET_ERROR_TYPE_INFO, _("NAT test failed to start NAT library\n")); if (NULL != nh->ltask) { GNUNET_SCHEDULER_cancel (nh->ltask); nh->ltask = NULL; } if (NULL != nh->lsock) { GNUNET_NETWORK_socket_close (nh->lsock); nh->lsock = NULL; } nh->status = GNUNET_NAT_ERROR_NAT_REGISTER_FAILED; nh->ttask = GNUNET_SCHEDULER_add_now (&do_timeout, nh); return nh; } } nh->ttask = GNUNET_SCHEDULER_add_delayed (timeout, &do_timeout, nh); return nh; }