Merge tag 'upstream/1.2.4'
[quagga-debian.git] / ospfd / ospf_routemap.c
1 /*
2  * Route map function of ospfd.
3  * Copyright (C) 2000 IP Infusion Inc.
4  *
5  * Written by Toshiaki Takada.
6  *
7  * This file is part of GNU Zebra.
8  *
9  * GNU Zebra is free software; you can redistribute it and/or modify it
10  * under the terms of the GNU General Public License as published by the
11  * Free Software Foundation; either version 2, or (at your option) any
12  * later version.
13  *
14  * GNU Zebra is distributed in the hope that it will be useful, but
15  * WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17  * General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with GNU Zebra; see the file COPYING.  If not, write to the Free
21  * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
22  * 02111-1307, USA.
23  */
24
25 #include <zebra.h>
26
27 #include "memory.h"
28 #include "prefix.h"
29 #include "table.h"
30 #include "routemap.h"
31 #include "command.h"
32 #include "log.h"
33 #include "plist.h"
34
35 #include "ospfd/ospfd.h"
36 #include "ospfd/ospf_asbr.h"
37 #include "ospfd/ospf_interface.h"
38 #include "ospfd/ospf_lsa.h"
39 #include "ospfd/ospf_route.h"
40 #include "ospfd/ospf_zebra.h"
41
42 /* Hook function for updating route_map assignment. */
43 static void
44 ospf_route_map_update (const char *name)
45 {
46   struct ospf *ospf;
47   int type;
48
49   /* If OSPF instatnce does not exist, return right now. */
50   ospf = ospf_lookup ();
51   if (ospf == NULL)
52     return;
53
54   /* Update route-map */
55   for (type = 0; type <= ZEBRA_ROUTE_MAX; type++)
56     {
57       if (ROUTEMAP_NAME (ospf, type)
58           && strcmp (ROUTEMAP_NAME (ospf, type), name) == 0)
59         {
60           /* Keep old route-map. */
61           struct route_map *old = ROUTEMAP (ospf, type);
62
63           /* Update route-map. */
64           ROUTEMAP (ospf, type) =
65             route_map_lookup_by_name (ROUTEMAP_NAME (ospf, type));
66
67           /* No update for this distribute type. */
68           if (old == NULL && ROUTEMAP (ospf, type) == NULL)
69             continue;
70
71           ospf_distribute_list_update (ospf, type);
72         }
73     }
74 }
75
76 static void
77 ospf_route_map_event (route_map_event_t event, const char *name)
78 {
79   struct ospf *ospf;
80   int type;
81
82   /* If OSPF instatnce does not exist, return right now. */
83   ospf = ospf_lookup ();
84   if (ospf == NULL)
85     return;
86
87   /* Update route-map. */
88   for (type = 0; type <= ZEBRA_ROUTE_MAX; type++)
89     {
90       if (ROUTEMAP_NAME (ospf, type) &&  ROUTEMAP (ospf, type)
91           && !strcmp (ROUTEMAP_NAME (ospf, type), name))
92         {
93           ospf_distribute_list_update (ospf, type);
94         }
95     }
96 }
97
98 /* Delete rip route map rule. */
99 static int
100 ospf_route_match_delete (struct vty *vty, struct route_map_index *index,
101                          const char *command, const char *arg)
102 {
103   int ret;
104
105   ret = route_map_delete_match (index, command, arg);
106   if (ret)
107     {
108       switch (ret)
109         {
110         case RMAP_RULE_MISSING:
111           vty_out (vty, "%% OSPF Can't find rule.%s", VTY_NEWLINE);
112           return CMD_WARNING;
113         case RMAP_COMPILE_ERROR:
114           vty_out (vty, "%% OSPF Argument is malformed.%s", VTY_NEWLINE);
115           return CMD_WARNING;
116         }
117     }
118
119   return CMD_SUCCESS;
120 }
121
122 static int
123 ospf_route_match_add (struct vty *vty, struct route_map_index *index,
124                       const char *command, const char *arg)
125 {                                                                              
126   int ret;
127
128   ret = route_map_add_match (index, command, arg);
129   if (ret)
130     {
131       switch (ret)
132         {
133         case RMAP_RULE_MISSING:
134           vty_out (vty, "%% OSPF Can't find rule.%s", VTY_NEWLINE);
135           return CMD_WARNING;
136         case RMAP_COMPILE_ERROR:
137           vty_out (vty, "%% OSPF Argument is malformed.%s", VTY_NEWLINE);
138           return CMD_WARNING;
139         }
140     }
141
142   return CMD_SUCCESS;
143 }
144
145 static int
146 ospf_route_set_add (struct vty *vty, struct route_map_index *index,
147                     const char *command, const char *arg)
148 {
149   int ret;
150
151   ret = route_map_add_set (index, command, arg);
152   if (ret)
153     {
154       switch (ret)
155         {
156         case RMAP_RULE_MISSING:
157           vty_out (vty, "%% OSPF Can't find rule.%s", VTY_NEWLINE);
158           return CMD_WARNING;
159         case RMAP_COMPILE_ERROR:
160           vty_out (vty, "%% OSPF Argument is malformed.%s", VTY_NEWLINE);
161           return CMD_WARNING;
162         }
163     }
164
165   return CMD_SUCCESS;
166 }
167
168 /* Delete rip route map rule. */
169 static int
170 ospf_route_set_delete (struct vty *vty, struct route_map_index *index,
171                        const char *command, const char *arg)
172 {                                              
173   int ret;
174
175   ret = route_map_delete_set (index, command, arg);
176   if (ret)
177     {
178       switch (ret)
179         {
180         case RMAP_RULE_MISSING:
181           vty_out (vty, "%% OSPF Can't find rule.%s", VTY_NEWLINE);
182           return CMD_WARNING;
183         case RMAP_COMPILE_ERROR:
184           vty_out (vty, "%% OSPF Argument is malformed.%s", VTY_NEWLINE);
185           return CMD_WARNING;
186         }
187     }
188
189   return CMD_SUCCESS;
190 }
191
192 /* `match ip netxthop ' */
193 /* Match function return 1 if match is success else return zero. */
194 static route_map_result_t
195 route_match_ip_nexthop (void *rule, struct prefix *prefix,
196                         route_map_object_t type, void *object)
197 {
198   struct access_list *alist;
199   struct external_info *ei = object;
200   struct prefix_ipv4 p;
201
202   if (type == RMAP_OSPF)
203     {
204       p.family = AF_INET;
205       p.prefix = ei->nexthop;
206       p.prefixlen = IPV4_MAX_BITLEN;
207
208       alist = access_list_lookup (AFI_IP, (char *) rule);
209       if (alist == NULL)
210         return RMAP_NOMATCH;
211
212       return (access_list_apply (alist, &p) == FILTER_DENY ?
213               RMAP_NOMATCH : RMAP_MATCH);
214     }
215   return RMAP_NOMATCH;
216 }
217
218 /* Route map `ip next-hop' match statement. `arg' should be
219    access-list name. */
220 static void *
221 route_match_ip_nexthop_compile (const char *arg)
222 {
223   return XSTRDUP (MTYPE_ROUTE_MAP_COMPILED, arg);
224 }
225
226 /* Free route map's compiled `ip address' value. */
227 static void
228 route_match_ip_nexthop_free (void *rule)
229 {
230   XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
231 }
232
233 /* Route map commands for metric matching. */
234 struct route_map_rule_cmd route_match_ip_nexthop_cmd =
235 {
236   "ip next-hop",
237   route_match_ip_nexthop,
238   route_match_ip_nexthop_compile,
239   route_match_ip_nexthop_free
240 };
241
242 /* `match ip next-hop prefix-list PREFIX_LIST' */
243
244 static route_map_result_t
245 route_match_ip_next_hop_prefix_list (void *rule, struct prefix *prefix,
246                                     route_map_object_t type, void *object)
247 {
248   struct prefix_list *plist;
249   struct external_info *ei = object;
250   struct prefix_ipv4 p;
251
252   if (type == RMAP_OSPF)
253     {
254       p.family = AF_INET;
255       p.prefix = ei->nexthop;
256       p.prefixlen = IPV4_MAX_BITLEN;
257
258       plist = prefix_list_lookup (AFI_IP, (char *) rule);
259       if (plist == NULL)
260         return RMAP_NOMATCH;
261
262       return (prefix_list_apply (plist, &p) == PREFIX_DENY ?
263               RMAP_NOMATCH : RMAP_MATCH);
264     }
265   return RMAP_NOMATCH;
266 }
267
268 static void *
269 route_match_ip_next_hop_prefix_list_compile (const char *arg)
270 {
271   return XSTRDUP (MTYPE_ROUTE_MAP_COMPILED, arg);
272 }
273
274 static void
275 route_match_ip_next_hop_prefix_list_free (void *rule)
276 {
277   XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
278 }
279
280 struct route_map_rule_cmd route_match_ip_next_hop_prefix_list_cmd =
281 {
282   "ip next-hop prefix-list",
283   route_match_ip_next_hop_prefix_list,
284   route_match_ip_next_hop_prefix_list_compile,
285   route_match_ip_next_hop_prefix_list_free
286 };
287
288 /* `match ip address IP_ACCESS_LIST' */
289 /* Match function should return 1 if match is success else return
290    zero. */
291 static route_map_result_t
292 route_match_ip_address (void *rule, struct prefix *prefix,
293                         route_map_object_t type, void *object)
294 {
295   struct access_list *alist;
296   /* struct prefix_ipv4 match; */
297
298   if (type == RMAP_OSPF)
299     {
300       alist = access_list_lookup (AFI_IP, (char *) rule);
301       if (alist == NULL)
302         return RMAP_NOMATCH;
303
304       return (access_list_apply (alist, prefix) == FILTER_DENY ?
305               RMAP_NOMATCH : RMAP_MATCH);
306     }
307   return RMAP_NOMATCH;
308 }
309
310 /* Route map `ip address' match statement.  `arg' should be
311    access-list name. */
312 static void *
313 route_match_ip_address_compile (const char *arg)
314 {
315   return XSTRDUP (MTYPE_ROUTE_MAP_COMPILED, arg);
316 }
317
318 /* Free route map's compiled `ip address' value. */
319 static void
320 route_match_ip_address_free (void *rule)
321 {
322   XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
323 }
324
325 /* Route map commands for ip address matching. */
326 struct route_map_rule_cmd route_match_ip_address_cmd =
327 {
328   "ip address",
329   route_match_ip_address,
330   route_match_ip_address_compile,
331   route_match_ip_address_free
332 };
333
334 /* `match ip address prefix-list PREFIX_LIST' */
335 static route_map_result_t
336 route_match_ip_address_prefix_list (void *rule, struct prefix *prefix,
337                                     route_map_object_t type, void *object)
338 {
339   struct prefix_list *plist;
340
341   if (type == RMAP_OSPF)
342     {
343       plist = prefix_list_lookup (AFI_IP, (char *) rule);
344       if (plist == NULL)
345         return RMAP_NOMATCH;
346
347       return (prefix_list_apply (plist, prefix) == PREFIX_DENY ?
348               RMAP_NOMATCH : RMAP_MATCH);
349     }
350   return RMAP_NOMATCH;
351 }
352
353 static void *
354 route_match_ip_address_prefix_list_compile (const char *arg)
355 {
356   return XSTRDUP (MTYPE_ROUTE_MAP_COMPILED, arg);
357 }
358
359 static void
360 route_match_ip_address_prefix_list_free (void *rule)
361 {
362   XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
363 }
364
365 struct route_map_rule_cmd route_match_ip_address_prefix_list_cmd =
366 {
367   "ip address prefix-list",
368   route_match_ip_address_prefix_list,
369   route_match_ip_address_prefix_list_compile,
370   route_match_ip_address_prefix_list_free
371 };
372
373 /* `match interface IFNAME' */
374 /* Match function should return 1 if match is success else return
375    zero. */
376 static route_map_result_t
377 route_match_interface (void *rule, struct prefix *prefix,
378                        route_map_object_t type, void *object)
379 {
380   struct interface *ifp;
381   struct external_info *ei;
382
383   if (type == RMAP_OSPF)
384     {
385       ei = object;
386       ifp = if_lookup_by_name ((char *)rule);
387
388       if (ifp == NULL || ifp->ifindex != ei->ifindex)
389         return RMAP_NOMATCH;
390
391       return RMAP_MATCH;
392     }
393   return RMAP_NOMATCH;
394 }
395
396 /* Route map `interface' match statement.  `arg' should be
397    interface name. */
398 static void *
399 route_match_interface_compile (const char *arg)
400 {
401   return XSTRDUP (MTYPE_ROUTE_MAP_COMPILED, arg);
402 }
403
404 /* Free route map's compiled `interface' value. */
405 static void
406 route_match_interface_free (void *rule)
407 {
408   XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
409 }
410
411 /* Route map commands for ip address matching. */
412 struct route_map_rule_cmd route_match_interface_cmd =
413 {
414   "interface",
415   route_match_interface,
416   route_match_interface_compile,
417   route_match_interface_free
418 };
419
420 /* Match function return 1 if match is success else return zero. */
421 static route_map_result_t
422 route_match_tag (void *rule, struct prefix *prefix,
423                  route_map_object_t type, void *object)
424 {
425   route_tag_t *tag;
426   struct external_info *ei;
427
428   if (type == RMAP_OSPF)
429     {
430       tag = rule;
431       ei = object;
432
433       return ((ei->tag == *tag)? RMAP_MATCH : RMAP_NOMATCH);
434     }
435
436   return RMAP_NOMATCH;
437 }
438
439 /* Route map commands for tag matching. */
440 static struct route_map_rule_cmd route_match_tag_cmd =
441 {
442   "tag",
443   route_match_tag,
444   route_map_rule_tag_compile,
445   route_map_rule_tag_free,
446 };
447
448
449 /* `set metric METRIC' */
450 /* Set metric to attribute. */
451 static route_map_result_t
452 route_set_metric (void *rule, struct prefix *prefix,
453                   route_map_object_t type, void *object)
454 {
455   u_int32_t *metric;
456   struct external_info *ei;
457
458   if (type == RMAP_OSPF)
459     {
460       /* Fetch routemap's rule information. */
461       metric = rule;
462       ei = object;
463
464       /* Set metric out value. */
465       ei->route_map_set.metric = *metric;
466     }
467   return RMAP_OKAY;
468 }
469
470 /* set metric compilation. */
471 static void *
472 route_set_metric_compile (const char *arg)
473 {
474   u_int32_t *metric;
475   int32_t ret;
476
477   /* OSPF doesn't support the +/- in
478      set metric <+/-metric> check
479      Ignore the +/- component */
480   if (! all_digit (arg))
481     {
482       if ((strncmp (arg, "+", 1) == 0 || strncmp (arg, "-", 1) == 0) &&
483           all_digit (arg+1))
484         {
485           zlog_warn ("OSPF does not support 'set metric +/-'");
486           arg++;
487         }
488       else
489         return NULL;
490     }
491
492   metric = XCALLOC (MTYPE_ROUTE_MAP_COMPILED, sizeof (u_int32_t));
493   ret = atoi (arg);
494
495   if (ret >= 0)
496     {
497       *metric = (u_int32_t)ret;
498       return metric;
499     }
500
501   XFREE (MTYPE_ROUTE_MAP_COMPILED, metric);
502   return NULL;
503 }
504
505 /* Free route map's compiled `set metric' value. */
506 static void
507 route_set_metric_free (void *rule)
508 {
509   XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
510 }
511
512 /* Set metric rule structure. */
513 struct route_map_rule_cmd route_set_metric_cmd =
514 {
515   "metric",
516   route_set_metric,
517   route_set_metric_compile,
518   route_set_metric_free,
519 };
520
521 /* `set metric-type TYPE' */
522 /* Set metric-type to attribute. */
523 static route_map_result_t
524 route_set_metric_type (void *rule, struct prefix *prefix,
525                        route_map_object_t type, void *object)
526 {
527   u_int32_t *metric_type;
528   struct external_info *ei;
529
530   if (type == RMAP_OSPF)
531     {
532       /* Fetch routemap's rule information. */
533       metric_type = rule;
534       ei = object;
535
536       /* Set metric out value. */
537       ei->route_map_set.metric_type = *metric_type;
538     }
539   return RMAP_OKAY;
540 }
541
542 /* set metric-type compilation. */
543 static void *
544 route_set_metric_type_compile (const char *arg)
545 {
546   u_int32_t *metric_type;
547
548   metric_type = XCALLOC (MTYPE_ROUTE_MAP_COMPILED, sizeof (u_int32_t));
549   if (strcmp (arg, "type-1") == 0)
550     *metric_type = EXTERNAL_METRIC_TYPE_1;
551   else if (strcmp (arg, "type-2") == 0)
552     *metric_type = EXTERNAL_METRIC_TYPE_2;
553
554   if (*metric_type == EXTERNAL_METRIC_TYPE_1 ||
555       *metric_type == EXTERNAL_METRIC_TYPE_2)
556     return metric_type;
557
558   XFREE (MTYPE_ROUTE_MAP_COMPILED, metric_type);
559   return NULL;
560 }
561
562 /* Free route map's compiled `set metric-type' value. */
563 static void
564 route_set_metric_type_free (void *rule)
565 {
566   XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
567 }
568
569 /* Set metric rule structure. */
570 struct route_map_rule_cmd route_set_metric_type_cmd =
571 {
572   "metric-type",
573   route_set_metric_type,
574   route_set_metric_type_compile,
575   route_set_metric_type_free,
576 };
577
578 static route_map_result_t
579 route_set_tag (void *rule, struct prefix *prefix,
580                route_map_object_t type, void *object)
581 {
582   route_tag_t *tag;
583   struct external_info *ei;
584
585   if (type == RMAP_OSPF)
586     {
587       tag = rule;
588       ei = object;
589
590       /* Set tag value */
591       ei->tag=*tag;
592     }
593
594   return RMAP_OKAY;
595 }
596
597 /* Route map commands for tag set. */
598 static struct route_map_rule_cmd route_set_tag_cmd =
599 {
600   "tag",
601   route_set_tag,
602   route_map_rule_tag_compile,
603   route_map_rule_tag_free,
604 };
605
606 DEFUN (match_ip_nexthop,
607        match_ip_nexthop_cmd,
608        "match ip next-hop (<1-199>|<1300-2699>|WORD)",
609        MATCH_STR
610        IP_STR
611        "Match next-hop address of route\n"
612        "IP access-list number\n"
613        "IP access-list number (expanded range)\n"
614        "IP access-list name\n")
615 {
616   return ospf_route_match_add (vty, vty->index, "ip next-hop", argv[0]);
617 }
618
619 DEFUN (no_match_ip_nexthop,
620        no_match_ip_nexthop_cmd,
621        "no match ip next-hop",
622        NO_STR
623        MATCH_STR
624        IP_STR
625        "Match next-hop address of route\n")
626 {
627   if (argc == 0)
628     return ospf_route_match_delete (vty, vty->index, "ip next-hop", NULL);
629
630   return ospf_route_match_delete (vty, vty->index, "ip next-hop", argv[0]);
631 }
632
633 ALIAS (no_match_ip_nexthop,
634        no_match_ip_nexthop_val_cmd,
635        "no match ip next-hop (<1-199>|<1300-2699>|WORD)",
636        NO_STR
637        MATCH_STR
638        IP_STR
639        "Match next-hop address of route\n"
640        "IP access-list number\n"
641        "IP access-list number (expanded range)\n"
642        "IP access-list name\n")
643
644 DEFUN (match_ip_next_hop_prefix_list,
645        match_ip_next_hop_prefix_list_cmd,
646        "match ip next-hop prefix-list WORD",
647        MATCH_STR
648        IP_STR
649        "Match next-hop address of route\n"
650        "Match entries of prefix-lists\n"
651        "IP prefix-list name\n")
652 {
653   return ospf_route_match_add (vty, vty->index, "ip next-hop prefix-list",
654                                argv[0]);
655 }
656
657 DEFUN (no_match_ip_next_hop_prefix_list,
658        no_match_ip_next_hop_prefix_list_cmd,
659        "no match ip next-hop prefix-list",
660        NO_STR
661        MATCH_STR
662        IP_STR
663        "Match next-hop address of route\n"
664        "Match entries of prefix-lists\n")
665 {
666   if (argc == 0)
667     return ospf_route_match_delete (vty, vty->index, "ip next-hop prefix-list",
668                                     NULL);
669   return ospf_route_match_delete (vty, vty->index, "ip next-hop prefix-list",
670                                   argv[0]);
671 }
672
673 ALIAS (no_match_ip_next_hop_prefix_list,
674        no_match_ip_next_hop_prefix_list_val_cmd,
675        "no match ip next-hop prefix-list WORD",
676        NO_STR
677        MATCH_STR
678        IP_STR
679        "Match next-hop address of route\n"
680        "Match entries of prefix-lists\n"
681        "IP prefix-list name\n")
682
683 DEFUN (match_ip_address,
684        match_ip_address_cmd,
685        "match ip address (<1-199>|<1300-2699>|WORD)",
686        MATCH_STR
687        IP_STR
688        "Match address of route\n"
689        "IP access-list number\n"
690        "IP access-list number (expanded range)\n"
691        "IP access-list name\n")
692 {
693   return ospf_route_match_add (vty, vty->index, "ip address", argv[0]);
694 }
695
696 DEFUN (no_match_ip_address,
697        no_match_ip_address_cmd,
698        "no match ip address",
699        NO_STR
700        MATCH_STR
701        IP_STR
702        "Match address of route\n")
703 {
704   if (argc == 0)
705     return ospf_route_match_delete (vty, vty->index, "ip address", NULL);
706
707   return ospf_route_match_delete (vty, vty->index, "ip address", argv[0]);
708 }
709
710 ALIAS (no_match_ip_address,
711        no_match_ip_address_val_cmd,
712        "no match ip address (<1-199>|<1300-2699>|WORD)",
713        NO_STR
714        MATCH_STR
715        IP_STR
716        "Match address of route\n"
717        "IP access-list number\n"
718        "IP access-list number (expanded range)\n"
719        "IP access-list name\n")
720
721 DEFUN (match_ip_address_prefix_list,
722        match_ip_address_prefix_list_cmd,
723        "match ip address prefix-list WORD",
724        MATCH_STR
725        IP_STR
726        "Match address of route\n"
727        "Match entries of prefix-lists\n"
728        "IP prefix-list name\n")
729 {
730   return ospf_route_match_add (vty, vty->index, "ip address prefix-list",
731                                argv[0]);
732 }
733
734 DEFUN (no_match_ip_address_prefix_list,
735        no_match_ip_address_prefix_list_cmd,
736        "no match ip address prefix-list",
737        NO_STR
738        MATCH_STR
739        IP_STR
740        "Match address of route\n"
741        "Match entries of prefix-lists\n")
742 {
743   if (argc == 0)
744     return ospf_route_match_delete (vty, vty->index, "ip address prefix-list",
745                                     NULL);
746   return ospf_route_match_delete (vty, vty->index, "ip address prefix-list",
747                                   argv[0]);
748 }
749
750 ALIAS (no_match_ip_address_prefix_list,
751        no_match_ip_address_prefix_list_val_cmd,
752        "no match ip address prefix-list WORD",
753        NO_STR
754        MATCH_STR
755        IP_STR
756        "Match address of route\n"
757        "Match entries of prefix-lists\n"
758        "IP prefix-list name\n")
759
760 DEFUN (match_interface,
761        match_interface_cmd,
762        "match interface WORD",
763        MATCH_STR
764        "Match first hop interface of route\n"
765        "Interface name\n")
766 {
767   return ospf_route_match_add (vty, vty->index, "interface", argv[0]);
768 }
769
770 DEFUN (no_match_interface,
771        no_match_interface_cmd,
772        "no match interface",
773        NO_STR
774        MATCH_STR
775        "Match first hop interface of route\n")
776 {
777   if (argc == 0)
778     return ospf_route_match_delete (vty, vty->index, "interface", NULL);
779
780   return ospf_route_match_delete (vty, vty->index, "interface", argv[0]);
781 }
782
783 ALIAS (no_match_interface,
784        no_match_interface_val_cmd,
785        "no match interface WORD",
786        NO_STR
787        MATCH_STR
788        "Match first hop interface of route\n"
789        "Interface name\n")
790
791 DEFUN (match_tag,
792        match_tag_cmd,
793        "match tag <1-4294967295>",
794        MATCH_STR
795        "Match tag of route\n"
796        "Tag value\n")
797 {
798   return ospf_route_match_add (vty, vty->index, "tag", argv[0]);
799 }
800
801 DEFUN (no_match_tag,
802        no_match_tag_cmd,
803        "no match tag",
804        NO_STR
805        MATCH_STR
806        "Match tag of route\n")
807 {
808   if (argc == 0)
809     return ospf_route_match_delete (vty, vty->index, "tag", NULL);
810
811   return ospf_route_match_delete (vty, vty->index, "tag", argv[0]);
812 }
813
814 ALIAS (no_match_tag,
815        no_match_tag_val_cmd,
816        "no match tag <1-4294967295>",
817        NO_STR
818        MATCH_STR
819        "Match tag of route\n"
820        "Tag value\n")
821
822 DEFUN (set_metric,
823        set_metric_cmd,
824        "set metric <0-4294967295>",
825        SET_STR
826        "Metric value for destination routing protocol\n"
827        "Metric value\n")
828 {
829   return ospf_route_set_add (vty, vty->index, "metric", argv[0]);
830 }
831
832 DEFUN (no_set_metric,
833        no_set_metric_cmd,
834        "no set metric",
835        NO_STR
836        SET_STR
837        "Metric value for destination routing protocol\n")
838 {
839   if (argc == 0)
840     return ospf_route_set_delete (vty, vty->index, "metric", NULL);
841
842   return ospf_route_set_delete (vty, vty->index, "metric", argv[0]);
843 }
844
845 ALIAS (no_set_metric,
846        no_set_metric_val_cmd,
847        "no set metric <0-4294967295>",
848        NO_STR
849        SET_STR
850        "Metric value for destination routing protocol\n"
851        "Metric value\n")
852
853 DEFUN (set_metric_type,
854        set_metric_type_cmd,
855        "set metric-type (type-1|type-2)",
856        SET_STR
857        "Type of metric for destination routing protocol\n"
858        "OSPF[6] external type 1 metric\n"
859        "OSPF[6] external type 2 metric\n")
860 {
861   if (strcmp (argv[0], "1") == 0)
862     return ospf_route_set_add (vty, vty->index, "metric-type", "type-1");
863   if (strcmp (argv[0], "2") == 0)
864     return ospf_route_set_add (vty, vty->index, "metric-type", "type-2");
865
866   return ospf_route_set_add (vty, vty->index, "metric-type", argv[0]);
867 }
868
869 DEFUN (no_set_metric_type,
870        no_set_metric_type_cmd,
871        "no set metric-type",
872        NO_STR
873        SET_STR
874        "Type of metric for destination routing protocol\n")
875 {
876   if (argc == 0)
877     return ospf_route_set_delete (vty, vty->index, "metric-type", NULL);
878
879   return ospf_route_set_delete (vty, vty->index, "metric-type", argv[0]);
880 }
881
882 ALIAS (no_set_metric_type,
883        no_set_metric_type_val_cmd,
884        "no set metric-type (type-1|type-2)",
885        NO_STR
886        SET_STR
887        "Type of metric for destination routing protocol\n"
888        "OSPF[6] external type 1 metric\n"
889        "OSPF[6] external type 2 metric\n")
890
891 DEFUN (set_tag,
892        set_tag_cmd,
893        "set tag <1-4294967295>",
894        SET_STR
895        "Tag value for routing protocol\n"
896        "Tag value\n")
897 {
898   return ospf_route_set_add (vty, vty->index, "tag", argv[0]);
899 }
900
901 DEFUN (no_set_tag,
902        no_set_tag_cmd,
903        "no set tag",
904        NO_STR
905        SET_STR
906        "Tag value for routing protocol\n")
907 {
908   if (argc == 0)
909       ospf_route_set_delete(vty, vty->index, "tag", NULL);
910
911   return ospf_route_set_delete (vty, vty->index, "tag", argv[0]);
912 }
913
914 ALIAS (no_set_tag,
915        no_set_tag_val_cmd,
916        "no set tag <1-4294967295>",
917        NO_STR
918        SET_STR
919        "Tag value for routing protocol\n"
920        "Tag value\n")
921
922 /* Route-map init */
923 void
924 ospf_route_map_init (void)
925 {
926   route_map_init ();
927   route_map_init_vty ();
928
929   route_map_add_hook (ospf_route_map_update);
930   route_map_delete_hook (ospf_route_map_update);
931   route_map_event_hook (ospf_route_map_event);
932   
933   route_map_install_match (&route_match_ip_nexthop_cmd);
934   route_map_install_match (&route_match_ip_next_hop_prefix_list_cmd);
935   route_map_install_match (&route_match_ip_address_cmd);
936   route_map_install_match (&route_match_ip_address_prefix_list_cmd);
937   route_map_install_match (&route_match_interface_cmd);
938   route_map_install_match (&route_match_tag_cmd);
939
940   route_map_install_set (&route_set_metric_cmd);
941   route_map_install_set (&route_set_metric_type_cmd);
942   route_map_install_set (&route_set_tag_cmd);
943
944   install_element (RMAP_NODE, &match_ip_nexthop_cmd);
945   install_element (RMAP_NODE, &no_match_ip_nexthop_cmd);
946   install_element (RMAP_NODE, &no_match_ip_nexthop_val_cmd);
947   install_element (RMAP_NODE, &match_ip_next_hop_prefix_list_cmd);
948   install_element (RMAP_NODE, &no_match_ip_next_hop_prefix_list_cmd);
949   install_element (RMAP_NODE, &no_match_ip_next_hop_prefix_list_val_cmd);
950   install_element (RMAP_NODE, &match_ip_address_cmd);
951   install_element (RMAP_NODE, &no_match_ip_address_cmd);
952   install_element (RMAP_NODE, &no_match_ip_address_val_cmd);
953   install_element (RMAP_NODE, &match_ip_address_prefix_list_cmd);
954   install_element (RMAP_NODE, &no_match_ip_address_prefix_list_cmd);
955   install_element (RMAP_NODE, &no_match_ip_address_prefix_list_val_cmd);
956   install_element (RMAP_NODE, &match_interface_cmd);
957   install_element (RMAP_NODE, &no_match_interface_cmd);
958   install_element (RMAP_NODE, &no_match_interface_val_cmd);
959   install_element (RMAP_NODE, &match_tag_cmd);
960   install_element (RMAP_NODE, &no_match_tag_cmd);
961   install_element (RMAP_NODE, &no_match_tag_val_cmd);
962
963   install_element (RMAP_NODE, &set_metric_cmd);
964   install_element (RMAP_NODE, &no_set_metric_cmd);
965   install_element (RMAP_NODE, &no_set_metric_val_cmd);
966   install_element (RMAP_NODE, &set_metric_type_cmd);
967   install_element (RMAP_NODE, &no_set_metric_type_cmd);
968   install_element (RMAP_NODE, &no_set_metric_type_val_cmd);
969   install_element (RMAP_NODE, &set_tag_cmd);
970   install_element (RMAP_NODE, &no_set_tag_cmd);
971   install_element (RMAP_NODE, &no_set_tag_val_cmd);
972 }