Fix memory leak when setting next hop for community inforecs
[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 <strings.h>
36 #include <jansson.h>
37 #include <talloc.h>
38
39 #include <tr_name_internal.h>
40 #include <trp_internal.h>
41 #include <tr_comm.h>
42 #include <tr_apc.h>
43 #include <tr_debug.h>
44
45
46 /* static prototypes */
47 static TRP_INFOREC_DATA *trp_inforec_route_new(TALLOC_CTX *mem_ctx);
48 static void trp_inforec_route_print(TRP_INFOREC_DATA *);
49 static TRP_INFOREC_DATA *trp_inforec_comm_new(TALLOC_CTX *mem_ctx);
50 static void trp_inforec_comm_print(TRP_INFOREC_DATA *);
51
52
53 struct trp_inforec_type_entry {
54   const char *name;
55   TRP_INFOREC_TYPE type;
56   TRP_INFOREC_DATA *(*allocate)(TALLOC_CTX *);
57   void (*print)(TRP_INFOREC_DATA *);
58 };
59 static struct trp_inforec_type_entry trp_inforec_type_table[] = {
60   { "route", TRP_INFOREC_TYPE_ROUTE, trp_inforec_route_new, trp_inforec_route_print },
61   { "comm", TRP_INFOREC_TYPE_COMMUNITY, trp_inforec_comm_new, trp_inforec_comm_print },
62   { NULL, TRP_INFOREC_TYPE_UNKNOWN, NULL, NULL } /* must be the last entry */
63 };
64
65
66 /* look up an entry in the trp_inforec_type_table */
67 static struct trp_inforec_type_entry *get_trp_inforec_type_entry(TRP_INFOREC_TYPE msgtype)
68 {
69   struct trp_inforec_type_entry *entry=trp_inforec_type_table;
70
71   while ((entry->type != TRP_INFOREC_TYPE_UNKNOWN)
72         && (entry->type != msgtype)) {
73     entry ++;
74   }
75   return entry;
76 }
77
78 /* translate strings to codes */
79 TRP_INFOREC_TYPE trp_inforec_type_from_string(const char *s)
80 {
81   struct trp_inforec_type_entry *entry=trp_inforec_type_table;
82
83   while ((entry->type != TRP_INFOREC_TYPE_UNKNOWN)
84         && (strcasecmp(s, entry->name)!=0)) {
85     entry++;
86   }
87   return entry->type;
88 }
89 /* translate codes to strings (do not need to be freed) 
90  * Returns NULL on an unknown code */
91 const char *trp_inforec_type_to_string(TRP_INFOREC_TYPE msgtype)
92 {
93   struct trp_inforec_type_entry *entry=get_trp_inforec_type_entry(msgtype);
94   return entry->name;
95 }
96
97 /* called by talloc when destroying an update message body */
98 static int trp_inforec_route_destructor(void *object)
99 {
100   TRP_INFOREC_ROUTE *body=talloc_get_type_abort(object, TRP_INFOREC_ROUTE);
101   
102   /* clean up TR_NAME data, which are not managed by talloc */
103   if (body->trust_router != NULL)
104     tr_free_name(body->trust_router);
105   if (body->next_hop != NULL)
106     tr_free_name(body->next_hop);
107   return 0;
108 }
109
110 static TRP_INFOREC_DATA *trp_inforec_route_new(TALLOC_CTX *mem_ctx)
111 {
112   TRP_INFOREC_DATA *new_data=talloc(mem_ctx, TRP_INFOREC_DATA);
113   TRP_INFOREC_ROUTE *new_rec=NULL;
114
115   if (new_data==NULL)
116     return NULL;
117
118   new_rec=talloc(new_data, TRP_INFOREC_ROUTE);
119   if (new_rec == NULL) {
120     talloc_free(new_data);
121     new_data=NULL;
122   } else {
123     new_rec->trust_router=NULL;
124     new_rec->next_hop=NULL;
125     new_rec->next_hop_port=0;
126     new_rec->metric=TRP_METRIC_INFINITY;
127     new_rec->interval=0;
128     talloc_set_destructor((void *)new_rec, trp_inforec_route_destructor);
129     new_data->route=new_rec;
130   }
131     
132   return new_data;
133 }
134
135
136 static int trp_inforec_comm_destructor(void *obj)
137 {
138   TRP_INFOREC_COMM *rec=talloc_get_type_abort(obj, TRP_INFOREC_COMM);
139   if (rec->owner_realm!=NULL)
140     tr_free_name(rec->owner_realm);
141   if (rec->owner_contact!=NULL)
142     tr_free_name(rec->owner_contact);
143   if (rec->provenance!=NULL)
144     json_decref(rec->provenance);
145   return 0;
146 }
147
148 static TRP_INFOREC_DATA *trp_inforec_comm_new(TALLOC_CTX *mem_ctx)
149 {
150   TRP_INFOREC_DATA *new_data=talloc(mem_ctx, TRP_INFOREC_DATA);
151   TRP_INFOREC_COMM *new_rec=NULL;
152
153   if (new_data==NULL)
154     return NULL;
155
156   new_rec=talloc(new_data, TRP_INFOREC_COMM);
157   if (new_rec==NULL) {
158     talloc_free(new_data);
159     new_data=NULL;
160   } else {
161     new_rec->comm_type=TR_COMM_UNKNOWN;
162     new_rec->role=TR_ROLE_UNKNOWN;
163     new_rec->apcs=NULL;
164     new_rec->owner_realm=NULL;
165     new_rec->owner_contact=NULL;
166     new_rec->expiration_interval=0;
167     new_rec->provenance=NULL;
168     new_rec->interval=0;
169     talloc_set_destructor((void *)new_rec, trp_inforec_comm_destructor);
170     new_data->comm=new_rec;
171   }
172
173   return new_data;
174 }
175
176 TRP_INFOREC *trp_inforec_get_next(TRP_INFOREC *rec)
177 {
178   if (rec!=NULL)
179     return rec->next;
180   else
181     return NULL;
182 }
183
184 static TRP_INFOREC *trp_inforec_get_tail(TRP_INFOREC *rec)
185 {
186   while ((rec->next)!=NULL)
187     rec=trp_inforec_get_next(rec);
188   return rec;
189 }
190
191 void trp_inforec_set_next(TRP_INFOREC *rec, TRP_INFOREC *next_rec)
192 {
193   if (rec !=NULL)
194     rec->next=next_rec;
195 }
196
197 TRP_INFOREC_TYPE trp_inforec_get_type(TRP_INFOREC *rec)
198 {
199   if (rec!=NULL)
200     return rec->type;
201   else
202     return TRP_INFOREC_TYPE_UNKNOWN;
203 }
204
205 void trp_inforec_set_type(TRP_INFOREC *rec, TRP_INFOREC_TYPE type)
206 {
207   if (rec!=NULL)
208     rec->type=type;
209 }
210
211 TR_NAME *trp_inforec_get_trust_router(TRP_INFOREC *rec)
212 {
213   switch (rec->type) {
214   case TRP_INFOREC_TYPE_ROUTE:
215     if (rec->data->route!=NULL)
216       return rec->data->route->trust_router;
217     break;
218   default:
219     break;
220   }
221   return NULL;
222 }
223
224 TR_NAME *trp_inforec_dup_trust_router(TRP_INFOREC *rec)
225 {
226   return tr_dup_name(trp_inforec_get_trust_router(rec));
227 }
228
229 TRP_RC trp_inforec_set_trust_router(TRP_INFOREC *rec, TR_NAME *trust_router)
230 {
231   switch (rec->type) {
232   case TRP_INFOREC_TYPE_ROUTE:
233     if (rec->data->route!=NULL) {
234       rec->data->route->trust_router=trust_router;
235       return TRP_SUCCESS;
236     }
237     break;
238   default:
239     break;
240   }
241   return TRP_ERROR;
242 }
243
244 /* TODO: need to return hostname/port --jlr */
245 TR_NAME *trp_inforec_get_next_hop(TRP_INFOREC *rec)
246 {
247   switch (rec->type) {
248   case TRP_INFOREC_TYPE_ROUTE:
249     if (rec->data->route!=NULL)
250       return rec->data->route->next_hop;
251     break;
252   default:
253     break;
254   }
255   return NULL;
256 }
257
258 TR_NAME *trp_inforec_dup_next_hop(TRP_INFOREC *rec)
259 {
260   return tr_dup_name(trp_inforec_get_next_hop(rec));
261 }
262
263 /**
264  * Set the next hop for the inforec
265  *
266  * Returns TRP_SUCCESS if it set the next hop value for the inforec.
267  * Returns TRP_UNSUPPORTED if the inforec does not have a next hop record but
268  * otherwise nothing went wrong.
269  * Returns TRP_ERROR or another error if there was a failure.
270  *
271  * @param rec
272  * @param next_hop
273  * @return TRP_SUCCESS if the value was set, TRP_UNSUPPORTED if the inforec does not support next hop, or an error code on failure
274  */
275 TRP_RC trp_inforec_set_next_hop(TRP_INFOREC *rec, TR_NAME *next_hop)
276 {
277   /* Any inforec types that support next_hop should set it here. */
278   switch (rec->type) {
279   case TRP_INFOREC_TYPE_ROUTE:
280     if (rec->data->route==NULL)
281       return TRP_ERROR;
282     rec->data->route->next_hop=next_hop;
283     break;
284
285   default:
286     /* next hop not used for other records */
287     return TRP_UNSUPPORTED;
288   }
289   return TRP_SUCCESS;
290 }
291
292 unsigned int trp_inforec_get_metric(TRP_INFOREC *rec)
293 {
294   switch (rec->type) {
295   case TRP_INFOREC_TYPE_ROUTE:
296     if (rec->data->route!=NULL)
297       return rec->data->route->metric;
298     break;
299   default:
300     break;
301   }
302   return TRP_METRIC_INVALID;
303 }
304
305 TRP_RC trp_inforec_set_metric(TRP_INFOREC *rec, unsigned int metric)
306 {
307   switch (rec->type) {
308   case TRP_INFOREC_TYPE_ROUTE:
309     if (rec->data->route!=NULL) {
310       rec->data->route->metric=metric;
311       return TRP_SUCCESS;
312     }
313     break;
314   default:
315     break;
316   }
317   return TRP_ERROR;
318 }
319
320 unsigned int trp_inforec_get_interval(TRP_INFOREC *rec)
321 {
322   switch (rec->type) {
323   case TRP_INFOREC_TYPE_ROUTE:
324     if (rec->data->route!=NULL)
325       return rec->data->route->interval;
326     break;
327   case TRP_INFOREC_TYPE_COMMUNITY:
328     if (rec->data->comm!=NULL)
329       return rec->data->comm->interval;
330     break;
331   default:
332     break;
333   }
334   return TRP_INTERVAL_INVALID;
335 }
336
337 TRP_RC trp_inforec_set_interval(TRP_INFOREC *rec, unsigned int interval)
338 {
339   switch (rec->type) {
340   case TRP_INFOREC_TYPE_ROUTE:
341     if (rec->data->route!=NULL) {
342       rec->data->route->interval=interval;
343       return TRP_SUCCESS;
344     }
345     break;
346   case TRP_INFOREC_TYPE_COMMUNITY:
347     if (rec->data->comm!=NULL) {
348       rec->data->comm->interval=interval;
349       return TRP_SUCCESS;
350     }
351   default:
352     break;
353   }
354   return TRP_ERROR;
355 }
356
357 time_t trp_inforec_get_exp_interval(TRP_INFOREC *rec)
358 {
359   switch (rec->type) {
360   case TRP_INFOREC_TYPE_COMMUNITY:
361     if (rec->data->comm!=NULL)
362       return rec->data->comm->expiration_interval;
363     break;
364   default:
365     break;
366   }
367   return 0;
368 }
369
370 TRP_RC trp_inforec_set_exp_interval(TRP_INFOREC *rec, time_t expint)
371 {
372   switch (rec->type) {
373   case TRP_INFOREC_TYPE_COMMUNITY:
374     if (rec->data->comm!=NULL) {
375       rec->data->comm->expiration_interval=expint;
376       return TRP_SUCCESS;
377     }
378     break;
379   default:
380     break;
381   }
382   return TRP_ERROR;
383 }
384
385 TR_COMM_TYPE trp_inforec_get_comm_type(TRP_INFOREC *rec)
386 {
387   switch (rec->type) {
388   case TRP_INFOREC_TYPE_COMMUNITY:
389     if (rec->data->comm!=NULL)
390       return rec->data->comm->comm_type;
391     break;
392   default:
393     break;
394   }
395   return TR_COMM_UNKNOWN;
396 }
397
398 TRP_RC trp_inforec_set_comm_type(TRP_INFOREC *rec, TR_COMM_TYPE type)
399 {
400   switch (rec->type) {
401   case TRP_INFOREC_TYPE_COMMUNITY:
402     if (rec->data->comm!=NULL) {
403       rec->data->comm->comm_type=type;
404       return TRP_SUCCESS;
405     }
406     break;
407   default:
408     break;
409   }
410   return TRP_ERROR;
411 }
412
413 TR_REALM_ROLE trp_inforec_get_role(TRP_INFOREC *rec)
414 {
415   switch (rec->type) {
416   case TRP_INFOREC_TYPE_COMMUNITY:
417     if (rec->data->comm!=NULL)
418       return rec->data->comm->role;
419     break;
420   default:
421     break;
422   }
423   return TR_ROLE_UNKNOWN;
424 }
425
426 TRP_RC trp_inforec_set_role(TRP_INFOREC *rec, TR_REALM_ROLE role)
427 {
428   switch (rec->type) {
429   case TRP_INFOREC_TYPE_COMMUNITY:
430     if (rec->data->comm!=NULL) {
431       rec->data->comm->role=role;
432       return TRP_SUCCESS;
433       break;
434     }
435   default:
436     break;
437   }
438   return TRP_ERROR;
439 }
440
441 TR_APC *trp_inforec_get_apcs(TRP_INFOREC *rec)
442 {
443   switch (rec->type) {
444   case TRP_INFOREC_TYPE_COMMUNITY:
445     if (rec->data->comm!=NULL)
446       return rec->data->comm->apcs;
447     break;
448   default:
449     break;
450   }
451   return NULL;
452 }
453
454 TRP_RC trp_inforec_set_apcs(TRP_INFOREC *rec, TR_APC *apcs)
455 {
456   switch (rec->type) {
457   case TRP_INFOREC_TYPE_COMMUNITY:
458     if (rec->data->comm!=NULL) {
459       rec->data->comm->apcs=apcs;
460       talloc_steal(rec, apcs);
461       return TRP_SUCCESS;
462     }
463     break;
464
465   default:
466     break;
467   }
468   return TRP_ERROR;
469 }
470
471 TR_NAME *trp_inforec_get_owner_realm(TRP_INFOREC *rec)
472 {
473   switch (rec->type) {
474   case TRP_INFOREC_TYPE_COMMUNITY:
475     if (rec->data->comm!=NULL)
476       return rec->data->comm->owner_realm;
477     break;
478   default:
479     break;
480   }
481   return NULL;
482 }
483
484 TRP_RC trp_inforec_set_owner_realm(TRP_INFOREC *rec, TR_NAME *name)
485 {
486   switch (rec->type) {
487   case TRP_INFOREC_TYPE_COMMUNITY:
488     if (rec->data->comm!=NULL) {
489       rec->data->comm->owner_realm=name;
490       return TRP_SUCCESS;
491   default:
492     break;
493     }
494     break;
495   }
496   return TRP_ERROR;
497 }
498
499 TR_NAME *trp_inforec_get_owner_contact(TRP_INFOREC *rec)
500 {
501   switch (rec->type) {
502   case TRP_INFOREC_TYPE_COMMUNITY:
503     if (rec->data->comm!=NULL)
504       return rec->data->comm->owner_contact;
505     break;
506   default:
507     break;
508   }
509   return NULL;
510 }
511
512 TRP_RC trp_inforec_set_owner_contact(TRP_INFOREC *rec, TR_NAME *name)
513 {
514   switch (rec->type) {
515   case TRP_INFOREC_TYPE_COMMUNITY:
516     if (rec->data->comm!=NULL) {
517       rec->data->comm->owner_contact=name;
518       return TRP_SUCCESS;
519     }
520     break;
521   default:
522     break;
523   }
524   return TRP_ERROR;
525 }
526
527 /* caller needs to incref the output if they're going to hang on to it */
528 json_t *trp_inforec_get_provenance(TRP_INFOREC *rec)
529 {
530   switch (rec->type) {
531   case TRP_INFOREC_TYPE_COMMUNITY:
532     if (rec->data->comm!=NULL)
533       return rec->data->comm->provenance;
534     break;
535   default:
536     break;
537   }
538   return NULL;
539 }
540
541 /* increments the reference count */
542 TRP_RC trp_inforec_set_provenance(TRP_INFOREC *rec, json_t *prov)
543 {
544   switch (rec->type) {
545   case TRP_INFOREC_TYPE_COMMUNITY:
546     if (rec->data->comm!=NULL) {
547       if (rec->data->comm->provenance!=NULL)
548         json_decref(rec->data->comm->provenance);
549       rec->data->comm->provenance=prov;
550       json_incref(prov);
551       return TRP_SUCCESS;
552     }
553     break;
554   default:
555     break;
556   }
557   return TRP_ERROR;
558 }
559
560 static TRP_RC trp_inforec_add_to_provenance(TRP_INFOREC *rec, TR_NAME *name)
561 {
562   json_t *jname=NULL;
563
564   switch (rec->type) {
565   case TRP_INFOREC_TYPE_ROUTE:
566     /* no provenance list */
567     break;
568   case TRP_INFOREC_TYPE_COMMUNITY:
569     jname=tr_name_to_json_string(name);
570     if (jname==NULL)
571       return TRP_ERROR;
572     if (rec->data->comm->provenance==NULL) {
573       rec->data->comm->provenance=json_array();
574       if (rec->data->comm->provenance==NULL) {
575         json_decref(jname);
576         return TRP_ERROR;
577       }
578     }
579     if (0!=json_array_append_new(rec->data->comm->provenance, jname)) {
580       json_decref(jname);
581       return TRP_ERROR;
582     }
583     break;
584   default:
585     break;
586   }
587   return TRP_SUCCESS;
588 }
589
590 TR_NAME *trp_inforec_dup_origin(TRP_INFOREC *rec)
591 {
592   TR_NAME *origin=NULL;
593   json_t *prov=trp_inforec_get_provenance(rec);
594   const char *s=NULL;
595
596   if (prov==NULL)
597     return NULL;
598
599   s=json_string_value(json_array_get(prov, 0));
600   if (s==NULL) {
601     tr_debug("trp_inforec_dup_origin: empty origin in provenance list.");
602     return NULL;
603   }
604   origin=tr_new_name(s);
605   return origin;
606 }
607
608 /* generic record type */
609 TRP_INFOREC *trp_inforec_new(TALLOC_CTX *mem_ctx, TRP_INFOREC_TYPE type)
610 {
611   TRP_INFOREC *new_rec=talloc(mem_ctx, TRP_INFOREC);
612   TRP_INFOREC_DATA *data=NULL;
613   struct trp_inforec_type_entry *dtype=get_trp_inforec_type_entry(type);
614
615   if ((new_rec != NULL) && (dtype->type != TRP_INFOREC_TYPE_UNKNOWN)) {
616     trp_inforec_set_type(new_rec, type);
617     trp_inforec_set_next(new_rec, NULL);
618     if (dtype->allocate!=NULL) {
619       data=dtype->allocate(new_rec);
620       if (data!=NULL)
621         new_rec->data=data;
622       else {
623         talloc_free(new_rec);
624         return NULL;
625       }
626     }
627   }
628   return new_rec;
629 }
630
631 void trp_inforec_free(TRP_INFOREC *rec)
632 {
633   if (rec!=NULL)
634     talloc_free(rec);
635 }
636
637 static int trp_upd_destructor(void *object)
638 {
639   TRP_UPD *upd=talloc_get_type_abort(object, TRP_UPD);
640   if (upd->realm!=NULL)
641     tr_free_name(upd->realm);
642   if (upd->comm!=NULL)
643     tr_free_name(upd->comm);
644   if (upd->peer!=NULL)
645     tr_free_name(upd->peer);
646   return 0;
647 }
648
649 TRP_UPD *trp_upd_new(TALLOC_CTX *mem_ctx)
650 {
651   TRP_UPD *new_body=talloc(mem_ctx, TRP_UPD);
652
653   if (new_body!=NULL) {
654     new_body->realm=NULL;
655     new_body->comm=NULL;
656     new_body->records=NULL;
657     new_body->peer=NULL;
658     talloc_set_destructor((void *)new_body, trp_upd_destructor);
659   }
660   return new_body;
661 }
662
663 void trp_upd_free(TRP_UPD *update)
664 {
665   if (update!=NULL)
666     talloc_free(update);
667 }
668
669 TRP_INFOREC *trp_upd_get_inforec(TRP_UPD *upd)
670 {
671   if (upd!=NULL)
672     return upd->records;
673   else
674     return NULL;
675 }
676
677 void trp_upd_set_inforec(TRP_UPD *upd, TRP_INFOREC *rec)
678 {
679   if (upd!=NULL)
680     upd->records=rec;
681 }
682
683 void trp_upd_add_inforec(TRP_UPD *upd, TRP_INFOREC *rec)
684 {
685   tr_debug("trp_upd_add_inforec: adding record.");
686   if (upd->records==NULL)
687     upd->records=rec;
688   else
689     trp_inforec_set_next(trp_inforec_get_tail(upd->records), rec);
690   talloc_steal(upd, rec);
691 }
692
693 /**
694  * Removes and frees the selected inforec.
695  *
696  * @param upd Update to remove from
697  * @param rec Inforec to remove
698  */
699 void trp_upd_remove_inforec(TRP_UPD *upd, TRP_INFOREC *rec)
700 {
701   TRP_INFOREC *this=upd->records;
702
703   /* special case for the first element */
704   if (this==rec) {
705     upd->records=upd->records->next;
706     trp_inforec_free(this);
707     return;
708   }
709
710   while (this->next!=NULL) {
711     if (this->next==rec) {
712       this->next=this->next->next; /* this->next is not null */
713       trp_inforec_free(rec);
714     }
715     this=this->next;
716   }
717 }
718
719 size_t trp_upd_num_inforecs(TRP_UPD *upd)
720 {
721   size_t count=0;
722   TRP_INFOREC *this=upd->records;
723
724   while (this != NULL) {
725     count++;
726     this=this->next;
727   }
728   return count;
729 }
730
731
732 TR_NAME *trp_upd_get_realm(TRP_UPD *upd)
733 {
734   return upd->realm;
735 }
736
737 TR_NAME *trp_upd_dup_realm(TRP_UPD *upd)
738 {
739   return tr_dup_name(upd->realm);
740 }
741
742 void trp_upd_set_realm(TRP_UPD *upd, TR_NAME *realm)
743 {
744   if (upd->realm!=NULL)
745     tr_free_name(upd->realm);
746   upd->realm=realm;
747 }
748
749 TR_NAME *trp_upd_get_comm(TRP_UPD *upd)
750 {
751   return upd->comm;
752 }
753
754 TR_NAME *trp_upd_dup_comm(TRP_UPD *upd)
755 {
756   return tr_dup_name(upd->comm);
757 }
758
759 void trp_upd_set_comm(TRP_UPD *upd, TR_NAME *comm)
760 {
761   if (upd->comm!=NULL)
762     tr_free_name(upd->comm);
763   upd->comm=comm;
764 }
765
766 TR_NAME *trp_upd_get_peer(TRP_UPD *upd)
767 {
768   return upd->peer;
769 }
770
771 TR_NAME *trp_upd_dup_peer(TRP_UPD *upd)
772 {
773   return tr_dup_name(upd->peer);
774 }
775
776 void trp_upd_set_peer(TRP_UPD *upd, TR_NAME *peer)
777 {
778   upd->peer=peer;
779 }
780
781 void trp_upd_set_next_hop(TRP_UPD *upd, const char *hostname, unsigned int port)
782 {
783   TRP_INFOREC *rec=NULL;
784   TR_NAME *cpy=NULL;
785
786   for (rec=trp_upd_get_inforec(upd); rec!=NULL; rec=trp_inforec_get_next(rec)) {
787     switch (trp_inforec_set_next_hop(rec, cpy=tr_new_name(hostname))) {
788       case TRP_SUCCESS:
789         /* Success, the TR_NAME in cpy is now stored with the inforec */
790         break;
791
792       case TRP_UNSUPPORTED:
793         /* No error, but the inforec does not accept a next_hop. Free our copy. */
794         tr_free_name(cpy);
795         break;
796
797       default:
798         tr_err("trp_upd_set_next_hop: error setting next hop.");
799         tr_free_name(cpy);
800         break;
801     }
802   }
803 }
804
805 void trp_upd_add_to_provenance(TRP_UPD *upd, TR_NAME *name)
806 {
807   TRP_INFOREC *rec=NULL;
808
809   /* add it to all inforecs */
810   for (rec=trp_upd_get_inforec(upd); rec!=NULL; rec=trp_inforec_get_next(rec)) {
811     if (TRP_SUCCESS!=trp_inforec_add_to_provenance(rec, name))
812       tr_err("trp_upd_set_peer: error adding peer to provenance list.");
813   }
814 }
815
816 /* pretty print */
817 static void trp_inforec_route_print(TRP_INFOREC_DATA *data)
818 {
819   if (data->route!=NULL) {
820     tr_info("     trust_router=%.*s\n     metric=%d\n     interval=%d]\n",
821            data->route->trust_router->len, data->route->trust_router->buf,
822            data->route->metric, data->route->interval);
823   }
824 }
825
826 static void trp_inforec_comm_print(TRP_INFOREC_DATA *data)
827 {
828   if (data->comm!=NULL) {
829     tr_info("     type=%s\n     role=%s\n     owner=%.*s\n     contact=%.*s]\n",
830            tr_comm_type_to_str(data->comm->comm_type),
831            tr_realm_role_to_str(data->comm->role),
832            data->comm->owner_realm->len, data->comm->owner_realm->buf,
833            data->comm->owner_contact->len, data->comm->owner_contact->buf);
834     /* TODO: print apcs */
835   }
836 }