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