1/* RIPv2 routemap.
2 * Copyright (C) 2005 6WIND <alain.ritoux@6wind.com>
3 * 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"
35
36struct rip_metric_modifier
37{
38  enum
39  {
40    metric_increment,
41    metric_decrement,
42    metric_absolute
43  } type;
44
45  u_char metric;
46};
47
48/* Add rip route map rule. */
49static int
50rip_route_match_add (struct vty *vty, struct route_map_index *index,
51		     const char *command, const char *arg)
52{
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;
63	case RMAP_COMPILE_ERROR:
64	  vty_out (vty, "%% Argument is malformed.%s", VTY_NEWLINE);
65	  return CMD_WARNING;
66	}
67    }
68  return CMD_SUCCESS;
69}
70
71/* Delete rip route map rule. */
72static int
73rip_route_match_delete (struct vty *vty, struct route_map_index *index,
74			const char *command, const char *arg)
75{
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;
86	case RMAP_COMPILE_ERROR:
87	  vty_out (vty, "%% Argument is malformed.%s", VTY_NEWLINE);
88	  return CMD_WARNING;
89	}
90    }
91  return CMD_SUCCESS;
92}
93
94/* Add rip route map rule. */
95static int
96rip_route_set_add (struct vty *vty, struct route_map_index *index,
97		   const char *command, const char *arg)
98{
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;
109	case RMAP_COMPILE_ERROR:
110	  /* 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	  }
118	}
119    }
120  return CMD_SUCCESS;
121}
122
123/* Delete rip route map rule. */
124static int
125rip_route_set_delete (struct vty *vty, struct route_map_index *index,
126		      const char *command, const char *arg)
127{
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;
138	case RMAP_COMPILE_ERROR:
139	  vty_out (vty, "%% Argument is malformed.%s", VTY_NEWLINE);
140	  return CMD_WARNING;
141	}
142    }
143  return CMD_SUCCESS;
144}
145
146/* Hook function for updating route_map assignment. */
147/* ARGSUSED */
148static void
149rip_route_map_update (const char *notused)
150{
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}
163
164/* `match metric METRIC' */
165/* Match function return 1 if match is success else return zero. */
166static route_map_result_t
167route_match_metric (void *rule, struct prefix *prefix,
168		    route_map_object_t type, void *object)
169{
170  u_int32_t *metric;
171  u_int32_t  check;
172  struct rip_info *rinfo;
173
174  if (type == RMAP_RIP)
175    {
176      metric = rule;
177      rinfo = object;
178
179      /* 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)
184	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 */
192static void *
193route_match_metric_compile (const char *arg)
194{
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. */
208static void
209route_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. */
225static route_map_result_t
226route_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
243      if (rinfo->ifindex_out == ifp->ifindex || rinfo->ifindex == ifp->ifindex)
244	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? */
253static void *
254route_match_interface_compile (const char *arg)
255{
256  return XSTRDUP (MTYPE_ROUTE_MAP_COMPILED, arg);
257}
258
259/* Free route map's compiled `match interface' value. */
260static void
261route_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. */
278static route_map_result_t
279route_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;
290      p.prefix = (rinfo->nexthop.s_addr) ? rinfo->nexthop : rinfo->from;
291      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. */
305static void *
306route_match_ip_next_hop_compile (const char *arg)
307{
308  return XSTRDUP (MTYPE_ROUTE_MAP_COMPILED, arg);
309}
310
311/* Free route map's compiled `. */
312static void
313route_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. */
319static struct route_map_rule_cmd route_match_ip_next_hop_cmd =
320{
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};
326
327/* `match ip next-hop prefix-list PREFIX_LIST' */
328
329static route_map_result_t
330route_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;
341      p.prefix = (rinfo->nexthop.s_addr) ? rinfo->nexthop : rinfo->from;
342      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
354static void *
355route_match_ip_next_hop_prefix_list_compile (const char *arg)
356{
357  return XSTRDUP (MTYPE_ROUTE_MAP_COMPILED, arg);
358}
359
360static void
361route_match_ip_next_hop_prefix_list_free (void *rule)
362{
363  XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
364}
365
366static struct route_map_rule_cmd route_match_ip_next_hop_prefix_list_cmd =
367{
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};
373
374/* `match ip address IP_ACCESS_LIST' */
375
376/* Match function should return 1 if match is success else return
377   zero. */
378static route_map_result_t
379route_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. */
398static void *
399route_match_ip_address_compile (const char *arg)
400{
401  return XSTRDUP (MTYPE_ROUTE_MAP_COMPILED, arg);
402}
403
404/* Free route map's compiled `ip address' value. */
405static void
406route_match_ip_address_free (void *rule)
407{
408  XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
409}
410
411/* Route map commands for ip address matching. */
412static struct route_map_rule_cmd route_match_ip_address_cmd =
413{
414  "ip address",
415  route_match_ip_address,
416  route_match_ip_address_compile,
417  route_match_ip_address_free
418};
419
420/* `match ip address prefix-list PREFIX_LIST' */
421
422static route_map_result_t
423route_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
440static void *
441route_match_ip_address_prefix_list_compile (const char *arg)
442{
443  return XSTRDUP (MTYPE_ROUTE_MAP_COMPILED, arg);
444}
445
446static void
447route_match_ip_address_prefix_list_free (void *rule)
448{
449  XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
450}
451
452static struct route_map_rule_cmd route_match_ip_address_prefix_list_cmd =
453{
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};
459
460/* `match tag TAG' */
461/* Match function return 1 if match is success else return zero. */
462static route_map_result_t
463route_match_tag (void *rule, struct prefix *prefix,
464		    route_map_object_t type, void *object)
465{
466  u_short *tag;
467  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 */
484static void *
485route_match_tag_compile (const char *arg)
486{
487  u_short *tag;
488
489  tag = XMALLOC (MTYPE_ROUTE_MAP_COMPILED, sizeof (u_short));
490  *tag = atoi (arg);
491
492  return tag;
493}
494
495/* Free route map's compiled `match tag' value. */
496static void
497route_match_tag_free (void *rule)
498{
499  XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
500}
501
502/* Route map commands for tag matching. */
503struct route_map_rule_cmd route_match_tag_cmd =
504{
505  "tag",
506  route_match_tag,
507  route_match_tag_compile,
508  route_match_tag_free
509};
510
511/* `set metric METRIC' */
512
513/* Set metric to attribute. */
514static route_map_result_t
515route_set_metric (void *rule, struct prefix *prefix,
516		  route_map_object_t type, void *object)
517{
518  if (type == RMAP_RIP)
519    {
520      struct rip_metric_modifier *mod;
521      struct rip_info *rinfo;
522
523      mod = rule;
524      rinfo = object;
525
526      if (mod->type == metric_increment)
527	rinfo->metric_out += mod->metric;
528      else if (mod->type == metric_decrement)
529	rinfo->metric_out -= mod->metric;
530      else if (mod->type == metric_absolute)
531	rinfo->metric_out = mod->metric;
532
533      if ((signed int)rinfo->metric_out < 1)
534	rinfo->metric_out = 1;
535      if (rinfo->metric_out > RIP_METRIC_INFINITY)
536	rinfo->metric_out = RIP_METRIC_INFINITY;
537
538      rinfo->metric_set = 1;
539    }
540  return RMAP_OKAY;
541}
542
543/* set metric compilation. */
544static void *
545route_set_metric_compile (const char *arg)
546{
547  int len;
548  const char *pnt;
549  int type;
550  long metric;
551  char *endptr = NULL;
552  struct rip_metric_modifier *mod;
553
554  len = strlen (arg);
555  pnt = arg;
556
557  if (len == 0)
558    return NULL;
559
560  /* Examine first character. */
561  if (arg[0] == '+')
562    {
563      type = metric_increment;
564      pnt++;
565    }
566  else if (arg[0] == '-')
567    {
568      type = metric_decrement;
569      pnt++;
570    }
571  else
572    type = metric_absolute;
573
574  /* Check beginning with digit string. */
575  if (*pnt < '0' || *pnt > '9')
576    return NULL;
577
578  /* Convert string to integer. */
579  metric = strtol (pnt, &endptr, 10);
580
581  if (metric == LONG_MAX || *endptr != '\0')
582    return NULL;
583  if (metric < 0 || metric > RIP_METRIC_INFINITY)
584    return NULL;
585
586  mod = XMALLOC (MTYPE_ROUTE_MAP_COMPILED,
587		 sizeof (struct rip_metric_modifier));
588  mod->type = type;
589  mod->metric = metric;
590
591  return mod;
592}
593
594/* Free route map's compiled `set metric' value. */
595static void
596route_set_metric_free (void *rule)
597{
598  XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
599}
600
601/* Set metric rule structure. */
602static struct route_map_rule_cmd route_set_metric_cmd =
603{
604  "metric",
605  route_set_metric,
606  route_set_metric_compile,
607  route_set_metric_free,
608};
609
610/* `set ip next-hop IP_ADDRESS' */
611
612/* Set nexthop to object.  ojbect must be pointer to struct attr. */
613static route_map_result_t
614route_set_ip_nexthop (void *rule, struct prefix *prefix,
615		      route_map_object_t type, void *object)
616{
617  struct in_addr *address;
618  struct rip_info *rinfo;
619
620  if(type == RMAP_RIP)
621    {
622      /* Fetch routemap's rule information. */
623      address = rule;
624      rinfo = object;
625
626      /* Set next hop value. */
627      rinfo->nexthop_out = *address;
628    }
629
630  return RMAP_OKAY;
631}
632
633/* Route map `ip nexthop' compile function.  Given string is converted
634   to struct in_addr structure. */
635static void *
636route_set_ip_nexthop_compile (const char *arg)
637{
638  int ret;
639  struct in_addr *address;
640
641  address = XMALLOC (MTYPE_ROUTE_MAP_COMPILED, sizeof (struct in_addr));
642
643  ret = inet_aton (arg, address);
644
645  if (ret == 0)
646    {
647      XFREE (MTYPE_ROUTE_MAP_COMPILED, address);
648      return NULL;
649    }
650
651  return address;
652}
653
654/* Free route map's compiled `ip nexthop' value. */
655static void
656route_set_ip_nexthop_free (void *rule)
657{
658  XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
659}
660
661/* Route map commands for ip nexthop set. */
662static struct route_map_rule_cmd route_set_ip_nexthop_cmd =
663{
664  "ip next-hop",
665  route_set_ip_nexthop,
666  route_set_ip_nexthop_compile,
667  route_set_ip_nexthop_free
668};
669
670/* `set tag TAG' */
671
672/* Set tag to object.  ojbect must be pointer to struct attr. */
673static route_map_result_t
674route_set_tag (void *rule, struct prefix *prefix,
675		      route_map_object_t type, void *object)
676{
677  u_short *tag;
678  struct rip_info *rinfo;
679
680  if(type == RMAP_RIP)
681    {
682      /* Fetch routemap's rule information. */
683      tag = rule;
684      rinfo = object;
685
686      /* Set next hop value. */
687      rinfo->tag_out = *tag;
688    }
689
690  return RMAP_OKAY;
691}
692
693/* Route map `tag' compile function.  Given string is converted
694   to u_short. */
695static void *
696route_set_tag_compile (const char *arg)
697{
698  u_short *tag;
699
700  tag = XMALLOC (MTYPE_ROUTE_MAP_COMPILED, sizeof (u_short));
701  *tag = atoi (arg);
702
703  return tag;
704}
705
706/* Free route map's compiled `ip nexthop' value. */
707static void
708route_set_tag_free (void *rule)
709{
710  XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
711}
712
713/* Route map commands for tag set. */
714static struct route_map_rule_cmd route_set_tag_cmd =
715{
716  "tag",
717  route_set_tag,
718  route_set_tag_compile,
719  route_set_tag_free
720};
721
722#define MATCH_STR "Match values from routing table\n"
723#define SET_STR "Set values in destination routing protocol\n"
724
725DEFUN (match_metric,
726       match_metric_cmd,
727       "match metric <0-4294967295>",
728       MATCH_STR
729       "Match metric of route\n"
730       "Metric value\n")
731{
732  return rip_route_match_add (vty, vty->index, "metric", argv[0]);
733}
734
735DEFUN (no_match_metric,
736       no_match_metric_cmd,
737       "no match metric",
738       NO_STR
739       MATCH_STR
740       "Match metric of route\n")
741{
742  if (argc == 0)
743    return rip_route_match_delete (vty, vty->index, "metric", NULL);
744
745  return rip_route_match_delete (vty, vty->index, "metric", argv[0]);
746}
747
748ALIAS (no_match_metric,
749       no_match_metric_val_cmd,
750       "no match metric <0-4294967295>",
751       NO_STR
752       MATCH_STR
753       "Match metric of route\n"
754       "Metric value\n")
755
756DEFUN (match_interface,
757       match_interface_cmd,
758       "match interface WORD",
759       MATCH_STR
760       "Match first hop interface of route\n"
761       "Interface name\n")
762{
763  return rip_route_match_add (vty, vty->index, "interface", argv[0]);
764}
765
766DEFUN (no_match_interface,
767       no_match_interface_cmd,
768       "no match interface",
769       NO_STR
770       MATCH_STR
771       "Match first hop interface of route\n")
772{
773  if (argc == 0)
774    return rip_route_match_delete (vty, vty->index, "interface", NULL);
775
776  return rip_route_match_delete (vty, vty->index, "interface", argv[0]);
777}
778
779ALIAS (no_match_interface,
780       no_match_interface_val_cmd,
781       "no match interface WORD",
782       NO_STR
783       MATCH_STR
784       "Match first hop interface of route\n"
785       "Interface name\n")
786
787DEFUN (match_ip_next_hop,
788       match_ip_next_hop_cmd,
789       "match ip next-hop (<1-199>|<1300-2699>|WORD)",
790       MATCH_STR
791       IP_STR
792       "Match next-hop address of route\n"
793       "IP access-list number\n"
794       "IP access-list number (expanded range)\n"
795       "IP Access-list name\n")
796{
797  return rip_route_match_add (vty, vty->index, "ip next-hop", argv[0]);
798}
799
800DEFUN (no_match_ip_next_hop,
801       no_match_ip_next_hop_cmd,
802       "no match ip next-hop",
803       NO_STR
804       MATCH_STR
805       IP_STR
806       "Match next-hop address of route\n")
807{
808  if (argc == 0)
809    return rip_route_match_delete (vty, vty->index, "ip next-hop", NULL);
810
811  return rip_route_match_delete (vty, vty->index, "ip next-hop", argv[0]);
812}
813
814ALIAS (no_match_ip_next_hop,
815       no_match_ip_next_hop_val_cmd,
816       "no match ip next-hop (<1-199>|<1300-2699>|WORD)",
817       NO_STR
818       MATCH_STR
819       IP_STR
820       "Match next-hop address of route\n"
821       "IP access-list number\n"
822       "IP access-list number (expanded range)\n"
823       "IP Access-list name\n")
824
825DEFUN (match_ip_next_hop_prefix_list,
826       match_ip_next_hop_prefix_list_cmd,
827       "match ip next-hop prefix-list WORD",
828       MATCH_STR
829       IP_STR
830       "Match next-hop address of route\n"
831       "Match entries of prefix-lists\n"
832       "IP prefix-list name\n")
833{
834  return rip_route_match_add (vty, vty->index, "ip next-hop prefix-list", argv[0]);
835}
836
837DEFUN (no_match_ip_next_hop_prefix_list,
838       no_match_ip_next_hop_prefix_list_cmd,
839       "no match ip next-hop prefix-list",
840       NO_STR
841       MATCH_STR
842       IP_STR
843       "Match next-hop address of route\n"
844       "Match entries of prefix-lists\n")
845{
846  if (argc == 0)
847    return rip_route_match_delete (vty, vty->index, "ip next-hop prefix-list", NULL);
848
849  return rip_route_match_delete (vty, vty->index, "ip next-hop prefix-list", argv[0]);
850}
851
852ALIAS (no_match_ip_next_hop_prefix_list,
853       no_match_ip_next_hop_prefix_list_val_cmd,
854       "no match ip next-hop prefix-list WORD",
855       NO_STR
856       MATCH_STR
857       IP_STR
858       "Match next-hop address of route\n"
859       "Match entries of prefix-lists\n"
860       "IP prefix-list name\n")
861
862DEFUN (match_ip_address,
863       match_ip_address_cmd,
864       "match ip address (<1-199>|<1300-2699>|WORD)",
865       MATCH_STR
866       IP_STR
867       "Match address of route\n"
868       "IP access-list number\n"
869       "IP access-list number (expanded range)\n"
870       "IP Access-list name\n")
871
872{
873  return rip_route_match_add (vty, vty->index, "ip address", argv[0]);
874}
875
876DEFUN (no_match_ip_address,
877       no_match_ip_address_cmd,
878       "no match ip address",
879       NO_STR
880       MATCH_STR
881       IP_STR
882       "Match address of route\n")
883{
884  if (argc == 0)
885    return rip_route_match_delete (vty, vty->index, "ip address", NULL);
886
887  return rip_route_match_delete (vty, vty->index, "ip address", argv[0]);
888}
889
890ALIAS (no_match_ip_address,
891       no_match_ip_address_val_cmd,
892       "no match ip address (<1-199>|<1300-2699>|WORD)",
893       NO_STR
894       MATCH_STR
895       IP_STR
896       "Match address of route\n"
897       "IP access-list number\n"
898       "IP access-list number (expanded range)\n"
899       "IP Access-list name\n")
900
901DEFUN (match_ip_address_prefix_list,
902       match_ip_address_prefix_list_cmd,
903       "match ip address prefix-list WORD",
904       MATCH_STR
905       IP_STR
906       "Match address of route\n"
907       "Match entries of prefix-lists\n"
908       "IP prefix-list name\n")
909{
910  return rip_route_match_add (vty, vty->index, "ip address prefix-list", argv[0]);
911}
912
913DEFUN (no_match_ip_address_prefix_list,
914       no_match_ip_address_prefix_list_cmd,
915       "no match ip address prefix-list",
916       NO_STR
917       MATCH_STR
918       IP_STR
919       "Match address of route\n"
920       "Match entries of prefix-lists\n")
921{
922  if (argc == 0)
923    return rip_route_match_delete (vty, vty->index, "ip address prefix-list", NULL);
924
925  return rip_route_match_delete (vty, vty->index, "ip address prefix-list", argv[0]);
926}
927
928ALIAS (no_match_ip_address_prefix_list,
929       no_match_ip_address_prefix_list_val_cmd,
930       "no match ip address prefix-list WORD",
931       NO_STR
932       MATCH_STR
933       IP_STR
934       "Match address of route\n"
935       "Match entries of prefix-lists\n"
936       "IP prefix-list name\n")
937
938DEFUN (match_tag,
939       match_tag_cmd,
940       "match tag <0-65535>",
941       MATCH_STR
942       "Match tag of route\n"
943       "Metric value\n")
944{
945  return rip_route_match_add (vty, vty->index, "tag", argv[0]);
946}
947
948DEFUN (no_match_tag,
949       no_match_tag_cmd,
950       "no match tag",
951       NO_STR
952       MATCH_STR
953       "Match tag of route\n")
954{
955  if (argc == 0)
956    return rip_route_match_delete (vty, vty->index, "tag", NULL);
957
958  return rip_route_match_delete (vty, vty->index, "tag", argv[0]);
959}
960
961ALIAS (no_match_tag,
962       no_match_tag_val_cmd,
963       "no match tag <0-65535>",
964       NO_STR
965       MATCH_STR
966       "Match tag of route\n"
967       "Metric value\n")
968
969/* set functions */
970
971DEFUN (set_metric,
972       set_metric_cmd,
973       "set metric <0-4294967295>",
974       SET_STR
975       "Metric value for destination routing protocol\n"
976       "Metric value\n")
977{
978  return rip_route_set_add (vty, vty->index, "metric", argv[0]);
979}
980
981ALIAS (set_metric,
982       set_metric_addsub_cmd,
983       "set metric <+/-metric>",
984       SET_STR
985       "Metric value for destination routing protocol\n"
986       "Add or subtract metric\n")
987
988DEFUN (no_set_metric,
989       no_set_metric_cmd,
990       "no set metric",
991       NO_STR
992       SET_STR
993       "Metric value for destination routing protocol\n")
994{
995  if (argc == 0)
996    return rip_route_set_delete (vty, vty->index, "metric", NULL);
997
998  return rip_route_set_delete (vty, vty->index, "metric", argv[0]);
999}
1000
1001ALIAS (no_set_metric,
1002       no_set_metric_val_cmd,
1003       "no set metric (<0-4294967295>|<+/-metric>)",
1004       NO_STR
1005       SET_STR
1006       "Metric value for destination routing protocol\n"
1007       "Metric value\n"
1008       "Add or subtract metric\n")
1009
1010DEFUN (set_ip_nexthop,
1011       set_ip_nexthop_cmd,
1012       "set ip next-hop A.B.C.D",
1013       SET_STR
1014       IP_STR
1015       "Next hop address\n"
1016       "IP address of next hop\n")
1017{
1018  union sockunion su;
1019  int ret;
1020
1021  ret = str2sockunion (argv[0], &su);
1022  if (ret < 0)
1023    {
1024      vty_out (vty, "%% Malformed next-hop address%s", VTY_NEWLINE);
1025      return CMD_WARNING;
1026    }
1027
1028  return rip_route_set_add (vty, vty->index, "ip next-hop", argv[0]);
1029}
1030
1031DEFUN (no_set_ip_nexthop,
1032       no_set_ip_nexthop_cmd,
1033       "no set ip next-hop",
1034       NO_STR
1035       SET_STR
1036       IP_STR
1037       "Next hop address\n")
1038{
1039  if (argc == 0)
1040    return rip_route_set_delete (vty, vty->index, "ip next-hop", NULL);
1041
1042  return rip_route_set_delete (vty, vty->index, "ip next-hop", argv[0]);
1043}
1044
1045ALIAS (no_set_ip_nexthop,
1046       no_set_ip_nexthop_val_cmd,
1047       "no set ip next-hop A.B.C.D",
1048       NO_STR
1049       SET_STR
1050       IP_STR
1051       "Next hop address\n"
1052       "IP address of next hop\n")
1053
1054DEFUN (set_tag,
1055       set_tag_cmd,
1056       "set tag <0-65535>",
1057       SET_STR
1058       "Tag value for routing protocol\n"
1059       "Tag value\n")
1060{
1061  return rip_route_set_add (vty, vty->index, "tag", argv[0]);
1062}
1063
1064DEFUN (no_set_tag,
1065       no_set_tag_cmd,
1066       "no set tag",
1067       NO_STR
1068       SET_STR
1069       "Tag value for routing protocol\n")
1070{
1071  if (argc == 0)
1072    return rip_route_set_delete (vty, vty->index, "tag", NULL);
1073
1074  return rip_route_set_delete (vty, vty->index, "tag", argv[0]);
1075}
1076
1077ALIAS (no_set_tag,
1078       no_set_tag_val_cmd,
1079       "no set tag <0-65535>",
1080       NO_STR
1081       SET_STR
1082       "Tag value for routing protocol\n"
1083       "Tag value\n")
1084
1085void
1086rip_route_map_reset ()
1087{
1088  ;
1089}
1090
1091/* Route-map init */
1092void
1093rip_route_map_init ()
1094{
1095  route_map_init ();
1096  route_map_init_vty ();
1097  route_map_add_hook (rip_route_map_update);
1098  route_map_delete_hook (rip_route_map_update);
1099
1100  route_map_install_match (&route_match_metric_cmd);
1101  route_map_install_match (&route_match_interface_cmd);
1102  route_map_install_match (&route_match_ip_next_hop_cmd);
1103  route_map_install_match (&route_match_ip_next_hop_prefix_list_cmd);
1104  route_map_install_match (&route_match_ip_address_cmd);
1105  route_map_install_match (&route_match_ip_address_prefix_list_cmd);
1106  route_map_install_match (&route_match_tag_cmd);
1107
1108  route_map_install_set (&route_set_metric_cmd);
1109  route_map_install_set (&route_set_ip_nexthop_cmd);
1110  route_map_install_set (&route_set_tag_cmd);
1111
1112  install_element (RMAP_NODE, &match_metric_cmd);
1113  install_element (RMAP_NODE, &no_match_metric_cmd);
1114  install_element (RMAP_NODE, &no_match_metric_val_cmd);
1115  install_element (RMAP_NODE, &match_interface_cmd);
1116  install_element (RMAP_NODE, &no_match_interface_cmd);
1117  install_element (RMAP_NODE, &no_match_interface_val_cmd);
1118  install_element (RMAP_NODE, &match_ip_next_hop_cmd);
1119  install_element (RMAP_NODE, &no_match_ip_next_hop_cmd);
1120  install_element (RMAP_NODE, &no_match_ip_next_hop_val_cmd);
1121  install_element (RMAP_NODE, &match_ip_next_hop_prefix_list_cmd);
1122  install_element (RMAP_NODE, &no_match_ip_next_hop_prefix_list_cmd);
1123  install_element (RMAP_NODE, &no_match_ip_next_hop_prefix_list_val_cmd);
1124  install_element (RMAP_NODE, &match_ip_address_cmd);
1125  install_element (RMAP_NODE, &no_match_ip_address_cmd);
1126  install_element (RMAP_NODE, &no_match_ip_address_val_cmd);
1127  install_element (RMAP_NODE, &match_ip_address_prefix_list_cmd);
1128  install_element (RMAP_NODE, &no_match_ip_address_prefix_list_cmd);
1129  install_element (RMAP_NODE, &no_match_ip_address_prefix_list_val_cmd);
1130  install_element (RMAP_NODE, &match_tag_cmd);
1131  install_element (RMAP_NODE, &no_match_tag_cmd);
1132  install_element (RMAP_NODE, &no_match_tag_val_cmd);
1133
1134  install_element (RMAP_NODE, &set_metric_cmd);
1135  install_element (RMAP_NODE, &set_metric_addsub_cmd);
1136  install_element (RMAP_NODE, &no_set_metric_cmd);
1137  install_element (RMAP_NODE, &no_set_metric_val_cmd);
1138  install_element (RMAP_NODE, &set_ip_nexthop_cmd);
1139  install_element (RMAP_NODE, &no_set_ip_nexthop_cmd);
1140  install_element (RMAP_NODE, &no_set_ip_nexthop_val_cmd);
1141  install_element (RMAP_NODE, &set_tag_cmd);
1142  install_element (RMAP_NODE, &no_set_tag_cmd);
1143  install_element (RMAP_NODE, &no_set_tag_val_cmd);
1144}
1145