blob: 3605e3f87d47ba3c663bebefa647ef43c6e32c2b [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 }
300}
301
302void
303ospf6_asbr_lsentry_add (struct ospf6_route *asbr_entry)
304{
hasso508e53e2004-05-18 18:57:06 +0000305 struct ospf6_lsa *lsa;
306 u_int16_t type;
307 u_int32_t router;
308
Paul Jakmacb4b8842006-05-15 10:39:30 +0000309 if (! CHECK_FLAG (asbr_entry->flag, OSPF6_ROUTE_BEST))
hasso508e53e2004-05-18 18:57:06 +0000310 {
Paul Jakmacb4b8842006-05-15 10:39:30 +0000311 char buf[16];
312 inet_ntop (AF_INET, &ADV_ROUTER_IN_PREFIX (&asbr_entry->prefix),
313 buf, sizeof (buf));
314 zlog_info ("ignore non-best path: lsentry %s add", buf);
315 return;
hasso508e53e2004-05-18 18:57:06 +0000316 }
317
318 type = htons (OSPF6_LSTYPE_AS_EXTERNAL);
319 router = ospf6_linkstate_prefix_adv_router (&asbr_entry->prefix);
Paul Jakmacb4b8842006-05-15 10:39:30 +0000320 for (lsa = ospf6_lsdb_type_router_head (type, router, ospf6->lsdb); lsa;
321 lsa = ospf6_lsdb_type_router_next (type, router, lsa))
hasso508e53e2004-05-18 18:57:06 +0000322 {
323 if (! OSPF6_LSA_IS_MAXAGE (lsa))
324 ospf6_asbr_lsa_add (lsa);
325 }
hasso508e53e2004-05-18 18:57:06 +0000326}
327
328void
329ospf6_asbr_lsentry_remove (struct ospf6_route *asbr_entry)
330{
hasso508e53e2004-05-18 18:57:06 +0000331 struct ospf6_lsa *lsa;
332 u_int16_t type;
333 u_int32_t router;
334
hasso508e53e2004-05-18 18:57:06 +0000335 type = htons (OSPF6_LSTYPE_AS_EXTERNAL);
336 router = ospf6_linkstate_prefix_adv_router (&asbr_entry->prefix);
337 for (lsa = ospf6_lsdb_type_router_head (type, router, ospf6->lsdb);
338 lsa; lsa = ospf6_lsdb_type_router_next (type, router, lsa))
339 ospf6_asbr_lsa_remove (lsa);
hasso508e53e2004-05-18 18:57:06 +0000340}
341
342
343
paul718e3742002-12-13 20:15:29 +0000344/* redistribute function */
hasso508e53e2004-05-18 18:57:06 +0000345
Paul Jakma6ac29a52008-08-15 13:45:30 +0100346static void
paul0c083ee2004-10-10 12:54:58 +0000347ospf6_asbr_routemap_set (int type, const char *mapname)
paul718e3742002-12-13 20:15:29 +0000348{
hasso508e53e2004-05-18 18:57:06 +0000349 if (ospf6->rmap[type].name)
350 free (ospf6->rmap[type].name);
351 ospf6->rmap[type].name = strdup (mapname);
352 ospf6->rmap[type].map = route_map_lookup_by_name (mapname);
paul718e3742002-12-13 20:15:29 +0000353}
354
Paul Jakma6ac29a52008-08-15 13:45:30 +0100355static void
paul718e3742002-12-13 20:15:29 +0000356ospf6_asbr_routemap_unset (int type)
357{
hasso508e53e2004-05-18 18:57:06 +0000358 if (ospf6->rmap[type].name)
359 free (ospf6->rmap[type].name);
360 ospf6->rmap[type].name = NULL;
361 ospf6->rmap[type].map = NULL;
paul718e3742002-12-13 20:15:29 +0000362}
363
Paul Jakma6ac29a52008-08-15 13:45:30 +0100364static void
paul0c083ee2004-10-10 12:54:58 +0000365ospf6_asbr_routemap_update (const char *mapname)
paul718e3742002-12-13 20:15:29 +0000366{
hasso508e53e2004-05-18 18:57:06 +0000367 int type;
368
369 if (ospf6 == NULL)
370 return;
371
372 for (type = 0; type < ZEBRA_ROUTE_MAX; type++)
paul718e3742002-12-13 20:15:29 +0000373 {
hasso508e53e2004-05-18 18:57:06 +0000374 if (ospf6->rmap[type].name)
375 ospf6->rmap[type].map =
376 route_map_lookup_by_name (ospf6->rmap[type].name);
paul718e3742002-12-13 20:15:29 +0000377 else
hasso508e53e2004-05-18 18:57:06 +0000378 ospf6->rmap[type].map = NULL;
379 }
380}
381
382int
383ospf6_asbr_is_asbr (struct ospf6 *o)
384{
385 return o->external_table->count;
386}
387
Paul Jakma6ac29a52008-08-15 13:45:30 +0100388static void
hasso508e53e2004-05-18 18:57:06 +0000389ospf6_asbr_redistribute_set (int type)
390{
391 ospf6_zebra_redistribute (type);
392}
393
Paul Jakma6ac29a52008-08-15 13:45:30 +0100394static void
hasso508e53e2004-05-18 18:57:06 +0000395ospf6_asbr_redistribute_unset (int type)
396{
397 struct ospf6_route *route;
398 struct ospf6_external_info *info;
399
400 ospf6_zebra_no_redistribute (type);
401
402 for (route = ospf6_route_head (ospf6->external_table); route;
403 route = ospf6_route_next (route))
404 {
405 info = route->route_option;
406 if (info->type != type)
407 continue;
408
409 ospf6_asbr_redistribute_remove (info->type, route->nexthop[0].ifindex,
410 &route->prefix);
411 }
Christian Franked9628722013-03-08 21:47:35 +0100412
413 ospf6_asbr_routemap_unset (type);
hasso508e53e2004-05-18 18:57:06 +0000414}
415
416void
417ospf6_asbr_redistribute_add (int type, int ifindex, struct prefix *prefix,
418 u_int nexthop_num, struct in6_addr *nexthop)
419{
420 int ret;
421 struct ospf6_route troute;
422 struct ospf6_external_info tinfo;
423 struct ospf6_route *route, *match;
424 struct ospf6_external_info *info;
425 struct prefix prefix_id;
426 struct route_node *node;
427 char pbuf[64], ibuf[16];
paul1eb8ef22005-04-07 07:30:20 +0000428 struct listnode *lnode, *lnnode;
hasso508e53e2004-05-18 18:57:06 +0000429 struct ospf6_area *oa;
430
431 if (! ospf6_zebra_is_redistribute (type))
432 return;
433
434 if (IS_OSPF6_DEBUG_ASBR)
435 {
436 prefix2str (prefix, pbuf, sizeof (pbuf));
hassoc6487d62004-12-24 06:00:11 +0000437 zlog_debug ("Redistribute %s (%s)", pbuf, ZROUTE_NAME (type));
hasso508e53e2004-05-18 18:57:06 +0000438 }
439
440 /* if route-map was specified but not found, do not advertise */
441 if (ospf6->rmap[type].name)
442 {
443 if (ospf6->rmap[type].map == NULL)
hasso03d52f82004-09-29 00:26:19 +0000444 ospf6_asbr_routemap_update (NULL);
hasso508e53e2004-05-18 18:57:06 +0000445 if (ospf6->rmap[type].map == NULL)
446 {
447 zlog_warn ("route-map \"%s\" not found, suppress redistributing",
448 ospf6->rmap[type].name);
449 return;
450 }
451 }
452
453 /* apply route-map */
454 if (ospf6->rmap[type].map)
455 {
456 memset (&troute, 0, sizeof (troute));
457 memset (&tinfo, 0, sizeof (tinfo));
458 troute.route_option = &tinfo;
Vyacheslav Trushkin42a7deb2011-11-16 14:22:03 +0400459 tinfo.ifindex = ifindex;
hasso508e53e2004-05-18 18:57:06 +0000460
461 ret = route_map_apply (ospf6->rmap[type].map, prefix,
462 RMAP_OSPF6, &troute);
paul47828742005-08-10 15:46:11 +0000463 if (ret == RMAP_DENYMATCH)
hasso508e53e2004-05-18 18:57:06 +0000464 {
465 if (IS_OSPF6_DEBUG_ASBR)
hassoc6487d62004-12-24 06:00:11 +0000466 zlog_debug ("Denied by route-map \"%s\"", ospf6->rmap[type].name);
hasso508e53e2004-05-18 18:57:06 +0000467 return;
468 }
469 }
470
471 match = ospf6_route_lookup (prefix, ospf6->external_table);
472 if (match)
473 {
474 info = match->route_option;
475
476 /* copy result of route-map */
477 if (ospf6->rmap[type].map)
478 {
479 if (troute.path.metric_type)
480 match->path.metric_type = troute.path.metric_type;
481 if (troute.path.cost)
482 match->path.cost = troute.path.cost;
483 if (! IN6_IS_ADDR_UNSPECIFIED (&tinfo.forwarding))
484 memcpy (&info->forwarding, &tinfo.forwarding,
485 sizeof (struct in6_addr));
486 }
487
488 info->type = type;
489 match->nexthop[0].ifindex = ifindex;
490 if (nexthop_num && nexthop)
491 memcpy (&match->nexthop[0].address, nexthop, sizeof (struct in6_addr));
492
493 /* create/update binding in external_id_table */
494 prefix_id.family = AF_INET;
495 prefix_id.prefixlen = 32;
496 prefix_id.u.prefix4.s_addr = htonl (info->id);
497 node = route_node_get (ospf6->external_id_table, &prefix_id);
498 node->info = match;
499
500 if (IS_OSPF6_DEBUG_ASBR)
501 {
502 inet_ntop (AF_INET, &prefix_id.u.prefix4, ibuf, sizeof (ibuf));
hassoc6487d62004-12-24 06:00:11 +0000503 zlog_debug ("Advertise as AS-External Id:%s", ibuf);
hasso508e53e2004-05-18 18:57:06 +0000504 }
505
hasso3b687352004-08-19 06:56:53 +0000506 match->path.origin.id = htonl (info->id);
hasso6452df02004-08-15 05:52:07 +0000507 ospf6_as_external_lsa_originate (match);
hasso508e53e2004-05-18 18:57:06 +0000508 return;
509 }
510
511 /* create new entry */
512 route = ospf6_route_create ();
513 route->type = OSPF6_DEST_TYPE_NETWORK;
514 memcpy (&route->prefix, prefix, sizeof (struct prefix));
515
516 info = (struct ospf6_external_info *)
Stephen Hemminger393deb92008-08-18 14:13:29 -0700517 XCALLOC (MTYPE_OSPF6_EXTERNAL_INFO, sizeof (struct ospf6_external_info));
hasso508e53e2004-05-18 18:57:06 +0000518 route->route_option = info;
519 info->id = ospf6->external_id++;
520
521 /* copy result of route-map */
522 if (ospf6->rmap[type].map)
523 {
524 if (troute.path.metric_type)
525 route->path.metric_type = troute.path.metric_type;
526 if (troute.path.cost)
527 route->path.cost = troute.path.cost;
528 if (! IN6_IS_ADDR_UNSPECIFIED (&tinfo.forwarding))
529 memcpy (&info->forwarding, &tinfo.forwarding,
530 sizeof (struct in6_addr));
531 }
532
533 info->type = type;
534 route->nexthop[0].ifindex = ifindex;
535 if (nexthop_num && nexthop)
536 memcpy (&route->nexthop[0].address, nexthop, sizeof (struct in6_addr));
537
538 /* create/update binding in external_id_table */
539 prefix_id.family = AF_INET;
540 prefix_id.prefixlen = 32;
541 prefix_id.u.prefix4.s_addr = htonl (info->id);
542 node = route_node_get (ospf6->external_id_table, &prefix_id);
543 node->info = route;
544
545 route = ospf6_route_add (route, ospf6->external_table);
546 route->route_option = info;
547
548 if (IS_OSPF6_DEBUG_ASBR)
549 {
550 inet_ntop (AF_INET, &prefix_id.u.prefix4, ibuf, sizeof (ibuf));
hassoc6487d62004-12-24 06:00:11 +0000551 zlog_debug ("Advertise as AS-External Id:%s", ibuf);
hasso508e53e2004-05-18 18:57:06 +0000552 }
553
hasso3b687352004-08-19 06:56:53 +0000554 route->path.origin.id = htonl (info->id);
hasso6452df02004-08-15 05:52:07 +0000555 ospf6_as_external_lsa_originate (route);
hasso508e53e2004-05-18 18:57:06 +0000556
557 /* Router-Bit (ASBR Flag) may have to be updated */
paul1eb8ef22005-04-07 07:30:20 +0000558 for (ALL_LIST_ELEMENTS (ospf6->area_list, lnode, lnnode, oa))
559 OSPF6_ROUTER_LSA_SCHEDULE (oa);
hasso508e53e2004-05-18 18:57:06 +0000560}
561
562void
563ospf6_asbr_redistribute_remove (int type, int ifindex, struct prefix *prefix)
564{
565 struct ospf6_route *match;
566 struct ospf6_external_info *info = NULL;
567 struct route_node *node;
568 struct ospf6_lsa *lsa;
569 struct prefix prefix_id;
570 char pbuf[64], ibuf[16];
paul1eb8ef22005-04-07 07:30:20 +0000571 struct listnode *lnode, *lnnode;
hasso508e53e2004-05-18 18:57:06 +0000572 struct ospf6_area *oa;
573
574 match = ospf6_route_lookup (prefix, ospf6->external_table);
575 if (match == NULL)
576 {
577 if (IS_OSPF6_DEBUG_ASBR)
578 {
579 prefix2str (prefix, pbuf, sizeof (pbuf));
hassoc6487d62004-12-24 06:00:11 +0000580 zlog_debug ("No such route %s to withdraw", pbuf);
hasso508e53e2004-05-18 18:57:06 +0000581 }
582 return;
583 }
584
585 info = match->route_option;
586 assert (info);
587
588 if (info->type != type)
589 {
590 if (IS_OSPF6_DEBUG_ASBR)
591 {
592 prefix2str (prefix, pbuf, sizeof (pbuf));
hassoc6487d62004-12-24 06:00:11 +0000593 zlog_debug ("Original protocol mismatch: %s", pbuf);
hasso508e53e2004-05-18 18:57:06 +0000594 }
595 return;
596 }
597
598 if (IS_OSPF6_DEBUG_ASBR)
599 {
600 prefix2str (prefix, pbuf, sizeof (pbuf));
601 inet_ntop (AF_INET, &prefix_id.u.prefix4, ibuf, sizeof (ibuf));
hassoc6487d62004-12-24 06:00:11 +0000602 zlog_debug ("Withdraw %s (AS-External Id:%s)", pbuf, ibuf);
hasso508e53e2004-05-18 18:57:06 +0000603 }
604
605 lsa = ospf6_lsdb_lookup (htons (OSPF6_LSTYPE_AS_EXTERNAL),
606 htonl (info->id), ospf6->router_id, ospf6->lsdb);
607 if (lsa)
hasso6452df02004-08-15 05:52:07 +0000608 ospf6_lsa_purge (lsa);
hasso508e53e2004-05-18 18:57:06 +0000609
610 /* remove binding in external_id_table */
611 prefix_id.family = AF_INET;
612 prefix_id.prefixlen = 32;
613 prefix_id.u.prefix4.s_addr = htonl (info->id);
614 node = route_node_lookup (ospf6->external_id_table, &prefix_id);
615 assert (node);
616 node->info = NULL;
617 route_unlock_node (node);
618
619 ospf6_route_remove (match, ospf6->external_table);
620 XFREE (MTYPE_OSPF6_EXTERNAL_INFO, info);
621
622 /* Router-Bit (ASBR Flag) may have to be updated */
paul1eb8ef22005-04-07 07:30:20 +0000623 for (ALL_LIST_ELEMENTS (ospf6->area_list, lnode, lnnode, oa))
624 OSPF6_ROUTER_LSA_SCHEDULE (oa);
paul718e3742002-12-13 20:15:29 +0000625}
626
627DEFUN (ospf6_redistribute,
628 ospf6_redistribute_cmd,
David Lampartere0ca5fd2009-09-16 01:52:42 +0200629 "redistribute " QUAGGA_REDIST_STR_OSPF6D,
paul718e3742002-12-13 20:15:29 +0000630 "Redistribute\n"
David Lampartere0ca5fd2009-09-16 01:52:42 +0200631 QUAGGA_REDIST_HELP_STR_OSPF6D
paul718e3742002-12-13 20:15:29 +0000632 )
633{
David Lampartere0ca5fd2009-09-16 01:52:42 +0200634 int type;
paul718e3742002-12-13 20:15:29 +0000635
David Lampartere0ca5fd2009-09-16 01:52:42 +0200636 type = proto_redistnum(AFI_IP6, argv[0]);
637 if (type < 0 || type == ZEBRA_ROUTE_OSPF6)
638 return CMD_WARNING;
paul718e3742002-12-13 20:15:29 +0000639
hasso508e53e2004-05-18 18:57:06 +0000640 ospf6_asbr_redistribute_unset (type);
hasso508e53e2004-05-18 18:57:06 +0000641 ospf6_asbr_redistribute_set (type);
paul718e3742002-12-13 20:15:29 +0000642 return CMD_SUCCESS;
643}
644
645DEFUN (ospf6_redistribute_routemap,
646 ospf6_redistribute_routemap_cmd,
David Lampartere0ca5fd2009-09-16 01:52:42 +0200647 "redistribute " QUAGGA_REDIST_STR_OSPF6D " route-map WORD",
paul718e3742002-12-13 20:15:29 +0000648 "Redistribute\n"
David Lampartere0ca5fd2009-09-16 01:52:42 +0200649 QUAGGA_REDIST_HELP_STR_OSPF6D
paul718e3742002-12-13 20:15:29 +0000650 "Route map reference\n"
651 "Route map name\n"
652 )
653{
David Lampartere0ca5fd2009-09-16 01:52:42 +0200654 int type;
paul718e3742002-12-13 20:15:29 +0000655
David Lampartere0ca5fd2009-09-16 01:52:42 +0200656 type = proto_redistnum(AFI_IP6, argv[0]);
657 if (type < 0 || type == ZEBRA_ROUTE_OSPF6)
658 return CMD_WARNING;
paul718e3742002-12-13 20:15:29 +0000659
hasso508e53e2004-05-18 18:57:06 +0000660 ospf6_asbr_redistribute_unset (type);
paul718e3742002-12-13 20:15:29 +0000661 ospf6_asbr_routemap_set (type, argv[1]);
hasso508e53e2004-05-18 18:57:06 +0000662 ospf6_asbr_redistribute_set (type);
paul718e3742002-12-13 20:15:29 +0000663 return CMD_SUCCESS;
664}
665
666DEFUN (no_ospf6_redistribute,
667 no_ospf6_redistribute_cmd,
David Lampartere0ca5fd2009-09-16 01:52:42 +0200668 "no redistribute " QUAGGA_REDIST_STR_OSPF6D,
paul718e3742002-12-13 20:15:29 +0000669 NO_STR
670 "Redistribute\n"
David Lampartere0ca5fd2009-09-16 01:52:42 +0200671 QUAGGA_REDIST_HELP_STR_OSPF6D
paul718e3742002-12-13 20:15:29 +0000672 )
673{
David Lampartere0ca5fd2009-09-16 01:52:42 +0200674 int type;
paul718e3742002-12-13 20:15:29 +0000675
David Lampartere0ca5fd2009-09-16 01:52:42 +0200676 type = proto_redistnum(AFI_IP6, argv[0]);
677 if (type < 0 || type == ZEBRA_ROUTE_OSPF6)
678 return CMD_WARNING;
paul718e3742002-12-13 20:15:29 +0000679
hasso508e53e2004-05-18 18:57:06 +0000680 ospf6_asbr_redistribute_unset (type);
paul718e3742002-12-13 20:15:29 +0000681
paul718e3742002-12-13 20:15:29 +0000682 return CMD_SUCCESS;
683}
684
paul718e3742002-12-13 20:15:29 +0000685int
686ospf6_redistribute_config_write (struct vty *vty)
687{
hasso508e53e2004-05-18 18:57:06 +0000688 int type;
paul718e3742002-12-13 20:15:29 +0000689
hasso508e53e2004-05-18 18:57:06 +0000690 for (type = 0; type < ZEBRA_ROUTE_MAX; type++)
paul718e3742002-12-13 20:15:29 +0000691 {
hasso508e53e2004-05-18 18:57:06 +0000692 if (type == ZEBRA_ROUTE_OSPF6)
693 continue;
694 if (! ospf6_zebra_is_redistribute (type))
paul718e3742002-12-13 20:15:29 +0000695 continue;
696
hasso508e53e2004-05-18 18:57:06 +0000697 if (ospf6->rmap[type].name)
paul718e3742002-12-13 20:15:29 +0000698 vty_out (vty, " redistribute %s route-map %s%s",
hasso049207c2004-08-04 20:02:13 +0000699 ZROUTE_NAME (type), ospf6->rmap[type].name, VNL);
paul718e3742002-12-13 20:15:29 +0000700 else
701 vty_out (vty, " redistribute %s%s",
hasso049207c2004-08-04 20:02:13 +0000702 ZROUTE_NAME (type), VNL);
paul718e3742002-12-13 20:15:29 +0000703 }
704
705 return 0;
706}
707
Paul Jakma6ac29a52008-08-15 13:45:30 +0100708static void
paul718e3742002-12-13 20:15:29 +0000709ospf6_redistribute_show_config (struct vty *vty)
710{
hasso508e53e2004-05-18 18:57:06 +0000711 int type;
712 int nroute[ZEBRA_ROUTE_MAX];
713 int total;
714 struct ospf6_route *route;
paul718e3742002-12-13 20:15:29 +0000715 struct ospf6_external_info *info;
paul718e3742002-12-13 20:15:29 +0000716
hasso508e53e2004-05-18 18:57:06 +0000717 total = 0;
718 for (type = 0; type < ZEBRA_ROUTE_MAX; type++)
719 nroute[type] = 0;
720 for (route = ospf6_route_head (ospf6->external_table); route;
721 route = ospf6_route_next (route))
paul718e3742002-12-13 20:15:29 +0000722 {
hasso508e53e2004-05-18 18:57:06 +0000723 info = route->route_option;
724 nroute[info->type]++;
725 total++;
paul718e3742002-12-13 20:15:29 +0000726 }
727
hasso049207c2004-08-04 20:02:13 +0000728 vty_out (vty, "Redistributing External Routes from:%s", VNL);
hasso508e53e2004-05-18 18:57:06 +0000729 for (type = 0; type < ZEBRA_ROUTE_MAX; type++)
paul718e3742002-12-13 20:15:29 +0000730 {
hasso508e53e2004-05-18 18:57:06 +0000731 if (type == ZEBRA_ROUTE_OSPF6)
732 continue;
733 if (! ospf6_zebra_is_redistribute (type))
hassoe26bbeb2003-05-25 21:39:29 +0000734 continue;
735
hasso508e53e2004-05-18 18:57:06 +0000736 if (ospf6->rmap[type].name)
737 vty_out (vty, " %d: %s with route-map \"%s\"%s%s", nroute[type],
738 ZROUTE_NAME (type), ospf6->rmap[type].name,
739 (ospf6->rmap[type].map ? "" : " (not found !)"),
hasso049207c2004-08-04 20:02:13 +0000740 VNL);
paul718e3742002-12-13 20:15:29 +0000741 else
hasso508e53e2004-05-18 18:57:06 +0000742 vty_out (vty, " %d: %s%s", nroute[type],
hasso049207c2004-08-04 20:02:13 +0000743 ZROUTE_NAME (type), VNL);
paul718e3742002-12-13 20:15:29 +0000744 }
hasso049207c2004-08-04 20:02:13 +0000745 vty_out (vty, "Total %d routes%s", total, VNL);
hasso508e53e2004-05-18 18:57:06 +0000746}
paul718e3742002-12-13 20:15:29 +0000747
paul718e3742002-12-13 20:15:29 +0000748
hasso508e53e2004-05-18 18:57:06 +0000749
750/* Routemap Functions */
Paul Jakma6ac29a52008-08-15 13:45:30 +0100751static route_map_result_t
hasso508e53e2004-05-18 18:57:06 +0000752ospf6_routemap_rule_match_address_prefixlist (void *rule,
753 struct prefix *prefix,
754 route_map_object_t type,
755 void *object)
756{
757 struct prefix_list *plist;
paul718e3742002-12-13 20:15:29 +0000758
hasso508e53e2004-05-18 18:57:06 +0000759 if (type != RMAP_OSPF6)
760 return RMAP_NOMATCH;
paul718e3742002-12-13 20:15:29 +0000761
hasso508e53e2004-05-18 18:57:06 +0000762 plist = prefix_list_lookup (AFI_IP6, (char *) rule);
763 if (plist == NULL)
764 return RMAP_NOMATCH;
paul718e3742002-12-13 20:15:29 +0000765
hasso508e53e2004-05-18 18:57:06 +0000766 return (prefix_list_apply (plist, prefix) == PREFIX_DENY ?
767 RMAP_NOMATCH : RMAP_MATCH);
768}
paul718e3742002-12-13 20:15:29 +0000769
Paul Jakma6ac29a52008-08-15 13:45:30 +0100770static void *
paul0c083ee2004-10-10 12:54:58 +0000771ospf6_routemap_rule_match_address_prefixlist_compile (const char *arg)
hasso508e53e2004-05-18 18:57:06 +0000772{
773 return XSTRDUP (MTYPE_ROUTE_MAP_COMPILED, arg);
paul718e3742002-12-13 20:15:29 +0000774}
775
Paul Jakma6ac29a52008-08-15 13:45:30 +0100776static void
hasso508e53e2004-05-18 18:57:06 +0000777ospf6_routemap_rule_match_address_prefixlist_free (void *rule)
paul718e3742002-12-13 20:15:29 +0000778{
hasso508e53e2004-05-18 18:57:06 +0000779 XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
780}
paul718e3742002-12-13 20:15:29 +0000781
hasso508e53e2004-05-18 18:57:06 +0000782struct route_map_rule_cmd
783ospf6_routemap_rule_match_address_prefixlist_cmd =
784{
785 "ipv6 address prefix-list",
786 ospf6_routemap_rule_match_address_prefixlist,
787 ospf6_routemap_rule_match_address_prefixlist_compile,
788 ospf6_routemap_rule_match_address_prefixlist_free,
789};
hassoe26bbeb2003-05-25 21:39:29 +0000790
Vyacheslav Trushkin42a7deb2011-11-16 14:22:03 +0400791/* `match interface IFNAME' */
792/* Match function should return 1 if match is success else return
793 zero. */
794static route_map_result_t
795ospf6_routemap_rule_match_interface (void *rule, struct prefix *prefix,
796 route_map_object_t type, void *object)
797{
798 struct interface *ifp;
799 struct ospf6_external_info *ei;
800
801 if (type == RMAP_OSPF6)
802 {
803 ei = ((struct ospf6_route *) object)->route_option;
804 ifp = if_lookup_by_name ((char *)rule);
805
806 if (ifp != NULL
807 && ei->ifindex == ifp->ifindex)
808 return RMAP_MATCH;
809 }
810
811 return RMAP_NOMATCH;
812}
813
814/* Route map `interface' match statement. `arg' should be
815 interface name. */
816static void *
817ospf6_routemap_rule_match_interface_compile (const char *arg)
818{
819 return XSTRDUP (MTYPE_ROUTE_MAP_COMPILED, arg);
820}
821
822/* Free route map's compiled `interface' value. */
823static void
824ospf6_routemap_rule_match_interface_free (void *rule)
825{
826 XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
827}
828
829/* Route map commands for interface matching. */
830struct route_map_rule_cmd
831ospf6_routemap_rule_match_interface_cmd =
832{
833 "interface",
834 ospf6_routemap_rule_match_interface,
835 ospf6_routemap_rule_match_interface_compile,
836 ospf6_routemap_rule_match_interface_free
837};
838
Paul Jakma6ac29a52008-08-15 13:45:30 +0100839static route_map_result_t
hasso508e53e2004-05-18 18:57:06 +0000840ospf6_routemap_rule_set_metric_type (void *rule, struct prefix *prefix,
841 route_map_object_t type, void *object)
842{
843 char *metric_type = rule;
844 struct ospf6_route *route = object;
hassoe26bbeb2003-05-25 21:39:29 +0000845
hasso508e53e2004-05-18 18:57:06 +0000846 if (type != RMAP_OSPF6)
847 return RMAP_OKAY;
paul718e3742002-12-13 20:15:29 +0000848
hasso508e53e2004-05-18 18:57:06 +0000849 if (strcmp (metric_type, "type-2") == 0)
850 route->path.metric_type = 2;
paul718e3742002-12-13 20:15:29 +0000851 else
hasso508e53e2004-05-18 18:57:06 +0000852 route->path.metric_type = 1;
paul718e3742002-12-13 20:15:29 +0000853
hasso508e53e2004-05-18 18:57:06 +0000854 return RMAP_OKAY;
855}
paul718e3742002-12-13 20:15:29 +0000856
Paul Jakma6ac29a52008-08-15 13:45:30 +0100857static void *
paul0c083ee2004-10-10 12:54:58 +0000858ospf6_routemap_rule_set_metric_type_compile (const char *arg)
hasso508e53e2004-05-18 18:57:06 +0000859{
860 if (strcmp (arg, "type-2") && strcmp (arg, "type-1"))
861 return NULL;
862 return XSTRDUP (MTYPE_ROUTE_MAP_COMPILED, arg);
paul718e3742002-12-13 20:15:29 +0000863}
864
Paul Jakma6ac29a52008-08-15 13:45:30 +0100865static void
hasso508e53e2004-05-18 18:57:06 +0000866ospf6_routemap_rule_set_metric_type_free (void *rule)
paul718e3742002-12-13 20:15:29 +0000867{
hasso508e53e2004-05-18 18:57:06 +0000868 XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
869}
paul718e3742002-12-13 20:15:29 +0000870
hasso508e53e2004-05-18 18:57:06 +0000871struct route_map_rule_cmd
872ospf6_routemap_rule_set_metric_type_cmd =
873{
874 "metric-type",
875 ospf6_routemap_rule_set_metric_type,
876 ospf6_routemap_rule_set_metric_type_compile,
877 ospf6_routemap_rule_set_metric_type_free,
878};
paul718e3742002-12-13 20:15:29 +0000879
Paul Jakma6ac29a52008-08-15 13:45:30 +0100880static route_map_result_t
hasso508e53e2004-05-18 18:57:06 +0000881ospf6_routemap_rule_set_metric (void *rule, struct prefix *prefix,
882 route_map_object_t type, void *object)
883{
884 char *metric = rule;
885 struct ospf6_route *route = object;
paul718e3742002-12-13 20:15:29 +0000886
hasso508e53e2004-05-18 18:57:06 +0000887 if (type != RMAP_OSPF6)
888 return RMAP_OKAY;
paul718e3742002-12-13 20:15:29 +0000889
hasso508e53e2004-05-18 18:57:06 +0000890 route->path.cost = atoi (metric);
891 return RMAP_OKAY;
892}
paul718e3742002-12-13 20:15:29 +0000893
Paul Jakma6ac29a52008-08-15 13:45:30 +0100894static void *
paul0c083ee2004-10-10 12:54:58 +0000895ospf6_routemap_rule_set_metric_compile (const char *arg)
hasso508e53e2004-05-18 18:57:06 +0000896{
897 u_int32_t metric;
898 char *endp;
899 metric = strtoul (arg, &endp, 0);
Dinesh Dutt8551e6d2013-10-22 17:42:18 -0700900 if (metric > OSPF_LS_INFINITY || *endp != '\0')
hasso508e53e2004-05-18 18:57:06 +0000901 return NULL;
902 return XSTRDUP (MTYPE_ROUTE_MAP_COMPILED, arg);
paul718e3742002-12-13 20:15:29 +0000903}
904
Paul Jakma6ac29a52008-08-15 13:45:30 +0100905static void
hasso508e53e2004-05-18 18:57:06 +0000906ospf6_routemap_rule_set_metric_free (void *rule)
paul718e3742002-12-13 20:15:29 +0000907{
hasso508e53e2004-05-18 18:57:06 +0000908 XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
909}
910
911struct route_map_rule_cmd
912ospf6_routemap_rule_set_metric_cmd =
913{
914 "metric",
915 ospf6_routemap_rule_set_metric,
916 ospf6_routemap_rule_set_metric_compile,
917 ospf6_routemap_rule_set_metric_free,
918};
919
Paul Jakma6ac29a52008-08-15 13:45:30 +0100920static route_map_result_t
hasso508e53e2004-05-18 18:57:06 +0000921ospf6_routemap_rule_set_forwarding (void *rule, struct prefix *prefix,
922 route_map_object_t type, void *object)
923{
924 char *forwarding = rule;
925 struct ospf6_route *route = object;
926 struct ospf6_external_info *info = route->route_option;
927
928 if (type != RMAP_OSPF6)
929 return RMAP_OKAY;
930
931 if (inet_pton (AF_INET6, forwarding, &info->forwarding) != 1)
932 {
933 memset (&info->forwarding, 0, sizeof (struct in6_addr));
934 return RMAP_ERROR;
935 }
936
937 return RMAP_OKAY;
938}
939
Paul Jakma6ac29a52008-08-15 13:45:30 +0100940static void *
paul0c083ee2004-10-10 12:54:58 +0000941ospf6_routemap_rule_set_forwarding_compile (const char *arg)
hasso508e53e2004-05-18 18:57:06 +0000942{
943 struct in6_addr a;
944 if (inet_pton (AF_INET6, arg, &a) != 1)
945 return NULL;
946 return XSTRDUP (MTYPE_ROUTE_MAP_COMPILED, arg);
947}
948
Paul Jakma6ac29a52008-08-15 13:45:30 +0100949static void
hasso508e53e2004-05-18 18:57:06 +0000950ospf6_routemap_rule_set_forwarding_free (void *rule)
951{
952 XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
953}
954
955struct route_map_rule_cmd
956ospf6_routemap_rule_set_forwarding_cmd =
957{
958 "forwarding-address",
959 ospf6_routemap_rule_set_forwarding,
960 ospf6_routemap_rule_set_forwarding_compile,
961 ospf6_routemap_rule_set_forwarding_free,
962};
963
Paul Jakma6ac29a52008-08-15 13:45:30 +0100964static int
hasso508e53e2004-05-18 18:57:06 +0000965route_map_command_status (struct vty *vty, int ret)
966{
967 if (! ret)
968 return CMD_SUCCESS;
969
970 switch (ret)
971 {
972 case RMAP_RULE_MISSING:
hasso049207c2004-08-04 20:02:13 +0000973 vty_out (vty, "Can't find rule.%s", VNL);
hasso508e53e2004-05-18 18:57:06 +0000974 break;
975 case RMAP_COMPILE_ERROR:
hasso049207c2004-08-04 20:02:13 +0000976 vty_out (vty, "Argument is malformed.%s", VNL);
hasso508e53e2004-05-18 18:57:06 +0000977 break;
978 default:
hasso049207c2004-08-04 20:02:13 +0000979 vty_out (vty, "route-map add set failed.%s", VNL);
hasso508e53e2004-05-18 18:57:06 +0000980 break;
981 }
982 return CMD_WARNING;
983}
984
985/* add "match address" */
986DEFUN (ospf6_routemap_match_address_prefixlist,
987 ospf6_routemap_match_address_prefixlist_cmd,
988 "match ipv6 address prefix-list WORD",
989 "Match values\n"
990 IPV6_STR
991 "Match address of route\n"
992 "Match entries of prefix-lists\n"
993 "IPv6 prefix-list name\n")
994{
995 int ret = route_map_add_match ((struct route_map_index *) vty->index,
996 "ipv6 address prefix-list", argv[0]);
997 return route_map_command_status (vty, ret);
998}
999
1000/* delete "match address" */
1001DEFUN (ospf6_routemap_no_match_address_prefixlist,
1002 ospf6_routemap_no_match_address_prefixlist_cmd,
1003 "no match ipv6 address prefix-list WORD",
1004 NO_STR
1005 "Match values\n"
1006 IPV6_STR
1007 "Match address of route\n"
1008 "Match entries of prefix-lists\n"
1009 "IPv6 prefix-list name\n")
1010{
1011 int ret = route_map_delete_match ((struct route_map_index *) vty->index,
1012 "ipv6 address prefix-list", argv[0]);
1013 return route_map_command_status (vty, ret);
1014}
1015
Vyacheslav Trushkin42a7deb2011-11-16 14:22:03 +04001016/* "match interface" */
1017DEFUN (ospf6_routemap_match_interface,
1018 ospf6_routemap_match_interface_cmd,
1019 "match interface WORD",
1020 MATCH_STR
1021 "Match first hop interface of route\n"
1022 "Interface name\n")
1023{
1024 return route_map_add_match ((struct route_map_index *) vty->index,
1025 "interface", argv[0]);
1026}
1027
1028/* "no match interface WORD" */
1029DEFUN (ospf6_routemap_no_match_interface,
1030 ospf6_routemap_no_match_interface_cmd,
1031 "no match interface",
1032 MATCH_STR
1033 NO_STR
1034 "Match first hop interface of route\n")
1035{
1036 int ret = route_map_delete_match ((struct route_map_index *) vty->index,
1037 "interface", (argc == 0) ? NULL : argv[0]);
1038 return route_map_command_status (vty, ret);
1039}
1040
1041ALIAS (ospf6_routemap_no_match_interface,
1042 ospf6_routemap_no_match_interface_val_cmd,
1043 "no match interface WORD",
1044 MATCH_STR
1045 NO_STR
1046 "Match first hop interface of route\n"
1047 "Interface name\n")
1048
hasso508e53e2004-05-18 18:57:06 +00001049/* add "set metric-type" */
1050DEFUN (ospf6_routemap_set_metric_type,
1051 ospf6_routemap_set_metric_type_cmd,
1052 "set metric-type (type-1|type-2)",
1053 "Set value\n"
1054 "Type of metric\n"
1055 "OSPF6 external type 1 metric\n"
1056 "OSPF6 external type 2 metric\n")
1057{
1058 int ret = route_map_add_set ((struct route_map_index *) vty->index,
1059 "metric-type", argv[0]);
1060 return route_map_command_status (vty, ret);
1061}
1062
1063/* delete "set metric-type" */
1064DEFUN (ospf6_routemap_no_set_metric_type,
1065 ospf6_routemap_no_set_metric_type_cmd,
1066 "no set metric-type (type-1|type-2)",
1067 NO_STR
1068 "Set value\n"
1069 "Type of metric\n"
1070 "OSPF6 external type 1 metric\n"
1071 "OSPF6 external type 2 metric\n")
1072{
1073 int ret = route_map_delete_set ((struct route_map_index *) vty->index,
1074 "metric-type", argv[0]);
1075 return route_map_command_status (vty, ret);
1076}
1077
1078/* add "set metric" */
1079DEFUN (set_metric,
1080 set_metric_cmd,
1081 "set metric <0-4294967295>",
1082 "Set value\n"
1083 "Metric value\n"
1084 "Metric value\n")
1085{
1086 int ret = route_map_add_set ((struct route_map_index *) vty->index,
1087 "metric", argv[0]);
1088 return route_map_command_status (vty, ret);
1089}
1090
1091/* delete "set metric" */
1092DEFUN (no_set_metric,
1093 no_set_metric_cmd,
1094 "no set metric <0-4294967295>",
1095 NO_STR
1096 "Set value\n"
1097 "Metric\n"
1098 "METRIC value\n")
1099{
1100 int ret = route_map_delete_set ((struct route_map_index *) vty->index,
1101 "metric", argv[0]);
1102 return route_map_command_status (vty, ret);
1103}
1104
1105/* add "set forwarding-address" */
1106DEFUN (ospf6_routemap_set_forwarding,
1107 ospf6_routemap_set_forwarding_cmd,
1108 "set forwarding-address X:X::X:X",
1109 "Set value\n"
1110 "Forwarding Address\n"
1111 "IPv6 Address\n")
1112{
1113 int ret = route_map_add_set ((struct route_map_index *) vty->index,
1114 "forwarding-address", argv[0]);
1115 return route_map_command_status (vty, ret);
1116}
1117
1118/* delete "set forwarding-address" */
1119DEFUN (ospf6_routemap_no_set_forwarding,
1120 ospf6_routemap_no_set_forwarding_cmd,
1121 "no set forwarding-address X:X::X:X",
1122 NO_STR
1123 "Set value\n"
1124 "Forwarding Address\n"
1125 "IPv6 Address\n")
1126{
1127 int ret = route_map_delete_set ((struct route_map_index *) vty->index,
1128 "forwarding-address", argv[0]);
1129 return route_map_command_status (vty, ret);
1130}
1131
Paul Jakma6ac29a52008-08-15 13:45:30 +01001132static void
1133ospf6_routemap_init (void)
hasso508e53e2004-05-18 18:57:06 +00001134{
1135 route_map_init ();
1136 route_map_init_vty ();
1137 route_map_add_hook (ospf6_asbr_routemap_update);
1138 route_map_delete_hook (ospf6_asbr_routemap_update);
1139
1140 route_map_install_match (&ospf6_routemap_rule_match_address_prefixlist_cmd);
Vyacheslav Trushkin42a7deb2011-11-16 14:22:03 +04001141 route_map_install_match (&ospf6_routemap_rule_match_interface_cmd);
1142
hasso508e53e2004-05-18 18:57:06 +00001143 route_map_install_set (&ospf6_routemap_rule_set_metric_type_cmd);
1144 route_map_install_set (&ospf6_routemap_rule_set_metric_cmd);
1145 route_map_install_set (&ospf6_routemap_rule_set_forwarding_cmd);
1146
1147 /* Match address prefix-list */
1148 install_element (RMAP_NODE, &ospf6_routemap_match_address_prefixlist_cmd);
1149 install_element (RMAP_NODE, &ospf6_routemap_no_match_address_prefixlist_cmd);
1150
Vyacheslav Trushkin42a7deb2011-11-16 14:22:03 +04001151 /* Match interface */
1152 install_element (RMAP_NODE, &ospf6_routemap_match_interface_cmd);
1153 install_element (RMAP_NODE, &ospf6_routemap_no_match_interface_cmd);
1154 install_element (RMAP_NODE, &ospf6_routemap_no_match_interface_val_cmd);
1155
hasso508e53e2004-05-18 18:57:06 +00001156 /* ASE Metric Type (e.g. Type-1/Type-2) */
1157 install_element (RMAP_NODE, &ospf6_routemap_set_metric_type_cmd);
1158 install_element (RMAP_NODE, &ospf6_routemap_no_set_metric_type_cmd);
1159
1160 /* ASE Metric */
1161 install_element (RMAP_NODE, &set_metric_cmd);
1162 install_element (RMAP_NODE, &no_set_metric_cmd);
1163
1164 /* ASE Metric */
1165 install_element (RMAP_NODE, &ospf6_routemap_set_forwarding_cmd);
1166 install_element (RMAP_NODE, &ospf6_routemap_no_set_forwarding_cmd);
1167}
1168
1169
1170/* Display functions */
Dinesh Dutte68a6762013-08-25 03:03:23 +00001171static char *
1172ospf6_as_external_lsa_get_prefix_str (struct ospf6_lsa *lsa, char *buf,
1173 int buflen, int pos)
1174{
1175 struct ospf6_as_external_lsa *external;
1176 struct in6_addr in6;
1177 int prefix_length = 0;
1178
1179 if (lsa)
1180 {
1181 external = (struct ospf6_as_external_lsa *)
1182 OSPF6_LSA_HEADER_END (lsa->header);
1183
1184 if (pos == 0)
1185 {
1186 ospf6_prefix_in6_addr (&in6, &external->prefix);
1187 prefix_length = external->prefix.prefix_length;
1188 }
1189 else {
1190 in6 = *((struct in6_addr *)
1191 ((caddr_t) external + sizeof (struct ospf6_as_external_lsa) +
1192 OSPF6_PREFIX_SPACE (external->prefix.prefix_length)));
1193 }
1194 if (buf)
1195 {
1196 inet_ntop (AF_INET6, &in6, buf, buflen);
1197 if (prefix_length)
1198 sprintf (&buf[strlen(buf)], "/%d", prefix_length);
1199 }
1200 }
1201 return (buf);
1202}
1203
Paul Jakma6ac29a52008-08-15 13:45:30 +01001204static int
hasso508e53e2004-05-18 18:57:06 +00001205ospf6_as_external_lsa_show (struct vty *vty, struct ospf6_lsa *lsa)
1206{
1207 struct ospf6_as_external_lsa *external;
paul718e3742002-12-13 20:15:29 +00001208 char buf[64];
paul718e3742002-12-13 20:15:29 +00001209
1210 assert (lsa->header);
hasso508e53e2004-05-18 18:57:06 +00001211 external = (struct ospf6_as_external_lsa *)
1212 OSPF6_LSA_HEADER_END (lsa->header);
paul718e3742002-12-13 20:15:29 +00001213
1214 /* bits */
hasso508e53e2004-05-18 18:57:06 +00001215 snprintf (buf, sizeof (buf), "%c%c%c",
1216 (CHECK_FLAG (external->bits_metric, OSPF6_ASBR_BIT_E) ? 'E' : '-'),
1217 (CHECK_FLAG (external->bits_metric, OSPF6_ASBR_BIT_F) ? 'F' : '-'),
1218 (CHECK_FLAG (external->bits_metric, OSPF6_ASBR_BIT_T) ? 'T' : '-'));
paul718e3742002-12-13 20:15:29 +00001219
hasso049207c2004-08-04 20:02:13 +00001220 vty_out (vty, " Bits: %s%s", buf, VNL);
hasso508e53e2004-05-18 18:57:06 +00001221 vty_out (vty, " Metric: %5lu%s", (u_long) OSPF6_ASBR_METRIC (external),
hasso049207c2004-08-04 20:02:13 +00001222 VNL);
paul718e3742002-12-13 20:15:29 +00001223
hasso508e53e2004-05-18 18:57:06 +00001224 ospf6_prefix_options_printbuf (external->prefix.prefix_options,
1225 buf, sizeof (buf));
1226 vty_out (vty, " Prefix Options: %s%s", buf,
hasso049207c2004-08-04 20:02:13 +00001227 VNL);
paul718e3742002-12-13 20:15:29 +00001228
1229 vty_out (vty, " Referenced LSType: %d%s",
hasso508e53e2004-05-18 18:57:06 +00001230 ntohs (external->prefix.prefix_refer_lstype),
hasso049207c2004-08-04 20:02:13 +00001231 VNL);
paul718e3742002-12-13 20:15:29 +00001232
Dinesh Dutte68a6762013-08-25 03:03:23 +00001233 vty_out (vty, " Prefix: %s%s",
1234 ospf6_as_external_lsa_get_prefix_str (lsa, buf, sizeof(buf), 0), VNL);
paul718e3742002-12-13 20:15:29 +00001235
1236 /* Forwarding-Address */
1237 if (CHECK_FLAG (external->bits_metric, OSPF6_ASBR_BIT_F))
1238 {
Dinesh Dutte68a6762013-08-25 03:03:23 +00001239 vty_out (vty, " Forwarding-Address: %s%s",
1240 ospf6_as_external_lsa_get_prefix_str (lsa, buf, sizeof(buf), 1),
1241 VNL);
paul718e3742002-12-13 20:15:29 +00001242 }
1243
1244 return 0;
1245}
1246
Paul Jakma6ac29a52008-08-15 13:45:30 +01001247static void
hasso508e53e2004-05-18 18:57:06 +00001248ospf6_asbr_external_route_show (struct vty *vty, struct ospf6_route *route)
paul718e3742002-12-13 20:15:29 +00001249{
hasso508e53e2004-05-18 18:57:06 +00001250 struct ospf6_external_info *info = route->route_option;
1251 char prefix[64], id[16], forwarding[64];
1252 u_int32_t tmp_id;
1253
1254 prefix2str (&route->prefix, prefix, sizeof (prefix));
1255 tmp_id = ntohl (info->id);
1256 inet_ntop (AF_INET, &tmp_id, id, sizeof (id));
1257 if (! IN6_IS_ADDR_UNSPECIFIED (&info->forwarding))
1258 inet_ntop (AF_INET6, &info->forwarding, forwarding, sizeof (forwarding));
1259 else
1260 snprintf (forwarding, sizeof (forwarding), ":: (ifindex %d)",
1261 route->nexthop[0].ifindex);
1262
ajsf52d13c2005-10-01 17:38:06 +00001263 vty_out (vty, "%c %-32s %-15s type-%d %5lu %s%s",
1264 zebra_route_char(info->type),
hasso508e53e2004-05-18 18:57:06 +00001265 prefix, id, route->path.metric_type,
1266 (u_long) (route->path.metric_type == 2 ?
1267 route->path.cost_e2 : route->path.cost),
hasso049207c2004-08-04 20:02:13 +00001268 forwarding, VNL);
paul718e3742002-12-13 20:15:29 +00001269}
1270
hasso508e53e2004-05-18 18:57:06 +00001271DEFUN (show_ipv6_ospf6_redistribute,
1272 show_ipv6_ospf6_redistribute_cmd,
1273 "show ipv6 ospf6 redistribute",
paul718e3742002-12-13 20:15:29 +00001274 SHOW_STR
1275 IP6_STR
paul718e3742002-12-13 20:15:29 +00001276 OSPF6_STR
1277 "redistributing External information\n"
1278 )
1279{
hasso508e53e2004-05-18 18:57:06 +00001280 struct ospf6_route *route;
paul718e3742002-12-13 20:15:29 +00001281
hasso508e53e2004-05-18 18:57:06 +00001282 ospf6_redistribute_show_config (vty);
1283
1284 for (route = ospf6_route_head (ospf6->external_table); route;
1285 route = ospf6_route_next (route))
1286 ospf6_asbr_external_route_show (vty, route);
1287
paul718e3742002-12-13 20:15:29 +00001288 return CMD_SUCCESS;
1289}
1290
hasso6452df02004-08-15 05:52:07 +00001291struct ospf6_lsa_handler as_external_handler =
hasso508e53e2004-05-18 18:57:06 +00001292{
hasso6452df02004-08-15 05:52:07 +00001293 OSPF6_LSTYPE_AS_EXTERNAL,
1294 "AS-External",
Dinesh Dutte68a6762013-08-25 03:03:23 +00001295 "ASE",
1296 ospf6_as_external_lsa_show,
1297 ospf6_as_external_lsa_get_prefix_str
hasso6452df02004-08-15 05:52:07 +00001298};
hasso508e53e2004-05-18 18:57:06 +00001299
paul718e3742002-12-13 20:15:29 +00001300void
Paul Jakma6ac29a52008-08-15 13:45:30 +01001301ospf6_asbr_init (void)
paul718e3742002-12-13 20:15:29 +00001302{
hasso508e53e2004-05-18 18:57:06 +00001303 ospf6_routemap_init ();
paul718e3742002-12-13 20:15:29 +00001304
hasso6452df02004-08-15 05:52:07 +00001305 ospf6_install_lsa_handler (&as_external_handler);
paul718e3742002-12-13 20:15:29 +00001306
hasso508e53e2004-05-18 18:57:06 +00001307 install_element (VIEW_NODE, &show_ipv6_ospf6_redistribute_cmd);
1308 install_element (ENABLE_NODE, &show_ipv6_ospf6_redistribute_cmd);
1309
paul718e3742002-12-13 20:15:29 +00001310 install_element (OSPF6_NODE, &ospf6_redistribute_cmd);
1311 install_element (OSPF6_NODE, &ospf6_redistribute_routemap_cmd);
1312 install_element (OSPF6_NODE, &no_ospf6_redistribute_cmd);
1313}
1314
Tom Goffae2254a2010-11-10 13:01:41 -08001315void
Christian Franked9628722013-03-08 21:47:35 +01001316ospf6_asbr_redistribute_reset (void)
1317{
1318 int type;
1319
1320 for (type = 0; type < ZEBRA_ROUTE_MAX; type++)
1321 {
1322 if (type == ZEBRA_ROUTE_OSPF6)
1323 continue;
1324 if (ospf6_zebra_is_redistribute (type))
1325 ospf6_asbr_redistribute_unset(type);
1326 }
1327}
1328
1329void
Tom Goffae2254a2010-11-10 13:01:41 -08001330ospf6_asbr_terminate (void)
1331{
1332 route_map_finish ();
1333}
paul718e3742002-12-13 20:15:29 +00001334
hasso508e53e2004-05-18 18:57:06 +00001335DEFUN (debug_ospf6_asbr,
1336 debug_ospf6_asbr_cmd,
1337 "debug ospf6 asbr",
1338 DEBUG_STR
1339 OSPF6_STR
1340 "Debug OSPFv3 ASBR function\n"
1341 )
1342{
1343 OSPF6_DEBUG_ASBR_ON ();
1344 return CMD_SUCCESS;
1345}
1346
1347DEFUN (no_debug_ospf6_asbr,
1348 no_debug_ospf6_asbr_cmd,
1349 "no debug ospf6 asbr",
1350 NO_STR
1351 DEBUG_STR
1352 OSPF6_STR
1353 "Debug OSPFv3 ASBR function\n"
1354 )
1355{
1356 OSPF6_DEBUG_ASBR_OFF ();
1357 return CMD_SUCCESS;
1358}
1359
1360int
1361config_write_ospf6_debug_asbr (struct vty *vty)
1362{
1363 if (IS_OSPF6_DEBUG_ASBR)
hasso049207c2004-08-04 20:02:13 +00001364 vty_out (vty, "debug ospf6 asbr%s", VNL);
hasso508e53e2004-05-18 18:57:06 +00001365 return 0;
1366}
1367
1368void
1369install_element_ospf6_debug_asbr ()
1370{
1371 install_element (ENABLE_NODE, &debug_ospf6_asbr_cmd);
1372 install_element (ENABLE_NODE, &no_debug_ospf6_asbr_cmd);
1373 install_element (CONFIG_NODE, &debug_ospf6_asbr_cmd);
1374 install_element (CONFIG_NODE, &no_debug_ospf6_asbr_cmd);
1375}
1376
1377