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