2 * Copyright (C) 1999 Yasuhiro Ohara
4 * This file is part of GNU Zebra.
6 * GNU Zebra is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; either version 2, or (at your option) any
11 * GNU Zebra is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with GNU Zebra; see the file COPYING. If not, write to the
18 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19 * Boston, MA 02111-1307, USA.
24 #include "ospf6_interface.h"
25 #include "ospf6_asbr.h"
27 #include "ospf6_linklist.h"
29 /* information about zebra. */
30 struct zclient
*zclient
= NULL
;
32 /* redistribute function */
34 ospf6_zebra_redistribute (int type
)
38 if (zclient
->redist
[type
])
41 if (! ospf6_is_asbr (ospf6
))
44 zclient
->redist
[type
] = 1;
46 if (zclient
->sock
> 0)
47 zebra_redistribute_send (ZEBRA_REDISTRIBUTE_ADD
, zclient
->sock
, type
);
50 CALL_CHANGE_HOOK (&top_hook
, ospf6
);
54 ospf6_zebra_no_redistribute (int type
)
58 if (!zclient
->redist
[type
])
61 if (ospf6_is_asbr (ospf6
))
64 zclient
->redist
[type
] = 0;
66 if (zclient
->sock
> 0)
67 zebra_redistribute_send (ZEBRA_REDISTRIBUTE_DELETE
, zclient
->sock
, type
);
70 CALL_CHANGE_HOOK (&top_hook
, ospf6
);
74 ospf6_zebra_is_redistribute (int type
)
76 return zclient
->redist
[type
];
80 /* Inteface addition message from zebra. */
82 ospf6_zebra_if_add (int command
, struct zclient
*zclient
, zebra_size_t length
)
84 struct interface
*ifp
;
86 ifp
= zebra_interface_add_read (zclient
->ibuf
);
89 if (IS_OSPF6_DUMP_ZEBRA
)
90 zlog_info ("ZEBRA: I/F add: %s index %d mtu %d",
91 ifp
->name
, ifp
->ifindex
, ifp
->mtu
);
93 ospf6_interface_if_add (ifp
);
99 ospf6_zebra_if_del (int command
, struct zclient
*zclient
, zebra_size_t length
)
102 struct interface
*ifp
= NULL
;
104 ifp
= zebra_interface_delete_read (zclient
->ibuf
);
107 if (IS_OSPF6_DUMP_ZEBRA
)
108 zlog_info ("ZEBRA: I/F delete: %s index %d mtu %d",
109 ifp
->name
, ifp
->ifindex
, ifp
->mtu
);
111 ospf6_interface_if_del (ifp
);
118 ospf6_zebra_if_state_update (int command
, struct zclient
*zclient
,
121 struct interface
*ifp
;
123 ifp
= zebra_interface_state_read (zclient
->ibuf
);
126 if (IS_OSPF6_DUMP_ZEBRA
)
127 zlog_info ("ZEBRA: I/F %s state change: index %d flags %ld metric %d mtu %d",
128 ifp
->name
, ifp
->ifindex
, ifp
->flags
, ifp
->metric
, ifp
->mtu
);
130 ospf6_interface_state_update (ifp
);
135 ospf6_zebra_if_address_update_add (int command
, struct zclient
*zclient
,
141 c
= zebra_interface_address_add_read (zclient
->ibuf
);
145 if (IS_OSPF6_DUMP_ZEBRA
)
146 zlog_info ("ZEBRA: I/F %s address add: %5s %s/%d",
147 c
->ifp
->name
, prefix_family_str (c
->address
),
148 inet_ntop (c
->address
->family
, &c
->address
->u
.prefix
,
149 buf
, sizeof (buf
)), c
->address
->prefixlen
);
151 if (c
->address
->family
== AF_INET6
)
152 ospf6_interface_address_update (c
->ifp
);
158 ospf6_zebra_if_address_update_delete (int command
, struct zclient
*zclient
,
164 c
= zebra_interface_address_delete_read (zclient
->ibuf
);
168 if (IS_OSPF6_DUMP_ZEBRA
)
169 zlog_info ("ZEBRA: I/F %s address del: %5s %s/%d",
170 c
->ifp
->name
, prefix_family_str (c
->address
),
171 inet_ntop (c
->address
->family
, &c
->address
->u
.prefix
,
172 buf
, sizeof (buf
)), c
->address
->prefixlen
);
174 if (c
->address
->family
== AF_INET6
)
175 ospf6_interface_address_update (c
->ifp
);
182 const char *zebra_route_name
[ZEBRA_ROUTE_MAX
] =
195 const char *zebra_route_abname
[ZEBRA_ROUTE_MAX
] =
196 { "X", "K", "C", "S", "r", "R", "o", "O", "B" };
199 ospf6_zebra_read_ipv6 (int command
, struct zclient
*zclient
,
203 struct zapi_ipv6 api
;
204 unsigned long ifindex
;
205 struct prefix_ipv6 p
;
206 struct in6_addr
*nexthop
;
207 char prefixstr
[128], nexthopstr
[128];
212 memset (&api
, 0, sizeof (api
));
214 /* Type, flags, message. */
215 api
.type
= stream_getc (s
);
216 api
.flags
= stream_getc (s
);
217 api
.message
= stream_getc (s
);
220 memset (&p
, 0, sizeof (struct prefix_ipv6
));
222 p
.prefixlen
= stream_getc (s
);
223 stream_get (&p
.prefix
, s
, PSIZE (p
.prefixlen
));
225 /* Nexthop, ifindex, distance, metric. */
226 if (CHECK_FLAG (api
.message
, ZAPI_MESSAGE_NEXTHOP
))
228 api
.nexthop_num
= stream_getc (s
);
229 nexthop
= (struct in6_addr
*)
230 malloc (api
.nexthop_num
* sizeof (struct in6_addr
));
231 stream_get (nexthop
, s
, api
.nexthop_num
* sizeof (struct in6_addr
));
233 if (CHECK_FLAG (api
.message
, ZAPI_MESSAGE_IFINDEX
))
235 api
.ifindex_num
= stream_getc (s
);
236 ifindex
= stream_getl (s
);
238 if (CHECK_FLAG (api
.message
, ZAPI_MESSAGE_DISTANCE
))
239 api
.distance
= stream_getc (s
);
242 if (CHECK_FLAG (api
.message
, ZAPI_MESSAGE_METRIC
))
243 api
.metric
= stream_getl (s
);
248 if (IS_OSPF6_DUMP_ZEBRA
)
250 prefix2str ((struct prefix
*)&p
, prefixstr
, sizeof (prefixstr
));
251 inet_ntop (AF_INET6
, &nexthop
, nexthopstr
, sizeof (nexthopstr
));
253 if (command
== ZEBRA_IPV6_ROUTE_ADD
)
254 zlog_info ("ZEBRA: Receive add %s route: %s nexthop:%s ifindex:%ld",
255 zebra_route_name
[api
.type
], prefixstr
,
256 nexthopstr
, ifindex
);
258 zlog_info ("ZEBRA: Receive remove %s route: %s nexthop:%s ifindex:%ld",
259 zebra_route_name
[api
.type
], prefixstr
,
260 nexthopstr
, ifindex
);
263 if (command
== ZEBRA_IPV6_ROUTE_ADD
)
264 ospf6_asbr_route_add (api
.type
, ifindex
, (struct prefix
*) &p
,
265 api
.nexthop_num
, nexthop
);
267 ospf6_asbr_route_remove (api
.type
, ifindex
, (struct prefix
*) &p
);
269 if (CHECK_FLAG (api
.message
, ZAPI_MESSAGE_NEXTHOP
))
280 "Zebra information\n")
284 vty_out (vty
, "Not connected to zebra%s", VTY_NEWLINE
);
286 vty_out (vty
, "Zebra Infomation%s", VTY_NEWLINE
);
287 vty_out (vty
, " enable: %d%s", zclient
->enable
, VTY_NEWLINE
);
288 vty_out (vty
, " fail: %d%s", zclient
->fail
, VTY_NEWLINE
);
289 vty_out (vty
, " redistribute default: %d%s", zclient
->redist_default
,
291 for (i
= 0; i
< ZEBRA_ROUTE_MAX
; i
++)
292 vty_out (vty
, " RouteType: %s - %s%s", zebra_route_name
[i
],
293 zclient
->redist
[i
] ? "redistributed" : "not redistributed",
301 "Enable a routing process\n"
302 "Make connection to zebra daemon\n")
304 if (IS_OSPF6_DUMP_CONFIG
)
305 zlog_info ("Config: router zebra");
307 vty
->node
= ZEBRA_NODE
;
309 zclient_start (zclient
);
313 DEFUN (no_router_zebra
,
317 "Configure routing process\n"
318 "Disable connection to zebra daemon\n")
320 if (IS_OSPF6_DUMP_CONFIG
)
321 zlog_info ("no router zebra");
324 zclient_stop (zclient
);
328 /* Zebra configuration write function. */
330 ospf6_zebra_config_write (struct vty
*vty
)
332 if (! zclient
->enable
)
334 vty_out (vty
, "no router zebra%s", VTY_NEWLINE
);
337 else if (! zclient
->redist
[ZEBRA_ROUTE_OSPF6
])
339 vty_out (vty
, "router zebra%s", VTY_NEWLINE
);
340 vty_out (vty
, " no redistribute ospf6%s", VTY_NEWLINE
);
346 /* Zebra node structure. */
347 struct cmd_node zebra_node
=
350 "%s(config-zebra)# ",
358 ospf6_zebra_route_update (int type
, struct ospf6_route_req
*request
)
360 char buf
[96], ifname
[IFNAMSIZ
];
362 struct zapi_ipv6 api
;
363 struct ospf6_route_req route
;
364 struct linklist
*nexthop_list
;
365 struct linklist_node node
;
366 struct ospf6_nexthop
*nexthop
= NULL
;
367 struct in6_addr
**nexthops
;
368 unsigned int *ifindexes
;
369 struct prefix_ipv6
*p
;
372 if (IS_OSPF6_DUMP_ZEBRA
)
374 prefix2str (&request
->route
.prefix
, buf
, sizeof (buf
));
376 zlog_info ("ZEBRA: Send remove route: %s", buf
);
378 zlog_info ("ZEBRA: Send add route: %s", buf
);
381 if (zclient
->sock
< 0)
383 if (IS_OSPF6_DUMP_ZEBRA
)
384 zlog_info ("ZEBRA: failed: not connected to zebra");
388 if (request
->path
.origin
.adv_router
== ospf6
->router_id
&&
389 (request
->path
.type
== OSPF6_PATH_TYPE_EXTERNAL1
||
390 request
->path
.type
== OSPF6_PATH_TYPE_EXTERNAL2
))
392 if (IS_OSPF6_DUMP_ZEBRA
)
393 zlog_info ("ZEBRA: self originated external route, ignore");
397 /* Only the best path (i.e. the first path of the path-list
398 in 'struct ospf6_route') will be sent to zebra. */
399 ospf6_route_lookup (&route
, &request
->route
.prefix
, request
->table
);
400 if (memcmp (&route
.path
, &request
->path
, sizeof (route
.path
)))
402 /* this is not preferred best route, ignore */
403 if (IS_OSPF6_DUMP_ZEBRA
)
404 zlog_info ("ZEBRA: not best path, ignore");
408 nexthop_list
= linklist_create ();
410 /* for each nexthop */
411 for (ospf6_route_lookup (&route
, &request
->route
.prefix
, request
->table
);
412 ! ospf6_route_end (&route
); ospf6_route_next (&route
))
414 if (memcmp (&route
.path
, &request
->path
, sizeof (route
.path
)))
417 #define IN6_IS_ILLEGAL_NEXTHOP(a)\
418 ((*(u_int32_t *)(void *)(&(a)->s6_addr[0]) == 0xffffffff) &&\
419 (*(u_int32_t *)(void *)(&(a)->s6_addr[4]) == 0xffffffff) &&\
420 (*(u_int32_t *)(void *)(&(a)->s6_addr[8]) == 0xffffffff) &&\
421 (*(u_int32_t *)(void *)(&(a)->s6_addr[12]) == 0xffffffff))
422 if (IN6_IS_ILLEGAL_NEXTHOP (&route
.nexthop
.address
))
424 zlog_warn ("ZEBRA: Illegal nexthop");
428 if (type
== REMOVE
&& ! memcmp (&route
.nexthop
, &request
->nexthop
,
429 sizeof (struct ospf6_nexthop
)))
432 nexthop
= XCALLOC (MTYPE_OSPF6_OTHER
, sizeof (struct ospf6_nexthop
));
435 zlog_warn ("ZEBRA: Can't update nexthop: malloc failed");
439 memcpy (nexthop
, &route
.nexthop
, sizeof (struct ospf6_nexthop
));
440 linklist_add (nexthop
, nexthop_list
);
443 if (type
== REMOVE
&& nexthop_list
->count
!= 0)
445 else if (type
== REMOVE
&& nexthop_list
->count
== 0)
447 if (IS_OSPF6_DUMP_ZEBRA
)
448 zlog_info ("ZEBRA: all nexthop with the selected path has gone");
450 if (! memcmp (&request
->route
, &route
.route
,
451 sizeof (struct ospf6_route
)))
453 /* send 'add' of alternative route */
454 struct ospf6_path seconde_path
;
456 if (IS_OSPF6_DUMP_ZEBRA
)
457 zlog_info ("ZEBRA: found alternative path to add");
459 memcpy (&seconde_path
, &route
.path
, sizeof (struct ospf6_path
));
462 while (! memcmp (&seconde_path
, &route
.path
,
463 sizeof (struct ospf6_path
)))
465 nexthop
= XCALLOC (MTYPE_OSPF6_OTHER
,
466 sizeof (struct ospf6_nexthop
));
468 zlog_warn ("ZEBRA: Can't update nexthop: malloc failed");
471 memcpy (nexthop
, &route
.nexthop
,
472 sizeof (struct ospf6_nexthop
));
473 linklist_add (nexthop
, nexthop_list
);
476 ospf6_route_next (&route
);
481 /* there is no alternative route. send 'remove' to zebra for
483 if (IS_OSPF6_DUMP_ZEBRA
)
484 zlog_info ("ZEBRA: can't find alternative path, remove");
486 if (IS_OSPF6_DUMP_ZEBRA
)
488 zlog_info ("ZEBRA: Debug: walk over the route ?");
489 ospf6_route_log_request ("Debug route", "***", &route
);
490 ospf6_route_log_request ("Debug request", "***", request
);
493 nexthop
= XCALLOC (MTYPE_OSPF6_OTHER
,
494 sizeof (struct ospf6_nexthop
));
496 zlog_warn ("ZEBRA: Can't update nexthop: malloc failed");
499 memcpy (nexthop
, &request
->nexthop
,
500 sizeof (struct ospf6_nexthop
));
501 linklist_add (nexthop
, nexthop_list
);
506 if (nexthop_list
->count
== 0)
508 if (IS_OSPF6_DUMP_ZEBRA
)
509 zlog_info ("ZEBRA: no nexthop, ignore");
510 linklist_delete (nexthop_list
);
514 /* allocate memory for nexthop_list */
515 nexthops
= XCALLOC (MTYPE_OSPF6_OTHER
,
516 nexthop_list
->count
* sizeof (struct in6_addr
*));
519 zlog_warn ("ZEBRA: Can't update zebra route: malloc failed");
520 for (linklist_head (nexthop_list
, &node
); !linklist_end (&node
);
521 linklist_next (&node
))
522 XFREE (MTYPE_OSPF6_OTHER
, node
.data
);
523 linklist_delete (nexthop_list
);
527 /* allocate memory for ifindex_list */
528 ifindexes
= XCALLOC (MTYPE_OSPF6_OTHER
,
529 nexthop_list
->count
* sizeof (unsigned int));
532 zlog_warn ("ZEBRA: Can't update zebra route: malloc failed");
533 for (linklist_head (nexthop_list
, &node
); !linklist_end (&node
);
534 linklist_next (&node
))
535 XFREE (MTYPE_OSPF6_OTHER
, node
.data
);
536 linklist_delete (nexthop_list
);
537 XFREE (MTYPE_OSPF6_OTHER
, nexthops
);
542 for (linklist_head (nexthop_list
, &node
); ! linklist_end (&node
);
543 linklist_next (&node
))
546 if (IS_OSPF6_DUMP_ZEBRA
)
548 inet_ntop (AF_INET6
, &nexthop
->address
, buf
, sizeof (buf
));
549 if_indextoname (nexthop
->ifindex
, ifname
);
550 zlog_info ("ZEBRA: nexthop: %s%%%s(%d)",
551 buf
, ifname
, nexthop
->ifindex
);
553 nexthops
[i
] = &nexthop
->address
;
554 ifindexes
[i
] = nexthop
->ifindex
;
558 api
.type
= ZEBRA_ROUTE_OSPF6
;
561 SET_FLAG (api
.message
, ZAPI_MESSAGE_NEXTHOP
);
562 SET_FLAG (api
.message
, ZAPI_MESSAGE_IFINDEX
);
563 api
.nexthop_num
= nexthop_list
->count
;
564 api
.nexthop
= nexthops
;
565 api
.ifindex_num
= nexthop_list
->count
;
566 api
.ifindex
= ifindexes
;
568 p
= (struct prefix_ipv6
*) &request
->route
.prefix
;
569 if (type
== REMOVE
&& nexthop_list
->count
== 1)
570 ret
= zapi_ipv6_delete (zclient
, p
, &api
);
572 ret
= zapi_ipv6_add (zclient
, p
, &api
);
575 zlog_err ("ZEBRA: zapi_ipv6_add () failed: %s", strerror (errno
));
577 for (linklist_head (nexthop_list
, &node
); !linklist_end (&node
);
578 linklist_next (&node
))
579 XFREE (MTYPE_OSPF6_OTHER
, node
.data
);
580 linklist_delete (nexthop_list
);
581 XFREE (MTYPE_OSPF6_OTHER
, nexthops
);
582 XFREE (MTYPE_OSPF6_OTHER
, ifindexes
);
588 ospf6_zebra_route_update_add (struct ospf6_route_req
*request
)
590 ospf6_zebra_route_update (ADD
, request
);
594 ospf6_zebra_route_update_remove (struct ospf6_route_req
*request
)
596 ospf6_zebra_route_update (REMOVE
, request
);
600 ospf6_zebra_redistribute_ospf6 ()
602 struct route_node
*node
;
604 for (node
= route_top (ospf6
->route_table
->table
); node
;
605 node
= route_next (node
))
607 if (! node
|| ! node
->info
)
609 ospf6_zebra_route_update_add (node
->info
);
614 ospf6_zebra_no_redistribute_ospf6 ()
616 struct route_node
*node
;
621 for (node
= route_top (ospf6
->route_table
->table
); node
;
622 node
= route_next (node
))
624 if (! node
|| ! node
->info
)
627 ospf6_zebra_route_update_remove (node
->info
);
632 DEFUN (redistribute_ospf6
,
633 redistribute_ospf6_cmd
,
634 "redistribute ospf6",
635 "Redistribute control\n"
639 if (IS_OSPF6_DUMP_CONFIG
)
640 zlog_info ("Config: redistribute ospf6");
642 zclient
->redist
[ZEBRA_ROUTE_OSPF6
] = 1;
644 /* set zebra route table */
645 ospf6_zebra_redistribute_ospf6 ();
650 DEFUN (no_redistribute_ospf6
,
651 no_redistribute_ospf6_cmd
,
652 "no redistribute ospf6",
654 "Redistribute control\n"
658 if (IS_OSPF6_DUMP_CONFIG
)
659 zlog_info ("Config: no redistribute ospf6");
661 zclient
->redist
[ZEBRA_ROUTE_OSPF6
] = 0;
666 /* clean up zebra route table */
667 ospf6_zebra_no_redistribute_ospf6 ();
669 ospf6_route_hook_unregister (ospf6_zebra_route_update_add
,
670 ospf6_zebra_route_update_add
,
671 ospf6_zebra_route_update_remove
,
680 /* Allocate zebra structure. */
681 zclient
= zclient_new ();
682 zclient_init (zclient
, ZEBRA_ROUTE_OSPF6
);
683 zclient
->interface_add
= ospf6_zebra_if_add
;
684 zclient
->interface_delete
= ospf6_zebra_if_del
;
685 zclient
->interface_up
= ospf6_zebra_if_state_update
;
686 zclient
->interface_down
= ospf6_zebra_if_state_update
;
687 zclient
->interface_address_add
= ospf6_zebra_if_address_update_add
;
688 zclient
->interface_address_delete
= ospf6_zebra_if_address_update_delete
;
689 zclient
->ipv4_route_add
= NULL
;
690 zclient
->ipv4_route_delete
= NULL
;
691 zclient
->ipv6_route_add
= ospf6_zebra_read_ipv6
;
692 zclient
->ipv6_route_delete
= ospf6_zebra_read_ipv6
;
694 /* redistribute connected route by default */
695 /* ospf6_zebra_redistribute (ZEBRA_ROUTE_CONNECT); */
697 /* Install zebra node. */
698 install_node (&zebra_node
, ospf6_zebra_config_write
);
700 /* Install command element for zebra node. */
701 install_element (VIEW_NODE
, &show_zebra_cmd
);
702 install_element (ENABLE_NODE
, &show_zebra_cmd
);
703 install_element (CONFIG_NODE
, &router_zebra_cmd
);
704 install_element (CONFIG_NODE
, &no_router_zebra_cmd
);
705 install_default (ZEBRA_NODE
);
706 install_element (ZEBRA_NODE
, &redistribute_ospf6_cmd
);
707 install_element (ZEBRA_NODE
, &no_redistribute_ospf6_cmd
);
710 hook
.name
= "ZebraRouteUpdate";
711 hook
.hook_add
= ospf6_zebra_route_update_add
;
712 hook
.hook_change
= ospf6_zebra_route_update_add
;
713 hook
.hook_remove
= ospf6_zebra_route_update_remove
;
714 ospf6_hook_register (&hook
, &route_hook
);
721 ospf6_zebra_finish ()
723 zclient_stop (zclient
);
724 zclient_free (zclient
);
725 zclient
= (struct zclient
*) NULL
;