blob: 1ba0100d4dd1d007a7030be49051903744bef187 [file] [log] [blame]
jardineb5d44e2003-12-23 08:09:43 +00001/*
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 *
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public Licenseas published by the Free
10 * Software Foundation; either version 2 of the License, or (at your option)
11 * any later version.
12 *
13 * This program is distributed in the hope that it will be useful,but WITHOUT
14 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
15 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
16 * more details.
17
18 * You should have received a copy of the GNU General Public License along
19 * with this program; if not, write to the Free Software Foundation, Inc.,
20 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
21 */
22
23#include <zebra.h>
jardineb5d44e2003-12-23 08:09:43 +000024
25#include "thread.h"
26#include "command.h"
27#include "memory.h"
28#include "log.h"
29#include "if.h"
30#include "network.h"
31#include "prefix.h"
32#include "zclient.h"
33#include "stream.h"
34#include "linklist.h"
35
hassoc89c05d2005-09-04 21:36:36 +000036#include "isisd/dict.h"
jardineb5d44e2003-12-23 08:09:43 +000037#include "isisd/isis_constants.h"
38#include "isisd/isis_common.h"
Josh Bailey3f045a02012-03-24 08:35:20 -070039#include "isisd/isis_flags.h"
40#include "isisd/isis_misc.h"
41#include "isisd/isis_circuit.h"
42#include "isisd/isis_tlv.h"
hassoc89c05d2005-09-04 21:36:36 +000043#include "isisd/isisd.h"
jardineb5d44e2003-12-23 08:09:43 +000044#include "isisd/isis_circuit.h"
45#include "isisd/isis_csm.h"
Josh Bailey3f045a02012-03-24 08:35:20 -070046#include "isisd/isis_lsp.h"
jardineb5d44e2003-12-23 08:09:43 +000047#include "isisd/isis_route.h"
48#include "isisd/isis_zebra.h"
49
50struct zclient *zclient = NULL;
51
hasso18a6dce2004-10-03 18:18:34 +000052/* Router-id update message from zebra. */
hasso92365882005-01-18 13:53:33 +000053static int
hasso18a6dce2004-10-03 18:18:34 +000054isis_router_id_update_zebra (int command, struct zclient *zclient,
55 zebra_size_t length)
56{
Josh Bailey3f045a02012-03-24 08:35:20 -070057 struct isis_area *area;
58 struct listnode *node;
hasso18a6dce2004-10-03 18:18:34 +000059 struct prefix router_id;
hasso18a6dce2004-10-03 18:18:34 +000060
Josh Bailey3f045a02012-03-24 08:35:20 -070061 zebra_router_id_update_read (zclient->ibuf, &router_id);
62 if (isis->router_id == router_id.u.prefix4.s_addr)
63 return 0;
hasso18a6dce2004-10-03 18:18:34 +000064
Josh Bailey3f045a02012-03-24 08:35:20 -070065 isis->router_id = router_id.u.prefix4.s_addr;
66 for (ALL_LIST_ELEMENTS_RO (isis->area_list, node, area))
67 if (listcount (area->area_addrs) > 0)
68 lsp_regenerate_schedule (area, area->is_type, 0);
69
hasso18a6dce2004-10-03 18:18:34 +000070 return 0;
71}
jardineb5d44e2003-12-23 08:09:43 +000072
hasso92365882005-01-18 13:53:33 +000073static int
jardineb5d44e2003-12-23 08:09:43 +000074isis_zebra_if_add (int command, struct zclient *zclient, zebra_size_t length)
75{
76 struct interface *ifp;
77
78 ifp = zebra_interface_add_read (zclient->ibuf);
hassof390d2c2004-09-10 20:48:21 +000079
hassoc89c05d2005-09-04 21:36:36 +000080 if (isis->debugs & DEBUG_ZEBRA)
81 zlog_debug ("Zebra I/F add: %s index %d flags %ld metric %d mtu %d",
Paul Jakma41b36e92006-12-08 01:09:50 +000082 ifp->name, ifp->ifindex, (long)ifp->flags, ifp->metric, ifp->mtu);
hassof390d2c2004-09-10 20:48:21 +000083
hassob30c5e62004-12-29 20:06:41 +000084 if (if_is_operative (ifp))
jardineb5d44e2003-12-23 08:09:43 +000085 isis_csm_state_change (IF_UP_FROM_Z, circuit_scan_by_ifp (ifp), ifp);
hassof390d2c2004-09-10 20:48:21 +000086
jardineb5d44e2003-12-23 08:09:43 +000087 return 0;
88}
89
hasso92365882005-01-18 13:53:33 +000090static int
jardineb5d44e2003-12-23 08:09:43 +000091isis_zebra_if_del (int command, struct zclient *zclient, zebra_size_t length)
92{
93 struct interface *ifp;
94 struct stream *s;
95
96 s = zclient->ibuf;
97 ifp = zebra_interface_state_read (s);
hassof390d2c2004-09-10 20:48:21 +000098
jardineb5d44e2003-12-23 08:09:43 +000099 if (!ifp)
100 return 0;
101
hassob30c5e62004-12-29 20:06:41 +0000102 if (if_is_operative (ifp))
jardineb5d44e2003-12-23 08:09:43 +0000103 zlog_warn ("Zebra: got delete of %s, but interface is still up",
hassof390d2c2004-09-10 20:48:21 +0000104 ifp->name);
jardineb5d44e2003-12-23 08:09:43 +0000105
hassoc89c05d2005-09-04 21:36:36 +0000106 if (isis->debugs & DEBUG_ZEBRA)
107 zlog_debug ("Zebra I/F delete: %s index %d flags %ld metric %d mtu %d",
Paul Jakma41b36e92006-12-08 01:09:50 +0000108 ifp->name, ifp->ifindex, (long)ifp->flags, ifp->metric, ifp->mtu);
jardineb5d44e2003-12-23 08:09:43 +0000109
Josh Bailey3f045a02012-03-24 08:35:20 -0700110 isis_csm_state_change (IF_DOWN_FROM_Z, circuit_scan_by_ifp (ifp), ifp);
ajsd2fc8892005-04-02 18:38:43 +0000111
112 /* Cannot call if_delete because we should retain the pseudo interface
113 in case there is configuration info attached to it. */
114 if_delete_retain(ifp);
hassof390d2c2004-09-10 20:48:21 +0000115
ajsd2fc8892005-04-02 18:38:43 +0000116 ifp->ifindex = IFINDEX_INTERNAL;
117
jardineb5d44e2003-12-23 08:09:43 +0000118 return 0;
119}
120
hasso92365882005-01-18 13:53:33 +0000121static int
hassof390d2c2004-09-10 20:48:21 +0000122isis_zebra_if_state_up (int command, struct zclient *zclient,
jardineb5d44e2003-12-23 08:09:43 +0000123 zebra_size_t length)
124{
125 struct interface *ifp;
hassof390d2c2004-09-10 20:48:21 +0000126
Josh Bailey3f045a02012-03-24 08:35:20 -0700127 ifp = zebra_interface_state_read (zclient->ibuf);
hassof390d2c2004-09-10 20:48:21 +0000128
Josh Bailey3f045a02012-03-24 08:35:20 -0700129 if (ifp == NULL)
jardineb5d44e2003-12-23 08:09:43 +0000130 return 0;
hassof390d2c2004-09-10 20:48:21 +0000131
jardineb5d44e2003-12-23 08:09:43 +0000132 isis_csm_state_change (IF_UP_FROM_Z, circuit_scan_by_ifp (ifp), ifp);
hassof390d2c2004-09-10 20:48:21 +0000133
jardineb5d44e2003-12-23 08:09:43 +0000134 return 0;
135}
136
hasso92365882005-01-18 13:53:33 +0000137static int
hassof390d2c2004-09-10 20:48:21 +0000138isis_zebra_if_state_down (int command, struct zclient *zclient,
jardineb5d44e2003-12-23 08:09:43 +0000139 zebra_size_t length)
140{
141 struct interface *ifp;
Josh Bailey3f045a02012-03-24 08:35:20 -0700142 struct isis_circuit *circuit;
hassof390d2c2004-09-10 20:48:21 +0000143
Josh Bailey3f045a02012-03-24 08:35:20 -0700144 ifp = zebra_interface_state_read (zclient->ibuf);
hassof390d2c2004-09-10 20:48:21 +0000145
jardineb5d44e2003-12-23 08:09:43 +0000146 if (ifp == NULL)
147 return 0;
hassof390d2c2004-09-10 20:48:21 +0000148
Josh Bailey3f045a02012-03-24 08:35:20 -0700149 circuit = isis_csm_state_change (IF_DOWN_FROM_Z, circuit_scan_by_ifp (ifp),
150 ifp);
151 if (circuit)
152 SET_FLAG(circuit->flags, ISIS_CIRCUIT_FLAPPED_AFTER_SPF);
hassof390d2c2004-09-10 20:48:21 +0000153
jardineb5d44e2003-12-23 08:09:43 +0000154 return 0;
155}
156
hasso92365882005-01-18 13:53:33 +0000157static int
hassof390d2c2004-09-10 20:48:21 +0000158isis_zebra_if_address_add (int command, struct zclient *zclient,
159 zebra_size_t length)
jardineb5d44e2003-12-23 08:09:43 +0000160{
161 struct connected *c;
162 struct prefix *p;
hassof7c43dc2004-09-26 16:24:14 +0000163 char buf[BUFSIZ];
jardineb5d44e2003-12-23 08:09:43 +0000164
hassof390d2c2004-09-10 20:48:21 +0000165 c = zebra_interface_address_read (ZEBRA_INTERFACE_ADDRESS_ADD,
166 zclient->ibuf);
167
jardineb5d44e2003-12-23 08:09:43 +0000168 if (c == NULL)
169 return 0;
hassof390d2c2004-09-10 20:48:21 +0000170
jardineb5d44e2003-12-23 08:09:43 +0000171 p = c->address;
hassof390d2c2004-09-10 20:48:21 +0000172
jardineb5d44e2003-12-23 08:09:43 +0000173 prefix2str (p, buf, BUFSIZ);
174#ifdef EXTREME_DEBUG
hassof390d2c2004-09-10 20:48:21 +0000175 if (p->family == AF_INET)
hasso529d65b2004-12-24 00:14:50 +0000176 zlog_debug ("connected IP address %s", buf);
jardineb5d44e2003-12-23 08:09:43 +0000177#ifdef HAVE_IPV6
178 if (p->family == AF_INET6)
hasso529d65b2004-12-24 00:14:50 +0000179 zlog_debug ("connected IPv6 address %s", buf);
jardineb5d44e2003-12-23 08:09:43 +0000180#endif /* HAVE_IPV6 */
181#endif /* EXTREME_DEBUG */
hassob30c5e62004-12-29 20:06:41 +0000182 if (if_is_operative (c->ifp))
183 isis_circuit_add_addr (circuit_scan_by_ifp (c->ifp), c);
jardineb5d44e2003-12-23 08:09:43 +0000184
185 return 0;
186}
187
hasso92365882005-01-18 13:53:33 +0000188static int
hassof390d2c2004-09-10 20:48:21 +0000189isis_zebra_if_address_del (int command, struct zclient *client,
190 zebra_size_t length)
jardineb5d44e2003-12-23 08:09:43 +0000191{
192 struct connected *c;
193 struct interface *ifp;
hasso1cd80842004-10-07 20:07:40 +0000194#ifdef EXTREME_DEBUG
hassof891f442004-09-14 13:54:30 +0000195 struct prefix *p;
196 u_char buf[BUFSIZ];
hasso1cd80842004-10-07 20:07:40 +0000197#endif /* EXTREME_DEBUG */
jardineb5d44e2003-12-23 08:09:43 +0000198
hassof390d2c2004-09-10 20:48:21 +0000199 c = zebra_interface_address_read (ZEBRA_INTERFACE_ADDRESS_DELETE,
200 zclient->ibuf);
201
jardineb5d44e2003-12-23 08:09:43 +0000202 if (c == NULL)
203 return 0;
hassof390d2c2004-09-10 20:48:21 +0000204
jardineb5d44e2003-12-23 08:09:43 +0000205 ifp = c->ifp;
hassof390d2c2004-09-10 20:48:21 +0000206
hassof891f442004-09-14 13:54:30 +0000207#ifdef EXTREME_DEBUG
208 p = c->address;
209 prefix2str (p, buf, BUFSIZ);
210
211 if (p->family == AF_INET)
hasso529d65b2004-12-24 00:14:50 +0000212 zlog_debug ("disconnected IP address %s", buf);
hassof891f442004-09-14 13:54:30 +0000213#ifdef HAVE_IPV6
214 if (p->family == AF_INET6)
hasso529d65b2004-12-24 00:14:50 +0000215 zlog_debug ("disconnected IPv6 address %s", buf);
hassof891f442004-09-14 13:54:30 +0000216#endif /* HAVE_IPV6 */
217#endif /* EXTREME_DEBUG */
hassof390d2c2004-09-10 20:48:21 +0000218
hassob30c5e62004-12-29 20:06:41 +0000219 if (if_is_operative (ifp))
220 isis_circuit_del_addr (circuit_scan_by_ifp (ifp), c);
hassof891f442004-09-14 13:54:30 +0000221 connected_free (c);
hassof390d2c2004-09-10 20:48:21 +0000222
jardineb5d44e2003-12-23 08:09:43 +0000223 return 0;
224}
225
hasso92365882005-01-18 13:53:33 +0000226static void
hassof390d2c2004-09-10 20:48:21 +0000227isis_zebra_route_add_ipv4 (struct prefix *prefix,
228 struct isis_route_info *route_info)
jardineb5d44e2003-12-23 08:09:43 +0000229{
230 u_char message, flags;
231 int psize;
232 struct stream *stream;
233 struct isis_nexthop *nexthop;
234 struct listnode *node;
235
Josh Bailey3f045a02012-03-24 08:35:20 -0700236 if (CHECK_FLAG (route_info->flag, ISIS_ROUTE_FLAG_ZEBRA_SYNCED))
jardineb5d44e2003-12-23 08:09:43 +0000237 return;
238
hassof390d2c2004-09-10 20:48:21 +0000239 if (zclient->redist[ZEBRA_ROUTE_ISIS])
240 {
241 message = 0;
242 flags = 0;
jardineb5d44e2003-12-23 08:09:43 +0000243
hassof390d2c2004-09-10 20:48:21 +0000244 SET_FLAG (message, ZAPI_MESSAGE_NEXTHOP);
245 SET_FLAG (message, ZAPI_MESSAGE_METRIC);
hasso2097cd82003-12-23 11:51:08 +0000246#if 0
hassof390d2c2004-09-10 20:48:21 +0000247 SET_FLAG (message, ZAPI_MESSAGE_DISTANCE);
hasso2097cd82003-12-23 11:51:08 +0000248#endif
hassof390d2c2004-09-10 20:48:21 +0000249
250 stream = zclient->obuf;
251 stream_reset (stream);
pauld3092e72006-01-17 17:33:46 +0000252 zclient_create_header (stream, ZEBRA_IPV4_ROUTE_ADD);
hassof390d2c2004-09-10 20:48:21 +0000253 /* type */
254 stream_putc (stream, ZEBRA_ROUTE_ISIS);
255 /* flags */
256 stream_putc (stream, flags);
257 /* message */
258 stream_putc (stream, message);
Avneesh Sachdevaa3b2642012-04-11 23:56:03 -0700259 /* SAFI */
260 stream_putw (stream, SAFI_UNICAST);
hassof390d2c2004-09-10 20:48:21 +0000261 /* prefix information */
262 psize = PSIZE (prefix->prefixlen);
263 stream_putc (stream, prefix->prefixlen);
264 stream_write (stream, (u_char *) & prefix->u.prefix4, psize);
265
266 stream_putc (stream, listcount (route_info->nexthops));
267
268 /* Nexthop, ifindex, distance and metric information */
paul1eb8ef22005-04-07 07:30:20 +0000269 for (ALL_LIST_ELEMENTS_RO (route_info->nexthops, node, nexthop))
hassof390d2c2004-09-10 20:48:21 +0000270 {
hassof390d2c2004-09-10 20:48:21 +0000271 /* FIXME: can it be ? */
272 if (nexthop->ip.s_addr != INADDR_ANY)
273 {
274 stream_putc (stream, ZEBRA_NEXTHOP_IPV4);
275 stream_put_in_addr (stream, &nexthop->ip);
276 }
277 else
278 {
279 stream_putc (stream, ZEBRA_NEXTHOP_IFINDEX);
280 stream_putl (stream, nexthop->ifindex);
281 }
282 }
283#if 0
284 if (CHECK_FLAG (message, ZAPI_MESSAGE_DISTANCE))
285 stream_putc (stream, route_info->depth);
286#endif
287 if (CHECK_FLAG (message, ZAPI_MESSAGE_METRIC))
288 stream_putl (stream, route_info->cost);
289
290 stream_putw_at (stream, 0, stream_get_endp (stream));
ajs634f9ea2005-04-11 15:51:40 +0000291 zclient_send_message(zclient);
Josh Bailey3f045a02012-03-24 08:35:20 -0700292 SET_FLAG (route_info->flag, ISIS_ROUTE_FLAG_ZEBRA_SYNCED);
293 UNSET_FLAG (route_info->flag, ISIS_ROUTE_FLAG_ZEBRA_RESYNC);
hassof390d2c2004-09-10 20:48:21 +0000294 }
jardineb5d44e2003-12-23 08:09:43 +0000295}
296
hasso92365882005-01-18 13:53:33 +0000297static void
hassof390d2c2004-09-10 20:48:21 +0000298isis_zebra_route_del_ipv4 (struct prefix *prefix,
299 struct isis_route_info *route_info)
jardineb5d44e2003-12-23 08:09:43 +0000300{
301 struct zapi_ipv4 api;
302 struct prefix_ipv4 prefix4;
hassof390d2c2004-09-10 20:48:21 +0000303
304 if (zclient->redist[ZEBRA_ROUTE_ISIS])
305 {
306 api.type = ZEBRA_ROUTE_ISIS;
307 api.flags = 0;
308 api.message = 0;
Avneesh Sachdevaa3b2642012-04-11 23:56:03 -0700309 api.safi = SAFI_UNICAST;
hassof390d2c2004-09-10 20:48:21 +0000310 prefix4.family = AF_INET;
311 prefix4.prefixlen = prefix->prefixlen;
312 prefix4.prefix = prefix->u.prefix4;
313 zapi_ipv4_route (ZEBRA_IPV4_ROUTE_DELETE, zclient, &prefix4, &api);
314 }
Josh Bailey3f045a02012-03-24 08:35:20 -0700315 UNSET_FLAG (route_info->flag, ISIS_ROUTE_FLAG_ZEBRA_SYNCED);
hassof390d2c2004-09-10 20:48:21 +0000316
jardineb5d44e2003-12-23 08:09:43 +0000317 return;
318}
319
320#ifdef HAVE_IPV6
David Lamparterf50ee932015-03-04 07:13:38 +0100321static void
jardineb5d44e2003-12-23 08:09:43 +0000322isis_zebra_route_add_ipv6 (struct prefix *prefix,
hassof390d2c2004-09-10 20:48:21 +0000323 struct isis_route_info *route_info)
jardineb5d44e2003-12-23 08:09:43 +0000324{
325 struct zapi_ipv6 api;
326 struct in6_addr **nexthop_list;
327 unsigned int *ifindex_list;
328 struct isis_nexthop6 *nexthop6;
329 int i, size;
330 struct listnode *node;
331 struct prefix_ipv6 prefix6;
332
Josh Bailey3f045a02012-03-24 08:35:20 -0700333 if (CHECK_FLAG (route_info->flag, ISIS_ROUTE_FLAG_ZEBRA_SYNCED))
jardineb5d44e2003-12-23 08:09:43 +0000334 return;
hassof390d2c2004-09-10 20:48:21 +0000335
jardineb5d44e2003-12-23 08:09:43 +0000336 api.type = ZEBRA_ROUTE_ISIS;
337 api.flags = 0;
338 api.message = 0;
Avneesh Sachdevaa3b2642012-04-11 23:56:03 -0700339 api.safi = SAFI_UNICAST;
jardineb5d44e2003-12-23 08:09:43 +0000340 SET_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP);
341 SET_FLAG (api.message, ZAPI_MESSAGE_IFINDEX);
342 SET_FLAG (api.message, ZAPI_MESSAGE_METRIC);
343 api.metric = route_info->cost;
344#if 0
345 SET_FLAG (api.message, ZAPI_MESSAGE_DISTANCE);
346 api.distance = route_info->depth;
347#endif
348 api.nexthop_num = listcount (route_info->nexthops6);
349 api.ifindex_num = listcount (route_info->nexthops6);
hassof390d2c2004-09-10 20:48:21 +0000350
jardineb5d44e2003-12-23 08:09:43 +0000351 /* allocate memory for nexthop_list */
352 size = sizeof (struct isis_nexthop6 *) * listcount (route_info->nexthops6);
353 nexthop_list = (struct in6_addr **) XMALLOC (MTYPE_ISIS_TMP, size);
hassof390d2c2004-09-10 20:48:21 +0000354 if (!nexthop_list)
355 {
356 zlog_err ("isis_zebra_add_route_ipv6: out of memory!");
357 return;
358 }
359
jardineb5d44e2003-12-23 08:09:43 +0000360 /* allocate memory for ifindex_list */
361 size = sizeof (unsigned int) * listcount (route_info->nexthops6);
362 ifindex_list = (unsigned int *) XMALLOC (MTYPE_ISIS_TMP, size);
hassof390d2c2004-09-10 20:48:21 +0000363 if (!ifindex_list)
364 {
365 zlog_err ("isis_zebra_add_route_ipv6: out of memory!");
366 XFREE (MTYPE_ISIS_TMP, nexthop_list);
367 return;
368 }
369
jardineb5d44e2003-12-23 08:09:43 +0000370 /* for each nexthop */
371 i = 0;
paul1eb8ef22005-04-07 07:30:20 +0000372 for (ALL_LIST_ELEMENTS_RO (route_info->nexthops6, node, nexthop6))
hassof390d2c2004-09-10 20:48:21 +0000373 {
hassof390d2c2004-09-10 20:48:21 +0000374 if (!IN6_IS_ADDR_LINKLOCAL (&nexthop6->ip6) &&
375 !IN6_IS_ADDR_UNSPECIFIED (&nexthop6->ip6))
376 {
377 api.nexthop_num--;
378 api.ifindex_num--;
379 continue;
380 }
381
382 nexthop_list[i] = &nexthop6->ip6;
383 ifindex_list[i] = nexthop6->ifindex;
384 i++;
jardineb5d44e2003-12-23 08:09:43 +0000385 }
hassof390d2c2004-09-10 20:48:21 +0000386
jardineb5d44e2003-12-23 08:09:43 +0000387 api.nexthop = nexthop_list;
388 api.ifindex = ifindex_list;
hassof390d2c2004-09-10 20:48:21 +0000389
390 if (api.nexthop_num && api.ifindex_num)
391 {
392 prefix6.family = AF_INET6;
393 prefix6.prefixlen = prefix->prefixlen;
394 memcpy (&prefix6.prefix, &prefix->u.prefix6, sizeof (struct in6_addr));
395 zapi_ipv6_route (ZEBRA_IPV6_ROUTE_ADD, zclient, &prefix6, &api);
Josh Bailey3f045a02012-03-24 08:35:20 -0700396 SET_FLAG (route_info->flag, ISIS_ROUTE_FLAG_ZEBRA_SYNCED);
397 UNSET_FLAG (route_info->flag, ISIS_ROUTE_FLAG_ZEBRA_RESYNC);
hassof390d2c2004-09-10 20:48:21 +0000398 }
399
jardineb5d44e2003-12-23 08:09:43 +0000400 XFREE (MTYPE_ISIS_TMP, nexthop_list);
401 XFREE (MTYPE_ISIS_TMP, ifindex_list);
hassof390d2c2004-09-10 20:48:21 +0000402
jardineb5d44e2003-12-23 08:09:43 +0000403 return;
404}
405
hasso92365882005-01-18 13:53:33 +0000406static void
hassof390d2c2004-09-10 20:48:21 +0000407isis_zebra_route_del_ipv6 (struct prefix *prefix,
408 struct isis_route_info *route_info)
jardineb5d44e2003-12-23 08:09:43 +0000409{
410 struct zapi_ipv6 api;
411 struct in6_addr **nexthop_list;
412 unsigned int *ifindex_list;
413 struct isis_nexthop6 *nexthop6;
414 int i, size;
415 struct listnode *node;
416 struct prefix_ipv6 prefix6;
417
Josh Bailey3f045a02012-03-24 08:35:20 -0700418 if (CHECK_FLAG (route_info->flag, ISIS_ROUTE_FLAG_ZEBRA_SYNCED))
jardineb5d44e2003-12-23 08:09:43 +0000419 return;
hassof390d2c2004-09-10 20:48:21 +0000420
jardineb5d44e2003-12-23 08:09:43 +0000421 api.type = ZEBRA_ROUTE_ISIS;
422 api.flags = 0;
423 api.message = 0;
Avneesh Sachdevaa3b2642012-04-11 23:56:03 -0700424 api.safi = SAFI_UNICAST;
jardineb5d44e2003-12-23 08:09:43 +0000425 SET_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP);
426 SET_FLAG (api.message, ZAPI_MESSAGE_IFINDEX);
427 api.nexthop_num = listcount (route_info->nexthops6);
428 api.ifindex_num = listcount (route_info->nexthops6);
hassof390d2c2004-09-10 20:48:21 +0000429
jardineb5d44e2003-12-23 08:09:43 +0000430 /* allocate memory for nexthop_list */
431 size = sizeof (struct isis_nexthop6 *) * listcount (route_info->nexthops6);
432 nexthop_list = (struct in6_addr **) XMALLOC (MTYPE_ISIS_TMP, size);
hassof390d2c2004-09-10 20:48:21 +0000433 if (!nexthop_list)
434 {
435 zlog_err ("isis_zebra_route_del_ipv6: out of memory!");
436 return;
437 }
438
jardineb5d44e2003-12-23 08:09:43 +0000439 /* allocate memory for ifindex_list */
440 size = sizeof (unsigned int) * listcount (route_info->nexthops6);
441 ifindex_list = (unsigned int *) XMALLOC (MTYPE_ISIS_TMP, size);
hassof390d2c2004-09-10 20:48:21 +0000442 if (!ifindex_list)
443 {
444 zlog_err ("isis_zebra_route_del_ipv6: out of memory!");
445 XFREE (MTYPE_ISIS_TMP, nexthop_list);
446 return;
447 }
448
jardineb5d44e2003-12-23 08:09:43 +0000449 /* for each nexthop */
450 i = 0;
paul1eb8ef22005-04-07 07:30:20 +0000451 for (ALL_LIST_ELEMENTS_RO (route_info->nexthops6, node, nexthop6))
hassof390d2c2004-09-10 20:48:21 +0000452 {
hassof390d2c2004-09-10 20:48:21 +0000453 if (!IN6_IS_ADDR_LINKLOCAL (&nexthop6->ip6) &&
454 !IN6_IS_ADDR_UNSPECIFIED (&nexthop6->ip6))
455 {
456 api.nexthop_num--;
457 api.ifindex_num--;
458 continue;
459 }
460
461 nexthop_list[i] = &nexthop6->ip6;
462 ifindex_list[i] = nexthop6->ifindex;
463 i++;
jardineb5d44e2003-12-23 08:09:43 +0000464 }
hassof390d2c2004-09-10 20:48:21 +0000465
jardineb5d44e2003-12-23 08:09:43 +0000466 api.nexthop = nexthop_list;
467 api.ifindex = ifindex_list;
jardineb5d44e2003-12-23 08:09:43 +0000468
hassof390d2c2004-09-10 20:48:21 +0000469 if (api.nexthop_num && api.ifindex_num)
470 {
471 prefix6.family = AF_INET6;
472 prefix6.prefixlen = prefix->prefixlen;
473 memcpy (&prefix6.prefix, &prefix->u.prefix6, sizeof (struct in6_addr));
474 zapi_ipv6_route (ZEBRA_IPV6_ROUTE_DELETE, zclient, &prefix6, &api);
Josh Bailey3f045a02012-03-24 08:35:20 -0700475 UNSET_FLAG (route_info->flag, ISIS_ROUTE_FLAG_ZEBRA_SYNCED);
hassof390d2c2004-09-10 20:48:21 +0000476 }
477
478 XFREE (MTYPE_ISIS_TMP, nexthop_list);
479 XFREE (MTYPE_ISIS_TMP, ifindex_list);
480}
jardineb5d44e2003-12-23 08:09:43 +0000481
482#endif /* HAVE_IPV6 */
483
jardineb5d44e2003-12-23 08:09:43 +0000484void
485isis_zebra_route_update (struct prefix *prefix,
hassof390d2c2004-09-10 20:48:21 +0000486 struct isis_route_info *route_info)
jardineb5d44e2003-12-23 08:09:43 +0000487{
488 if (zclient->sock < 0)
489 return;
490
491 if (!zclient->redist[ZEBRA_ROUTE_ISIS])
492 return;
493
hassof390d2c2004-09-10 20:48:21 +0000494 if (CHECK_FLAG (route_info->flag, ISIS_ROUTE_FLAG_ACTIVE))
495 {
496 if (prefix->family == AF_INET)
497 isis_zebra_route_add_ipv4 (prefix, route_info);
jardineb5d44e2003-12-23 08:09:43 +0000498#ifdef HAVE_IPV6
hassof390d2c2004-09-10 20:48:21 +0000499 else if (prefix->family == AF_INET6)
500 isis_zebra_route_add_ipv6 (prefix, route_info);
jardineb5d44e2003-12-23 08:09:43 +0000501#endif /* HAVE_IPV6 */
hassof390d2c2004-09-10 20:48:21 +0000502 }
503 else
504 {
505 if (prefix->family == AF_INET)
506 isis_zebra_route_del_ipv4 (prefix, route_info);
jardineb5d44e2003-12-23 08:09:43 +0000507#ifdef HAVE_IPV6
hassof390d2c2004-09-10 20:48:21 +0000508 else if (prefix->family == AF_INET6)
509 isis_zebra_route_del_ipv6 (prefix, route_info);
jardineb5d44e2003-12-23 08:09:43 +0000510#endif /* HAVE_IPV6 */
hassof390d2c2004-09-10 20:48:21 +0000511 }
jardineb5d44e2003-12-23 08:09:43 +0000512 return;
513}
514
hasso92365882005-01-18 13:53:33 +0000515static int
hassof390d2c2004-09-10 20:48:21 +0000516isis_zebra_read_ipv4 (int command, struct zclient *zclient,
jardineb5d44e2003-12-23 08:09:43 +0000517 zebra_size_t length)
518{
519 struct stream *stream;
520 struct zapi_ipv4 api;
521 struct prefix_ipv4 p;
David Lamparterf50ee932015-03-04 07:13:38 +0100522 unsigned long ifindex __attribute__ ((unused));
523 struct in_addr nexthop __attribute__ ((unused));
jardineb5d44e2003-12-23 08:09:43 +0000524
525 stream = zclient->ibuf;
526 memset (&p, 0, sizeof (struct prefix_ipv4));
527 ifindex = 0;
528
hassof390d2c2004-09-10 20:48:21 +0000529 api.type = stream_getc (stream);
530 api.flags = stream_getc (stream);
jardineb5d44e2003-12-23 08:09:43 +0000531 api.message = stream_getc (stream);
532
533 p.family = AF_INET;
534 p.prefixlen = stream_getc (stream);
535 stream_get (&p.prefix, stream, PSIZE (p.prefixlen));
hassof390d2c2004-09-10 20:48:21 +0000536
537 if (CHECK_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP))
538 {
jardineb5d44e2003-12-23 08:09:43 +0000539 api.nexthop_num = stream_getc (stream);
540 nexthop.s_addr = stream_get_ipv4 (stream);
hassof390d2c2004-09-10 20:48:21 +0000541 }
542 if (CHECK_FLAG (api.message, ZAPI_MESSAGE_IFINDEX))
543 {
544 api.ifindex_num = stream_getc (stream);
545 ifindex = stream_getl (stream);
546 }
jardineb5d44e2003-12-23 08:09:43 +0000547 if (CHECK_FLAG (api.message, ZAPI_MESSAGE_DISTANCE))
548 api.distance = stream_getc (stream);
549 if (CHECK_FLAG (api.message, ZAPI_MESSAGE_METRIC))
550 api.metric = stream_getl (stream);
551 else
552 api.metric = 0;
hassof390d2c2004-09-10 20:48:21 +0000553
554 if (command == ZEBRA_IPV4_ROUTE_ADD)
555 {
hassoc89c05d2005-09-04 21:36:36 +0000556 if (isis->debugs & DEBUG_ZEBRA)
557 zlog_debug ("IPv4 Route add from Z");
hassof390d2c2004-09-10 20:48:21 +0000558 }
jardineb5d44e2003-12-23 08:09:43 +0000559
560 return 0;
561}
562
Paul Jakma41b36e92006-12-08 01:09:50 +0000563#ifdef HAVE_IPV6
hasso92365882005-01-18 13:53:33 +0000564static int
hassof390d2c2004-09-10 20:48:21 +0000565isis_zebra_read_ipv6 (int command, struct zclient *zclient,
jardineb5d44e2003-12-23 08:09:43 +0000566 zebra_size_t length)
567{
jardineb5d44e2003-12-23 08:09:43 +0000568 return 0;
569}
Paul Jakma41b36e92006-12-08 01:09:50 +0000570#endif
jardineb5d44e2003-12-23 08:09:43 +0000571
572#define ISIS_TYPE_IS_REDISTRIBUTED(T) \
573T == ZEBRA_ROUTE_MAX ? zclient->default_information : zclient->redist[type]
574
575int
576isis_distribute_list_update (int routetype)
577{
578 return 0;
579}
580
hasso92365882005-01-18 13:53:33 +0000581#if 0 /* Not yet. */
582static int
hassof390d2c2004-09-10 20:48:21 +0000583isis_redistribute_default_set (int routetype, int metric_type,
584 int metric_value)
jardineb5d44e2003-12-23 08:09:43 +0000585{
586 return 0;
587}
hasso92365882005-01-18 13:53:33 +0000588#endif /* 0 */
jardineb5d44e2003-12-23 08:09:43 +0000589
jardineb5d44e2003-12-23 08:09:43 +0000590void
591isis_zebra_init ()
592{
jardineb5d44e2003-12-23 08:09:43 +0000593 zclient = zclient_new ();
594 zclient_init (zclient, ZEBRA_ROUTE_ISIS);
hasso18a6dce2004-10-03 18:18:34 +0000595 zclient->router_id_update = isis_router_id_update_zebra;
jardineb5d44e2003-12-23 08:09:43 +0000596 zclient->interface_add = isis_zebra_if_add;
597 zclient->interface_delete = isis_zebra_if_del;
598 zclient->interface_up = isis_zebra_if_state_up;
599 zclient->interface_down = isis_zebra_if_state_down;
600 zclient->interface_address_add = isis_zebra_if_address_add;
601 zclient->interface_address_delete = isis_zebra_if_address_del;
602 zclient->ipv4_route_add = isis_zebra_read_ipv4;
603 zclient->ipv4_route_delete = isis_zebra_read_ipv4;
604#ifdef HAVE_IPV6
605 zclient->ipv6_route_add = isis_zebra_read_ipv6;
606 zclient->ipv6_route_delete = isis_zebra_read_ipv6;
607#endif /* HAVE_IPV6 */
608
609 return;
610}