]> git.proxmox.com Git - mirror_frr.git/blob - isisd/isis_zebra.c
zebra: Fix label manager memory leak (#5680)
[mirror_frr.git] / isisd / isis_zebra.c
1 /*
2 * IS-IS Rout(e)ing protocol - isis_zebra.c
3 *
4 * Copyright (C) 2001,2002 Sampo Saaristo
5 * Tampere University of Technology
6 * Institute of Communications Engineering
7 * Copyright (C) 2013-2015 Christian Franke <chris@opensourcerouting.org>
8 *
9 * This program is free software; you can redistribute it and/or modify it
10 * under the terms of the GNU General Public Licenseas published by the Free
11 * Software Foundation; either version 2 of the License, or (at your option)
12 * any later version.
13 *
14 * This program is distributed in the hope that it will be useful,but WITHOUT
15 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
16 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
17 * more details.
18 *
19 * You should have received a copy of the GNU General Public License along
20 * with this program; see the file COPYING; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
22 */
23
24 #include <zebra.h>
25
26 #include "thread.h"
27 #include "command.h"
28 #include "memory.h"
29 #include "log.h"
30 #include "lib_errors.h"
31 #include "if.h"
32 #include "network.h"
33 #include "prefix.h"
34 #include "zclient.h"
35 #include "stream.h"
36 #include "linklist.h"
37 #include "nexthop.h"
38 #include "vrf.h"
39 #include "libfrr.h"
40
41 #include "isisd/isis_constants.h"
42 #include "isisd/isis_common.h"
43 #include "isisd/isis_flags.h"
44 #include "isisd/isis_misc.h"
45 #include "isisd/isis_circuit.h"
46 #include "isisd/isisd.h"
47 #include "isisd/isis_circuit.h"
48 #include "isisd/isis_csm.h"
49 #include "isisd/isis_lsp.h"
50 #include "isisd/isis_route.h"
51 #include "isisd/isis_zebra.h"
52 #include "isisd/isis_te.h"
53
54 struct zclient *zclient = NULL;
55
56 /* Router-id update message from zebra. */
57 static int isis_router_id_update_zebra(ZAPI_CALLBACK_ARGS)
58 {
59 struct isis_area *area;
60 struct listnode *node;
61 struct prefix router_id;
62
63 zebra_router_id_update_read(zclient->ibuf, &router_id);
64 if (isis->router_id == router_id.u.prefix4.s_addr)
65 return 0;
66
67 isis->router_id = router_id.u.prefix4.s_addr;
68 for (ALL_LIST_ELEMENTS_RO(isis->area_list, node, area))
69 if (listcount(area->area_addrs) > 0)
70 lsp_regenerate_schedule(area, area->is_type, 0);
71
72 return 0;
73 }
74
75 static int isis_zebra_if_address_add(ZAPI_CALLBACK_ARGS)
76 {
77 struct connected *c;
78 struct prefix *p;
79 char buf[PREFIX2STR_BUFFER];
80
81 c = zebra_interface_address_read(ZEBRA_INTERFACE_ADDRESS_ADD,
82 zclient->ibuf, vrf_id);
83
84 if (c == NULL)
85 return 0;
86
87 p = c->address;
88
89 prefix2str(p, buf, sizeof(buf));
90 #ifdef EXTREME_DEBUG
91 if (p->family == AF_INET)
92 zlog_debug("connected IP address %s", buf);
93 if (p->family == AF_INET6)
94 zlog_debug("connected IPv6 address %s", buf);
95 #endif /* EXTREME_DEBUG */
96 if (if_is_operative(c->ifp))
97 isis_circuit_add_addr(circuit_scan_by_ifp(c->ifp), c);
98
99 return 0;
100 }
101
102 static int isis_zebra_if_address_del(ZAPI_CALLBACK_ARGS)
103 {
104 struct connected *c;
105 struct interface *ifp;
106 #ifdef EXTREME_DEBUG
107 struct prefix *p;
108 char buf[PREFIX2STR_BUFFER];
109 #endif /* EXTREME_DEBUG */
110
111 c = zebra_interface_address_read(ZEBRA_INTERFACE_ADDRESS_DELETE,
112 zclient->ibuf, vrf_id);
113
114 if (c == NULL)
115 return 0;
116
117 ifp = c->ifp;
118
119 #ifdef EXTREME_DEBUG
120 p = c->address;
121 prefix2str(p, buf, sizeof(buf));
122
123 if (p->family == AF_INET)
124 zlog_debug("disconnected IP address %s", buf);
125 if (p->family == AF_INET6)
126 zlog_debug("disconnected IPv6 address %s", buf);
127 #endif /* EXTREME_DEBUG */
128
129 if (if_is_operative(ifp))
130 isis_circuit_del_addr(circuit_scan_by_ifp(ifp), c);
131 connected_free(&c);
132
133 return 0;
134 }
135
136 static int isis_zebra_link_params(ZAPI_CALLBACK_ARGS)
137 {
138 struct interface *ifp;
139
140 ifp = zebra_interface_link_params_read(zclient->ibuf, vrf_id);
141
142 if (ifp == NULL)
143 return 0;
144
145 /* Update TE TLV */
146 isis_mpls_te_update(ifp);
147
148 return 0;
149 }
150
151 void isis_zebra_route_add_route(struct prefix *prefix,
152 struct prefix_ipv6 *src_p,
153 struct isis_route_info *route_info)
154 {
155 struct zapi_route api;
156 struct zapi_nexthop *api_nh;
157 struct isis_nexthop *nexthop;
158 struct listnode *node;
159 int count = 0;
160
161 if (zclient->sock < 0)
162 return;
163
164 memset(&api, 0, sizeof(api));
165 api.vrf_id = VRF_DEFAULT;
166 api.type = PROTO_TYPE;
167 api.safi = SAFI_UNICAST;
168 api.prefix = *prefix;
169 if (src_p && src_p->prefixlen) {
170 api.src_prefix = *src_p;
171 SET_FLAG(api.message, ZAPI_MESSAGE_SRCPFX);
172 }
173 SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP);
174 SET_FLAG(api.message, ZAPI_MESSAGE_METRIC);
175 api.metric = route_info->cost;
176 #if 0
177 SET_FLAG(api.message, ZAPI_MESSAGE_DISTANCE);
178 api.distance = route_info->depth;
179 #endif
180
181 /* Nexthops */
182 for (ALL_LIST_ELEMENTS_RO(route_info->nexthops, node, nexthop)) {
183 if (count >= MULTIPATH_NUM)
184 break;
185 api_nh = &api.nexthops[count];
186 if (fabricd)
187 SET_FLAG(api_nh->flags, ZAPI_NEXTHOP_FLAG_ONLINK);
188 api_nh->vrf_id = VRF_DEFAULT;
189
190 switch (nexthop->family) {
191 case AF_INET:
192 /* FIXME: can it be ? */
193 if (nexthop->ip.ipv4.s_addr != INADDR_ANY) {
194 api_nh->type = NEXTHOP_TYPE_IPV4_IFINDEX;
195 api_nh->gate.ipv4 = nexthop->ip.ipv4;
196 } else {
197 api_nh->type = NEXTHOP_TYPE_IFINDEX;
198 }
199 break;
200 case AF_INET6:
201 if (!IN6_IS_ADDR_LINKLOCAL(&nexthop->ip.ipv6)
202 && !IN6_IS_ADDR_UNSPECIFIED(&nexthop->ip.ipv6)) {
203 continue;
204 }
205 api_nh->gate.ipv6 = nexthop->ip.ipv6;
206 api_nh->type = NEXTHOP_TYPE_IPV6_IFINDEX;
207 break;
208 default:
209 flog_err(EC_LIB_DEVELOPMENT,
210 "%s: unknown address family [%d]", __func__,
211 nexthop->family);
212 exit(1);
213 }
214
215 api_nh->ifindex = nexthop->ifindex;
216 count++;
217 }
218 if (!count)
219 return;
220
221 api.nexthop_num = count;
222
223 zclient_route_send(ZEBRA_ROUTE_ADD, zclient, &api);
224 }
225
226 void isis_zebra_route_del_route(struct prefix *prefix,
227 struct prefix_ipv6 *src_p,
228 struct isis_route_info *route_info)
229 {
230 struct zapi_route api;
231
232 if (zclient->sock < 0)
233 return;
234
235 memset(&api, 0, sizeof(api));
236 api.vrf_id = VRF_DEFAULT;
237 api.type = PROTO_TYPE;
238 api.safi = SAFI_UNICAST;
239 api.prefix = *prefix;
240 if (src_p && src_p->prefixlen) {
241 api.src_prefix = *src_p;
242 SET_FLAG(api.message, ZAPI_MESSAGE_SRCPFX);
243 }
244
245 zclient_route_send(ZEBRA_ROUTE_DELETE, zclient, &api);
246 }
247
248 static int isis_zebra_read(ZAPI_CALLBACK_ARGS)
249 {
250 struct zapi_route api;
251
252 if (zapi_route_decode(zclient->ibuf, &api) < 0)
253 return -1;
254
255 if (api.prefix.family == AF_INET6
256 && IN6_IS_ADDR_LINKLOCAL(&api.prefix.u.prefix6))
257 return 0;
258
259 /*
260 * Avoid advertising a false default reachability. (A default
261 * route installed by IS-IS gets redistributed from zebra back
262 * into IS-IS causing us to start advertising default reachabity
263 * without this check)
264 */
265 if (api.prefix.prefixlen == 0
266 && api.src_prefix.prefixlen == 0
267 && api.type == PROTO_TYPE) {
268 cmd = ZEBRA_REDISTRIBUTE_ROUTE_DEL;
269 }
270
271 if (cmd == ZEBRA_REDISTRIBUTE_ROUTE_ADD)
272 isis_redist_add(api.type, &api.prefix, &api.src_prefix,
273 api.distance, api.metric);
274 else
275 isis_redist_delete(api.type, &api.prefix, &api.src_prefix);
276
277 return 0;
278 }
279
280 int isis_distribute_list_update(int routetype)
281 {
282 return 0;
283 }
284
285 void isis_zebra_redistribute_set(afi_t afi, int type)
286 {
287 if (type == DEFAULT_ROUTE)
288 zclient_redistribute_default(ZEBRA_REDISTRIBUTE_DEFAULT_ADD,
289 zclient, afi, VRF_DEFAULT);
290 else
291 zclient_redistribute(ZEBRA_REDISTRIBUTE_ADD, zclient, afi, type,
292 0, VRF_DEFAULT);
293 }
294
295 void isis_zebra_redistribute_unset(afi_t afi, int type)
296 {
297 if (type == DEFAULT_ROUTE)
298 zclient_redistribute_default(ZEBRA_REDISTRIBUTE_DEFAULT_DELETE,
299 zclient, afi, VRF_DEFAULT);
300 else
301 zclient_redistribute(ZEBRA_REDISTRIBUTE_DELETE, zclient, afi,
302 type, 0, VRF_DEFAULT);
303 }
304
305 static void isis_zebra_connected(struct zclient *zclient)
306 {
307 zclient_send_reg_requests(zclient, VRF_DEFAULT);
308 }
309
310 void isis_zebra_init(struct thread_master *master)
311 {
312 zclient = zclient_new(master, &zclient_options_default);
313 zclient_init(zclient, PROTO_TYPE, 0, &isisd_privs);
314 zclient->zebra_connected = isis_zebra_connected;
315 zclient->router_id_update = isis_router_id_update_zebra;
316 zclient->interface_address_add = isis_zebra_if_address_add;
317 zclient->interface_address_delete = isis_zebra_if_address_del;
318 zclient->interface_link_params = isis_zebra_link_params;
319 zclient->redistribute_route_add = isis_zebra_read;
320 zclient->redistribute_route_del = isis_zebra_read;
321
322 return;
323 }
324
325 void isis_zebra_stop(void)
326 {
327 zclient_stop(zclient);
328 zclient_free(zclient);
329 frr_fini();
330 }