1/* RIPng routemap.
2 * Copyright (C) 1999 Kunihiro Ishiguro
3 *
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 Free
18 * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
19 * 02111-1307, USA.
20 */
21
22#include <zebra.h>
23
24#include "if.h"
25#include "memory.h"
26#include "prefix.h"
27#include "routemap.h"
28#include "command.h"
29
30#include "ripngd/ripngd.h"
31
32#if 0
33/* `match interface IFNAME' */
34route_map_result_t
35route_match_interface (void *rule, struct prefix *prefix,
36		       route_map_object_t type, void *object)
37{
38  struct ripng_info *rinfo;
39  struct interface *ifp;
40  char *ifname;
41
42  if (type == ROUTE_MAP_RIPNG)
43    {
44      ifname = rule;
45      ifp = if_lookup_by_name(ifname);
46
47      if (!ifp)
48	return RM_NOMATCH;
49
50      rinfo = object;
51
52      if (rinfo->ifindex == ifp->ifindex)
53	return RM_MATCH;
54      else
55	return RM_NOMATCH;
56    }
57  return RM_NOMATCH;
58}
59
60void *
61route_match_interface_compile (char *arg)
62{
63  return XSTRDUP (MTYPE_ROUTE_MAP_COMPILED, arg);
64}
65
66void
67route_match_interface_free (void *rule)
68{
69  XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
70}
71
72struct route_map_rule_cmd route_match_interface_cmd =
73{
74  "interface",
75  route_match_interface,
76  route_match_interface_compile,
77  route_match_interface_free
78};
79#endif /* 0 */
80
81struct rip_metric_modifier
82{
83  enum
84  {
85    metric_increment,
86    metric_decrement,
87    metric_absolute
88  } type;
89
90  u_char metric;
91};
92
93route_map_result_t
94route_set_metric (void *rule, struct prefix *prefix,
95		  route_map_object_t type, void *object)
96{
97  if (type == RMAP_RIPNG)
98    {
99      struct rip_metric_modifier *mod;
100      struct ripng_info *rinfo;
101
102      mod = rule;
103      rinfo = object;
104
105      if (mod->type == metric_increment)
106	rinfo->metric += mod->metric;
107      else if (mod->type == metric_decrement)
108	rinfo->metric -= mod->metric;
109      else if (mod->type == metric_absolute)
110	rinfo->metric = mod->metric;
111
112      if (rinfo->metric < 1)
113	rinfo->metric = 1;
114      if (rinfo->metric > RIPNG_METRIC_INFINITY)
115	rinfo->metric = RIPNG_METRIC_INFINITY;
116
117      rinfo->metric_set = 1;
118    }
119  return RMAP_OKAY;
120}
121
122void *
123route_set_metric_compile (char *arg)
124{
125  int len;
126  char *pnt;
127  int type;
128  long metric;
129  char *endptr = NULL;
130  struct rip_metric_modifier *mod;
131
132  len = strlen (arg);
133  pnt = arg;
134
135  if (len == 0)
136    return NULL;
137
138  /* Examine first character. */
139  if (arg[0] == '+')
140    {
141      type = metric_increment;
142      pnt++;
143    }
144  else if (arg[0] == '-')
145    {
146      type = metric_decrement;
147      pnt++;
148    }
149  else
150    type = metric_absolute;
151
152  /* Check beginning with digit string. */
153  if (*pnt < '0' || *pnt > '9')
154    return NULL;
155
156  /* Convert string to integer. */
157  metric = strtol (pnt, &endptr, 10);
158
159  if (metric == LONG_MAX || *endptr != '\0')
160    return NULL;
161  if (metric < 0 || metric > RIPNG_METRIC_INFINITY)
162    return NULL;
163
164  mod = XMALLOC (MTYPE_ROUTE_MAP_COMPILED,
165		 sizeof (struct rip_metric_modifier));
166  mod->type = type;
167  mod->metric = metric;
168
169  return mod;
170}
171
172void
173route_set_metric_free (void *rule)
174{
175  XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
176}
177
178struct route_map_rule_cmd route_set_metric_cmd =
179{
180  "metric",
181  route_set_metric,
182  route_set_metric_compile,
183  route_set_metric_free,
184};
185
186int
187ripng_route_match_add (struct vty *vty, struct route_map_index *index,
188		       char *command, char *arg)
189{
190  int ret;
191
192  ret = route_map_add_match (index, command, arg);
193  if (ret)
194    {
195      switch (ret)
196	{
197	case RMAP_RULE_MISSING:
198	  vty_out (vty, "Can't find rule.%s", VTY_NEWLINE);
199	  return CMD_WARNING;
200	  break;
201	case RMAP_COMPILE_ERROR:
202	  vty_out (vty, "Argument is malformed.%s", VTY_NEWLINE);
203	  return CMD_WARNING;
204	  break;
205	}
206    }
207  return CMD_SUCCESS;
208}
209
210int
211ripng_route_match_delete (struct vty *vty, struct route_map_index *index,
212			  char *command, char *arg)
213{
214  int ret;
215
216  ret = route_map_delete_match (index, command, arg);
217  if (ret)
218    {
219      switch (ret)
220	{
221	case RMAP_RULE_MISSING:
222	  vty_out (vty, "Can't find rule.%s", VTY_NEWLINE);
223	  return CMD_WARNING;
224	  break;
225	case RMAP_COMPILE_ERROR:
226	  vty_out (vty, "Argument is malformed.%s", VTY_NEWLINE);
227	  return CMD_WARNING;
228	  break;
229	}
230    }
231  return CMD_SUCCESS;
232}
233
234int
235ripng_route_set_add (struct vty *vty, struct route_map_index *index,
236		     char *command, char *arg)
237{
238  int ret;
239
240  ret = route_map_add_set (index, command, arg);
241  if (ret)
242    {
243      switch (ret)
244	{
245	case RMAP_RULE_MISSING:
246	  vty_out (vty, "Can't find rule.%s", VTY_NEWLINE);
247	  return CMD_WARNING;
248	  break;
249	case RMAP_COMPILE_ERROR:
250	  vty_out (vty, "Argument is malformed.%s", VTY_NEWLINE);
251	  return CMD_WARNING;
252	  break;
253	}
254    }
255  return CMD_SUCCESS;
256}
257
258int
259ripng_route_set_delete (struct vty *vty, struct route_map_index *index,
260			char *command, char *arg)
261{
262  int ret;
263
264  ret = route_map_delete_set (index, command, arg);
265  if (ret)
266    {
267      switch (ret)
268	{
269	case RMAP_RULE_MISSING:
270	  vty_out (vty, "Can't find rule.%s", VTY_NEWLINE);
271	  return CMD_WARNING;
272	  break;
273	case RMAP_COMPILE_ERROR:
274	  vty_out (vty, "Argument is malformed.%s", VTY_NEWLINE);
275	  return CMD_WARNING;
276	  break;
277	}
278    }
279  return CMD_SUCCESS;
280}
281
282#if 0
283DEFUN (match_interface,
284       match_interface_cmd,
285       "match interface WORD",
286       "Match value\n"
287       "Interface\n"
288       "Interface name\n")
289{
290  return ripng_route_match_add (vty, vty->index, "interface", argv[0]);
291}
292
293DEFUN (no_match_interface,
294       no_match_interface_cmd,
295       "no match interface WORD",
296       NO_STR
297       "Match value\n"
298       "Interface\n"
299       "Interface name\n")
300{
301  return ripng_route_match_delete (vty, vty->index, "interface", argv[0]);
302}
303#endif /* 0 */
304
305DEFUN (set_metric,
306       set_metric_cmd,
307       "set metric <0-4294967295>",
308       "Set value\n"
309       "Metric\n"
310       "METRIC value\n")
311{
312  return ripng_route_set_add (vty, vty->index, "metric", argv[0]);
313}
314
315DEFUN (no_set_metric,
316       no_set_metric_cmd,
317       "no set metric <0-4294967295>",
318       NO_STR
319       "Set value\n"
320       "Metric\n"
321       "METRIC value\n")
322{
323  return ripng_route_set_delete (vty, vty->index, "metric", argv[0]);
324}
325
326void
327ripng_route_map_init ()
328{
329  route_map_init ();
330  route_map_init_vty ();
331
332  /* route_map_install_match (&route_match_interface_cmd); */
333  route_map_install_set (&route_set_metric_cmd);
334
335  /*
336  install_element (RMAP_NODE, &match_interface_cmd);
337  install_element (RMAP_NODE, &no_match_interface_cmd);
338  */
339
340  install_element (RMAP_NODE, &set_metric_cmd);
341  install_element (RMAP_NODE, &no_set_metric_cmd);
342}
343