*
* @param data the data to encode
* @param len the length of the input
- * @param output where to write the output (*output should be NULL,
+ * @param[out] output where to write the output (*output should be NULL,
* is allocated)
* @return the size of the output
*/
size_t
-GNUNET_STRINGS_base64_decode (const char *data, size_t len, char **output);
+GNUNET_STRINGS_base64_decode (const char *data,
+ size_t len,
+ char **output);
/**
* Parse a path that might be an URI.
*
* @param path path to parse. Must be NULL-terminated.
- * @param scheme_part a pointer to 'char *' where a pointer to a string that
+ * @param[out] scheme_part pointer to a string that
* represents the URI scheme will be stored. Can be NULL. The string is
* allocated by the function, and should be freed by GNUNET_free() when
* it is no longer needed.
* @param path_part a pointer to 'const char *' where a pointer to the path
* part of the URI will be stored. Can be NULL. Points to the same block
- * of memory as 'path', and thus must not be freed. Might point to '\0',
+ * of memory as @a path, and thus must not be freed. Might point to '\0',
* if path part is zero-length.
* @return #GNUNET_YES if it's an URI, #GNUNET_NO otherwise. If 'path' is not
* an URI, '* scheme_part' and '*path_part' will remain unchanged
struct sockaddr_in *r_buf);
+/**
+ * Parse an address given as a string into a
+ * `struct sockaddr`.
+ *
+ * @param addr the address
+ * @param[out] af set to the parsed address family (i.e. AF_INET)
+ * @param[out] sa set to the parsed address
+ * @return 0 on error, otherwise number of bytes in @a sa
+ */
+size_t
+GNUNET_STRINGS_parse_socket_addr (const char *addr,
+ uint8_t *af,
+ struct sockaddr **sa);
+
+
/**
* Tries to convert @a addr string to an IP (v4 or v6) address.
* Will automatically decide whether to treat 'addr' as v4 or v6 address.
static struct GNUNET_NAT_AutoHandle *ah;
/**
- * Port we use.
+ * Port we advertise.
*/
-static unsigned int port;
+static unsigned int adv_port;
/**
* Flag set to 1 if we use IPPROTO_UDP.
}
+/**
+ * Function called to report success or failure for
+ * NAT configuration test.
+ *
+ * @param cls closure
+ * @param result #GNUNET_NAT_ERROR_SUCCESS on success, otherwise the specific error code
+ */
+static void
+test_report_cb (void *cls,
+ enum GNUNET_NAT_StatusCode result)
+{
+ nt = NULL;
+ PRINTF ("NAT test result: %s\n",
+ GNUNET_NAT_status2string (result));
+ test_finished ();
+}
+
+
+/**
+ * Signature of the callback passed to #GNUNET_NAT_register() for
+ * a function to call whenever our set of 'valid' addresses changes.
+ *
+ * @param cls closure
+ * @param add_remove #GNUNET_YES to add a new public IP address,
+ * #GNUNET_NO to remove a previous (now invalid) one
+ * @param ac address class the address belongs to
+ * @param addr either the previous or the new public IP address
+ * @param addrlen actual length of the @a addr
+ */
+static void
+address_cb (void *cls,
+ int add_remove,
+ enum GNUNET_NAT_AddressClass ac,
+ const struct sockaddr *addr,
+ socklen_t addrlen)
+{
+ // FIXME: print!
+}
+
+
+/**
+ * Signature of the callback passed to #GNUNET_NAT_register().
+ * for a function to call whenever someone asks us to do connection
+ * reversal.
+ *
+ * @param cls closure
+ * @param local_addr address where we received the request
+ * @param local_addrlen actual length of the @a local_addr
+ * @param remote_addr public IP address of the other peer
+ * @param remote_addrlen actual length of the @a remote_addr
+ */
+static void
+reversal_cb (void *cls,
+ const struct sockaddr *local_addr,
+ socklen_t local_addrlen,
+ const struct sockaddr *remote_addr,
+ socklen_t remote_addrlen)
+{
+ // FIXME: print!
+}
+
+
/**
* Task run on shutdown.
*
const char *cfgfile,
const struct GNUNET_CONFIGURATION_Handle *c)
{
+ uint8_t af;
+ struct sockaddr_in bind_sa;
+ struct sockaddr_in extern_sa;
+ struct sockaddr *local_sa;
+ struct sockaddr *remote_sa;
+ size_t local_len;
+ size_t remote_len;
+
if (use_tcp && use_udp)
{
GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
global_ret = 1;
return;
}
+ if (NULL != bind_addr)
+ {
+ if (GNUNET_OK !=
+ GNUNET_STRINGS_to_address_ipv4 (bind_addr,
+ strlen (bind_addr),
+ &bind_sa))
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
+ "Invalid socket address `%s'\n",
+ bind_addr);
+ global_ret = 1;
+ return;
+ }
+ }
+ if (NULL != extern_addr)
+ {
+ if (GNUNET_OK !=
+ GNUNET_STRINGS_to_address_ipv4 (extern_addr,
+ strlen (extern_addr),
+ &extern_sa))
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
+ "Invalid socket address `%s'\n",
+ extern_addr);
+ global_ret = 1;
+ return;
+ }
+ }
+ if (NULL != local_addr)
+ {
+ local_len = GNUNET_STRINGS_parse_socket_addr (local_addr,
+ &af,
+ &local_sa);
+ if (0 == local_len)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
+ "Invalid socket address `%s'\n",
+ local_addr);
+ global_ret = 1;
+ return;
+ }
+ }
+ if (NULL != remote_addr)
+ {
+ remote_len = GNUNET_STRINGS_parse_socket_addr (remote_addr,
+ &af,
+ &remote_sa);
+ if (0 == remote_len)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
+ "Invalid socket address `%s'\n",
+ remote_addr);
+ global_ret = 1;
+ return;
+ }
+ }
+
+ if (NULL != bind_addr)
+ {
+ if (NULL == extern_addr)
+ extern_sa = bind_sa;
+ nt = GNUNET_NAT_test_start (c,
+ proto,
+ bind_sa.sin_addr,
+ ntohs (bind_sa.sin_port),
+ extern_sa.sin_addr,
+ ntohs (extern_sa.sin_port),
+ &test_report_cb,
+ NULL);
+ }
+
+ if (NULL != local_addr)
+ {
+ nh = GNUNET_NAT_register (c,
+ proto,
+ (uint16_t) adv_port,
+ 1,
+ (const struct sockaddr **) &local_sa,
+ &local_len,
+ &address_cb,
+ (listen_reversal) ? &reversal_cb : NULL,
+ NULL);
+ }
+
+ if (NULL != remote_addr)
+ {
+ int ret;
+
+ if ( (NULL == nh) ||
+ (sizeof (struct sockaddr_in) != local_len) )
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
+ "Require IPv4 local address to initiate connection reversal\n");
+ global_ret = 1;
+ GNUNET_SCHEDULER_shutdown ();
+ return;
+ }
+ if (sizeof (struct sockaddr_in) != remote_len)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
+ "Require IPv4 reversal target address\n");
+ global_ret = 1;
+ GNUNET_SCHEDULER_shutdown ();
+ return;
+ }
+ ret = GNUNET_NAT_request_reversal (nh,
+ (const struct sockaddr_in *) &local_sa,
+ (const struct sockaddr_in *) &remote_sa);
+ switch (ret)
+ {
+ case GNUNET_SYSERR:
+ GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
+ "Connection reversal internal error\n");
+ break;
+ case GNUNET_NO:
+ GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
+ "Connection reversal unavailable\n");
+ break;
+ case GNUNET_OK:
+ /* operation in progress */
+ break;
+ }
+ }
+
if (do_auto)
{
ah = GNUNET_NAT_autoconfig_start (c,
GNUNET_NO, &GNUNET_GETOPT_set_one, &do_auto },
{'b', "bind", "ADDRESS",
gettext_noop ("which IP and port are we bound to"),
- GNUNET_YES, &GNUNET_GETOPT_set_string, &bind_addr},
+ GNUNET_YES, &GNUNET_GETOPT_set_string, &bind_addr },
{'e', "external", "ADDRESS",
gettext_noop ("which external IP and port should be used to test"),
- GNUNET_YES, &GNUNET_GETOPT_set_string, &extern_addr},
+ GNUNET_YES, &GNUNET_GETOPT_set_string, &extern_addr },
{'l', "local", "ADDRESS",
gettext_noop ("which IP and port are we locally using to listen to for connection reversals"),
- GNUNET_YES, &GNUNET_GETOPT_set_string, &local_addr},
+ GNUNET_YES, &GNUNET_GETOPT_set_string, &local_addr },
{'r', "remote", "ADDRESS",
gettext_noop ("which remote IP and port should be asked for connection reversal"),
- GNUNET_YES, &GNUNET_GETOPT_set_string, &remote_addr},
+ GNUNET_YES, &GNUNET_GETOPT_set_string, &remote_addr },
{'L', "listen", NULL,
gettext_noop ("listen for connection reversal requests"),
GNUNET_NO, &GNUNET_GETOPT_set_one, &listen_reversal },
{'p', "port", NULL,
- gettext_noop ("port to use"),
- GNUNET_YES, &GNUNET_GETOPT_set_uint, &port},
+ gettext_noop ("port to use to advertise"),
+ GNUNET_YES, &GNUNET_GETOPT_set_uint, &adv_port },
{'s', "stun", NULL,
gettext_noop ("enable STUN processing"),
GNUNET_NO, &GNUNET_GETOPT_set_one, &do_stun },
/**
- * Tries to convert 'zt_addr' string to an IPv6 address.
+ * Tries to convert @a zt_addr string to an IPv6 address.
* The string is expected to have the format "[ABCD::01]:80".
*
* @param zt_addr 0-terminated string. May be mangled by the function.
* the contents of @a r_buf are undefined.
*/
int
-GNUNET_STRINGS_to_address_ipv4 (const char *zt_addr, uint16_t addrlen,
+GNUNET_STRINGS_to_address_ipv4 (const char *zt_addr,
+ uint16_t addrlen,
struct sockaddr_in *r_buf)
{
unsigned int temps[4];
if (addrlen < 9)
return GNUNET_SYSERR;
- cnt = SSCANF (zt_addr, "%u.%u.%u.%u:%u", &temps[0], &temps[1], &temps[2], &temps[3], &port);
+ cnt = SSCANF (zt_addr,
+ "%u.%u.%u.%u:%u",
+ &temps[0],
+ &temps[1],
+ &temps[2],
+ &temps[3],
+ &port);
if (5 != cnt)
return GNUNET_SYSERR;
for (cnt = 0; cnt < 4; cnt++)
* @param addrlen number of bytes in @a addr (if addr is 0-terminated,
* 0-terminator should not be counted towards addrlen).
* @param r_buf a buffer to fill.
- * @return #GNUNET_OK if conversion succeded. GNUNET_SYSERR otherwise, in which
- * case the contents of r_buf are undefined.
+ * @return #GNUNET_OK if conversion succeded. #GNUNET_SYSERR otherwise, in which
+ * case the contents of @a r_buf are undefined.
*/
int
GNUNET_STRINGS_to_address_ip (const char *addr,
}
+/**
+ * Parse an address given as a string into a
+ * `struct sockaddr`.
+ *
+ * @param addr the address
+ * @param[out] af set to the parsed address family (i.e. AF_INET)
+ * @param[out] sa set to the parsed address
+ * @return 0 on error, otherwise number of bytes in @a sa
+ */
+size_t
+GNUNET_STRINGS_parse_socket_addr (const char *addr,
+ uint8_t *af,
+ struct sockaddr **sa)
+{
+ char *cp = GNUNET_strdup (addr);
+
+ *af = AF_UNSPEC;
+ if ('[' == *addr)
+ {
+ /* IPv6 */
+ *sa = GNUNET_malloc (sizeof (struct sockaddr_in6));
+ if (GNUNET_OK !=
+ GNUNET_STRINGS_to_address_ipv6 (cp,
+ strlen (cp),
+ (struct sockaddr_in6 *) *sa))
+ {
+ GNUNET_free (*sa);
+ *sa = NULL;
+ GNUNET_free (cp);
+ return 0;
+ }
+ *af = AF_INET6;
+ GNUNET_free (cp);
+ return sizeof (struct sockaddr_in6);
+ }
+ else
+ {
+ /* IPv4 */
+ *sa = GNUNET_malloc (sizeof (struct sockaddr_in));
+ if (GNUNET_OK !=
+ GNUNET_STRINGS_to_address_ipv4 (cp,
+ strlen (cp),
+ (struct sockaddr_in *) *sa))
+ {
+ GNUNET_free (*sa);
+ *sa = NULL;
+ GNUNET_free (cp);
+ return 0;
+ }
+ *af = AF_INET;
+ GNUNET_free (cp);
+ return sizeof (struct sockaddr_in);
+ }
+}
+
+
/**
* Makes a copy of argv that consists of a single memory chunk that can be
* freed with a single call to GNUNET_free();
* @return #GNUNET_OK on success, #GNUNET_SYSERR on failure
*/
int
-GNUNET_STRINGS_get_utf8_args (int argc, char *const *argv, int *u8argc, char *const **u8argv)
+GNUNET_STRINGS_get_utf8_args (int argc,
+ char *const *argv,
+ int *u8argc,
+ char *const **u8argv)
{
#if WINDOWS
wchar_t *wcmd;