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/isis_constants.h"
37 #include "isisd/isis_common.h"
38 #include "isisd/isis_circuit.h"
39 #include "isisd/isis_csm.h"
40 #include "isisd/isis_route.h"
41 #include "isisd/isis_zebra.h"
43 struct zclient
*zclient
= NULL
;
45 extern struct thread_master
*master
;
48 isis_zebra_if_add (int command
, struct zclient
*zclient
, zebra_size_t length
)
50 struct interface
*ifp
;
52 ifp
= zebra_interface_add_read (zclient
->ibuf
);
55 zlog_info ("Zebra I/F add: %s index %d flags %ld metric %d mtu %d",
56 ifp
->name
, ifp
->ifindex
, ifp
->flags
, ifp
->metric
, ifp
->mtu
);
59 isis_csm_state_change (IF_UP_FROM_Z
, circuit_scan_by_ifp (ifp
), ifp
);
65 isis_zebra_if_del (int command
, struct zclient
*zclient
, zebra_size_t length
)
67 struct interface
*ifp
;
71 ifp
= zebra_interface_state_read (s
);
77 zlog_warn ("Zebra: got delete of %s, but interface is still up",
80 zlog_info ("Zebra I/F delete: %s index %d flags %ld metric %d mtu %d",
81 ifp
->name
, ifp
->ifindex
, ifp
->flags
, ifp
->metric
, ifp
->mtu
);
85 isis_csm_state_change (IF_DOWN_FROM_Z
, circuit_scan_by_ifp (ifp
), ifp
);
91 zebra_interface_if_lookup (struct stream
*s
)
93 struct interface
*ifp
;
94 u_char ifname_tmp
[INTERFACE_NAMSIZ
];
96 /* Read interface name. */
97 stream_get (ifname_tmp
, s
, INTERFACE_NAMSIZ
);
99 /* Lookup this by interface index. */
100 ifp
= if_lookup_by_name (ifname_tmp
);
102 /* If such interface does not exist, indicate an error */
110 zebra_interface_if_set_value (struct stream
*s
, struct interface
*ifp
)
112 /* Read interface's index. */
113 ifp
->ifindex
= stream_getl (s
);
115 /* Read interface's value. */
116 ifp
->flags
= stream_getl (s
);
117 ifp
->metric
= stream_getl (s
);
118 ifp
->mtu
= stream_getl (s
);
119 ifp
->bandwidth
= stream_getl (s
);
123 isis_zebra_if_state_up (int command
, struct zclient
*zclient
,
126 struct interface
*ifp
;
128 ifp
= zebra_interface_if_lookup (zclient
->ibuf
);
133 if (if_is_up (ifp
)) {
134 zebra_interface_if_set_value (zclient
->ibuf
, ifp
);
135 isis_circuit_update_params (circuit_scan_by_ifp (ifp
), ifp
);
139 zebra_interface_if_set_value (zclient
->ibuf
, ifp
);
140 isis_csm_state_change (IF_UP_FROM_Z
, circuit_scan_by_ifp (ifp
), ifp
);
147 isis_zebra_if_state_down (int command
, struct zclient
*zclient
,
150 struct interface
*ifp
;
152 ifp
= zebra_interface_if_lookup (zclient
->ibuf
);
157 if (if_is_up (ifp
)) {
158 zebra_interface_if_set_value (zclient
->ibuf
, ifp
);
159 isis_csm_state_change (IF_DOWN_FROM_Z
, circuit_scan_by_ifp (ifp
), ifp
);
166 isis_zebra_if_address_add (int command
, struct zclient
*zclient
,
173 c
= zebra_interface_address_read (ZEBRA_INTERFACE_ADDRESS_ADD
,
181 prefix2str (p
, buf
, BUFSIZ
);
183 if (p
->family
== AF_INET
)
184 zlog_info ("connected IP address %s", buf
);
186 if (p
->family
== AF_INET6
)
187 zlog_info ("connected IPv6 address %s", buf
);
188 #endif /* HAVE_IPV6 */
189 #endif /* EXTREME_DEBUG */
190 isis_circuit_add_addr (circuit_scan_by_ifp (c
->ifp
), c
);
196 isis_zebra_if_address_del (int command
, struct zclient
*client
,
200 struct interface
*ifp
;
202 c
= zebra_interface_address_read (ZEBRA_INTERFACE_ADDRESS_DELETE
,
212 isis_circuit_del_addr (circuit_scan_by_ifp (ifp
), c
);
218 isis_zebra_route_add_ipv4 (struct prefix
*prefix
,
219 struct isis_route_info
*route_info
)
221 u_char message
, flags
;
223 struct stream
*stream
;
224 struct isis_nexthop
*nexthop
;
225 struct listnode
*node
;
227 if (CHECK_FLAG (route_info
->flag
, ISIS_ROUTE_FLAG_ZEBRA_SYNC
))
230 if (zclient
->redist
[ZEBRA_ROUTE_ISIS
]) {
234 SET_FLAG (message
, ZAPI_MESSAGE_NEXTHOP
);
235 SET_FLAG (message
, ZAPI_MESSAGE_METRIC
);
237 SET_FLAG (message
, ZAPI_MESSAGE_DISTANCE
);
240 stream
= zclient
->obuf
;
241 stream_reset (stream
);
242 /* Length place holder. */
243 stream_putw (stream
, 0);
245 stream_putc (stream
, ZEBRA_IPV4_ROUTE_ADD
);
247 stream_putc (stream
, ZEBRA_ROUTE_ISIS
);
249 stream_putc (stream
, flags
);
251 stream_putc (stream
, message
);
252 /* prefix information */
253 psize
= PSIZE (prefix
->prefixlen
);
254 stream_putc (stream
, prefix
->prefixlen
);
255 stream_write (stream
, (u_char
*)&prefix
->u
.prefix4
, psize
);
257 stream_putc (stream
, listcount (route_info
->nexthops
));
259 /* Nexthop, ifindex, distance and metric information */
260 for (node
= listhead (route_info
->nexthops
); node
; nextnode (node
)) {
261 nexthop
= getdata (node
);
262 /* FIXME: can it be ? */
263 if (nexthop
->ip
.s_addr
!= INADDR_ANY
) {
264 stream_putc (stream
, ZEBRA_NEXTHOP_IPV4
);
265 stream_put_in_addr (stream
, &nexthop
->ip
);
267 stream_putc (stream
, ZEBRA_NEXTHOP_IFINDEX
);
268 stream_putl (stream
, nexthop
->ifindex
);
272 if (CHECK_FLAG (message
, ZAPI_MESSAGE_DISTANCE
))
273 stream_putc (stream
, route_info
->depth
);
275 if (CHECK_FLAG (message
, ZAPI_MESSAGE_METRIC
))
276 stream_putl (stream
, route_info
->cost
);
278 stream_putw_at (stream
, 0, stream_get_endp (stream
));
279 writen (zclient
->sock
, stream
->data
, stream_get_endp (stream
));
284 isis_zebra_route_del_ipv4 (struct prefix
*prefix
,
285 struct isis_route_info
*route_info
)
287 struct zapi_ipv4 api
;
288 struct prefix_ipv4 prefix4
;
290 if (zclient
->redist
[ZEBRA_ROUTE_ISIS
]) {
291 api
.type
= ZEBRA_ROUTE_ISIS
;
294 prefix4
.family
= AF_INET
;
295 prefix4
.prefixlen
= prefix
->prefixlen
;
296 prefix4
.prefix
= prefix
->u
.prefix4
;
297 zapi_ipv4_route (ZEBRA_IPV4_ROUTE_DELETE
, zclient
, &prefix4
, &api
);
305 isis_zebra_route_add_ipv6 (struct prefix
*prefix
,
306 struct isis_route_info
*route_info
)
308 struct zapi_ipv6 api
;
309 struct in6_addr
**nexthop_list
;
310 unsigned int *ifindex_list
;
311 struct isis_nexthop6
*nexthop6
;
313 struct listnode
*node
;
314 struct prefix_ipv6 prefix6
;
316 if (CHECK_FLAG (route_info
->flag
, ISIS_ROUTE_FLAG_ZEBRA_SYNC
))
319 api
.type
= ZEBRA_ROUTE_ISIS
;
322 SET_FLAG (api
.message
, ZAPI_MESSAGE_NEXTHOP
);
323 SET_FLAG (api
.message
, ZAPI_MESSAGE_IFINDEX
);
324 SET_FLAG (api
.message
, ZAPI_MESSAGE_METRIC
);
325 api
.metric
= route_info
->cost
;
327 SET_FLAG (api
.message
, ZAPI_MESSAGE_DISTANCE
);
328 api
.distance
= route_info
->depth
;
330 api
.nexthop_num
= listcount (route_info
->nexthops6
);
331 api
.ifindex_num
= listcount (route_info
->nexthops6
);
333 /* allocate memory for nexthop_list */
334 size
= sizeof (struct isis_nexthop6
*) * listcount (route_info
->nexthops6
);
335 nexthop_list
= (struct in6_addr
**) XMALLOC (MTYPE_ISIS_TMP
, size
);
337 zlog_err ("isis_zebra_add_route_ipv6: out of memory!");
341 /* allocate memory for ifindex_list */
342 size
= sizeof (unsigned int) * listcount (route_info
->nexthops6
);
343 ifindex_list
= (unsigned int *) XMALLOC (MTYPE_ISIS_TMP
, size
);
345 zlog_err ("isis_zebra_add_route_ipv6: out of memory!");
346 XFREE (MTYPE_ISIS_TMP
, nexthop_list
);
350 /* for each nexthop */
352 for (node
= listhead (route_info
->nexthops6
); node
; nextnode (node
)) {
353 nexthop6
= getdata (node
);
355 if (!IN6_IS_ADDR_LINKLOCAL (&nexthop6
->ip6
) &&
356 !IN6_IS_ADDR_UNSPECIFIED (&nexthop6
->ip6
)) {
362 nexthop_list
[i
] = &nexthop6
->ip6
;
363 ifindex_list
[i
] = nexthop6
->ifindex
;
367 api
.nexthop
= nexthop_list
;
368 api
.ifindex
= ifindex_list
;
370 if (api
.nexthop_num
&& api
.ifindex_num
) {
371 prefix6
.family
= AF_INET6
;
372 prefix6
.prefixlen
= prefix
->prefixlen
;
373 memcpy (&prefix6
.prefix
, &prefix
->u
.prefix6
, sizeof (struct in6_addr
));
374 zapi_ipv6_route (ZEBRA_IPV6_ROUTE_ADD
, zclient
, &prefix6
, &api
);
375 SET_FLAG (route_info
->flag
, ISIS_ROUTE_FLAG_ZEBRA_SYNC
);
378 XFREE (MTYPE_ISIS_TMP
, nexthop_list
);
379 XFREE (MTYPE_ISIS_TMP
, ifindex_list
);
385 isis_zebra_route_del_ipv6 (struct prefix
*prefix
,
386 struct isis_route_info
*route_info
)
388 struct zapi_ipv6 api
;
389 struct in6_addr
**nexthop_list
;
390 unsigned int *ifindex_list
;
391 struct isis_nexthop6
*nexthop6
;
393 struct listnode
*node
;
394 struct prefix_ipv6 prefix6
;
396 if (CHECK_FLAG (route_info
->flag
, ISIS_ROUTE_FLAG_ZEBRA_SYNC
))
399 api
.type
= ZEBRA_ROUTE_ISIS
;
402 SET_FLAG (api
.message
, ZAPI_MESSAGE_NEXTHOP
);
403 SET_FLAG (api
.message
, ZAPI_MESSAGE_IFINDEX
);
404 api
.nexthop_num
= listcount (route_info
->nexthops6
);
405 api
.ifindex_num
= listcount (route_info
->nexthops6
);
407 /* allocate memory for nexthop_list */
408 size
= sizeof (struct isis_nexthop6
*) * listcount (route_info
->nexthops6
);
409 nexthop_list
= (struct in6_addr
**) XMALLOC (MTYPE_ISIS_TMP
, size
);
411 zlog_err ("isis_zebra_route_del_ipv6: out of memory!");
415 /* allocate memory for ifindex_list */
416 size
= sizeof (unsigned int) * listcount (route_info
->nexthops6
);
417 ifindex_list
= (unsigned int *) XMALLOC (MTYPE_ISIS_TMP
, size
);
419 zlog_err ("isis_zebra_route_del_ipv6: out of memory!");
420 XFREE (MTYPE_ISIS_TMP
, nexthop_list
);
424 /* for each nexthop */
426 for (node
= listhead (route_info
->nexthops6
); node
; nextnode (node
)) {
427 nexthop6
= getdata (node
);
429 if (!IN6_IS_ADDR_LINKLOCAL (&nexthop6
->ip6
) &&
430 !IN6_IS_ADDR_UNSPECIFIED (&nexthop6
->ip6
)) {
436 nexthop_list
[i
] = &nexthop6
->ip6
;
437 ifindex_list
[i
] = nexthop6
->ifindex
;
441 api
.nexthop
= nexthop_list
;
442 api
.ifindex
= ifindex_list
;
444 if (api
.nexthop_num
&& api
.ifindex_num
) {
445 prefix6
.family
= AF_INET6
;
446 prefix6
.prefixlen
= prefix
->prefixlen
;
447 memcpy (&prefix6
.prefix
, &prefix
->u
.prefix6
, sizeof (struct in6_addr
));
448 zapi_ipv6_route (ZEBRA_IPV6_ROUTE_DELETE
, zclient
, &prefix6
, &api
);
449 UNSET_FLAG (route_info
->flag
, ISIS_ROUTE_FLAG_ZEBRA_SYNC
);
452 XFREE (MTYPE_ISIS_TMP
, nexthop_list
);
453 XFREE (MTYPE_ISIS_TMP
, ifindex_list
);
457 #endif /* HAVE_IPV6 */
462 isis_zebra_route_update (struct prefix
*prefix
,
463 struct isis_route_info
*route_info
)
465 if (zclient
->sock
< 0)
468 if (!zclient
->redist
[ZEBRA_ROUTE_ISIS
])
471 if (CHECK_FLAG (route_info
->flag
, ISIS_ROUTE_FLAG_ACTIVE
)) {
472 if (prefix
->family
== AF_INET
)
473 isis_zebra_route_add_ipv4 (prefix
, route_info
);
475 else if (prefix
->family
== AF_INET6
)
476 isis_zebra_route_add_ipv6 (prefix
, route_info
);
477 #endif /* HAVE_IPV6 */
479 if (prefix
->family
== AF_INET
)
480 isis_zebra_route_del_ipv4 (prefix
, route_info
);
482 else if (prefix
->family
== AF_INET6
)
483 isis_zebra_route_del_ipv6 (prefix
, route_info
);
484 #endif /* HAVE_IPV6 */
491 isis_zebra_read_ipv4 (int command
, struct zclient
*zclient
,
494 struct stream
*stream
;
495 struct zapi_ipv4 api
;
496 struct prefix_ipv4 p
;
497 unsigned long ifindex
;
498 struct in_addr nexthop
;
500 stream
= zclient
->ibuf
;
501 memset (&p
, 0, sizeof (struct prefix_ipv4
));
504 api
.type
= stream_getc (stream
);
505 api
.flags
= stream_getc (stream
);
506 api
.message
= stream_getc (stream
);
509 p
.prefixlen
= stream_getc (stream
);
510 stream_get (&p
.prefix
, stream
, PSIZE (p
.prefixlen
));
512 if (CHECK_FLAG (api
.message
, ZAPI_MESSAGE_NEXTHOP
)) {
513 api
.nexthop_num
= stream_getc (stream
);
514 nexthop
.s_addr
= stream_get_ipv4 (stream
);
516 if (CHECK_FLAG (api
.message
, ZAPI_MESSAGE_IFINDEX
)) {
517 api
.ifindex_num
= stream_getc (stream
);
518 ifindex
= stream_getl (stream
);
520 if (CHECK_FLAG (api
.message
, ZAPI_MESSAGE_DISTANCE
))
521 api
.distance
= stream_getc (stream
);
522 if (CHECK_FLAG (api
.message
, ZAPI_MESSAGE_METRIC
))
523 api
.metric
= stream_getl (stream
);
527 if (command
== ZEBRA_IPV4_ROUTE_ADD
) {
528 zlog_info ("IPv4 Route add from Z");
536 isis_zebra_read_ipv6 (int command
, struct zclient
*zclient
,
543 #define ISIS_TYPE_IS_REDISTRIBUTED(T) \
544 T == ZEBRA_ROUTE_MAX ? zclient->default_information : zclient->redist[type]
547 isis_distribute_list_update (int routetype
)
553 isis_redistribute_default_set(int routetype
, int metric_type
, int metric_value
)
563 zclient
= zclient_new ();
564 zclient_init (zclient
, ZEBRA_ROUTE_ISIS
);
565 zclient
->interface_add
= isis_zebra_if_add
;
566 zclient
->interface_delete
= isis_zebra_if_del
;
567 zclient
->interface_up
= isis_zebra_if_state_up
;
568 zclient
->interface_down
= isis_zebra_if_state_down
;
569 zclient
->interface_address_add
= isis_zebra_if_address_add
;
570 zclient
->interface_address_delete
= isis_zebra_if_address_del
;
571 zclient
->ipv4_route_add
= isis_zebra_read_ipv4
;
572 zclient
->ipv4_route_delete
= isis_zebra_read_ipv4
;
574 zclient
->ipv6_route_add
= isis_zebra_read_ipv6
;
575 zclient
->ipv6_route_delete
= isis_zebra_read_ipv6
;
576 #endif /* HAVE_IPV6 */
585 zclient_stop (zclient
);
586 zclient_free (zclient
);
587 zclient
= (struct zclient
*) NULL
;