]> git.proxmox.com Git - mirror_frr.git/blob - ospf6d/ospf6_interface.c
Merge pull request #12447 from karlquan/master
[mirror_frr.git] / ospf6d / ospf6_interface.c
1 /*
2 * Copyright (C) 2003 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 along
17 * with this program; see the file COPYING; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19 */
20
21 #include <zebra.h>
22
23 #include "memory.h"
24 #include "if.h"
25 #include "log.h"
26 #include "command.h"
27 #include "thread.h"
28 #include "prefix.h"
29 #include "plist.h"
30 #include "zclient.h"
31
32 #include "ospf6_lsa.h"
33 #include "ospf6_lsdb.h"
34 #include "ospf6_top.h"
35 #include "ospf6_network.h"
36 #include "ospf6_message.h"
37 #include "ospf6_route.h"
38 #include "ospf6_area.h"
39 #include "ospf6_abr.h"
40 #include "ospf6_nssa.h"
41 #include "ospf6_interface.h"
42 #include "ospf6_neighbor.h"
43 #include "ospf6_intra.h"
44 #include "ospf6_spf.h"
45 #include "ospf6d.h"
46 #include "ospf6_bfd.h"
47 #include "ospf6_zebra.h"
48 #include "ospf6_gr.h"
49 #include "lib/json.h"
50 #include "ospf6_proto.h"
51 #include "lib/keychain.h"
52 #include "ospf6_auth_trailer.h"
53
54 DEFINE_MTYPE_STATIC(OSPF6D, OSPF6_IF, "OSPF6 interface");
55 DEFINE_MTYPE(OSPF6D, OSPF6_AUTH_KEYCHAIN, "OSPF6 auth keychain");
56 DEFINE_MTYPE(OSPF6D, OSPF6_AUTH_MANUAL_KEY, "OSPF6 auth key");
57 DEFINE_MTYPE_STATIC(OSPF6D, CFG_PLIST_NAME, "configured prefix list names");
58 DEFINE_QOBJ_TYPE(ospf6_interface);
59 DEFINE_HOOK(ospf6_interface_change,
60 (struct ospf6_interface * oi, int state, int old_state),
61 (oi, state, old_state));
62
63 unsigned char conf_debug_ospf6_interface = 0;
64
65 const char *const ospf6_interface_state_str[] = {
66 "None", "Down", "Loopback", "Waiting", "PointToPoint",
67 "DROther", "BDR", "DR", NULL};
68
69 int ospf6_interface_neighbor_count(struct ospf6_interface *oi)
70 {
71 int count = 0;
72 struct ospf6_neighbor *nbr = NULL;
73 struct listnode *node;
74
75 for (ALL_LIST_ELEMENTS_RO(oi->neighbor_list, node, nbr)) {
76 /* Down state is not shown. */
77 if (nbr->state == OSPF6_NEIGHBOR_DOWN)
78 continue;
79 count++;
80 }
81
82 return count;
83 }
84
85 struct ospf6_interface *ospf6_interface_lookup_by_ifindex(ifindex_t ifindex,
86 vrf_id_t vrf_id)
87 {
88 struct ospf6_interface *oi;
89 struct interface *ifp;
90
91 ifp = if_lookup_by_index(ifindex, vrf_id);
92 if (ifp == NULL)
93 return (struct ospf6_interface *)NULL;
94
95 oi = (struct ospf6_interface *)ifp->info;
96 return oi;
97 }
98
99 /* schedule routing table recalculation */
100 static void ospf6_interface_lsdb_hook(struct ospf6_lsa *lsa,
101 unsigned int reason)
102 {
103 struct ospf6_interface *oi;
104
105 if (lsa == NULL)
106 return;
107
108 oi = lsa->lsdb->data;
109 switch (ntohs(lsa->header->type)) {
110 case OSPF6_LSTYPE_LINK:
111 if (oi->state == OSPF6_INTERFACE_DR)
112 OSPF6_INTRA_PREFIX_LSA_SCHEDULE_TRANSIT(oi);
113 if (oi->area)
114 ospf6_spf_schedule(oi->area->ospf6, reason);
115 break;
116
117 default:
118 break;
119 }
120 }
121
122 static void ospf6_interface_lsdb_hook_add(struct ospf6_lsa *lsa)
123 {
124 ospf6_interface_lsdb_hook(lsa, ospf6_lsadd_to_spf_reason(lsa));
125 }
126
127 static void ospf6_interface_lsdb_hook_remove(struct ospf6_lsa *lsa)
128 {
129 ospf6_interface_lsdb_hook(lsa, ospf6_lsremove_to_spf_reason(lsa));
130 }
131
132 static uint8_t ospf6_default_iftype(struct interface *ifp)
133 {
134 if (if_is_pointopoint(ifp))
135 return OSPF_IFTYPE_POINTOPOINT;
136 else if (if_is_loopback(ifp))
137 return OSPF_IFTYPE_LOOPBACK;
138 else
139 return OSPF_IFTYPE_BROADCAST;
140 }
141
142 static uint32_t ospf6_interface_get_cost(struct ospf6_interface *oi)
143 {
144 /* If all else fails, use default OSPF cost */
145 uint32_t cost;
146 uint32_t bw, refbw;
147 struct ospf6 *ospf6;
148 /* interface speed and bw can be 0 in some platforms,
149 * use ospf default bw. If bw is configured then it would
150 * be used.
151 */
152 if (!oi->interface->bandwidth && oi->interface->speed) {
153 bw = oi->interface->speed;
154 } else {
155 bw = oi->interface->bandwidth ? oi->interface->bandwidth
156 : OSPF6_INTERFACE_BANDWIDTH;
157 }
158
159 ospf6 = oi->interface->vrf->info;
160 refbw = ospf6 ? ospf6->ref_bandwidth : OSPF6_REFERENCE_BANDWIDTH;
161
162 /* A specified ip ospf cost overrides a calculated one. */
163 if (CHECK_FLAG(oi->flag, OSPF6_INTERFACE_NOAUTOCOST))
164 cost = oi->cost;
165 else {
166 cost = (uint32_t)((double)refbw / (double)bw + (double)0.5);
167 if (cost < 1)
168 cost = 1;
169 }
170
171 return cost;
172 }
173
174 static void ospf6_interface_force_recalculate_cost(struct ospf6_interface *oi)
175 {
176 /* update cost held in route_connected list in ospf6_interface */
177 ospf6_interface_connected_route_update(oi->interface);
178
179 /* execute LSA hooks */
180 if (oi->area) {
181 OSPF6_LINK_LSA_SCHEDULE(oi);
182 OSPF6_ROUTER_LSA_SCHEDULE(oi->area);
183 OSPF6_NETWORK_LSA_SCHEDULE(oi);
184 OSPF6_INTRA_PREFIX_LSA_SCHEDULE_TRANSIT(oi);
185 OSPF6_INTRA_PREFIX_LSA_SCHEDULE_STUB(oi->area);
186 }
187 }
188
189 static void ospf6_interface_recalculate_cost(struct ospf6_interface *oi)
190 {
191 uint32_t newcost;
192
193 newcost = ospf6_interface_get_cost(oi);
194 if (newcost == oi->cost)
195 return;
196 oi->cost = newcost;
197
198 ospf6_interface_force_recalculate_cost(oi);
199 }
200
201 /* Create new ospf6 interface structure */
202 struct ospf6_interface *ospf6_interface_create(struct interface *ifp)
203 {
204 struct ospf6_interface *oi;
205 unsigned int iobuflen;
206
207 oi = XCALLOC(MTYPE_OSPF6_IF, sizeof(struct ospf6_interface));
208
209 oi->obuf = ospf6_fifo_new();
210
211 oi->area = (struct ospf6_area *)NULL;
212 oi->neighbor_list = list_new();
213 oi->neighbor_list->cmp = ospf6_neighbor_cmp;
214 oi->linklocal_addr = (struct in6_addr *)NULL;
215 oi->instance_id = OSPF6_INTERFACE_INSTANCE_ID;
216 oi->transdelay = OSPF6_INTERFACE_TRANSDELAY;
217 oi->priority = OSPF6_INTERFACE_PRIORITY;
218
219 oi->hello_interval = OSPF_HELLO_INTERVAL_DEFAULT;
220 oi->dead_interval = OSPF_ROUTER_DEAD_INTERVAL_DEFAULT;
221 oi->rxmt_interval = OSPF_RETRANSMIT_INTERVAL_DEFAULT;
222 oi->type = ospf6_default_iftype(ifp);
223 oi->state = OSPF6_INTERFACE_DOWN;
224 oi->flag = 0;
225 oi->mtu_ignore = 0;
226 oi->c_ifmtu = 0;
227
228 /* Try to adjust I/O buffer size with IfMtu */
229 oi->ifmtu = ifp->mtu6;
230 iobuflen = ospf6_iobuf_size(ifp->mtu6);
231 if (oi->ifmtu > iobuflen) {
232 if (IS_OSPF6_DEBUG_INTERFACE)
233 zlog_debug(
234 "Interface %s: IfMtu is adjusted to I/O buffer size: %d.",
235 ifp->name, iobuflen);
236 oi->ifmtu = iobuflen;
237 }
238
239 QOBJ_REG(oi, ospf6_interface);
240
241 oi->lsupdate_list = ospf6_lsdb_create(oi);
242 oi->lsack_list = ospf6_lsdb_create(oi);
243 oi->lsdb = ospf6_lsdb_create(oi);
244 oi->lsdb->hook_add = ospf6_interface_lsdb_hook_add;
245 oi->lsdb->hook_remove = ospf6_interface_lsdb_hook_remove;
246 oi->lsdb_self = ospf6_lsdb_create(oi);
247
248 oi->route_connected =
249 OSPF6_ROUTE_TABLE_CREATE(INTERFACE, CONNECTED_ROUTES);
250 oi->route_connected->scope = oi;
251
252 /* link both */
253 oi->interface = ifp;
254 ifp->info = oi;
255
256 /* Compute cost. */
257 oi->cost = ospf6_interface_get_cost(oi);
258
259 oi->at_data.flags = 0;
260
261 return oi;
262 }
263
264 void ospf6_interface_delete(struct ospf6_interface *oi)
265 {
266 struct listnode *node, *nnode;
267 struct ospf6_neighbor *on;
268
269 QOBJ_UNREG(oi);
270
271 ospf6_fifo_free(oi->obuf);
272
273 for (ALL_LIST_ELEMENTS(oi->neighbor_list, node, nnode, on))
274 ospf6_neighbor_delete(on);
275
276 list_delete(&oi->neighbor_list);
277
278 THREAD_OFF(oi->thread_send_hello);
279 THREAD_OFF(oi->thread_send_lsupdate);
280 THREAD_OFF(oi->thread_send_lsack);
281 THREAD_OFF(oi->thread_sso);
282 THREAD_OFF(oi->thread_wait_timer);
283
284 ospf6_lsdb_remove_all(oi->lsdb);
285 ospf6_lsdb_remove_all(oi->lsupdate_list);
286 ospf6_lsdb_remove_all(oi->lsack_list);
287
288 ospf6_lsdb_delete(oi->lsdb);
289 ospf6_lsdb_delete(oi->lsdb_self);
290
291 ospf6_lsdb_delete(oi->lsupdate_list);
292 ospf6_lsdb_delete(oi->lsack_list);
293
294 ospf6_route_table_delete(oi->route_connected);
295
296 /* cut link */
297 oi->interface->info = NULL;
298
299 /* plist_name */
300 if (oi->plist_name)
301 XFREE(MTYPE_CFG_PLIST_NAME, oi->plist_name);
302
303 /* disable from area list if possible */
304 ospf6_area_interface_delete(oi);
305
306 /* Free BFD allocated data. */
307 XFREE(MTYPE_TMP, oi->bfd_config.profile);
308
309 XFREE(MTYPE_OSPF6_IF, oi);
310 }
311
312 void ospf6_interface_enable(struct ospf6_interface *oi)
313 {
314 UNSET_FLAG(oi->flag, OSPF6_INTERFACE_DISABLE);
315 ospf6_interface_state_update(oi->interface);
316 }
317
318 void ospf6_interface_disable(struct ospf6_interface *oi)
319 {
320 SET_FLAG(oi->flag, OSPF6_INTERFACE_DISABLE);
321
322 thread_execute(master, interface_down, oi, 0);
323
324 ospf6_lsdb_remove_all(oi->lsdb);
325 ospf6_lsdb_remove_all(oi->lsdb_self);
326 ospf6_lsdb_remove_all(oi->lsupdate_list);
327 ospf6_lsdb_remove_all(oi->lsack_list);
328
329 THREAD_OFF(oi->thread_send_hello);
330 THREAD_OFF(oi->thread_send_lsupdate);
331 THREAD_OFF(oi->thread_send_lsack);
332 THREAD_OFF(oi->thread_sso);
333
334 THREAD_OFF(oi->thread_network_lsa);
335 THREAD_OFF(oi->thread_link_lsa);
336 THREAD_OFF(oi->thread_intra_prefix_lsa);
337 THREAD_OFF(oi->thread_as_extern_lsa);
338 THREAD_OFF(oi->thread_wait_timer);
339 }
340
341 static struct in6_addr *
342 ospf6_interface_get_linklocal_address(struct interface *ifp)
343 {
344 struct listnode *n;
345 struct connected *c;
346 struct in6_addr *l = (struct in6_addr *)NULL;
347
348 /* for each connected address */
349 for (ALL_LIST_ELEMENTS_RO(ifp->connected, n, c)) {
350 /* if family not AF_INET6, ignore */
351 if (c->address->family != AF_INET6)
352 continue;
353
354 /* linklocal scope check */
355 if (IN6_IS_ADDR_LINKLOCAL(&c->address->u.prefix6))
356 l = &c->address->u.prefix6;
357 }
358 return l;
359 }
360
361 void ospf6_interface_state_update(struct interface *ifp)
362 {
363 struct ospf6_interface *oi;
364 unsigned int iobuflen;
365
366 oi = (struct ospf6_interface *)ifp->info;
367 if (oi == NULL)
368 return;
369 if (CHECK_FLAG(oi->flag, OSPF6_INTERFACE_DISABLE))
370 return;
371
372 /* Adjust the mtu values if the kernel told us something new */
373 if (ifp->mtu6 != oi->ifmtu) {
374 /* If nothing configured, accept it and check for buffer size */
375 if (!oi->c_ifmtu) {
376 oi->ifmtu = ifp->mtu6;
377 iobuflen = ospf6_iobuf_size(ifp->mtu6);
378 if (oi->ifmtu > iobuflen) {
379 if (IS_OSPF6_DEBUG_INTERFACE)
380 zlog_debug(
381 "Interface %s: IfMtu is adjusted to I/O buffer size: %d.",
382 ifp->name, iobuflen);
383 oi->ifmtu = iobuflen;
384 }
385 } else if (oi->c_ifmtu > ifp->mtu6) {
386 oi->ifmtu = ifp->mtu6;
387 zlog_warn(
388 "Configured mtu %u on %s overridden by kernel %u",
389 oi->c_ifmtu, ifp->name, ifp->mtu6);
390 } else
391 oi->ifmtu = oi->c_ifmtu;
392 }
393
394 if (if_is_operative(ifp)
395 && (ospf6_interface_get_linklocal_address(oi->interface)
396 || if_is_loopback(oi->interface)))
397 thread_execute(master, interface_up, oi, 0);
398 else
399 thread_execute(master, interface_down, oi, 0);
400
401 return;
402 }
403
404 void ospf6_interface_connected_route_update(struct interface *ifp)
405 {
406 struct ospf6_interface *oi;
407 struct ospf6_route *route;
408 struct connected *c;
409 struct listnode *node, *nnode;
410 struct in6_addr nh_addr;
411
412 oi = (struct ospf6_interface *)ifp->info;
413 if (oi == NULL)
414 return;
415
416 /* reset linklocal pointer */
417 oi->linklocal_addr = ospf6_interface_get_linklocal_address(ifp);
418
419 /* if area is null, do not make connected-route list */
420 if (oi->area == NULL)
421 return;
422
423 if (CHECK_FLAG(oi->flag, OSPF6_INTERFACE_DISABLE))
424 return;
425
426 /* update "route to advertise" interface route table */
427 ospf6_route_remove_all(oi->route_connected);
428
429 for (ALL_LIST_ELEMENTS(oi->interface->connected, node, nnode, c)) {
430 if (c->address->family != AF_INET6)
431 continue;
432
433 CONTINUE_IF_ADDRESS_LINKLOCAL(IS_OSPF6_DEBUG_INTERFACE,
434 c->address);
435 CONTINUE_IF_ADDRESS_UNSPECIFIED(IS_OSPF6_DEBUG_INTERFACE,
436 c->address);
437 CONTINUE_IF_ADDRESS_LOOPBACK(IS_OSPF6_DEBUG_INTERFACE,
438 c->address);
439 CONTINUE_IF_ADDRESS_V4COMPAT(IS_OSPF6_DEBUG_INTERFACE,
440 c->address);
441 CONTINUE_IF_ADDRESS_V4MAPPED(IS_OSPF6_DEBUG_INTERFACE,
442 c->address);
443
444 /* apply filter */
445 if (oi->plist_name) {
446 struct prefix_list *plist;
447 enum prefix_list_type ret;
448
449 plist = prefix_list_lookup(AFI_IP6, oi->plist_name);
450 ret = prefix_list_apply(plist, (void *)c->address);
451 if (ret == PREFIX_DENY) {
452 if (IS_OSPF6_DEBUG_INTERFACE)
453 zlog_debug(
454 "%pFX on %s filtered by prefix-list %s ",
455 c->address, oi->interface->name,
456 oi->plist_name);
457 continue;
458 }
459 }
460
461 route = ospf6_route_create(oi->area->ospf6);
462 memcpy(&route->prefix, c->address, sizeof(struct prefix));
463 apply_mask(&route->prefix);
464 route->type = OSPF6_DEST_TYPE_NETWORK;
465 route->path.area_id = oi->area->area_id;
466 route->path.type = OSPF6_PATH_TYPE_INTRA;
467 route->path.cost = oi->cost;
468 inet_pton(AF_INET6, "::1", &nh_addr);
469 ospf6_route_add_nexthop(route, oi->interface->ifindex,
470 &nh_addr);
471 ospf6_route_add(route, oi->route_connected);
472 }
473
474 /* create new Link-LSA */
475 OSPF6_LINK_LSA_SCHEDULE(oi);
476 OSPF6_INTRA_PREFIX_LSA_SCHEDULE_TRANSIT(oi);
477 OSPF6_INTRA_PREFIX_LSA_SCHEDULE_STUB(oi->area);
478 }
479
480 static int ospf6_interface_state_change(uint8_t next_state,
481 struct ospf6_interface *oi)
482 {
483 uint8_t prev_state;
484 struct ospf6 *ospf6;
485
486 prev_state = oi->state;
487 oi->state = next_state;
488
489 if (prev_state == next_state)
490 return -1;
491
492 if (!oi->area)
493 return -1;
494
495 /* log */
496 if (IS_OSPF6_DEBUG_INTERFACE) {
497 zlog_debug("Interface state change %s: %s -> %s",
498 oi->interface->name,
499 ospf6_interface_state_str[prev_state],
500 ospf6_interface_state_str[next_state]);
501 }
502 oi->state_change++;
503
504 ospf6 = oi->area->ospf6;
505
506 if ((prev_state == OSPF6_INTERFACE_DR
507 || prev_state == OSPF6_INTERFACE_BDR)
508 && (next_state != OSPF6_INTERFACE_DR
509 && next_state != OSPF6_INTERFACE_BDR))
510 ospf6_sso(oi->interface->ifindex, &alldrouters6,
511 IPV6_LEAVE_GROUP, ospf6->fd);
512
513 if ((prev_state != OSPF6_INTERFACE_DR
514 && prev_state != OSPF6_INTERFACE_BDR)
515 && (next_state == OSPF6_INTERFACE_DR
516 || next_state == OSPF6_INTERFACE_BDR))
517 ospf6_sso(oi->interface->ifindex, &alldrouters6,
518 IPV6_JOIN_GROUP, ospf6->fd);
519
520 OSPF6_ROUTER_LSA_SCHEDULE(oi->area);
521 OSPF6_LINK_LSA_SCHEDULE(oi);
522 if (next_state == OSPF6_INTERFACE_DOWN) {
523 OSPF6_NETWORK_LSA_EXECUTE(oi);
524 OSPF6_INTRA_PREFIX_LSA_EXECUTE_TRANSIT(oi);
525 OSPF6_INTRA_PREFIX_LSA_SCHEDULE_STUB(oi->area);
526 OSPF6_INTRA_PREFIX_LSA_EXECUTE_TRANSIT(oi);
527 } else if (prev_state == OSPF6_INTERFACE_DR
528 || next_state == OSPF6_INTERFACE_DR) {
529 OSPF6_NETWORK_LSA_SCHEDULE(oi);
530 OSPF6_INTRA_PREFIX_LSA_SCHEDULE_TRANSIT(oi);
531 OSPF6_INTRA_PREFIX_LSA_SCHEDULE_STUB(oi->area);
532 }
533
534 hook_call(ospf6_interface_change, oi, next_state, prev_state);
535
536 return 0;
537 }
538
539
540 /* DR Election, RFC2328 section 9.4 */
541
542 #define IS_ELIGIBLE(n) \
543 ((n)->state >= OSPF6_NEIGHBOR_TWOWAY && (n)->priority != 0)
544
545 static struct ospf6_neighbor *better_bdrouter(struct ospf6_neighbor *a,
546 struct ospf6_neighbor *b)
547 {
548 if ((a == NULL || !IS_ELIGIBLE(a) || a->drouter == a->router_id)
549 && (b == NULL || !IS_ELIGIBLE(b) || b->drouter == b->router_id))
550 return NULL;
551 else if (a == NULL || !IS_ELIGIBLE(a) || a->drouter == a->router_id)
552 return b;
553 else if (b == NULL || !IS_ELIGIBLE(b) || b->drouter == b->router_id)
554 return a;
555
556 if (a->bdrouter == a->router_id && b->bdrouter != b->router_id)
557 return a;
558 if (a->bdrouter != a->router_id && b->bdrouter == b->router_id)
559 return b;
560
561 if (a->priority > b->priority)
562 return a;
563 if (a->priority < b->priority)
564 return b;
565
566 if (ntohl(a->router_id) > ntohl(b->router_id))
567 return a;
568 if (ntohl(a->router_id) < ntohl(b->router_id))
569 return b;
570
571 zlog_warn("Router-ID duplicate ?");
572 return a;
573 }
574
575 static struct ospf6_neighbor *better_drouter(struct ospf6_neighbor *a,
576 struct ospf6_neighbor *b)
577 {
578 if ((a == NULL || !IS_ELIGIBLE(a) || a->drouter != a->router_id)
579 && (b == NULL || !IS_ELIGIBLE(b) || b->drouter != b->router_id))
580 return NULL;
581 else if (a == NULL || !IS_ELIGIBLE(a) || a->drouter != a->router_id)
582 return b;
583 else if (b == NULL || !IS_ELIGIBLE(b) || b->drouter != b->router_id)
584 return a;
585
586 if (a->drouter == a->router_id && b->drouter != b->router_id)
587 return a;
588 if (a->drouter != a->router_id && b->drouter == b->router_id)
589 return b;
590
591 if (a->priority > b->priority)
592 return a;
593 if (a->priority < b->priority)
594 return b;
595
596 if (ntohl(a->router_id) > ntohl(b->router_id))
597 return a;
598 if (ntohl(a->router_id) < ntohl(b->router_id))
599 return b;
600
601 zlog_warn("Router-ID duplicate ?");
602 return a;
603 }
604
605 uint8_t dr_election(struct ospf6_interface *oi)
606 {
607 struct listnode *node, *nnode;
608 struct ospf6_neighbor *on, *drouter, *bdrouter, myself;
609 struct ospf6_neighbor *best_drouter, *best_bdrouter;
610 uint8_t next_state = 0;
611
612 drouter = bdrouter = NULL;
613 best_drouter = best_bdrouter = NULL;
614
615 /* pseudo neighbor myself, including noting current DR/BDR (1) */
616 memset(&myself, 0, sizeof(myself));
617 inet_ntop(AF_INET, &oi->area->ospf6->router_id, myself.name,
618 sizeof(myself.name));
619 myself.state = OSPF6_NEIGHBOR_TWOWAY;
620 myself.drouter = oi->drouter;
621 myself.bdrouter = oi->bdrouter;
622 myself.priority = oi->priority;
623 myself.router_id = oi->area->ospf6->router_id;
624
625 /* Electing BDR (2) */
626 for (ALL_LIST_ELEMENTS(oi->neighbor_list, node, nnode, on))
627 bdrouter = better_bdrouter(bdrouter, on);
628
629 best_bdrouter = bdrouter;
630 bdrouter = better_bdrouter(best_bdrouter, &myself);
631
632 /* Electing DR (3) */
633 for (ALL_LIST_ELEMENTS(oi->neighbor_list, node, nnode, on))
634 drouter = better_drouter(drouter, on);
635
636 best_drouter = drouter;
637 drouter = better_drouter(best_drouter, &myself);
638 if (drouter == NULL)
639 drouter = bdrouter;
640
641 /* the router itself is newly/no longer DR/BDR (4) */
642 if ((drouter == &myself && myself.drouter != myself.router_id)
643 || (drouter != &myself && myself.drouter == myself.router_id)
644 || (bdrouter == &myself && myself.bdrouter != myself.router_id)
645 || (bdrouter != &myself && myself.bdrouter == myself.router_id)) {
646 myself.drouter = (drouter ? drouter->router_id : htonl(0));
647 myself.bdrouter = (bdrouter ? bdrouter->router_id : htonl(0));
648
649 /* compatible to Electing BDR (2) */
650 bdrouter = better_bdrouter(best_bdrouter, &myself);
651
652 /* compatible to Electing DR (3) */
653 drouter = better_drouter(best_drouter, &myself);
654 if (drouter == NULL)
655 drouter = bdrouter;
656 }
657
658 /* Set interface state accordingly (5) */
659 if (drouter && drouter == &myself)
660 next_state = OSPF6_INTERFACE_DR;
661 else if (bdrouter && bdrouter == &myself)
662 next_state = OSPF6_INTERFACE_BDR;
663 else
664 next_state = OSPF6_INTERFACE_DROTHER;
665
666 /* If NBMA, schedule Start for each neighbor having priority of 0 (6) */
667 /* XXX */
668
669 /* If DR or BDR change, invoke AdjOK? for each neighbor (7) */
670 /* RFC 2328 section 12.4. Originating LSAs (3) will be handled
671 accordingly after AdjOK */
672 if (oi->drouter != (drouter ? drouter->router_id : htonl(0))
673 || oi->bdrouter != (bdrouter ? bdrouter->router_id : htonl(0))) {
674 if (IS_OSPF6_DEBUG_INTERFACE)
675 zlog_debug("DR Election on %s: DR: %s BDR: %s",
676 oi->interface->name,
677 (drouter ? drouter->name : "0.0.0.0"),
678 (bdrouter ? bdrouter->name : "0.0.0.0"));
679
680 for (ALL_LIST_ELEMENTS_RO(oi->neighbor_list, node, on)) {
681 if (on->state < OSPF6_NEIGHBOR_TWOWAY)
682 continue;
683 /* Schedule AdjOK. */
684 thread_add_event(master, adj_ok, on, 0,
685 &on->thread_adj_ok);
686 }
687 }
688
689 oi->drouter = (drouter ? drouter->router_id : htonl(0));
690 oi->bdrouter = (bdrouter ? bdrouter->router_id : htonl(0));
691 return next_state;
692 }
693
694 #ifdef __FreeBSD__
695
696 #include <ifaddrs.h>
697
698 static bool ifmaddr_check(ifindex_t ifindex, struct in6_addr *addr)
699 {
700 struct ifmaddrs *ifmap, *ifma;
701 struct sockaddr_dl *sdl;
702 struct sockaddr_in6 *sin6;
703 bool found = false;
704
705 if (getifmaddrs(&ifmap) != 0)
706 return false;
707
708 for (ifma = ifmap; ifma; ifma = ifma->ifma_next) {
709 if (ifma->ifma_name == NULL || ifma->ifma_addr == NULL)
710 continue;
711 if (ifma->ifma_name->sa_family != AF_LINK)
712 continue;
713 if (ifma->ifma_addr->sa_family != AF_INET6)
714 continue;
715 sdl = (struct sockaddr_dl *)ifma->ifma_name;
716 sin6 = (struct sockaddr_in6 *)ifma->ifma_addr;
717 if (sdl->sdl_index == ifindex
718 && memcmp(&sin6->sin6_addr, addr, IPV6_MAX_BYTELEN) == 0) {
719 found = true;
720 break;
721 }
722 }
723
724 if (ifmap)
725 freeifmaddrs(ifmap);
726
727 return found;
728 }
729
730 #endif /* __FreeBSD__ */
731
732 /* Interface State Machine */
733 void interface_up(struct thread *thread)
734 {
735 struct ospf6_interface *oi;
736 struct ospf6 *ospf6;
737
738 oi = (struct ospf6_interface *)THREAD_ARG(thread);
739 assert(oi && oi->interface);
740
741 if (!oi->type_cfg)
742 oi->type = ospf6_default_iftype(oi->interface);
743
744 thread_cancel(&oi->thread_sso);
745
746 if (IS_OSPF6_DEBUG_INTERFACE)
747 zlog_debug("Interface Event %s: [InterfaceUp]",
748 oi->interface->name);
749
750 /* check physical interface is up */
751 if (!if_is_operative(oi->interface)) {
752 zlog_warn("Interface %s is down, can't execute [InterfaceUp]",
753 oi->interface->name);
754 return;
755 }
756
757 /* check interface has a link-local address */
758 if (!(ospf6_interface_get_linklocal_address(oi->interface)
759 || if_is_loopback(oi->interface))) {
760 zlog_warn(
761 "Interface %s has no link local address, can't execute [InterfaceUp]",
762 oi->interface->name);
763 return;
764 }
765
766 /* Recompute cost */
767 ospf6_interface_recalculate_cost(oi);
768
769 /* if already enabled, do nothing */
770 if (oi->state > OSPF6_INTERFACE_DOWN) {
771 if (IS_OSPF6_DEBUG_INTERFACE)
772 zlog_debug("Interface %s already enabled",
773 oi->interface->name);
774 return;
775 }
776
777 /* If no area assigned, return */
778 if (oi->area == NULL) {
779 zlog_warn(
780 "%s: Not scheduling Hello for %s as there is no area assigned yet",
781 __func__, oi->interface->name);
782 return;
783 }
784
785 #ifdef __FreeBSD__
786 /*
787 * There's a delay in FreeBSD between issuing a command to leave a
788 * multicast group and an actual leave. If we execute "no router ospf6"
789 * and "router ospf6" fast enough, we can end up in a situation when OS
790 * performs the leave later than it performs the join and the interface
791 * remains without a multicast group. We have to do the join only after
792 * the interface actually left the group.
793 */
794 if (ifmaddr_check(oi->interface->ifindex, &allspfrouters6)) {
795 zlog_info(
796 "Interface %s is still in all routers group, rescheduling for SSO",
797 oi->interface->name);
798 thread_add_timer(master, interface_up, oi,
799 OSPF6_INTERFACE_SSO_RETRY_INT,
800 &oi->thread_sso);
801 return;
802 }
803 #endif /* __FreeBSD__ */
804
805 ospf6 = oi->area->ospf6;
806
807 /* Join AllSPFRouters */
808 if (ospf6_sso(oi->interface->ifindex, &allspfrouters6, IPV6_JOIN_GROUP,
809 ospf6->fd)
810 < 0) {
811 if (oi->sso_try_cnt++ < OSPF6_INTERFACE_SSO_RETRY_MAX) {
812 zlog_info(
813 "Scheduling %s for sso retry, trial count: %d",
814 oi->interface->name, oi->sso_try_cnt);
815 thread_add_timer(master, interface_up, oi,
816 OSPF6_INTERFACE_SSO_RETRY_INT,
817 &oi->thread_sso);
818 }
819 return;
820 }
821 oi->sso_try_cnt = 0; /* Reset on success */
822
823 /* Update interface route */
824 ospf6_interface_connected_route_update(oi->interface);
825
826 /* Schedule Hello */
827 if (!CHECK_FLAG(oi->flag, OSPF6_INTERFACE_PASSIVE)
828 && !if_is_loopback(oi->interface)) {
829 thread_add_timer(master, ospf6_hello_send, oi, 0,
830 &oi->thread_send_hello);
831 }
832
833 /* decide next interface state */
834 if (oi->type == OSPF_IFTYPE_LOOPBACK) {
835 ospf6_interface_state_change(OSPF6_INTERFACE_LOOPBACK, oi);
836 } else if (oi->type == OSPF_IFTYPE_POINTOPOINT) {
837 ospf6_interface_state_change(OSPF6_INTERFACE_POINTTOPOINT, oi);
838 } else if (oi->priority == 0)
839 ospf6_interface_state_change(OSPF6_INTERFACE_DROTHER, oi);
840 else {
841 ospf6_interface_state_change(OSPF6_INTERFACE_WAITING, oi);
842 thread_add_timer(master, wait_timer, oi, oi->dead_interval,
843 &oi->thread_wait_timer);
844 }
845 }
846
847 void wait_timer(struct thread *thread)
848 {
849 struct ospf6_interface *oi;
850
851 oi = (struct ospf6_interface *)THREAD_ARG(thread);
852 assert(oi && oi->interface);
853
854 if (IS_OSPF6_DEBUG_INTERFACE)
855 zlog_debug("Interface Event %s: [WaitTimer]",
856 oi->interface->name);
857
858 if (oi->state == OSPF6_INTERFACE_WAITING)
859 ospf6_interface_state_change(dr_election(oi), oi);
860 }
861
862 void backup_seen(struct thread *thread)
863 {
864 struct ospf6_interface *oi;
865
866 oi = (struct ospf6_interface *)THREAD_ARG(thread);
867 assert(oi && oi->interface);
868
869 if (IS_OSPF6_DEBUG_INTERFACE)
870 zlog_debug("Interface Event %s: [BackupSeen]",
871 oi->interface->name);
872
873 if (oi->state == OSPF6_INTERFACE_WAITING)
874 ospf6_interface_state_change(dr_election(oi), oi);
875 }
876
877 void neighbor_change(struct thread *thread)
878 {
879 struct ospf6_interface *oi;
880
881 oi = (struct ospf6_interface *)THREAD_ARG(thread);
882 assert(oi && oi->interface);
883
884 if (IS_OSPF6_DEBUG_INTERFACE)
885 zlog_debug("Interface Event %s: [NeighborChange]",
886 oi->interface->name);
887
888 if (oi->state == OSPF6_INTERFACE_DROTHER
889 || oi->state == OSPF6_INTERFACE_BDR
890 || oi->state == OSPF6_INTERFACE_DR)
891 ospf6_interface_state_change(dr_election(oi), oi);
892 }
893
894 void interface_down(struct thread *thread)
895 {
896 struct ospf6_interface *oi;
897 struct listnode *node, *nnode;
898 struct ospf6_neighbor *on;
899 struct ospf6 *ospf6;
900
901 oi = (struct ospf6_interface *)THREAD_ARG(thread);
902 assert(oi && oi->interface);
903
904 if (IS_OSPF6_DEBUG_INTERFACE)
905 zlog_debug("Interface Event %s: [InterfaceDown]",
906 oi->interface->name);
907
908 /* Stop Hellos */
909 THREAD_OFF(oi->thread_send_hello);
910
911 /* Stop trying to set socket options. */
912 THREAD_OFF(oi->thread_sso);
913
914 /* Cease the HELPER role for all the neighbours
915 * of this interface.
916 */
917 if (ospf6_interface_neighbor_count(oi)) {
918 struct listnode *ln;
919 struct ospf6_neighbor *nbr = NULL;
920
921 for (ALL_LIST_ELEMENTS_RO(oi->neighbor_list, ln, nbr))
922 ospf6_gr_helper_exit(nbr, OSPF6_GR_HELPER_TOPO_CHG);
923 }
924
925 for (ALL_LIST_ELEMENTS(oi->neighbor_list, node, nnode, on))
926 ospf6_neighbor_delete(on);
927
928 list_delete_all_node(oi->neighbor_list);
929
930 /* When interface state is reset, also reset information about
931 * DR election, as it is no longer valid. */
932 oi->drouter = oi->prev_drouter = htonl(0);
933 oi->bdrouter = oi->prev_bdrouter = htonl(0);
934
935 if (oi->area == NULL)
936 return;
937
938 ospf6 = oi->area->ospf6;
939 /* Leave AllSPFRouters */
940 if (oi->state > OSPF6_INTERFACE_DOWN)
941 ospf6_sso(oi->interface->ifindex, &allspfrouters6,
942 IPV6_LEAVE_GROUP, ospf6->fd);
943
944 /* deal with write fifo */
945 ospf6_fifo_flush(oi->obuf);
946 if (oi->on_write_q) {
947 listnode_delete(ospf6->oi_write_q, oi);
948 if (list_isempty(ospf6->oi_write_q))
949 thread_cancel(&ospf6->t_write);
950 oi->on_write_q = 0;
951 }
952
953 ospf6_interface_state_change(OSPF6_INTERFACE_DOWN, oi);
954 }
955
956
957 static const char *ospf6_iftype_str(uint8_t iftype)
958 {
959 switch (iftype) {
960 case OSPF_IFTYPE_LOOPBACK:
961 return "LOOPBACK";
962 case OSPF_IFTYPE_BROADCAST:
963 return "BROADCAST";
964 case OSPF_IFTYPE_POINTOPOINT:
965 return "POINTOPOINT";
966 }
967 return "UNKNOWN";
968 }
969
970 /* show specified interface structure */
971 static int ospf6_interface_show(struct vty *vty, struct interface *ifp,
972 json_object *json_obj, bool use_json)
973 {
974 struct ospf6_interface *oi;
975 struct connected *c;
976 struct prefix *p;
977 struct listnode *i;
978 char strbuf[PREFIX2STR_BUFFER], drouter[32], bdrouter[32];
979 uint8_t default_iftype;
980 struct timeval res, now;
981 char duration[32];
982 struct ospf6_lsa *lsa, *lsanext;
983 json_object *json_arr;
984 json_object *json_addr;
985 struct json_object *json_auth = NULL;
986
987 default_iftype = ospf6_default_iftype(ifp);
988
989 if (use_json) {
990 json_object_string_add(json_obj, "status",
991 (if_is_operative(ifp) ? "up" : "down"));
992 json_object_string_add(json_obj, "type",
993 ospf6_iftype_str(default_iftype));
994 json_object_int_add(json_obj, "interfaceId", ifp->ifindex);
995
996 if (ifp->info == NULL)
997 return 0;
998
999 oi = (struct ospf6_interface *)ifp->info;
1000
1001 if (if_is_operative(ifp) && oi->type != default_iftype)
1002 json_object_string_add(json_obj, "operatingAsType",
1003 ospf6_iftype_str(oi->type));
1004
1005 } else {
1006 vty_out(vty, "%s is %s, type %s\n", ifp->name,
1007 (if_is_operative(ifp) ? "up" : "down"),
1008 ospf6_iftype_str(default_iftype));
1009 vty_out(vty, " Interface ID: %d\n", ifp->ifindex);
1010
1011 if (ifp->info == NULL) {
1012 vty_out(vty, " OSPF not enabled on this interface\n");
1013 return 0;
1014 }
1015 oi = (struct ospf6_interface *)ifp->info;
1016
1017 if (if_is_operative(ifp) && oi->type != default_iftype)
1018 vty_out(vty, " Operating as type %s\n",
1019 ospf6_iftype_str(oi->type));
1020 }
1021
1022 if (use_json) {
1023 json_arr = json_object_new_array();
1024 for (ALL_LIST_ELEMENTS_RO(ifp->connected, i, c)) {
1025 json_addr = json_object_new_object();
1026 p = c->address;
1027 prefix2str(p, strbuf, sizeof(strbuf));
1028 switch (p->family) {
1029 case AF_INET:
1030 json_object_string_add(json_addr, "type",
1031 "inet");
1032 json_object_string_add(json_addr, "address",
1033 strbuf);
1034 json_object_array_add(json_arr, json_addr);
1035 break;
1036 case AF_INET6:
1037 json_object_string_add(json_addr, "type",
1038 "inet6");
1039 json_object_string_add(json_addr, "address",
1040 strbuf);
1041 json_object_array_add(json_arr, json_addr);
1042 break;
1043 default:
1044 json_object_string_add(json_addr, "type",
1045 "unknown");
1046 json_object_string_add(json_addr, "address",
1047 strbuf);
1048 json_object_array_add(json_arr, json_addr);
1049 break;
1050 }
1051 }
1052 json_object_object_add(json_obj, "internetAddress", json_arr);
1053 } else {
1054 vty_out(vty, " Internet Address:\n");
1055
1056 for (ALL_LIST_ELEMENTS_RO(ifp->connected, i, c)) {
1057 p = c->address;
1058 prefix2str(p, strbuf, sizeof(strbuf));
1059 switch (p->family) {
1060 case AF_INET:
1061 vty_out(vty, " inet : %pFX\n", p);
1062 break;
1063 case AF_INET6:
1064 vty_out(vty, " inet6: %pFX\n", p);
1065 break;
1066 default:
1067 vty_out(vty, " ??? : %pFX\n", p);
1068 break;
1069 }
1070 }
1071 }
1072
1073 if (use_json) {
1074 if (oi->area) {
1075 json_object_boolean_true_add(json_obj,
1076 "attachedToArea");
1077 json_object_int_add(json_obj, "instanceId",
1078 oi->instance_id);
1079 json_object_int_add(json_obj, "interfaceMtu",
1080 oi->ifmtu);
1081 json_object_int_add(json_obj, "autoDetect", ifp->mtu6);
1082 json_object_string_add(json_obj, "mtuMismatchDetection",
1083 oi->mtu_ignore ? "disabled"
1084 : "enabled");
1085 inet_ntop(AF_INET, &oi->area->area_id, strbuf,
1086 sizeof(strbuf));
1087 json_object_string_add(json_obj, "areaId", strbuf);
1088 json_object_int_add(json_obj, "cost", oi->cost);
1089 } else
1090 json_object_boolean_false_add(json_obj,
1091 "attachedToArea");
1092
1093 } else {
1094 if (oi->area) {
1095 vty_out(vty,
1096 " Instance ID %d, Interface MTU %d (autodetect: %d)\n",
1097 oi->instance_id, oi->ifmtu, ifp->mtu6);
1098 vty_out(vty, " MTU mismatch detection: %s\n",
1099 oi->mtu_ignore ? "disabled" : "enabled");
1100 inet_ntop(AF_INET, &oi->area->area_id, strbuf,
1101 sizeof(strbuf));
1102 vty_out(vty, " Area ID %s, Cost %u\n", strbuf,
1103 oi->cost);
1104 } else
1105 vty_out(vty, " Not Attached to Area\n");
1106 }
1107
1108 if (use_json) {
1109 json_object_string_add(json_obj, "ospf6InterfaceState",
1110 ospf6_interface_state_str[oi->state]);
1111 json_object_int_add(json_obj, "transmitDelaySec",
1112 oi->transdelay);
1113 json_object_int_add(json_obj, "priority", oi->priority);
1114 json_object_int_add(json_obj, "timerIntervalsConfigHello",
1115 oi->hello_interval);
1116 json_object_int_add(json_obj, "timerIntervalsConfigDead",
1117 oi->dead_interval);
1118 json_object_int_add(json_obj, "timerIntervalsConfigRetransmit",
1119 oi->rxmt_interval);
1120 json_object_boolean_add(
1121 json_obj, "timerPassiveIface",
1122 !!CHECK_FLAG(oi->flag, OSPF6_INTERFACE_PASSIVE));
1123 } else {
1124 vty_out(vty, " State %s, Transmit Delay %d sec, Priority %d\n",
1125 ospf6_interface_state_str[oi->state], oi->transdelay,
1126 oi->priority);
1127 vty_out(vty, " Timer intervals configured:\n");
1128 if (!CHECK_FLAG(oi->flag, OSPF6_INTERFACE_PASSIVE))
1129 vty_out(vty,
1130 " Hello %d(%pTHd), Dead %d, Retransmit %d\n",
1131 oi->hello_interval, oi->thread_send_hello,
1132 oi->dead_interval, oi->rxmt_interval);
1133 else
1134 vty_out(vty, " No Hellos (Passive interface)\n");
1135 }
1136
1137 inet_ntop(AF_INET, &oi->drouter, drouter, sizeof(drouter));
1138 inet_ntop(AF_INET, &oi->bdrouter, bdrouter, sizeof(bdrouter));
1139 if (use_json) {
1140 json_object_string_add(json_obj, "dr", drouter);
1141 json_object_string_add(json_obj, "bdr", bdrouter);
1142 json_object_int_add(json_obj, "numberOfInterfaceScopedLsa",
1143 oi->lsdb->count);
1144 } else {
1145 vty_out(vty, " DR: %s BDR: %s\n", drouter, bdrouter);
1146 vty_out(vty, " Number of I/F scoped LSAs is %u\n",
1147 oi->lsdb->count);
1148 }
1149
1150 monotime(&now);
1151
1152 if (use_json) {
1153 timerclear(&res);
1154 if (thread_is_scheduled(oi->thread_send_lsupdate))
1155 timersub(&oi->thread_send_lsupdate->u.sands, &now,
1156 &res);
1157 timerstring(&res, duration, sizeof(duration));
1158 json_object_int_add(json_obj, "pendingLsaLsUpdateCount",
1159 oi->lsupdate_list->count);
1160 json_object_string_add(json_obj, "pendingLsaLsUpdateTime",
1161 duration);
1162 json_object_string_add(
1163 json_obj, "lsUpdateSendThread",
1164 (thread_is_scheduled(oi->thread_send_lsupdate)
1165 ? "on"
1166 : "off"));
1167
1168 json_arr = json_object_new_array();
1169 for (ALL_LSDB(oi->lsupdate_list, lsa, lsanext))
1170 json_object_array_add(
1171 json_arr, json_object_new_string(lsa->name));
1172 json_object_object_add(json_obj, "pendingLsaLsUpdate",
1173 json_arr);
1174
1175 timerclear(&res);
1176 if (thread_is_scheduled(oi->thread_send_lsack))
1177 timersub(&oi->thread_send_lsack->u.sands, &now, &res);
1178 timerstring(&res, duration, sizeof(duration));
1179
1180 json_object_int_add(json_obj, "pendingLsaLsAckCount",
1181 oi->lsack_list->count);
1182 json_object_string_add(json_obj, "pendingLsaLsAckTime",
1183 duration);
1184 json_object_string_add(
1185 json_obj, "lsAckSendThread",
1186 (thread_is_scheduled(oi->thread_send_lsack) ? "on"
1187 : "off"));
1188
1189 json_arr = json_object_new_array();
1190 for (ALL_LSDB(oi->lsack_list, lsa, lsanext))
1191 json_object_array_add(
1192 json_arr, json_object_new_string(lsa->name));
1193 json_object_object_add(json_obj, "pendingLsaLsAck", json_arr);
1194
1195 } else {
1196 timerclear(&res);
1197 if (thread_is_scheduled(oi->thread_send_lsupdate))
1198 timersub(&oi->thread_send_lsupdate->u.sands, &now,
1199 &res);
1200 timerstring(&res, duration, sizeof(duration));
1201 vty_out(vty,
1202 " %d Pending LSAs for LSUpdate in Time %s [thread %s]\n",
1203 oi->lsupdate_list->count, duration,
1204 (thread_is_scheduled(oi->thread_send_lsupdate)
1205 ? "on"
1206 : "off"));
1207 for (ALL_LSDB(oi->lsupdate_list, lsa, lsanext))
1208 vty_out(vty, " %s\n", lsa->name);
1209
1210 timerclear(&res);
1211 if (thread_is_scheduled(oi->thread_send_lsack))
1212 timersub(&oi->thread_send_lsack->u.sands, &now, &res);
1213 timerstring(&res, duration, sizeof(duration));
1214 vty_out(vty,
1215 " %d Pending LSAs for LSAck in Time %s [thread %s]\n",
1216 oi->lsack_list->count, duration,
1217 (thread_is_scheduled(oi->thread_send_lsack) ? "on"
1218 : "off"));
1219 for (ALL_LSDB(oi->lsack_list, lsa, lsanext))
1220 vty_out(vty, " %s\n", lsa->name);
1221 }
1222
1223 /* BFD specific. */
1224 if (oi->bfd_config.enabled) {
1225 if (use_json) {
1226 struct json_object *json_bfd = json_object_new_object();
1227
1228 json_object_int_add(
1229 json_bfd, "detectMultiplier",
1230 oi->bfd_config.detection_multiplier);
1231 json_object_int_add(json_bfd, "rxMinInterval",
1232 oi->bfd_config.min_rx);
1233 json_object_int_add(json_bfd, "txMinInterval",
1234 oi->bfd_config.min_tx);
1235 json_object_object_add(json_obj, "peerBfdInfo",
1236 json_bfd);
1237 } else {
1238 vty_out(vty,
1239 " BFD: Detect Multiplier: %d, Min Rx interval: %d, Min Tx interval: %d\n",
1240 oi->bfd_config.detection_multiplier,
1241 oi->bfd_config.min_rx, oi->bfd_config.min_tx);
1242 }
1243 }
1244
1245 if (use_json)
1246 json_auth = json_object_new_object();
1247 if (oi->at_data.flags != 0) {
1248 if (use_json) {
1249 if (CHECK_FLAG(oi->at_data.flags,
1250 OSPF6_AUTH_TRAILER_KEYCHAIN)) {
1251 json_object_string_add(json_auth, "authType",
1252 "keychain");
1253 json_object_string_add(json_auth,
1254 "keychainName",
1255 oi->at_data.keychain);
1256 } else if (CHECK_FLAG(oi->at_data.flags,
1257 OSPF6_AUTH_TRAILER_MANUAL_KEY))
1258 json_object_string_add(json_auth, "authType",
1259 "manualkey");
1260 json_object_int_add(json_auth, "txPktDrop",
1261 oi->at_data.tx_drop);
1262 json_object_int_add(json_auth, "rxPktDrop",
1263 oi->at_data.rx_drop);
1264 } else {
1265 if (CHECK_FLAG(oi->at_data.flags,
1266 OSPF6_AUTH_TRAILER_KEYCHAIN))
1267 vty_out(vty,
1268 " Authentication Trailer is enabled with key-chain %s\n",
1269 oi->at_data.keychain);
1270 else if (CHECK_FLAG(oi->at_data.flags,
1271 OSPF6_AUTH_TRAILER_MANUAL_KEY))
1272 vty_out(vty,
1273 " Authentication trailer is enabled with manual key\n");
1274 vty_out(vty,
1275 " Packet drop Tx %u, Packet drop Rx %u\n",
1276 oi->at_data.tx_drop, oi->at_data.rx_drop);
1277 }
1278 } else {
1279 if (use_json)
1280 json_object_string_add(json_auth, "authType", "NULL");
1281 else
1282 vty_out(vty, " Authentication Trailer is disabled\n");
1283 }
1284
1285 if (use_json)
1286 json_object_object_add(json_obj, "authInfo", json_auth);
1287
1288 return 0;
1289 }
1290
1291 /* Find the global address to be used as a forwarding address in NSSA LSA.*/
1292 struct in6_addr *ospf6_interface_get_global_address(struct interface *ifp)
1293 {
1294 struct listnode *n;
1295 struct connected *c;
1296
1297 /* for each connected address */
1298 for (ALL_LIST_ELEMENTS_RO(ifp->connected, n, c)) {
1299 /* if family not AF_INET6, ignore */
1300 if (c->address->family != AF_INET6)
1301 continue;
1302
1303 if (!IN6_IS_ADDR_LINKLOCAL(&c->address->u.prefix6))
1304 return &c->address->u.prefix6;
1305 }
1306
1307 return NULL;
1308 }
1309
1310
1311 static int show_ospf6_interface_common(struct vty *vty, vrf_id_t vrf_id,
1312 int argc, struct cmd_token **argv,
1313 int idx_ifname, int intf_idx,
1314 int json_idx, bool uj)
1315 {
1316
1317 struct vrf *vrf = vrf_lookup_by_id(vrf_id);
1318 struct interface *ifp;
1319 json_object *json;
1320 json_object *json_int;
1321
1322 if (uj) {
1323 json = json_object_new_object();
1324 if (argc == json_idx) {
1325 ifp = if_lookup_by_name(argv[idx_ifname]->arg, vrf_id);
1326 json_int = json_object_new_object();
1327 if (ifp == NULL) {
1328 json_object_string_add(json, "noSuchInterface",
1329 argv[idx_ifname]->arg);
1330 vty_json(vty, json);
1331 json_object_free(json_int);
1332 return CMD_WARNING;
1333 }
1334 ospf6_interface_show(vty, ifp, json_int, uj);
1335 json_object_object_add(json, ifp->name, json_int);
1336 } else {
1337 FOR_ALL_INTERFACES (vrf, ifp) {
1338 json_int = json_object_new_object();
1339 ospf6_interface_show(vty, ifp, json_int, uj);
1340 json_object_object_add(json, ifp->name,
1341 json_int);
1342 }
1343 }
1344 vty_json(vty, json);
1345 } else {
1346 if (argc == intf_idx) {
1347 ifp = if_lookup_by_name(argv[idx_ifname]->arg, vrf_id);
1348 if (ifp == NULL) {
1349 vty_out(vty, "No such Interface: %s\n",
1350 argv[idx_ifname]->arg);
1351 return CMD_WARNING;
1352 }
1353 ospf6_interface_show(vty, ifp, NULL, uj);
1354 } else {
1355 FOR_ALL_INTERFACES (vrf, ifp)
1356 ospf6_interface_show(vty, ifp, NULL, uj);
1357 }
1358 }
1359 return CMD_SUCCESS;
1360 }
1361
1362 /* show interface */
1363 DEFUN(show_ipv6_ospf6_interface, show_ipv6_ospf6_interface_ifname_cmd,
1364 "show ipv6 ospf6 [vrf <NAME|all>] interface [IFNAME] [json]",
1365 SHOW_STR IP6_STR OSPF6_STR VRF_CMD_HELP_STR
1366 "All VRFs\n" INTERFACE_STR IFNAME_STR JSON_STR)
1367 {
1368 int idx_ifname = 4;
1369 int intf_idx = 5;
1370 int json_idx = 6;
1371 struct listnode *node;
1372 struct ospf6 *ospf6;
1373 const char *vrf_name = NULL;
1374 bool all_vrf = false;
1375 int idx_vrf = 0;
1376 bool uj = use_json(argc, argv);
1377
1378 OSPF6_FIND_VRF_ARGS(argv, argc, idx_vrf, vrf_name, all_vrf);
1379 if (idx_vrf > 0) {
1380 idx_ifname += 2;
1381 intf_idx += 2;
1382 json_idx += 2;
1383 }
1384
1385 for (ALL_LIST_ELEMENTS_RO(om6->ospf6, node, ospf6)) {
1386 if (all_vrf || strcmp(ospf6->name, vrf_name) == 0) {
1387 show_ospf6_interface_common(vty, ospf6->vrf_id, argc,
1388 argv, idx_ifname, intf_idx,
1389 json_idx, uj);
1390
1391 if (!all_vrf)
1392 break;
1393 }
1394 }
1395
1396 OSPF6_CMD_CHECK_VRF(uj, all_vrf, ospf6);
1397
1398 return CMD_SUCCESS;
1399 }
1400
1401 static int ospf6_interface_show_traffic(struct vty *vty,
1402 struct interface *intf_ifp,
1403 int display_once, json_object *json,
1404 bool use_json, vrf_id_t vrf_id)
1405 {
1406 struct interface *ifp;
1407 struct vrf *vrf = NULL;
1408 struct ospf6_interface *oi = NULL;
1409 json_object *json_interface;
1410
1411 if (!display_once && !use_json) {
1412 vty_out(vty, "\n");
1413 vty_out(vty, "%-12s%-17s%-17s%-17s%-17s%-17s\n", "Interface",
1414 " HELLO", " DB-Desc", " LS-Req", " LS-Update",
1415 " LS-Ack");
1416 vty_out(vty, "%-10s%-18s%-18s%-17s%-17s%-17s\n", "",
1417 " Rx/Tx", " Rx/Tx", " Rx/Tx", " Rx/Tx",
1418 " Rx/Tx");
1419 vty_out(vty,
1420 "--------------------------------------------------------------------------------------------\n");
1421 }
1422
1423 if (intf_ifp == NULL) {
1424 vrf = vrf_lookup_by_id(vrf_id);
1425 FOR_ALL_INTERFACES (vrf, ifp) {
1426 if (ifp->info)
1427 oi = (struct ospf6_interface *)ifp->info;
1428 else
1429 continue;
1430
1431 if (use_json) {
1432 json_interface = json_object_new_object();
1433 json_object_int_add(json_interface, "helloRx",
1434 oi->hello_in);
1435 json_object_int_add(json_interface, "helloTx",
1436 oi->hello_out);
1437 json_object_int_add(json_interface, "dbDescRx",
1438 oi->db_desc_in);
1439 json_object_int_add(json_interface, "dbDescTx",
1440 oi->db_desc_out);
1441 json_object_int_add(json_interface, "lsReqRx",
1442 oi->ls_req_in);
1443 json_object_int_add(json_interface, "lsReqTx",
1444 oi->ls_req_out);
1445 json_object_int_add(json_interface,
1446 "lsUpdateRx",
1447 oi->ls_upd_in);
1448 json_object_int_add(json_interface,
1449 "lsUpdateTx",
1450 oi->ls_upd_out);
1451 json_object_int_add(json_interface, "lsAckRx",
1452 oi->ls_ack_in);
1453 json_object_int_add(json_interface, "lsAckTx",
1454 oi->ls_ack_out);
1455
1456 json_object_object_add(json,
1457 oi->interface->name,
1458 json_interface);
1459 } else
1460 vty_out(vty,
1461 "%-10s %8u/%-8u %7u/%-7u %7u/%-7u %7u/%-7u %7u/%-7u\n",
1462 oi->interface->name, oi->hello_in,
1463 oi->hello_out, oi->db_desc_in,
1464 oi->db_desc_out, oi->ls_req_in,
1465 oi->ls_req_out, oi->ls_upd_in,
1466 oi->ls_upd_out, oi->ls_ack_in,
1467 oi->ls_ack_out);
1468 }
1469 } else {
1470 oi = intf_ifp->info;
1471 if (oi == NULL)
1472 return CMD_WARNING;
1473
1474 if (use_json) {
1475 json_interface = json_object_new_object();
1476 json_object_int_add(json_interface, "helloRx",
1477 oi->hello_in);
1478 json_object_int_add(json_interface, "helloTx",
1479 oi->hello_out);
1480 json_object_int_add(json_interface, "dbDescRx",
1481 oi->db_desc_in);
1482 json_object_int_add(json_interface, "dbDescTx",
1483 oi->db_desc_out);
1484 json_object_int_add(json_interface, "lsReqRx",
1485 oi->ls_req_in);
1486 json_object_int_add(json_interface, "lsReqTx",
1487 oi->ls_req_out);
1488 json_object_int_add(json_interface, "lsUpdateRx",
1489 oi->ls_upd_in);
1490 json_object_int_add(json_interface, "lsUpdateTx",
1491 oi->ls_upd_out);
1492 json_object_int_add(json_interface, "lsAckRx",
1493 oi->ls_ack_in);
1494 json_object_int_add(json_interface, "lsAckTx",
1495 oi->ls_ack_out);
1496
1497 json_object_object_add(json, oi->interface->name,
1498 json_interface);
1499 } else
1500 vty_out(vty,
1501 "%-10s %8u/%-8u %7u/%-7u %7u/%-7u %7u/%-7u %7u/%-7u\n",
1502 oi->interface->name, oi->hello_in,
1503 oi->hello_out, oi->db_desc_in, oi->db_desc_out,
1504 oi->ls_req_in, oi->ls_req_out, oi->ls_upd_in,
1505 oi->ls_upd_out, oi->ls_ack_in, oi->ls_ack_out);
1506 }
1507
1508 return CMD_SUCCESS;
1509 }
1510
1511 static int ospf6_interface_show_traffic_common(struct vty *vty, int argc,
1512 struct cmd_token **argv,
1513 vrf_id_t vrf_id, bool uj)
1514 {
1515 int idx_ifname = 0;
1516 int display_once = 0;
1517 char *intf_name = NULL;
1518 struct interface *ifp = NULL;
1519 json_object *json = NULL;
1520
1521 if (uj)
1522 json = json_object_new_object();
1523
1524 if (argv_find(argv, argc, "IFNAME", &idx_ifname)) {
1525 intf_name = argv[idx_ifname]->arg;
1526 ifp = if_lookup_by_name(intf_name, vrf_id);
1527 if (uj) {
1528 if (ifp == NULL) {
1529 json_object_string_add(json, "status",
1530 "No Such Interface");
1531 json_object_string_add(json, "interface",
1532 intf_name);
1533 vty_json(vty, json);
1534 return CMD_WARNING;
1535 }
1536 if (ifp->info == NULL) {
1537 json_object_string_add(
1538 json, "status",
1539 "OSPF not enabled on this interface");
1540 json_object_string_add(json, "interface",
1541 intf_name);
1542 vty_json(vty, json);
1543 return 0;
1544 }
1545 } else {
1546 if (ifp == NULL) {
1547 vty_out(vty, "No such Interface: %s\n",
1548 intf_name);
1549 return CMD_WARNING;
1550 }
1551 if (ifp->info == NULL) {
1552 vty_out(vty,
1553 " OSPF not enabled on this interface %s\n",
1554 intf_name);
1555 return 0;
1556 }
1557 }
1558 }
1559
1560 ospf6_interface_show_traffic(vty, ifp, display_once, json, uj, vrf_id);
1561
1562 if (uj)
1563 vty_json(vty, json);
1564
1565 return CMD_SUCCESS;
1566 }
1567
1568 /* show interface */
1569 DEFUN(show_ipv6_ospf6_interface_traffic, show_ipv6_ospf6_interface_traffic_cmd,
1570 "show ipv6 ospf6 [vrf <NAME|all>] interface traffic [IFNAME] [json]",
1571 SHOW_STR IP6_STR OSPF6_STR VRF_CMD_HELP_STR
1572 "All VRFs\n" INTERFACE_STR
1573 "Protocol Packet counters\n" IFNAME_STR JSON_STR)
1574 {
1575 struct ospf6 *ospf6;
1576 struct listnode *node;
1577 const char *vrf_name = NULL;
1578 bool all_vrf = false;
1579 int idx_vrf = 0;
1580 bool uj = use_json(argc, argv);
1581
1582 OSPF6_FIND_VRF_ARGS(argv, argc, idx_vrf, vrf_name, all_vrf);
1583
1584 for (ALL_LIST_ELEMENTS_RO(om6->ospf6, node, ospf6)) {
1585 if (all_vrf || strcmp(ospf6->name, vrf_name) == 0) {
1586 ospf6_interface_show_traffic_common(vty, argc, argv,
1587 ospf6->vrf_id, uj);
1588
1589 if (!all_vrf)
1590 break;
1591 }
1592 }
1593
1594 OSPF6_CMD_CHECK_VRF(uj, all_vrf, ospf6);
1595
1596 return CMD_SUCCESS;
1597 }
1598
1599
1600 DEFUN(show_ipv6_ospf6_interface_ifname_prefix,
1601 show_ipv6_ospf6_interface_ifname_prefix_cmd,
1602 "show ipv6 ospf6 [vrf <NAME|all>] interface IFNAME prefix\
1603 [<\
1604 detail\
1605 |<X:X::X:X|X:X::X:X/M> [<match|detail>]\
1606 >] [json]",
1607 SHOW_STR IP6_STR OSPF6_STR VRF_CMD_HELP_STR
1608 "All VRFs\n" INTERFACE_STR IFNAME_STR
1609 "Display connected prefixes to advertise\n"
1610 "Display details of the prefixes\n" OSPF6_ROUTE_ADDRESS_STR
1611 OSPF6_ROUTE_PREFIX_STR OSPF6_ROUTE_MATCH_STR
1612 "Display details of the prefixes\n" JSON_STR)
1613 {
1614 int idx_ifname = 4;
1615 int idx_prefix = 6;
1616 struct ospf6_interface *oi;
1617 bool uj = use_json(argc, argv);
1618
1619 struct ospf6 *ospf6;
1620 struct listnode *node;
1621 struct interface *ifp;
1622 const char *vrf_name = NULL;
1623 bool all_vrf = false;
1624 int idx_vrf = 0;
1625
1626 OSPF6_FIND_VRF_ARGS(argv, argc, idx_vrf, vrf_name, all_vrf);
1627 if (idx_vrf > 0) {
1628 idx_ifname += 2;
1629 idx_prefix += 2;
1630 }
1631
1632 for (ALL_LIST_ELEMENTS_RO(om6->ospf6, node, ospf6)) {
1633 if (all_vrf || strcmp(ospf6->name, vrf_name) == 0) {
1634 ifp = if_lookup_by_name(argv[idx_ifname]->arg,
1635 ospf6->vrf_id);
1636 if (ifp == NULL) {
1637 vty_out(vty, "No such Interface: %s\n",
1638 argv[idx_ifname]->arg);
1639 return CMD_WARNING;
1640 }
1641
1642 oi = ifp->info;
1643 if (oi == NULL
1644 || CHECK_FLAG(oi->flag, OSPF6_INTERFACE_DISABLE)) {
1645 vty_out(vty,
1646 "Interface %s not attached to area\n",
1647 argv[idx_ifname]->arg);
1648 return CMD_WARNING;
1649 }
1650
1651 ospf6_route_table_show(vty, idx_prefix, argc, argv,
1652 oi->route_connected, uj);
1653
1654 if (!all_vrf)
1655 break;
1656 }
1657 }
1658
1659 OSPF6_CMD_CHECK_VRF(uj, all_vrf, ospf6);
1660
1661 return CMD_SUCCESS;
1662 }
1663
1664 DEFUN(show_ipv6_ospf6_interface_prefix, show_ipv6_ospf6_interface_prefix_cmd,
1665 "show ipv6 ospf6 [vrf <NAME|all>] interface prefix\
1666 [<\
1667 detail\
1668 |<X:X::X:X|X:X::X:X/M> [<match|detail>]\
1669 >] [json]",
1670 SHOW_STR IP6_STR OSPF6_STR VRF_CMD_HELP_STR
1671 "All VRFs\n" INTERFACE_STR
1672 "Display connected prefixes to advertise\n"
1673 "Display details of the prefixes\n" OSPF6_ROUTE_ADDRESS_STR
1674 OSPF6_ROUTE_PREFIX_STR OSPF6_ROUTE_MATCH_STR
1675 "Display details of the prefixes\n" JSON_STR)
1676 {
1677 struct vrf *vrf = NULL;
1678 int idx_prefix = 5;
1679 struct ospf6_interface *oi;
1680 struct interface *ifp;
1681 bool uj = use_json(argc, argv);
1682 struct listnode *node;
1683 struct ospf6 *ospf6;
1684 const char *vrf_name = NULL;
1685 bool all_vrf = false;
1686 int idx_vrf = 0;
1687
1688 OSPF6_FIND_VRF_ARGS(argv, argc, idx_vrf, vrf_name, all_vrf);
1689 if (idx_vrf > 0)
1690 idx_prefix += 2;
1691
1692 for (ALL_LIST_ELEMENTS_RO(om6->ospf6, node, ospf6)) {
1693 if (all_vrf || strcmp(ospf6->name, vrf_name) == 0) {
1694 vrf = vrf_lookup_by_id(ospf6->vrf_id);
1695 FOR_ALL_INTERFACES (vrf, ifp) {
1696 oi = (struct ospf6_interface *)ifp->info;
1697 if (oi == NULL
1698 || CHECK_FLAG(oi->flag,
1699 OSPF6_INTERFACE_DISABLE))
1700 continue;
1701
1702 ospf6_route_table_show(vty, idx_prefix, argc,
1703 argv,
1704 oi->route_connected, uj);
1705 }
1706 if (!all_vrf)
1707 break;
1708 }
1709 }
1710
1711 OSPF6_CMD_CHECK_VRF(uj, all_vrf, ospf6);
1712
1713 return CMD_SUCCESS;
1714 }
1715
1716 void ospf6_interface_start(struct ospf6_interface *oi)
1717 {
1718 struct ospf6 *ospf6;
1719 struct ospf6_area *oa;
1720
1721 if (oi->area_id_format == OSPF6_AREA_FMT_UNSET)
1722 return;
1723
1724 if (oi->area) {
1725 /* Recompute cost */
1726 ospf6_interface_recalculate_cost(oi);
1727 return;
1728 }
1729
1730 ospf6 = oi->interface->vrf->info;
1731 if (!ospf6)
1732 return;
1733
1734 oa = ospf6_area_lookup(oi->area_id, ospf6);
1735 if (oa == NULL)
1736 oa = ospf6_area_create(oi->area_id, ospf6, oi->area_id_format);
1737
1738 /* attach interface to area */
1739 listnode_add(oa->if_list, oi);
1740 oi->area = oa;
1741
1742 SET_FLAG(oa->flag, OSPF6_AREA_ENABLE);
1743
1744 /* start up */
1745 ospf6_interface_enable(oi);
1746
1747 /* If the router is ABR, originate summary routes */
1748 if (ospf6_check_and_set_router_abr(ospf6)) {
1749 ospf6_abr_enable_area(oa);
1750 ospf6_schedule_abr_task(ospf6);
1751 }
1752 }
1753
1754 void ospf6_interface_stop(struct ospf6_interface *oi)
1755 {
1756 struct ospf6_area *oa;
1757
1758 oa = oi->area;
1759 if (!oa)
1760 return;
1761
1762 ospf6_interface_disable(oi);
1763
1764 listnode_delete(oa->if_list, oi);
1765 oi->area = NULL;
1766
1767 if (oa->if_list->count == 0) {
1768 UNSET_FLAG(oa->flag, OSPF6_AREA_ENABLE);
1769 ospf6_abr_disable_area(oa);
1770 }
1771 }
1772
1773 /* interface variable set command */
1774 DEFUN (ipv6_ospf6_area,
1775 ipv6_ospf6_area_cmd,
1776 "ipv6 ospf6 area <A.B.C.D|(0-4294967295)>",
1777 IP6_STR
1778 OSPF6_STR
1779 "Specify the OSPF6 area ID\n"
1780 "OSPF6 area ID in IPv4 address notation\n"
1781 "OSPF6 area ID in decimal notation\n")
1782 {
1783 VTY_DECLVAR_CONTEXT(interface, ifp);
1784 struct ospf6_interface *oi;
1785 int idx_ipv4 = 3;
1786 uint32_t area_id;
1787 int format;
1788
1789 assert(ifp);
1790
1791 oi = (struct ospf6_interface *)ifp->info;
1792 if (oi == NULL)
1793 oi = ospf6_interface_create(ifp);
1794 assert(oi);
1795
1796 if (oi->area) {
1797 vty_out(vty, "%s already attached to Area %s\n",
1798 oi->interface->name, oi->area->name);
1799 return CMD_SUCCESS;
1800 }
1801
1802 if (str2area_id(argv[idx_ipv4]->arg, &area_id, &format)) {
1803 vty_out(vty, "Malformed Area-ID: %s\n", argv[idx_ipv4]->arg);
1804 return CMD_WARNING_CONFIG_FAILED;
1805 }
1806
1807 oi->area_id = area_id;
1808 oi->area_id_format = format;
1809
1810 ospf6_interface_start(oi);
1811
1812 return CMD_SUCCESS;
1813 }
1814
1815 DEFUN (no_ipv6_ospf6_area,
1816 no_ipv6_ospf6_area_cmd,
1817 "no ipv6 ospf6 area [<A.B.C.D|(0-4294967295)>]",
1818 NO_STR
1819 IP6_STR
1820 OSPF6_STR
1821 "Specify the OSPF6 area ID\n"
1822 "OSPF6 area ID in IPv4 address notation\n"
1823 "OSPF6 area ID in decimal notation\n")
1824 {
1825 VTY_DECLVAR_CONTEXT(interface, ifp);
1826 struct ospf6_interface *oi;
1827
1828 assert(ifp);
1829
1830 oi = (struct ospf6_interface *)ifp->info;
1831 if (oi == NULL)
1832 oi = ospf6_interface_create(ifp);
1833 assert(oi);
1834
1835 ospf6_interface_stop(oi);
1836
1837 oi->area_id = 0;
1838 oi->area_id_format = OSPF6_AREA_FMT_UNSET;
1839
1840 return CMD_SUCCESS;
1841 }
1842
1843 DEFUN (ipv6_ospf6_ifmtu,
1844 ipv6_ospf6_ifmtu_cmd,
1845 "ipv6 ospf6 ifmtu (1-65535)",
1846 IP6_STR
1847 OSPF6_STR
1848 "Interface MTU\n"
1849 "OSPFv3 Interface MTU\n"
1850 )
1851 {
1852 VTY_DECLVAR_CONTEXT(interface, ifp);
1853 int idx_number = 3;
1854 struct ospf6_interface *oi;
1855 unsigned int ifmtu, iobuflen;
1856 struct listnode *node, *nnode;
1857 struct ospf6_neighbor *on;
1858
1859 assert(ifp);
1860
1861 oi = (struct ospf6_interface *)ifp->info;
1862 if (oi == NULL)
1863 oi = ospf6_interface_create(ifp);
1864 assert(oi);
1865
1866 ifmtu = strtol(argv[idx_number]->arg, NULL, 10);
1867
1868 if (oi->c_ifmtu == ifmtu)
1869 return CMD_SUCCESS;
1870
1871 if (ifp->mtu6 != 0 && ifp->mtu6 < ifmtu) {
1872 vty_out(vty,
1873 "%s's ospf6 ifmtu cannot go beyond physical mtu (%d)\n",
1874 ifp->name, ifp->mtu6);
1875 return CMD_WARNING_CONFIG_FAILED;
1876 }
1877
1878 if (oi->ifmtu < ifmtu) {
1879 iobuflen = ospf6_iobuf_size(ifmtu);
1880 if (iobuflen < ifmtu) {
1881 vty_out(vty,
1882 "%s's ifmtu is adjusted to I/O buffer size (%d).\n",
1883 ifp->name, iobuflen);
1884 oi->ifmtu = oi->c_ifmtu = iobuflen;
1885 } else
1886 oi->ifmtu = oi->c_ifmtu = ifmtu;
1887 } else
1888 oi->ifmtu = oi->c_ifmtu = ifmtu;
1889
1890 /* re-establish adjacencies */
1891 for (ALL_LIST_ELEMENTS(oi->neighbor_list, node, nnode, on)) {
1892 THREAD_OFF(on->inactivity_timer);
1893 thread_add_event(master, inactivity_timer, on, 0, NULL);
1894 }
1895
1896 return CMD_SUCCESS;
1897 }
1898
1899 DEFUN (no_ipv6_ospf6_ifmtu,
1900 no_ipv6_ospf6_ifmtu_cmd,
1901 "no ipv6 ospf6 ifmtu [(1-65535)]",
1902 NO_STR
1903 IP6_STR
1904 OSPF6_STR
1905 "Interface MTU\n"
1906 "OSPFv3 Interface MTU\n"
1907 )
1908 {
1909 VTY_DECLVAR_CONTEXT(interface, ifp);
1910 struct ospf6_interface *oi;
1911 unsigned int iobuflen;
1912 struct listnode *node, *nnode;
1913 struct ospf6_neighbor *on;
1914
1915 assert(ifp);
1916
1917 oi = (struct ospf6_interface *)ifp->info;
1918 if (oi == NULL)
1919 oi = ospf6_interface_create(ifp);
1920 assert(oi);
1921
1922 if (oi->ifmtu < ifp->mtu) {
1923 iobuflen = ospf6_iobuf_size(ifp->mtu);
1924 if (iobuflen < ifp->mtu) {
1925 vty_out(vty,
1926 "%s's ifmtu is adjusted to I/O buffer size (%d).\n",
1927 ifp->name, iobuflen);
1928 oi->ifmtu = iobuflen;
1929 } else
1930 oi->ifmtu = ifp->mtu;
1931 } else
1932 oi->ifmtu = ifp->mtu;
1933
1934 oi->c_ifmtu = 0;
1935
1936 /* re-establish adjacencies */
1937 for (ALL_LIST_ELEMENTS(oi->neighbor_list, node, nnode, on)) {
1938 THREAD_OFF(on->inactivity_timer);
1939 thread_add_event(master, inactivity_timer, on, 0, NULL);
1940 }
1941
1942 return CMD_SUCCESS;
1943 }
1944
1945 DEFUN (ipv6_ospf6_cost,
1946 ipv6_ospf6_cost_cmd,
1947 "ipv6 ospf6 cost (1-65535)",
1948 IP6_STR
1949 OSPF6_STR
1950 "Interface cost\n"
1951 "Outgoing metric of this interface\n")
1952 {
1953 VTY_DECLVAR_CONTEXT(interface, ifp);
1954 int idx_number = 3;
1955 struct ospf6_interface *oi;
1956 unsigned long int lcost;
1957
1958 assert(ifp);
1959
1960 oi = (struct ospf6_interface *)ifp->info;
1961 if (oi == NULL)
1962 oi = ospf6_interface_create(ifp);
1963 assert(oi);
1964
1965 lcost = strtol(argv[idx_number]->arg, NULL, 10);
1966
1967 if (lcost > UINT32_MAX) {
1968 vty_out(vty, "Cost %ld is out of range\n", lcost);
1969 return CMD_WARNING_CONFIG_FAILED;
1970 }
1971
1972 SET_FLAG(oi->flag, OSPF6_INTERFACE_NOAUTOCOST);
1973 if (oi->cost == lcost)
1974 return CMD_SUCCESS;
1975
1976 oi->cost = lcost;
1977 ospf6_interface_force_recalculate_cost(oi);
1978
1979 return CMD_SUCCESS;
1980 }
1981
1982 DEFUN (no_ipv6_ospf6_cost,
1983 no_ipv6_ospf6_cost_cmd,
1984 "no ipv6 ospf6 cost [(1-65535)]",
1985 NO_STR
1986 IP6_STR
1987 OSPF6_STR
1988 "Calculate interface cost from bandwidth\n"
1989 "Outgoing metric of this interface\n")
1990 {
1991 VTY_DECLVAR_CONTEXT(interface, ifp);
1992 struct ospf6_interface *oi;
1993 assert(ifp);
1994
1995 oi = (struct ospf6_interface *)ifp->info;
1996 if (oi == NULL)
1997 oi = ospf6_interface_create(ifp);
1998 assert(oi);
1999
2000 UNSET_FLAG(oi->flag, OSPF6_INTERFACE_NOAUTOCOST);
2001
2002 ospf6_interface_recalculate_cost(oi);
2003
2004 return CMD_SUCCESS;
2005 }
2006
2007 DEFUN (auto_cost_reference_bandwidth,
2008 auto_cost_reference_bandwidth_cmd,
2009 "auto-cost reference-bandwidth (1-4294967)",
2010 "Calculate OSPF interface cost according to bandwidth\n"
2011 "Use reference bandwidth method to assign OSPF cost\n"
2012 "The reference bandwidth in terms of Mbits per second\n")
2013 {
2014 VTY_DECLVAR_CONTEXT(ospf6, o);
2015 int idx_number = 2;
2016 struct ospf6_area *oa;
2017 struct ospf6_interface *oi;
2018 struct listnode *i, *j;
2019 uint32_t refbw;
2020
2021 refbw = strtol(argv[idx_number]->arg, NULL, 10);
2022 if (refbw < 1 || refbw > 4294967) {
2023 vty_out(vty, "reference-bandwidth value is invalid\n");
2024 return CMD_WARNING_CONFIG_FAILED;
2025 }
2026
2027 /* If reference bandwidth is changed. */
2028 if ((refbw) == o->ref_bandwidth)
2029 return CMD_SUCCESS;
2030
2031 o->ref_bandwidth = refbw;
2032 for (ALL_LIST_ELEMENTS_RO(o->area_list, i, oa))
2033 for (ALL_LIST_ELEMENTS_RO(oa->if_list, j, oi))
2034 ospf6_interface_recalculate_cost(oi);
2035
2036 return CMD_SUCCESS;
2037 }
2038
2039 DEFUN (no_auto_cost_reference_bandwidth,
2040 no_auto_cost_reference_bandwidth_cmd,
2041 "no auto-cost reference-bandwidth [(1-4294967)]",
2042 NO_STR
2043 "Calculate OSPF interface cost according to bandwidth\n"
2044 "Use reference bandwidth method to assign OSPF cost\n"
2045 "The reference bandwidth in terms of Mbits per second\n")
2046 {
2047 VTY_DECLVAR_CONTEXT(ospf6, o);
2048 struct ospf6_area *oa;
2049 struct ospf6_interface *oi;
2050 struct listnode *i, *j;
2051
2052 if (o->ref_bandwidth == OSPF6_REFERENCE_BANDWIDTH)
2053 return CMD_SUCCESS;
2054
2055 o->ref_bandwidth = OSPF6_REFERENCE_BANDWIDTH;
2056 for (ALL_LIST_ELEMENTS_RO(o->area_list, i, oa))
2057 for (ALL_LIST_ELEMENTS_RO(oa->if_list, j, oi))
2058 ospf6_interface_recalculate_cost(oi);
2059
2060 return CMD_SUCCESS;
2061 }
2062
2063
2064 DEFUN (ospf6_write_multiplier,
2065 ospf6_write_multiplier_cmd,
2066 "write-multiplier (1-100)",
2067 "Write multiplier\n"
2068 "Maximum number of interface serviced per write\n")
2069 {
2070 VTY_DECLVAR_CONTEXT(ospf6, o);
2071 uint32_t write_oi_count;
2072
2073 write_oi_count = strtol(argv[1]->arg, NULL, 10);
2074 if (write_oi_count < 1 || write_oi_count > 100) {
2075 vty_out(vty, "write-multiplier value is invalid\n");
2076 return CMD_WARNING_CONFIG_FAILED;
2077 }
2078
2079 o->write_oi_count = write_oi_count;
2080 return CMD_SUCCESS;
2081 }
2082
2083 DEFUN (no_ospf6_write_multiplier,
2084 no_ospf6_write_multiplier_cmd,
2085 "no write-multiplier (1-100)",
2086 NO_STR
2087 "Write multiplier\n"
2088 "Maximum number of interface serviced per write\n")
2089 {
2090 VTY_DECLVAR_CONTEXT(ospf6, o);
2091
2092 o->write_oi_count = OSPF6_WRITE_INTERFACE_COUNT_DEFAULT;
2093 return CMD_SUCCESS;
2094 }
2095
2096 DEFUN (ipv6_ospf6_hellointerval,
2097 ipv6_ospf6_hellointerval_cmd,
2098 "ipv6 ospf6 hello-interval (1-65535)",
2099 IP6_STR
2100 OSPF6_STR
2101 "Time between HELLO packets\n"
2102 SECONDS_STR)
2103 {
2104 VTY_DECLVAR_CONTEXT(interface, ifp);
2105 int idx_number = 3;
2106 struct ospf6_interface *oi;
2107 assert(ifp);
2108
2109 oi = (struct ospf6_interface *)ifp->info;
2110 if (oi == NULL)
2111 oi = ospf6_interface_create(ifp);
2112 assert(oi);
2113
2114 oi->hello_interval = strmatch(argv[0]->text, "no")
2115 ? OSPF_HELLO_INTERVAL_DEFAULT
2116 : strtoul(argv[idx_number]->arg, NULL, 10);
2117
2118 /*
2119 * If the thread is scheduled, send the new hello now.
2120 */
2121 if (thread_is_scheduled(oi->thread_send_hello)) {
2122 THREAD_OFF(oi->thread_send_hello);
2123
2124 thread_add_timer(master, ospf6_hello_send, oi, 0,
2125 &oi->thread_send_hello);
2126 }
2127 return CMD_SUCCESS;
2128 }
2129
2130 ALIAS (ipv6_ospf6_hellointerval,
2131 no_ipv6_ospf6_hellointerval_cmd,
2132 "no ipv6 ospf6 hello-interval [(1-65535)]",
2133 NO_STR
2134 IP6_STR
2135 OSPF6_STR
2136 "Time between HELLO packets\n"
2137 SECONDS_STR)
2138
2139 /* interface variable set command */
2140 DEFUN (ipv6_ospf6_deadinterval,
2141 ipv6_ospf6_deadinterval_cmd,
2142 "ipv6 ospf6 dead-interval (1-65535)",
2143 IP6_STR
2144 OSPF6_STR
2145 "Interval time after which a neighbor is declared down\n"
2146 SECONDS_STR)
2147 {
2148 VTY_DECLVAR_CONTEXT(interface, ifp);
2149 int idx_number = 3;
2150 struct ospf6_interface *oi;
2151 assert(ifp);
2152
2153 oi = (struct ospf6_interface *)ifp->info;
2154 if (oi == NULL)
2155 oi = ospf6_interface_create(ifp);
2156 assert(oi);
2157
2158 oi->dead_interval = strmatch(argv[0]->arg, "no")
2159 ? OSPF_ROUTER_DEAD_INTERVAL_DEFAULT
2160 : strtoul(argv[idx_number]->arg, NULL, 10);
2161 return CMD_SUCCESS;
2162 }
2163
2164 ALIAS (ipv6_ospf6_deadinterval,
2165 no_ipv6_ospf6_deadinterval_cmd,
2166 "no ipv6 ospf6 dead-interval [(1-65535)]",
2167 NO_STR
2168 IP6_STR
2169 OSPF6_STR
2170 "Interval time after which a neighbor is declared down\n"
2171 SECONDS_STR)
2172
2173 /* interface variable set command */
2174 DEFUN (ipv6_ospf6_transmitdelay,
2175 ipv6_ospf6_transmitdelay_cmd,
2176 "ipv6 ospf6 transmit-delay (1-3600)",
2177 IP6_STR
2178 OSPF6_STR
2179 "Link state transmit delay\n"
2180 SECONDS_STR)
2181 {
2182 VTY_DECLVAR_CONTEXT(interface, ifp);
2183 int idx_number = 3;
2184 struct ospf6_interface *oi;
2185 assert(ifp);
2186
2187 oi = (struct ospf6_interface *)ifp->info;
2188 if (oi == NULL)
2189 oi = ospf6_interface_create(ifp);
2190 assert(oi);
2191
2192 oi->transdelay = strmatch(argv[0]->text, "no")
2193 ? OSPF6_INTERFACE_TRANSDELAY
2194 : strtoul(argv[idx_number]->arg, NULL, 10);
2195 return CMD_SUCCESS;
2196 }
2197
2198 ALIAS (ipv6_ospf6_transmitdelay,
2199 no_ipv6_ospf6_transmitdelay_cmd,
2200 "no ipv6 ospf6 transmit-delay [(1-3600)]",
2201 NO_STR
2202 IP6_STR
2203 OSPF6_STR
2204 "Link state transmit delay\n"
2205 SECONDS_STR)
2206
2207 /* interface variable set command */
2208 DEFUN (ipv6_ospf6_retransmitinterval,
2209 ipv6_ospf6_retransmitinterval_cmd,
2210 "ipv6 ospf6 retransmit-interval (1-65535)",
2211 IP6_STR
2212 OSPF6_STR
2213 "Time between retransmitting lost link state advertisements\n"
2214 SECONDS_STR)
2215 {
2216 VTY_DECLVAR_CONTEXT(interface, ifp);
2217 int idx_number = 3;
2218 struct ospf6_interface *oi;
2219 assert(ifp);
2220
2221 oi = (struct ospf6_interface *)ifp->info;
2222 if (oi == NULL)
2223 oi = ospf6_interface_create(ifp);
2224 assert(oi);
2225
2226 oi->rxmt_interval = strmatch(argv[0]->text, "no")
2227 ? OSPF_RETRANSMIT_INTERVAL_DEFAULT
2228 : strtoul(argv[idx_number]->arg, NULL, 10);
2229 return CMD_SUCCESS;
2230 }
2231
2232 ALIAS (ipv6_ospf6_retransmitinterval,
2233 no_ipv6_ospf6_retransmitinterval_cmd,
2234 "no ipv6 ospf6 retransmit-interval [(1-65535)]",
2235 NO_STR
2236 IP6_STR
2237 OSPF6_STR
2238 "Time between retransmitting lost link state advertisements\n"
2239 SECONDS_STR)
2240
2241 /* interface variable set command */
2242 DEFUN (ipv6_ospf6_priority,
2243 ipv6_ospf6_priority_cmd,
2244 "ipv6 ospf6 priority (0-255)",
2245 IP6_STR
2246 OSPF6_STR
2247 "Router priority\n"
2248 "Priority value\n")
2249 {
2250 VTY_DECLVAR_CONTEXT(interface, ifp);
2251 int idx_number = 3;
2252 struct ospf6_interface *oi;
2253 assert(ifp);
2254
2255 oi = (struct ospf6_interface *)ifp->info;
2256 if (oi == NULL)
2257 oi = ospf6_interface_create(ifp);
2258 assert(oi);
2259
2260 oi->priority = strmatch(argv[0]->text, "no")
2261 ? OSPF6_INTERFACE_PRIORITY
2262 : strtoul(argv[idx_number]->arg, NULL, 10);
2263
2264 if (oi->area
2265 && (oi->state == OSPF6_INTERFACE_DROTHER
2266 || oi->state == OSPF6_INTERFACE_BDR
2267 || oi->state == OSPF6_INTERFACE_DR)) {
2268 if (ospf6_interface_state_change(dr_election(oi), oi) == -1)
2269 OSPF6_LINK_LSA_SCHEDULE(oi);
2270 }
2271
2272 return CMD_SUCCESS;
2273 }
2274
2275 ALIAS (ipv6_ospf6_priority,
2276 no_ipv6_ospf6_priority_cmd,
2277 "no ipv6 ospf6 priority [(0-255)]",
2278 NO_STR
2279 IP6_STR
2280 OSPF6_STR
2281 "Router priority\n"
2282 "Priority value\n")
2283
2284 DEFUN (ipv6_ospf6_instance,
2285 ipv6_ospf6_instance_cmd,
2286 "ipv6 ospf6 instance-id (0-255)",
2287 IP6_STR
2288 OSPF6_STR
2289 "Instance ID for this interface\n"
2290 "Instance ID value\n")
2291 {
2292 VTY_DECLVAR_CONTEXT(interface, ifp);
2293 int idx_number = 3;
2294 struct ospf6_interface *oi;
2295 assert(ifp);
2296
2297 oi = (struct ospf6_interface *)ifp->info;
2298 if (oi == NULL)
2299 oi = ospf6_interface_create(ifp);
2300 assert(oi);
2301
2302 oi->instance_id = strmatch(argv[0]->text, "no")
2303 ? OSPF6_INTERFACE_INSTANCE_ID
2304 : strtoul(argv[idx_number]->arg, NULL, 10);
2305 return CMD_SUCCESS;
2306 }
2307
2308 ALIAS (ipv6_ospf6_instance,
2309 no_ipv6_ospf6_instance_cmd,
2310 "no ipv6 ospf6 instance-id [(0-255)]",
2311 NO_STR
2312 IP6_STR
2313 OSPF6_STR
2314 "Instance ID for this interface\n"
2315 "Instance ID value\n")
2316
2317 DEFUN (ipv6_ospf6_passive,
2318 ipv6_ospf6_passive_cmd,
2319 "ipv6 ospf6 passive",
2320 IP6_STR
2321 OSPF6_STR
2322 "Passive interface; no adjacency will be formed on this interface\n"
2323 )
2324 {
2325 VTY_DECLVAR_CONTEXT(interface, ifp);
2326 struct ospf6_interface *oi;
2327 struct listnode *node, *nnode;
2328 struct ospf6_neighbor *on;
2329
2330 assert(ifp);
2331
2332 oi = (struct ospf6_interface *)ifp->info;
2333 if (oi == NULL)
2334 oi = ospf6_interface_create(ifp);
2335 assert(oi);
2336
2337 SET_FLAG(oi->flag, OSPF6_INTERFACE_PASSIVE);
2338 THREAD_OFF(oi->thread_send_hello);
2339 THREAD_OFF(oi->thread_sso);
2340
2341 for (ALL_LIST_ELEMENTS(oi->neighbor_list, node, nnode, on)) {
2342 THREAD_OFF(on->inactivity_timer);
2343 thread_add_event(master, inactivity_timer, on, 0, NULL);
2344 }
2345
2346 return CMD_SUCCESS;
2347 }
2348
2349 DEFUN (no_ipv6_ospf6_passive,
2350 no_ipv6_ospf6_passive_cmd,
2351 "no ipv6 ospf6 passive",
2352 NO_STR
2353 IP6_STR
2354 OSPF6_STR
2355 "passive interface: No Adjacency will be formed on this I/F\n"
2356 )
2357 {
2358 VTY_DECLVAR_CONTEXT(interface, ifp);
2359 struct ospf6_interface *oi;
2360 assert(ifp);
2361
2362 oi = (struct ospf6_interface *)ifp->info;
2363 if (oi == NULL)
2364 oi = ospf6_interface_create(ifp);
2365 assert(oi);
2366
2367 UNSET_FLAG(oi->flag, OSPF6_INTERFACE_PASSIVE);
2368 THREAD_OFF(oi->thread_send_hello);
2369 THREAD_OFF(oi->thread_sso);
2370
2371 /* don't send hellos over loopback interface */
2372 if (!if_is_loopback(oi->interface))
2373 thread_add_timer(master, ospf6_hello_send, oi, 0,
2374 &oi->thread_send_hello);
2375
2376 return CMD_SUCCESS;
2377 }
2378
2379 DEFUN (ipv6_ospf6_mtu_ignore,
2380 ipv6_ospf6_mtu_ignore_cmd,
2381 "ipv6 ospf6 mtu-ignore",
2382 IP6_STR
2383 OSPF6_STR
2384 "Disable MTU mismatch detection on this interface\n"
2385 )
2386 {
2387 VTY_DECLVAR_CONTEXT(interface, ifp);
2388 struct ospf6_interface *oi;
2389 assert(ifp);
2390
2391 oi = (struct ospf6_interface *)ifp->info;
2392 if (oi == NULL)
2393 oi = ospf6_interface_create(ifp);
2394 assert(oi);
2395
2396 oi->mtu_ignore = 1;
2397
2398 return CMD_SUCCESS;
2399 }
2400
2401 DEFUN (no_ipv6_ospf6_mtu_ignore,
2402 no_ipv6_ospf6_mtu_ignore_cmd,
2403 "no ipv6 ospf6 mtu-ignore",
2404 NO_STR
2405 IP6_STR
2406 OSPF6_STR
2407 "Disable MTU mismatch detection on this interface\n"
2408 )
2409 {
2410 VTY_DECLVAR_CONTEXT(interface, ifp);
2411 struct ospf6_interface *oi;
2412 assert(ifp);
2413
2414 oi = (struct ospf6_interface *)ifp->info;
2415 if (oi == NULL)
2416 oi = ospf6_interface_create(ifp);
2417 assert(oi);
2418
2419 oi->mtu_ignore = 0;
2420
2421 return CMD_SUCCESS;
2422 }
2423
2424 DEFUN (ipv6_ospf6_advertise_prefix_list,
2425 ipv6_ospf6_advertise_prefix_list_cmd,
2426 "ipv6 ospf6 advertise prefix-list WORD",
2427 IP6_STR
2428 OSPF6_STR
2429 "Advertising options\n"
2430 "Filter prefix using prefix-list\n"
2431 "Prefix list name\n"
2432 )
2433 {
2434 VTY_DECLVAR_CONTEXT(interface, ifp);
2435 int idx_word = 4;
2436 struct ospf6_interface *oi;
2437 assert(ifp);
2438
2439 oi = (struct ospf6_interface *)ifp->info;
2440 if (oi == NULL)
2441 oi = ospf6_interface_create(ifp);
2442 assert(oi);
2443
2444 if (oi->plist_name)
2445 XFREE(MTYPE_CFG_PLIST_NAME, oi->plist_name);
2446 oi->plist_name = XSTRDUP(MTYPE_CFG_PLIST_NAME, argv[idx_word]->arg);
2447
2448 ospf6_interface_connected_route_update(oi->interface);
2449
2450 if (oi->area) {
2451 OSPF6_LINK_LSA_SCHEDULE(oi);
2452 if (oi->state == OSPF6_INTERFACE_DR) {
2453 OSPF6_NETWORK_LSA_SCHEDULE(oi);
2454 OSPF6_INTRA_PREFIX_LSA_SCHEDULE_TRANSIT(oi);
2455 }
2456 OSPF6_INTRA_PREFIX_LSA_SCHEDULE_STUB(oi->area);
2457 }
2458
2459 return CMD_SUCCESS;
2460 }
2461
2462 DEFUN (no_ipv6_ospf6_advertise_prefix_list,
2463 no_ipv6_ospf6_advertise_prefix_list_cmd,
2464 "no ipv6 ospf6 advertise prefix-list [WORD]",
2465 NO_STR
2466 IP6_STR
2467 OSPF6_STR
2468 "Advertising options\n"
2469 "Filter prefix using prefix-list\n"
2470 "Prefix list name\n")
2471 {
2472 VTY_DECLVAR_CONTEXT(interface, ifp);
2473 struct ospf6_interface *oi;
2474 assert(ifp);
2475
2476 oi = (struct ospf6_interface *)ifp->info;
2477 if (oi == NULL)
2478 oi = ospf6_interface_create(ifp);
2479 assert(oi);
2480
2481 if (oi->plist_name)
2482 XFREE(MTYPE_CFG_PLIST_NAME, oi->plist_name);
2483
2484 ospf6_interface_connected_route_update(oi->interface);
2485
2486 if (oi->area) {
2487 OSPF6_LINK_LSA_SCHEDULE(oi);
2488 if (oi->state == OSPF6_INTERFACE_DR) {
2489 OSPF6_NETWORK_LSA_SCHEDULE(oi);
2490 OSPF6_INTRA_PREFIX_LSA_SCHEDULE_TRANSIT(oi);
2491 }
2492 OSPF6_INTRA_PREFIX_LSA_SCHEDULE_STUB(oi->area);
2493 }
2494
2495 return CMD_SUCCESS;
2496 }
2497
2498 DEFUN (ipv6_ospf6_network,
2499 ipv6_ospf6_network_cmd,
2500 "ipv6 ospf6 network <broadcast|point-to-point>",
2501 IP6_STR
2502 OSPF6_STR
2503 "Network type\n"
2504 "Specify OSPF6 broadcast network\n"
2505 "Specify OSPF6 point-to-point network\n"
2506 )
2507 {
2508 VTY_DECLVAR_CONTEXT(interface, ifp);
2509 int idx_network = 3;
2510 struct ospf6_interface *oi;
2511 assert(ifp);
2512
2513 oi = (struct ospf6_interface *)ifp->info;
2514 if (oi == NULL) {
2515 oi = ospf6_interface_create(ifp);
2516 }
2517 assert(oi);
2518
2519 oi->type_cfg = true;
2520
2521 if (strncmp(argv[idx_network]->arg, "b", 1) == 0) {
2522 if (oi->type == OSPF_IFTYPE_BROADCAST)
2523 return CMD_SUCCESS;
2524
2525 oi->type = OSPF_IFTYPE_BROADCAST;
2526 } else if (strncmp(argv[idx_network]->arg, "point-to-p", 10) == 0) {
2527 if (oi->type == OSPF_IFTYPE_POINTOPOINT) {
2528 return CMD_SUCCESS;
2529 }
2530 oi->type = OSPF_IFTYPE_POINTOPOINT;
2531 }
2532
2533 /* Reset the interface */
2534 thread_execute(master, interface_down, oi, 0);
2535 thread_execute(master, interface_up, oi, 0);
2536
2537 return CMD_SUCCESS;
2538 }
2539
2540 DEFUN (no_ipv6_ospf6_network,
2541 no_ipv6_ospf6_network_cmd,
2542 "no ipv6 ospf6 network [<broadcast|point-to-point>]",
2543 NO_STR
2544 IP6_STR
2545 OSPF6_STR
2546 "Set default network type\n"
2547 "Specify OSPF6 broadcast network\n"
2548 "Specify OSPF6 point-to-point network\n")
2549 {
2550 VTY_DECLVAR_CONTEXT(interface, ifp);
2551 struct ospf6_interface *oi;
2552 int type;
2553
2554 assert(ifp);
2555
2556 oi = (struct ospf6_interface *)ifp->info;
2557 if (oi == NULL) {
2558 return CMD_SUCCESS;
2559 }
2560
2561 oi->type_cfg = false;
2562
2563 type = ospf6_default_iftype(ifp);
2564 if (oi->type == type) {
2565 return CMD_SUCCESS;
2566 }
2567 oi->type = type;
2568
2569 /* Reset the interface */
2570 thread_execute(master, interface_down, oi, 0);
2571 thread_execute(master, interface_up, oi, 0);
2572
2573 return CMD_SUCCESS;
2574 }
2575
2576 static int config_write_ospf6_interface(struct vty *vty, struct vrf *vrf)
2577 {
2578 struct ospf6_interface *oi;
2579 struct interface *ifp;
2580 char buf[INET_ADDRSTRLEN];
2581
2582 FOR_ALL_INTERFACES (vrf, ifp) {
2583 oi = (struct ospf6_interface *)ifp->info;
2584 if (oi == NULL)
2585 continue;
2586
2587 if_vty_config_start(vty, ifp);
2588
2589 if (ifp->desc)
2590 vty_out(vty, " description %s\n", ifp->desc);
2591 if (oi->area_id_format != OSPF6_AREA_FMT_UNSET) {
2592 area_id2str(buf, sizeof(buf), oi->area_id,
2593 oi->area_id_format);
2594 vty_out(vty, " ipv6 ospf6 area %s\n", buf);
2595 }
2596 if (oi->c_ifmtu)
2597 vty_out(vty, " ipv6 ospf6 ifmtu %d\n", oi->c_ifmtu);
2598
2599 if (CHECK_FLAG(oi->flag, OSPF6_INTERFACE_NOAUTOCOST))
2600 vty_out(vty, " ipv6 ospf6 cost %d\n", oi->cost);
2601
2602 if (oi->hello_interval != OSPF6_INTERFACE_HELLO_INTERVAL)
2603 vty_out(vty, " ipv6 ospf6 hello-interval %d\n",
2604 oi->hello_interval);
2605
2606 if (oi->dead_interval != OSPF6_INTERFACE_DEAD_INTERVAL)
2607 vty_out(vty, " ipv6 ospf6 dead-interval %d\n",
2608 oi->dead_interval);
2609
2610 if (oi->rxmt_interval != OSPF6_INTERFACE_RXMT_INTERVAL)
2611 vty_out(vty, " ipv6 ospf6 retransmit-interval %d\n",
2612 oi->rxmt_interval);
2613
2614 if (oi->priority != OSPF6_INTERFACE_PRIORITY)
2615 vty_out(vty, " ipv6 ospf6 priority %d\n", oi->priority);
2616
2617 if (oi->transdelay != OSPF6_INTERFACE_TRANSDELAY)
2618 vty_out(vty, " ipv6 ospf6 transmit-delay %d\n",
2619 oi->transdelay);
2620
2621 if (oi->instance_id != OSPF6_INTERFACE_INSTANCE_ID)
2622 vty_out(vty, " ipv6 ospf6 instance-id %d\n",
2623 oi->instance_id);
2624
2625 if (oi->plist_name)
2626 vty_out(vty, " ipv6 ospf6 advertise prefix-list %s\n",
2627 oi->plist_name);
2628
2629 if (CHECK_FLAG(oi->flag, OSPF6_INTERFACE_PASSIVE))
2630 vty_out(vty, " ipv6 ospf6 passive\n");
2631
2632 if (oi->mtu_ignore)
2633 vty_out(vty, " ipv6 ospf6 mtu-ignore\n");
2634
2635 if (oi->type_cfg && oi->type == OSPF_IFTYPE_POINTOPOINT)
2636 vty_out(vty, " ipv6 ospf6 network point-to-point\n");
2637 else if (oi->type_cfg && oi->type == OSPF_IFTYPE_BROADCAST)
2638 vty_out(vty, " ipv6 ospf6 network broadcast\n");
2639
2640 ospf6_bfd_write_config(vty, oi);
2641
2642 ospf6_auth_write_config(vty, &oi->at_data);
2643 if_vty_config_end(vty);
2644 }
2645 return 0;
2646 }
2647
2648 /* Configuration write function for ospfd. */
2649 static int config_write_interface(struct vty *vty)
2650 {
2651 int write = 0;
2652 struct vrf *vrf = NULL;
2653
2654 /* Display all VRF aware OSPF interface configuration */
2655 RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
2656 write += config_write_ospf6_interface(vty, vrf);
2657 }
2658
2659 return write;
2660 }
2661
2662 static int ospf6_ifp_create(struct interface *ifp)
2663 {
2664 if (IS_OSPF6_DEBUG_ZEBRA(RECV))
2665 zlog_debug("Zebra Interface add: %s index %d mtu %d", ifp->name,
2666 ifp->ifindex, ifp->mtu6);
2667
2668 if (ifp->info)
2669 ospf6_interface_start(ifp->info);
2670
2671 return 0;
2672 }
2673
2674 static int ospf6_ifp_up(struct interface *ifp)
2675 {
2676 if (IS_OSPF6_DEBUG_ZEBRA(RECV))
2677 zlog_debug(
2678 "Zebra Interface state change: %s index %d flags %llx metric %d mtu %d bandwidth %d",
2679 ifp->name, ifp->ifindex, (unsigned long long)ifp->flags,
2680 ifp->metric, ifp->mtu6, ifp->bandwidth);
2681
2682 ospf6_interface_state_update(ifp);
2683
2684 return 0;
2685 }
2686
2687 static int ospf6_ifp_down(struct interface *ifp)
2688 {
2689 if (IS_OSPF6_DEBUG_ZEBRA(RECV))
2690 zlog_debug(
2691 "Zebra Interface state change: %s index %d flags %llx metric %d mtu %d bandwidth %d",
2692 ifp->name, ifp->ifindex, (unsigned long long)ifp->flags,
2693 ifp->metric, ifp->mtu6, ifp->bandwidth);
2694
2695 ospf6_interface_state_update(ifp);
2696
2697 return 0;
2698 }
2699
2700 static int ospf6_ifp_destroy(struct interface *ifp)
2701 {
2702 if (if_is_up(ifp))
2703 zlog_warn("Zebra: got delete of %s, but interface is still up",
2704 ifp->name);
2705
2706 if (IS_OSPF6_DEBUG_ZEBRA(RECV))
2707 zlog_debug("Zebra Interface delete: %s index %d mtu %d",
2708 ifp->name, ifp->ifindex, ifp->mtu6);
2709
2710 if (ifp->info)
2711 ospf6_interface_stop(ifp->info);
2712
2713 return 0;
2714 }
2715
2716 void ospf6_interface_init(void)
2717 {
2718 /* Install interface node. */
2719 if_cmd_init(config_write_interface);
2720 if_zapi_callbacks(ospf6_ifp_create, ospf6_ifp_up,
2721 ospf6_ifp_down, ospf6_ifp_destroy);
2722
2723 install_element(VIEW_NODE, &show_ipv6_ospf6_interface_prefix_cmd);
2724 install_element(VIEW_NODE, &show_ipv6_ospf6_interface_ifname_cmd);
2725 install_element(VIEW_NODE,
2726 &show_ipv6_ospf6_interface_ifname_prefix_cmd);
2727 install_element(VIEW_NODE, &show_ipv6_ospf6_interface_traffic_cmd);
2728
2729 install_element(INTERFACE_NODE, &ipv6_ospf6_area_cmd);
2730 install_element(INTERFACE_NODE, &no_ipv6_ospf6_area_cmd);
2731 install_element(INTERFACE_NODE, &ipv6_ospf6_cost_cmd);
2732 install_element(INTERFACE_NODE, &no_ipv6_ospf6_cost_cmd);
2733 install_element(INTERFACE_NODE, &ipv6_ospf6_ifmtu_cmd);
2734 install_element(INTERFACE_NODE, &no_ipv6_ospf6_ifmtu_cmd);
2735
2736 install_element(INTERFACE_NODE, &ipv6_ospf6_deadinterval_cmd);
2737 install_element(INTERFACE_NODE, &ipv6_ospf6_hellointerval_cmd);
2738 install_element(INTERFACE_NODE, &ipv6_ospf6_priority_cmd);
2739 install_element(INTERFACE_NODE, &ipv6_ospf6_retransmitinterval_cmd);
2740 install_element(INTERFACE_NODE, &ipv6_ospf6_transmitdelay_cmd);
2741 install_element(INTERFACE_NODE, &ipv6_ospf6_instance_cmd);
2742 install_element(INTERFACE_NODE, &no_ipv6_ospf6_deadinterval_cmd);
2743 install_element(INTERFACE_NODE, &no_ipv6_ospf6_hellointerval_cmd);
2744 install_element(INTERFACE_NODE, &no_ipv6_ospf6_priority_cmd);
2745 install_element(INTERFACE_NODE, &no_ipv6_ospf6_retransmitinterval_cmd);
2746 install_element(INTERFACE_NODE, &no_ipv6_ospf6_transmitdelay_cmd);
2747 install_element(INTERFACE_NODE, &no_ipv6_ospf6_instance_cmd);
2748
2749 install_element(INTERFACE_NODE, &ipv6_ospf6_passive_cmd);
2750 install_element(INTERFACE_NODE, &no_ipv6_ospf6_passive_cmd);
2751
2752 install_element(INTERFACE_NODE, &ipv6_ospf6_mtu_ignore_cmd);
2753 install_element(INTERFACE_NODE, &no_ipv6_ospf6_mtu_ignore_cmd);
2754
2755 install_element(INTERFACE_NODE, &ipv6_ospf6_advertise_prefix_list_cmd);
2756 install_element(INTERFACE_NODE,
2757 &no_ipv6_ospf6_advertise_prefix_list_cmd);
2758
2759 install_element(INTERFACE_NODE, &ipv6_ospf6_network_cmd);
2760 install_element(INTERFACE_NODE, &no_ipv6_ospf6_network_cmd);
2761
2762 /* reference bandwidth commands */
2763 install_element(OSPF6_NODE, &auto_cost_reference_bandwidth_cmd);
2764 install_element(OSPF6_NODE, &no_auto_cost_reference_bandwidth_cmd);
2765 /* write-multiplier commands */
2766 install_element(OSPF6_NODE, &ospf6_write_multiplier_cmd);
2767 install_element(OSPF6_NODE, &no_ospf6_write_multiplier_cmd);
2768 }
2769
2770 /* Clear the specified interface structure */
2771 void ospf6_interface_clear(struct interface *ifp)
2772 {
2773 struct ospf6_interface *oi;
2774
2775 if (!if_is_operative(ifp))
2776 return;
2777
2778 if (ifp->info == NULL)
2779 return;
2780
2781 oi = (struct ospf6_interface *)ifp->info;
2782
2783 if (IS_OSPF6_DEBUG_INTERFACE)
2784 zlog_debug("Interface %s: clear by reset", ifp->name);
2785
2786 /* Reset the interface */
2787 thread_execute(master, interface_down, oi, 0);
2788 thread_execute(master, interface_up, oi, 0);
2789 }
2790
2791 /* Clear interface */
2792 DEFUN (clear_ipv6_ospf6_interface,
2793 clear_ipv6_ospf6_interface_cmd,
2794 "clear ipv6 ospf6 [vrf NAME] interface [IFNAME]",
2795 CLEAR_STR
2796 IP6_STR
2797 OSPF6_STR
2798 VRF_CMD_HELP_STR
2799 INTERFACE_STR
2800 IFNAME_STR
2801 )
2802 {
2803 struct vrf *vrf;
2804 int idx_vrf = 3;
2805 int idx_ifname = 4;
2806 struct interface *ifp;
2807 const char *vrf_name;
2808
2809 if (argv_find(argv, argc, "vrf", &idx_vrf))
2810 vrf_name = argv[idx_vrf + 1]->arg;
2811 else
2812 vrf_name = VRF_DEFAULT_NAME;
2813 vrf = vrf_lookup_by_name(vrf_name);
2814 if (!vrf) {
2815 vty_out(vty, "%% VRF %s not found\n", vrf_name);
2816 return CMD_WARNING;
2817 }
2818
2819 if (!argv_find(argv, argc, "IFNAME", &idx_ifname)) {
2820 /* Clear all the ospfv3 interfaces. */
2821 FOR_ALL_INTERFACES (vrf, ifp)
2822 ospf6_interface_clear(ifp);
2823 } else {
2824 /* Interface name is specified. */
2825 ifp = if_lookup_by_name_vrf(argv[idx_ifname]->arg, vrf);
2826 if (!ifp) {
2827 vty_out(vty, "No such Interface: %s\n",
2828 argv[idx_ifname]->arg);
2829 return CMD_WARNING;
2830 }
2831 ospf6_interface_clear(ifp);
2832 }
2833
2834 return CMD_SUCCESS;
2835 }
2836
2837 void install_element_ospf6_clear_interface(void)
2838 {
2839 install_element(ENABLE_NODE, &clear_ipv6_ospf6_interface_cmd);
2840 }
2841
2842 DEFUN (debug_ospf6_interface,
2843 debug_ospf6_interface_cmd,
2844 "debug ospf6 interface",
2845 DEBUG_STR
2846 OSPF6_STR
2847 "Debug OSPFv3 Interface\n"
2848 )
2849 {
2850 OSPF6_DEBUG_INTERFACE_ON();
2851 return CMD_SUCCESS;
2852 }
2853
2854 DEFUN (no_debug_ospf6_interface,
2855 no_debug_ospf6_interface_cmd,
2856 "no debug ospf6 interface",
2857 NO_STR
2858 DEBUG_STR
2859 OSPF6_STR
2860 "Debug OSPFv3 Interface\n"
2861 )
2862 {
2863 OSPF6_DEBUG_INTERFACE_OFF();
2864 return CMD_SUCCESS;
2865 }
2866
2867 int config_write_ospf6_debug_interface(struct vty *vty)
2868 {
2869 if (IS_OSPF6_DEBUG_INTERFACE)
2870 vty_out(vty, "debug ospf6 interface\n");
2871 return 0;
2872 }
2873
2874 void install_element_ospf6_debug_interface(void)
2875 {
2876 install_element(ENABLE_NODE, &debug_ospf6_interface_cmd);
2877 install_element(ENABLE_NODE, &no_debug_ospf6_interface_cmd);
2878 install_element(CONFIG_NODE, &debug_ospf6_interface_cmd);
2879 install_element(CONFIG_NODE, &no_debug_ospf6_interface_cmd);
2880 }
2881
2882 void ospf6_auth_write_config(struct vty *vty, struct ospf6_auth_data *at_data)
2883 {
2884 if (CHECK_FLAG(at_data->flags, OSPF6_AUTH_TRAILER_KEYCHAIN))
2885 vty_out(vty, " ipv6 ospf6 authentication keychain %s\n",
2886 at_data->keychain);
2887 else if (CHECK_FLAG(at_data->flags, OSPF6_AUTH_TRAILER_MANUAL_KEY))
2888 vty_out(vty,
2889 " ipv6 ospf6 authentication key-id %d hash-algo %s key %s\n",
2890 at_data->key_id,
2891 keychain_get_algo_name_by_id(at_data->hash_algo),
2892 at_data->auth_key);
2893 }
2894
2895 DEFUN(ipv6_ospf6_intf_auth_trailer_keychain,
2896 ipv6_ospf6_intf_auth_trailer_keychain_cmd,
2897 "ipv6 ospf6 authentication keychain KEYCHAIN_NAME",
2898 IP6_STR OSPF6_STR
2899 "Enable authentication on this interface\n"
2900 "Keychain\n"
2901 "Keychain name\n")
2902 {
2903 VTY_DECLVAR_CONTEXT(interface, ifp);
2904 int keychain_idx = 4;
2905 struct ospf6_interface *oi;
2906
2907 oi = (struct ospf6_interface *)ifp->info;
2908 if (oi == NULL)
2909 oi = ospf6_interface_create(ifp);
2910
2911 assert(oi);
2912 if (CHECK_FLAG(oi->at_data.flags, OSPF6_AUTH_TRAILER_MANUAL_KEY)) {
2913 vty_out(vty,
2914 "Manual key configured, unconfigure it before configuring key chain\n");
2915 return CMD_WARNING_CONFIG_FAILED;
2916 }
2917
2918 SET_FLAG(oi->at_data.flags, OSPF6_AUTH_TRAILER_KEYCHAIN);
2919 if (oi->at_data.keychain)
2920 XFREE(MTYPE_OSPF6_AUTH_KEYCHAIN, oi->at_data.keychain);
2921
2922 oi->at_data.keychain =
2923 XSTRDUP(MTYPE_OSPF6_AUTH_KEYCHAIN, argv[keychain_idx]->arg);
2924
2925 return CMD_SUCCESS;
2926 }
2927
2928 DEFUN(no_ipv6_ospf6_intf_auth_trailer_keychain,
2929 no_ipv6_ospf6_intf_auth_trailer_keychain_cmd,
2930 "no ipv6 ospf6 authentication keychain [KEYCHAIN_NAME]",
2931 NO_STR IP6_STR OSPF6_STR
2932 "Enable authentication on this interface\n"
2933 "Keychain\n"
2934 "Keychain name\n")
2935 {
2936 VTY_DECLVAR_CONTEXT(interface, ifp);
2937 struct ospf6_interface *oi;
2938
2939 oi = (struct ospf6_interface *)ifp->info;
2940 if (oi == NULL)
2941 oi = ospf6_interface_create(ifp);
2942
2943 assert(oi);
2944 if (!CHECK_FLAG(oi->at_data.flags, OSPF6_AUTH_TRAILER_KEYCHAIN))
2945 return CMD_SUCCESS;
2946
2947 if (oi->at_data.keychain) {
2948 oi->at_data.flags = 0;
2949 XFREE(MTYPE_OSPF6_AUTH_KEYCHAIN, oi->at_data.keychain);
2950 oi->at_data.keychain = NULL;
2951 }
2952
2953 return CMD_SUCCESS;
2954 }
2955
2956 DEFUN(ipv6_ospf6_intf_auth_trailer_key, ipv6_ospf6_intf_auth_trailer_key_cmd,
2957 "ipv6 ospf6 authentication key-id (1-65535) hash-algo "
2958 "<md5|hmac-sha-1|hmac-sha-256|hmac-sha-384|hmac-sha-512> "
2959 "key WORD",
2960 IP6_STR OSPF6_STR
2961 "Authentication\n"
2962 "Key ID\n"
2963 "Key ID value\n"
2964 "Cryptographic-algorithm\n"
2965 "Use MD5 algorithm\n"
2966 "Use HMAC-SHA-1 algorithm\n"
2967 "Use HMAC-SHA-256 algorithm\n"
2968 "Use HMAC-SHA-384 algorithm\n"
2969 "Use HMAC-SHA-512 algorithm\n"
2970 "Password\n"
2971 "Password string (key)\n")
2972 {
2973 VTY_DECLVAR_CONTEXT(interface, ifp);
2974 int key_id_idx = 4;
2975 int hash_algo_idx = 6;
2976 int password_idx = 8;
2977 struct ospf6_interface *oi;
2978 uint8_t hash_algo = KEYCHAIN_ALGO_NULL;
2979
2980 oi = (struct ospf6_interface *)ifp->info;
2981 if (oi == NULL)
2982 oi = ospf6_interface_create(ifp);
2983
2984 assert(oi);
2985 if (CHECK_FLAG(oi->at_data.flags, OSPF6_AUTH_TRAILER_KEYCHAIN)) {
2986 vty_out(vty,
2987 "key chain configured, unconfigure it before configuring manual key\n");
2988 return CMD_WARNING_CONFIG_FAILED;
2989 }
2990
2991 hash_algo = keychain_get_algo_id_by_name(argv[hash_algo_idx]->arg);
2992 #ifndef CRYPTO_OPENSSL
2993 if (hash_algo == KEYCHAIN_ALGO_NULL) {
2994 vty_out(vty,
2995 "Hash algorithm not supported, compile with --with-crypto=openssl\n");
2996 return CMD_WARNING_CONFIG_FAILED;
2997 }
2998 #endif /* CRYPTO_OPENSSL */
2999
3000 SET_FLAG(oi->at_data.flags, OSPF6_AUTH_TRAILER_MANUAL_KEY);
3001 oi->at_data.hash_algo = hash_algo;
3002 oi->at_data.key_id = (uint16_t)strtol(argv[key_id_idx]->arg, NULL, 10);
3003 if (oi->at_data.auth_key)
3004 XFREE(MTYPE_OSPF6_AUTH_MANUAL_KEY, oi->at_data.auth_key);
3005 oi->at_data.auth_key =
3006 XSTRDUP(MTYPE_OSPF6_AUTH_MANUAL_KEY, argv[password_idx]->arg);
3007
3008 return CMD_SUCCESS;
3009 }
3010
3011 DEFUN(no_ipv6_ospf6_intf_auth_trailer_key,
3012 no_ipv6_ospf6_intf_auth_trailer_key_cmd,
3013 "no ipv6 ospf6 authentication key-id [(1-65535) hash-algo "
3014 "<md5|hmac-sha-1|hmac-sha-256|hmac-sha-384|hmac-sha-512> "
3015 "key WORD]",
3016 NO_STR IP6_STR OSPF6_STR
3017 "Authentication\n"
3018 "Key ID\n"
3019 "Key ID value\n"
3020 "Cryptographic-algorithm\n"
3021 "Use MD5 algorithm\n"
3022 "Use HMAC-SHA-1 algorithm\n"
3023 "Use HMAC-SHA-256 algorithm\n"
3024 "Use HMAC-SHA-384 algorithm\n"
3025 "Use HMAC-SHA-512 algorithm\n"
3026 "Password\n"
3027 "Password string (key)\n")
3028 {
3029 VTY_DECLVAR_CONTEXT(interface, ifp);
3030 struct ospf6_interface *oi;
3031 #ifndef CRYPTO_OPENSSL
3032 int hash_algo_idx = 7;
3033 uint8_t hash_algo = KEYCHAIN_ALGO_NULL;
3034 #endif /* CRYPTO_OPENSSL */
3035
3036 oi = (struct ospf6_interface *)ifp->info;
3037 if (oi == NULL)
3038 oi = ospf6_interface_create(ifp);
3039
3040 assert(oi);
3041 if (!CHECK_FLAG(oi->at_data.flags, OSPF6_AUTH_TRAILER_MANUAL_KEY))
3042 return CMD_SUCCESS;
3043
3044 #ifndef CRYPTO_OPENSSL
3045 hash_algo = keychain_get_algo_id_by_name(argv[hash_algo_idx]->arg);
3046 if (hash_algo == KEYCHAIN_ALGO_NULL) {
3047 vty_out(vty,
3048 "Hash algorithm not supported, compile with --with-crypto=openssl\n");
3049 return CMD_WARNING_CONFIG_FAILED;
3050 }
3051 #endif /* CRYPTO_OPENSSL */
3052
3053 if (oi->at_data.auth_key) {
3054 oi->at_data.flags = 0;
3055 XFREE(MTYPE_OSPF6_AUTH_MANUAL_KEY, oi->at_data.auth_key);
3056 oi->at_data.auth_key = NULL;
3057 }
3058
3059 return CMD_SUCCESS;
3060 }
3061
3062 void ospf6_interface_auth_trailer_cmd_init(void)
3063 {
3064 /*Install OSPF6 auth trailer commands at interface level */
3065 install_element(INTERFACE_NODE,
3066 &ipv6_ospf6_intf_auth_trailer_keychain_cmd);
3067 install_element(INTERFACE_NODE,
3068 &no_ipv6_ospf6_intf_auth_trailer_keychain_cmd);
3069 install_element(INTERFACE_NODE, &ipv6_ospf6_intf_auth_trailer_key_cmd);
3070 install_element(INTERFACE_NODE,
3071 &no_ipv6_ospf6_intf_auth_trailer_key_cmd);
3072 }