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