quagga plugin routes additional
[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-2013 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.safi = SAFI_UNICAST;
67   route.prefixlen = r->rt_dst.prefix_len;
68   if (olsr_cnf->ip_version == AF_INET)
69     route.prefix.v4.s_addr = r->rt_dst.prefix.v4.s_addr;
70   else
71     memcpy(route.prefix.v6.s6_addr, r->rt_dst.prefix.v6.s6_addr, sizeof route.prefix.v6.s6_addr);
72   route.ifindex_num = 0;
73   route.ifindex = NULL;
74   route.nexthop_num = 0;
75   route.nexthop = NULL;
76
77   if ((olsr_cnf->ip_version == AF_INET && r->rt_best->rtp_nexthop.gateway.v4.s_addr == r->rt_dst.prefix.v4.s_addr &&
78        route.prefixlen == 32) ||
79       (olsr_cnf->ip_version == AF_INET6 &&
80        !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) &&
81        route.prefixlen == 128)) {
82     route.ifindex_num++;
83     route.ifindex = olsr_malloc(sizeof *route.ifindex, "QUAGGA: New zebra route ifindex");
84     *route.ifindex = r->rt_best->rtp_nexthop.iif_index;
85   } else {
86     route.nexthop_num++;
87     route.nexthop = olsr_malloc(sizeof *route.nexthop, "QUAGGA: New zebra route nexthop");
88     if (olsr_cnf->ip_version == AF_INET)
89       route.nexthop->v4.s_addr = r->rt_best->rtp_nexthop.gateway.v4.s_addr;
90     else
91       memcpy(route.nexthop->v6.s6_addr, r->rt_best->rtp_nexthop.gateway.v6.s6_addr, sizeof route.nexthop->v6.s6_addr);
92   }
93
94   route.metric = r->rt_best->rtp_metric.hops;
95
96   if (zebra.distance) {
97     route.message |= ZAPI_MESSAGE_DISTANCE;
98     route.distance = zebra.distance;
99   }
100
101   retval = zclient_write(zpacket_route(olsr_cnf->ip_version == AF_INET ? ZEBRA_IPV4_ROUTE_ADD : ZEBRA_IPV6_ROUTE_ADD, &route));
102   if(!retval && zebra.options & OPTION_ROUTE_ADDITIONAL)
103     retval = olsr_cnf->ip_version == AF_INET ? zebra.orig_addroute_function(r) : zebra.orig_addroute6_function(r);
104
105   free(route.ifindex);
106   free(route.nexthop);
107
108   return retval;
109 }
110
111 int
112 zebra_delroute(const struct rt_entry *r)
113 {
114   struct zroute route;
115   int retval;
116
117   route.distance = 0;
118   route.type = ZEBRA_ROUTE_OLSR;
119   route.flags = zebra.flags;
120   route.message = ZAPI_MESSAGE_NEXTHOP | ZAPI_MESSAGE_METRIC;
121   route.safi = SAFI_UNICAST;
122   route.prefixlen = r->rt_dst.prefix_len;
123   if (olsr_cnf->ip_version == AF_INET)
124     route.prefix.v4.s_addr = r->rt_dst.prefix.v4.s_addr;
125   else
126     memcpy(route.prefix.v6.s6_addr, r->rt_dst.prefix.v6.s6_addr, sizeof route.prefix.v6.s6_addr);
127   route.ifindex_num = 0;
128   route.ifindex = NULL;
129   route.nexthop_num = 0;
130   route.nexthop = NULL;
131
132   if ((olsr_cnf->ip_version == AF_INET && r->rt_nexthop.gateway.v4.s_addr == r->rt_dst.prefix.v4.s_addr &&
133        route.prefixlen == 32) ||
134       (olsr_cnf->ip_version == AF_INET6 &&
135        !memcmp(r->rt_nexthop.gateway.v6.s6_addr, r->rt_dst.prefix.v6.s6_addr, sizeof r->rt_nexthop.gateway.v6.s6_addr) &&
136        route.prefixlen == 128)) {
137     route.ifindex_num++;
138     route.ifindex = olsr_malloc(sizeof *route.ifindex, "QUAGGA: New zebra route ifindex");
139     *route.ifindex = r->rt_nexthop.iif_index;
140   } else {
141     route.nexthop_num++;
142     route.nexthop = olsr_malloc(sizeof *route.nexthop, "QUAGGA: New zebra route nexthop");
143     if (olsr_cnf->ip_version == AF_INET)
144       route.nexthop->v4.s_addr = r->rt_nexthop.gateway.v4.s_addr;
145     else
146       memcpy(route.nexthop->v6.s6_addr, r->rt_nexthop.gateway.v6.s6_addr, sizeof route.nexthop->v6.s6_addr);
147   }
148
149   route.metric = 0;
150
151   if (zebra.distance) {
152     route.message |= ZAPI_MESSAGE_DISTANCE;
153     route.distance = zebra.distance;
154   }
155
156   retval = zclient_write(zpacket_route(olsr_cnf->ip_version == AF_INET ? ZEBRA_IPV4_ROUTE_DELETE : ZEBRA_IPV6_ROUTE_DELETE, &route));
157   if(!retval && zebra.options & OPTION_ROUTE_ADDITIONAL)
158     retval = olsr_cnf->ip_version == AF_INET ? zebra.orig_delroute_function(r) : zebra.orig_delroute6_function(r);
159
160   free(route.ifindex);
161   free(route.nexthop);
162
163   return retval;
164 }
165
166 void
167 zebra_redistribute(uint16_t cmd)
168 {
169   unsigned char type;
170
171   for (type = 0; type < ZEBRA_ROUTE_MAX; type++)
172     if (zebra.redistribute[type]) {
173       if (zclient_write(zpacket_redistribute(cmd, type)) < 0)
174         olsr_exit("(QUAGGA) Could not write redistribute packet!", EXIT_FAILURE);
175     }
176
177 }
178
179 void
180 zebra_hello(uint16_t cmd)
181 {
182
183   if (zclient_write(zpacket_redistribute(cmd, ZEBRA_ROUTE_OLSR)) < 0)
184     olsr_exit("(QUAGGA) Could not write hello packet!", EXIT_FAILURE);
185
186 }
187
188 /*
189  * Local Variables:
190  * c-basic-offset: 2
191  * indent-tabs-mode: nil
192  * End:
193  */