Update route table when a TRP update is received. Not tested.
[trust_router.git] / trp / trp_upd.c
1 #include <jansson.h>
2 #include <talloc.h>
3
4 #include <trust_router/tr_name.h>
5 #include <trp_internal.h>
6 #include <tr_debug.h>
7
8
9 /* static prototypes */
10 static void *trp_inforec_route_new(TALLOC_CTX *mem_ctx);
11 static void trp_inforec_route_print(TRP_INFOREC_DATA);
12
13
14 struct trp_inforec_type_entry {
15   const char *name;
16   TRP_INFOREC_TYPE type;
17   void *(*allocate)(TALLOC_CTX *);
18   void (*print)(TRP_INFOREC_DATA);
19 };
20 static struct trp_inforec_type_entry trp_inforec_type_table[] = {
21   { "route", TRP_INFOREC_TYPE_ROUTE, trp_inforec_route_new, trp_inforec_route_print },
22   { "comm", TRP_INFOREC_TYPE_COMMUNITY, NULL, NULL },
23   { NULL, TRP_INFOREC_TYPE_UNKNOWN, NULL, NULL } /* must be the last entry */
24 };
25
26
27 /* look up an entry in the trp_inforec_type_table */
28 static struct trp_inforec_type_entry *get_trp_inforec_type_entry(TRP_INFOREC_TYPE msgtype)
29 {
30   struct trp_inforec_type_entry *entry=trp_inforec_type_table;
31
32   while ((entry->type != TRP_INFOREC_TYPE_UNKNOWN)
33         && (entry->type != msgtype)) {
34     entry ++;
35   }
36   return entry;
37 }
38
39 /* translate strings to codes */
40 TRP_INFOREC_TYPE trp_inforec_type_from_string(const char *s)
41 {
42   struct trp_inforec_type_entry *entry=trp_inforec_type_table;
43
44   while ((entry->type != TRP_INFOREC_TYPE_UNKNOWN)
45         && (strcmp(s, entry->name)!=0)) {
46     entry++;
47   }
48   return entry->type;
49 }
50 /* translate codes to strings (do not need to be freed) 
51  * Returns NULL on an unknown code */
52 const char *trp_inforec_type_to_string(TRP_INFOREC_TYPE msgtype)
53 {
54   struct trp_inforec_type_entry *entry=get_trp_inforec_type_entry(msgtype);
55   return entry->name;
56 }
57
58 /* called by talloc when destroying an update message body */
59 static int trp_inforec_route_destructor(void *object)
60 {
61   TRP_INFOREC_ROUTE *body=talloc_get_type_abort(object, TRP_INFOREC_ROUTE);
62   
63   /* clean up TR_NAME data, which are not managed by talloc */
64   if (body->comm != NULL) {
65     tr_free_name(body->comm);
66     body->comm=NULL;
67     tr_debug("trp_inforec_route_destructor: freed community");
68   }
69   if (body->realm != NULL) {
70     tr_free_name(body->realm);
71     body->realm=NULL;
72     tr_debug("trp_inforec_route_destructor: freed realm");
73   }
74   if (body->trust_router != NULL) {
75     tr_free_name(body->trust_router);
76     body->trust_router=NULL;
77     tr_debug("trp_inforec_route_destructor: freed trust_router");
78   }
79   if (body->next_hop != NULL) {
80     tr_free_name(body->next_hop);
81     body->hop=NULL;
82     tr_debug("trp_inforec_route_destructor: freed next_hop");
83   }
84
85   return 0;
86 }
87
88 static void *trp_inforec_route_new(TALLOC_CTX *mem_ctx)
89 {
90   TRP_INFOREC_ROUTE *new_rec=talloc(mem_ctx, TRP_INFOREC_ROUTE);
91
92   if (new_rec != NULL) {
93     new_rec->comm=NULL;
94     new_rec->realm=NULL;
95     new_rec->trust_router=NULL;
96     new_rec->next_hop=NULL;
97     new_rec->metric=TRP_METRIC_INFINITY;
98     new_rec->interval=0;
99     talloc_set_destructor((void *)new_rec, trp_inforec_route_destructor);
100   }
101   return new_rec;
102 }
103
104 TRP_INFOREC *trp_inforec_get_next(TRP_INFOREC *rec)
105 {
106   if (rec!=NULL)
107     return rec->next;
108   else
109     return NULL;
110 }
111
112 void trp_inforec_set_next(TRP_INFOREC *rec, TRP_INFOREC *next_rec)
113 {
114   if (rec !=NULL)
115     rec->next=next_rec;
116 }
117
118 TRP_INFOREC_TYPE trp_inforec_get_type(TRP_INFOREC *rec)
119 {
120   if (rec)
121     return rec->type;
122   else
123     return TRP_INFOREC_TYPE_UNKNOWN;
124 }
125
126 void trp_inforec_set_type(TRP_INFOREC *rec, TRP_INFOREC_TYPE type)
127 {
128   if (rec!=NULL)
129     rec->type=type;
130 }
131
132 TR_NAME *trp_inforec_get_comm(TRP_INFOREC *rec)
133 {
134   switch (rec->type) {
135   case TRP_INFOREC_TYPE_ROUTE:
136     if (rec->data.route!=NULL)
137       return rec->data.route->comm;
138     break;
139   default:
140     break;
141   }
142   return NULL;
143 }
144
145 TRP_RC trp_inforec_set_comm(TRP_INFOREC *rec, TR_NAME *comm)
146 {
147   switch (rec->type) {
148   case TRP_INFOREC_TYPE_ROUTE:
149     if (rec->data.route!=NULL) {
150       rec->data.route->comm=comm;
151       return TRP_SUCCESS;
152     }
153     break;
154   default:
155     break;
156   }
157   return TRP_ERROR;
158 }
159
160 TR_NAME *trp_inforec_get_realm(TRP_INFOREC *rec)
161 {
162   switch (rec->type) {
163   case TRP_INFOREC_TYPE_ROUTE:
164     if (rec->data.route!=NULL)
165       return rec->data.route->realm;
166     break;
167   default:
168     break;
169   }
170   return NULL;
171 }
172
173 TRP_RC trp_inforec_set_realm(TRP_INFOREC *rec, TR_NAME *realm)
174 {
175   switch (rec->type) {
176   case TRP_INFOREC_TYPE_ROUTE:
177     if (rec->data.route!=NULL) {
178       rec->data.route->realm=realm;
179       return TRP_SUCCESS;
180     } 
181     break;
182   default:
183     break;
184   }
185   return TRP_ERROR;
186 }
187
188 TR_NAME *trp_inforec_get_trust_router(TRP_INFOREC *rec)
189 {
190   switch (rec->type) {
191   case TRP_INFOREC_TYPE_ROUTE:
192     if (rec->data.route!=NULL)
193       return rec->data.route->trust_router;
194     break;
195   default:
196     break;
197   }
198   return NULL;
199 }
200
201 TRP_RC trp_inforec_set_trust_router(TRP_INFOREC *rec, TR_NAME *trust_router)
202 {
203   switch (rec->type) {
204   case TRP_INFOREC_TYPE_ROUTE:
205     if (rec->data.route!=NULL) {
206       rec->data.route->trust_router=trust_router;
207       return TRP_SUCCESS;
208     }
209     break;
210   default:
211     break;
212   }
213   return TRP_ERROR;
214 }
215
216 TR_NAME *trp_inforec_get_next_hop(TRP_INFOREC *rec)
217 {
218   switch (rec->type) {
219   case TRP_INFOREC_TYPE_ROUTE:
220     if (rec->data.route!=NULL)
221       return rec->data.route->next_hop;
222     break;
223   default:
224     break;
225   }
226   return NULL;
227 }
228
229 TRP_RC trp_inforec_set_next_hop(TRP_INFOREC *rec, TR_NAME *next_hop)
230 {
231   switch (rec->type) {
232   case TRP_INFOREC_TYPE_ROUTE:
233     if (rec->data.route!=NULL) {
234       rec->data.route->next_hop=next_hop;
235       return TRP_SUCCESS;
236     }
237     break;
238   default:
239     break;
240   }
241   return TRP_ERROR;
242 }
243
244 unsigned int trp_inforec_get_metric(TRP_INFOREC *rec)
245 {
246   switch (rec->type) {
247   case TRP_INFOREC_TYPE_ROUTE:
248     if (rec->data.route!=NULL)
249       return rec->data.route->metric;
250     break;
251   default:
252     break;
253   }
254   return TRP_METRIC_INVALID;
255 }
256
257 TRP_RC trp_inforec_set_metric(TRP_INFOREC *rec, unsigned int metric)
258 {
259   switch (rec->type) {
260   case TRP_INFOREC_TYPE_ROUTE:
261     if (rec->data.route!=NULL) {
262       rec->data.route->metric=metric;
263       return TRP_SUCCESS;
264     }
265     break;
266   default:
267     break;
268   }
269   return TRP_ERROR;
270 }
271
272 unsigned int trp_inforec_get_interval(TRP_INFOREC *rec)
273 {
274   switch (rec->type) {
275   case TRP_INFOREC_TYPE_ROUTE:
276     if (rec->data.route!=NULL)
277       return rec->data.route->interval;
278     break;
279   default:
280     break;
281   }
282   return TRP_INTERVAL_INVALID;
283 }
284
285 TRP_RC trp_inforec_set_interval(TRP_INFOREC *rec, unsigned int interval)
286 {
287   switch (rec->type) {
288   case TRP_INFOREC_TYPE_ROUTE:
289     if (rec->data.route!=NULL) {
290       rec->data.route->interval=interval;
291       return TRP_SUCCESS;
292   default:
293     break;
294     }
295     break;
296   }
297   return TRP_ERROR;
298 }
299
300 /* for internal use only; must set rec->type before calling this */
301 static TRP_RC trp_inforec_set_data(TRP_INFOREC *rec, void *data)
302 {
303   if (data==NULL)
304     return TRP_ERROR;
305
306   switch (rec->type) {
307   case TRP_INFOREC_TYPE_ROUTE:
308     rec->data.route=talloc_get_type(data, TRP_INFOREC_ROUTE);
309     break;
310   default:
311     return TRP_BADTYPE;
312   }
313   return TRP_SUCCESS;
314 }
315
316 /* generic record type */
317 TRP_INFOREC *trp_inforec_new(TALLOC_CTX *mem_ctx, TRP_INFOREC_TYPE type)
318 {
319   TRP_INFOREC *new_rec=talloc(mem_ctx, TRP_INFOREC);
320   struct trp_inforec_type_entry *dtype=get_trp_inforec_type_entry(type);
321
322   if ((new_rec != NULL) && (dtype->type != TRP_INFOREC_TYPE_UNKNOWN)) {
323     trp_inforec_set_type(new_rec, type);
324     trp_inforec_set_next(new_rec, NULL);
325     if (dtype->allocate!=NULL) {
326       if (TRP_SUCCESS!=trp_inforec_set_data(new_rec, dtype->allocate(new_rec))) {
327         talloc_free(new_rec);
328         new_rec=NULL;
329       }
330     }
331   }
332   return new_rec;
333 }
334
335 void trp_inforec_free(TRP_INFOREC *rec)
336 {
337   if (rec!=NULL)
338     talloc_free(rec);
339 }
340
341 static int trp_upd_destructor(void *object)
342 {
343   TRP_UPD *upd=talloc_get_type_abort(object, TRP_UPD);
344   if (upd->peer!=NULL)
345     tr_free_name(upd->peer);
346   return 0;
347 }
348
349 TRP_UPD *trp_upd_new(TALLOC_CTX *mem_ctx)
350 {
351   TRP_UPD *new_body=talloc(mem_ctx, TRP_UPD);
352
353   if (new_body!=NULL) {
354     new_body->records=NULL;
355     new_body->peer=NULL;
356     talloc_set_destructor(new_body, trp_upd_destructor);
357   }
358   return new_body;
359 }
360
361 void trp_upd_free(TRP_UPD *update)
362 {
363   if (update!=NULL)
364     talloc_free(update);
365 }
366
367 TRP_INFOREC *trp_upd_get_inforec(TRP_UPD *upd)
368 {
369   if (upd!=NULL)
370     return upd->records;
371   else
372     return NULL;
373 }
374
375 void trp_upd_set_inforec(TRP_UPD *upd, TRP_INFOREC *rec)
376 {
377   if (upd!=NULL)
378     upd->records=rec;
379 }
380
381 TR_NAME *trp_upd_get_peer(TRP_UPD *upd)
382 {
383   return upd->peer;
384 }
385
386 void trp_upd_set_peer(TRP_UPD *upd, TR_NAME *peer)
387 {
388   TRP_INFOREC *rec=NULL;
389   TR_NAME *cpy=NULL;
390
391   upd->peer=peer;
392   for (rec=trp_upd_get_inforec(upd); rec!=NULL; rec=trp_inforec_get_next(rec)) {
393     if (trp_inforec_set_next_hop(rec, cpy=tr_dup_name(peer)) != TRP_SUCCESS)
394       tr_free_name(cpy);
395   }
396 }
397
398 /* pretty print */
399 static void trp_inforec_route_print(TRP_INFOREC_DATA data)
400 {
401   if (data.route!=NULL) {
402     printf("     community=%.*s\n     realm=%.*s\n     trust_router=%.*s\n     metric=%d\n     interval=%d]\n",
403            data.route->comm->len, data.route->comm->buf,
404            data.route->realm->len, data.route->realm->buf,
405            data.route->trust_router->len, data.route->trust_router->buf,
406            data.route->metric, data.route->interval);
407   }
408 }
409