1/*
2 * OSPFv3 Route-Map
3 * Copyright (C) 1999 Yasuhiro Ohara
4 *
5 * This file is part of GNU Zebra.
6 *
7 * GNU Zebra is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation; either version 2, or (at your option) any
10 * later version.
11 *
12 * GNU Zebra is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15 * General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with GNU Zebra; see the file COPYING.  If not, write to the
19 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20 * Boston, MA 02111-1307, USA.
21 */
22
23#include <zebra.h>
24
25#if 1
26#include "ospf6d.h"
27#else
28#include "log.h"
29#include "memory.h"
30#include "linklist.h"
31#include "prefix.h"
32#include "command.h"
33#include "vty.h"
34#include "routemap.h"
35#include "plist.h"
36
37#include "ospf6_top.h"
38#include "ospf6_redistribute.h"
39#endif
40
41route_map_result_t
42ospf6_routemap_rule_match_address_prefixlist (void *rule,
43                                              struct prefix *prefix,
44                                              route_map_object_t type,
45                                              void *object)
46{
47  struct prefix_list *plist;
48
49  if (type != RMAP_OSPF6)
50    return RMAP_NOMATCH;
51
52  plist = prefix_list_lookup (AFI_IP6, (char *) rule);
53
54  if (plist == NULL)
55    return RMAP_NOMATCH;
56
57  return (prefix_list_apply (plist, prefix) == PREFIX_DENY ?
58          RMAP_NOMATCH : RMAP_MATCH);
59}
60
61void *
62ospf6_routemap_rule_match_address_prefixlist_compile (char *arg)
63{
64  return XSTRDUP (MTYPE_ROUTE_MAP_COMPILED, arg);
65}
66
67void
68ospf6_routemap_rule_match_address_prefixlist_free (void *rule)
69{
70  XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
71}
72
73struct route_map_rule_cmd ospf6_routemap_rule_match_address_prefixlist_cmd =
74{
75  "ipv6 address prefix-list",
76  ospf6_routemap_rule_match_address_prefixlist,
77  ospf6_routemap_rule_match_address_prefixlist_compile,
78  ospf6_routemap_rule_match_address_prefixlist_free,
79};
80
81route_map_result_t
82ospf6_routemap_rule_set_metric_type (void *rule, struct prefix *prefix,
83                                     route_map_object_t type, void *object)
84{
85  char *metric_type = rule;
86  struct ospf6_route_req *route = object;
87
88  if (type != RMAP_OSPF6)
89    return RMAP_OKAY;
90
91  if (strcmp (metric_type, "type-2") == 0)
92    route->path.metric_type = 2;
93  else
94    route->path.metric_type = 1;
95
96  return RMAP_OKAY;
97}
98
99void *
100ospf6_routemap_rule_set_metric_type_compile (char *arg)
101{
102  return XSTRDUP (MTYPE_ROUTE_MAP_COMPILED, arg);
103}
104
105void
106ospf6_routemap_rule_set_metric_type_free (void *rule)
107{
108  XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
109}
110
111struct route_map_rule_cmd ospf6_routemap_rule_set_metric_type_cmd =
112{
113  "metric-type",
114  ospf6_routemap_rule_set_metric_type,
115  ospf6_routemap_rule_set_metric_type_compile,
116  ospf6_routemap_rule_set_metric_type_free,
117};
118
119route_map_result_t
120ospf6_routemap_rule_set_metric (void *rule, struct prefix *prefix,
121                                route_map_object_t type, void *object)
122{
123  char *metric = rule;
124  struct ospf6_route_req *route = object;
125
126  if (type != RMAP_OSPF6)
127    return RMAP_OKAY;
128
129  route->path.cost = atoi (metric);
130  route->path.cost_e2 = atoi (metric);
131
132  return RMAP_OKAY;
133}
134
135void *
136ospf6_routemap_rule_set_metric_compile (char *arg)
137{
138  return XSTRDUP (MTYPE_ROUTE_MAP_COMPILED, arg);
139}
140
141void
142ospf6_routemap_rule_set_metric_free (void *rule)
143{
144  XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
145}
146
147struct route_map_rule_cmd ospf6_routemap_rule_set_metric_cmd =
148{
149  "metric",
150  ospf6_routemap_rule_set_metric,
151  ospf6_routemap_rule_set_metric_compile,
152  ospf6_routemap_rule_set_metric_free,
153};
154
155route_map_result_t
156ospf6_routemap_rule_set_forwarding (void *rule, struct prefix *prefix,
157                                    route_map_object_t type, void *object)
158{
159  char *forwarding = rule;
160  struct ospf6_route_req *route = object;
161
162  if (type != RMAP_OSPF6)
163    return RMAP_OKAY;
164
165  if (inet_pton (AF_INET6, forwarding, &route->nexthop.address) != 1)
166    {
167      memset (&route->nexthop.address, 0, sizeof (struct in6_addr));
168      return RMAP_ERROR;
169    }
170
171  return RMAP_OKAY;
172}
173
174void *
175ospf6_routemap_rule_set_forwarding_compile (char *arg)
176{
177  return XSTRDUP (MTYPE_ROUTE_MAP_COMPILED, arg);
178}
179
180void
181ospf6_routemap_rule_set_forwarding_free (void *rule)
182{
183  XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
184}
185
186struct route_map_rule_cmd ospf6_routemap_rule_set_forwarding_cmd =
187{
188  "forwarding-address",
189  ospf6_routemap_rule_set_forwarding,
190  ospf6_routemap_rule_set_forwarding_compile,
191  ospf6_routemap_rule_set_forwarding_free,
192};
193
194int
195route_map_command_status (struct vty *vty, int ret)
196{
197  if (! ret)
198    return CMD_SUCCESS;
199
200  switch (ret)
201    {
202    case RMAP_RULE_MISSING:
203      vty_out (vty, "Can't find rule.%s", VTY_NEWLINE);
204      break;
205    case RMAP_COMPILE_ERROR:
206      vty_out (vty, "Argument is malformed.%s", VTY_NEWLINE);
207      break;
208    default:
209      vty_out (vty, "route-map add set failed.%s", VTY_NEWLINE);
210      break;
211    }
212  return CMD_WARNING;
213}
214
215/* add "match address" */
216DEFUN (ospf6_routemap_match_address_prefixlist,
217       ospf6_routemap_match_address_prefixlist_cmd,
218       "match ipv6 address prefix-list WORD",
219       "Match values\n"
220       IPV6_STR
221       "Match address of route\n"
222       "Match entries of prefix-lists\n"
223       "IPv6 prefix-list name\n")
224{
225  int ret = route_map_add_match ((struct route_map_index *) vty->index,
226                                 "ipv6 address prefix-list", argv[0]);
227  return route_map_command_status (vty, ret);
228}
229
230/* delete "match address" */
231DEFUN (ospf6_routemap_no_match_address_prefixlist,
232       ospf6_routemap_no_match_address_prefixlist_cmd,
233       "no match ipv6 address prefix-list WORD",
234       NO_STR
235       "Match values\n"
236       IPV6_STR
237       "Match address of route\n"
238       "Match entries of prefix-lists\n"
239       "IPv6 prefix-list name\n")
240{
241  int ret = route_map_delete_match ((struct route_map_index *) vty->index,
242                                    "ipv6 address prefix-list", argv[0]);
243  return route_map_command_status (vty, ret);
244}
245
246/* add "set metric-type" */
247DEFUN (ospf6_routemap_set_metric_type,
248       ospf6_routemap_set_metric_type_cmd,
249       "set metric-type (type-1|type-2)",
250       "Set value\n"
251       "Type of metric\n"
252       "OSPF6 external type 1 metric\n"
253       "OSPF6 external type 2 metric\n")
254{
255  int ret = route_map_add_set ((struct route_map_index *) vty->index,
256                               "metric-type", argv[0]);
257  return route_map_command_status (vty, ret);
258}
259
260/* delete "set metric-type" */
261DEFUN (ospf6_routemap_no_set_metric_type,
262       ospf6_routemap_no_set_metric_type_cmd,
263       "no set metric-type (type-1|type-2)",
264       NO_STR
265       "Set value\n"
266       "Type of metric\n"
267       "OSPF6 external type 1 metric\n"
268       "OSPF6 external type 2 metric\n")
269{
270  int ret = route_map_delete_set ((struct route_map_index *) vty->index,
271                                  "metric-type", argv[0]);
272  return route_map_command_status (vty, ret);
273}
274
275/* add "set metric" */
276DEFUN (set_metric,
277       set_metric_cmd,
278       "set metric <0-4294967295>",
279       "Set value\n"
280       "Metric value\n"
281       "Metric value\n")
282{
283  int ret = route_map_add_set ((struct route_map_index *) vty->index,
284                               "metric", argv[0]);
285  return route_map_command_status (vty, ret);
286}
287
288/* delete "set metric" */
289DEFUN (no_set_metric,
290       no_set_metric_cmd,
291       "no set metric <0-4294967295>",
292       NO_STR
293       "Set value\n"
294       "Metric\n"
295       "METRIC value\n")
296{
297  int ret = route_map_delete_set ((struct route_map_index *) vty->index,
298                                  "metric", argv[0]);
299  return route_map_command_status (vty, ret);
300}
301
302/* add "set forwarding-address" */
303DEFUN (ospf6_routemap_set_forwarding,
304       ospf6_routemap_set_forwarding_cmd,
305       "set forwarding-address X:X::X:X",
306       "Set value\n"
307       "Forwarding Address\n"
308       "IPv6 Address\n")
309{
310  int ret = route_map_add_set ((struct route_map_index *) vty->index,
311                               "forwarding-address", argv[0]);
312  return route_map_command_status (vty, ret);
313}
314
315/* delete "set forwarding-address" */
316DEFUN (ospf6_routemap_no_set_forwarding,
317       ospf6_routemap_no_set_forwarding_cmd,
318       "no set forwarding-address X:X::X:X",
319       NO_STR
320       "Set value\n"
321       "Forwarding Address\n"
322       "IPv6 Address\n")
323{
324  int ret = route_map_delete_set ((struct route_map_index *) vty->index,
325                                  "forwarding-address", argv[0]);
326  return route_map_command_status (vty, ret);
327}
328
329void
330ospf6_routemap_init ()
331{
332  route_map_init ();
333  route_map_init_vty ();
334  route_map_add_hook (ospf6_redistribute_routemap_update);
335  route_map_delete_hook (ospf6_redistribute_routemap_update);
336
337  route_map_install_match (&ospf6_routemap_rule_match_address_prefixlist_cmd);
338  route_map_install_set (&ospf6_routemap_rule_set_metric_type_cmd);
339  route_map_install_set (&ospf6_routemap_rule_set_metric_cmd);
340  route_map_install_set (&ospf6_routemap_rule_set_forwarding_cmd);
341
342  /* Match address prefix-list */
343  install_element (RMAP_NODE, &ospf6_routemap_match_address_prefixlist_cmd);
344  install_element (RMAP_NODE, &ospf6_routemap_no_match_address_prefixlist_cmd);
345
346  /* ASE Metric Type (e.g. Type-1/Type-2) */
347  install_element (RMAP_NODE, &ospf6_routemap_set_metric_type_cmd);
348  install_element (RMAP_NODE, &ospf6_routemap_no_set_metric_type_cmd);
349
350  /* ASE Metric */
351  install_element (RMAP_NODE, &set_metric_cmd);
352  install_element (RMAP_NODE, &no_set_metric_cmd);
353
354  /* ASE Metric */
355  install_element (RMAP_NODE, &ospf6_routemap_set_forwarding_cmd);
356  install_element (RMAP_NODE, &ospf6_routemap_no_set_forwarding_cmd);
357}
358
359