]> git.proxmox.com Git - mirror_frr.git/blame - ospf6d/ospf6_area.c
bgpd, lib, ospf6d, vtysh: fix possible snprintf possible truncation
[mirror_frr.git] / ospf6d / ospf6_area.c
CommitLineData
718e3744 1/*
508e53e2 2 * Copyright (C) 2003 Yasuhiro Ohara
718e3744 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 *
896014f4
DL
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
718e3744 19 */
20
508e53e2 21#include <zebra.h>
22
23#include "log.h"
24#include "memory.h"
25#include "linklist.h"
26#include "thread.h"
27#include "vty.h"
28#include "command.h"
29#include "if.h"
30#include "prefix.h"
31#include "table.h"
34956b31 32#include "plist.h"
33#include "filter.h"
508e53e2 34
508e53e2 35#include "ospf6_proto.h"
36#include "ospf6_lsa.h"
37#include "ospf6_lsdb.h"
38#include "ospf6_route.h"
39#include "ospf6_spf.h"
40#include "ospf6_top.h"
41#include "ospf6_area.h"
42#include "ospf6_interface.h"
43#include "ospf6_intra.h"
049207c3 44#include "ospf6_abr.h"
ca1f4309 45#include "ospf6_asbr.h"
049207c3 46#include "ospf6d.h"
718e3744 47
427f8e61
DL
48DEFINE_MTYPE_STATIC(OSPF6D, OSPF6_PLISTNAME, "Prefix list name")
49
d62a17ae 50int ospf6_area_cmp(void *va, void *vb)
508e53e2 51{
d62a17ae 52 struct ospf6_area *oa = (struct ospf6_area *)va;
53 struct ospf6_area *ob = (struct ospf6_area *)vb;
54 return (ntohl(oa->area_id) < ntohl(ob->area_id) ? -1 : 1);
508e53e2 55}
718e3744 56
508e53e2 57/* schedule routing table recalculation */
d62a17ae 58static void ospf6_area_lsdb_hook_add(struct ospf6_lsa *lsa)
59{
60 switch (ntohs(lsa->header->type)) {
61 case OSPF6_LSTYPE_ROUTER:
62 case OSPF6_LSTYPE_NETWORK:
63 if (IS_OSPF6_DEBUG_EXAMIN_TYPE(lsa->header->type)) {
996c9314
LB
64 zlog_debug("%s Examin LSA %s", __PRETTY_FUNCTION__,
65 lsa->name);
26e14616 66 zlog_debug(" Schedule SPF Calculation for %s",
d62a17ae 67 OSPF6_AREA(lsa->lsdb->data)->name);
68 }
69 ospf6_spf_schedule(
70 OSPF6_PROCESS(OSPF6_AREA(lsa->lsdb->data)->ospf6),
71 ospf6_lsadd_to_spf_reason(lsa));
72 break;
73
74 case OSPF6_LSTYPE_INTRA_PREFIX:
75 ospf6_intra_prefix_lsa_add(lsa);
76 break;
77
78 case OSPF6_LSTYPE_INTER_PREFIX:
79 case OSPF6_LSTYPE_INTER_ROUTER:
80 ospf6_abr_examin_summary(lsa,
81 (struct ospf6_area *)lsa->lsdb->data);
82 break;
83
84 default:
85 break;
86 }
718e3744 87}
88
d62a17ae 89static void ospf6_area_lsdb_hook_remove(struct ospf6_lsa *lsa)
90{
91 switch (ntohs(lsa->header->type)) {
92 case OSPF6_LSTYPE_ROUTER:
93 case OSPF6_LSTYPE_NETWORK:
94 if (IS_OSPF6_DEBUG_EXAMIN_TYPE(lsa->header->type)) {
95 zlog_debug("LSA disappearing: %s", lsa->name);
96 zlog_debug("Schedule SPF Calculation for %s",
97 OSPF6_AREA(lsa->lsdb->data)->name);
98 }
99 ospf6_spf_schedule(
100 OSPF6_PROCESS(OSPF6_AREA(lsa->lsdb->data)->ospf6),
101 ospf6_lsremove_to_spf_reason(lsa));
102 break;
103
104 case OSPF6_LSTYPE_INTRA_PREFIX:
105 ospf6_intra_prefix_lsa_remove(lsa);
106 break;
107
108 case OSPF6_LSTYPE_INTER_PREFIX:
109 case OSPF6_LSTYPE_INTER_ROUTER:
110 ospf6_abr_examin_summary(lsa,
111 (struct ospf6_area *)lsa->lsdb->data);
112 break;
113
114 default:
115 break;
116 }
718e3744 117}
118
d62a17ae 119static void ospf6_area_route_hook_add(struct ospf6_route *route)
718e3744 120{
064d4355
CS
121 struct ospf6_route *copy;
122
123 copy = ospf6_route_copy(route);
d62a17ae 124 ospf6_route_add(copy, ospf6->route_table);
718e3744 125}
126
d62a17ae 127static void ospf6_area_route_hook_remove(struct ospf6_route *route)
718e3744 128{
d62a17ae 129 struct ospf6_route *copy;
718e3744 130
d62a17ae 131 copy = ospf6_route_lookup_identical(route, ospf6->route_table);
132 if (copy)
133 ospf6_route_remove(copy, ospf6->route_table);
718e3744 134}
135
d62a17ae 136static void ospf6_area_stub_update(struct ospf6_area *area)
ca1f4309
DS
137{
138
d62a17ae 139 if (IS_AREA_STUB(area)) {
140 if (IS_OSPF6_DEBUG_ORIGINATE(ROUTER))
141 zlog_debug("Stubbing out area for if %s\n", area->name);
142 OSPF6_OPT_CLEAR(area->options, OSPF6_OPT_E);
143 } else if (IS_AREA_ENABLED(area)) {
144 if (IS_OSPF6_DEBUG_ORIGINATE(ROUTER))
145 zlog_debug("Normal area for if %s\n", area->name);
146 OSPF6_OPT_SET(area->options, OSPF6_OPT_E);
147 ospf6_asbr_send_externals_to_area(area);
148 }
149
150 OSPF6_ROUTER_LSA_SCHEDULE(area);
ca1f4309
DS
151}
152
d62a17ae 153static int ospf6_area_stub_set(struct ospf6 *ospf6, struct ospf6_area *area)
ca1f4309 154{
d62a17ae 155 if (!IS_AREA_STUB(area)) {
156 SET_FLAG(area->flag, OSPF6_AREA_STUB);
157 ospf6_area_stub_update(area);
158 }
ca1f4309 159
d62a17ae 160 return (1);
ca1f4309
DS
161}
162
d62a17ae 163static void ospf6_area_stub_unset(struct ospf6 *ospf6, struct ospf6_area *area)
ca1f4309 164{
d62a17ae 165 if (IS_AREA_STUB(area)) {
166 UNSET_FLAG(area->flag, OSPF6_AREA_STUB);
167 ospf6_area_stub_update(area);
168 }
ca1f4309
DS
169}
170
d62a17ae 171static void ospf6_area_no_summary_set(struct ospf6 *ospf6,
172 struct ospf6_area *area)
ca1f4309 173{
d62a17ae 174 if (area) {
175 if (!area->no_summary) {
176 area->no_summary = 1;
177 ospf6_abr_range_reset_cost(ospf6);
178 ospf6_abr_prefix_resummarize(ospf6);
179 }
ca1f4309 180 }
ca1f4309
DS
181}
182
d62a17ae 183static void ospf6_area_no_summary_unset(struct ospf6 *ospf6,
184 struct ospf6_area *area)
ca1f4309 185{
d62a17ae 186 if (area) {
187 if (area->no_summary) {
188 area->no_summary = 0;
189 ospf6_abr_range_reset_cost(ospf6);
190 ospf6_abr_prefix_resummarize(ospf6);
191 }
ca1f4309 192 }
ca1f4309
DS
193}
194
79c3f4f4
QY
195/**
196 * Make new area structure.
197 *
198 * @param area_id - ospf6 area ID
199 * @param o - ospf6 instance
200 * @param df - display format for area ID
201 */
d7c0a89a 202struct ospf6_area *ospf6_area_create(uint32_t area_id, struct ospf6 *o, int df)
718e3744 203{
d62a17ae 204 struct ospf6_area *oa;
205
206 oa = XCALLOC(MTYPE_OSPF6_AREA, sizeof(struct ospf6_area));
207
208 switch (df) {
209 case OSPF6_AREA_FMT_DECIMAL:
210 snprintf(oa->name, sizeof(oa->name), "%u", ntohl(area_id));
211 break;
212 default:
213 case OSPF6_AREA_FMT_DOTTEDQUAD:
214 inet_ntop(AF_INET, &area_id, oa->name, sizeof(oa->name));
215 break;
216 }
217
218 oa->area_id = area_id;
219 oa->if_list = list_new();
220
221 oa->lsdb = ospf6_lsdb_create(oa);
222 oa->lsdb->hook_add = ospf6_area_lsdb_hook_add;
223 oa->lsdb->hook_remove = ospf6_area_lsdb_hook_remove;
224 oa->lsdb_self = ospf6_lsdb_create(oa);
da086a3b 225 oa->temp_router_lsa_lsdb = ospf6_lsdb_create(oa);
d62a17ae 226
227 oa->spf_table = OSPF6_ROUTE_TABLE_CREATE(AREA, SPF_RESULTS);
228 oa->spf_table->scope = oa;
229 oa->route_table = OSPF6_ROUTE_TABLE_CREATE(AREA, ROUTES);
230 oa->route_table->scope = oa;
231 oa->route_table->hook_add = ospf6_area_route_hook_add;
232 oa->route_table->hook_remove = ospf6_area_route_hook_remove;
233
234 oa->range_table = OSPF6_ROUTE_TABLE_CREATE(AREA, PREFIX_RANGES);
235 oa->range_table->scope = oa;
236 bf_init(oa->range_table->idspace, 32);
237 oa->summary_prefix = OSPF6_ROUTE_TABLE_CREATE(AREA, SUMMARY_PREFIXES);
238 oa->summary_prefix->scope = oa;
239 oa->summary_router = OSPF6_ROUTE_TABLE_CREATE(AREA, SUMMARY_ROUTERS);
240 oa->summary_router->scope = oa;
9a703f8d 241 oa->router_lsa_size_limit = 1024 + 256;
d62a17ae 242
243 /* set default options */
244 if (CHECK_FLAG(o->flag, OSPF6_STUB_ROUTER)) {
245 OSPF6_OPT_CLEAR(oa->options, OSPF6_OPT_V6);
246 OSPF6_OPT_CLEAR(oa->options, OSPF6_OPT_R);
247 } else {
248 OSPF6_OPT_SET(oa->options, OSPF6_OPT_V6);
249 OSPF6_OPT_SET(oa->options, OSPF6_OPT_R);
250 }
251
252 OSPF6_OPT_SET(oa->options, OSPF6_OPT_E);
253
254 SET_FLAG(oa->flag, OSPF6_AREA_ACTIVE);
255 SET_FLAG(oa->flag, OSPF6_AREA_ENABLE);
256
257 oa->ospf6 = o;
258 listnode_add_sort(o->area_list, oa);
259
260 if (area_id == OSPF_AREA_BACKBONE) {
261 o->backbone = oa;
262 }
263
264 return oa;
718e3744 265}
266
d62a17ae 267void ospf6_area_delete(struct ospf6_area *oa)
718e3744 268{
d62a17ae 269 struct listnode *n;
270 struct ospf6_interface *oi;
718e3744 271
d62a17ae 272 /* The ospf6_interface structs store configuration
273 * information which should not be lost/reset when
274 * deleting an area.
275 * So just detach the interface from the area and
276 * keep it around. */
277 for (ALL_LIST_ELEMENTS_RO(oa->if_list, n, oi))
278 oi->area = NULL;
d9628728 279
affe9e99 280 list_delete_and_null(&oa->if_list);
718e3744 281
d62a17ae 282 ospf6_lsdb_delete(oa->lsdb);
283 ospf6_lsdb_delete(oa->lsdb_self);
da086a3b 284 ospf6_lsdb_delete(oa->temp_router_lsa_lsdb);
6452df09 285
d62a17ae 286 ospf6_spf_table_finish(oa->spf_table);
287 ospf6_route_table_delete(oa->spf_table);
288 ospf6_route_table_delete(oa->route_table);
508e53e2 289
d62a17ae 290 ospf6_route_table_delete(oa->range_table);
291 ospf6_route_table_delete(oa->summary_prefix);
292 ospf6_route_table_delete(oa->summary_router);
508e53e2 293
d62a17ae 294 listnode_delete(oa->ospf6->area_list, oa);
295 oa->ospf6 = NULL;
508e53e2 296
d62a17ae 297 /* free area */
298 XFREE(MTYPE_OSPF6_AREA, oa);
508e53e2 299}
300
d7c0a89a 301struct ospf6_area *ospf6_area_lookup(uint32_t area_id, struct ospf6 *ospf6)
718e3744 302{
d62a17ae 303 struct ospf6_area *oa;
304 struct listnode *n;
718e3744 305
d62a17ae 306 for (ALL_LIST_ELEMENTS_RO(ospf6->area_list, n, oa))
307 if (oa->area_id == area_id)
308 return oa;
718e3744 309
d62a17ae 310 return (struct ospf6_area *)NULL;
718e3744 311}
312
d62a17ae 313void ospf6_area_enable(struct ospf6_area *oa)
718e3744 314{
d62a17ae 315 struct listnode *node, *nnode;
316 struct ospf6_interface *oi;
718e3744 317
d62a17ae 318 SET_FLAG(oa->flag, OSPF6_AREA_ENABLE);
508e53e2 319
d62a17ae 320 for (ALL_LIST_ELEMENTS(oa->if_list, node, nnode, oi))
321 ospf6_interface_enable(oi);
322 ospf6_abr_enable_area(oa);
718e3744 323}
324
d62a17ae 325void ospf6_area_disable(struct ospf6_area *oa)
718e3744 326{
d62a17ae 327 struct listnode *node, *nnode;
328 struct ospf6_interface *oi;
718e3744 329
d62a17ae 330 UNSET_FLAG(oa->flag, OSPF6_AREA_ENABLE);
718e3744 331
d62a17ae 332 for (ALL_LIST_ELEMENTS(oa->if_list, node, nnode, oi))
333 ospf6_interface_disable(oi);
d9628728 334
d62a17ae 335 ospf6_abr_disable_area(oa);
336 ospf6_lsdb_remove_all(oa->lsdb);
337 ospf6_lsdb_remove_all(oa->lsdb_self);
d9628728 338
d62a17ae 339 ospf6_spf_table_finish(oa->spf_table);
340 ospf6_route_remove_all(oa->route_table);
d9628728 341
d62a17ae 342 THREAD_OFF(oa->thread_router_lsa);
343 THREAD_OFF(oa->thread_intra_prefix_lsa);
508e53e2 344}
718e3744 345
6b0655a2 346
d62a17ae 347void ospf6_area_show(struct vty *vty, struct ospf6_area *oa)
508e53e2 348{
d62a17ae 349 struct listnode *i;
350 struct ospf6_interface *oi;
351 unsigned long result;
352
353 if (!IS_AREA_STUB(oa))
354 vty_out(vty, " Area %s\n", oa->name);
355 else {
356 if (oa->no_summary) {
357 vty_out(vty, " Area %s[Stub, No Summary]\n", oa->name);
358 } else {
359 vty_out(vty, " Area %s[Stub]\n", oa->name);
360 }
ca1f4309 361 }
d62a17ae 362 vty_out(vty, " Number of Area scoped LSAs is %u\n",
363 oa->lsdb->count);
364
365 vty_out(vty, " Interface attached to this area:");
366 for (ALL_LIST_ELEMENTS_RO(oa->if_list, i, oi))
367 vty_out(vty, " %s", oi->interface->name);
368 vty_out(vty, "\n");
369
370 if (oa->ts_spf.tv_sec || oa->ts_spf.tv_usec) {
371 result = monotime_since(&oa->ts_spf, NULL);
372 if (result / TIMER_SECOND_MICRO > 0) {
373 vty_out(vty, "SPF last executed %ld.%lds ago\n",
374 result / TIMER_SECOND_MICRO,
375 result % TIMER_SECOND_MICRO);
376 } else {
377 vty_out(vty, "SPF last executed %ldus ago\n", result);
378 }
379 } else
380 vty_out(vty, "SPF has not been run\n");
381}
382
383
384#define OSPF6_CMD_AREA_GET(str, oa) \
385 { \
386 char *ep; \
d7c0a89a 387 uint32_t area_id = htonl(strtoul(str, &ep, 10)); \
d62a17ae 388 if (*ep && inet_pton(AF_INET, str, &area_id) != 1) { \
389 vty_out(vty, "Malformed Area-ID: %s\n", str); \
390 return CMD_SUCCESS; \
391 } \
392 int format = !*ep ? OSPF6_AREA_FMT_DECIMAL \
393 : OSPF6_AREA_FMT_DOTTEDQUAD; \
394 oa = ospf6_area_lookup(area_id, ospf6); \
395 if (oa == NULL) \
396 oa = ospf6_area_create(area_id, ospf6, format); \
ca1f4309 397 }
6452df09 398
399DEFUN (area_range,
400 area_range_cmd,
6de69f83 401 "area <A.B.C.D|(0-4294967295)> range X:X::X:X/M [<advertise|not-advertise|cost (0-16777215)>]",
6fbde29d
RW
402 "OSPF6 area parameters\n"
403 "OSPF6 area ID in IP address format\n"
404 "OSPF6 area ID as a decimal value\n"
6452df09 405 "Configured address range\n"
406 "Specify IPv6 prefix\n"
093d7a3a
DW
407 "Advertise\n"
408 "Do not advertise\n"
409 "User specified metric for this range\n"
410 "Advertised metric for this range\n")
6452df09 411{
d62a17ae 412 int idx_ipv4 = 1;
413 int idx_ipv6_prefixlen = 3;
414 int idx_type = 4;
415 int ret;
416 struct ospf6_area *oa;
417 struct prefix prefix;
418 struct ospf6_route *range;
d7c0a89a 419 uint32_t cost = OSPF_AREA_RANGE_COST_UNSPEC;
d62a17ae 420
421 OSPF6_CMD_AREA_GET(argv[idx_ipv4]->arg, oa);
422
423 ret = str2prefix(argv[idx_ipv6_prefixlen]->arg, &prefix);
424 if (ret != 1 || prefix.family != AF_INET6) {
425 vty_out(vty, "Malformed argument: %s\n",
426 argv[idx_ipv6_prefixlen]->arg);
427 return CMD_SUCCESS;
c3c0ac83 428 }
d62a17ae 429
430 range = ospf6_route_lookup(&prefix, oa->range_table);
431 if (range == NULL) {
432 range = ospf6_route_create();
433 range->type = OSPF6_DEST_TYPE_RANGE;
434 range->prefix = prefix;
435 range->path.area_id = oa->area_id;
436 range->path.cost = OSPF_AREA_RANGE_COST_UNSPEC;
c3c0ac83 437 }
d62a17ae 438
439 if (argc > idx_type) {
440 if (strmatch(argv[idx_type]->text, "not-advertise")) {
441 SET_FLAG(range->flag, OSPF6_ROUTE_DO_NOT_ADVERTISE);
442 } else if (strmatch(argv[idx_type]->text, "advertise")) {
443 UNSET_FLAG(range->flag, OSPF6_ROUTE_DO_NOT_ADVERTISE);
444 } else {
445 cost = strtoul(argv[5]->arg, NULL, 10);
446 UNSET_FLAG(range->flag, OSPF6_ROUTE_DO_NOT_ADVERTISE);
447 }
c3c0ac83 448 }
6452df09 449
d62a17ae 450 range->path.u.cost_config = cost;
c3c0ac83 451
d62a17ae 452 zlog_debug("%s: for prefix %s, flag = %x\n", __func__,
453 argv[idx_ipv6_prefixlen]->arg, range->flag);
454 if (range->rnode == NULL) {
455 ospf6_route_add(range, oa->range_table);
456 }
c3c0ac83 457
d62a17ae 458 if (ospf6_is_router_abr(ospf6)) {
459 /* Redo summaries if required */
460 ospf6_abr_prefix_resummarize(ospf6);
461 }
86f9e5a7 462
d62a17ae 463 return CMD_SUCCESS;
6452df09 464}
465
6452df09 466DEFUN (no_area_range,
467 no_area_range_cmd,
3a2d747c 468 "no area <A.B.C.D|(0-4294967295)> range X:X::X:X/M [<advertise|not-advertise|cost (0-16777215)>]",
813d4307 469 NO_STR
6fbde29d 470 "OSPF6 area parameters\n"
3a2d747c
QY
471 "OSPF6 area ID in IP address format\n"
472 "OSPF6 area ID as a decimal value\n"
6452df09 473 "Configured address range\n"
3a2d747c
QY
474 "Specify IPv6 prefix\n"
475 "Advertise\n"
476 "Do not advertise\n"
477 "User specified metric for this range\n"
478 "Advertised metric for this range\n")
6452df09 479{
d62a17ae 480 int idx_ipv4 = 2;
481 int idx_ipv6 = 4;
482 int ret;
483 struct ospf6_area *oa;
484 struct prefix prefix;
485 struct ospf6_route *range, *route;
6452df09 486
d62a17ae 487 OSPF6_CMD_AREA_GET(argv[idx_ipv4]->arg, oa);
488
489 ret = str2prefix(argv[idx_ipv6]->arg, &prefix);
490 if (ret != 1 || prefix.family != AF_INET6) {
491 vty_out(vty, "Malformed argument: %s\n", argv[idx_ipv6]->arg);
492 return CMD_SUCCESS;
493 }
494
495 range = ospf6_route_lookup(&prefix, oa->range_table);
496 if (range == NULL) {
497 vty_out(vty, "Range %s does not exists.\n",
498 argv[idx_ipv6]->arg);
499 return CMD_SUCCESS;
500 }
501
502 if (ospf6_is_router_abr(oa->ospf6)) {
503 /* Blow away the aggregated LSA and route */
504 SET_FLAG(range->flag, OSPF6_ROUTE_REMOVE);
505
506 /* Redo summaries if required */
507 for (route = ospf6_route_head(ospf6->route_table); route;
508 route = ospf6_route_next(route))
509 ospf6_abr_originate_summary(route);
510
511 /* purge the old aggregated summary LSA */
512 ospf6_abr_originate_summary(range);
513 }
514 ospf6_route_remove(range, oa->range_table);
515
516 return CMD_SUCCESS;
517}
518
519void ospf6_area_config_write(struct vty *vty)
520{
521 struct listnode *node;
522 struct ospf6_area *oa;
523 struct ospf6_route *range;
524 char buf[PREFIX2STR_BUFFER];
525
526 for (ALL_LIST_ELEMENTS_RO(ospf6->area_list, node, oa)) {
527 for (range = ospf6_route_head(oa->range_table); range;
528 range = ospf6_route_next(range)) {
529 prefix2str(&range->prefix, buf, sizeof(buf));
530 vty_out(vty, " area %s range %s", oa->name, buf);
531
532 if (CHECK_FLAG(range->flag,
533 OSPF6_ROUTE_DO_NOT_ADVERTISE)) {
534 vty_out(vty, " not-advertise");
535 } else {
536 // "advertise" is the default so we do not
537 // display it
538 if (range->path.u.cost_config
539 != OSPF_AREA_RANGE_COST_UNSPEC)
540 vty_out(vty, " cost %d",
541 range->path.u.cost_config);
542 }
543 vty_out(vty, "\n");
544 }
545 if (IS_AREA_STUB(oa)) {
546 if (oa->no_summary)
547 vty_out(vty, " area %s stub no-summary\n",
548 oa->name);
549 else
550 vty_out(vty, " area %s stub\n", oa->name);
551 }
552 if (PREFIX_NAME_IN(oa))
553 vty_out(vty, " area %s filter-list prefix %s in\n",
554 oa->name, PREFIX_NAME_IN(oa));
555 if (PREFIX_NAME_OUT(oa))
556 vty_out(vty, " area %s filter-list prefix %s out\n",
557 oa->name, PREFIX_NAME_OUT(oa));
558 if (IMPORT_NAME(oa))
559 vty_out(vty, " area %s import-list %s\n", oa->name,
560 IMPORT_NAME(oa));
561 if (EXPORT_NAME(oa))
562 vty_out(vty, " area %s export-list %s\n", oa->name,
563 EXPORT_NAME(oa));
ca1f4309 564 }
6452df09 565}
566
34956b31 567DEFUN (area_filter_list,
568 area_filter_list_cmd,
6147e2c6 569 "area A.B.C.D filter-list prefix WORD <in|out>",
b2d4d039
RW
570 "OSPF6 area parameters\n"
571 "OSPF6 area ID in IP address format\n"
572 "Filter networks between OSPF6 areas\n"
573 "Filter prefixes between OSPF6 areas\n"
34956b31 574 "Name of an IPv6 prefix-list\n"
575 "Filter networks sent to this area\n"
576 "Filter networks sent from this area\n")
577{
d62a17ae 578 char *inout = argv[argc - 1]->text;
579 char *areaid = argv[1]->arg;
580 char *plistname = argv[4]->arg;
581
582 struct ospf6_area *area;
583 struct prefix_list *plist;
584
585 OSPF6_CMD_AREA_GET(areaid, area);
586
587 plist = prefix_list_lookup(AFI_IP6, plistname);
588 if (strmatch(inout, "in")) {
589 PREFIX_LIST_IN(area) = plist;
427f8e61 590 XFREE(MTYPE_OSPF6_PLISTNAME, PREFIX_NAME_IN(area));
996c9314
LB
591 PREFIX_NAME_IN(area) =
592 XSTRDUP(MTYPE_OSPF6_PLISTNAME, plistname);
d62a17ae 593 ospf6_abr_reimport(area);
594 } else {
595 PREFIX_LIST_OUT(area) = plist;
427f8e61 596 XFREE(MTYPE_OSPF6_PLISTNAME, PREFIX_NAME_OUT(area));
996c9314
LB
597 PREFIX_NAME_OUT(area) =
598 XSTRDUP(MTYPE_OSPF6_PLISTNAME, plistname);
d62a17ae 599 ospf6_abr_enable_area(area);
600 }
601
602 return CMD_SUCCESS;
34956b31 603}
d62a17ae 604
34956b31 605DEFUN (no_area_filter_list,
606 no_area_filter_list_cmd,
6147e2c6 607 "no area A.B.C.D filter-list prefix WORD <in|out>",
34956b31 608 NO_STR
b2d4d039
RW
609 "OSPF6 area parameters\n"
610 "OSPF6 area ID in IP address format\n"
611 "Filter networks between OSPF6 areas\n"
612 "Filter prefixes between OSPF6 areas\n"
34956b31 613 "Name of an IPv6 prefix-list\n"
614 "Filter networks sent to this area\n"
615 "Filter networks sent from this area\n")
616{
d62a17ae 617 char *inout = argv[argc - 1]->text;
618 char *areaid = argv[2]->arg;
619 char *plistname = argv[5]->arg;
620
621 struct ospf6_area *area;
622
623 OSPF6_CMD_AREA_GET(areaid, area);
624
625 if (strmatch(inout, "in")) {
626 if (PREFIX_NAME_IN(area))
627 if (!strmatch(PREFIX_NAME_IN(area), plistname))
628 return CMD_SUCCESS;
629
630 PREFIX_LIST_IN(area) = NULL;
427f8e61 631 XFREE(MTYPE_OSPF6_PLISTNAME, PREFIX_NAME_IN(area));
d62a17ae 632 ospf6_abr_reimport(area);
633 } else {
634 if (PREFIX_NAME_OUT(area))
635 if (!strmatch(PREFIX_NAME_OUT(area), plistname))
636 return CMD_SUCCESS;
637
427f8e61 638 XFREE(MTYPE_OSPF6_PLISTNAME, PREFIX_NAME_OUT(area));
d62a17ae 639 ospf6_abr_enable_area(area);
640 }
641
642 return CMD_SUCCESS;
34956b31 643}
644
427f8e61
DL
645void ospf6_area_plist_update(struct prefix_list *plist, int add)
646{
647 struct ospf6_area *oa;
648 struct listnode *n;
649 const char *name = prefix_list_name(plist);
650
e017797b
DS
651 if (!ospf6)
652 return;
653
427f8e61 654 for (ALL_LIST_ELEMENTS_RO(ospf6->area_list, n, oa)) {
ff6bda17 655 if (PREFIX_NAME_IN(oa) && !strcmp(PREFIX_NAME_IN(oa), name))
427f8e61 656 PREFIX_LIST_IN(oa) = add ? plist : NULL;
ff6bda17 657 if (PREFIX_NAME_OUT(oa) && !strcmp(PREFIX_NAME_OUT(oa), name))
427f8e61
DL
658 PREFIX_LIST_OUT(oa) = add ? plist : NULL;
659 }
660}
661
34956b31 662DEFUN (area_import_list,
663 area_import_list_cmd,
664 "area A.B.C.D import-list NAME",
b2d4d039
RW
665 "OSPF6 area parameters\n"
666 "OSPF6 area ID in IP address format\n"
34956b31 667 "Set the filter for networks from other areas announced to the specified one\n"
668 "Name of the acess-list\n")
669{
d62a17ae 670 int idx_ipv4 = 1;
671 int idx_name = 3;
672 struct ospf6_area *area;
673 struct access_list *list;
34956b31 674
d62a17ae 675 OSPF6_CMD_AREA_GET(argv[idx_ipv4]->arg, area);
34956b31 676
d62a17ae 677 list = access_list_lookup(AFI_IP6, argv[idx_name]->arg);
34956b31 678
d62a17ae 679 IMPORT_LIST(area) = list;
34956b31 680
d62a17ae 681 if (IMPORT_NAME(area))
682 free(IMPORT_NAME(area));
34956b31 683
d62a17ae 684 IMPORT_NAME(area) = strdup(argv[idx_name]->arg);
685 ospf6_abr_reimport(area);
34956b31 686
d62a17ae 687 return CMD_SUCCESS;
34956b31 688}
689
690DEFUN (no_area_import_list,
691 no_area_import_list_cmd,
692 "no area A.B.C.D import-list NAME",
6fbde29d 693 NO_STR
b2d4d039
RW
694 "OSPF6 area parameters\n"
695 "OSPF6 area ID in IP address format\n"
34956b31 696 "Unset the filter for networks announced to other areas\n"
6fbde29d 697 "Name of the access-list\n")
34956b31 698{
d62a17ae 699 int idx_ipv4 = 2;
700 struct ospf6_area *area;
34956b31 701
d62a17ae 702 OSPF6_CMD_AREA_GET(argv[idx_ipv4]->arg, area);
34956b31 703
d62a17ae 704 IMPORT_LIST(area) = 0;
34956b31 705
d62a17ae 706 if (IMPORT_NAME(area))
707 free(IMPORT_NAME(area));
34956b31 708
d62a17ae 709 IMPORT_NAME(area) = NULL;
710 ospf6_abr_reimport(area);
34956b31 711
d62a17ae 712 return CMD_SUCCESS;
34956b31 713}
714
715DEFUN (area_export_list,
716 area_export_list_cmd,
717 "area A.B.C.D export-list NAME",
b2d4d039
RW
718 "OSPF6 area parameters\n"
719 "OSPF6 area ID in IP address format\n"
34956b31 720 "Set the filter for networks announced to other areas\n"
721 "Name of the acess-list\n")
722{
d62a17ae 723 int idx_ipv4 = 1;
724 int idx_name = 3;
725 struct ospf6_area *area;
726 struct access_list *list;
34956b31 727
d62a17ae 728 OSPF6_CMD_AREA_GET(argv[idx_ipv4]->arg, area);
34956b31 729
d62a17ae 730 list = access_list_lookup(AFI_IP6, argv[idx_name]->arg);
34956b31 731
d62a17ae 732 EXPORT_LIST(area) = list;
34956b31 733
d62a17ae 734 if (EXPORT_NAME(area))
735 free(EXPORT_NAME(area));
34956b31 736
d62a17ae 737 EXPORT_NAME(area) = strdup(argv[idx_name]->arg);
738 ospf6_abr_enable_area(area);
34956b31 739
d62a17ae 740 return CMD_SUCCESS;
34956b31 741}
742
743DEFUN (no_area_export_list,
744 no_area_export_list_cmd,
745 "no area A.B.C.D export-list NAME",
6fbde29d 746 NO_STR
b2d4d039
RW
747 "OSPF6 area parameters\n"
748 "OSPF6 area ID in IP address format\n"
34956b31 749 "Unset the filter for networks announced to other areas\n"
750 "Name of the access-list\n")
751{
d62a17ae 752 int idx_ipv4 = 2;
753 struct ospf6_area *area;
34956b31 754
d62a17ae 755 OSPF6_CMD_AREA_GET(argv[idx_ipv4]->arg, area);
34956b31 756
d62a17ae 757 EXPORT_LIST(area) = 0;
34956b31 758
d62a17ae 759 if (EXPORT_NAME(area))
760 free(EXPORT_NAME(area));
34956b31 761
d62a17ae 762 EXPORT_NAME(area) = NULL;
763 ospf6_abr_enable_area(area);
34956b31 764
d62a17ae 765 return CMD_SUCCESS;
34956b31 766}
767
508e53e2 768DEFUN (show_ipv6_ospf6_spf_tree,
769 show_ipv6_ospf6_spf_tree_cmd,
770 "show ipv6 ospf6 spf tree",
771 SHOW_STR
772 IP6_STR
773 OSPF6_STR
774 "Shortest Path First caculation\n"
775 "Show SPF tree\n")
718e3744 776{
d62a17ae 777 struct listnode *node;
778 struct ospf6_area *oa;
779 struct ospf6_vertex *root;
780 struct ospf6_route *route;
781 struct prefix prefix;
782
783 OSPF6_CMD_CHECK_RUNNING();
784
785 ospf6_linkstate_prefix(ospf6->router_id, htonl(0), &prefix);
786
787 for (ALL_LIST_ELEMENTS_RO(ospf6->area_list, node, oa)) {
788 route = ospf6_route_lookup(&prefix, oa->spf_table);
789 if (route == NULL) {
790 vty_out(vty, "LS entry for root not found in area %s\n",
791 oa->name);
792 continue;
793 }
794 root = (struct ospf6_vertex *)route->route_option;
795 ospf6_spf_display_subtree(vty, "", 0, root);
796 }
797
798 return CMD_SUCCESS;
508e53e2 799}
800
801DEFUN (show_ipv6_ospf6_area_spf_tree,
802 show_ipv6_ospf6_area_spf_tree_cmd,
803 "show ipv6 ospf6 area A.B.C.D spf tree",
804 SHOW_STR
805 IP6_STR
806 OSPF6_STR
807 OSPF6_AREA_STR
808 OSPF6_AREA_ID_STR
809 "Shortest Path First caculation\n"
810 "Show SPF tree\n")
811{
d62a17ae 812 int idx_ipv4 = 4;
d7c0a89a 813 uint32_t area_id;
d62a17ae 814 struct ospf6_area *oa;
815 struct ospf6_vertex *root;
816 struct ospf6_route *route;
817 struct prefix prefix;
818
819 OSPF6_CMD_CHECK_RUNNING();
820
821 ospf6_linkstate_prefix(ospf6->router_id, htonl(0), &prefix);
822
823 if (inet_pton(AF_INET, argv[idx_ipv4]->arg, &area_id) != 1) {
824 vty_out(vty, "Malformed Area-ID: %s\n", argv[idx_ipv4]->arg);
825 return CMD_SUCCESS;
826 }
827 oa = ospf6_area_lookup(area_id, ospf6);
828 if (oa == NULL) {
829 vty_out(vty, "No such Area: %s\n", argv[idx_ipv4]->arg);
830 return CMD_SUCCESS;
831 }
832
833 route = ospf6_route_lookup(&prefix, oa->spf_table);
834 if (route == NULL) {
835 vty_out(vty, "LS entry for root not found in area %s\n",
836 oa->name);
837 return CMD_SUCCESS;
838 }
839 root = (struct ospf6_vertex *)route->route_option;
840 ospf6_spf_display_subtree(vty, "", 0, root);
841
842 return CMD_SUCCESS;
718e3744 843}
844
508e53e2 845DEFUN (show_ipv6_ospf6_simulate_spf_tree_root,
846 show_ipv6_ospf6_simulate_spf_tree_root_cmd,
847 "show ipv6 ospf6 simulate spf-tree A.B.C.D area A.B.C.D",
848 SHOW_STR
849 IP6_STR
850 OSPF6_STR
d7fa34c1 851 "Shortest Path First calculation\n"
508e53e2 852 "Show SPF tree\n"
d7fa34c1
QY
853 "Specify root's router-id to calculate another router's SPF tree\n"
854 "OSPF6 area parameters\n"
855 OSPF6_AREA_ID_STR)
508e53e2 856{
d62a17ae 857 int idx_ipv4 = 5;
858 int idx_ipv4_2 = 7;
d7c0a89a 859 uint32_t area_id;
d62a17ae 860 struct ospf6_area *oa;
861 struct ospf6_vertex *root;
862 struct ospf6_route *route;
863 struct prefix prefix;
d7c0a89a 864 uint32_t router_id;
d62a17ae 865 struct ospf6_route_table *spf_table;
866 unsigned char tmp_debug_ospf6_spf = 0;
867
868 OSPF6_CMD_CHECK_RUNNING();
869
870 inet_pton(AF_INET, argv[idx_ipv4]->arg, &router_id);
871 ospf6_linkstate_prefix(router_id, htonl(0), &prefix);
872
873 if (inet_pton(AF_INET, argv[idx_ipv4_2]->arg, &area_id) != 1) {
874 vty_out(vty, "Malformed Area-ID: %s\n", argv[idx_ipv4_2]->arg);
875 return CMD_SUCCESS;
876 }
877 oa = ospf6_area_lookup(area_id, ospf6);
878 if (oa == NULL) {
879 vty_out(vty, "No such Area: %s\n", argv[idx_ipv4_2]->arg);
880 return CMD_SUCCESS;
881 }
882
883 tmp_debug_ospf6_spf = conf_debug_ospf6_spf;
884 conf_debug_ospf6_spf = 0;
885
886 spf_table = OSPF6_ROUTE_TABLE_CREATE(NONE, SPF_RESULTS);
887 ospf6_spf_calculation(router_id, spf_table, oa);
888
889 conf_debug_ospf6_spf = tmp_debug_ospf6_spf;
890
891 route = ospf6_route_lookup(&prefix, spf_table);
892 if (route == NULL) {
893 ospf6_spf_table_finish(spf_table);
894 ospf6_route_table_delete(spf_table);
895 return CMD_SUCCESS;
896 }
897 root = (struct ospf6_vertex *)route->route_option;
898 ospf6_spf_display_subtree(vty, "", 0, root);
899
900 ospf6_spf_table_finish(spf_table);
901 ospf6_route_table_delete(spf_table);
902
903 return CMD_SUCCESS;
508e53e2 904}
905
ca1f4309
DS
906DEFUN (ospf6_area_stub,
907 ospf6_area_stub_cmd,
6147e2c6 908 "area <A.B.C.D|(0-4294967295)> stub",
ca1f4309
DS
909 "OSPF6 area parameters\n"
910 "OSPF6 area ID in IP address format\n"
911 "OSPF6 area ID as a decimal value\n"
912 "Configure OSPF6 area as stub\n")
913{
d62a17ae 914 int idx_ipv4_number = 1;
915 struct ospf6_area *area;
ca1f4309 916
d62a17ae 917 OSPF6_CMD_AREA_GET(argv[idx_ipv4_number]->arg, area);
ca1f4309 918
d62a17ae 919 if (!ospf6_area_stub_set(ospf6, area)) {
920 vty_out(vty,
921 "First deconfigure all virtual link through this area\n");
922 return CMD_WARNING_CONFIG_FAILED;
923 }
ca1f4309 924
d62a17ae 925 ospf6_area_no_summary_unset(ospf6, area);
ca1f4309 926
d62a17ae 927 return CMD_SUCCESS;
ca1f4309
DS
928}
929
930DEFUN (ospf6_area_stub_no_summary,
931 ospf6_area_stub_no_summary_cmd,
6147e2c6 932 "area <A.B.C.D|(0-4294967295)> stub no-summary",
ca1f4309
DS
933 "OSPF6 stub parameters\n"
934 "OSPF6 area ID in IP address format\n"
935 "OSPF6 area ID as a decimal value\n"
936 "Configure OSPF6 area as stub\n"
937 "Do not inject inter-area routes into stub\n")
938{
d62a17ae 939 int idx_ipv4_number = 1;
940 struct ospf6_area *area;
ca1f4309 941
d62a17ae 942 OSPF6_CMD_AREA_GET(argv[idx_ipv4_number]->arg, area);
ca1f4309 943
d62a17ae 944 if (!ospf6_area_stub_set(ospf6, area)) {
945 vty_out(vty,
946 "First deconfigure all virtual link through this area\n");
947 return CMD_WARNING_CONFIG_FAILED;
948 }
ca1f4309 949
d62a17ae 950 ospf6_area_no_summary_set(ospf6, area);
ca1f4309 951
d62a17ae 952 return CMD_SUCCESS;
ca1f4309
DS
953}
954
955DEFUN (no_ospf6_area_stub,
956 no_ospf6_area_stub_cmd,
6147e2c6 957 "no area <A.B.C.D|(0-4294967295)> stub",
ca1f4309
DS
958 NO_STR
959 "OSPF6 area parameters\n"
960 "OSPF6 area ID in IP address format\n"
961 "OSPF6 area ID as a decimal value\n"
962 "Configure OSPF6 area as stub\n")
963{
d62a17ae 964 int idx_ipv4_number = 2;
965 struct ospf6_area *area;
ca1f4309 966
d62a17ae 967 OSPF6_CMD_AREA_GET(argv[idx_ipv4_number]->arg, area);
ca1f4309 968
d62a17ae 969 ospf6_area_stub_unset(ospf6, area);
970 ospf6_area_no_summary_unset(ospf6, area);
ca1f4309 971
d62a17ae 972 return CMD_SUCCESS;
ca1f4309
DS
973}
974
975DEFUN (no_ospf6_area_stub_no_summary,
976 no_ospf6_area_stub_no_summary_cmd,
6147e2c6 977 "no area <A.B.C.D|(0-4294967295)> stub no-summary",
ca1f4309
DS
978 NO_STR
979 "OSPF6 area parameters\n"
980 "OSPF6 area ID in IP address format\n"
981 "OSPF6 area ID as a decimal value\n"
982 "Configure OSPF6 area as stub\n"
983 "Do not inject inter-area routes into area\n")
984{
d62a17ae 985 int idx_ipv4_number = 2;
986 struct ospf6_area *area;
ca1f4309 987
d62a17ae 988 OSPF6_CMD_AREA_GET(argv[idx_ipv4_number]->arg, area);
ca1f4309 989
d62a17ae 990 ospf6_area_stub_unset(ospf6, area);
991 ospf6_area_no_summary_unset(ospf6, area);
ca1f4309 992
d62a17ae 993 return CMD_SUCCESS;
ca1f4309
DS
994}
995
d62a17ae 996void ospf6_area_init(void)
508e53e2 997{
d62a17ae 998 install_element(VIEW_NODE, &show_ipv6_ospf6_spf_tree_cmd);
999 install_element(VIEW_NODE, &show_ipv6_ospf6_area_spf_tree_cmd);
1000 install_element(VIEW_NODE, &show_ipv6_ospf6_simulate_spf_tree_root_cmd);
ca1f4309 1001
d62a17ae 1002 install_element(OSPF6_NODE, &area_range_cmd);
1003 install_element(OSPF6_NODE, &no_area_range_cmd);
1004 install_element(OSPF6_NODE, &ospf6_area_stub_no_summary_cmd);
1005 install_element(OSPF6_NODE, &ospf6_area_stub_cmd);
1006 install_element(OSPF6_NODE, &no_ospf6_area_stub_no_summary_cmd);
1007 install_element(OSPF6_NODE, &no_ospf6_area_stub_cmd);
34956b31 1008
34956b31 1009
d62a17ae 1010 install_element(OSPF6_NODE, &area_import_list_cmd);
1011 install_element(OSPF6_NODE, &no_area_import_list_cmd);
1012 install_element(OSPF6_NODE, &area_export_list_cmd);
1013 install_element(OSPF6_NODE, &no_area_export_list_cmd);
34956b31 1014
d62a17ae 1015 install_element(OSPF6_NODE, &area_filter_list_cmd);
1016 install_element(OSPF6_NODE, &no_area_filter_list_cmd);
508e53e2 1017}