4 #include <trust_router/tr_name.h>
5 #include <trp_internal.h>
6 #include <trp_rtable.h>
9 /* Note: be careful mixing talloc with glib. */
11 static int trp_rentry_destructor(void *obj)
13 TRP_RENTRY *entry=talloc_get_type_abort(obj, TRP_RENTRY);
15 tr_free_name(entry->apc);
16 if (entry->realm!=NULL)
17 tr_free_name(entry->realm);
18 if (entry->trust_router!=NULL)
19 tr_free_name(entry->trust_router);
20 if (entry->peer!=NULL)
21 tr_free_name(entry->peer);
22 if (entry->next_hop!=NULL)
23 tr_free_name(entry->next_hop);
27 TRP_RENTRY *trp_rentry_new(TALLOC_CTX *mem_ctx)
29 TRP_RENTRY *entry=talloc(mem_ctx, TRP_RENTRY);
33 entry->trust_router=NULL;
37 entry->expiry=talloc(entry, struct timespec);
38 if (entry->expiry==NULL) {
42 talloc_set_destructor((void *)entry, trp_rentry_destructor);
47 void trp_rentry_free(TRP_RENTRY *entry)
53 void trp_rentry_set_apc(TRP_RENTRY *entry, TR_NAME *apc)
58 TR_NAME *trp_rentry_get_apc(TRP_RENTRY *entry)
63 void trp_rentry_set_realm(TRP_RENTRY *entry, TR_NAME *realm)
68 TR_NAME *trp_rentry_get_realm(TRP_RENTRY *entry)
73 void trp_rentry_set_trust_router(TRP_RENTRY *entry, TR_NAME *tr)
75 entry->trust_router=tr;
78 TR_NAME *trp_rentry_get_trust_router(TRP_RENTRY *entry)
80 return entry->trust_router;
83 void trp_rentry_set_peer(TRP_RENTRY *entry, TR_NAME *peer)
88 TR_NAME *trp_rentry_get_peer(TRP_RENTRY *entry)
93 void trp_rentry_set_metric(TRP_RENTRY *entry, unsigned int metric)
98 unsigned int trp_rentry_get_metric(TRP_RENTRY *entry)
100 return entry->metric;
103 void trp_rentry_set_next_hop(TRP_RENTRY *entry, TR_NAME *next_hop)
105 entry->next_hop=next_hop;
108 TR_NAME *trp_rentry_get_next_hop(TRP_RENTRY *entry)
110 return entry->next_hop;
113 void trp_rentry_set_selected(TRP_RENTRY *entry, int sel)
118 int trp_rentry_get_selected(TRP_RENTRY *entry)
120 return entry->selected;
123 /* copies incoming value, does not assume responsibility for freeing */
124 void trp_rentry_set_expiry(TRP_RENTRY *entry, struct timespec *exp)
126 entry->expiry->tv_sec=exp->tv_sec;
127 entry->expiry->tv_nsec=exp->tv_nsec;
130 struct timespec *trp_rentry_get_expiry(TRP_RENTRY *entry)
132 return entry->expiry;
136 /* result must be freed with g_free */
137 static gchar *tr_name_to_g_str(const TR_NAME *n)
139 gchar *s=g_strndup(n->buf, n->len);
143 /* hash function for TR_NAME keys */
144 static guint trp_tr_name_hash(gconstpointer key)
146 const TR_NAME *name=(TR_NAME *)key;
147 gchar *s=tr_name_to_g_str(name);
148 guint hash=g_str_hash(s);
153 /* hash equality function for TR_NAME keys */
154 static gboolean trp_tr_name_equal(gconstpointer key1, gconstpointer key2)
156 const TR_NAME *n1=(TR_NAME *)key1;
157 const TR_NAME *n2=(TR_NAME *)key2;
158 gchar *s1=tr_name_to_g_str(n1);
159 gchar *s2=tr_name_to_g_str(n2);
160 gboolean equal=g_str_equal(s1, s2);
166 /* free a value to the top level rtable (a hash of all entries in the apc) */
167 static void trp_rtable_destroy_table(gpointer data)
169 g_hash_table_destroy(data);
172 static void trp_rtable_destroy_rentry(gpointer data)
174 trp_rentry_free(data);
177 static void trp_rtable_destroy_tr_name(gpointer data)
182 TRP_RTABLE *trp_rtable_new(void)
184 GHashTable *new=g_hash_table_new_full(trp_tr_name_hash,
186 trp_rtable_destroy_tr_name,
187 trp_rtable_destroy_table);
191 void trp_rtable_free(TRP_RTABLE *rtbl)
193 g_hash_table_destroy(rtbl);
196 static GHashTable *trp_rtbl_get_or_add_table(GHashTable *tbl, TR_NAME *key, GDestroyNotify destroy)
198 GHashTable *val_tbl=NULL;
200 val_tbl=g_hash_table_lookup(tbl, key);
202 val_tbl=g_hash_table_new_full(trp_tr_name_hash,
204 trp_rtable_destroy_tr_name,
206 g_hash_table_insert(tbl, tr_dup_name(key), val_tbl);
211 void trp_rtable_add(TRP_RTABLE *rtbl, TRP_RENTRY *entry)
213 GHashTable *apc_tbl=NULL;
214 GHashTable *realm_tbl=NULL;
216 apc_tbl=trp_rtbl_get_or_add_table(rtbl, entry->apc, trp_rtable_destroy_table);
217 realm_tbl=trp_rtbl_get_or_add_table(apc_tbl, entry->realm, trp_rtable_destroy_rentry);
218 g_hash_table_insert(realm_tbl, tr_dup_name(entry->peer), entry); /* destroys and replaces a duplicate */
221 /* note: the entry pointer passed in is invalid after calling this because the entry is freed */
222 void trp_rtable_remove(TRP_RTABLE *rtbl, TRP_RENTRY *entry)
224 GHashTable *apc_tbl=NULL;
225 GHashTable *realm_tbl=NULL;
227 apc_tbl=g_hash_table_lookup(rtbl, entry->apc);
231 realm_tbl=g_hash_table_lookup(apc_tbl, entry->realm);
235 /* remove the element */
236 g_hash_table_remove(realm_tbl, entry->peer);
237 /* if that was the last entry in the realm, remove the realm table */
238 if (g_hash_table_size(realm_tbl)==0)
239 g_hash_table_remove(apc_tbl, entry->realm);
240 /* if that was the last realm in the apc, remove the apc table */
241 if (g_hash_table_size(apc_tbl)==0)
242 g_hash_table_remove(rtbl, entry->apc);
245 /* gets the actual hash table, for internal use only */
246 static GHashTable *trp_rtable_get_apc_table(TRP_RTABLE *rtbl, TR_NAME *apc)
248 return g_hash_table_lookup(rtbl, apc);
251 /* gets the actual hash table, for internal use only */
252 static GHashTable *trp_rtable_get_realm_table(TRP_RTABLE *rtbl, TR_NAME *apc, TR_NAME *realm)
254 GHashTable *apc_tbl=trp_rtable_get_apc_table(rtbl, apc);
258 return g_hash_table_lookup(apc_tbl, realm);
261 struct table_size_cookie {
265 static void trp_rtable_size_helper(gpointer key, gpointer value, gpointer user_data)
267 struct table_size_cookie *data=(struct table_size_cookie *)user_data;
268 data->size += trp_rtable_apc_size(data->rtbl, (TR_NAME *)key);
270 size_t trp_rtable_size(TRP_RTABLE *rtbl)
272 struct table_size_cookie data={rtbl, 0};
273 g_hash_table_foreach(rtbl, trp_rtable_size_helper, &data);
277 struct table_apc_size_cookie {
282 static void table_apc_size_helper(gpointer key, gpointer value, gpointer user_data)
284 struct table_apc_size_cookie *data=(struct table_apc_size_cookie *)user_data;
285 data->size += trp_rtable_realm_size(data->rtbl, data->apc, (TR_NAME *)key);
287 size_t trp_rtable_apc_size(TRP_RTABLE *rtbl, TR_NAME *apc)
289 struct table_apc_size_cookie data={apc, rtbl, 0};
290 GHashTable *apc_tbl=trp_rtable_get_apc_table(rtbl, apc);
293 g_hash_table_foreach(apc_tbl, table_apc_size_helper, &data);
297 size_t trp_rtable_realm_size(TRP_RTABLE *rtbl, TR_NAME *apc, TR_NAME *realm)
299 GHashTable *realm_tbl=trp_rtable_get_realm_table(rtbl, apc, realm);
303 return g_hash_table_size(g_hash_table_lookup(
304 g_hash_table_lookup(rtbl, apc),
308 /* Returns an array of pointers to TRP_RENTRY, length of array in n_out.
309 * Caller must free the array (in the talloc NULL context), but must
310 * not free its contents. */
311 TRP_RENTRY **trp_rtable_get_entries(TRP_RTABLE *rtbl, size_t *n_out)
313 TRP_RENTRY **ret=NULL;
316 TRP_RENTRY **apc_entries=NULL;
320 *n_out=trp_rtable_size(rtbl);
324 ret=talloc_array(NULL, TRP_RENTRY *, *n_out);
326 tr_crit("trp_rtable_get_entries: unable to allocate return array.");
331 ii_ret=0; /* counts output entries */
332 apc=trp_rtable_get_apcs(rtbl, &n_apc);
334 apc_entries=trp_rtable_get_apc_entries(rtbl, apc[n_apc], &n_entries);
336 ret[ii_ret++]=apc_entries[n_entries];
337 talloc_free(apc_entries);
341 if (ii_ret!=*n_out) {
342 tr_crit("trp_rtable_get_entries: found incorrect number of entries.");
350 /* Returns an array of pointers to TR_NAME, length of array in n_out.
351 * Caller must free the array (in the talloc NULL context). */
352 TR_NAME **trp_rtable_get_apcs(TRP_RTABLE *rtbl, size_t *n_out)
354 size_t len=g_hash_table_size(rtbl); /* known apcs are keys in top level hash table */
365 ret=talloc_array(NULL, TR_NAME *, len);
367 tr_crit("trp_rtable_get_apcs: unable to allocate return array.");
371 apcs=g_hash_table_get_keys(rtbl);
372 for (ii=0,p=apcs; p!=NULL; ii++,p=g_list_next(p))
373 ret[ii]=(TR_NAME *)p->data;
381 /* Returns an array of pointers to TR_NAME, length of array in n_out.
382 * Caller must free the array (in the talloc NULL context). */
383 TR_NAME **trp_rtable_get_apc_realms(TRP_RTABLE *rtbl, TR_NAME *apc, size_t *n_out)
386 TRP_RTABLE *apc_tbl=g_hash_table_lookup(rtbl, apc);;
395 *n_out=g_hash_table_size(apc_tbl); /* set output length */
396 ret=talloc_array(NULL, TR_NAME *, *n_out);
397 entries=g_hash_table_get_keys(apc_tbl);
398 for (ii=0,p=entries; p!=NULL; ii++,p=g_list_next(p))
399 ret[ii]=(TR_NAME *)p->data;
401 g_list_free(entries);
405 /* Get all entries in an apc. Returns an array of pointers in NULL talloc context.
406 * Caller must free this list with talloc_free, but must not free the entries in the
408 TRP_RENTRY **trp_rtable_get_apc_entries(TRP_RTABLE *rtbl, TR_NAME *apc, size_t *n_out)
411 TR_NAME **realm=NULL;
413 TRP_RENTRY **realm_entries=NULL;
415 TRP_RENTRY **ret=NULL;
418 *n_out=trp_rtable_apc_size(rtbl, apc);
422 ret=talloc_array(NULL, TRP_RENTRY *, *n_out);
424 tr_crit("trp_rtable_get_apc_entries: could not allocate return array.");
429 ii_ret=0; /* counts entries in the output array */
430 realm=trp_rtable_get_apc_realms(rtbl, apc, &n_realms);
431 for (ii=0; ii<n_realms; ii++) {
432 realm_entries=trp_rtable_get_realm_entries(rtbl, apc, realm[ii], &n_entries);
433 for (jj=0; jj<n_entries; jj++)
434 ret[ii_ret++]=realm_entries[jj];
435 talloc_free(realm_entries);
439 if (ii_ret!=*n_out) {
440 tr_crit("trp_rtable_get_apc_entries: found incorrect number of entries.");
449 /* Get all entries in an apc/realm. Returns an array of pointers in NULL talloc context.
450 * Caller must free this list with talloc_free, but must not free the entries in the
452 TRP_RENTRY **trp_rtable_get_realm_entries(TRP_RTABLE *rtbl, TR_NAME *apc, TR_NAME *realm, size_t *n_out)
455 TRP_RENTRY **ret=NULL;
458 peer=trp_rtable_get_apc_realm_peers(rtbl, apc, realm, n_out);
459 ret=talloc_array(NULL, TRP_RENTRY *, *n_out);
461 tr_crit("trp_rtable_get_realm_entries: could not allocate return array.");
466 for (ii=0; ii<*n_out; ii++)
467 ret[ii]=trp_rtable_get_entry(rtbl, apc, realm, peer[ii]);
472 TR_NAME **trp_rtable_get_apc_realm_peers(TRP_RTABLE *rtbl, TR_NAME *apc, TR_NAME *realm, size_t *n_out)
475 GHashTable *realm_tbl=NULL;
480 *n_out=trp_rtable_realm_size(rtbl, apc, realm);
483 realm_tbl=trp_rtable_get_realm_table(rtbl, apc, realm);
484 ret=talloc_array(NULL, TR_NAME *, *n_out);
486 tr_crit("trp_rtable_get_apc_realm_peers: could not allocate return array.");
490 keys=g_hash_table_get_keys(realm_tbl);
491 for (ii=0,p=keys; p!=NULL; ii++,p=g_list_next(p))
492 ret[ii]=(TR_NAME *)p->data;
497 /* Gets a single entry. Do not free it. */
498 TRP_RENTRY *trp_rtable_get_entry(TRP_RTABLE *rtbl, TR_NAME *apc, TR_NAME *realm, TR_NAME *peer)
500 GHashTable *apc_tbl=NULL;
501 GHashTable *realm_tbl=NULL;
503 apc_tbl=g_hash_table_lookup(rtbl, apc);
506 realm_tbl=g_hash_table_lookup(apc_tbl, realm);
509 return g_hash_table_lookup(realm_tbl, peer); /* does not copy or increment ref count */