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