olsrd-quagga: Fix memory leak when adding and deleting routes
[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
103   free(route.ifindex);
104   free(route.nexthop);
105
106   return retval;
107 }
108
109 int
110 zebra_delroute(const struct rt_entry *r)
111 {
112   struct zroute route;
113   int retval;
114
115   route.distance = 0;
116   route.type = ZEBRA_ROUTE_OLSR;
117   route.flags = zebra.flags;
118   route.message = ZAPI_MESSAGE_NEXTHOP | ZAPI_MESSAGE_METRIC;
119   route.safi = SAFI_UNICAST;
120   route.prefixlen = r->rt_dst.prefix_len;
121   if (olsr_cnf->ip_version == AF_INET)
122     route.prefix.v4.s_addr = r->rt_dst.prefix.v4.s_addr;
123   else
124     memcpy(route.prefix.v6.s6_addr, r->rt_dst.prefix.v6.s6_addr, sizeof route.prefix.v6.s6_addr);
125   route.ifindex_num = 0;
126   route.ifindex = NULL;
127   route.nexthop_num = 0;
128   route.nexthop = NULL;
129
130   if ((olsr_cnf->ip_version == AF_INET && r->rt_nexthop.gateway.v4.s_addr == r->rt_dst.prefix.v4.s_addr &&
131        route.prefixlen == 32) ||
132       (olsr_cnf->ip_version == AF_INET6 &&
133        !memcmp(r->rt_nexthop.gateway.v6.s6_addr, r->rt_dst.prefix.v6.s6_addr, sizeof r->rt_nexthop.gateway.v6.s6_addr) &&
134        route.prefixlen == 128)) {
135     route.ifindex_num++;
136     route.ifindex = olsr_malloc(sizeof *route.ifindex, "QUAGGA: New zebra route ifindex");
137     *route.ifindex = r->rt_nexthop.iif_index;
138   } else {
139     route.nexthop_num++;
140     route.nexthop = olsr_malloc(sizeof *route.nexthop, "QUAGGA: New zebra route nexthop");
141     if (olsr_cnf->ip_version == AF_INET)
142       route.nexthop->v4.s_addr = r->rt_nexthop.gateway.v4.s_addr;
143     else
144       memcpy(route.nexthop->v6.s6_addr, r->rt_nexthop.gateway.v6.s6_addr, sizeof route.nexthop->v6.s6_addr);
145   }
146
147   route.metric = 0;
148
149   if (zebra.distance) {
150     route.message |= ZAPI_MESSAGE_DISTANCE;
151     route.distance = zebra.distance;
152   }
153
154   retval = zclient_write(zpacket_route(olsr_cnf->ip_version == AF_INET ? ZEBRA_IPV4_ROUTE_DELETE : ZEBRA_IPV6_ROUTE_DELETE, &route));
155
156   free(route.ifindex);
157   free(route.nexthop);
158
159   return retval;
160 }
161
162 void
163 zebra_redistribute(uint16_t cmd)
164 {
165   unsigned char type;
166
167   for (type = 0; type < ZEBRA_ROUTE_MAX; type++)
168     if (zebra.redistribute[type]) {
169       if (zclient_write(zpacket_redistribute(cmd, type)) < 0)
170         olsr_exit("(QUAGGA) Could not write redistribute packet!", EXIT_FAILURE);
171     }
172
173 }
174
175 void
176 zebra_hello(uint16_t cmd)
177 {
178
179   if (zclient_write(zpacket_redistribute(cmd, ZEBRA_ROUTE_OLSR)) < 0)
180     olsr_exit("(QUAGGA) Could not write hello packet!", EXIT_FAILURE);
181
182 }
183
184 /*
185  * Local Variables:
186  * c-basic-offset: 2
187  * indent-tabs-mode: nil
188  * End:
189  */