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