Connect to hard-coded peer and exchange route info. Buggy and incomplete.
[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->next_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 static TRP_INFOREC *trp_inforec_get_tail(TRP_INFOREC *rec)
113 {
114   while ((rec->next)!=NULL)
115     rec=trp_inforec_get_next(rec);
116   return rec;
117 }
118
119 void trp_inforec_set_next(TRP_INFOREC *rec, TRP_INFOREC *next_rec)
120 {
121   if (rec !=NULL)
122     rec->next=next_rec;
123 }
124
125 TRP_INFOREC_TYPE trp_inforec_get_type(TRP_INFOREC *rec)
126 {
127   if (rec)
128     return rec->type;
129   else
130     return TRP_INFOREC_TYPE_UNKNOWN;
131 }
132
133 void trp_inforec_set_type(TRP_INFOREC *rec, TRP_INFOREC_TYPE type)
134 {
135   if (rec!=NULL)
136     rec->type=type;
137 }
138
139 TR_NAME *trp_inforec_get_comm(TRP_INFOREC *rec)
140 {
141   switch (rec->type) {
142   case TRP_INFOREC_TYPE_ROUTE:
143     if (rec->data.route!=NULL)
144       return rec->data.route->comm;
145     break;
146   default:
147     break;
148   }
149   return NULL;
150 }
151
152 TR_NAME *trp_inforec_dup_comm(TRP_INFOREC *rec)
153 {
154   return tr_dup_name(trp_inforec_get_comm(rec));
155 }
156
157 TRP_RC trp_inforec_set_comm(TRP_INFOREC *rec, TR_NAME *comm)
158 {
159   switch (rec->type) {
160   case TRP_INFOREC_TYPE_ROUTE:
161     if (rec->data.route!=NULL) {
162       rec->data.route->comm=comm;
163       return TRP_SUCCESS;
164     }
165     break;
166   default:
167     break;
168   }
169   return TRP_ERROR;
170 }
171
172 TR_NAME *trp_inforec_get_realm(TRP_INFOREC *rec)
173 {
174   switch (rec->type) {
175   case TRP_INFOREC_TYPE_ROUTE:
176     if (rec->data.route!=NULL)
177       return rec->data.route->realm;
178     break;
179   default:
180     break;
181   }
182   return NULL;
183 }
184
185 TR_NAME *trp_inforec_dup_realm(TRP_INFOREC *rec)
186 {
187   return tr_dup_name(trp_inforec_get_realm(rec));
188 }
189
190 TRP_RC trp_inforec_set_realm(TRP_INFOREC *rec, TR_NAME *realm)
191 {
192   switch (rec->type) {
193   case TRP_INFOREC_TYPE_ROUTE:
194     if (rec->data.route!=NULL) {
195       rec->data.route->realm=realm;
196       return TRP_SUCCESS;
197     } 
198     break;
199   default:
200     break;
201   }
202   return TRP_ERROR;
203 }
204
205 TR_NAME *trp_inforec_get_trust_router(TRP_INFOREC *rec)
206 {
207   switch (rec->type) {
208   case TRP_INFOREC_TYPE_ROUTE:
209     if (rec->data.route!=NULL)
210       return rec->data.route->trust_router;
211     break;
212   default:
213     break;
214   }
215   return NULL;
216 }
217
218 TR_NAME *trp_inforec_dup_trust_router(TRP_INFOREC *rec)
219 {
220   return tr_dup_name(trp_inforec_get_trust_router(rec));
221 }
222
223 TRP_RC trp_inforec_set_trust_router(TRP_INFOREC *rec, TR_NAME *trust_router)
224 {
225   switch (rec->type) {
226   case TRP_INFOREC_TYPE_ROUTE:
227     if (rec->data.route!=NULL) {
228       rec->data.route->trust_router=trust_router;
229       return TRP_SUCCESS;
230     }
231     break;
232   default:
233     break;
234   }
235   return TRP_ERROR;
236 }
237
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 /* for internal use only; must set rec->type before calling this */
328 static TRP_RC trp_inforec_set_data(TRP_INFOREC *rec, void *data)
329 {
330   if (data==NULL)
331     return TRP_ERROR;
332
333   switch (rec->type) {
334   case TRP_INFOREC_TYPE_ROUTE:
335     rec->data.route=talloc_get_type(data, TRP_INFOREC_ROUTE);
336     break;
337   default:
338     return TRP_BADTYPE;
339   }
340   return TRP_SUCCESS;
341 }
342
343 /* generic record type */
344 TRP_INFOREC *trp_inforec_new(TALLOC_CTX *mem_ctx, TRP_INFOREC_TYPE type)
345 {
346   TRP_INFOREC *new_rec=talloc(mem_ctx, TRP_INFOREC);
347   struct trp_inforec_type_entry *dtype=get_trp_inforec_type_entry(type);
348
349   if ((new_rec != NULL) && (dtype->type != TRP_INFOREC_TYPE_UNKNOWN)) {
350     trp_inforec_set_type(new_rec, type);
351     trp_inforec_set_next(new_rec, NULL);
352     if (dtype->allocate!=NULL) {
353       if (TRP_SUCCESS!=trp_inforec_set_data(new_rec, dtype->allocate(new_rec))) {
354         talloc_free(new_rec);
355         new_rec=NULL;
356       }
357     }
358   }
359   return new_rec;
360 }
361
362 void trp_inforec_free(TRP_INFOREC *rec)
363 {
364   if (rec!=NULL)
365     talloc_free(rec);
366 }
367
368 static int trp_upd_destructor(void *object)
369 {
370   TRP_UPD *upd=talloc_get_type_abort(object, TRP_UPD);
371   if (upd->peer!=NULL)
372     tr_free_name(upd->peer);
373   return 0;
374 }
375
376 TRP_UPD *trp_upd_new(TALLOC_CTX *mem_ctx)
377 {
378   TRP_UPD *new_body=talloc(mem_ctx, TRP_UPD);
379
380   if (new_body!=NULL) {
381     new_body->records=NULL;
382     new_body->peer=NULL;
383     talloc_set_destructor((void *)new_body, trp_upd_destructor);
384   }
385   return new_body;
386 }
387
388 void trp_upd_free(TRP_UPD *update)
389 {
390   if (update!=NULL)
391     talloc_free(update);
392 }
393
394 TRP_INFOREC *trp_upd_get_inforec(TRP_UPD *upd)
395 {
396   if (upd!=NULL)
397     return upd->records;
398   else
399     return NULL;
400 }
401
402 void trp_upd_set_inforec(TRP_UPD *upd, TRP_INFOREC *rec)
403 {
404   if (upd!=NULL)
405     upd->records=rec;
406 }
407
408 void trp_upd_add_inforec(TRP_UPD *upd, TRP_INFOREC *rec)
409 {
410   tr_debug("trp_upd_add_inforec: adding record.");
411   if (upd->records==NULL)
412     upd->records=rec;
413   else
414     trp_inforec_set_next(trp_inforec_get_tail(upd->records), rec);
415   talloc_steal(upd, rec);
416 }
417
418 TR_NAME *trp_upd_get_peer(TRP_UPD *upd)
419 {
420   return upd->peer;
421 }
422
423 void trp_upd_set_peer(TRP_UPD *upd, TR_NAME *peer)
424 {
425   TRP_INFOREC *rec=NULL;
426   TR_NAME *cpy=NULL;
427
428   upd->peer=peer;
429   for (rec=trp_upd_get_inforec(upd); rec!=NULL; rec=trp_inforec_get_next(rec)) {
430     if (trp_inforec_set_next_hop(rec, cpy=tr_dup_name(peer)) != TRP_SUCCESS) {
431       tr_err("trp_upd_set_peer: error setting peer.");
432       tr_free_name(cpy);
433     }
434   }
435 }
436
437 /* pretty print */
438 static void trp_inforec_route_print(TRP_INFOREC_DATA data)
439 {
440   if (data.route!=NULL) {
441     printf("     community=%.*s\n     realm=%.*s\n     trust_router=%.*s\n     metric=%d\n     interval=%d]\n",
442            data.route->comm->len, data.route->comm->buf,
443            data.route->realm->len, data.route->realm->buf,
444            data.route->trust_router->len, data.route->trust_router->buf,
445            data.route->metric, data.route->interval);
446   }
447 }
448