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