void udp_broadcast_receive (struct Plugin *plugin, const char * buf, ssize_t size, struct sockaddr *addr, size_t addrlen) { struct GNUNET_ATS_Information ats; if ((GNUNET_YES == plugin->broadcast_ipv4) && (addrlen == sizeof (struct sockaddr_in))) { LOG (GNUNET_ERROR_TYPE_DEBUG, "Received IPv4 HELLO beacon broadcast with %i bytes from address %s\n", size, GNUNET_a2s ((const struct sockaddr *) addr, addrlen)); struct Mstv4Context *mc; mc = GNUNET_malloc (sizeof (struct Mstv4Context)); struct sockaddr_in *av4 = (struct sockaddr_in *) addr; mc->addr.ipv4_addr = av4->sin_addr.s_addr; mc->addr.u4_port = av4->sin_port; ats = plugin->env->get_address_type (plugin->env->cls, (const struct sockaddr *) addr, addrlen); mc->ats_address_network_type = ats.value; GNUNET_assert (NULL != plugin->broadcast_ipv4_mst); if (GNUNET_OK != GNUNET_SERVER_mst_receive (plugin->broadcast_ipv4_mst, mc, buf, size, GNUNET_NO, GNUNET_NO)) GNUNET_free (mc); } else if ((GNUNET_YES == plugin->broadcast_ipv4) && (addrlen == sizeof (struct sockaddr_in6))) { LOG (GNUNET_ERROR_TYPE_DEBUG, "Received IPv6 HELLO beacon broadcast with %i bytes from address %s\n", size, GNUNET_a2s ((const struct sockaddr *) &addr, addrlen)); struct Mstv6Context *mc; mc = GNUNET_malloc (sizeof (struct Mstv6Context)); struct sockaddr_in6 *av6 = (struct sockaddr_in6 *) addr; mc->addr.ipv6_addr = av6->sin6_addr; mc->addr.u6_port = av6->sin6_port; ats = plugin->env->get_address_type (plugin->env->cls, (const struct sockaddr *) addr, addrlen); mc->ats_address_network_type = ats.value; GNUNET_assert (NULL != plugin->broadcast_ipv4_mst); if (GNUNET_OK != GNUNET_SERVER_mst_receive (plugin->broadcast_ipv6_mst, mc, buf, size, GNUNET_NO, GNUNET_NO)) GNUNET_free (mc); } }
/** * Transmit a message. * * @param tmit * Transmission handle. * @param method_name * Which method should be invoked. * @param env * Environment for the message. * Should stay available until the first call to notify_data. * Can be NULL if there are no modifiers or @a notify_mod is * provided instead. * @param notify_mod * Function to call to obtain modifiers. * Can be NULL if there are no modifiers or @a env is provided instead. * @param notify_data * Function to call to obtain fragments of the data. * @param notify_cls * Closure for @a notify_mod and @a notify_data. * @param flags * Flags for the message being transmitted. * * @return #GNUNET_OK if the transmission was started. * #GNUNET_SYSERR if another transmission is already going on. */ int GNUNET_PSYC_transmit_message (struct GNUNET_PSYC_TransmitHandle *tmit, const char *method_name, const struct GNUNET_ENV_Environment *env, GNUNET_PSYC_TransmitNotifyModifier notify_mod, GNUNET_PSYC_TransmitNotifyData notify_data, void *notify_cls, uint32_t flags) { if (GNUNET_NO != tmit->in_transmit) return GNUNET_SYSERR; tmit->in_transmit = GNUNET_YES; size_t size = strlen (method_name) + 1; struct GNUNET_PSYC_MessageMethod *pmeth; tmit->msg = GNUNET_malloc (sizeof (*tmit->msg) + sizeof (*pmeth) + size); tmit->msg->size = sizeof (*tmit->msg) + sizeof (*pmeth) + size; if (NULL != notify_mod) { tmit->notify_mod = notify_mod; tmit->notify_mod_cls = notify_cls; } else { tmit->notify_mod = &transmit_notify_env; tmit->notify_mod_cls = tmit; if (NULL != env) { struct GNUNET_ENV_Modifier mod = {}; mod.next = GNUNET_ENV_environment_head (env); tmit->mod = &mod; struct GNUNET_ENV_Modifier *m = tmit->mod; while (NULL != (m = m->next)) { if (m->oper != GNUNET_ENV_OP_SET) flags |= GNUNET_PSYC_MASTER_TRANSMIT_STATE_MODIFY; } } else { tmit->mod = NULL; } } pmeth = (struct GNUNET_PSYC_MessageMethod *) &tmit->msg[1]; pmeth->header.type = htons (GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_METHOD); pmeth->header.size = htons (sizeof (*pmeth) + size); pmeth->flags = htonl (flags); memcpy (&pmeth[1], method_name, size); tmit->state = GNUNET_PSYC_MESSAGE_STATE_MODIFIER; tmit->notify_data = notify_data; tmit->notify_data_cls = notify_cls; transmit_mod (tmit); return GNUNET_OK; }
static struct GNUNET_GNSRECORD_Data * create_record (int count) { unsigned int c; struct GNUNET_GNSRECORD_Data *rd; rd = GNUNET_malloc (count * sizeof (struct GNUNET_GNSRECORD_Data)); for (c = 0; c < count; c++) { rd[c].expiration_time = GNUNET_TIME_absolute_get().abs_value_us + 1000000000; rd[c].record_type = TEST_RECORD_TYPE; rd[c].data_size = TEST_RECORD_DATALEN; rd[c].data = GNUNET_malloc(TEST_RECORD_DATALEN); memset ((char *) rd[c].data, TEST_RECORD_DATA, TEST_RECORD_DATALEN); } return rd; }
static struct GNUNET_NAMESTORE_RecordData * create_record (unsigned int count) { unsigned int c; struct GNUNET_NAMESTORE_RecordData * rd; rd = GNUNET_malloc (count * sizeof (struct GNUNET_NAMESTORE_RecordData)); for (c = 0; c < count; c++) { rd[c].expiration_time = GNUNET_TIME_relative_to_absolute (GNUNET_TIME_UNIT_HOURS).abs_value; rd[c].record_type = 1111; rd[c].data_size = 50; rd[c].data = GNUNET_malloc(50); memset ((char *) rd[c].data, 'a', 50); } return rd; }
/** * Main state machine that goes over all options and * runs the next requested function. * * @param cls unused * @param tc scheduler context */ static void state_machine (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { tt = GNUNET_SCHEDULER_NO_TASK; if (NULL != put_uri) { GPI_plugins_load (cfg); if (GNUNET_SYSERR == parse_hello_uri (put_uri)) fprintf (stderr, _("Invalid URI `%s'\n"), put_uri); GNUNET_free (put_uri); put_uri = NULL; return; } if (GNUNET_YES == get_info) { get_info = GNUNET_NO; GPI_plugins_load (cfg); pic = GNUNET_PEERINFO_iterate (peerinfo, NULL, TIMEOUT, &print_peer_info, NULL); return; } if (GNUNET_YES == get_self) { struct GNUNET_CRYPTO_HashAsciiEncoded enc; get_self = GNUNET_NO; GNUNET_CRYPTO_hash_to_enc (&my_peer_identity.hashPubKey, &enc); if (be_quiet) printf ("%s\n", (char *) &enc); else printf (_("I am peer `%s'.\n"), (const char *) &enc); } if (GNUNET_YES == get_uri) { struct GetUriContext *guc; char *pkey; guc = GNUNET_malloc (sizeof (struct GetUriContext)); pkey = GNUNET_CRYPTO_rsa_public_key_to_string (&my_public_key); GNUNET_asprintf (&guc->uri, "%s%s", HELLO_URI_PREFIX, pkey); GNUNET_free (pkey); GPI_plugins_load (cfg); pic = GNUNET_PEERINFO_iterate (peerinfo, &my_peer_identity, TIMEOUT, &print_my_uri, guc); get_uri = GNUNET_NO; return; } GNUNET_SCHEDULER_shutdown (); }
/** * Check if some client is monitoring GET messages and notify * them in that case. * * @param options Options, for instance RecordRoute, DemultiplexEverywhere. * @param type The type of data in the request. * @param hop_count Hop count so far. * @param path_length number of entries in path (or 0 if not recorded). * @param path peers on the GET path (or NULL if not recorded). * @param desired_replication_level Desired replication level. * @param key Key of the requested data. */ void GDS_CLIENTS_process_get (uint32_t options, enum GNUNET_BLOCK_Type type, uint32_t hop_count, uint32_t desired_replication_level, unsigned int path_length, const struct GNUNET_PeerIdentity *path, const struct GNUNET_HashCode * key) { struct ClientMonitorRecord *m; struct ClientList **cl; unsigned int cl_size; cl = NULL; cl_size = 0; for (m = monitor_head; NULL != m; m = m->next) { if ((GNUNET_BLOCK_TYPE_ANY == m->type || m->type == type) && (NULL == m->key || memcmp (key, m->key, sizeof(struct GNUNET_HashCode)) == 0)) { struct PendingMessage *pm; struct GNUNET_DHT_MonitorGetMessage *mmsg; struct GNUNET_PeerIdentity *msg_path; size_t msize; unsigned int i; /* Don't send duplicates */ for (i = 0; i < cl_size; i++) if (cl[i] == m->client) break; if (i < cl_size) continue; GNUNET_array_append (cl, cl_size, m->client); msize = path_length * sizeof (struct GNUNET_PeerIdentity); msize += sizeof (struct GNUNET_DHT_MonitorGetMessage); msize += sizeof (struct PendingMessage); pm = GNUNET_malloc (msize); mmsg = (struct GNUNET_DHT_MonitorGetMessage *) &pm[1]; pm->msg = &mmsg->header; mmsg->header.size = htons (msize - sizeof (struct PendingMessage)); mmsg->header.type = htons (GNUNET_MESSAGE_TYPE_DHT_MONITOR_GET); mmsg->options = htonl(options); mmsg->type = htonl(type); mmsg->hop_count = htonl(hop_count); mmsg->desired_replication_level = htonl(desired_replication_level); mmsg->get_path_length = htonl(path_length); memcpy (&mmsg->key, key, sizeof (struct GNUNET_HashCode)); msg_path = (struct GNUNET_PeerIdentity *) &mmsg[1]; if (path_length > 0) memcpy (msg_path, path, path_length * sizeof (struct GNUNET_PeerIdentity)); add_pending_message (m->client, pm); } } GNUNET_free_non_null (cl); }
/** * Read a share from its binary representation. * * @param data Binary representation of the share. * @param len Length of @a data. * @param[out] readlen Number of bytes read, * ignored if NULL. * @return The share, or NULL on error. */ struct GNUNET_SECRETSHARING_Share * GNUNET_SECRETSHARING_share_read (const void *data, size_t len, size_t *readlen) { struct GNUNET_SECRETSHARING_Share *share; const struct GNUNET_SECRETSHARING_ShareHeaderNBO *sh = data; char *p; size_t n; uint16_t payload_size; payload_size = ntohs (sh->num_peers) * (sizeof (uint16_t) + sizeof (struct GNUNET_SECRETSHARING_FieldElement) + sizeof (struct GNUNET_PeerIdentity)); if (NULL != readlen) *readlen = payload_size + sizeof *sh; share = GNUNET_malloc (sizeof *share); share->threshold = ntohs (sh->threshold); share->num_peers = ntohs (sh->num_peers); share->my_peer = ntohs (sh->my_peer); share->my_share = sh->my_share; share->public_key = sh->public_key; p = (void *) &sh[1]; n = share->num_peers * sizeof (struct GNUNET_PeerIdentity); share->peers = GNUNET_malloc (n); memcpy (share->peers, p, n); p += n; n = share->num_peers * sizeof (struct GNUNET_SECRETSHARING_FieldElement); share->sigmas = GNUNET_malloc (n); memcpy (share->sigmas, p, n); p += n; n = share->num_peers * sizeof (uint16_t); share->original_indices = GNUNET_malloc (n); memcpy (share->original_indices, p, n); return share; }
/** * Print information about the peer. * Currently prints the GNUNET_PeerIdentity and the transport address. * * @param cls the 'struct PrintContext' * @param peer identity of the peer * @param hello addresses of the peer * @param err_msg error message */ static void print_peer_info (void *cls, const struct GNUNET_PeerIdentity *peer, const struct GNUNET_HELLO_Message *hello, const char *err_msg) { struct GNUNET_CRYPTO_HashAsciiEncoded enc; struct PrintContext *pc; if (NULL == peer) { pic = NULL; /* end of iteration */ if (NULL != err_msg) { FPRINTF (stderr, _("Error in communication with PEERINFO service: %s\n"), err_msg); } if (NULL == pc_head) tt = GNUNET_SCHEDULER_add_now (&state_machine, NULL); return; } if ((GNUNET_YES == be_quiet) || (NULL == hello)) { GNUNET_CRYPTO_hash_to_enc (&peer->hashPubKey, &enc); printf ("%s\n", (const char *) &enc); return; } pc = GNUNET_malloc (sizeof (struct PrintContext)); GNUNET_CONTAINER_DLL_insert (pc_head, pc_tail, pc); pc->peer = *peer; GNUNET_HELLO_iterate_addresses (hello, GNUNET_NO, &count_address, pc); if (0 == pc->off) { dump_pc (pc); return; } pc->address_list_size = pc->off; pc->address_list = GNUNET_malloc (sizeof (struct AddressRecord) * pc->off); GNUNET_HELLO_iterate_addresses (hello, GNUNET_NO, &print_address, pc); }
/** * Obtain the location of ".my.cnf". * * @param cfg our configuration * @param section the section * @return NULL on error */ static char * get_my_cnf_path (const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section) { char *cnffile; char *home_dir; struct stat st; #ifndef WINDOWS struct passwd *pw; #endif int configured; #ifndef WINDOWS pw = getpwuid (getuid ()); if (!pw) { GNUNET_log_from_strerror (GNUNET_ERROR_TYPE_ERROR, "mysql", "getpwuid"); return NULL; } if (GNUNET_YES == GNUNET_CONFIGURATION_have_value (cfg, section, "CONFIG")) { GNUNET_assert (GNUNET_OK == GNUNET_CONFIGURATION_get_value_filename (cfg, section, "CONFIG", &cnffile)); configured = GNUNET_YES; } else { home_dir = GNUNET_strdup (pw->pw_dir); GNUNET_asprintf (&cnffile, "%s/.my.cnf", home_dir); GNUNET_free (home_dir); configured = GNUNET_NO; } #else home_dir = (char *) GNUNET_malloc (_MAX_PATH + 1); plibc_conv_to_win_path ("~/", home_dir); GNUNET_asprintf (&cnffile, "%s/.my.cnf", home_dir); GNUNET_free (home_dir); configured = GNUNET_NO; #endif GNUNET_log_from (GNUNET_ERROR_TYPE_INFO, "mysql", _("Trying to use file `%s' for MySQL configuration.\n"), cnffile); if ((0 != STAT (cnffile, &st)) || (0 != ACCESS (cnffile, R_OK)) || (!S_ISREG (st.st_mode))) { if (configured == GNUNET_YES) GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR, "mysql", _("Could not access file `%s': %s\n"), cnffile, STRERROR (errno)); GNUNET_free (cnffile); return NULL; } return cnffile; }
/** * This function is called *before* the DNS request has been * given to a "local" DNS resolver. Tunneling for DNS requests * was enabled, so we now need to send the request via some MESH * tunnel to a DNS EXIT for resolution. * * @param cls closure * @param rh request handle to user for reply * @param request_length number of bytes in request * @param request udp payload of the DNS request */ static void dns_pre_request_handler (void *cls, struct GNUNET_DNS_RequestHandle *rh, size_t request_length, const char *request) { struct RequestContext *rc; size_t mlen; struct GNUNET_MessageHeader hdr; struct GNUNET_TUN_DnsHeader dns; GNUNET_STATISTICS_update (stats, gettext_noop ("# DNS requests intercepted"), 1, GNUNET_NO); if (0 == dns_exit_available) { GNUNET_STATISTICS_update (stats, gettext_noop ("# DNS requests dropped (DNS mesh tunnel down)"), 1, GNUNET_NO); GNUNET_DNS_request_drop (rh); return; } if (request_length < sizeof (dns)) { GNUNET_STATISTICS_update (stats, gettext_noop ("# DNS requests dropped (malformed)"), 1, GNUNET_NO); GNUNET_DNS_request_drop (rh); return; } memcpy (&dns, request, sizeof (dns)); GNUNET_assert (NULL != mesh_tunnel); mlen = sizeof (struct GNUNET_MessageHeader) + request_length; rc = GNUNET_malloc (sizeof (struct RequestContext) + mlen); rc->rh = rh; rc->mesh_message = (const struct GNUNET_MessageHeader*) &rc[1]; rc->timeout_task = GNUNET_SCHEDULER_add_delayed (TIMEOUT, &timeout_request, rc); rc->dns_id = dns.id; hdr.type = htons (GNUNET_MESSAGE_TYPE_VPN_DNS_TO_INTERNET); hdr.size = htons (mlen); memcpy (&rc[1], &hdr, sizeof (struct GNUNET_MessageHeader)); memcpy (&(((char*)&rc[1])[sizeof (struct GNUNET_MessageHeader)]), request, request_length); GNUNET_CONTAINER_DLL_insert_tail (transmit_queue_head, transmit_queue_tail, rc); if (NULL == mesh_th) mesh_th = GNUNET_MESH_notify_transmit_ready (mesh_tunnel, GNUNET_NO, 0, TIMEOUT, NULL, mlen, &transmit_dns_request_to_mesh, NULL); }
/** * Perform a PUT operation storing data in the DHT. FIXME: we should * change the protocol to get a confirmation for the PUT from the DHT * and call 'cont' only after getting the confirmation; otherwise, the * client has no good way of telling if the 'PUT' message actually got * to the DHT service! * * @param handle handle to DHT service * @param key the key to store under * @param desired_replication_level estimate of how many * nearest peers this request should reach * @param options routing options for this message * @param type type of the value * @param size number of bytes in data; must be less than 64k * @param data the data to store * @param exp desired expiration time for the value * @param timeout how long to wait for transmission of this request * @param cont continuation to call when done (transmitting request to service) * You must not call #GNUNET_DHT_disconnect in this continuation * @param cont_cls closure for @a cont */ struct GNUNET_DHT_PutHandle * GNUNET_DHT_put (struct GNUNET_DHT_Handle *handle, const struct GNUNET_HashCode * key, uint32_t desired_replication_level, enum GNUNET_DHT_RouteOption options, enum GNUNET_BLOCK_Type type, size_t size, const void *data, struct GNUNET_TIME_Absolute exp, struct GNUNET_TIME_Relative timeout, GNUNET_DHT_PutContinuation cont, void *cont_cls) { struct GNUNET_DHT_ClientPutMessage *put_msg; size_t msize; struct PendingMessage *pending; struct GNUNET_DHT_PutHandle *ph; msize = sizeof (struct GNUNET_DHT_ClientPutMessage) + size; if ((msize >= GNUNET_SERVER_MAX_MESSAGE_SIZE) || (size >= GNUNET_SERVER_MAX_MESSAGE_SIZE)) { GNUNET_break (0); return NULL; } ph = GNUNET_new (struct GNUNET_DHT_PutHandle); ph->dht_handle = handle; ph->timeout_task = GNUNET_SCHEDULER_add_delayed (timeout, &timeout_put_request, ph); ph->cont = cont; ph->cont_cls = cont_cls; ph->unique_id = ++handle->uid_gen; pending = GNUNET_malloc (sizeof (struct PendingMessage) + msize); ph->pending = pending; put_msg = (struct GNUNET_DHT_ClientPutMessage *) &pending[1]; pending->msg = &put_msg->header; pending->handle = handle; pending->cont = &mark_put_message_gone; pending->cont_cls = ph; pending->free_on_send = GNUNET_YES; put_msg->header.size = htons (msize); put_msg->header.type = htons (GNUNET_MESSAGE_TYPE_DHT_CLIENT_PUT); put_msg->type = htonl (type); put_msg->options = htonl ((uint32_t) options); put_msg->desired_replication_level = htonl (desired_replication_level); put_msg->unique_id = ph->unique_id; put_msg->expiration = GNUNET_TIME_absolute_hton (exp); put_msg->key = *key; memcpy (&put_msg[1], data, size); GNUNET_CONTAINER_DLL_insert (handle->pending_head, handle->pending_tail, pending); pending->in_pending_queue = GNUNET_YES; GNUNET_CONTAINER_DLL_insert_tail (handle->put_head, handle->put_tail, ph); process_pending_messages (handle); return ph; }
struct Session * create_session (struct Plugin *plugin, const struct GNUNET_PeerIdentity *target, const void *addr, size_t addrlen) { struct Session *s = NULL; GNUNET_assert ((addrlen == sizeof (struct IPv6HttpAddress)) || (addrlen == sizeof (struct IPv4HttpAddress))); s = GNUNET_malloc (sizeof (struct Session)); memcpy (&s->target, target, sizeof (struct GNUNET_PeerIdentity)); s->plugin = plugin; s->addr = GNUNET_malloc (addrlen); memcpy (s->addr, addr, addrlen); s->addrlen = addrlen; s->ats_address_network_type = htonl (GNUNET_ATS_NET_UNSPECIFIED); start_session_timeout(s); return s; }
static struct GNUNET_NAMESTORE_RecordData * create_record (int count) { int c; struct GNUNET_NAMESTORE_RecordData * rd; rd = GNUNET_malloc (count * sizeof (struct GNUNET_NAMESTORE_RecordData)); for (c = 0; c < RECORDS; c++) { rd[c].expiration = GNUNET_TIME_absolute_get(); rd[c].record_type = TEST_RECORD_TYPE; rd[c].data_size = TEST_RECORD_DATALEN; rd[c].data = GNUNET_malloc(TEST_RECORD_DATALEN); memset ((char *) rd[c].data, TEST_RECORD_DATA, TEST_RECORD_DATALEN); } return rd; }
/** * Start or stop a service. * * @param h handle to ARM * @param service_name name of the service * @param timeout how long to wait before failing for good * @param cb callback to invoke when service is ready * @param cb_cls closure for callback * @param type type of the request */ static void change_service (struct GNUNET_ARM_Handle *h, const char *service_name, struct GNUNET_TIME_Relative timeout, GNUNET_ARM_ResultCallback cb, void *cb_cls, uint16_t type) { struct ARMControlMessage *cm; size_t slen; struct GNUNET_ARM_Message *msg; slen = strlen (service_name) + 1; if (slen + sizeof (struct GNUNET_ARM_Message) >= GNUNET_SERVER_MAX_MESSAGE_SIZE) { GNUNET_break (0); if (cb != NULL) cb (cb_cls, GNUNET_ARM_REQUEST_TOO_LONG, NULL, 0); return; } LOG (GNUNET_ERROR_TYPE_DEBUG, "Requesting %s of service `%s'.\n", (GNUNET_MESSAGE_TYPE_ARM_START == type) ? "start" : "termination", service_name); cm = GNUNET_malloc (sizeof (struct ARMControlMessage) + slen); cm->h = h; cm->result_cont = cb; cm->cont_cls = cb_cls; cm->timeout = GNUNET_TIME_relative_to_absolute (timeout); memcpy (&cm[1], service_name, slen); msg = GNUNET_malloc (sizeof (struct GNUNET_ARM_Message) + slen); msg->header.size = htons (sizeof (struct GNUNET_ARM_Message) + slen); msg->header.type = htons (type); msg->reserved = htonl (0); memcpy (&msg[1], service_name, slen); cm->msg = msg; LOG (GNUNET_ERROR_TYPE_DEBUG, "Inserting a control message into the queue. Timeout is %s\n", GNUNET_STRINGS_relative_time_to_string (GNUNET_TIME_absolute_get_remaining (cm->timeout), GNUNET_NO)); GNUNET_CONTAINER_DLL_insert_tail (h->control_pending_head, h->control_pending_tail, cm); cm->timeout_task_id = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_absolute_get_remaining (cm->timeout), &control_message_timeout, cm); trigger_next_request (h, GNUNET_NO); }
/** * Transform topics to regex expression. * * @param topic topic of subscription as provided by the subscriber * @param regex_topic client identification of the client */ static void get_regex (char *topic, char **regex_topic) { char *plus; char *hash; char *prefixed_topic; int i; int j; int k; int plus_counter = 0; int hash_exists = 0; plus = strchr(topic,'+'); while (plus != NULL) { plus_counter +=1; plus=strchr(plus+1,'+'); } hash = strchr(topic,'#'); if (hash != NULL) { hash_exists = 1; } add_prefix(topic, &prefixed_topic); *regex_topic = GNUNET_malloc (strlen(prefixed_topic) - plus_counter - hash_exists + plus_counter*strlen(plus_regex) + hash_exists*strlen(hash_regex)+1); j = 0; for (i = 0; prefixed_topic[i] != '\0'; i++) { if (prefixed_topic[i] == '+') { for (k = 0; k<strlen(plus_regex); k++) { (*regex_topic)[j] = plus_regex[k]; j++; } } else if (prefixed_topic[i] == '#') { j--; for (k = 0; k<strlen(hash_regex); k++) { (*regex_topic)[j] = hash_regex[k]; j++; } } else { (*regex_topic)[j] = prefixed_topic[i]; j++; } } (*regex_topic)[j] = '\0'; }
int EnumNICs2 (INTERFACE_INFO **ifs4, int *ifs4_len, SOCKET_ADDRESS_LIST **ifs6) { int result = 0; SOCKET s4; SOCKET s6; int ifs4len = 0; int ifs6len = 0; INTERFACE_INFO *interfaces4 = NULL; SOCKET_ADDRESS_LIST *interfaces6 = NULL; SetLastError (0); s4 = socket (AF_INET, SOCK_STREAM, IPPROTO_TCP); (void) GetLastError (); SetLastError (0); s6 = socket (AF_INET6, SOCK_STREAM, IPPROTO_TCP); (void) GetLastError (); if (s6 != INVALID_SOCKET) { ifs6len = EnumNICs_IPv6_get_ifs_count (s6); if (ifs6len > 0) { interfaces6 = (SOCKET_ADDRESS_LIST *) GNUNET_malloc (ifs6len); result = EnumNICs_IPv6_get_ifs (s6, interfaces6, ifs6len) || result; } closesocket (s6); s6 = INVALID_SOCKET; } if (s4 != INVALID_SOCKET) { result = EnumNICs_IPv4_get_ifs (s4, &interfaces4, &ifs4len) || result; closesocket (s4); s4 = INVALID_SOCKET; } if (ifs6len + ifs4len == 0) goto error; if (!result) { *ifs4 = interfaces4; *ifs4_len = ifs4len; *ifs6 = interfaces6; return GNUNET_OK; } error: if (interfaces4 != NULL) GNUNET_free (interfaces4); if (interfaces6 != NULL) GNUNET_free (interfaces6); if (s4 != INVALID_SOCKET) closesocket (s4); if (s6 != INVALID_SOCKET) closesocket (s6); return GNUNET_SYSERR; }
/** * Connect to the peerinfo service. * * @param cfg configuration to use * @return NULL on error (configuration related, actual connection * establishment may happen asynchronously). */ struct GNUNET_PEERINFO_Handle * GNUNET_PEERINFO_connect (const struct GNUNET_CONFIGURATION_Handle *cfg) { struct GNUNET_PEERINFO_Handle *h; h = GNUNET_malloc (sizeof (struct GNUNET_PEERINFO_Handle)); h->client = GNUNET_CLIENT_connect ("peerinfo", cfg); h->cfg = cfg; return h; }
/** * Start a DNS stub resolver. * * @param dns_ip target IP address to use * @return NULL on error */ struct GNUNET_DNSSTUB_Context * GNUNET_DNSSTUB_start (const char *dns_ip) { struct GNUNET_DNSSTUB_Context *ctx; ctx = GNUNET_malloc (sizeof (struct GNUNET_DNSSTUB_Context)); if (NULL != dns_ip) ctx->dns_exit = GNUNET_strdup (dns_ip); return ctx; }
/** * Initialize the connection with the GNS service. * * @param cfg configuration to use * @return handle to the GNS service, or NULL on error */ struct GNUNET_GNS_Handle * GNUNET_GNS_connect (const struct GNUNET_CONFIGURATION_Handle *cfg) { struct GNUNET_GNS_Handle *handle; handle = GNUNET_malloc (sizeof (struct GNUNET_GNS_Handle)); handle->cfg = cfg; reconnect (handle); return handle; }
/** * Create a new load value. * * @param autodecline speed at which this value should automatically * decline in the absence of external events; at the given * frequency, 0-load values will be added to the load * @return the new load value */ struct GNUNET_LOAD_Value * GNUNET_LOAD_value_init (struct GNUNET_TIME_Relative autodecline) { struct GNUNET_LOAD_Value *ret; ret = GNUNET_malloc (sizeof (struct GNUNET_LOAD_Value)); ret->autodecline = autodecline; ret->last_update = GNUNET_TIME_absolute_get (); return ret; }
/** * Get an IP address as a string. * * @param sa host address * @param salen length of host address in @a sa * @param do_resolve use #GNUNET_NO to return numeric hostname * @param timeout how long to try resolving * @param callback function to call with hostnames * last callback is NULL when finished * @param cls closure for @a callback * @return handle that can be used to cancel the request */ struct GNUNET_RESOLVER_RequestHandle * GNUNET_RESOLVER_hostname_get (const struct sockaddr *sa, socklen_t salen, int do_resolve, struct GNUNET_TIME_Relative timeout, GNUNET_RESOLVER_HostnameCallback callback, void *cls) { struct GNUNET_RESOLVER_RequestHandle *rh; size_t ip_len; const void *ip; check_config (); switch (sa->sa_family) { case AF_INET: GNUNET_assert (salen == sizeof (struct sockaddr_in)); ip_len = sizeof (struct in_addr); ip = &((const struct sockaddr_in*)sa)->sin_addr; break; case AF_INET6: GNUNET_assert (salen == sizeof (struct sockaddr_in6)); ip_len = sizeof (struct in6_addr); ip = &((const struct sockaddr_in6*)sa)->sin6_addr; break; default: GNUNET_break (0); return NULL; } rh = GNUNET_malloc (sizeof (struct GNUNET_RESOLVER_RequestHandle) + salen); rh->name_callback = callback; rh->cls = cls; rh->af = sa->sa_family; rh->timeout = GNUNET_TIME_relative_to_absolute (timeout); memcpy (&rh[1], ip, ip_len); rh->data_len = ip_len; rh->direction = GNUNET_YES; rh->received_response = GNUNET_NO; if (GNUNET_NO == do_resolve) { rh->task = GNUNET_SCHEDULER_add_now (&numeric_reverse, rh); return rh; } GNUNET_CONTAINER_DLL_insert_tail (req_head, req_tail, rh); rh->was_queued = GNUNET_YES; if (NULL != s_task) { GNUNET_SCHEDULER_cancel (s_task); s_task = NULL; } process_requests (); return rh; }
/** * Recusively update the info about what is the first hop to reach the node * * @param tree Tree this nodes belongs to. * @param parent ID from node form which to start updating. * @param hop If known, ID of the first hop. * If not known, NULL to find out and pass on children. */ static void tree_node_update_first_hops (struct MeshTunnelTree *tree, struct MeshTunnelTreeNode *parent, struct GNUNET_PeerIdentity *hop) { struct GNUNET_PeerIdentity pi; struct GNUNET_PeerIdentity *copy; struct GNUNET_PeerIdentity id; struct MeshTunnelTreeNode *n; #if MESH_TREE_DEBUG GNUNET_PEER_resolve (parent->peer, &id); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "tree: Finding first hop for %s.\n", GNUNET_i2s (&id)); #endif if (NULL == hop) { struct MeshTunnelTreeNode *aux; struct MeshTunnelTreeNode *old; aux = old = parent; while (aux != tree->me) { #if MESH_TREE_DEBUG GNUNET_PEER_resolve (aux->peer, &id); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "tree: ... checking %s.\n", GNUNET_i2s (&id)); #endif old = aux; aux = aux->parent; GNUNET_assert (NULL != aux); } #if MESH_TREE_DEBUG GNUNET_PEER_resolve (old->peer, &id); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "tree: It's %s!\n", GNUNET_i2s (&id)); #endif hop = π GNUNET_PEER_resolve (old->peer, hop); } GNUNET_PEER_resolve (parent->peer, &id); copy = GNUNET_CONTAINER_multihashmap_get (tree->first_hops, &id.hashPubKey); if (NULL == copy) copy = GNUNET_malloc (sizeof (struct GNUNET_PeerIdentity)); *copy = *hop; (void) GNUNET_CONTAINER_multihashmap_put (tree->first_hops, &id.hashPubKey, copy, GNUNET_CONTAINER_MULTIHASHMAPOPTION_REPLACE); for (n = parent->children_head; NULL != n; n = n->next) { tree_node_update_first_hops (tree, n, hop); } }
/** * Function called to (recursively) add all of the files in the * directory to the tree. Called by the directory scanner to initiate * the scan. Does NOT yet add any metadata. * * @param filename file or directory to scan * @param dst where to store the resulting share tree item; * NULL is stored in 'dst' upon recoverable errors (GNUNET_OK is returned) * @return GNUNET_OK on success, GNUNET_SYSERR on error */ static int preprocess_file (const char *filename, struct ScanTreeNode **dst) { struct ScanTreeNode *item; struct stat sbuf; uint64_t fsize = 0; if ((0 != STAT (filename, &sbuf)) || ((!S_ISDIR (sbuf.st_mode)) && (GNUNET_OK != GNUNET_DISK_file_size ( filename, &fsize, GNUNET_NO, GNUNET_YES)))) { /* If the file doesn't exist (or is not stat-able for any other reason) skip it (but report it), but do continue. */ if (GNUNET_OK != write_message (GNUNET_MESSAGE_TYPE_FS_PUBLISH_HELPER_SKIP_FILE, filename, strlen (filename) + 1)) return GNUNET_SYSERR; /* recoverable error, store 'NULL' in *dst */ *dst = NULL; return GNUNET_OK; } /* Report the progress */ if (GNUNET_OK != write_message (S_ISDIR (sbuf.st_mode) ? GNUNET_MESSAGE_TYPE_FS_PUBLISH_HELPER_PROGRESS_DIRECTORY : GNUNET_MESSAGE_TYPE_FS_PUBLISH_HELPER_PROGRESS_FILE, filename, strlen (filename) + 1)) return GNUNET_SYSERR; item = GNUNET_malloc (sizeof (struct ScanTreeNode)); item->filename = GNUNET_strdup (filename); item->is_directory = (S_ISDIR (sbuf.st_mode)) ? GNUNET_YES : GNUNET_NO; item->file_size = fsize; if (GNUNET_YES == item->is_directory) { struct RecursionContext rc; rc.parent = item; rc.stop = GNUNET_NO; GNUNET_DISK_directory_scan (filename, &scan_callback, &rc); if ( (GNUNET_YES == rc.stop) || (GNUNET_OK != write_message (GNUNET_MESSAGE_TYPE_FS_PUBLISH_HELPER_PROGRESS_DIRECTORY, "..", 3)) ) { free_tree (item); return GNUNET_SYSERR; } } *dst = item; return GNUNET_OK; }
/** * We've gotten a HELLO from another peer. Consider it for * advertising. * * @param hello the HELLO we got */ static void consider_for_advertising (const struct GNUNET_HELLO_Message *hello) { int have_address; struct GNUNET_PeerIdentity pid; struct GNUNET_TIME_Absolute dt; struct GNUNET_HELLO_Message *nh; struct Peer *peer; uint16_t size; if (GNUNET_OK != GNUNET_HELLO_get_id (hello, &pid)) { GNUNET_break (0); return; } if (0 == memcmp (&pid, &my_identity, sizeof (struct GNUNET_PeerIdentity))) return; /* that's me! */ have_address = GNUNET_NO; GNUNET_HELLO_iterate_addresses (hello, GNUNET_NO, &address_iterator, &have_address); if (GNUNET_NO == have_address) return; /* no point in advertising this one... */ peer = GNUNET_CONTAINER_multihashmap_get (peers, &pid.hashPubKey); if (NULL == peer) { peer = make_peer (&pid, hello, GNUNET_NO); } else if (peer->hello != NULL) { dt = GNUNET_HELLO_equals (peer->hello, hello, GNUNET_TIME_absolute_get ()); if (dt.abs_value == GNUNET_TIME_UNIT_FOREVER_ABS.abs_value) return; /* nothing new here */ } GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Found `%s' from peer `%s' for advertising\n", "HELLO", GNUNET_i2s (&pid)); if (peer->hello != NULL) { nh = GNUNET_HELLO_merge (peer->hello, hello); GNUNET_free (peer->hello); peer->hello = nh; } else { size = GNUNET_HELLO_size (hello); peer->hello = GNUNET_malloc (size); memcpy (peer->hello, hello, size); } if (peer->filter != NULL) GNUNET_CONTAINER_bloomfilter_free (peer->filter); setup_filter (peer); /* since we have a new HELLO to pick from, re-schedule all * HELLO requests that are not bound by the HELLO send rate! */ GNUNET_CONTAINER_multihashmap_iterate (peers, &reschedule_hellos, peer); }
/** * Create a connection handle by (asynchronously) connecting to a host. * This function returns immediately, even if the connection has not * yet been established. This function only creates TCP connections. * * @param cfg configuration to use * @param hostname name of the host to connect to * @param port port to connect to * @return the connection handle */ struct GNUNET_CONNECTION_Handle * GNUNET_CONNECTION_create_from_connect (const struct GNUNET_CONFIGURATION_Handle *cfg, const char *hostname, uint16_t port) { struct GNUNET_CONNECTION_Handle *connection; GNUNET_assert (0 < strlen (hostname)); /* sanity check */ connection = GNUNET_malloc (sizeof (struct GNUNET_CONNECTION_Handle)); connection->cfg = cfg; connection->write_buffer_size = GNUNET_SERVER_MIN_BUFFER_SIZE; connection->write_buffer = GNUNET_malloc (connection->write_buffer_size); connection->port = port; connection->hostname = GNUNET_strdup (hostname); connection->dns_active = GNUNET_RESOLVER_ip_get (connection->hostname, AF_UNSPEC, GNUNET_CONNECTION_CONNECT_RETRY_TIMEOUT, &try_connect_using_address, connection); return connection; }
/** * Obtain the network address of the other party. * * @param connection the client to get the address for * @param addr where to store the address * @param addrlen where to store the length of the address * @return GNUNET_OK on success */ int GNUNET_CONNECTION_get_address (struct GNUNET_CONNECTION_Handle *connection, void **addr, size_t * addrlen) { if ((NULL == connection->addr) || (0 == connection->addrlen)) return GNUNET_NO; *addr = GNUNET_malloc (connection->addrlen); memcpy (*addr, connection->addr, connection->addrlen); *addrlen = connection->addrlen; return GNUNET_OK; }
/** * Send a message via DV service. * * @param sh service handle * @param target intended recpient * @param msg message payload * @param cb function to invoke when done * @param cb_cls closure for @a cb * @return handle to cancel the operation */ struct GNUNET_DV_TransmitHandle * GNUNET_DV_send (struct GNUNET_DV_ServiceHandle *sh, const struct GNUNET_PeerIdentity *target, const struct GNUNET_MessageHeader *msg, GNUNET_DV_MessageSentCallback cb, void *cb_cls) { struct GNUNET_DV_TransmitHandle *th; struct GNUNET_DV_SendMessage *sm; struct ConnectedPeer *peer; if (ntohs (msg->size) + sizeof (struct GNUNET_DV_SendMessage) >= GNUNET_SERVER_MAX_MESSAGE_SIZE) { GNUNET_break (0); return NULL; } LOG (GNUNET_ERROR_TYPE_DEBUG, "Asked to send %u bytes of type %u to %s via %p\n", (unsigned int) ntohs (msg->size), (unsigned int) ntohs (msg->type), GNUNET_i2s (target), sh->client); peer = GNUNET_CONTAINER_multipeermap_get (sh->peers, target); if (NULL == peer) { GNUNET_break (0); return NULL; } th = GNUNET_malloc (sizeof (struct GNUNET_DV_TransmitHandle) + sizeof (struct GNUNET_DV_SendMessage) + ntohs (msg->size)); th->sh = sh; th->target = peer; th->cb = cb; th->cb_cls = cb_cls; th->msg = (const struct GNUNET_MessageHeader *) &th[1]; sm = (struct GNUNET_DV_SendMessage *) &th[1]; sm->header.type = htons (GNUNET_MESSAGE_TYPE_DV_SEND); sm->header.size = htons (sizeof (struct GNUNET_DV_SendMessage) + ntohs (msg->size)); if (0 == sh->uid_gen) sh->uid_gen = 1; th->uid = sh->uid_gen; sm->uid = htonl (sh->uid_gen++); /* use memcpy here as 'target' may not be sufficiently aligned */ memcpy (&sm->target, target, sizeof (struct GNUNET_PeerIdentity)); memcpy (&sm[1], msg, ntohs (msg->size)); GNUNET_CONTAINER_DLL_insert_tail (sh->th_head, sh->th_tail, th); start_transmit (sh); return th; }
/** * Return unique variant of the namespace name. * Use it after GNUNET_PSEUDONYM_get_info() to make sure * that name is unique. * * @param cfg configuration * @param nsid cryptographic ID of the namespace * @param name name to uniquify * @param suffix if not NULL, filled with the suffix value * @return NULL on failure (should never happen), name on success. * Free the name with GNUNET_free(). */ char * GNUNET_PSEUDONYM_name_uniquify (const struct GNUNET_CONFIGURATION_Handle *cfg, const struct GNUNET_HashCode * nsid, const char *name, unsigned int *suffix) { struct GNUNET_HashCode nh; uint64_t len; char *fn; struct GNUNET_DISK_FileHandle *fh; unsigned int i; unsigned int idx; char *ret; struct stat sbuf; GNUNET_CRYPTO_hash (name, strlen (name), &nh); fn = get_data_filename (cfg, PS_NAMES_DIR, &nh); GNUNET_assert (fn != NULL); len = 0; if (0 == STAT (fn, &sbuf)) GNUNET_break (GNUNET_OK == GNUNET_DISK_file_size (fn, &len, GNUNET_YES, GNUNET_YES)); fh = GNUNET_DISK_file_open (fn, GNUNET_DISK_OPEN_CREATE | GNUNET_DISK_OPEN_READWRITE, GNUNET_DISK_PERM_USER_READ | GNUNET_DISK_PERM_USER_WRITE); i = 0; idx = -1; while ((len >= sizeof (struct GNUNET_HashCode)) && (sizeof (struct GNUNET_HashCode) == GNUNET_DISK_file_read (fh, &nh, sizeof (struct GNUNET_HashCode)))) { if (0 == memcmp (&nh, nsid, sizeof (struct GNUNET_HashCode))) { idx = i; break; } i++; len -= sizeof (struct GNUNET_HashCode); } if (idx == -1) { idx = i; if (sizeof (struct GNUNET_HashCode) != GNUNET_DISK_file_write (fh, nsid, sizeof (struct GNUNET_HashCode))) LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_WARNING, "write", fn); } GNUNET_DISK_file_close (fh); ret = GNUNET_malloc (strlen (name) + 32); GNUNET_snprintf (ret, strlen (name) + 32, "%s-%u", name, idx); if (suffix != NULL) *suffix = idx; GNUNET_free (fn); return ret; }
/** * Convert a string to one or more IP addresses. * * @param hostname the hostname to resolve * @param af AF_INET or AF_INET6; use AF_UNSPEC for "any" * @param callback function to call with addresses * @param callback_cls closure for callback * @param timeout how long to try resolving * @return handle that can be used to cancel the request, NULL on error */ struct GNUNET_RESOLVER_RequestHandle * GNUNET_RESOLVER_ip_get (const char *hostname, int af, struct GNUNET_TIME_Relative timeout, GNUNET_RESOLVER_AddressCallback callback, void *callback_cls) { struct GNUNET_RESOLVER_RequestHandle *rh; size_t slen; unsigned int i; struct in_addr v4; struct in6_addr v6; slen = strlen (hostname) + 1; if (slen + sizeof (struct GNUNET_RESOLVER_GetMessage) >= GNUNET_SERVER_MAX_MESSAGE_SIZE) { GNUNET_break (0); return NULL; } rh = GNUNET_malloc (sizeof (struct GNUNET_RESOLVER_RequestHandle) + slen); rh->af = af; rh->addr_callback = callback; rh->cls = callback_cls; memcpy (&rh[1], hostname, slen); rh->data_len = slen; rh->timeout = GNUNET_TIME_relative_to_absolute (timeout); rh->direction = GNUNET_NO; /* first, check if this is a numeric address */ if (((1 == inet_pton (AF_INET, hostname, &v4)) && ((af == AF_INET) || (af == AF_UNSPEC))) || ((1 == inet_pton (AF_INET6, hostname, &v6)) && ((af == AF_INET6) || (af == AF_UNSPEC)))) { rh->task = GNUNET_SCHEDULER_add_now (&numeric_resolution, rh); return rh; } /* then, check if this is a loopback address */ i = 0; while (loopback[i] != NULL) if (0 == strcasecmp (loopback[i++], hostname)) { rh->task = GNUNET_SCHEDULER_add_now (&loopback_resolution, rh); return rh; } GNUNET_CONTAINER_DLL_insert_tail (req_head, req_tail, rh); rh->was_queued = GNUNET_YES; if (s_task != GNUNET_SCHEDULER_NO_TASK) { GNUNET_SCHEDULER_cancel (s_task); s_task = GNUNET_SCHEDULER_NO_TASK; } process_requests (); return rh; }
/** * Initialize the connection with the NAMESTORE service. * * @param cfg configuration to use * @return handle to the GNS service, or NULL on error */ struct GNUNET_NAMESTORE_Handle * GNUNET_NAMESTORE_connect (const struct GNUNET_CONFIGURATION_Handle *cfg) { struct GNUNET_NAMESTORE_Handle *h; h = GNUNET_malloc (sizeof (struct GNUNET_NAMESTORE_Handle)); h->cfg = cfg; h->reconnect_task = GNUNET_SCHEDULER_add_now (&reconnect_task, h); h->op_id = 0; return h; }