blob: 00a2b66c0748e38bc1e5d46ce38d05ede5955026 [file] [log] [blame]
paul718e3742002-12-13 20:15:29 +00001/*
2 * Copyright (C) 2001-2002 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
34#include "ospf6_prefix.h" /* xxx for ospf6_asbr.h */
35#include "ospf6_lsa.h" /* xxx for ospf6_asbr.h */
36#include "ospf6_route.h" /* xxx for ospf6_asbr.h, ospf6_zebra.h */
37#include "ospf6_zebra.h"
38#include "ospf6_asbr.h"
39#include "ospf6_damp.h"
40#include "ospf6_top.h"
41#include "ospf6_lsdb.h"
42#include "ospf6_proto.h"
43
44extern struct thread_master *master;
45
46struct route_table *external_table;
47struct
48{
49 char *name;
50 struct route_map *map;
51} rmap [ZEBRA_ROUTE_MAX];
52
53static u_int32_t link_state_id = 0;
54
55char *
56zroute_name[] =
57{
58 "system", "kernel", "connected", "static",
59 "rip", "ripng", "ospf", "ospf6", "bgp", "unknown"
60};
61char *
62zroute_abname[] =
63{
64 "X", "K", "C", "S", "R", "R", "O", "O", "B", "?"
65};
66
67#define ZROUTE_NAME(x) \
68 (0 < (x) && (x) < ZEBRA_ROUTE_MAX ? \
69 zroute_name[(x)] : zroute_name[ZEBRA_ROUTE_MAX])
70
71#define ZROUTE_ABNAME(x) \
72 (0 < (x) && (x) < ZEBRA_ROUTE_MAX ? \
73 zroute_abname[(x)] : zroute_abname[ZEBRA_ROUTE_MAX])
74
75/* redistribute function */
76void
77ospf6_asbr_routemap_set (int type, char *mapname)
78{
79 if (rmap[type].name)
80 free (rmap[type].name);
81
82 rmap[type].name = strdup (mapname);
83 rmap[type].map = route_map_lookup_by_name (mapname);
84}
85
86void
87ospf6_asbr_routemap_unset (int type)
88{
89 if (rmap[type].name)
90 free (rmap[type].name);
91 rmap[type].name = NULL;
92 rmap[type].map = NULL;
93}
94
95void
96ospf6_asbr_routemap_update ()
97{
98 int i;
99 for (i = 0; i < ZEBRA_ROUTE_MAX; i++)
100 {
101 if (rmap[i].name)
102 rmap[i].map = route_map_lookup_by_name (rmap[i].name);
103 else
104 rmap[i].map = NULL;
105 }
106}
107
108DEFUN (ospf6_redistribute,
109 ospf6_redistribute_cmd,
110 "redistribute (static|kernel|connected|ripng|bgp)",
111 "Redistribute\n"
112 "Static route\n"
113 "Kernel route\n"
114 "Connected route\n"
115 "RIPng route\n"
116 "BGP route\n"
117 )
118{
119 int type = 0;
120
121 if (strncmp (argv[0], "sta", 3) == 0)
122 type = ZEBRA_ROUTE_STATIC;
123 else if (strncmp (argv[0], "ker", 3) == 0)
124 type = ZEBRA_ROUTE_KERNEL;
125 else if (strncmp (argv[0], "con", 3) == 0)
126 type = ZEBRA_ROUTE_CONNECT;
127 else if (strncmp (argv[0], "rip", 3) == 0)
128 type = ZEBRA_ROUTE_RIPNG;
129 else if (strncmp (argv[0], "bgp", 3) == 0)
130 type = ZEBRA_ROUTE_BGP;
131
132 ospf6_zebra_no_redistribute (type);
133 ospf6_asbr_routemap_unset (type);
134 ospf6_zebra_redistribute (type);
135 return CMD_SUCCESS;
136}
137
138DEFUN (ospf6_redistribute_routemap,
139 ospf6_redistribute_routemap_cmd,
140 "redistribute (static|kernel|connected|ripng|bgp) route-map WORD",
141 "Redistribute\n"
142 "Static routes\n"
143 "Kernel route\n"
144 "Connected route\n"
145 "RIPng route\n"
146 "BGP route\n"
147 "Route map reference\n"
148 "Route map name\n"
149 )
150{
151 int type = 0;
152
153 if (strncmp (argv[0], "sta", 3) == 0)
154 type = ZEBRA_ROUTE_STATIC;
155 else if (strncmp (argv[0], "ker", 3) == 0)
156 type = ZEBRA_ROUTE_KERNEL;
157 else if (strncmp (argv[0], "con", 3) == 0)
158 type = ZEBRA_ROUTE_CONNECT;
159 else if (strncmp (argv[0], "rip", 3) == 0)
160 type = ZEBRA_ROUTE_RIPNG;
161 else if (strncmp (argv[0], "bgp", 3) == 0)
162 type = ZEBRA_ROUTE_BGP;
163
164 ospf6_zebra_no_redistribute (type);
165 ospf6_asbr_routemap_set (type, argv[1]);
166 ospf6_zebra_redistribute (type);
167 return CMD_SUCCESS;
168}
169
170DEFUN (no_ospf6_redistribute,
171 no_ospf6_redistribute_cmd,
172 "no redistribute (static|kernel|connected|ripng|bgp)",
173 NO_STR
174 "Redistribute\n"
175 "Static route\n"
176 "Kernel route\n"
177 "Connected route\n"
178 "RIPng route\n"
179 "BGP route\n"
180 )
181{
182 int type = 0;
183 struct route_node *node;
184 struct ospf6_external_route *route;
185 struct ospf6_external_info *info, *info_next = NULL;
186
187 if (strncmp (argv[0], "sta", 3) == 0)
188 type = ZEBRA_ROUTE_STATIC;
189 else if (strncmp (argv[0], "ker", 3) == 0)
190 type = ZEBRA_ROUTE_KERNEL;
191 else if (strncmp (argv[0], "con", 3) == 0)
192 type = ZEBRA_ROUTE_CONNECT;
193 else if (strncmp (argv[0], "rip", 3) == 0)
194 type = ZEBRA_ROUTE_RIPNG;
195 else if (strncmp (argv[0], "bgp", 3) == 0)
196 type = ZEBRA_ROUTE_BGP;
197
198 ospf6_zebra_no_redistribute (type);
199 ospf6_asbr_routemap_unset (type);
200
201 /* remove redistributed route */
202 for (node = route_top (external_table); node; node = route_next (node))
203 {
204 route = node->info;
205 if (! route)
206 continue;
207 for (info = route->info_head; info; info = info_next)
208 {
209 info_next = info->next;
210 if (info->type != type)
211 continue;
212 ospf6_asbr_route_remove (info->type, info->ifindex,
213 &route->prefix);
214 }
215 }
216
217 return CMD_SUCCESS;
218}
219
220
221int
222ospf6_redistribute_config_write (struct vty *vty)
223{
224 int i;
225
226 for (i = 0; i < ZEBRA_ROUTE_MAX; i++)
227 {
228 if (i == ZEBRA_ROUTE_OSPF6)
229 continue;
230
231 if (! ospf6_zebra_is_redistribute (i))
232 continue;
233
234 if (rmap[i].map)
235 vty_out (vty, " redistribute %s route-map %s%s",
236 ZROUTE_NAME(i), rmap[i].name, VTY_NEWLINE);
237 else
238 vty_out (vty, " redistribute %s%s",
239 ZROUTE_NAME(i), VTY_NEWLINE);
240 }
241
242 return 0;
243}
244
245void
246ospf6_redistribute_show_config (struct vty *vty)
247{
248 int i;
249
250 if (! ospf6_zebra_is_redistribute(ZEBRA_ROUTE_SYSTEM) &&
251 ! ospf6_zebra_is_redistribute(ZEBRA_ROUTE_KERNEL) &&
252 ! ospf6_zebra_is_redistribute(ZEBRA_ROUTE_STATIC) &&
253 ! ospf6_zebra_is_redistribute(ZEBRA_ROUTE_RIPNG) &&
254 ! ospf6_zebra_is_redistribute(ZEBRA_ROUTE_BGP))
255 return;
256
257 vty_out (vty, " Redistributing External Routes from,%s", VTY_NEWLINE);
258 for (i = 0; i < ZEBRA_ROUTE_MAX; i++)
259 {
260 if (i == ZEBRA_ROUTE_OSPF6)
261 continue;
262 if (! ospf6_zebra_is_redistribute (i))
263 continue;
264
265 if (rmap[i].map)
266 vty_out (vty, " %s with route-map %s%s",
267 ZROUTE_NAME(i), rmap[i].name, VTY_NEWLINE);
268 else
269 vty_out (vty, " %s%s", ZROUTE_NAME(i), VTY_NEWLINE);
270 }
271}
272
273/* AS External LSA origination */
274int
275ospf6_asbr_external_lsa_originate (struct thread *thread)
276{
277 struct ospf6_external_info *info;
278 char buffer [MAXLSASIZE];
279 struct ospf6_lsa_as_external *e;
280 char *p;
281
282 info = THREAD_ARG (thread);
283
284 /* clear thread */
285 info->thread_originate = NULL;
286
287 if (info->is_removed)
288 {
289 if (IS_OSPF6_DUMP_ASBR)
290 {
291 char pbuf[64];
292 prefix2str (&info->route->prefix, pbuf, sizeof (pbuf));
293 zlog_info ("ASBR: quit redistribution %s: state is down",
294 pbuf);
295 }
296 return 0;
297 }
298
299 /* prepare buffer */
300 memset (buffer, 0, sizeof (buffer));
301 e = (struct ospf6_lsa_as_external *) buffer;
302 p = (char *) (e + 1);
303
304 if (info->metric_type == 2)
305 SET_FLAG (e->bits_metric, OSPF6_ASBR_BIT_E); /* type2 */
306 else
307 UNSET_FLAG (e->bits_metric, OSPF6_ASBR_BIT_E); /* type1, default */
308
309 /* forwarding address */
310 if (! IN6_IS_ADDR_UNSPECIFIED (&info->forwarding))
311 SET_FLAG (e->bits_metric, OSPF6_ASBR_BIT_F);
312 else
313 UNSET_FLAG (e->bits_metric, OSPF6_ASBR_BIT_F);
314
315 /* external route tag */
316 UNSET_FLAG (e->bits_metric, OSPF6_ASBR_BIT_T);
317
318 /* set metric. note: related to E bit */
319 OSPF6_ASBR_METRIC_SET (e, info->metric);
320
321 /* prefixlen */
322 e->prefix.prefix_length = info->route->prefix.prefixlen;
323
324 /* PrefixOptions */
325 e->prefix.prefix_options = info->prefix_options;
326
327 /* don't use refer LS-type */
328 e->prefix.prefix_refer_lstype = htons (0);
329
330 /* set Prefix */
331 memcpy (p, &info->route->prefix.u.prefix6,
332 OSPF6_PREFIX_SPACE (info->route->prefix.prefixlen));
333 ospf6_prefix_apply_mask (&e->prefix);
334 p += OSPF6_PREFIX_SPACE (info->route->prefix.prefixlen);
335
336 /* Forwarding address */
337 if (CHECK_FLAG (e->bits_metric, OSPF6_ASBR_BIT_F))
338 {
339 memcpy (p, &info->forwarding, sizeof (struct in6_addr));
340 p += sizeof (struct in6_addr);
341 }
342
343 /* External Route Tag */
344 if (CHECK_FLAG (e->bits_metric, OSPF6_ASBR_BIT_T))
345 {
346 /* xxx */
347 }
348
349 ospf6_lsa_originate (htons (OSPF6_LSA_TYPE_AS_EXTERNAL),
350 htonl (info->id), ospf6->router_id,
351 (char *) buffer, p - buffer, ospf6);
352 return 0;
353}
354
355int
356ospf6_asbr_schedule_external (void *data)
357{
358 struct ospf6_external_info *info = data;
359 u_long elasped_time, time = 0;
360
361 if (info->thread_originate)
362 {
363 if (IS_OSPF6_DUMP_ASBR)
364 {
365 char pbuf[64];
366 prefix2str (&info->route->prefix, pbuf, sizeof (pbuf));
367 zlog_info ("ASBR: schedule redistribution %s: another thread",
368 pbuf);
369 }
370 return 0;
371 }
372
373 elasped_time =
374 ospf6_lsa_has_elasped (htons (OSPF6_LSA_TYPE_AS_EXTERNAL),
375 htonl (info->id), ospf6->router_id, ospf6);
376 if (elasped_time < OSPF6_MIN_LS_INTERVAL)
377 time = OSPF6_MIN_LS_INTERVAL - elasped_time;
378 else
379 time = 0;
380
381 //if (IS_OSPF6_DUMP_ASBR)
382 {
383 char pbuf[64];
384 prefix2str (&info->route->prefix, pbuf, sizeof (pbuf));
385 zlog_info ("ASBR: schedule redistribution %s as LS-ID %ld after %lu sec",
386 pbuf, (u_long) info->id, time);
387 }
388
389 if (time)
390 info->thread_originate =
391 thread_add_timer (master, ospf6_asbr_external_lsa_originate, info, time);
392 else
393 info->thread_originate =
394 thread_add_timer (master, ospf6_asbr_external_lsa_originate, info, 0);
395
396 return 0;
397}
398
399int
400ospf6_asbr_external_lsa_flush (void *data)
401{
402 struct ospf6_lsa *lsa = data;
403 if (lsa)
404 ospf6_lsa_premature_aging (lsa);
405 return 0;
406}
407
408int
409ospf6_asbr_external_lsa_refresh (void *data)
410{
411 struct ospf6_lsa *lsa = data;
412 struct ospf6_lsa_as_external *e;
413 struct prefix prefix;
414 struct route_node *node;
415 struct ospf6_external_route *route;
416 struct ospf6_external_info *info;
417
418 if (IS_OSPF6_DUMP_ASBR)
419 zlog_info ("ASBR: refresh %s", lsa->str);
420
421 e = (struct ospf6_lsa_as_external *) (lsa->header + 1);
422 ospf6_prefix_in6_addr (&e->prefix, &prefix.u.prefix6);
423 prefix.prefixlen = e->prefix.prefix_length;
424 prefix.family = AF_INET6;
425 apply_mask_ipv6 ((struct prefix_ipv6 *) &prefix);
426
427 node = route_node_lookup (external_table, &prefix);
428 if (! node || ! node->info)
429 {
430 char pname[64];
431
432 prefix2str (&prefix, pname, sizeof (pname));
433 if (IS_OSPF6_DUMP_ASBR)
434 zlog_info ("ASBR: could not find %s: premature age", pname);
435 ospf6_lsa_premature_aging (lsa);
436 return 0;
437 }
438
439 /* find external_info */
440 route = node->info;
441 for (info = route->info_head; info; info = info->next)
442 {
443 if (lsa->header->id == htonl (info->id))
444 break;
445 }
446
447 if (info)
448 ospf6_asbr_schedule_external (info);
449 else
450 ospf6_lsa_premature_aging (lsa);
451
452 return 0;
453}
454
455void
456ospf6_asbr_route_add (int type, int ifindex, struct prefix *prefix,
457 u_int nexthop_num, struct in6_addr *nexthop)
458{
459 int ret;
460 struct route_node *node;
461 struct ospf6_external_route *route;
462 struct ospf6_external_info *info, tinfo;
463
464 if (! ospf6_zebra_is_redistribute (type))
465 return;
466
467 /* apply route-map */
468 memset (&tinfo, 0, sizeof (struct ospf6_external_info));
469 if (rmap[type].map)
470 {
471 ret = route_map_apply (rmap[type].map, prefix, RMAP_OSPF6, &tinfo);
472 if (ret == RMAP_DENYMATCH)
473 {
474 if (IS_OSPF6_DUMP_ASBR)
475 zlog_info ("ASBR: denied by route-map %s", rmap[type].name);
476 return;
477 }
478 }
479
480 node = route_node_get (external_table, prefix);
481 route = node->info;
482
483 if (! route)
484 {
485 route = XMALLOC (MTYPE_OSPF6_EXTERNAL_INFO,
486 sizeof (struct ospf6_external_route));
487 memset (route, 0, sizeof (struct ospf6_external_route));
488
489 memcpy (&route->prefix, prefix, sizeof (struct prefix));
490
491 node->info = route;
492 route->node = node;
493 }
494
495 for (info = route->info_head; info; info = info->next)
496 {
497 if (info->type == type && info->ifindex == ifindex)
498 break;
499 }
500
501 if (! info)
502 {
503 info = XMALLOC (MTYPE_OSPF6_EXTERNAL_INFO,
504 sizeof (struct ospf6_external_info));
505 memset (info, 0, sizeof (struct ospf6_external_info));
506
507 info->route = route;
508 /* add tail */
509 info->prev = route->info_tail;
510 if (route->info_tail)
511 route->info_tail->next = info;
512 else
513 route->info_head = info;
514 route->info_tail = info;
515
516 info->id = link_state_id++;
517 }
518
519 /* copy result of route-map */
520 info->metric_type = tinfo.metric_type;
521 info->metric = tinfo.metric;
522 memcpy (&info->forwarding, &tinfo.forwarding,
523 sizeof (struct in6_addr));
524
525 info->type = type;
526 info->ifindex = ifindex;
527
528 if (nexthop_num && nexthop)
529 {
530 info->nexthop_num = nexthop_num;
531
532 if (info->nexthop)
533 XFREE (MTYPE_OSPF6_EXTERNAL_INFO, info->nexthop);
534
535 info->nexthop = (struct in6_addr *)
536 XMALLOC (MTYPE_OSPF6_EXTERNAL_INFO,
537 nexthop_num * sizeof (struct in6_addr));
538 memcpy (info->nexthop, nexthop,
539 nexthop_num * sizeof (struct in6_addr));
540 }
541
542 info->is_removed = 0;
543
544 //if (IS_OSPF6_DUMP_ASBR)
545 {
546 char pbuf[64];
547 struct timeval now;
548 prefix2str (&info->route->prefix, pbuf, sizeof (pbuf));
549 gettimeofday (&now, NULL);
550 zlog_info ("ASBR: start redistributing %s as LS-ID %ld: %ld.%06ld",
551 pbuf, (u_long) info->id, now.tv_sec, now.tv_usec);
552 }
553
554#ifdef HAVE_OSPF6_DAMP
555 ospf6_damp_event_up (OSPF6_DAMP_TYPE_ROUTE, prefix,
556 ospf6_asbr_schedule_external, info);
557#else /*HAVE_OSPF6_DAMP*/
558 ospf6_asbr_schedule_external (info);
559#endif /*HAVE_OSPF6_DAMP*/
560}
561
562void
563ospf6_asbr_route_remove (int type, int ifindex, struct prefix *prefix)
564{
565 struct route_node *node;
566 struct ospf6_external_route *route;
567 struct ospf6_external_info *info;
568 struct ospf6_lsa *lsa;
569
570 node = route_node_get (external_table, prefix);
571 route = node->info;
572
573 if (! route)
574 return;
575
576 for (info = route->info_head; info; info = info->next)
577 {
578 if (info->type == type && info->ifindex == ifindex)
579 break;
580 }
581
582 if (! info)
583 return;
584
585 //if (IS_OSPF6_DUMP_ASBR)
586 {
587 char pbuf[64];
588 struct timeval now;
589 prefix2str (&info->route->prefix, pbuf, sizeof (pbuf));
590 gettimeofday (&now, NULL);
591 zlog_info ("ASBR: quit redistributing %s as LS-ID %ld: %ld.%06ld",
592 pbuf, (u_long) info->id, now.tv_sec, now.tv_usec);
593 }
594
595 if (info->thread_originate)
596 thread_cancel (info->thread_originate);
597 info->thread_originate = NULL;
598
599 lsa = ospf6_lsdb_lookup (htons (OSPF6_LSA_TYPE_AS_EXTERNAL),
600 htonl (info->id), ospf6->router_id, ospf6);
601#ifdef HAVE_OSPF6_DAMP
602 ospf6_damp_event_down (OSPF6_DAMP_TYPE_ROUTE, &info->route->prefix,
603 ospf6_asbr_external_lsa_flush, lsa);
604#else /*HAVE_OSPF6_DAMP*/
605 ospf6_asbr_external_lsa_flush (lsa);
606#endif /*HAVE_OSPF6_DAMP*/
607
608#if 1
609 info->is_removed = 1;
610#else
611 /* remove from route */
612 if (info->prev)
613 info->prev->next = info->next;
614 else
615 info->route->info_head = info->next;
616 if (info->next)
617 info->next->prev = info->prev;
618 else
619 info->route->info_tail = info->prev;
620
621 /* if no info, free route */
622 if (! info->route->info_head && ! info->route->info_tail)
623 {
624 info->route->node->info = NULL;
625 free (info->route);
626 }
627
628 if (info->nexthop)
629 free (info->nexthop);
630 free (info);
631#endif /*0*/
632}
633
634void
635ospf6_asbr_external_lsa_add (struct ospf6_lsa *lsa)
636{
637 struct ospf6_lsa_as_external *external;
638 struct prefix_ls asbr_id;
639 struct ospf6_route_req asbr_entry;
640 struct ospf6_route_req request;
641
642 external = OSPF6_LSA_HEADER_END (lsa->header);
643
644 if (IS_LSA_MAXAGE (lsa))
645 {
646 if (IS_OSPF6_DUMP_ASBR)
647 zlog_info ("ASBR: maxage external lsa: %s seq: %lx",
648 lsa->str, (u_long)ntohl (lsa->header->seqnum));
649 ospf6_asbr_external_lsa_remove (lsa);
650 return;
651 }
652
653 if (IS_OSPF6_DUMP_ASBR)
654 zlog_info ("ASBR: new external lsa: %s seq: %lx",
655 lsa->str, (u_long)ntohl (lsa->header->seqnum));
656
657 if (lsa->header->adv_router == ospf6->router_id)
658 {
659 if (IS_OSPF6_DUMP_ASBR)
660 zlog_info ("ASBR: my external LSA, ignore");
661 return;
662 }
663
664 if (OSPF6_ASBR_METRIC (external) == LS_INFINITY)
665 {
666 if (IS_OSPF6_DUMP_ASBR)
667 zlog_info ("ASBR: metric is infinity, ignore");
668 return;
669 }
670
671 memset (&asbr_id, 0, sizeof (asbr_id));
672 asbr_id.family = AF_UNSPEC;
673 asbr_id.prefixlen = 64; /* xxx */
674 asbr_id.adv_router.s_addr = lsa->header->adv_router;
675
676 ospf6_route_lookup (&asbr_entry, (struct prefix *) &asbr_id,
677 ospf6->topology_table);
678
679 if (ospf6_route_end (&asbr_entry))
680 {
681 if (IS_OSPF6_DUMP_ASBR)
682 {
683 char buf[64];
684 inet_ntop (AF_INET, &asbr_id.adv_router, buf, sizeof (buf));
685 zlog_info ("ASBR: router %s not found, ignore", buf);
686 }
687 return;
688 }
689
690 memset (&request, 0, sizeof (request));
691 request.route.type = OSPF6_DEST_TYPE_NETWORK;
692 request.route.prefix.family = AF_INET6;
693 request.route.prefix.prefixlen = external->prefix.prefix_length;
694 memcpy (&request.route.prefix.u.prefix6, (char *)(external + 1),
695 OSPF6_PREFIX_SPACE (request.route.prefix.prefixlen));
696
697 request.path.area_id = asbr_entry.path.area_id;
698 request.path.origin.type = htons (OSPF6_LSA_TYPE_AS_EXTERNAL);
699 request.path.origin.id = lsa->header->id;
700 request.path.origin.adv_router = lsa->header->adv_router;
701 if (CHECK_FLAG (external->bits_metric, OSPF6_ASBR_BIT_E))
702 {
703 request.path.type = OSPF6_PATH_TYPE_EXTERNAL2;
704 request.path.metric_type = 2;
705 request.path.cost = asbr_entry.path.cost;
706 request.path.cost_e2 = OSPF6_ASBR_METRIC (external);
707 }
708 else
709 {
710 request.path.type = OSPF6_PATH_TYPE_EXTERNAL1;
711 request.path.metric_type = 1;
712 request.path.cost = asbr_entry.path.cost
713 + OSPF6_ASBR_METRIC (external);
714 request.path.cost_e2 = 0;
715 }
716 request.path.prefix_options = external->prefix.prefix_options;
717
718 while (((struct prefix_ls *)&asbr_entry.route.prefix)->adv_router.s_addr ==
719 asbr_id.adv_router.s_addr &&
720 asbr_entry.route.type == OSPF6_DEST_TYPE_ROUTER)
721 {
722 memcpy (&request.nexthop, &asbr_entry.nexthop,
723 sizeof (struct ospf6_nexthop));
724 if (IS_OSPF6_DUMP_ASBR)
725 {
726 char buf[64], nhop[64], ifname[IFNAMSIZ];
727 prefix2str (&request.route.prefix, buf, sizeof (buf));
728 inet_ntop (AF_INET6, &request.nexthop.address, nhop, sizeof (nhop));
729 if_indextoname (request.nexthop.ifindex, ifname);
730 zlog_info ("ASBR: add route: %s %s%%%s", buf, nhop, ifname);
731 }
732 ospf6_route_add (&request, ospf6->route_table);
733 ospf6_route_next (&asbr_entry);
734 }
735}
736
737void
738ospf6_asbr_external_lsa_remove (struct ospf6_lsa *lsa)
739{
740 struct ospf6_lsa_as_external *external;
741 struct prefix dest;
742 char buf[64];
743 struct ospf6_route_req request;
744
745 if (IS_OSPF6_DUMP_ASBR)
746 zlog_info ("ASBR: withdraw external lsa: %s seq: %lx",
747 lsa->str, (u_long)ntohl (lsa->header->seqnum));
748
749 if (lsa->header->adv_router == ospf6->router_id)
750 {
751 if (IS_OSPF6_DUMP_ASBR)
752 zlog_info ("ASBR: my external LSA, ignore");
753 return;
754 }
755
756 external = OSPF6_LSA_HEADER_END (lsa->header);
757 memset (&dest, 0, sizeof (dest));
758 dest.family = AF_INET6;
759 dest.prefixlen = external->prefix.prefix_length;
760 memcpy (&dest.u.prefix6, (char *)(external + 1),
761 OSPF6_PREFIX_SPACE (dest.prefixlen));
762
763 ospf6_route_lookup (&request, &dest, ospf6->route_table);
764 if (ospf6_route_end (&request))
765 {
766 if (IS_OSPF6_DUMP_ASBR)
767 {
768 prefix2str (&dest, buf, sizeof (buf));
769 zlog_info ("ASBR: %s not found", buf);
770 }
771 return;
772 }
773
774 while (request.path.origin.id != lsa->header->id ||
775 request.path.origin.adv_router != lsa->header->adv_router)
776 {
777 if (prefix_same (&request.route.prefix, &dest) != 1)
778 {
779 if (IS_OSPF6_DUMP_ASBR)
780 zlog_info ("ASBR: Can't find the entry matches the origin");
781 return;
782 }
783 ospf6_route_next (&request);
784 }
785 assert (request.path.origin.id == lsa->header->id);
786 assert (request.path.origin.adv_router == request.path.origin.adv_router);
787
788 while (request.path.origin.id == lsa->header->id &&
789 request.path.origin.adv_router == lsa->header->adv_router &&
790 prefix_same (&request.route.prefix, &dest) == 1)
791 {
792 if (IS_OSPF6_DUMP_ASBR)
793 {
794 char nhop[64], ifname[IFNAMSIZ];
795 prefix2str (&dest, buf, sizeof (buf));
796 inet_ntop (AF_INET6, &request.nexthop.address, nhop, sizeof (nhop));
797 if_indextoname (request.nexthop.ifindex, ifname);
798 zlog_info ("ASBR: remove route: %s %s%%%s", buf, nhop, ifname);
799 }
800
801 ospf6_route_remove (&request, ospf6->route_table);
802 ospf6_route_next (&request);
803 }
804}
805
806void
807ospf6_asbr_external_lsa_change (struct ospf6_lsa *old, struct ospf6_lsa *new)
808{
809 assert (old || new);
810
811 if (old == NULL)
812 ospf6_asbr_external_lsa_add (new);
813 else if (new == NULL)
814 ospf6_asbr_external_lsa_remove (old);
815 else
816 {
817 ospf6_route_table_freeze (ospf6->route_table);
818 ospf6_asbr_external_lsa_remove (old);
819 ospf6_asbr_external_lsa_add (new);
820 ospf6_route_table_thaw (ospf6->route_table);
821 }
822}
823
824void
825ospf6_asbr_asbr_entry_add (struct ospf6_route_req *topo_entry)
826{
827 struct ospf6_lsdb_node node;
828
829 struct prefix_ls *inter_router;
830 u_int32_t id, adv_router;
831
832 inter_router = (struct prefix_ls *) &topo_entry->route.prefix;
833 id = inter_router->id.s_addr;
834 adv_router = inter_router->adv_router.s_addr;
835
836 if (IS_OSPF6_DUMP_ASBR)
837 {
838 char buf[64];
839 inet_ntop (AF_INET, &inter_router->adv_router, buf, sizeof (buf));
840 zlog_info ("ASBR: new router found: %s", buf);
841 }
842
843 if (ntohl (id) != 0 ||
844 ! OSPF6_OPT_ISSET (topo_entry->path.capability, OSPF6_OPT_E))
845 {
846 zlog_warn ("ASBR: Inter topology table malformed");
847 return;
848 }
849
850 for (ospf6_lsdb_type_router (&node, htons (OSPF6_LSA_TYPE_AS_EXTERNAL),
851 adv_router, ospf6->lsdb);
852 ! ospf6_lsdb_is_end (&node);
853 ospf6_lsdb_next (&node))
854 ospf6_asbr_external_lsa_add (node.lsa);
855}
856
857void
858ospf6_asbr_asbr_entry_remove (struct ospf6_route_req *topo_entry)
859{
860 struct prefix_ls *inter_router;
861 u_int32_t id, adv_router;
862 struct ospf6_route_req request;
863
864 inter_router = (struct prefix_ls *) &topo_entry->route.prefix;
865 id = inter_router->id.s_addr;
866 adv_router = inter_router->adv_router.s_addr;
867
868 if (IS_OSPF6_DUMP_ASBR)
869 {
870 char buf[64];
871 inet_ntop (AF_INET, &inter_router->adv_router, buf, sizeof (buf));
872 zlog_info ("ASBR: router disappearing: %s", buf);
873 }
874
875 if (ntohl (id) != 0 ||
876 ! OSPF6_OPT_ISSET (topo_entry->path.capability, OSPF6_OPT_E))
877 {
878 zlog_warn ("ASBR: Inter topology table malformed");
879 }
880
881 for (ospf6_route_head (&request, ospf6->route_table);
882 ! ospf6_route_end (&request);
883 ospf6_route_next (&request))
884 {
885 if (request.path.type != OSPF6_PATH_TYPE_EXTERNAL1 &&
886 request.path.type != OSPF6_PATH_TYPE_EXTERNAL2)
887 continue;
888 if (request.path.area_id != topo_entry->path.area_id)
889 continue;
890 if (request.path.origin.adv_router != topo_entry->path.origin.adv_router)
891 continue;
892 if (memcmp (&topo_entry->nexthop, &request.nexthop,
893 sizeof (struct ospf6_nexthop)))
894 continue;
895
896 ospf6_route_remove (&request, ospf6->route_table);
897 }
898}
899
900int
901ospf6_asbr_external_show (struct vty *vty, struct ospf6_lsa *lsa)
902{
903 struct ospf6_lsa_as_external *external;
904 char buf[128], *ptr;
905 struct in6_addr in6;
906
907 assert (lsa->header);
908 external = (struct ospf6_lsa_as_external *)(lsa->header + 1);
909
910 /* bits */
911 snprintf (buf, sizeof (buf), "%s%s%s",
912 (CHECK_FLAG (external->bits_metric, OSPF6_ASBR_BIT_E) ?
913 "E" : "-"),
914 (CHECK_FLAG (external->bits_metric, OSPF6_ASBR_BIT_F) ?
915 "F" : "-"),
916 (CHECK_FLAG (external->bits_metric, OSPF6_ASBR_BIT_T) ?
917 "T" : "-"));
918
919 vty_out (vty, " Bits: %s%s", buf, VTY_NEWLINE);
920 vty_out (vty, " Metric: %5lu%s", (u_long)OSPF6_ASBR_METRIC (external),
921 VTY_NEWLINE);
922
923 ospf6_prefix_options_str (external->prefix.prefix_options,
924 buf, sizeof (buf));
925 vty_out (vty, " Prefix Options: %s%s", buf, VTY_NEWLINE);
926
927 vty_out (vty, " Referenced LSType: %d%s",
928 ntohs (external->prefix.prefix_refer_lstype), VTY_NEWLINE);
929
930 ospf6_prefix_in6_addr (&external->prefix, &in6);
931 inet_ntop (AF_INET6, &in6, buf, sizeof (buf));
932 vty_out (vty, " Prefix: %s/%d%s",
933 buf, external->prefix.prefix_length, VTY_NEWLINE);
934
935 /* Forwarding-Address */
936 if (CHECK_FLAG (external->bits_metric, OSPF6_ASBR_BIT_F))
937 {
938 ptr = ((char *)(external + 1))
939 + OSPF6_PREFIX_SPACE (external->prefix.prefix_length);
940 inet_ntop (AF_INET6, (struct in6_addr *) ptr, buf, sizeof (buf));
941 vty_out (vty, " Forwarding-Address: %s%s", buf, VTY_NEWLINE);
942 }
943
944 return 0;
945}
946
947void
948ospf6_asbr_database_hook (struct ospf6_lsa *old, struct ospf6_lsa *new)
949{
950 if (old)
951 ospf6_asbr_external_lsa_remove (old);
952 if (new && ! IS_LSA_MAXAGE (new))
953 ospf6_asbr_external_lsa_add (new);
954}
955
956void
957ospf6_asbr_register_as_external ()
958{
959 struct ospf6_lsa_slot slot;
960
961 memset (&slot, 0, sizeof (slot));
962 slot.type = htons (OSPF6_LSA_TYPE_AS_EXTERNAL);
963 slot.name = "AS-External";
964 slot.func_show = ospf6_asbr_external_show;
965 slot.func_refresh = ospf6_asbr_external_lsa_refresh;
966 ospf6_lsa_slot_register (&slot);
967
968 ospf6_lsdb_hook[OSPF6_LSA_TYPE_AS_EXTERNAL & OSPF6_LSTYPE_CODE_MASK].hook =
969 ospf6_asbr_database_hook;
970}
971
972void
973ospf6_asbr_external_info_show (struct vty *vty,
974 struct ospf6_external_info *info)
975{
976 char prefix_buf[64], id_buf[16];
977 struct in_addr id;
978
979 if (info->is_removed)
980 return;
981
982 id.s_addr = ntohl (info->id);
983 inet_ntop (AF_INET, &id, id_buf, sizeof (id_buf));
984 prefix2str (&info->route->prefix, prefix_buf, sizeof (prefix_buf));
985 vty_out (vty, "%s %-32s %3d %-15s %3d %lu(type-%d)%s",
986 ZROUTE_ABNAME(info->type), prefix_buf, info->ifindex, id_buf,
987 info->nexthop_num, (u_long) info->metric, info->metric_type,
988 VTY_NEWLINE);
989}
990
991void
992ospf6_asbr_external_route_show (struct vty *vty,
993 struct ospf6_external_route *route)
994{
995 struct ospf6_external_info *info;
996 for (info = route->info_head; info; info = info->next)
997 ospf6_asbr_external_info_show (vty, info);
998}
999
1000DEFUN (show_ipv6_route_ospf6_external,
1001 show_ipv6_route_ospf6_external_cmd,
1002 "show ipv6 ospf6 route redistribute",
1003 SHOW_STR
1004 IP6_STR
1005 ROUTE_STR
1006 OSPF6_STR
1007 "redistributing External information\n"
1008 )
1009{
1010 struct route_node *node;
1011 struct ospf6_external_route *route;
1012
1013 vty_out (vty, "%s %-32s %3s %-15s %3s %s%s",
1014 " ", "Prefix", "I/F", "LS-Id", "#NH", "Metric",
1015 VTY_NEWLINE);
1016 for (node = route_top (external_table); node; node = route_next (node))
1017 {
1018 route = node->info;
1019 if (route)
1020 ospf6_asbr_external_route_show (vty, route);
1021 }
1022 return CMD_SUCCESS;
1023}
1024
1025void
1026ospf6_asbr_init ()
1027{
1028 external_table = route_table_init ();
1029 link_state_id = 0;
1030
1031 ospf6_asbr_register_as_external ();
1032
1033 install_element (VIEW_NODE, &show_ipv6_route_ospf6_external_cmd);
1034 install_element (ENABLE_NODE, &show_ipv6_route_ospf6_external_cmd);
1035 install_element (OSPF6_NODE, &ospf6_redistribute_cmd);
1036 install_element (OSPF6_NODE, &ospf6_redistribute_routemap_cmd);
1037 install_element (OSPF6_NODE, &no_ospf6_redistribute_cmd);
1038}
1039
1040