2 * IS-IS Rout(e)ing protocol - isis_zebra.c
4 * Copyright (C) 2001,2002 Sampo Saaristo
5 * Tampere University of Technology
6 * Institute of Communications Engineering
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)
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
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.
36 #include "isisd/dict.h"
37 #include "isisd/isis_constants.h"
38 #include "isisd/isis_common.h"
39 #include "isisd/isisd.h"
40 #include "isisd/isis_circuit.h"
41 #include "isisd/isis_csm.h"
42 #include "isisd/isis_route.h"
43 #include "isisd/isis_zebra.h"
45 struct zclient
*zclient
= NULL
;
47 extern struct thread_master
*master
;
48 extern struct isis
*isis
;
50 struct in_addr router_id_zebra
;
52 /* Router-id update message from zebra. */
54 isis_router_id_update_zebra (int command
, struct zclient
*zclient
,
57 struct prefix router_id
;
59 zebra_router_id_update_read (zclient
->ibuf
,&router_id
);
60 router_id_zebra
= router_id
.u
.prefix4
;
62 /* FIXME: Do we react somehow? */
67 isis_zebra_if_add (int command
, struct zclient
*zclient
, zebra_size_t length
)
69 struct interface
*ifp
;
71 ifp
= zebra_interface_add_read (zclient
->ibuf
);
73 if (isis
->debugs
& DEBUG_ZEBRA
)
74 zlog_debug ("Zebra I/F add: %s index %d flags %ld metric %d mtu %d",
75 ifp
->name
, ifp
->ifindex
, (long)ifp
->flags
, ifp
->metric
, ifp
->mtu
);
77 if (if_is_operative (ifp
))
78 isis_csm_state_change (IF_UP_FROM_Z
, circuit_scan_by_ifp (ifp
), ifp
);
84 isis_zebra_if_del (int command
, struct zclient
*zclient
, zebra_size_t length
)
86 struct interface
*ifp
;
90 ifp
= zebra_interface_state_read (s
);
95 if (if_is_operative (ifp
))
96 zlog_warn ("Zebra: got delete of %s, but interface is still up",
99 if (isis
->debugs
& DEBUG_ZEBRA
)
100 zlog_debug ("Zebra I/F delete: %s index %d flags %ld metric %d mtu %d",
101 ifp
->name
, ifp
->ifindex
, (long)ifp
->flags
, ifp
->metric
, ifp
->mtu
);
104 /* Cannot call if_delete because we should retain the pseudo interface
105 in case there is configuration info attached to it. */
106 if_delete_retain(ifp
);
108 isis_csm_state_change (IF_DOWN_FROM_Z
, circuit_scan_by_ifp (ifp
), ifp
);
110 ifp
->ifindex
= IFINDEX_INTERNAL
;
115 static struct interface
*
116 zebra_interface_if_lookup (struct stream
*s
)
118 char ifname_tmp
[INTERFACE_NAMSIZ
];
120 /* Read interface name. */
121 stream_get (ifname_tmp
, s
, INTERFACE_NAMSIZ
);
123 /* And look it up. */
124 return if_lookup_by_name_len(ifname_tmp
,
125 strnlen(ifname_tmp
, INTERFACE_NAMSIZ
));
129 isis_zebra_if_state_up (int command
, struct zclient
*zclient
,
132 struct interface
*ifp
;
134 ifp
= zebra_interface_if_lookup (zclient
->ibuf
);
139 if (if_is_operative (ifp
))
141 zebra_interface_if_set_value (zclient
->ibuf
, ifp
);
142 /* HT: This is wrong actually. We can't assume that circuit exist
143 * if we delete circuit during if_state_down event. Needs rethink.
145 isis_circuit_update_params (circuit_scan_by_ifp (ifp
), ifp
);
149 zebra_interface_if_set_value (zclient
->ibuf
, ifp
);
150 isis_csm_state_change (IF_UP_FROM_Z
, circuit_scan_by_ifp (ifp
), ifp
);
156 isis_zebra_if_state_down (int command
, struct zclient
*zclient
,
159 struct interface
*ifp
;
161 ifp
= zebra_interface_if_lookup (zclient
->ibuf
);
166 if (if_is_operative (ifp
))
168 zebra_interface_if_set_value (zclient
->ibuf
, ifp
);
169 isis_csm_state_change (IF_DOWN_FROM_Z
, circuit_scan_by_ifp (ifp
), ifp
);
176 isis_zebra_if_address_add (int command
, struct zclient
*zclient
,
183 c
= zebra_interface_address_read (ZEBRA_INTERFACE_ADDRESS_ADD
,
191 prefix2str (p
, buf
, BUFSIZ
);
193 if (p
->family
== AF_INET
)
194 zlog_debug ("connected IP address %s", buf
);
196 if (p
->family
== AF_INET6
)
197 zlog_debug ("connected IPv6 address %s", buf
);
198 #endif /* HAVE_IPV6 */
199 #endif /* EXTREME_DEBUG */
200 if (if_is_operative (c
->ifp
))
201 isis_circuit_add_addr (circuit_scan_by_ifp (c
->ifp
), c
);
207 isis_zebra_if_address_del (int command
, struct zclient
*client
,
211 struct interface
*ifp
;
215 #endif /* EXTREME_DEBUG */
217 c
= zebra_interface_address_read (ZEBRA_INTERFACE_ADDRESS_DELETE
,
227 prefix2str (p
, buf
, BUFSIZ
);
229 if (p
->family
== AF_INET
)
230 zlog_debug ("disconnected IP address %s", buf
);
232 if (p
->family
== AF_INET6
)
233 zlog_debug ("disconnected IPv6 address %s", buf
);
234 #endif /* HAVE_IPV6 */
235 #endif /* EXTREME_DEBUG */
237 if (if_is_operative (ifp
))
238 isis_circuit_del_addr (circuit_scan_by_ifp (ifp
), c
);
245 isis_zebra_route_add_ipv4 (struct prefix
*prefix
,
246 struct isis_route_info
*route_info
)
248 u_char message
, flags
;
250 struct stream
*stream
;
251 struct isis_nexthop
*nexthop
;
252 struct listnode
*node
;
254 if (CHECK_FLAG (route_info
->flag
, ISIS_ROUTE_FLAG_ZEBRA_SYNC
))
257 if (zclient
->redist
[ZEBRA_ROUTE_ISIS
])
262 SET_FLAG (message
, ZAPI_MESSAGE_NEXTHOP
);
263 SET_FLAG (message
, ZAPI_MESSAGE_METRIC
);
265 SET_FLAG (message
, ZAPI_MESSAGE_DISTANCE
);
268 stream
= zclient
->obuf
;
269 stream_reset (stream
);
270 zclient_create_header (stream
, ZEBRA_IPV4_ROUTE_ADD
);
272 stream_putc (stream
, ZEBRA_ROUTE_ISIS
);
274 stream_putc (stream
, flags
);
276 stream_putc (stream
, message
);
277 /* prefix information */
278 psize
= PSIZE (prefix
->prefixlen
);
279 stream_putc (stream
, prefix
->prefixlen
);
280 stream_write (stream
, (u_char
*) & prefix
->u
.prefix4
, psize
);
282 stream_putc (stream
, listcount (route_info
->nexthops
));
284 /* Nexthop, ifindex, distance and metric information */
285 for (ALL_LIST_ELEMENTS_RO (route_info
->nexthops
, node
, nexthop
))
287 /* FIXME: can it be ? */
288 if (nexthop
->ip
.s_addr
!= INADDR_ANY
)
290 stream_putc (stream
, ZEBRA_NEXTHOP_IPV4
);
291 stream_put_in_addr (stream
, &nexthop
->ip
);
295 stream_putc (stream
, ZEBRA_NEXTHOP_IFINDEX
);
296 stream_putl (stream
, nexthop
->ifindex
);
300 if (CHECK_FLAG (message
, ZAPI_MESSAGE_DISTANCE
))
301 stream_putc (stream
, route_info
->depth
);
303 if (CHECK_FLAG (message
, ZAPI_MESSAGE_METRIC
))
304 stream_putl (stream
, route_info
->cost
);
306 stream_putw_at (stream
, 0, stream_get_endp (stream
));
307 zclient_send_message(zclient
);
308 SET_FLAG (route_info
->flag
, ISIS_ROUTE_FLAG_ZEBRA_SYNC
);
313 isis_zebra_route_del_ipv4 (struct prefix
*prefix
,
314 struct isis_route_info
*route_info
)
316 struct zapi_ipv4 api
;
317 struct prefix_ipv4 prefix4
;
319 if (zclient
->redist
[ZEBRA_ROUTE_ISIS
])
321 api
.type
= ZEBRA_ROUTE_ISIS
;
324 prefix4
.family
= AF_INET
;
325 prefix4
.prefixlen
= prefix
->prefixlen
;
326 prefix4
.prefix
= prefix
->u
.prefix4
;
327 zapi_ipv4_route (ZEBRA_IPV4_ROUTE_DELETE
, zclient
, &prefix4
, &api
);
329 UNSET_FLAG (route_info
->flag
, ISIS_ROUTE_FLAG_ZEBRA_SYNC
);
336 isis_zebra_route_add_ipv6 (struct prefix
*prefix
,
337 struct isis_route_info
*route_info
)
339 struct zapi_ipv6 api
;
340 struct in6_addr
**nexthop_list
;
341 unsigned int *ifindex_list
;
342 struct isis_nexthop6
*nexthop6
;
344 struct listnode
*node
;
345 struct prefix_ipv6 prefix6
;
347 if (CHECK_FLAG (route_info
->flag
, ISIS_ROUTE_FLAG_ZEBRA_SYNC
))
350 api
.type
= ZEBRA_ROUTE_ISIS
;
353 SET_FLAG (api
.message
, ZAPI_MESSAGE_NEXTHOP
);
354 SET_FLAG (api
.message
, ZAPI_MESSAGE_IFINDEX
);
355 SET_FLAG (api
.message
, ZAPI_MESSAGE_METRIC
);
356 api
.metric
= route_info
->cost
;
358 SET_FLAG (api
.message
, ZAPI_MESSAGE_DISTANCE
);
359 api
.distance
= route_info
->depth
;
361 api
.nexthop_num
= listcount (route_info
->nexthops6
);
362 api
.ifindex_num
= listcount (route_info
->nexthops6
);
364 /* allocate memory for nexthop_list */
365 size
= sizeof (struct isis_nexthop6
*) * listcount (route_info
->nexthops6
);
366 nexthop_list
= (struct in6_addr
**) XMALLOC (MTYPE_ISIS_TMP
, size
);
369 zlog_err ("isis_zebra_add_route_ipv6: out of memory!");
373 /* allocate memory for ifindex_list */
374 size
= sizeof (unsigned int) * listcount (route_info
->nexthops6
);
375 ifindex_list
= (unsigned int *) XMALLOC (MTYPE_ISIS_TMP
, size
);
378 zlog_err ("isis_zebra_add_route_ipv6: out of memory!");
379 XFREE (MTYPE_ISIS_TMP
, nexthop_list
);
383 /* for each nexthop */
385 for (ALL_LIST_ELEMENTS_RO (route_info
->nexthops6
, node
, nexthop6
))
387 if (!IN6_IS_ADDR_LINKLOCAL (&nexthop6
->ip6
) &&
388 !IN6_IS_ADDR_UNSPECIFIED (&nexthop6
->ip6
))
395 nexthop_list
[i
] = &nexthop6
->ip6
;
396 ifindex_list
[i
] = nexthop6
->ifindex
;
400 api
.nexthop
= nexthop_list
;
401 api
.ifindex
= ifindex_list
;
403 if (api
.nexthop_num
&& api
.ifindex_num
)
405 prefix6
.family
= AF_INET6
;
406 prefix6
.prefixlen
= prefix
->prefixlen
;
407 memcpy (&prefix6
.prefix
, &prefix
->u
.prefix6
, sizeof (struct in6_addr
));
408 zapi_ipv6_route (ZEBRA_IPV6_ROUTE_ADD
, zclient
, &prefix6
, &api
);
409 SET_FLAG (route_info
->flag
, ISIS_ROUTE_FLAG_ZEBRA_SYNC
);
412 XFREE (MTYPE_ISIS_TMP
, nexthop_list
);
413 XFREE (MTYPE_ISIS_TMP
, ifindex_list
);
419 isis_zebra_route_del_ipv6 (struct prefix
*prefix
,
420 struct isis_route_info
*route_info
)
422 struct zapi_ipv6 api
;
423 struct in6_addr
**nexthop_list
;
424 unsigned int *ifindex_list
;
425 struct isis_nexthop6
*nexthop6
;
427 struct listnode
*node
;
428 struct prefix_ipv6 prefix6
;
430 if (CHECK_FLAG (route_info
->flag
, ISIS_ROUTE_FLAG_ZEBRA_SYNC
))
433 api
.type
= ZEBRA_ROUTE_ISIS
;
436 SET_FLAG (api
.message
, ZAPI_MESSAGE_NEXTHOP
);
437 SET_FLAG (api
.message
, ZAPI_MESSAGE_IFINDEX
);
438 api
.nexthop_num
= listcount (route_info
->nexthops6
);
439 api
.ifindex_num
= listcount (route_info
->nexthops6
);
441 /* allocate memory for nexthop_list */
442 size
= sizeof (struct isis_nexthop6
*) * listcount (route_info
->nexthops6
);
443 nexthop_list
= (struct in6_addr
**) XMALLOC (MTYPE_ISIS_TMP
, size
);
446 zlog_err ("isis_zebra_route_del_ipv6: out of memory!");
450 /* allocate memory for ifindex_list */
451 size
= sizeof (unsigned int) * listcount (route_info
->nexthops6
);
452 ifindex_list
= (unsigned int *) XMALLOC (MTYPE_ISIS_TMP
, size
);
455 zlog_err ("isis_zebra_route_del_ipv6: out of memory!");
456 XFREE (MTYPE_ISIS_TMP
, nexthop_list
);
460 /* for each nexthop */
462 for (ALL_LIST_ELEMENTS_RO (route_info
->nexthops6
, node
, nexthop6
))
464 if (!IN6_IS_ADDR_LINKLOCAL (&nexthop6
->ip6
) &&
465 !IN6_IS_ADDR_UNSPECIFIED (&nexthop6
->ip6
))
472 nexthop_list
[i
] = &nexthop6
->ip6
;
473 ifindex_list
[i
] = nexthop6
->ifindex
;
477 api
.nexthop
= nexthop_list
;
478 api
.ifindex
= ifindex_list
;
480 if (api
.nexthop_num
&& api
.ifindex_num
)
482 prefix6
.family
= AF_INET6
;
483 prefix6
.prefixlen
= prefix
->prefixlen
;
484 memcpy (&prefix6
.prefix
, &prefix
->u
.prefix6
, sizeof (struct in6_addr
));
485 zapi_ipv6_route (ZEBRA_IPV6_ROUTE_DELETE
, zclient
, &prefix6
, &api
);
486 UNSET_FLAG (route_info
->flag
, ISIS_ROUTE_FLAG_ZEBRA_SYNC
);
489 XFREE (MTYPE_ISIS_TMP
, nexthop_list
);
490 XFREE (MTYPE_ISIS_TMP
, ifindex_list
);
493 #endif /* HAVE_IPV6 */
496 isis_zebra_route_update (struct prefix
*prefix
,
497 struct isis_route_info
*route_info
)
499 if (zclient
->sock
< 0)
502 if (!zclient
->redist
[ZEBRA_ROUTE_ISIS
])
505 if (CHECK_FLAG (route_info
->flag
, ISIS_ROUTE_FLAG_ACTIVE
))
507 if (prefix
->family
== AF_INET
)
508 isis_zebra_route_add_ipv4 (prefix
, route_info
);
510 else if (prefix
->family
== AF_INET6
)
511 isis_zebra_route_add_ipv6 (prefix
, route_info
);
512 #endif /* HAVE_IPV6 */
516 if (prefix
->family
== AF_INET
)
517 isis_zebra_route_del_ipv4 (prefix
, route_info
);
519 else if (prefix
->family
== AF_INET6
)
520 isis_zebra_route_del_ipv6 (prefix
, route_info
);
521 #endif /* HAVE_IPV6 */
527 isis_zebra_read_ipv4 (int command
, struct zclient
*zclient
,
530 struct stream
*stream
;
531 struct zapi_ipv4 api
;
532 struct prefix_ipv4 p
;
533 unsigned long ifindex
;
534 struct in_addr nexthop
;
536 stream
= zclient
->ibuf
;
537 memset (&p
, 0, sizeof (struct prefix_ipv4
));
540 api
.type
= stream_getc (stream
);
541 api
.flags
= stream_getc (stream
);
542 api
.message
= stream_getc (stream
);
545 p
.prefixlen
= stream_getc (stream
);
546 stream_get (&p
.prefix
, stream
, PSIZE (p
.prefixlen
));
548 if (CHECK_FLAG (api
.message
, ZAPI_MESSAGE_NEXTHOP
))
550 api
.nexthop_num
= stream_getc (stream
);
551 nexthop
.s_addr
= stream_get_ipv4 (stream
);
553 if (CHECK_FLAG (api
.message
, ZAPI_MESSAGE_IFINDEX
))
555 api
.ifindex_num
= stream_getc (stream
);
556 ifindex
= stream_getl (stream
);
558 if (CHECK_FLAG (api
.message
, ZAPI_MESSAGE_DISTANCE
))
559 api
.distance
= stream_getc (stream
);
560 if (CHECK_FLAG (api
.message
, ZAPI_MESSAGE_METRIC
))
561 api
.metric
= stream_getl (stream
);
565 if (command
== ZEBRA_IPV4_ROUTE_ADD
)
567 if (isis
->debugs
& DEBUG_ZEBRA
)
568 zlog_debug ("IPv4 Route add from Z");
576 isis_zebra_read_ipv6 (int command
, struct zclient
*zclient
,
583 #define ISIS_TYPE_IS_REDISTRIBUTED(T) \
584 T == ZEBRA_ROUTE_MAX ? zclient->default_information : zclient->redist[type]
587 isis_distribute_list_update (int routetype
)
594 isis_redistribute_default_set (int routetype
, int metric_type
,
604 zclient
= zclient_new ();
605 zclient_init (zclient
, ZEBRA_ROUTE_ISIS
);
606 zclient
->router_id_update
= isis_router_id_update_zebra
;
607 zclient
->interface_add
= isis_zebra_if_add
;
608 zclient
->interface_delete
= isis_zebra_if_del
;
609 zclient
->interface_up
= isis_zebra_if_state_up
;
610 zclient
->interface_down
= isis_zebra_if_state_down
;
611 zclient
->interface_address_add
= isis_zebra_if_address_add
;
612 zclient
->interface_address_delete
= isis_zebra_if_address_del
;
613 zclient
->ipv4_route_add
= isis_zebra_read_ipv4
;
614 zclient
->ipv4_route_delete
= isis_zebra_read_ipv4
;
616 zclient
->ipv6_route_add
= isis_zebra_read_ipv6
;
617 zclient
->ipv6_route_delete
= isis_zebra_read_ipv6
;
618 #endif /* HAVE_IPV6 */