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