98898ff34f3ff69fcbf418c026f23b88e4628950
[trust_router.git] / trp / trp_upd.c
1 /*
2  * Copyright (c) 2016, JANET(UK)
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  *
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  *
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  *
16  * 3. Neither the name of JANET(UK) nor the names of its contributors
17  *    may be used to endorse or promote products derived from this software
18  *    without specific prior written permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
23  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
24  * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
25  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
26  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
27  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
29  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
31  * OF THE POSSIBILITY OF SUCH DAMAGE.
32  *
33  */
34
35 #include <jansson.h>
36 #include <talloc.h>
37
38 #include <trust_router/tr_name.h>
39 #include <trp_internal.h>
40 #include <tr_comm.h>
41 #include <tr_apc.h>
42 #include <tr_debug.h>
43
44
45 /* static prototypes */
46 static TRP_INFOREC_DATA *trp_inforec_route_new(TALLOC_CTX *mem_ctx);
47 static void trp_inforec_route_print(TRP_INFOREC_DATA *);
48 static TRP_INFOREC_DATA *trp_inforec_comm_new(TALLOC_CTX *mem_ctx);
49 static void trp_inforec_comm_print(TRP_INFOREC_DATA *);
50
51
52 struct trp_inforec_type_entry {
53   const char *name;
54   TRP_INFOREC_TYPE type;
55   TRP_INFOREC_DATA *(*allocate)(TALLOC_CTX *);
56   void (*print)(TRP_INFOREC_DATA *);
57 };
58 static struct trp_inforec_type_entry trp_inforec_type_table[] = {
59   { "route", TRP_INFOREC_TYPE_ROUTE, trp_inforec_route_new, trp_inforec_route_print },
60   { "comm", TRP_INFOREC_TYPE_COMMUNITY, trp_inforec_comm_new, trp_inforec_comm_print },
61   { NULL, TRP_INFOREC_TYPE_UNKNOWN, NULL, NULL } /* must be the last entry */
62 };
63
64
65 /* look up an entry in the trp_inforec_type_table */
66 static struct trp_inforec_type_entry *get_trp_inforec_type_entry(TRP_INFOREC_TYPE msgtype)
67 {
68   struct trp_inforec_type_entry *entry=trp_inforec_type_table;
69
70   while ((entry->type != TRP_INFOREC_TYPE_UNKNOWN)
71         && (entry->type != msgtype)) {
72     entry ++;
73   }
74   return entry;
75 }
76
77 /* translate strings to codes */
78 TRP_INFOREC_TYPE trp_inforec_type_from_string(const char *s)
79 {
80   struct trp_inforec_type_entry *entry=trp_inforec_type_table;
81
82   while ((entry->type != TRP_INFOREC_TYPE_UNKNOWN)
83         && (strcmp(s, entry->name)!=0)) {
84     entry++;
85   }
86   return entry->type;
87 }
88 /* translate codes to strings (do not need to be freed) 
89  * Returns NULL on an unknown code */
90 const char *trp_inforec_type_to_string(TRP_INFOREC_TYPE msgtype)
91 {
92   struct trp_inforec_type_entry *entry=get_trp_inforec_type_entry(msgtype);
93   return entry->name;
94 }
95
96 /* called by talloc when destroying an update message body */
97 static int trp_inforec_route_destructor(void *object)
98 {
99   TRP_INFOREC_ROUTE *body=talloc_get_type_abort(object, TRP_INFOREC_ROUTE);
100   
101   /* clean up TR_NAME data, which are not managed by talloc */
102   if (body->trust_router != NULL)
103     tr_free_name(body->trust_router);
104   if (body->next_hop != NULL)
105     tr_free_name(body->next_hop);
106   return 0;
107 }
108
109 static TRP_INFOREC_DATA *trp_inforec_route_new(TALLOC_CTX *mem_ctx)
110 {
111   TRP_INFOREC_DATA *new_data=talloc(mem_ctx, TRP_INFOREC_DATA);
112   TRP_INFOREC_ROUTE *new_rec=NULL;
113
114   if (new_data==NULL)
115     return NULL;
116
117   new_rec=talloc(new_data, TRP_INFOREC_ROUTE);
118   if (new_rec == NULL) {
119     talloc_free(new_data);
120     new_data=NULL;
121   } else {
122     new_rec->trust_router=NULL;
123     new_rec->next_hop=NULL;
124     new_rec->next_hop_port=0;
125     new_rec->metric=TRP_METRIC_INFINITY;
126     new_rec->interval=0;
127     talloc_set_destructor((void *)new_rec, trp_inforec_route_destructor);
128     new_data->route=new_rec;
129   }
130     
131   return new_data;
132 }
133
134
135 static int trp_inforec_comm_destructor(void *obj)
136 {
137   TRP_INFOREC_COMM *rec=talloc_get_type_abort(obj, TRP_INFOREC_COMM);
138   if (rec->owner_realm!=NULL)
139     tr_free_name(rec->owner_realm);
140   if (rec->owner_contact!=NULL)
141     tr_free_name(rec->owner_contact);
142   if (rec->provenance!=NULL)
143     json_decref(rec->provenance);
144   return 0;
145 }
146
147 static TRP_INFOREC_DATA *trp_inforec_comm_new(TALLOC_CTX *mem_ctx)
148 {
149   TRP_INFOREC_DATA *new_data=talloc(mem_ctx, TRP_INFOREC_DATA);
150   TRP_INFOREC_COMM *new_rec=NULL;
151
152   if (new_data==NULL)
153     return NULL;
154
155   new_rec=talloc(new_data, TRP_INFOREC_COMM);
156   if (new_rec==NULL) {
157     talloc_free(new_data);
158     new_data=NULL;
159   } else {
160     new_rec->comm_type=TR_COMM_UNKNOWN;
161     new_rec->role=TR_ROLE_UNKNOWN;
162     new_rec->apcs=NULL;
163     new_rec->owner_realm=NULL;
164     new_rec->owner_contact=NULL;
165     new_rec->expiration_interval=0;
166     new_rec->provenance=NULL;
167     new_rec->interval=0;
168     talloc_set_destructor((void *)new_rec, trp_inforec_comm_destructor);
169     new_data->comm=new_rec;
170   }
171
172   return new_data;
173 }
174
175 TRP_INFOREC *trp_inforec_get_next(TRP_INFOREC *rec)
176 {
177   if (rec!=NULL)
178     return rec->next;
179   else
180     return NULL;
181 }
182
183 static TRP_INFOREC *trp_inforec_get_tail(TRP_INFOREC *rec)
184 {
185   while ((rec->next)!=NULL)
186     rec=trp_inforec_get_next(rec);
187   return rec;
188 }
189
190 void trp_inforec_set_next(TRP_INFOREC *rec, TRP_INFOREC *next_rec)
191 {
192   if (rec !=NULL)
193     rec->next=next_rec;
194 }
195
196 TRP_INFOREC_TYPE trp_inforec_get_type(TRP_INFOREC *rec)
197 {
198   if (rec!=NULL)
199     return rec->type;
200   else
201     return TRP_INFOREC_TYPE_UNKNOWN;
202 }
203
204 void trp_inforec_set_type(TRP_INFOREC *rec, TRP_INFOREC_TYPE type)
205 {
206   if (rec!=NULL)
207     rec->type=type;
208 }
209
210 TR_NAME *trp_inforec_get_trust_router(TRP_INFOREC *rec)
211 {
212   switch (rec->type) {
213   case TRP_INFOREC_TYPE_ROUTE:
214     if (rec->data->route!=NULL)
215       return rec->data->route->trust_router;
216     break;
217   default:
218     break;
219   }
220   return NULL;
221 }
222
223 TR_NAME *trp_inforec_dup_trust_router(TRP_INFOREC *rec)
224 {
225   return tr_dup_name(trp_inforec_get_trust_router(rec));
226 }
227
228 TRP_RC trp_inforec_set_trust_router(TRP_INFOREC *rec, TR_NAME *trust_router)
229 {
230   switch (rec->type) {
231   case TRP_INFOREC_TYPE_ROUTE:
232     if (rec->data->route!=NULL) {
233       rec->data->route->trust_router=trust_router;
234       return TRP_SUCCESS;
235     }
236     break;
237   default:
238     break;
239   }
240   return TRP_ERROR;
241 }
242
243 /* TODO: need to return hostname/port --jlr */
244 TR_NAME *trp_inforec_get_next_hop(TRP_INFOREC *rec)
245 {
246   switch (rec->type) {
247   case TRP_INFOREC_TYPE_ROUTE:
248     if (rec->data->route!=NULL)
249       return rec->data->route->next_hop;
250     break;
251   default:
252     break;
253   }
254   return NULL;
255 }
256
257 TR_NAME *trp_inforec_dup_next_hop(TRP_INFOREC *rec)
258 {
259   return tr_dup_name(trp_inforec_get_next_hop(rec));
260 }
261
262 TRP_RC trp_inforec_set_next_hop(TRP_INFOREC *rec, TR_NAME *next_hop)
263 {
264   switch (rec->type) {
265   case TRP_INFOREC_TYPE_ROUTE:
266     if (rec->data->route==NULL)
267       return TRP_ERROR;
268     rec->data->route->next_hop=next_hop;
269     break;
270   case TRP_INFOREC_TYPE_COMMUNITY:
271     /* next hop not used for community records */
272     break;
273   default:
274     break;
275   }
276   return TRP_SUCCESS;
277 }
278
279 unsigned int trp_inforec_get_metric(TRP_INFOREC *rec)
280 {
281   switch (rec->type) {
282   case TRP_INFOREC_TYPE_ROUTE:
283     if (rec->data->route!=NULL)
284       return rec->data->route->metric;
285     break;
286   default:
287     break;
288   }
289   return TRP_METRIC_INVALID;
290 }
291
292 TRP_RC trp_inforec_set_metric(TRP_INFOREC *rec, unsigned int metric)
293 {
294   switch (rec->type) {
295   case TRP_INFOREC_TYPE_ROUTE:
296     if (rec->data->route!=NULL) {
297       rec->data->route->metric=metric;
298       return TRP_SUCCESS;
299     }
300     break;
301   default:
302     break;
303   }
304   return TRP_ERROR;
305 }
306
307 unsigned int trp_inforec_get_interval(TRP_INFOREC *rec)
308 {
309   switch (rec->type) {
310   case TRP_INFOREC_TYPE_ROUTE:
311     if (rec->data->route!=NULL)
312       return rec->data->route->interval;
313     break;
314   case TRP_INFOREC_TYPE_COMMUNITY:
315     if (rec->data->comm!=NULL)
316       return rec->data->comm->interval;
317     break;
318   default:
319     break;
320   }
321   return TRP_INTERVAL_INVALID;
322 }
323
324 TRP_RC trp_inforec_set_interval(TRP_INFOREC *rec, unsigned int interval)
325 {
326   switch (rec->type) {
327   case TRP_INFOREC_TYPE_ROUTE:
328     if (rec->data->route!=NULL) {
329       rec->data->route->interval=interval;
330       return TRP_SUCCESS;
331     }
332     break;
333   case TRP_INFOREC_TYPE_COMMUNITY:
334     if (rec->data->comm!=NULL) {
335       rec->data->comm->interval=interval;
336       return TRP_SUCCESS;
337     }
338   default:
339     break;
340   }
341   return TRP_ERROR;
342 }
343
344 time_t trp_inforec_get_exp_interval(TRP_INFOREC *rec)
345 {
346   switch (rec->type) {
347   case TRP_INFOREC_TYPE_COMMUNITY:
348     if (rec->data->comm!=NULL)
349       return rec->data->comm->expiration_interval;
350     break;
351   default:
352     break;
353   }
354   return 0;
355 }
356
357 TRP_RC trp_inforec_set_exp_interval(TRP_INFOREC *rec, time_t expint)
358 {
359   switch (rec->type) {
360   case TRP_INFOREC_TYPE_COMMUNITY:
361     if (rec->data->comm!=NULL) {
362       rec->data->comm->expiration_interval=expint;
363       return TRP_SUCCESS;
364     }
365     break;
366   default:
367     break;
368   }
369   return TRP_ERROR;
370 }
371
372 TR_COMM_TYPE trp_inforec_get_comm_type(TRP_INFOREC *rec)
373 {
374   switch (rec->type) {
375   case TRP_INFOREC_TYPE_COMMUNITY:
376     if (rec->data->comm!=NULL)
377       return rec->data->comm->comm_type;
378     break;
379   default:
380     break;
381   }
382   return TR_COMM_UNKNOWN;
383 }
384
385 TRP_RC trp_inforec_set_comm_type(TRP_INFOREC *rec, TR_COMM_TYPE type)
386 {
387   switch (rec->type) {
388   case TRP_INFOREC_TYPE_COMMUNITY:
389     if (rec->data->comm!=NULL) {
390       rec->data->comm->comm_type=type;
391       return TRP_SUCCESS;
392     }
393     break;
394   default:
395     break;
396   }
397   return TRP_ERROR;
398 }
399
400 TR_REALM_ROLE trp_inforec_get_role(TRP_INFOREC *rec)
401 {
402   switch (rec->type) {
403   case TRP_INFOREC_TYPE_COMMUNITY:
404     if (rec->data->comm!=NULL)
405       return rec->data->comm->role;
406     break;
407   default:
408     break;
409   }
410   return TR_ROLE_UNKNOWN;
411 }
412
413 TRP_RC trp_inforec_set_role(TRP_INFOREC *rec, TR_REALM_ROLE role)
414 {
415   switch (rec->type) {
416   case TRP_INFOREC_TYPE_COMMUNITY:
417     if (rec->data->comm!=NULL) {
418       rec->data->comm->role=role;
419       return TRP_SUCCESS;
420       break;
421     }
422   default:
423     break;
424   }
425   return TRP_ERROR;
426 }
427
428 TR_APC *trp_inforec_get_apcs(TRP_INFOREC *rec)
429 {
430   switch (rec->type) {
431   case TRP_INFOREC_TYPE_COMMUNITY:
432     if (rec->data->comm!=NULL)
433       return rec->data->comm->apcs;
434     break;
435   default:
436     break;
437   }
438   return NULL;
439 }
440
441 TRP_RC trp_inforec_set_apcs(TRP_INFOREC *rec, TR_APC *apcs)
442 {
443   switch (rec->type) {
444   case TRP_INFOREC_TYPE_COMMUNITY:
445     if (rec->data->comm!=NULL) {
446       rec->data->comm->apcs=apcs;
447       talloc_steal(rec, apcs);
448       return TRP_SUCCESS;
449     }
450     break;
451
452   default:
453     break;
454   }
455   return TRP_ERROR;
456 }
457
458 TR_NAME *trp_inforec_get_owner_realm(TRP_INFOREC *rec)
459 {
460   switch (rec->type) {
461   case TRP_INFOREC_TYPE_COMMUNITY:
462     if (rec->data->comm!=NULL)
463       return rec->data->comm->owner_realm;
464     break;
465   default:
466     break;
467   }
468   return NULL;
469 }
470
471 TRP_RC trp_inforec_set_owner_realm(TRP_INFOREC *rec, TR_NAME *name)
472 {
473   switch (rec->type) {
474   case TRP_INFOREC_TYPE_COMMUNITY:
475     if (rec->data->comm!=NULL) {
476       rec->data->comm->owner_realm=name;
477       return TRP_SUCCESS;
478   default:
479     break;
480     }
481     break;
482   }
483   return TRP_ERROR;
484 }
485
486 TR_NAME *trp_inforec_get_owner_contact(TRP_INFOREC *rec)
487 {
488   switch (rec->type) {
489   case TRP_INFOREC_TYPE_COMMUNITY:
490     if (rec->data->comm!=NULL)
491       return rec->data->comm->owner_contact;
492     break;
493   default:
494     break;
495   }
496   return NULL;
497 }
498
499 TRP_RC trp_inforec_set_owner_contact(TRP_INFOREC *rec, TR_NAME *name)
500 {
501   switch (rec->type) {
502   case TRP_INFOREC_TYPE_COMMUNITY:
503     if (rec->data->comm!=NULL) {
504       rec->data->comm->owner_contact=name;
505       return TRP_SUCCESS;
506     }
507     break;
508   default:
509     break;
510   }
511   return TRP_ERROR;
512 }
513
514 /* caller needs to incref the output if they're going to hang on to it */
515 json_t *trp_inforec_get_provenance(TRP_INFOREC *rec)
516 {
517   switch (rec->type) {
518   case TRP_INFOREC_TYPE_COMMUNITY:
519     if (rec->data->comm!=NULL)
520       return rec->data->comm->provenance;
521     break;
522   default:
523     break;
524   }
525   return NULL;
526 }
527
528 /* increments the reference count */
529 TRP_RC trp_inforec_set_provenance(TRP_INFOREC *rec, json_t *prov)
530 {
531   switch (rec->type) {
532   case TRP_INFOREC_TYPE_COMMUNITY:
533     if (rec->data->comm!=NULL) {
534       if (rec->data->comm->provenance!=NULL)
535         json_decref(rec->data->comm->provenance);
536       rec->data->comm->provenance=prov;
537       json_incref(prov);
538       return TRP_SUCCESS;
539     }
540     break;
541   default:
542     break;
543   }
544   return TRP_ERROR;
545 }
546
547 static TRP_RC trp_inforec_add_to_provenance(TRP_INFOREC *rec, TR_NAME *name)
548 {
549   json_t *jname=NULL;
550
551   switch (rec->type) {
552   case TRP_INFOREC_TYPE_ROUTE:
553     /* no provenance list */
554     break;
555   case TRP_INFOREC_TYPE_COMMUNITY:
556     jname=tr_name_to_json_string(name);
557     if (jname==NULL)
558       return TRP_ERROR;
559     if (rec->data->comm->provenance==NULL) {
560       rec->data->comm->provenance=json_array();
561       if (rec->data->comm->provenance==NULL) {
562         json_decref(jname);
563         return TRP_ERROR;
564       }
565     }
566     if (0!=json_array_append_new(rec->data->comm->provenance, jname)) {
567       json_decref(jname);
568       return TRP_ERROR;
569     }
570     break;
571   default:
572     break;
573   }
574   return TRP_SUCCESS;
575 }
576
577 TR_NAME *trp_inforec_dup_origin(TRP_INFOREC *rec)
578 {
579   TR_NAME *origin=NULL;
580   json_t *prov=trp_inforec_get_provenance(rec);
581   const char *s=NULL;
582
583   if (prov==NULL)
584     return NULL;
585
586   s=json_string_value(json_array_get(prov, 0));
587   if (s==NULL) {
588     tr_debug("trp_inforec_dup_origin: empty origin in provenance list.");
589     return NULL;
590   }
591   origin=tr_new_name(s);
592   return origin;
593 }
594
595 /* generic record type */
596 TRP_INFOREC *trp_inforec_new(TALLOC_CTX *mem_ctx, TRP_INFOREC_TYPE type)
597 {
598   TRP_INFOREC *new_rec=talloc(mem_ctx, TRP_INFOREC);
599   TRP_INFOREC_DATA *data=NULL;
600   struct trp_inforec_type_entry *dtype=get_trp_inforec_type_entry(type);
601
602   if ((new_rec != NULL) && (dtype->type != TRP_INFOREC_TYPE_UNKNOWN)) {
603     trp_inforec_set_type(new_rec, type);
604     trp_inforec_set_next(new_rec, NULL);
605     if (dtype->allocate!=NULL) {
606       data=dtype->allocate(new_rec);
607       if (data!=NULL)
608         new_rec->data=data;
609       else {
610         talloc_free(new_rec);
611         return NULL;
612       }
613     }
614   }
615   return new_rec;
616 }
617
618 void trp_inforec_free(TRP_INFOREC *rec)
619 {
620   if (rec!=NULL)
621     talloc_free(rec);
622 }
623
624 static int trp_upd_destructor(void *object)
625 {
626   TRP_UPD *upd=talloc_get_type_abort(object, TRP_UPD);
627   if (upd->realm!=NULL)
628     tr_free_name(upd->realm);
629   if (upd->comm!=NULL)
630     tr_free_name(upd->comm);
631   if (upd->peer!=NULL)
632     tr_free_name(upd->peer);
633   return 0;
634 }
635
636 TRP_UPD *trp_upd_new(TALLOC_CTX *mem_ctx)
637 {
638   TRP_UPD *new_body=talloc(mem_ctx, TRP_UPD);
639
640   if (new_body!=NULL) {
641     new_body->realm=NULL;
642     new_body->comm=NULL;
643     new_body->records=NULL;
644     new_body->peer=NULL;
645     talloc_set_destructor((void *)new_body, trp_upd_destructor);
646   }
647   return new_body;
648 }
649
650 void trp_upd_free(TRP_UPD *update)
651 {
652   if (update!=NULL)
653     talloc_free(update);
654 }
655
656 TRP_INFOREC *trp_upd_get_inforec(TRP_UPD *upd)
657 {
658   if (upd!=NULL)
659     return upd->records;
660   else
661     return NULL;
662 }
663
664 void trp_upd_set_inforec(TRP_UPD *upd, TRP_INFOREC *rec)
665 {
666   if (upd!=NULL)
667     upd->records=rec;
668 }
669
670 void trp_upd_add_inforec(TRP_UPD *upd, TRP_INFOREC *rec)
671 {
672   tr_debug("trp_upd_add_inforec: adding record.");
673   if (upd->records==NULL)
674     upd->records=rec;
675   else
676     trp_inforec_set_next(trp_inforec_get_tail(upd->records), rec);
677   talloc_steal(upd, rec);
678 }
679
680 TR_NAME *trp_upd_get_realm(TRP_UPD *upd)
681 {
682   return upd->realm;
683 }
684
685 TR_NAME *trp_upd_dup_realm(TRP_UPD *upd)
686 {
687   return tr_dup_name(upd->realm);
688 }
689
690 void trp_upd_set_realm(TRP_UPD *upd, TR_NAME *realm)
691 {
692   if (upd->realm!=NULL)
693     tr_free_name(upd->realm);
694   upd->realm=realm;
695 }
696
697 TR_NAME *trp_upd_get_comm(TRP_UPD *upd)
698 {
699   return upd->comm;
700 }
701
702 TR_NAME *trp_upd_dup_comm(TRP_UPD *upd)
703 {
704   return tr_dup_name(upd->comm);
705 }
706
707 void trp_upd_set_comm(TRP_UPD *upd, TR_NAME *comm)
708 {
709   if (upd->comm!=NULL)
710     tr_free_name(upd->comm);
711   upd->comm=comm;
712 }
713
714 TR_NAME *trp_upd_get_peer(TRP_UPD *upd)
715 {
716   return upd->peer;
717 }
718
719 TR_NAME *trp_upd_dup_peer(TRP_UPD *upd)
720 {
721   return tr_dup_name(upd->peer);
722 }
723
724 void trp_upd_set_peer(TRP_UPD *upd, TR_NAME *peer)
725 {
726   upd->peer=peer;
727 }
728
729 void trp_upd_set_next_hop(TRP_UPD *upd, const char *hostname, unsigned int port)
730 {
731   TRP_INFOREC *rec=NULL;
732   TR_NAME *cpy=NULL;
733   
734   for (rec=trp_upd_get_inforec(upd); rec!=NULL; rec=trp_inforec_get_next(rec)) {
735     if (trp_inforec_set_next_hop(rec, cpy=tr_new_name(hostname)) != TRP_SUCCESS) {
736       tr_err("trp_upd_set_next_hop: error setting next hop.");
737       tr_free_name(cpy);
738     }
739   }
740 }
741
742 void trp_upd_add_to_provenance(TRP_UPD *upd, TR_NAME *name)
743 {
744   TRP_INFOREC *rec=NULL;
745
746   /* add it to all inforecs */
747   for (rec=trp_upd_get_inforec(upd); rec!=NULL; rec=trp_inforec_get_next(rec)) {
748     if (TRP_SUCCESS!=trp_inforec_add_to_provenance(rec, name))
749       tr_err("trp_upd_set_peer: error adding peer to provenance list.");
750   }
751 }
752
753 /* pretty print */
754 static void trp_inforec_route_print(TRP_INFOREC_DATA *data)
755 {
756   if (data->route!=NULL) {
757     printf("     trust_router=%.*s\n     metric=%d\n     interval=%d]\n",
758            data->route->trust_router->len, data->route->trust_router->buf,
759            data->route->metric, data->route->interval);
760   }
761 }
762
763 static void trp_inforec_comm_print(TRP_INFOREC_DATA *data)
764 {
765   if (data->comm!=NULL) {
766     printf("     type=%s\n     role=%s\n     owner=%.*s\n     contact=%.*s]\n",
767            tr_comm_type_to_str(data->comm->comm_type),
768            tr_realm_role_to_str(data->comm->role),
769            data->comm->owner_realm->len, data->comm->owner_realm->buf,
770            data->comm->owner_contact->len, data->comm->owner_contact->buf);
771     /* TODO: print apcs */
772   }
773 }