Fix pointer error.
[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->provenance=NULL;
166     talloc_set_destructor((void *)new_rec, trp_inforec_comm_destructor);
167     new_data->comm=new_rec;
168   }
169
170   return new_data;
171 }
172
173 TRP_INFOREC *trp_inforec_get_next(TRP_INFOREC *rec)
174 {
175   if (rec!=NULL)
176     return rec->next;
177   else
178     return NULL;
179 }
180
181 static TRP_INFOREC *trp_inforec_get_tail(TRP_INFOREC *rec)
182 {
183   while ((rec->next)!=NULL)
184     rec=trp_inforec_get_next(rec);
185   return rec;
186 }
187
188 void trp_inforec_set_next(TRP_INFOREC *rec, TRP_INFOREC *next_rec)
189 {
190   if (rec !=NULL)
191     rec->next=next_rec;
192 }
193
194 TRP_INFOREC_TYPE trp_inforec_get_type(TRP_INFOREC *rec)
195 {
196   if (rec)
197     return rec->type;
198   else
199     return TRP_INFOREC_TYPE_UNKNOWN;
200 }
201
202 void trp_inforec_set_type(TRP_INFOREC *rec, TRP_INFOREC_TYPE type)
203 {
204   if (rec!=NULL)
205     rec->type=type;
206 }
207
208 TR_NAME *trp_inforec_get_trust_router(TRP_INFOREC *rec)
209 {
210   switch (rec->type) {
211   case TRP_INFOREC_TYPE_ROUTE:
212     if (rec->data->route!=NULL)
213       return rec->data->route->trust_router;
214     break;
215   default:
216     break;
217   }
218   return NULL;
219 }
220
221 TR_NAME *trp_inforec_dup_trust_router(TRP_INFOREC *rec)
222 {
223   return tr_dup_name(trp_inforec_get_trust_router(rec));
224 }
225
226 TRP_RC trp_inforec_set_trust_router(TRP_INFOREC *rec, TR_NAME *trust_router)
227 {
228   switch (rec->type) {
229   case TRP_INFOREC_TYPE_ROUTE:
230     if (rec->data->route!=NULL) {
231       rec->data->route->trust_router=trust_router;
232       return TRP_SUCCESS;
233     }
234     break;
235   default:
236     break;
237   }
238   return TRP_ERROR;
239 }
240
241 /* TODO: need to return hostname/port --jlr */
242 TR_NAME *trp_inforec_get_next_hop(TRP_INFOREC *rec)
243 {
244   switch (rec->type) {
245   case TRP_INFOREC_TYPE_ROUTE:
246     if (rec->data->route!=NULL)
247       return rec->data->route->next_hop;
248     break;
249   default:
250     break;
251   }
252   return NULL;
253 }
254
255 TR_NAME *trp_inforec_dup_next_hop(TRP_INFOREC *rec)
256 {
257   return tr_dup_name(trp_inforec_get_next_hop(rec));
258 }
259
260 TRP_RC trp_inforec_set_next_hop(TRP_INFOREC *rec, TR_NAME *next_hop)
261 {
262   switch (rec->type) {
263   case TRP_INFOREC_TYPE_ROUTE:
264     if (rec->data->route!=NULL) {
265       rec->data->route->next_hop=next_hop;
266       return TRP_SUCCESS;
267     }
268     break;
269   default:
270     break;
271   }
272   return TRP_ERROR;
273 }
274
275 unsigned int trp_inforec_get_metric(TRP_INFOREC *rec)
276 {
277   switch (rec->type) {
278   case TRP_INFOREC_TYPE_ROUTE:
279     if (rec->data->route!=NULL)
280       return rec->data->route->metric;
281     break;
282   default:
283     break;
284   }
285   return TRP_METRIC_INVALID;
286 }
287
288 TRP_RC trp_inforec_set_metric(TRP_INFOREC *rec, unsigned int metric)
289 {
290   switch (rec->type) {
291   case TRP_INFOREC_TYPE_ROUTE:
292     if (rec->data->route!=NULL) {
293       rec->data->route->metric=metric;
294       return TRP_SUCCESS;
295     }
296     break;
297   default:
298     break;
299   }
300   return TRP_ERROR;
301 }
302
303 unsigned int trp_inforec_get_interval(TRP_INFOREC *rec)
304 {
305   switch (rec->type) {
306   case TRP_INFOREC_TYPE_ROUTE:
307     if (rec->data->route!=NULL)
308       return rec->data->route->interval;
309     break;
310   case TRP_INFOREC_TYPE_COMMUNITY:
311     if (rec->data->comm!=NULL)
312       return rec->data->comm->interval;
313     break;
314   default:
315     break;
316   }
317   return TRP_INTERVAL_INVALID;
318 }
319
320 TRP_RC trp_inforec_set_interval(TRP_INFOREC *rec, unsigned int interval)
321 {
322   switch (rec->type) {
323   case TRP_INFOREC_TYPE_ROUTE:
324     if (rec->data->route!=NULL) {
325       rec->data->route->interval=interval;
326       return TRP_SUCCESS;
327     }
328     break;
329   case TRP_INFOREC_TYPE_COMMUNITY:
330     if (rec->data->comm!=NULL) {
331       rec->data->comm->interval=interval;
332       return TRP_SUCCESS;
333     }
334   default:
335     break;
336   }
337   return TRP_ERROR;
338 }
339
340 TR_COMM_TYPE trp_inforec_get_comm_type(TRP_INFOREC *rec)
341 {
342   switch (rec->type) {
343   case TRP_INFOREC_TYPE_COMMUNITY:
344     if (rec->data->comm!=NULL)
345       return rec->data->comm->comm_type;
346     break;
347   default:
348     break;
349   }
350   return TR_COMM_UNKNOWN;
351 }
352
353 TRP_RC trp_inforec_set_comm_type(TRP_INFOREC *rec, TR_COMM_TYPE type)
354 {
355   switch (rec->type) {
356   case TRP_INFOREC_TYPE_COMMUNITY:
357     if (rec->data->comm!=NULL) {
358       rec->data->comm->comm_type=type;
359       return TRP_SUCCESS;
360     }
361     break;
362   default:
363     break;
364   }
365   return TRP_ERROR;
366 }
367
368 TR_REALM_ROLE trp_inforec_get_role(TRP_INFOREC *rec)
369 {
370   switch (rec->type) {
371   case TRP_INFOREC_TYPE_COMMUNITY:
372     if (rec->data->comm!=NULL)
373       return rec->data->comm->role;
374     break;
375   default:
376     break;
377   }
378   return TR_ROLE_UNKNOWN;
379 }
380
381 TRP_RC trp_inforec_set_role(TRP_INFOREC *rec, TR_REALM_ROLE role)
382 {
383   switch (rec->type) {
384   case TRP_INFOREC_TYPE_COMMUNITY:
385     if (rec->data->comm!=NULL) {
386       rec->data->comm->role=role;
387       return TRP_SUCCESS;
388       break;
389     }
390   default:
391     break;
392   }
393   return TRP_ERROR;
394 }
395
396 TR_APC *trp_inforec_get_apcs(TRP_INFOREC *rec)
397 {
398   switch (rec->type) {
399   case TRP_INFOREC_TYPE_COMMUNITY:
400     if (rec->data->comm!=NULL)
401       return rec->data->comm->apcs;
402     break;
403   default:
404     break;
405   }
406   return NULL;
407 }
408
409 TRP_RC trp_inforec_set_apcs(TRP_INFOREC *rec, TR_APC *apcs)
410 {
411   switch (rec->type) {
412   case TRP_INFOREC_TYPE_COMMUNITY:
413     if (rec->data->comm!=NULL) {
414       rec->data->comm->apcs=apcs;
415       talloc_steal(rec, apcs);
416       return TRP_SUCCESS;
417   default:
418     break;
419     }
420     break;
421   }
422   return TRP_ERROR;
423 }
424
425 TR_NAME *trp_inforec_get_owner_realm(TRP_INFOREC *rec)
426 {
427   switch (rec->type) {
428   case TRP_INFOREC_TYPE_COMMUNITY:
429     if (rec->data->comm!=NULL)
430       return rec->data->comm->owner_realm;
431     break;
432   default:
433     break;
434   }
435   return NULL;
436 }
437
438 TRP_RC trp_inforec_set_owner_realm(TRP_INFOREC *rec, TR_NAME *name)
439 {
440   switch (rec->type) {
441   case TRP_INFOREC_TYPE_COMMUNITY:
442     if (rec->data->comm!=NULL) {
443       rec->data->comm->owner_realm=name;
444       return TRP_SUCCESS;
445   default:
446     break;
447     }
448     break;
449   }
450   return TRP_ERROR;
451 }
452
453 TR_NAME *trp_inforec_get_owner_contact(TRP_INFOREC *rec)
454 {
455   switch (rec->type) {
456   case TRP_INFOREC_TYPE_COMMUNITY:
457     if (rec->data->comm!=NULL)
458       return rec->data->comm->owner_contact;
459     break;
460   default:
461     break;
462   }
463   return NULL;
464 }
465
466 TRP_RC trp_inforec_set_owner_contact(TRP_INFOREC *rec, TR_NAME *name)
467 {
468   switch (rec->type) {
469   case TRP_INFOREC_TYPE_COMMUNITY:
470     if (rec->data->comm!=NULL) {
471       rec->data->comm->owner_contact=name;
472       return TRP_SUCCESS;
473     }
474     break;
475   default:
476     break;
477   }
478   return TRP_ERROR;
479 }
480
481 /* caller needs to incref the output if they're going to hang on to it */
482 json_t *trp_inforec_get_provenance(TRP_INFOREC *rec)
483 {
484   switch (rec->type) {
485   case TRP_INFOREC_TYPE_COMMUNITY:
486     if (rec->data->comm!=NULL)
487       return rec->data->comm->provenance;
488     break;
489   default:
490     break;
491   }
492   return NULL;
493 }
494
495 /* increments the reference count */
496 TRP_RC trp_inforec_set_provenance(TRP_INFOREC *rec, json_t *prov)
497 {
498   switch (rec->type) {
499   case TRP_INFOREC_TYPE_COMMUNITY:
500     if (rec->data->comm!=NULL) {
501       if (rec->data->comm->provenance!=NULL)
502         json_decref(rec->data->comm->provenance);
503       rec->data->comm->provenance=prov;
504       json_incref(prov);
505       return TRP_SUCCESS;
506     }
507     break;
508   default:
509     break;
510   }
511   return TRP_ERROR;
512 }
513
514 /* generic record type */
515 TRP_INFOREC *trp_inforec_new(TALLOC_CTX *mem_ctx, TRP_INFOREC_TYPE type)
516 {
517   TRP_INFOREC *new_rec=talloc(mem_ctx, TRP_INFOREC);
518   TRP_INFOREC_DATA *data=NULL;
519   struct trp_inforec_type_entry *dtype=get_trp_inforec_type_entry(type);
520
521   if ((new_rec != NULL) && (dtype->type != TRP_INFOREC_TYPE_UNKNOWN)) {
522     trp_inforec_set_type(new_rec, type);
523     trp_inforec_set_next(new_rec, NULL);
524     if (dtype->allocate!=NULL) {
525       data=dtype->allocate(new_rec);
526       if (data!=NULL)
527         new_rec->data=data;
528       else {
529         talloc_free(new_rec);
530         return NULL;
531       }
532     }
533   }
534   return new_rec;
535 }
536
537 void trp_inforec_free(TRP_INFOREC *rec)
538 {
539   if (rec!=NULL)
540     talloc_free(rec);
541 }
542
543 static int trp_upd_destructor(void *object)
544 {
545   TRP_UPD *upd=talloc_get_type_abort(object, TRP_UPD);
546   if (upd->realm!=NULL)
547     tr_free_name(upd->realm);
548   if (upd->comm!=NULL)
549     tr_free_name(upd->comm);
550   if (upd->peer!=NULL)
551     tr_free_name(upd->peer);
552   return 0;
553 }
554
555 TRP_UPD *trp_upd_new(TALLOC_CTX *mem_ctx)
556 {
557   TRP_UPD *new_body=talloc(mem_ctx, TRP_UPD);
558
559   if (new_body!=NULL) {
560     new_body->realm=NULL;
561     new_body->comm=NULL;
562     new_body->records=NULL;
563     new_body->peer=NULL;
564     talloc_set_destructor((void *)new_body, trp_upd_destructor);
565   }
566   return new_body;
567 }
568
569 void trp_upd_free(TRP_UPD *update)
570 {
571   if (update!=NULL)
572     talloc_free(update);
573 }
574
575 TRP_INFOREC *trp_upd_get_inforec(TRP_UPD *upd)
576 {
577   if (upd!=NULL)
578     return upd->records;
579   else
580     return NULL;
581 }
582
583 void trp_upd_set_inforec(TRP_UPD *upd, TRP_INFOREC *rec)
584 {
585   if (upd!=NULL)
586     upd->records=rec;
587 }
588
589 void trp_upd_add_inforec(TRP_UPD *upd, TRP_INFOREC *rec)
590 {
591   tr_debug("trp_upd_add_inforec: adding record.");
592   if (upd->records==NULL)
593     upd->records=rec;
594   else
595     trp_inforec_set_next(trp_inforec_get_tail(upd->records), rec);
596   talloc_steal(upd, rec);
597 }
598
599 TR_NAME *trp_upd_get_realm(TRP_UPD *upd)
600 {
601   return upd->realm;
602 }
603
604 TR_NAME *trp_upd_dup_realm(TRP_UPD *upd)
605 {
606   return tr_dup_name(upd->realm);
607 }
608
609 void trp_upd_set_realm(TRP_UPD *upd, TR_NAME *realm)
610 {
611   if (upd->realm!=NULL)
612     tr_free_name(upd->realm);
613   upd->realm=realm;
614 }
615
616 TR_NAME *trp_upd_get_comm(TRP_UPD *upd)
617 {
618   return upd->comm;
619 }
620
621 TR_NAME *trp_upd_dup_comm(TRP_UPD *upd)
622 {
623   return tr_dup_name(upd->comm);
624 }
625
626 void trp_upd_set_comm(TRP_UPD *upd, TR_NAME *comm)
627 {
628   if (upd->comm!=NULL)
629     tr_free_name(upd->comm);
630   upd->comm=comm;
631 }
632
633 TR_NAME *trp_upd_get_peer(TRP_UPD *upd)
634 {
635   return upd->peer;
636 }
637
638 TR_NAME *trp_upd_dup_peer(TRP_UPD *upd)
639 {
640   return tr_dup_name(upd->peer);
641 }
642
643 void trp_upd_set_peer(TRP_UPD *upd, TR_NAME *peer)
644 {
645   upd->peer=peer;
646 }
647
648 void trp_upd_set_next_hop(TRP_UPD *upd, const char *hostname, unsigned int port)
649 {
650   TRP_INFOREC *rec=NULL;
651   TR_NAME *cpy=NULL;
652   
653   for (rec=trp_upd_get_inforec(upd); rec!=NULL; rec=trp_inforec_get_next(rec)) {
654     if (trp_inforec_set_next_hop(rec, cpy=tr_new_name(hostname)) != TRP_SUCCESS) {
655       tr_err("trp_upd_set_peer: error setting peer.");
656       tr_free_name(cpy);
657     }
658   }
659 }
660
661 /* pretty print */
662 static void trp_inforec_route_print(TRP_INFOREC_DATA *data)
663 {
664   if (data->route!=NULL) {
665     printf("     trust_router=%.*s\n     metric=%d\n     interval=%d]\n",
666            data->route->trust_router->len, data->route->trust_router->buf,
667            data->route->metric, data->route->interval);
668   }
669 }
670
671 static void trp_inforec_comm_print(TRP_INFOREC_DATA *data)
672 {
673   if (data->comm!=NULL) {
674     printf("     type=%s\n     role=%s\n     owner=%.*s\n     contact=%.*s]\n",
675            tr_comm_type_to_str(data->comm->comm_type),
676            tr_realm_role_to_str(data->comm->role),
677            data->comm->owner_realm->len, data->comm->owner_realm->buf,
678            data->comm->owner_contact->len, data->comm->owner_contact->buf);
679     /* TODO: print apcs */
680   }
681 }