1/* Route map function of bgpd.
2   Copyright (C) 1998, 1999 Kunihiro Ishiguro
3
4This file is part of GNU Zebra.
5
6GNU Zebra is free software; you can redistribute it and/or modify it
7under the terms of the GNU General Public License as published by the
8Free Software Foundation; either version 2, or (at your option) any
9later version.
10
11GNU Zebra is distributed in the hope that it will be useful, but
12WITHOUT ANY WARRANTY; without even the implied warranty of
13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14General Public License for more details.
15
16You should have received a copy of the GNU General Public License
17along with GNU Zebra; see the file COPYING.  If not, write to the Free
18Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
1902111-1307, USA.  */
20
21#include <zebra.h>
22
23#include "prefix.h"
24#include "filter.h"
25#include "routemap.h"
26#include "command.h"
27#include "linklist.h"
28#include "plist.h"
29#include "memory.h"
30#include "log.h"
31#ifdef HAVE_GNU_REGEX
32#include <regex.h>
33#else
34#include "regex-gnu.h"
35#endif /* HAVE_GNU_REGEX */
36#include "buffer.h"
37#include "sockunion.h"
38
39#include "bgpd/bgpd.h"
40#include "bgpd/bgp_table.h"
41#include "bgpd/bgp_attr.h"
42#include "bgpd/bgp_aspath.h"
43#include "bgpd/bgp_route.h"
44#include "bgpd/bgp_regex.h"
45#include "bgpd/bgp_community.h"
46#include "bgpd/bgp_clist.h"
47#include "bgpd/bgp_filter.h"
48#include "bgpd/bgp_mplsvpn.h"
49#include "bgpd/bgp_ecommunity.h"
50
51/* Memo of route-map commands.
52
53o Cisco route-map
54
55 match as-path          :  Done
56       community        :  Done
57       interface        :  Not yet
58       ip address       :  Done
59       ip next-hop      :  Done
60       ip route-source  :  (This will not be implemented by bgpd)
61       ip prefix-list   :  Done
62       ipv6 address     :  Done
63       ipv6 next-hop    :  Done
64       ipv6 route-source:  (This will not be implemented by bgpd)
65       ipv6 prefix-list :  Done
66       length           :  (This will not be implemented by bgpd)
67       metric           :  Done
68       route-type       :  (This will not be implemented by bgpd)
69       tag              :  (This will not be implemented by bgpd)
70
71 set  as-path prepend   :  Done
72      as-path tag       :  Not yet
73      automatic-tag     :  (This will not be implemented by bgpd)
74      community         :  Done
75      comm-list         :  Not yet
76      dampning          :  Not yet
77      default           :  (This will not be implemented by bgpd)
78      interface         :  (This will not be implemented by bgpd)
79      ip default        :  (This will not be implemented by bgpd)
80      ip next-hop       :  Done
81      ip precedence     :  (This will not be implemented by bgpd)
82      ip tos            :  (This will not be implemented by bgpd)
83      level             :  (This will not be implemented by bgpd)
84      local-preference  :  Done
85      metric            :  Done
86      metric-type       :  Not yet
87      origin            :  Done
88      tag               :  (This will not be implemented by bgpd)
89      weight            :  Done
90
91o Local extention
92
93  set ipv6 next-hop global: Done
94  set ipv6 next-hop local : Done
95
96*/
97
98/* `match ip address IP_ACCESS_LIST' */
99
100/* Match function should return 1 if match is success else return
101   zero. */
102route_map_result_t
103route_match_ip_address (void *rule, struct prefix *prefix,
104			route_map_object_t type, void *object)
105{
106  struct access_list *alist;
107  /* struct prefix_ipv4 match; */
108
109  if (type == RMAP_BGP)
110    {
111      alist = access_list_lookup (AFI_IP, (char *) rule);
112      if (alist == NULL)
113	return RMAP_NOMATCH;
114
115      return (access_list_apply (alist, prefix) == FILTER_DENY ?
116	      RMAP_NOMATCH : RMAP_MATCH);
117    }
118  return RMAP_NOMATCH;
119}
120
121/* Route map `ip address' match statement.  `arg' should be
122   access-list name. */
123void *
124route_match_ip_address_compile (char *arg)
125{
126  return XSTRDUP (MTYPE_ROUTE_MAP_COMPILED, arg);
127}
128
129/* Free route map's compiled `ip address' value. */
130void
131route_match_ip_address_free (void *rule)
132{
133  XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
134}
135
136/* Route map commands for ip address matching. */
137struct route_map_rule_cmd route_match_ip_address_cmd =
138{
139  "ip address",
140  route_match_ip_address,
141  route_match_ip_address_compile,
142  route_match_ip_address_free
143};
144
145/* `match ip next-hop IP_ADDRESS' */
146
147/* Match function return 1 if match is success else return zero. */
148route_map_result_t
149route_match_ip_next_hop (void *rule, struct prefix *prefix,
150			 route_map_object_t type, void *object)
151{
152  struct access_list *alist;
153  struct bgp_info *bgp_info;
154  struct prefix_ipv4 p;
155
156  if (type == RMAP_BGP)
157    {
158      bgp_info = object;
159      p.family = AF_INET;
160      p.prefix = bgp_info->attr->nexthop;
161      p.prefixlen = IPV4_MAX_BITLEN;
162
163      alist = access_list_lookup (AFI_IP, (char *) rule);
164      if (alist == NULL)
165	return RMAP_NOMATCH;
166
167      return (access_list_apply (alist, &p) == FILTER_DENY ?
168              RMAP_NOMATCH : RMAP_MATCH);
169    }
170  return RMAP_NOMATCH;
171}
172
173/* Route map `ip next-hop' match statement. `arg' is
174   access-list name. */
175void *
176route_match_ip_next_hop_compile (char *arg)
177{
178  return XSTRDUP (MTYPE_ROUTE_MAP_COMPILED, arg);
179}
180
181/* Free route map's compiled `ip address' value. */
182void
183route_match_ip_next_hop_free (void *rule)
184{
185  XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
186}
187
188/* Route map commands for ip next-hop matching. */
189struct route_map_rule_cmd route_match_ip_next_hop_cmd =
190{
191  "ip next-hop",
192  route_match_ip_next_hop,
193  route_match_ip_next_hop_compile,
194  route_match_ip_next_hop_free
195};
196
197/* `match ip address prefix-list PREFIX_LIST' */
198
199route_map_result_t
200route_match_ip_address_prefix_list (void *rule, struct prefix *prefix,
201				    route_map_object_t type, void *object)
202{
203  struct prefix_list *plist;
204
205  if (type == RMAP_BGP)
206    {
207      plist = prefix_list_lookup (AFI_IP, (char *) rule);
208      if (plist == NULL)
209	return RMAP_NOMATCH;
210
211      return (prefix_list_apply (plist, prefix) == PREFIX_DENY ?
212	      RMAP_NOMATCH : RMAP_MATCH);
213    }
214  return RMAP_NOMATCH;
215}
216
217void *
218route_match_ip_address_prefix_list_compile (char *arg)
219{
220  return XSTRDUP (MTYPE_ROUTE_MAP_COMPILED, arg);
221}
222
223void
224route_match_ip_address_prefix_list_free (void *rule)
225{
226  XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
227}
228
229struct route_map_rule_cmd route_match_ip_address_prefix_list_cmd =
230{
231  "ip address prefix-list",
232  route_match_ip_address_prefix_list,
233  route_match_ip_address_prefix_list_compile,
234  route_match_ip_address_prefix_list_free
235};
236
237/* `match ip next-hop prefix-list PREFIX_LIST' */
238
239route_map_result_t
240route_match_ip_next_hop_prefix_list (void *rule, struct prefix *prefix,
241                                    route_map_object_t type, void *object)
242{
243  struct prefix_list *plist;
244  struct bgp_info *bgp_info;
245  struct prefix_ipv4 p;
246
247  if (type == RMAP_BGP)
248    {
249      bgp_info = object;
250      p.family = AF_INET;
251      p.prefix = bgp_info->attr->nexthop;
252      p.prefixlen = IPV4_MAX_BITLEN;
253
254      plist = prefix_list_lookup (AFI_IP, (char *) rule);
255      if (plist == NULL)
256        return RMAP_NOMATCH;
257
258      return (prefix_list_apply (plist, &p) == PREFIX_DENY ?
259              RMAP_NOMATCH : RMAP_MATCH);
260    }
261  return RMAP_NOMATCH;
262}
263
264void *
265route_match_ip_next_hop_prefix_list_compile (char *arg)
266{
267  return XSTRDUP (MTYPE_ROUTE_MAP_COMPILED, arg);
268}
269
270void
271route_match_ip_next_hop_prefix_list_free (void *rule)
272{
273  XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
274}
275
276struct route_map_rule_cmd route_match_ip_next_hop_prefix_list_cmd =
277{
278  "ip next-hop prefix-list",
279  route_match_ip_next_hop_prefix_list,
280  route_match_ip_next_hop_prefix_list_compile,
281  route_match_ip_next_hop_prefix_list_free
282};
283
284/* `match metric METRIC' */
285
286/* Match function return 1 if match is success else return zero. */
287route_map_result_t
288route_match_metric (void *rule, struct prefix *prefix,
289		    route_map_object_t type, void *object)
290{
291  u_int32_t *med;
292  struct bgp_info *bgp_info;
293
294  if (type == RMAP_BGP)
295    {
296      med = rule;
297      bgp_info = object;
298
299      if (bgp_info->attr->med == *med)
300	return RMAP_MATCH;
301      else
302	return RMAP_NOMATCH;
303    }
304  return RMAP_NOMATCH;
305}
306
307/* Route map `match metric' match statement. `arg' is MED value */
308void *
309route_match_metric_compile (char *arg)
310{
311  u_int32_t *med;
312  char *endptr = NULL;
313
314  med = XMALLOC (MTYPE_ROUTE_MAP_COMPILED, sizeof (u_int32_t));
315  *med = strtoul (arg, &endptr, 10);
316  if (*endptr != '\0' || *med == ULONG_MAX)
317    {
318      XFREE (MTYPE_ROUTE_MAP_COMPILED, med);
319      return NULL;
320    }
321  return med;
322}
323
324/* Free route map's compiled `match metric' value. */
325void
326route_match_metric_free (void *rule)
327{
328  XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
329}
330
331/* Route map commands for metric matching. */
332struct route_map_rule_cmd route_match_metric_cmd =
333{
334  "metric",
335  route_match_metric,
336  route_match_metric_compile,
337  route_match_metric_free
338};
339
340/* `match as-path ASPATH' */
341
342/* Match function for as-path match.  I assume given object is */
343route_map_result_t
344route_match_aspath (void *rule, struct prefix *prefix,
345		    route_map_object_t type, void *object)
346{
347
348  struct as_list *as_list;
349  struct bgp_info *bgp_info;
350
351  if (type == RMAP_BGP)
352    {
353      as_list = as_list_lookup ((char *) rule);
354      if (as_list == NULL)
355	return RMAP_NOMATCH;
356
357      bgp_info = object;
358
359      /* Perform match. */
360      return ((as_list_apply (as_list, bgp_info->attr->aspath) == AS_FILTER_DENY) ? RMAP_NOMATCH : RMAP_MATCH);
361    }
362  return RMAP_NOMATCH;
363}
364
365/* Compile function for as-path match. */
366void *
367route_match_aspath_compile (char *arg)
368{
369  return XSTRDUP (MTYPE_ROUTE_MAP_COMPILED, arg);
370}
371
372/* Compile function for as-path match. */
373void
374route_match_aspath_free (void *rule)
375{
376  XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
377}
378
379/* Route map commands for aspath matching. */
380struct route_map_rule_cmd route_match_aspath_cmd =
381{
382  "as-path",
383  route_match_aspath,
384  route_match_aspath_compile,
385  route_match_aspath_free
386};
387
388#if ROUTE_MATCH_ASPATH_OLD
389/* `match as-path ASPATH' */
390
391/* Match function for as-path match.  I assume given object is */
392int
393route_match_aspath (void *rule, struct prefix *prefix, void *object)
394{
395  regex_t *regex;
396  struct bgp_info *bgp_info;
397
398  regex = rule;
399  bgp_info = object;
400
401  /* Perform match. */
402  return bgp_regexec (regex, bgp_info->attr->aspath);
403}
404
405/* Compile function for as-path match. */
406void *
407route_match_aspath_compile (char *arg)
408{
409  regex_t *regex;
410
411  regex = bgp_regcomp (arg);
412  if (! regex)
413    return NULL;
414
415  return regex;
416}
417
418/* Compile function for as-path match. */
419void
420route_match_aspath_free (void *rule)
421{
422  regex_t *regex = rule;
423
424  bgp_regex_free (regex);
425}
426
427/* Route map commands for aspath matching. */
428struct route_map_rule_cmd route_match_aspath_cmd =
429{
430  "as-path",
431  route_match_aspath,
432  route_match_aspath_compile,
433  route_match_aspath_free
434};
435#endif /* ROUTE_MATCH_ASPATH_OLD */
436
437/* `match community COMMUNIY' */
438struct rmap_community
439{
440  char *name;
441  int exact;
442};
443
444/* Match function for community match. */
445route_map_result_t
446route_match_community (void *rule, struct prefix *prefix,
447		       route_map_object_t type, void *object)
448{
449  struct community_list *list;
450  struct bgp_info *bgp_info;
451  struct rmap_community *rcom;
452
453  if (type == RMAP_BGP)
454    {
455      bgp_info = object;
456      rcom = rule;
457
458      list = community_list_lookup (bgp_clist, rcom->name, COMMUNITY_LIST_AUTO);
459      if (! list)
460	return RMAP_NOMATCH;
461
462      if (rcom->exact)
463	{
464	  if (community_list_exact_match (bgp_info->attr->community, list))
465	    return RMAP_MATCH;
466	}
467      else
468	{
469	  if (community_list_match (bgp_info->attr->community, list))
470	    return RMAP_MATCH;
471	}
472    }
473  return RMAP_NOMATCH;
474}
475
476/* Compile function for community match. */
477void *
478route_match_community_compile (char *arg)
479{
480  struct rmap_community *rcom;
481  int len;
482  char *p;
483
484  rcom = XCALLOC (MTYPE_ROUTE_MAP_COMPILED, sizeof (struct rmap_community));
485
486  p = strchr (arg, ' ');
487  if (p)
488    {
489      len = p - arg;
490      rcom->name = XCALLOC (MTYPE_ROUTE_MAP_COMPILED, len + 1);
491      memcpy (rcom->name, arg, len);
492      rcom->exact = 1;
493    }
494  else
495    {
496      rcom->name = XSTRDUP (MTYPE_ROUTE_MAP_COMPILED, arg);
497      rcom->exact = 0;
498    }
499  return rcom;
500}
501
502/* Compile function for community match. */
503void
504route_match_community_free (void *rule)
505{
506  struct rmap_community *rcom = rule;
507
508  XFREE (MTYPE_ROUTE_MAP_COMPILED, rcom->name);
509  XFREE (MTYPE_ROUTE_MAP_COMPILED, rcom);
510}
511
512/* Route map commands for community matching. */
513struct route_map_rule_cmd route_match_community_cmd =
514{
515  "community",
516  route_match_community,
517  route_match_community_compile,
518  route_match_community_free
519};
520
521/* `match nlri` and `set nlri` are replaced by `address-family ipv4`
522   and `address-family vpnv4'.  */
523
524/* `match origin' */
525route_map_result_t
526route_match_origin (void *rule, struct prefix *prefix,
527		    route_map_object_t type, void *object)
528{
529  u_char *origin;
530  struct bgp_info *bgp_info;
531
532  if (type == RMAP_BGP)
533    {
534      origin = rule;
535      bgp_info = object;
536
537      if (bgp_info->attr->origin == *origin)
538	return RMAP_MATCH;
539    }
540
541  return RMAP_NOMATCH;
542}
543
544void *
545route_match_origin_compile (char *arg)
546{
547  u_char *origin;
548
549  origin = XMALLOC (MTYPE_ROUTE_MAP_COMPILED, sizeof (u_char));
550
551  if (strcmp (arg, "igp") == 0)
552    *origin = 0;
553  else if (strcmp (arg, "egp") == 0)
554    *origin = 1;
555  else
556    *origin = 2;
557
558  return origin;
559}
560
561/* Free route map's compiled `ip address' value. */
562void
563route_match_origin_free (void *rule)
564{
565  XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
566}
567
568/* Route map commands for origin matching. */
569struct route_map_rule_cmd route_match_origin_cmd =
570{
571  "origin",
572  route_match_origin,
573  route_match_origin_compile,
574  route_match_origin_free
575};
576/* `set ip next-hop IP_ADDRESS' */
577
578/* Set nexthop to object.  ojbect must be pointer to struct attr. */
579route_map_result_t
580route_set_ip_nexthop (void *rule, struct prefix *prefix,
581		      route_map_object_t type, void *object)
582{
583  struct in_addr *address;
584  struct bgp_info *bgp_info;
585
586  if (type == RMAP_BGP)
587    {
588      /* Fetch routemap's rule information. */
589      address = rule;
590      bgp_info = object;
591
592      /* Set next hop value. */
593      bgp_info->attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_NEXT_HOP);
594      bgp_info->attr->nexthop = *address;
595    }
596
597  return RMAP_OKAY;
598}
599
600/* Route map `ip nexthop' compile function.  Given string is converted
601   to struct in_addr structure. */
602void *
603route_set_ip_nexthop_compile (char *arg)
604{
605  int ret;
606  struct in_addr *address;
607
608  address = XMALLOC (MTYPE_ROUTE_MAP_COMPILED, sizeof (struct in_addr));
609
610  ret = inet_aton (arg, address);
611
612  if (ret == 0)
613    {
614      XFREE (MTYPE_ROUTE_MAP_COMPILED, address);
615      return NULL;
616    }
617
618  return address;
619}
620
621/* Free route map's compiled `ip nexthop' value. */
622void
623route_set_ip_nexthop_free (void *rule)
624{
625  XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
626}
627
628/* Route map commands for ip nexthop set. */
629struct route_map_rule_cmd route_set_ip_nexthop_cmd =
630{
631  "ip next-hop",
632  route_set_ip_nexthop,
633  route_set_ip_nexthop_compile,
634  route_set_ip_nexthop_free
635};
636
637/* `set local-preference LOCAL_PREF' */
638
639/* Set local preference. */
640route_map_result_t
641route_set_local_pref (void *rule, struct prefix *prefix,
642		      route_map_object_t type, void *object)
643{
644  u_int32_t *local_pref;
645  struct bgp_info *bgp_info;
646
647  if (type == RMAP_BGP)
648    {
649      /* Fetch routemap's rule information. */
650      local_pref = rule;
651      bgp_info = object;
652
653      /* Set local preference value. */
654      bgp_info->attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_LOCAL_PREF);
655      bgp_info->attr->local_pref = *local_pref;
656    }
657
658  return RMAP_OKAY;
659}
660
661/* set local preference compilation. */
662void *
663route_set_local_pref_compile (char *arg)
664{
665  u_int32_t *local_pref;
666  char *endptr = NULL;
667
668  /* Local preference value shoud be integer. */
669  if (! all_digit (arg))
670    return NULL;
671
672  local_pref = XMALLOC (MTYPE_ROUTE_MAP_COMPILED, sizeof (u_int32_t));
673  *local_pref = strtoul (arg, &endptr, 10);
674  if (*endptr != '\0' || *local_pref == ULONG_MAX)
675    {
676      XFREE (MTYPE_ROUTE_MAP_COMPILED, local_pref);
677      return NULL;
678    }
679  return local_pref;
680}
681
682/* Free route map's local preference value. */
683void
684route_set_local_pref_free (void *rule)
685{
686  XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
687}
688
689/* Set local preference rule structure. */
690struct route_map_rule_cmd route_set_local_pref_cmd =
691{
692  "local-preference",
693  route_set_local_pref,
694  route_set_local_pref_compile,
695  route_set_local_pref_free,
696};
697
698/* `set weight WEIGHT' */
699
700/* Set weight. */
701route_map_result_t
702route_set_weight (void *rule, struct prefix *prefix, route_map_object_t type,
703		  void *object)
704{
705  u_int32_t *weight;
706  struct bgp_info *bgp_info;
707
708  if (type == RMAP_BGP)
709    {
710      /* Fetch routemap's rule information. */
711      weight = rule;
712      bgp_info = object;
713
714      /* Set weight value. */
715      bgp_info->attr->weight = *weight;
716    }
717
718  return RMAP_OKAY;
719}
720
721/* set local preference compilation. */
722void *
723route_set_weight_compile (char *arg)
724{
725  u_int32_t *weight;
726  char *endptr = NULL;
727
728  /* Local preference value shoud be integer. */
729  if (! all_digit (arg))
730    return NULL;
731
732  weight = XMALLOC (MTYPE_ROUTE_MAP_COMPILED, sizeof (u_int32_t));
733  *weight = strtoul (arg, &endptr, 10);
734  if (*endptr != '\0' || *weight == ULONG_MAX)
735    {
736      XFREE (MTYPE_ROUTE_MAP_COMPILED, weight);
737      return NULL;
738    }
739  return weight;
740}
741
742/* Free route map's local preference value. */
743void
744route_set_weight_free (void *rule)
745{
746  XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
747}
748
749/* Set local preference rule structure. */
750struct route_map_rule_cmd route_set_weight_cmd =
751{
752  "weight",
753  route_set_weight,
754  route_set_weight_compile,
755  route_set_weight_free,
756};
757
758/* `set metric METRIC' */
759
760/* Set metric to attribute. */
761route_map_result_t
762route_set_metric (void *rule, struct prefix *prefix,
763		  route_map_object_t type, void *object)
764{
765  char *metric;
766  u_int32_t metric_val;
767  struct bgp_info *bgp_info;
768
769  if (type == RMAP_BGP)
770    {
771      /* Fetch routemap's rule information. */
772      metric = rule;
773      bgp_info = object;
774
775      if (! (bgp_info->attr->flag & ATTR_FLAG_BIT (BGP_ATTR_MULTI_EXIT_DISC)))
776	bgp_info->attr->med = 0;
777      bgp_info->attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_MULTI_EXIT_DISC);
778
779      if (all_digit (metric))
780	{
781	  metric_val = strtoul (metric, (char **)NULL, 10);
782	  bgp_info->attr->med = metric_val;
783	}
784      else
785	{
786	  metric_val = strtoul (metric+1, (char **)NULL, 10);
787
788	  if (strncmp (metric, "+", 1) == 0)
789	    {
790	      if (bgp_info->attr->med/2 + metric_val/2 > ULONG_MAX/2)
791		bgp_info->attr->med = ULONG_MAX-1;
792	      else
793		bgp_info->attr->med += metric_val;
794	    }
795	  else if (strncmp (metric, "-", 1) == 0)
796	    {
797	      if (bgp_info->attr->med <= metric_val)
798		bgp_info->attr->med = 0;
799	      else
800		bgp_info->attr->med -= metric_val;
801	    }
802	}
803    }
804  return RMAP_OKAY;
805}
806
807/* set metric compilation. */
808void *
809route_set_metric_compile (char *arg)
810{
811  u_int32_t metric;
812  char *endptr = NULL;
813
814  if (all_digit (arg))
815    {
816      /* set metric value check*/
817      metric = strtoul (arg, &endptr, 10);
818      if (*endptr != '\0' || metric == ULONG_MAX)
819        return NULL;
820    }
821  else
822    {
823      /* set metric +/-value check */
824      if ((strncmp (arg, "+", 1) != 0
825	   && strncmp (arg, "-", 1) != 0)
826	   || (! all_digit (arg+1)))
827	return NULL;
828
829      metric = strtoul (arg+1, &endptr, 10);
830      if (*endptr != '\0' || metric == ULONG_MAX)
831	return NULL;
832    }
833
834  return XSTRDUP (MTYPE_ROUTE_MAP_COMPILED, arg);
835}
836
837/* Free route map's compiled `set metric' value. */
838void
839route_set_metric_free (void *rule)
840{
841  XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
842}
843
844/* Set metric rule structure. */
845struct route_map_rule_cmd route_set_metric_cmd =
846{
847  "metric",
848  route_set_metric,
849  route_set_metric_compile,
850  route_set_metric_free,
851};
852
853/* `set as-path prepend ASPATH' */
854
855/* For AS path prepend mechanism. */
856route_map_result_t
857route_set_aspath_prepend (void *rule, struct prefix *prefix, route_map_object_t type, void *object)
858{
859  struct aspath *aspath;
860  struct aspath *new;
861  struct bgp_info *binfo;
862
863  if (type == RMAP_BGP)
864    {
865      aspath = rule;
866      binfo = object;
867
868      if (binfo->attr->aspath->refcnt)
869	new = aspath_dup (binfo->attr->aspath);
870      else
871	new = binfo->attr->aspath;
872
873      aspath_prepend (aspath, new);
874      binfo->attr->aspath = new;
875    }
876
877  return RMAP_OKAY;
878}
879
880/* Compile function for as-path prepend. */
881void *
882route_set_aspath_prepend_compile (char *arg)
883{
884  struct aspath *aspath;
885
886  aspath = aspath_str2aspath (arg);
887  if (! aspath)
888    return NULL;
889  return aspath;
890}
891
892/* Compile function for as-path prepend. */
893void
894route_set_aspath_prepend_free (void *rule)
895{
896  struct aspath *aspath = rule;
897  aspath_free (aspath);
898}
899
900/* Set metric rule structure. */
901struct route_map_rule_cmd route_set_aspath_prepend_cmd =
902{
903  "as-path prepend",
904  route_set_aspath_prepend,
905  route_set_aspath_prepend_compile,
906  route_set_aspath_prepend_free,
907};
908
909/* `set community COMMUNITY' */
910struct rmap_com_set
911{
912  struct community *com;
913  int additive;
914  int none;
915};
916
917/* For community set mechanism. */
918route_map_result_t
919route_set_community (void *rule, struct prefix *prefix,
920		     route_map_object_t type, void *object)
921{
922  struct rmap_com_set *rcs;
923  struct bgp_info *binfo;
924  struct attr *attr;
925  struct community *new = NULL;
926  struct community *old;
927  struct community *merge;
928
929  if (type == RMAP_BGP)
930    {
931      rcs = rule;
932      binfo = object;
933      attr = binfo->attr;
934      old = attr->community;
935
936      /* "none" case.  */
937      if (rcs->none)
938	{
939	  attr->flag &= ~(ATTR_FLAG_BIT (BGP_ATTR_COMMUNITIES));
940	  attr->community = NULL;
941	  return RMAP_OKAY;
942	}
943
944      /* "additive" case.  */
945      if (rcs->additive && old)
946	{
947	  merge = community_merge (community_dup (old), rcs->com);
948	  new = community_uniq_sort (merge);
949	  community_free (merge);
950	}
951      else
952	new = community_dup (rcs->com);
953
954      attr->community = new;
955      attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_COMMUNITIES);
956    }
957
958  return RMAP_OKAY;
959}
960
961/* Compile function for set community. */
962void *
963route_set_community_compile (char *arg)
964{
965  struct rmap_com_set *rcs;
966  struct community *com = NULL;
967  char *sp;
968  int additive = 0;
969  int none = 0;
970
971  if (strcmp (arg, "none") == 0)
972    none = 1;
973  else
974    {
975      sp = strstr (arg, "additive");
976
977      if (sp && sp > arg)
978  	{
979	  /* "additive" keyworkd is included.  */
980	  additive = 1;
981	  *(sp - 1) = '\0';
982	}
983
984      com = community_str2com (arg);
985
986      if (additive)
987	*(sp - 1) = ' ';
988
989      if (! com)
990	return NULL;
991    }
992
993  rcs = XMALLOC (MTYPE_ROUTE_MAP_COMPILED, sizeof (struct rmap_com_set));
994  memset (rcs, 0, sizeof (struct rmap_com_set));
995
996  rcs->com = com;
997  rcs->additive = additive;
998  rcs->none = none;
999
1000  return rcs;
1001}
1002
1003/* Free function for set community. */
1004void
1005route_set_community_free (void *rule)
1006{
1007  struct rmap_com_set *rcs = rule;
1008
1009  if (rcs->com)
1010    community_free (rcs->com);
1011  XFREE (MTYPE_ROUTE_MAP_COMPILED, rcs);
1012}
1013
1014/* Set community rule structure. */
1015struct route_map_rule_cmd route_set_community_cmd =
1016{
1017  "community",
1018  route_set_community,
1019  route_set_community_compile,
1020  route_set_community_free,
1021};
1022
1023/* `set comm-list (<1-99>|<100-199>|WORD) delete' */
1024
1025/* For community set mechanism. */
1026route_map_result_t
1027route_set_community_delete (void *rule, struct prefix *prefix,
1028			    route_map_object_t type, void *object)
1029{
1030  struct community_list *list;
1031  struct community *merge;
1032  struct community *new;
1033  struct community *old;
1034  struct bgp_info *binfo;
1035
1036  if (type == RMAP_BGP)
1037    {
1038      if (! rule)
1039	return RMAP_OKAY;
1040
1041      binfo = object;
1042      list = community_list_lookup (bgp_clist, rule, COMMUNITY_LIST_AUTO);
1043      old = binfo->attr->community;
1044
1045      if (list && old)
1046	{
1047	  merge = community_list_match_delete (community_dup (old), list);
1048	  new = community_uniq_sort (merge);
1049	  community_free (merge);
1050
1051	  if (new->size == 0)
1052	    {
1053	      binfo->attr->community = NULL;
1054	      binfo->attr->flag &= ~ATTR_FLAG_BIT (BGP_ATTR_COMMUNITIES);
1055	      community_free (new);
1056	    }
1057	  else
1058	    {
1059	      binfo->attr->community = new;
1060	      binfo->attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_COMMUNITIES);
1061	    }
1062	}
1063    }
1064
1065  return RMAP_OKAY;
1066}
1067
1068/* Compile function for set community. */
1069void *
1070route_set_community_delete_compile (char *arg)
1071{
1072  char *p;
1073  char *str;
1074  int len;
1075
1076  p = strchr (arg, ' ');
1077  if (p)
1078    {
1079      len = p - arg;
1080      str = XCALLOC (MTYPE_ROUTE_MAP_COMPILED, len + 1);
1081      memcpy (str, arg, len);
1082    }
1083  else
1084    str = NULL;
1085
1086  return str;
1087}
1088
1089/* Free function for set community. */
1090void
1091route_set_community_delete_free (void *rule)
1092{
1093  XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
1094}
1095
1096/* Set community rule structure. */
1097struct route_map_rule_cmd route_set_community_delete_cmd =
1098{
1099  "comm-list",
1100  route_set_community_delete,
1101  route_set_community_delete_compile,
1102  route_set_community_delete_free,
1103};
1104
1105/* `set extcommunity rt COMMUNITY' */
1106
1107/* For community set mechanism. */
1108route_map_result_t
1109route_set_ecommunity_rt (void *rule, struct prefix *prefix,
1110			 route_map_object_t type, void *object)
1111{
1112  struct ecommunity *ecom;
1113  struct ecommunity *new_ecom;
1114  struct ecommunity *old_ecom;
1115  struct bgp_info *bgp_info;
1116
1117  if (type == RMAP_BGP)
1118    {
1119      ecom = rule;
1120      bgp_info = object;
1121
1122      if (! ecom)
1123	return RMAP_OKAY;
1124
1125      /* We assume additive for Extended Community. */
1126      old_ecom = bgp_info->attr->ecommunity;
1127
1128      if (old_ecom)
1129	new_ecom = ecommunity_merge (ecommunity_dup (old_ecom), ecom);
1130      else
1131	new_ecom = ecommunity_dup (ecom);
1132
1133      bgp_info->attr->ecommunity = new_ecom;
1134
1135      bgp_info->attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_EXT_COMMUNITIES);
1136    }
1137  return RMAP_OKAY;
1138}
1139
1140/* Compile function for set community. */
1141void *
1142route_set_ecommunity_rt_compile (char *arg)
1143{
1144  struct ecommunity *ecom;
1145
1146  ecom = ecommunity_str2com (arg, ECOMMUNITY_ROUTE_TARGET, 0);
1147  if (! ecom)
1148    return NULL;
1149  return ecom;
1150}
1151
1152/* Free function for set community. */
1153void
1154route_set_ecommunity_rt_free (void *rule)
1155{
1156  struct ecommunity *ecom = rule;
1157  ecommunity_free (ecom);
1158}
1159
1160/* Set community rule structure. */
1161struct route_map_rule_cmd route_set_ecommunity_rt_cmd =
1162{
1163  "extcommunity rt",
1164  route_set_ecommunity_rt,
1165  route_set_ecommunity_rt_compile,
1166  route_set_ecommunity_rt_free,
1167};
1168
1169/* `set extcommunity soo COMMUNITY' */
1170
1171/* For community set mechanism. */
1172route_map_result_t
1173route_set_ecommunity_soo (void *rule, struct prefix *prefix,
1174			 route_map_object_t type, void *object)
1175{
1176  struct ecommunity *ecom;
1177  struct bgp_info *bgp_info;
1178
1179  if (type == RMAP_BGP)
1180    {
1181      ecom = rule;
1182      bgp_info = object;
1183
1184      if (! ecom)
1185	return RMAP_OKAY;
1186
1187      bgp_info->attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_EXT_COMMUNITIES);
1188      bgp_info->attr->ecommunity = ecommunity_dup (ecom);
1189    }
1190  return RMAP_OKAY;
1191}
1192
1193/* Compile function for set community. */
1194void *
1195route_set_ecommunity_soo_compile (char *arg)
1196{
1197  struct ecommunity *ecom;
1198
1199  ecom = ecommunity_str2com (arg, ECOMMUNITY_SITE_ORIGIN, 0);
1200  if (! ecom)
1201    return NULL;
1202
1203  return ecom;
1204}
1205
1206/* Free function for set community. */
1207void
1208route_set_ecommunity_soo_free (void *rule)
1209{
1210  struct ecommunity *ecom = rule;
1211  ecommunity_free (ecom);
1212}
1213
1214/* Set community rule structure. */
1215struct route_map_rule_cmd route_set_ecommunity_soo_cmd =
1216{
1217  "extcommunity soo",
1218  route_set_ecommunity_soo,
1219  route_set_ecommunity_soo_compile,
1220  route_set_ecommunity_soo_free,
1221};
1222
1223/* `set origin ORIGIN' */
1224
1225/* For origin set. */
1226route_map_result_t
1227route_set_origin (void *rule, struct prefix *prefix, route_map_object_t type, void *object)
1228{
1229  u_char *origin;
1230  struct bgp_info *bgp_info;
1231
1232  if (type == RMAP_BGP)
1233    {
1234      origin = rule;
1235      bgp_info = object;
1236
1237      bgp_info->attr->origin = *origin;
1238    }
1239
1240  return RMAP_OKAY;
1241}
1242
1243/* Compile function for origin set. */
1244void *
1245route_set_origin_compile (char *arg)
1246{
1247  u_char *origin;
1248
1249  origin = XMALLOC (MTYPE_ROUTE_MAP_COMPILED, sizeof (u_char));
1250
1251  if (strcmp (arg, "igp") == 0)
1252    *origin = 0;
1253  else if (strcmp (arg, "egp") == 0)
1254    *origin = 1;
1255  else
1256    *origin = 2;
1257
1258  return origin;
1259}
1260
1261/* Compile function for origin set. */
1262void
1263route_set_origin_free (void *rule)
1264{
1265  XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
1266}
1267
1268/* Set metric rule structure. */
1269struct route_map_rule_cmd route_set_origin_cmd =
1270{
1271  "origin",
1272  route_set_origin,
1273  route_set_origin_compile,
1274  route_set_origin_free,
1275};
1276
1277/* `set atomic-aggregate' */
1278
1279/* For atomic aggregate set. */
1280route_map_result_t
1281route_set_atomic_aggregate (void *rule, struct prefix *prefix,
1282			    route_map_object_t type, void *object)
1283{
1284  struct bgp_info *bgp_info;
1285
1286  if (type == RMAP_BGP)
1287    {
1288      bgp_info = object;
1289      bgp_info->attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_ATOMIC_AGGREGATE);
1290    }
1291
1292  return RMAP_OKAY;
1293}
1294
1295/* Compile function for atomic aggregate. */
1296void *
1297route_set_atomic_aggregate_compile (char *arg)
1298{
1299  return (void *)1;
1300}
1301
1302/* Compile function for atomic aggregate. */
1303void
1304route_set_atomic_aggregate_free (void *rule)
1305{
1306  return;
1307}
1308
1309/* Set atomic aggregate rule structure. */
1310struct route_map_rule_cmd route_set_atomic_aggregate_cmd =
1311{
1312  "atomic-aggregate",
1313  route_set_atomic_aggregate,
1314  route_set_atomic_aggregate_compile,
1315  route_set_atomic_aggregate_free,
1316};
1317
1318/* `set aggregator as AS A.B.C.D' */
1319struct aggregator
1320{
1321  as_t as;
1322  struct in_addr address;
1323};
1324
1325route_map_result_t
1326route_set_aggregator_as (void *rule, struct prefix *prefix,
1327			 route_map_object_t type, void *object)
1328{
1329  struct bgp_info *bgp_info;
1330  struct aggregator *aggregator;
1331
1332  if (type == RMAP_BGP)
1333    {
1334      bgp_info = object;
1335      aggregator = rule;
1336
1337      bgp_info->attr->aggregator_as = aggregator->as;
1338      bgp_info->attr->aggregator_addr = aggregator->address;
1339      bgp_info->attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_AGGREGATOR);
1340    }
1341
1342  return RMAP_OKAY;
1343}
1344
1345void *
1346route_set_aggregator_as_compile (char *arg)
1347{
1348  struct aggregator *aggregator;
1349  char as[10];
1350  char address[20];
1351
1352  aggregator = XMALLOC (MTYPE_ROUTE_MAP_COMPILED, sizeof (struct aggregator));
1353  memset (aggregator, 0, sizeof (struct aggregator));
1354
1355  sscanf (arg, "%s %s", as, address);
1356
1357  aggregator->as = strtoul (as, NULL, 10);
1358  inet_aton (address, &aggregator->address);
1359
1360  return aggregator;
1361}
1362
1363void
1364route_set_aggregator_as_free (void *rule)
1365{
1366  XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
1367}
1368
1369struct route_map_rule_cmd route_set_aggregator_as_cmd =
1370{
1371  "aggregator as",
1372  route_set_aggregator_as,
1373  route_set_aggregator_as_compile,
1374  route_set_aggregator_as_free,
1375};
1376
1377#ifdef HAVE_IPV6
1378/* `match ipv6 address IP_ACCESS_LIST' */
1379
1380route_map_result_t
1381route_match_ipv6_address (void *rule, struct prefix *prefix,
1382			  route_map_object_t type, void *object)
1383{
1384  struct access_list *alist;
1385
1386  if (type == RMAP_BGP)
1387    {
1388      alist = access_list_lookup (AFI_IP6, (char *) rule);
1389      if (alist == NULL)
1390	return RMAP_NOMATCH;
1391
1392      return (access_list_apply (alist, prefix) == FILTER_DENY ?
1393	      RMAP_NOMATCH : RMAP_MATCH);
1394    }
1395  return RMAP_NOMATCH;
1396}
1397
1398void *
1399route_match_ipv6_address_compile (char *arg)
1400{
1401  return XSTRDUP (MTYPE_ROUTE_MAP_COMPILED, arg);
1402}
1403
1404void
1405route_match_ipv6_address_free (void *rule)
1406{
1407  XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
1408}
1409
1410/* Route map commands for ip address matching. */
1411struct route_map_rule_cmd route_match_ipv6_address_cmd =
1412{
1413  "ipv6 address",
1414  route_match_ipv6_address,
1415  route_match_ipv6_address_compile,
1416  route_match_ipv6_address_free
1417};
1418
1419/* `match ipv6 next-hop IP_ADDRESS' */
1420
1421route_map_result_t
1422route_match_ipv6_next_hop (void *rule, struct prefix *prefix,
1423			   route_map_object_t type, void *object)
1424{
1425  struct in6_addr *addr;
1426  struct bgp_info *bgp_info;
1427
1428  if (type == RMAP_BGP)
1429    {
1430      addr = rule;
1431      bgp_info = object;
1432
1433      if (IPV6_ADDR_SAME (&bgp_info->attr->mp_nexthop_global, rule))
1434	return RMAP_MATCH;
1435
1436      if (bgp_info->attr->mp_nexthop_len == 32 &&
1437	  IPV6_ADDR_SAME (&bgp_info->attr->mp_nexthop_local, rule))
1438	return RMAP_MATCH;
1439
1440      return RMAP_NOMATCH;
1441    }
1442
1443  return RMAP_NOMATCH;
1444}
1445
1446void *
1447route_match_ipv6_next_hop_compile (char *arg)
1448{
1449  struct in6_addr *address;
1450  int ret;
1451
1452  address = XMALLOC (MTYPE_ROUTE_MAP_COMPILED, sizeof (struct in6_addr));
1453
1454  ret = inet_pton (AF_INET6, arg, address);
1455  if (!ret)
1456    {
1457      XFREE (MTYPE_ROUTE_MAP_COMPILED, address);
1458      return NULL;
1459    }
1460
1461  return address;
1462}
1463
1464void
1465route_match_ipv6_next_hop_free (void *rule)
1466{
1467  XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
1468}
1469
1470struct route_map_rule_cmd route_match_ipv6_next_hop_cmd =
1471{
1472  "ipv6 next-hop",
1473  route_match_ipv6_next_hop,
1474  route_match_ipv6_next_hop_compile,
1475  route_match_ipv6_next_hop_free
1476};
1477
1478/* `match ipv6 address prefix-list PREFIX_LIST' */
1479
1480route_map_result_t
1481route_match_ipv6_address_prefix_list (void *rule, struct prefix *prefix,
1482			      route_map_object_t type, void *object)
1483{
1484  struct prefix_list *plist;
1485
1486  if (type == RMAP_BGP)
1487    {
1488      plist = prefix_list_lookup (AFI_IP6, (char *) rule);
1489      if (plist == NULL)
1490	return RMAP_NOMATCH;
1491
1492      return (prefix_list_apply (plist, prefix) == PREFIX_DENY ?
1493	      RMAP_NOMATCH : RMAP_MATCH);
1494    }
1495  return RMAP_NOMATCH;
1496}
1497
1498void *
1499route_match_ipv6_address_prefix_list_compile (char *arg)
1500{
1501  return XSTRDUP (MTYPE_ROUTE_MAP_COMPILED, arg);
1502}
1503
1504void
1505route_match_ipv6_address_prefix_list_free (void *rule)
1506{
1507  XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
1508}
1509
1510struct route_map_rule_cmd route_match_ipv6_address_prefix_list_cmd =
1511{
1512  "ipv6 address prefix-list",
1513  route_match_ipv6_address_prefix_list,
1514  route_match_ipv6_address_prefix_list_compile,
1515  route_match_ipv6_address_prefix_list_free
1516};
1517
1518/* `set ipv6 nexthop global IP_ADDRESS' */
1519
1520/* Set nexthop to object.  ojbect must be pointer to struct attr. */
1521route_map_result_t
1522route_set_ipv6_nexthop_global (void *rule, struct prefix *prefix,
1523			       route_map_object_t type, void *object)
1524{
1525  struct in6_addr *address;
1526  struct bgp_info *bgp_info;
1527
1528  if (type == RMAP_BGP)
1529    {
1530      /* Fetch routemap's rule information. */
1531      address = rule;
1532      bgp_info = object;
1533
1534      /* Set next hop value. */
1535      bgp_info->attr->mp_nexthop_global = *address;
1536
1537      /* Set nexthop length. */
1538      if (bgp_info->attr->mp_nexthop_len == 0)
1539	bgp_info->attr->mp_nexthop_len = 16;
1540    }
1541
1542  return RMAP_OKAY;
1543}
1544
1545/* Route map `ip next-hop' compile function.  Given string is converted
1546   to struct in_addr structure. */
1547void *
1548route_set_ipv6_nexthop_global_compile (char *arg)
1549{
1550  int ret;
1551  struct in6_addr *address;
1552
1553  address = XMALLOC (MTYPE_ROUTE_MAP_COMPILED, sizeof (struct in6_addr));
1554
1555  ret = inet_pton (AF_INET6, arg, address);
1556
1557  if (ret == 0)
1558    {
1559      XFREE (MTYPE_ROUTE_MAP_COMPILED, address);
1560      return NULL;
1561    }
1562
1563  return address;
1564}
1565
1566/* Free route map's compiled `ip next-hop' value. */
1567void
1568route_set_ipv6_nexthop_global_free (void *rule)
1569{
1570  XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
1571}
1572
1573/* Route map commands for ip nexthop set. */
1574struct route_map_rule_cmd route_set_ipv6_nexthop_global_cmd =
1575{
1576  "ipv6 next-hop global",
1577  route_set_ipv6_nexthop_global,
1578  route_set_ipv6_nexthop_global_compile,
1579  route_set_ipv6_nexthop_global_free
1580};
1581
1582/* `set ipv6 nexthop local IP_ADDRESS' */
1583
1584/* Set nexthop to object.  ojbect must be pointer to struct attr. */
1585route_map_result_t
1586route_set_ipv6_nexthop_local (void *rule, struct prefix *prefix,
1587			      route_map_object_t type, void *object)
1588{
1589  struct in6_addr *address;
1590  struct bgp_info *bgp_info;
1591
1592  if (type == RMAP_BGP)
1593    {
1594      /* Fetch routemap's rule information. */
1595      address = rule;
1596      bgp_info = object;
1597
1598      /* Set next hop value. */
1599      bgp_info->attr->mp_nexthop_local = *address;
1600
1601      /* Set nexthop length. */
1602      if (bgp_info->attr->mp_nexthop_len != 32)
1603	bgp_info->attr->mp_nexthop_len = 32;
1604    }
1605
1606  return RMAP_OKAY;
1607}
1608
1609/* Route map `ip nexthop' compile function.  Given string is converted
1610   to struct in_addr structure. */
1611void *
1612route_set_ipv6_nexthop_local_compile (char *arg)
1613{
1614  int ret;
1615  struct in6_addr *address;
1616
1617  address = XMALLOC (MTYPE_ROUTE_MAP_COMPILED, sizeof (struct in6_addr));
1618
1619  ret = inet_pton (AF_INET6, arg, address);
1620
1621  if (ret == 0)
1622    {
1623      XFREE (MTYPE_ROUTE_MAP_COMPILED, address);
1624      return NULL;
1625    }
1626
1627  return address;
1628}
1629
1630/* Free route map's compiled `ip nexthop' value. */
1631void
1632route_set_ipv6_nexthop_local_free (void *rule)
1633{
1634  XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
1635}
1636
1637/* Route map commands for ip nexthop set. */
1638struct route_map_rule_cmd route_set_ipv6_nexthop_local_cmd =
1639{
1640  "ipv6 next-hop local",
1641  route_set_ipv6_nexthop_local,
1642  route_set_ipv6_nexthop_local_compile,
1643  route_set_ipv6_nexthop_local_free
1644};
1645#endif /* HAVE_IPV6 */
1646
1647/* `set vpnv4 nexthop A.B.C.D' */
1648
1649route_map_result_t
1650route_set_vpnv4_nexthop (void *rule, struct prefix *prefix,
1651			 route_map_object_t type, void *object)
1652{
1653  struct in_addr *address;
1654  struct bgp_info *bgp_info;
1655
1656  if (type == RMAP_BGP)
1657    {
1658      /* Fetch routemap's rule information. */
1659      address = rule;
1660      bgp_info = object;
1661
1662      /* Set next hop value. */
1663      bgp_info->attr->mp_nexthop_global_in = *address;
1664    }
1665
1666  return RMAP_OKAY;
1667}
1668
1669void *
1670route_set_vpnv4_nexthop_compile (char *arg)
1671{
1672  int ret;
1673  struct in_addr *address;
1674
1675  address = XMALLOC (MTYPE_ROUTE_MAP_COMPILED, sizeof (struct in_addr));
1676
1677  ret = inet_aton (arg, address);
1678
1679  if (ret == 0)
1680    {
1681      XFREE (MTYPE_ROUTE_MAP_COMPILED, address);
1682      return NULL;
1683    }
1684
1685  return address;
1686}
1687
1688void
1689route_set_vpnv4_nexthop_free (void *rule)
1690{
1691  XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
1692}
1693
1694/* Route map commands for ip nexthop set. */
1695struct route_map_rule_cmd route_set_vpnv4_nexthop_cmd =
1696{
1697  "vpnv4 next-hop",
1698  route_set_vpnv4_nexthop,
1699  route_set_vpnv4_nexthop_compile,
1700  route_set_vpnv4_nexthop_free
1701};
1702
1703/* `set originator-id' */
1704
1705/* For origin set. */
1706route_map_result_t
1707route_set_originator_id (void *rule, struct prefix *prefix, route_map_object_t type, void *object)
1708{
1709  struct in_addr *address;
1710  struct bgp_info *bgp_info;
1711
1712  if (type == RMAP_BGP)
1713    {
1714      address = rule;
1715      bgp_info = object;
1716
1717      bgp_info->attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_ORIGINATOR_ID);
1718      bgp_info->attr->originator_id = *address;
1719    }
1720
1721  return RMAP_OKAY;
1722}
1723
1724/* Compile function for originator-id set. */
1725void *
1726route_set_originator_id_compile (char *arg)
1727{
1728  int ret;
1729  struct in_addr *address;
1730
1731  address = XMALLOC (MTYPE_ROUTE_MAP_COMPILED, sizeof (struct in_addr));
1732
1733  ret = inet_aton (arg, address);
1734
1735  if (ret == 0)
1736    {
1737      XFREE (MTYPE_ROUTE_MAP_COMPILED, address);
1738      return NULL;
1739    }
1740
1741  return address;
1742}
1743
1744/* Compile function for originator_id set. */
1745void
1746route_set_originator_id_free (void *rule)
1747{
1748  XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
1749}
1750
1751/* Set metric rule structure. */
1752struct route_map_rule_cmd route_set_originator_id_cmd =
1753{
1754  "originator-id",
1755  route_set_originator_id,
1756  route_set_originator_id_compile,
1757  route_set_originator_id_free,
1758};
1759
1760/* Add bgp route map rule. */
1761int
1762bgp_route_match_add (struct vty *vty, struct route_map_index *index,
1763		    char *command, char *arg)
1764{
1765  int ret;
1766
1767  ret = route_map_add_match (index, command, arg);
1768  if (ret)
1769    {
1770      switch (ret)
1771	{
1772	case RMAP_RULE_MISSING:
1773	  vty_out (vty, "%% Can't find rule.%s", VTY_NEWLINE);
1774	  return CMD_WARNING;
1775	  break;
1776	case RMAP_COMPILE_ERROR:
1777	  vty_out (vty, "%% Argument is malformed.%s", VTY_NEWLINE);
1778	  return CMD_WARNING;
1779	  break;
1780	}
1781    }
1782  return CMD_SUCCESS;
1783}
1784
1785/* Delete bgp route map rule. */
1786int
1787bgp_route_match_delete (struct vty *vty, struct route_map_index *index,
1788			char *command, char *arg)
1789{
1790  int ret;
1791
1792  ret = route_map_delete_match (index, command, arg);
1793  if (ret)
1794    {
1795      switch (ret)
1796	{
1797	case RMAP_RULE_MISSING:
1798	  vty_out (vty, "%% Can't find rule.%s", VTY_NEWLINE);
1799	  return CMD_WARNING;
1800	  break;
1801	case RMAP_COMPILE_ERROR:
1802	  vty_out (vty, "%% Argument is malformed.%s", VTY_NEWLINE);
1803	  return CMD_WARNING;
1804	  break;
1805	}
1806    }
1807  return CMD_SUCCESS;
1808}
1809
1810/* Add bgp route map rule. */
1811int
1812bgp_route_set_add (struct vty *vty, struct route_map_index *index,
1813		   char *command, char *arg)
1814{
1815  int ret;
1816
1817  ret = route_map_add_set (index, command, arg);
1818  if (ret)
1819    {
1820      switch (ret)
1821	{
1822	case RMAP_RULE_MISSING:
1823	  vty_out (vty, "%% Can't find rule.%s", VTY_NEWLINE);
1824	  return CMD_WARNING;
1825	  break;
1826	case RMAP_COMPILE_ERROR:
1827	  vty_out (vty, "%% Argument is malformed.%s", VTY_NEWLINE);
1828	  return CMD_WARNING;
1829	  break;
1830	}
1831    }
1832  return CMD_SUCCESS;
1833}
1834
1835/* Delete bgp route map rule. */
1836int
1837bgp_route_set_delete (struct vty *vty, struct route_map_index *index,
1838		      char *command, char *arg)
1839{
1840  int ret;
1841
1842  ret = route_map_delete_set (index, command, arg);
1843  if (ret)
1844    {
1845      switch (ret)
1846	{
1847	case RMAP_RULE_MISSING:
1848	  vty_out (vty, "%% Can't find rule.%s", VTY_NEWLINE);
1849	  return CMD_WARNING;
1850	  break;
1851	case RMAP_COMPILE_ERROR:
1852	  vty_out (vty, "%% Argument is malformed.%s", VTY_NEWLINE);
1853	  return CMD_WARNING;
1854	  break;
1855	}
1856    }
1857  return CMD_SUCCESS;
1858}
1859
1860/* Hook function for updating route_map assignment. */
1861void
1862bgp_route_map_update ()
1863{
1864  int i;
1865  afi_t afi;
1866  safi_t safi;
1867  int direct;
1868  struct listnode *nn, *nm;
1869  struct bgp *bgp;
1870  struct peer *peer;
1871  struct peer_group *group;
1872  struct bgp_filter *filter;
1873  struct bgp_node *bn;
1874  struct bgp_static *bgp_static;
1875
1876  /* For neighbor route-map updates. */
1877  LIST_LOOP (bm->bgp, bgp, nn)
1878    {
1879      LIST_LOOP (bgp->peer, peer, nm)
1880	{
1881	  for (afi = AFI_IP; afi < AFI_MAX; afi++)
1882	    for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
1883	      {
1884		filter = &peer->filter[afi][safi];
1885
1886		for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
1887		  {
1888		    if (filter->map[direct].name)
1889		      filter->map[direct].map =
1890			route_map_lookup_by_name (filter->map[direct].name);
1891		    else
1892		      filter->map[direct].map = NULL;
1893		  }
1894
1895		if (filter->usmap.name)
1896		  filter->usmap.map = route_map_lookup_by_name (filter->usmap.name);
1897		else
1898		  filter->usmap.map = NULL;
1899	      }
1900	}
1901      LIST_LOOP (bgp->group, group, nm)
1902	{
1903	  for (afi = AFI_IP; afi < AFI_MAX; afi++)
1904	    for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
1905	      {
1906		filter = &group->conf->filter[afi][safi];
1907
1908		for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
1909		  {
1910		    if (filter->map[direct].name)
1911		      filter->map[direct].map =
1912			route_map_lookup_by_name (filter->map[direct].name);
1913		    else
1914		      filter->map[direct].map = NULL;
1915		  }
1916
1917		if (filter->usmap.name)
1918		  filter->usmap.map = route_map_lookup_by_name (filter->usmap.name);
1919		else
1920		  filter->usmap.map = NULL;
1921	      }
1922	}
1923    }
1924
1925  /* For default-originate route-map updates. */
1926  LIST_LOOP (bm->bgp, bgp, nn)
1927    {
1928      LIST_LOOP (bgp->peer, peer, nm)
1929	{
1930	  for (afi = AFI_IP; afi < AFI_MAX; afi++)
1931	    for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
1932	      {
1933		if (peer->default_rmap[afi][safi].name)
1934		  peer->default_rmap[afi][safi].map =
1935		    route_map_lookup_by_name (peer->default_rmap[afi][safi].name);
1936		else
1937		  peer->default_rmap[afi][safi].map = NULL;
1938	      }
1939	}
1940    }
1941
1942  /* For network route-map updates. */
1943  LIST_LOOP (bm->bgp, bgp, nn)
1944    {
1945      for (afi = AFI_IP; afi < AFI_MAX; afi++)
1946	for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
1947	  for (bn = bgp_table_top (bgp->route[afi][safi]); bn;
1948	       bn = bgp_route_next (bn))
1949	    if ((bgp_static = bn->info) != NULL)
1950	      {
1951		if (bgp_static->rmap.name)
1952		  bgp_static->rmap.map =
1953			 route_map_lookup_by_name (bgp_static->rmap.name);
1954		else
1955		  bgp_static->rmap.map = NULL;
1956	      }
1957    }
1958
1959  /* For redistribute route-map updates. */
1960  LIST_LOOP (bm->bgp, bgp, nn)
1961    {
1962      for (i = 0; i < ZEBRA_ROUTE_MAX; i++)
1963	{
1964	  if (bgp->rmap[ZEBRA_FAMILY_IPV4][i].name)
1965	    bgp->rmap[ZEBRA_FAMILY_IPV4][i].map =
1966	      route_map_lookup_by_name (bgp->rmap[ZEBRA_FAMILY_IPV4][i].name);
1967#ifdef HAVE_IPV6
1968	  if (bgp->rmap[ZEBRA_FAMILY_IPV6][i].name)
1969	    bgp->rmap[ZEBRA_FAMILY_IPV6][i].map =
1970	      route_map_lookup_by_name (bgp->rmap[ZEBRA_FAMILY_IPV6][i].name);
1971#endif /* HAVE_IPV6 */
1972	}
1973    }
1974}
1975
1976DEFUN (match_ip_address,
1977       match_ip_address_cmd,
1978       "match ip address (<1-199>|<1300-2699>|WORD)",
1979       MATCH_STR
1980       IP_STR
1981       "Match address of route\n"
1982       "IP access-list number\n"
1983       "IP access-list number (expanded range)\n"
1984       "IP Access-list name\n")
1985{
1986  return bgp_route_match_add (vty, vty->index, "ip address", argv[0]);
1987}
1988
1989DEFUN (no_match_ip_address,
1990       no_match_ip_address_cmd,
1991       "no match ip address",
1992       NO_STR
1993       MATCH_STR
1994       IP_STR
1995       "Match address of route\n")
1996{
1997  if (argc == 0)
1998    return bgp_route_match_delete (vty, vty->index, "ip address", NULL);
1999
2000  return bgp_route_match_delete (vty, vty->index, "ip address", argv[0]);
2001}
2002
2003ALIAS (no_match_ip_address,
2004       no_match_ip_address_val_cmd,
2005       "no match ip address (<1-199>|<1300-2699>|WORD)",
2006       NO_STR
2007       MATCH_STR
2008       IP_STR
2009       "Match address of route\n"
2010       "IP access-list number\n"
2011       "IP access-list number (expanded range)\n"
2012       "IP Access-list name\n")
2013
2014DEFUN (match_ip_next_hop,
2015       match_ip_next_hop_cmd,
2016       "match ip next-hop (<1-199>|<1300-2699>|WORD)",
2017       MATCH_STR
2018       IP_STR
2019       "Match next-hop address of route\n"
2020       "IP access-list number\n"
2021       "IP access-list number (expanded range)\n"
2022       "IP Access-list name\n")
2023{
2024  return bgp_route_match_add (vty, vty->index, "ip next-hop", argv[0]);
2025}
2026
2027DEFUN (no_match_ip_next_hop,
2028       no_match_ip_next_hop_cmd,
2029       "no match ip next-hop",
2030       NO_STR
2031       MATCH_STR
2032       IP_STR
2033       "Match next-hop address of route\n")
2034{
2035  if (argc == 0)
2036    return bgp_route_match_delete (vty, vty->index, "ip next-hop", NULL);
2037
2038  return bgp_route_match_delete (vty, vty->index, "ip next-hop", argv[0]);
2039}
2040
2041ALIAS (no_match_ip_next_hop,
2042       no_match_ip_next_hop_val_cmd,
2043       "no match ip next-hop (<1-199>|<1300-2699>|WORD)",
2044       NO_STR
2045       MATCH_STR
2046       IP_STR
2047       "Match next-hop address of route\n"
2048       "IP access-list number\n"
2049       "IP access-list number (expanded range)\n"
2050       "IP Access-list name\n")
2051
2052DEFUN (match_ip_address_prefix_list,
2053       match_ip_address_prefix_list_cmd,
2054       "match ip address prefix-list WORD",
2055       MATCH_STR
2056       IP_STR
2057       "Match address of route\n"
2058       "Match entries of prefix-lists\n"
2059       "IP prefix-list name\n")
2060{
2061  return bgp_route_match_add (vty, vty->index, "ip address prefix-list", argv[0]);
2062}
2063
2064DEFUN (no_match_ip_address_prefix_list,
2065       no_match_ip_address_prefix_list_cmd,
2066       "no match ip address prefix-list",
2067       NO_STR
2068       MATCH_STR
2069       IP_STR
2070       "Match address of route\n"
2071       "Match entries of prefix-lists\n")
2072{
2073  if (argc == 0)
2074    return bgp_route_match_delete (vty, vty->index, "ip address prefix-list", NULL);
2075
2076  return bgp_route_match_delete (vty, vty->index, "ip address prefix-list", argv[0]);
2077}
2078
2079ALIAS (no_match_ip_address_prefix_list,
2080       no_match_ip_address_prefix_list_val_cmd,
2081       "no match ip address prefix-list WORD",
2082       NO_STR
2083       MATCH_STR
2084       IP_STR
2085       "Match address of route\n"
2086       "Match entries of prefix-lists\n"
2087       "IP prefix-list name\n")
2088
2089DEFUN (match_ip_next_hop_prefix_list,
2090       match_ip_next_hop_prefix_list_cmd,
2091       "match ip next-hop prefix-list WORD",
2092       MATCH_STR
2093       IP_STR
2094       "Match next-hop address of route\n"
2095       "Match entries of prefix-lists\n"
2096       "IP prefix-list name\n")
2097{
2098  return bgp_route_match_add (vty, vty->index, "ip next-hop prefix-list", argv[0]);
2099}
2100
2101DEFUN (no_match_ip_next_hop_prefix_list,
2102       no_match_ip_next_hop_prefix_list_cmd,
2103       "no match ip next-hop prefix-list",
2104       NO_STR
2105       MATCH_STR
2106       IP_STR
2107       "Match next-hop address of route\n"
2108       "Match entries of prefix-lists\n")
2109{
2110  if (argc == 0)
2111    return bgp_route_match_delete (vty, vty->index, "ip next-hop prefix-list", NULL);
2112
2113  return bgp_route_match_delete (vty, vty->index, "ip next-hop prefix-list", argv[0]);
2114}
2115
2116ALIAS (no_match_ip_next_hop_prefix_list,
2117       no_match_ip_next_hop_prefix_list_val_cmd,
2118       "no match ip next-hop prefix-list WORD",
2119       NO_STR
2120       MATCH_STR
2121       IP_STR
2122       "Match next-hop address of route\n"
2123       "Match entries of prefix-lists\n"
2124       "IP prefix-list name\n")
2125
2126DEFUN (match_metric,
2127       match_metric_cmd,
2128       "match metric <0-4294967295>",
2129       MATCH_STR
2130       "Match metric of route\n"
2131       "Metric value\n")
2132{
2133  return bgp_route_match_add (vty, vty->index, "metric", argv[0]);
2134}
2135
2136DEFUN (no_match_metric,
2137       no_match_metric_cmd,
2138       "no match metric",
2139       NO_STR
2140       MATCH_STR
2141       "Match metric of route\n")
2142{
2143  if (argc == 0)
2144    return bgp_route_match_delete (vty, vty->index, "metric", NULL);
2145
2146  return bgp_route_match_delete (vty, vty->index, "metric", argv[0]);
2147}
2148
2149ALIAS (no_match_metric,
2150       no_match_metric_val_cmd,
2151       "no match metric <0-4294967295>",
2152       NO_STR
2153       MATCH_STR
2154       "Match metric of route\n"
2155       "Metric value\n")
2156
2157DEFUN (match_community,
2158       match_community_cmd,
2159       "match community (<1-99>|<100-199>|WORD)",
2160       MATCH_STR
2161       "Match BGP community list\n"
2162       "Community-list number (standard)\n"
2163       "Community-list number (expanded)\n"
2164       "Community-list name\n")
2165{
2166  return bgp_route_match_add (vty, vty->index, "community", argv[0]);
2167}
2168
2169DEFUN (match_community_exact,
2170       match_community_exact_cmd,
2171       "match community (<1-99>|<100-199>|WORD) exact-match",
2172       MATCH_STR
2173       "Match BGP community list\n"
2174       "Community-list number (standard)\n"
2175       "Community-list number (expanded)\n"
2176       "Community-list name\n"
2177       "Do exact matching of communities\n")
2178{
2179  int ret;
2180  char *argstr;
2181
2182  argstr = XMALLOC (MTYPE_ROUTE_MAP_COMPILED,
2183		    strlen (argv[0]) + strlen ("exact-match") + 2);
2184
2185  sprintf (argstr, "%s exact-match", argv[0]);
2186
2187  ret = bgp_route_match_add (vty, vty->index, "community", argstr);
2188
2189  XFREE (MTYPE_ROUTE_MAP_COMPILED, argstr);
2190
2191  return ret;
2192}
2193
2194DEFUN (no_match_community,
2195       no_match_community_cmd,
2196       "no match community",
2197       NO_STR
2198       MATCH_STR
2199       "Match BGP community list\n")
2200{
2201  return bgp_route_match_delete (vty, vty->index, "community", NULL);
2202}
2203
2204ALIAS (no_match_community,
2205       no_match_community_val_cmd,
2206       "no match community (<1-99>|<100-199>|WORD)",
2207       NO_STR
2208       MATCH_STR
2209       "Match BGP community list\n"
2210       "Community-list number (standard)\n"
2211       "Community-list number (expanded)\n"
2212       "Community-list name\n")
2213
2214ALIAS (no_match_community,
2215       no_match_community_exact_cmd,
2216       "no match community (<1-99>|<100-199>|WORD) exact-match",
2217       NO_STR
2218       MATCH_STR
2219       "Match BGP community list\n"
2220       "Community-list number (standard)\n"
2221       "Community-list number (expanded)\n"
2222       "Community-list name\n"
2223       "Do exact matching of communities\n")
2224
2225DEFUN (match_aspath,
2226       match_aspath_cmd,
2227       "match as-path WORD",
2228       MATCH_STR
2229       "Match BGP AS path list\n"
2230       "AS path access-list name\n")
2231{
2232  return bgp_route_match_add (vty, vty->index, "as-path", argv[0]);
2233}
2234
2235DEFUN (no_match_aspath,
2236       no_match_aspath_cmd,
2237       "no match as-path",
2238       NO_STR
2239       MATCH_STR
2240       "Match BGP AS path list\n")
2241{
2242  return bgp_route_match_delete (vty, vty->index, "as-path", NULL);
2243}
2244
2245ALIAS (no_match_aspath,
2246       no_match_aspath_val_cmd,
2247       "no match as-path WORD",
2248       NO_STR
2249       MATCH_STR
2250       "Match BGP AS path list\n"
2251       "AS path access-list name\n")
2252
2253DEFUN (match_origin,
2254       match_origin_cmd,
2255       "match origin (egp|igp|incomplete)",
2256       MATCH_STR
2257       "BGP origin code\n"
2258       "remote EGP\n"
2259       "local IGP\n"
2260       "unknown heritage\n")
2261{
2262  if (strncmp (argv[0], "igp", 2) == 0)
2263    return bgp_route_match_add (vty, vty->index, "origin", "igp");
2264  if (strncmp (argv[0], "egp", 1) == 0)
2265    return bgp_route_match_add (vty, vty->index, "origin", "egp");
2266  if (strncmp (argv[0], "incomplete", 2) == 0)
2267    return bgp_route_match_add (vty, vty->index, "origin", "incomplete");
2268
2269  return CMD_WARNING;
2270}
2271
2272DEFUN (no_match_origin,
2273       no_match_origin_cmd,
2274       "no match origin",
2275       NO_STR
2276       MATCH_STR
2277       "BGP origin code\n")
2278{
2279  return bgp_route_match_delete (vty, vty->index, "origin", NULL);
2280}
2281
2282ALIAS (no_match_origin,
2283       no_match_origin_val_cmd,
2284       "no match origin (egp|igp|incomplete)",
2285       NO_STR
2286       MATCH_STR
2287       "BGP origin code\n"
2288       "remote EGP\n"
2289       "local IGP\n"
2290       "unknown heritage\n")
2291
2292DEFUN (set_ip_nexthop,
2293       set_ip_nexthop_cmd,
2294       "set ip next-hop A.B.C.D",
2295       SET_STR
2296       IP_STR
2297       "Next hop address\n"
2298       "IP address of next hop\n")
2299{
2300  union sockunion su;
2301  int ret;
2302
2303  ret = str2sockunion (argv[0], &su);
2304  if (ret < 0)
2305    {
2306      vty_out (vty, "%% Malformed Next-hop address%s", VTY_NEWLINE);
2307      return CMD_WARNING;
2308    }
2309
2310  return bgp_route_set_add (vty, vty->index, "ip next-hop", argv[0]);
2311}
2312
2313DEFUN (no_set_ip_nexthop,
2314       no_set_ip_nexthop_cmd,
2315       "no set ip next-hop",
2316       NO_STR
2317       SET_STR
2318       IP_STR
2319       "Next hop address\n")
2320{
2321  if (argc == 0)
2322    return bgp_route_set_delete (vty, vty->index, "ip next-hop", NULL);
2323
2324  return bgp_route_set_delete (vty, vty->index, "ip next-hop", argv[0]);
2325}
2326
2327ALIAS (no_set_ip_nexthop,
2328       no_set_ip_nexthop_val_cmd,
2329       "no set ip next-hop A.B.C.D",
2330       NO_STR
2331       SET_STR
2332       IP_STR
2333       "Next hop address\n"
2334       "IP address of next hop\n")
2335
2336DEFUN (set_metric,
2337       set_metric_cmd,
2338       "set metric (<0-4294967295>|<+/-metric>)",
2339       SET_STR
2340       "Metric value for destination routing protocol\n"
2341       "Metric value\n"
2342       "Add or subtract metric\n")
2343{
2344  return bgp_route_set_add (vty, vty->index, "metric", argv[0]);
2345}
2346
2347DEFUN (no_set_metric,
2348       no_set_metric_cmd,
2349       "no set metric",
2350       NO_STR
2351       SET_STR
2352       "Metric value for destination routing protocol\n")
2353{
2354  if (argc == 0)
2355    return bgp_route_set_delete (vty, vty->index, "metric", NULL);
2356
2357  return bgp_route_set_delete (vty, vty->index, "metric", argv[0]);
2358}
2359
2360ALIAS (no_set_metric,
2361       no_set_metric_val_cmd,
2362       "no set metric <0-4294967295>",
2363       NO_STR
2364       SET_STR
2365       "Metric value for destination routing protocol\n"
2366       "Metric value\n")
2367
2368DEFUN (set_local_pref,
2369       set_local_pref_cmd,
2370       "set local-preference <0-4294967295>",
2371       SET_STR
2372       "BGP local preference path attribute\n"
2373       "Preference value\n")
2374{
2375  return bgp_route_set_add (vty, vty->index, "local-preference", argv[0]);
2376}
2377
2378DEFUN (no_set_local_pref,
2379       no_set_local_pref_cmd,
2380       "no set local-preference",
2381       NO_STR
2382       SET_STR
2383       "BGP local preference path attribute\n")
2384{
2385  if (argc == 0)
2386    return bgp_route_set_delete (vty, vty->index, "local-preference", NULL);
2387
2388  return bgp_route_set_delete (vty, vty->index, "local-preference", argv[0]);
2389}
2390
2391ALIAS (no_set_local_pref,
2392       no_set_local_pref_val_cmd,
2393       "no set local-preference <0-4294967295>",
2394       NO_STR
2395       SET_STR
2396       "BGP local preference path attribute\n"
2397       "Preference value\n")
2398
2399DEFUN (set_weight,
2400       set_weight_cmd,
2401       "set weight <0-4294967295>",
2402       SET_STR
2403       "BGP weight for routing table\n"
2404       "Weight value\n")
2405{
2406  return bgp_route_set_add (vty, vty->index, "weight", argv[0]);
2407}
2408
2409DEFUN (no_set_weight,
2410       no_set_weight_cmd,
2411       "no set weight",
2412       NO_STR
2413       SET_STR
2414       "BGP weight for routing table\n")
2415{
2416  if (argc == 0)
2417    return bgp_route_set_delete (vty, vty->index, "weight", NULL);
2418
2419  return bgp_route_set_delete (vty, vty->index, "weight", argv[0]);
2420}
2421
2422ALIAS (no_set_weight,
2423       no_set_weight_val_cmd,
2424       "no set weight <0-4294967295>",
2425       NO_STR
2426       SET_STR
2427       "BGP weight for routing table\n"
2428       "Weight value\n")
2429
2430DEFUN (set_aspath_prepend,
2431       set_aspath_prepend_cmd,
2432       "set as-path prepend .<1-65535>",
2433       SET_STR
2434       "Prepend string for a BGP AS-path attribute\n"
2435       "Prepend to the as-path\n"
2436       "AS number\n")
2437{
2438  int ret;
2439  char *str;
2440
2441  str = argv_concat (argv, argc, 0);
2442  ret = bgp_route_set_add (vty, vty->index, "as-path prepend", str);
2443  XFREE (MTYPE_TMP, str);
2444
2445  return ret;
2446}
2447
2448DEFUN (no_set_aspath_prepend,
2449       no_set_aspath_prepend_cmd,
2450       "no set as-path prepend",
2451       NO_STR
2452       SET_STR
2453       "Prepend string for a BGP AS-path attribute\n"
2454       "Prepend to the as-path\n")
2455{
2456  return bgp_route_set_delete (vty, vty->index, "as-path prepend", NULL);
2457}
2458
2459ALIAS (no_set_aspath_prepend,
2460       no_set_aspath_prepend_val_cmd,
2461       "no set as-path prepend .<1-65535>",
2462       NO_STR
2463       SET_STR
2464       "Prepend string for a BGP AS-path attribute\n"
2465       "Prepend to the as-path\n"
2466       "AS number\n")
2467
2468DEFUN (set_community,
2469       set_community_cmd,
2470       "set community .AA:NN",
2471       SET_STR
2472       "BGP community attribute\n"
2473       "Community number in aa:nn format or local-AS|no-advertise|no-export|internet or additive\n")
2474{
2475  int i;
2476  int first = 0;
2477  int additive = 0;
2478  struct buffer *b;
2479  struct community *com = NULL;
2480  char *str;
2481  char *argstr;
2482  int ret;
2483
2484  b = buffer_new (1024);
2485
2486  for (i = 0; i < argc; i++)
2487    {
2488      if (strncmp (argv[i], "additive", strlen (argv[i])) == 0)
2489 	{
2490 	  additive = 1;
2491 	  continue;
2492 	}
2493
2494      if (first)
2495	buffer_putc (b, ' ');
2496      else
2497	first = 1;
2498
2499      if (strncmp (argv[i], "internet", strlen (argv[i])) == 0)
2500 	{
2501	  buffer_putstr (b, "internet");
2502 	  continue;
2503 	}
2504      if (strncmp (argv[i], "local-AS", strlen (argv[i])) == 0)
2505 	{
2506	  buffer_putstr (b, "local-AS");
2507 	  continue;
2508 	}
2509      if (strncmp (argv[i], "no-a", strlen ("no-a")) == 0
2510	  && strncmp (argv[i], "no-advertise", strlen (argv[i])) == 0)
2511 	{
2512	  buffer_putstr (b, "no-advertise");
2513 	  continue;
2514 	}
2515      if (strncmp (argv[i], "no-e", strlen ("no-e"))== 0
2516	  && strncmp (argv[i], "no-export", strlen (argv[i])) == 0)
2517 	{
2518	  buffer_putstr (b, "no-export");
2519 	  continue;
2520 	}
2521      buffer_putstr (b, argv[i]);
2522    }
2523  buffer_putc (b, '\0');
2524
2525  /* Fetch result string then compile it to communities attribute.  */
2526  str = buffer_getstr (b);
2527  buffer_free (b);
2528
2529  if (str)
2530    {
2531      com = community_str2com (str);
2532      free (str);
2533    }
2534
2535  /* Can't compile user input into communities attribute.  */
2536  if (! com)
2537    {
2538      vty_out (vty, "%% Malformed communities attribute%s", VTY_NEWLINE);
2539      return CMD_WARNING;
2540    }
2541
2542  /* Set communites attribute string.  */
2543  str = community_str (com);
2544
2545  if (additive)
2546    {
2547      argstr = XCALLOC (MTYPE_TMP, strlen (str) + strlen (" additive") + 1);
2548      strcpy (argstr, str);
2549      strcpy (argstr + strlen (str), " additive");
2550      ret =  bgp_route_set_add (vty, vty->index, "community", argstr);
2551      XFREE (MTYPE_TMP, argstr);
2552    }
2553  else
2554    ret =  bgp_route_set_add (vty, vty->index, "community", str);
2555
2556  community_free (com);
2557
2558  return ret;
2559}
2560
2561DEFUN (set_community_none,
2562       set_community_none_cmd,
2563       "set community none",
2564       SET_STR
2565       "BGP community attribute\n"
2566       "No community attribute\n")
2567{
2568  return bgp_route_set_add (vty, vty->index, "community", "none");
2569}
2570
2571DEFUN (no_set_community,
2572       no_set_community_cmd,
2573       "no set community",
2574       NO_STR
2575       SET_STR
2576       "BGP community attribute\n")
2577{
2578  return bgp_route_set_delete (vty, vty->index, "community", NULL);
2579}
2580
2581ALIAS (no_set_community,
2582       no_set_community_val_cmd,
2583       "no set community .AA:NN",
2584       NO_STR
2585       SET_STR
2586       "BGP community attribute\n"
2587       "Community number in aa:nn format or local-AS|no-advertise|no-export|internet or additive\n")
2588
2589ALIAS (no_set_community,
2590       no_set_community_none_cmd,
2591       "no set community none",
2592       NO_STR
2593       SET_STR
2594       "BGP community attribute\n"
2595       "No community attribute\n")
2596
2597DEFUN (set_community_delete,
2598       set_community_delete_cmd,
2599       "set comm-list (<1-99>|<100-199>|WORD) delete",
2600       SET_STR
2601       "set BGP community list (for deletion)\n"
2602       "Community-list number (standard)\n"
2603       "Communitly-list number (expanded)\n"
2604       "Community-list name\n"
2605       "Delete matching communities\n")
2606{
2607  char *str;
2608
2609  str = XCALLOC (MTYPE_TMP, strlen (argv[0]) + strlen (" delete") + 1);
2610  strcpy (str, argv[0]);
2611  strcpy (str + strlen (argv[0]), " delete");
2612
2613  bgp_route_set_add (vty, vty->index, "comm-list", str);
2614
2615  XFREE (MTYPE_TMP, str);
2616  return CMD_SUCCESS;
2617}
2618
2619DEFUN (no_set_community_delete,
2620       no_set_community_delete_cmd,
2621       "no set comm-list",
2622       NO_STR
2623       SET_STR
2624       "set BGP community list (for deletion)\n")
2625{
2626  return bgp_route_set_delete (vty, vty->index, "comm-list", NULL);
2627}
2628
2629ALIAS (no_set_community_delete,
2630       no_set_community_delete_val_cmd,
2631       "no set comm-list (<1-99>|<100-199>|WORD) delete",
2632       NO_STR
2633       SET_STR
2634       "set BGP community list (for deletion)\n"
2635       "Community-list number (standard)\n"
2636       "Communitly-list number (expanded)\n"
2637       "Community-list name\n"
2638       "Delete matching communities\n")
2639
2640DEFUN (set_ecommunity_rt,
2641       set_ecommunity_rt_cmd,
2642       "set extcommunity rt .ASN:nn_or_IP-address:nn",
2643       SET_STR
2644       "BGP extended community attribute\n"
2645       "Route Target extened communityt\n"
2646       "VPN extended community\n")
2647{
2648  int ret;
2649  char *str;
2650
2651  str = argv_concat (argv, argc, 0);
2652  ret = bgp_route_set_add (vty, vty->index, "extcommunity rt", str);
2653  XFREE (MTYPE_TMP, str);
2654
2655  return ret;
2656}
2657
2658DEFUN (no_set_ecommunity_rt,
2659       no_set_ecommunity_rt_cmd,
2660       "no set extcommunity rt",
2661       NO_STR
2662       SET_STR
2663       "BGP extended community attribute\n"
2664       "Route Target extened communityt\n")
2665{
2666  return bgp_route_set_delete (vty, vty->index, "extcommunity rt", NULL);
2667}
2668
2669ALIAS (no_set_ecommunity_rt,
2670       no_set_ecommunity_rt_val_cmd,
2671       "no set extcommunity rt .ASN:nn_or_IP-address:nn",
2672       NO_STR
2673       SET_STR
2674       "BGP extended community attribute\n"
2675       "Route Target extened communityt\n"
2676       "VPN extended community\n")
2677
2678DEFUN (set_ecommunity_soo,
2679       set_ecommunity_soo_cmd,
2680       "set extcommunity soo .ASN:nn_or_IP-address:nn",
2681       SET_STR
2682       "BGP extended community attribute\n"
2683       "Site-of-Origin extended community\n"
2684       "VPN extended community\n")
2685{
2686  int ret;
2687  char *str;
2688
2689  str = argv_concat (argv, argc, 0);
2690  ret = bgp_route_set_add (vty, vty->index, "extcommunity soo", str);
2691  XFREE (MTYPE_TMP, str);
2692  return ret;
2693}
2694
2695DEFUN (no_set_ecommunity_soo,
2696       no_set_ecommunity_soo_cmd,
2697       "no set extcommunity soo",
2698       NO_STR
2699       SET_STR
2700       "BGP extended community attribute\n"
2701       "Site-of-Origin extended community\n")
2702{
2703  return bgp_route_set_delete (vty, vty->index, "extcommunity soo", NULL);
2704}
2705
2706ALIAS (no_set_ecommunity_soo,
2707       no_set_ecommunity_soo_val_cmd,
2708       "no set extcommunity soo .ASN:nn_or_IP-address:nn",
2709       NO_STR
2710       SET_STR
2711       "BGP extended community attribute\n"
2712       "Site-of-Origin extended community\n"
2713       "VPN extended community\n")
2714
2715DEFUN (set_origin,
2716       set_origin_cmd,
2717       "set origin (egp|igp|incomplete)",
2718       SET_STR
2719       "BGP origin code\n"
2720       "remote EGP\n"
2721       "local IGP\n"
2722       "unknown heritage\n")
2723{
2724  if (strncmp (argv[0], "igp", 2) == 0)
2725    return bgp_route_set_add (vty, vty->index, "origin", "igp");
2726  if (strncmp (argv[0], "egp", 1) == 0)
2727    return bgp_route_set_add (vty, vty->index, "origin", "egp");
2728  if (strncmp (argv[0], "incomplete", 2) == 0)
2729    return bgp_route_set_add (vty, vty->index, "origin", "incomplete");
2730
2731  return CMD_WARNING;
2732}
2733
2734DEFUN (no_set_origin,
2735       no_set_origin_cmd,
2736       "no set origin",
2737       NO_STR
2738       SET_STR
2739       "BGP origin code\n")
2740{
2741  return bgp_route_set_delete (vty, vty->index, "origin", NULL);
2742}
2743
2744ALIAS (no_set_origin,
2745       no_set_origin_val_cmd,
2746       "no set origin (egp|igp|incomplete)",
2747       NO_STR
2748       SET_STR
2749       "BGP origin code\n"
2750       "remote EGP\n"
2751       "local IGP\n"
2752       "unknown heritage\n")
2753
2754DEFUN (set_atomic_aggregate,
2755       set_atomic_aggregate_cmd,
2756       "set atomic-aggregate",
2757       SET_STR
2758       "BGP atomic aggregate attribute\n" )
2759{
2760  return bgp_route_set_add (vty, vty->index, "atomic-aggregate", NULL);
2761}
2762
2763DEFUN (no_set_atomic_aggregate,
2764       no_set_atomic_aggregate_cmd,
2765       "no set atomic-aggregate",
2766       NO_STR
2767       SET_STR
2768       "BGP atomic aggregate attribute\n" )
2769{
2770  return bgp_route_set_delete (vty, vty->index, "atomic-aggregate", NULL);
2771}
2772
2773DEFUN (set_aggregator_as,
2774       set_aggregator_as_cmd,
2775       "set aggregator as <1-65535> A.B.C.D",
2776       SET_STR
2777       "BGP aggregator attribute\n"
2778       "AS number of aggregator\n"
2779       "AS number\n"
2780       "IP address of aggregator\n")
2781{
2782  int ret;
2783  as_t as;
2784  struct in_addr address;
2785  char *endptr = NULL;
2786  char *argstr;
2787
2788  as = strtoul (argv[0], &endptr, 10);
2789  if (as == 0 || as == ULONG_MAX || *endptr != '\0')
2790    {
2791      vty_out (vty, "AS path value malformed%s", VTY_NEWLINE);
2792      return CMD_WARNING;
2793    }
2794
2795  ret = inet_aton (argv[1], &address);
2796  if (ret == 0)
2797    {
2798      vty_out (vty, "Aggregator IP address is invalid%s", VTY_NEWLINE);
2799      return CMD_WARNING;
2800    }
2801
2802  argstr = XMALLOC (MTYPE_ROUTE_MAP_COMPILED,
2803		    strlen (argv[0]) + strlen (argv[1]) + 2);
2804
2805  sprintf (argstr, "%s %s", argv[0], argv[1]);
2806
2807  ret = bgp_route_set_add (vty, vty->index, "aggregator as", argstr);
2808
2809  XFREE (MTYPE_ROUTE_MAP_COMPILED, argstr);
2810
2811  return ret;
2812}
2813
2814DEFUN (no_set_aggregator_as,
2815       no_set_aggregator_as_cmd,
2816       "no set aggregator as",
2817       NO_STR
2818       SET_STR
2819       "BGP aggregator attribute\n"
2820       "AS number of aggregator\n")
2821{
2822  int ret;
2823  as_t as;
2824  struct in_addr address;
2825  char *endptr = NULL;
2826  char *argstr;
2827
2828  if (argv == 0)
2829    return bgp_route_set_delete (vty, vty->index, "aggregator as", NULL);
2830
2831  as = strtoul (argv[0], &endptr, 10);
2832  if (as == 0 || as == ULONG_MAX || *endptr != '\0')
2833    {
2834      vty_out (vty, "AS path value malformed%s", VTY_NEWLINE);
2835      return CMD_WARNING;
2836    }
2837
2838  ret = inet_aton (argv[1], &address);
2839  if (ret == 0)
2840    {
2841      vty_out (vty, "Aggregator IP address is invalid%s", VTY_NEWLINE);
2842      return CMD_WARNING;
2843    }
2844
2845  argstr = XMALLOC (MTYPE_ROUTE_MAP_COMPILED,
2846		    strlen (argv[0]) + strlen (argv[1]) + 2);
2847
2848  sprintf (argstr, "%s %s", argv[0], argv[1]);
2849
2850  ret = bgp_route_set_delete (vty, vty->index, "aggregator as", argstr);
2851
2852  XFREE (MTYPE_ROUTE_MAP_COMPILED, argstr);
2853
2854  return ret;
2855}
2856
2857ALIAS (no_set_aggregator_as,
2858       no_set_aggregator_as_val_cmd,
2859       "no set aggregator as <1-65535> A.B.C.D",
2860       NO_STR
2861       SET_STR
2862       "BGP aggregator attribute\n"
2863       "AS number of aggregator\n"
2864       "AS number\n"
2865       "IP address of aggregator\n")
2866
2867
2868#ifdef HAVE_IPV6
2869DEFUN (match_ipv6_address,
2870       match_ipv6_address_cmd,
2871       "match ipv6 address WORD",
2872       MATCH_STR
2873       IPV6_STR
2874       "Match IPv6 address of route\n"
2875       "IPv6 access-list name\n")
2876{
2877  return bgp_route_match_add (vty, vty->index, "ipv6 address", argv[0]);
2878}
2879
2880DEFUN (no_match_ipv6_address,
2881       no_match_ipv6_address_cmd,
2882       "no match ipv6 address WORD",
2883       NO_STR
2884       MATCH_STR
2885       IPV6_STR
2886       "Match IPv6 address of route\n"
2887       "IPv6 access-list name\n")
2888{
2889  return bgp_route_match_delete (vty, vty->index, "ipv6 address", argv[0]);
2890}
2891
2892DEFUN (match_ipv6_next_hop,
2893       match_ipv6_next_hop_cmd,
2894       "match ipv6 next-hop X:X::X:X",
2895       MATCH_STR
2896       IPV6_STR
2897       "Match IPv6 next-hop address of route\n"
2898       "IPv6 address of next hop\n")
2899{
2900  return bgp_route_match_add (vty, vty->index, "ipv6 next-hop", argv[0]);
2901}
2902
2903DEFUN (no_match_ipv6_next_hop,
2904       no_match_ipv6_next_hop_cmd,
2905       "no match ipv6 next-hop X:X::X:X",
2906       NO_STR
2907       MATCH_STR
2908       IPV6_STR
2909       "Match IPv6 next-hop address of route\n"
2910       "IPv6 address of next hop\n")
2911{
2912  return bgp_route_match_delete (vty, vty->index, "ipv6 next-hop", argv[0]);
2913}
2914
2915DEFUN (match_ipv6_address_prefix_list,
2916       match_ipv6_address_prefix_list_cmd,
2917       "match ipv6 address prefix-list WORD",
2918       MATCH_STR
2919       IPV6_STR
2920       "Match address of route\n"
2921       "Match entries of prefix-lists\n"
2922       "IP prefix-list name\n")
2923{
2924  return bgp_route_match_add (vty, vty->index, "ipv6 address prefix-list", argv[0]);
2925}
2926
2927DEFUN (no_match_ipv6_address_prefix_list,
2928       no_match_ipv6_address_prefix_list_cmd,
2929       "no match ipv6 address prefix-list WORD",
2930       NO_STR
2931       MATCH_STR
2932       IPV6_STR
2933       "Match address of route\n"
2934       "Match entries of prefix-lists\n"
2935       "IP prefix-list name\n")
2936{
2937  return bgp_route_match_delete (vty, vty->index, "ipv6 address prefix-list", argv[0]);
2938}
2939
2940DEFUN (set_ipv6_nexthop_global,
2941       set_ipv6_nexthop_global_cmd,
2942       "set ipv6 next-hop global X:X::X:X",
2943       SET_STR
2944       IPV6_STR
2945       "IPv6 next-hop address\n"
2946       "IPv6 global address\n"
2947       "IPv6 address of next hop\n")
2948{
2949  return bgp_route_set_add (vty, vty->index, "ipv6 next-hop global", argv[0]);
2950}
2951
2952DEFUN (no_set_ipv6_nexthop_global,
2953       no_set_ipv6_nexthop_global_cmd,
2954       "no set ipv6 next-hop global",
2955       NO_STR
2956       SET_STR
2957       IPV6_STR
2958       "IPv6 next-hop address\n"
2959       "IPv6 global address\n")
2960{
2961  if (argc == 0)
2962    return bgp_route_set_delete (vty, vty->index, "ipv6 next-hop global", NULL);
2963
2964  return bgp_route_set_delete (vty, vty->index, "ipv6 next-hop global", argv[0]);
2965}
2966
2967ALIAS (no_set_ipv6_nexthop_global,
2968       no_set_ipv6_nexthop_global_val_cmd,
2969       "no set ipv6 next-hop global X:X::X:X",
2970       NO_STR
2971       SET_STR
2972       IPV6_STR
2973       "IPv6 next-hop address\n"
2974       "IPv6 global address\n"
2975       "IPv6 address of next hop\n")
2976
2977DEFUN (set_ipv6_nexthop_local,
2978       set_ipv6_nexthop_local_cmd,
2979       "set ipv6 next-hop local X:X::X:X",
2980       SET_STR
2981       IPV6_STR
2982       "IPv6 next-hop address\n"
2983       "IPv6 local address\n"
2984       "IPv6 address of next hop\n")
2985{
2986  return bgp_route_set_add (vty, vty->index, "ipv6 next-hop local", argv[0]);
2987}
2988
2989DEFUN (no_set_ipv6_nexthop_local,
2990       no_set_ipv6_nexthop_local_cmd,
2991       "no set ipv6 next-hop local",
2992       NO_STR
2993       SET_STR
2994       IPV6_STR
2995       "IPv6 next-hop address\n"
2996       "IPv6 local address\n")
2997{
2998  if (argc == 0)
2999    return bgp_route_set_delete (vty, vty->index, "ipv6 next-hop local", NULL);
3000
3001  return bgp_route_set_delete (vty, vty->index, "ipv6 next-hop local", argv[0]);
3002}
3003
3004ALIAS (no_set_ipv6_nexthop_local,
3005       no_set_ipv6_nexthop_local_val_cmd,
3006       "no set ipv6 next-hop local X:X::X:X",
3007       NO_STR
3008       SET_STR
3009       IPV6_STR
3010       "IPv6 next-hop address\n"
3011       "IPv6 local address\n"
3012       "IPv6 address of next hop\n")
3013#endif /* HAVE_IPV6 */
3014
3015DEFUN (set_vpnv4_nexthop,
3016       set_vpnv4_nexthop_cmd,
3017       "set vpnv4 next-hop A.B.C.D",
3018       SET_STR
3019       "VPNv4 information\n"
3020       "VPNv4 next-hop address\n"
3021       "IP address of next hop\n")
3022{
3023  return bgp_route_set_add (vty, vty->index, "vpnv4 next-hop", argv[0]);
3024}
3025
3026DEFUN (no_set_vpnv4_nexthop,
3027       no_set_vpnv4_nexthop_cmd,
3028       "no set vpnv4 next-hop",
3029       NO_STR
3030       SET_STR
3031       "VPNv4 information\n"
3032       "VPNv4 next-hop address\n")
3033{
3034  if (argc == 0)
3035    return bgp_route_set_delete (vty, vty->index, "vpnv4 next-hop", NULL);
3036
3037  return bgp_route_set_delete (vty, vty->index, "vpnv4 next-hop", argv[0]);
3038}
3039
3040ALIAS (no_set_vpnv4_nexthop,
3041       no_set_vpnv4_nexthop_val_cmd,
3042       "no set vpnv4 next-hop A.B.C.D",
3043       NO_STR
3044       SET_STR
3045       "VPNv4 information\n"
3046       "VPNv4 next-hop address\n"
3047       "IP address of next hop\n")
3048
3049DEFUN (set_originator_id,
3050       set_originator_id_cmd,
3051       "set originator-id A.B.C.D",
3052       SET_STR
3053       "BGP originator ID attribute\n"
3054       "IP address of originator\n")
3055{
3056  return bgp_route_set_add (vty, vty->index, "originator-id", argv[0]);
3057}
3058
3059DEFUN (no_set_originator_id,
3060       no_set_originator_id_cmd,
3061       "no set originator-id",
3062       NO_STR
3063       SET_STR
3064       "BGP originator ID attribute\n")
3065{
3066  if (argc == 0)
3067    return bgp_route_set_delete (vty, vty->index, "originator-id", NULL);
3068
3069  return bgp_route_set_delete (vty, vty->index, "originator-id", argv[0]);
3070}
3071
3072ALIAS (no_set_originator_id,
3073       no_set_originator_id_val_cmd,
3074       "no set originator-id A.B.C.D",
3075       NO_STR
3076       SET_STR
3077       "BGP originator ID attribute\n"
3078       "IP address of originator\n")
3079
3080
3081/* Initialization of route map. */
3082void
3083bgp_route_map_init ()
3084{
3085  route_map_init ();
3086  route_map_init_vty ();
3087  route_map_add_hook (bgp_route_map_update);
3088  route_map_delete_hook (bgp_route_map_update);
3089
3090  route_map_install_match (&route_match_ip_address_cmd);
3091  route_map_install_match (&route_match_ip_next_hop_cmd);
3092  route_map_install_match (&route_match_ip_address_prefix_list_cmd);
3093  route_map_install_match (&route_match_ip_next_hop_prefix_list_cmd);
3094  route_map_install_match (&route_match_aspath_cmd);
3095  route_map_install_match (&route_match_community_cmd);
3096  route_map_install_match (&route_match_metric_cmd);
3097  route_map_install_match (&route_match_origin_cmd);
3098
3099  route_map_install_set (&route_set_ip_nexthop_cmd);
3100  route_map_install_set (&route_set_local_pref_cmd);
3101  route_map_install_set (&route_set_weight_cmd);
3102  route_map_install_set (&route_set_metric_cmd);
3103  route_map_install_set (&route_set_aspath_prepend_cmd);
3104  route_map_install_set (&route_set_origin_cmd);
3105  route_map_install_set (&route_set_atomic_aggregate_cmd);
3106  route_map_install_set (&route_set_aggregator_as_cmd);
3107  route_map_install_set (&route_set_community_cmd);
3108  route_map_install_set (&route_set_community_delete_cmd);
3109  route_map_install_set (&route_set_vpnv4_nexthop_cmd);
3110  route_map_install_set (&route_set_originator_id_cmd);
3111  route_map_install_set (&route_set_ecommunity_rt_cmd);
3112  route_map_install_set (&route_set_ecommunity_soo_cmd);
3113
3114  install_element (RMAP_NODE, &match_ip_address_cmd);
3115  install_element (RMAP_NODE, &no_match_ip_address_cmd);
3116  install_element (RMAP_NODE, &no_match_ip_address_val_cmd);
3117  install_element (RMAP_NODE, &match_ip_next_hop_cmd);
3118  install_element (RMAP_NODE, &no_match_ip_next_hop_cmd);
3119  install_element (RMAP_NODE, &no_match_ip_next_hop_val_cmd);
3120
3121  install_element (RMAP_NODE, &match_ip_address_prefix_list_cmd);
3122  install_element (RMAP_NODE, &no_match_ip_address_prefix_list_cmd);
3123  install_element (RMAP_NODE, &no_match_ip_address_prefix_list_val_cmd);
3124  install_element (RMAP_NODE, &match_ip_next_hop_prefix_list_cmd);
3125  install_element (RMAP_NODE, &no_match_ip_next_hop_prefix_list_cmd);
3126  install_element (RMAP_NODE, &no_match_ip_next_hop_prefix_list_val_cmd);
3127
3128  install_element (RMAP_NODE, &match_aspath_cmd);
3129  install_element (RMAP_NODE, &no_match_aspath_cmd);
3130  install_element (RMAP_NODE, &no_match_aspath_val_cmd);
3131  install_element (RMAP_NODE, &match_metric_cmd);
3132  install_element (RMAP_NODE, &no_match_metric_cmd);
3133  install_element (RMAP_NODE, &no_match_metric_val_cmd);
3134  install_element (RMAP_NODE, &match_community_cmd);
3135  install_element (RMAP_NODE, &match_community_exact_cmd);
3136  install_element (RMAP_NODE, &no_match_community_cmd);
3137  install_element (RMAP_NODE, &no_match_community_val_cmd);
3138  install_element (RMAP_NODE, &no_match_community_exact_cmd);
3139  install_element (RMAP_NODE, &match_origin_cmd);
3140  install_element (RMAP_NODE, &no_match_origin_cmd);
3141  install_element (RMAP_NODE, &no_match_origin_val_cmd);
3142
3143  install_element (RMAP_NODE, &set_ip_nexthop_cmd);
3144  install_element (RMAP_NODE, &no_set_ip_nexthop_cmd);
3145  install_element (RMAP_NODE, &no_set_ip_nexthop_val_cmd);
3146  install_element (RMAP_NODE, &set_local_pref_cmd);
3147  install_element (RMAP_NODE, &no_set_local_pref_cmd);
3148  install_element (RMAP_NODE, &no_set_local_pref_val_cmd);
3149  install_element (RMAP_NODE, &set_weight_cmd);
3150  install_element (RMAP_NODE, &no_set_weight_cmd);
3151  install_element (RMAP_NODE, &no_set_weight_val_cmd);
3152  install_element (RMAP_NODE, &set_metric_cmd);
3153  install_element (RMAP_NODE, &no_set_metric_cmd);
3154  install_element (RMAP_NODE, &no_set_metric_val_cmd);
3155  install_element (RMAP_NODE, &set_aspath_prepend_cmd);
3156  install_element (RMAP_NODE, &no_set_aspath_prepend_cmd);
3157  install_element (RMAP_NODE, &no_set_aspath_prepend_val_cmd);
3158  install_element (RMAP_NODE, &set_origin_cmd);
3159  install_element (RMAP_NODE, &no_set_origin_cmd);
3160  install_element (RMAP_NODE, &no_set_origin_val_cmd);
3161  install_element (RMAP_NODE, &set_atomic_aggregate_cmd);
3162  install_element (RMAP_NODE, &no_set_atomic_aggregate_cmd);
3163  install_element (RMAP_NODE, &set_aggregator_as_cmd);
3164  install_element (RMAP_NODE, &no_set_aggregator_as_cmd);
3165  install_element (RMAP_NODE, &no_set_aggregator_as_val_cmd);
3166  install_element (RMAP_NODE, &set_community_cmd);
3167  install_element (RMAP_NODE, &set_community_none_cmd);
3168  install_element (RMAP_NODE, &no_set_community_cmd);
3169  install_element (RMAP_NODE, &no_set_community_val_cmd);
3170  install_element (RMAP_NODE, &no_set_community_none_cmd);
3171  install_element (RMAP_NODE, &set_community_delete_cmd);
3172  install_element (RMAP_NODE, &no_set_community_delete_cmd);
3173  install_element (RMAP_NODE, &no_set_community_delete_val_cmd);
3174  install_element (RMAP_NODE, &set_ecommunity_rt_cmd);
3175  install_element (RMAP_NODE, &no_set_ecommunity_rt_cmd);
3176  install_element (RMAP_NODE, &no_set_ecommunity_rt_val_cmd);
3177  install_element (RMAP_NODE, &set_ecommunity_soo_cmd);
3178  install_element (RMAP_NODE, &no_set_ecommunity_soo_cmd);
3179  install_element (RMAP_NODE, &no_set_ecommunity_soo_val_cmd);
3180  install_element (RMAP_NODE, &set_vpnv4_nexthop_cmd);
3181  install_element (RMAP_NODE, &no_set_vpnv4_nexthop_cmd);
3182  install_element (RMAP_NODE, &no_set_vpnv4_nexthop_val_cmd);
3183  install_element (RMAP_NODE, &set_originator_id_cmd);
3184  install_element (RMAP_NODE, &no_set_originator_id_cmd);
3185  install_element (RMAP_NODE, &no_set_originator_id_val_cmd);
3186
3187#ifdef HAVE_IPV6
3188  route_map_install_match (&route_match_ipv6_address_cmd);
3189  route_map_install_match (&route_match_ipv6_next_hop_cmd);
3190  route_map_install_match (&route_match_ipv6_address_prefix_list_cmd);
3191  route_map_install_set (&route_set_ipv6_nexthop_global_cmd);
3192  route_map_install_set (&route_set_ipv6_nexthop_local_cmd);
3193
3194  install_element (RMAP_NODE, &match_ipv6_address_cmd);
3195  install_element (RMAP_NODE, &no_match_ipv6_address_cmd);
3196  install_element (RMAP_NODE, &match_ipv6_next_hop_cmd);
3197  install_element (RMAP_NODE, &no_match_ipv6_next_hop_cmd);
3198  install_element (RMAP_NODE, &match_ipv6_address_prefix_list_cmd);
3199  install_element (RMAP_NODE, &no_match_ipv6_address_prefix_list_cmd);
3200  install_element (RMAP_NODE, &set_ipv6_nexthop_global_cmd);
3201  install_element (RMAP_NODE, &no_set_ipv6_nexthop_global_cmd);
3202  install_element (RMAP_NODE, &no_set_ipv6_nexthop_global_val_cmd);
3203  install_element (RMAP_NODE, &set_ipv6_nexthop_local_cmd);
3204  install_element (RMAP_NODE, &no_set_ipv6_nexthop_local_cmd);
3205  install_element (RMAP_NODE, &no_set_ipv6_nexthop_local_val_cmd);
3206#endif /* HAVE_IPV6 */
3207}
3208