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