]> git.proxmox.com Git - mirror_frr.git/blame - ospf6d/ospf6_asbr.c
debianpkg: Add debian9 backport to distribution tar
[mirror_frr.git] / ospf6d / ospf6_asbr.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 *
16 * You should have received a copy of the GNU General Public License
ac4d0be5 17 * along with GNU Zebra; see the file COPYING. If not, write to the
18 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19 * Boston, MA 02111-1307, USA.
718e3744 20 */
21
22#include <zebra.h>
23
24#include "log.h"
25#include "memory.h"
26#include "prefix.h"
27#include "command.h"
28#include "vty.h"
29#include "routemap.h"
30#include "table.h"
31#include "plist.h"
32#include "thread.h"
508e53e2 33#include "linklist.h"
718e3744 34
508e53e2 35#include "ospf6_proto.h"
36#include "ospf6_lsa.h"
37#include "ospf6_lsdb.h"
38#include "ospf6_route.h"
718e3744 39#include "ospf6_zebra.h"
6452df09 40#include "ospf6_message.h"
41
718e3744 42#include "ospf6_top.h"
508e53e2 43#include "ospf6_area.h"
6452df09 44#include "ospf6_interface.h"
45#include "ospf6_neighbor.h"
508e53e2 46#include "ospf6_asbr.h"
47#include "ospf6_intra.h"
6452df09 48#include "ospf6_flood.h"
049207c3 49#include "ospf6d.h"
718e3744 50
508e53e2 51unsigned char conf_debug_ospf6_asbr = 0;
718e3744 52
f52d13cb 53#define ZROUTE_NAME(x) zebra_route_string(x)
508e53e2 54
55/* AS External LSA origination */
ac4d0be5 56static void ospf6_as_external_lsa_originate(struct ospf6_route *route)
718e3744 57{
ac4d0be5 58 char buffer[OSPF6_MAX_LSASIZE];
59 struct ospf6_lsa_header *lsa_header;
60 struct ospf6_lsa *lsa;
61 struct ospf6_external_info *info = route->route_option;
62
63 struct ospf6_as_external_lsa *as_external_lsa;
64 char buf[PREFIX2STR_BUFFER];
65 caddr_t p;
66
67 if (IS_OSPF6_DEBUG_ASBR || IS_OSPF6_DEBUG_ORIGINATE(AS_EXTERNAL)) {
68 prefix2str(&route->prefix, buf, sizeof(buf));
69 zlog_debug("Originate AS-External-LSA for %s", buf);
70 }
71
72 /* prepare buffer */
73 memset(buffer, 0, sizeof(buffer));
74 lsa_header = (struct ospf6_lsa_header *)buffer;
75 as_external_lsa = (struct ospf6_as_external_lsa
76 *)((caddr_t)lsa_header
77 + sizeof(struct ospf6_lsa_header));
78 p = (caddr_t)((caddr_t)as_external_lsa
79 + sizeof(struct ospf6_as_external_lsa));
80
81 /* Fill AS-External-LSA */
82 /* Metric type */
83 if (route->path.metric_type == 2)
84 SET_FLAG(as_external_lsa->bits_metric, OSPF6_ASBR_BIT_E);
85 else
86 UNSET_FLAG(as_external_lsa->bits_metric, OSPF6_ASBR_BIT_E);
87
88 /* forwarding address */
89 if (!IN6_IS_ADDR_UNSPECIFIED(&info->forwarding))
90 SET_FLAG(as_external_lsa->bits_metric, OSPF6_ASBR_BIT_F);
91 else
92 UNSET_FLAG(as_external_lsa->bits_metric, OSPF6_ASBR_BIT_F);
93
94 /* external route tag */
95 if (info->tag)
96 SET_FLAG(as_external_lsa->bits_metric, OSPF6_ASBR_BIT_T);
97 else
98 UNSET_FLAG(as_external_lsa->bits_metric, OSPF6_ASBR_BIT_T);
99
100 /* Set metric */
101 OSPF6_ASBR_METRIC_SET(as_external_lsa, route->path.cost);
102
103 /* prefixlen */
104 as_external_lsa->prefix.prefix_length = route->prefix.prefixlen;
105
106 /* PrefixOptions */
107 as_external_lsa->prefix.prefix_options = route->path.prefix_options;
108
109 /* don't use refer LS-type */
110 as_external_lsa->prefix.prefix_refer_lstype = htons(0);
111
112 /* set Prefix */
113 memcpy(p, &route->prefix.u.prefix6,
114 OSPF6_PREFIX_SPACE(route->prefix.prefixlen));
115 ospf6_prefix_apply_mask(&as_external_lsa->prefix);
116 p += OSPF6_PREFIX_SPACE(route->prefix.prefixlen);
117
118 /* Forwarding address */
119 if (CHECK_FLAG(as_external_lsa->bits_metric, OSPF6_ASBR_BIT_F)) {
120 memcpy(p, &info->forwarding, sizeof(struct in6_addr));
121 p += sizeof(struct in6_addr);
122 }
123
124 /* External Route Tag */
125 if (CHECK_FLAG(as_external_lsa->bits_metric, OSPF6_ASBR_BIT_T)) {
126 route_tag_t network_order = htonl(info->tag);
127
128 memcpy(p, &network_order, sizeof(network_order));
129 p += sizeof(network_order);
130 }
131
132 /* Fill LSA Header */
133 lsa_header->age = 0;
134 lsa_header->type = htons(OSPF6_LSTYPE_AS_EXTERNAL);
135 lsa_header->id = route->path.origin.id;
136 lsa_header->adv_router = ospf6->router_id;
137 lsa_header->seqnum =
138 ospf6_new_ls_seqnum(lsa_header->type, lsa_header->id,
139 lsa_header->adv_router, ospf6->lsdb);
140 lsa_header->length = htons((caddr_t)p - (caddr_t)lsa_header);
141
142 /* LSA checksum */
143 ospf6_lsa_checksum(lsa_header);
144
145 /* create LSA */
146 lsa = ospf6_lsa_create(lsa_header);
147
148 /* Originate */
149 ospf6_lsa_originate_process(lsa, ospf6);
718e3744 150}
151
ac4d0be5 152static route_tag_t ospf6_as_external_lsa_get_tag(struct ospf6_lsa *lsa)
464015fa 153{
ac4d0be5 154 struct ospf6_as_external_lsa *external;
155 ptrdiff_t tag_offset;
156 route_tag_t network_order;
464015fa 157
ac4d0be5 158 if (!lsa)
159 return 0;
464015fa 160
ac4d0be5 161 external = (struct ospf6_as_external_lsa *)OSPF6_LSA_HEADER_END(
162 lsa->header);
464015fa 163
ac4d0be5 164 if (!CHECK_FLAG(external->bits_metric, OSPF6_ASBR_BIT_T))
165 return 0;
464015fa 166
ac4d0be5 167 tag_offset = sizeof(*external)
168 + OSPF6_PREFIX_SPACE(external->prefix.prefix_length);
169 if (CHECK_FLAG(external->bits_metric, OSPF6_ASBR_BIT_F))
170 tag_offset += sizeof(struct in6_addr);
464015fa 171
ac4d0be5 172 memcpy(&network_order, (caddr_t)external + tag_offset,
173 sizeof(network_order));
174 return ntohl(network_order);
464015fa 175}
6b0655a2 176
ac4d0be5 177void ospf6_asbr_lsa_add(struct ospf6_lsa *lsa)
718e3744 178{
ac4d0be5 179 struct ospf6_as_external_lsa *external;
180 struct prefix asbr_id;
181 struct ospf6_route *asbr_entry, *route;
182 char buf[PREFIX2STR_BUFFER];
183
184 external = (struct ospf6_as_external_lsa *)OSPF6_LSA_HEADER_END(
185 lsa->header);
186
187 if (IS_OSPF6_DEBUG_EXAMIN(AS_EXTERNAL))
188 zlog_debug("Calculate AS-External route for %s", lsa->name);
189
190 if (lsa->header->adv_router == ospf6->router_id) {
191 if (IS_OSPF6_DEBUG_EXAMIN(AS_EXTERNAL))
192 zlog_debug("Ignore self-originated AS-External-LSA");
193 return;
194 }
195
196 if (OSPF6_ASBR_METRIC(external) == OSPF_LS_INFINITY) {
197 if (IS_OSPF6_DEBUG_EXAMIN(AS_EXTERNAL))
198 zlog_debug("Ignore LSA with LSInfinity Metric");
199 return;
200 }
201
202 if (CHECK_FLAG(external->prefix.prefix_options,
203 OSPF6_PREFIX_OPTION_NU)) {
204 if (IS_OSPF6_DEBUG_EXAMIN(AS_EXTERNAL))
205 zlog_debug("Ignore LSA with NU bit set Metric");
206 return;
207 }
208
209 ospf6_linkstate_prefix(lsa->header->adv_router, htonl(0), &asbr_id);
210 asbr_entry = ospf6_route_lookup(&asbr_id, ospf6->brouter_table);
211 if (asbr_entry == NULL
212 || !CHECK_FLAG(asbr_entry->path.router_bits, OSPF6_ROUTER_BIT_E)) {
213 if (IS_OSPF6_DEBUG_EXAMIN(AS_EXTERNAL)) {
214 prefix2str(&asbr_id, buf, sizeof(buf));
215 zlog_debug("ASBR entry not found: %s", buf);
216 }
217 return;
218 }
219
220 route = ospf6_route_create();
221 route->type = OSPF6_DEST_TYPE_NETWORK;
222 route->prefix.family = AF_INET6;
223 route->prefix.prefixlen = external->prefix.prefix_length;
224 ospf6_prefix_in6_addr(&route->prefix.u.prefix6, &external->prefix);
225
226 route->path.area_id = asbr_entry->path.area_id;
227 route->path.origin.type = lsa->header->type;
228 route->path.origin.id = lsa->header->id;
229 route->path.origin.adv_router = lsa->header->adv_router;
230
231 route->path.prefix_options = external->prefix.prefix_options;
232 if (CHECK_FLAG(external->bits_metric, OSPF6_ASBR_BIT_E)) {
233 route->path.type = OSPF6_PATH_TYPE_EXTERNAL2;
234 route->path.metric_type = 2;
235 route->path.cost = asbr_entry->path.cost;
236 route->path.u.cost_e2 = OSPF6_ASBR_METRIC(external);
237 } else {
238 route->path.type = OSPF6_PATH_TYPE_EXTERNAL1;
239 route->path.metric_type = 1;
240 route->path.cost =
241 asbr_entry->path.cost + OSPF6_ASBR_METRIC(external);
242 route->path.u.cost_e2 = 0;
243 }
244
245 route->path.tag = ospf6_as_external_lsa_get_tag(lsa);
246
247 ospf6_route_copy_nexthops(route, asbr_entry);
248
249 if (IS_OSPF6_DEBUG_EXAMIN(AS_EXTERNAL)) {
250 prefix2str(&route->prefix, buf, sizeof(buf));
251 zlog_debug("AS-External route add: %s", buf);
252 }
253
254 ospf6_route_add(route, ospf6->route_table);
718e3744 255}
256
ac4d0be5 257void ospf6_asbr_lsa_remove(struct ospf6_lsa *lsa)
718e3744 258{
ac4d0be5 259 struct ospf6_as_external_lsa *external;
260 struct prefix prefix;
261 struct ospf6_route *route, *nroute;
262 char buf[PREFIX2STR_BUFFER];
263
264 external = (struct ospf6_as_external_lsa *)OSPF6_LSA_HEADER_END(
265 lsa->header);
266
267 if (IS_OSPF6_DEBUG_EXAMIN(AS_EXTERNAL))
268 zlog_debug("Withdraw AS-External route for %s", lsa->name);
269
270 if (lsa->header->adv_router == ospf6->router_id) {
271 if (IS_OSPF6_DEBUG_EXAMIN(AS_EXTERNAL))
272 zlog_debug("Ignore self-originated AS-External-LSA");
273 return;
274 }
275
276 memset(&prefix, 0, sizeof(struct prefix));
277 prefix.family = AF_INET6;
278 prefix.prefixlen = external->prefix.prefix_length;
279 ospf6_prefix_in6_addr(&prefix.u.prefix6, &external->prefix);
280
281 route = ospf6_route_lookup(&prefix, ospf6->route_table);
282 if (route == NULL) {
283 if (IS_OSPF6_DEBUG_EXAMIN(AS_EXTERNAL)) {
284 prefix2str(&prefix, buf, sizeof(buf));
285 zlog_debug("AS-External route %s not found", buf);
286 }
287 return;
288 }
289
290 for (ospf6_route_lock(route);
291 route && ospf6_route_is_prefix(&prefix, route); route = nroute) {
292 nroute = ospf6_route_next(route);
293 if (route->type != OSPF6_DEST_TYPE_NETWORK)
294 continue;
295 if (route->path.origin.type != lsa->header->type)
296 continue;
297 if (route->path.origin.id != lsa->header->id)
298 continue;
299 if (route->path.origin.adv_router != lsa->header->adv_router)
300 continue;
301
302 if (IS_OSPF6_DEBUG_EXAMIN(AS_EXTERNAL)) {
303 prefix2str(&route->prefix, buf, sizeof(buf));
304 zlog_debug("AS-External route remove: %s", buf);
305 }
306 ospf6_route_remove(route, ospf6->route_table);
307 }
308 if (route != NULL)
309 ospf6_route_unlock(route);
718e3744 310}
311
ac4d0be5 312void ospf6_asbr_lsentry_add(struct ospf6_route *asbr_entry)
508e53e2 313{
ac4d0be5 314 struct ospf6_lsa *lsa;
315 u_int16_t type;
316 u_int32_t router;
317
318 if (!CHECK_FLAG(asbr_entry->flag, OSPF6_ROUTE_BEST)) {
319 char buf[16];
320 inet_ntop(AF_INET, &ADV_ROUTER_IN_PREFIX(&asbr_entry->prefix),
321 buf, sizeof(buf));
322 zlog_info("ignore non-best path: lsentry %s add", buf);
323 return;
324 }
325
326 type = htons(OSPF6_LSTYPE_AS_EXTERNAL);
327 router = ospf6_linkstate_prefix_adv_router(&asbr_entry->prefix);
328 for (lsa = ospf6_lsdb_type_router_head(type, router, ospf6->lsdb); lsa;
329 lsa = ospf6_lsdb_type_router_next(type, router, lsa)) {
330 if (!OSPF6_LSA_IS_MAXAGE(lsa))
331 ospf6_asbr_lsa_add(lsa);
332 }
508e53e2 333}
334
ac4d0be5 335void ospf6_asbr_lsentry_remove(struct ospf6_route *asbr_entry)
718e3744 336{
ac4d0be5 337 struct ospf6_lsa *lsa;
338 u_int16_t type;
339 u_int32_t router;
340
341 type = htons(OSPF6_LSTYPE_AS_EXTERNAL);
342 router = ospf6_linkstate_prefix_adv_router(&asbr_entry->prefix);
343 for (lsa = ospf6_lsdb_type_router_head(type, router, ospf6->lsdb); lsa;
344 lsa = ospf6_lsdb_type_router_next(type, router, lsa))
345 ospf6_asbr_lsa_remove(lsa);
508e53e2 346}
718e3744 347
508e53e2 348
508e53e2 349/* redistribute function */
350
ac4d0be5 351static void ospf6_asbr_routemap_set(int type, const char *mapname)
508e53e2 352{
ac4d0be5 353 if (ospf6->rmap[type].name)
354 free(ospf6->rmap[type].name);
355 ospf6->rmap[type].name = strdup(mapname);
356 ospf6->rmap[type].map = route_map_lookup_by_name(mapname);
718e3744 357}
358
ac4d0be5 359static void ospf6_asbr_routemap_unset(int type)
718e3744 360{
ac4d0be5 361 if (ospf6->rmap[type].name)
362 free(ospf6->rmap[type].name);
363 ospf6->rmap[type].name = NULL;
364 ospf6->rmap[type].map = NULL;
508e53e2 365}
366
ac4d0be5 367static void ospf6_asbr_routemap_update(const char *mapname)
508e53e2 368{
ac4d0be5 369 int type;
370
371 if (ospf6 == NULL)
372 return;
373
374 for (type = 0; type < ZEBRA_ROUTE_MAX; type++) {
375 if (ospf6->rmap[type].name)
376 ospf6->rmap[type].map = route_map_lookup_by_name(
377 ospf6->rmap[type].name);
378 else
379 ospf6->rmap[type].map = NULL;
380 }
718e3744 381}
382
ac4d0be5 383int ospf6_asbr_is_asbr(struct ospf6 *o)
508e53e2 384{
ac4d0be5 385 return o->external_table->count;
508e53e2 386}
387
ac4d0be5 388static void ospf6_asbr_redistribute_set(int type)
718e3744 389{
ac4d0be5 390 ospf6_zebra_redistribute(type);
508e53e2 391}
392
ac4d0be5 393static void ospf6_asbr_redistribute_unset(int type)
508e53e2 394{
ac4d0be5 395 struct ospf6_route *route;
396 struct ospf6_external_info *info;
718e3744 397
ac4d0be5 398 ospf6_zebra_no_redistribute(type);
508e53e2 399
ac4d0be5 400 for (route = ospf6_route_head(ospf6->external_table); route;
401 route = ospf6_route_next(route)) {
402 info = route->route_option;
403 if (info->type != type)
404 continue;
718e3744 405
ac4d0be5 406 ospf6_asbr_redistribute_remove(info->type, 0, &route->prefix);
407 }
d9628728 408
ac4d0be5 409 ospf6_asbr_routemap_unset(type);
508e53e2 410}
718e3744 411
ca1f4309 412/* When an area is unstubified, flood all the external LSAs in the area */
ac4d0be5 413void ospf6_asbr_send_externals_to_area(struct ospf6_area *oa)
ca1f4309 414{
ac4d0be5 415 struct ospf6_lsa *lsa;
416
417 for (lsa = ospf6_lsdb_head(oa->ospf6->lsdb); lsa;
418 lsa = ospf6_lsdb_next(lsa)) {
419 if (ntohs(lsa->header->type) == OSPF6_LSTYPE_AS_EXTERNAL) {
420 zlog_debug("%s: Flooding AS-External LSA %s\n",
421 __func__, lsa->name);
422 ospf6_flood_area(NULL, lsa, oa);
423 }
ca1f4309 424 }
ca1f4309
DS
425}
426
ac4d0be5 427void ospf6_asbr_redistribute_add(int type, ifindex_t ifindex,
428 struct prefix *prefix, u_int nexthop_num,
429 struct in6_addr *nexthop, route_tag_t tag)
508e53e2 430{
ac4d0be5 431 int ret;
432 struct ospf6_route troute;
433 struct ospf6_external_info tinfo;
434 struct ospf6_route *route, *match;
435 struct ospf6_external_info *info;
436 struct prefix prefix_id;
437 struct route_node *node;
438 char pbuf[PREFIX2STR_BUFFER], ibuf[16];
439 struct listnode *lnode, *lnnode;
440 struct ospf6_area *oa;
441
442 if (!ospf6_zebra_is_redistribute(type))
443 return;
444
445 if (IS_OSPF6_DEBUG_ASBR) {
446 prefix2str(prefix, pbuf, sizeof(pbuf));
447 zlog_debug("Redistribute %s (%s)", pbuf, ZROUTE_NAME(type));
448 }
449
450 /* if route-map was specified but not found, do not advertise */
451 if (ospf6->rmap[type].name) {
452 if (ospf6->rmap[type].map == NULL)
453 ospf6_asbr_routemap_update(NULL);
454 if (ospf6->rmap[type].map == NULL) {
455 zlog_warn(
456 "route-map \"%s\" not found, suppress redistributing",
457 ospf6->rmap[type].name);
458 return;
459 }
460 }
461
462 /* apply route-map */
463 if (ospf6->rmap[type].map) {
464 memset(&troute, 0, sizeof(troute));
465 memset(&tinfo, 0, sizeof(tinfo));
466 troute.route_option = &tinfo;
467 tinfo.ifindex = ifindex;
468 tinfo.tag = tag;
469
470 ret = route_map_apply(ospf6->rmap[type].map, prefix, RMAP_OSPF6,
471 &troute);
472 if (ret == RMAP_DENYMATCH) {
473 if (IS_OSPF6_DEBUG_ASBR)
474 zlog_debug("Denied by route-map \"%s\"",
475 ospf6->rmap[type].name);
476 return;
477 }
478 }
479
480 match = ospf6_route_lookup(prefix, ospf6->external_table);
481 if (match) {
482 info = match->route_option;
483
484 /* copy result of route-map */
485 if (ospf6->rmap[type].map) {
486 if (troute.path.metric_type)
487 match->path.metric_type =
488 troute.path.metric_type;
489 if (troute.path.cost)
490 match->path.cost = troute.path.cost;
491 if (!IN6_IS_ADDR_UNSPECIFIED(&tinfo.forwarding))
492 memcpy(&info->forwarding, &tinfo.forwarding,
493 sizeof(struct in6_addr));
494 info->tag = tinfo.tag;
495 } else {
496 /* If there is no route-map, simply update the tag */
497 info->tag = tag;
498 }
499
500 info->type = type;
501
502 if (nexthop_num && nexthop)
503 ospf6_route_add_nexthop(match, ifindex, nexthop);
504 else
505 ospf6_route_add_nexthop(match, ifindex, NULL);
506
507 /* create/update binding in external_id_table */
508 prefix_id.family = AF_INET;
509 prefix_id.prefixlen = 32;
510 prefix_id.u.prefix4.s_addr = htonl(info->id);
511 node = route_node_get(ospf6->external_id_table, &prefix_id);
512 node->info = match;
513
514 if (IS_OSPF6_DEBUG_ASBR) {
515 inet_ntop(AF_INET, &prefix_id.u.prefix4, ibuf,
516 sizeof(ibuf));
517 zlog_debug("Advertise as AS-External Id:%s", ibuf);
518 }
519
520 match->path.origin.id = htonl(info->id);
521 ospf6_as_external_lsa_originate(match);
522 return;
523 }
524
525 /* create new entry */
526 route = ospf6_route_create();
527 route->type = OSPF6_DEST_TYPE_NETWORK;
528 memcpy(&route->prefix, prefix, sizeof(struct prefix));
529
530 info = (struct ospf6_external_info *)XCALLOC(
531 MTYPE_OSPF6_EXTERNAL_INFO, sizeof(struct ospf6_external_info));
532 route->route_option = info;
533 info->id = ospf6->external_id++;
534
535 /* copy result of route-map */
536 if (ospf6->rmap[type].map) {
537 if (troute.path.metric_type)
538 route->path.metric_type = troute.path.metric_type;
539 if (troute.path.cost)
540 route->path.cost = troute.path.cost;
541 if (!IN6_IS_ADDR_UNSPECIFIED(&tinfo.forwarding))
542 memcpy(&info->forwarding, &tinfo.forwarding,
543 sizeof(struct in6_addr));
544 info->tag = tinfo.tag;
545 } else {
546 /* If there is no route-map, simply set the tag */
547 info->tag = tag;
548 }
549
550 info->type = type;
551 if (nexthop_num && nexthop)
552 ospf6_route_add_nexthop(route, ifindex, nexthop);
553 else
554 ospf6_route_add_nexthop(route, ifindex, NULL);
555
556 /* create/update binding in external_id_table */
557 prefix_id.family = AF_INET;
558 prefix_id.prefixlen = 32;
559 prefix_id.u.prefix4.s_addr = htonl(info->id);
560 node = route_node_get(ospf6->external_id_table, &prefix_id);
561 node->info = route;
562
563 route = ospf6_route_add(route, ospf6->external_table);
564 route->route_option = info;
565
566 if (IS_OSPF6_DEBUG_ASBR) {
567 inet_ntop(AF_INET, &prefix_id.u.prefix4, ibuf, sizeof(ibuf));
568 zlog_debug("Advertise as AS-External Id:%s", ibuf);
569 }
570
571 route->path.origin.id = htonl(info->id);
572 ospf6_as_external_lsa_originate(route);
573
574 /* Router-Bit (ASBR Flag) may have to be updated */
575 for (ALL_LIST_ELEMENTS(ospf6->area_list, lnode, lnnode, oa))
576 OSPF6_ROUTER_LSA_SCHEDULE(oa);
718e3744 577}
578
ac4d0be5 579void ospf6_asbr_redistribute_remove(int type, ifindex_t ifindex,
580 struct prefix *prefix)
718e3744 581{
ac4d0be5 582 struct ospf6_route *match;
583 struct ospf6_external_info *info = NULL;
584 struct route_node *node;
585 struct ospf6_lsa *lsa;
586 struct prefix prefix_id;
587 char pbuf[PREFIX2STR_BUFFER], ibuf[16];
588 struct listnode *lnode, *lnnode;
589 struct ospf6_area *oa;
590
591 match = ospf6_route_lookup(prefix, ospf6->external_table);
592 if (match == NULL) {
593 if (IS_OSPF6_DEBUG_ASBR) {
594 prefix2str(prefix, pbuf, sizeof(pbuf));
595 zlog_debug("No such route %s to withdraw", pbuf);
596 }
597 return;
598 }
599
600 info = match->route_option;
601 assert(info);
602
603 if (info->type != type) {
604 if (IS_OSPF6_DEBUG_ASBR) {
605 prefix2str(prefix, pbuf, sizeof(pbuf));
606 zlog_debug("Original protocol mismatch: %s", pbuf);
607 }
608 return;
609 }
610
611 if (IS_OSPF6_DEBUG_ASBR) {
612 prefix2str(prefix, pbuf, sizeof(pbuf));
613 inet_ntop(AF_INET, &prefix_id.u.prefix4, ibuf, sizeof(ibuf));
614 zlog_debug("Withdraw %s (AS-External Id:%s)", pbuf, ibuf);
615 }
616
617 lsa = ospf6_lsdb_lookup(htons(OSPF6_LSTYPE_AS_EXTERNAL),
618 htonl(info->id), ospf6->router_id, ospf6->lsdb);
619 if (lsa)
620 ospf6_lsa_purge(lsa);
621
622 /* remove binding in external_id_table */
623 prefix_id.family = AF_INET;
624 prefix_id.prefixlen = 32;
625 prefix_id.u.prefix4.s_addr = htonl(info->id);
626 node = route_node_lookup(ospf6->external_id_table, &prefix_id);
627 assert(node);
628 node->info = NULL;
629 route_unlock_node(node);
630
631 ospf6_route_remove(match, ospf6->external_table);
632 XFREE(MTYPE_OSPF6_EXTERNAL_INFO, info);
633
634 /* Router-Bit (ASBR Flag) may have to be updated */
635 for (ALL_LIST_ELEMENTS(ospf6->area_list, lnode, lnnode, oa))
636 OSPF6_ROUTER_LSA_SCHEDULE(oa);
718e3744 637}
638
508e53e2 639DEFUN (ospf6_redistribute,
640 ospf6_redistribute_cmd,
40d1cbfb 641 "redistribute " FRR_REDIST_STR_OSPF6D,
508e53e2 642 "Redistribute\n"
3b14d86e 643 FRR_REDIST_HELP_STR_OSPF6D)
718e3744 644{
ac4d0be5 645 int type;
e0ca5fde 646
ac4d0be5 647 char *proto = argv[argc - 1]->text;
648 type = proto_redistnum(AFI_IP6, proto);
649 if (type < 0)
650 return CMD_WARNING;
718e3744 651
ac4d0be5 652 ospf6_asbr_redistribute_unset(type);
653 ospf6_asbr_redistribute_set(type);
654 return CMD_SUCCESS;
508e53e2 655}
718e3744 656
508e53e2 657DEFUN (ospf6_redistribute_routemap,
658 ospf6_redistribute_routemap_cmd,
40d1cbfb 659 "redistribute " FRR_REDIST_STR_OSPF6D " route-map WORD",
508e53e2 660 "Redistribute\n"
ab0181ee 661 FRR_REDIST_HELP_STR_OSPF6D
508e53e2 662 "Route map reference\n"
e52702f2 663 "Route map name\n")
508e53e2 664{
ac4d0be5 665 int idx_protocol = 1;
666 int idx_word = 3;
667 int type;
668
669 char *proto = argv[idx_protocol]->text;
670 type = proto_redistnum(AFI_IP6, proto);
671 if (type < 0)
672 return CMD_WARNING;
673
674 ospf6_asbr_redistribute_unset(type);
675 ospf6_asbr_routemap_set(type, argv[idx_word]->arg);
676 ospf6_asbr_redistribute_set(type);
677 return CMD_SUCCESS;
508e53e2 678}
679
680DEFUN (no_ospf6_redistribute,
681 no_ospf6_redistribute_cmd,
40d1cbfb 682 "no redistribute " FRR_REDIST_STR_OSPF6D " [route-map WORD]",
508e53e2 683 NO_STR
684 "Redistribute\n"
ab0181ee 685 FRR_REDIST_HELP_STR_OSPF6D
1d68dbfe
DW
686 "Route map reference\n"
687 "Route map name\n")
508e53e2 688{
ac4d0be5 689 int idx_protocol = 2;
690 int type;
e0ca5fde 691
ac4d0be5 692 char *proto = argv[idx_protocol]->text;
693 type = proto_redistnum(AFI_IP6, proto);
694 if (type < 0)
695 return CMD_WARNING;
e26bbeba 696
ac4d0be5 697 ospf6_asbr_redistribute_unset(type);
e26bbeba 698
ac4d0be5 699 return CMD_SUCCESS;
508e53e2 700}
718e3744 701
ac4d0be5 702int ospf6_redistribute_config_write(struct vty *vty)
508e53e2 703{
ac4d0be5 704 int type;
705
706 for (type = 0; type < ZEBRA_ROUTE_MAX; type++) {
707 if (type == ZEBRA_ROUTE_OSPF6)
708 continue;
709 if (!ospf6_zebra_is_redistribute(type))
710 continue;
711
712 if (ospf6->rmap[type].name)
713 vty_out(vty, " redistribute %s route-map %s%s",
714 ZROUTE_NAME(type), ospf6->rmap[type].name, VNL);
715 else
716 vty_out(vty, " redistribute %s%s", ZROUTE_NAME(type),
717 VNL);
718 }
719
720 return 0;
718e3744 721}
722
ac4d0be5 723static void ospf6_redistribute_show_config(struct vty *vty)
718e3744 724{
ac4d0be5 725 int type;
726 int nroute[ZEBRA_ROUTE_MAX];
727 int total;
728 struct ospf6_route *route;
729 struct ospf6_external_info *info;
730
731 total = 0;
732 for (type = 0; type < ZEBRA_ROUTE_MAX; type++)
733 nroute[type] = 0;
734 for (route = ospf6_route_head(ospf6->external_table); route;
735 route = ospf6_route_next(route)) {
736 info = route->route_option;
737 nroute[info->type]++;
738 total++;
739 }
718e3744 740
ac4d0be5 741 vty_out(vty, "Redistributing External Routes from:%s", VNL);
742 for (type = 0; type < ZEBRA_ROUTE_MAX; type++) {
743 if (type == ZEBRA_ROUTE_OSPF6)
744 continue;
745 if (!ospf6_zebra_is_redistribute(type))
746 continue;
747
748 if (ospf6->rmap[type].name)
749 vty_out(vty, " %d: %s with route-map \"%s\"%s%s",
750 nroute[type], ZROUTE_NAME(type),
751 ospf6->rmap[type].name,
752 (ospf6->rmap[type].map ? "" : " (not found !)"),
753 VNL);
754 else
755 vty_out(vty, " %d: %s%s", nroute[type],
756 ZROUTE_NAME(type), VNL);
757 }
758 vty_out(vty, "Total %d routes%s", total, VNL);
759}
718e3744 760
6b0655a2 761
508e53e2 762/* Routemap Functions */
6ac29a51 763static route_map_result_t
ac4d0be5 764ospf6_routemap_rule_match_address_prefixlist(void *rule, struct prefix *prefix,
765 route_map_object_t type,
766 void *object)
508e53e2 767{
ac4d0be5 768 struct prefix_list *plist;
718e3744 769
ac4d0be5 770 if (type != RMAP_OSPF6)
771 return RMAP_NOMATCH;
718e3744 772
ac4d0be5 773 plist = prefix_list_lookup(AFI_IP6, (char *)rule);
774 if (plist == NULL)
775 return RMAP_NOMATCH;
718e3744 776
ac4d0be5 777 return (prefix_list_apply(plist, prefix) == PREFIX_DENY ? RMAP_NOMATCH
778 : RMAP_MATCH);
508e53e2 779}
718e3744 780
6ac29a51 781static void *
ac4d0be5 782ospf6_routemap_rule_match_address_prefixlist_compile(const char *arg)
508e53e2 783{
ac4d0be5 784 return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg);
718e3744 785}
786
ac4d0be5 787static void ospf6_routemap_rule_match_address_prefixlist_free(void *rule)
718e3744 788{
ac4d0be5 789 XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
508e53e2 790}
718e3744 791
ac4d0be5 792struct route_map_rule_cmd ospf6_routemap_rule_match_address_prefixlist_cmd = {
793 "ipv6 address prefix-list",
794 ospf6_routemap_rule_match_address_prefixlist,
795 ospf6_routemap_rule_match_address_prefixlist_compile,
796 ospf6_routemap_rule_match_address_prefixlist_free,
508e53e2 797};
718e3744 798
42a7debf
VT
799/* `match interface IFNAME' */
800/* Match function should return 1 if match is success else return
801 zero. */
802static route_map_result_t
ac4d0be5 803ospf6_routemap_rule_match_interface(void *rule, struct prefix *prefix,
804 route_map_object_t type, void *object)
42a7debf 805{
ac4d0be5 806 struct interface *ifp;
807 struct ospf6_external_info *ei;
42a7debf 808
ac4d0be5 809 if (type == RMAP_OSPF6) {
810 ei = ((struct ospf6_route *)object)->route_option;
811 ifp = if_lookup_by_name((char *)rule, VRF_DEFAULT);
42a7debf 812
ac4d0be5 813 if (ifp != NULL && ei->ifindex == ifp->ifindex)
814 return RMAP_MATCH;
815 }
42a7debf 816
ac4d0be5 817 return RMAP_NOMATCH;
42a7debf
VT
818}
819
820/* Route map `interface' match statement. `arg' should be
821 interface name. */
ac4d0be5 822static void *ospf6_routemap_rule_match_interface_compile(const char *arg)
42a7debf 823{
ac4d0be5 824 return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg);
42a7debf
VT
825}
826
827/* Free route map's compiled `interface' value. */
ac4d0be5 828static void ospf6_routemap_rule_match_interface_free(void *rule)
42a7debf 829{
ac4d0be5 830 XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
42a7debf
VT
831}
832
833/* Route map commands for interface matching. */
ac4d0be5 834struct route_map_rule_cmd ospf6_routemap_rule_match_interface_cmd = {
835 "interface", ospf6_routemap_rule_match_interface,
836 ospf6_routemap_rule_match_interface_compile,
837 ospf6_routemap_rule_match_interface_free};
42a7debf 838
464015fa 839/* Match function for matching route tags */
ac4d0be5 840static route_map_result_t ospf6_routemap_rule_match_tag(void *rule,
841 struct prefix *prefix,
842 route_map_object_t type,
843 void *object)
464015fa 844{
ac4d0be5 845 route_tag_t *tag = rule;
846 struct ospf6_route *route = object;
847 struct ospf6_external_info *info = route->route_option;
464015fa 848
ac4d0be5 849 if (type == RMAP_OSPF6 && info->tag == *tag)
850 return RMAP_MATCH;
464015fa 851
ac4d0be5 852 return RMAP_NOMATCH;
464015fa
CF
853}
854
ac4d0be5 855static struct route_map_rule_cmd ospf6_routemap_rule_match_tag_cmd = {
856 "tag", ospf6_routemap_rule_match_tag, route_map_rule_tag_compile,
857 route_map_rule_tag_free,
464015fa
CF
858};
859
6ac29a51 860static route_map_result_t
ac4d0be5 861ospf6_routemap_rule_set_metric_type(void *rule, struct prefix *prefix,
862 route_map_object_t type, void *object)
508e53e2 863{
ac4d0be5 864 char *metric_type = rule;
865 struct ospf6_route *route = object;
718e3744 866
ac4d0be5 867 if (type != RMAP_OSPF6)
868 return RMAP_OKAY;
718e3744 869
ac4d0be5 870 if (strcmp(metric_type, "type-2") == 0)
871 route->path.metric_type = 2;
872 else
873 route->path.metric_type = 1;
718e3744 874
ac4d0be5 875 return RMAP_OKAY;
508e53e2 876}
718e3744 877
ac4d0be5 878static void *ospf6_routemap_rule_set_metric_type_compile(const char *arg)
508e53e2 879{
ac4d0be5 880 if (strcmp(arg, "type-2") && strcmp(arg, "type-1"))
881 return NULL;
882 return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg);
718e3744 883}
884
ac4d0be5 885static void ospf6_routemap_rule_set_metric_type_free(void *rule)
718e3744 886{
ac4d0be5 887 XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
508e53e2 888}
718e3744 889
ac4d0be5 890struct route_map_rule_cmd ospf6_routemap_rule_set_metric_type_cmd = {
891 "metric-type", ospf6_routemap_rule_set_metric_type,
892 ospf6_routemap_rule_set_metric_type_compile,
893 ospf6_routemap_rule_set_metric_type_free,
508e53e2 894};
718e3744 895
6ac29a51 896static route_map_result_t
ac4d0be5 897ospf6_routemap_rule_set_metric(void *rule, struct prefix *prefix,
898 route_map_object_t type, void *object)
508e53e2 899{
ac4d0be5 900 char *metric = rule;
901 struct ospf6_route *route = object;
718e3744 902
ac4d0be5 903 if (type != RMAP_OSPF6)
904 return RMAP_OKAY;
718e3744 905
ac4d0be5 906 route->path.cost = atoi(metric);
907 return RMAP_OKAY;
508e53e2 908}
718e3744 909
ac4d0be5 910static void *ospf6_routemap_rule_set_metric_compile(const char *arg)
508e53e2 911{
ac4d0be5 912 u_int32_t metric;
913 char *endp;
914 metric = strtoul(arg, &endp, 0);
915 if (metric > OSPF_LS_INFINITY || *endp != '\0')
916 return NULL;
917 return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg);
718e3744 918}
919
ac4d0be5 920static void ospf6_routemap_rule_set_metric_free(void *rule)
718e3744 921{
ac4d0be5 922 XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
508e53e2 923}
718e3744 924
ac4d0be5 925struct route_map_rule_cmd ospf6_routemap_rule_set_metric_cmd = {
926 "metric", ospf6_routemap_rule_set_metric,
927 ospf6_routemap_rule_set_metric_compile,
928 ospf6_routemap_rule_set_metric_free,
508e53e2 929};
718e3744 930
6ac29a51 931static route_map_result_t
ac4d0be5 932ospf6_routemap_rule_set_forwarding(void *rule, struct prefix *prefix,
933 route_map_object_t type, void *object)
508e53e2 934{
ac4d0be5 935 char *forwarding = rule;
936 struct ospf6_route *route = object;
937 struct ospf6_external_info *info = route->route_option;
718e3744 938
ac4d0be5 939 if (type != RMAP_OSPF6)
940 return RMAP_OKAY;
718e3744 941
ac4d0be5 942 if (inet_pton(AF_INET6, forwarding, &info->forwarding) != 1) {
943 memset(&info->forwarding, 0, sizeof(struct in6_addr));
944 return RMAP_ERROR;
945 }
718e3744 946
ac4d0be5 947 return RMAP_OKAY;
718e3744 948}
949
ac4d0be5 950static void *ospf6_routemap_rule_set_forwarding_compile(const char *arg)
718e3744 951{
ac4d0be5 952 struct in6_addr a;
953 if (inet_pton(AF_INET6, arg, &a) != 1)
954 return NULL;
955 return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg);
718e3744 956}
957
ac4d0be5 958static void ospf6_routemap_rule_set_forwarding_free(void *rule)
718e3744 959{
ac4d0be5 960 XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
508e53e2 961}
718e3744 962
ac4d0be5 963struct route_map_rule_cmd ospf6_routemap_rule_set_forwarding_cmd = {
964 "forwarding-address", ospf6_routemap_rule_set_forwarding,
965 ospf6_routemap_rule_set_forwarding_compile,
966 ospf6_routemap_rule_set_forwarding_free,
508e53e2 967};
718e3744 968
ac4d0be5 969static route_map_result_t ospf6_routemap_rule_set_tag(void *rule,
970 struct prefix *prefix,
971 route_map_object_t type,
972 void *object)
464015fa 973{
ac4d0be5 974 route_tag_t *tag = rule;
975 struct ospf6_route *route = object;
976 struct ospf6_external_info *info = route->route_option;
464015fa 977
ac4d0be5 978 if (type != RMAP_OSPF6)
979 return RMAP_OKAY;
464015fa 980
ac4d0be5 981 info->tag = *tag;
982 return RMAP_OKAY;
464015fa
CF
983}
984
ac4d0be5 985static struct route_map_rule_cmd ospf6_routemap_rule_set_tag_cmd = {
986 "tag", ospf6_routemap_rule_set_tag, route_map_rule_tag_compile,
987 route_map_rule_tag_free,
464015fa
CF
988};
989
ac4d0be5 990static int route_map_command_status(struct vty *vty, int ret)
508e53e2 991{
ac4d0be5 992 if (!ret)
993 return CMD_SUCCESS;
994
995 switch (ret) {
996 case RMAP_RULE_MISSING:
997 vty_out(vty, "OSPF6 Can't find rule.%s", VNL);
998 break;
999 case RMAP_COMPILE_ERROR:
1000 vty_out(vty, "OSPF6 Argument is malformed.%s", VNL);
1001 break;
1002 default:
1003 vty_out(vty, "OSPF6 route-map add set failed.%s", VNL);
1004 break;
1005 }
1006 return CMD_WARNING;
508e53e2 1007}
718e3744 1008
508e53e2 1009/* add "set metric-type" */
1010DEFUN (ospf6_routemap_set_metric_type,
1011 ospf6_routemap_set_metric_type_cmd,
6147e2c6 1012 "set metric-type <type-1|type-2>",
508e53e2 1013 "Set value\n"
1014 "Type of metric\n"
1015 "OSPF6 external type 1 metric\n"
1016 "OSPF6 external type 2 metric\n")
1017{
ac4d0be5 1018 VTY_DECLVAR_CONTEXT(route_map_index, route_map_index);
1019 int idx_external = 2;
1020 int ret = route_map_add_set(route_map_index, "metric-type",
1021 argv[idx_external]->arg);
1022 return route_map_command_status(vty, ret);
718e3744 1023}
1024
508e53e2 1025/* delete "set metric-type" */
1026DEFUN (ospf6_routemap_no_set_metric_type,
1027 ospf6_routemap_no_set_metric_type_cmd,
dab8cd00 1028 "no set metric-type [<type-1|type-2>]",
508e53e2 1029 NO_STR
1030 "Set value\n"
1031 "Type of metric\n"
1032 "OSPF6 external type 1 metric\n"
1033 "OSPF6 external type 2 metric\n")
718e3744 1034{
ac4d0be5 1035 VTY_DECLVAR_CONTEXT(route_map_index, route_map_index);
1036 char *ext = (argc == 4) ? argv[3]->text : NULL;
1037 int ret = route_map_delete_set(route_map_index, "metric-type", ext);
1038 return route_map_command_status(vty, ret);
508e53e2 1039}
718e3744 1040
508e53e2 1041/* add "set forwarding-address" */
1042DEFUN (ospf6_routemap_set_forwarding,
1043 ospf6_routemap_set_forwarding_cmd,
1044 "set forwarding-address X:X::X:X",
1045 "Set value\n"
1046 "Forwarding Address\n"
1047 "IPv6 Address\n")
1048{
ac4d0be5 1049 VTY_DECLVAR_CONTEXT(route_map_index, route_map_index);
1050 int idx_ipv6 = 2;
1051 int ret = route_map_add_set(route_map_index, "forwarding-address",
1052 argv[idx_ipv6]->arg);
1053 return route_map_command_status(vty, ret);
508e53e2 1054}
718e3744 1055
508e53e2 1056/* delete "set forwarding-address" */
1057DEFUN (ospf6_routemap_no_set_forwarding,
1058 ospf6_routemap_no_set_forwarding_cmd,
1059 "no set forwarding-address X:X::X:X",
1060 NO_STR
1061 "Set value\n"
1062 "Forwarding Address\n"
1063 "IPv6 Address\n")
1064{
ac4d0be5 1065 VTY_DECLVAR_CONTEXT(route_map_index, route_map_index);
1066 int idx_ipv6 = 3;
1067 int ret = route_map_delete_set(route_map_index, "forwarding-address",
1068 argv[idx_ipv6]->arg);
1069 return route_map_command_status(vty, ret);
508e53e2 1070}
718e3744 1071
ac4d0be5 1072static void ospf6_routemap_init(void)
508e53e2 1073{
ac4d0be5 1074 route_map_init();
b2575bc0 1075
ac4d0be5 1076 route_map_add_hook(ospf6_asbr_routemap_update);
1077 route_map_delete_hook(ospf6_asbr_routemap_update);
508e53e2 1078
ac4d0be5 1079 route_map_set_metric_hook(generic_set_add);
1080 route_map_no_set_metric_hook(generic_set_delete);
82f97584 1081
ac4d0be5 1082 route_map_match_tag_hook(generic_match_add);
1083 route_map_no_match_tag_hook(generic_match_delete);
e1a1b2ed 1084
ac4d0be5 1085 route_map_match_ipv6_address_prefix_list_hook(generic_match_add);
1086 route_map_no_match_ipv6_address_prefix_list_hook(generic_match_delete);
e1a1b2ed 1087
ac4d0be5 1088 route_map_match_interface_hook(generic_match_add);
1089 route_map_no_match_interface_hook(generic_match_delete);
e1a1b2ed 1090
ac4d0be5 1091 route_map_install_match(
1092 &ospf6_routemap_rule_match_address_prefixlist_cmd);
1093 route_map_install_match(&ospf6_routemap_rule_match_interface_cmd);
1094 route_map_install_match(&ospf6_routemap_rule_match_tag_cmd);
42a7debf 1095
ac4d0be5 1096 route_map_install_set(&ospf6_routemap_rule_set_metric_type_cmd);
1097 route_map_install_set(&ospf6_routemap_rule_set_metric_cmd);
1098 route_map_install_set(&ospf6_routemap_rule_set_forwarding_cmd);
1099 route_map_install_set(&ospf6_routemap_rule_set_tag_cmd);
508e53e2 1100
ac4d0be5 1101 /* ASE Metric Type (e.g. Type-1/Type-2) */
1102 install_element(RMAP_NODE, &ospf6_routemap_set_metric_type_cmd);
1103 install_element(RMAP_NODE, &ospf6_routemap_no_set_metric_type_cmd);
508e53e2 1104
ac4d0be5 1105 /* ASE Metric */
1106 install_element(RMAP_NODE, &ospf6_routemap_set_forwarding_cmd);
1107 install_element(RMAP_NODE, &ospf6_routemap_no_set_forwarding_cmd);
718e3744 1108}
1109
6b0655a2 1110
508e53e2 1111/* Display functions */
ac4d0be5 1112static char *ospf6_as_external_lsa_get_prefix_str(struct ospf6_lsa *lsa,
1113 char *buf, int buflen,
1114 int pos)
e68a6767 1115{
ac4d0be5 1116 struct ospf6_as_external_lsa *external;
1117 struct in6_addr in6;
1118 int prefix_length = 0;
1119
1120 if (lsa) {
1121 external = (struct ospf6_as_external_lsa *)OSPF6_LSA_HEADER_END(
1122 lsa->header);
1123
1124 if (pos == 0) {
1125 ospf6_prefix_in6_addr(&in6, &external->prefix);
1126 prefix_length = external->prefix.prefix_length;
1127 } else {
1128 in6 = *((struct in6_addr
1129 *)((caddr_t)external
1130 + sizeof(struct
1131 ospf6_as_external_lsa)
1132 + OSPF6_PREFIX_SPACE(
1133 external->prefix
1134 .prefix_length)));
1135 }
1136 if (buf) {
1137 inet_ntop(AF_INET6, &in6, buf, buflen);
1138 if (prefix_length)
1139 sprintf(&buf[strlen(buf)], "/%d",
1140 prefix_length);
1141 }
e68a6767 1142 }
ac4d0be5 1143 return (buf);
e68a6767
DD
1144}
1145
ac4d0be5 1146static int ospf6_as_external_lsa_show(struct vty *vty, struct ospf6_lsa *lsa)
718e3744 1147{
ac4d0be5 1148 struct ospf6_as_external_lsa *external;
1149 char buf[64];
1150
1151 assert(lsa->header);
1152 external = (struct ospf6_as_external_lsa *)OSPF6_LSA_HEADER_END(
1153 lsa->header);
1154
1155 /* bits */
1156 snprintf(buf, sizeof(buf), "%c%c%c",
1157 (CHECK_FLAG(external->bits_metric, OSPF6_ASBR_BIT_E) ? 'E'
1158 : '-'),
1159 (CHECK_FLAG(external->bits_metric, OSPF6_ASBR_BIT_F) ? 'F'
1160 : '-'),
1161 (CHECK_FLAG(external->bits_metric, OSPF6_ASBR_BIT_T) ? 'T'
1162 : '-'));
1163
1164 vty_out(vty, " Bits: %s%s", buf, VNL);
1165 vty_out(vty, " Metric: %5lu%s", (u_long)OSPF6_ASBR_METRIC(external),
1166 VNL);
1167
1168 ospf6_prefix_options_printbuf(external->prefix.prefix_options, buf,
1169 sizeof(buf));
1170 vty_out(vty, " Prefix Options: %s%s", buf, VNL);
1171
1172 vty_out(vty, " Referenced LSType: %d%s",
1173 ntohs(external->prefix.prefix_refer_lstype), VNL);
1174
1175 vty_out(vty, " Prefix: %s%s",
1176 ospf6_as_external_lsa_get_prefix_str(lsa, buf, sizeof(buf), 0),
1177 VNL);
1178
1179 /* Forwarding-Address */
1180 if (CHECK_FLAG(external->bits_metric, OSPF6_ASBR_BIT_F)) {
1181 vty_out(vty, " Forwarding-Address: %s%s",
1182 ospf6_as_external_lsa_get_prefix_str(lsa, buf,
1183 sizeof(buf), 1),
1184 VNL);
1185 }
1186
1187 /* Tag */
1188 if (CHECK_FLAG(external->bits_metric, OSPF6_ASBR_BIT_T)) {
1189 vty_out(vty, " Tag: %" ROUTE_TAG_PRI "%s",
1190 ospf6_as_external_lsa_get_tag(lsa), VNL);
1191 }
1192
1193 return 0;
718e3744 1194}
1195
ac4d0be5 1196static void ospf6_asbr_external_route_show(struct vty *vty,
1197 struct ospf6_route *route)
718e3744 1198{
ac4d0be5 1199 struct ospf6_external_info *info = route->route_option;
1200 char prefix[PREFIX2STR_BUFFER], id[16], forwarding[64];
1201 u_int32_t tmp_id;
1202
1203 prefix2str(&route->prefix, prefix, sizeof(prefix));
1204 tmp_id = ntohl(info->id);
1205 inet_ntop(AF_INET, &tmp_id, id, sizeof(id));
1206 if (!IN6_IS_ADDR_UNSPECIFIED(&info->forwarding))
1207 inet_ntop(AF_INET6, &info->forwarding, forwarding,
1208 sizeof(forwarding));
1209 else
1210 snprintf(forwarding, sizeof(forwarding), ":: (ifindex %d)",
1211 ospf6_route_get_first_nh_index(route));
1212
1213 vty_out(vty, "%c %-32s %-15s type-%d %5lu %s%s",
1214 zebra_route_char(info->type), prefix, id,
1215 route->path.metric_type,
1216 (u_long)(route->path.metric_type == 2 ? route->path.u.cost_e2
1217 : route->path.cost),
1218 forwarding, VNL);
718e3744 1219}
1220
508e53e2 1221DEFUN (show_ipv6_ospf6_redistribute,
1222 show_ipv6_ospf6_redistribute_cmd,
1223 "show ipv6 ospf6 redistribute",
1224 SHOW_STR
1225 IP6_STR
1226 OSPF6_STR
1227 "redistributing External information\n"
1228 )
718e3744 1229{
ac4d0be5 1230 struct ospf6_route *route;
718e3744 1231
ac4d0be5 1232 OSPF6_CMD_CHECK_RUNNING();
b52a8a52 1233
ac4d0be5 1234 ospf6_redistribute_show_config(vty);
718e3744 1235
ac4d0be5 1236 for (route = ospf6_route_head(ospf6->external_table); route;
1237 route = ospf6_route_next(route))
1238 ospf6_asbr_external_route_show(vty, route);
508e53e2 1239
ac4d0be5 1240 return CMD_SUCCESS;
718e3744 1241}
1242
ac4d0be5 1243struct ospf6_lsa_handler as_external_handler = {
1244 OSPF6_LSTYPE_AS_EXTERNAL, "AS-External", "ASE",
1245 ospf6_as_external_lsa_show, ospf6_as_external_lsa_get_prefix_str};
508e53e2 1246
ac4d0be5 1247void ospf6_asbr_init(void)
718e3744 1248{
ac4d0be5 1249 ospf6_routemap_init();
508e53e2 1250
ac4d0be5 1251 ospf6_install_lsa_handler(&as_external_handler);
718e3744 1252
ac4d0be5 1253 install_element(VIEW_NODE, &show_ipv6_ospf6_redistribute_cmd);
508e53e2 1254
ac4d0be5 1255 install_element(OSPF6_NODE, &ospf6_redistribute_cmd);
1256 install_element(OSPF6_NODE, &ospf6_redistribute_routemap_cmd);
1257 install_element(OSPF6_NODE, &no_ospf6_redistribute_cmd);
718e3744 1258}
1259
ac4d0be5 1260void ospf6_asbr_redistribute_reset(void)
d9628728 1261{
ac4d0be5 1262 int type;
1263
1264 for (type = 0; type < ZEBRA_ROUTE_MAX; type++) {
1265 if (type == ZEBRA_ROUTE_OSPF6)
1266 continue;
1267 if (ospf6_zebra_is_redistribute(type))
1268 ospf6_asbr_redistribute_unset(type);
1269 }
d9628728
CF
1270}
1271
ac4d0be5 1272void ospf6_asbr_terminate(void)
ae2254aa 1273{
ac4d0be5 1274 route_map_finish();
ae2254aa 1275}
718e3744 1276
508e53e2 1277DEFUN (debug_ospf6_asbr,
1278 debug_ospf6_asbr_cmd,
1279 "debug ospf6 asbr",
1280 DEBUG_STR
1281 OSPF6_STR
1282 "Debug OSPFv3 ASBR function\n"
1283 )
1284{
ac4d0be5 1285 OSPF6_DEBUG_ASBR_ON();
1286 return CMD_SUCCESS;
508e53e2 1287}
1288
1289DEFUN (no_debug_ospf6_asbr,
1290 no_debug_ospf6_asbr_cmd,
1291 "no debug ospf6 asbr",
1292 NO_STR
1293 DEBUG_STR
1294 OSPF6_STR
1295 "Debug OSPFv3 ASBR function\n"
1296 )
1297{
ac4d0be5 1298 OSPF6_DEBUG_ASBR_OFF();
1299 return CMD_SUCCESS;
508e53e2 1300}
1301
ac4d0be5 1302int config_write_ospf6_debug_asbr(struct vty *vty)
508e53e2 1303{
ac4d0be5 1304 if (IS_OSPF6_DEBUG_ASBR)
1305 vty_out(vty, "debug ospf6 asbr%s", VNL);
1306 return 0;
508e53e2 1307}
1308
ac4d0be5 1309void install_element_ospf6_debug_asbr()
92300491 1310{
ac4d0be5 1311 install_element(ENABLE_NODE, &debug_ospf6_asbr_cmd);
1312 install_element(ENABLE_NODE, &no_debug_ospf6_asbr_cmd);
1313 install_element(CONFIG_NODE, &debug_ospf6_asbr_cmd);
1314 install_element(CONFIG_NODE, &no_debug_ospf6_asbr_cmd);
92300491 1315}