LCOV - code coverage report
Current view: top level - feature/dircommon - fp_pair.c (source / functions) Hit Total Coverage
Test: lcov.info Lines: 112 112 100.0 %
Date: 2021-11-24 03:28:48 Functions: 28 28 100.0 %

          Line data    Source code
       1             : /* Copyright (c) 2013-2021, The Tor Project, Inc. */
       2             : /* See LICENSE for licensing information */
       3             : 
       4             : /**
       5             :  * \file fp_pair.c
       6             :  *
       7             :  * \brief Manages data structures for associating pairs of fingerprints. Used
       8             :  * to handle combinations of identity/signing-key fingerprints for
       9             :  * authorities.
      10             :  *
      11             :  * This is a nice, simple, compact data structure module that handles a map
      12             :  * from (signing key fingerprint, identity key fingerprint) to void *.  The
      13             :  * fingerprints here are SHA1 digests of RSA keys.
      14             :  *
      15             :  * This structure is used in directory.c and in routerlist.c for handling
      16             :  * handling authority certificates, since we never want more than a single
      17             :  * certificate for any (ID key, signing key) pair.
      18             :  **/
      19             : 
      20             : #include "core/or/or.h"
      21             : #include "feature/dircommon/fp_pair.h"
      22             : 
      23             : /* Define fp_pair_map_t structures */
      24             : 
      25             : struct fp_pair_map_entry_t {
      26             :   HT_ENTRY(fp_pair_map_entry_t) node;
      27             :   void *val;
      28             :   fp_pair_t key;
      29             : };
      30             : 
      31             : struct fp_pair_map_t {
      32             :   HT_HEAD(fp_pair_map_impl, fp_pair_map_entry_t) head;
      33             : };
      34             : 
      35             : /*
      36             :  * Hash function and equality checker for fp_pair_map_t
      37             :  */
      38             : 
      39             : /** Compare fp_pair_entry_t objects by key value. */
      40             : static inline int
      41          18 : fp_pair_map_entries_eq(const fp_pair_map_entry_t *a,
      42             :                        const fp_pair_map_entry_t *b)
      43             : {
      44          18 :   return tor_memeq(&(a->key), &(b->key), sizeof(fp_pair_t));
      45             : }
      46             : 
      47             : /** Return a hash value for an fp_pair_entry_t. */
      48             : static inline unsigned int
      49          47 : fp_pair_map_entry_hash(const fp_pair_map_entry_t *a)
      50             : {
      51          47 :   tor_assert(sizeof(a->key) == DIGEST_LEN*2);
      52          47 :   return (unsigned) siphash24g(&a->key, DIGEST_LEN*2);
      53             : }
      54             : 
      55             : /*
      56             :  * Hash table functions for fp_pair_map_t
      57             :  */
      58             : 
      59         169 : HT_PROTOTYPE(fp_pair_map_impl, fp_pair_map_entry_t, node,
      60             :              fp_pair_map_entry_hash, fp_pair_map_entries_eq);
      61         290 : HT_GENERATE2(fp_pair_map_impl, fp_pair_map_entry_t, node,
      62             :              fp_pair_map_entry_hash, fp_pair_map_entries_eq,
      63             :              0.6, tor_reallocarray_, tor_free_);
      64             : 
      65             : /** Constructor to create a new empty map from fp_pair_t to void *
      66             :  */
      67             : 
      68             : fp_pair_map_t *
      69           1 : fp_pair_map_new(void)
      70             : {
      71           1 :   fp_pair_map_t *result;
      72             : 
      73           1 :   result = tor_malloc(sizeof(fp_pair_map_t));
      74           1 :   HT_INIT(fp_pair_map_impl, &result->head);
      75           1 :   return result;
      76             : }
      77             : 
      78             : /** Set the current value for key to val; returns the previous
      79             :  * value for key if one was set, or NULL if one was not.
      80             :  */
      81             : 
      82             : void *
      83           8 : fp_pair_map_set(fp_pair_map_t *map, const fp_pair_t *key, void *val)
      84             : {
      85           8 :   fp_pair_map_entry_t *resolve;
      86           8 :   fp_pair_map_entry_t search;
      87           8 :   void *oldval;
      88             : 
      89           8 :   tor_assert(map);
      90           8 :   tor_assert(key);
      91           8 :   tor_assert(val);
      92             : 
      93           8 :   memcpy(&(search.key), key, sizeof(*key));
      94           8 :   resolve = HT_FIND(fp_pair_map_impl, &(map->head), &search);
      95           8 :   if (resolve) {
      96           1 :     oldval = resolve->val;
      97           1 :     resolve->val = val;
      98             :   } else {
      99           7 :     resolve = tor_malloc_zero(sizeof(fp_pair_map_entry_t));
     100           7 :     memcpy(&(resolve->key), key, sizeof(*key));
     101           7 :     resolve->val = val;
     102           7 :     HT_INSERT(fp_pair_map_impl, &(map->head), resolve);
     103           7 :     oldval = NULL;
     104             :   }
     105             : 
     106           8 :   return oldval;
     107             : }
     108             : 
     109             : /** Set the current value for the key (first, second) to val; returns
     110             :  * the previous value for key if one was set, or NULL if one was not.
     111             :  */
     112             : 
     113             : void *
     114           1 : fp_pair_map_set_by_digests(fp_pair_map_t *map,
     115             :                            const char *first, const char *second,
     116             :                            void *val)
     117             : {
     118           1 :   fp_pair_t k;
     119             : 
     120           1 :   tor_assert(first);
     121           1 :   tor_assert(second);
     122             : 
     123           1 :   memcpy(k.first, first, DIGEST_LEN);
     124           1 :   memcpy(k.second, second, DIGEST_LEN);
     125             : 
     126           1 :   return fp_pair_map_set(map, &k, val);
     127             : }
     128             : 
     129             : /** Return the current value associated with key, or NULL if no value is set.
     130             :  */
     131             : 
     132             : void *
     133          12 : fp_pair_map_get(const fp_pair_map_t *map, const fp_pair_t *key)
     134             : {
     135          12 :   fp_pair_map_entry_t *resolve;
     136          12 :   fp_pair_map_entry_t search;
     137          12 :   void *val = NULL;
     138             : 
     139          12 :   tor_assert(map);
     140          12 :   tor_assert(key);
     141             : 
     142          12 :   memcpy(&(search.key), key, sizeof(*key));
     143          12 :   resolve = HT_FIND(fp_pair_map_impl, &(map->head), &search);
     144          12 :   if (resolve) val = resolve->val;
     145             : 
     146          12 :   return val;
     147             : }
     148             : 
     149             : /** Return the current value associated the key (first, second), or
     150             :  * NULL if no value is set.
     151             :  */
     152             : 
     153             : void *
     154           1 : fp_pair_map_get_by_digests(const fp_pair_map_t *map,
     155             :                            const char *first, const char *second)
     156             : {
     157           1 :   fp_pair_t k;
     158             : 
     159           1 :   tor_assert(first);
     160           1 :   tor_assert(second);
     161             : 
     162           1 :   memcpy(k.first, first, DIGEST_LEN);
     163           1 :   memcpy(k.second, second, DIGEST_LEN);
     164             : 
     165           1 :   return fp_pair_map_get(map, &k);
     166             : }
     167             : 
     168             : /** Remove the value currently associated with key from the map.
     169             :  * Return the value if one was set, or NULL if there was no entry for
     170             :  * key.  The caller must free any storage associated with the
     171             :  * returned value.
     172             :  */
     173             : 
     174             : void *
     175           2 : fp_pair_map_remove(fp_pair_map_t *map, const fp_pair_t *key)
     176             : {
     177           2 :   fp_pair_map_entry_t *resolve;
     178           2 :   fp_pair_map_entry_t search;
     179           2 :   void *val = NULL;
     180             : 
     181           2 :   tor_assert(map);
     182           2 :   tor_assert(key);
     183             : 
     184           2 :   memcpy(&(search.key), key, sizeof(*key));
     185           2 :   resolve = HT_REMOVE(fp_pair_map_impl, &(map->head), &search);
     186           2 :   if (resolve) {
     187           1 :     val = resolve->val;
     188           1 :     tor_free(resolve);
     189             :   }
     190             : 
     191           2 :   return val;
     192             : }
     193             : 
     194             : /** Remove all entries from map, and deallocate storage for those entries.
     195             :  * If free_val is provided, it is invoked on every value in map.
     196             :  */
     197             : 
     198             : void
     199           1 : fp_pair_map_free_(fp_pair_map_t *map, void (*free_val)(void*))
     200             : {
     201           1 :   fp_pair_map_entry_t **ent, **next, *this;
     202             : 
     203           1 :   if (map) {
     204           1 :     for (ent = HT_START(fp_pair_map_impl, &(map->head));
     205           6 :          ent != NULL; ent = next) {
     206           5 :       this = *ent;
     207           5 :       next = HT_NEXT_RMV(fp_pair_map_impl, &(map->head), ent);
     208           5 :       if (free_val) free_val(this->val);
     209           5 :       tor_free(this);
     210             :     }
     211           1 :     tor_assert(HT_EMPTY(&(map->head)));
     212           1 :     HT_CLEAR(fp_pair_map_impl, &(map->head));
     213           1 :     tor_free(map);
     214             :   }
     215           1 : }
     216             : 
     217             : /** Return true iff map has no entries.
     218             :  */
     219             : 
     220             : int
     221           2 : fp_pair_map_isempty(const fp_pair_map_t *map)
     222             : {
     223           2 :   tor_assert(map);
     224             : 
     225           2 :   return HT_EMPTY(&(map->head));
     226             : }
     227             : 
     228             : /** Return the number of items in map.
     229             :  */
     230             : 
     231             : int
     232           2 : fp_pair_map_size(const fp_pair_map_t *map)
     233             : {
     234           2 :   tor_assert(map);
     235             : 
     236           2 :   return HT_SIZE(&(map->head));
     237             : }
     238             : 
     239             : /** return an iterator pointing to the start of map.
     240             :  */
     241             : 
     242             : fp_pair_map_iter_t *
     243           1 : fp_pair_map_iter_init(fp_pair_map_t *map)
     244             : {
     245           1 :   tor_assert(map);
     246             : 
     247           1 :   return HT_START(fp_pair_map_impl, &(map->head));
     248             : }
     249             : 
     250             : /** Advance iter a single step to the next entry of map, and return
     251             :  * its new value.
     252             :  */
     253             : 
     254             : fp_pair_map_iter_t *
     255           5 : fp_pair_map_iter_next(fp_pair_map_t *map, fp_pair_map_iter_t *iter)
     256             : {
     257           5 :   tor_assert(map);
     258           5 :   tor_assert(iter);
     259             : 
     260           5 :   return HT_NEXT(fp_pair_map_impl, &(map->head), iter);
     261             : }
     262             : 
     263             : /** Advance iter a single step to the next entry of map, removing the current
     264             :  * entry, and return its new value.
     265             :  */
     266             : 
     267             : fp_pair_map_iter_t *
     268           1 : fp_pair_map_iter_next_rmv(fp_pair_map_t *map, fp_pair_map_iter_t *iter)
     269             : {
     270           1 :   fp_pair_map_entry_t *rmv;
     271             : 
     272           1 :   tor_assert(map);
     273           1 :   tor_assert(iter);
     274           1 :   tor_assert(*iter);
     275             : 
     276           1 :   rmv = *iter;
     277           1 :   iter = HT_NEXT_RMV(fp_pair_map_impl, &(map->head), iter);
     278           1 :   tor_free(rmv);
     279             : 
     280           1 :   return iter;
     281             : }
     282             : 
     283             : /** Set *key_out and *val_out to the current entry pointed to by iter.
     284             :  */
     285             : 
     286             : void
     287           6 : fp_pair_map_iter_get(fp_pair_map_iter_t *iter,
     288             :                      fp_pair_t *key_out, void **val_out)
     289             : {
     290           6 :   tor_assert(iter);
     291           6 :   tor_assert(*iter);
     292             : 
     293           6 :   if (key_out) memcpy(key_out, &((*iter)->key), sizeof(fp_pair_t));
     294           6 :   if (val_out) *val_out = (*iter)->val;
     295           6 : }
     296             : 
     297             : /** Return true iff iter has advanced past the last entry of its map.
     298             :  */
     299             : 
     300             : int
     301           7 : fp_pair_map_iter_done(fp_pair_map_iter_t *iter)
     302             : {
     303           7 :   return (iter == NULL);
     304             : }
     305             : 
     306             : /** Assert if anything has gone wrong with the internal
     307             :  * representation of map.
     308             :  */
     309             : 
     310             : void
     311           5 : fp_pair_map_assert_ok(const fp_pair_map_t *map)
     312             : {
     313           5 :   tor_assert(!fp_pair_map_impl_HT_REP_IS_BAD_(&(map->head)));
     314           5 : }

Generated by: LCOV version 1.14