1 /*
2  * The olsr.org Optimized Link-State Routing daemon (olsrd)
3  *
4  * (c) by the OLSR project
5  *
6  * See our Git repository to find out who worked on this file
7  * and thus is a copyright holder on it.
8  *
9  * All rights reserved.
10  *
11  * Redistribution and use in source and binary forms, with or without
12  * modification, are permitted provided that the following conditions
13  * are met:
14  *
15  * * Redistributions of source code must retain the above copyright
16  *   notice, this list of conditions and the following disclaimer.
17  * * Redistributions in binary form must reproduce the above copyright
18  *   notice, this list of conditions and the following disclaimer in
19  *   the documentation and/or other materials provided with the
20  *   distribution.
21  * * Neither the name of olsr.org, olsrd nor the names of its
22  *   contributors may be used to endorse or promote products derived
23  *   from this software without specific prior written permission.
24  *
25  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
26  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
27  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
28  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
29  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
30  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
31  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
32  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
33  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
34  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
35  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
36  * POSSIBILITY OF SUCH DAMAGE.
37  *
38  * Visit http://www.olsr.org for more information.
39  *
40  * If you find this software useful feel free to make a donation
41  * to the project. For more information see the website or contact
42  * the copyright holders.
43  *
44  */
45 
46 /* -------------------------------------------------------------------------
47  * File               : quagga.c
48  * Description        : functions to interface zebra with olsrd
49  * ------------------------------------------------------------------------- */
50 
51 #include "defs.h"
52 #include "olsr.h"
53 #include "log.h"
54 
55 #include "common.h"
56 #include "quagga.h"
57 #include "packet.h"
58 #include "client.h"
59 
60 struct zebra zebra;
61 
62 void
zebra_init(void)63 zebra_init(void)
64 {
65 
66   memset(&zebra, 0, sizeof zebra);
67   zebra.sockpath = olsr_malloc(sizeof (ZEBRA_SOCKPATH), "QUAGGA: New socket path");
68   strscpy(zebra.sockpath, ZEBRA_SOCKPATH, sizeof (ZEBRA_SOCKPATH));
69 
70 }
71 
72 void
zebra_fini(void)73 zebra_fini(void)
74 {
75   struct rt_entry *tmp;
76 
77   if (zebra.options & OPTION_EXPORT) {
78     OLSR_FOR_ALL_RT_ENTRIES(tmp) {
79       zebra_delroute(tmp);
80     }
81     OLSR_FOR_ALL_RT_ENTRIES_END(tmp);
82   }
83   zebra_redistribute(ZEBRA_REDISTRIBUTE_DELETE);
84 
85 }
86 
87 int
zebra_addroute(const struct rt_entry * r)88 zebra_addroute(const struct rt_entry *r)
89 {
90   struct zroute route;
91   int retval;
92 
93   route.distance = 0;
94   route.type = ZEBRA_ROUTE_OLSR;
95   route.flags = zebra.flags;
96   route.message = ZAPI_MESSAGE_NEXTHOP | ZAPI_MESSAGE_METRIC;
97   route.safi = SAFI_UNICAST;
98   route.prefixlen = r->rt_dst.prefix_len;
99   if (olsr_cnf->ip_version == AF_INET)
100     route.prefix.v4.s_addr = r->rt_dst.prefix.v4.s_addr;
101   else
102     memcpy(route.prefix.v6.s6_addr, r->rt_dst.prefix.v6.s6_addr, sizeof route.prefix.v6.s6_addr);
103   route.ifindex_num = 0;
104   route.ifindex = NULL;
105   route.nexthop_num = 0;
106   route.nexthop = NULL;
107 
108   if ((olsr_cnf->ip_version == AF_INET && r->rt_best->rtp_nexthop.gateway.v4.s_addr == r->rt_dst.prefix.v4.s_addr &&
109        route.prefixlen == 32) ||
110       (olsr_cnf->ip_version == AF_INET6 &&
111        !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) &&
112        route.prefixlen == 128)) {
113     route.ifindex_num++;
114     route.ifindex = olsr_malloc(sizeof *route.ifindex, "QUAGGA: New zebra route ifindex");
115     *route.ifindex = r->rt_best->rtp_nexthop.iif_index;
116   } else {
117     route.nexthop_num++;
118     route.nexthop = olsr_malloc(sizeof *route.nexthop, "QUAGGA: New zebra route nexthop");
119     if (olsr_cnf->ip_version == AF_INET)
120       route.nexthop->v4.s_addr = r->rt_best->rtp_nexthop.gateway.v4.s_addr;
121     else
122       memcpy(route.nexthop->v6.s6_addr, r->rt_best->rtp_nexthop.gateway.v6.s6_addr, sizeof route.nexthop->v6.s6_addr);
123   }
124 
125   route.metric = r->rt_best->rtp_metric.hops;
126 
127   if (zebra.distance) {
128     route.message |= ZAPI_MESSAGE_DISTANCE;
129     route.distance = zebra.distance;
130   }
131 
132   retval = zclient_write(zpacket_route(olsr_cnf->ip_version == AF_INET ? ZEBRA_IPV4_ROUTE_ADD : ZEBRA_IPV6_ROUTE_ADD, &route));
133   if(!retval && (zebra.options & OPTION_ROUTE_ADDITIONAL))
134     retval = olsr_cnf->ip_version == AF_INET ? zebra.orig_addroute_function(r) : zebra.orig_addroute6_function(r);
135 
136   free(route.ifindex);
137   free(route.nexthop);
138 
139   return retval;
140 }
141 
142 int
zebra_delroute(const struct rt_entry * r)143 zebra_delroute(const struct rt_entry *r)
144 {
145   struct zroute route;
146   int retval;
147 
148   route.distance = 0;
149   route.type = ZEBRA_ROUTE_OLSR;
150   route.flags = zebra.flags;
151   route.message = ZAPI_MESSAGE_NEXTHOP | ZAPI_MESSAGE_METRIC;
152   route.safi = SAFI_UNICAST;
153   route.prefixlen = r->rt_dst.prefix_len;
154   if (olsr_cnf->ip_version == AF_INET)
155     route.prefix.v4.s_addr = r->rt_dst.prefix.v4.s_addr;
156   else
157     memcpy(route.prefix.v6.s6_addr, r->rt_dst.prefix.v6.s6_addr, sizeof route.prefix.v6.s6_addr);
158   route.ifindex_num = 0;
159   route.ifindex = NULL;
160   route.nexthop_num = 0;
161   route.nexthop = NULL;
162 
163   if ((olsr_cnf->ip_version == AF_INET && r->rt_nexthop.gateway.v4.s_addr == r->rt_dst.prefix.v4.s_addr &&
164        route.prefixlen == 32) ||
165       (olsr_cnf->ip_version == AF_INET6 &&
166        !memcmp(r->rt_nexthop.gateway.v6.s6_addr, r->rt_dst.prefix.v6.s6_addr, sizeof r->rt_nexthop.gateway.v6.s6_addr) &&
167        route.prefixlen == 128)) {
168     route.ifindex_num++;
169     route.ifindex = olsr_malloc(sizeof *route.ifindex, "QUAGGA: New zebra route ifindex");
170     *route.ifindex = r->rt_nexthop.iif_index;
171   } else {
172     route.nexthop_num++;
173     route.nexthop = olsr_malloc(sizeof *route.nexthop, "QUAGGA: New zebra route nexthop");
174     if (olsr_cnf->ip_version == AF_INET)
175       route.nexthop->v4.s_addr = r->rt_nexthop.gateway.v4.s_addr;
176     else
177       memcpy(route.nexthop->v6.s6_addr, r->rt_nexthop.gateway.v6.s6_addr, sizeof route.nexthop->v6.s6_addr);
178   }
179 
180   route.metric = 0;
181 
182   if (zebra.distance) {
183     route.message |= ZAPI_MESSAGE_DISTANCE;
184     route.distance = zebra.distance;
185   }
186 
187   retval = zclient_write(zpacket_route(olsr_cnf->ip_version == AF_INET ? ZEBRA_IPV4_ROUTE_DELETE : ZEBRA_IPV6_ROUTE_DELETE, &route));
188   if(!retval && (zebra.options & OPTION_ROUTE_ADDITIONAL))
189     retval = olsr_cnf->ip_version == AF_INET ? zebra.orig_delroute_function(r) : zebra.orig_delroute6_function(r);
190 
191   free(route.ifindex);
192   free(route.nexthop);
193 
194   return retval;
195 }
196 
197 void
zebra_redistribute(uint16_t cmd)198 zebra_redistribute(uint16_t cmd)
199 {
200   unsigned char type;
201 
202   for (type = 0; type < ZEBRA_ROUTE_MAX; type++)
203     if (zebra.redistribute[type]) {
204       if (zclient_write(zpacket_redistribute(cmd, type)) < 0)
205         olsr_exit("QUAGGA: Could not write redistribute packet", EXIT_FAILURE);
206     }
207 
208 }
209 
210 void
zebra_hello(uint16_t cmd)211 zebra_hello(uint16_t cmd)
212 {
213 
214   if (zclient_write(zpacket_redistribute(cmd, ZEBRA_ROUTE_OLSR)) < 0)
215     olsr_exit("QUAGGA: Could not write hello packet", EXIT_FAILURE);
216 
217 }
218 
219 /*
220  * Local Variables:
221  * c-basic-offset: 2
222  * indent-tabs-mode: nil
223  * End:
224  */
225