Send all msgs in trpc outgoing queue, not just the first.
[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_debug.h>
41
42
43 /* static prototypes */
44 static TRP_INFOREC_DATA *trp_inforec_route_new(TALLOC_CTX *mem_ctx);
45 static void trp_inforec_route_print(TRP_INFOREC_DATA *);
46 static TRP_INFOREC_DATA *trp_inforec_comm_new(TALLOC_CTX *mem_ctx);
47 static void trp_inforec_comm_print(TRP_INFOREC_DATA *);
48
49
50 struct trp_inforec_type_entry {
51   const char *name;
52   TRP_INFOREC_TYPE type;
53   TRP_INFOREC_DATA *(*allocate)(TALLOC_CTX *);
54   void (*print)(TRP_INFOREC_DATA *);
55 };
56 static struct trp_inforec_type_entry trp_inforec_type_table[] = {
57   { "route", TRP_INFOREC_TYPE_ROUTE, trp_inforec_route_new, trp_inforec_route_print },
58   { "comm", TRP_INFOREC_TYPE_COMMUNITY, trp_inforec_comm_new, trp_inforec_comm_print },
59   { NULL, TRP_INFOREC_TYPE_UNKNOWN, NULL, NULL } /* must be the last entry */
60 };
61
62
63 /* look up an entry in the trp_inforec_type_table */
64 static struct trp_inforec_type_entry *get_trp_inforec_type_entry(TRP_INFOREC_TYPE msgtype)
65 {
66   struct trp_inforec_type_entry *entry=trp_inforec_type_table;
67
68   while ((entry->type != TRP_INFOREC_TYPE_UNKNOWN)
69         && (entry->type != msgtype)) {
70     entry ++;
71   }
72   return entry;
73 }
74
75 /* translate strings to codes */
76 TRP_INFOREC_TYPE trp_inforec_type_from_string(const char *s)
77 {
78   struct trp_inforec_type_entry *entry=trp_inforec_type_table;
79
80   while ((entry->type != TRP_INFOREC_TYPE_UNKNOWN)
81         && (strcmp(s, entry->name)!=0)) {
82     entry++;
83   }
84   return entry->type;
85 }
86 /* translate codes to strings (do not need to be freed) 
87  * Returns NULL on an unknown code */
88 const char *trp_inforec_type_to_string(TRP_INFOREC_TYPE msgtype)
89 {
90   struct trp_inforec_type_entry *entry=get_trp_inforec_type_entry(msgtype);
91   return entry->name;
92 }
93
94 /* called by talloc when destroying an update message body */
95 static int trp_inforec_route_destructor(void *object)
96 {
97   TRP_INFOREC_ROUTE *body=talloc_get_type_abort(object, TRP_INFOREC_ROUTE);
98   
99   /* clean up TR_NAME data, which are not managed by talloc */
100   if (body->trust_router != NULL)
101     tr_free_name(body->trust_router);
102   if (body->next_hop != NULL)
103     tr_free_name(body->next_hop);
104   return 0;
105 }
106
107 static TRP_INFOREC_DATA *trp_inforec_route_new(TALLOC_CTX *mem_ctx)
108 {
109   TRP_INFOREC_DATA *new_data=talloc(mem_ctx, TRP_INFOREC_DATA);
110   TRP_INFOREC_ROUTE *new_rec=NULL;
111
112   if (new_data==NULL)
113     return NULL;
114
115   new_rec=talloc(new_data, TRP_INFOREC_ROUTE);
116   if (new_rec == NULL) {
117     talloc_free(new_data);
118     new_data=NULL;
119   } else {
120     new_rec->trust_router=NULL;
121     new_rec->next_hop=NULL;
122     new_rec->next_hop_port=0;
123     new_rec->metric=TRP_METRIC_INFINITY;
124     new_rec->interval=0;
125     talloc_set_destructor((void *)new_rec, trp_inforec_route_destructor);
126     new_data->route=new_rec;
127   }
128     
129   return new_data;
130 }
131
132
133 static int trp_inforec_comm_destructor(void *obj)
134 {
135   TRP_INFOREC_COMM *rec=talloc_get_type_abort(obj, TRP_INFOREC_COMM);
136   if (rec->owner_realm!=NULL)
137     tr_free_name(rec->owner_realm);
138   if (rec->owner_contact!=NULL)
139     tr_free_name(rec->owner_contact);
140   return 0;
141 }
142
143 static TRP_INFOREC_DATA *trp_inforec_comm_new(TALLOC_CTX *mem_ctx)
144 {
145   TRP_INFOREC_DATA *new_data=talloc(mem_ctx, TRP_INFOREC_DATA);
146   TRP_INFOREC_COMM *new_rec=NULL;
147
148   if (new_data==NULL)
149     return NULL;
150
151   new_rec=talloc(new_data, TRP_INFOREC_COMM);
152   if (new_rec==NULL) {
153     talloc_free(new_data);
154     new_data=NULL;
155   } else {
156     new_rec->type=TR_COMM_UNKNOWN;
157     new_rec->is_service_realm=0;
158     new_rec->is_idp_realm=0;
159     new_rec->apcs=NULL;
160     new_rec->owner_realm=NULL;
161     new_rec->owner_contact=NULL;
162     talloc_set_destructor((void *)new_rec, trp_inforec_comm_destructor);
163     new_data->comm=new_rec;
164   }
165
166   return new_data;
167 }
168
169 TRP_INFOREC *trp_inforec_get_next(TRP_INFOREC *rec)
170 {
171   if (rec!=NULL)
172     return rec->next;
173   else
174     return NULL;
175 }
176
177 static TRP_INFOREC *trp_inforec_get_tail(TRP_INFOREC *rec)
178 {
179   while ((rec->next)!=NULL)
180     rec=trp_inforec_get_next(rec);
181   return rec;
182 }
183
184 void trp_inforec_set_next(TRP_INFOREC *rec, TRP_INFOREC *next_rec)
185 {
186   if (rec !=NULL)
187     rec->next=next_rec;
188 }
189
190 TRP_INFOREC_TYPE trp_inforec_get_type(TRP_INFOREC *rec)
191 {
192   if (rec)
193     return rec->type;
194   else
195     return TRP_INFOREC_TYPE_UNKNOWN;
196 }
197
198 void trp_inforec_set_type(TRP_INFOREC *rec, TRP_INFOREC_TYPE type)
199 {
200   if (rec!=NULL)
201     rec->type=type;
202 }
203
204 TR_NAME *trp_inforec_get_trust_router(TRP_INFOREC *rec)
205 {
206   switch (rec->type) {
207   case TRP_INFOREC_TYPE_ROUTE:
208     if (rec->data->route!=NULL)
209       return rec->data->route->trust_router;
210     break;
211   default:
212     break;
213   }
214   return NULL;
215 }
216
217 TR_NAME *trp_inforec_dup_trust_router(TRP_INFOREC *rec)
218 {
219   return tr_dup_name(trp_inforec_get_trust_router(rec));
220 }
221
222 TRP_RC trp_inforec_set_trust_router(TRP_INFOREC *rec, TR_NAME *trust_router)
223 {
224   switch (rec->type) {
225   case TRP_INFOREC_TYPE_ROUTE:
226     if (rec->data->route!=NULL) {
227       rec->data->route->trust_router=trust_router;
228       return TRP_SUCCESS;
229     }
230     break;
231   default:
232     break;
233   }
234   return TRP_ERROR;
235 }
236
237 /* TODO: need to return hostname/port --jlr */
238 TR_NAME *trp_inforec_get_next_hop(TRP_INFOREC *rec)
239 {
240   switch (rec->type) {
241   case TRP_INFOREC_TYPE_ROUTE:
242     if (rec->data->route!=NULL)
243       return rec->data->route->next_hop;
244     break;
245   default:
246     break;
247   }
248   return NULL;
249 }
250
251 TR_NAME *trp_inforec_dup_next_hop(TRP_INFOREC *rec)
252 {
253   return tr_dup_name(trp_inforec_get_next_hop(rec));
254 }
255
256 TRP_RC trp_inforec_set_next_hop(TRP_INFOREC *rec, TR_NAME *next_hop)
257 {
258   switch (rec->type) {
259   case TRP_INFOREC_TYPE_ROUTE:
260     if (rec->data->route!=NULL) {
261       rec->data->route->next_hop=next_hop;
262       return TRP_SUCCESS;
263     }
264     break;
265   default:
266     break;
267   }
268   return TRP_ERROR;
269 }
270
271 unsigned int trp_inforec_get_metric(TRP_INFOREC *rec)
272 {
273   switch (rec->type) {
274   case TRP_INFOREC_TYPE_ROUTE:
275     if (rec->data->route!=NULL)
276       return rec->data->route->metric;
277     break;
278   default:
279     break;
280   }
281   return TRP_METRIC_INVALID;
282 }
283
284 TRP_RC trp_inforec_set_metric(TRP_INFOREC *rec, unsigned int metric)
285 {
286   switch (rec->type) {
287   case TRP_INFOREC_TYPE_ROUTE:
288     if (rec->data->route!=NULL) {
289       rec->data->route->metric=metric;
290       return TRP_SUCCESS;
291     }
292     break;
293   default:
294     break;
295   }
296   return TRP_ERROR;
297 }
298
299 unsigned int trp_inforec_get_interval(TRP_INFOREC *rec)
300 {
301   switch (rec->type) {
302   case TRP_INFOREC_TYPE_ROUTE:
303     if (rec->data->route!=NULL)
304       return rec->data->route->interval;
305     break;
306   default:
307     break;
308   }
309   return TRP_INTERVAL_INVALID;
310 }
311
312 TRP_RC trp_inforec_set_interval(TRP_INFOREC *rec, unsigned int interval)
313 {
314   switch (rec->type) {
315   case TRP_INFOREC_TYPE_ROUTE:
316     if (rec->data->route!=NULL) {
317       rec->data->route->interval=interval;
318       return TRP_SUCCESS;
319   default:
320     break;
321     }
322     break;
323   }
324   return TRP_ERROR;
325 }
326
327 /* generic record type */
328 TRP_INFOREC *trp_inforec_new(TALLOC_CTX *mem_ctx, TRP_INFOREC_TYPE type)
329 {
330   TRP_INFOREC *new_rec=talloc(mem_ctx, TRP_INFOREC);
331   TRP_INFOREC_DATA *data=NULL;
332   struct trp_inforec_type_entry *dtype=get_trp_inforec_type_entry(type);
333
334   if ((new_rec != NULL) && (dtype->type != TRP_INFOREC_TYPE_UNKNOWN)) {
335     trp_inforec_set_type(new_rec, type);
336     trp_inforec_set_next(new_rec, NULL);
337     if (dtype->allocate!=NULL) {
338       data=dtype->allocate(new_rec);
339       if (data!=NULL)
340         new_rec->data=data;
341       else {
342         talloc_free(new_rec);
343         return NULL;
344       }
345     }
346   }
347   return new_rec;
348 }
349
350 void trp_inforec_free(TRP_INFOREC *rec)
351 {
352   if (rec!=NULL)
353     talloc_free(rec);
354 }
355
356 static int trp_upd_destructor(void *object)
357 {
358   TRP_UPD *upd=talloc_get_type_abort(object, TRP_UPD);
359   if (upd->realm!=NULL)
360     tr_free_name(upd->realm);
361   if (upd->comm!=NULL)
362     tr_free_name(upd->comm);
363   if (upd->peer!=NULL)
364     tr_free_name(upd->peer);
365   return 0;
366 }
367
368 TRP_UPD *trp_upd_new(TALLOC_CTX *mem_ctx)
369 {
370   TRP_UPD *new_body=talloc(mem_ctx, TRP_UPD);
371
372   if (new_body!=NULL) {
373     new_body->realm=NULL;
374     new_body->comm=NULL;
375     new_body->records=NULL;
376     new_body->peer=NULL;
377     talloc_set_destructor((void *)new_body, trp_upd_destructor);
378   }
379   return new_body;
380 }
381
382 void trp_upd_free(TRP_UPD *update)
383 {
384   if (update!=NULL)
385     talloc_free(update);
386 }
387
388 TRP_INFOREC *trp_upd_get_inforec(TRP_UPD *upd)
389 {
390   if (upd!=NULL)
391     return upd->records;
392   else
393     return NULL;
394 }
395
396 void trp_upd_set_inforec(TRP_UPD *upd, TRP_INFOREC *rec)
397 {
398   if (upd!=NULL)
399     upd->records=rec;
400 }
401
402 void trp_upd_add_inforec(TRP_UPD *upd, TRP_INFOREC *rec)
403 {
404   tr_debug("trp_upd_add_inforec: adding record.");
405   if (upd->records==NULL)
406     upd->records=rec;
407   else
408     trp_inforec_set_next(trp_inforec_get_tail(upd->records), rec);
409   talloc_steal(upd, rec);
410 }
411
412 TR_NAME *trp_upd_get_realm(TRP_UPD *upd)
413 {
414   return upd->realm;
415 }
416
417 TR_NAME *trp_upd_dup_realm(TRP_UPD *upd)
418 {
419   return tr_dup_name(upd->realm);
420 }
421
422 void trp_upd_set_realm(TRP_UPD *upd, TR_NAME *realm)
423 {
424   if (upd->realm!=NULL)
425     tr_free_name(upd->realm);
426   upd->realm=realm;
427 }
428
429 TR_NAME *trp_upd_get_comm(TRP_UPD *upd)
430 {
431   return upd->comm;
432 }
433
434 TR_NAME *trp_upd_dup_comm(TRP_UPD *upd)
435 {
436   return tr_dup_name(upd->comm);
437 }
438
439 void trp_upd_set_comm(TRP_UPD *upd, TR_NAME *comm)
440 {
441   if (upd->comm!=NULL)
442     tr_free_name(upd->comm);
443   upd->comm=comm;
444 }
445
446 TR_NAME *trp_upd_get_peer(TRP_UPD *upd)
447 {
448   return upd->peer;
449 }
450
451 TR_NAME *trp_upd_dup_peer(TRP_UPD *upd)
452 {
453   return tr_dup_name(upd->peer);
454 }
455
456 void trp_upd_set_peer(TRP_UPD *upd, TR_NAME *peer)
457 {
458   upd->peer=peer;
459 }
460
461 void trp_upd_set_next_hop(TRP_UPD *upd, const char *hostname, unsigned int port)
462 {
463   TRP_INFOREC *rec=NULL;
464   TR_NAME *cpy=NULL;
465   
466   for (rec=trp_upd_get_inforec(upd); rec!=NULL; rec=trp_inforec_get_next(rec)) {
467     if (trp_inforec_set_next_hop(rec, cpy=tr_new_name(hostname)) != TRP_SUCCESS) {
468       tr_err("trp_upd_set_peer: error setting peer.");
469       tr_free_name(cpy);
470     }
471   }
472 }
473
474 /* pretty print */
475 static void trp_inforec_route_print(TRP_INFOREC_DATA *data)
476 {
477   if (data->route!=NULL) {
478     printf("     trust_router=%.*s\n     metric=%d\n     interval=%d]\n",
479            data->route->trust_router->len, data->route->trust_router->buf,
480            data->route->metric, data->route->interval);
481   }
482 }
483
484 static void trp_inforec_comm_print(TRP_INFOREC_DATA *data)
485 {
486   if (data->comm!=NULL) {
487     printf("     type=%s\n     service=%s\n     IdP=%s\n     owner=%.*s\n     contact=%.*s]\n",
488            tr_comm_type_to_str(data->comm->type),
489            (data->comm->is_service_realm)?"yes":"no",
490            (data->comm->is_idp_realm)?"yes":"no",
491            data->comm->owner_realm->len, data->comm->owner_realm->buf,
492            data->comm->owner_contact->len, data->comm->owner_contact->buf);
493     /* TODO: print apcs */
494   }
495 }