]> git.proxmox.com Git - mirror_frr.git/blob - isisd/isis_zebra.c
isisd: isisd-warnings.patch
[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 *
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>
24
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
36 #include "isisd/dict.h"
37 #include "isisd/isis_constants.h"
38 #include "isisd/isis_common.h"
39 #include "isisd/isis_flags.h"
40 #include "isisd/isis_misc.h"
41 #include "isisd/isis_circuit.h"
42 #include "isisd/isis_tlv.h"
43 #include "isisd/isisd.h"
44 #include "isisd/isis_circuit.h"
45 #include "isisd/isis_csm.h"
46 #include "isisd/isis_lsp.h"
47 #include "isisd/isis_route.h"
48 #include "isisd/isis_zebra.h"
49
50 struct zclient *zclient = NULL;
51
52 /* Router-id update message from zebra. */
53 static int
54 isis_router_id_update_zebra (int command, struct zclient *zclient,
55 zebra_size_t length)
56 {
57 struct isis_area *area;
58 struct listnode *node;
59 struct prefix router_id;
60
61 zebra_router_id_update_read (zclient->ibuf, &router_id);
62 if (isis->router_id == router_id.u.prefix4.s_addr)
63 return 0;
64
65 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
70 return 0;
71 }
72
73 static int
74 isis_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);
79
80 if (isis->debugs & DEBUG_ZEBRA)
81 zlog_debug ("Zebra I/F add: %s index %d flags %ld metric %d mtu %d",
82 ifp->name, ifp->ifindex, (long)ifp->flags, ifp->metric, ifp->mtu);
83
84 if (if_is_operative (ifp))
85 isis_csm_state_change (IF_UP_FROM_Z, circuit_scan_by_ifp (ifp), ifp);
86
87 return 0;
88 }
89
90 static int
91 isis_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);
98
99 if (!ifp)
100 return 0;
101
102 if (if_is_operative (ifp))
103 zlog_warn ("Zebra: got delete of %s, but interface is still up",
104 ifp->name);
105
106 if (isis->debugs & DEBUG_ZEBRA)
107 zlog_debug ("Zebra I/F delete: %s index %d flags %ld metric %d mtu %d",
108 ifp->name, ifp->ifindex, (long)ifp->flags, ifp->metric, ifp->mtu);
109
110 isis_csm_state_change (IF_DOWN_FROM_Z, circuit_scan_by_ifp (ifp), ifp);
111
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);
115
116 ifp->ifindex = IFINDEX_INTERNAL;
117
118 return 0;
119 }
120
121 static int
122 isis_zebra_if_state_up (int command, struct zclient *zclient,
123 zebra_size_t length)
124 {
125 struct interface *ifp;
126
127 ifp = zebra_interface_state_read (zclient->ibuf);
128
129 if (ifp == NULL)
130 return 0;
131
132 isis_csm_state_change (IF_UP_FROM_Z, circuit_scan_by_ifp (ifp), ifp);
133
134 return 0;
135 }
136
137 static int
138 isis_zebra_if_state_down (int command, struct zclient *zclient,
139 zebra_size_t length)
140 {
141 struct interface *ifp;
142 struct isis_circuit *circuit;
143
144 ifp = zebra_interface_state_read (zclient->ibuf);
145
146 if (ifp == NULL)
147 return 0;
148
149 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);
153
154 return 0;
155 }
156
157 static int
158 isis_zebra_if_address_add (int command, struct zclient *zclient,
159 zebra_size_t length)
160 {
161 struct connected *c;
162 struct prefix *p;
163 char buf[BUFSIZ];
164
165 c = zebra_interface_address_read (ZEBRA_INTERFACE_ADDRESS_ADD,
166 zclient->ibuf);
167
168 if (c == NULL)
169 return 0;
170
171 p = c->address;
172
173 prefix2str (p, buf, BUFSIZ);
174 #ifdef EXTREME_DEBUG
175 if (p->family == AF_INET)
176 zlog_debug ("connected IP address %s", buf);
177 #ifdef HAVE_IPV6
178 if (p->family == AF_INET6)
179 zlog_debug ("connected IPv6 address %s", buf);
180 #endif /* HAVE_IPV6 */
181 #endif /* EXTREME_DEBUG */
182 if (if_is_operative (c->ifp))
183 isis_circuit_add_addr (circuit_scan_by_ifp (c->ifp), c);
184
185 return 0;
186 }
187
188 static int
189 isis_zebra_if_address_del (int command, struct zclient *client,
190 zebra_size_t length)
191 {
192 struct connected *c;
193 struct interface *ifp;
194 #ifdef EXTREME_DEBUG
195 struct prefix *p;
196 u_char buf[BUFSIZ];
197 #endif /* EXTREME_DEBUG */
198
199 c = zebra_interface_address_read (ZEBRA_INTERFACE_ADDRESS_DELETE,
200 zclient->ibuf);
201
202 if (c == NULL)
203 return 0;
204
205 ifp = c->ifp;
206
207 #ifdef EXTREME_DEBUG
208 p = c->address;
209 prefix2str (p, buf, BUFSIZ);
210
211 if (p->family == AF_INET)
212 zlog_debug ("disconnected IP address %s", buf);
213 #ifdef HAVE_IPV6
214 if (p->family == AF_INET6)
215 zlog_debug ("disconnected IPv6 address %s", buf);
216 #endif /* HAVE_IPV6 */
217 #endif /* EXTREME_DEBUG */
218
219 if (if_is_operative (ifp))
220 isis_circuit_del_addr (circuit_scan_by_ifp (ifp), c);
221 connected_free (c);
222
223 return 0;
224 }
225
226 static void
227 isis_zebra_route_add_ipv4 (struct prefix *prefix,
228 struct isis_route_info *route_info)
229 {
230 u_char message, flags;
231 int psize;
232 struct stream *stream;
233 struct isis_nexthop *nexthop;
234 struct listnode *node;
235
236 if (CHECK_FLAG (route_info->flag, ISIS_ROUTE_FLAG_ZEBRA_SYNCED))
237 return;
238
239 if (zclient->redist[AFI_IP][ZEBRA_ROUTE_ISIS].enabled)
240 {
241 message = 0;
242 flags = 0;
243
244 SET_FLAG (message, ZAPI_MESSAGE_NEXTHOP);
245 SET_FLAG (message, ZAPI_MESSAGE_METRIC);
246 #if 0
247 SET_FLAG (message, ZAPI_MESSAGE_DISTANCE);
248 #endif
249
250 stream = zclient->obuf;
251 stream_reset (stream);
252 zclient_create_header (stream, ZEBRA_IPV4_ROUTE_ADD);
253 /* type */
254 stream_putc (stream, ZEBRA_ROUTE_ISIS);
255 /* instance */
256 stream_putw (stream, 0);
257 /* flags */
258 stream_putc (stream, flags);
259 /* message */
260 stream_putc (stream, message);
261 /* SAFI */
262 stream_putw (stream, SAFI_UNICAST);
263 /* prefix information */
264 psize = PSIZE (prefix->prefixlen);
265 stream_putc (stream, prefix->prefixlen);
266 stream_write (stream, (u_char *) & prefix->u.prefix4, psize);
267
268 stream_putc (stream, listcount (route_info->nexthops));
269
270 /* Nexthop, ifindex, distance and metric information */
271 for (ALL_LIST_ELEMENTS_RO (route_info->nexthops, node, nexthop))
272 {
273 /* FIXME: can it be ? */
274 if (nexthop->ip.s_addr != INADDR_ANY)
275 {
276 stream_putc (stream, ZEBRA_NEXTHOP_IPV4);
277 stream_put_in_addr (stream, &nexthop->ip);
278 }
279 else
280 {
281 stream_putc (stream, ZEBRA_NEXTHOP_IFINDEX);
282 stream_putl (stream, nexthop->ifindex);
283 }
284 }
285 #if 0
286 if (CHECK_FLAG (message, ZAPI_MESSAGE_DISTANCE))
287 stream_putc (stream, route_info->depth);
288 #endif
289 if (CHECK_FLAG (message, ZAPI_MESSAGE_METRIC))
290 stream_putl (stream, route_info->cost);
291
292 stream_putw_at (stream, 0, stream_get_endp (stream));
293 zclient_send_message(zclient);
294 SET_FLAG (route_info->flag, ISIS_ROUTE_FLAG_ZEBRA_SYNCED);
295 UNSET_FLAG (route_info->flag, ISIS_ROUTE_FLAG_ZEBRA_RESYNC);
296 }
297 }
298
299 static void
300 isis_zebra_route_del_ipv4 (struct prefix *prefix,
301 struct isis_route_info *route_info)
302 {
303 struct zapi_ipv4 api;
304 struct prefix_ipv4 prefix4;
305
306 if (zclient->redist[AFI_IP][ZEBRA_ROUTE_ISIS].enabled)
307 {
308 api.type = ZEBRA_ROUTE_ISIS;
309 api.instance = 0;
310 api.flags = 0;
311 api.message = 0;
312 api.safi = SAFI_UNICAST;
313 prefix4.family = AF_INET;
314 prefix4.prefixlen = prefix->prefixlen;
315 prefix4.prefix = prefix->u.prefix4;
316 zapi_ipv4_route (ZEBRA_IPV4_ROUTE_DELETE, zclient, &prefix4, &api);
317 }
318 UNSET_FLAG (route_info->flag, ISIS_ROUTE_FLAG_ZEBRA_SYNCED);
319
320 return;
321 }
322
323 #ifdef HAVE_IPV6
324 static void
325 isis_zebra_route_add_ipv6 (struct prefix *prefix,
326 struct isis_route_info *route_info)
327 {
328 struct zapi_ipv6 api;
329 struct in6_addr **nexthop_list;
330 unsigned int *ifindex_list;
331 struct isis_nexthop6 *nexthop6;
332 int i, size;
333 struct listnode *node;
334 struct prefix_ipv6 prefix6;
335
336 if (CHECK_FLAG (route_info->flag, ISIS_ROUTE_FLAG_ZEBRA_SYNCED))
337 return;
338
339 api.type = ZEBRA_ROUTE_ISIS;
340 api.instance = 0;
341 api.flags = 0;
342 api.message = 0;
343 api.safi = SAFI_UNICAST;
344 SET_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP);
345 SET_FLAG (api.message, ZAPI_MESSAGE_IFINDEX);
346 SET_FLAG (api.message, ZAPI_MESSAGE_METRIC);
347 api.metric = route_info->cost;
348 #if 0
349 SET_FLAG (api.message, ZAPI_MESSAGE_DISTANCE);
350 api.distance = route_info->depth;
351 #endif
352 api.nexthop_num = listcount (route_info->nexthops6);
353 api.ifindex_num = listcount (route_info->nexthops6);
354
355 /* allocate memory for nexthop_list */
356 size = sizeof (struct isis_nexthop6 *) * listcount (route_info->nexthops6);
357 nexthop_list = (struct in6_addr **) XMALLOC (MTYPE_ISIS_TMP, size);
358 if (!nexthop_list)
359 {
360 zlog_err ("isis_zebra_add_route_ipv6: out of memory!");
361 return;
362 }
363
364 /* allocate memory for ifindex_list */
365 size = sizeof (unsigned int) * listcount (route_info->nexthops6);
366 ifindex_list = (unsigned int *) XMALLOC (MTYPE_ISIS_TMP, size);
367 if (!ifindex_list)
368 {
369 zlog_err ("isis_zebra_add_route_ipv6: out of memory!");
370 XFREE (MTYPE_ISIS_TMP, nexthop_list);
371 return;
372 }
373
374 /* for each nexthop */
375 i = 0;
376 for (ALL_LIST_ELEMENTS_RO (route_info->nexthops6, node, nexthop6))
377 {
378 if (!IN6_IS_ADDR_LINKLOCAL (&nexthop6->ip6) &&
379 !IN6_IS_ADDR_UNSPECIFIED (&nexthop6->ip6))
380 {
381 api.nexthop_num--;
382 api.ifindex_num--;
383 continue;
384 }
385
386 nexthop_list[i] = &nexthop6->ip6;
387 ifindex_list[i] = nexthop6->ifindex;
388 i++;
389 }
390
391 api.nexthop = nexthop_list;
392 api.ifindex = ifindex_list;
393
394 if (api.nexthop_num && api.ifindex_num)
395 {
396 prefix6.family = AF_INET6;
397 prefix6.prefixlen = prefix->prefixlen;
398 memcpy (&prefix6.prefix, &prefix->u.prefix6, sizeof (struct in6_addr));
399 zapi_ipv6_route (ZEBRA_IPV6_ROUTE_ADD, zclient, &prefix6, &api);
400 SET_FLAG (route_info->flag, ISIS_ROUTE_FLAG_ZEBRA_SYNCED);
401 UNSET_FLAG (route_info->flag, ISIS_ROUTE_FLAG_ZEBRA_RESYNC);
402 }
403
404 XFREE (MTYPE_ISIS_TMP, nexthop_list);
405 XFREE (MTYPE_ISIS_TMP, ifindex_list);
406
407 return;
408 }
409
410 static void
411 isis_zebra_route_del_ipv6 (struct prefix *prefix,
412 struct isis_route_info *route_info)
413 {
414 struct zapi_ipv6 api;
415 struct in6_addr **nexthop_list;
416 unsigned int *ifindex_list;
417 struct isis_nexthop6 *nexthop6;
418 int i, size;
419 struct listnode *node;
420 struct prefix_ipv6 prefix6;
421
422 if (CHECK_FLAG (route_info->flag, ISIS_ROUTE_FLAG_ZEBRA_SYNCED))
423 return;
424
425 api.type = ZEBRA_ROUTE_ISIS;
426 api.instance = 0;
427 api.flags = 0;
428 api.message = 0;
429 api.safi = SAFI_UNICAST;
430 SET_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP);
431 SET_FLAG (api.message, ZAPI_MESSAGE_IFINDEX);
432 api.nexthop_num = listcount (route_info->nexthops6);
433 api.ifindex_num = listcount (route_info->nexthops6);
434
435 /* allocate memory for nexthop_list */
436 size = sizeof (struct isis_nexthop6 *) * listcount (route_info->nexthops6);
437 nexthop_list = (struct in6_addr **) XMALLOC (MTYPE_ISIS_TMP, size);
438 if (!nexthop_list)
439 {
440 zlog_err ("isis_zebra_route_del_ipv6: out of memory!");
441 return;
442 }
443
444 /* allocate memory for ifindex_list */
445 size = sizeof (unsigned int) * listcount (route_info->nexthops6);
446 ifindex_list = (unsigned int *) XMALLOC (MTYPE_ISIS_TMP, size);
447 if (!ifindex_list)
448 {
449 zlog_err ("isis_zebra_route_del_ipv6: out of memory!");
450 XFREE (MTYPE_ISIS_TMP, nexthop_list);
451 return;
452 }
453
454 /* for each nexthop */
455 i = 0;
456 for (ALL_LIST_ELEMENTS_RO (route_info->nexthops6, node, nexthop6))
457 {
458 if (!IN6_IS_ADDR_LINKLOCAL (&nexthop6->ip6) &&
459 !IN6_IS_ADDR_UNSPECIFIED (&nexthop6->ip6))
460 {
461 api.nexthop_num--;
462 api.ifindex_num--;
463 continue;
464 }
465
466 nexthop_list[i] = &nexthop6->ip6;
467 ifindex_list[i] = nexthop6->ifindex;
468 i++;
469 }
470
471 api.nexthop = nexthop_list;
472 api.ifindex = ifindex_list;
473
474 if (api.nexthop_num && api.ifindex_num)
475 {
476 prefix6.family = AF_INET6;
477 prefix6.prefixlen = prefix->prefixlen;
478 memcpy (&prefix6.prefix, &prefix->u.prefix6, sizeof (struct in6_addr));
479 zapi_ipv6_route (ZEBRA_IPV6_ROUTE_DELETE, zclient, &prefix6, &api);
480 UNSET_FLAG (route_info->flag, ISIS_ROUTE_FLAG_ZEBRA_SYNCED);
481 }
482
483 XFREE (MTYPE_ISIS_TMP, nexthop_list);
484 XFREE (MTYPE_ISIS_TMP, ifindex_list);
485 }
486
487 #endif /* HAVE_IPV6 */
488
489 void
490 isis_zebra_route_update (struct prefix *prefix,
491 struct isis_route_info *route_info)
492 {
493 if (zclient->sock < 0)
494 return;
495
496 if ((prefix->family == AF_INET && !zclient->redist[AFI_IP][ZEBRA_ROUTE_ISIS].enabled) ||
497 (prefix->family == AF_INET6 && !zclient->redist[AFI_IP6][ZEBRA_ROUTE_ISIS].enabled))
498 return;
499
500 if (CHECK_FLAG (route_info->flag, ISIS_ROUTE_FLAG_ACTIVE))
501 {
502 if (prefix->family == AF_INET)
503 isis_zebra_route_add_ipv4 (prefix, route_info);
504 #ifdef HAVE_IPV6
505 else if (prefix->family == AF_INET6)
506 isis_zebra_route_add_ipv6 (prefix, route_info);
507 #endif /* HAVE_IPV6 */
508 }
509 else
510 {
511 if (prefix->family == AF_INET)
512 isis_zebra_route_del_ipv4 (prefix, route_info);
513 #ifdef HAVE_IPV6
514 else if (prefix->family == AF_INET6)
515 isis_zebra_route_del_ipv6 (prefix, route_info);
516 #endif /* HAVE_IPV6 */
517 }
518 return;
519 }
520
521 static int
522 isis_zebra_read_ipv4 (int command, struct zclient *zclient,
523 zebra_size_t length)
524 {
525 struct stream *stream;
526 struct zapi_ipv4 api;
527 struct prefix_ipv4 p;
528
529 stream = zclient->ibuf;
530 memset (&p, 0, sizeof (struct prefix_ipv4));
531
532 api.type = stream_getc (stream);
533 api.instance = stream_getw (stream);
534 api.flags = stream_getc (stream);
535 api.message = stream_getc (stream);
536
537 p.family = AF_INET;
538 p.prefixlen = stream_getc (stream);
539 stream_get (&p.prefix, stream, PSIZE (p.prefixlen));
540
541 if (CHECK_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP))
542 {
543 api.nexthop_num = stream_getc (stream);
544 (void)stream_get_ipv4 (stream);
545 }
546 if (CHECK_FLAG (api.message, ZAPI_MESSAGE_IFINDEX))
547 {
548 api.ifindex_num = stream_getc (stream);
549 stream_getl (stream);
550 }
551 if (CHECK_FLAG (api.message, ZAPI_MESSAGE_DISTANCE))
552 api.distance = stream_getc (stream);
553 if (CHECK_FLAG (api.message, ZAPI_MESSAGE_METRIC))
554 api.metric = stream_getl (stream);
555 else
556 api.metric = 0;
557
558 if (command == ZEBRA_IPV4_ROUTE_ADD)
559 {
560 if (isis->debugs & DEBUG_ZEBRA)
561 zlog_debug ("IPv4 Route add from Z");
562 }
563
564 return 0;
565 }
566
567 #ifdef HAVE_IPV6
568 static int
569 isis_zebra_read_ipv6 (int command, struct zclient *zclient,
570 zebra_size_t length)
571 {
572 return 0;
573 }
574 #endif
575
576 #define ISIS_TYPE_IS_REDISTRIBUTED(T) \
577 T == ZEBRA_ROUTE_MAX ? zclient->default_information : \
578 (zclient->redist[AFI_IP][type].enabled || client->redist[AFI_IP6][type].enabled)
579
580 int
581 isis_distribute_list_update (int routetype)
582 {
583 return 0;
584 }
585
586 #if 0 /* Not yet. */
587 static int
588 isis_redistribute_default_set (int routetype, int metric_type,
589 int metric_value)
590 {
591 return 0;
592 }
593 #endif /* 0 */
594
595 void
596 isis_zebra_init ()
597 {
598 zclient = zclient_new ();
599 zclient_init (zclient, ZEBRA_ROUTE_ISIS, 0);
600 zclient->router_id_update = isis_router_id_update_zebra;
601 zclient->interface_add = isis_zebra_if_add;
602 zclient->interface_delete = isis_zebra_if_del;
603 zclient->interface_up = isis_zebra_if_state_up;
604 zclient->interface_down = isis_zebra_if_state_down;
605 zclient->interface_address_add = isis_zebra_if_address_add;
606 zclient->interface_address_delete = isis_zebra_if_address_del;
607 zclient->ipv4_route_add = isis_zebra_read_ipv4;
608 zclient->ipv4_route_delete = isis_zebra_read_ipv4;
609 #ifdef HAVE_IPV6
610 zclient->ipv6_route_add = isis_zebra_read_ipv6;
611 zclient->ipv6_route_delete = isis_zebra_read_ipv6;
612 #endif /* HAVE_IPV6 */
613
614 return;
615 }