Merge redistribute add and delete functions
[olsrd.git] / lib / quagga / src / quagga.c
1 /*
2  * OLSRd Quagga plugin
3  *
4  * Copyright (C) 2006-2008 Immo 'FaUl' Wehrenberg <immo@chaostreff-dortmund.de>
5  * Copyright (C) 2007-2010 Vasilis Tsiligiannis <acinonyxs@yahoo.gr>
6  *
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License version 2 as
9  * published by the Free Software Foundation or - at your option - under
10  * the terms of the GNU General Public Licence version 2 but can be
11  * linked to any BSD-Licenced Software with public available sourcecode
12  *
13  */
14
15 /* -------------------------------------------------------------------------
16  * File               : quagga.c
17  * Description        : functions to interface zebra with olsrd
18  * ------------------------------------------------------------------------- */
19
20 #include "defs.h"
21 #include "olsr.h"
22 #include "log.h"
23
24 #include "common.h"
25 #include "quagga.h"
26 #include "packet.h"
27 #include "client.h"
28
29 struct zebra zebra;
30
31 void
32 zebra_init(void)
33 {
34
35   memset(&zebra, 0, sizeof zebra);
36   zebra.sockpath = olsr_malloc(sizeof ZEBRA_SOCKPATH  + 1, "QUAGGA: New socket path");
37   strscpy(zebra.sockpath, ZEBRA_SOCKPATH, sizeof ZEBRA_SOCKPATH);
38
39 }
40
41 void
42 zebra_fini(void)
43 {
44   struct rt_entry *tmp;
45
46   if (zebra.options & OPTION_EXPORT) {
47     OLSR_FOR_ALL_RT_ENTRIES(tmp) {
48       zebra_delroute(tmp);
49     }
50     OLSR_FOR_ALL_RT_ENTRIES_END(tmp);
51   }
52   zebra_redistribute(ZEBRA_REDISTRIBUTE_DELETE);
53
54 }
55
56 int
57 zebra_addroute(const struct rt_entry *r)
58 {
59   struct zroute route;
60   int retval;
61
62   route.distance = 0;
63   route.type = ZEBRA_ROUTE_OLSR;
64   route.flags = zebra.flags;
65   route.message = ZAPI_MESSAGE_NEXTHOP | ZAPI_MESSAGE_METRIC;
66   route.prefixlen = r->rt_dst.prefix_len;
67   if (olsr_cnf->ip_version == AF_INET)
68     route.prefix.v4.s_addr = r->rt_dst.prefix.v4.s_addr;
69   else
70     memcpy(route.prefix.v6.s6_addr, r->rt_dst.prefix.v6.s6_addr, sizeof route.prefix.v6.s6_addr);
71   route.ifindex_num = 0;
72   route.ifindex = NULL;
73   route.nexthop_num = 0;
74   route.nexthop = NULL;
75
76   if ((olsr_cnf->ip_version == AF_INET && r->rt_best->rtp_nexthop.gateway.v4.s_addr == r->rt_dst.prefix.v4.s_addr &&
77         route.prefixlen == 32) ||
78       (olsr_cnf->ip_version == AF_INET6 &&
79         !memcmp(r->rt_best->rtp_nexthop.gateway.v6.s6_addr, r->rt_dst.prefix.v6.s6_addr, sizeof r->rt_best->rtp_nexthop.gateway.v6.s6_addr) &&
80         route.prefixlen == 128)) {
81     return 0;                   /* Quagga BUG workaround: don't add routes with destination = gateway
82                                    see http://lists.olsr.org/pipermail/olsr-users/2006-June/001726.html */
83     route.ifindex_num++;
84     route.ifindex = olsr_malloc(sizeof *route.ifindex, "QUAGGA: New zebra route ifindex");
85     *route.ifindex = r->rt_best->rtp_nexthop.iif_index;
86   } else {
87     route.nexthop_num++;
88     route.nexthop = olsr_malloc(sizeof *route.nexthop, "QUAGGA: New zebra route nexthop");
89     if (olsr_cnf->ip_version == AF_INET)
90       route.nexthop->v4.s_addr = r->rt_best->rtp_nexthop.gateway.v4.s_addr;
91     else
92       memcpy(route.nexthop->v6.s6_addr, r->rt_best->rtp_nexthop.gateway.v6.s6_addr, sizeof route.nexthop->v6.s6_addr);
93   }
94
95   route.metric = r->rt_best->rtp_metric.hops;
96
97   if (zebra.distance) {
98     route.message |= ZAPI_MESSAGE_DISTANCE;
99     route.distance = zebra.distance;
100   }
101
102   retval = zclient_write(zpacket_route(olsr_cnf->ip_version == AF_INET ? ZEBRA_IPV4_ROUTE_ADD : ZEBRA_IPV6_ROUTE_ADD, &route));
103
104   return retval;
105 }
106
107 int
108 zebra_delroute(const struct rt_entry *r)
109 {
110   struct zroute route;
111   int retval;
112
113   route.distance = 0;
114   route.type = ZEBRA_ROUTE_OLSR;
115   route.flags = zebra.flags;
116   route.message = ZAPI_MESSAGE_NEXTHOP | ZAPI_MESSAGE_METRIC;
117   route.prefixlen = r->rt_dst.prefix_len;
118   if (olsr_cnf->ip_version == AF_INET)
119     route.prefix.v4.s_addr = r->rt_dst.prefix.v4.s_addr;
120   else
121     memcpy(route.prefix.v6.s6_addr, r->rt_dst.prefix.v6.s6_addr, sizeof route.prefix.v6.s6_addr);
122   route.ifindex_num = 0;
123   route.ifindex = NULL;
124   route.nexthop_num = 0;
125   route.nexthop = NULL;
126
127   if ((olsr_cnf->ip_version == AF_INET && r->rt_nexthop.gateway.v4.s_addr == r->rt_dst.prefix.v4.s_addr &&
128         route.prefixlen == 32) ||
129        (olsr_cnf->ip_version == AF_INET6 &&
130         !memcmp(r->rt_nexthop.gateway.v6.s6_addr, r->rt_dst.prefix.v6.s6_addr, sizeof r->rt_nexthop.gateway.v6.s6_addr) &&
131         route.prefixlen == 128)) {
132     return 0;                   /* Quagga BUG workaround: don't delete routes with destination = gateway
133                                    see http://lists.olsr.org/pipermail/olsr-users/2006-June/001726.html */
134     route.ifindex_num++;
135     route.ifindex = olsr_malloc(sizeof *route.ifindex, "QUAGGA: New zebra route ifindex");
136     *route.ifindex = r->rt_nexthop.iif_index;
137   } else {
138     route.nexthop_num++;
139     route.nexthop = olsr_malloc(sizeof *route.nexthop, "QUAGGA: New zebra route nexthop");
140     if (olsr_cnf->ip_version == AF_INET)
141       route.nexthop->v4.s_addr = r->rt_nexthop.gateway.v4.s_addr;
142     else
143       memcpy(route.nexthop->v6.s6_addr, r->rt_nexthop.gateway.v6.s6_addr, sizeof route.nexthop->v6.s6_addr);
144   }
145
146   route.metric = 0;
147
148   if (zebra.distance) {
149     route.message |= ZAPI_MESSAGE_DISTANCE;
150     route.distance = zebra.distance;
151   }
152
153   retval = zclient_write(zpacket_route(olsr_cnf->ip_version == AF_INET ? ZEBRA_IPV4_ROUTE_DELETE : ZEBRA_IPV6_ROUTE_DELETE, &route));
154
155   return retval;
156 }
157
158 void
159 zebra_redistribute(uint16_t cmd)
160 {
161   unsigned char type;
162
163   for (type = 0; type < ZEBRA_ROUTE_MAX; type++)
164     if (zebra.redistribute[type]) {
165       if (zclient_write(zpacket_redistribute(cmd, type)) < 0)
166         olsr_exit("(QUAGGA) Could not write redistribute packet!", EXIT_FAILURE);
167     }
168
169 }
170
171 /*
172  * Local Variables:
173  * c-basic-offset: 2
174  * indent-tabs-mode: nil
175  * End:
176  */