/** * Helper: implements keypin_check and keypin_check_and_add. */ static int keypin_check_and_add_impl(const uint8_t *rsa_id_digest, const uint8_t *ed25519_id_key, const int do_not_add, const int replace) { keypin_ent_t search, *ent; memset(&search, 0, sizeof(search)); memcpy(search.rsa_id, rsa_id_digest, sizeof(search.rsa_id)); memcpy(search.ed25519_key, ed25519_id_key, sizeof(search.ed25519_key)); /* Search by RSA key digest first */ ent = HT_FIND(rsamap, &the_rsa_map, &search); if (ent) { tor_assert(fast_memeq(ent->rsa_id, rsa_id_digest, sizeof(ent->rsa_id))); if (tor_memeq(ent->ed25519_key, ed25519_id_key,sizeof(ent->ed25519_key))) { return KEYPIN_FOUND; /* Match on both keys. Great. */ } else { if (!replace) return KEYPIN_MISMATCH; /* Found RSA with different Ed key */ } } /* See if we know a different RSA key for this ed key */ if (! replace) { ent = HT_FIND(edmap, &the_ed_map, &search); if (ent) { /* If we got here, then the ed key matches and the RSA doesn't */ tor_assert(fast_memeq(ent->ed25519_key, ed25519_id_key, sizeof(ent->ed25519_key))); tor_assert(fast_memneq(ent->rsa_id, rsa_id_digest, sizeof(ent->rsa_id))); return KEYPIN_MISMATCH; } } /* Okay, this one is new to us. */ if (do_not_add) return KEYPIN_NOT_FOUND; ent = tor_memdup(&search, sizeof(search)); int r = keypin_add_or_replace_entry_in_map(ent); if (! replace) { tor_assert(r == 1); } else { tor_assert(r != 0); } keypin_journal_append_entry(rsa_id_digest, ed25519_id_key); return KEYPIN_ADDED; }
void * fp_pair_map_set(fp_pair_map_t *map, const fp_pair_t *key, void *val) { fp_pair_map_entry_t *resolve; fp_pair_map_entry_t search; void *oldval; tor_assert(map); tor_assert(key); tor_assert(val); memcpy(&(search.key), key, sizeof(*key)); resolve = HT_FIND(fp_pair_map_impl, &(map->head), &search); if (resolve) { oldval = resolve->val; resolve->val = val; } else { resolve = tor_malloc_zero(sizeof(fp_pair_map_entry_t)); memcpy(&(resolve->key), key, sizeof(*key)); resolve->val = val; HT_INSERT(fp_pair_map_impl, &(map->head), resolve); oldval = NULL; } return oldval; }
/** Helper: Look up and return an entry in the map of directory requests * using <b>type</b> and <b>dirreq_id</b> as key parts. If there * is no such entry, return NULL. */ static dirreq_map_entry_t * dirreq_map_get_(dirreq_type_t type, uint64_t dirreq_id) { dirreq_map_entry_t lookup; lookup.type = type; lookup.dirreq_id = dirreq_id; return HT_FIND(dirreqmap, &dirreq_map, &lookup); }
int sandbox_getaddrinfo(const char *name, const char *servname, const struct addrinfo *hints, struct addrinfo **res) { int err; struct cached_getaddrinfo_item_t search, *item; if (servname != NULL) { log_warn(LD_BUG, "called with non-NULL servname"); return EAI_NONAME; } if (name == NULL) { log_warn(LD_BUG, "called with NULL name"); return EAI_NONAME; } *res = NULL; memset(&search, 0, sizeof(search)); search.name = (char *) name; search.family = hints ? hints->ai_family : AF_UNSPEC; item = HT_FIND(getaddrinfo_cache, &getaddrinfo_cache, &search); if (! sandbox_is_active()) { /* If the sandbox is not turned on yet, then getaddrinfo and store the result. */ err = getaddrinfo(name, NULL, hints, res); log_info(LD_NET,"(Sandbox) getaddrinfo %s.", err ? "failed" : "succeeded"); if (! item) { item = tor_malloc_zero(sizeof(*item)); item->name = tor_strdup(name); item->family = hints ? hints->ai_family : AF_UNSPEC; HT_INSERT(getaddrinfo_cache, &getaddrinfo_cache, item); } if (item->res) { freeaddrinfo(item->res); item->res = NULL; } item->res = *res; item->err = err; return err; } /* Otherwise, the sanbox is on. If we have an item, yield its cached result. */ if (item) { *res = item->res; return item->err; } /* getting here means something went wrong */ log_err(LD_BUG,"(Sandbox) failed to get address %s!", name); return EAI_NONAME; }
/** Helper: given a SSL* pointer, return the tor_tls_t object using that * pointer. */ static INLINE tor_tls_t * tor_tls_get_by_ssl(const SSL *ssl) { tor_tls_t search, *result; memset(&search, 0, sizeof(search)); search.ssl = (SSL*)ssl; result = HT_FIND(tlsmap, &tlsmap_root, &search); return result; }
/** Return the circuit from the circuitmap with token <b>search_token</b>. */ static circuit_t * get_circuit_with_token(hs_token_t *search_token) { tor_assert(the_hs_circuitmap); /* We use a dummy circuit object for the hash table search routine. */ circuit_t search_circ; search_circ.hs_token = search_token; return HT_FIND(hs_circuitmap_ht, the_hs_circuitmap, &search_circ); }
/** As node_get_by_id, but returns a non-const pointer */ node_t * node_get_mutable_by_id(const char *identity_digest) { node_t search, *node; if (PREDICT_UNLIKELY(the_nodelist == NULL)) return NULL; memcpy(&search.identity, identity_digest, DIGEST_LEN); node = HT_FIND(nodelist_map, &the_nodelist->nodes_by_id, &search); return node; }
/** Note that we've seen a client connect from the IP <b>addr</b> * at time <b>now</b>. Ignored by all but bridges and directories if * configured accordingly. */ void geoip_note_client_seen(geoip_client_action_t action, const tor_addr_t *addr, time_t now) { const or_options_t *options = get_options(); clientmap_entry_t lookup, *ent; if (action == GEOIP_CLIENT_CONNECT) { /* Only remember statistics as entry guard or as bridge. */ if (!options->EntryStatistics && (!(options->BridgeRelay && options->BridgeRecordUsageByCountry))) return; } else { if (options->BridgeRelay || options->BridgeAuthoritativeDir || !options->DirReqStatistics) return; } tor_addr_copy(&lookup.addr, addr); lookup.action = (int)action; ent = HT_FIND(clientmap, &client_history, &lookup); if (! ent) { ent = tor_malloc_zero(sizeof(clientmap_entry_t)); tor_addr_copy(&ent->addr, addr); ent->action = (int)action; HT_INSERT(clientmap, &client_history, ent); } if (now / 60 <= (int)MAX_LAST_SEEN_IN_MINUTES && now >= 0) ent->last_seen_in_minutes = (unsigned)(now/60); else ent->last_seen_in_minutes = 0; if (action == GEOIP_CLIENT_NETWORKSTATUS || action == GEOIP_CLIENT_NETWORKSTATUS_V2) { int country_idx = geoip_get_country_by_addr(addr); if (country_idx < 0) country_idx = 0; /** unresolved requests are stored at index 0. */ if (country_idx >= 0 && country_idx < smartlist_len(geoip_countries)) { geoip_country_t *country = smartlist_get(geoip_countries, country_idx); if (action == GEOIP_CLIENT_NETWORKSTATUS) ++country->n_v3_ns_requests; else ++country->n_v2_ns_requests; } /* Periodically determine share of requests that we should see */ if (last_time_determined_shares + REQUEST_SHARE_INTERVAL < now) geoip_determine_shares(now); } }
/** Set the current value for <b>key</b> to <b>val</b>. Returns the previous * value for <b>key</b> if one was set, or NULL if one was not. * * This function makes a copy of <b>key</b> if necessary, but not of * <b>val</b>. */ void * strmap_set(strmap_t *map, const char *key, void *val) { strmap_entry_t *resolve; strmap_entry_t search; void *oldval; tor_assert(map); tor_assert(key); tor_assert(val); search.key = (char*)key; resolve = HT_FIND(strmap_impl, &map->head, &search); if (resolve) { oldval = resolve->val; resolve->val = val; return oldval; } else { resolve = tor_malloc_zero(sizeof(strmap_entry_t)); resolve->key = tor_strdup(key); resolve->val = val; tor_assert(!HT_FIND(strmap_impl, &map->head, resolve)); HT_INSERT(strmap_impl, &map->head, resolve); return NULL; } }
void * fp_pair_map_get(const fp_pair_map_t *map, const fp_pair_t *key) { fp_pair_map_entry_t *resolve; fp_pair_map_entry_t search; void *val = NULL; tor_assert(map); tor_assert(key); memcpy(&(search.key), key, sizeof(*key)); resolve = HT_FIND(fp_pair_map_impl, &(map->head), &search); if (resolve) val = resolve->val; return val; }
/** Return a circ such that: * - circ-\>n_circ_id or circ-\>p_circ_id is equal to <b>circ_id</b>, and * - circ is attached to <b>conn</b>, either as p_conn or n_conn. * Return NULL if no such circuit exists. */ static INLINE circuit_t * circuit_get_by_circid_orconn_impl(circid_t circ_id, or_connection_t *conn) { orconn_circid_circuit_map_t search; orconn_circid_circuit_map_t *found; if (_last_circid_orconn_ent && circ_id == _last_circid_orconn_ent->circ_id && conn == _last_circid_orconn_ent->or_conn) { found = _last_circid_orconn_ent; } else { search.circ_id = circ_id; search.or_conn = conn; found = HT_FIND(orconn_circid_map, &orconn_circid_circuit_map, &search); _last_circid_orconn_ent = found; } if (found && found->circuit) return found->circuit; return NULL; /* The rest of this checks for bugs. Disabled by default. */ { circuit_t *circ; for (circ=global_circuitlist;circ;circ = circ->next) { if (! CIRCUIT_IS_ORIGIN(circ)) { or_circuit_t *or_circ = TO_OR_CIRCUIT(circ); if (or_circ->p_conn == conn && or_circ->p_circ_id == circ_id) { log_warn(LD_BUG, "circuit matches p_conn, but not in hash table (Bug!)"); return circ; } } if (circ->n_conn == conn && circ->n_circ_id == circ_id) { log_warn(LD_BUG, "circuit matches n_conn, but not in hash table (Bug!)"); return circ; } } return NULL; } }
/** Like strmap_set() above but for digestmaps. */ void * digestmap_set(digestmap_t *map, const char *key, void *val) { #ifndef OPTIMIZED_DIGESTMAP_SET digestmap_entry_t *resolve; #endif digestmap_entry_t search; void *oldval; tor_assert(map); tor_assert(key); tor_assert(val); memcpy(&search.key, key, DIGEST_LEN); #ifndef OPTIMIZED_DIGESTMAP_SET resolve = HT_FIND(digestmap_impl, &map->head, &search); if (resolve) { oldval = resolve->val; resolve->val = val; return oldval; } else { resolve = tor_malloc_zero(sizeof(digestmap_entry_t)); memcpy(resolve->key, key, DIGEST_LEN); resolve->val = val; HT_INSERT(digestmap_impl, &map->head, resolve); return NULL; } #else /* We spend up to 5% of our time in this function, so the code below is * meant to optimize the check/alloc/set cycle by avoiding the two trips to * the hash table that we do in the unoptimized code above. (Each of * HT_INSERT and HT_FIND calls HT_SET_HASH and HT_FIND_P.) */ _HT_FIND_OR_INSERT(digestmap_impl, node, digestmap_entry_hash, &(map->head), digestmap_entry_t, &search, ptr, { /* we found an entry. */ oldval = (*ptr)->val; (*ptr)->val = val; return oldval; },
rcb_t *load_get_chunks(const char *get_chunk_file, int *cnt) { FILE *fp = NULL; char buff[GET_LINE_LEN + 1]; uint8_t hash[SHA1_HASH_SIZE]; //original hash, not hash string uint32_t wr_chk_id; chunk_map_t *map; int req_cnt = 0; rcb_t *head = NULL; rcb_t *p = NULL; fp = fopen(get_chunk_file, "r"); if(!fp) { return NULL; } // load the chunks while(NULL != fgets(buff, GET_LINE_LEN + 1, fp)) { char *str; p = create_rcb(); if(NULL == p) goto err; str = strtok(buff, " \n"); if(NULL == str) goto err; if(0 != str_to_uint32(buff, &wr_chk_id)) goto err; p->wr_chk_id = wr_chk_id; str = strtok(NULL, " \n"); if(NULL == str) goto err; if(strlen(str) != SHA1_HASH_SIZE * 2) goto err; hex2binary(str, SHA1_HASH_SIZE * 2, hash); HT_FIND(&g_chunkmap_ht, chunk_map_t, hash, hash, map); if(!map) { free(p); } else { p->chk_map = map; p->next = head; head = p; req_cnt++; } } fclose(fp); *cnt = req_cnt; return head; err: if(fp) fclose(fp); if(p) free(p); *cnt = req_cnt; return head; }
/** Implementation helper for circuit_set_{p,n}_circid_orconn: A circuit ID * and/or or_connection for circ has just changed from <b>old_conn, old_id</b> * to <b>conn, id</b>. Adjust the conn,circid map as appropriate, removing * the old entry (if any) and adding a new one. If <b>active</b> is true, * remove the circuit from the list of active circuits on old_conn and add it * to the list of active circuits on conn. * XXX "active" isn't an arg anymore */ static void circuit_set_circid_orconn_helper(circuit_t *circ, int direction, circid_t id, or_connection_t *conn) { orconn_circid_circuit_map_t search; orconn_circid_circuit_map_t *found; or_connection_t *old_conn, **conn_ptr; circid_t old_id, *circid_ptr; int was_active, make_active; if (direction == CELL_DIRECTION_OUT) { conn_ptr = &circ->n_conn; circid_ptr = &circ->n_circ_id; was_active = circ->next_active_on_n_conn != NULL; make_active = circ->n_conn_cells.n > 0; } else { or_circuit_t *c = TO_OR_CIRCUIT(circ); conn_ptr = &c->p_conn; circid_ptr = &c->p_circ_id; was_active = c->next_active_on_p_conn != NULL; make_active = c->p_conn_cells.n > 0; } old_conn = *conn_ptr; old_id = *circid_ptr; if (id == old_id && conn == old_conn) return; if (_last_circid_orconn_ent && ((old_id == _last_circid_orconn_ent->circ_id && old_conn == _last_circid_orconn_ent->or_conn) || (id == _last_circid_orconn_ent->circ_id && conn == _last_circid_orconn_ent->or_conn))) { _last_circid_orconn_ent = NULL; } if (old_conn) { /* we may need to remove it from the conn-circid map */ tor_assert(old_conn->_base.magic == OR_CONNECTION_MAGIC); search.circ_id = old_id; search.or_conn = old_conn; found = HT_REMOVE(orconn_circid_map, &orconn_circid_circuit_map, &search); if (found) { tor_free(found); --old_conn->n_circuits; } if (was_active && old_conn != conn) make_circuit_inactive_on_conn(circ,old_conn); } /* Change the values only after we have possibly made the circuit inactive * on the previous conn. */ *conn_ptr = conn; *circid_ptr = id; if (conn == NULL) return; /* now add the new one to the conn-circid map */ search.circ_id = id; search.or_conn = conn; found = HT_FIND(orconn_circid_map, &orconn_circid_circuit_map, &search); if (found) { found->circuit = circ; } else { found = tor_malloc_zero(sizeof(orconn_circid_circuit_map_t)); found->circ_id = id; found->or_conn = conn; found->circuit = circ; HT_INSERT(orconn_circid_map, &orconn_circid_circuit_map, found); } if (make_active && old_conn != conn) make_circuit_active_on_conn(circ,conn); ++conn->n_circuits; }
memmove(&c->n_v3_ns_requests[0], &c->n_v3_ns_requests[1], sizeof(uint32_t)*(REQUEST_HIST_LEN-1)); c->n_v2_ns_requests[REQUEST_HIST_LEN-1] = 0; c->n_v3_ns_requests[REQUEST_HIST_LEN-1] = 0; }); current_request_period_starts += REQUEST_HIST_PERIOD; if (n_old_request_periods < REQUEST_HIST_LEN-1) ++n_old_request_periods; } /* We use the low 3 bits of the time to encode the action. Since we're * potentially remembering tons of clients, we don't want to make * clientmap_entry_t larger than it has to be. */ now = (now & ~ACTION_MASK) | (((int)action) & ACTION_MASK); lookup.ipaddr = addr; ent = HT_FIND(clientmap, &client_history, &lookup); if (ent) { ent->last_seen = now; } else { ent = tor_malloc_zero(sizeof(clientmap_entry_t)); ent->ipaddr = addr; ent->last_seen = now; HT_INSERT(clientmap, &client_history, ent); } if (action == GEOIP_CLIENT_NETWORKSTATUS || action == GEOIP_CLIENT_NETWORKSTATUS_V2) { int country_idx = geoip_get_country_by_ip(addr); if (country_idx >= 0 && country_idx < smartlist_len(geoip_countries)) { geoip_country_t *country = smartlist_get(geoip_countries, country_idx); if (action == GEOIP_CLIENT_NETWORKSTATUS)