/** * @brief Convert string representation of peer id to peer id. * * Counterpart to #GNUNET_i2s_full. * * @param string_repr The string representation of the peer id * * @return The peer id */ static const struct GNUNET_PeerIdentity * s2i_full (const char *string_repr) { struct GNUNET_PeerIdentity *peer; size_t len; int ret; peer = GNUNET_new (struct GNUNET_PeerIdentity); len = strlen (string_repr); if (52 > len) { LOG (GNUNET_ERROR_TYPE_WARNING, "Not able to convert string representation of PeerID to PeerID\n" "Sting representation: %s (len %u) - too short\n", string_repr, len); GNUNET_break (0); } else if (52 < len) { len = 52; } ret = GNUNET_CRYPTO_eddsa_public_key_from_string (string_repr, len, &peer->public_key); if (GNUNET_OK != ret) { LOG (GNUNET_ERROR_TYPE_WARNING, "Not able to convert string representation of PeerID to PeerID\n" "Sting representation: %s\n", string_repr); GNUNET_break (0); } return peer; }
/** * Call MESH's monitor API, get info of one connection. * * @param cls Closure (unused). * @param tc TaskContext */ static void create_channel (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct GNUNET_PeerIdentity pid; enum GNUNET_MESH_ChannelOption opt; GNUNET_assert (NULL == ch); if (GNUNET_OK != GNUNET_CRYPTO_eddsa_public_key_from_string (target_id, strlen (target_id), &pid.public_key)) { FPRINTF (stderr, _("Invalid target `%s'\n"), target_id); GNUNET_SCHEDULER_shutdown (); return; } GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Connecting to `%s'\n", target_id); opt = GNUNET_MESH_OPTION_DEFAULT | GNUNET_MESH_OPTION_RELIABLE; ch = GNUNET_MESH_channel_create (mh, NULL, &pid, target_port, opt); if (GNUNET_NO == echo) listen_stdio (); else GNUNET_SCHEDULER_add_now (send_echo, NULL); }
/** * Convert human-readable version of a 'value' of a record to the binary * representation. * * @param cls closure, unused * @param type type of the record * @param s human-readable string * @param data set to value in binary encoding (will be allocated) * @param data_size set to number of bytes in @a data * @return #GNUNET_OK on success */ static int conversation_string_to_value (void *cls, uint32_t type, const char *s, void **data, size_t *data_size) { if (NULL == s) { GNUNET_break (0); return GNUNET_SYSERR; } switch (type) { case GNUNET_GNSRECORD_TYPE_PHONE: { struct GNUNET_CONVERSATION_PhoneRecord *pr; char line_port[103]; const char *dash; struct GNUNET_PeerIdentity peer; if ( (NULL == (dash = strchr (s, '-'))) || (1 != sscanf (s, "%103s-", line_port)) || (GNUNET_OK != GNUNET_CRYPTO_eddsa_public_key_from_string (dash + 1, strlen (dash + 1), &peer.public_key)) ) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Unable to parse PHONE record `%s'\n"), s); return GNUNET_SYSERR; } pr = GNUNET_new (struct GNUNET_CONVERSATION_PhoneRecord); pr->version = htonl (1); pr->reserved = htonl (0); if (GNUNET_OK != GNUNET_STRINGS_string_to_data (line_port, strlen (line_port), &pr->line_port, sizeof (struct GNUNET_HashCode))) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Unable to parse PHONE record `%s'\n"), s); GNUNET_free (pr); return GNUNET_SYSERR; } pr->peer = peer; *data = pr; *data_size = sizeof (struct GNUNET_CONVERSATION_PhoneRecord); return GNUNET_OK; } default: return GNUNET_SYSERR; } }
/** * Call MESH's monitor API, get info of one tunnel. * * @param cls Closure (unused). * @param tc TaskContext */ static void show_tunnel (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct GNUNET_PeerIdentity pid; if (GNUNET_OK != GNUNET_CRYPTO_eddsa_public_key_from_string (tunnel_id, strlen (tunnel_id), &pid.public_key)) { fprintf (stderr, _("Invalid tunnel owner `%s'\n"), tunnel_id); GNUNET_SCHEDULER_shutdown(); return; } GNUNET_MESH_get_tunnel (mh, &pid, tunnel_callback, NULL); }
/** * Set an option of type 'struct GNUNET_PeerIdentity *' from the command line. * A pointer to this function should be passed as part of the * 'struct GNUNET_GETOPT_CommandLineOption' array to initialize options * of this type. It should be followed by a pointer to a value of * type 'struct GNUNET_PeerIdentity *', which will be allocated with the requested string. * * @param ctx command line processing context * @param scls additional closure (will point to the 'char *', * which will be allocated) * @param option name of the option * @param value actual value of the option (a PeerID) * @return #GNUNET_OK */ static int GNUNET_GETOPT_set_peerid (struct GNUNET_GETOPT_CommandLineProcessorContext *ctx, void *scls, const char *option, const char *value) { struct GNUNET_PeerIdentity **val = (struct GNUNET_PeerIdentity **) scls; GNUNET_assert (NULL != value); GNUNET_free_non_null (*val); /* Not quite sure whether that is a sane way */ *val = GNUNET_new (struct GNUNET_PeerIdentity); if (GNUNET_OK != GNUNET_CRYPTO_eddsa_public_key_from_string (value, strlen (value), &((*val)->public_key))) { FPRINTF (stderr, "Invalid peer ID %s\n", value); return GNUNET_SYSERR; } return GNUNET_OK; }
/** * Convert human-readable version of a 'value' of a record to the binary * representation. * * @param cls closure, unused * @param type type of the record * @param s human-readable string * @param data set to value in binary encoding (will be allocated) * @param data_size set to number of bytes in @a data * @return #GNUNET_OK on success */ static int gns_string_to_value (void *cls, uint32_t type, const char *s, void **data, size_t *data_size) { struct GNUNET_CRYPTO_EcdsaPublicKey pkey; if (NULL == s) return GNUNET_SYSERR; switch (type) { case GNUNET_GNSRECORD_TYPE_PKEY: if (GNUNET_OK != GNUNET_CRYPTO_ecdsa_public_key_from_string (s, strlen (s), &pkey)) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Unable to parse PKEY record `%s'\n"), s); return GNUNET_SYSERR; } *data = GNUNET_new (struct GNUNET_CRYPTO_EcdsaPublicKey); memcpy (*data, &pkey, sizeof (pkey)); *data_size = sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey); return GNUNET_OK; case GNUNET_GNSRECORD_TYPE_NICK: *data = GNUNET_strdup (s); *data_size = strlen (s); return GNUNET_OK; case GNUNET_GNSRECORD_TYPE_LEHO: *data = GNUNET_strdup (s); *data_size = strlen (s); return GNUNET_OK; case GNUNET_GNSRECORD_TYPE_GNS2DNS: { char nsbuf[514]; char *cpy; char *at; size_t off; cpy = GNUNET_strdup (s); at = strchr (cpy, '@'); if (NULL == at) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Unable to parse GNS2DNS record `%s'\n"), s); GNUNET_free (cpy); return GNUNET_SYSERR; } *at = '\0'; at++; off = 0; if ( (GNUNET_OK != GNUNET_DNSPARSER_builder_add_name (nsbuf, sizeof (nsbuf), &off, cpy)) || (GNUNET_OK != GNUNET_DNSPARSER_builder_add_name (nsbuf, sizeof (nsbuf), &off, at)) ) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Failed to serialize GNS2DNS record with value `%s'\n"), s); GNUNET_free (cpy); return GNUNET_SYSERR; } GNUNET_free (cpy); *data_size = off; *data = GNUNET_malloc (off); memcpy (*data, nsbuf, off); return GNUNET_OK; } case GNUNET_GNSRECORD_TYPE_VPN: { struct GNUNET_TUN_GnsVpnRecord *vpn; char s_peer[103 + 1]; char s_serv[253 + 1]; unsigned int proto; if (3 != SSCANF (s, "%u %103s %253s", &proto, s_peer, s_serv)) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Unable to parse VPN record string `%s'\n"), s); return GNUNET_SYSERR; } *data_size = sizeof (struct GNUNET_TUN_GnsVpnRecord) + strlen (s_serv) + 1; *data = vpn = GNUNET_malloc (*data_size); if (GNUNET_OK != GNUNET_CRYPTO_eddsa_public_key_from_string ((char*) s_peer, strlen (s_peer), &vpn->peer.public_key)) { GNUNET_free (vpn); *data_size = 0; return GNUNET_SYSERR; } vpn->proto = htons ((uint16_t) proto); strcpy ((char*)&vpn[1], s_serv); return GNUNET_OK; } case GNUNET_GNSRECORD_TYPE_BOX: { struct GNUNET_GNSRECORD_BoxRecord *box; size_t rest; unsigned int protocol; unsigned int service; unsigned int record_type; void *bval; size_t bval_size; if (3 != SSCANF (s, "%u %u %u ", &protocol, &service, &record_type)) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Unable to parse BOX record string `%s'\n"), s); return GNUNET_SYSERR; } rest = snprintf (NULL, 0, "%u %u %u ", protocol, service, record_type); if (GNUNET_OK != GNUNET_GNSRECORD_string_to_value (record_type, &s[rest], &bval, &bval_size)) return GNUNET_SYSERR; *data_size = sizeof (struct GNUNET_GNSRECORD_BoxRecord) + bval_size; *data = box = GNUNET_malloc (*data_size); box->protocol = htons (protocol); box->service = htons (service); box->record_type = htonl (record_type); memcpy (&box[1], bval, bval_size); GNUNET_free (bval); return GNUNET_OK; } default: return GNUNET_SYSERR; } }
/** * Convert human-readable version of a 'value' of a record to the binary * representation. * * @param cls closure, unused * @param type type of the record * @param s human-readable string * @param data set to value in binary encoding (will be allocated) * @param data_size set to number of bytes in @a data * @return #GNUNET_OK on success */ static int gns_string_to_value (void *cls, uint32_t type, const char *s, void **data, size_t *data_size) { struct GNUNET_CRYPTO_EcdsaPublicKey pkey; if (NULL == s) return GNUNET_SYSERR; switch (type) { case GNUNET_GNSRECORD_TYPE_PKEY: if (GNUNET_OK != GNUNET_CRYPTO_ecdsa_public_key_from_string (s, strlen (s), &pkey)) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Unable to parse PKEY record `%s'\n"), s); return GNUNET_SYSERR; } *data = GNUNET_new (struct GNUNET_CRYPTO_EcdsaPublicKey); GNUNET_memcpy (*data, &pkey, sizeof (pkey)); *data_size = sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey); return GNUNET_OK; case GNUNET_GNSRECORD_TYPE_NICK: *data = GNUNET_strdup (s); *data_size = strlen (s); return GNUNET_OK; case GNUNET_GNSRECORD_TYPE_LEHO: *data = GNUNET_strdup (s); *data_size = strlen (s); return GNUNET_OK; case GNUNET_GNSRECORD_TYPE_GNS2DNS: { char nsbuf[514]; char *cpy; char *at; size_t off; cpy = GNUNET_strdup (s); at = strchr (cpy, '@'); if (NULL == at) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Unable to parse GNS2DNS record `%s'\n"), s); GNUNET_free (cpy); return GNUNET_SYSERR; } *at = '\0'; at++; off = 0; if ( (GNUNET_OK != GNUNET_DNSPARSER_builder_add_name (nsbuf, sizeof (nsbuf), &off, cpy)) || (GNUNET_OK != GNUNET_DNSPARSER_builder_add_name (nsbuf, sizeof (nsbuf), &off, at)) ) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Failed to serialize GNS2DNS record with value `%s'\n"), s); GNUNET_free (cpy); return GNUNET_SYSERR; } GNUNET_free (cpy); *data_size = off; *data = GNUNET_malloc (off); GNUNET_memcpy (*data, nsbuf, off); return GNUNET_OK; } case GNUNET_GNSRECORD_TYPE_VPN: { struct GNUNET_TUN_GnsVpnRecord *vpn; char s_peer[103 + 1]; char s_serv[253 + 1]; unsigned int proto; if (3 != SSCANF (s, "%u %103s %253s", &proto, s_peer, s_serv)) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Unable to parse VPN record string `%s'\n"), s); return GNUNET_SYSERR; } *data_size = sizeof (struct GNUNET_TUN_GnsVpnRecord) + strlen (s_serv) + 1; *data = vpn = GNUNET_malloc (*data_size); if (GNUNET_OK != GNUNET_CRYPTO_eddsa_public_key_from_string ((char*) s_peer, strlen (s_peer), &vpn->peer.public_key)) { GNUNET_free (vpn); *data_size = 0; return GNUNET_SYSERR; } vpn->proto = htons ((uint16_t) proto); strcpy ((char*)&vpn[1], s_serv); return GNUNET_OK; } case GNUNET_GNSRECORD_TYPE_BOX: { struct GNUNET_GNSRECORD_BoxRecord *box; size_t rest; unsigned int protocol; unsigned int service; unsigned int record_type; void *bval; size_t bval_size; if (3 != SSCANF (s, "%u %u %u ", &protocol, &service, &record_type)) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Unable to parse BOX record string `%s'\n"), s); return GNUNET_SYSERR; } rest = snprintf (NULL, 0, "%u %u %u ", protocol, service, record_type); if (GNUNET_OK != GNUNET_GNSRECORD_string_to_value (record_type, &s[rest], &bval, &bval_size)) return GNUNET_SYSERR; *data_size = sizeof (struct GNUNET_GNSRECORD_BoxRecord) + bval_size; *data = box = GNUNET_malloc (*data_size); box->protocol = htons (protocol); box->service = htons (service); box->record_type = htonl (record_type); GNUNET_memcpy (&box[1], bval, bval_size); GNUNET_free (bval); return GNUNET_OK; } case GNUNET_GNSRECORD_TYPE_REVERSE: { struct GNUNET_GNSRECORD_ReverseRecord *rev; char known_by[253 + 1]; struct GNUNET_TIME_Absolute expiration; /* TODO: From crypto_ecc.c * Why is this not a constant??? */ size_t enclen = (sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey)) * 8; if (enclen % 5 > 0) enclen += 5 - enclen % 5; enclen /= 5; /* 260/5 = 52 */ char pkey_str[enclen + 1]; if (3 != SSCANF (s, "%253s %52s %"SCNu64, known_by, pkey_str, &expiration.abs_value_us)) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Unable to parse REVERSE record string `%s'\n"), s); return GNUNET_SYSERR; } *data_size = sizeof (struct GNUNET_GNSRECORD_ReverseRecord) + strlen (known_by) + 1; *data = rev = GNUNET_malloc (*data_size); GNUNET_CRYPTO_ecdsa_public_key_from_string (pkey_str, strlen (pkey_str), &rev->pkey); rev->expiration = expiration; GNUNET_memcpy (&rev[1], known_by, strlen (known_by)); return GNUNET_OK; } default: return GNUNET_SYSERR; } }
/** * Main function that will be run by the scheduler. * * @param cls closure * @param args remaining command-line arguments * @param cfgfile name of the configuration file used (for saving, can be NULL!) * @param cfg configuration */ static void run (void *cls, char *const *args, const char *cfgfile, const struct GNUNET_CONFIGURATION_Handle *cfg) { int dst_af; int req_af; struct GNUNET_PeerIdentity peer; struct GNUNET_HashCode sd; const void *addr; struct in_addr v4; struct in6_addr v6; uint8_t protocol; struct GNUNET_TIME_Absolute etime; etime = GNUNET_TIME_relative_to_absolute (duration); GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, &do_disconnect, NULL); handle = GNUNET_VPN_connect (cfg); if (NULL == handle) goto error; req_af = AF_UNSPEC; if (ipv4) { if (ipv6) { FPRINTF (stderr, _("Option `%s' makes no sense with option `%s'.\n"), "-4", "-6"); goto error; } req_af = AF_INET; } if (ipv6) req_af = AF_INET6; if (NULL == target_ip) { if (NULL == service_name) { FPRINTF (stderr, _("Option `%s' or `%s' is required.\n"), "-i", "-s"); goto error; } if (NULL == peer_id) { FPRINTF (stderr, _("Option `%s' is required when using option `%s'.\n"), "-p", "-s"); goto error; } if (! (tcp | udp) ) { FPRINTF (stderr, _("Option `%s' or `%s' is required when using option `%s'.\n"), "-t", "-u", "-s"); goto error; } if (tcp & udp) { FPRINTF (stderr, _("Option `%s' makes no sense with option `%s'.\n"), "-t", "-u"); goto error; } if (tcp) protocol = IPPROTO_TCP; if (udp) protocol = IPPROTO_UDP; if (GNUNET_OK != GNUNET_CRYPTO_eddsa_public_key_from_string (peer_id, strlen (peer_id), &peer.public_key)) { FPRINTF (stderr, _("`%s' is not a valid peer identifier.\n"), peer_id); goto error; } GNUNET_TUN_service_name_to_hash (service_name, &sd); request = GNUNET_VPN_redirect_to_peer (handle, req_af, protocol, &peer, &sd, etime, &allocation_cb, NULL); } else { if (1 != inet_pton (AF_INET6, target_ip, &v6)) { if (1 != inet_pton (AF_INET, target_ip, &v4)) { FPRINTF (stderr, _("`%s' is not a valid IP address.\n"), target_ip); goto error; } else { dst_af = AF_INET; addr = &v4; } } else { dst_af = AF_INET6; addr = &v6; } request = GNUNET_VPN_redirect_to_ip (handle, req_af, dst_af, addr, etime, &allocation_cb, NULL); } return; error: GNUNET_SCHEDULER_shutdown (); ret = 1; }