Set trust router port in trp_inforec_set_trust_router()
[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 int trp_inforec_get_trust_router_port(TRP_INFOREC *rec)
225 {
226   switch (rec->type) {
227     case TRP_INFOREC_TYPE_ROUTE:
228       if (rec->data->route!=NULL)
229         return rec->data->route->trust_router_port;
230       /* fall through */
231     default:
232       return -1;
233   }
234 }
235
236 TR_NAME *trp_inforec_dup_trust_router(TRP_INFOREC *rec)
237 {
238   return tr_dup_name(trp_inforec_get_trust_router(rec));
239 }
240
241 TRP_RC trp_inforec_set_trust_router(TRP_INFOREC *rec, TR_NAME *trust_router, int port)
242 {
243   switch (rec->type) {
244   case TRP_INFOREC_TYPE_ROUTE:
245     if (rec->data->route!=NULL) {
246       rec->data->route->trust_router=trust_router;
247       rec->data->route->trust_router_port = port;
248       return TRP_SUCCESS;
249     }
250     break;
251   default:
252     break;
253   }
254   return TRP_ERROR;
255 }
256
257 TR_NAME *trp_inforec_get_next_hop(TRP_INFOREC *rec)
258 {
259   switch (rec->type) {
260     case TRP_INFOREC_TYPE_ROUTE:
261       if (rec->data->route!=NULL)
262         return rec->data->route->next_hop;
263       break;
264     default:
265       break;
266   }
267   return NULL;
268 }
269
270 TR_NAME *trp_inforec_dup_next_hop(TRP_INFOREC *rec)
271 {
272   return tr_dup_name(trp_inforec_get_next_hop(rec));
273 }
274
275 /**
276  * Set the next hop for the inforec
277  *
278  * Returns TRP_SUCCESS if it set the next hop value for the inforec.
279  * Returns TRP_UNSUPPORTED if the inforec does not have a next hop record but
280  * otherwise nothing went wrong.
281  * Returns TRP_ERROR or another error if there was a failure.
282  *
283  * @param rec
284  * @param next_hop
285  * @return TRP_SUCCESS if the value was set, TRP_UNSUPPORTED if the inforec does not support next hop, or an error code on failure
286  */
287 TRP_RC trp_inforec_set_next_hop(TRP_INFOREC *rec, TR_NAME *next_hop, int port)
288 {
289   /* Any inforec types that support next_hop should set it here. */
290   switch (rec->type) {
291   case TRP_INFOREC_TYPE_ROUTE:
292     if (rec->data->route==NULL)
293       return TRP_ERROR;
294     rec->data->route->next_hop = next_hop;
295     rec->data->route->next_hop_port = port;
296     break;
297
298   default:
299     /* next hop not used for other records */
300     return TRP_UNSUPPORTED;
301   }
302   return TRP_SUCCESS;
303 }
304
305 int trp_inforec_get_next_hop_port(TRP_INFOREC *rec)
306 {
307   switch (rec->type) {
308     case TRP_INFOREC_TYPE_ROUTE:
309       if (rec->data->route!=NULL)
310         return rec->data->route->next_hop_port;
311       /* fall through */
312     default:
313       return -1;
314   }
315 }
316
317 unsigned int trp_inforec_get_metric(TRP_INFOREC *rec)
318 {
319   switch (rec->type) {
320   case TRP_INFOREC_TYPE_ROUTE:
321     if (rec->data->route!=NULL)
322       return rec->data->route->metric;
323     break;
324   default:
325     break;
326   }
327   return TRP_METRIC_INVALID;
328 }
329
330 TRP_RC trp_inforec_set_metric(TRP_INFOREC *rec, unsigned int metric)
331 {
332   switch (rec->type) {
333   case TRP_INFOREC_TYPE_ROUTE:
334     if (rec->data->route!=NULL) {
335       rec->data->route->metric=metric;
336       return TRP_SUCCESS;
337     }
338     break;
339   default:
340     break;
341   }
342   return TRP_ERROR;
343 }
344
345 unsigned int trp_inforec_get_interval(TRP_INFOREC *rec)
346 {
347   switch (rec->type) {
348   case TRP_INFOREC_TYPE_ROUTE:
349     if (rec->data->route!=NULL)
350       return rec->data->route->interval;
351     break;
352   case TRP_INFOREC_TYPE_COMMUNITY:
353     if (rec->data->comm!=NULL)
354       return rec->data->comm->interval;
355     break;
356   default:
357     break;
358   }
359   return TRP_INTERVAL_INVALID;
360 }
361
362 TRP_RC trp_inforec_set_interval(TRP_INFOREC *rec, unsigned int interval)
363 {
364   switch (rec->type) {
365   case TRP_INFOREC_TYPE_ROUTE:
366     if (rec->data->route!=NULL) {
367       rec->data->route->interval=interval;
368       return TRP_SUCCESS;
369     }
370     break;
371   case TRP_INFOREC_TYPE_COMMUNITY:
372     if (rec->data->comm!=NULL) {
373       rec->data->comm->interval=interval;
374       return TRP_SUCCESS;
375     }
376   default:
377     break;
378   }
379   return TRP_ERROR;
380 }
381
382 time_t trp_inforec_get_exp_interval(TRP_INFOREC *rec)
383 {
384   switch (rec->type) {
385   case TRP_INFOREC_TYPE_COMMUNITY:
386     if (rec->data->comm!=NULL)
387       return rec->data->comm->expiration_interval;
388     break;
389   default:
390     break;
391   }
392   return 0;
393 }
394
395 TRP_RC trp_inforec_set_exp_interval(TRP_INFOREC *rec, time_t expint)
396 {
397   switch (rec->type) {
398   case TRP_INFOREC_TYPE_COMMUNITY:
399     if (rec->data->comm!=NULL) {
400       rec->data->comm->expiration_interval=expint;
401       return TRP_SUCCESS;
402     }
403     break;
404   default:
405     break;
406   }
407   return TRP_ERROR;
408 }
409
410 TR_COMM_TYPE trp_inforec_get_comm_type(TRP_INFOREC *rec)
411 {
412   switch (rec->type) {
413   case TRP_INFOREC_TYPE_COMMUNITY:
414     if (rec->data->comm!=NULL)
415       return rec->data->comm->comm_type;
416     break;
417   default:
418     break;
419   }
420   return TR_COMM_UNKNOWN;
421 }
422
423 TRP_RC trp_inforec_set_comm_type(TRP_INFOREC *rec, TR_COMM_TYPE type)
424 {
425   switch (rec->type) {
426   case TRP_INFOREC_TYPE_COMMUNITY:
427     if (rec->data->comm!=NULL) {
428       rec->data->comm->comm_type=type;
429       return TRP_SUCCESS;
430     }
431     break;
432   default:
433     break;
434   }
435   return TRP_ERROR;
436 }
437
438 TR_REALM_ROLE trp_inforec_get_role(TRP_INFOREC *rec)
439 {
440   switch (rec->type) {
441   case TRP_INFOREC_TYPE_COMMUNITY:
442     if (rec->data->comm!=NULL)
443       return rec->data->comm->role;
444     break;
445   default:
446     break;
447   }
448   return TR_ROLE_UNKNOWN;
449 }
450
451 TRP_RC trp_inforec_set_role(TRP_INFOREC *rec, TR_REALM_ROLE role)
452 {
453   switch (rec->type) {
454   case TRP_INFOREC_TYPE_COMMUNITY:
455     if (rec->data->comm!=NULL) {
456       rec->data->comm->role=role;
457       return TRP_SUCCESS;
458       break;
459     }
460   default:
461     break;
462   }
463   return TRP_ERROR;
464 }
465
466 TR_APC *trp_inforec_get_apcs(TRP_INFOREC *rec)
467 {
468   switch (rec->type) {
469   case TRP_INFOREC_TYPE_COMMUNITY:
470     if (rec->data->comm!=NULL)
471       return rec->data->comm->apcs;
472     break;
473   default:
474     break;
475   }
476   return NULL;
477 }
478
479 TRP_RC trp_inforec_set_apcs(TRP_INFOREC *rec, TR_APC *apcs)
480 {
481   switch (rec->type) {
482   case TRP_INFOREC_TYPE_COMMUNITY:
483     if (rec->data->comm!=NULL) {
484       rec->data->comm->apcs=apcs;
485       talloc_steal(rec, apcs);
486       return TRP_SUCCESS;
487     }
488     break;
489
490   default:
491     break;
492   }
493   return TRP_ERROR;
494 }
495
496 TR_NAME *trp_inforec_get_owner_realm(TRP_INFOREC *rec)
497 {
498   switch (rec->type) {
499   case TRP_INFOREC_TYPE_COMMUNITY:
500     if (rec->data->comm!=NULL)
501       return rec->data->comm->owner_realm;
502     break;
503   default:
504     break;
505   }
506   return NULL;
507 }
508
509 TRP_RC trp_inforec_set_owner_realm(TRP_INFOREC *rec, TR_NAME *name)
510 {
511   switch (rec->type) {
512   case TRP_INFOREC_TYPE_COMMUNITY:
513     if (rec->data->comm!=NULL) {
514       rec->data->comm->owner_realm=name;
515       return TRP_SUCCESS;
516   default:
517     break;
518     }
519     break;
520   }
521   return TRP_ERROR;
522 }
523
524 TR_NAME *trp_inforec_get_owner_contact(TRP_INFOREC *rec)
525 {
526   switch (rec->type) {
527   case TRP_INFOREC_TYPE_COMMUNITY:
528     if (rec->data->comm!=NULL)
529       return rec->data->comm->owner_contact;
530     break;
531   default:
532     break;
533   }
534   return NULL;
535 }
536
537 TRP_RC trp_inforec_set_owner_contact(TRP_INFOREC *rec, TR_NAME *name)
538 {
539   switch (rec->type) {
540   case TRP_INFOREC_TYPE_COMMUNITY:
541     if (rec->data->comm!=NULL) {
542       rec->data->comm->owner_contact=name;
543       return TRP_SUCCESS;
544     }
545     break;
546   default:
547     break;
548   }
549   return TRP_ERROR;
550 }
551
552 /* caller needs to incref the output if they're going to hang on to it */
553 json_t *trp_inforec_get_provenance(TRP_INFOREC *rec)
554 {
555   switch (rec->type) {
556   case TRP_INFOREC_TYPE_COMMUNITY:
557     if (rec->data->comm!=NULL)
558       return rec->data->comm->provenance;
559     break;
560   default:
561     break;
562   }
563   return NULL;
564 }
565
566 /* increments the reference count */
567 TRP_RC trp_inforec_set_provenance(TRP_INFOREC *rec, json_t *prov)
568 {
569   switch (rec->type) {
570   case TRP_INFOREC_TYPE_COMMUNITY:
571     if (rec->data->comm!=NULL) {
572       if (rec->data->comm->provenance!=NULL)
573         json_decref(rec->data->comm->provenance);
574       rec->data->comm->provenance=prov;
575       json_incref(prov);
576       return TRP_SUCCESS;
577     }
578     break;
579   default:
580     break;
581   }
582   return TRP_ERROR;
583 }
584
585 static TRP_RC trp_inforec_add_to_provenance(TRP_INFOREC *rec, TR_NAME *name)
586 {
587   json_t *jname=NULL;
588
589   switch (rec->type) {
590   case TRP_INFOREC_TYPE_ROUTE:
591     /* no provenance list */
592     break;
593   case TRP_INFOREC_TYPE_COMMUNITY:
594     jname=tr_name_to_json_string(name);
595     if (jname==NULL)
596       return TRP_ERROR;
597     if (rec->data->comm->provenance==NULL) {
598       rec->data->comm->provenance=json_array();
599       if (rec->data->comm->provenance==NULL) {
600         json_decref(jname);
601         return TRP_ERROR;
602       }
603     }
604     if (0!=json_array_append_new(rec->data->comm->provenance, jname)) {
605       json_decref(jname);
606       return TRP_ERROR;
607     }
608     break;
609   default:
610     break;
611   }
612   return TRP_SUCCESS;
613 }
614
615 TR_NAME *trp_inforec_dup_origin(TRP_INFOREC *rec)
616 {
617   TR_NAME *origin=NULL;
618   json_t *prov=trp_inforec_get_provenance(rec);
619   const char *s=NULL;
620
621   if (prov==NULL)
622     return NULL;
623
624   s=json_string_value(json_array_get(prov, 0));
625   if (s==NULL) {
626     tr_debug("trp_inforec_dup_origin: empty origin in provenance list.");
627     return NULL;
628   }
629   origin=tr_new_name(s);
630   return origin;
631 }
632
633 /* generic record type */
634 TRP_INFOREC *trp_inforec_new(TALLOC_CTX *mem_ctx, TRP_INFOREC_TYPE type)
635 {
636   TRP_INFOREC *new_rec=talloc(mem_ctx, TRP_INFOREC);
637   TRP_INFOREC_DATA *data=NULL;
638   struct trp_inforec_type_entry *dtype=get_trp_inforec_type_entry(type);
639
640   if ((new_rec != NULL) && (dtype->type != TRP_INFOREC_TYPE_UNKNOWN)) {
641     trp_inforec_set_type(new_rec, type);
642     trp_inforec_set_next(new_rec, NULL);
643     if (dtype->allocate!=NULL) {
644       data=dtype->allocate(new_rec);
645       if (data!=NULL)
646         new_rec->data=data;
647       else {
648         talloc_free(new_rec);
649         return NULL;
650       }
651     }
652   }
653   return new_rec;
654 }
655
656 void trp_inforec_free(TRP_INFOREC *rec)
657 {
658   if (rec!=NULL)
659     talloc_free(rec);
660 }
661
662 static int trp_upd_destructor(void *object)
663 {
664   TRP_UPD *upd=talloc_get_type_abort(object, TRP_UPD);
665   if (upd->realm!=NULL)
666     tr_free_name(upd->realm);
667   if (upd->comm!=NULL)
668     tr_free_name(upd->comm);
669   if (upd->peer!=NULL)
670     tr_free_name(upd->peer);
671   return 0;
672 }
673
674 TRP_UPD *trp_upd_new(TALLOC_CTX *mem_ctx)
675 {
676   TRP_UPD *new_body=talloc(mem_ctx, TRP_UPD);
677
678   if (new_body!=NULL) {
679     new_body->realm=NULL;
680     new_body->comm=NULL;
681     new_body->records=NULL;
682     new_body->peer=NULL;
683     talloc_set_destructor((void *)new_body, trp_upd_destructor);
684   }
685   return new_body;
686 }
687
688 void trp_upd_free(TRP_UPD *update)
689 {
690   if (update!=NULL)
691     talloc_free(update);
692 }
693
694 TRP_INFOREC *trp_upd_get_inforec(TRP_UPD *upd)
695 {
696   if (upd!=NULL)
697     return upd->records;
698   else
699     return NULL;
700 }
701
702 void trp_upd_set_inforec(TRP_UPD *upd, TRP_INFOREC *rec)
703 {
704   if (upd!=NULL)
705     upd->records=rec;
706 }
707
708 void trp_upd_add_inforec(TRP_UPD *upd, TRP_INFOREC *rec)
709 {
710   tr_debug("trp_upd_add_inforec: adding record.");
711   if (upd->records==NULL)
712     upd->records=rec;
713   else
714     trp_inforec_set_next(trp_inforec_get_tail(upd->records), rec);
715   talloc_steal(upd, rec);
716 }
717
718 /**
719  * Removes and frees the selected inforec.
720  *
721  * @param upd Update to remove from
722  * @param rec Inforec to remove
723  */
724 void trp_upd_remove_inforec(TRP_UPD *upd, TRP_INFOREC *rec)
725 {
726   TRP_INFOREC *this=upd->records;
727
728   /* special case for the first element */
729   if (this==rec) {
730     upd->records=upd->records->next;
731     trp_inforec_free(this);
732     return;
733   }
734
735   while (this->next!=NULL) {
736     if (this->next==rec) {
737       this->next=this->next->next; /* this->next is not null */
738       trp_inforec_free(rec);
739     }
740     this=this->next;
741   }
742 }
743
744 size_t trp_upd_num_inforecs(TRP_UPD *upd)
745 {
746   size_t count=0;
747   TRP_INFOREC *this=upd->records;
748
749   while (this != NULL) {
750     count++;
751     this=this->next;
752   }
753   return count;
754 }
755
756
757 TR_NAME *trp_upd_get_realm(TRP_UPD *upd)
758 {
759   return upd->realm;
760 }
761
762 TR_NAME *trp_upd_dup_realm(TRP_UPD *upd)
763 {
764   return tr_dup_name(upd->realm);
765 }
766
767 void trp_upd_set_realm(TRP_UPD *upd, TR_NAME *realm)
768 {
769   if (upd->realm!=NULL)
770     tr_free_name(upd->realm);
771   upd->realm=realm;
772 }
773
774 TR_NAME *trp_upd_get_comm(TRP_UPD *upd)
775 {
776   return upd->comm;
777 }
778
779 TR_NAME *trp_upd_dup_comm(TRP_UPD *upd)
780 {
781   return tr_dup_name(upd->comm);
782 }
783
784 void trp_upd_set_comm(TRP_UPD *upd, TR_NAME *comm)
785 {
786   if (upd->comm!=NULL)
787     tr_free_name(upd->comm);
788   upd->comm=comm;
789 }
790
791 TR_NAME *trp_upd_get_peer(TRP_UPD *upd)
792 {
793   return upd->peer;
794 }
795
796 TR_NAME *trp_upd_dup_peer(TRP_UPD *upd)
797 {
798   return tr_dup_name(upd->peer);
799 }
800
801 void trp_upd_set_peer(TRP_UPD *upd, TR_NAME *peer)
802 {
803   upd->peer=peer;
804 }
805
806 void trp_upd_set_next_hop(TRP_UPD *upd, const char *hostname, int port)
807 {
808   TRP_INFOREC *rec=NULL;
809   TR_NAME *cpy=NULL;
810
811   for (rec=trp_upd_get_inforec(upd); rec!=NULL; rec=trp_inforec_get_next(rec)) {
812     switch (trp_inforec_set_next_hop(rec, cpy=tr_new_name(hostname), port)) {
813       case TRP_SUCCESS:
814         /* Success, the TR_NAME in cpy is now stored with the inforec */
815         break;
816
817       case TRP_UNSUPPORTED:
818         /* No error, but the inforec does not accept a next_hop. Free our copy. */
819         tr_free_name(cpy);
820         break;
821
822       default:
823         tr_err("trp_upd_set_next_hop: error setting next hop.");
824         tr_free_name(cpy);
825         break;
826     }
827   }
828 }
829
830 void trp_upd_add_to_provenance(TRP_UPD *upd, TR_NAME *name)
831 {
832   TRP_INFOREC *rec=NULL;
833
834   /* add it to all inforecs */
835   for (rec=trp_upd_get_inforec(upd); rec!=NULL; rec=trp_inforec_get_next(rec)) {
836     if (TRP_SUCCESS!=trp_inforec_add_to_provenance(rec, name))
837       tr_err("trp_upd_set_peer: error adding peer to provenance list.");
838   }
839 }
840
841 /* pretty print */
842 static void trp_inforec_route_print(TRP_INFOREC_DATA *data)
843 {
844   if (data->route!=NULL) {
845     tr_info("     trust_router=%.*s\n     metric=%d\n     interval=%d]\n",
846            data->route->trust_router->len, data->route->trust_router->buf,
847            data->route->metric, data->route->interval);
848   }
849 }
850
851 static void trp_inforec_comm_print(TRP_INFOREC_DATA *data)
852 {
853   if (data->comm!=NULL) {
854     tr_info("     type=%s\n     role=%s\n     owner=%.*s\n     contact=%.*s]\n",
855            tr_comm_type_to_str(data->comm->comm_type),
856            tr_realm_role_to_str(data->comm->role),
857            data->comm->owner_realm->len, data->comm->owner_realm->buf,
858            data->comm->owner_contact->len, data->comm->owner_contact->buf);
859     /* TODO: print apcs */
860   }
861 }