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