366ce0d3adc3028f487c9fa781425e2991434b72
[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                 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 #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         ret = 0;
315         continue;
316       } else {
317         olsr_printf(1, "(QUAGGA) Disconnected from zebra\n");
318         zebra.status &= ~STATUS_CONNECTED;
319         free(pnt);
320         return -1;
321       }
322     }
323     p = p + ret;
324   }
325   while ((length -= ret));
326   free(pnt);
327   return 0;
328 }
329
330 /* Creates a Route-Packet-Payload, needs address, netmask, nexthop,
331    distance, and a pointer of an size_t */
332 static unsigned char *
333 zebra_route_packet(struct ipv4_route r, ssize_t * optlen)
334 {
335
336   int count;
337
338   unsigned char *cmdopt, *t;
339   *optlen = 4;                  // first: type, flags, message, prefixlen
340   *optlen += r.prefixlen / 8 + (r.prefixlen % 8 ? 1 : 0);       // + prefix
341   if (r.message & ZAPI_MESSAGE_NEXTHOP) {
342     if (r.nexthops->type == ZEBRA_NEXTHOP_IPV4 || r.nexthops->type == ZEBRA_NEXTHOP_IPV4_IFINDEX) {
343       *optlen += (sizeof r.nexthops->payload.v4 + sizeof r.nexthops->type) * r.nh_count + 1;
344     } else if (r.nexthops->type == 0)
345       *optlen += 5;
346   }
347   if (r.message & ZAPI_MESSAGE_IFINDEX)
348     *optlen += r.ind_num * sizeof *r.index + 1;
349   if (r.message & ZAPI_MESSAGE_DISTANCE)
350     (*optlen)++;
351   if (r.message & ZAPI_MESSAGE_METRIC)
352     *optlen += sizeof r.metric;
353
354   cmdopt = olsr_malloc(*optlen, "zebra add_v4_route");
355
356   t = cmdopt;
357   *t++ = r.type;
358   *t++ = r.flags;
359   *t++ = r.message;
360   *t++ = r.prefixlen;
361   for (count = 0; count < r.prefixlen / 8 + (r.prefixlen % 8 ? 1 : 0); count++) {
362     *t++ = *((char *)&r.prefix + count);        /* this is so sick!! */
363   }
364
365   if (r.message & ZAPI_MESSAGE_NEXTHOP) {
366     *t++ = r.nh_count;
367     *t++ = r.nexthops->type;
368     if (r.nexthops->type == ZEBRA_NEXTHOP_IPV4 || r.nexthops->type == ZEBRA_NEXTHOP_IPV4_IFINDEX) {
369       for (count = 0; count != r.nh_count; count++) {
370         memcpy(t, &r.nexthops[count].payload.v4, sizeof r.nexthops->payload.v4);
371         t += sizeof r.nexthops->payload.v4;
372       }
373     } else if (r.nexthops->type == 0) {
374       *t++ = 0;
375       *t++ = 0;
376       *t++ = 0;
377     }
378   }
379   if (r.message & ZAPI_MESSAGE_IFINDEX) {
380     *t++ = r.ind_num;
381     memcpy(t, r.index, sizeof *r.index * r.ind_num);
382     t += sizeof r.index * r.ind_num;
383   }
384   if (r.message & ZAPI_MESSAGE_DISTANCE)
385     *t++ = r.distance;
386   if (r.message & ZAPI_MESSAGE_METRIC) {
387     memcpy(t, &r.metric, sizeof r.metric);
388     t += sizeof r.metric;
389   }
390   return cmdopt;
391 }
392
393 /* adds a route to zebra-daemon */
394 int
395 zebra_add_v4_route(const struct ipv4_route r)
396 {
397
398   unsigned char *cmdopt;
399   ssize_t optlen;
400   int retval;
401
402   cmdopt = zebra_route_packet(r, &optlen);
403
404   retval = zebra_send_command(ZEBRA_IPV4_ROUTE_ADD, cmdopt, optlen);
405   free(cmdopt);
406   return retval;
407
408 }
409
410 /* deletes a route from the zebra-daemon */
411 int
412 zebra_delete_v4_route(struct ipv4_route r)
413 {
414
415   unsigned char *cmdopt;
416   ssize_t optlen;
417   int retval;
418
419   cmdopt = zebra_route_packet(r, &optlen);
420
421   retval = zebra_send_command(ZEBRA_IPV4_ROUTE_DELETE, cmdopt, optlen);
422   free(cmdopt);
423
424   return retval;
425
426 }
427
428 /* Check wether there is data from zebra aviable */
429 void
430 zebra_check(void *foo __attribute__ ((unused)))
431 {
432   unsigned char *data, *f;
433   ssize_t len, ret;
434
435   if (!(zebra.status & STATUS_CONNECTED)) {
436     zebra_reconnect();
437     return;
438   }
439   data = try_read(&len);
440   if (data) {
441     f = data;
442     do {
443       ret = zebra_parse_packet(f, len);
444       if (!ret)                 // something wired happened
445         olsr_exit("(QUAGGA) Zero message length??? ", EXIT_FAILURE);
446       f += ret;
447     }
448     while ((f - data) < len);
449     free(data);
450   }
451 }
452
453 // tries to read a packet from zebra_socket
454 // if there is something to read - make sure to read whole packages
455 static unsigned char *
456 try_read(ssize_t * len)
457 {
458   unsigned char *buf = NULL;
459   ssize_t ret = 0, bsize = 0;
460   uint16_t length = 0, l = 0;
461   int sockstate;
462
463   *len = 0;
464
465   sockstate = fcntl(zebra.sock, F_GETFL, 0);
466   fcntl(zebra.sock, F_SETFL, sockstate | O_NONBLOCK);
467
468   do {
469     if (*len == bsize) {
470       bsize += BUFSIZE;
471       buf = my_realloc(buf, bsize, "Zebra try_read");
472     }
473     ret = read (zebra.sock, buf + *len, bsize - *len);
474     if (!ret) {                 // nothing more to read, packet is broken, discard!
475       free(buf);
476       return NULL;
477     }
478
479     if (ret < 0) {
480       if (errno != EAGAIN) {    // oops - we got disconnected
481         olsr_printf(1, "(QUAGGA) Disconnected from zebra\n");
482         zebra.status &= ~STATUS_CONNECTED;
483       }
484       free(buf);
485       return NULL;
486     }
487
488     *len += ret;
489     do {
490       memcpy(&length, buf + l, 2);
491       length = ntohs(length);
492       l += length;
493     } while (*len > l);
494     if (*len < l)
495       fcntl(zebra.sock, F_SETFL, sockstate);
496   }
497   while (*len != l); // GOT FULL PACKAGE!!
498
499   fcntl(zebra.sock, F_SETFL, sockstate);
500   return buf;
501 }
502
503 /* Parse a packet recived from zebra */
504 int
505 zebra_parse_packet(unsigned char *packet, ssize_t maxlen)
506 {
507
508   uint16_t command;
509   int skip;
510
511   /* Array of functions */
512   int (*foo[ZEBRA_MESSAGE_MAX]) (unsigned char *, size_t) = {
513   parse_interface_add, parse_interface_delete, parse_interface_address_add, parse_interface_address_delete, parse_interface_up,
514       parse_interface_down, ipv4_route_add, ipv4_route_delete, parse_ipv6_route_add};
515
516   uint16_t length;
517   int ret;
518
519 #ifdef MY_DEBUG
520   puts("DEBUG: zebra_parse_packet");
521 #endif
522
523   memcpy(&length, packet, 2);
524   length = ntohs(length);
525
526   if (maxlen < length) {
527     olsr_printf(1, "(QUAGGA) maxlen = %lu, packet_length = %d\n", (unsigned long)maxlen, length);
528     olsr_exit("(QUAGGA) programmer is an idiot", EXIT_FAILURE);
529   }
530 #ifdef ZEBRA_HEADER_MARKER
531   if (packet[2] == 255) {       // found header marker!!
532     //packet[3] == ZSERV_VERSION: FIXME: HANDLE THIS!
533     memcpy(&command, packet + 4, sizeof command);       // two bytes command now!
534     command = ntohs(command) - 1;
535     skip = 6;
536   }
537 #else
538   command = packet[2] - 1;
539   skip = 3;
540 #endif
541
542   if (command < ZEBRA_MESSAGE_MAX && foo[command]) {
543     if (!(ret = foo[command] (packet + skip, length - skip)))
544       return length;
545     else
546       olsr_printf(1, "(QUAGGA) Parse error: %d\n", ret);
547   } else
548     olsr_printf(1, "(QUAGGA) Unknown packet type: %d\n", packet[2]);
549
550   olsr_printf(1, "(Quagga) RECIVED PACKET FROM ZEBRA THAT I CAN'T PARSE");
551
552   return length;
553 }
554
555 static int
556 parse_interface_add(unsigned char *opt __attribute__ ((unused)), size_t len __attribute__ ((unused)))
557 {
558   //todo
559   return 0;
560 }
561
562 static int
563 parse_interface_delete(unsigned char *opt __attribute__ ((unused)), size_t len __attribute__ ((unused)))
564 {
565   //todo
566   return 0;
567 }
568
569 static int
570 parse_interface_address_add(unsigned char *opt __attribute__ ((unused)), size_t len __attribute__ ((unused)))
571 {
572
573   //todo
574   return 0;
575 }
576
577 static int
578 parse_interface_up(unsigned char *opt __attribute__ ((unused)), size_t len __attribute__ ((unused)))
579 {
580
581   //todo
582   return 0;
583 }
584
585 static int
586 parse_interface_down(unsigned char *opt __attribute__ ((unused)), size_t len __attribute__ ((unused)))
587 {
588
589   //todo
590   return 0;
591 }
592
593 static int
594 parse_interface_address_delete(unsigned char *opt __attribute__ ((unused)), size_t len __attribute__ ((unused)))
595 {
596   //todo
597   return 0;
598 }
599
600 /* Parse an ipv4-route-packet recived from zebra
601  */
602 static int
603 parse_ipv4_route(unsigned char *opt, size_t len, struct ipv4_route *r)
604 {
605   int c;
606   size_t size;
607
608   if (len < 4)
609     return -1;
610
611   r->type = *opt++;
612   r->flags = *opt++;
613   r->message = *opt++;
614   r->prefixlen = *opt++;
615   len -= 4;
616   r->prefix = 0;
617
618   if ((int)len < r->prefixlen / 8 + (r->prefixlen % 8 ? 1 : 0))
619     return -1;
620
621   size = r->prefixlen/8 + (r->prefixlen % 8 ? 1 : 0);
622   memcpy (&r->prefix, opt, size);
623   opt += size;
624   len -= size;
625
626   if (r->message & ZAPI_MESSAGE_NEXTHOP) {
627     if (len < 1)
628       return -1;
629     r->nh_count = *opt++;
630     len--;
631     if (len < (sizeof(uint32_t) + 1) * r->nh_count)
632       return -1;
633     r->nexthops =
634       olsr_malloc((sizeof r->nexthops->type + sizeof r->nexthops->payload) * r->nh_count, "quagga: parse_ipv4_route_add");
635     for (c = 0; c < r->nh_count; c++) {
636 // Quagga Bug! nexthop type is NOT sent by zebra
637 //      r->nexthops[c].type = *opt++;
638 //      len--;
639       memcpy(&r->nexthops[c].payload.v4, opt, sizeof(uint32_t));
640       opt += sizeof(uint32_t);
641       len -= sizeof(uint32_t);
642     }
643   }
644
645   if (r->message & ZAPI_MESSAGE_IFINDEX) {
646     if (len < 1)
647       return -1;
648     r->ind_num = *opt++;
649     len--;
650     if (len < sizeof(uint32_t) * r->ind_num)
651       return -1;
652     r->index = olsr_malloc(sizeof(uint32_t) * r->ind_num, "quagga: parse_ipv4_route_add");
653     memcpy(r->index, opt, r->ind_num * sizeof(uint32_t));
654     opt += sizeof(uint32_t) * r->ind_num;
655     len -= sizeof(uint32_t) * r->ind_num;
656   }
657
658   if (r->message & ZAPI_MESSAGE_DISTANCE) {
659     if (len < 1)
660       return -1;
661     r->distance = *opt++;
662     len--;
663   }
664
665   if (r->message & ZAPI_MESSAGE_METRIC) {
666     if (len < sizeof(uint32_t))
667       return -1;
668     memcpy(&r->metric, opt, sizeof(uint32_t));
669   }
670
671   return 0;
672 }
673
674 static int
675 ipv4_route_add(unsigned char *opt, size_t len)
676 {
677
678   struct ipv4_route r;
679   int f;
680
681   f = parse_ipv4_route(opt, len, &r);
682   if (f < 0)
683     return f;
684
685   return add_hna4_route(r);
686 }
687
688 static int
689 ipv4_route_delete(unsigned char *opt, size_t len)
690 {
691   struct ipv4_route r;
692   int f;
693
694   f = parse_ipv4_route(opt, len, &r);
695   if (f < 0)
696     return f;
697
698   return delete_hna4_route(r);
699
700 }
701
702 static int
703 parse_ipv6_route_add(unsigned char *opt __attribute__ ((unused)), size_t len __attribute__ ((unused)))
704 {
705   //todo
706   return 0;
707 }
708
709 /* start redistribution FROM zebra */
710 int
711 zebra_redistribute(unsigned char type)
712 {
713
714   if (type > ZEBRA_ROUTE_MAX)
715     return -1;
716   zebra.redistribute[type - 1] = 1;
717
718   return zebra_send_command(ZEBRA_REDISTRIBUTE_ADD, &type, 1);
719
720 }
721
722 /* end redistribution FROM zebra */
723 int
724 zebra_disable_redistribute(unsigned char type)
725 {
726
727   if (type > ZEBRA_ROUTE_MAX)
728     return -1;
729   zebra.redistribute[type - 1] = 0;
730
731   return zebra_send_command(ZEBRA_REDISTRIBUTE_DELETE, &type, 1);
732
733 }
734
735 int
736 add_hna4_route(struct ipv4_route r)
737 {
738   union olsr_ip_addr net;
739
740 #ifdef MY_DEBUG
741   dump_ipv4_route(r, "add_hna4_route");
742 #endif
743
744   net.v4.s_addr = r.prefix;
745
746   ip_prefix_list_add(&olsr_cnf->hna_entries, &net, r.prefixlen);
747   free_ipv4_route(r);
748   return 0;
749 }
750
751 int
752 delete_hna4_route(struct ipv4_route r)
753 {
754
755   union olsr_ip_addr net;
756
757 #ifdef MY_DEBUG
758   dump_ipv4_route(r, "delete_hna4_route");
759 #endif
760
761   net.v4.s_addr = r.prefix;
762
763   ip_prefix_list_remove(&olsr_cnf->hna_entries, &net, r.prefixlen);
764   free_ipv4_route(r);
765   return 0;
766
767 }
768
769 static void
770 free_ipv4_route(struct ipv4_route r)
771 {
772
773   if (r.message & ZAPI_MESSAGE_IFINDEX && r.ind_num)
774     free(r.index);
775   if (r.message & ZAPI_MESSAGE_NEXTHOP && r.nh_count)
776     free(r.nexthops);
777
778 }
779
780 /*
781 static uint8_t masktoprefixlen (uint32_t mask) {
782
783   uint8_t prefixlen = 0;
784
785   mask = htonl (mask);
786
787   if (mask) while (mask << ++prefixlen && prefixlen < 32);
788
789   return prefixlen;
790
791 }
792 */
793
794 int
795 zebra_add_olsr_v4_route(const struct rt_entry *r)
796 {
797
798   struct ipv4_route route;
799   int retval;
800
801   route.index = NULL;
802   route.distance = 0;
803   route.type = ZEBRA_ROUTE_OLSR;        // OLSR
804   route.message = ZAPI_MESSAGE_METRIC;
805   route.flags = zebra.flags;
806   route.prefixlen = r->rt_dst.prefix_len;
807   route.prefix = r->rt_dst.prefix.v4.s_addr;
808   if ((r->rt_best->rtp_nexthop.gateway.v4.s_addr == r->rt_dst.prefix.v4.s_addr && route.prefixlen == 32)) {
809     route.message |= ZAPI_MESSAGE_IFINDEX | ZAPI_MESSAGE_NEXTHOP;
810     route.ind_num = 1;
811     route.index = olsr_malloc(sizeof *route.index, "zebra_add_olsr_v4_route");
812     *route.index = htonl(r->rt_best->rtp_nexthop.iif_index);
813     route.nexthops = olsr_malloc(sizeof route.nexthops->type + sizeof route.nexthops->payload, "zebra_add_olsr_v4_route");
814     route.nh_count = 1;
815     route.nexthops->type = 0;
816   } else {
817     route.message |= ZAPI_MESSAGE_NEXTHOP;
818     route.nh_count = 1;
819     route.nexthops =
820       olsr_malloc(route.nh_count * (sizeof route.nexthops->type + sizeof route.nexthops->payload), "zebra_add_olsr_v4_route");
821     route.nexthops->type = ZEBRA_NEXTHOP_IPV4;
822     route.nexthops->payload.v4 = r->rt_best->rtp_nexthop.gateway.v4.s_addr;
823   }
824
825   route.metric = r->rt_best->rtp_metric.hops;
826   route.metric = htonl(route.metric);
827
828   if (zebra.distance) {
829     route.message |= ZAPI_MESSAGE_DISTANCE;
830     route.distance = zebra.distance;
831   }
832
833   retval = zebra_add_v4_route(route);
834   free_ipv4_route(route);
835   return retval;
836 }
837
838 int
839 zebra_del_olsr_v4_route(const struct rt_entry *r)
840 {
841
842   struct ipv4_route route;
843   int retval;
844   route.index = NULL;
845   route.distance = 0;
846   route.type = ZEBRA_ROUTE_OLSR;        // OLSR
847   route.message = ZAPI_MESSAGE_METRIC;
848   route.flags = zebra.flags;
849   route.prefixlen = r->rt_dst.prefix_len;
850   route.prefix = r->rt_dst.prefix.v4.s_addr;
851   if ((r->rt_nexthop.gateway.v4.s_addr == r->rt_dst.prefix.v4.s_addr && route.prefixlen == 32)) {
852     route.message |= ZAPI_MESSAGE_IFINDEX;
853     route.ind_num = 1;
854     route.index = olsr_malloc(sizeof *route.index, "zebra_add_olsr_v4_route");
855     *route.index = htonl(r->rt_nexthop.iif_index);
856     route.nexthops = olsr_malloc(sizeof route.nexthops->type + sizeof route.nexthops->payload, "zebra_add_olsr_v4_route");
857     route.nh_count = 1;
858     route.nexthops->type = 0;
859   } else {
860     route.message |= ZAPI_MESSAGE_NEXTHOP;
861     route.nh_count = 1;
862     route.nexthops =
863       olsr_malloc(route.nh_count * (sizeof route.nexthops->type + sizeof route.nexthops->payload), "zebra_add_olsr_v4_route");
864     route.nexthops->type = ZEBRA_NEXTHOP_IPV4;
865     route.nexthops->payload.v4 = r->rt_nexthop.gateway.v4.s_addr;
866   }
867   route.metric = 0;
868
869   if (zebra.distance) {
870     route.message |= ZAPI_MESSAGE_DISTANCE;
871     route.distance = zebra.distance;
872   }
873
874   retval = zebra_delete_v4_route(route);
875
876   free_ipv4_route(route);
877   return retval;
878 }
879
880 void
881 zebra_olsr_distance(unsigned char dist)
882 {
883   zebra.distance = dist;
884 }
885
886 void
887 zebra_olsr_localpref(void)
888 {
889   zebra.flags &= ZEBRA_FLAG_SELECTED;
890 }
891
892 void
893 zebra_export_routes(unsigned char t)
894 {
895   if (t)
896     zebra.options |= OPTION_EXPORT;
897   else
898     zebra.options &= ~OPTION_EXPORT;
899 }
900
901 /*
902  * Local Variables:
903  * c-basic-offset: 2
904  * indent-tabs-mode: nil
905  * End:
906  */