blob: 4b7d214aa2ffcb8aa7e083353a59f10495477954 [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;
Paul Jakma7aa9dce2014-09-19 14:42:23 +010061 struct ospf6_lsa *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
hasso1e058382004-09-01 21:36:14 +000068 if (IS_OSPF6_DEBUG_ASBR || IS_OSPF6_DEBUG_ORIGINATE (AS_EXTERNAL))
hasso508e53e2004-05-18 18:57:06 +000069 {
70 prefix2str (&route->prefix, buf, sizeof (buf));
hassoc6487d62004-12-24 06:00:11 +000071 zlog_debug ("Originate AS-External-LSA for %s", buf);
hasso508e53e2004-05-18 18:57:06 +000072 }
73
74 /* prepare buffer */
75 memset (buffer, 0, sizeof (buffer));
76 lsa_header = (struct ospf6_lsa_header *) buffer;
77 as_external_lsa = (struct ospf6_as_external_lsa *)
78 ((caddr_t) lsa_header + sizeof (struct ospf6_lsa_header));
79 p = (caddr_t)
80 ((caddr_t) as_external_lsa + sizeof (struct ospf6_as_external_lsa));
81
82 /* Fill AS-External-LSA */
83 /* Metric type */
84 if (route->path.metric_type == 2)
85 SET_FLAG (as_external_lsa->bits_metric, OSPF6_ASBR_BIT_E);
86 else
87 UNSET_FLAG (as_external_lsa->bits_metric, OSPF6_ASBR_BIT_E);
88
89 /* forwarding address */
Paul Jakma0b26f812006-05-15 10:47:53 +000090 if (! IN6_IS_ADDR_UNSPECIFIED (&info->forwarding))
hasso508e53e2004-05-18 18:57:06 +000091 SET_FLAG (as_external_lsa->bits_metric, OSPF6_ASBR_BIT_F);
92 else
93 UNSET_FLAG (as_external_lsa->bits_metric, OSPF6_ASBR_BIT_F);
94
95 /* external route tag */
96 UNSET_FLAG (as_external_lsa->bits_metric, OSPF6_ASBR_BIT_T);
97
98 /* Set metric */
99 OSPF6_ASBR_METRIC_SET (as_external_lsa, route->path.cost);
100
101 /* prefixlen */
102 as_external_lsa->prefix.prefix_length = route->prefix.prefixlen;
103
104 /* PrefixOptions */
105 as_external_lsa->prefix.prefix_options = route->path.prefix_options;
106
107 /* don't use refer LS-type */
108 as_external_lsa->prefix.prefix_refer_lstype = htons (0);
109
110 /* set Prefix */
111 memcpy (p, &route->prefix.u.prefix6,
112 OSPF6_PREFIX_SPACE (route->prefix.prefixlen));
113 ospf6_prefix_apply_mask (&as_external_lsa->prefix);
114 p += OSPF6_PREFIX_SPACE (route->prefix.prefixlen);
115
116 /* Forwarding address */
117 if (CHECK_FLAG (as_external_lsa->bits_metric, OSPF6_ASBR_BIT_F))
118 {
Paul Jakma0b26f812006-05-15 10:47:53 +0000119 memcpy (p, &info->forwarding, sizeof (struct in6_addr));
hasso508e53e2004-05-18 18:57:06 +0000120 p += sizeof (struct in6_addr);
121 }
122
123 /* External Route Tag */
124 if (CHECK_FLAG (as_external_lsa->bits_metric, OSPF6_ASBR_BIT_T))
125 {
126 /* xxx */
127 }
128
129 /* Fill LSA Header */
130 lsa_header->age = 0;
131 lsa_header->type = htons (OSPF6_LSTYPE_AS_EXTERNAL);
hasso6452df02004-08-15 05:52:07 +0000132 lsa_header->id = route->path.origin.id;
hasso508e53e2004-05-18 18:57:06 +0000133 lsa_header->adv_router = ospf6->router_id;
134 lsa_header->seqnum =
hasso049207c2004-08-04 20:02:13 +0000135 ospf6_new_ls_seqnum (lsa_header->type, lsa_header->id,
136 lsa_header->adv_router, ospf6->lsdb);
hasso508e53e2004-05-18 18:57:06 +0000137 lsa_header->length = htons ((caddr_t) p - (caddr_t) lsa_header);
138
139 /* LSA checksum */
140 ospf6_lsa_checksum (lsa_header);
141
142 /* create LSA */
143 lsa = ospf6_lsa_create (lsa_header);
hasso508e53e2004-05-18 18:57:06 +0000144
145 /* Originate */
hasso6452df02004-08-15 05:52:07 +0000146 ospf6_lsa_originate_process (lsa, ospf6);
hasso508e53e2004-05-18 18:57:06 +0000147}
148
David Lamparter6b0655a2014-06-04 06:53:35 +0200149
hasso508e53e2004-05-18 18:57:06 +0000150void
151ospf6_asbr_lsa_add (struct ospf6_lsa *lsa)
152{
153 struct ospf6_as_external_lsa *external;
154 struct prefix asbr_id;
155 struct ospf6_route *asbr_entry, *route;
156 char buf[64];
157 int i;
158
159 external = (struct ospf6_as_external_lsa *)
160 OSPF6_LSA_HEADER_END (lsa->header);
161
hasso1e058382004-09-01 21:36:14 +0000162 if (IS_OSPF6_DEBUG_EXAMIN (AS_EXTERNAL))
hassoc6487d62004-12-24 06:00:11 +0000163 zlog_debug ("Calculate AS-External route for %s", lsa->name);
hasso508e53e2004-05-18 18:57:06 +0000164
165 if (lsa->header->adv_router == ospf6->router_id)
166 {
hasso1e058382004-09-01 21:36:14 +0000167 if (IS_OSPF6_DEBUG_EXAMIN (AS_EXTERNAL))
hassoc6487d62004-12-24 06:00:11 +0000168 zlog_debug ("Ignore self-originated AS-External-LSA");
hasso508e53e2004-05-18 18:57:06 +0000169 return;
170 }
171
Dinesh Dutt8551e6d2013-10-22 17:42:18 -0700172 if (OSPF6_ASBR_METRIC (external) == OSPF_LS_INFINITY)
hasso508e53e2004-05-18 18:57:06 +0000173 {
hasso1e058382004-09-01 21:36:14 +0000174 if (IS_OSPF6_DEBUG_EXAMIN (AS_EXTERNAL))
hassoc6487d62004-12-24 06:00:11 +0000175 zlog_debug ("Ignore LSA with LSInfinity Metric");
hasso508e53e2004-05-18 18:57:06 +0000176 return;
177 }
178
Dinesh Dutt01879112013-08-25 03:03:31 +0000179 if (CHECK_FLAG(external->prefix.prefix_options, OSPF6_PREFIX_OPTION_NU))
180 {
181 if (IS_OSPF6_DEBUG_EXAMIN (AS_EXTERNAL))
182 zlog_debug ("Ignore LSA with NU bit set Metric");
183 return;
184 }
185
hassoccb59b12004-08-25 09:10:37 +0000186 ospf6_linkstate_prefix (lsa->header->adv_router, htonl (0), &asbr_id);
hasso6452df02004-08-15 05:52:07 +0000187 asbr_entry = ospf6_route_lookup (&asbr_id, ospf6->brouter_table);
hasso63069ad2004-09-02 13:01:01 +0000188 if (asbr_entry == NULL ||
189 ! CHECK_FLAG (asbr_entry->path.router_bits, OSPF6_ROUTER_BIT_E))
hasso508e53e2004-05-18 18:57:06 +0000190 {
hasso1e058382004-09-01 21:36:14 +0000191 if (IS_OSPF6_DEBUG_EXAMIN (AS_EXTERNAL))
hasso508e53e2004-05-18 18:57:06 +0000192 {
193 prefix2str (&asbr_id, buf, sizeof (buf));
hassoc6487d62004-12-24 06:00:11 +0000194 zlog_debug ("ASBR entry not found: %s", buf);
hasso508e53e2004-05-18 18:57:06 +0000195 }
196 return;
197 }
198
199 route = ospf6_route_create ();
200 route->type = OSPF6_DEST_TYPE_NETWORK;
201 route->prefix.family = AF_INET6;
202 route->prefix.prefixlen = external->prefix.prefix_length;
203 ospf6_prefix_in6_addr (&route->prefix.u.prefix6, &external->prefix);
204
205 route->path.area_id = asbr_entry->path.area_id;
206 route->path.origin.type = lsa->header->type;
207 route->path.origin.id = lsa->header->id;
208 route->path.origin.adv_router = lsa->header->adv_router;
209
210 route->path.prefix_options = external->prefix.prefix_options;
211 if (CHECK_FLAG (external->bits_metric, OSPF6_ASBR_BIT_E))
212 {
213 route->path.type = OSPF6_PATH_TYPE_EXTERNAL2;
214 route->path.metric_type = 2;
215 route->path.cost = asbr_entry->path.cost;
216 route->path.cost_e2 = OSPF6_ASBR_METRIC (external);
217 }
218 else
219 {
220 route->path.type = OSPF6_PATH_TYPE_EXTERNAL1;
221 route->path.metric_type = 1;
222 route->path.cost = asbr_entry->path.cost + OSPF6_ASBR_METRIC (external);
223 route->path.cost_e2 = 0;
224 }
225
226 for (i = 0; i < OSPF6_MULTI_PATH_LIMIT; i++)
227 ospf6_nexthop_copy (&route->nexthop[i], &asbr_entry->nexthop[i]);
228
hasso1e058382004-09-01 21:36:14 +0000229 if (IS_OSPF6_DEBUG_EXAMIN (AS_EXTERNAL))
hasso508e53e2004-05-18 18:57:06 +0000230 {
231 prefix2str (&route->prefix, buf, sizeof (buf));
hassoc6487d62004-12-24 06:00:11 +0000232 zlog_debug ("AS-External route add: %s", buf);
hasso508e53e2004-05-18 18:57:06 +0000233 }
234
235 ospf6_route_add (route, ospf6->route_table);
236}
237
238void
239ospf6_asbr_lsa_remove (struct ospf6_lsa *lsa)
240{
241 struct ospf6_as_external_lsa *external;
242 struct prefix prefix;
Vipin Kumar8c075ef2015-05-19 18:03:53 -0700243 struct ospf6_route *route, *nroute;
hasso508e53e2004-05-18 18:57:06 +0000244 char buf[64];
245
246 external = (struct ospf6_as_external_lsa *)
247 OSPF6_LSA_HEADER_END (lsa->header);
248
hasso1e058382004-09-01 21:36:14 +0000249 if (IS_OSPF6_DEBUG_EXAMIN (AS_EXTERNAL))
hassoc6487d62004-12-24 06:00:11 +0000250 zlog_debug ("Withdraw AS-External route for %s", lsa->name);
hasso508e53e2004-05-18 18:57:06 +0000251
252 if (lsa->header->adv_router == ospf6->router_id)
253 {
hasso1e058382004-09-01 21:36:14 +0000254 if (IS_OSPF6_DEBUG_EXAMIN (AS_EXTERNAL))
hassoc6487d62004-12-24 06:00:11 +0000255 zlog_debug ("Ignore self-originated AS-External-LSA");
hasso508e53e2004-05-18 18:57:06 +0000256 return;
257 }
258
259 memset (&prefix, 0, sizeof (struct prefix));
260 prefix.family = AF_INET6;
261 prefix.prefixlen = external->prefix.prefix_length;
262 ospf6_prefix_in6_addr (&prefix.u.prefix6, &external->prefix);
263
264 route = ospf6_route_lookup (&prefix, ospf6->route_table);
265 if (route == NULL)
266 {
hasso1e058382004-09-01 21:36:14 +0000267 if (IS_OSPF6_DEBUG_EXAMIN (AS_EXTERNAL))
hasso508e53e2004-05-18 18:57:06 +0000268 {
269 prefix2str (&prefix, buf, sizeof (buf));
hassoc6487d62004-12-24 06:00:11 +0000270 zlog_debug ("AS-External route %s not found", buf);
hasso508e53e2004-05-18 18:57:06 +0000271 }
272 return;
273 }
274
275 for (ospf6_route_lock (route);
276 route && ospf6_route_is_prefix (&prefix, route);
Vipin Kumar8c075ef2015-05-19 18:03:53 -0700277 route = nroute)
hasso508e53e2004-05-18 18:57:06 +0000278 {
Vipin Kumar8c075ef2015-05-19 18:03:53 -0700279 nroute = ospf6_route_next (route);
hasso508e53e2004-05-18 18:57:06 +0000280 if (route->type != OSPF6_DEST_TYPE_NETWORK)
281 continue;
282 if (route->path.origin.type != lsa->header->type)
283 continue;
284 if (route->path.origin.id != lsa->header->id)
285 continue;
286 if (route->path.origin.adv_router != lsa->header->adv_router)
287 continue;
288
hasso1e058382004-09-01 21:36:14 +0000289 if (IS_OSPF6_DEBUG_EXAMIN (AS_EXTERNAL))
hasso508e53e2004-05-18 18:57:06 +0000290 {
291 prefix2str (&route->prefix, buf, sizeof (buf));
hassoc6487d62004-12-24 06:00:11 +0000292 zlog_debug ("AS-External route remove: %s", buf);
hasso508e53e2004-05-18 18:57:06 +0000293 }
294 ospf6_route_remove (route, ospf6->route_table);
295 }
Christian Frankec78a46c2013-03-20 10:50:09 +0000296 if (route != NULL)
297 ospf6_route_unlock (route);
hasso508e53e2004-05-18 18:57:06 +0000298}
299
300void
301ospf6_asbr_lsentry_add (struct ospf6_route *asbr_entry)
302{
hasso508e53e2004-05-18 18:57:06 +0000303 struct ospf6_lsa *lsa;
304 u_int16_t type;
305 u_int32_t router;
306
Paul Jakmacb4b8842006-05-15 10:39:30 +0000307 if (! CHECK_FLAG (asbr_entry->flag, OSPF6_ROUTE_BEST))
hasso508e53e2004-05-18 18:57:06 +0000308 {
Paul Jakmacb4b8842006-05-15 10:39:30 +0000309 char buf[16];
310 inet_ntop (AF_INET, &ADV_ROUTER_IN_PREFIX (&asbr_entry->prefix),
311 buf, sizeof (buf));
312 zlog_info ("ignore non-best path: lsentry %s add", buf);
313 return;
hasso508e53e2004-05-18 18:57:06 +0000314 }
315
316 type = htons (OSPF6_LSTYPE_AS_EXTERNAL);
317 router = ospf6_linkstate_prefix_adv_router (&asbr_entry->prefix);
Paul Jakmacb4b8842006-05-15 10:39:30 +0000318 for (lsa = ospf6_lsdb_type_router_head (type, router, ospf6->lsdb); lsa;
319 lsa = ospf6_lsdb_type_router_next (type, router, lsa))
hasso508e53e2004-05-18 18:57:06 +0000320 {
321 if (! OSPF6_LSA_IS_MAXAGE (lsa))
322 ospf6_asbr_lsa_add (lsa);
323 }
hasso508e53e2004-05-18 18:57:06 +0000324}
325
326void
327ospf6_asbr_lsentry_remove (struct ospf6_route *asbr_entry)
328{
hasso508e53e2004-05-18 18:57:06 +0000329 struct ospf6_lsa *lsa;
330 u_int16_t type;
331 u_int32_t router;
332
hasso508e53e2004-05-18 18:57:06 +0000333 type = htons (OSPF6_LSTYPE_AS_EXTERNAL);
334 router = ospf6_linkstate_prefix_adv_router (&asbr_entry->prefix);
335 for (lsa = ospf6_lsdb_type_router_head (type, router, ospf6->lsdb);
336 lsa; lsa = ospf6_lsdb_type_router_next (type, router, lsa))
337 ospf6_asbr_lsa_remove (lsa);
hasso508e53e2004-05-18 18:57:06 +0000338}
339
340
David Lamparter6b0655a2014-06-04 06:53:35 +0200341
paul718e3742002-12-13 20:15:29 +0000342/* redistribute function */
hasso508e53e2004-05-18 18:57:06 +0000343
Paul Jakma6ac29a52008-08-15 13:45:30 +0100344static void
paul0c083ee2004-10-10 12:54:58 +0000345ospf6_asbr_routemap_set (int type, const char *mapname)
paul718e3742002-12-13 20:15:29 +0000346{
hasso508e53e2004-05-18 18:57:06 +0000347 if (ospf6->rmap[type].name)
348 free (ospf6->rmap[type].name);
349 ospf6->rmap[type].name = strdup (mapname);
350 ospf6->rmap[type].map = route_map_lookup_by_name (mapname);
paul718e3742002-12-13 20:15:29 +0000351}
352
Paul Jakma6ac29a52008-08-15 13:45:30 +0100353static void
paul718e3742002-12-13 20:15:29 +0000354ospf6_asbr_routemap_unset (int type)
355{
hasso508e53e2004-05-18 18:57:06 +0000356 if (ospf6->rmap[type].name)
357 free (ospf6->rmap[type].name);
358 ospf6->rmap[type].name = NULL;
359 ospf6->rmap[type].map = NULL;
paul718e3742002-12-13 20:15:29 +0000360}
361
Paul Jakma6ac29a52008-08-15 13:45:30 +0100362static void
paul0c083ee2004-10-10 12:54:58 +0000363ospf6_asbr_routemap_update (const char *mapname)
paul718e3742002-12-13 20:15:29 +0000364{
hasso508e53e2004-05-18 18:57:06 +0000365 int type;
366
367 if (ospf6 == NULL)
368 return;
369
370 for (type = 0; type < ZEBRA_ROUTE_MAX; type++)
paul718e3742002-12-13 20:15:29 +0000371 {
hasso508e53e2004-05-18 18:57:06 +0000372 if (ospf6->rmap[type].name)
373 ospf6->rmap[type].map =
374 route_map_lookup_by_name (ospf6->rmap[type].name);
paul718e3742002-12-13 20:15:29 +0000375 else
hasso508e53e2004-05-18 18:57:06 +0000376 ospf6->rmap[type].map = NULL;
377 }
378}
379
380int
381ospf6_asbr_is_asbr (struct ospf6 *o)
382{
383 return o->external_table->count;
384}
385
Paul Jakma6ac29a52008-08-15 13:45:30 +0100386static void
hasso508e53e2004-05-18 18:57:06 +0000387ospf6_asbr_redistribute_set (int type)
388{
389 ospf6_zebra_redistribute (type);
390}
391
Paul Jakma6ac29a52008-08-15 13:45:30 +0100392static void
hasso508e53e2004-05-18 18:57:06 +0000393ospf6_asbr_redistribute_unset (int type)
394{
395 struct ospf6_route *route;
396 struct ospf6_external_info *info;
397
398 ospf6_zebra_no_redistribute (type);
399
400 for (route = ospf6_route_head (ospf6->external_table); route;
401 route = ospf6_route_next (route))
402 {
403 info = route->route_option;
404 if (info->type != type)
405 continue;
406
407 ospf6_asbr_redistribute_remove (info->type, route->nexthop[0].ifindex,
408 &route->prefix);
409 }
Christian Franked9628722013-03-08 21:47:35 +0100410
411 ospf6_asbr_routemap_unset (type);
hasso508e53e2004-05-18 18:57:06 +0000412}
413
414void
Paul Jakma9099f9b2016-01-18 10:12:10 +0000415ospf6_asbr_redistribute_add (int type, ifindex_t ifindex, struct prefix *prefix,
hasso508e53e2004-05-18 18:57:06 +0000416 u_int nexthop_num, struct in6_addr *nexthop)
417{
418 int ret;
419 struct ospf6_route troute;
420 struct ospf6_external_info tinfo;
421 struct ospf6_route *route, *match;
422 struct ospf6_external_info *info;
423 struct prefix prefix_id;
424 struct route_node *node;
425 char pbuf[64], ibuf[16];
paul1eb8ef22005-04-07 07:30:20 +0000426 struct listnode *lnode, *lnnode;
hasso508e53e2004-05-18 18:57:06 +0000427 struct ospf6_area *oa;
428
429 if (! ospf6_zebra_is_redistribute (type))
430 return;
431
432 if (IS_OSPF6_DEBUG_ASBR)
433 {
434 prefix2str (prefix, pbuf, sizeof (pbuf));
hassoc6487d62004-12-24 06:00:11 +0000435 zlog_debug ("Redistribute %s (%s)", pbuf, ZROUTE_NAME (type));
hasso508e53e2004-05-18 18:57:06 +0000436 }
437
438 /* if route-map was specified but not found, do not advertise */
439 if (ospf6->rmap[type].name)
440 {
441 if (ospf6->rmap[type].map == NULL)
hasso03d52f82004-09-29 00:26:19 +0000442 ospf6_asbr_routemap_update (NULL);
hasso508e53e2004-05-18 18:57:06 +0000443 if (ospf6->rmap[type].map == NULL)
444 {
445 zlog_warn ("route-map \"%s\" not found, suppress redistributing",
446 ospf6->rmap[type].name);
447 return;
448 }
449 }
450
451 /* apply route-map */
452 if (ospf6->rmap[type].map)
453 {
454 memset (&troute, 0, sizeof (troute));
455 memset (&tinfo, 0, sizeof (tinfo));
456 troute.route_option = &tinfo;
Vyacheslav Trushkin42a7deb2011-11-16 14:22:03 +0400457 tinfo.ifindex = ifindex;
hasso508e53e2004-05-18 18:57:06 +0000458
459 ret = route_map_apply (ospf6->rmap[type].map, prefix,
460 RMAP_OSPF6, &troute);
paul47828742005-08-10 15:46:11 +0000461 if (ret == RMAP_DENYMATCH)
hasso508e53e2004-05-18 18:57:06 +0000462 {
463 if (IS_OSPF6_DEBUG_ASBR)
hassoc6487d62004-12-24 06:00:11 +0000464 zlog_debug ("Denied by route-map \"%s\"", ospf6->rmap[type].name);
hasso508e53e2004-05-18 18:57:06 +0000465 return;
466 }
467 }
468
469 match = ospf6_route_lookup (prefix, ospf6->external_table);
470 if (match)
471 {
472 info = match->route_option;
473
474 /* copy result of route-map */
475 if (ospf6->rmap[type].map)
476 {
477 if (troute.path.metric_type)
478 match->path.metric_type = troute.path.metric_type;
479 if (troute.path.cost)
480 match->path.cost = troute.path.cost;
481 if (! IN6_IS_ADDR_UNSPECIFIED (&tinfo.forwarding))
482 memcpy (&info->forwarding, &tinfo.forwarding,
483 sizeof (struct in6_addr));
484 }
485
486 info->type = type;
487 match->nexthop[0].ifindex = ifindex;
488 if (nexthop_num && nexthop)
489 memcpy (&match->nexthop[0].address, nexthop, sizeof (struct in6_addr));
490
491 /* create/update binding in external_id_table */
492 prefix_id.family = AF_INET;
493 prefix_id.prefixlen = 32;
494 prefix_id.u.prefix4.s_addr = htonl (info->id);
495 node = route_node_get (ospf6->external_id_table, &prefix_id);
496 node->info = match;
497
498 if (IS_OSPF6_DEBUG_ASBR)
499 {
500 inet_ntop (AF_INET, &prefix_id.u.prefix4, ibuf, sizeof (ibuf));
hassoc6487d62004-12-24 06:00:11 +0000501 zlog_debug ("Advertise as AS-External Id:%s", ibuf);
hasso508e53e2004-05-18 18:57:06 +0000502 }
503
hasso3b687352004-08-19 06:56:53 +0000504 match->path.origin.id = htonl (info->id);
hasso6452df02004-08-15 05:52:07 +0000505 ospf6_as_external_lsa_originate (match);
hasso508e53e2004-05-18 18:57:06 +0000506 return;
507 }
508
509 /* create new entry */
510 route = ospf6_route_create ();
511 route->type = OSPF6_DEST_TYPE_NETWORK;
512 memcpy (&route->prefix, prefix, sizeof (struct prefix));
513
514 info = (struct ospf6_external_info *)
Stephen Hemminger393deb92008-08-18 14:13:29 -0700515 XCALLOC (MTYPE_OSPF6_EXTERNAL_INFO, sizeof (struct ospf6_external_info));
hasso508e53e2004-05-18 18:57:06 +0000516 route->route_option = info;
517 info->id = ospf6->external_id++;
518
519 /* copy result of route-map */
520 if (ospf6->rmap[type].map)
521 {
522 if (troute.path.metric_type)
523 route->path.metric_type = troute.path.metric_type;
524 if (troute.path.cost)
525 route->path.cost = troute.path.cost;
526 if (! IN6_IS_ADDR_UNSPECIFIED (&tinfo.forwarding))
527 memcpy (&info->forwarding, &tinfo.forwarding,
528 sizeof (struct in6_addr));
529 }
530
531 info->type = type;
532 route->nexthop[0].ifindex = ifindex;
533 if (nexthop_num && nexthop)
534 memcpy (&route->nexthop[0].address, nexthop, sizeof (struct in6_addr));
535
536 /* create/update binding in external_id_table */
537 prefix_id.family = AF_INET;
538 prefix_id.prefixlen = 32;
539 prefix_id.u.prefix4.s_addr = htonl (info->id);
540 node = route_node_get (ospf6->external_id_table, &prefix_id);
541 node->info = route;
542
543 route = ospf6_route_add (route, ospf6->external_table);
544 route->route_option = info;
545
546 if (IS_OSPF6_DEBUG_ASBR)
547 {
548 inet_ntop (AF_INET, &prefix_id.u.prefix4, ibuf, sizeof (ibuf));
hassoc6487d62004-12-24 06:00:11 +0000549 zlog_debug ("Advertise as AS-External Id:%s", ibuf);
hasso508e53e2004-05-18 18:57:06 +0000550 }
551
hasso3b687352004-08-19 06:56:53 +0000552 route->path.origin.id = htonl (info->id);
hasso6452df02004-08-15 05:52:07 +0000553 ospf6_as_external_lsa_originate (route);
hasso508e53e2004-05-18 18:57:06 +0000554
555 /* Router-Bit (ASBR Flag) may have to be updated */
paul1eb8ef22005-04-07 07:30:20 +0000556 for (ALL_LIST_ELEMENTS (ospf6->area_list, lnode, lnnode, oa))
557 OSPF6_ROUTER_LSA_SCHEDULE (oa);
hasso508e53e2004-05-18 18:57:06 +0000558}
559
560void
Paul Jakma9099f9b2016-01-18 10:12:10 +0000561ospf6_asbr_redistribute_remove (int type, ifindex_t ifindex,
562 struct prefix *prefix)
hasso508e53e2004-05-18 18:57:06 +0000563{
564 struct ospf6_route *match;
565 struct ospf6_external_info *info = NULL;
566 struct route_node *node;
567 struct ospf6_lsa *lsa;
568 struct prefix prefix_id;
569 char pbuf[64], ibuf[16];
paul1eb8ef22005-04-07 07:30:20 +0000570 struct listnode *lnode, *lnnode;
hasso508e53e2004-05-18 18:57:06 +0000571 struct ospf6_area *oa;
572
573 match = ospf6_route_lookup (prefix, ospf6->external_table);
574 if (match == NULL)
575 {
576 if (IS_OSPF6_DEBUG_ASBR)
577 {
578 prefix2str (prefix, pbuf, sizeof (pbuf));
hassoc6487d62004-12-24 06:00:11 +0000579 zlog_debug ("No such route %s to withdraw", pbuf);
hasso508e53e2004-05-18 18:57:06 +0000580 }
581 return;
582 }
583
584 info = match->route_option;
585 assert (info);
586
587 if (info->type != type)
588 {
589 if (IS_OSPF6_DEBUG_ASBR)
590 {
591 prefix2str (prefix, pbuf, sizeof (pbuf));
hassoc6487d62004-12-24 06:00:11 +0000592 zlog_debug ("Original protocol mismatch: %s", pbuf);
hasso508e53e2004-05-18 18:57:06 +0000593 }
594 return;
595 }
596
597 if (IS_OSPF6_DEBUG_ASBR)
598 {
599 prefix2str (prefix, pbuf, sizeof (pbuf));
600 inet_ntop (AF_INET, &prefix_id.u.prefix4, ibuf, sizeof (ibuf));
hassoc6487d62004-12-24 06:00:11 +0000601 zlog_debug ("Withdraw %s (AS-External Id:%s)", pbuf, ibuf);
hasso508e53e2004-05-18 18:57:06 +0000602 }
603
604 lsa = ospf6_lsdb_lookup (htons (OSPF6_LSTYPE_AS_EXTERNAL),
605 htonl (info->id), ospf6->router_id, ospf6->lsdb);
606 if (lsa)
hasso6452df02004-08-15 05:52:07 +0000607 ospf6_lsa_purge (lsa);
hasso508e53e2004-05-18 18:57:06 +0000608
609 /* remove binding in external_id_table */
610 prefix_id.family = AF_INET;
611 prefix_id.prefixlen = 32;
612 prefix_id.u.prefix4.s_addr = htonl (info->id);
613 node = route_node_lookup (ospf6->external_id_table, &prefix_id);
614 assert (node);
615 node->info = NULL;
616 route_unlock_node (node);
617
618 ospf6_route_remove (match, ospf6->external_table);
619 XFREE (MTYPE_OSPF6_EXTERNAL_INFO, info);
620
621 /* Router-Bit (ASBR Flag) may have to be updated */
paul1eb8ef22005-04-07 07:30:20 +0000622 for (ALL_LIST_ELEMENTS (ospf6->area_list, lnode, lnnode, oa))
623 OSPF6_ROUTER_LSA_SCHEDULE (oa);
paul718e3742002-12-13 20:15:29 +0000624}
625
626DEFUN (ospf6_redistribute,
627 ospf6_redistribute_cmd,
David Lampartere0ca5fd2009-09-16 01:52:42 +0200628 "redistribute " QUAGGA_REDIST_STR_OSPF6D,
paul718e3742002-12-13 20:15:29 +0000629 "Redistribute\n"
David Lampartere0ca5fd2009-09-16 01:52:42 +0200630 QUAGGA_REDIST_HELP_STR_OSPF6D
paul718e3742002-12-13 20:15:29 +0000631 )
632{
David Lampartere0ca5fd2009-09-16 01:52:42 +0200633 int type;
paul718e3742002-12-13 20:15:29 +0000634
David Lampartere0ca5fd2009-09-16 01:52:42 +0200635 type = proto_redistnum(AFI_IP6, argv[0]);
636 if (type < 0 || type == ZEBRA_ROUTE_OSPF6)
637 return CMD_WARNING;
paul718e3742002-12-13 20:15:29 +0000638
hasso508e53e2004-05-18 18:57:06 +0000639 ospf6_asbr_redistribute_unset (type);
hasso508e53e2004-05-18 18:57:06 +0000640 ospf6_asbr_redistribute_set (type);
paul718e3742002-12-13 20:15:29 +0000641 return CMD_SUCCESS;
642}
643
644DEFUN (ospf6_redistribute_routemap,
645 ospf6_redistribute_routemap_cmd,
David Lampartere0ca5fd2009-09-16 01:52:42 +0200646 "redistribute " QUAGGA_REDIST_STR_OSPF6D " route-map WORD",
paul718e3742002-12-13 20:15:29 +0000647 "Redistribute\n"
David Lampartere0ca5fd2009-09-16 01:52:42 +0200648 QUAGGA_REDIST_HELP_STR_OSPF6D
paul718e3742002-12-13 20:15:29 +0000649 "Route map reference\n"
650 "Route map name\n"
651 )
652{
David Lampartere0ca5fd2009-09-16 01:52:42 +0200653 int type;
paul718e3742002-12-13 20:15:29 +0000654
David Lampartere0ca5fd2009-09-16 01:52:42 +0200655 type = proto_redistnum(AFI_IP6, argv[0]);
656 if (type < 0 || type == ZEBRA_ROUTE_OSPF6)
657 return CMD_WARNING;
paul718e3742002-12-13 20:15:29 +0000658
hasso508e53e2004-05-18 18:57:06 +0000659 ospf6_asbr_redistribute_unset (type);
paul718e3742002-12-13 20:15:29 +0000660 ospf6_asbr_routemap_set (type, argv[1]);
hasso508e53e2004-05-18 18:57:06 +0000661 ospf6_asbr_redistribute_set (type);
paul718e3742002-12-13 20:15:29 +0000662 return CMD_SUCCESS;
663}
664
665DEFUN (no_ospf6_redistribute,
666 no_ospf6_redistribute_cmd,
David Lampartere0ca5fd2009-09-16 01:52:42 +0200667 "no redistribute " QUAGGA_REDIST_STR_OSPF6D,
paul718e3742002-12-13 20:15:29 +0000668 NO_STR
669 "Redistribute\n"
David Lampartere0ca5fd2009-09-16 01:52:42 +0200670 QUAGGA_REDIST_HELP_STR_OSPF6D
paul718e3742002-12-13 20:15:29 +0000671 )
672{
David Lampartere0ca5fd2009-09-16 01:52:42 +0200673 int type;
paul718e3742002-12-13 20:15:29 +0000674
David Lampartere0ca5fd2009-09-16 01:52:42 +0200675 type = proto_redistnum(AFI_IP6, argv[0]);
676 if (type < 0 || type == ZEBRA_ROUTE_OSPF6)
677 return CMD_WARNING;
paul718e3742002-12-13 20:15:29 +0000678
hasso508e53e2004-05-18 18:57:06 +0000679 ospf6_asbr_redistribute_unset (type);
paul718e3742002-12-13 20:15:29 +0000680
paul718e3742002-12-13 20:15:29 +0000681 return CMD_SUCCESS;
682}
683
Daniel Walton69424be2015-05-19 18:03:41 -0700684ALIAS (no_ospf6_redistribute,
685 no_ospf6_redistribute_route_map_cmd,
686 "no redistribute " QUAGGA_REDIST_STR_OSPF6D " route-map WORD",
687 NO_STR
688 "Redistribute\n"
689 QUAGGA_REDIST_HELP_STR_OSPF6D
690 "Route map reference\n"
691 "Route map name\n")
692
paul718e3742002-12-13 20:15:29 +0000693int
694ospf6_redistribute_config_write (struct vty *vty)
695{
hasso508e53e2004-05-18 18:57:06 +0000696 int type;
paul718e3742002-12-13 20:15:29 +0000697
hasso508e53e2004-05-18 18:57:06 +0000698 for (type = 0; type < ZEBRA_ROUTE_MAX; type++)
paul718e3742002-12-13 20:15:29 +0000699 {
hasso508e53e2004-05-18 18:57:06 +0000700 if (type == ZEBRA_ROUTE_OSPF6)
701 continue;
702 if (! ospf6_zebra_is_redistribute (type))
paul718e3742002-12-13 20:15:29 +0000703 continue;
704
hasso508e53e2004-05-18 18:57:06 +0000705 if (ospf6->rmap[type].name)
paul718e3742002-12-13 20:15:29 +0000706 vty_out (vty, " redistribute %s route-map %s%s",
hasso049207c2004-08-04 20:02:13 +0000707 ZROUTE_NAME (type), ospf6->rmap[type].name, VNL);
paul718e3742002-12-13 20:15:29 +0000708 else
709 vty_out (vty, " redistribute %s%s",
hasso049207c2004-08-04 20:02:13 +0000710 ZROUTE_NAME (type), VNL);
paul718e3742002-12-13 20:15:29 +0000711 }
712
713 return 0;
714}
715
Paul Jakma6ac29a52008-08-15 13:45:30 +0100716static void
paul718e3742002-12-13 20:15:29 +0000717ospf6_redistribute_show_config (struct vty *vty)
718{
hasso508e53e2004-05-18 18:57:06 +0000719 int type;
720 int nroute[ZEBRA_ROUTE_MAX];
721 int total;
722 struct ospf6_route *route;
paul718e3742002-12-13 20:15:29 +0000723 struct ospf6_external_info *info;
paul718e3742002-12-13 20:15:29 +0000724
hasso508e53e2004-05-18 18:57:06 +0000725 total = 0;
726 for (type = 0; type < ZEBRA_ROUTE_MAX; type++)
727 nroute[type] = 0;
728 for (route = ospf6_route_head (ospf6->external_table); route;
729 route = ospf6_route_next (route))
paul718e3742002-12-13 20:15:29 +0000730 {
hasso508e53e2004-05-18 18:57:06 +0000731 info = route->route_option;
732 nroute[info->type]++;
733 total++;
paul718e3742002-12-13 20:15:29 +0000734 }
735
hasso049207c2004-08-04 20:02:13 +0000736 vty_out (vty, "Redistributing External Routes from:%s", VNL);
hasso508e53e2004-05-18 18:57:06 +0000737 for (type = 0; type < ZEBRA_ROUTE_MAX; type++)
paul718e3742002-12-13 20:15:29 +0000738 {
hasso508e53e2004-05-18 18:57:06 +0000739 if (type == ZEBRA_ROUTE_OSPF6)
740 continue;
741 if (! ospf6_zebra_is_redistribute (type))
hassoe26bbeb2003-05-25 21:39:29 +0000742 continue;
743
hasso508e53e2004-05-18 18:57:06 +0000744 if (ospf6->rmap[type].name)
745 vty_out (vty, " %d: %s with route-map \"%s\"%s%s", nroute[type],
746 ZROUTE_NAME (type), ospf6->rmap[type].name,
747 (ospf6->rmap[type].map ? "" : " (not found !)"),
hasso049207c2004-08-04 20:02:13 +0000748 VNL);
paul718e3742002-12-13 20:15:29 +0000749 else
hasso508e53e2004-05-18 18:57:06 +0000750 vty_out (vty, " %d: %s%s", nroute[type],
hasso049207c2004-08-04 20:02:13 +0000751 ZROUTE_NAME (type), VNL);
paul718e3742002-12-13 20:15:29 +0000752 }
hasso049207c2004-08-04 20:02:13 +0000753 vty_out (vty, "Total %d routes%s", total, VNL);
hasso508e53e2004-05-18 18:57:06 +0000754}
paul718e3742002-12-13 20:15:29 +0000755
paul718e3742002-12-13 20:15:29 +0000756
David Lamparter6b0655a2014-06-04 06:53:35 +0200757
hasso508e53e2004-05-18 18:57:06 +0000758/* Routemap Functions */
Paul Jakma6ac29a52008-08-15 13:45:30 +0100759static route_map_result_t
hasso508e53e2004-05-18 18:57:06 +0000760ospf6_routemap_rule_match_address_prefixlist (void *rule,
761 struct prefix *prefix,
762 route_map_object_t type,
763 void *object)
764{
765 struct prefix_list *plist;
paul718e3742002-12-13 20:15:29 +0000766
hasso508e53e2004-05-18 18:57:06 +0000767 if (type != RMAP_OSPF6)
768 return RMAP_NOMATCH;
paul718e3742002-12-13 20:15:29 +0000769
hasso508e53e2004-05-18 18:57:06 +0000770 plist = prefix_list_lookup (AFI_IP6, (char *) rule);
771 if (plist == NULL)
772 return RMAP_NOMATCH;
paul718e3742002-12-13 20:15:29 +0000773
hasso508e53e2004-05-18 18:57:06 +0000774 return (prefix_list_apply (plist, prefix) == PREFIX_DENY ?
775 RMAP_NOMATCH : RMAP_MATCH);
776}
paul718e3742002-12-13 20:15:29 +0000777
Paul Jakma6ac29a52008-08-15 13:45:30 +0100778static void *
paul0c083ee2004-10-10 12:54:58 +0000779ospf6_routemap_rule_match_address_prefixlist_compile (const char *arg)
hasso508e53e2004-05-18 18:57:06 +0000780{
781 return XSTRDUP (MTYPE_ROUTE_MAP_COMPILED, arg);
paul718e3742002-12-13 20:15:29 +0000782}
783
Paul Jakma6ac29a52008-08-15 13:45:30 +0100784static void
hasso508e53e2004-05-18 18:57:06 +0000785ospf6_routemap_rule_match_address_prefixlist_free (void *rule)
paul718e3742002-12-13 20:15:29 +0000786{
hasso508e53e2004-05-18 18:57:06 +0000787 XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
788}
paul718e3742002-12-13 20:15:29 +0000789
hasso508e53e2004-05-18 18:57:06 +0000790struct route_map_rule_cmd
791ospf6_routemap_rule_match_address_prefixlist_cmd =
792{
793 "ipv6 address prefix-list",
794 ospf6_routemap_rule_match_address_prefixlist,
795 ospf6_routemap_rule_match_address_prefixlist_compile,
796 ospf6_routemap_rule_match_address_prefixlist_free,
797};
hassoe26bbeb2003-05-25 21:39:29 +0000798
Vyacheslav Trushkin42a7deb2011-11-16 14:22:03 +0400799/* `match interface IFNAME' */
800/* Match function should return 1 if match is success else return
801 zero. */
802static route_map_result_t
803ospf6_routemap_rule_match_interface (void *rule, struct prefix *prefix,
804 route_map_object_t type, void *object)
805{
806 struct interface *ifp;
807 struct ospf6_external_info *ei;
808
809 if (type == RMAP_OSPF6)
810 {
811 ei = ((struct ospf6_route *) object)->route_option;
812 ifp = if_lookup_by_name ((char *)rule);
813
814 if (ifp != NULL
815 && ei->ifindex == ifp->ifindex)
816 return RMAP_MATCH;
817 }
818
819 return RMAP_NOMATCH;
820}
821
822/* Route map `interface' match statement. `arg' should be
823 interface name. */
824static void *
825ospf6_routemap_rule_match_interface_compile (const char *arg)
826{
827 return XSTRDUP (MTYPE_ROUTE_MAP_COMPILED, arg);
828}
829
830/* Free route map's compiled `interface' value. */
831static void
832ospf6_routemap_rule_match_interface_free (void *rule)
833{
834 XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
835}
836
837/* Route map commands for interface matching. */
838struct route_map_rule_cmd
839ospf6_routemap_rule_match_interface_cmd =
840{
841 "interface",
842 ospf6_routemap_rule_match_interface,
843 ospf6_routemap_rule_match_interface_compile,
844 ospf6_routemap_rule_match_interface_free
845};
846
Paul Jakma6ac29a52008-08-15 13:45:30 +0100847static route_map_result_t
hasso508e53e2004-05-18 18:57:06 +0000848ospf6_routemap_rule_set_metric_type (void *rule, struct prefix *prefix,
849 route_map_object_t type, void *object)
850{
851 char *metric_type = rule;
852 struct ospf6_route *route = object;
hassoe26bbeb2003-05-25 21:39:29 +0000853
hasso508e53e2004-05-18 18:57:06 +0000854 if (type != RMAP_OSPF6)
855 return RMAP_OKAY;
paul718e3742002-12-13 20:15:29 +0000856
hasso508e53e2004-05-18 18:57:06 +0000857 if (strcmp (metric_type, "type-2") == 0)
858 route->path.metric_type = 2;
paul718e3742002-12-13 20:15:29 +0000859 else
hasso508e53e2004-05-18 18:57:06 +0000860 route->path.metric_type = 1;
paul718e3742002-12-13 20:15:29 +0000861
hasso508e53e2004-05-18 18:57:06 +0000862 return RMAP_OKAY;
863}
paul718e3742002-12-13 20:15:29 +0000864
Paul Jakma6ac29a52008-08-15 13:45:30 +0100865static void *
paul0c083ee2004-10-10 12:54:58 +0000866ospf6_routemap_rule_set_metric_type_compile (const char *arg)
hasso508e53e2004-05-18 18:57:06 +0000867{
868 if (strcmp (arg, "type-2") && strcmp (arg, "type-1"))
869 return NULL;
870 return XSTRDUP (MTYPE_ROUTE_MAP_COMPILED, arg);
paul718e3742002-12-13 20:15:29 +0000871}
872
Paul Jakma6ac29a52008-08-15 13:45:30 +0100873static void
hasso508e53e2004-05-18 18:57:06 +0000874ospf6_routemap_rule_set_metric_type_free (void *rule)
paul718e3742002-12-13 20:15:29 +0000875{
hasso508e53e2004-05-18 18:57:06 +0000876 XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
877}
paul718e3742002-12-13 20:15:29 +0000878
hasso508e53e2004-05-18 18:57:06 +0000879struct route_map_rule_cmd
880ospf6_routemap_rule_set_metric_type_cmd =
881{
882 "metric-type",
883 ospf6_routemap_rule_set_metric_type,
884 ospf6_routemap_rule_set_metric_type_compile,
885 ospf6_routemap_rule_set_metric_type_free,
886};
paul718e3742002-12-13 20:15:29 +0000887
Paul Jakma6ac29a52008-08-15 13:45:30 +0100888static route_map_result_t
hasso508e53e2004-05-18 18:57:06 +0000889ospf6_routemap_rule_set_metric (void *rule, struct prefix *prefix,
890 route_map_object_t type, void *object)
891{
892 char *metric = rule;
893 struct ospf6_route *route = object;
paul718e3742002-12-13 20:15:29 +0000894
hasso508e53e2004-05-18 18:57:06 +0000895 if (type != RMAP_OSPF6)
896 return RMAP_OKAY;
paul718e3742002-12-13 20:15:29 +0000897
hasso508e53e2004-05-18 18:57:06 +0000898 route->path.cost = atoi (metric);
899 return RMAP_OKAY;
900}
paul718e3742002-12-13 20:15:29 +0000901
Paul Jakma6ac29a52008-08-15 13:45:30 +0100902static void *
paul0c083ee2004-10-10 12:54:58 +0000903ospf6_routemap_rule_set_metric_compile (const char *arg)
hasso508e53e2004-05-18 18:57:06 +0000904{
905 u_int32_t metric;
906 char *endp;
907 metric = strtoul (arg, &endp, 0);
Dinesh Dutt8551e6d2013-10-22 17:42:18 -0700908 if (metric > OSPF_LS_INFINITY || *endp != '\0')
hasso508e53e2004-05-18 18:57:06 +0000909 return NULL;
910 return XSTRDUP (MTYPE_ROUTE_MAP_COMPILED, arg);
paul718e3742002-12-13 20:15:29 +0000911}
912
Paul Jakma6ac29a52008-08-15 13:45:30 +0100913static void
hasso508e53e2004-05-18 18:57:06 +0000914ospf6_routemap_rule_set_metric_free (void *rule)
paul718e3742002-12-13 20:15:29 +0000915{
hasso508e53e2004-05-18 18:57:06 +0000916 XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
917}
918
919struct route_map_rule_cmd
920ospf6_routemap_rule_set_metric_cmd =
921{
922 "metric",
923 ospf6_routemap_rule_set_metric,
924 ospf6_routemap_rule_set_metric_compile,
925 ospf6_routemap_rule_set_metric_free,
926};
927
Paul Jakma6ac29a52008-08-15 13:45:30 +0100928static route_map_result_t
hasso508e53e2004-05-18 18:57:06 +0000929ospf6_routemap_rule_set_forwarding (void *rule, struct prefix *prefix,
930 route_map_object_t type, void *object)
931{
932 char *forwarding = rule;
933 struct ospf6_route *route = object;
934 struct ospf6_external_info *info = route->route_option;
935
936 if (type != RMAP_OSPF6)
937 return RMAP_OKAY;
938
939 if (inet_pton (AF_INET6, forwarding, &info->forwarding) != 1)
940 {
941 memset (&info->forwarding, 0, sizeof (struct in6_addr));
942 return RMAP_ERROR;
943 }
944
945 return RMAP_OKAY;
946}
947
Paul Jakma6ac29a52008-08-15 13:45:30 +0100948static void *
paul0c083ee2004-10-10 12:54:58 +0000949ospf6_routemap_rule_set_forwarding_compile (const char *arg)
hasso508e53e2004-05-18 18:57:06 +0000950{
951 struct in6_addr a;
952 if (inet_pton (AF_INET6, arg, &a) != 1)
953 return NULL;
954 return XSTRDUP (MTYPE_ROUTE_MAP_COMPILED, arg);
955}
956
Paul Jakma6ac29a52008-08-15 13:45:30 +0100957static void
hasso508e53e2004-05-18 18:57:06 +0000958ospf6_routemap_rule_set_forwarding_free (void *rule)
959{
960 XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
961}
962
963struct route_map_rule_cmd
964ospf6_routemap_rule_set_forwarding_cmd =
965{
966 "forwarding-address",
967 ospf6_routemap_rule_set_forwarding,
968 ospf6_routemap_rule_set_forwarding_compile,
969 ospf6_routemap_rule_set_forwarding_free,
970};
971
Paul Jakma6ac29a52008-08-15 13:45:30 +0100972static int
hasso508e53e2004-05-18 18:57:06 +0000973route_map_command_status (struct vty *vty, int ret)
974{
975 if (! ret)
976 return CMD_SUCCESS;
977
978 switch (ret)
979 {
980 case RMAP_RULE_MISSING:
Daniel Waltonc7f25b92015-05-19 17:47:22 -0700981 vty_out (vty, "OSPF6 Can't find rule.%s", VNL);
hasso508e53e2004-05-18 18:57:06 +0000982 break;
983 case RMAP_COMPILE_ERROR:
Daniel Waltonc7f25b92015-05-19 17:47:22 -0700984 vty_out (vty, "OSPF6 Argument is malformed.%s", VNL);
hasso508e53e2004-05-18 18:57:06 +0000985 break;
986 default:
Daniel Waltonc7f25b92015-05-19 17:47:22 -0700987 vty_out (vty, "OSPF6 route-map add set failed.%s", VNL);
hasso508e53e2004-05-18 18:57:06 +0000988 break;
989 }
990 return CMD_WARNING;
991}
992
993/* add "match address" */
994DEFUN (ospf6_routemap_match_address_prefixlist,
995 ospf6_routemap_match_address_prefixlist_cmd,
996 "match ipv6 address prefix-list WORD",
997 "Match values\n"
998 IPV6_STR
999 "Match address of route\n"
1000 "Match entries of prefix-lists\n"
1001 "IPv6 prefix-list name\n")
1002{
1003 int ret = route_map_add_match ((struct route_map_index *) vty->index,
1004 "ipv6 address prefix-list", argv[0]);
1005 return route_map_command_status (vty, ret);
1006}
1007
1008/* delete "match address" */
1009DEFUN (ospf6_routemap_no_match_address_prefixlist,
1010 ospf6_routemap_no_match_address_prefixlist_cmd,
1011 "no match ipv6 address prefix-list WORD",
1012 NO_STR
1013 "Match values\n"
1014 IPV6_STR
1015 "Match address of route\n"
1016 "Match entries of prefix-lists\n"
1017 "IPv6 prefix-list name\n")
1018{
1019 int ret = route_map_delete_match ((struct route_map_index *) vty->index,
1020 "ipv6 address prefix-list", argv[0]);
1021 return route_map_command_status (vty, ret);
1022}
1023
Vyacheslav Trushkin42a7deb2011-11-16 14:22:03 +04001024/* "match interface" */
1025DEFUN (ospf6_routemap_match_interface,
1026 ospf6_routemap_match_interface_cmd,
1027 "match interface WORD",
1028 MATCH_STR
1029 "Match first hop interface of route\n"
1030 "Interface name\n")
1031{
1032 return route_map_add_match ((struct route_map_index *) vty->index,
1033 "interface", argv[0]);
1034}
1035
1036/* "no match interface WORD" */
1037DEFUN (ospf6_routemap_no_match_interface,
1038 ospf6_routemap_no_match_interface_cmd,
1039 "no match interface",
1040 MATCH_STR
1041 NO_STR
1042 "Match first hop interface of route\n")
1043{
1044 int ret = route_map_delete_match ((struct route_map_index *) vty->index,
1045 "interface", (argc == 0) ? NULL : argv[0]);
1046 return route_map_command_status (vty, ret);
1047}
1048
1049ALIAS (ospf6_routemap_no_match_interface,
1050 ospf6_routemap_no_match_interface_val_cmd,
1051 "no match interface WORD",
1052 MATCH_STR
1053 NO_STR
1054 "Match first hop interface of route\n"
1055 "Interface name\n")
1056
hasso508e53e2004-05-18 18:57:06 +00001057/* add "set metric-type" */
1058DEFUN (ospf6_routemap_set_metric_type,
1059 ospf6_routemap_set_metric_type_cmd,
1060 "set metric-type (type-1|type-2)",
1061 "Set value\n"
1062 "Type of metric\n"
1063 "OSPF6 external type 1 metric\n"
1064 "OSPF6 external type 2 metric\n")
1065{
1066 int ret = route_map_add_set ((struct route_map_index *) vty->index,
1067 "metric-type", argv[0]);
1068 return route_map_command_status (vty, ret);
1069}
1070
1071/* delete "set metric-type" */
1072DEFUN (ospf6_routemap_no_set_metric_type,
1073 ospf6_routemap_no_set_metric_type_cmd,
1074 "no set metric-type (type-1|type-2)",
1075 NO_STR
1076 "Set value\n"
1077 "Type of metric\n"
1078 "OSPF6 external type 1 metric\n"
1079 "OSPF6 external type 2 metric\n")
1080{
1081 int ret = route_map_delete_set ((struct route_map_index *) vty->index,
1082 "metric-type", argv[0]);
1083 return route_map_command_status (vty, ret);
1084}
1085
1086/* add "set metric" */
1087DEFUN (set_metric,
1088 set_metric_cmd,
1089 "set metric <0-4294967295>",
1090 "Set value\n"
1091 "Metric value\n"
1092 "Metric value\n")
1093{
1094 int ret = route_map_add_set ((struct route_map_index *) vty->index,
1095 "metric", argv[0]);
1096 return route_map_command_status (vty, ret);
1097}
1098
1099/* delete "set metric" */
1100DEFUN (no_set_metric,
1101 no_set_metric_cmd,
Daniel Walton62f936e2015-11-09 20:21:59 -05001102 "no set metric",
hasso508e53e2004-05-18 18:57:06 +00001103 NO_STR
Daniel Walton62f936e2015-11-09 20:21:59 -05001104 SET_STR
1105 "Metric value for destination routing protocol\n")
hasso508e53e2004-05-18 18:57:06 +00001106{
Daniel Walton62f936e2015-11-09 20:21:59 -05001107 int ret = 0;
1108
1109 if (argc == 0)
1110 ret = route_map_delete_set ((struct route_map_index *) vty->index,
1111 "metric", NULL);
1112 else
1113 ret = route_map_delete_set ((struct route_map_index *) vty->index,
1114 "metric", argv[0]);
hasso508e53e2004-05-18 18:57:06 +00001115 return route_map_command_status (vty, ret);
1116}
1117
Daniel Walton62f936e2015-11-09 20:21:59 -05001118ALIAS (no_set_metric,
1119 no_set_metric_val_cmd,
1120 "no set metric <0-4294967295>",
1121 NO_STR
1122 SET_STR
1123 "Metric value for destination routing protocol\n"
1124 "Metric value\n")
1125
hasso508e53e2004-05-18 18:57:06 +00001126/* add "set forwarding-address" */
1127DEFUN (ospf6_routemap_set_forwarding,
1128 ospf6_routemap_set_forwarding_cmd,
1129 "set forwarding-address X:X::X:X",
1130 "Set value\n"
1131 "Forwarding Address\n"
1132 "IPv6 Address\n")
1133{
1134 int ret = route_map_add_set ((struct route_map_index *) vty->index,
1135 "forwarding-address", argv[0]);
1136 return route_map_command_status (vty, ret);
1137}
1138
1139/* delete "set forwarding-address" */
1140DEFUN (ospf6_routemap_no_set_forwarding,
1141 ospf6_routemap_no_set_forwarding_cmd,
1142 "no set forwarding-address X:X::X:X",
1143 NO_STR
1144 "Set value\n"
1145 "Forwarding Address\n"
1146 "IPv6 Address\n")
1147{
1148 int ret = route_map_delete_set ((struct route_map_index *) vty->index,
1149 "forwarding-address", argv[0]);
1150 return route_map_command_status (vty, ret);
1151}
1152
Paul Jakma6ac29a52008-08-15 13:45:30 +01001153static void
1154ospf6_routemap_init (void)
hasso508e53e2004-05-18 18:57:06 +00001155{
1156 route_map_init ();
1157 route_map_init_vty ();
1158 route_map_add_hook (ospf6_asbr_routemap_update);
1159 route_map_delete_hook (ospf6_asbr_routemap_update);
1160
1161 route_map_install_match (&ospf6_routemap_rule_match_address_prefixlist_cmd);
Vyacheslav Trushkin42a7deb2011-11-16 14:22:03 +04001162 route_map_install_match (&ospf6_routemap_rule_match_interface_cmd);
1163
hasso508e53e2004-05-18 18:57:06 +00001164 route_map_install_set (&ospf6_routemap_rule_set_metric_type_cmd);
1165 route_map_install_set (&ospf6_routemap_rule_set_metric_cmd);
1166 route_map_install_set (&ospf6_routemap_rule_set_forwarding_cmd);
1167
1168 /* Match address prefix-list */
1169 install_element (RMAP_NODE, &ospf6_routemap_match_address_prefixlist_cmd);
1170 install_element (RMAP_NODE, &ospf6_routemap_no_match_address_prefixlist_cmd);
1171
Vyacheslav Trushkin42a7deb2011-11-16 14:22:03 +04001172 /* Match interface */
1173 install_element (RMAP_NODE, &ospf6_routemap_match_interface_cmd);
1174 install_element (RMAP_NODE, &ospf6_routemap_no_match_interface_cmd);
1175 install_element (RMAP_NODE, &ospf6_routemap_no_match_interface_val_cmd);
1176
hasso508e53e2004-05-18 18:57:06 +00001177 /* ASE Metric Type (e.g. Type-1/Type-2) */
1178 install_element (RMAP_NODE, &ospf6_routemap_set_metric_type_cmd);
1179 install_element (RMAP_NODE, &ospf6_routemap_no_set_metric_type_cmd);
1180
1181 /* ASE Metric */
1182 install_element (RMAP_NODE, &set_metric_cmd);
1183 install_element (RMAP_NODE, &no_set_metric_cmd);
Daniel Walton62f936e2015-11-09 20:21:59 -05001184 install_element (RMAP_NODE, &no_set_metric_val_cmd);
hasso508e53e2004-05-18 18:57:06 +00001185
1186 /* ASE Metric */
1187 install_element (RMAP_NODE, &ospf6_routemap_set_forwarding_cmd);
1188 install_element (RMAP_NODE, &ospf6_routemap_no_set_forwarding_cmd);
1189}
1190
David Lamparter6b0655a2014-06-04 06:53:35 +02001191
hasso508e53e2004-05-18 18:57:06 +00001192/* Display functions */
Dinesh Dutte68a6762013-08-25 03:03:23 +00001193static char *
1194ospf6_as_external_lsa_get_prefix_str (struct ospf6_lsa *lsa, char *buf,
1195 int buflen, int pos)
1196{
1197 struct ospf6_as_external_lsa *external;
1198 struct in6_addr in6;
1199 int prefix_length = 0;
1200
1201 if (lsa)
1202 {
1203 external = (struct ospf6_as_external_lsa *)
1204 OSPF6_LSA_HEADER_END (lsa->header);
1205
1206 if (pos == 0)
1207 {
1208 ospf6_prefix_in6_addr (&in6, &external->prefix);
1209 prefix_length = external->prefix.prefix_length;
1210 }
1211 else {
1212 in6 = *((struct in6_addr *)
1213 ((caddr_t) external + sizeof (struct ospf6_as_external_lsa) +
1214 OSPF6_PREFIX_SPACE (external->prefix.prefix_length)));
1215 }
1216 if (buf)
1217 {
1218 inet_ntop (AF_INET6, &in6, buf, buflen);
1219 if (prefix_length)
1220 sprintf (&buf[strlen(buf)], "/%d", prefix_length);
1221 }
1222 }
1223 return (buf);
1224}
1225
Paul Jakma6ac29a52008-08-15 13:45:30 +01001226static int
hasso508e53e2004-05-18 18:57:06 +00001227ospf6_as_external_lsa_show (struct vty *vty, struct ospf6_lsa *lsa)
1228{
1229 struct ospf6_as_external_lsa *external;
paul718e3742002-12-13 20:15:29 +00001230 char buf[64];
paul718e3742002-12-13 20:15:29 +00001231
1232 assert (lsa->header);
hasso508e53e2004-05-18 18:57:06 +00001233 external = (struct ospf6_as_external_lsa *)
1234 OSPF6_LSA_HEADER_END (lsa->header);
paul718e3742002-12-13 20:15:29 +00001235
1236 /* bits */
hasso508e53e2004-05-18 18:57:06 +00001237 snprintf (buf, sizeof (buf), "%c%c%c",
1238 (CHECK_FLAG (external->bits_metric, OSPF6_ASBR_BIT_E) ? 'E' : '-'),
1239 (CHECK_FLAG (external->bits_metric, OSPF6_ASBR_BIT_F) ? 'F' : '-'),
1240 (CHECK_FLAG (external->bits_metric, OSPF6_ASBR_BIT_T) ? 'T' : '-'));
paul718e3742002-12-13 20:15:29 +00001241
hasso049207c2004-08-04 20:02:13 +00001242 vty_out (vty, " Bits: %s%s", buf, VNL);
hasso508e53e2004-05-18 18:57:06 +00001243 vty_out (vty, " Metric: %5lu%s", (u_long) OSPF6_ASBR_METRIC (external),
hasso049207c2004-08-04 20:02:13 +00001244 VNL);
paul718e3742002-12-13 20:15:29 +00001245
hasso508e53e2004-05-18 18:57:06 +00001246 ospf6_prefix_options_printbuf (external->prefix.prefix_options,
1247 buf, sizeof (buf));
1248 vty_out (vty, " Prefix Options: %s%s", buf,
hasso049207c2004-08-04 20:02:13 +00001249 VNL);
paul718e3742002-12-13 20:15:29 +00001250
1251 vty_out (vty, " Referenced LSType: %d%s",
hasso508e53e2004-05-18 18:57:06 +00001252 ntohs (external->prefix.prefix_refer_lstype),
hasso049207c2004-08-04 20:02:13 +00001253 VNL);
paul718e3742002-12-13 20:15:29 +00001254
Dinesh Dutte68a6762013-08-25 03:03:23 +00001255 vty_out (vty, " Prefix: %s%s",
1256 ospf6_as_external_lsa_get_prefix_str (lsa, buf, sizeof(buf), 0), VNL);
paul718e3742002-12-13 20:15:29 +00001257
1258 /* Forwarding-Address */
1259 if (CHECK_FLAG (external->bits_metric, OSPF6_ASBR_BIT_F))
1260 {
Dinesh Dutte68a6762013-08-25 03:03:23 +00001261 vty_out (vty, " Forwarding-Address: %s%s",
1262 ospf6_as_external_lsa_get_prefix_str (lsa, buf, sizeof(buf), 1),
1263 VNL);
paul718e3742002-12-13 20:15:29 +00001264 }
1265
1266 return 0;
1267}
1268
Paul Jakma6ac29a52008-08-15 13:45:30 +01001269static void
hasso508e53e2004-05-18 18:57:06 +00001270ospf6_asbr_external_route_show (struct vty *vty, struct ospf6_route *route)
paul718e3742002-12-13 20:15:29 +00001271{
hasso508e53e2004-05-18 18:57:06 +00001272 struct ospf6_external_info *info = route->route_option;
1273 char prefix[64], id[16], forwarding[64];
1274 u_int32_t tmp_id;
1275
1276 prefix2str (&route->prefix, prefix, sizeof (prefix));
1277 tmp_id = ntohl (info->id);
1278 inet_ntop (AF_INET, &tmp_id, id, sizeof (id));
1279 if (! IN6_IS_ADDR_UNSPECIFIED (&info->forwarding))
1280 inet_ntop (AF_INET6, &info->forwarding, forwarding, sizeof (forwarding));
1281 else
1282 snprintf (forwarding, sizeof (forwarding), ":: (ifindex %d)",
1283 route->nexthop[0].ifindex);
1284
ajsf52d13c2005-10-01 17:38:06 +00001285 vty_out (vty, "%c %-32s %-15s type-%d %5lu %s%s",
1286 zebra_route_char(info->type),
hasso508e53e2004-05-18 18:57:06 +00001287 prefix, id, route->path.metric_type,
1288 (u_long) (route->path.metric_type == 2 ?
1289 route->path.cost_e2 : route->path.cost),
hasso049207c2004-08-04 20:02:13 +00001290 forwarding, VNL);
paul718e3742002-12-13 20:15:29 +00001291}
1292
hasso508e53e2004-05-18 18:57:06 +00001293DEFUN (show_ipv6_ospf6_redistribute,
1294 show_ipv6_ospf6_redistribute_cmd,
1295 "show ipv6 ospf6 redistribute",
paul718e3742002-12-13 20:15:29 +00001296 SHOW_STR
1297 IP6_STR
paul718e3742002-12-13 20:15:29 +00001298 OSPF6_STR
1299 "redistributing External information\n"
1300 )
1301{
hasso508e53e2004-05-18 18:57:06 +00001302 struct ospf6_route *route;
paul718e3742002-12-13 20:15:29 +00001303
Vipin Kumarf972dec2015-05-19 18:03:41 -07001304 OSPF6_CMD_CHECK_RUNNING ();
1305
hasso508e53e2004-05-18 18:57:06 +00001306 ospf6_redistribute_show_config (vty);
1307
1308 for (route = ospf6_route_head (ospf6->external_table); route;
1309 route = ospf6_route_next (route))
1310 ospf6_asbr_external_route_show (vty, route);
1311
paul718e3742002-12-13 20:15:29 +00001312 return CMD_SUCCESS;
1313}
1314
hasso6452df02004-08-15 05:52:07 +00001315struct ospf6_lsa_handler as_external_handler =
hasso508e53e2004-05-18 18:57:06 +00001316{
hasso6452df02004-08-15 05:52:07 +00001317 OSPF6_LSTYPE_AS_EXTERNAL,
1318 "AS-External",
Dinesh Dutte68a6762013-08-25 03:03:23 +00001319 "ASE",
1320 ospf6_as_external_lsa_show,
1321 ospf6_as_external_lsa_get_prefix_str
hasso6452df02004-08-15 05:52:07 +00001322};
hasso508e53e2004-05-18 18:57:06 +00001323
paul718e3742002-12-13 20:15:29 +00001324void
Paul Jakma6ac29a52008-08-15 13:45:30 +01001325ospf6_asbr_init (void)
paul718e3742002-12-13 20:15:29 +00001326{
hasso508e53e2004-05-18 18:57:06 +00001327 ospf6_routemap_init ();
paul718e3742002-12-13 20:15:29 +00001328
hasso6452df02004-08-15 05:52:07 +00001329 ospf6_install_lsa_handler (&as_external_handler);
paul718e3742002-12-13 20:15:29 +00001330
hasso508e53e2004-05-18 18:57:06 +00001331 install_element (VIEW_NODE, &show_ipv6_ospf6_redistribute_cmd);
hasso508e53e2004-05-18 18:57:06 +00001332
paul718e3742002-12-13 20:15:29 +00001333 install_element (OSPF6_NODE, &ospf6_redistribute_cmd);
1334 install_element (OSPF6_NODE, &ospf6_redistribute_routemap_cmd);
1335 install_element (OSPF6_NODE, &no_ospf6_redistribute_cmd);
Daniel Walton69424be2015-05-19 18:03:41 -07001336 install_element (OSPF6_NODE, &no_ospf6_redistribute_route_map_cmd);
paul718e3742002-12-13 20:15:29 +00001337}
1338
Tom Goffae2254a2010-11-10 13:01:41 -08001339void
Christian Franked9628722013-03-08 21:47:35 +01001340ospf6_asbr_redistribute_reset (void)
1341{
1342 int type;
1343
1344 for (type = 0; type < ZEBRA_ROUTE_MAX; type++)
1345 {
1346 if (type == ZEBRA_ROUTE_OSPF6)
1347 continue;
1348 if (ospf6_zebra_is_redistribute (type))
1349 ospf6_asbr_redistribute_unset(type);
1350 }
1351}
1352
1353void
Tom Goffae2254a2010-11-10 13:01:41 -08001354ospf6_asbr_terminate (void)
1355{
1356 route_map_finish ();
1357}
paul718e3742002-12-13 20:15:29 +00001358
hasso508e53e2004-05-18 18:57:06 +00001359DEFUN (debug_ospf6_asbr,
1360 debug_ospf6_asbr_cmd,
1361 "debug ospf6 asbr",
1362 DEBUG_STR
1363 OSPF6_STR
1364 "Debug OSPFv3 ASBR function\n"
1365 )
1366{
1367 OSPF6_DEBUG_ASBR_ON ();
1368 return CMD_SUCCESS;
1369}
1370
1371DEFUN (no_debug_ospf6_asbr,
1372 no_debug_ospf6_asbr_cmd,
1373 "no debug ospf6 asbr",
1374 NO_STR
1375 DEBUG_STR
1376 OSPF6_STR
1377 "Debug OSPFv3 ASBR function\n"
1378 )
1379{
1380 OSPF6_DEBUG_ASBR_OFF ();
1381 return CMD_SUCCESS;
1382}
1383
1384int
1385config_write_ospf6_debug_asbr (struct vty *vty)
1386{
1387 if (IS_OSPF6_DEBUG_ASBR)
hasso049207c2004-08-04 20:02:13 +00001388 vty_out (vty, "debug ospf6 asbr%s", VNL);
hasso508e53e2004-05-18 18:57:06 +00001389 return 0;
1390}
1391
1392void
1393install_element_ospf6_debug_asbr ()
1394{
1395 install_element (ENABLE_NODE, &debug_ospf6_asbr_cmd);
1396 install_element (ENABLE_NODE, &no_debug_ospf6_asbr_cmd);
1397 install_element (CONFIG_NODE, &debug_ospf6_asbr_cmd);
1398 install_element (CONFIG_NODE, &no_debug_ospf6_asbr_cmd);
1399}
1400
1401