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