blob: 870ab1857ea12a33325cec08ae39f4d9eb7e7428 [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;
243 struct ospf6_route *route;
244 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);
277 route = ospf6_route_next (route))
278 {
279 if (route->type != OSPF6_DEST_TYPE_NETWORK)
280 continue;
281 if (route->path.origin.type != lsa->header->type)
282 continue;
283 if (route->path.origin.id != lsa->header->id)
284 continue;
285 if (route->path.origin.adv_router != lsa->header->adv_router)
286 continue;
287
hasso1e058382004-09-01 21:36:14 +0000288 if (IS_OSPF6_DEBUG_EXAMIN (AS_EXTERNAL))
hasso508e53e2004-05-18 18:57:06 +0000289 {
290 prefix2str (&route->prefix, buf, sizeof (buf));
hassoc6487d62004-12-24 06:00:11 +0000291 zlog_debug ("AS-External route remove: %s", buf);
hasso508e53e2004-05-18 18:57:06 +0000292 }
293 ospf6_route_remove (route, ospf6->route_table);
294 }
Christian Frankec78a46c2013-03-20 10:50:09 +0000295 if (route != NULL)
296 ospf6_route_unlock (route);
hasso508e53e2004-05-18 18:57:06 +0000297}
298
299void
300ospf6_asbr_lsentry_add (struct ospf6_route *asbr_entry)
301{
hasso508e53e2004-05-18 18:57:06 +0000302 struct ospf6_lsa *lsa;
303 u_int16_t type;
304 u_int32_t router;
305
Paul Jakmacb4b8842006-05-15 10:39:30 +0000306 if (! CHECK_FLAG (asbr_entry->flag, OSPF6_ROUTE_BEST))
hasso508e53e2004-05-18 18:57:06 +0000307 {
Paul Jakmacb4b8842006-05-15 10:39:30 +0000308 char buf[16];
309 inet_ntop (AF_INET, &ADV_ROUTER_IN_PREFIX (&asbr_entry->prefix),
310 buf, sizeof (buf));
311 zlog_info ("ignore non-best path: lsentry %s add", buf);
312 return;
hasso508e53e2004-05-18 18:57:06 +0000313 }
314
315 type = htons (OSPF6_LSTYPE_AS_EXTERNAL);
316 router = ospf6_linkstate_prefix_adv_router (&asbr_entry->prefix);
Paul Jakmacb4b8842006-05-15 10:39:30 +0000317 for (lsa = ospf6_lsdb_type_router_head (type, router, ospf6->lsdb); lsa;
318 lsa = ospf6_lsdb_type_router_next (type, router, lsa))
hasso508e53e2004-05-18 18:57:06 +0000319 {
320 if (! OSPF6_LSA_IS_MAXAGE (lsa))
321 ospf6_asbr_lsa_add (lsa);
322 }
hasso508e53e2004-05-18 18:57:06 +0000323}
324
325void
326ospf6_asbr_lsentry_remove (struct ospf6_route *asbr_entry)
327{
hasso508e53e2004-05-18 18:57:06 +0000328 struct ospf6_lsa *lsa;
329 u_int16_t type;
330 u_int32_t router;
331
hasso508e53e2004-05-18 18:57:06 +0000332 type = htons (OSPF6_LSTYPE_AS_EXTERNAL);
333 router = ospf6_linkstate_prefix_adv_router (&asbr_entry->prefix);
334 for (lsa = ospf6_lsdb_type_router_head (type, router, ospf6->lsdb);
335 lsa; lsa = ospf6_lsdb_type_router_next (type, router, lsa))
336 ospf6_asbr_lsa_remove (lsa);
hasso508e53e2004-05-18 18:57:06 +0000337}
338
339
David Lamparter6b0655a2014-06-04 06:53:35 +0200340
paul718e3742002-12-13 20:15:29 +0000341/* redistribute function */
hasso508e53e2004-05-18 18:57:06 +0000342
Paul Jakma6ac29a52008-08-15 13:45:30 +0100343static void
paul0c083ee2004-10-10 12:54:58 +0000344ospf6_asbr_routemap_set (int type, const char *mapname)
paul718e3742002-12-13 20:15:29 +0000345{
hasso508e53e2004-05-18 18:57:06 +0000346 if (ospf6->rmap[type].name)
347 free (ospf6->rmap[type].name);
348 ospf6->rmap[type].name = strdup (mapname);
349 ospf6->rmap[type].map = route_map_lookup_by_name (mapname);
paul718e3742002-12-13 20:15:29 +0000350}
351
Paul Jakma6ac29a52008-08-15 13:45:30 +0100352static void
paul718e3742002-12-13 20:15:29 +0000353ospf6_asbr_routemap_unset (int type)
354{
hasso508e53e2004-05-18 18:57:06 +0000355 if (ospf6->rmap[type].name)
356 free (ospf6->rmap[type].name);
357 ospf6->rmap[type].name = NULL;
358 ospf6->rmap[type].map = NULL;
paul718e3742002-12-13 20:15:29 +0000359}
360
Paul Jakma6ac29a52008-08-15 13:45:30 +0100361static void
paul0c083ee2004-10-10 12:54:58 +0000362ospf6_asbr_routemap_update (const char *mapname)
paul718e3742002-12-13 20:15:29 +0000363{
hasso508e53e2004-05-18 18:57:06 +0000364 int type;
365
366 if (ospf6 == NULL)
367 return;
368
369 for (type = 0; type < ZEBRA_ROUTE_MAX; type++)
paul718e3742002-12-13 20:15:29 +0000370 {
hasso508e53e2004-05-18 18:57:06 +0000371 if (ospf6->rmap[type].name)
372 ospf6->rmap[type].map =
373 route_map_lookup_by_name (ospf6->rmap[type].name);
paul718e3742002-12-13 20:15:29 +0000374 else
hasso508e53e2004-05-18 18:57:06 +0000375 ospf6->rmap[type].map = NULL;
376 }
377}
378
379int
380ospf6_asbr_is_asbr (struct ospf6 *o)
381{
382 return o->external_table->count;
383}
384
Paul Jakma6ac29a52008-08-15 13:45:30 +0100385static void
hasso508e53e2004-05-18 18:57:06 +0000386ospf6_asbr_redistribute_set (int type)
387{
388 ospf6_zebra_redistribute (type);
389}
390
Paul Jakma6ac29a52008-08-15 13:45:30 +0100391static void
hasso508e53e2004-05-18 18:57:06 +0000392ospf6_asbr_redistribute_unset (int type)
393{
394 struct ospf6_route *route;
395 struct ospf6_external_info *info;
396
397 ospf6_zebra_no_redistribute (type);
398
399 for (route = ospf6_route_head (ospf6->external_table); route;
400 route = ospf6_route_next (route))
401 {
402 info = route->route_option;
403 if (info->type != type)
404 continue;
405
406 ospf6_asbr_redistribute_remove (info->type, route->nexthop[0].ifindex,
407 &route->prefix);
408 }
Christian Franked9628722013-03-08 21:47:35 +0100409
410 ospf6_asbr_routemap_unset (type);
hasso508e53e2004-05-18 18:57:06 +0000411}
412
413void
Paul Jakma9099f9b2016-01-18 10:12:10 +0000414ospf6_asbr_redistribute_add (int type, ifindex_t ifindex, struct prefix *prefix,
hasso508e53e2004-05-18 18:57:06 +0000415 u_int nexthop_num, struct in6_addr *nexthop)
416{
417 int ret;
418 struct ospf6_route troute;
419 struct ospf6_external_info tinfo;
420 struct ospf6_route *route, *match;
421 struct ospf6_external_info *info;
422 struct prefix prefix_id;
423 struct route_node *node;
424 char pbuf[64], ibuf[16];
paul1eb8ef22005-04-07 07:30:20 +0000425 struct listnode *lnode, *lnnode;
hasso508e53e2004-05-18 18:57:06 +0000426 struct ospf6_area *oa;
427
428 if (! ospf6_zebra_is_redistribute (type))
429 return;
430
431 if (IS_OSPF6_DEBUG_ASBR)
432 {
433 prefix2str (prefix, pbuf, sizeof (pbuf));
hassoc6487d62004-12-24 06:00:11 +0000434 zlog_debug ("Redistribute %s (%s)", pbuf, ZROUTE_NAME (type));
hasso508e53e2004-05-18 18:57:06 +0000435 }
436
437 /* if route-map was specified but not found, do not advertise */
438 if (ospf6->rmap[type].name)
439 {
440 if (ospf6->rmap[type].map == NULL)
hasso03d52f82004-09-29 00:26:19 +0000441 ospf6_asbr_routemap_update (NULL);
hasso508e53e2004-05-18 18:57:06 +0000442 if (ospf6->rmap[type].map == NULL)
443 {
444 zlog_warn ("route-map \"%s\" not found, suppress redistributing",
445 ospf6->rmap[type].name);
446 return;
447 }
448 }
449
450 /* apply route-map */
451 if (ospf6->rmap[type].map)
452 {
453 memset (&troute, 0, sizeof (troute));
454 memset (&tinfo, 0, sizeof (tinfo));
455 troute.route_option = &tinfo;
Vyacheslav Trushkin42a7deb2011-11-16 14:22:03 +0400456 tinfo.ifindex = ifindex;
hasso508e53e2004-05-18 18:57:06 +0000457
458 ret = route_map_apply (ospf6->rmap[type].map, prefix,
459 RMAP_OSPF6, &troute);
paul47828742005-08-10 15:46:11 +0000460 if (ret == RMAP_DENYMATCH)
hasso508e53e2004-05-18 18:57:06 +0000461 {
462 if (IS_OSPF6_DEBUG_ASBR)
hassoc6487d62004-12-24 06:00:11 +0000463 zlog_debug ("Denied by route-map \"%s\"", ospf6->rmap[type].name);
hasso508e53e2004-05-18 18:57:06 +0000464 return;
465 }
466 }
467
468 match = ospf6_route_lookup (prefix, ospf6->external_table);
469 if (match)
470 {
471 info = match->route_option;
472
473 /* copy result of route-map */
474 if (ospf6->rmap[type].map)
475 {
476 if (troute.path.metric_type)
477 match->path.metric_type = troute.path.metric_type;
478 if (troute.path.cost)
479 match->path.cost = troute.path.cost;
480 if (! IN6_IS_ADDR_UNSPECIFIED (&tinfo.forwarding))
481 memcpy (&info->forwarding, &tinfo.forwarding,
482 sizeof (struct in6_addr));
483 }
484
485 info->type = type;
486 match->nexthop[0].ifindex = ifindex;
487 if (nexthop_num && nexthop)
488 memcpy (&match->nexthop[0].address, nexthop, sizeof (struct in6_addr));
489
490 /* create/update binding in external_id_table */
491 prefix_id.family = AF_INET;
492 prefix_id.prefixlen = 32;
493 prefix_id.u.prefix4.s_addr = htonl (info->id);
494 node = route_node_get (ospf6->external_id_table, &prefix_id);
495 node->info = match;
496
497 if (IS_OSPF6_DEBUG_ASBR)
498 {
499 inet_ntop (AF_INET, &prefix_id.u.prefix4, ibuf, sizeof (ibuf));
hassoc6487d62004-12-24 06:00:11 +0000500 zlog_debug ("Advertise as AS-External Id:%s", ibuf);
hasso508e53e2004-05-18 18:57:06 +0000501 }
502
hasso3b687352004-08-19 06:56:53 +0000503 match->path.origin.id = htonl (info->id);
hasso6452df02004-08-15 05:52:07 +0000504 ospf6_as_external_lsa_originate (match);
hasso508e53e2004-05-18 18:57:06 +0000505 return;
506 }
507
508 /* create new entry */
509 route = ospf6_route_create ();
510 route->type = OSPF6_DEST_TYPE_NETWORK;
511 memcpy (&route->prefix, prefix, sizeof (struct prefix));
512
513 info = (struct ospf6_external_info *)
Stephen Hemminger393deb92008-08-18 14:13:29 -0700514 XCALLOC (MTYPE_OSPF6_EXTERNAL_INFO, sizeof (struct ospf6_external_info));
hasso508e53e2004-05-18 18:57:06 +0000515 route->route_option = info;
516 info->id = ospf6->external_id++;
517
518 /* copy result of route-map */
519 if (ospf6->rmap[type].map)
520 {
521 if (troute.path.metric_type)
522 route->path.metric_type = troute.path.metric_type;
523 if (troute.path.cost)
524 route->path.cost = troute.path.cost;
525 if (! IN6_IS_ADDR_UNSPECIFIED (&tinfo.forwarding))
526 memcpy (&info->forwarding, &tinfo.forwarding,
527 sizeof (struct in6_addr));
528 }
529
530 info->type = type;
531 route->nexthop[0].ifindex = ifindex;
532 if (nexthop_num && nexthop)
533 memcpy (&route->nexthop[0].address, nexthop, sizeof (struct in6_addr));
534
535 /* create/update binding in external_id_table */
536 prefix_id.family = AF_INET;
537 prefix_id.prefixlen = 32;
538 prefix_id.u.prefix4.s_addr = htonl (info->id);
539 node = route_node_get (ospf6->external_id_table, &prefix_id);
540 node->info = route;
541
542 route = ospf6_route_add (route, ospf6->external_table);
543 route->route_option = info;
544
545 if (IS_OSPF6_DEBUG_ASBR)
546 {
547 inet_ntop (AF_INET, &prefix_id.u.prefix4, ibuf, sizeof (ibuf));
hassoc6487d62004-12-24 06:00:11 +0000548 zlog_debug ("Advertise as AS-External Id:%s", ibuf);
hasso508e53e2004-05-18 18:57:06 +0000549 }
550
hasso3b687352004-08-19 06:56:53 +0000551 route->path.origin.id = htonl (info->id);
hasso6452df02004-08-15 05:52:07 +0000552 ospf6_as_external_lsa_originate (route);
hasso508e53e2004-05-18 18:57:06 +0000553
554 /* Router-Bit (ASBR Flag) may have to be updated */
paul1eb8ef22005-04-07 07:30:20 +0000555 for (ALL_LIST_ELEMENTS (ospf6->area_list, lnode, lnnode, oa))
556 OSPF6_ROUTER_LSA_SCHEDULE (oa);
hasso508e53e2004-05-18 18:57:06 +0000557}
558
559void
Paul Jakma9099f9b2016-01-18 10:12:10 +0000560ospf6_asbr_redistribute_remove (int type, ifindex_t ifindex,
561 struct prefix *prefix)
hasso508e53e2004-05-18 18:57:06 +0000562{
563 struct ospf6_route *match;
564 struct ospf6_external_info *info = NULL;
565 struct route_node *node;
566 struct ospf6_lsa *lsa;
567 struct prefix prefix_id;
568 char pbuf[64], ibuf[16];
paul1eb8ef22005-04-07 07:30:20 +0000569 struct listnode *lnode, *lnnode;
hasso508e53e2004-05-18 18:57:06 +0000570 struct ospf6_area *oa;
571
572 match = ospf6_route_lookup (prefix, ospf6->external_table);
573 if (match == NULL)
574 {
575 if (IS_OSPF6_DEBUG_ASBR)
576 {
577 prefix2str (prefix, pbuf, sizeof (pbuf));
hassoc6487d62004-12-24 06:00:11 +0000578 zlog_debug ("No such route %s to withdraw", pbuf);
hasso508e53e2004-05-18 18:57:06 +0000579 }
580 return;
581 }
582
583 info = match->route_option;
584 assert (info);
585
586 if (info->type != type)
587 {
588 if (IS_OSPF6_DEBUG_ASBR)
589 {
590 prefix2str (prefix, pbuf, sizeof (pbuf));
hassoc6487d62004-12-24 06:00:11 +0000591 zlog_debug ("Original protocol mismatch: %s", pbuf);
hasso508e53e2004-05-18 18:57:06 +0000592 }
593 return;
594 }
595
596 if (IS_OSPF6_DEBUG_ASBR)
597 {
598 prefix2str (prefix, pbuf, sizeof (pbuf));
599 inet_ntop (AF_INET, &prefix_id.u.prefix4, ibuf, sizeof (ibuf));
hassoc6487d62004-12-24 06:00:11 +0000600 zlog_debug ("Withdraw %s (AS-External Id:%s)", pbuf, ibuf);
hasso508e53e2004-05-18 18:57:06 +0000601 }
602
603 lsa = ospf6_lsdb_lookup (htons (OSPF6_LSTYPE_AS_EXTERNAL),
604 htonl (info->id), ospf6->router_id, ospf6->lsdb);
605 if (lsa)
hasso6452df02004-08-15 05:52:07 +0000606 ospf6_lsa_purge (lsa);
hasso508e53e2004-05-18 18:57:06 +0000607
608 /* remove binding in external_id_table */
609 prefix_id.family = AF_INET;
610 prefix_id.prefixlen = 32;
611 prefix_id.u.prefix4.s_addr = htonl (info->id);
612 node = route_node_lookup (ospf6->external_id_table, &prefix_id);
613 assert (node);
614 node->info = NULL;
615 route_unlock_node (node);
616
617 ospf6_route_remove (match, ospf6->external_table);
618 XFREE (MTYPE_OSPF6_EXTERNAL_INFO, info);
619
620 /* Router-Bit (ASBR Flag) may have to be updated */
paul1eb8ef22005-04-07 07:30:20 +0000621 for (ALL_LIST_ELEMENTS (ospf6->area_list, lnode, lnnode, oa))
622 OSPF6_ROUTER_LSA_SCHEDULE (oa);
paul718e3742002-12-13 20:15:29 +0000623}
624
625DEFUN (ospf6_redistribute,
626 ospf6_redistribute_cmd,
David Lampartere0ca5fd2009-09-16 01:52:42 +0200627 "redistribute " QUAGGA_REDIST_STR_OSPF6D,
paul718e3742002-12-13 20:15:29 +0000628 "Redistribute\n"
David Lampartere0ca5fd2009-09-16 01:52:42 +0200629 QUAGGA_REDIST_HELP_STR_OSPF6D
paul718e3742002-12-13 20:15:29 +0000630 )
631{
David Lampartere0ca5fd2009-09-16 01:52:42 +0200632 int type;
paul718e3742002-12-13 20:15:29 +0000633
David Lampartere0ca5fd2009-09-16 01:52:42 +0200634 type = proto_redistnum(AFI_IP6, argv[0]);
635 if (type < 0 || type == ZEBRA_ROUTE_OSPF6)
636 return CMD_WARNING;
paul718e3742002-12-13 20:15:29 +0000637
hasso508e53e2004-05-18 18:57:06 +0000638 ospf6_asbr_redistribute_unset (type);
hasso508e53e2004-05-18 18:57:06 +0000639 ospf6_asbr_redistribute_set (type);
paul718e3742002-12-13 20:15:29 +0000640 return CMD_SUCCESS;
641}
642
643DEFUN (ospf6_redistribute_routemap,
644 ospf6_redistribute_routemap_cmd,
David Lampartere0ca5fd2009-09-16 01:52:42 +0200645 "redistribute " QUAGGA_REDIST_STR_OSPF6D " route-map WORD",
paul718e3742002-12-13 20:15:29 +0000646 "Redistribute\n"
David Lampartere0ca5fd2009-09-16 01:52:42 +0200647 QUAGGA_REDIST_HELP_STR_OSPF6D
paul718e3742002-12-13 20:15:29 +0000648 "Route map reference\n"
649 "Route map name\n"
650 )
651{
David Lampartere0ca5fd2009-09-16 01:52:42 +0200652 int type;
paul718e3742002-12-13 20:15:29 +0000653
David Lampartere0ca5fd2009-09-16 01:52:42 +0200654 type = proto_redistnum(AFI_IP6, argv[0]);
655 if (type < 0 || type == ZEBRA_ROUTE_OSPF6)
656 return CMD_WARNING;
paul718e3742002-12-13 20:15:29 +0000657
hasso508e53e2004-05-18 18:57:06 +0000658 ospf6_asbr_redistribute_unset (type);
paul718e3742002-12-13 20:15:29 +0000659 ospf6_asbr_routemap_set (type, argv[1]);
hasso508e53e2004-05-18 18:57:06 +0000660 ospf6_asbr_redistribute_set (type);
paul718e3742002-12-13 20:15:29 +0000661 return CMD_SUCCESS;
662}
663
664DEFUN (no_ospf6_redistribute,
665 no_ospf6_redistribute_cmd,
David Lampartere0ca5fd2009-09-16 01:52:42 +0200666 "no redistribute " QUAGGA_REDIST_STR_OSPF6D,
paul718e3742002-12-13 20:15:29 +0000667 NO_STR
668 "Redistribute\n"
David Lampartere0ca5fd2009-09-16 01:52:42 +0200669 QUAGGA_REDIST_HELP_STR_OSPF6D
paul718e3742002-12-13 20:15:29 +0000670 )
671{
David Lampartere0ca5fd2009-09-16 01:52:42 +0200672 int type;
paul718e3742002-12-13 20:15:29 +0000673
David Lampartere0ca5fd2009-09-16 01:52:42 +0200674 type = proto_redistnum(AFI_IP6, argv[0]);
675 if (type < 0 || type == ZEBRA_ROUTE_OSPF6)
676 return CMD_WARNING;
paul718e3742002-12-13 20:15:29 +0000677
hasso508e53e2004-05-18 18:57:06 +0000678 ospf6_asbr_redistribute_unset (type);
paul718e3742002-12-13 20:15:29 +0000679
paul718e3742002-12-13 20:15:29 +0000680 return CMD_SUCCESS;
681}
682
Daniel Walton69424be2015-05-19 18:03:41 -0700683ALIAS (no_ospf6_redistribute,
684 no_ospf6_redistribute_route_map_cmd,
685 "no redistribute " QUAGGA_REDIST_STR_OSPF6D " route-map WORD",
686 NO_STR
687 "Redistribute\n"
688 QUAGGA_REDIST_HELP_STR_OSPF6D
689 "Route map reference\n"
690 "Route map name\n")
691
paul718e3742002-12-13 20:15:29 +0000692int
693ospf6_redistribute_config_write (struct vty *vty)
694{
hasso508e53e2004-05-18 18:57:06 +0000695 int type;
paul718e3742002-12-13 20:15:29 +0000696
hasso508e53e2004-05-18 18:57:06 +0000697 for (type = 0; type < ZEBRA_ROUTE_MAX; type++)
paul718e3742002-12-13 20:15:29 +0000698 {
hasso508e53e2004-05-18 18:57:06 +0000699 if (type == ZEBRA_ROUTE_OSPF6)
700 continue;
701 if (! ospf6_zebra_is_redistribute (type))
paul718e3742002-12-13 20:15:29 +0000702 continue;
703
hasso508e53e2004-05-18 18:57:06 +0000704 if (ospf6->rmap[type].name)
paul718e3742002-12-13 20:15:29 +0000705 vty_out (vty, " redistribute %s route-map %s%s",
hasso049207c2004-08-04 20:02:13 +0000706 ZROUTE_NAME (type), ospf6->rmap[type].name, VNL);
paul718e3742002-12-13 20:15:29 +0000707 else
708 vty_out (vty, " redistribute %s%s",
hasso049207c2004-08-04 20:02:13 +0000709 ZROUTE_NAME (type), VNL);
paul718e3742002-12-13 20:15:29 +0000710 }
711
712 return 0;
713}
714
Paul Jakma6ac29a52008-08-15 13:45:30 +0100715static void
paul718e3742002-12-13 20:15:29 +0000716ospf6_redistribute_show_config (struct vty *vty)
717{
hasso508e53e2004-05-18 18:57:06 +0000718 int type;
719 int nroute[ZEBRA_ROUTE_MAX];
720 int total;
721 struct ospf6_route *route;
paul718e3742002-12-13 20:15:29 +0000722 struct ospf6_external_info *info;
paul718e3742002-12-13 20:15:29 +0000723
hasso508e53e2004-05-18 18:57:06 +0000724 total = 0;
725 for (type = 0; type < ZEBRA_ROUTE_MAX; type++)
726 nroute[type] = 0;
727 for (route = ospf6_route_head (ospf6->external_table); route;
728 route = ospf6_route_next (route))
paul718e3742002-12-13 20:15:29 +0000729 {
hasso508e53e2004-05-18 18:57:06 +0000730 info = route->route_option;
731 nroute[info->type]++;
732 total++;
paul718e3742002-12-13 20:15:29 +0000733 }
734
hasso049207c2004-08-04 20:02:13 +0000735 vty_out (vty, "Redistributing External Routes from:%s", VNL);
hasso508e53e2004-05-18 18:57:06 +0000736 for (type = 0; type < ZEBRA_ROUTE_MAX; type++)
paul718e3742002-12-13 20:15:29 +0000737 {
hasso508e53e2004-05-18 18:57:06 +0000738 if (type == ZEBRA_ROUTE_OSPF6)
739 continue;
740 if (! ospf6_zebra_is_redistribute (type))
hassoe26bbeb2003-05-25 21:39:29 +0000741 continue;
742
hasso508e53e2004-05-18 18:57:06 +0000743 if (ospf6->rmap[type].name)
744 vty_out (vty, " %d: %s with route-map \"%s\"%s%s", nroute[type],
745 ZROUTE_NAME (type), ospf6->rmap[type].name,
746 (ospf6->rmap[type].map ? "" : " (not found !)"),
hasso049207c2004-08-04 20:02:13 +0000747 VNL);
paul718e3742002-12-13 20:15:29 +0000748 else
hasso508e53e2004-05-18 18:57:06 +0000749 vty_out (vty, " %d: %s%s", nroute[type],
hasso049207c2004-08-04 20:02:13 +0000750 ZROUTE_NAME (type), VNL);
paul718e3742002-12-13 20:15:29 +0000751 }
hasso049207c2004-08-04 20:02:13 +0000752 vty_out (vty, "Total %d routes%s", total, VNL);
hasso508e53e2004-05-18 18:57:06 +0000753}
paul718e3742002-12-13 20:15:29 +0000754
paul718e3742002-12-13 20:15:29 +0000755
David Lamparter6b0655a2014-06-04 06:53:35 +0200756
hasso508e53e2004-05-18 18:57:06 +0000757/* Routemap Functions */
Paul Jakma6ac29a52008-08-15 13:45:30 +0100758static route_map_result_t
hasso508e53e2004-05-18 18:57:06 +0000759ospf6_routemap_rule_match_address_prefixlist (void *rule,
760 struct prefix *prefix,
761 route_map_object_t type,
762 void *object)
763{
764 struct prefix_list *plist;
paul718e3742002-12-13 20:15:29 +0000765
hasso508e53e2004-05-18 18:57:06 +0000766 if (type != RMAP_OSPF6)
767 return RMAP_NOMATCH;
paul718e3742002-12-13 20:15:29 +0000768
hasso508e53e2004-05-18 18:57:06 +0000769 plist = prefix_list_lookup (AFI_IP6, (char *) rule);
770 if (plist == NULL)
771 return RMAP_NOMATCH;
paul718e3742002-12-13 20:15:29 +0000772
hasso508e53e2004-05-18 18:57:06 +0000773 return (prefix_list_apply (plist, prefix) == PREFIX_DENY ?
774 RMAP_NOMATCH : RMAP_MATCH);
775}
paul718e3742002-12-13 20:15:29 +0000776
Paul Jakma6ac29a52008-08-15 13:45:30 +0100777static void *
paul0c083ee2004-10-10 12:54:58 +0000778ospf6_routemap_rule_match_address_prefixlist_compile (const char *arg)
hasso508e53e2004-05-18 18:57:06 +0000779{
780 return XSTRDUP (MTYPE_ROUTE_MAP_COMPILED, arg);
paul718e3742002-12-13 20:15:29 +0000781}
782
Paul Jakma6ac29a52008-08-15 13:45:30 +0100783static void
hasso508e53e2004-05-18 18:57:06 +0000784ospf6_routemap_rule_match_address_prefixlist_free (void *rule)
paul718e3742002-12-13 20:15:29 +0000785{
hasso508e53e2004-05-18 18:57:06 +0000786 XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
787}
paul718e3742002-12-13 20:15:29 +0000788
hasso508e53e2004-05-18 18:57:06 +0000789struct route_map_rule_cmd
790ospf6_routemap_rule_match_address_prefixlist_cmd =
791{
792 "ipv6 address prefix-list",
793 ospf6_routemap_rule_match_address_prefixlist,
794 ospf6_routemap_rule_match_address_prefixlist_compile,
795 ospf6_routemap_rule_match_address_prefixlist_free,
796};
hassoe26bbeb2003-05-25 21:39:29 +0000797
Vyacheslav Trushkin42a7deb2011-11-16 14:22:03 +0400798/* `match interface IFNAME' */
799/* Match function should return 1 if match is success else return
800 zero. */
801static route_map_result_t
802ospf6_routemap_rule_match_interface (void *rule, struct prefix *prefix,
803 route_map_object_t type, void *object)
804{
805 struct interface *ifp;
806 struct ospf6_external_info *ei;
807
808 if (type == RMAP_OSPF6)
809 {
810 ei = ((struct ospf6_route *) object)->route_option;
811 ifp = if_lookup_by_name ((char *)rule);
812
813 if (ifp != NULL
814 && ei->ifindex == ifp->ifindex)
815 return RMAP_MATCH;
816 }
817
818 return RMAP_NOMATCH;
819}
820
821/* Route map `interface' match statement. `arg' should be
822 interface name. */
823static void *
824ospf6_routemap_rule_match_interface_compile (const char *arg)
825{
826 return XSTRDUP (MTYPE_ROUTE_MAP_COMPILED, arg);
827}
828
829/* Free route map's compiled `interface' value. */
830static void
831ospf6_routemap_rule_match_interface_free (void *rule)
832{
833 XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
834}
835
836/* Route map commands for interface matching. */
837struct route_map_rule_cmd
838ospf6_routemap_rule_match_interface_cmd =
839{
840 "interface",
841 ospf6_routemap_rule_match_interface,
842 ospf6_routemap_rule_match_interface_compile,
843 ospf6_routemap_rule_match_interface_free
844};
845
Paul Jakma6ac29a52008-08-15 13:45:30 +0100846static route_map_result_t
hasso508e53e2004-05-18 18:57:06 +0000847ospf6_routemap_rule_set_metric_type (void *rule, struct prefix *prefix,
848 route_map_object_t type, void *object)
849{
850 char *metric_type = rule;
851 struct ospf6_route *route = object;
hassoe26bbeb2003-05-25 21:39:29 +0000852
hasso508e53e2004-05-18 18:57:06 +0000853 if (type != RMAP_OSPF6)
854 return RMAP_OKAY;
paul718e3742002-12-13 20:15:29 +0000855
hasso508e53e2004-05-18 18:57:06 +0000856 if (strcmp (metric_type, "type-2") == 0)
857 route->path.metric_type = 2;
paul718e3742002-12-13 20:15:29 +0000858 else
hasso508e53e2004-05-18 18:57:06 +0000859 route->path.metric_type = 1;
paul718e3742002-12-13 20:15:29 +0000860
hasso508e53e2004-05-18 18:57:06 +0000861 return RMAP_OKAY;
862}
paul718e3742002-12-13 20:15:29 +0000863
Paul Jakma6ac29a52008-08-15 13:45:30 +0100864static void *
paul0c083ee2004-10-10 12:54:58 +0000865ospf6_routemap_rule_set_metric_type_compile (const char *arg)
hasso508e53e2004-05-18 18:57:06 +0000866{
867 if (strcmp (arg, "type-2") && strcmp (arg, "type-1"))
868 return NULL;
869 return XSTRDUP (MTYPE_ROUTE_MAP_COMPILED, arg);
paul718e3742002-12-13 20:15:29 +0000870}
871
Paul Jakma6ac29a52008-08-15 13:45:30 +0100872static void
hasso508e53e2004-05-18 18:57:06 +0000873ospf6_routemap_rule_set_metric_type_free (void *rule)
paul718e3742002-12-13 20:15:29 +0000874{
hasso508e53e2004-05-18 18:57:06 +0000875 XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
876}
paul718e3742002-12-13 20:15:29 +0000877
hasso508e53e2004-05-18 18:57:06 +0000878struct route_map_rule_cmd
879ospf6_routemap_rule_set_metric_type_cmd =
880{
881 "metric-type",
882 ospf6_routemap_rule_set_metric_type,
883 ospf6_routemap_rule_set_metric_type_compile,
884 ospf6_routemap_rule_set_metric_type_free,
885};
paul718e3742002-12-13 20:15:29 +0000886
Paul Jakma6ac29a52008-08-15 13:45:30 +0100887static route_map_result_t
hasso508e53e2004-05-18 18:57:06 +0000888ospf6_routemap_rule_set_metric (void *rule, struct prefix *prefix,
889 route_map_object_t type, void *object)
890{
891 char *metric = rule;
892 struct ospf6_route *route = object;
paul718e3742002-12-13 20:15:29 +0000893
hasso508e53e2004-05-18 18:57:06 +0000894 if (type != RMAP_OSPF6)
895 return RMAP_OKAY;
paul718e3742002-12-13 20:15:29 +0000896
hasso508e53e2004-05-18 18:57:06 +0000897 route->path.cost = atoi (metric);
898 return RMAP_OKAY;
899}
paul718e3742002-12-13 20:15:29 +0000900
Paul Jakma6ac29a52008-08-15 13:45:30 +0100901static void *
paul0c083ee2004-10-10 12:54:58 +0000902ospf6_routemap_rule_set_metric_compile (const char *arg)
hasso508e53e2004-05-18 18:57:06 +0000903{
904 u_int32_t metric;
905 char *endp;
906 metric = strtoul (arg, &endp, 0);
Dinesh Dutt8551e6d2013-10-22 17:42:18 -0700907 if (metric > OSPF_LS_INFINITY || *endp != '\0')
hasso508e53e2004-05-18 18:57:06 +0000908 return NULL;
909 return XSTRDUP (MTYPE_ROUTE_MAP_COMPILED, arg);
paul718e3742002-12-13 20:15:29 +0000910}
911
Paul Jakma6ac29a52008-08-15 13:45:30 +0100912static void
hasso508e53e2004-05-18 18:57:06 +0000913ospf6_routemap_rule_set_metric_free (void *rule)
paul718e3742002-12-13 20:15:29 +0000914{
hasso508e53e2004-05-18 18:57:06 +0000915 XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
916}
917
918struct route_map_rule_cmd
919ospf6_routemap_rule_set_metric_cmd =
920{
921 "metric",
922 ospf6_routemap_rule_set_metric,
923 ospf6_routemap_rule_set_metric_compile,
924 ospf6_routemap_rule_set_metric_free,
925};
926
Paul Jakma6ac29a52008-08-15 13:45:30 +0100927static route_map_result_t
hasso508e53e2004-05-18 18:57:06 +0000928ospf6_routemap_rule_set_forwarding (void *rule, struct prefix *prefix,
929 route_map_object_t type, void *object)
930{
931 char *forwarding = rule;
932 struct ospf6_route *route = object;
933 struct ospf6_external_info *info = route->route_option;
934
935 if (type != RMAP_OSPF6)
936 return RMAP_OKAY;
937
938 if (inet_pton (AF_INET6, forwarding, &info->forwarding) != 1)
939 {
940 memset (&info->forwarding, 0, sizeof (struct in6_addr));
941 return RMAP_ERROR;
942 }
943
944 return RMAP_OKAY;
945}
946
Paul Jakma6ac29a52008-08-15 13:45:30 +0100947static void *
paul0c083ee2004-10-10 12:54:58 +0000948ospf6_routemap_rule_set_forwarding_compile (const char *arg)
hasso508e53e2004-05-18 18:57:06 +0000949{
950 struct in6_addr a;
951 if (inet_pton (AF_INET6, arg, &a) != 1)
952 return NULL;
953 return XSTRDUP (MTYPE_ROUTE_MAP_COMPILED, arg);
954}
955
Paul Jakma6ac29a52008-08-15 13:45:30 +0100956static void
hasso508e53e2004-05-18 18:57:06 +0000957ospf6_routemap_rule_set_forwarding_free (void *rule)
958{
959 XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
960}
961
962struct route_map_rule_cmd
963ospf6_routemap_rule_set_forwarding_cmd =
964{
965 "forwarding-address",
966 ospf6_routemap_rule_set_forwarding,
967 ospf6_routemap_rule_set_forwarding_compile,
968 ospf6_routemap_rule_set_forwarding_free,
969};
970
Paul Jakma6ac29a52008-08-15 13:45:30 +0100971static int
hasso508e53e2004-05-18 18:57:06 +0000972route_map_command_status (struct vty *vty, int ret)
973{
974 if (! ret)
975 return CMD_SUCCESS;
976
977 switch (ret)
978 {
979 case RMAP_RULE_MISSING:
hasso049207c2004-08-04 20:02:13 +0000980 vty_out (vty, "Can't find rule.%s", VNL);
hasso508e53e2004-05-18 18:57:06 +0000981 break;
982 case RMAP_COMPILE_ERROR:
hasso049207c2004-08-04 20:02:13 +0000983 vty_out (vty, "Argument is malformed.%s", VNL);
hasso508e53e2004-05-18 18:57:06 +0000984 break;
985 default:
hasso049207c2004-08-04 20:02:13 +0000986 vty_out (vty, "route-map add set failed.%s", VNL);
hasso508e53e2004-05-18 18:57:06 +0000987 break;
988 }
989 return CMD_WARNING;
990}
991
992/* add "match address" */
993DEFUN (ospf6_routemap_match_address_prefixlist,
994 ospf6_routemap_match_address_prefixlist_cmd,
995 "match ipv6 address prefix-list WORD",
996 "Match values\n"
997 IPV6_STR
998 "Match address of route\n"
999 "Match entries of prefix-lists\n"
1000 "IPv6 prefix-list name\n")
1001{
1002 int ret = route_map_add_match ((struct route_map_index *) vty->index,
1003 "ipv6 address prefix-list", argv[0]);
1004 return route_map_command_status (vty, ret);
1005}
1006
1007/* delete "match address" */
1008DEFUN (ospf6_routemap_no_match_address_prefixlist,
1009 ospf6_routemap_no_match_address_prefixlist_cmd,
1010 "no match ipv6 address prefix-list WORD",
1011 NO_STR
1012 "Match values\n"
1013 IPV6_STR
1014 "Match address of route\n"
1015 "Match entries of prefix-lists\n"
1016 "IPv6 prefix-list name\n")
1017{
1018 int ret = route_map_delete_match ((struct route_map_index *) vty->index,
1019 "ipv6 address prefix-list", argv[0]);
1020 return route_map_command_status (vty, ret);
1021}
1022
Vyacheslav Trushkin42a7deb2011-11-16 14:22:03 +04001023/* "match interface" */
1024DEFUN (ospf6_routemap_match_interface,
1025 ospf6_routemap_match_interface_cmd,
1026 "match interface WORD",
1027 MATCH_STR
1028 "Match first hop interface of route\n"
1029 "Interface name\n")
1030{
1031 return route_map_add_match ((struct route_map_index *) vty->index,
1032 "interface", argv[0]);
1033}
1034
1035/* "no match interface WORD" */
1036DEFUN (ospf6_routemap_no_match_interface,
1037 ospf6_routemap_no_match_interface_cmd,
1038 "no match interface",
1039 MATCH_STR
1040 NO_STR
1041 "Match first hop interface of route\n")
1042{
1043 int ret = route_map_delete_match ((struct route_map_index *) vty->index,
1044 "interface", (argc == 0) ? NULL : argv[0]);
1045 return route_map_command_status (vty, ret);
1046}
1047
1048ALIAS (ospf6_routemap_no_match_interface,
1049 ospf6_routemap_no_match_interface_val_cmd,
1050 "no match interface WORD",
1051 MATCH_STR
1052 NO_STR
1053 "Match first hop interface of route\n"
1054 "Interface name\n")
1055
hasso508e53e2004-05-18 18:57:06 +00001056/* add "set metric-type" */
1057DEFUN (ospf6_routemap_set_metric_type,
1058 ospf6_routemap_set_metric_type_cmd,
1059 "set metric-type (type-1|type-2)",
1060 "Set value\n"
1061 "Type of metric\n"
1062 "OSPF6 external type 1 metric\n"
1063 "OSPF6 external type 2 metric\n")
1064{
1065 int ret = route_map_add_set ((struct route_map_index *) vty->index,
1066 "metric-type", argv[0]);
1067 return route_map_command_status (vty, ret);
1068}
1069
1070/* delete "set metric-type" */
1071DEFUN (ospf6_routemap_no_set_metric_type,
1072 ospf6_routemap_no_set_metric_type_cmd,
1073 "no set metric-type (type-1|type-2)",
1074 NO_STR
1075 "Set value\n"
1076 "Type of metric\n"
1077 "OSPF6 external type 1 metric\n"
1078 "OSPF6 external type 2 metric\n")
1079{
1080 int ret = route_map_delete_set ((struct route_map_index *) vty->index,
1081 "metric-type", argv[0]);
1082 return route_map_command_status (vty, ret);
1083}
1084
1085/* add "set metric" */
1086DEFUN (set_metric,
1087 set_metric_cmd,
1088 "set metric <0-4294967295>",
1089 "Set value\n"
1090 "Metric value\n"
1091 "Metric value\n")
1092{
1093 int ret = route_map_add_set ((struct route_map_index *) vty->index,
1094 "metric", argv[0]);
1095 return route_map_command_status (vty, ret);
1096}
1097
1098/* delete "set metric" */
1099DEFUN (no_set_metric,
1100 no_set_metric_cmd,
Daniel Walton62f936e2015-11-09 20:21:59 -05001101 "no set metric",
hasso508e53e2004-05-18 18:57:06 +00001102 NO_STR
Daniel Walton62f936e2015-11-09 20:21:59 -05001103 SET_STR
1104 "Metric value for destination routing protocol\n")
hasso508e53e2004-05-18 18:57:06 +00001105{
Daniel Walton62f936e2015-11-09 20:21:59 -05001106 int ret = 0;
1107
1108 if (argc == 0)
1109 ret = route_map_delete_set ((struct route_map_index *) vty->index,
1110 "metric", NULL);
1111 else
1112 ret = route_map_delete_set ((struct route_map_index *) vty->index,
1113 "metric", argv[0]);
hasso508e53e2004-05-18 18:57:06 +00001114 return route_map_command_status (vty, ret);
1115}
1116
Daniel Walton62f936e2015-11-09 20:21:59 -05001117ALIAS (no_set_metric,
1118 no_set_metric_val_cmd,
1119 "no set metric <0-4294967295>",
1120 NO_STR
1121 SET_STR
1122 "Metric value for destination routing protocol\n"
1123 "Metric value\n")
1124
hasso508e53e2004-05-18 18:57:06 +00001125/* add "set forwarding-address" */
1126DEFUN (ospf6_routemap_set_forwarding,
1127 ospf6_routemap_set_forwarding_cmd,
1128 "set forwarding-address X:X::X:X",
1129 "Set value\n"
1130 "Forwarding Address\n"
1131 "IPv6 Address\n")
1132{
1133 int ret = route_map_add_set ((struct route_map_index *) vty->index,
1134 "forwarding-address", argv[0]);
1135 return route_map_command_status (vty, ret);
1136}
1137
1138/* delete "set forwarding-address" */
1139DEFUN (ospf6_routemap_no_set_forwarding,
1140 ospf6_routemap_no_set_forwarding_cmd,
1141 "no set forwarding-address X:X::X:X",
1142 NO_STR
1143 "Set value\n"
1144 "Forwarding Address\n"
1145 "IPv6 Address\n")
1146{
1147 int ret = route_map_delete_set ((struct route_map_index *) vty->index,
1148 "forwarding-address", argv[0]);
1149 return route_map_command_status (vty, ret);
1150}
1151
Paul Jakma6ac29a52008-08-15 13:45:30 +01001152static void
1153ospf6_routemap_init (void)
hasso508e53e2004-05-18 18:57:06 +00001154{
1155 route_map_init ();
1156 route_map_init_vty ();
1157 route_map_add_hook (ospf6_asbr_routemap_update);
1158 route_map_delete_hook (ospf6_asbr_routemap_update);
1159
1160 route_map_install_match (&ospf6_routemap_rule_match_address_prefixlist_cmd);
Vyacheslav Trushkin42a7deb2011-11-16 14:22:03 +04001161 route_map_install_match (&ospf6_routemap_rule_match_interface_cmd);
1162
hasso508e53e2004-05-18 18:57:06 +00001163 route_map_install_set (&ospf6_routemap_rule_set_metric_type_cmd);
1164 route_map_install_set (&ospf6_routemap_rule_set_metric_cmd);
1165 route_map_install_set (&ospf6_routemap_rule_set_forwarding_cmd);
1166
1167 /* Match address prefix-list */
1168 install_element (RMAP_NODE, &ospf6_routemap_match_address_prefixlist_cmd);
1169 install_element (RMAP_NODE, &ospf6_routemap_no_match_address_prefixlist_cmd);
1170
Vyacheslav Trushkin42a7deb2011-11-16 14:22:03 +04001171 /* Match interface */
1172 install_element (RMAP_NODE, &ospf6_routemap_match_interface_cmd);
1173 install_element (RMAP_NODE, &ospf6_routemap_no_match_interface_cmd);
1174 install_element (RMAP_NODE, &ospf6_routemap_no_match_interface_val_cmd);
1175
hasso508e53e2004-05-18 18:57:06 +00001176 /* ASE Metric Type (e.g. Type-1/Type-2) */
1177 install_element (RMAP_NODE, &ospf6_routemap_set_metric_type_cmd);
1178 install_element (RMAP_NODE, &ospf6_routemap_no_set_metric_type_cmd);
1179
1180 /* ASE Metric */
1181 install_element (RMAP_NODE, &set_metric_cmd);
1182 install_element (RMAP_NODE, &no_set_metric_cmd);
Daniel Walton62f936e2015-11-09 20:21:59 -05001183 install_element (RMAP_NODE, &no_set_metric_val_cmd);
hasso508e53e2004-05-18 18:57:06 +00001184
1185 /* ASE Metric */
1186 install_element (RMAP_NODE, &ospf6_routemap_set_forwarding_cmd);
1187 install_element (RMAP_NODE, &ospf6_routemap_no_set_forwarding_cmd);
1188}
1189
David Lamparter6b0655a2014-06-04 06:53:35 +02001190
hasso508e53e2004-05-18 18:57:06 +00001191/* Display functions */
Dinesh Dutte68a6762013-08-25 03:03:23 +00001192static char *
1193ospf6_as_external_lsa_get_prefix_str (struct ospf6_lsa *lsa, char *buf,
1194 int buflen, int pos)
1195{
1196 struct ospf6_as_external_lsa *external;
1197 struct in6_addr in6;
1198 int prefix_length = 0;
1199
1200 if (lsa)
1201 {
1202 external = (struct ospf6_as_external_lsa *)
1203 OSPF6_LSA_HEADER_END (lsa->header);
1204
1205 if (pos == 0)
1206 {
1207 ospf6_prefix_in6_addr (&in6, &external->prefix);
1208 prefix_length = external->prefix.prefix_length;
1209 }
1210 else {
1211 in6 = *((struct in6_addr *)
1212 ((caddr_t) external + sizeof (struct ospf6_as_external_lsa) +
1213 OSPF6_PREFIX_SPACE (external->prefix.prefix_length)));
1214 }
1215 if (buf)
1216 {
1217 inet_ntop (AF_INET6, &in6, buf, buflen);
1218 if (prefix_length)
1219 sprintf (&buf[strlen(buf)], "/%d", prefix_length);
1220 }
1221 }
1222 return (buf);
1223}
1224
Paul Jakma6ac29a52008-08-15 13:45:30 +01001225static int
hasso508e53e2004-05-18 18:57:06 +00001226ospf6_as_external_lsa_show (struct vty *vty, struct ospf6_lsa *lsa)
1227{
1228 struct ospf6_as_external_lsa *external;
paul718e3742002-12-13 20:15:29 +00001229 char buf[64];
paul718e3742002-12-13 20:15:29 +00001230
1231 assert (lsa->header);
hasso508e53e2004-05-18 18:57:06 +00001232 external = (struct ospf6_as_external_lsa *)
1233 OSPF6_LSA_HEADER_END (lsa->header);
paul718e3742002-12-13 20:15:29 +00001234
1235 /* bits */
hasso508e53e2004-05-18 18:57:06 +00001236 snprintf (buf, sizeof (buf), "%c%c%c",
1237 (CHECK_FLAG (external->bits_metric, OSPF6_ASBR_BIT_E) ? 'E' : '-'),
1238 (CHECK_FLAG (external->bits_metric, OSPF6_ASBR_BIT_F) ? 'F' : '-'),
1239 (CHECK_FLAG (external->bits_metric, OSPF6_ASBR_BIT_T) ? 'T' : '-'));
paul718e3742002-12-13 20:15:29 +00001240
hasso049207c2004-08-04 20:02:13 +00001241 vty_out (vty, " Bits: %s%s", buf, VNL);
hasso508e53e2004-05-18 18:57:06 +00001242 vty_out (vty, " Metric: %5lu%s", (u_long) OSPF6_ASBR_METRIC (external),
hasso049207c2004-08-04 20:02:13 +00001243 VNL);
paul718e3742002-12-13 20:15:29 +00001244
hasso508e53e2004-05-18 18:57:06 +00001245 ospf6_prefix_options_printbuf (external->prefix.prefix_options,
1246 buf, sizeof (buf));
1247 vty_out (vty, " Prefix Options: %s%s", buf,
hasso049207c2004-08-04 20:02:13 +00001248 VNL);
paul718e3742002-12-13 20:15:29 +00001249
1250 vty_out (vty, " Referenced LSType: %d%s",
hasso508e53e2004-05-18 18:57:06 +00001251 ntohs (external->prefix.prefix_refer_lstype),
hasso049207c2004-08-04 20:02:13 +00001252 VNL);
paul718e3742002-12-13 20:15:29 +00001253
Dinesh Dutte68a6762013-08-25 03:03:23 +00001254 vty_out (vty, " Prefix: %s%s",
1255 ospf6_as_external_lsa_get_prefix_str (lsa, buf, sizeof(buf), 0), VNL);
paul718e3742002-12-13 20:15:29 +00001256
1257 /* Forwarding-Address */
1258 if (CHECK_FLAG (external->bits_metric, OSPF6_ASBR_BIT_F))
1259 {
Dinesh Dutte68a6762013-08-25 03:03:23 +00001260 vty_out (vty, " Forwarding-Address: %s%s",
1261 ospf6_as_external_lsa_get_prefix_str (lsa, buf, sizeof(buf), 1),
1262 VNL);
paul718e3742002-12-13 20:15:29 +00001263 }
1264
1265 return 0;
1266}
1267
Paul Jakma6ac29a52008-08-15 13:45:30 +01001268static void
hasso508e53e2004-05-18 18:57:06 +00001269ospf6_asbr_external_route_show (struct vty *vty, struct ospf6_route *route)
paul718e3742002-12-13 20:15:29 +00001270{
hasso508e53e2004-05-18 18:57:06 +00001271 struct ospf6_external_info *info = route->route_option;
1272 char prefix[64], id[16], forwarding[64];
1273 u_int32_t tmp_id;
1274
1275 prefix2str (&route->prefix, prefix, sizeof (prefix));
1276 tmp_id = ntohl (info->id);
1277 inet_ntop (AF_INET, &tmp_id, id, sizeof (id));
1278 if (! IN6_IS_ADDR_UNSPECIFIED (&info->forwarding))
1279 inet_ntop (AF_INET6, &info->forwarding, forwarding, sizeof (forwarding));
1280 else
1281 snprintf (forwarding, sizeof (forwarding), ":: (ifindex %d)",
1282 route->nexthop[0].ifindex);
1283
ajsf52d13c2005-10-01 17:38:06 +00001284 vty_out (vty, "%c %-32s %-15s type-%d %5lu %s%s",
1285 zebra_route_char(info->type),
hasso508e53e2004-05-18 18:57:06 +00001286 prefix, id, route->path.metric_type,
1287 (u_long) (route->path.metric_type == 2 ?
1288 route->path.cost_e2 : route->path.cost),
hasso049207c2004-08-04 20:02:13 +00001289 forwarding, VNL);
paul718e3742002-12-13 20:15:29 +00001290}
1291
hasso508e53e2004-05-18 18:57:06 +00001292DEFUN (show_ipv6_ospf6_redistribute,
1293 show_ipv6_ospf6_redistribute_cmd,
1294 "show ipv6 ospf6 redistribute",
paul718e3742002-12-13 20:15:29 +00001295 SHOW_STR
1296 IP6_STR
paul718e3742002-12-13 20:15:29 +00001297 OSPF6_STR
1298 "redistributing External information\n"
1299 )
1300{
hasso508e53e2004-05-18 18:57:06 +00001301 struct ospf6_route *route;
paul718e3742002-12-13 20:15:29 +00001302
Vipin Kumarf972dec2015-05-19 18:03:41 -07001303 OSPF6_CMD_CHECK_RUNNING ();
1304
hasso508e53e2004-05-18 18:57:06 +00001305 ospf6_redistribute_show_config (vty);
1306
1307 for (route = ospf6_route_head (ospf6->external_table); route;
1308 route = ospf6_route_next (route))
1309 ospf6_asbr_external_route_show (vty, route);
1310
paul718e3742002-12-13 20:15:29 +00001311 return CMD_SUCCESS;
1312}
1313
hasso6452df02004-08-15 05:52:07 +00001314struct ospf6_lsa_handler as_external_handler =
hasso508e53e2004-05-18 18:57:06 +00001315{
hasso6452df02004-08-15 05:52:07 +00001316 OSPF6_LSTYPE_AS_EXTERNAL,
1317 "AS-External",
Dinesh Dutte68a6762013-08-25 03:03:23 +00001318 "ASE",
1319 ospf6_as_external_lsa_show,
1320 ospf6_as_external_lsa_get_prefix_str
hasso6452df02004-08-15 05:52:07 +00001321};
hasso508e53e2004-05-18 18:57:06 +00001322
paul718e3742002-12-13 20:15:29 +00001323void
Paul Jakma6ac29a52008-08-15 13:45:30 +01001324ospf6_asbr_init (void)
paul718e3742002-12-13 20:15:29 +00001325{
hasso508e53e2004-05-18 18:57:06 +00001326 ospf6_routemap_init ();
paul718e3742002-12-13 20:15:29 +00001327
hasso6452df02004-08-15 05:52:07 +00001328 ospf6_install_lsa_handler (&as_external_handler);
paul718e3742002-12-13 20:15:29 +00001329
hasso508e53e2004-05-18 18:57:06 +00001330 install_element (VIEW_NODE, &show_ipv6_ospf6_redistribute_cmd);
hasso508e53e2004-05-18 18:57:06 +00001331
paul718e3742002-12-13 20:15:29 +00001332 install_element (OSPF6_NODE, &ospf6_redistribute_cmd);
1333 install_element (OSPF6_NODE, &ospf6_redistribute_routemap_cmd);
1334 install_element (OSPF6_NODE, &no_ospf6_redistribute_cmd);
Daniel Walton69424be2015-05-19 18:03:41 -07001335 install_element (OSPF6_NODE, &no_ospf6_redistribute_route_map_cmd);
paul718e3742002-12-13 20:15:29 +00001336}
1337
Tom Goffae2254a2010-11-10 13:01:41 -08001338void
Christian Franked9628722013-03-08 21:47:35 +01001339ospf6_asbr_redistribute_reset (void)
1340{
1341 int type;
1342
1343 for (type = 0; type < ZEBRA_ROUTE_MAX; type++)
1344 {
1345 if (type == ZEBRA_ROUTE_OSPF6)
1346 continue;
1347 if (ospf6_zebra_is_redistribute (type))
1348 ospf6_asbr_redistribute_unset(type);
1349 }
1350}
1351
1352void
Tom Goffae2254a2010-11-10 13:01:41 -08001353ospf6_asbr_terminate (void)
1354{
1355 route_map_finish ();
1356}
paul718e3742002-12-13 20:15:29 +00001357
hasso508e53e2004-05-18 18:57:06 +00001358DEFUN (debug_ospf6_asbr,
1359 debug_ospf6_asbr_cmd,
1360 "debug ospf6 asbr",
1361 DEBUG_STR
1362 OSPF6_STR
1363 "Debug OSPFv3 ASBR function\n"
1364 )
1365{
1366 OSPF6_DEBUG_ASBR_ON ();
1367 return CMD_SUCCESS;
1368}
1369
1370DEFUN (no_debug_ospf6_asbr,
1371 no_debug_ospf6_asbr_cmd,
1372 "no debug ospf6 asbr",
1373 NO_STR
1374 DEBUG_STR
1375 OSPF6_STR
1376 "Debug OSPFv3 ASBR function\n"
1377 )
1378{
1379 OSPF6_DEBUG_ASBR_OFF ();
1380 return CMD_SUCCESS;
1381}
1382
1383int
1384config_write_ospf6_debug_asbr (struct vty *vty)
1385{
1386 if (IS_OSPF6_DEBUG_ASBR)
hasso049207c2004-08-04 20:02:13 +00001387 vty_out (vty, "debug ospf6 asbr%s", VNL);
hasso508e53e2004-05-18 18:57:06 +00001388 return 0;
1389}
1390
1391void
1392install_element_ospf6_debug_asbr ()
1393{
1394 install_element (ENABLE_NODE, &debug_ospf6_asbr_cmd);
1395 install_element (ENABLE_NODE, &no_debug_ospf6_asbr_cmd);
1396 install_element (CONFIG_NODE, &debug_ospf6_asbr_cmd);
1397 install_element (CONFIG_NODE, &no_debug_ospf6_asbr_cmd);
1398}
1399
1400