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