blob: c414970b8a102a804c40e8b2c71cc1911fcd473d [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
Dinesh Dutt8551e6d2013-10-22 17:42:18 -0700177 if (OSPF6_ASBR_METRIC (external) == OSPF_LS_INFINITY)
hasso508e53e2004-05-18 18:57:06 +0000178 {
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
Dinesh Dutt01879112013-08-25 03:03:31 +0000184 if (CHECK_FLAG(external->prefix.prefix_options, OSPF6_PREFIX_OPTION_NU))
185 {
186 if (IS_OSPF6_DEBUG_EXAMIN (AS_EXTERNAL))
187 zlog_debug ("Ignore LSA with NU bit set Metric");
188 return;
189 }
190
hassoccb59b12004-08-25 09:10:37 +0000191 ospf6_linkstate_prefix (lsa->header->adv_router, htonl (0), &asbr_id);
hasso6452df02004-08-15 05:52:07 +0000192 asbr_entry = ospf6_route_lookup (&asbr_id, ospf6->brouter_table);
hasso63069ad2004-09-02 13:01:01 +0000193 if (asbr_entry == NULL ||
194 ! CHECK_FLAG (asbr_entry->path.router_bits, OSPF6_ROUTER_BIT_E))
hasso508e53e2004-05-18 18:57:06 +0000195 {
hasso1e058382004-09-01 21:36:14 +0000196 if (IS_OSPF6_DEBUG_EXAMIN (AS_EXTERNAL))
hasso508e53e2004-05-18 18:57:06 +0000197 {
198 prefix2str (&asbr_id, buf, sizeof (buf));
hassoc6487d62004-12-24 06:00:11 +0000199 zlog_debug ("ASBR entry not found: %s", buf);
hasso508e53e2004-05-18 18:57:06 +0000200 }
201 return;
202 }
203
204 route = ospf6_route_create ();
205 route->type = OSPF6_DEST_TYPE_NETWORK;
206 route->prefix.family = AF_INET6;
207 route->prefix.prefixlen = external->prefix.prefix_length;
208 ospf6_prefix_in6_addr (&route->prefix.u.prefix6, &external->prefix);
209
210 route->path.area_id = asbr_entry->path.area_id;
211 route->path.origin.type = lsa->header->type;
212 route->path.origin.id = lsa->header->id;
213 route->path.origin.adv_router = lsa->header->adv_router;
214
215 route->path.prefix_options = external->prefix.prefix_options;
216 if (CHECK_FLAG (external->bits_metric, OSPF6_ASBR_BIT_E))
217 {
218 route->path.type = OSPF6_PATH_TYPE_EXTERNAL2;
219 route->path.metric_type = 2;
220 route->path.cost = asbr_entry->path.cost;
221 route->path.cost_e2 = OSPF6_ASBR_METRIC (external);
222 }
223 else
224 {
225 route->path.type = OSPF6_PATH_TYPE_EXTERNAL1;
226 route->path.metric_type = 1;
227 route->path.cost = asbr_entry->path.cost + OSPF6_ASBR_METRIC (external);
228 route->path.cost_e2 = 0;
229 }
230
231 for (i = 0; i < OSPF6_MULTI_PATH_LIMIT; i++)
232 ospf6_nexthop_copy (&route->nexthop[i], &asbr_entry->nexthop[i]);
233
hasso1e058382004-09-01 21:36:14 +0000234 if (IS_OSPF6_DEBUG_EXAMIN (AS_EXTERNAL))
hasso508e53e2004-05-18 18:57:06 +0000235 {
236 prefix2str (&route->prefix, buf, sizeof (buf));
hassoc6487d62004-12-24 06:00:11 +0000237 zlog_debug ("AS-External route add: %s", buf);
hasso508e53e2004-05-18 18:57:06 +0000238 }
239
240 ospf6_route_add (route, ospf6->route_table);
241}
242
243void
244ospf6_asbr_lsa_remove (struct ospf6_lsa *lsa)
245{
246 struct ospf6_as_external_lsa *external;
247 struct prefix prefix;
248 struct ospf6_route *route;
249 char buf[64];
250
251 external = (struct ospf6_as_external_lsa *)
252 OSPF6_LSA_HEADER_END (lsa->header);
253
hasso1e058382004-09-01 21:36:14 +0000254 if (IS_OSPF6_DEBUG_EXAMIN (AS_EXTERNAL))
hassoc6487d62004-12-24 06:00:11 +0000255 zlog_debug ("Withdraw AS-External route for %s", lsa->name);
hasso508e53e2004-05-18 18:57:06 +0000256
257 if (lsa->header->adv_router == ospf6->router_id)
258 {
hasso1e058382004-09-01 21:36:14 +0000259 if (IS_OSPF6_DEBUG_EXAMIN (AS_EXTERNAL))
hassoc6487d62004-12-24 06:00:11 +0000260 zlog_debug ("Ignore self-originated AS-External-LSA");
hasso508e53e2004-05-18 18:57:06 +0000261 return;
262 }
263
264 memset (&prefix, 0, sizeof (struct prefix));
265 prefix.family = AF_INET6;
266 prefix.prefixlen = external->prefix.prefix_length;
267 ospf6_prefix_in6_addr (&prefix.u.prefix6, &external->prefix);
268
269 route = ospf6_route_lookup (&prefix, ospf6->route_table);
270 if (route == NULL)
271 {
hasso1e058382004-09-01 21:36:14 +0000272 if (IS_OSPF6_DEBUG_EXAMIN (AS_EXTERNAL))
hasso508e53e2004-05-18 18:57:06 +0000273 {
274 prefix2str (&prefix, buf, sizeof (buf));
hassoc6487d62004-12-24 06:00:11 +0000275 zlog_debug ("AS-External route %s not found", buf);
hasso508e53e2004-05-18 18:57:06 +0000276 }
277 return;
278 }
279
280 for (ospf6_route_lock (route);
281 route && ospf6_route_is_prefix (&prefix, route);
282 route = ospf6_route_next (route))
283 {
284 if (route->type != OSPF6_DEST_TYPE_NETWORK)
285 continue;
286 if (route->path.origin.type != lsa->header->type)
287 continue;
288 if (route->path.origin.id != lsa->header->id)
289 continue;
290 if (route->path.origin.adv_router != lsa->header->adv_router)
291 continue;
292
hasso1e058382004-09-01 21:36:14 +0000293 if (IS_OSPF6_DEBUG_EXAMIN (AS_EXTERNAL))
hasso508e53e2004-05-18 18:57:06 +0000294 {
295 prefix2str (&route->prefix, buf, sizeof (buf));
hassoc6487d62004-12-24 06:00:11 +0000296 zlog_debug ("AS-External route remove: %s", buf);
hasso508e53e2004-05-18 18:57:06 +0000297 }
298 ospf6_route_remove (route, ospf6->route_table);
299 }
Christian Frankec78a46c2013-03-20 10:50:09 +0000300 if (route != NULL)
301 ospf6_route_unlock (route);
hasso508e53e2004-05-18 18:57:06 +0000302}
303
304void
305ospf6_asbr_lsentry_add (struct ospf6_route *asbr_entry)
306{
hasso508e53e2004-05-18 18:57:06 +0000307 struct ospf6_lsa *lsa;
308 u_int16_t type;
309 u_int32_t router;
310
Paul Jakmacb4b8842006-05-15 10:39:30 +0000311 if (! CHECK_FLAG (asbr_entry->flag, OSPF6_ROUTE_BEST))
hasso508e53e2004-05-18 18:57:06 +0000312 {
Paul Jakmacb4b8842006-05-15 10:39:30 +0000313 char buf[16];
314 inet_ntop (AF_INET, &ADV_ROUTER_IN_PREFIX (&asbr_entry->prefix),
315 buf, sizeof (buf));
316 zlog_info ("ignore non-best path: lsentry %s add", buf);
317 return;
hasso508e53e2004-05-18 18:57:06 +0000318 }
319
320 type = htons (OSPF6_LSTYPE_AS_EXTERNAL);
321 router = ospf6_linkstate_prefix_adv_router (&asbr_entry->prefix);
Paul Jakmacb4b8842006-05-15 10:39:30 +0000322 for (lsa = ospf6_lsdb_type_router_head (type, router, ospf6->lsdb); lsa;
323 lsa = ospf6_lsdb_type_router_next (type, router, lsa))
hasso508e53e2004-05-18 18:57:06 +0000324 {
325 if (! OSPF6_LSA_IS_MAXAGE (lsa))
326 ospf6_asbr_lsa_add (lsa);
327 }
hasso508e53e2004-05-18 18:57:06 +0000328}
329
330void
331ospf6_asbr_lsentry_remove (struct ospf6_route *asbr_entry)
332{
hasso508e53e2004-05-18 18:57:06 +0000333 struct ospf6_lsa *lsa;
334 u_int16_t type;
335 u_int32_t router;
336
hasso508e53e2004-05-18 18:57:06 +0000337 type = htons (OSPF6_LSTYPE_AS_EXTERNAL);
338 router = ospf6_linkstate_prefix_adv_router (&asbr_entry->prefix);
339 for (lsa = ospf6_lsdb_type_router_head (type, router, ospf6->lsdb);
340 lsa; lsa = ospf6_lsdb_type_router_next (type, router, lsa))
341 ospf6_asbr_lsa_remove (lsa);
hasso508e53e2004-05-18 18:57:06 +0000342}
343
344
345
paul718e3742002-12-13 20:15:29 +0000346/* redistribute function */
hasso508e53e2004-05-18 18:57:06 +0000347
Paul Jakma6ac29a52008-08-15 13:45:30 +0100348static void
paul0c083ee2004-10-10 12:54:58 +0000349ospf6_asbr_routemap_set (int type, const char *mapname)
paul718e3742002-12-13 20:15:29 +0000350{
hasso508e53e2004-05-18 18:57:06 +0000351 if (ospf6->rmap[type].name)
352 free (ospf6->rmap[type].name);
353 ospf6->rmap[type].name = strdup (mapname);
354 ospf6->rmap[type].map = route_map_lookup_by_name (mapname);
paul718e3742002-12-13 20:15:29 +0000355}
356
Paul Jakma6ac29a52008-08-15 13:45:30 +0100357static void
paul718e3742002-12-13 20:15:29 +0000358ospf6_asbr_routemap_unset (int type)
359{
hasso508e53e2004-05-18 18:57:06 +0000360 if (ospf6->rmap[type].name)
361 free (ospf6->rmap[type].name);
362 ospf6->rmap[type].name = NULL;
363 ospf6->rmap[type].map = NULL;
paul718e3742002-12-13 20:15:29 +0000364}
365
Paul Jakma6ac29a52008-08-15 13:45:30 +0100366static void
paul0c083ee2004-10-10 12:54:58 +0000367ospf6_asbr_routemap_update (const char *mapname)
paul718e3742002-12-13 20:15:29 +0000368{
hasso508e53e2004-05-18 18:57:06 +0000369 int type;
370
371 if (ospf6 == NULL)
372 return;
373
374 for (type = 0; type < ZEBRA_ROUTE_MAX; type++)
paul718e3742002-12-13 20:15:29 +0000375 {
hasso508e53e2004-05-18 18:57:06 +0000376 if (ospf6->rmap[type].name)
377 ospf6->rmap[type].map =
378 route_map_lookup_by_name (ospf6->rmap[type].name);
paul718e3742002-12-13 20:15:29 +0000379 else
hasso508e53e2004-05-18 18:57:06 +0000380 ospf6->rmap[type].map = NULL;
381 }
382}
383
384int
385ospf6_asbr_is_asbr (struct ospf6 *o)
386{
387 return o->external_table->count;
388}
389
Paul Jakma6ac29a52008-08-15 13:45:30 +0100390static void
hasso508e53e2004-05-18 18:57:06 +0000391ospf6_asbr_redistribute_set (int type)
392{
393 ospf6_zebra_redistribute (type);
394}
395
Paul Jakma6ac29a52008-08-15 13:45:30 +0100396static void
hasso508e53e2004-05-18 18:57:06 +0000397ospf6_asbr_redistribute_unset (int type)
398{
399 struct ospf6_route *route;
400 struct ospf6_external_info *info;
401
402 ospf6_zebra_no_redistribute (type);
403
404 for (route = ospf6_route_head (ospf6->external_table); route;
405 route = ospf6_route_next (route))
406 {
407 info = route->route_option;
408 if (info->type != type)
409 continue;
410
411 ospf6_asbr_redistribute_remove (info->type, route->nexthop[0].ifindex,
412 &route->prefix);
413 }
Christian Franked9628722013-03-08 21:47:35 +0100414
415 ospf6_asbr_routemap_unset (type);
hasso508e53e2004-05-18 18:57:06 +0000416}
417
418void
419ospf6_asbr_redistribute_add (int type, int ifindex, struct prefix *prefix,
420 u_int nexthop_num, struct in6_addr *nexthop)
421{
422 int ret;
423 struct ospf6_route troute;
424 struct ospf6_external_info tinfo;
425 struct ospf6_route *route, *match;
426 struct ospf6_external_info *info;
427 struct prefix prefix_id;
428 struct route_node *node;
429 char pbuf[64], ibuf[16];
paul1eb8ef22005-04-07 07:30:20 +0000430 struct listnode *lnode, *lnnode;
hasso508e53e2004-05-18 18:57:06 +0000431 struct ospf6_area *oa;
432
433 if (! ospf6_zebra_is_redistribute (type))
434 return;
435
436 if (IS_OSPF6_DEBUG_ASBR)
437 {
438 prefix2str (prefix, pbuf, sizeof (pbuf));
hassoc6487d62004-12-24 06:00:11 +0000439 zlog_debug ("Redistribute %s (%s)", pbuf, ZROUTE_NAME (type));
hasso508e53e2004-05-18 18:57:06 +0000440 }
441
442 /* if route-map was specified but not found, do not advertise */
443 if (ospf6->rmap[type].name)
444 {
445 if (ospf6->rmap[type].map == NULL)
hasso03d52f82004-09-29 00:26:19 +0000446 ospf6_asbr_routemap_update (NULL);
hasso508e53e2004-05-18 18:57:06 +0000447 if (ospf6->rmap[type].map == NULL)
448 {
449 zlog_warn ("route-map \"%s\" not found, suppress redistributing",
450 ospf6->rmap[type].name);
451 return;
452 }
453 }
454
455 /* apply route-map */
456 if (ospf6->rmap[type].map)
457 {
458 memset (&troute, 0, sizeof (troute));
459 memset (&tinfo, 0, sizeof (tinfo));
460 troute.route_option = &tinfo;
Vyacheslav Trushkin42a7deb2011-11-16 14:22:03 +0400461 tinfo.ifindex = ifindex;
hasso508e53e2004-05-18 18:57:06 +0000462
463 ret = route_map_apply (ospf6->rmap[type].map, prefix,
464 RMAP_OSPF6, &troute);
paul47828742005-08-10 15:46:11 +0000465 if (ret == RMAP_DENYMATCH)
hasso508e53e2004-05-18 18:57:06 +0000466 {
467 if (IS_OSPF6_DEBUG_ASBR)
hassoc6487d62004-12-24 06:00:11 +0000468 zlog_debug ("Denied by route-map \"%s\"", ospf6->rmap[type].name);
hasso508e53e2004-05-18 18:57:06 +0000469 return;
470 }
471 }
472
473 match = ospf6_route_lookup (prefix, ospf6->external_table);
474 if (match)
475 {
476 info = match->route_option;
477
478 /* copy result of route-map */
479 if (ospf6->rmap[type].map)
480 {
481 if (troute.path.metric_type)
482 match->path.metric_type = troute.path.metric_type;
483 if (troute.path.cost)
484 match->path.cost = troute.path.cost;
485 if (! IN6_IS_ADDR_UNSPECIFIED (&tinfo.forwarding))
486 memcpy (&info->forwarding, &tinfo.forwarding,
487 sizeof (struct in6_addr));
488 }
489
490 info->type = type;
491 match->nexthop[0].ifindex = ifindex;
492 if (nexthop_num && nexthop)
493 memcpy (&match->nexthop[0].address, nexthop, sizeof (struct in6_addr));
494
495 /* create/update binding in external_id_table */
496 prefix_id.family = AF_INET;
497 prefix_id.prefixlen = 32;
498 prefix_id.u.prefix4.s_addr = htonl (info->id);
499 node = route_node_get (ospf6->external_id_table, &prefix_id);
500 node->info = match;
501
502 if (IS_OSPF6_DEBUG_ASBR)
503 {
504 inet_ntop (AF_INET, &prefix_id.u.prefix4, ibuf, sizeof (ibuf));
hassoc6487d62004-12-24 06:00:11 +0000505 zlog_debug ("Advertise as AS-External Id:%s", ibuf);
hasso508e53e2004-05-18 18:57:06 +0000506 }
507
hasso3b687352004-08-19 06:56:53 +0000508 match->path.origin.id = htonl (info->id);
hasso6452df02004-08-15 05:52:07 +0000509 ospf6_as_external_lsa_originate (match);
hasso508e53e2004-05-18 18:57:06 +0000510 return;
511 }
512
513 /* create new entry */
514 route = ospf6_route_create ();
515 route->type = OSPF6_DEST_TYPE_NETWORK;
516 memcpy (&route->prefix, prefix, sizeof (struct prefix));
517
518 info = (struct ospf6_external_info *)
Stephen Hemminger393deb92008-08-18 14:13:29 -0700519 XCALLOC (MTYPE_OSPF6_EXTERNAL_INFO, sizeof (struct ospf6_external_info));
hasso508e53e2004-05-18 18:57:06 +0000520 route->route_option = info;
521 info->id = ospf6->external_id++;
522
523 /* copy result of route-map */
524 if (ospf6->rmap[type].map)
525 {
526 if (troute.path.metric_type)
527 route->path.metric_type = troute.path.metric_type;
528 if (troute.path.cost)
529 route->path.cost = troute.path.cost;
530 if (! IN6_IS_ADDR_UNSPECIFIED (&tinfo.forwarding))
531 memcpy (&info->forwarding, &tinfo.forwarding,
532 sizeof (struct in6_addr));
533 }
534
535 info->type = type;
536 route->nexthop[0].ifindex = ifindex;
537 if (nexthop_num && nexthop)
538 memcpy (&route->nexthop[0].address, nexthop, sizeof (struct in6_addr));
539
540 /* create/update binding in external_id_table */
541 prefix_id.family = AF_INET;
542 prefix_id.prefixlen = 32;
543 prefix_id.u.prefix4.s_addr = htonl (info->id);
544 node = route_node_get (ospf6->external_id_table, &prefix_id);
545 node->info = route;
546
547 route = ospf6_route_add (route, ospf6->external_table);
548 route->route_option = info;
549
550 if (IS_OSPF6_DEBUG_ASBR)
551 {
552 inet_ntop (AF_INET, &prefix_id.u.prefix4, ibuf, sizeof (ibuf));
hassoc6487d62004-12-24 06:00:11 +0000553 zlog_debug ("Advertise as AS-External Id:%s", ibuf);
hasso508e53e2004-05-18 18:57:06 +0000554 }
555
hasso3b687352004-08-19 06:56:53 +0000556 route->path.origin.id = htonl (info->id);
hasso6452df02004-08-15 05:52:07 +0000557 ospf6_as_external_lsa_originate (route);
hasso508e53e2004-05-18 18:57:06 +0000558
559 /* Router-Bit (ASBR Flag) may have to be updated */
paul1eb8ef22005-04-07 07:30:20 +0000560 for (ALL_LIST_ELEMENTS (ospf6->area_list, lnode, lnnode, oa))
561 OSPF6_ROUTER_LSA_SCHEDULE (oa);
hasso508e53e2004-05-18 18:57:06 +0000562}
563
564void
565ospf6_asbr_redistribute_remove (int type, int ifindex, struct prefix *prefix)
566{
567 struct ospf6_route *match;
568 struct ospf6_external_info *info = NULL;
569 struct route_node *node;
570 struct ospf6_lsa *lsa;
571 struct prefix prefix_id;
572 char pbuf[64], ibuf[16];
paul1eb8ef22005-04-07 07:30:20 +0000573 struct listnode *lnode, *lnnode;
hasso508e53e2004-05-18 18:57:06 +0000574 struct ospf6_area *oa;
575
576 match = ospf6_route_lookup (prefix, ospf6->external_table);
577 if (match == NULL)
578 {
579 if (IS_OSPF6_DEBUG_ASBR)
580 {
581 prefix2str (prefix, pbuf, sizeof (pbuf));
hassoc6487d62004-12-24 06:00:11 +0000582 zlog_debug ("No such route %s to withdraw", pbuf);
hasso508e53e2004-05-18 18:57:06 +0000583 }
584 return;
585 }
586
587 info = match->route_option;
588 assert (info);
589
590 if (info->type != type)
591 {
592 if (IS_OSPF6_DEBUG_ASBR)
593 {
594 prefix2str (prefix, pbuf, sizeof (pbuf));
hassoc6487d62004-12-24 06:00:11 +0000595 zlog_debug ("Original protocol mismatch: %s", pbuf);
hasso508e53e2004-05-18 18:57:06 +0000596 }
597 return;
598 }
599
600 if (IS_OSPF6_DEBUG_ASBR)
601 {
602 prefix2str (prefix, pbuf, sizeof (pbuf));
603 inet_ntop (AF_INET, &prefix_id.u.prefix4, ibuf, sizeof (ibuf));
hassoc6487d62004-12-24 06:00:11 +0000604 zlog_debug ("Withdraw %s (AS-External Id:%s)", pbuf, ibuf);
hasso508e53e2004-05-18 18:57:06 +0000605 }
606
607 lsa = ospf6_lsdb_lookup (htons (OSPF6_LSTYPE_AS_EXTERNAL),
608 htonl (info->id), ospf6->router_id, ospf6->lsdb);
609 if (lsa)
hasso6452df02004-08-15 05:52:07 +0000610 ospf6_lsa_purge (lsa);
hasso508e53e2004-05-18 18:57:06 +0000611
612 /* remove binding in external_id_table */
613 prefix_id.family = AF_INET;
614 prefix_id.prefixlen = 32;
615 prefix_id.u.prefix4.s_addr = htonl (info->id);
616 node = route_node_lookup (ospf6->external_id_table, &prefix_id);
617 assert (node);
618 node->info = NULL;
619 route_unlock_node (node);
620
621 ospf6_route_remove (match, ospf6->external_table);
622 XFREE (MTYPE_OSPF6_EXTERNAL_INFO, info);
623
624 /* Router-Bit (ASBR Flag) may have to be updated */
paul1eb8ef22005-04-07 07:30:20 +0000625 for (ALL_LIST_ELEMENTS (ospf6->area_list, lnode, lnnode, oa))
626 OSPF6_ROUTER_LSA_SCHEDULE (oa);
paul718e3742002-12-13 20:15:29 +0000627}
628
629DEFUN (ospf6_redistribute,
630 ospf6_redistribute_cmd,
David Lampartere0ca5fd2009-09-16 01:52:42 +0200631 "redistribute " QUAGGA_REDIST_STR_OSPF6D,
paul718e3742002-12-13 20:15:29 +0000632 "Redistribute\n"
David Lampartere0ca5fd2009-09-16 01:52:42 +0200633 QUAGGA_REDIST_HELP_STR_OSPF6D
paul718e3742002-12-13 20:15:29 +0000634 )
635{
David Lampartere0ca5fd2009-09-16 01:52:42 +0200636 int type;
paul718e3742002-12-13 20:15:29 +0000637
David Lampartere0ca5fd2009-09-16 01:52:42 +0200638 type = proto_redistnum(AFI_IP6, argv[0]);
639 if (type < 0 || type == ZEBRA_ROUTE_OSPF6)
640 return CMD_WARNING;
paul718e3742002-12-13 20:15:29 +0000641
hasso508e53e2004-05-18 18:57:06 +0000642 ospf6_asbr_redistribute_unset (type);
hasso508e53e2004-05-18 18:57:06 +0000643 ospf6_asbr_redistribute_set (type);
paul718e3742002-12-13 20:15:29 +0000644 return CMD_SUCCESS;
645}
646
647DEFUN (ospf6_redistribute_routemap,
648 ospf6_redistribute_routemap_cmd,
David Lampartere0ca5fd2009-09-16 01:52:42 +0200649 "redistribute " QUAGGA_REDIST_STR_OSPF6D " route-map WORD",
paul718e3742002-12-13 20:15:29 +0000650 "Redistribute\n"
David Lampartere0ca5fd2009-09-16 01:52:42 +0200651 QUAGGA_REDIST_HELP_STR_OSPF6D
paul718e3742002-12-13 20:15:29 +0000652 "Route map reference\n"
653 "Route map name\n"
654 )
655{
David Lampartere0ca5fd2009-09-16 01:52:42 +0200656 int type;
paul718e3742002-12-13 20:15:29 +0000657
David Lampartere0ca5fd2009-09-16 01:52:42 +0200658 type = proto_redistnum(AFI_IP6, argv[0]);
659 if (type < 0 || type == ZEBRA_ROUTE_OSPF6)
660 return CMD_WARNING;
paul718e3742002-12-13 20:15:29 +0000661
hasso508e53e2004-05-18 18:57:06 +0000662 ospf6_asbr_redistribute_unset (type);
paul718e3742002-12-13 20:15:29 +0000663 ospf6_asbr_routemap_set (type, argv[1]);
hasso508e53e2004-05-18 18:57:06 +0000664 ospf6_asbr_redistribute_set (type);
paul718e3742002-12-13 20:15:29 +0000665 return CMD_SUCCESS;
666}
667
668DEFUN (no_ospf6_redistribute,
669 no_ospf6_redistribute_cmd,
David Lampartere0ca5fd2009-09-16 01:52:42 +0200670 "no redistribute " QUAGGA_REDIST_STR_OSPF6D,
paul718e3742002-12-13 20:15:29 +0000671 NO_STR
672 "Redistribute\n"
David Lampartere0ca5fd2009-09-16 01:52:42 +0200673 QUAGGA_REDIST_HELP_STR_OSPF6D
paul718e3742002-12-13 20:15:29 +0000674 )
675{
David Lampartere0ca5fd2009-09-16 01:52:42 +0200676 int type;
paul718e3742002-12-13 20:15:29 +0000677
David Lampartere0ca5fd2009-09-16 01:52:42 +0200678 type = proto_redistnum(AFI_IP6, argv[0]);
679 if (type < 0 || type == ZEBRA_ROUTE_OSPF6)
680 return CMD_WARNING;
paul718e3742002-12-13 20:15:29 +0000681
hasso508e53e2004-05-18 18:57:06 +0000682 ospf6_asbr_redistribute_unset (type);
paul718e3742002-12-13 20:15:29 +0000683
paul718e3742002-12-13 20:15:29 +0000684 return CMD_SUCCESS;
685}
686
paul718e3742002-12-13 20:15:29 +0000687int
688ospf6_redistribute_config_write (struct vty *vty)
689{
hasso508e53e2004-05-18 18:57:06 +0000690 int type;
paul718e3742002-12-13 20:15:29 +0000691
hasso508e53e2004-05-18 18:57:06 +0000692 for (type = 0; type < ZEBRA_ROUTE_MAX; type++)
paul718e3742002-12-13 20:15:29 +0000693 {
hasso508e53e2004-05-18 18:57:06 +0000694 if (type == ZEBRA_ROUTE_OSPF6)
695 continue;
696 if (! ospf6_zebra_is_redistribute (type))
paul718e3742002-12-13 20:15:29 +0000697 continue;
698
hasso508e53e2004-05-18 18:57:06 +0000699 if (ospf6->rmap[type].name)
paul718e3742002-12-13 20:15:29 +0000700 vty_out (vty, " redistribute %s route-map %s%s",
hasso049207c2004-08-04 20:02:13 +0000701 ZROUTE_NAME (type), ospf6->rmap[type].name, VNL);
paul718e3742002-12-13 20:15:29 +0000702 else
703 vty_out (vty, " redistribute %s%s",
hasso049207c2004-08-04 20:02:13 +0000704 ZROUTE_NAME (type), VNL);
paul718e3742002-12-13 20:15:29 +0000705 }
706
707 return 0;
708}
709
Paul Jakma6ac29a52008-08-15 13:45:30 +0100710static void
paul718e3742002-12-13 20:15:29 +0000711ospf6_redistribute_show_config (struct vty *vty)
712{
hasso508e53e2004-05-18 18:57:06 +0000713 int type;
714 int nroute[ZEBRA_ROUTE_MAX];
715 int total;
716 struct ospf6_route *route;
paul718e3742002-12-13 20:15:29 +0000717 struct ospf6_external_info *info;
paul718e3742002-12-13 20:15:29 +0000718
hasso508e53e2004-05-18 18:57:06 +0000719 total = 0;
720 for (type = 0; type < ZEBRA_ROUTE_MAX; type++)
721 nroute[type] = 0;
722 for (route = ospf6_route_head (ospf6->external_table); route;
723 route = ospf6_route_next (route))
paul718e3742002-12-13 20:15:29 +0000724 {
hasso508e53e2004-05-18 18:57:06 +0000725 info = route->route_option;
726 nroute[info->type]++;
727 total++;
paul718e3742002-12-13 20:15:29 +0000728 }
729
hasso049207c2004-08-04 20:02:13 +0000730 vty_out (vty, "Redistributing External Routes from:%s", VNL);
hasso508e53e2004-05-18 18:57:06 +0000731 for (type = 0; type < ZEBRA_ROUTE_MAX; type++)
paul718e3742002-12-13 20:15:29 +0000732 {
hasso508e53e2004-05-18 18:57:06 +0000733 if (type == ZEBRA_ROUTE_OSPF6)
734 continue;
735 if (! ospf6_zebra_is_redistribute (type))
hassoe26bbeb2003-05-25 21:39:29 +0000736 continue;
737
hasso508e53e2004-05-18 18:57:06 +0000738 if (ospf6->rmap[type].name)
739 vty_out (vty, " %d: %s with route-map \"%s\"%s%s", nroute[type],
740 ZROUTE_NAME (type), ospf6->rmap[type].name,
741 (ospf6->rmap[type].map ? "" : " (not found !)"),
hasso049207c2004-08-04 20:02:13 +0000742 VNL);
paul718e3742002-12-13 20:15:29 +0000743 else
hasso508e53e2004-05-18 18:57:06 +0000744 vty_out (vty, " %d: %s%s", nroute[type],
hasso049207c2004-08-04 20:02:13 +0000745 ZROUTE_NAME (type), VNL);
paul718e3742002-12-13 20:15:29 +0000746 }
hasso049207c2004-08-04 20:02:13 +0000747 vty_out (vty, "Total %d routes%s", total, VNL);
hasso508e53e2004-05-18 18:57:06 +0000748}
paul718e3742002-12-13 20:15:29 +0000749
paul718e3742002-12-13 20:15:29 +0000750
hasso508e53e2004-05-18 18:57:06 +0000751
752/* Routemap Functions */
Paul Jakma6ac29a52008-08-15 13:45:30 +0100753static route_map_result_t
hasso508e53e2004-05-18 18:57:06 +0000754ospf6_routemap_rule_match_address_prefixlist (void *rule,
755 struct prefix *prefix,
756 route_map_object_t type,
757 void *object)
758{
759 struct prefix_list *plist;
paul718e3742002-12-13 20:15:29 +0000760
hasso508e53e2004-05-18 18:57:06 +0000761 if (type != RMAP_OSPF6)
762 return RMAP_NOMATCH;
paul718e3742002-12-13 20:15:29 +0000763
hasso508e53e2004-05-18 18:57:06 +0000764 plist = prefix_list_lookup (AFI_IP6, (char *) rule);
765 if (plist == NULL)
766 return RMAP_NOMATCH;
paul718e3742002-12-13 20:15:29 +0000767
hasso508e53e2004-05-18 18:57:06 +0000768 return (prefix_list_apply (plist, prefix) == PREFIX_DENY ?
769 RMAP_NOMATCH : RMAP_MATCH);
770}
paul718e3742002-12-13 20:15:29 +0000771
Paul Jakma6ac29a52008-08-15 13:45:30 +0100772static void *
paul0c083ee2004-10-10 12:54:58 +0000773ospf6_routemap_rule_match_address_prefixlist_compile (const char *arg)
hasso508e53e2004-05-18 18:57:06 +0000774{
775 return XSTRDUP (MTYPE_ROUTE_MAP_COMPILED, arg);
paul718e3742002-12-13 20:15:29 +0000776}
777
Paul Jakma6ac29a52008-08-15 13:45:30 +0100778static void
hasso508e53e2004-05-18 18:57:06 +0000779ospf6_routemap_rule_match_address_prefixlist_free (void *rule)
paul718e3742002-12-13 20:15:29 +0000780{
hasso508e53e2004-05-18 18:57:06 +0000781 XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
782}
paul718e3742002-12-13 20:15:29 +0000783
hasso508e53e2004-05-18 18:57:06 +0000784struct route_map_rule_cmd
785ospf6_routemap_rule_match_address_prefixlist_cmd =
786{
787 "ipv6 address prefix-list",
788 ospf6_routemap_rule_match_address_prefixlist,
789 ospf6_routemap_rule_match_address_prefixlist_compile,
790 ospf6_routemap_rule_match_address_prefixlist_free,
791};
hassoe26bbeb2003-05-25 21:39:29 +0000792
Vyacheslav Trushkin42a7deb2011-11-16 14:22:03 +0400793/* `match interface IFNAME' */
794/* Match function should return 1 if match is success else return
795 zero. */
796static route_map_result_t
797ospf6_routemap_rule_match_interface (void *rule, struct prefix *prefix,
798 route_map_object_t type, void *object)
799{
800 struct interface *ifp;
801 struct ospf6_external_info *ei;
802
803 if (type == RMAP_OSPF6)
804 {
805 ei = ((struct ospf6_route *) object)->route_option;
806 ifp = if_lookup_by_name ((char *)rule);
807
808 if (ifp != NULL
809 && ei->ifindex == ifp->ifindex)
810 return RMAP_MATCH;
811 }
812
813 return RMAP_NOMATCH;
814}
815
816/* Route map `interface' match statement. `arg' should be
817 interface name. */
818static void *
819ospf6_routemap_rule_match_interface_compile (const char *arg)
820{
821 return XSTRDUP (MTYPE_ROUTE_MAP_COMPILED, arg);
822}
823
824/* Free route map's compiled `interface' value. */
825static void
826ospf6_routemap_rule_match_interface_free (void *rule)
827{
828 XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
829}
830
831/* Route map commands for interface matching. */
832struct route_map_rule_cmd
833ospf6_routemap_rule_match_interface_cmd =
834{
835 "interface",
836 ospf6_routemap_rule_match_interface,
837 ospf6_routemap_rule_match_interface_compile,
838 ospf6_routemap_rule_match_interface_free
839};
840
Paul Jakma6ac29a52008-08-15 13:45:30 +0100841static route_map_result_t
hasso508e53e2004-05-18 18:57:06 +0000842ospf6_routemap_rule_set_metric_type (void *rule, struct prefix *prefix,
843 route_map_object_t type, void *object)
844{
845 char *metric_type = rule;
846 struct ospf6_route *route = object;
hassoe26bbeb2003-05-25 21:39:29 +0000847
hasso508e53e2004-05-18 18:57:06 +0000848 if (type != RMAP_OSPF6)
849 return RMAP_OKAY;
paul718e3742002-12-13 20:15:29 +0000850
hasso508e53e2004-05-18 18:57:06 +0000851 if (strcmp (metric_type, "type-2") == 0)
852 route->path.metric_type = 2;
paul718e3742002-12-13 20:15:29 +0000853 else
hasso508e53e2004-05-18 18:57:06 +0000854 route->path.metric_type = 1;
paul718e3742002-12-13 20:15:29 +0000855
hasso508e53e2004-05-18 18:57:06 +0000856 return RMAP_OKAY;
857}
paul718e3742002-12-13 20:15:29 +0000858
Paul Jakma6ac29a52008-08-15 13:45:30 +0100859static void *
paul0c083ee2004-10-10 12:54:58 +0000860ospf6_routemap_rule_set_metric_type_compile (const char *arg)
hasso508e53e2004-05-18 18:57:06 +0000861{
862 if (strcmp (arg, "type-2") && strcmp (arg, "type-1"))
863 return NULL;
864 return XSTRDUP (MTYPE_ROUTE_MAP_COMPILED, arg);
paul718e3742002-12-13 20:15:29 +0000865}
866
Paul Jakma6ac29a52008-08-15 13:45:30 +0100867static void
hasso508e53e2004-05-18 18:57:06 +0000868ospf6_routemap_rule_set_metric_type_free (void *rule)
paul718e3742002-12-13 20:15:29 +0000869{
hasso508e53e2004-05-18 18:57:06 +0000870 XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
871}
paul718e3742002-12-13 20:15:29 +0000872
hasso508e53e2004-05-18 18:57:06 +0000873struct route_map_rule_cmd
874ospf6_routemap_rule_set_metric_type_cmd =
875{
876 "metric-type",
877 ospf6_routemap_rule_set_metric_type,
878 ospf6_routemap_rule_set_metric_type_compile,
879 ospf6_routemap_rule_set_metric_type_free,
880};
paul718e3742002-12-13 20:15:29 +0000881
Paul Jakma6ac29a52008-08-15 13:45:30 +0100882static route_map_result_t
hasso508e53e2004-05-18 18:57:06 +0000883ospf6_routemap_rule_set_metric (void *rule, struct prefix *prefix,
884 route_map_object_t type, void *object)
885{
886 char *metric = rule;
887 struct ospf6_route *route = object;
paul718e3742002-12-13 20:15:29 +0000888
hasso508e53e2004-05-18 18:57:06 +0000889 if (type != RMAP_OSPF6)
890 return RMAP_OKAY;
paul718e3742002-12-13 20:15:29 +0000891
hasso508e53e2004-05-18 18:57:06 +0000892 route->path.cost = atoi (metric);
893 return RMAP_OKAY;
894}
paul718e3742002-12-13 20:15:29 +0000895
Paul Jakma6ac29a52008-08-15 13:45:30 +0100896static void *
paul0c083ee2004-10-10 12:54:58 +0000897ospf6_routemap_rule_set_metric_compile (const char *arg)
hasso508e53e2004-05-18 18:57:06 +0000898{
899 u_int32_t metric;
900 char *endp;
901 metric = strtoul (arg, &endp, 0);
Dinesh Dutt8551e6d2013-10-22 17:42:18 -0700902 if (metric > OSPF_LS_INFINITY || *endp != '\0')
hasso508e53e2004-05-18 18:57:06 +0000903 return NULL;
904 return XSTRDUP (MTYPE_ROUTE_MAP_COMPILED, arg);
paul718e3742002-12-13 20:15:29 +0000905}
906
Paul Jakma6ac29a52008-08-15 13:45:30 +0100907static void
hasso508e53e2004-05-18 18:57:06 +0000908ospf6_routemap_rule_set_metric_free (void *rule)
paul718e3742002-12-13 20:15:29 +0000909{
hasso508e53e2004-05-18 18:57:06 +0000910 XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
911}
912
913struct route_map_rule_cmd
914ospf6_routemap_rule_set_metric_cmd =
915{
916 "metric",
917 ospf6_routemap_rule_set_metric,
918 ospf6_routemap_rule_set_metric_compile,
919 ospf6_routemap_rule_set_metric_free,
920};
921
Paul Jakma6ac29a52008-08-15 13:45:30 +0100922static route_map_result_t
hasso508e53e2004-05-18 18:57:06 +0000923ospf6_routemap_rule_set_forwarding (void *rule, struct prefix *prefix,
924 route_map_object_t type, void *object)
925{
926 char *forwarding = rule;
927 struct ospf6_route *route = object;
928 struct ospf6_external_info *info = route->route_option;
929
930 if (type != RMAP_OSPF6)
931 return RMAP_OKAY;
932
933 if (inet_pton (AF_INET6, forwarding, &info->forwarding) != 1)
934 {
935 memset (&info->forwarding, 0, sizeof (struct in6_addr));
936 return RMAP_ERROR;
937 }
938
939 return RMAP_OKAY;
940}
941
Paul Jakma6ac29a52008-08-15 13:45:30 +0100942static void *
paul0c083ee2004-10-10 12:54:58 +0000943ospf6_routemap_rule_set_forwarding_compile (const char *arg)
hasso508e53e2004-05-18 18:57:06 +0000944{
945 struct in6_addr a;
946 if (inet_pton (AF_INET6, arg, &a) != 1)
947 return NULL;
948 return XSTRDUP (MTYPE_ROUTE_MAP_COMPILED, arg);
949}
950
Paul Jakma6ac29a52008-08-15 13:45:30 +0100951static void
hasso508e53e2004-05-18 18:57:06 +0000952ospf6_routemap_rule_set_forwarding_free (void *rule)
953{
954 XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
955}
956
957struct route_map_rule_cmd
958ospf6_routemap_rule_set_forwarding_cmd =
959{
960 "forwarding-address",
961 ospf6_routemap_rule_set_forwarding,
962 ospf6_routemap_rule_set_forwarding_compile,
963 ospf6_routemap_rule_set_forwarding_free,
964};
965
Paul Jakma6ac29a52008-08-15 13:45:30 +0100966static int
hasso508e53e2004-05-18 18:57:06 +0000967route_map_command_status (struct vty *vty, int ret)
968{
969 if (! ret)
970 return CMD_SUCCESS;
971
972 switch (ret)
973 {
974 case RMAP_RULE_MISSING:
hasso049207c2004-08-04 20:02:13 +0000975 vty_out (vty, "Can't find rule.%s", VNL);
hasso508e53e2004-05-18 18:57:06 +0000976 break;
977 case RMAP_COMPILE_ERROR:
hasso049207c2004-08-04 20:02:13 +0000978 vty_out (vty, "Argument is malformed.%s", VNL);
hasso508e53e2004-05-18 18:57:06 +0000979 break;
980 default:
hasso049207c2004-08-04 20:02:13 +0000981 vty_out (vty, "route-map add set failed.%s", VNL);
hasso508e53e2004-05-18 18:57:06 +0000982 break;
983 }
984 return CMD_WARNING;
985}
986
987/* add "match address" */
988DEFUN (ospf6_routemap_match_address_prefixlist,
989 ospf6_routemap_match_address_prefixlist_cmd,
990 "match ipv6 address prefix-list WORD",
991 "Match values\n"
992 IPV6_STR
993 "Match address of route\n"
994 "Match entries of prefix-lists\n"
995 "IPv6 prefix-list name\n")
996{
997 int ret = route_map_add_match ((struct route_map_index *) vty->index,
998 "ipv6 address prefix-list", argv[0]);
999 return route_map_command_status (vty, ret);
1000}
1001
1002/* delete "match address" */
1003DEFUN (ospf6_routemap_no_match_address_prefixlist,
1004 ospf6_routemap_no_match_address_prefixlist_cmd,
1005 "no match ipv6 address prefix-list WORD",
1006 NO_STR
1007 "Match values\n"
1008 IPV6_STR
1009 "Match address of route\n"
1010 "Match entries of prefix-lists\n"
1011 "IPv6 prefix-list name\n")
1012{
1013 int ret = route_map_delete_match ((struct route_map_index *) vty->index,
1014 "ipv6 address prefix-list", argv[0]);
1015 return route_map_command_status (vty, ret);
1016}
1017
Vyacheslav Trushkin42a7deb2011-11-16 14:22:03 +04001018/* "match interface" */
1019DEFUN (ospf6_routemap_match_interface,
1020 ospf6_routemap_match_interface_cmd,
1021 "match interface WORD",
1022 MATCH_STR
1023 "Match first hop interface of route\n"
1024 "Interface name\n")
1025{
1026 return route_map_add_match ((struct route_map_index *) vty->index,
1027 "interface", argv[0]);
1028}
1029
1030/* "no match interface WORD" */
1031DEFUN (ospf6_routemap_no_match_interface,
1032 ospf6_routemap_no_match_interface_cmd,
1033 "no match interface",
1034 MATCH_STR
1035 NO_STR
1036 "Match first hop interface of route\n")
1037{
1038 int ret = route_map_delete_match ((struct route_map_index *) vty->index,
1039 "interface", (argc == 0) ? NULL : argv[0]);
1040 return route_map_command_status (vty, ret);
1041}
1042
1043ALIAS (ospf6_routemap_no_match_interface,
1044 ospf6_routemap_no_match_interface_val_cmd,
1045 "no match interface WORD",
1046 MATCH_STR
1047 NO_STR
1048 "Match first hop interface of route\n"
1049 "Interface name\n")
1050
hasso508e53e2004-05-18 18:57:06 +00001051/* add "set metric-type" */
1052DEFUN (ospf6_routemap_set_metric_type,
1053 ospf6_routemap_set_metric_type_cmd,
1054 "set metric-type (type-1|type-2)",
1055 "Set value\n"
1056 "Type of metric\n"
1057 "OSPF6 external type 1 metric\n"
1058 "OSPF6 external type 2 metric\n")
1059{
1060 int ret = route_map_add_set ((struct route_map_index *) vty->index,
1061 "metric-type", argv[0]);
1062 return route_map_command_status (vty, ret);
1063}
1064
1065/* delete "set metric-type" */
1066DEFUN (ospf6_routemap_no_set_metric_type,
1067 ospf6_routemap_no_set_metric_type_cmd,
1068 "no set metric-type (type-1|type-2)",
1069 NO_STR
1070 "Set value\n"
1071 "Type of metric\n"
1072 "OSPF6 external type 1 metric\n"
1073 "OSPF6 external type 2 metric\n")
1074{
1075 int ret = route_map_delete_set ((struct route_map_index *) vty->index,
1076 "metric-type", argv[0]);
1077 return route_map_command_status (vty, ret);
1078}
1079
1080/* add "set metric" */
1081DEFUN (set_metric,
1082 set_metric_cmd,
1083 "set metric <0-4294967295>",
1084 "Set value\n"
1085 "Metric value\n"
1086 "Metric value\n")
1087{
1088 int ret = route_map_add_set ((struct route_map_index *) vty->index,
1089 "metric", argv[0]);
1090 return route_map_command_status (vty, ret);
1091}
1092
1093/* delete "set metric" */
1094DEFUN (no_set_metric,
1095 no_set_metric_cmd,
1096 "no set metric <0-4294967295>",
1097 NO_STR
1098 "Set value\n"
1099 "Metric\n"
1100 "METRIC value\n")
1101{
1102 int ret = route_map_delete_set ((struct route_map_index *) vty->index,
1103 "metric", argv[0]);
1104 return route_map_command_status (vty, ret);
1105}
1106
1107/* add "set forwarding-address" */
1108DEFUN (ospf6_routemap_set_forwarding,
1109 ospf6_routemap_set_forwarding_cmd,
1110 "set forwarding-address X:X::X:X",
1111 "Set value\n"
1112 "Forwarding Address\n"
1113 "IPv6 Address\n")
1114{
1115 int ret = route_map_add_set ((struct route_map_index *) vty->index,
1116 "forwarding-address", argv[0]);
1117 return route_map_command_status (vty, ret);
1118}
1119
1120/* delete "set forwarding-address" */
1121DEFUN (ospf6_routemap_no_set_forwarding,
1122 ospf6_routemap_no_set_forwarding_cmd,
1123 "no set forwarding-address X:X::X:X",
1124 NO_STR
1125 "Set value\n"
1126 "Forwarding Address\n"
1127 "IPv6 Address\n")
1128{
1129 int ret = route_map_delete_set ((struct route_map_index *) vty->index,
1130 "forwarding-address", argv[0]);
1131 return route_map_command_status (vty, ret);
1132}
1133
Paul Jakma6ac29a52008-08-15 13:45:30 +01001134static void
1135ospf6_routemap_init (void)
hasso508e53e2004-05-18 18:57:06 +00001136{
1137 route_map_init ();
1138 route_map_init_vty ();
1139 route_map_add_hook (ospf6_asbr_routemap_update);
1140 route_map_delete_hook (ospf6_asbr_routemap_update);
1141
1142 route_map_install_match (&ospf6_routemap_rule_match_address_prefixlist_cmd);
Vyacheslav Trushkin42a7deb2011-11-16 14:22:03 +04001143 route_map_install_match (&ospf6_routemap_rule_match_interface_cmd);
1144
hasso508e53e2004-05-18 18:57:06 +00001145 route_map_install_set (&ospf6_routemap_rule_set_metric_type_cmd);
1146 route_map_install_set (&ospf6_routemap_rule_set_metric_cmd);
1147 route_map_install_set (&ospf6_routemap_rule_set_forwarding_cmd);
1148
1149 /* Match address prefix-list */
1150 install_element (RMAP_NODE, &ospf6_routemap_match_address_prefixlist_cmd);
1151 install_element (RMAP_NODE, &ospf6_routemap_no_match_address_prefixlist_cmd);
1152
Vyacheslav Trushkin42a7deb2011-11-16 14:22:03 +04001153 /* Match interface */
1154 install_element (RMAP_NODE, &ospf6_routemap_match_interface_cmd);
1155 install_element (RMAP_NODE, &ospf6_routemap_no_match_interface_cmd);
1156 install_element (RMAP_NODE, &ospf6_routemap_no_match_interface_val_cmd);
1157
hasso508e53e2004-05-18 18:57:06 +00001158 /* ASE Metric Type (e.g. Type-1/Type-2) */
1159 install_element (RMAP_NODE, &ospf6_routemap_set_metric_type_cmd);
1160 install_element (RMAP_NODE, &ospf6_routemap_no_set_metric_type_cmd);
1161
1162 /* ASE Metric */
1163 install_element (RMAP_NODE, &set_metric_cmd);
1164 install_element (RMAP_NODE, &no_set_metric_cmd);
1165
1166 /* ASE Metric */
1167 install_element (RMAP_NODE, &ospf6_routemap_set_forwarding_cmd);
1168 install_element (RMAP_NODE, &ospf6_routemap_no_set_forwarding_cmd);
1169}
1170
1171
1172/* Display functions */
Dinesh Dutte68a6762013-08-25 03:03:23 +00001173static char *
1174ospf6_as_external_lsa_get_prefix_str (struct ospf6_lsa *lsa, char *buf,
1175 int buflen, int pos)
1176{
1177 struct ospf6_as_external_lsa *external;
1178 struct in6_addr in6;
1179 int prefix_length = 0;
1180
1181 if (lsa)
1182 {
1183 external = (struct ospf6_as_external_lsa *)
1184 OSPF6_LSA_HEADER_END (lsa->header);
1185
1186 if (pos == 0)
1187 {
1188 ospf6_prefix_in6_addr (&in6, &external->prefix);
1189 prefix_length = external->prefix.prefix_length;
1190 }
1191 else {
1192 in6 = *((struct in6_addr *)
1193 ((caddr_t) external + sizeof (struct ospf6_as_external_lsa) +
1194 OSPF6_PREFIX_SPACE (external->prefix.prefix_length)));
1195 }
1196 if (buf)
1197 {
1198 inet_ntop (AF_INET6, &in6, buf, buflen);
1199 if (prefix_length)
1200 sprintf (&buf[strlen(buf)], "/%d", prefix_length);
1201 }
1202 }
1203 return (buf);
1204}
1205
Paul Jakma6ac29a52008-08-15 13:45:30 +01001206static int
hasso508e53e2004-05-18 18:57:06 +00001207ospf6_as_external_lsa_show (struct vty *vty, struct ospf6_lsa *lsa)
1208{
1209 struct ospf6_as_external_lsa *external;
paul718e3742002-12-13 20:15:29 +00001210 char buf[64];
paul718e3742002-12-13 20:15:29 +00001211
1212 assert (lsa->header);
hasso508e53e2004-05-18 18:57:06 +00001213 external = (struct ospf6_as_external_lsa *)
1214 OSPF6_LSA_HEADER_END (lsa->header);
paul718e3742002-12-13 20:15:29 +00001215
1216 /* bits */
hasso508e53e2004-05-18 18:57:06 +00001217 snprintf (buf, sizeof (buf), "%c%c%c",
1218 (CHECK_FLAG (external->bits_metric, OSPF6_ASBR_BIT_E) ? 'E' : '-'),
1219 (CHECK_FLAG (external->bits_metric, OSPF6_ASBR_BIT_F) ? 'F' : '-'),
1220 (CHECK_FLAG (external->bits_metric, OSPF6_ASBR_BIT_T) ? 'T' : '-'));
paul718e3742002-12-13 20:15:29 +00001221
hasso049207c2004-08-04 20:02:13 +00001222 vty_out (vty, " Bits: %s%s", buf, VNL);
hasso508e53e2004-05-18 18:57:06 +00001223 vty_out (vty, " Metric: %5lu%s", (u_long) OSPF6_ASBR_METRIC (external),
hasso049207c2004-08-04 20:02:13 +00001224 VNL);
paul718e3742002-12-13 20:15:29 +00001225
hasso508e53e2004-05-18 18:57:06 +00001226 ospf6_prefix_options_printbuf (external->prefix.prefix_options,
1227 buf, sizeof (buf));
1228 vty_out (vty, " Prefix Options: %s%s", buf,
hasso049207c2004-08-04 20:02:13 +00001229 VNL);
paul718e3742002-12-13 20:15:29 +00001230
1231 vty_out (vty, " Referenced LSType: %d%s",
hasso508e53e2004-05-18 18:57:06 +00001232 ntohs (external->prefix.prefix_refer_lstype),
hasso049207c2004-08-04 20:02:13 +00001233 VNL);
paul718e3742002-12-13 20:15:29 +00001234
Dinesh Dutte68a6762013-08-25 03:03:23 +00001235 vty_out (vty, " Prefix: %s%s",
1236 ospf6_as_external_lsa_get_prefix_str (lsa, buf, sizeof(buf), 0), VNL);
paul718e3742002-12-13 20:15:29 +00001237
1238 /* Forwarding-Address */
1239 if (CHECK_FLAG (external->bits_metric, OSPF6_ASBR_BIT_F))
1240 {
Dinesh Dutte68a6762013-08-25 03:03:23 +00001241 vty_out (vty, " Forwarding-Address: %s%s",
1242 ospf6_as_external_lsa_get_prefix_str (lsa, buf, sizeof(buf), 1),
1243 VNL);
paul718e3742002-12-13 20:15:29 +00001244 }
1245
1246 return 0;
1247}
1248
Paul Jakma6ac29a52008-08-15 13:45:30 +01001249static void
hasso508e53e2004-05-18 18:57:06 +00001250ospf6_asbr_external_route_show (struct vty *vty, struct ospf6_route *route)
paul718e3742002-12-13 20:15:29 +00001251{
hasso508e53e2004-05-18 18:57:06 +00001252 struct ospf6_external_info *info = route->route_option;
1253 char prefix[64], id[16], forwarding[64];
1254 u_int32_t tmp_id;
1255
1256 prefix2str (&route->prefix, prefix, sizeof (prefix));
1257 tmp_id = ntohl (info->id);
1258 inet_ntop (AF_INET, &tmp_id, id, sizeof (id));
1259 if (! IN6_IS_ADDR_UNSPECIFIED (&info->forwarding))
1260 inet_ntop (AF_INET6, &info->forwarding, forwarding, sizeof (forwarding));
1261 else
1262 snprintf (forwarding, sizeof (forwarding), ":: (ifindex %d)",
1263 route->nexthop[0].ifindex);
1264
ajsf52d13c2005-10-01 17:38:06 +00001265 vty_out (vty, "%c %-32s %-15s type-%d %5lu %s%s",
1266 zebra_route_char(info->type),
hasso508e53e2004-05-18 18:57:06 +00001267 prefix, id, route->path.metric_type,
1268 (u_long) (route->path.metric_type == 2 ?
1269 route->path.cost_e2 : route->path.cost),
hasso049207c2004-08-04 20:02:13 +00001270 forwarding, VNL);
paul718e3742002-12-13 20:15:29 +00001271}
1272
hasso508e53e2004-05-18 18:57:06 +00001273DEFUN (show_ipv6_ospf6_redistribute,
1274 show_ipv6_ospf6_redistribute_cmd,
1275 "show ipv6 ospf6 redistribute",
paul718e3742002-12-13 20:15:29 +00001276 SHOW_STR
1277 IP6_STR
paul718e3742002-12-13 20:15:29 +00001278 OSPF6_STR
1279 "redistributing External information\n"
1280 )
1281{
hasso508e53e2004-05-18 18:57:06 +00001282 struct ospf6_route *route;
paul718e3742002-12-13 20:15:29 +00001283
hasso508e53e2004-05-18 18:57:06 +00001284 ospf6_redistribute_show_config (vty);
1285
1286 for (route = ospf6_route_head (ospf6->external_table); route;
1287 route = ospf6_route_next (route))
1288 ospf6_asbr_external_route_show (vty, route);
1289
paul718e3742002-12-13 20:15:29 +00001290 return CMD_SUCCESS;
1291}
1292
hasso6452df02004-08-15 05:52:07 +00001293struct ospf6_lsa_handler as_external_handler =
hasso508e53e2004-05-18 18:57:06 +00001294{
hasso6452df02004-08-15 05:52:07 +00001295 OSPF6_LSTYPE_AS_EXTERNAL,
1296 "AS-External",
Dinesh Dutte68a6762013-08-25 03:03:23 +00001297 "ASE",
1298 ospf6_as_external_lsa_show,
1299 ospf6_as_external_lsa_get_prefix_str
hasso6452df02004-08-15 05:52:07 +00001300};
hasso508e53e2004-05-18 18:57:06 +00001301
paul718e3742002-12-13 20:15:29 +00001302void
Paul Jakma6ac29a52008-08-15 13:45:30 +01001303ospf6_asbr_init (void)
paul718e3742002-12-13 20:15:29 +00001304{
hasso508e53e2004-05-18 18:57:06 +00001305 ospf6_routemap_init ();
paul718e3742002-12-13 20:15:29 +00001306
hasso6452df02004-08-15 05:52:07 +00001307 ospf6_install_lsa_handler (&as_external_handler);
paul718e3742002-12-13 20:15:29 +00001308
hasso508e53e2004-05-18 18:57:06 +00001309 install_element (VIEW_NODE, &show_ipv6_ospf6_redistribute_cmd);
1310 install_element (ENABLE_NODE, &show_ipv6_ospf6_redistribute_cmd);
1311
paul718e3742002-12-13 20:15:29 +00001312 install_element (OSPF6_NODE, &ospf6_redistribute_cmd);
1313 install_element (OSPF6_NODE, &ospf6_redistribute_routemap_cmd);
1314 install_element (OSPF6_NODE, &no_ospf6_redistribute_cmd);
1315}
1316
Tom Goffae2254a2010-11-10 13:01:41 -08001317void
Christian Franked9628722013-03-08 21:47:35 +01001318ospf6_asbr_redistribute_reset (void)
1319{
1320 int type;
1321
1322 for (type = 0; type < ZEBRA_ROUTE_MAX; type++)
1323 {
1324 if (type == ZEBRA_ROUTE_OSPF6)
1325 continue;
1326 if (ospf6_zebra_is_redistribute (type))
1327 ospf6_asbr_redistribute_unset(type);
1328 }
1329}
1330
1331void
Tom Goffae2254a2010-11-10 13:01:41 -08001332ospf6_asbr_terminate (void)
1333{
1334 route_map_finish ();
1335}
paul718e3742002-12-13 20:15:29 +00001336
hasso508e53e2004-05-18 18:57:06 +00001337DEFUN (debug_ospf6_asbr,
1338 debug_ospf6_asbr_cmd,
1339 "debug ospf6 asbr",
1340 DEBUG_STR
1341 OSPF6_STR
1342 "Debug OSPFv3 ASBR function\n"
1343 )
1344{
1345 OSPF6_DEBUG_ASBR_ON ();
1346 return CMD_SUCCESS;
1347}
1348
1349DEFUN (no_debug_ospf6_asbr,
1350 no_debug_ospf6_asbr_cmd,
1351 "no debug ospf6 asbr",
1352 NO_STR
1353 DEBUG_STR
1354 OSPF6_STR
1355 "Debug OSPFv3 ASBR function\n"
1356 )
1357{
1358 OSPF6_DEBUG_ASBR_OFF ();
1359 return CMD_SUCCESS;
1360}
1361
1362int
1363config_write_ospf6_debug_asbr (struct vty *vty)
1364{
1365 if (IS_OSPF6_DEBUG_ASBR)
hasso049207c2004-08-04 20:02:13 +00001366 vty_out (vty, "debug ospf6 asbr%s", VNL);
hasso508e53e2004-05-18 18:57:06 +00001367 return 0;
1368}
1369
1370void
1371install_element_ospf6_debug_asbr ()
1372{
1373 install_element (ENABLE_NODE, &debug_ospf6_asbr_cmd);
1374 install_element (ENABLE_NODE, &no_debug_ospf6_asbr_cmd);
1375 install_element (CONFIG_NODE, &debug_ospf6_asbr_cmd);
1376 install_element (CONFIG_NODE, &no_debug_ospf6_asbr_cmd);
1377}
1378
1379