]> git.proxmox.com Git - mirror_frr.git/blob - ospf6d/ospf6_zebra.c
Initial revision
[mirror_frr.git] / ospf6d / ospf6_zebra.c
1 /*
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. */
30 struct zclient *zclient = NULL;
31
32 /* redistribute function */
33 void
34 ospf6_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
53 void
54 ospf6_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
73 int
74 ospf6_zebra_is_redistribute (int type)
75 {
76 return zclient->redist[type];
77 }
78
79
80 /* Inteface addition message from zebra. */
81 int
82 ospf6_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
98 int
99 ospf6_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
117 int
118 ospf6_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
134 int
135 ospf6_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
157 int
158 ospf6_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 \f
182 const 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
195 const char *zebra_route_abname[ZEBRA_ROUTE_MAX] =
196 { "X", "K", "C", "S", "r", "R", "o", "O", "B" };
197
198 int
199 ospf6_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 \f
276 DEFUN (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
298 DEFUN (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
313 DEFUN (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. */
329 int
330 ospf6_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. */
347 struct cmd_node zebra_node =
348 {
349 ZEBRA_NODE,
350 "%s(config-zebra)# ",
351 };
352
353 #define ADD 0
354 #define CHANGE 1
355 #define REMOVE 2
356
357 static void
358 ospf6_zebra_route_update (int type, struct ospf6_route_req *request)
359 {
360 char buf[96], ifname[IFNAMSIZ];
361
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;
370 int i, ret = 0;
371
372 if (IS_OSPF6_DUMP_ZEBRA)
373 {
374 prefix2str (&request->route.prefix, buf, sizeof (buf));
375 if (type == REMOVE)
376 zlog_info ("ZEBRA: Send remove route: %s", buf);
377 else
378 zlog_info ("ZEBRA: Send add route: %s", buf);
379 }
380
381 if (zclient->sock < 0)
382 {
383 if (IS_OSPF6_DUMP_ZEBRA)
384 zlog_info ("ZEBRA: failed: not connected to zebra");
385 return;
386 }
387
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))
391 {
392 if (IS_OSPF6_DUMP_ZEBRA)
393 zlog_info ("ZEBRA: self originated external route, ignore");
394 return;
395 }
396
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)))
401 {
402 /* this is not preferred best route, ignore */
403 if (IS_OSPF6_DUMP_ZEBRA)
404 zlog_info ("ZEBRA: not best path, ignore");
405 return;
406 }
407
408 nexthop_list = linklist_create ();
409
410 /* for each nexthop */
411 for (ospf6_route_lookup (&route, &request->route.prefix, request->table);
412 ! ospf6_route_end (&route); ospf6_route_next (&route))
413 {
414 if (memcmp (&route.path, &request->path, sizeof (route.path)))
415 break;
416
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))
423 {
424 zlog_warn ("ZEBRA: Illegal nexthop");
425 continue;
426 }
427
428 if (type == REMOVE && ! memcmp (&route.nexthop, &request->nexthop,
429 sizeof (struct ospf6_nexthop)))
430 continue;
431
432 nexthop = XCALLOC (MTYPE_OSPF6_OTHER, sizeof (struct ospf6_nexthop));
433 if (! nexthop)
434 {
435 zlog_warn ("ZEBRA: Can't update nexthop: malloc failed");
436 continue;
437 }
438
439 memcpy (nexthop, &route.nexthop, sizeof (struct ospf6_nexthop));
440 linklist_add (nexthop, nexthop_list);
441 }
442
443 if (type == REMOVE && nexthop_list->count != 0)
444 type = ADD;
445 else if (type == REMOVE && nexthop_list->count == 0)
446 {
447 if (IS_OSPF6_DUMP_ZEBRA)
448 zlog_info ("ZEBRA: all nexthop with the selected path has gone");
449
450 if (! memcmp (&request->route, &route.route,
451 sizeof (struct ospf6_route)))
452 {
453 /* send 'add' of alternative route */
454 struct ospf6_path seconde_path;
455
456 if (IS_OSPF6_DUMP_ZEBRA)
457 zlog_info ("ZEBRA: found alternative path to add");
458
459 memcpy (&seconde_path, &route.path, sizeof (struct ospf6_path));
460 type = ADD;
461
462 while (! memcmp (&seconde_path, &route.path,
463 sizeof (struct ospf6_path)))
464 {
465 nexthop = XCALLOC (MTYPE_OSPF6_OTHER,
466 sizeof (struct ospf6_nexthop));
467 if (! nexthop)
468 zlog_warn ("ZEBRA: Can't update nexthop: malloc failed");
469 else
470 {
471 memcpy (nexthop, &route.nexthop,
472 sizeof (struct ospf6_nexthop));
473 linklist_add (nexthop, nexthop_list);
474 }
475
476 ospf6_route_next (&route);
477 }
478 }
479 else
480 {
481 /* there is no alternative route. send 'remove' to zebra for
482 requested route */
483 if (IS_OSPF6_DUMP_ZEBRA)
484 zlog_info ("ZEBRA: can't find alternative path, remove");
485
486 if (IS_OSPF6_DUMP_ZEBRA)
487 {
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);
491 }
492
493 nexthop = XCALLOC (MTYPE_OSPF6_OTHER,
494 sizeof (struct ospf6_nexthop));
495 if (! nexthop)
496 zlog_warn ("ZEBRA: Can't update nexthop: malloc failed");
497 else
498 {
499 memcpy (nexthop, &request->nexthop,
500 sizeof (struct ospf6_nexthop));
501 linklist_add (nexthop, nexthop_list);
502 }
503 }
504 }
505
506 if (nexthop_list->count == 0)
507 {
508 if (IS_OSPF6_DUMP_ZEBRA)
509 zlog_info ("ZEBRA: no nexthop, ignore");
510 linklist_delete (nexthop_list);
511 return;
512 }
513
514 /* allocate memory for nexthop_list */
515 nexthops = XCALLOC (MTYPE_OSPF6_OTHER,
516 nexthop_list->count * sizeof (struct in6_addr *));
517 if (! nexthops)
518 {
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);
524 return;
525 }
526
527 /* allocate memory for ifindex_list */
528 ifindexes = XCALLOC (MTYPE_OSPF6_OTHER,
529 nexthop_list->count * sizeof (unsigned int));
530 if (! ifindexes)
531 {
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);
538 return;
539 }
540
541 i = 0;
542 for (linklist_head (nexthop_list, &node); ! linklist_end (&node);
543 linklist_next (&node))
544 {
545 nexthop = node.data;
546 if (IS_OSPF6_DUMP_ZEBRA)
547 {
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);
552 }
553 nexthops[i] = &nexthop->address;
554 ifindexes[i] = nexthop->ifindex;
555 i++;
556 }
557
558 api.type = ZEBRA_ROUTE_OSPF6;
559 api.flags = 0;
560 api.message = 0;
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;
567
568 p = (struct prefix_ipv6 *) &request->route.prefix;
569 if (type == REMOVE && nexthop_list->count == 1)
570 ret = zapi_ipv6_delete (zclient, p, &api);
571 else
572 ret = zapi_ipv6_add (zclient, p, &api);
573
574 if (ret < 0)
575 zlog_err ("ZEBRA: zapi_ipv6_add () failed: %s", strerror (errno));
576
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);
583
584 return;
585 }
586
587 void
588 ospf6_zebra_route_update_add (struct ospf6_route_req *request)
589 {
590 ospf6_zebra_route_update (ADD, request);
591 }
592
593 void
594 ospf6_zebra_route_update_remove (struct ospf6_route_req *request)
595 {
596 ospf6_zebra_route_update (REMOVE, request);
597 }
598
599 static void
600 ospf6_zebra_redistribute_ospf6 ()
601 {
602 struct route_node *node;
603
604 for (node = route_top (ospf6->route_table->table); node;
605 node = route_next (node))
606 {
607 if (! node || ! node->info)
608 continue;
609 ospf6_zebra_route_update_add (node->info);
610 }
611 }
612
613 static void
614 ospf6_zebra_no_redistribute_ospf6 ()
615 {
616 struct route_node *node;
617
618 if (! ospf6)
619 return;
620
621 for (node = route_top (ospf6->route_table->table); node;
622 node = route_next (node))
623 {
624 if (! node || ! node->info)
625 continue;
626
627 ospf6_zebra_route_update_remove (node->info);
628 }
629 }
630
631
632 DEFUN (redistribute_ospf6,
633 redistribute_ospf6_cmd,
634 "redistribute ospf6",
635 "Redistribute control\n"
636 "OSPF6 route\n")
637 {
638 /* log */
639 if (IS_OSPF6_DUMP_CONFIG)
640 zlog_info ("Config: redistribute ospf6");
641
642 zclient->redist[ZEBRA_ROUTE_OSPF6] = 1;
643
644 /* set zebra route table */
645 ospf6_zebra_redistribute_ospf6 ();
646
647 return CMD_SUCCESS;
648 }
649
650 DEFUN (no_redistribute_ospf6,
651 no_redistribute_ospf6_cmd,
652 "no redistribute ospf6",
653 NO_STR
654 "Redistribute control\n"
655 "OSPF6 route\n")
656 {
657 /* log */
658 if (IS_OSPF6_DUMP_CONFIG)
659 zlog_info ("Config: no redistribute ospf6");
660
661 zclient->redist[ZEBRA_ROUTE_OSPF6] = 0;
662
663 if (! ospf6)
664 return CMD_SUCCESS;
665
666 /* clean up zebra route table */
667 ospf6_zebra_no_redistribute_ospf6 ();
668
669 ospf6_route_hook_unregister (ospf6_zebra_route_update_add,
670 ospf6_zebra_route_update_add,
671 ospf6_zebra_route_update_remove,
672 ospf6->route_table);
673
674 return CMD_SUCCESS;
675 }
676
677 void
678 ospf6_zebra_init ()
679 {
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;
693
694 /* redistribute connected route by default */
695 /* ospf6_zebra_redistribute (ZEBRA_ROUTE_CONNECT); */
696
697 /* Install zebra node. */
698 install_node (&zebra_node, ospf6_zebra_config_write);
699
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);
708
709 #if 0
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);
715 #endif
716
717 return;
718 }
719
720 void
721 ospf6_zebra_finish ()
722 {
723 zclient_stop (zclient);
724 zclient_free (zclient);
725 zclient = (struct zclient *) NULL;
726 }
727