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