merge quagga-plugin with http://git.acinonyx.ath.cx/?p=olsr-quagga.git
[olsrd.git] / lib / quagga / src / quagga.c
1 /***************************************************************************
2  projekt              : olsrd-quagga
3  file                 : quagga.c  
4  usage                : communication with the zebra-daemon 
5  copyright            : (C) 2006 by Immo 'FaUl' Wehrenberg
6  e-mail               : immo@chaostreff-dortmund.de
7  ***************************************************************************/
8
9 /***************************************************************************
10  *                                                                         *
11  *   This program is free software; you can redistribute it and/or modify  *
12  *   it under the terms of the GNU General Public License version 2 as     *
13  *   published by the Free Software Foundation.                            *
14  *                                                                         *
15  ***************************************************************************/
16
17
18 #ifdef MY_DEBUG
19 #include <stdio.h>
20 #endif
21
22 #define HAVE_SOCKLEN_T
23
24 #include <stdint.h>
25 #include <sys/types.h>
26 #include <sys/socket.h>
27 #include <netinet/in.h>
28 #include <fcntl.h>
29
30 #include "quagga.h"
31 #include "olsr.h"
32 #include "log.h"
33 #include "defs.h"
34 #include "routing_table.h"
35
36 #ifdef USE_UNIX_DOMAIN_SOCKET
37 #include <sys/un.h>
38 #define ZEBRA_SOCKET "/var/run/quagga/zserv.api"
39 #endif
40
41 #define ZEBRA_IPV4_ROUTE_ADD            7
42 #define ZEBRA_IPV4_ROUTE_DELETE         8
43 #define ZEBRA_REDISTRIBUTE_ADD          11
44 #define ZEBRA_REDISTRIBUTE_DELETE       12
45 #define ZEBRA_MESSAGE_MAX               23
46
47 #define ZEBRA_ROUTE_OLSR                11
48 #define ZEBRA_ROUTE_MAX                 12
49
50 #define ZEBRA_FLAG_SELECTED             0x10
51
52 #define ZEBRA_NEXTHOP_IPV4              3
53 #define ZEBRA_NEXTHOP_IPV4_IFINDEX      4
54
55 #define ZAPI_MESSAGE_NEXTHOP  0x01
56 #define ZAPI_MESSAGE_IFINDEX  0x02
57 #define ZAPI_MESSAGE_DISTANCE 0x04
58 #define ZAPI_MESSAGE_METRIC   0x08
59
60 #define BUFSIZE 1024
61
62 #define STATUS_CONNECTED 1
63 #define OPTION_EXPORT 1
64
65 static struct {
66   char status; // internal status
67   char options; // internal options
68   int sock; // Socket to zebra...
69   char redistribute[ZEBRA_ROUTE_MAX];
70   char distance;
71   char flags;
72   struct ipv4_route *v4_rt; // routes currently exportet to zebra
73 } zebra;
74
75
76 /* prototypes intern */
77 static unsigned char *try_read (ssize_t *);
78 static unsigned char* zebra_route_packet (struct ipv4_route r, ssize_t *);
79 static int parse_interface_add (unsigned char *, size_t);
80 static int parse_interface_delete (unsigned char *, size_t);
81 static int parse_interface_up (unsigned char *, size_t);
82 static int parse_interface_down (unsigned char *, size_t);
83 static int parse_interface_address_add (unsigned char *, size_t);
84 static int parse_interface_address_delete (unsigned char *, size_t);
85 static int parse_ipv4_route (unsigned char *, size_t, struct ipv4_route *);
86 static int ipv4_route_add (unsigned char *, size_t);
87 static int ipv4_route_delete (unsigned char *, size_t);
88 static int parse_ipv6_route_add (unsigned char*, size_t);
89 static void zebra_reconnect (void);
90 static void zebra_connect (void);
91
92 static void free_ipv4_route (struct ipv4_route);
93 /* 
94 static void update_olsr_zebra_routes (struct ipv4_route*, struct ipv4_route*);
95 static struct ipv4_route *zebra_create_ipv4_route_table_entry (uint32_t,
96                                                                uint32_t,
97                                                                uint32_t);
98 static struct ipv4_route *zebra_create_ipv4_route_table (void);
99 static void zebra_free_ipv4_route_table (struct ipv4_route*);
100 */
101
102 /*static uint8_t masktoprefixlen (uint32_t);*/
103
104
105 #ifdef MY_DEBUG
106 static void dump_ipv4_route (struct ipv4_route r, char *c) {
107   int i = 0, x = 0;
108
109   puts (c);
110   printf("type: %d\n", r.type);
111   puts("flags:");
112   printf("  Internal: %s\n",r.flags&ZEBRA_FLAG_INTERNAL?"yes":"no");
113   printf("  Selfroute %s\n",r.flags&ZEBRA_FLAG_SELFROUTE?"yes":"no");
114   printf("  Blackhole %s\n",r.flags&ZEBRA_FLAG_BLACKHOLE?"yes":"no");
115   printf("  IBGP: %s\n",r.flags&ZEBRA_FLAG_IBGP?"yes":"no");
116   printf("  Selected: %s\n",r.flags&ZEBRA_FLAG_SELECTED?"yes":"no");
117   printf("  Changed: %s\n",r.flags&ZEBRA_FLAG_CHANGED?"yes":"no");
118   printf("  static: %s\n",r.flags&ZEBRA_FLAG_STATIC?"yes":"no");
119   printf("  reject: %s\n",r.flags&ZEBRA_FLAG_REJECT?"yes":"no");
120   puts("message:");
121   printf("  nexthop: %s\n",r.message&ZAPI_MESSAGE_NEXTHOP?"yes":"no");
122   printf("  ifindex: %s\n",r.message&ZAPI_MESSAGE_IFINDEX?"yes":"no");
123   printf("  distance: %s\n",r.message&ZAPI_MESSAGE_DISTANCE?"yes":"no");
124   printf("  metric: %s\n",r.message&ZAPI_MESSAGE_METRIC?"yes":"no");
125   printf("Prefixlen: %d\n", r.prefixlen);
126   printf("Prefix: %d", (unsigned char)r.prefix);
127   c = (char*) &r.prefix;
128   while (++i < (r.prefixlen/8 + (r.prefixlen % 8 ? 1 : 0)))
129     printf(".%d",(unsigned char)*(c + i));
130   while (i++ < 4)
131     printf(".0");
132   puts("");
133   i=0;
134   if (r.message&ZAPI_MESSAGE_NEXTHOP) {
135     printf("nexthop-count: %d\n", r.nh_count);
136     while (i++ < r.nh_count) {
137       if (r.nexthops[i].type == ZEBRA_NEXTHOP_IPV4) {
138         c = (unsigned char*) &r.nexthops[i].payload.v4;
139         printf ("Nexthop %d: %d", i, (unsigned char) *c);
140         while (++x < 4) {
141           printf (".%d", (unsigned char) c[x]);
142         }
143         puts("");
144       }
145     }
146     i=0;
147   }
148   if (r.message&ZAPI_MESSAGE_IFINDEX) {
149     
150     printf("index-number: %d\n", r.ind_num);
151     while (i++ < r.ind_num)
152       printf("Index: %d: %d\n", i, r.index[i]);
153     i=0;
154     if (r.message&ZAPI_MESSAGE_DISTANCE)
155       printf("Distance: %d\n",r.distance);
156     if (r.message&ZAPI_MESSAGE_METRIC)
157       printf("Metric: %d\n",r.metric);
158     puts("\n");
159   }
160 }
161 #endif
162
163 void *my_realloc (void *buf, size_t s, const char *c) {
164   buf = realloc (buf, s);
165   if (!buf) {
166     OLSR_PRINTF (1, "(QUAGGA) OUT OF MEMORY: %s\n", strerror(errno));
167     olsr_syslog(OLSR_LOG_ERR, "olsrd: out of memory!: %m\n");
168     olsr_exit(c, EXIT_FAILURE);
169   }
170   return buf;
171 }
172
173 void init_zebra (void) {
174   zebra_connect();
175   if (!(zebra.status&STATUS_CONNECTED))
176     olsr_exit ("(QUAGGA) AIIIII, could not connect to zebra! is zebra running?", 
177                EXIT_FAILURE);
178 }
179
180 void zebra_cleanup (void) {
181   int i;
182   struct rt_entry *tmp;
183   
184   if (zebra.options & OPTION_EXPORT) {
185     OLSR_FOR_ALL_RT_ENTRIES(tmp) {
186       zebra_del_olsr_v4_route(tmp);
187     } OLSR_FOR_ALL_RT_ENTRIES_END(tmp);
188   }
189
190   for (i = 0; i < ZEBRA_ROUTE_MAX; i++)
191     if (zebra.redistribute[i]) zebra_disable_redistribute(i + 1);
192 }
193
194
195 static void zebra_reconnect (void) {
196   struct rt_entry *tmp;
197   int i;
198
199   zebra_connect();
200   if (!(zebra.status & STATUS_CONNECTED)) return; // try again next time
201
202   if (zebra.options & OPTION_EXPORT) {
203     OLSR_FOR_ALL_RT_ENTRIES(tmp) {
204       zebra_add_olsr_v4_route (tmp);
205     } OLSR_FOR_ALL_RT_ENTRIES_END(tmp);
206   }  
207
208   for (i = 0; i < ZEBRA_ROUTE_MAX; i++)
209     if (zebra.redistribute[i]) zebra_redistribute(i + 1);
210   /* Zebra sends us all routes of type it knows after 
211      zebra_redistribute(type) */
212 }
213
214
215
216 /* Connect to the zebra-daemon, returns a socket */
217 static void zebra_connect (void) {
218   
219   int ret;
220
221 #ifndef USE_UNIX_DOMAIN_SOCKET
222   struct sockaddr_in i;
223   if (close (zebra.sock) < 0) olsr_exit ("(QUAGGA) Could not close socket!", EXIT_FAILURE);
224   
225
226   zebra.sock = socket (AF_INET,SOCK_STREAM, 0);
227 #else
228   struct sockaddr_un i;
229   if (close (zebra.sock) < 0) olsr_exit ("(QUAGGA) Could not close socket!", EXIT_FAILURE);
230
231   zebra.sock = socket (AF_UNIX,SOCK_STREAM, 0);
232 #endif
233
234   if (zebra.sock <0 )
235     olsr_exit("(QUAGGA) Could not create socket!", EXIT_FAILURE);
236   
237   memset (&i, 0, sizeof i);
238 #ifndef USE_UNIX_DOMAIN_SOCKET
239   i.sin_family = AF_INET;
240   i.sin_port = htons (ZEBRA_PORT);
241   i.sin_addr.s_addr = htonl (INADDR_LOOPBACK);
242 #else
243   i.sun_family = AF_UNIX;
244   strcpy (i.sun_path, ZEBRA_SOCKET);
245 #endif
246
247   ret = connect (zebra.sock, (struct sockaddr *)&i, sizeof i);
248   if  (ret < 0) zebra.status &= ~STATUS_CONNECTED;
249   else zebra.status |= STATUS_CONNECTED;
250 }
251
252     
253 /* Sends a command to zebra, command is 
254    the command defined in zebra.h, options is the packet-payload, 
255    optlen the length, of the payload */
256 unsigned char zebra_send_command (unsigned char command, 
257                                   unsigned char *options, int optlen) {
258
259   char *p, *pnt;
260   uint16_t len;
261   int ret;
262
263 #ifdef ZEBRA_HEADER_MARKER
264   uint16_t cmd;
265   uint16_t length = optlen + 6; /* length of option + command + packet_length +
266                                    marker + zserv-version */
267 #else
268   uint16_t length = optlen + 3;  // length of option + command + packet_length
269 #endif  
270
271   if (!(zebra.status & STATUS_CONNECTED)) return 0;
272
273   p = olsr_malloc (length, "zebra_send_command");
274   pnt = p;
275   
276   len = htons(length);
277
278   memcpy (p, &len, 2);
279
280 #ifdef ZEBRA_HEADER_MARKER
281   p[2] = ZEBRA_HEADER_MARKER;
282   p[3] = ZSERV_VERSION;
283   cmd = htons (command);
284   memcpy (p + 4, &cmd, 2);
285 #else
286   p[2] = command;
287 #endif
288   memcpy (p + length-optlen, options, optlen);
289
290   errno = 0;
291
292   do {
293     ret = write (zebra.sock, p, length);
294     if (ret < 0) {
295       if (errno == EINTR) {
296         errno = 0;
297         continue;
298       }
299       else {
300         olsr_printf (1, "(QUAGGA) Disconnected from zebra\n");
301         zebra.status &= ~STATUS_CONNECTED;
302         free (pnt);
303         return -1;
304       }
305     }
306     p = p+ret;
307   } while ((length -= ret));
308   free (pnt);
309   return 0;
310 }
311
312
313 /* Creates a Route-Packet-Payload, needs address, netmask, nexthop, 
314    distance, and a pointer of an size_t */
315 static unsigned char* zebra_route_packet (struct ipv4_route r, 
316                                           ssize_t *optlen) {
317
318   int count;
319
320   unsigned char *cmdopt, *t;
321   *optlen = 4; // first: type, flags, message, prefixlen
322   *optlen += r.prefixlen / 8 + (r.prefixlen % 8 ? 1 : 0); // + prefix
323   if (r.message & ZAPI_MESSAGE_NEXTHOP) {
324     if (r.nexthops->type == ZEBRA_NEXTHOP_IPV4 
325         || r.nexthops->type == ZEBRA_NEXTHOP_IPV4_IFINDEX){
326       *optlen += (sizeof r.nexthops->payload.v4 
327                   + sizeof r.nexthops->type) * r.nh_count + 1;
328     }
329     else if (r.nexthops->type == 0) 
330       *optlen += 5;
331   }
332   if (r.message & ZAPI_MESSAGE_IFINDEX)
333     *optlen += r.ind_num * sizeof *r.index + 1;
334   if (r.message & ZAPI_MESSAGE_DISTANCE)
335     (*optlen)++;
336   if (r.message & ZAPI_MESSAGE_METRIC)
337     *optlen += sizeof r.metric;
338
339   cmdopt = olsr_malloc (*optlen, "zebra add_v4_route");
340
341   t = cmdopt;
342   *t++ = r.type; 
343   *t++ = r.flags; 
344   *t++ = r.message;
345   *t++ = r.prefixlen;
346   for (count = 0; count < r.prefixlen/8 + (r.prefixlen % 8 ? 1 : 0); count++) {
347     *t++ = *((char*)&r.prefix + count); /* this is so sick!! */
348   }
349
350   if (r.message & ZAPI_MESSAGE_NEXTHOP) {
351     *t++ = r.nh_count;
352     *t++ = r.nexthops->type;
353     if (r.nexthops->type == ZEBRA_NEXTHOP_IPV4 || 
354         r.nexthops->type == ZEBRA_NEXTHOP_IPV4_IFINDEX) {
355       for (count = 0; count != r.nh_count; count++) {
356         memcpy (t, &r.nexthops[count].payload.v4, 
357                 sizeof r.nexthops->payload.v4);
358         t += sizeof r.nexthops->payload.v4;
359       }
360     }
361     else if (r.nexthops->type == 0) {
362       *t++ = 0;
363       *t++ = 0;
364       *t++ = 0;
365     }
366   }
367   if (r.message & ZAPI_MESSAGE_IFINDEX) {
368     *t++ = r.ind_num;
369     memcpy (t, r.index, sizeof *r.index * r.ind_num);
370     t += sizeof r.index * r.ind_num;
371   }
372   if (r.message & ZAPI_MESSAGE_DISTANCE)
373     *t++ = r.distance;
374   if (r.message & ZAPI_MESSAGE_METRIC) {
375     memcpy (t, &r.metric, sizeof r.metric);
376     t += sizeof r.metric;
377   }
378   return cmdopt;
379 }
380
381
382 /* adds a route to zebra-daemon */
383 int zebra_add_v4_route (const struct ipv4_route r) {
384   
385   unsigned char *cmdopt;
386   ssize_t optlen;
387   int retval;
388
389   cmdopt = zebra_route_packet (r, &optlen);
390
391   retval = zebra_send_command (ZEBRA_IPV4_ROUTE_ADD, cmdopt, optlen);
392   free (cmdopt);
393   return retval;
394   
395 }
396
397 /* deletes a route from the zebra-daemon */
398 int zebra_delete_v4_route (struct ipv4_route r) {
399   
400   unsigned char *cmdopt;
401   ssize_t optlen;
402   int retval;
403
404   cmdopt = zebra_route_packet (r, &optlen);
405   
406   retval = zebra_send_command (ZEBRA_IPV4_ROUTE_DELETE, cmdopt, optlen);
407   free (cmdopt);
408
409   return retval;
410   
411 }
412
413
414 /* Check wether there is data from zebra aviable */
415 void zebra_check (void* foo __attribute__((unused))) {
416   unsigned char *data, *f;
417   ssize_t len, ret;
418
419   if (!(zebra.status & STATUS_CONNECTED)) {
420     zebra_reconnect();
421     return;
422   }
423   data = try_read (&len);
424   if (data) {
425     f = data;
426     do {
427       ret = zebra_parse_packet (f, len);
428       if (!ret) // something wired happened
429         olsr_exit ("(QUAGGA) Zero message length??? ", EXIT_FAILURE);
430       f += ret;
431     } while ((f - data) < len);
432     free (data);
433   }
434 }
435
436
437 // tries to read a packet from zebra_socket
438 // if there is something to read - make sure to read whole packages
439 static unsigned char *try_read (ssize_t *len) {
440   unsigned char *buf = NULL;
441   ssize_t ret = 0, bsize = 0;
442   uint16_t length = 0, l = 0;
443   int sockstate;
444
445   *len = 0;
446
447   sockstate = fcntl (zebra.sock, F_GETFL, 0);
448   fcntl (zebra.sock, F_SETFL, sockstate|O_NONBLOCK);
449
450   do { 
451     if (*len == bsize) {
452       bsize += BUFSIZE;
453       buf = my_realloc (buf, bsize, "Zebra try_read");
454     }
455     ret = read (zebra.sock, buf + l, bsize - l);
456     if (!ret) { // nothing more to read, packet is broken, discard!
457       free (buf);
458       return NULL;
459     }
460
461     if (ret < 0) {
462       if (errno != EAGAIN) { // oops - we got disconnected
463         olsr_printf (1, "(QUAGGA) Disconnected from zebra\n");
464         zebra.status &= ~STATUS_CONNECTED;
465       }
466       free (buf);
467       return NULL;
468     }
469
470     *len += ret;
471     while ((*len - l) > length) {
472       l += length;
473       memcpy (&length, buf + l, 2);
474       length = ntohs (length);
475     }
476     if (((*len) - l) == length) break; // GOT FULL PACKAGE!!
477     if (*len < l) {
478       fcntl (zebra.sock, F_SETFL, sockstate);
479       continue;
480     }
481   } while (1);
482
483   fcntl (zebra.sock, F_SETFL, sockstate);
484   return buf;
485 }
486
487
488 /* Parse a packet recived from zebra */
489 int zebra_parse_packet (unsigned char *packet, ssize_t maxlen) {
490
491   uint16_t command;
492   int skip;
493
494   /* Array of functions */
495   int (*foo[ZEBRA_MESSAGE_MAX]) (unsigned char *, size_t) = {
496     parse_interface_add,
497     parse_interface_delete,
498     parse_interface_address_add,
499     parse_interface_address_delete,
500     parse_interface_up,
501     parse_interface_down,
502     ipv4_route_add,
503     ipv4_route_delete,
504     parse_ipv6_route_add
505   };
506
507   uint16_t length;
508   int ret;
509
510 #ifdef MY_DEBUG
511   puts ("DEBUG: zebra_parse_packet");
512 #endif
513
514   memcpy (&length, packet, 2);
515   length = ntohs (length);
516   
517   if (maxlen < length) {
518     olsr_printf (1, "(QUAGGA) maxlen = %lu, packet_length = %d\n", (unsigned long)maxlen, length);
519     olsr_exit ("(QUAGGA) programmer is an idiot", EXIT_FAILURE);
520   }
521
522 #ifdef ZEBRA_HEADER_MARKER
523   if (packet[2] == 255) { // found header marker!!
524     //packet[3] == ZSERV_VERSION: FIXME: HANDLE THIS!
525     memcpy (&command, packet + 4, sizeof command); // two bytes command now!
526     command = ntohs (command) - 1; 
527     skip = 6;
528   }
529 #else
530   command = packet[2] - 1;
531   skip = 3;
532 #endif
533
534   if (command < ZEBRA_MESSAGE_MAX && foo[command]) { 
535     if (!(ret = foo[command] (packet + skip, length - skip))) 
536       return length;
537     else olsr_printf (1, "(QUAGGA) Parse error: %d\n", ret);
538   }
539   else
540     olsr_printf (1, "(QUAGGA) Unknown packet type: %d\n", packet[2]);
541
542   olsr_printf (1, "(Quagga) RECIVED PACKET FROM ZEBRA THAT I CAN'T PARSE");
543
544   return length;
545 }
546
547
548 static int parse_interface_add (unsigned char *opt __attribute__((unused)), size_t len __attribute__((unused))) {
549   //todo
550   return 0;
551 }
552
553
554 static int parse_interface_delete (unsigned char *opt __attribute__((unused)), size_t len __attribute__((unused))) {
555   //todo
556   return 0;
557 }
558
559
560 static int parse_interface_address_add (unsigned char *opt __attribute__((unused)), size_t len __attribute__((unused))) {
561   
562   //todo
563   return 0;
564 }
565
566 static int parse_interface_up (unsigned char *opt __attribute__((unused)), size_t len __attribute__((unused))) {
567   
568   //todo
569   return 0;
570 }
571
572 static int parse_interface_down (unsigned char *opt __attribute__((unused)), size_t len __attribute__((unused))) {
573   
574   //todo
575   return 0;
576 }
577
578
579 static int parse_interface_address_delete (unsigned char *opt __attribute__((unused)), size_t  len __attribute__((unused))) {
580   //todo
581   return 0;
582 }
583
584
585 /* Parse an ipv4-route-packet recived from zebra
586  */
587 static int parse_ipv4_route (unsigned char *opt, size_t len, struct ipv4_route *r) {
588   int c;
589
590   if (len < 4) return -1;
591   
592   r->type = *opt++;
593   r->flags = *opt++;
594   r->message = *opt++;
595   r->prefixlen = *opt++;
596   len -= 4;
597   r->prefix = 0;
598   
599   if ((int)len < r->prefixlen/8 + (r->prefixlen % 8 ? 1 : 0)) return -1;
600   
601   memcpy (&r->prefix, opt, r->prefixlen/8 + (r->prefixlen % 8 ? 1 : 0));
602   opt += r->prefixlen/8 + (r->prefixlen % 8 ? 1 : 0);
603   
604   if (r->message & ZAPI_MESSAGE_NEXTHOP) {
605     if (len < 1) return -1;
606     r->nh_count = *opt++;
607     len--;
608     if (len < (sizeof (uint32_t) + 1) * r->nh_count) return -1;
609     r->nexthops = olsr_malloc ((sizeof r->nexthops->type +
610                                 sizeof r->nexthops->payload) * r->nh_count,
611                                "quagga: parse_ipv4_route_add");
612     for (c = 0; c < r->nh_count; c++) {
613       r->nexthops[c].type = *opt++;
614       memcpy (&r->nexthops[c].payload.v4, opt, sizeof (uint32_t));
615       opt += sizeof (uint32_t);
616       len -= sizeof (uint32_t) + 1;
617     }
618   }
619
620   if (r->message & ZAPI_MESSAGE_IFINDEX) {
621     if (len < 1) return -1;
622     r->ind_num = *opt++;
623     if (len < sizeof (uint32_t) * r->ind_num) return -1;
624     r->index = olsr_malloc (sizeof (uint32_t) * r->ind_num,
625                             "quagga: parse_ipv4_route_add");
626     memcpy (r->index, opt, r->ind_num * sizeof (uint32_t));
627     opt += sizeof (uint32_t) * r->ind_num;
628     len -= sizeof (uint32_t) * r->ind_num;
629   }
630
631   if (r->message & ZAPI_MESSAGE_DISTANCE) {
632     if (len < 1) return -1;
633     r->distance = *opt++;
634     len--;
635   }
636
637   if (r->message & ZAPI_MESSAGE_METRIC) {
638     if (len < sizeof (uint32_t)) return -1;
639     memcpy (&r->metric, opt, sizeof (uint32_t));
640   }
641
642   return 0;
643 }
644
645
646 static int ipv4_route_add (unsigned char *opt, size_t len) {
647
648   struct ipv4_route r;
649   int f;
650     
651   f = parse_ipv4_route (opt, len, &r);
652   if (f < 0) return f;
653
654   return add_hna4_route (r);
655 }
656
657 static int ipv4_route_delete (unsigned char *opt, size_t len) {
658   struct ipv4_route r;
659   int f;
660   
661   f = parse_ipv4_route (opt, len, &r);
662   if (f < 0) return f;
663
664   return delete_hna4_route (r);
665   
666 }
667
668 static int parse_ipv6_route_add (unsigned char *opt __attribute__((unused)), size_t len __attribute__((unused))) {
669   //todo
670   return 0;
671 }
672
673
674 /* start redistribution FROM zebra */
675 int zebra_redistribute (unsigned char type) {
676
677   if (type > ZEBRA_ROUTE_MAX) return -1;
678   zebra.redistribute[type - 1] = 1;
679
680   return zebra_send_command (ZEBRA_REDISTRIBUTE_ADD, &type, 1);
681   
682   
683 }  
684
685
686 /* end redistribution FROM zebra */
687 int zebra_disable_redistribute (unsigned char type) {
688   
689   if (type > ZEBRA_ROUTE_MAX) return -1;
690   zebra.redistribute[type - 1] = 0;
691
692   return zebra_send_command (ZEBRA_REDISTRIBUTE_DELETE, &type, 1);
693
694 }
695   
696 int add_hna4_route (struct ipv4_route r) {
697   union olsr_ip_addr net;
698   
699 #ifdef MY_DEBUG
700   dump_ipv4_route(r, "add_hna4_route");
701 #endif
702
703   net.v4.s_addr = r.prefix;
704
705   ip_prefix_list_add(&olsr_cnf->hna_entries, &net, r.prefixlen);
706   free_ipv4_route(r);
707   return 0;
708 }
709
710 int delete_hna4_route (struct ipv4_route r) {
711
712   union olsr_ip_addr net;
713
714 #ifdef MY_DEBUG
715   dump_ipv4_route(r, "delete_hna4_route");
716 #endif
717
718   net.v4.s_addr = r.prefix;
719
720   ip_prefix_list_remove(&olsr_cnf->hna_entries, &net, r.prefixlen) ? 0 : -1;
721   free_ipv4_route(r);
722   return 0;
723
724 }
725
726 static void free_ipv4_route (struct ipv4_route r) {
727
728   if(r.message&ZAPI_MESSAGE_IFINDEX && r.ind_num) free(r.index);
729   if(r.message&ZAPI_MESSAGE_NEXTHOP && r.nh_count) free(r.nexthops);
730
731 }
732
733 /*
734 static uint8_t masktoprefixlen (uint32_t mask) {
735  
736   uint8_t prefixlen = 0;
737
738   mask = htonl (mask);
739
740   if (mask) while (mask << ++prefixlen && prefixlen < 32);
741
742   return prefixlen;
743   
744 }
745 */
746
747 int zebra_add_olsr_v4_route (const struct rt_entry *r) {
748   
749   struct ipv4_route route;
750   int retval;
751   
752   route.type = ZEBRA_ROUTE_OLSR; // OLSR
753   route.message = ZAPI_MESSAGE_METRIC;
754   route.flags = zebra.flags;
755   route.prefixlen = r->rt_dst.prefix_len;
756   route.prefix = r->rt_dst.prefix.v4.s_addr;
757   if ((r->rt_best->rtp_nexthop.gateway.v4.s_addr == r->rt_dst.prefix.v4.s_addr && 
758        route.prefixlen == 32)) {
759     route.message |= ZAPI_MESSAGE_IFINDEX | ZAPI_MESSAGE_NEXTHOP;
760     route.ind_num = 1;
761     route.index = olsr_malloc (sizeof *route.index, 
762                                "zebra_add_olsr_v4_route");
763     *route.index = htonl(r->rt_best->rtp_nexthop.iif_index);
764     route.nexthops = olsr_malloc (sizeof route.nexthops->type +
765                                   sizeof route.nexthops->payload,
766                                   "zebra_add_olsr_v4_route");
767     route.nh_count = 1;
768     route.nexthops->type = 0;
769   }
770   else {
771     route.message |= ZAPI_MESSAGE_NEXTHOP;
772     route.nh_count = 1;
773     route.nexthops = olsr_malloc (route.nh_count * 
774                                   (sizeof route.nexthops->type + 
775                                    sizeof route.nexthops->payload), 
776                                    "zebra_add_olsr_v4_route");
777     route.nexthops->type = ZEBRA_NEXTHOP_IPV4;
778     route.nexthops->payload.v4 = r->rt_best->rtp_nexthop.gateway.v4.s_addr;
779   }
780
781   route.metric = r->rt_best->rtp_metric.hops;
782   route.metric = htonl(route.metric);
783
784   if (zebra.distance) {
785     route.message |= ZAPI_MESSAGE_DISTANCE;
786     route.distance = zebra.distance;
787   }
788
789   retval = zebra_add_v4_route(route);
790   free_ipv4_route (route);
791   return retval;
792 }
793
794 int zebra_del_olsr_v4_route (const struct rt_entry *r) {
795   
796   struct ipv4_route route;
797   int retval;
798   route.type = ZEBRA_ROUTE_OLSR; // OLSR
799   route.message = ZAPI_MESSAGE_METRIC;
800   route.flags = zebra.flags;
801   route.prefixlen = r->rt_dst.prefix_len;
802   route.prefix = r->rt_dst.prefix.v4.s_addr;
803   if ((r->rt_nexthop.gateway.v4.s_addr == r->rt_dst.prefix.v4.s_addr && 
804        route.prefixlen == 32)){
805     route.message |= ZAPI_MESSAGE_IFINDEX;
806     route.ind_num = 1;
807     route.index = olsr_malloc (sizeof *route.index, 
808                                "zebra_add_olsr_v4_route");
809     *route.index = htonl (r->rt_nexthop.iif_index);
810     route.nexthops = olsr_malloc (sizeof route.nexthops->type +
811                                   sizeof route.nexthops->payload,
812                                   "zebra_add_olsr_v4_route");
813     route.nh_count = 1;
814     route.nexthops->type = 0;
815   }
816   else {
817     route.message |= ZAPI_MESSAGE_NEXTHOP;
818     route.nh_count = 1;
819     route.nexthops = olsr_malloc (route.nh_count * 
820                                   (sizeof route.nexthops->type +
821                                    sizeof route.nexthops->payload), 
822                                   "zebra_add_olsr_v4_route");
823     route.nexthops->type = ZEBRA_NEXTHOP_IPV4;
824     route.nexthops->payload.v4 = r->rt_nexthop.gateway.v4.s_addr;
825   }
826   route.metric = 0;
827   
828   if (zebra.distance) {
829     route.message |= ZAPI_MESSAGE_DISTANCE;
830     route.distance = zebra.distance;
831   }
832
833   retval = zebra_delete_v4_route(route);
834
835   free_ipv4_route (route);
836   return retval;
837 }
838
839 void zebra_olsr_distance (unsigned char dist) {
840   zebra.distance = dist;
841 }
842
843 void zebra_olsr_localpref (void) {
844   zebra.flags &= ZEBRA_FLAG_SELECTED;
845 }
846
847 void zebra_export_routes (unsigned char t) {
848   if (t)
849     zebra.options |= OPTION_EXPORT;
850   else
851     zebra.options &= ~OPTION_EXPORT;
852 }