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