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