blob: 347ba1cf08f02140d704d9e7418f8961eb35225e [file] [log] [blame]
paul718e3742002-12-13 20:15:29 +00001/*
2 * Copyright (C) 1999 Yasuhiro Ohara
3 *
4 * This file is part of GNU Zebra.
5 *
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
9 * later version.
10 *
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.
15 *
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.
20 */
21
22#include "ospf6d.h"
23
24#include "ospf6_interface.h"
25#include "ospf6_asbr.h"
26
27#include "ospf6_linklist.h"
28
29/* information about zebra. */
30struct zclient *zclient = NULL;
31
32/* redistribute function */
33void
34ospf6_zebra_redistribute (int type)
35{
36 int top_change = 0;
37
38 if (zclient->redist[type])
39 return;
40
41 if (! ospf6_is_asbr (ospf6))
42 top_change = 1;
43
44 zclient->redist[type] = 1;
45
46 if (zclient->sock > 0)
47 zebra_redistribute_send (ZEBRA_REDISTRIBUTE_ADD, zclient->sock, type);
48
49 if (top_change)
50 CALL_CHANGE_HOOK (&top_hook, ospf6);
51}
52
53void
54ospf6_zebra_no_redistribute (int type)
55{
56 int top_change = 0;
57
58 if (!zclient->redist[type])
59 return;
60
61 if (ospf6_is_asbr (ospf6))
62 top_change = 1;
63
64 zclient->redist[type] = 0;
65
66 if (zclient->sock > 0)
67 zebra_redistribute_send (ZEBRA_REDISTRIBUTE_DELETE, zclient->sock, type);
68
69 if (top_change)
70 CALL_CHANGE_HOOK (&top_hook, ospf6);
71}
72
73int
74ospf6_zebra_is_redistribute (int type)
75{
76 return zclient->redist[type];
77}
78
79
80/* Inteface addition message from zebra. */
81int
82ospf6_zebra_if_add (int command, struct zclient *zclient, zebra_size_t length)
83{
84 struct interface *ifp;
85
86 ifp = zebra_interface_add_read (zclient->ibuf);
87
88 /* log */
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);
92
93 ospf6_interface_if_add (ifp);
94
95 return 0;
96}
97
98int
99ospf6_zebra_if_del (int command, struct zclient *zclient, zebra_size_t length)
100{
101#if 0
102 struct interface *ifp = NULL;
103
104 ifp = zebra_interface_delete_read (zclient->ibuf);
105
106 /* log */
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);
110
111 ospf6_interface_if_del (ifp);
112#endif
113
114 return 0;
115}
116
117int
118ospf6_zebra_if_state_update (int command, struct zclient *zclient,
119 zebra_size_t length)
120{
121 struct interface *ifp;
122
123 ifp = zebra_interface_state_read (zclient->ibuf);
124
125 /* log */
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);
129
130 ospf6_interface_state_update (ifp);
131 return 0;
132}
133
134int
135ospf6_zebra_if_address_update_add (int command, struct zclient *zclient,
136 zebra_size_t length)
137{
138 struct connected *c;
139 char buf[128];
140
141 c = zebra_interface_address_add_read (zclient->ibuf);
142 if (c == NULL)
143 return 0;
144
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);
150
151 if (c->address->family == AF_INET6)
152 ospf6_interface_address_update (c->ifp);
153
154 return 0;
155}
156
157int
158ospf6_zebra_if_address_update_delete (int command, struct zclient *zclient,
159 zebra_size_t length)
160{
161 struct connected *c;
162 char buf[128];
163
164 c = zebra_interface_address_delete_read (zclient->ibuf);
165 if (c == NULL)
166 return 0;
167
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);
173
174 if (c->address->family == AF_INET6)
175 ospf6_interface_address_update (c->ifp);
176
177 return 0;
178}
179
180
181
182const char *zebra_route_name[ZEBRA_ROUTE_MAX] =
183{
184 "System",
185 "Kernel",
186 "Connect",
187 "Static",
188 "RIP",
189 "RIPng",
190 "OSPF",
191 "OSPF6",
192 "BGP",
193};
194
195const char *zebra_route_abname[ZEBRA_ROUTE_MAX] =
196 { "X", "K", "C", "S", "r", "R", "o", "O", "B" };
197
198int
199ospf6_zebra_read_ipv6 (int command, struct zclient *zclient,
200 zebra_size_t length)
201{
202 struct stream *s;
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];
208
209 s = zclient->ibuf;
210 ifindex = 0;
211 nexthop = NULL;
212 memset (&api, 0, sizeof (api));
213
214 /* Type, flags, message. */
215 api.type = stream_getc (s);
216 api.flags = stream_getc (s);
217 api.message = stream_getc (s);
218
219 /* IPv6 prefix. */
220 memset (&p, 0, sizeof (struct prefix_ipv6));
221 p.family = AF_INET6;
222 p.prefixlen = stream_getc (s);
223 stream_get (&p.prefix, s, PSIZE (p.prefixlen));
224
225 /* Nexthop, ifindex, distance, metric. */
226 if (CHECK_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP))
227 {
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));
232 }
233 if (CHECK_FLAG (api.message, ZAPI_MESSAGE_IFINDEX))
234 {
235 api.ifindex_num = stream_getc (s);
236 ifindex = stream_getl (s);
237 }
238 if (CHECK_FLAG (api.message, ZAPI_MESSAGE_DISTANCE))
239 api.distance = stream_getc (s);
240 else
241 api.distance = 0;
242 if (CHECK_FLAG (api.message, ZAPI_MESSAGE_METRIC))
243 api.metric = stream_getl (s);
244 else
245 api.metric = 0;
246
247 /* log */
248 if (IS_OSPF6_DUMP_ZEBRA)
249 {
250 prefix2str ((struct prefix *)&p, prefixstr, sizeof (prefixstr));
251 inet_ntop (AF_INET6, &nexthop, nexthopstr, sizeof (nexthopstr));
252
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);
257 else
258 zlog_info ("ZEBRA: Receive remove %s route: %s nexthop:%s ifindex:%ld",
259 zebra_route_name [api.type], prefixstr,
260 nexthopstr, ifindex);
261 }
262
263 if (command == ZEBRA_IPV6_ROUTE_ADD)
264 ospf6_asbr_route_add (api.type, ifindex, (struct prefix *) &p,
265 api.nexthop_num, nexthop);
266 else
267 ospf6_asbr_route_remove (api.type, ifindex, (struct prefix *) &p);
268
269 if (CHECK_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP))
270 free (nexthop);
271
272 return 0;
273}
274
275
276DEFUN (show_zebra,
277 show_zebra_cmd,
278 "show zebra",
279 SHOW_STR
280 "Zebra information\n")
281{
282 int i;
283 if (!zclient)
284 vty_out (vty, "Not connected to zebra%s", VTY_NEWLINE);
285
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,
290 VTY_NEWLINE);
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",
294 VTY_NEWLINE);
295 return CMD_SUCCESS;
296}
297
298DEFUN (router_zebra,
299 router_zebra_cmd,
300 "router zebra",
301 "Enable a routing process\n"
302 "Make connection to zebra daemon\n")
303{
304 if (IS_OSPF6_DUMP_CONFIG)
305 zlog_info ("Config: router zebra");
306
307 vty->node = ZEBRA_NODE;
308 zclient->enable = 1;
309 zclient_start (zclient);
310 return CMD_SUCCESS;
311}
312
313DEFUN (no_router_zebra,
314 no_router_zebra_cmd,
315 "no router zebra",
316 NO_STR
317 "Configure routing process\n"
318 "Disable connection to zebra daemon\n")
319{
320 if (IS_OSPF6_DUMP_CONFIG)
321 zlog_info ("no router zebra");
322
323 zclient->enable = 0;
324 zclient_stop (zclient);
325 return CMD_SUCCESS;
326}
327
328/* Zebra configuration write function. */
329int
330ospf6_zebra_config_write (struct vty *vty)
331{
332 if (! zclient->enable)
333 {
334 vty_out (vty, "no router zebra%s", VTY_NEWLINE);
335 return 1;
336 }
337 else if (! zclient->redist[ZEBRA_ROUTE_OSPF6])
338 {
339 vty_out (vty, "router zebra%s", VTY_NEWLINE);
340 vty_out (vty, " no redistribute ospf6%s", VTY_NEWLINE);
341 return 1;
342 }
343 return 0;
344}
345
346/* Zebra node structure. */
347struct cmd_node zebra_node =
348{
349 ZEBRA_NODE,
350 "%s(config-zebra)# ",
paul733e8102003-05-18 15:26:26 +0000351 vtysh: 0
paul718e3742002-12-13 20:15:29 +0000352};
353
354#define ADD 0
355#define CHANGE 1
356#define REMOVE 2
357
358static void
359ospf6_zebra_route_update (int type, struct ospf6_route_req *request)
360{
361 char buf[96], ifname[IFNAMSIZ];
362
363 struct zapi_ipv6 api;
364 struct ospf6_route_req route;
365 struct linklist *nexthop_list;
366 struct linklist_node node;
367 struct ospf6_nexthop *nexthop = NULL;
368 struct in6_addr **nexthops;
369 unsigned int *ifindexes;
370 struct prefix_ipv6 *p;
371 int i, ret = 0;
372
373 if (IS_OSPF6_DUMP_ZEBRA)
374 {
375 prefix2str (&request->route.prefix, buf, sizeof (buf));
376 if (type == REMOVE)
377 zlog_info ("ZEBRA: Send remove route: %s", buf);
378 else
379 zlog_info ("ZEBRA: Send add route: %s", buf);
380 }
381
382 if (zclient->sock < 0)
383 {
384 if (IS_OSPF6_DUMP_ZEBRA)
385 zlog_info ("ZEBRA: failed: not connected to zebra");
386 return;
387 }
388
389 if (request->path.origin.adv_router == ospf6->router_id &&
390 (request->path.type == OSPF6_PATH_TYPE_EXTERNAL1 ||
391 request->path.type == OSPF6_PATH_TYPE_EXTERNAL2))
392 {
393 if (IS_OSPF6_DUMP_ZEBRA)
394 zlog_info ("ZEBRA: self originated external route, ignore");
395 return;
396 }
397
398 /* Only the best path (i.e. the first path of the path-list
399 in 'struct ospf6_route') will be sent to zebra. */
400 ospf6_route_lookup (&route, &request->route.prefix, request->table);
401 if (memcmp (&route.path, &request->path, sizeof (route.path)))
402 {
403 /* this is not preferred best route, ignore */
404 if (IS_OSPF6_DUMP_ZEBRA)
405 zlog_info ("ZEBRA: not best path, ignore");
406 return;
407 }
408
409 nexthop_list = linklist_create ();
410
411 /* for each nexthop */
412 for (ospf6_route_lookup (&route, &request->route.prefix, request->table);
413 ! ospf6_route_end (&route); ospf6_route_next (&route))
414 {
415 if (memcmp (&route.path, &request->path, sizeof (route.path)))
416 break;
417
418 #define IN6_IS_ILLEGAL_NEXTHOP(a)\
419 ((*(u_int32_t *)(void *)(&(a)->s6_addr[0]) == 0xffffffff) &&\
420 (*(u_int32_t *)(void *)(&(a)->s6_addr[4]) == 0xffffffff) &&\
421 (*(u_int32_t *)(void *)(&(a)->s6_addr[8]) == 0xffffffff) &&\
422 (*(u_int32_t *)(void *)(&(a)->s6_addr[12]) == 0xffffffff))
423 if (IN6_IS_ILLEGAL_NEXTHOP (&route.nexthop.address))
424 {
425 zlog_warn ("ZEBRA: Illegal nexthop");
426 continue;
427 }
428
429 if (type == REMOVE && ! memcmp (&route.nexthop, &request->nexthop,
430 sizeof (struct ospf6_nexthop)))
431 continue;
432
433 nexthop = XCALLOC (MTYPE_OSPF6_OTHER, sizeof (struct ospf6_nexthop));
434 if (! nexthop)
435 {
436 zlog_warn ("ZEBRA: Can't update nexthop: malloc failed");
437 continue;
438 }
439
440 memcpy (nexthop, &route.nexthop, sizeof (struct ospf6_nexthop));
441 linklist_add (nexthop, nexthop_list);
442 }
443
444 if (type == REMOVE && nexthop_list->count != 0)
445 type = ADD;
446 else if (type == REMOVE && nexthop_list->count == 0)
447 {
448 if (IS_OSPF6_DUMP_ZEBRA)
449 zlog_info ("ZEBRA: all nexthop with the selected path has gone");
450
451 if (! memcmp (&request->route, &route.route,
452 sizeof (struct ospf6_route)))
453 {
454 /* send 'add' of alternative route */
455 struct ospf6_path seconde_path;
456
457 if (IS_OSPF6_DUMP_ZEBRA)
458 zlog_info ("ZEBRA: found alternative path to add");
459
460 memcpy (&seconde_path, &route.path, sizeof (struct ospf6_path));
461 type = ADD;
462
463 while (! memcmp (&seconde_path, &route.path,
464 sizeof (struct ospf6_path)))
465 {
466 nexthop = XCALLOC (MTYPE_OSPF6_OTHER,
467 sizeof (struct ospf6_nexthop));
468 if (! nexthop)
469 zlog_warn ("ZEBRA: Can't update nexthop: malloc failed");
470 else
471 {
472 memcpy (nexthop, &route.nexthop,
473 sizeof (struct ospf6_nexthop));
474 linklist_add (nexthop, nexthop_list);
475 }
476
477 ospf6_route_next (&route);
478 }
479 }
480 else
481 {
482 /* there is no alternative route. send 'remove' to zebra for
483 requested route */
484 if (IS_OSPF6_DUMP_ZEBRA)
485 zlog_info ("ZEBRA: can't find alternative path, remove");
486
487 if (IS_OSPF6_DUMP_ZEBRA)
488 {
489 zlog_info ("ZEBRA: Debug: walk over the route ?");
490 ospf6_route_log_request ("Debug route", "***", &route);
491 ospf6_route_log_request ("Debug request", "***", request);
492 }
493
494 nexthop = XCALLOC (MTYPE_OSPF6_OTHER,
495 sizeof (struct ospf6_nexthop));
496 if (! nexthop)
497 zlog_warn ("ZEBRA: Can't update nexthop: malloc failed");
498 else
499 {
500 memcpy (nexthop, &request->nexthop,
501 sizeof (struct ospf6_nexthop));
502 linklist_add (nexthop, nexthop_list);
503 }
504 }
505 }
506
507 if (nexthop_list->count == 0)
508 {
509 if (IS_OSPF6_DUMP_ZEBRA)
510 zlog_info ("ZEBRA: no nexthop, ignore");
511 linklist_delete (nexthop_list);
512 return;
513 }
514
515 /* allocate memory for nexthop_list */
516 nexthops = XCALLOC (MTYPE_OSPF6_OTHER,
517 nexthop_list->count * sizeof (struct in6_addr *));
518 if (! nexthops)
519 {
520 zlog_warn ("ZEBRA: Can't update zebra route: malloc failed");
521 for (linklist_head (nexthop_list, &node); !linklist_end (&node);
522 linklist_next (&node))
523 XFREE (MTYPE_OSPF6_OTHER, node.data);
524 linklist_delete (nexthop_list);
525 return;
526 }
527
528 /* allocate memory for ifindex_list */
529 ifindexes = XCALLOC (MTYPE_OSPF6_OTHER,
530 nexthop_list->count * sizeof (unsigned int));
531 if (! ifindexes)
532 {
533 zlog_warn ("ZEBRA: Can't update zebra route: malloc failed");
534 for (linklist_head (nexthop_list, &node); !linklist_end (&node);
535 linklist_next (&node))
536 XFREE (MTYPE_OSPF6_OTHER, node.data);
537 linklist_delete (nexthop_list);
538 XFREE (MTYPE_OSPF6_OTHER, nexthops);
539 return;
540 }
541
542 i = 0;
543 for (linklist_head (nexthop_list, &node); ! linklist_end (&node);
544 linklist_next (&node))
545 {
546 nexthop = node.data;
547 if (IS_OSPF6_DUMP_ZEBRA)
548 {
549 inet_ntop (AF_INET6, &nexthop->address, buf, sizeof (buf));
550 if_indextoname (nexthop->ifindex, ifname);
551 zlog_info ("ZEBRA: nexthop: %s%%%s(%d)",
552 buf, ifname, nexthop->ifindex);
553 }
554 nexthops[i] = &nexthop->address;
555 ifindexes[i] = nexthop->ifindex;
556 i++;
557 }
558
559 api.type = ZEBRA_ROUTE_OSPF6;
560 api.flags = 0;
561 api.message = 0;
562 SET_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP);
563 SET_FLAG (api.message, ZAPI_MESSAGE_IFINDEX);
564 api.nexthop_num = nexthop_list->count;
565 api.nexthop = nexthops;
566 api.ifindex_num = nexthop_list->count;
567 api.ifindex = ifindexes;
568
569 p = (struct prefix_ipv6 *) &request->route.prefix;
570 if (type == REMOVE && nexthop_list->count == 1)
571 ret = zapi_ipv6_delete (zclient, p, &api);
572 else
573 ret = zapi_ipv6_add (zclient, p, &api);
574
575 if (ret < 0)
576 zlog_err ("ZEBRA: zapi_ipv6_add () failed: %s", strerror (errno));
577
578 for (linklist_head (nexthop_list, &node); !linklist_end (&node);
579 linklist_next (&node))
580 XFREE (MTYPE_OSPF6_OTHER, node.data);
581 linklist_delete (nexthop_list);
582 XFREE (MTYPE_OSPF6_OTHER, nexthops);
583 XFREE (MTYPE_OSPF6_OTHER, ifindexes);
584
585 return;
586}
587
588void
589ospf6_zebra_route_update_add (struct ospf6_route_req *request)
590{
591 ospf6_zebra_route_update (ADD, request);
592}
593
594void
595ospf6_zebra_route_update_remove (struct ospf6_route_req *request)
596{
597 ospf6_zebra_route_update (REMOVE, request);
598}
599
600static void
601ospf6_zebra_redistribute_ospf6 ()
602{
603 struct route_node *node;
604
605 for (node = route_top (ospf6->route_table->table); node;
606 node = route_next (node))
607 {
608 if (! node || ! node->info)
609 continue;
610 ospf6_zebra_route_update_add (node->info);
611 }
612}
613
614static void
615ospf6_zebra_no_redistribute_ospf6 ()
616{
617 struct route_node *node;
618
619 if (! ospf6)
620 return;
621
622 for (node = route_top (ospf6->route_table->table); node;
623 node = route_next (node))
624 {
625 if (! node || ! node->info)
626 continue;
627
628 ospf6_zebra_route_update_remove (node->info);
629 }
630}
631
632
633DEFUN (redistribute_ospf6,
634 redistribute_ospf6_cmd,
635 "redistribute ospf6",
636 "Redistribute control\n"
637 "OSPF6 route\n")
638{
639 /* log */
640 if (IS_OSPF6_DUMP_CONFIG)
641 zlog_info ("Config: redistribute ospf6");
642
643 zclient->redist[ZEBRA_ROUTE_OSPF6] = 1;
644
645 /* set zebra route table */
646 ospf6_zebra_redistribute_ospf6 ();
647
648 return CMD_SUCCESS;
649}
650
651DEFUN (no_redistribute_ospf6,
652 no_redistribute_ospf6_cmd,
653 "no redistribute ospf6",
654 NO_STR
655 "Redistribute control\n"
656 "OSPF6 route\n")
657{
658 /* log */
659 if (IS_OSPF6_DUMP_CONFIG)
660 zlog_info ("Config: no redistribute ospf6");
661
662 zclient->redist[ZEBRA_ROUTE_OSPF6] = 0;
663
664 if (! ospf6)
665 return CMD_SUCCESS;
666
667 /* clean up zebra route table */
668 ospf6_zebra_no_redistribute_ospf6 ();
669
670 ospf6_route_hook_unregister (ospf6_zebra_route_update_add,
671 ospf6_zebra_route_update_add,
672 ospf6_zebra_route_update_remove,
673 ospf6->route_table);
674
675 return CMD_SUCCESS;
676}
677
678void
679ospf6_zebra_init ()
680{
681 /* Allocate zebra structure. */
682 zclient = zclient_new ();
683 zclient_init (zclient, ZEBRA_ROUTE_OSPF6);
684 zclient->interface_add = ospf6_zebra_if_add;
685 zclient->interface_delete = ospf6_zebra_if_del;
686 zclient->interface_up = ospf6_zebra_if_state_update;
687 zclient->interface_down = ospf6_zebra_if_state_update;
688 zclient->interface_address_add = ospf6_zebra_if_address_update_add;
689 zclient->interface_address_delete = ospf6_zebra_if_address_update_delete;
690 zclient->ipv4_route_add = NULL;
691 zclient->ipv4_route_delete = NULL;
692 zclient->ipv6_route_add = ospf6_zebra_read_ipv6;
693 zclient->ipv6_route_delete = ospf6_zebra_read_ipv6;
694
695 /* redistribute connected route by default */
696 /* ospf6_zebra_redistribute (ZEBRA_ROUTE_CONNECT); */
697
698 /* Install zebra node. */
699 install_node (&zebra_node, ospf6_zebra_config_write);
700
701 /* Install command element for zebra node. */
702 install_element (VIEW_NODE, &show_zebra_cmd);
703 install_element (ENABLE_NODE, &show_zebra_cmd);
704 install_element (CONFIG_NODE, &router_zebra_cmd);
705 install_element (CONFIG_NODE, &no_router_zebra_cmd);
706 install_default (ZEBRA_NODE);
707 install_element (ZEBRA_NODE, &redistribute_ospf6_cmd);
708 install_element (ZEBRA_NODE, &no_redistribute_ospf6_cmd);
709
710#if 0
711 hook.name = "ZebraRouteUpdate";
712 hook.hook_add = ospf6_zebra_route_update_add;
713 hook.hook_change = ospf6_zebra_route_update_add;
714 hook.hook_remove = ospf6_zebra_route_update_remove;
715 ospf6_hook_register (&hook, &route_hook);
716#endif
717
718 return;
719}
720
721void
722ospf6_zebra_finish ()
723{
724 zclient_stop (zclient);
725 zclient_free (zclient);
726 zclient = (struct zclient *) NULL;
727}
728