blob: 9bb963881a807c0f46bc01c420f6fbcac4790b7a [file] [log] [blame]
paul718e3742002-12-13 20:15:29 +00001/* RIPv2 routemap.
vincentfbf5d032005-09-29 11:25:50 +00002 * Copyright (C) 2005 6WIND <alain.ritoux@6wind.com>
paul718e3742002-12-13 20:15:29 +00003 * Copyright (C) 1999 Kunihiro Ishiguro <kunihiro@zebra.org>
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 Free
19 * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
20 * 02111-1307, USA.
21 */
22
23#include <zebra.h>
24
25#include "memory.h"
26#include "prefix.h"
27#include "routemap.h"
28#include "command.h"
29#include "filter.h"
30#include "log.h"
31#include "sockunion.h" /* for inet_aton () */
32#include "plist.h"
33
34#include "ripd/ripd.h"
David Lamparter6b0655a2014-06-04 06:53:35 +020035
hasso16705132003-05-25 14:49:19 +000036struct rip_metric_modifier
37{
38 enum
39 {
40 metric_increment,
41 metric_decrement,
42 metric_absolute
43 } type;
44
45 u_char metric;
46};
paul718e3742002-12-13 20:15:29 +000047
48/* Add rip route map rule. */
pauldc63bfd2005-10-25 23:31:05 +000049static int
paul718e3742002-12-13 20:15:29 +000050rip_route_match_add (struct vty *vty, struct route_map_index *index,
hasso98b718a2004-10-11 12:57:57 +000051 const char *command, const char *arg)
paul718e3742002-12-13 20:15:29 +000052{
53 int ret;
54
55 ret = route_map_add_match (index, command, arg);
56 if (ret)
57 {
58 switch (ret)
59 {
60 case RMAP_RULE_MISSING:
61 vty_out (vty, "%% Can't find rule.%s", VTY_NEWLINE);
62 return CMD_WARNING;
paul718e3742002-12-13 20:15:29 +000063 case RMAP_COMPILE_ERROR:
64 vty_out (vty, "%% Argument is malformed.%s", VTY_NEWLINE);
65 return CMD_WARNING;
paul718e3742002-12-13 20:15:29 +000066 }
67 }
68 return CMD_SUCCESS;
69}
70
71/* Delete rip route map rule. */
pauldc63bfd2005-10-25 23:31:05 +000072static int
paul718e3742002-12-13 20:15:29 +000073rip_route_match_delete (struct vty *vty, struct route_map_index *index,
hasso98b718a2004-10-11 12:57:57 +000074 const char *command, const char *arg)
paul718e3742002-12-13 20:15:29 +000075{
76 int ret;
77
78 ret = route_map_delete_match (index, command, arg);
79 if (ret)
80 {
81 switch (ret)
82 {
83 case RMAP_RULE_MISSING:
84 vty_out (vty, "%% Can't find rule.%s", VTY_NEWLINE);
85 return CMD_WARNING;
paul718e3742002-12-13 20:15:29 +000086 case RMAP_COMPILE_ERROR:
87 vty_out (vty, "%% Argument is malformed.%s", VTY_NEWLINE);
88 return CMD_WARNING;
paul718e3742002-12-13 20:15:29 +000089 }
90 }
91 return CMD_SUCCESS;
92}
93
94/* Add rip route map rule. */
pauldc63bfd2005-10-25 23:31:05 +000095static int
paul718e3742002-12-13 20:15:29 +000096rip_route_set_add (struct vty *vty, struct route_map_index *index,
hasso98b718a2004-10-11 12:57:57 +000097 const char *command, const char *arg)
paul718e3742002-12-13 20:15:29 +000098{
99 int ret;
100
101 ret = route_map_add_set (index, command, arg);
102 if (ret)
103 {
104 switch (ret)
105 {
106 case RMAP_RULE_MISSING:
107 vty_out (vty, "%% Can't find rule.%s", VTY_NEWLINE);
108 return CMD_WARNING;
paul718e3742002-12-13 20:15:29 +0000109 case RMAP_COMPILE_ERROR:
vincentfbf5d032005-09-29 11:25:50 +0000110 /* rip, ripng and other protocols share the set metric command
111 but only values from 0 to 16 are valid for rip and ripng
112 if metric is out of range for rip and ripng, it is not for
113 other protocols. Do not return an error */
114 if (strcmp(command, "metric")) {
115 vty_out (vty, "%% Argument is malformed.%s", VTY_NEWLINE);
116 return CMD_WARNING;
117 }
paul718e3742002-12-13 20:15:29 +0000118 }
119 }
120 return CMD_SUCCESS;
121}
122
123/* Delete rip route map rule. */
pauldc63bfd2005-10-25 23:31:05 +0000124static int
paul718e3742002-12-13 20:15:29 +0000125rip_route_set_delete (struct vty *vty, struct route_map_index *index,
hasso98b718a2004-10-11 12:57:57 +0000126 const char *command, const char *arg)
paul718e3742002-12-13 20:15:29 +0000127{
128 int ret;
129
130 ret = route_map_delete_set (index, command, arg);
131 if (ret)
132 {
133 switch (ret)
134 {
135 case RMAP_RULE_MISSING:
136 vty_out (vty, "%% Can't find rule.%s", VTY_NEWLINE);
137 return CMD_WARNING;
paul718e3742002-12-13 20:15:29 +0000138 case RMAP_COMPILE_ERROR:
139 vty_out (vty, "%% Argument is malformed.%s", VTY_NEWLINE);
140 return CMD_WARNING;
paul718e3742002-12-13 20:15:29 +0000141 }
142 }
143 return CMD_SUCCESS;
144}
145
146/* Hook function for updating route_map assignment. */
paul11dde9c2004-05-31 14:00:00 +0000147/* ARGSUSED */
pauldc63bfd2005-10-25 23:31:05 +0000148static void
hasso98b718a2004-10-11 12:57:57 +0000149rip_route_map_update (const char *notused)
paul718e3742002-12-13 20:15:29 +0000150{
151 int i;
152
153 if (rip)
154 {
155 for (i = 0; i < ZEBRA_ROUTE_MAX; i++)
156 {
157 if (rip->route_map[i].name)
158 rip->route_map[i].map =
159 route_map_lookup_by_name (rip->route_map[i].name);
160 }
161 }
162}
David Lamparter6b0655a2014-06-04 06:53:35 +0200163
paul718e3742002-12-13 20:15:29 +0000164/* `match metric METRIC' */
165/* Match function return 1 if match is success else return zero. */
pauldc63bfd2005-10-25 23:31:05 +0000166static route_map_result_t
paul718e3742002-12-13 20:15:29 +0000167route_match_metric (void *rule, struct prefix *prefix,
168 route_map_object_t type, void *object)
169{
170 u_int32_t *metric;
vincentfbf5d032005-09-29 11:25:50 +0000171 u_int32_t check;
paul718e3742002-12-13 20:15:29 +0000172 struct rip_info *rinfo;
173
174 if (type == RMAP_RIP)
175 {
176 metric = rule;
177 rinfo = object;
178
vincentfbf5d032005-09-29 11:25:50 +0000179 /* If external metric is available, the route-map should
180 work on this one (for redistribute purpose) */
181 check = (rinfo->external_metric) ? rinfo->external_metric :
182 rinfo->metric;
183 if (check == *metric)
paul718e3742002-12-13 20:15:29 +0000184 return RMAP_MATCH;
185 else
186 return RMAP_NOMATCH;
187 }
188 return RMAP_NOMATCH;
189}
190
191/* Route map `match metric' match statement. `arg' is METRIC value */
pauldc63bfd2005-10-25 23:31:05 +0000192static void *
hasso98b718a2004-10-11 12:57:57 +0000193route_match_metric_compile (const char *arg)
paul718e3742002-12-13 20:15:29 +0000194{
195 u_int32_t *metric;
196
197 metric = XMALLOC (MTYPE_ROUTE_MAP_COMPILED, sizeof (u_int32_t));
198 *metric = atoi (arg);
199
200 if(*metric > 0)
201 return metric;
202
203 XFREE (MTYPE_ROUTE_MAP_COMPILED, metric);
204 return NULL;
205}
206
207/* Free route map's compiled `match metric' value. */
pauldc63bfd2005-10-25 23:31:05 +0000208static void
paul718e3742002-12-13 20:15:29 +0000209route_match_metric_free (void *rule)
210{
211 XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
212}
213
214/* Route map commands for metric matching. */
215struct route_map_rule_cmd route_match_metric_cmd =
216{
217 "metric",
218 route_match_metric,
219 route_match_metric_compile,
220 route_match_metric_free
221};
222
223/* `match interface IFNAME' */
224/* Match function return 1 if match is success else return zero. */
pauldc63bfd2005-10-25 23:31:05 +0000225static route_map_result_t
paul718e3742002-12-13 20:15:29 +0000226route_match_interface (void *rule, struct prefix *prefix,
227 route_map_object_t type, void *object)
228{
229 struct rip_info *rinfo;
230 struct interface *ifp;
231 char *ifname;
232
233 if (type == RMAP_RIP)
234 {
235 ifname = rule;
236 ifp = if_lookup_by_name(ifname);
237
238 if (!ifp)
239 return RMAP_NOMATCH;
240
241 rinfo = object;
242
hassocf96db12005-05-25 21:15:32 +0000243 if (rinfo->ifindex_out == ifp->ifindex || rinfo->ifindex == ifp->ifindex)
paul718e3742002-12-13 20:15:29 +0000244 return RMAP_MATCH;
245 else
246 return RMAP_NOMATCH;
247 }
248 return RMAP_NOMATCH;
249}
250
251/* Route map `match interface' match statement. `arg' is IFNAME value */
252/* XXX I don`t know if I need to check does interface exist? */
pauldc63bfd2005-10-25 23:31:05 +0000253static void *
hasso98b718a2004-10-11 12:57:57 +0000254route_match_interface_compile (const char *arg)
paul718e3742002-12-13 20:15:29 +0000255{
256 return XSTRDUP (MTYPE_ROUTE_MAP_COMPILED, arg);
257}
258
259/* Free route map's compiled `match interface' value. */
pauldc63bfd2005-10-25 23:31:05 +0000260static void
paul718e3742002-12-13 20:15:29 +0000261route_match_interface_free (void *rule)
262{
263 XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
264}
265
266/* Route map commands for interface matching. */
267struct route_map_rule_cmd route_match_interface_cmd =
268{
269 "interface",
270 route_match_interface,
271 route_match_interface_compile,
272 route_match_interface_free
273};
274
275/* `match ip next-hop IP_ACCESS_LIST' */
276
277/* Match function return 1 if match is success else return zero. */
pauldc63bfd2005-10-25 23:31:05 +0000278static route_map_result_t
paul718e3742002-12-13 20:15:29 +0000279route_match_ip_next_hop (void *rule, struct prefix *prefix,
280 route_map_object_t type, void *object)
281{
282 struct access_list *alist;
283 struct rip_info *rinfo;
284 struct prefix_ipv4 p;
285
286 if (type == RMAP_RIP)
287 {
288 rinfo = object;
289 p.family = AF_INET;
hassodc625e82005-05-26 06:26:40 +0000290 p.prefix = (rinfo->nexthop.s_addr) ? rinfo->nexthop : rinfo->from;
paul718e3742002-12-13 20:15:29 +0000291 p.prefixlen = IPV4_MAX_BITLEN;
292
293 alist = access_list_lookup (AFI_IP, (char *) rule);
294 if (alist == NULL)
295 return RMAP_NOMATCH;
296
297 return (access_list_apply (alist, &p) == FILTER_DENY ?
298 RMAP_NOMATCH : RMAP_MATCH);
299 }
300 return RMAP_NOMATCH;
301}
302
303/* Route map `ip next-hop' match statement. `arg' should be
304 access-list name. */
pauldc63bfd2005-10-25 23:31:05 +0000305static void *
hasso98b718a2004-10-11 12:57:57 +0000306route_match_ip_next_hop_compile (const char *arg)
paul718e3742002-12-13 20:15:29 +0000307{
308 return XSTRDUP (MTYPE_ROUTE_MAP_COMPILED, arg);
309}
310
311/* Free route map's compiled `. */
pauldc63bfd2005-10-25 23:31:05 +0000312static void
paul718e3742002-12-13 20:15:29 +0000313route_match_ip_next_hop_free (void *rule)
314{
315 XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
316}
317
318/* Route map commands for ip next-hop matching. */
pauldc63bfd2005-10-25 23:31:05 +0000319static struct route_map_rule_cmd route_match_ip_next_hop_cmd =
paul718e3742002-12-13 20:15:29 +0000320{
321 "ip next-hop",
322 route_match_ip_next_hop,
323 route_match_ip_next_hop_compile,
324 route_match_ip_next_hop_free
325};
David Lamparter6b0655a2014-06-04 06:53:35 +0200326
paul718e3742002-12-13 20:15:29 +0000327/* `match ip next-hop prefix-list PREFIX_LIST' */
328
pauldc63bfd2005-10-25 23:31:05 +0000329static route_map_result_t
paul718e3742002-12-13 20:15:29 +0000330route_match_ip_next_hop_prefix_list (void *rule, struct prefix *prefix,
331 route_map_object_t type, void *object)
332{
333 struct prefix_list *plist;
334 struct rip_info *rinfo;
335 struct prefix_ipv4 p;
336
337 if (type == RMAP_RIP)
338 {
339 rinfo = object;
340 p.family = AF_INET;
hassodc625e82005-05-26 06:26:40 +0000341 p.prefix = (rinfo->nexthop.s_addr) ? rinfo->nexthop : rinfo->from;
paul718e3742002-12-13 20:15:29 +0000342 p.prefixlen = IPV4_MAX_BITLEN;
343
344 plist = prefix_list_lookup (AFI_IP, (char *) rule);
345 if (plist == NULL)
346 return RMAP_NOMATCH;
347
348 return (prefix_list_apply (plist, &p) == PREFIX_DENY ?
349 RMAP_NOMATCH : RMAP_MATCH);
350 }
351 return RMAP_NOMATCH;
352}
353
pauldc63bfd2005-10-25 23:31:05 +0000354static void *
hasso98b718a2004-10-11 12:57:57 +0000355route_match_ip_next_hop_prefix_list_compile (const char *arg)
paul718e3742002-12-13 20:15:29 +0000356{
357 return XSTRDUP (MTYPE_ROUTE_MAP_COMPILED, arg);
358}
359
pauldc63bfd2005-10-25 23:31:05 +0000360static void
paul718e3742002-12-13 20:15:29 +0000361route_match_ip_next_hop_prefix_list_free (void *rule)
362{
363 XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
364}
365
pauldc63bfd2005-10-25 23:31:05 +0000366static struct route_map_rule_cmd route_match_ip_next_hop_prefix_list_cmd =
paul718e3742002-12-13 20:15:29 +0000367{
368 "ip next-hop prefix-list",
369 route_match_ip_next_hop_prefix_list,
370 route_match_ip_next_hop_prefix_list_compile,
371 route_match_ip_next_hop_prefix_list_free
372};
David Lamparter6b0655a2014-06-04 06:53:35 +0200373
paul718e3742002-12-13 20:15:29 +0000374/* `match ip address IP_ACCESS_LIST' */
375
376/* Match function should return 1 if match is success else return
377 zero. */
pauldc63bfd2005-10-25 23:31:05 +0000378static route_map_result_t
paul718e3742002-12-13 20:15:29 +0000379route_match_ip_address (void *rule, struct prefix *prefix,
380 route_map_object_t type, void *object)
381{
382 struct access_list *alist;
383
384 if (type == RMAP_RIP)
385 {
386 alist = access_list_lookup (AFI_IP, (char *) rule);
387 if (alist == NULL)
388 return RMAP_NOMATCH;
389
390 return (access_list_apply (alist, prefix) == FILTER_DENY ?
391 RMAP_NOMATCH : RMAP_MATCH);
392 }
393 return RMAP_NOMATCH;
394}
395
396/* Route map `ip address' match statement. `arg' should be
397 access-list name. */
pauldc63bfd2005-10-25 23:31:05 +0000398static void *
hasso98b718a2004-10-11 12:57:57 +0000399route_match_ip_address_compile (const char *arg)
paul718e3742002-12-13 20:15:29 +0000400{
401 return XSTRDUP (MTYPE_ROUTE_MAP_COMPILED, arg);
402}
403
404/* Free route map's compiled `ip address' value. */
pauldc63bfd2005-10-25 23:31:05 +0000405static void
paul718e3742002-12-13 20:15:29 +0000406route_match_ip_address_free (void *rule)
407{
408 XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
409}
410
411/* Route map commands for ip address matching. */
pauldc63bfd2005-10-25 23:31:05 +0000412static struct route_map_rule_cmd route_match_ip_address_cmd =
paul718e3742002-12-13 20:15:29 +0000413{
414 "ip address",
415 route_match_ip_address,
416 route_match_ip_address_compile,
417 route_match_ip_address_free
418};
David Lamparter6b0655a2014-06-04 06:53:35 +0200419
paul718e3742002-12-13 20:15:29 +0000420/* `match ip address prefix-list PREFIX_LIST' */
421
pauldc63bfd2005-10-25 23:31:05 +0000422static route_map_result_t
paul718e3742002-12-13 20:15:29 +0000423route_match_ip_address_prefix_list (void *rule, struct prefix *prefix,
424 route_map_object_t type, void *object)
425{
426 struct prefix_list *plist;
427
428 if (type == RMAP_RIP)
429 {
430 plist = prefix_list_lookup (AFI_IP, (char *) rule);
431 if (plist == NULL)
432 return RMAP_NOMATCH;
433
434 return (prefix_list_apply (plist, prefix) == PREFIX_DENY ?
435 RMAP_NOMATCH : RMAP_MATCH);
436 }
437 return RMAP_NOMATCH;
438}
439
pauldc63bfd2005-10-25 23:31:05 +0000440static void *
hasso98b718a2004-10-11 12:57:57 +0000441route_match_ip_address_prefix_list_compile (const char *arg)
paul718e3742002-12-13 20:15:29 +0000442{
443 return XSTRDUP (MTYPE_ROUTE_MAP_COMPILED, arg);
444}
445
pauldc63bfd2005-10-25 23:31:05 +0000446static void
paul718e3742002-12-13 20:15:29 +0000447route_match_ip_address_prefix_list_free (void *rule)
448{
449 XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
450}
451
pauldc63bfd2005-10-25 23:31:05 +0000452static struct route_map_rule_cmd route_match_ip_address_prefix_list_cmd =
paul718e3742002-12-13 20:15:29 +0000453{
454 "ip address prefix-list",
455 route_match_ip_address_prefix_list,
456 route_match_ip_address_prefix_list_compile,
457 route_match_ip_address_prefix_list_free
458};
hasso16705132003-05-25 14:49:19 +0000459
460/* `match tag TAG' */
461/* Match function return 1 if match is success else return zero. */
pauldc63bfd2005-10-25 23:31:05 +0000462static route_map_result_t
hasso16705132003-05-25 14:49:19 +0000463route_match_tag (void *rule, struct prefix *prefix,
464 route_map_object_t type, void *object)
465{
Paul Jakma96d10602016-07-01 14:23:45 +0100466 route_tag_t *tag;
hasso16705132003-05-25 14:49:19 +0000467 struct rip_info *rinfo;
468
469 if (type == RMAP_RIP)
470 {
471 tag = rule;
472 rinfo = object;
473
474 /* The information stored by rinfo is host ordered. */
475 if (rinfo->tag == *tag)
476 return RMAP_MATCH;
477 else
478 return RMAP_NOMATCH;
479 }
480 return RMAP_NOMATCH;
481}
482
483/* Route map `match tag' match statement. `arg' is TAG value */
pauldc63bfd2005-10-25 23:31:05 +0000484static void *
hasso98b718a2004-10-11 12:57:57 +0000485route_match_tag_compile (const char *arg)
hasso16705132003-05-25 14:49:19 +0000486{
Paul Jakma96d10602016-07-01 14:23:45 +0100487 route_tag_t *tag;
488 route_tag_t tmp;
Piotr Chytła3b4fb572015-12-01 10:16:02 -0500489
490 /* tag value shoud be integer. */
491 if (! all_digit (arg))
492 return NULL;
493
494 tmp = atoi(arg);
495 if (tmp < 1)
496 return NULL;
hasso16705132003-05-25 14:49:19 +0000497
498 tag = XMALLOC (MTYPE_ROUTE_MAP_COMPILED, sizeof (u_short));
Piotr Chytła3b4fb572015-12-01 10:16:02 -0500499
500 if (!tag)
501 return tag;
502
503 *tag = tmp;
hasso16705132003-05-25 14:49:19 +0000504
505 return tag;
506}
507
508/* Free route map's compiled `match tag' value. */
pauldc63bfd2005-10-25 23:31:05 +0000509static void
hasso16705132003-05-25 14:49:19 +0000510route_match_tag_free (void *rule)
511{
512 XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
513}
514
515/* Route map commands for tag matching. */
516struct route_map_rule_cmd route_match_tag_cmd =
517{
518 "tag",
519 route_match_tag,
520 route_match_tag_compile,
521 route_match_tag_free
522};
David Lamparter6b0655a2014-06-04 06:53:35 +0200523
paul718e3742002-12-13 20:15:29 +0000524/* `set metric METRIC' */
525
526/* Set metric to attribute. */
pauldc63bfd2005-10-25 23:31:05 +0000527static route_map_result_t
paul718e3742002-12-13 20:15:29 +0000528route_set_metric (void *rule, struct prefix *prefix,
529 route_map_object_t type, void *object)
530{
paul718e3742002-12-13 20:15:29 +0000531 if (type == RMAP_RIP)
532 {
hasso16705132003-05-25 14:49:19 +0000533 struct rip_metric_modifier *mod;
534 struct rip_info *rinfo;
535
536 mod = rule;
paul718e3742002-12-13 20:15:29 +0000537 rinfo = object;
hasso16705132003-05-25 14:49:19 +0000538
539 if (mod->type == metric_increment)
540 rinfo->metric_out += mod->metric;
541 else if (mod->type == metric_decrement)
542 rinfo->metric_out -= mod->metric;
543 else if (mod->type == metric_absolute)
544 rinfo->metric_out = mod->metric;
545
Paul Jakmab25ea4d2006-09-11 02:14:16 +0000546 if ((signed int)rinfo->metric_out < 1)
hasso16705132003-05-25 14:49:19 +0000547 rinfo->metric_out = 1;
548 if (rinfo->metric_out > RIP_METRIC_INFINITY)
549 rinfo->metric_out = RIP_METRIC_INFINITY;
550
paul718e3742002-12-13 20:15:29 +0000551 rinfo->metric_set = 1;
552 }
553 return RMAP_OKAY;
554}
555
556/* set metric compilation. */
pauldc63bfd2005-10-25 23:31:05 +0000557static void *
hasso98b718a2004-10-11 12:57:57 +0000558route_set_metric_compile (const char *arg)
paul718e3742002-12-13 20:15:29 +0000559{
hasso16705132003-05-25 14:49:19 +0000560 int len;
hasso98b718a2004-10-11 12:57:57 +0000561 const char *pnt;
hasso16705132003-05-25 14:49:19 +0000562 int type;
563 long metric;
564 char *endptr = NULL;
565 struct rip_metric_modifier *mod;
paul718e3742002-12-13 20:15:29 +0000566
hasso16705132003-05-25 14:49:19 +0000567 len = strlen (arg);
568 pnt = arg;
paul718e3742002-12-13 20:15:29 +0000569
hasso16705132003-05-25 14:49:19 +0000570 if (len == 0)
571 return NULL;
paul718e3742002-12-13 20:15:29 +0000572
hasso16705132003-05-25 14:49:19 +0000573 /* Examine first character. */
574 if (arg[0] == '+')
575 {
576 type = metric_increment;
577 pnt++;
578 }
579 else if (arg[0] == '-')
580 {
581 type = metric_decrement;
582 pnt++;
583 }
584 else
585 type = metric_absolute;
paul718e3742002-12-13 20:15:29 +0000586
hasso16705132003-05-25 14:49:19 +0000587 /* Check beginning with digit string. */
588 if (*pnt < '0' || *pnt > '9')
589 return NULL;
590
591 /* Convert string to integer. */
592 metric = strtol (pnt, &endptr, 10);
593
594 if (metric == LONG_MAX || *endptr != '\0')
595 return NULL;
596 if (metric < 0 || metric > RIP_METRIC_INFINITY)
597 return NULL;
598
599 mod = XMALLOC (MTYPE_ROUTE_MAP_COMPILED,
600 sizeof (struct rip_metric_modifier));
601 mod->type = type;
602 mod->metric = metric;
603
604 return mod;
paul718e3742002-12-13 20:15:29 +0000605}
606
607/* Free route map's compiled `set metric' value. */
pauldc63bfd2005-10-25 23:31:05 +0000608static void
paul718e3742002-12-13 20:15:29 +0000609route_set_metric_free (void *rule)
610{
611 XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
612}
613
614/* Set metric rule structure. */
pauldc63bfd2005-10-25 23:31:05 +0000615static struct route_map_rule_cmd route_set_metric_cmd =
paul718e3742002-12-13 20:15:29 +0000616{
617 "metric",
618 route_set_metric,
619 route_set_metric_compile,
620 route_set_metric_free,
621};
622
623/* `set ip next-hop IP_ADDRESS' */
624
625/* Set nexthop to object. ojbect must be pointer to struct attr. */
pauldc63bfd2005-10-25 23:31:05 +0000626static route_map_result_t
paul718e3742002-12-13 20:15:29 +0000627route_set_ip_nexthop (void *rule, struct prefix *prefix,
628 route_map_object_t type, void *object)
629{
630 struct in_addr *address;
631 struct rip_info *rinfo;
632
633 if(type == RMAP_RIP)
634 {
635 /* Fetch routemap's rule information. */
636 address = rule;
637 rinfo = object;
638
639 /* Set next hop value. */
640 rinfo->nexthop_out = *address;
641 }
642
643 return RMAP_OKAY;
644}
645
646/* Route map `ip nexthop' compile function. Given string is converted
647 to struct in_addr structure. */
pauldc63bfd2005-10-25 23:31:05 +0000648static void *
hasso98b718a2004-10-11 12:57:57 +0000649route_set_ip_nexthop_compile (const char *arg)
paul718e3742002-12-13 20:15:29 +0000650{
651 int ret;
652 struct in_addr *address;
653
654 address = XMALLOC (MTYPE_ROUTE_MAP_COMPILED, sizeof (struct in_addr));
655
656 ret = inet_aton (arg, address);
657
658 if (ret == 0)
659 {
660 XFREE (MTYPE_ROUTE_MAP_COMPILED, address);
661 return NULL;
662 }
663
664 return address;
665}
666
667/* Free route map's compiled `ip nexthop' value. */
pauldc63bfd2005-10-25 23:31:05 +0000668static void
paul718e3742002-12-13 20:15:29 +0000669route_set_ip_nexthop_free (void *rule)
670{
671 XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
672}
673
674/* Route map commands for ip nexthop set. */
pauldc63bfd2005-10-25 23:31:05 +0000675static struct route_map_rule_cmd route_set_ip_nexthop_cmd =
paul718e3742002-12-13 20:15:29 +0000676{
677 "ip next-hop",
678 route_set_ip_nexthop,
679 route_set_ip_nexthop_compile,
680 route_set_ip_nexthop_free
681};
hasso16705132003-05-25 14:49:19 +0000682
683/* `set tag TAG' */
684
685/* Set tag to object. ojbect must be pointer to struct attr. */
pauldc63bfd2005-10-25 23:31:05 +0000686static route_map_result_t
hasso16705132003-05-25 14:49:19 +0000687route_set_tag (void *rule, struct prefix *prefix,
688 route_map_object_t type, void *object)
689{
Paul Jakma96d10602016-07-01 14:23:45 +0100690 route_tag_t *tag;
hasso16705132003-05-25 14:49:19 +0000691 struct rip_info *rinfo;
692
693 if(type == RMAP_RIP)
694 {
695 /* Fetch routemap's rule information. */
696 tag = rule;
697 rinfo = object;
698
699 /* Set next hop value. */
700 rinfo->tag_out = *tag;
701 }
702
703 return RMAP_OKAY;
704}
705
706/* Route map `tag' compile function. Given string is converted
707 to u_short. */
pauldc63bfd2005-10-25 23:31:05 +0000708static void *
hasso98b718a2004-10-11 12:57:57 +0000709route_set_tag_compile (const char *arg)
hasso16705132003-05-25 14:49:19 +0000710{
Paul Jakma96d10602016-07-01 14:23:45 +0100711 route_tag_t *tag;
hasso16705132003-05-25 14:49:19 +0000712
713 tag = XMALLOC (MTYPE_ROUTE_MAP_COMPILED, sizeof (u_short));
714 *tag = atoi (arg);
715
716 return tag;
717}
718
719/* Free route map's compiled `ip nexthop' value. */
pauldc63bfd2005-10-25 23:31:05 +0000720static void
hasso16705132003-05-25 14:49:19 +0000721route_set_tag_free (void *rule)
722{
723 XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
724}
725
726/* Route map commands for tag set. */
pauldc63bfd2005-10-25 23:31:05 +0000727static struct route_map_rule_cmd route_set_tag_cmd =
hasso16705132003-05-25 14:49:19 +0000728{
729 "tag",
730 route_set_tag,
731 route_set_tag_compile,
732 route_set_tag_free
733};
David Lamparter6b0655a2014-06-04 06:53:35 +0200734
paul718e3742002-12-13 20:15:29 +0000735#define MATCH_STR "Match values from routing table\n"
736#define SET_STR "Set values in destination routing protocol\n"
737
738DEFUN (match_metric,
739 match_metric_cmd,
740 "match metric <0-4294967295>",
741 MATCH_STR
742 "Match metric of route\n"
743 "Metric value\n")
744{
745 return rip_route_match_add (vty, vty->index, "metric", argv[0]);
746}
747
748DEFUN (no_match_metric,
749 no_match_metric_cmd,
750 "no match metric",
751 NO_STR
752 MATCH_STR
753 "Match metric of route\n")
754{
755 if (argc == 0)
756 return rip_route_match_delete (vty, vty->index, "metric", NULL);
757
758 return rip_route_match_delete (vty, vty->index, "metric", argv[0]);
759}
760
761ALIAS (no_match_metric,
762 no_match_metric_val_cmd,
763 "no match metric <0-4294967295>",
764 NO_STR
765 MATCH_STR
766 "Match metric of route\n"
767 "Metric value\n")
768
769DEFUN (match_interface,
770 match_interface_cmd,
771 "match interface WORD",
772 MATCH_STR
773 "Match first hop interface of route\n"
774 "Interface name\n")
775{
776 return rip_route_match_add (vty, vty->index, "interface", argv[0]);
777}
778
779DEFUN (no_match_interface,
780 no_match_interface_cmd,
781 "no match interface",
782 NO_STR
783 MATCH_STR
784 "Match first hop interface of route\n")
785{
786 if (argc == 0)
787 return rip_route_match_delete (vty, vty->index, "interface", NULL);
788
789 return rip_route_match_delete (vty, vty->index, "interface", argv[0]);
790}
791
792ALIAS (no_match_interface,
793 no_match_interface_val_cmd,
794 "no match interface WORD",
795 NO_STR
796 MATCH_STR
797 "Match first hop interface of route\n"
798 "Interface name\n")
799
800DEFUN (match_ip_next_hop,
801 match_ip_next_hop_cmd,
paul73ffb252003-04-19 15:49:49 +0000802 "match ip next-hop (<1-199>|<1300-2699>|WORD)",
paul718e3742002-12-13 20:15:29 +0000803 MATCH_STR
804 IP_STR
805 "Match next-hop address of route\n"
paul73ffb252003-04-19 15:49:49 +0000806 "IP access-list number\n"
807 "IP access-list number (expanded range)\n"
808 "IP Access-list name\n")
paul718e3742002-12-13 20:15:29 +0000809{
810 return rip_route_match_add (vty, vty->index, "ip next-hop", argv[0]);
811}
812
813DEFUN (no_match_ip_next_hop,
814 no_match_ip_next_hop_cmd,
815 "no match ip next-hop",
816 NO_STR
817 MATCH_STR
818 IP_STR
819 "Match next-hop address of route\n")
820{
821 if (argc == 0)
822 return rip_route_match_delete (vty, vty->index, "ip next-hop", NULL);
823
824 return rip_route_match_delete (vty, vty->index, "ip next-hop", argv[0]);
825}
826
827ALIAS (no_match_ip_next_hop,
828 no_match_ip_next_hop_val_cmd,
paul73ffb252003-04-19 15:49:49 +0000829 "no match ip next-hop (<1-199>|<1300-2699>|WORD)",
paul718e3742002-12-13 20:15:29 +0000830 NO_STR
831 MATCH_STR
832 IP_STR
833 "Match next-hop address of route\n"
paul73ffb252003-04-19 15:49:49 +0000834 "IP access-list number\n"
835 "IP access-list number (expanded range)\n"
836 "IP Access-list name\n")
paul718e3742002-12-13 20:15:29 +0000837
838DEFUN (match_ip_next_hop_prefix_list,
839 match_ip_next_hop_prefix_list_cmd,
840 "match ip next-hop prefix-list WORD",
841 MATCH_STR
842 IP_STR
843 "Match next-hop address of route\n"
844 "Match entries of prefix-lists\n"
845 "IP prefix-list name\n")
846{
847 return rip_route_match_add (vty, vty->index, "ip next-hop prefix-list", argv[0]);
848}
849
850DEFUN (no_match_ip_next_hop_prefix_list,
851 no_match_ip_next_hop_prefix_list_cmd,
852 "no match ip next-hop prefix-list",
853 NO_STR
854 MATCH_STR
855 IP_STR
856 "Match next-hop address of route\n"
857 "Match entries of prefix-lists\n")
858{
859 if (argc == 0)
860 return rip_route_match_delete (vty, vty->index, "ip next-hop prefix-list", NULL);
861
862 return rip_route_match_delete (vty, vty->index, "ip next-hop prefix-list", argv[0]);
863}
864
865ALIAS (no_match_ip_next_hop_prefix_list,
866 no_match_ip_next_hop_prefix_list_val_cmd,
867 "no match ip next-hop prefix-list WORD",
868 NO_STR
869 MATCH_STR
870 IP_STR
871 "Match next-hop address of route\n"
872 "Match entries of prefix-lists\n"
873 "IP prefix-list name\n")
874
paul73ffb252003-04-19 15:49:49 +0000875DEFUN (match_ip_address,
paul718e3742002-12-13 20:15:29 +0000876 match_ip_address_cmd,
paul73ffb252003-04-19 15:49:49 +0000877 "match ip address (<1-199>|<1300-2699>|WORD)",
paul718e3742002-12-13 20:15:29 +0000878 MATCH_STR
879 IP_STR
880 "Match address of route\n"
paul73ffb252003-04-19 15:49:49 +0000881 "IP access-list number\n"
882 "IP access-list number (expanded range)\n"
883 "IP Access-list name\n")
884
paul718e3742002-12-13 20:15:29 +0000885{
886 return rip_route_match_add (vty, vty->index, "ip address", argv[0]);
887}
888
889DEFUN (no_match_ip_address,
890 no_match_ip_address_cmd,
891 "no match ip address",
892 NO_STR
893 MATCH_STR
894 IP_STR
895 "Match address of route\n")
896{
897 if (argc == 0)
898 return rip_route_match_delete (vty, vty->index, "ip address", NULL);
899
900 return rip_route_match_delete (vty, vty->index, "ip address", argv[0]);
901}
902
paul73ffb252003-04-19 15:49:49 +0000903ALIAS (no_match_ip_address,
paul718e3742002-12-13 20:15:29 +0000904 no_match_ip_address_val_cmd,
paul73ffb252003-04-19 15:49:49 +0000905 "no match ip address (<1-199>|<1300-2699>|WORD)",
paul718e3742002-12-13 20:15:29 +0000906 NO_STR
907 MATCH_STR
908 IP_STR
909 "Match address of route\n"
paul73ffb252003-04-19 15:49:49 +0000910 "IP access-list number\n"
911 "IP access-list number (expanded range)\n"
912 "IP Access-list name\n")
paul718e3742002-12-13 20:15:29 +0000913
914DEFUN (match_ip_address_prefix_list,
915 match_ip_address_prefix_list_cmd,
916 "match ip address prefix-list WORD",
917 MATCH_STR
918 IP_STR
919 "Match address of route\n"
920 "Match entries of prefix-lists\n"
921 "IP prefix-list name\n")
922{
923 return rip_route_match_add (vty, vty->index, "ip address prefix-list", argv[0]);
924}
925
926DEFUN (no_match_ip_address_prefix_list,
927 no_match_ip_address_prefix_list_cmd,
928 "no match ip address prefix-list",
929 NO_STR
930 MATCH_STR
931 IP_STR
932 "Match address of route\n"
933 "Match entries of prefix-lists\n")
934{
935 if (argc == 0)
936 return rip_route_match_delete (vty, vty->index, "ip address prefix-list", NULL);
937
938 return rip_route_match_delete (vty, vty->index, "ip address prefix-list", argv[0]);
939}
940
941ALIAS (no_match_ip_address_prefix_list,
942 no_match_ip_address_prefix_list_val_cmd,
943 "no match ip address prefix-list WORD",
944 NO_STR
945 MATCH_STR
946 IP_STR
947 "Match address of route\n"
948 "Match entries of prefix-lists\n"
949 "IP prefix-list name\n")
950
hasso16705132003-05-25 14:49:19 +0000951DEFUN (match_tag,
952 match_tag_cmd,
Piotr Chytła3b4fb572015-12-01 10:16:02 -0500953 "match tag <1-65535>",
hasso16705132003-05-25 14:49:19 +0000954 MATCH_STR
955 "Match tag of route\n"
956 "Metric value\n")
957{
958 return rip_route_match_add (vty, vty->index, "tag", argv[0]);
959}
960
961DEFUN (no_match_tag,
962 no_match_tag_cmd,
963 "no match tag",
964 NO_STR
965 MATCH_STR
966 "Match tag of route\n")
967{
968 if (argc == 0)
969 return rip_route_match_delete (vty, vty->index, "tag", NULL);
970
971 return rip_route_match_delete (vty, vty->index, "tag", argv[0]);
972}
973
974ALIAS (no_match_tag,
975 no_match_tag_val_cmd,
Piotr Chytła3b4fb572015-12-01 10:16:02 -0500976 "no match tag <1-65535>",
hasso16705132003-05-25 14:49:19 +0000977 NO_STR
978 MATCH_STR
979 "Match tag of route\n"
980 "Metric value\n")
981
paul718e3742002-12-13 20:15:29 +0000982/* set functions */
983
984DEFUN (set_metric,
985 set_metric_cmd,
hassodd55f9e2003-05-25 16:02:39 +0000986 "set metric <0-4294967295>",
paul718e3742002-12-13 20:15:29 +0000987 SET_STR
988 "Metric value for destination routing protocol\n"
hassodd55f9e2003-05-25 16:02:39 +0000989 "Metric value\n")
paul718e3742002-12-13 20:15:29 +0000990{
991 return rip_route_set_add (vty, vty->index, "metric", argv[0]);
992}
993
hassodd55f9e2003-05-25 16:02:39 +0000994ALIAS (set_metric,
995 set_metric_addsub_cmd,
996 "set metric <+/-metric>",
997 SET_STR
998 "Metric value for destination routing protocol\n"
hasso033e8612005-05-28 04:50:54 +0000999 "Add or subtract metric\n")
hassodd55f9e2003-05-25 16:02:39 +00001000
paul718e3742002-12-13 20:15:29 +00001001DEFUN (no_set_metric,
1002 no_set_metric_cmd,
1003 "no set metric",
1004 NO_STR
1005 SET_STR
1006 "Metric value for destination routing protocol\n")
1007{
1008 if (argc == 0)
1009 return rip_route_set_delete (vty, vty->index, "metric", NULL);
1010
1011 return rip_route_set_delete (vty, vty->index, "metric", argv[0]);
1012}
1013
1014ALIAS (no_set_metric,
1015 no_set_metric_val_cmd,
Daniel Walton62f936e2015-11-09 20:21:59 -05001016 "no set metric <0-4294967295>",
paul718e3742002-12-13 20:15:29 +00001017 NO_STR
1018 SET_STR
1019 "Metric value for destination routing protocol\n"
Daniel Walton62f936e2015-11-09 20:21:59 -05001020 "Metric value\n")
1021
1022ALIAS (no_set_metric,
1023 no_set_metric_addsub_cmd,
1024 "no set metric <+/-metric>",
1025 NO_STR
1026 SET_STR
1027 "Metric value for destination routing protocol\n"
hasso16705132003-05-25 14:49:19 +00001028 "Add or subtract metric\n")
paul718e3742002-12-13 20:15:29 +00001029
1030DEFUN (set_ip_nexthop,
1031 set_ip_nexthop_cmd,
1032 "set ip next-hop A.B.C.D",
1033 SET_STR
1034 IP_STR
1035 "Next hop address\n"
1036 "IP address of next hop\n")
1037{
1038 union sockunion su;
1039 int ret;
1040
1041 ret = str2sockunion (argv[0], &su);
1042 if (ret < 0)
1043 {
1044 vty_out (vty, "%% Malformed next-hop address%s", VTY_NEWLINE);
1045 return CMD_WARNING;
1046 }
1047
1048 return rip_route_set_add (vty, vty->index, "ip next-hop", argv[0]);
1049}
1050
1051DEFUN (no_set_ip_nexthop,
1052 no_set_ip_nexthop_cmd,
1053 "no set ip next-hop",
1054 NO_STR
1055 SET_STR
1056 IP_STR
1057 "Next hop address\n")
1058{
1059 if (argc == 0)
1060 return rip_route_set_delete (vty, vty->index, "ip next-hop", NULL);
1061
1062 return rip_route_set_delete (vty, vty->index, "ip next-hop", argv[0]);
1063}
1064
1065ALIAS (no_set_ip_nexthop,
1066 no_set_ip_nexthop_val_cmd,
1067 "no set ip next-hop A.B.C.D",
1068 NO_STR
1069 SET_STR
1070 IP_STR
1071 "Next hop address\n"
1072 "IP address of next hop\n")
1073
hasso16705132003-05-25 14:49:19 +00001074DEFUN (set_tag,
1075 set_tag_cmd,
Piotr Chytła3b4fb572015-12-01 10:16:02 -05001076 "set tag <1-65535>",
hasso16705132003-05-25 14:49:19 +00001077 SET_STR
1078 "Tag value for routing protocol\n"
1079 "Tag value\n")
1080{
1081 return rip_route_set_add (vty, vty->index, "tag", argv[0]);
1082}
1083
1084DEFUN (no_set_tag,
1085 no_set_tag_cmd,
1086 "no set tag",
1087 NO_STR
1088 SET_STR
1089 "Tag value for routing protocol\n")
1090{
1091 if (argc == 0)
1092 return rip_route_set_delete (vty, vty->index, "tag", NULL);
1093
1094 return rip_route_set_delete (vty, vty->index, "tag", argv[0]);
1095}
1096
1097ALIAS (no_set_tag,
1098 no_set_tag_val_cmd,
Piotr Chytła3b4fb572015-12-01 10:16:02 -05001099 "no set tag <1-65535>",
hasso16705132003-05-25 14:49:19 +00001100 NO_STR
1101 SET_STR
1102 "Tag value for routing protocol\n"
1103 "Tag value\n")
1104
paul718e3742002-12-13 20:15:29 +00001105void
1106rip_route_map_reset ()
1107{
1108 ;
1109}
1110
1111/* Route-map init */
1112void
1113rip_route_map_init ()
1114{
1115 route_map_init ();
1116 route_map_init_vty ();
1117 route_map_add_hook (rip_route_map_update);
1118 route_map_delete_hook (rip_route_map_update);
1119
1120 route_map_install_match (&route_match_metric_cmd);
1121 route_map_install_match (&route_match_interface_cmd);
1122 route_map_install_match (&route_match_ip_next_hop_cmd);
1123 route_map_install_match (&route_match_ip_next_hop_prefix_list_cmd);
1124 route_map_install_match (&route_match_ip_address_cmd);
1125 route_map_install_match (&route_match_ip_address_prefix_list_cmd);
hasso16705132003-05-25 14:49:19 +00001126 route_map_install_match (&route_match_tag_cmd);
paul718e3742002-12-13 20:15:29 +00001127
1128 route_map_install_set (&route_set_metric_cmd);
1129 route_map_install_set (&route_set_ip_nexthop_cmd);
hasso16705132003-05-25 14:49:19 +00001130 route_map_install_set (&route_set_tag_cmd);
paul718e3742002-12-13 20:15:29 +00001131
1132 install_element (RMAP_NODE, &match_metric_cmd);
1133 install_element (RMAP_NODE, &no_match_metric_cmd);
1134 install_element (RMAP_NODE, &no_match_metric_val_cmd);
1135 install_element (RMAP_NODE, &match_interface_cmd);
1136 install_element (RMAP_NODE, &no_match_interface_cmd);
1137 install_element (RMAP_NODE, &no_match_interface_val_cmd);
1138 install_element (RMAP_NODE, &match_ip_next_hop_cmd);
1139 install_element (RMAP_NODE, &no_match_ip_next_hop_cmd);
1140 install_element (RMAP_NODE, &no_match_ip_next_hop_val_cmd);
1141 install_element (RMAP_NODE, &match_ip_next_hop_prefix_list_cmd);
1142 install_element (RMAP_NODE, &no_match_ip_next_hop_prefix_list_cmd);
1143 install_element (RMAP_NODE, &no_match_ip_next_hop_prefix_list_val_cmd);
1144 install_element (RMAP_NODE, &match_ip_address_cmd);
1145 install_element (RMAP_NODE, &no_match_ip_address_cmd);
1146 install_element (RMAP_NODE, &no_match_ip_address_val_cmd);
1147 install_element (RMAP_NODE, &match_ip_address_prefix_list_cmd);
1148 install_element (RMAP_NODE, &no_match_ip_address_prefix_list_cmd);
1149 install_element (RMAP_NODE, &no_match_ip_address_prefix_list_val_cmd);
hasso16705132003-05-25 14:49:19 +00001150 install_element (RMAP_NODE, &match_tag_cmd);
1151 install_element (RMAP_NODE, &no_match_tag_cmd);
1152 install_element (RMAP_NODE, &no_match_tag_val_cmd);
paul718e3742002-12-13 20:15:29 +00001153
1154 install_element (RMAP_NODE, &set_metric_cmd);
hassodd55f9e2003-05-25 16:02:39 +00001155 install_element (RMAP_NODE, &set_metric_addsub_cmd);
paul718e3742002-12-13 20:15:29 +00001156 install_element (RMAP_NODE, &no_set_metric_cmd);
1157 install_element (RMAP_NODE, &no_set_metric_val_cmd);
Daniel Walton62f936e2015-11-09 20:21:59 -05001158 install_element (RMAP_NODE, &no_set_metric_addsub_cmd);
paul718e3742002-12-13 20:15:29 +00001159 install_element (RMAP_NODE, &set_ip_nexthop_cmd);
1160 install_element (RMAP_NODE, &no_set_ip_nexthop_cmd);
1161 install_element (RMAP_NODE, &no_set_ip_nexthop_val_cmd);
hasso16705132003-05-25 14:49:19 +00001162 install_element (RMAP_NODE, &set_tag_cmd);
1163 install_element (RMAP_NODE, &no_set_tag_cmd);
1164 install_element (RMAP_NODE, &no_set_tag_val_cmd);
paul718e3742002-12-13 20:15:29 +00001165}