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