2 * Copyright (c) 2016, JANET(UK)
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
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.
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.
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.
39 #include <tr_name_internal.h>
40 #include <trp_internal.h>
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 *);
53 struct trp_inforec_type_entry {
55 TRP_INFOREC_TYPE type;
56 TRP_INFOREC_DATA *(*allocate)(TALLOC_CTX *);
57 void (*print)(TRP_INFOREC_DATA *);
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 */
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)
69 struct trp_inforec_type_entry *entry=trp_inforec_type_table;
71 while ((entry->type != TRP_INFOREC_TYPE_UNKNOWN)
72 && (entry->type != msgtype)) {
78 /* translate strings to codes */
79 TRP_INFOREC_TYPE trp_inforec_type_from_string(const char *s)
81 struct trp_inforec_type_entry *entry=trp_inforec_type_table;
83 while ((entry->type != TRP_INFOREC_TYPE_UNKNOWN)
84 && (strcasecmp(s, entry->name)!=0)) {
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)
93 struct trp_inforec_type_entry *entry=get_trp_inforec_type_entry(msgtype);
97 /* called by talloc when destroying an update message body */
98 static int trp_inforec_route_destructor(void *object)
100 TRP_INFOREC_ROUTE *body=talloc_get_type_abort(object, TRP_INFOREC_ROUTE);
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);
110 static TRP_INFOREC_DATA *trp_inforec_route_new(TALLOC_CTX *mem_ctx)
112 TRP_INFOREC_DATA *new_data=talloc(mem_ctx, TRP_INFOREC_DATA);
113 TRP_INFOREC_ROUTE *new_rec=NULL;
118 new_rec=talloc(new_data, TRP_INFOREC_ROUTE);
119 if (new_rec == NULL) {
120 talloc_free(new_data);
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;
128 talloc_set_destructor((void *)new_rec, trp_inforec_route_destructor);
129 new_data->route=new_rec;
136 static int trp_inforec_comm_destructor(void *obj)
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);
148 static TRP_INFOREC_DATA *trp_inforec_comm_new(TALLOC_CTX *mem_ctx)
150 TRP_INFOREC_DATA *new_data=talloc(mem_ctx, TRP_INFOREC_DATA);
151 TRP_INFOREC_COMM *new_rec=NULL;
156 new_rec=talloc(new_data, TRP_INFOREC_COMM);
158 talloc_free(new_data);
161 new_rec->comm_type=TR_COMM_UNKNOWN;
162 new_rec->role=TR_ROLE_UNKNOWN;
164 new_rec->owner_realm=NULL;
165 new_rec->owner_contact=NULL;
166 new_rec->expiration_interval=0;
167 new_rec->provenance=NULL;
169 talloc_set_destructor((void *)new_rec, trp_inforec_comm_destructor);
170 new_data->comm=new_rec;
176 TRP_INFOREC *trp_inforec_get_next(TRP_INFOREC *rec)
184 static TRP_INFOREC *trp_inforec_get_tail(TRP_INFOREC *rec)
186 while ((rec->next)!=NULL)
187 rec=trp_inforec_get_next(rec);
191 void trp_inforec_set_next(TRP_INFOREC *rec, TRP_INFOREC *next_rec)
197 TRP_INFOREC_TYPE trp_inforec_get_type(TRP_INFOREC *rec)
202 return TRP_INFOREC_TYPE_UNKNOWN;
205 void trp_inforec_set_type(TRP_INFOREC *rec, TRP_INFOREC_TYPE type)
211 TR_NAME *trp_inforec_get_trust_router(TRP_INFOREC *rec)
214 case TRP_INFOREC_TYPE_ROUTE:
215 if (rec->data->route!=NULL)
216 return rec->data->route->trust_router;
224 int trp_inforec_get_trust_router_port(TRP_INFOREC *rec)
227 case TRP_INFOREC_TYPE_ROUTE:
228 if (rec->data->route!=NULL)
229 return rec->data->route->trust_router_port;
236 TR_NAME *trp_inforec_dup_trust_router(TRP_INFOREC *rec)
238 return tr_dup_name(trp_inforec_get_trust_router(rec));
241 TRP_RC trp_inforec_set_trust_router(TRP_INFOREC *rec, TR_NAME *trust_router, int port)
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;
257 TR_NAME *trp_inforec_get_next_hop(TRP_INFOREC *rec)
260 case TRP_INFOREC_TYPE_ROUTE:
261 if (rec->data->route!=NULL)
262 return rec->data->route->next_hop;
270 TR_NAME *trp_inforec_dup_next_hop(TRP_INFOREC *rec)
272 return tr_dup_name(trp_inforec_get_next_hop(rec));
276 * Set the next hop for the inforec
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.
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
287 TRP_RC trp_inforec_set_next_hop(TRP_INFOREC *rec, TR_NAME *next_hop, int port)
289 /* Any inforec types that support next_hop should set it here. */
291 case TRP_INFOREC_TYPE_ROUTE:
292 if (rec->data->route==NULL)
294 rec->data->route->next_hop = next_hop;
295 rec->data->route->next_hop_port = port;
299 /* next hop not used for other records */
300 return TRP_UNSUPPORTED;
305 int trp_inforec_get_next_hop_port(TRP_INFOREC *rec)
308 case TRP_INFOREC_TYPE_ROUTE:
309 if (rec->data->route!=NULL)
310 return rec->data->route->next_hop_port;
317 unsigned int trp_inforec_get_metric(TRP_INFOREC *rec)
320 case TRP_INFOREC_TYPE_ROUTE:
321 if (rec->data->route!=NULL)
322 return rec->data->route->metric;
327 return TRP_METRIC_INVALID;
330 TRP_RC trp_inforec_set_metric(TRP_INFOREC *rec, unsigned int metric)
333 case TRP_INFOREC_TYPE_ROUTE:
334 if (rec->data->route!=NULL) {
335 rec->data->route->metric=metric;
345 unsigned int trp_inforec_get_interval(TRP_INFOREC *rec)
348 case TRP_INFOREC_TYPE_ROUTE:
349 if (rec->data->route!=NULL)
350 return rec->data->route->interval;
352 case TRP_INFOREC_TYPE_COMMUNITY:
353 if (rec->data->comm!=NULL)
354 return rec->data->comm->interval;
359 return TRP_INTERVAL_INVALID;
362 TRP_RC trp_inforec_set_interval(TRP_INFOREC *rec, unsigned int interval)
365 case TRP_INFOREC_TYPE_ROUTE:
366 if (rec->data->route!=NULL) {
367 rec->data->route->interval=interval;
371 case TRP_INFOREC_TYPE_COMMUNITY:
372 if (rec->data->comm!=NULL) {
373 rec->data->comm->interval=interval;
382 time_t trp_inforec_get_exp_interval(TRP_INFOREC *rec)
385 case TRP_INFOREC_TYPE_COMMUNITY:
386 if (rec->data->comm!=NULL)
387 return rec->data->comm->expiration_interval;
395 TRP_RC trp_inforec_set_exp_interval(TRP_INFOREC *rec, time_t expint)
398 case TRP_INFOREC_TYPE_COMMUNITY:
399 if (rec->data->comm!=NULL) {
400 rec->data->comm->expiration_interval=expint;
410 TR_COMM_TYPE trp_inforec_get_comm_type(TRP_INFOREC *rec)
413 case TRP_INFOREC_TYPE_COMMUNITY:
414 if (rec->data->comm!=NULL)
415 return rec->data->comm->comm_type;
420 return TR_COMM_UNKNOWN;
423 TRP_RC trp_inforec_set_comm_type(TRP_INFOREC *rec, TR_COMM_TYPE type)
426 case TRP_INFOREC_TYPE_COMMUNITY:
427 if (rec->data->comm!=NULL) {
428 rec->data->comm->comm_type=type;
438 TR_REALM_ROLE trp_inforec_get_role(TRP_INFOREC *rec)
441 case TRP_INFOREC_TYPE_COMMUNITY:
442 if (rec->data->comm!=NULL)
443 return rec->data->comm->role;
448 return TR_ROLE_UNKNOWN;
451 TRP_RC trp_inforec_set_role(TRP_INFOREC *rec, TR_REALM_ROLE role)
454 case TRP_INFOREC_TYPE_COMMUNITY:
455 if (rec->data->comm!=NULL) {
456 rec->data->comm->role=role;
466 TR_APC *trp_inforec_get_apcs(TRP_INFOREC *rec)
469 case TRP_INFOREC_TYPE_COMMUNITY:
470 if (rec->data->comm!=NULL)
471 return rec->data->comm->apcs;
479 TRP_RC trp_inforec_set_apcs(TRP_INFOREC *rec, TR_APC *apcs)
482 case TRP_INFOREC_TYPE_COMMUNITY:
483 if (rec->data->comm!=NULL) {
484 rec->data->comm->apcs=apcs;
485 talloc_steal(rec, apcs);
496 TR_NAME *trp_inforec_get_owner_realm(TRP_INFOREC *rec)
499 case TRP_INFOREC_TYPE_COMMUNITY:
500 if (rec->data->comm!=NULL)
501 return rec->data->comm->owner_realm;
509 TRP_RC trp_inforec_set_owner_realm(TRP_INFOREC *rec, TR_NAME *name)
512 case TRP_INFOREC_TYPE_COMMUNITY:
513 if (rec->data->comm!=NULL) {
514 rec->data->comm->owner_realm=name;
524 TR_NAME *trp_inforec_get_owner_contact(TRP_INFOREC *rec)
527 case TRP_INFOREC_TYPE_COMMUNITY:
528 if (rec->data->comm!=NULL)
529 return rec->data->comm->owner_contact;
537 TRP_RC trp_inforec_set_owner_contact(TRP_INFOREC *rec, TR_NAME *name)
540 case TRP_INFOREC_TYPE_COMMUNITY:
541 if (rec->data->comm!=NULL) {
542 rec->data->comm->owner_contact=name;
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)
556 case TRP_INFOREC_TYPE_COMMUNITY:
557 if (rec->data->comm!=NULL)
558 return rec->data->comm->provenance;
566 /* increments the reference count */
567 TRP_RC trp_inforec_set_provenance(TRP_INFOREC *rec, json_t *prov)
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;
585 static TRP_RC trp_inforec_add_to_provenance(TRP_INFOREC *rec, TR_NAME *name)
590 case TRP_INFOREC_TYPE_ROUTE:
591 /* no provenance list */
593 case TRP_INFOREC_TYPE_COMMUNITY:
594 jname=tr_name_to_json_string(name);
597 if (rec->data->comm->provenance==NULL) {
598 rec->data->comm->provenance=json_array();
599 if (rec->data->comm->provenance==NULL) {
604 if (0!=json_array_append_new(rec->data->comm->provenance, jname)) {
615 TR_NAME *trp_inforec_dup_origin(TRP_INFOREC *rec)
617 TR_NAME *origin=NULL;
618 json_t *prov=trp_inforec_get_provenance(rec);
624 s=json_string_value(json_array_get(prov, 0));
626 tr_debug("trp_inforec_dup_origin: empty origin in provenance list.");
629 origin=tr_new_name(s);
633 /* generic record type */
634 TRP_INFOREC *trp_inforec_new(TALLOC_CTX *mem_ctx, TRP_INFOREC_TYPE type)
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);
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);
648 talloc_free(new_rec);
656 void trp_inforec_free(TRP_INFOREC *rec)
662 static int trp_upd_destructor(void *object)
664 TRP_UPD *upd=talloc_get_type_abort(object, TRP_UPD);
665 if (upd->realm!=NULL)
666 tr_free_name(upd->realm);
668 tr_free_name(upd->comm);
670 tr_free_name(upd->peer);
674 TRP_UPD *trp_upd_new(TALLOC_CTX *mem_ctx)
676 TRP_UPD *new_body=talloc(mem_ctx, TRP_UPD);
678 if (new_body!=NULL) {
679 new_body->realm=NULL;
681 new_body->records=NULL;
683 talloc_set_destructor((void *)new_body, trp_upd_destructor);
688 void trp_upd_free(TRP_UPD *update)
694 TRP_INFOREC *trp_upd_get_inforec(TRP_UPD *upd)
702 void trp_upd_set_inforec(TRP_UPD *upd, TRP_INFOREC *rec)
708 void trp_upd_add_inforec(TRP_UPD *upd, TRP_INFOREC *rec)
710 tr_debug("trp_upd_add_inforec: adding record.");
711 if (upd->records==NULL)
714 trp_inforec_set_next(trp_inforec_get_tail(upd->records), rec);
715 talloc_steal(upd, rec);
719 * Removes and frees the selected inforec.
721 * @param upd Update to remove from
722 * @param rec Inforec to remove
724 void trp_upd_remove_inforec(TRP_UPD *upd, TRP_INFOREC *rec)
726 TRP_INFOREC *this=upd->records;
728 /* special case for the first element */
730 upd->records=upd->records->next;
731 trp_inforec_free(this);
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);
744 size_t trp_upd_num_inforecs(TRP_UPD *upd)
747 TRP_INFOREC *this=upd->records;
749 while (this != NULL) {
757 TR_NAME *trp_upd_get_realm(TRP_UPD *upd)
762 TR_NAME *trp_upd_dup_realm(TRP_UPD *upd)
764 return tr_dup_name(upd->realm);
767 void trp_upd_set_realm(TRP_UPD *upd, TR_NAME *realm)
769 if (upd->realm!=NULL)
770 tr_free_name(upd->realm);
774 TR_NAME *trp_upd_get_comm(TRP_UPD *upd)
779 TR_NAME *trp_upd_dup_comm(TRP_UPD *upd)
781 return tr_dup_name(upd->comm);
784 void trp_upd_set_comm(TRP_UPD *upd, TR_NAME *comm)
787 tr_free_name(upd->comm);
791 TR_NAME *trp_upd_get_peer(TRP_UPD *upd)
796 TR_NAME *trp_upd_dup_peer(TRP_UPD *upd)
798 return tr_dup_name(upd->peer);
801 void trp_upd_set_peer(TRP_UPD *upd, TR_NAME *peer)
806 void trp_upd_set_next_hop(TRP_UPD *upd, const char *hostname, int port)
808 TRP_INFOREC *rec=NULL;
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)) {
814 /* Success, the TR_NAME in cpy is now stored with the inforec */
817 case TRP_UNSUPPORTED:
818 /* No error, but the inforec does not accept a next_hop. Free our copy. */
823 tr_err("trp_upd_set_next_hop: error setting next hop.");
830 void trp_upd_add_to_provenance(TRP_UPD *upd, TR_NAME *name)
832 TRP_INFOREC *rec=NULL;
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.");
842 static void trp_inforec_route_print(TRP_INFOREC_DATA *data)
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);
851 static void trp_inforec_comm_print(TRP_INFOREC_DATA *data)
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 */