blob: bc05dc279df0f51c4c33d9911ac4492e78665eb8 [file] [log] [blame]
paul718e3742002-12-13 20:15:29 +00001/*
hasso508e53e2004-05-18 18:57:06 +00002 * Copyright (C) 2003 Yasuhiro Ohara
paul718e3742002-12-13 20:15:29 +00003 *
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"
hasso508e53e2004-05-18 18:57:06 +000033#include "linklist.h"
paul718e3742002-12-13 20:15:29 +000034
paul718e3742002-12-13 20:15:29 +000035#include "ospf6_proto.h"
hasso508e53e2004-05-18 18:57:06 +000036#include "ospf6_lsa.h"
37#include "ospf6_lsdb.h"
38#include "ospf6_route.h"
39#include "ospf6_zebra.h"
hasso6452df02004-08-15 05:52:07 +000040#include "ospf6_message.h"
41
hasso508e53e2004-05-18 18:57:06 +000042#include "ospf6_top.h"
43#include "ospf6_area.h"
hasso6452df02004-08-15 05:52:07 +000044#include "ospf6_interface.h"
45#include "ospf6_neighbor.h"
hasso508e53e2004-05-18 18:57:06 +000046#include "ospf6_asbr.h"
47#include "ospf6_intra.h"
hasso6452df02004-08-15 05:52:07 +000048#include "ospf6_flood.h"
hasso049207c2004-08-04 20:02:13 +000049#include "ospf6d.h"
paul718e3742002-12-13 20:15:29 +000050
hasso508e53e2004-05-18 18:57:06 +000051unsigned char conf_debug_ospf6_asbr = 0;
paul718e3742002-12-13 20:15:29 +000052
ajsf52d13c2005-10-01 17:38:06 +000053#define ZROUTE_NAME(x) zebra_route_string(x)
hasso508e53e2004-05-18 18:57:06 +000054
55/* AS External LSA origination */
Paul Jakma6ac29a52008-08-15 13:45:30 +010056static void
hasso6452df02004-08-15 05:52:07 +000057ospf6_as_external_lsa_originate (struct ospf6_route *route)
paul718e3742002-12-13 20:15:29 +000058{
hasso508e53e2004-05-18 18:57:06 +000059 char buffer[OSPF6_MAX_LSASIZE];
60 struct ospf6_lsa_header *lsa_header;
61 struct ospf6_lsa *old, *lsa;
Paul Jakma0b26f812006-05-15 10:47:53 +000062 struct ospf6_external_info *info = route->route_option;
paul718e3742002-12-13 20:15:29 +000063
hasso508e53e2004-05-18 18:57:06 +000064 struct ospf6_as_external_lsa *as_external_lsa;
65 char buf[64];
66 caddr_t p;
paul718e3742002-12-13 20:15:29 +000067
hasso508e53e2004-05-18 18:57:06 +000068 /* find previous LSA */
69 old = ospf6_lsdb_lookup (htons (OSPF6_LSTYPE_AS_EXTERNAL),
hasso6452df02004-08-15 05:52:07 +000070 route->path.origin.id, ospf6->router_id,
hasso508e53e2004-05-18 18:57:06 +000071 ospf6->lsdb);
72
hasso1e058382004-09-01 21:36:14 +000073 if (IS_OSPF6_DEBUG_ASBR || IS_OSPF6_DEBUG_ORIGINATE (AS_EXTERNAL))
hasso508e53e2004-05-18 18:57:06 +000074 {
75 prefix2str (&route->prefix, buf, sizeof (buf));
hassoc6487d62004-12-24 06:00:11 +000076 zlog_debug ("Originate AS-External-LSA for %s", buf);
hasso508e53e2004-05-18 18:57:06 +000077 }
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 */
Paul Jakma0b26f812006-05-15 10:47:53 +000095 if (! IN6_IS_ADDR_UNSPECIFIED (&info->forwarding))
hasso508e53e2004-05-18 18:57:06 +000096 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 {
Paul Jakma0b26f812006-05-15 10:47:53 +0000124 memcpy (p, &info->forwarding, sizeof (struct in6_addr));
hasso508e53e2004-05-18 18:57:06 +0000125 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);
hasso6452df02004-08-15 05:52:07 +0000137 lsa_header->id = route->path.origin.id;
hasso508e53e2004-05-18 18:57:06 +0000138 lsa_header->adv_router = ospf6->router_id;
139 lsa_header->seqnum =
hasso049207c2004-08-04 20:02:13 +0000140 ospf6_new_ls_seqnum (lsa_header->type, lsa_header->id,
141 lsa_header->adv_router, ospf6->lsdb);
hasso508e53e2004-05-18 18:57:06 +0000142 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);
hasso508e53e2004-05-18 18:57:06 +0000149
150 /* Originate */
hasso6452df02004-08-15 05:52:07 +0000151 ospf6_lsa_originate_process (lsa, ospf6);
hasso508e53e2004-05-18 18:57:06 +0000152}
153
hasso508e53e2004-05-18 18:57:06 +0000154
155void
156ospf6_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
hasso1e058382004-09-01 21:36:14 +0000167 if (IS_OSPF6_DEBUG_EXAMIN (AS_EXTERNAL))
hassoc6487d62004-12-24 06:00:11 +0000168 zlog_debug ("Calculate AS-External route for %s", lsa->name);
hasso508e53e2004-05-18 18:57:06 +0000169
170 if (lsa->header->adv_router == ospf6->router_id)
171 {
hasso1e058382004-09-01 21:36:14 +0000172 if (IS_OSPF6_DEBUG_EXAMIN (AS_EXTERNAL))
hassoc6487d62004-12-24 06:00:11 +0000173 zlog_debug ("Ignore self-originated AS-External-LSA");
hasso508e53e2004-05-18 18:57:06 +0000174 return;
175 }
176
177 if (OSPF6_ASBR_METRIC (external) == LS_INFINITY)
178 {
hasso1e058382004-09-01 21:36:14 +0000179 if (IS_OSPF6_DEBUG_EXAMIN (AS_EXTERNAL))
hassoc6487d62004-12-24 06:00:11 +0000180 zlog_debug ("Ignore LSA with LSInfinity Metric");
hasso508e53e2004-05-18 18:57:06 +0000181 return;
182 }
183
hassoccb59b12004-08-25 09:10:37 +0000184 ospf6_linkstate_prefix (lsa->header->adv_router, htonl (0), &asbr_id);
hasso6452df02004-08-15 05:52:07 +0000185 asbr_entry = ospf6_route_lookup (&asbr_id, ospf6->brouter_table);
hasso63069ad2004-09-02 13:01:01 +0000186 if (asbr_entry == NULL ||
187 ! CHECK_FLAG (asbr_entry->path.router_bits, OSPF6_ROUTER_BIT_E))
hasso508e53e2004-05-18 18:57:06 +0000188 {
hasso1e058382004-09-01 21:36:14 +0000189 if (IS_OSPF6_DEBUG_EXAMIN (AS_EXTERNAL))
hasso508e53e2004-05-18 18:57:06 +0000190 {
191 prefix2str (&asbr_id, buf, sizeof (buf));
hassoc6487d62004-12-24 06:00:11 +0000192 zlog_debug ("ASBR entry not found: %s", buf);
hasso508e53e2004-05-18 18:57:06 +0000193 }
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
hasso1e058382004-09-01 21:36:14 +0000227 if (IS_OSPF6_DEBUG_EXAMIN (AS_EXTERNAL))
hasso508e53e2004-05-18 18:57:06 +0000228 {
229 prefix2str (&route->prefix, buf, sizeof (buf));
hassoc6487d62004-12-24 06:00:11 +0000230 zlog_debug ("AS-External route add: %s", buf);
hasso508e53e2004-05-18 18:57:06 +0000231 }
232
233 ospf6_route_add (route, ospf6->route_table);
234}
235
236void
237ospf6_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
hasso1e058382004-09-01 21:36:14 +0000247 if (IS_OSPF6_DEBUG_EXAMIN (AS_EXTERNAL))
hassoc6487d62004-12-24 06:00:11 +0000248 zlog_debug ("Withdraw AS-External route for %s", lsa->name);
hasso508e53e2004-05-18 18:57:06 +0000249
250 if (lsa->header->adv_router == ospf6->router_id)
251 {
hasso1e058382004-09-01 21:36:14 +0000252 if (IS_OSPF6_DEBUG_EXAMIN (AS_EXTERNAL))
hassoc6487d62004-12-24 06:00:11 +0000253 zlog_debug ("Ignore self-originated AS-External-LSA");
hasso508e53e2004-05-18 18:57:06 +0000254 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 {
hasso1e058382004-09-01 21:36:14 +0000265 if (IS_OSPF6_DEBUG_EXAMIN (AS_EXTERNAL))
hasso508e53e2004-05-18 18:57:06 +0000266 {
267 prefix2str (&prefix, buf, sizeof (buf));
hassoc6487d62004-12-24 06:00:11 +0000268 zlog_debug ("AS-External route %s not found", buf);
hasso508e53e2004-05-18 18:57:06 +0000269 }
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
hasso1e058382004-09-01 21:36:14 +0000286 if (IS_OSPF6_DEBUG_EXAMIN (AS_EXTERNAL))
hasso508e53e2004-05-18 18:57:06 +0000287 {
288 prefix2str (&route->prefix, buf, sizeof (buf));
hassoc6487d62004-12-24 06:00:11 +0000289 zlog_debug ("AS-External route remove: %s", buf);
hasso508e53e2004-05-18 18:57:06 +0000290 }
291 ospf6_route_remove (route, ospf6->route_table);
292 }
293}
294
295void
296ospf6_asbr_lsentry_add (struct ospf6_route *asbr_entry)
297{
hasso508e53e2004-05-18 18:57:06 +0000298 struct ospf6_lsa *lsa;
299 u_int16_t type;
300 u_int32_t router;
301
Paul Jakmacb4b8842006-05-15 10:39:30 +0000302 if (! CHECK_FLAG (asbr_entry->flag, OSPF6_ROUTE_BEST))
hasso508e53e2004-05-18 18:57:06 +0000303 {
Paul Jakmacb4b8842006-05-15 10:39:30 +0000304 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;
hasso508e53e2004-05-18 18:57:06 +0000309 }
310
311 type = htons (OSPF6_LSTYPE_AS_EXTERNAL);
312 router = ospf6_linkstate_prefix_adv_router (&asbr_entry->prefix);
Paul Jakmacb4b8842006-05-15 10:39:30 +0000313 for (lsa = ospf6_lsdb_type_router_head (type, router, ospf6->lsdb); lsa;
314 lsa = ospf6_lsdb_type_router_next (type, router, lsa))
hasso508e53e2004-05-18 18:57:06 +0000315 {
316 if (! OSPF6_LSA_IS_MAXAGE (lsa))
317 ospf6_asbr_lsa_add (lsa);
318 }
hasso508e53e2004-05-18 18:57:06 +0000319}
320
321void
322ospf6_asbr_lsentry_remove (struct ospf6_route *asbr_entry)
323{
hasso508e53e2004-05-18 18:57:06 +0000324 struct ospf6_lsa *lsa;
325 u_int16_t type;
326 u_int32_t router;
327
hasso508e53e2004-05-18 18:57:06 +0000328 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);
hasso508e53e2004-05-18 18:57:06 +0000333}
334
335
336
paul718e3742002-12-13 20:15:29 +0000337/* redistribute function */
hasso508e53e2004-05-18 18:57:06 +0000338
Paul Jakma6ac29a52008-08-15 13:45:30 +0100339static void
paul0c083ee2004-10-10 12:54:58 +0000340ospf6_asbr_routemap_set (int type, const char *mapname)
paul718e3742002-12-13 20:15:29 +0000341{
hasso508e53e2004-05-18 18:57:06 +0000342 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);
paul718e3742002-12-13 20:15:29 +0000346}
347
Paul Jakma6ac29a52008-08-15 13:45:30 +0100348static void
paul718e3742002-12-13 20:15:29 +0000349ospf6_asbr_routemap_unset (int type)
350{
hasso508e53e2004-05-18 18:57:06 +0000351 if (ospf6->rmap[type].name)
352 free (ospf6->rmap[type].name);
353 ospf6->rmap[type].name = NULL;
354 ospf6->rmap[type].map = NULL;
paul718e3742002-12-13 20:15:29 +0000355}
356
Paul Jakma6ac29a52008-08-15 13:45:30 +0100357static void
paul0c083ee2004-10-10 12:54:58 +0000358ospf6_asbr_routemap_update (const char *mapname)
paul718e3742002-12-13 20:15:29 +0000359{
hasso508e53e2004-05-18 18:57:06 +0000360 int type;
361
362 if (ospf6 == NULL)
363 return;
364
365 for (type = 0; type < ZEBRA_ROUTE_MAX; type++)
paul718e3742002-12-13 20:15:29 +0000366 {
hasso508e53e2004-05-18 18:57:06 +0000367 if (ospf6->rmap[type].name)
368 ospf6->rmap[type].map =
369 route_map_lookup_by_name (ospf6->rmap[type].name);
paul718e3742002-12-13 20:15:29 +0000370 else
hasso508e53e2004-05-18 18:57:06 +0000371 ospf6->rmap[type].map = NULL;
372 }
373}
374
375int
376ospf6_asbr_is_asbr (struct ospf6 *o)
377{
378 return o->external_table->count;
379}
380
Paul Jakma6ac29a52008-08-15 13:45:30 +0100381static void
hasso508e53e2004-05-18 18:57:06 +0000382ospf6_asbr_redistribute_set (int type)
383{
384 ospf6_zebra_redistribute (type);
385}
386
Paul Jakma6ac29a52008-08-15 13:45:30 +0100387static void
hasso508e53e2004-05-18 18:57:06 +0000388ospf6_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
407void
408ospf6_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];
paul1eb8ef22005-04-07 07:30:20 +0000419 struct listnode *lnode, *lnnode;
hasso508e53e2004-05-18 18:57:06 +0000420 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));
hassoc6487d62004-12-24 06:00:11 +0000428 zlog_debug ("Redistribute %s (%s)", pbuf, ZROUTE_NAME (type));
hasso508e53e2004-05-18 18:57:06 +0000429 }
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)
hasso03d52f82004-09-29 00:26:19 +0000435 ospf6_asbr_routemap_update (NULL);
hasso508e53e2004-05-18 18:57:06 +0000436 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;
Vyacheslav Trushkin1ce08782011-11-16 14:22:03 +0400450 tinfo.ifindex = ifindex;
hasso508e53e2004-05-18 18:57:06 +0000451
452 ret = route_map_apply (ospf6->rmap[type].map, prefix,
453 RMAP_OSPF6, &troute);
paul47828742005-08-10 15:46:11 +0000454 if (ret == RMAP_DENYMATCH)
hasso508e53e2004-05-18 18:57:06 +0000455 {
456 if (IS_OSPF6_DEBUG_ASBR)
hassoc6487d62004-12-24 06:00:11 +0000457 zlog_debug ("Denied by route-map \"%s\"", ospf6->rmap[type].name);
hasso508e53e2004-05-18 18:57:06 +0000458 return;
459 }
460 }
461
462 match = ospf6_route_lookup (prefix, ospf6->external_table);
463 if (match)
464 {
465 info = match->route_option;
466
467 /* copy result of route-map */
468 if (ospf6->rmap[type].map)
469 {
470 if (troute.path.metric_type)
471 match->path.metric_type = troute.path.metric_type;
472 if (troute.path.cost)
473 match->path.cost = troute.path.cost;
474 if (! IN6_IS_ADDR_UNSPECIFIED (&tinfo.forwarding))
475 memcpy (&info->forwarding, &tinfo.forwarding,
476 sizeof (struct in6_addr));
477 }
478
479 info->type = type;
480 match->nexthop[0].ifindex = ifindex;
481 if (nexthop_num && nexthop)
482 memcpy (&match->nexthop[0].address, nexthop, sizeof (struct in6_addr));
483
484 /* create/update binding in external_id_table */
485 prefix_id.family = AF_INET;
486 prefix_id.prefixlen = 32;
487 prefix_id.u.prefix4.s_addr = htonl (info->id);
488 node = route_node_get (ospf6->external_id_table, &prefix_id);
489 node->info = match;
490
491 if (IS_OSPF6_DEBUG_ASBR)
492 {
493 inet_ntop (AF_INET, &prefix_id.u.prefix4, ibuf, sizeof (ibuf));
hassoc6487d62004-12-24 06:00:11 +0000494 zlog_debug ("Advertise as AS-External Id:%s", ibuf);
hasso508e53e2004-05-18 18:57:06 +0000495 }
496
hasso3b687352004-08-19 06:56:53 +0000497 match->path.origin.id = htonl (info->id);
hasso6452df02004-08-15 05:52:07 +0000498 ospf6_as_external_lsa_originate (match);
hasso508e53e2004-05-18 18:57:06 +0000499 return;
500 }
501
502 /* create new entry */
503 route = ospf6_route_create ();
504 route->type = OSPF6_DEST_TYPE_NETWORK;
505 memcpy (&route->prefix, prefix, sizeof (struct prefix));
506
507 info = (struct ospf6_external_info *)
Stephen Hemminger393deb92008-08-18 14:13:29 -0700508 XCALLOC (MTYPE_OSPF6_EXTERNAL_INFO, sizeof (struct ospf6_external_info));
hasso508e53e2004-05-18 18:57:06 +0000509 route->route_option = info;
510 info->id = ospf6->external_id++;
511
512 /* copy result of route-map */
513 if (ospf6->rmap[type].map)
514 {
515 if (troute.path.metric_type)
516 route->path.metric_type = troute.path.metric_type;
517 if (troute.path.cost)
518 route->path.cost = troute.path.cost;
519 if (! IN6_IS_ADDR_UNSPECIFIED (&tinfo.forwarding))
520 memcpy (&info->forwarding, &tinfo.forwarding,
521 sizeof (struct in6_addr));
522 }
523
524 info->type = type;
525 route->nexthop[0].ifindex = ifindex;
526 if (nexthop_num && nexthop)
527 memcpy (&route->nexthop[0].address, nexthop, sizeof (struct in6_addr));
528
529 /* create/update binding in external_id_table */
530 prefix_id.family = AF_INET;
531 prefix_id.prefixlen = 32;
532 prefix_id.u.prefix4.s_addr = htonl (info->id);
533 node = route_node_get (ospf6->external_id_table, &prefix_id);
534 node->info = route;
535
536 route = ospf6_route_add (route, ospf6->external_table);
537 route->route_option = info;
538
539 if (IS_OSPF6_DEBUG_ASBR)
540 {
541 inet_ntop (AF_INET, &prefix_id.u.prefix4, ibuf, sizeof (ibuf));
hassoc6487d62004-12-24 06:00:11 +0000542 zlog_debug ("Advertise as AS-External Id:%s", ibuf);
hasso508e53e2004-05-18 18:57:06 +0000543 }
544
hasso3b687352004-08-19 06:56:53 +0000545 route->path.origin.id = htonl (info->id);
hasso6452df02004-08-15 05:52:07 +0000546 ospf6_as_external_lsa_originate (route);
hasso508e53e2004-05-18 18:57:06 +0000547
548 /* Router-Bit (ASBR Flag) may have to be updated */
paul1eb8ef22005-04-07 07:30:20 +0000549 for (ALL_LIST_ELEMENTS (ospf6->area_list, lnode, lnnode, oa))
550 OSPF6_ROUTER_LSA_SCHEDULE (oa);
hasso508e53e2004-05-18 18:57:06 +0000551}
552
553void
554ospf6_asbr_redistribute_remove (int type, int ifindex, struct prefix *prefix)
555{
556 struct ospf6_route *match;
557 struct ospf6_external_info *info = NULL;
558 struct route_node *node;
559 struct ospf6_lsa *lsa;
560 struct prefix prefix_id;
561 char pbuf[64], ibuf[16];
paul1eb8ef22005-04-07 07:30:20 +0000562 struct listnode *lnode, *lnnode;
hasso508e53e2004-05-18 18:57:06 +0000563 struct ospf6_area *oa;
564
565 match = ospf6_route_lookup (prefix, ospf6->external_table);
566 if (match == NULL)
567 {
568 if (IS_OSPF6_DEBUG_ASBR)
569 {
570 prefix2str (prefix, pbuf, sizeof (pbuf));
hassoc6487d62004-12-24 06:00:11 +0000571 zlog_debug ("No such route %s to withdraw", pbuf);
hasso508e53e2004-05-18 18:57:06 +0000572 }
573 return;
574 }
575
576 info = match->route_option;
577 assert (info);
578
579 if (info->type != type)
580 {
581 if (IS_OSPF6_DEBUG_ASBR)
582 {
583 prefix2str (prefix, pbuf, sizeof (pbuf));
hassoc6487d62004-12-24 06:00:11 +0000584 zlog_debug ("Original protocol mismatch: %s", pbuf);
hasso508e53e2004-05-18 18:57:06 +0000585 }
586 return;
587 }
588
589 if (IS_OSPF6_DEBUG_ASBR)
590 {
591 prefix2str (prefix, pbuf, sizeof (pbuf));
592 inet_ntop (AF_INET, &prefix_id.u.prefix4, ibuf, sizeof (ibuf));
hassoc6487d62004-12-24 06:00:11 +0000593 zlog_debug ("Withdraw %s (AS-External Id:%s)", pbuf, ibuf);
hasso508e53e2004-05-18 18:57:06 +0000594 }
595
596 lsa = ospf6_lsdb_lookup (htons (OSPF6_LSTYPE_AS_EXTERNAL),
597 htonl (info->id), ospf6->router_id, ospf6->lsdb);
598 if (lsa)
hasso6452df02004-08-15 05:52:07 +0000599 ospf6_lsa_purge (lsa);
hasso508e53e2004-05-18 18:57:06 +0000600
601 /* remove binding in external_id_table */
602 prefix_id.family = AF_INET;
603 prefix_id.prefixlen = 32;
604 prefix_id.u.prefix4.s_addr = htonl (info->id);
605 node = route_node_lookup (ospf6->external_id_table, &prefix_id);
606 assert (node);
607 node->info = NULL;
608 route_unlock_node (node);
609
610 ospf6_route_remove (match, ospf6->external_table);
611 XFREE (MTYPE_OSPF6_EXTERNAL_INFO, info);
612
613 /* Router-Bit (ASBR Flag) may have to be updated */
paul1eb8ef22005-04-07 07:30:20 +0000614 for (ALL_LIST_ELEMENTS (ospf6->area_list, lnode, lnnode, oa))
615 OSPF6_ROUTER_LSA_SCHEDULE (oa);
paul718e3742002-12-13 20:15:29 +0000616}
617
618DEFUN (ospf6_redistribute,
619 ospf6_redistribute_cmd,
David Lamparterdaca2cf2009-09-16 01:52:42 +0200620 "redistribute " QUAGGA_REDIST_STR_OSPF6D,
paul718e3742002-12-13 20:15:29 +0000621 "Redistribute\n"
David Lamparterdaca2cf2009-09-16 01:52:42 +0200622 QUAGGA_REDIST_HELP_STR_OSPF6D
paul718e3742002-12-13 20:15:29 +0000623 )
624{
David Lamparterdaca2cf2009-09-16 01:52:42 +0200625 int type;
paul718e3742002-12-13 20:15:29 +0000626
David Lamparterdaca2cf2009-09-16 01:52:42 +0200627 type = proto_redistnum(AFI_IP6, argv[0]);
628 if (type < 0 || type == ZEBRA_ROUTE_OSPF6)
629 return CMD_WARNING;
paul718e3742002-12-13 20:15:29 +0000630
hasso508e53e2004-05-18 18:57:06 +0000631 ospf6_asbr_redistribute_unset (type);
paul718e3742002-12-13 20:15:29 +0000632 ospf6_asbr_routemap_unset (type);
hasso508e53e2004-05-18 18:57:06 +0000633 ospf6_asbr_redistribute_set (type);
paul718e3742002-12-13 20:15:29 +0000634 return CMD_SUCCESS;
635}
636
637DEFUN (ospf6_redistribute_routemap,
638 ospf6_redistribute_routemap_cmd,
David Lamparterdaca2cf2009-09-16 01:52:42 +0200639 "redistribute " QUAGGA_REDIST_STR_OSPF6D " route-map WORD",
paul718e3742002-12-13 20:15:29 +0000640 "Redistribute\n"
David Lamparterdaca2cf2009-09-16 01:52:42 +0200641 QUAGGA_REDIST_HELP_STR_OSPF6D
paul718e3742002-12-13 20:15:29 +0000642 "Route map reference\n"
643 "Route map name\n"
644 )
645{
David Lamparterdaca2cf2009-09-16 01:52:42 +0200646 int type;
paul718e3742002-12-13 20:15:29 +0000647
David Lamparterdaca2cf2009-09-16 01:52:42 +0200648 type = proto_redistnum(AFI_IP6, argv[0]);
649 if (type < 0 || type == ZEBRA_ROUTE_OSPF6)
650 return CMD_WARNING;
paul718e3742002-12-13 20:15:29 +0000651
hasso508e53e2004-05-18 18:57:06 +0000652 ospf6_asbr_redistribute_unset (type);
paul718e3742002-12-13 20:15:29 +0000653 ospf6_asbr_routemap_set (type, argv[1]);
hasso508e53e2004-05-18 18:57:06 +0000654 ospf6_asbr_redistribute_set (type);
paul718e3742002-12-13 20:15:29 +0000655 return CMD_SUCCESS;
656}
657
658DEFUN (no_ospf6_redistribute,
659 no_ospf6_redistribute_cmd,
David Lamparterdaca2cf2009-09-16 01:52:42 +0200660 "no redistribute " QUAGGA_REDIST_STR_OSPF6D,
paul718e3742002-12-13 20:15:29 +0000661 NO_STR
662 "Redistribute\n"
David Lamparterdaca2cf2009-09-16 01:52:42 +0200663 QUAGGA_REDIST_HELP_STR_OSPF6D
paul718e3742002-12-13 20:15:29 +0000664 )
665{
David Lamparterdaca2cf2009-09-16 01:52:42 +0200666 int type;
paul718e3742002-12-13 20:15:29 +0000667
David Lamparterdaca2cf2009-09-16 01:52:42 +0200668 type = proto_redistnum(AFI_IP6, argv[0]);
669 if (type < 0 || type == ZEBRA_ROUTE_OSPF6)
670 return CMD_WARNING;
paul718e3742002-12-13 20:15:29 +0000671
hasso508e53e2004-05-18 18:57:06 +0000672 ospf6_asbr_redistribute_unset (type);
paul718e3742002-12-13 20:15:29 +0000673 ospf6_asbr_routemap_unset (type);
674
paul718e3742002-12-13 20:15:29 +0000675 return CMD_SUCCESS;
676}
677
paul718e3742002-12-13 20:15:29 +0000678int
679ospf6_redistribute_config_write (struct vty *vty)
680{
hasso508e53e2004-05-18 18:57:06 +0000681 int type;
paul718e3742002-12-13 20:15:29 +0000682
hasso508e53e2004-05-18 18:57:06 +0000683 for (type = 0; type < ZEBRA_ROUTE_MAX; type++)
paul718e3742002-12-13 20:15:29 +0000684 {
hasso508e53e2004-05-18 18:57:06 +0000685 if (type == ZEBRA_ROUTE_OSPF6)
686 continue;
687 if (! ospf6_zebra_is_redistribute (type))
paul718e3742002-12-13 20:15:29 +0000688 continue;
689
hasso508e53e2004-05-18 18:57:06 +0000690 if (ospf6->rmap[type].name)
paul718e3742002-12-13 20:15:29 +0000691 vty_out (vty, " redistribute %s route-map %s%s",
hasso049207c2004-08-04 20:02:13 +0000692 ZROUTE_NAME (type), ospf6->rmap[type].name, VNL);
paul718e3742002-12-13 20:15:29 +0000693 else
694 vty_out (vty, " redistribute %s%s",
hasso049207c2004-08-04 20:02:13 +0000695 ZROUTE_NAME (type), VNL);
paul718e3742002-12-13 20:15:29 +0000696 }
697
698 return 0;
699}
700
Paul Jakma6ac29a52008-08-15 13:45:30 +0100701static void
paul718e3742002-12-13 20:15:29 +0000702ospf6_redistribute_show_config (struct vty *vty)
703{
hasso508e53e2004-05-18 18:57:06 +0000704 int type;
705 int nroute[ZEBRA_ROUTE_MAX];
706 int total;
707 struct ospf6_route *route;
paul718e3742002-12-13 20:15:29 +0000708 struct ospf6_external_info *info;
paul718e3742002-12-13 20:15:29 +0000709
hasso508e53e2004-05-18 18:57:06 +0000710 total = 0;
711 for (type = 0; type < ZEBRA_ROUTE_MAX; type++)
712 nroute[type] = 0;
713 for (route = ospf6_route_head (ospf6->external_table); route;
714 route = ospf6_route_next (route))
paul718e3742002-12-13 20:15:29 +0000715 {
hasso508e53e2004-05-18 18:57:06 +0000716 info = route->route_option;
717 nroute[info->type]++;
718 total++;
paul718e3742002-12-13 20:15:29 +0000719 }
720
hasso049207c2004-08-04 20:02:13 +0000721 vty_out (vty, "Redistributing External Routes from:%s", VNL);
hasso508e53e2004-05-18 18:57:06 +0000722 for (type = 0; type < ZEBRA_ROUTE_MAX; type++)
paul718e3742002-12-13 20:15:29 +0000723 {
hasso508e53e2004-05-18 18:57:06 +0000724 if (type == ZEBRA_ROUTE_OSPF6)
725 continue;
726 if (! ospf6_zebra_is_redistribute (type))
hassoe26bbeb2003-05-25 21:39:29 +0000727 continue;
728
hasso508e53e2004-05-18 18:57:06 +0000729 if (ospf6->rmap[type].name)
730 vty_out (vty, " %d: %s with route-map \"%s\"%s%s", nroute[type],
731 ZROUTE_NAME (type), ospf6->rmap[type].name,
732 (ospf6->rmap[type].map ? "" : " (not found !)"),
hasso049207c2004-08-04 20:02:13 +0000733 VNL);
paul718e3742002-12-13 20:15:29 +0000734 else
hasso508e53e2004-05-18 18:57:06 +0000735 vty_out (vty, " %d: %s%s", nroute[type],
hasso049207c2004-08-04 20:02:13 +0000736 ZROUTE_NAME (type), VNL);
paul718e3742002-12-13 20:15:29 +0000737 }
hasso049207c2004-08-04 20:02:13 +0000738 vty_out (vty, "Total %d routes%s", total, VNL);
hasso508e53e2004-05-18 18:57:06 +0000739}
paul718e3742002-12-13 20:15:29 +0000740
paul718e3742002-12-13 20:15:29 +0000741
hasso508e53e2004-05-18 18:57:06 +0000742
743/* Routemap Functions */
Paul Jakma6ac29a52008-08-15 13:45:30 +0100744static route_map_result_t
hasso508e53e2004-05-18 18:57:06 +0000745ospf6_routemap_rule_match_address_prefixlist (void *rule,
746 struct prefix *prefix,
747 route_map_object_t type,
748 void *object)
749{
750 struct prefix_list *plist;
paul718e3742002-12-13 20:15:29 +0000751
hasso508e53e2004-05-18 18:57:06 +0000752 if (type != RMAP_OSPF6)
753 return RMAP_NOMATCH;
paul718e3742002-12-13 20:15:29 +0000754
hasso508e53e2004-05-18 18:57:06 +0000755 plist = prefix_list_lookup (AFI_IP6, (char *) rule);
756 if (plist == NULL)
757 return RMAP_NOMATCH;
paul718e3742002-12-13 20:15:29 +0000758
hasso508e53e2004-05-18 18:57:06 +0000759 return (prefix_list_apply (plist, prefix) == PREFIX_DENY ?
760 RMAP_NOMATCH : RMAP_MATCH);
761}
paul718e3742002-12-13 20:15:29 +0000762
Paul Jakma6ac29a52008-08-15 13:45:30 +0100763static void *
paul0c083ee2004-10-10 12:54:58 +0000764ospf6_routemap_rule_match_address_prefixlist_compile (const char *arg)
hasso508e53e2004-05-18 18:57:06 +0000765{
766 return XSTRDUP (MTYPE_ROUTE_MAP_COMPILED, arg);
paul718e3742002-12-13 20:15:29 +0000767}
768
Paul Jakma6ac29a52008-08-15 13:45:30 +0100769static void
hasso508e53e2004-05-18 18:57:06 +0000770ospf6_routemap_rule_match_address_prefixlist_free (void *rule)
paul718e3742002-12-13 20:15:29 +0000771{
hasso508e53e2004-05-18 18:57:06 +0000772 XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
773}
paul718e3742002-12-13 20:15:29 +0000774
hasso508e53e2004-05-18 18:57:06 +0000775struct route_map_rule_cmd
776ospf6_routemap_rule_match_address_prefixlist_cmd =
777{
778 "ipv6 address prefix-list",
779 ospf6_routemap_rule_match_address_prefixlist,
780 ospf6_routemap_rule_match_address_prefixlist_compile,
781 ospf6_routemap_rule_match_address_prefixlist_free,
782};
hassoe26bbeb2003-05-25 21:39:29 +0000783
Vyacheslav Trushkin1ce08782011-11-16 14:22:03 +0400784/* `match interface IFNAME' */
785/* Match function should return 1 if match is success else return
786 zero. */
787static route_map_result_t
788ospf6_routemap_rule_match_interface (void *rule, struct prefix *prefix,
789 route_map_object_t type, void *object)
790{
791 struct interface *ifp;
792 struct ospf6_external_info *ei;
793
794 if (type == RMAP_OSPF6)
795 {
796 ei = ((struct ospf6_route *) object)->route_option;
797 ifp = if_lookup_by_name ((char *)rule);
798
799 if (ifp != NULL
800 && ei->ifindex == ifp->ifindex)
801 return RMAP_MATCH;
802 }
803
804 return RMAP_NOMATCH;
805}
806
807/* Route map `interface' match statement. `arg' should be
808 interface name. */
809static void *
810ospf6_routemap_rule_match_interface_compile (const char *arg)
811{
812 return XSTRDUP (MTYPE_ROUTE_MAP_COMPILED, arg);
813}
814
815/* Free route map's compiled `interface' value. */
816static void
817ospf6_routemap_rule_match_interface_free (void *rule)
818{
819 XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
820}
821
822/* Route map commands for interface matching. */
823struct route_map_rule_cmd
824ospf6_routemap_rule_match_interface_cmd =
825{
826 "interface",
827 ospf6_routemap_rule_match_interface,
828 ospf6_routemap_rule_match_interface_compile,
829 ospf6_routemap_rule_match_interface_free
830};
831
Paul Jakma6ac29a52008-08-15 13:45:30 +0100832static route_map_result_t
hasso508e53e2004-05-18 18:57:06 +0000833ospf6_routemap_rule_set_metric_type (void *rule, struct prefix *prefix,
834 route_map_object_t type, void *object)
835{
836 char *metric_type = rule;
837 struct ospf6_route *route = object;
hassoe26bbeb2003-05-25 21:39:29 +0000838
hasso508e53e2004-05-18 18:57:06 +0000839 if (type != RMAP_OSPF6)
840 return RMAP_OKAY;
paul718e3742002-12-13 20:15:29 +0000841
hasso508e53e2004-05-18 18:57:06 +0000842 if (strcmp (metric_type, "type-2") == 0)
843 route->path.metric_type = 2;
paul718e3742002-12-13 20:15:29 +0000844 else
hasso508e53e2004-05-18 18:57:06 +0000845 route->path.metric_type = 1;
paul718e3742002-12-13 20:15:29 +0000846
hasso508e53e2004-05-18 18:57:06 +0000847 return RMAP_OKAY;
848}
paul718e3742002-12-13 20:15:29 +0000849
Paul Jakma6ac29a52008-08-15 13:45:30 +0100850static void *
paul0c083ee2004-10-10 12:54:58 +0000851ospf6_routemap_rule_set_metric_type_compile (const char *arg)
hasso508e53e2004-05-18 18:57:06 +0000852{
853 if (strcmp (arg, "type-2") && strcmp (arg, "type-1"))
854 return NULL;
855 return XSTRDUP (MTYPE_ROUTE_MAP_COMPILED, arg);
paul718e3742002-12-13 20:15:29 +0000856}
857
Paul Jakma6ac29a52008-08-15 13:45:30 +0100858static void
hasso508e53e2004-05-18 18:57:06 +0000859ospf6_routemap_rule_set_metric_type_free (void *rule)
paul718e3742002-12-13 20:15:29 +0000860{
hasso508e53e2004-05-18 18:57:06 +0000861 XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
862}
paul718e3742002-12-13 20:15:29 +0000863
hasso508e53e2004-05-18 18:57:06 +0000864struct route_map_rule_cmd
865ospf6_routemap_rule_set_metric_type_cmd =
866{
867 "metric-type",
868 ospf6_routemap_rule_set_metric_type,
869 ospf6_routemap_rule_set_metric_type_compile,
870 ospf6_routemap_rule_set_metric_type_free,
871};
paul718e3742002-12-13 20:15:29 +0000872
Paul Jakma6ac29a52008-08-15 13:45:30 +0100873static route_map_result_t
hasso508e53e2004-05-18 18:57:06 +0000874ospf6_routemap_rule_set_metric (void *rule, struct prefix *prefix,
875 route_map_object_t type, void *object)
876{
877 char *metric = rule;
878 struct ospf6_route *route = object;
paul718e3742002-12-13 20:15:29 +0000879
hasso508e53e2004-05-18 18:57:06 +0000880 if (type != RMAP_OSPF6)
881 return RMAP_OKAY;
paul718e3742002-12-13 20:15:29 +0000882
hasso508e53e2004-05-18 18:57:06 +0000883 route->path.cost = atoi (metric);
884 return RMAP_OKAY;
885}
paul718e3742002-12-13 20:15:29 +0000886
Paul Jakma6ac29a52008-08-15 13:45:30 +0100887static void *
paul0c083ee2004-10-10 12:54:58 +0000888ospf6_routemap_rule_set_metric_compile (const char *arg)
hasso508e53e2004-05-18 18:57:06 +0000889{
890 u_int32_t metric;
891 char *endp;
892 metric = strtoul (arg, &endp, 0);
893 if (metric > LS_INFINITY || *endp != '\0')
894 return NULL;
895 return XSTRDUP (MTYPE_ROUTE_MAP_COMPILED, arg);
paul718e3742002-12-13 20:15:29 +0000896}
897
Paul Jakma6ac29a52008-08-15 13:45:30 +0100898static void
hasso508e53e2004-05-18 18:57:06 +0000899ospf6_routemap_rule_set_metric_free (void *rule)
paul718e3742002-12-13 20:15:29 +0000900{
hasso508e53e2004-05-18 18:57:06 +0000901 XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
902}
903
904struct route_map_rule_cmd
905ospf6_routemap_rule_set_metric_cmd =
906{
907 "metric",
908 ospf6_routemap_rule_set_metric,
909 ospf6_routemap_rule_set_metric_compile,
910 ospf6_routemap_rule_set_metric_free,
911};
912
Paul Jakma6ac29a52008-08-15 13:45:30 +0100913static route_map_result_t
hasso508e53e2004-05-18 18:57:06 +0000914ospf6_routemap_rule_set_forwarding (void *rule, struct prefix *prefix,
915 route_map_object_t type, void *object)
916{
917 char *forwarding = rule;
918 struct ospf6_route *route = object;
919 struct ospf6_external_info *info = route->route_option;
920
921 if (type != RMAP_OSPF6)
922 return RMAP_OKAY;
923
924 if (inet_pton (AF_INET6, forwarding, &info->forwarding) != 1)
925 {
926 memset (&info->forwarding, 0, sizeof (struct in6_addr));
927 return RMAP_ERROR;
928 }
929
930 return RMAP_OKAY;
931}
932
Paul Jakma6ac29a52008-08-15 13:45:30 +0100933static void *
paul0c083ee2004-10-10 12:54:58 +0000934ospf6_routemap_rule_set_forwarding_compile (const char *arg)
hasso508e53e2004-05-18 18:57:06 +0000935{
936 struct in6_addr a;
937 if (inet_pton (AF_INET6, arg, &a) != 1)
938 return NULL;
939 return XSTRDUP (MTYPE_ROUTE_MAP_COMPILED, arg);
940}
941
Paul Jakma6ac29a52008-08-15 13:45:30 +0100942static void
hasso508e53e2004-05-18 18:57:06 +0000943ospf6_routemap_rule_set_forwarding_free (void *rule)
944{
945 XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
946}
947
948struct route_map_rule_cmd
949ospf6_routemap_rule_set_forwarding_cmd =
950{
951 "forwarding-address",
952 ospf6_routemap_rule_set_forwarding,
953 ospf6_routemap_rule_set_forwarding_compile,
954 ospf6_routemap_rule_set_forwarding_free,
955};
956
Paul Jakma6ac29a52008-08-15 13:45:30 +0100957static int
hasso508e53e2004-05-18 18:57:06 +0000958route_map_command_status (struct vty *vty, int ret)
959{
960 if (! ret)
961 return CMD_SUCCESS;
962
963 switch (ret)
964 {
965 case RMAP_RULE_MISSING:
hasso049207c2004-08-04 20:02:13 +0000966 vty_out (vty, "Can't find rule.%s", VNL);
hasso508e53e2004-05-18 18:57:06 +0000967 break;
968 case RMAP_COMPILE_ERROR:
hasso049207c2004-08-04 20:02:13 +0000969 vty_out (vty, "Argument is malformed.%s", VNL);
hasso508e53e2004-05-18 18:57:06 +0000970 break;
971 default:
hasso049207c2004-08-04 20:02:13 +0000972 vty_out (vty, "route-map add set failed.%s", VNL);
hasso508e53e2004-05-18 18:57:06 +0000973 break;
974 }
975 return CMD_WARNING;
976}
977
978/* add "match address" */
979DEFUN (ospf6_routemap_match_address_prefixlist,
980 ospf6_routemap_match_address_prefixlist_cmd,
981 "match ipv6 address prefix-list WORD",
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_add_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/* delete "match address" */
994DEFUN (ospf6_routemap_no_match_address_prefixlist,
995 ospf6_routemap_no_match_address_prefixlist_cmd,
996 "no match ipv6 address prefix-list WORD",
997 NO_STR
998 "Match values\n"
999 IPV6_STR
1000 "Match address of route\n"
1001 "Match entries of prefix-lists\n"
1002 "IPv6 prefix-list name\n")
1003{
1004 int ret = route_map_delete_match ((struct route_map_index *) vty->index,
1005 "ipv6 address prefix-list", argv[0]);
1006 return route_map_command_status (vty, ret);
1007}
1008
Vyacheslav Trushkin1ce08782011-11-16 14:22:03 +04001009/* "match interface" */
1010DEFUN (ospf6_routemap_match_interface,
1011 ospf6_routemap_match_interface_cmd,
1012 "match interface WORD",
1013 MATCH_STR
1014 "Match first hop interface of route\n"
1015 "Interface name\n")
1016{
1017 return route_map_add_match ((struct route_map_index *) vty->index,
1018 "interface", argv[0]);
1019}
1020
1021/* "no match interface WORD" */
1022DEFUN (ospf6_routemap_no_match_interface,
1023 ospf6_routemap_no_match_interface_cmd,
1024 "no match interface",
1025 MATCH_STR
1026 NO_STR
1027 "Match first hop interface of route\n")
1028{
1029 int ret = route_map_delete_match ((struct route_map_index *) vty->index,
1030 "interface", (argc == 0) ? NULL : argv[0]);
1031 return route_map_command_status (vty, ret);
1032}
1033
1034ALIAS (ospf6_routemap_no_match_interface,
1035 ospf6_routemap_no_match_interface_val_cmd,
1036 "no match interface WORD",
1037 MATCH_STR
1038 NO_STR
1039 "Match first hop interface of route\n"
1040 "Interface name\n")
1041
hasso508e53e2004-05-18 18:57:06 +00001042/* add "set metric-type" */
1043DEFUN (ospf6_routemap_set_metric_type,
1044 ospf6_routemap_set_metric_type_cmd,
1045 "set metric-type (type-1|type-2)",
1046 "Set value\n"
1047 "Type of metric\n"
1048 "OSPF6 external type 1 metric\n"
1049 "OSPF6 external type 2 metric\n")
1050{
1051 int ret = route_map_add_set ((struct route_map_index *) vty->index,
1052 "metric-type", argv[0]);
1053 return route_map_command_status (vty, ret);
1054}
1055
1056/* delete "set metric-type" */
1057DEFUN (ospf6_routemap_no_set_metric_type,
1058 ospf6_routemap_no_set_metric_type_cmd,
1059 "no set metric-type (type-1|type-2)",
1060 NO_STR
1061 "Set value\n"
1062 "Type of metric\n"
1063 "OSPF6 external type 1 metric\n"
1064 "OSPF6 external type 2 metric\n")
1065{
1066 int ret = route_map_delete_set ((struct route_map_index *) vty->index,
1067 "metric-type", argv[0]);
1068 return route_map_command_status (vty, ret);
1069}
1070
1071/* add "set metric" */
1072DEFUN (set_metric,
1073 set_metric_cmd,
1074 "set metric <0-4294967295>",
1075 "Set value\n"
1076 "Metric value\n"
1077 "Metric value\n")
1078{
1079 int ret = route_map_add_set ((struct route_map_index *) vty->index,
1080 "metric", argv[0]);
1081 return route_map_command_status (vty, ret);
1082}
1083
1084/* delete "set metric" */
1085DEFUN (no_set_metric,
1086 no_set_metric_cmd,
1087 "no set metric <0-4294967295>",
1088 NO_STR
1089 "Set value\n"
1090 "Metric\n"
1091 "METRIC value\n")
1092{
1093 int ret = route_map_delete_set ((struct route_map_index *) vty->index,
1094 "metric", argv[0]);
1095 return route_map_command_status (vty, ret);
1096}
1097
1098/* add "set forwarding-address" */
1099DEFUN (ospf6_routemap_set_forwarding,
1100 ospf6_routemap_set_forwarding_cmd,
1101 "set forwarding-address X:X::X:X",
1102 "Set value\n"
1103 "Forwarding Address\n"
1104 "IPv6 Address\n")
1105{
1106 int ret = route_map_add_set ((struct route_map_index *) vty->index,
1107 "forwarding-address", argv[0]);
1108 return route_map_command_status (vty, ret);
1109}
1110
1111/* delete "set forwarding-address" */
1112DEFUN (ospf6_routemap_no_set_forwarding,
1113 ospf6_routemap_no_set_forwarding_cmd,
1114 "no set forwarding-address X:X::X:X",
1115 NO_STR
1116 "Set value\n"
1117 "Forwarding Address\n"
1118 "IPv6 Address\n")
1119{
1120 int ret = route_map_delete_set ((struct route_map_index *) vty->index,
1121 "forwarding-address", argv[0]);
1122 return route_map_command_status (vty, ret);
1123}
1124
Paul Jakma6ac29a52008-08-15 13:45:30 +01001125static void
1126ospf6_routemap_init (void)
hasso508e53e2004-05-18 18:57:06 +00001127{
1128 route_map_init ();
1129 route_map_init_vty ();
1130 route_map_add_hook (ospf6_asbr_routemap_update);
1131 route_map_delete_hook (ospf6_asbr_routemap_update);
1132
1133 route_map_install_match (&ospf6_routemap_rule_match_address_prefixlist_cmd);
Vyacheslav Trushkin1ce08782011-11-16 14:22:03 +04001134 route_map_install_match (&ospf6_routemap_rule_match_interface_cmd);
1135
hasso508e53e2004-05-18 18:57:06 +00001136 route_map_install_set (&ospf6_routemap_rule_set_metric_type_cmd);
1137 route_map_install_set (&ospf6_routemap_rule_set_metric_cmd);
1138 route_map_install_set (&ospf6_routemap_rule_set_forwarding_cmd);
1139
1140 /* Match address prefix-list */
1141 install_element (RMAP_NODE, &ospf6_routemap_match_address_prefixlist_cmd);
1142 install_element (RMAP_NODE, &ospf6_routemap_no_match_address_prefixlist_cmd);
1143
Vyacheslav Trushkin1ce08782011-11-16 14:22:03 +04001144 /* Match interface */
1145 install_element (RMAP_NODE, &ospf6_routemap_match_interface_cmd);
1146 install_element (RMAP_NODE, &ospf6_routemap_no_match_interface_cmd);
1147 install_element (RMAP_NODE, &ospf6_routemap_no_match_interface_val_cmd);
1148
hasso508e53e2004-05-18 18:57:06 +00001149 /* ASE Metric Type (e.g. Type-1/Type-2) */
1150 install_element (RMAP_NODE, &ospf6_routemap_set_metric_type_cmd);
1151 install_element (RMAP_NODE, &ospf6_routemap_no_set_metric_type_cmd);
1152
1153 /* ASE Metric */
1154 install_element (RMAP_NODE, &set_metric_cmd);
1155 install_element (RMAP_NODE, &no_set_metric_cmd);
1156
1157 /* ASE Metric */
1158 install_element (RMAP_NODE, &ospf6_routemap_set_forwarding_cmd);
1159 install_element (RMAP_NODE, &ospf6_routemap_no_set_forwarding_cmd);
1160}
1161
1162
1163/* Display functions */
Paul Jakma6ac29a52008-08-15 13:45:30 +01001164static int
hasso508e53e2004-05-18 18:57:06 +00001165ospf6_as_external_lsa_show (struct vty *vty, struct ospf6_lsa *lsa)
1166{
1167 struct ospf6_as_external_lsa *external;
paul718e3742002-12-13 20:15:29 +00001168 char buf[64];
hasso508e53e2004-05-18 18:57:06 +00001169 struct in6_addr in6, *forwarding;
paul718e3742002-12-13 20:15:29 +00001170
1171 assert (lsa->header);
hasso508e53e2004-05-18 18:57:06 +00001172 external = (struct ospf6_as_external_lsa *)
1173 OSPF6_LSA_HEADER_END (lsa->header);
paul718e3742002-12-13 20:15:29 +00001174
1175 /* bits */
hasso508e53e2004-05-18 18:57:06 +00001176 snprintf (buf, sizeof (buf), "%c%c%c",
1177 (CHECK_FLAG (external->bits_metric, OSPF6_ASBR_BIT_E) ? 'E' : '-'),
1178 (CHECK_FLAG (external->bits_metric, OSPF6_ASBR_BIT_F) ? 'F' : '-'),
1179 (CHECK_FLAG (external->bits_metric, OSPF6_ASBR_BIT_T) ? 'T' : '-'));
paul718e3742002-12-13 20:15:29 +00001180
hasso049207c2004-08-04 20:02:13 +00001181 vty_out (vty, " Bits: %s%s", buf, VNL);
hasso508e53e2004-05-18 18:57:06 +00001182 vty_out (vty, " Metric: %5lu%s", (u_long) OSPF6_ASBR_METRIC (external),
hasso049207c2004-08-04 20:02:13 +00001183 VNL);
paul718e3742002-12-13 20:15:29 +00001184
hasso508e53e2004-05-18 18:57:06 +00001185 ospf6_prefix_options_printbuf (external->prefix.prefix_options,
1186 buf, sizeof (buf));
1187 vty_out (vty, " Prefix Options: %s%s", buf,
hasso049207c2004-08-04 20:02:13 +00001188 VNL);
paul718e3742002-12-13 20:15:29 +00001189
1190 vty_out (vty, " Referenced LSType: %d%s",
hasso508e53e2004-05-18 18:57:06 +00001191 ntohs (external->prefix.prefix_refer_lstype),
hasso049207c2004-08-04 20:02:13 +00001192 VNL);
paul718e3742002-12-13 20:15:29 +00001193
hasso508e53e2004-05-18 18:57:06 +00001194 ospf6_prefix_in6_addr (&in6, &external->prefix);
paul718e3742002-12-13 20:15:29 +00001195 inet_ntop (AF_INET6, &in6, buf, sizeof (buf));
hasso508e53e2004-05-18 18:57:06 +00001196 vty_out (vty, " Prefix: %s/%d%s", buf,
hasso049207c2004-08-04 20:02:13 +00001197 external->prefix.prefix_length, VNL);
paul718e3742002-12-13 20:15:29 +00001198
1199 /* Forwarding-Address */
1200 if (CHECK_FLAG (external->bits_metric, OSPF6_ASBR_BIT_F))
1201 {
hasso508e53e2004-05-18 18:57:06 +00001202 forwarding = (struct in6_addr *)
1203 ((caddr_t) external + sizeof (struct ospf6_as_external_lsa) +
1204 OSPF6_PREFIX_SPACE (external->prefix.prefix_length));
1205 inet_ntop (AF_INET6, forwarding, buf, sizeof (buf));
hasso049207c2004-08-04 20:02:13 +00001206 vty_out (vty, " Forwarding-Address: %s%s", buf, VNL);
paul718e3742002-12-13 20:15:29 +00001207 }
1208
1209 return 0;
1210}
1211
Paul Jakma6ac29a52008-08-15 13:45:30 +01001212static void
hasso508e53e2004-05-18 18:57:06 +00001213ospf6_asbr_external_route_show (struct vty *vty, struct ospf6_route *route)
paul718e3742002-12-13 20:15:29 +00001214{
hasso508e53e2004-05-18 18:57:06 +00001215 struct ospf6_external_info *info = route->route_option;
1216 char prefix[64], id[16], forwarding[64];
1217 u_int32_t tmp_id;
1218
1219 prefix2str (&route->prefix, prefix, sizeof (prefix));
1220 tmp_id = ntohl (info->id);
1221 inet_ntop (AF_INET, &tmp_id, id, sizeof (id));
1222 if (! IN6_IS_ADDR_UNSPECIFIED (&info->forwarding))
1223 inet_ntop (AF_INET6, &info->forwarding, forwarding, sizeof (forwarding));
1224 else
1225 snprintf (forwarding, sizeof (forwarding), ":: (ifindex %d)",
1226 route->nexthop[0].ifindex);
1227
ajsf52d13c2005-10-01 17:38:06 +00001228 vty_out (vty, "%c %-32s %-15s type-%d %5lu %s%s",
1229 zebra_route_char(info->type),
hasso508e53e2004-05-18 18:57:06 +00001230 prefix, id, route->path.metric_type,
1231 (u_long) (route->path.metric_type == 2 ?
1232 route->path.cost_e2 : route->path.cost),
hasso049207c2004-08-04 20:02:13 +00001233 forwarding, VNL);
paul718e3742002-12-13 20:15:29 +00001234}
1235
hasso508e53e2004-05-18 18:57:06 +00001236DEFUN (show_ipv6_ospf6_redistribute,
1237 show_ipv6_ospf6_redistribute_cmd,
1238 "show ipv6 ospf6 redistribute",
paul718e3742002-12-13 20:15:29 +00001239 SHOW_STR
1240 IP6_STR
paul718e3742002-12-13 20:15:29 +00001241 OSPF6_STR
1242 "redistributing External information\n"
1243 )
1244{
hasso508e53e2004-05-18 18:57:06 +00001245 struct ospf6_route *route;
paul718e3742002-12-13 20:15:29 +00001246
hasso508e53e2004-05-18 18:57:06 +00001247 ospf6_redistribute_show_config (vty);
1248
1249 for (route = ospf6_route_head (ospf6->external_table); route;
1250 route = ospf6_route_next (route))
1251 ospf6_asbr_external_route_show (vty, route);
1252
paul718e3742002-12-13 20:15:29 +00001253 return CMD_SUCCESS;
1254}
1255
hasso6452df02004-08-15 05:52:07 +00001256struct ospf6_lsa_handler as_external_handler =
hasso508e53e2004-05-18 18:57:06 +00001257{
hasso6452df02004-08-15 05:52:07 +00001258 OSPF6_LSTYPE_AS_EXTERNAL,
1259 "AS-External",
1260 ospf6_as_external_lsa_show
1261};
hasso508e53e2004-05-18 18:57:06 +00001262
paul718e3742002-12-13 20:15:29 +00001263void
Paul Jakma6ac29a52008-08-15 13:45:30 +01001264ospf6_asbr_init (void)
paul718e3742002-12-13 20:15:29 +00001265{
hasso508e53e2004-05-18 18:57:06 +00001266 ospf6_routemap_init ();
paul718e3742002-12-13 20:15:29 +00001267
hasso6452df02004-08-15 05:52:07 +00001268 ospf6_install_lsa_handler (&as_external_handler);
paul718e3742002-12-13 20:15:29 +00001269
hasso508e53e2004-05-18 18:57:06 +00001270 install_element (VIEW_NODE, &show_ipv6_ospf6_redistribute_cmd);
1271 install_element (ENABLE_NODE, &show_ipv6_ospf6_redistribute_cmd);
1272
paul718e3742002-12-13 20:15:29 +00001273 install_element (OSPF6_NODE, &ospf6_redistribute_cmd);
1274 install_element (OSPF6_NODE, &ospf6_redistribute_routemap_cmd);
1275 install_element (OSPF6_NODE, &no_ospf6_redistribute_cmd);
1276}
1277
1278
hasso508e53e2004-05-18 18:57:06 +00001279DEFUN (debug_ospf6_asbr,
1280 debug_ospf6_asbr_cmd,
1281 "debug ospf6 asbr",
1282 DEBUG_STR
1283 OSPF6_STR
1284 "Debug OSPFv3 ASBR function\n"
1285 )
1286{
1287 OSPF6_DEBUG_ASBR_ON ();
1288 return CMD_SUCCESS;
1289}
1290
1291DEFUN (no_debug_ospf6_asbr,
1292 no_debug_ospf6_asbr_cmd,
1293 "no debug ospf6 asbr",
1294 NO_STR
1295 DEBUG_STR
1296 OSPF6_STR
1297 "Debug OSPFv3 ASBR function\n"
1298 )
1299{
1300 OSPF6_DEBUG_ASBR_OFF ();
1301 return CMD_SUCCESS;
1302}
1303
1304int
1305config_write_ospf6_debug_asbr (struct vty *vty)
1306{
1307 if (IS_OSPF6_DEBUG_ASBR)
hasso049207c2004-08-04 20:02:13 +00001308 vty_out (vty, "debug ospf6 asbr%s", VNL);
hasso508e53e2004-05-18 18:57:06 +00001309 return 0;
1310}
1311
1312void
1313install_element_ospf6_debug_asbr ()
1314{
1315 install_element (ENABLE_NODE, &debug_ospf6_asbr_cmd);
1316 install_element (ENABLE_NODE, &no_debug_ospf6_asbr_cmd);
1317 install_element (CONFIG_NODE, &debug_ospf6_asbr_cmd);
1318 install_element (CONFIG_NODE, &no_debug_ospf6_asbr_cmd);
1319}
1320
1321