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