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.
38 #include <trust_router/tr_name.h>
39 #include <trp_internal.h>
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 *);
52 struct trp_inforec_type_entry {
54 TRP_INFOREC_TYPE type;
55 TRP_INFOREC_DATA *(*allocate)(TALLOC_CTX *);
56 void (*print)(TRP_INFOREC_DATA *);
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 */
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)
68 struct trp_inforec_type_entry *entry=trp_inforec_type_table;
70 while ((entry->type != TRP_INFOREC_TYPE_UNKNOWN)
71 && (entry->type != msgtype)) {
77 /* translate strings to codes */
78 TRP_INFOREC_TYPE trp_inforec_type_from_string(const char *s)
80 struct trp_inforec_type_entry *entry=trp_inforec_type_table;
82 while ((entry->type != TRP_INFOREC_TYPE_UNKNOWN)
83 && (strcmp(s, entry->name)!=0)) {
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)
92 struct trp_inforec_type_entry *entry=get_trp_inforec_type_entry(msgtype);
96 /* called by talloc when destroying an update message body */
97 static int trp_inforec_route_destructor(void *object)
99 TRP_INFOREC_ROUTE *body=talloc_get_type_abort(object, TRP_INFOREC_ROUTE);
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);
109 static TRP_INFOREC_DATA *trp_inforec_route_new(TALLOC_CTX *mem_ctx)
111 TRP_INFOREC_DATA *new_data=talloc(mem_ctx, TRP_INFOREC_DATA);
112 TRP_INFOREC_ROUTE *new_rec=NULL;
117 new_rec=talloc(new_data, TRP_INFOREC_ROUTE);
118 if (new_rec == NULL) {
119 talloc_free(new_data);
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;
127 talloc_set_destructor((void *)new_rec, trp_inforec_route_destructor);
128 new_data->route=new_rec;
135 static int trp_inforec_comm_destructor(void *obj)
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);
147 static TRP_INFOREC_DATA *trp_inforec_comm_new(TALLOC_CTX *mem_ctx)
149 TRP_INFOREC_DATA *new_data=talloc(mem_ctx, TRP_INFOREC_DATA);
150 TRP_INFOREC_COMM *new_rec=NULL;
155 new_rec=talloc(new_data, TRP_INFOREC_COMM);
157 talloc_free(new_data);
160 new_rec->comm_type=TR_COMM_UNKNOWN;
161 new_rec->role=TR_ROLE_UNKNOWN;
163 new_rec->owner_realm=NULL;
164 new_rec->owner_contact=NULL;
165 new_rec->expiration_interval=0;
166 new_rec->provenance=NULL;
168 talloc_set_destructor((void *)new_rec, trp_inforec_comm_destructor);
169 new_data->comm=new_rec;
175 TRP_INFOREC *trp_inforec_get_next(TRP_INFOREC *rec)
183 static TRP_INFOREC *trp_inforec_get_tail(TRP_INFOREC *rec)
185 while ((rec->next)!=NULL)
186 rec=trp_inforec_get_next(rec);
190 void trp_inforec_set_next(TRP_INFOREC *rec, TRP_INFOREC *next_rec)
196 TRP_INFOREC_TYPE trp_inforec_get_type(TRP_INFOREC *rec)
201 return TRP_INFOREC_TYPE_UNKNOWN;
204 void trp_inforec_set_type(TRP_INFOREC *rec, TRP_INFOREC_TYPE type)
210 TR_NAME *trp_inforec_get_trust_router(TRP_INFOREC *rec)
213 case TRP_INFOREC_TYPE_ROUTE:
214 if (rec->data->route!=NULL)
215 return rec->data->route->trust_router;
223 TR_NAME *trp_inforec_dup_trust_router(TRP_INFOREC *rec)
225 return tr_dup_name(trp_inforec_get_trust_router(rec));
228 TRP_RC trp_inforec_set_trust_router(TRP_INFOREC *rec, TR_NAME *trust_router)
231 case TRP_INFOREC_TYPE_ROUTE:
232 if (rec->data->route!=NULL) {
233 rec->data->route->trust_router=trust_router;
243 /* TODO: need to return hostname/port --jlr */
244 TR_NAME *trp_inforec_get_next_hop(TRP_INFOREC *rec)
247 case TRP_INFOREC_TYPE_ROUTE:
248 if (rec->data->route!=NULL)
249 return rec->data->route->next_hop;
257 TR_NAME *trp_inforec_dup_next_hop(TRP_INFOREC *rec)
259 return tr_dup_name(trp_inforec_get_next_hop(rec));
262 TRP_RC trp_inforec_set_next_hop(TRP_INFOREC *rec, TR_NAME *next_hop)
265 case TRP_INFOREC_TYPE_ROUTE:
266 if (rec->data->route==NULL)
268 rec->data->route->next_hop=next_hop;
270 case TRP_INFOREC_TYPE_COMMUNITY:
271 /* next hop not used for community records */
279 unsigned int trp_inforec_get_metric(TRP_INFOREC *rec)
282 case TRP_INFOREC_TYPE_ROUTE:
283 if (rec->data->route!=NULL)
284 return rec->data->route->metric;
289 return TRP_METRIC_INVALID;
292 TRP_RC trp_inforec_set_metric(TRP_INFOREC *rec, unsigned int metric)
295 case TRP_INFOREC_TYPE_ROUTE:
296 if (rec->data->route!=NULL) {
297 rec->data->route->metric=metric;
307 unsigned int trp_inforec_get_interval(TRP_INFOREC *rec)
310 case TRP_INFOREC_TYPE_ROUTE:
311 if (rec->data->route!=NULL)
312 return rec->data->route->interval;
314 case TRP_INFOREC_TYPE_COMMUNITY:
315 if (rec->data->comm!=NULL)
316 return rec->data->comm->interval;
321 return TRP_INTERVAL_INVALID;
324 TRP_RC trp_inforec_set_interval(TRP_INFOREC *rec, unsigned int interval)
327 case TRP_INFOREC_TYPE_ROUTE:
328 if (rec->data->route!=NULL) {
329 rec->data->route->interval=interval;
333 case TRP_INFOREC_TYPE_COMMUNITY:
334 if (rec->data->comm!=NULL) {
335 rec->data->comm->interval=interval;
344 time_t trp_inforec_get_exp_interval(TRP_INFOREC *rec)
347 case TRP_INFOREC_TYPE_COMMUNITY:
348 if (rec->data->comm!=NULL)
349 return rec->data->comm->expiration_interval;
357 TRP_RC trp_inforec_set_exp_interval(TRP_INFOREC *rec, time_t expint)
360 case TRP_INFOREC_TYPE_COMMUNITY:
361 if (rec->data->comm!=NULL) {
362 rec->data->comm->expiration_interval=expint;
372 TR_COMM_TYPE trp_inforec_get_comm_type(TRP_INFOREC *rec)
375 case TRP_INFOREC_TYPE_COMMUNITY:
376 if (rec->data->comm!=NULL)
377 return rec->data->comm->comm_type;
382 return TR_COMM_UNKNOWN;
385 TRP_RC trp_inforec_set_comm_type(TRP_INFOREC *rec, TR_COMM_TYPE type)
388 case TRP_INFOREC_TYPE_COMMUNITY:
389 if (rec->data->comm!=NULL) {
390 rec->data->comm->comm_type=type;
400 TR_REALM_ROLE trp_inforec_get_role(TRP_INFOREC *rec)
403 case TRP_INFOREC_TYPE_COMMUNITY:
404 if (rec->data->comm!=NULL)
405 return rec->data->comm->role;
410 return TR_ROLE_UNKNOWN;
413 TRP_RC trp_inforec_set_role(TRP_INFOREC *rec, TR_REALM_ROLE role)
416 case TRP_INFOREC_TYPE_COMMUNITY:
417 if (rec->data->comm!=NULL) {
418 rec->data->comm->role=role;
428 TR_APC *trp_inforec_get_apcs(TRP_INFOREC *rec)
431 case TRP_INFOREC_TYPE_COMMUNITY:
432 if (rec->data->comm!=NULL)
433 return rec->data->comm->apcs;
441 TRP_RC trp_inforec_set_apcs(TRP_INFOREC *rec, TR_APC *apcs)
444 case TRP_INFOREC_TYPE_COMMUNITY:
445 if (rec->data->comm!=NULL) {
446 rec->data->comm->apcs=apcs;
447 talloc_steal(rec, apcs);
458 TR_NAME *trp_inforec_get_owner_realm(TRP_INFOREC *rec)
461 case TRP_INFOREC_TYPE_COMMUNITY:
462 if (rec->data->comm!=NULL)
463 return rec->data->comm->owner_realm;
471 TRP_RC trp_inforec_set_owner_realm(TRP_INFOREC *rec, TR_NAME *name)
474 case TRP_INFOREC_TYPE_COMMUNITY:
475 if (rec->data->comm!=NULL) {
476 rec->data->comm->owner_realm=name;
486 TR_NAME *trp_inforec_get_owner_contact(TRP_INFOREC *rec)
489 case TRP_INFOREC_TYPE_COMMUNITY:
490 if (rec->data->comm!=NULL)
491 return rec->data->comm->owner_contact;
499 TRP_RC trp_inforec_set_owner_contact(TRP_INFOREC *rec, TR_NAME *name)
502 case TRP_INFOREC_TYPE_COMMUNITY:
503 if (rec->data->comm!=NULL) {
504 rec->data->comm->owner_contact=name;
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)
518 case TRP_INFOREC_TYPE_COMMUNITY:
519 if (rec->data->comm!=NULL)
520 return rec->data->comm->provenance;
528 /* increments the reference count */
529 TRP_RC trp_inforec_set_provenance(TRP_INFOREC *rec, json_t *prov)
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;
547 static TRP_RC trp_inforec_add_to_provenance(TRP_INFOREC *rec, TR_NAME *name)
552 case TRP_INFOREC_TYPE_ROUTE:
553 /* no provenance list */
555 case TRP_INFOREC_TYPE_COMMUNITY:
556 jname=tr_name_to_json_string(name);
559 if (rec->data->comm->provenance==NULL) {
560 rec->data->comm->provenance=json_array();
561 if (rec->data->comm->provenance==NULL) {
566 if (0!=json_array_append_new(rec->data->comm->provenance, jname)) {
577 TR_NAME *trp_inforec_dup_origin(TRP_INFOREC *rec)
579 TR_NAME *origin=NULL;
580 json_t *prov=trp_inforec_get_provenance(rec);
586 s=json_string_value(json_array_get(prov, 0));
588 tr_debug("trp_inforec_dup_origin: empty origin in provenance list.");
591 origin=tr_new_name(s);
595 /* generic record type */
596 TRP_INFOREC *trp_inforec_new(TALLOC_CTX *mem_ctx, TRP_INFOREC_TYPE type)
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);
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);
610 talloc_free(new_rec);
618 void trp_inforec_free(TRP_INFOREC *rec)
624 static int trp_upd_destructor(void *object)
626 TRP_UPD *upd=talloc_get_type_abort(object, TRP_UPD);
627 if (upd->realm!=NULL)
628 tr_free_name(upd->realm);
630 tr_free_name(upd->comm);
632 tr_free_name(upd->peer);
636 TRP_UPD *trp_upd_new(TALLOC_CTX *mem_ctx)
638 TRP_UPD *new_body=talloc(mem_ctx, TRP_UPD);
640 if (new_body!=NULL) {
641 new_body->realm=NULL;
643 new_body->records=NULL;
645 talloc_set_destructor((void *)new_body, trp_upd_destructor);
650 void trp_upd_free(TRP_UPD *update)
656 TRP_INFOREC *trp_upd_get_inforec(TRP_UPD *upd)
664 void trp_upd_set_inforec(TRP_UPD *upd, TRP_INFOREC *rec)
670 void trp_upd_add_inforec(TRP_UPD *upd, TRP_INFOREC *rec)
672 tr_debug("trp_upd_add_inforec: adding record.");
673 if (upd->records==NULL)
676 trp_inforec_set_next(trp_inforec_get_tail(upd->records), rec);
677 talloc_steal(upd, rec);
680 TR_NAME *trp_upd_get_realm(TRP_UPD *upd)
685 TR_NAME *trp_upd_dup_realm(TRP_UPD *upd)
687 return tr_dup_name(upd->realm);
690 void trp_upd_set_realm(TRP_UPD *upd, TR_NAME *realm)
692 if (upd->realm!=NULL)
693 tr_free_name(upd->realm);
697 TR_NAME *trp_upd_get_comm(TRP_UPD *upd)
702 TR_NAME *trp_upd_dup_comm(TRP_UPD *upd)
704 return tr_dup_name(upd->comm);
707 void trp_upd_set_comm(TRP_UPD *upd, TR_NAME *comm)
710 tr_free_name(upd->comm);
714 TR_NAME *trp_upd_get_peer(TRP_UPD *upd)
719 TR_NAME *trp_upd_dup_peer(TRP_UPD *upd)
721 return tr_dup_name(upd->peer);
724 void trp_upd_set_peer(TRP_UPD *upd, TR_NAME *peer)
729 void trp_upd_set_next_hop(TRP_UPD *upd, const char *hostname, unsigned int port)
731 TRP_INFOREC *rec=NULL;
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.");
742 void trp_upd_add_to_provenance(TRP_UPD *upd, TR_NAME *name)
744 TRP_INFOREC *rec=NULL;
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.");
754 static void trp_inforec_route_print(TRP_INFOREC_DATA *data)
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);
763 static void trp_inforec_comm_print(TRP_INFOREC_DATA *data)
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 */