New upstream release and new maintainer
[quagga-debian.git] / bgpd / bgp_routemap.c
1 /* Route map function of bgpd.
2    Copyright (C) 1998, 1999 Kunihiro Ishiguro
3
4 This file is part of GNU Zebra.
5
6 GNU Zebra is free software; you can redistribute it and/or modify it
7 under the terms of the GNU General Public License as published by the
8 Free Software Foundation; either version 2, or (at your option) any
9 later version.
10
11 GNU Zebra is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with GNU Zebra; see the file COPYING.  If not, write to the Free
18 Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
19 02111-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_LIBPCREPOSIX
32 # include <pcreposix.h>
33 #else
34 # ifdef HAVE_GNU_REGEX
35 #  include <regex.h>
36 # else
37 #  include "regex-gnu.h"
38 # endif /* HAVE_GNU_REGEX */
39 #endif /* HAVE_LIBPCREPOSIX */
40 #include "buffer.h"
41 #include "sockunion.h"
42
43 #include "bgpd/bgpd.h"
44 #include "bgpd/bgp_table.h"
45 #include "bgpd/bgp_attr.h"
46 #include "bgpd/bgp_aspath.h"
47 #include "bgpd/bgp_route.h"
48 #include "bgpd/bgp_regex.h"
49 #include "bgpd/bgp_community.h"
50 #include "bgpd/bgp_clist.h"
51 #include "bgpd/bgp_filter.h"
52 #include "bgpd/bgp_mplsvpn.h"
53 #include "bgpd/bgp_ecommunity.h"
54 #include "bgpd/bgp_lcommunity.h"
55 #include "bgpd/bgp_vty.h"
56
57 /* Memo of route-map commands.
58
59 o Cisco route-map
60
61  match as-path          :  Done
62        community        :  Done
63        lcommunity       :  Done
64        interface        :  Not yet
65        ip address       :  Done
66        ip next-hop      :  Done
67        ip route-source  :  Done
68        ip prefix-list   :  Done
69        ipv6 address     :  Done
70        ipv6 next-hop    :  Done
71        ipv6 route-source:  (This will not be implemented by bgpd)
72        ipv6 prefix-list :  Done
73        length           :  (This will not be implemented by bgpd)
74        metric           :  Done
75        route-type       :  (This will not be implemented by bgpd)
76        tag              :  Done
77        local-preference :  Done
78
79  set  as-path prepend   :  Done
80       as-path tag       :  Not yet
81       automatic-tag     :  (This will not be implemented by bgpd)
82       community         :  Done
83       large-community   :  Done
84       large-comm-list   :  Done
85       comm-list         :  Not yet
86       dampning          :  Not yet
87       default           :  (This will not be implemented by bgpd)
88       interface         :  (This will not be implemented by bgpd)
89       ip default        :  (This will not be implemented by bgpd)
90       ip next-hop       :  Done
91       ip precedence     :  (This will not be implemented by bgpd)
92       ip tos            :  (This will not be implemented by bgpd)
93       level             :  (This will not be implemented by bgpd)
94       local-preference  :  Done
95       metric            :  Done
96       metric-type       :  Not yet
97       origin            :  Done
98       tag               :  Done
99       weight            :  Done
100
101 o Local extensions
102
103   set ipv6 next-hop global: Done
104   set ipv6 next-hop local : Done
105   set as-path exclude     : Done
106
107 */ 
108
109  /* generic value manipulation to be shared in multiple rules */
110
111 #define RMAP_VALUE_SET 0
112 #define RMAP_VALUE_ADD 1
113 #define RMAP_VALUE_SUB 2
114
115 struct rmap_value
116 {
117   u_int8_t action;
118   u_int8_t variable;
119   u_int32_t value;
120 };
121
122 static int
123 route_value_match (struct rmap_value *rv, u_int32_t value)
124 {
125   if (rv->variable == 0 && value == rv->value)
126     return RMAP_MATCH;
127
128   return RMAP_NOMATCH;
129 }
130
131 static u_int32_t
132 route_value_adjust (struct rmap_value *rv, u_int32_t current, struct peer *peer)
133 {
134   u_int32_t value;
135
136   switch (rv->variable)
137     {
138     case 1:
139       value = peer->rtt;
140       break;
141     default:
142       value = rv->value;
143       break;
144     }
145
146   switch (rv->action)
147     {
148     case RMAP_VALUE_ADD:
149       if (current > UINT32_MAX-value)
150         return UINT32_MAX;
151       return current + value;
152     case RMAP_VALUE_SUB:
153       if (current <= value)
154         return 0;
155       return current - value;
156     default:
157       return value;
158     }
159 }
160
161 static void *
162 route_value_compile (const char *arg)
163 {
164   u_int8_t action = RMAP_VALUE_SET, var = 0;
165   unsigned long larg = 0;
166   char *endptr = NULL;
167   struct rmap_value *rv;
168
169   if (arg[0] == '+')
170     {
171       action = RMAP_VALUE_ADD;
172       arg++;
173     }
174   else if (arg[0] == '-')
175     {
176       action = RMAP_VALUE_SUB;
177       arg++;
178     }
179
180   if (all_digit(arg))
181     {
182       errno = 0;
183       larg = strtoul (arg, &endptr, 10);
184       if (*arg == 0 || *endptr != 0 || errno || larg > UINT32_MAX)
185         return NULL;
186     }
187   else
188     {
189       if (strcmp(arg, "rtt") == 0)
190         var = 1;
191       else
192         return NULL;
193     }
194
195   rv = XMALLOC (MTYPE_ROUTE_MAP_COMPILED, sizeof(struct rmap_value));
196   if (!rv)
197     return NULL;
198
199   rv->action = action;
200   rv->variable = var;
201   rv->value = larg;
202   return rv;
203 }
204
205 static void
206 route_value_free (void *rule)
207 {
208   XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
209 }
210
211  /* generic as path object to be shared in multiple rules */
212
213 static void *
214 route_aspath_compile (const char *arg)
215 {
216   struct aspath *aspath;
217
218   aspath = aspath_str2aspath (arg);
219   if (! aspath)
220     return NULL;
221   return aspath;
222 }
223
224 static void
225 route_aspath_free (void *rule)
226 {
227   struct aspath *aspath = rule;
228   aspath_free (aspath);
229 }
230
231  /* 'match peer (A.B.C.D|X:X::X:X)' */
232
233 /* Compares the peer specified in the 'match peer' clause with the peer
234     received in bgp_info->peer. If it is the same, or if the peer structure
235     received is a peer_group containing it, returns RMAP_MATCH. */
236 static route_map_result_t
237 route_match_peer (void *rule, struct prefix *prefix, route_map_object_t type,
238       void *object)
239 {
240   union sockunion *su;
241   union sockunion su_def = { .sin = { .sin_family = AF_INET,
242                                       .sin_addr.s_addr = INADDR_ANY } };
243   struct peer_group *group;
244   struct peer *peer;
245   struct listnode *node, *nnode;
246
247   if (type == RMAP_BGP)
248     {
249       su = rule;
250       peer = ((struct bgp_info *) object)->peer;
251
252       if ( ! CHECK_FLAG (peer->rmap_type, PEER_RMAP_TYPE_IMPORT) &&
253            ! CHECK_FLAG (peer->rmap_type, PEER_RMAP_TYPE_EXPORT) )
254         return RMAP_NOMATCH;
255
256       /* If su='0.0.0.0' (command 'match peer local'), and it's a NETWORK,
257           REDISTRIBUTE or DEFAULT_GENERATED route => return RMAP_MATCH */
258       if (sockunion_same (su, &su_def))
259         {
260           int ret;
261           if ( CHECK_FLAG (peer->rmap_type, PEER_RMAP_TYPE_NETWORK) ||
262                CHECK_FLAG (peer->rmap_type, PEER_RMAP_TYPE_REDISTRIBUTE) ||
263                CHECK_FLAG (peer->rmap_type, PEER_RMAP_TYPE_DEFAULT))
264             ret = RMAP_MATCH;
265           else
266             ret = RMAP_NOMATCH;
267           return ret;
268         }
269
270       if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
271         {
272           if (sockunion_same (su, &peer->su))
273             return RMAP_MATCH;
274
275           return RMAP_NOMATCH;
276         }
277       else
278         {
279           group = peer->group;
280           for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
281             {
282               if (sockunion_same (su, &peer->su))
283                 return RMAP_MATCH;
284             }
285           return RMAP_NOMATCH;
286         }
287     }
288   return RMAP_NOMATCH;
289 }
290
291 static void *
292 route_match_peer_compile (const char *arg)
293 {
294   union sockunion *su;
295   int ret;
296
297   su = XMALLOC (MTYPE_ROUTE_MAP_COMPILED, sizeof (union sockunion));
298
299   ret = str2sockunion (strcmp(arg, "local") ? arg : "0.0.0.0", su);
300   if (ret < 0) {
301     XFREE (MTYPE_ROUTE_MAP_COMPILED, su);
302     return NULL;
303   }
304
305   return su;
306 }
307
308 /* Free route map's compiled `ip address' value. */
309 static void
310 route_match_peer_free (void *rule)
311 {
312   XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
313 }
314
315 /* Route map commands for ip address matching. */
316 struct route_map_rule_cmd route_match_peer_cmd =
317 {
318   "peer",
319   route_match_peer,
320   route_match_peer_compile,
321   route_match_peer_free
322 };
323
324 /* `match ip address IP_ACCESS_LIST' */
325
326 /* Match function should return 1 if match is success else return
327    zero. */
328 static route_map_result_t
329 route_match_ip_address (void *rule, struct prefix *prefix, 
330                         route_map_object_t type, void *object)
331 {
332   struct access_list *alist;
333   /* struct prefix_ipv4 match; */
334
335   if (type == RMAP_BGP)
336     {
337       alist = access_list_lookup (AFI_IP, (char *) rule);
338       if (alist == NULL)
339         return RMAP_NOMATCH;
340     
341       return (access_list_apply (alist, prefix) == FILTER_DENY ?
342               RMAP_NOMATCH : RMAP_MATCH);
343     }
344   return RMAP_NOMATCH;
345 }
346
347 /* Route map `ip address' match statement.  `arg' should be
348    access-list name. */
349 static void *
350 route_match_ip_address_compile (const char *arg)
351 {
352   return XSTRDUP (MTYPE_ROUTE_MAP_COMPILED, arg);
353 }
354
355 /* Free route map's compiled `ip address' value. */
356 static void
357 route_match_ip_address_free (void *rule)
358 {
359   XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
360 }
361
362 /* Route map commands for ip address matching. */
363 struct route_map_rule_cmd route_match_ip_address_cmd =
364 {
365   "ip address",
366   route_match_ip_address,
367   route_match_ip_address_compile,
368   route_match_ip_address_free
369 };
370
371 /* `match ip next-hop IP_ADDRESS' */
372
373 /* Match function return 1 if match is success else return zero. */
374 static route_map_result_t
375 route_match_ip_next_hop (void *rule, struct prefix *prefix, 
376                          route_map_object_t type, void *object)
377 {
378   struct access_list *alist;
379   struct bgp_info *bgp_info;
380   struct prefix_ipv4 p;
381
382   if (type == RMAP_BGP)
383     {
384       bgp_info = object;
385       p.family = AF_INET;
386       p.prefix = bgp_info->attr->nexthop;
387       p.prefixlen = IPV4_MAX_BITLEN;
388
389       alist = access_list_lookup (AFI_IP, (char *) rule);
390       if (alist == NULL)
391         return RMAP_NOMATCH;
392
393       return (access_list_apply (alist, &p) == FILTER_DENY ?
394               RMAP_NOMATCH : RMAP_MATCH);
395     }
396   return RMAP_NOMATCH;
397 }
398
399 /* Route map `ip next-hop' match statement. `arg' is
400    access-list name. */
401 static void *
402 route_match_ip_next_hop_compile (const char *arg)
403 {
404   return XSTRDUP (MTYPE_ROUTE_MAP_COMPILED, arg);
405 }
406
407 /* Free route map's compiled `ip address' value. */
408 static void
409 route_match_ip_next_hop_free (void *rule)
410 {
411   XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
412 }
413
414 /* Route map commands for ip next-hop matching. */
415 struct route_map_rule_cmd route_match_ip_next_hop_cmd =
416 {
417   "ip next-hop",
418   route_match_ip_next_hop,
419   route_match_ip_next_hop_compile,
420   route_match_ip_next_hop_free
421 };
422
423 /* `match ip route-source ACCESS-LIST' */
424
425 /* Match function return 1 if match is success else return zero. */
426 static route_map_result_t
427 route_match_ip_route_source (void *rule, struct prefix *prefix, 
428                              route_map_object_t type, void *object)
429 {
430   struct access_list *alist;
431   struct bgp_info *bgp_info;
432   struct peer *peer;
433   struct prefix_ipv4 p;
434
435   if (type == RMAP_BGP)
436     {
437       bgp_info = object;
438       peer = bgp_info->peer;
439
440       if (! peer || sockunion_family (&peer->su) != AF_INET)
441         return RMAP_NOMATCH;
442
443       p.family = AF_INET;
444       p.prefix = peer->su.sin.sin_addr;
445       p.prefixlen = IPV4_MAX_BITLEN;
446
447       alist = access_list_lookup (AFI_IP, (char *) rule);
448       if (alist == NULL)
449         return RMAP_NOMATCH;
450
451       return (access_list_apply (alist, &p) == FILTER_DENY ?
452               RMAP_NOMATCH : RMAP_MATCH);
453     }
454   return RMAP_NOMATCH;
455 }
456
457 /* Route map `ip route-source' match statement. `arg' is
458    access-list name. */
459 static void *
460 route_match_ip_route_source_compile (const char *arg)
461 {
462   return XSTRDUP (MTYPE_ROUTE_MAP_COMPILED, arg);
463 }
464
465 /* Free route map's compiled `ip address' value. */
466 static void
467 route_match_ip_route_source_free (void *rule)
468 {
469   XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
470 }
471
472 /* Route map commands for ip route-source matching. */
473 struct route_map_rule_cmd route_match_ip_route_source_cmd =
474 {
475   "ip route-source",
476   route_match_ip_route_source,
477   route_match_ip_route_source_compile,
478   route_match_ip_route_source_free
479 };
480
481 /* `match ip address prefix-list PREFIX_LIST' */
482
483 static route_map_result_t
484 route_match_ip_address_prefix_list (void *rule, struct prefix *prefix, 
485                                     route_map_object_t type, void *object)
486 {
487   struct prefix_list *plist;
488
489   if (type == RMAP_BGP)
490     {
491       plist = prefix_list_lookup (AFI_IP, (char *) rule);
492       if (plist == NULL)
493         return RMAP_NOMATCH;
494     
495       return (prefix_list_apply (plist, prefix) == PREFIX_DENY ?
496               RMAP_NOMATCH : RMAP_MATCH);
497     }
498   return RMAP_NOMATCH;
499 }
500
501 static void *
502 route_match_ip_address_prefix_list_compile (const char *arg)
503 {
504   return XSTRDUP (MTYPE_ROUTE_MAP_COMPILED, arg);
505 }
506
507 static void
508 route_match_ip_address_prefix_list_free (void *rule)
509 {
510   XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
511 }
512
513 struct route_map_rule_cmd route_match_ip_address_prefix_list_cmd =
514 {
515   "ip address prefix-list",
516   route_match_ip_address_prefix_list,
517   route_match_ip_address_prefix_list_compile,
518   route_match_ip_address_prefix_list_free
519 };
520
521 /* `match ip next-hop prefix-list PREFIX_LIST' */
522
523 static route_map_result_t
524 route_match_ip_next_hop_prefix_list (void *rule, struct prefix *prefix,
525                                     route_map_object_t type, void *object)
526 {
527   struct prefix_list *plist;
528   struct bgp_info *bgp_info;
529   struct prefix_ipv4 p;
530
531   if (type == RMAP_BGP)
532     {
533       bgp_info = object;
534       p.family = AF_INET;
535       p.prefix = bgp_info->attr->nexthop;
536       p.prefixlen = IPV4_MAX_BITLEN;
537
538       plist = prefix_list_lookup (AFI_IP, (char *) rule);
539       if (plist == NULL)
540         return RMAP_NOMATCH;
541
542       return (prefix_list_apply (plist, &p) == PREFIX_DENY ?
543               RMAP_NOMATCH : RMAP_MATCH);
544     }
545   return RMAP_NOMATCH;
546 }
547
548 static void *
549 route_match_ip_next_hop_prefix_list_compile (const char *arg)
550 {
551   return XSTRDUP (MTYPE_ROUTE_MAP_COMPILED, arg);
552 }
553
554 static void
555 route_match_ip_next_hop_prefix_list_free (void *rule)
556 {
557   XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
558 }
559
560 struct route_map_rule_cmd route_match_ip_next_hop_prefix_list_cmd =
561 {
562   "ip next-hop prefix-list",
563   route_match_ip_next_hop_prefix_list,
564   route_match_ip_next_hop_prefix_list_compile,
565   route_match_ip_next_hop_prefix_list_free
566 };
567
568 /* `match ip route-source prefix-list PREFIX_LIST' */
569
570 static route_map_result_t
571 route_match_ip_route_source_prefix_list (void *rule, struct prefix *prefix,
572                                          route_map_object_t type, void *object)
573 {
574   struct prefix_list *plist;
575   struct bgp_info *bgp_info;
576   struct peer *peer;
577   struct prefix_ipv4 p;
578
579   if (type == RMAP_BGP)
580     {
581       bgp_info = object;
582       peer = bgp_info->peer;
583
584       if (! peer || sockunion_family (&peer->su) != AF_INET)
585         return RMAP_NOMATCH;
586
587       p.family = AF_INET;
588       p.prefix = peer->su.sin.sin_addr;
589       p.prefixlen = IPV4_MAX_BITLEN;
590
591       plist = prefix_list_lookup (AFI_IP, (char *) rule);
592       if (plist == NULL)
593         return RMAP_NOMATCH;
594
595       return (prefix_list_apply (plist, &p) == PREFIX_DENY ?
596               RMAP_NOMATCH : RMAP_MATCH);
597     }
598   return RMAP_NOMATCH;
599 }
600
601 static void *
602 route_match_ip_route_source_prefix_list_compile (const char *arg)
603 {
604   return XSTRDUP (MTYPE_ROUTE_MAP_COMPILED, arg);
605 }
606
607 static void
608 route_match_ip_route_source_prefix_list_free (void *rule)
609 {
610   XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
611 }
612
613 struct route_map_rule_cmd route_match_ip_route_source_prefix_list_cmd =
614 {
615   "ip route-source prefix-list",
616   route_match_ip_route_source_prefix_list,
617   route_match_ip_route_source_prefix_list_compile,
618   route_match_ip_route_source_prefix_list_free
619 };
620
621 /* `match local-preference LOCAL-PREF' */
622
623 /* Match function return 1 if match is success else return zero. */
624 static route_map_result_t
625 route_match_local_pref (void *rule, struct prefix *prefix,
626                         route_map_object_t type, void *object)
627 {
628   u_int32_t *local_pref;
629   struct bgp_info *bgp_info;
630
631   if (type == RMAP_BGP)
632     {
633       local_pref = rule;
634       bgp_info = object;
635
636       if (bgp_info->attr->local_pref == *local_pref)
637         return RMAP_MATCH;
638       else
639         return RMAP_NOMATCH;
640     }
641   return RMAP_NOMATCH;
642 }
643
644 /* Route map `match local-preference' match statement.
645    `arg' is local-pref value */
646 static void *
647 route_match_local_pref_compile (const char *arg)
648 {
649   u_int32_t *local_pref;
650   char *endptr = NULL;
651   unsigned long tmpval;
652
653   /* Locpref value shoud be integer. */
654   if (! all_digit (arg))
655     return NULL;
656
657   errno = 0;
658   tmpval = strtoul (arg, &endptr, 10);
659   if (*endptr != '\0' || errno || tmpval > UINT32_MAX)
660     return NULL;
661
662   local_pref = XMALLOC (MTYPE_ROUTE_MAP_COMPILED, sizeof (u_int32_t));
663
664   if (!local_pref)
665     return local_pref;
666
667   *local_pref = tmpval;
668   return local_pref;
669 }
670
671 /* Free route map's compiled `match local-preference' value. */
672 static void
673 route_match_local_pref_free (void *rule)
674 {
675   XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
676 }
677
678 /* Route map commands for metric matching. */
679 struct route_map_rule_cmd route_match_local_pref_cmd =
680 {
681   "local-preference",
682   route_match_local_pref,
683   route_match_local_pref_compile,
684   route_match_local_pref_free
685 };
686
687 /* `match metric METRIC' */
688
689 /* Match function return 1 if match is success else return zero. */
690 static route_map_result_t
691 route_match_metric (void *rule, struct prefix *prefix, 
692                     route_map_object_t type, void *object)
693 {
694   struct rmap_value *rv;
695   struct bgp_info *bgp_info;
696
697   if (type == RMAP_BGP)
698     {
699       rv = rule;
700       bgp_info = object;
701       return route_value_match(rv, bgp_info->attr->med);
702     }
703   return RMAP_NOMATCH;
704 }
705
706 /* Route map commands for metric matching. */
707 struct route_map_rule_cmd route_match_metric_cmd =
708 {
709   "metric",
710   route_match_metric,
711   route_value_compile,
712   route_value_free,
713 };
714
715 /* `match as-path ASPATH' */
716
717 /* Match function for as-path match.  I assume given object is */
718 static route_map_result_t
719 route_match_aspath (void *rule, struct prefix *prefix, 
720                     route_map_object_t type, void *object)
721 {
722   
723   struct as_list *as_list;
724   struct bgp_info *bgp_info;
725
726   if (type == RMAP_BGP)
727     {
728       as_list = as_list_lookup ((char *) rule);
729       if (as_list == NULL)
730         return RMAP_NOMATCH;
731     
732       bgp_info = object;
733     
734       /* Perform match. */
735       return ((as_list_apply (as_list, bgp_info->attr->aspath) == AS_FILTER_DENY) ? RMAP_NOMATCH : RMAP_MATCH);
736     }
737   return RMAP_NOMATCH;
738 }
739
740 /* Compile function for as-path match. */
741 static void *
742 route_match_aspath_compile (const char *arg)
743 {
744   return XSTRDUP (MTYPE_ROUTE_MAP_COMPILED, arg);
745 }
746
747 /* Compile function for as-path match. */
748 static void
749 route_match_aspath_free (void *rule)
750 {
751   XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
752 }
753
754 /* Route map commands for aspath matching. */
755 struct route_map_rule_cmd route_match_aspath_cmd = 
756 {
757   "as-path",
758   route_match_aspath,
759   route_match_aspath_compile,
760   route_match_aspath_free
761 };
762
763 /* `match community COMMUNIY' */
764 struct rmap_community
765 {
766   char *name;
767   int exact;
768 };
769
770 /* Match function for community match. */
771 static route_map_result_t
772 route_match_community (void *rule, struct prefix *prefix, 
773                        route_map_object_t type, void *object)
774 {
775   struct community_list *list;
776   struct bgp_info *bgp_info;
777   struct rmap_community *rcom;
778
779   if (type == RMAP_BGP) 
780     {
781       bgp_info = object;
782       rcom = rule;
783
784       list = community_list_lookup (bgp_clist, rcom->name, COMMUNITY_LIST_MASTER);
785       if (! list)
786         return RMAP_NOMATCH;
787
788       if (rcom->exact)
789         {
790           if (community_list_exact_match (bgp_info->attr->community, list))
791             return RMAP_MATCH;
792         }
793       else
794         {
795           if (community_list_match (bgp_info->attr->community, list))
796             return RMAP_MATCH;
797         }
798     }
799   return RMAP_NOMATCH;
800 }
801
802 /* Compile function for community match. */
803 static void *
804 route_match_community_compile (const char *arg)
805 {
806   struct rmap_community *rcom;
807   int len;
808   char *p;
809
810   rcom = XCALLOC (MTYPE_ROUTE_MAP_COMPILED, sizeof (struct rmap_community));
811
812   p = strchr (arg, ' ');
813   if (p)
814     {
815       len = p - arg;
816       rcom->name = XCALLOC (MTYPE_ROUTE_MAP_COMPILED, len + 1);
817       memcpy (rcom->name, arg, len);
818       rcom->exact = 1;
819     }
820   else
821     {
822       rcom->name = XSTRDUP (MTYPE_ROUTE_MAP_COMPILED, arg);
823       rcom->exact = 0;
824     }
825   return rcom;
826 }
827
828 /* Compile function for community match. */
829 static void
830 route_match_community_free (void *rule)
831 {
832   struct rmap_community *rcom = rule;
833
834   XFREE (MTYPE_ROUTE_MAP_COMPILED, rcom->name); 
835   XFREE (MTYPE_ROUTE_MAP_COMPILED, rcom);
836 }
837
838 /* Route map commands for community matching. */
839 struct route_map_rule_cmd route_match_community_cmd = 
840 {
841   "community",
842   route_match_community,
843   route_match_community_compile,
844   route_match_community_free
845 };
846
847 /* Match function for lcommunity match. */
848 static route_map_result_t
849 route_match_lcommunity (void *rule, struct prefix *prefix,
850                        route_map_object_t type, void *object)
851 {
852   struct community_list *list;
853   struct bgp_info *bgp_info;
854   struct rmap_community *rcom;
855
856   if (type == RMAP_BGP)
857     {
858       bgp_info = object;
859       rcom = rule;
860
861       list = community_list_lookup (bgp_clist, rcom->name,
862                                     LARGE_COMMUNITY_LIST_MASTER);
863       if (! list)
864         return RMAP_NOMATCH;
865
866       if (bgp_info->attr->extra &&
867           lcommunity_list_match (bgp_info->attr->extra->lcommunity, list))
868         return RMAP_MATCH;
869
870     }
871   return RMAP_NOMATCH;
872 }
873
874 /* Compile function for community match. */
875 static void *
876 route_match_lcommunity_compile (const char *arg)
877 {
878   struct rmap_community *rcom;
879   int len;
880   char *p;
881
882   rcom = XCALLOC (MTYPE_ROUTE_MAP_COMPILED, sizeof (struct rmap_community));
883
884   p = strchr (arg, ' ');
885   if (p)
886     {
887       len = p - arg;
888       rcom->name = XCALLOC (MTYPE_ROUTE_MAP_COMPILED, len + 1);
889       memcpy (rcom->name, arg, len);
890     }
891   else
892     {
893       rcom->name = XSTRDUP (MTYPE_ROUTE_MAP_COMPILED, arg);
894       rcom->exact = 0;
895     }
896   return rcom;
897 }
898
899 /* Compile function for community match. */
900 static void
901 route_match_lcommunity_free (void *rule)
902 {
903   struct rmap_community *rcom = rule;
904
905   XFREE (MTYPE_ROUTE_MAP_COMPILED, rcom->name);
906   XFREE (MTYPE_ROUTE_MAP_COMPILED, rcom);
907 }
908
909 /* Route map commands for community matching. */
910 struct route_map_rule_cmd route_match_lcommunity_cmd =
911 {
912   "large-community",
913   route_match_lcommunity,
914   route_match_lcommunity_compile,
915   route_match_lcommunity_free
916 };
917
918
919 /* Match function for extcommunity match. */
920 static route_map_result_t
921 route_match_ecommunity (void *rule, struct prefix *prefix,
922                         route_map_object_t type, void *object)
923 {
924   struct community_list *list;
925   struct bgp_info *bgp_info;
926
927   if (type == RMAP_BGP)
928     {
929       bgp_info = object;
930
931       if (!bgp_info->attr->extra)
932         return RMAP_NOMATCH;
933
934       list = community_list_lookup (bgp_clist, (char *) rule,
935                                     EXTCOMMUNITY_LIST_MASTER);
936       if (! list)
937         return RMAP_NOMATCH;
938
939       if (ecommunity_list_match (bgp_info->attr->extra->ecommunity, list))
940         return RMAP_MATCH;
941     }
942   return RMAP_NOMATCH;
943 }
944
945 /* Compile function for extcommunity match. */
946 static void *
947 route_match_ecommunity_compile (const char *arg)
948 {
949   return XSTRDUP (MTYPE_ROUTE_MAP_COMPILED, arg);
950 }
951
952 /* Compile function for extcommunity match. */
953 static void
954 route_match_ecommunity_free (void *rule)
955 {
956   XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
957 }
958
959 /* Route map commands for community matching. */
960 struct route_map_rule_cmd route_match_ecommunity_cmd = 
961 {
962   "extcommunity",
963   route_match_ecommunity,
964   route_match_ecommunity_compile,
965   route_match_ecommunity_free
966 };
967
968 /* `match nlri` and `set nlri` are replaced by `address-family ipv4`
969    and `address-family vpnv4'.  */
970
971 /* `match origin' */
972 static route_map_result_t
973 route_match_origin (void *rule, struct prefix *prefix, 
974                     route_map_object_t type, void *object)
975 {
976   u_char *origin;
977   struct bgp_info *bgp_info;
978
979   if (type == RMAP_BGP)
980     {
981       origin = rule;
982       bgp_info = object;
983     
984       if (bgp_info->attr->origin == *origin)
985         return RMAP_MATCH;
986     }
987
988   return RMAP_NOMATCH;
989 }
990
991 static void *
992 route_match_origin_compile (const char *arg)
993 {
994   u_char *origin;
995
996   origin = XMALLOC (MTYPE_ROUTE_MAP_COMPILED, sizeof (u_char));
997
998   if (strcmp (arg, "igp") == 0)
999     *origin = 0;
1000   else if (strcmp (arg, "egp") == 0)
1001     *origin = 1;
1002   else
1003     *origin = 2;
1004
1005   return origin;
1006 }
1007
1008 /* Free route map's compiled `ip address' value. */
1009 static void
1010 route_match_origin_free (void *rule)
1011 {
1012   XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
1013 }
1014
1015 /* Route map commands for origin matching. */
1016 struct route_map_rule_cmd route_match_origin_cmd =
1017 {
1018   "origin",
1019   route_match_origin,
1020   route_match_origin_compile,
1021   route_match_origin_free
1022 };
1023
1024 /* match probability  { */
1025
1026 static route_map_result_t
1027 route_match_probability (void *rule, struct prefix *prefix,
1028                     route_map_object_t type, void *object)
1029 {
1030   long r = random();
1031
1032   switch (*(long *) rule)
1033   {
1034     case 0: break;
1035     case RAND_MAX: return RMAP_MATCH;
1036     default:
1037       if (r < *(long *) rule)
1038         {
1039           return RMAP_MATCH;
1040         }
1041   }
1042
1043   return RMAP_NOMATCH;
1044 }
1045
1046 static void *
1047 route_match_probability_compile (const char *arg)
1048 {
1049   long *lobule;
1050   unsigned  perc;
1051
1052   perc    = atoi (arg);
1053   lobule  = XMALLOC (MTYPE_ROUTE_MAP_COMPILED, sizeof (long));
1054
1055   switch (perc)
1056     {
1057       case 0:   *lobule = 0; break;
1058       case 100: *lobule = RAND_MAX; break;
1059       default:  *lobule = RAND_MAX / 100 * perc;
1060     }
1061
1062   return lobule;
1063 }
1064
1065 static void
1066 route_match_probability_free (void *rule)
1067 {
1068   XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
1069 }
1070
1071 struct route_map_rule_cmd route_match_probability_cmd =
1072 {
1073   "probability",
1074   route_match_probability,
1075   route_match_probability_compile,
1076   route_match_probability_free
1077 };
1078
1079 /* } */
1080
1081 /* `set ip next-hop IP_ADDRESS' */
1082
1083 /* Match function return 1 if match is success else return zero. */
1084 static route_map_result_t
1085 route_match_tag (void *rule, struct prefix *prefix,
1086                  route_map_object_t type, void *object)
1087 {
1088   route_tag_t *tag;
1089   struct bgp_info *bgp_info;
1090
1091   if (type == RMAP_BGP)
1092     {
1093       tag = rule;
1094       bgp_info = object;
1095
1096       if (!bgp_info->attr->extra)
1097          return RMAP_NOMATCH;
1098
1099       return ((bgp_info->attr->extra->tag == *tag)? RMAP_MATCH : RMAP_NOMATCH);
1100     }
1101
1102   return RMAP_NOMATCH;
1103 }
1104
1105 /* Route map commands for tag matching. */
1106 static struct route_map_rule_cmd route_match_tag_cmd =
1107 {
1108   "tag",
1109   route_match_tag,
1110   route_map_rule_tag_compile,
1111   route_map_rule_tag_free,
1112 };
1113
1114
1115 /* Set nexthop to object.  ojbect must be pointer to struct attr. */
1116 struct rmap_ip_nexthop_set
1117 {
1118   struct in_addr *address;
1119   int peer_address;
1120 };
1121
1122 static route_map_result_t
1123 route_set_ip_nexthop (void *rule, struct prefix *prefix,
1124                       route_map_object_t type, void *object)
1125 {
1126   struct rmap_ip_nexthop_set *rins = rule;
1127   struct bgp_info *bgp_info;
1128   struct peer *peer;
1129
1130   if (type == RMAP_BGP)
1131     {
1132       bgp_info = object;
1133       peer = bgp_info->peer;
1134
1135       if (rins->peer_address)
1136         {
1137          if ((CHECK_FLAG (peer->rmap_type, PEER_RMAP_TYPE_IN) ||
1138            CHECK_FLAG (peer->rmap_type, PEER_RMAP_TYPE_IMPORT))
1139               && peer->su_remote 
1140               && sockunion_family (peer->su_remote) == AF_INET)
1141             {
1142               bgp_info->attr->nexthop.s_addr = sockunion2ip (peer->su_remote);
1143               bgp_info->attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_NEXT_HOP);
1144             }
1145           else if (CHECK_FLAG (peer->rmap_type, PEER_RMAP_TYPE_OUT)
1146                    && peer->su_local
1147                    && sockunion_family (peer->su_local) == AF_INET)
1148             {
1149               bgp_info->attr->nexthop.s_addr = sockunion2ip (peer->su_local);
1150               bgp_info->attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_NEXT_HOP);
1151             }
1152         }
1153       else
1154         {
1155           /* Set next hop value. */ 
1156           bgp_info->attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_NEXT_HOP);
1157           bgp_info->attr->nexthop = *rins->address;
1158         }
1159     }
1160
1161   return RMAP_OKAY;
1162 }
1163
1164 /* Route map `ip nexthop' compile function.  Given string is converted
1165    to struct in_addr structure. */
1166 static void *
1167 route_set_ip_nexthop_compile (const char *arg)
1168 {
1169   struct rmap_ip_nexthop_set *rins;
1170   struct in_addr *address = NULL;
1171   int peer_address = 0;
1172   int ret;
1173
1174   if (strcmp (arg, "peer-address") == 0)
1175     peer_address = 1;
1176   else
1177     {
1178       address = XMALLOC (MTYPE_ROUTE_MAP_COMPILED, sizeof (struct in_addr));
1179       ret = inet_aton (arg, address);
1180
1181       if (ret == 0)
1182         {
1183           XFREE (MTYPE_ROUTE_MAP_COMPILED, address);
1184           return NULL;
1185         }
1186     }
1187
1188   rins = XCALLOC (MTYPE_ROUTE_MAP_COMPILED, sizeof (struct rmap_ip_nexthop_set));
1189
1190   rins->address = address;
1191   rins->peer_address = peer_address;
1192
1193   return rins;
1194 }
1195
1196 /* Free route map's compiled `ip nexthop' value. */
1197 static void
1198 route_set_ip_nexthop_free (void *rule)
1199 {
1200   struct rmap_ip_nexthop_set *rins = rule;
1201
1202   if (rins->address)
1203     XFREE (MTYPE_ROUTE_MAP_COMPILED, rins->address);
1204     
1205   XFREE (MTYPE_ROUTE_MAP_COMPILED, rins);
1206 }
1207
1208 /* Route map commands for ip nexthop set. */
1209 struct route_map_rule_cmd route_set_ip_nexthop_cmd =
1210 {
1211   "ip next-hop",
1212   route_set_ip_nexthop,
1213   route_set_ip_nexthop_compile,
1214   route_set_ip_nexthop_free
1215 };
1216
1217 /* `set local-preference LOCAL_PREF' */
1218
1219 /* Set local preference. */
1220 static route_map_result_t
1221 route_set_local_pref (void *rule, struct prefix *prefix,
1222                       route_map_object_t type, void *object)
1223 {
1224   struct rmap_value *rv;
1225   struct bgp_info *bgp_info;
1226   u_int32_t locpref = 0;
1227
1228   if (type == RMAP_BGP)
1229     {
1230       /* Fetch routemap's rule information. */
1231       rv = rule;
1232       bgp_info = object;
1233     
1234       /* Set local preference value. */ 
1235       if (bgp_info->attr->flag & ATTR_FLAG_BIT (BGP_ATTR_LOCAL_PREF))
1236         locpref = bgp_info->attr->local_pref;
1237
1238       bgp_info->attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_LOCAL_PREF);
1239       bgp_info->attr->local_pref = route_value_adjust(rv, locpref, bgp_info->peer);
1240     }
1241
1242   return RMAP_OKAY;
1243 }
1244
1245 /* Set local preference rule structure. */
1246 struct route_map_rule_cmd route_set_local_pref_cmd = 
1247 {
1248   "local-preference",
1249   route_set_local_pref,
1250   route_value_compile,
1251   route_value_free,
1252 };
1253
1254 /* `set weight WEIGHT' */
1255
1256 /* Set weight. */
1257 static route_map_result_t
1258 route_set_weight (void *rule, struct prefix *prefix, route_map_object_t type,
1259                   void *object)
1260 {
1261   struct rmap_value *rv;
1262   struct bgp_info *bgp_info;
1263   u_int32_t weight;
1264
1265   if (type == RMAP_BGP)
1266     {
1267       /* Fetch routemap's rule information. */
1268       rv = rule;
1269       bgp_info = object;
1270     
1271       /* Set weight value. */ 
1272       weight = route_value_adjust(rv, 0, bgp_info->peer);
1273       if (weight)
1274         (bgp_attr_extra_get (bgp_info->attr))->weight = weight;
1275       else if (bgp_info->attr->extra)
1276         bgp_info->attr->extra->weight = 0;
1277     }
1278
1279   return RMAP_OKAY;
1280 }
1281
1282 /* Set local preference rule structure. */
1283 struct route_map_rule_cmd route_set_weight_cmd = 
1284 {
1285   "weight",
1286   route_set_weight,
1287   route_value_compile,
1288   route_value_free,
1289 };
1290
1291 /* `set metric METRIC' */
1292
1293 /* Set metric to attribute. */
1294 static route_map_result_t
1295 route_set_metric (void *rule, struct prefix *prefix, 
1296                   route_map_object_t type, void *object)
1297 {
1298   struct rmap_value *rv;
1299   struct bgp_info *bgp_info;
1300   u_int32_t med = 0;
1301
1302   if (type == RMAP_BGP)
1303     {
1304       /* Fetch routemap's rule information. */
1305       rv = rule;
1306       bgp_info = object;
1307
1308       if (bgp_info->attr->flag & ATTR_FLAG_BIT (BGP_ATTR_MULTI_EXIT_DISC))
1309         med = bgp_info->attr->med;
1310
1311       bgp_info->attr->med = route_value_adjust(rv, med, bgp_info->peer);
1312       bgp_info->attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_MULTI_EXIT_DISC);
1313     }
1314   return RMAP_OKAY;
1315 }
1316
1317 /* Set metric rule structure. */
1318 struct route_map_rule_cmd route_set_metric_cmd = 
1319 {
1320   "metric",
1321   route_set_metric,
1322   route_value_compile,
1323   route_value_free,
1324 };
1325
1326 /* `set as-path prepend ASPATH' */
1327
1328 /* For AS path prepend mechanism. */
1329 static route_map_result_t
1330 route_set_aspath_prepend (void *rule, struct prefix *prefix, route_map_object_t type, void *object)
1331 {
1332   struct aspath *aspath;
1333   struct aspath *new;
1334   struct bgp_info *binfo;
1335
1336   if (type == RMAP_BGP)
1337     {
1338       binfo = object;
1339     
1340       if (binfo->attr->aspath->refcnt)
1341         new = aspath_dup (binfo->attr->aspath);
1342       else
1343         new = binfo->attr->aspath;
1344
1345       if ((uintptr_t)rule > 10)
1346       {
1347         aspath = rule;
1348         aspath_prepend (aspath, new);
1349       }
1350       else
1351       {
1352         as_t as = aspath_leftmost(new);
1353         if (!as) as = binfo->peer->as;
1354         new = aspath_add_seq_n (new, as, (uintptr_t) rule);
1355       }
1356
1357       binfo->attr->aspath = new;
1358     }
1359
1360   return RMAP_OKAY;
1361 }
1362
1363 static void *
1364 route_set_aspath_prepend_compile (const char *arg)
1365 {
1366   unsigned int num;
1367
1368   if (sscanf(arg, "last-as %u", &num) == 1 && num > 0 && num < 10)
1369     return (void*)(uintptr_t)num;
1370
1371   return route_aspath_compile(arg);
1372 }
1373
1374 static void
1375 route_set_aspath_prepend_free (void *rule)
1376 {
1377   if ((uintptr_t)rule > 10)
1378     route_aspath_free(rule);
1379 }
1380
1381
1382 /* Set as-path prepend rule structure. */
1383 struct route_map_rule_cmd route_set_aspath_prepend_cmd = 
1384 {
1385   "as-path prepend",
1386   route_set_aspath_prepend,
1387   route_set_aspath_prepend_compile,
1388   route_set_aspath_prepend_free,
1389 };
1390
1391 /* `set as-path exclude ASn' */
1392
1393 /* For ASN exclude mechanism.
1394  * Iterate over ASns requested and filter them from the given AS_PATH one by one.
1395  * Make a deep copy of existing AS_PATH, but for the first ASn only.
1396  */
1397 static route_map_result_t
1398 route_set_aspath_exclude (void *rule, struct prefix *dummy, route_map_object_t type, void *object)
1399 {
1400   struct aspath * new_path, * exclude_path;
1401   struct bgp_info *binfo;
1402
1403   if (type == RMAP_BGP)
1404   {
1405     exclude_path = rule;
1406     binfo = object;
1407     if (binfo->attr->aspath->refcnt)
1408       new_path = aspath_dup (binfo->attr->aspath);
1409     else
1410       new_path = binfo->attr->aspath;
1411     binfo->attr->aspath = aspath_filter_exclude (new_path, exclude_path);
1412   }
1413   return RMAP_OKAY;
1414 }
1415
1416 /* Set ASn exlude rule structure. */
1417 struct route_map_rule_cmd route_set_aspath_exclude_cmd = 
1418 {
1419   "as-path exclude",
1420   route_set_aspath_exclude,
1421   route_aspath_compile,
1422   route_aspath_free,
1423 };
1424
1425 /* `set community COMMUNITY' */
1426 struct rmap_com_set
1427 {
1428   struct community *com;
1429   int additive;
1430   int none;
1431 };
1432
1433 /* For community set mechanism. */
1434 static route_map_result_t
1435 route_set_community (void *rule, struct prefix *prefix,
1436                      route_map_object_t type, void *object)
1437 {
1438   struct rmap_com_set *rcs;
1439   struct bgp_info *binfo;
1440   struct attr *attr;
1441   struct community *new = NULL;
1442   struct community *old;
1443   struct community *merge;
1444   
1445   if (type == RMAP_BGP)
1446     {
1447       rcs = rule;
1448       binfo = object;
1449       attr = binfo->attr;
1450       old = attr->community;
1451
1452       /* "none" case.  */
1453       if (rcs->none)
1454         {
1455           attr->flag &= ~(ATTR_FLAG_BIT (BGP_ATTR_COMMUNITIES));
1456           attr->community = NULL;
1457           /* See the longer comment down below. */
1458           if (old && old->refcnt == 0)
1459             community_free(old);
1460           return RMAP_OKAY;
1461         }
1462
1463       /* "additive" case.  */
1464       if (rcs->additive && old)
1465         {
1466           merge = community_merge (community_dup (old), rcs->com);
1467           
1468           /* HACK: if the old community is not intern'd, 
1469            * we should free it here, or all reference to it may be lost.
1470            * Really need to cleanup attribute caching sometime.
1471            */
1472           if (old->refcnt == 0)
1473             community_free (old);
1474           new = community_uniq_sort (merge);
1475           community_free (merge);
1476         }
1477       else
1478         new = community_dup (rcs->com);
1479       
1480       /* will be interned by caller if required */
1481       attr->community = new;
1482
1483       attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_COMMUNITIES);
1484     }
1485
1486   return RMAP_OKAY;
1487 }
1488
1489 /* Compile function for set community. */
1490 static void *
1491 route_set_community_compile (const char *arg)
1492 {
1493   struct rmap_com_set *rcs;
1494   struct community *com = NULL;
1495   char *sp;
1496   int additive = 0;
1497   int none = 0;
1498   
1499   if (strcmp (arg, "none") == 0)
1500     none = 1;
1501   else
1502     {
1503       sp = strstr (arg, "additive");
1504
1505       if (sp && sp > arg)
1506         {
1507           /* "additive" keyworkd is included.  */
1508           additive = 1;
1509           *(sp - 1) = '\0';
1510         }
1511
1512       com = community_str2com (arg);
1513
1514       if (additive)
1515         *(sp - 1) = ' ';
1516
1517       if (! com)
1518         return NULL;
1519     }
1520   
1521   rcs = XCALLOC (MTYPE_ROUTE_MAP_COMPILED, sizeof (struct rmap_com_set));
1522   rcs->com = com;
1523   rcs->additive = additive;
1524   rcs->none = none;
1525   
1526   return rcs;
1527 }
1528
1529 /* Free function for set community. */
1530 static void
1531 route_set_community_free (void *rule)
1532 {
1533   struct rmap_com_set *rcs = rule;
1534
1535   if (rcs->com)
1536     community_free (rcs->com);
1537   XFREE (MTYPE_ROUTE_MAP_COMPILED, rcs);
1538 }
1539
1540 /* Set community rule structure. */
1541 struct route_map_rule_cmd route_set_community_cmd = 
1542 {
1543   "community",
1544   route_set_community,
1545   route_set_community_compile,
1546   route_set_community_free,
1547 };
1548
1549 /* `set community COMMUNITY' */
1550 struct rmap_lcom_set
1551 {
1552   struct lcommunity *lcom;
1553   int additive;
1554   int none;
1555 };
1556
1557
1558 /* For lcommunity set mechanism. */
1559 static route_map_result_t
1560 route_set_lcommunity (void *rule, struct prefix *prefix,
1561                      route_map_object_t type, void *object)
1562 {
1563   struct rmap_lcom_set *rcs;
1564   struct bgp_info *binfo;
1565   struct attr *attr;
1566   struct lcommunity *new = NULL;
1567   struct lcommunity *old;
1568   struct lcommunity *merge;
1569
1570   if (type == RMAP_BGP)
1571     {
1572       rcs = rule;
1573       binfo = object;
1574       attr = binfo->attr;
1575       old = (attr->extra) ? attr->extra->lcommunity : NULL;
1576
1577       /* "none" case.  */
1578       if (rcs->none)
1579         {
1580           attr->flag &= ~(ATTR_FLAG_BIT (BGP_ATTR_LARGE_COMMUNITIES));
1581           if (attr->extra) {
1582             attr->extra->lcommunity = NULL;
1583           }
1584           /* See the longer comment down below. */
1585           if (old && old->refcnt == 0)
1586             lcommunity_free(&old);
1587           return RMAP_OKAY;
1588         }
1589
1590       if (rcs->additive && old)
1591         {
1592           merge = lcommunity_merge (lcommunity_dup (old), rcs->lcom);
1593
1594           /* HACK: if the old large-community is not intern'd,
1595            * we should free it here, or all reference to it may be lost.
1596            * Really need to cleanup attribute caching sometime.
1597            */
1598           if (old->refcnt == 0)
1599             lcommunity_free (&old);
1600           new = lcommunity_uniq_sort (merge);
1601           lcommunity_free (&merge);
1602         }
1603       else
1604         {
1605           new = lcommunity_dup (rcs->lcom);
1606         }
1607
1608       /* will be interned by caller if required */
1609       bgp_attr_extra_get (attr)->lcommunity = new;
1610       attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_LARGE_COMMUNITIES);
1611     }
1612
1613   return RMAP_OKAY;
1614 }
1615
1616 /* Compile function for set community. */
1617 static void *
1618 route_set_lcommunity_compile (const char *arg)
1619 {
1620   struct rmap_lcom_set *rcs;
1621   struct lcommunity *lcom = NULL;
1622   char *sp;
1623   int additive = 0;
1624   int none = 0;
1625
1626   if (strcmp (arg, "none") == 0)
1627     none = 1;
1628   else
1629     {
1630       sp = strstr (arg, "additive");
1631
1632       if (sp && sp > arg)
1633         {
1634           /* "additive" keyworkd is included.  */
1635           additive = 1;
1636           *(sp - 1) = '\0';
1637         }
1638
1639       lcom = lcommunity_str2com (arg);
1640
1641      if (additive)
1642         *(sp - 1) = ' ';
1643
1644      if (! lcom)
1645         return NULL;
1646     }
1647
1648   rcs = XCALLOC (MTYPE_ROUTE_MAP_COMPILED, sizeof (struct rmap_com_set));
1649   rcs->lcom = lcom;
1650   rcs->additive = additive;
1651   rcs->none = none;
1652
1653   return rcs;
1654 }
1655
1656 /* Free function for set lcommunity. */
1657 static void
1658 route_set_lcommunity_free (void *rule)
1659 {
1660   struct rmap_lcom_set *rcs = rule;
1661
1662   if (rcs->lcom) {
1663     lcommunity_free (&rcs->lcom);
1664   }
1665   XFREE (MTYPE_ROUTE_MAP_COMPILED, rcs);
1666 }
1667
1668 /* Set community rule structure. */
1669 struct route_map_rule_cmd route_set_lcommunity_cmd =
1670 {
1671   "large-community",
1672   route_set_lcommunity,
1673   route_set_lcommunity_compile,
1674   route_set_lcommunity_free,
1675 };
1676
1677 /* `set large-comm-list (<1-99>|<100-500>|WORD) delete' */
1678
1679 /* For large community set mechanism. */
1680 static route_map_result_t
1681 route_set_lcommunity_delete (void *rule, struct prefix *prefix,
1682                              route_map_object_t type, void *object)
1683 {
1684   struct community_list *list;
1685   struct lcommunity *merge;
1686   struct lcommunity *new;
1687   struct lcommunity *old;
1688   struct bgp_info *binfo;
1689
1690   if (type == RMAP_BGP)
1691     {
1692       if (! rule)
1693         return RMAP_OKAY;
1694
1695       binfo = object;
1696       list = community_list_lookup (bgp_clist, rule,
1697                                     LARGE_COMMUNITY_LIST_MASTER);
1698       old = ((binfo->attr->extra) ? binfo->attr->extra->lcommunity : NULL);
1699
1700       if (list && old)
1701         {
1702           merge = lcommunity_list_match_delete (lcommunity_dup (old), list);
1703           new = lcommunity_uniq_sort (merge);
1704           lcommunity_free (&merge);
1705
1706           /* HACK: if the old community is not intern'd,
1707            * we should free it here, or all reference to it may be lost.
1708            * Really need to cleanup attribute caching sometime.
1709            */
1710           if (old->refcnt == 0)
1711             lcommunity_free (&old);
1712
1713           if (new->size == 0)
1714             {
1715               binfo->attr->extra->lcommunity = NULL;
1716               binfo->attr->flag &= ~ATTR_FLAG_BIT (BGP_ATTR_LARGE_COMMUNITIES);
1717               lcommunity_free (&new);
1718             }
1719           else
1720             {
1721               binfo->attr->extra->lcommunity = new;
1722               binfo->attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_LARGE_COMMUNITIES);
1723             }
1724         }
1725     }
1726
1727   return RMAP_OKAY;
1728 }
1729
1730 /* Compile function for set lcommunity. */
1731 static void *
1732 route_set_lcommunity_delete_compile (const char *arg)
1733 {
1734   char *p;
1735   char *str;
1736   int len;
1737
1738   p = strchr (arg, ' ');
1739   if (p)
1740     {
1741       len = p - arg;
1742       str = XCALLOC (MTYPE_ROUTE_MAP_COMPILED, len + 1);
1743       memcpy (str, arg, len);
1744     }
1745   else
1746     str = NULL;
1747
1748   return str;
1749 }
1750
1751 /* Free function for set lcommunity. */
1752 static void
1753 route_set_lcommunity_delete_free (void *rule)
1754 {
1755   XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
1756 }
1757
1758 /* Set lcommunity rule structure. */
1759 struct route_map_rule_cmd route_set_lcommunity_delete_cmd =
1760 {
1761   "large-comm-list",
1762   route_set_lcommunity_delete,
1763   route_set_lcommunity_delete_compile,
1764   route_set_lcommunity_delete_free,
1765 };
1766
1767
1768 /* `set comm-list (<1-99>|<100-500>|WORD) delete' */
1769
1770 /* For community set mechanism. */
1771 static route_map_result_t
1772 route_set_community_delete (void *rule, struct prefix *prefix,
1773                             route_map_object_t type, void *object)
1774 {
1775   struct community_list *list;
1776   struct community *merge;
1777   struct community *new;
1778   struct community *old;
1779   struct bgp_info *binfo;
1780
1781   if (type == RMAP_BGP)
1782     {
1783       if (! rule)
1784         return RMAP_OKAY;
1785
1786       binfo = object;
1787       list = community_list_lookup (bgp_clist, rule, COMMUNITY_LIST_MASTER);
1788       old = binfo->attr->community;
1789
1790       if (list && old)
1791         {
1792           merge = community_list_match_delete (community_dup (old), list);
1793           new = community_uniq_sort (merge);
1794           community_free (merge);
1795
1796           /* HACK: if the old community is not intern'd,
1797            * we should free it here, or all reference to it may be lost.
1798            * Really need to cleanup attribute caching sometime.
1799            */
1800           if (old->refcnt == 0)
1801             community_free (old);
1802
1803           if (new->size == 0)
1804             {
1805               binfo->attr->community = NULL;
1806               binfo->attr->flag &= ~ATTR_FLAG_BIT (BGP_ATTR_COMMUNITIES);
1807               community_free (new);
1808             }
1809           else
1810             {
1811               binfo->attr->community = new;
1812               binfo->attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_COMMUNITIES);
1813             }
1814         }
1815     }
1816
1817   return RMAP_OKAY;
1818 }
1819
1820 /* Compile function for set community. */
1821 static void *
1822 route_set_community_delete_compile (const char *arg)
1823 {
1824   char *p;
1825   char *str;
1826   int len;
1827
1828   p = strchr (arg, ' ');
1829   if (p)
1830     {
1831       len = p - arg;
1832       str = XCALLOC (MTYPE_ROUTE_MAP_COMPILED, len + 1);
1833       memcpy (str, arg, len);
1834     }
1835   else
1836     str = NULL;
1837
1838   return str;
1839 }
1840
1841 /* Free function for set community. */
1842 static void
1843 route_set_community_delete_free (void *rule)
1844 {
1845   XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
1846 }
1847
1848 /* Set community rule structure. */
1849 struct route_map_rule_cmd route_set_community_delete_cmd =
1850 {
1851   "comm-list",
1852   route_set_community_delete,
1853   route_set_community_delete_compile,
1854   route_set_community_delete_free,
1855 };
1856
1857 /* `set extcommunity rt COMMUNITY' */
1858
1859 /* For community set mechanism.  Used by _rt and _soo. */
1860 static route_map_result_t
1861 route_set_ecommunity (void *rule, struct prefix *prefix,
1862                       route_map_object_t type, void *object)
1863 {
1864   struct ecommunity *ecom;
1865   struct ecommunity *new_ecom;
1866   struct ecommunity *old_ecom;
1867   struct bgp_info *bgp_info;
1868
1869   if (type == RMAP_BGP)
1870     {
1871       ecom = rule;
1872       bgp_info = object;
1873     
1874       if (! ecom)
1875         return RMAP_OKAY;
1876     
1877       /* We assume additive for Extended Community. */
1878       old_ecom = (bgp_attr_extra_get (bgp_info->attr))->ecommunity;
1879
1880       if (old_ecom)
1881         {
1882           new_ecom = ecommunity_merge (ecommunity_dup (old_ecom), ecom);
1883
1884           /* old_ecom->refcnt = 1 => owned elsewhere, e.g. bgp_update_receive()
1885            *         ->refcnt = 0 => set by a previous route-map statement */
1886           if (!old_ecom->refcnt)
1887             ecommunity_free (&old_ecom);
1888         }
1889       else
1890         new_ecom = ecommunity_dup (ecom);
1891
1892       /* will be intern()'d or attr_flush()'d by bgp_update_main() */
1893       bgp_info->attr->extra->ecommunity = new_ecom;
1894
1895       bgp_info->attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_EXT_COMMUNITIES);
1896     }
1897   return RMAP_OKAY;
1898 }
1899
1900 /* Compile function for set community. */
1901 static void *
1902 route_set_ecommunity_rt_compile (const char *arg)
1903 {
1904   struct ecommunity *ecom;
1905
1906   ecom = ecommunity_str2com (arg, ECOMMUNITY_ROUTE_TARGET, 0);
1907   if (! ecom)
1908     return NULL;
1909   return ecommunity_intern (ecom);
1910 }
1911
1912 /* Free function for set community.  Used by _rt and _soo */
1913 static void
1914 route_set_ecommunity_free (void *rule)
1915 {
1916   struct ecommunity *ecom = rule;
1917   ecommunity_unintern (&ecom);
1918 }
1919
1920 /* Set community rule structure. */
1921 struct route_map_rule_cmd route_set_ecommunity_rt_cmd = 
1922 {
1923   "extcommunity rt",
1924   route_set_ecommunity,
1925   route_set_ecommunity_rt_compile,
1926   route_set_ecommunity_free,
1927 };
1928
1929 /* `set extcommunity soo COMMUNITY' */
1930
1931 /* Compile function for set community. */
1932 static void *
1933 route_set_ecommunity_soo_compile (const char *arg)
1934 {
1935   struct ecommunity *ecom;
1936
1937   ecom = ecommunity_str2com (arg, ECOMMUNITY_SITE_ORIGIN, 0);
1938   if (! ecom)
1939     return NULL;
1940   
1941   return ecommunity_intern (ecom);
1942 }
1943
1944 /* Set community rule structure. */
1945 struct route_map_rule_cmd route_set_ecommunity_soo_cmd = 
1946 {
1947   "extcommunity soo",
1948   route_set_ecommunity,
1949   route_set_ecommunity_soo_compile,
1950   route_set_ecommunity_free,
1951 };
1952
1953 /* `set origin ORIGIN' */
1954
1955 /* For origin set. */
1956 static route_map_result_t
1957 route_set_origin (void *rule, struct prefix *prefix, route_map_object_t type, void *object)
1958 {
1959   u_char *origin;
1960   struct bgp_info *bgp_info;
1961
1962   if (type == RMAP_BGP)
1963     {
1964       origin = rule;
1965       bgp_info = object;
1966     
1967       bgp_info->attr->origin = *origin;
1968     }
1969
1970   return RMAP_OKAY;
1971 }
1972
1973 /* Compile function for origin set. */
1974 static void *
1975 route_set_origin_compile (const char *arg)
1976 {
1977   u_char *origin;
1978
1979   origin = XMALLOC (MTYPE_ROUTE_MAP_COMPILED, sizeof (u_char));
1980
1981   if (strcmp (arg, "igp") == 0)
1982     *origin = 0;
1983   else if (strcmp (arg, "egp") == 0)
1984     *origin = 1;
1985   else
1986     *origin = 2;
1987
1988   return origin;
1989 }
1990
1991 /* Compile function for origin set. */
1992 static void
1993 route_set_origin_free (void *rule)
1994 {
1995   XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
1996 }
1997
1998 /* Set origin rule structure. */
1999 struct route_map_rule_cmd route_set_origin_cmd = 
2000 {
2001   "origin",
2002   route_set_origin,
2003   route_set_origin_compile,
2004   route_set_origin_free,
2005 };
2006
2007 /* `set atomic-aggregate' */
2008
2009 /* For atomic aggregate set. */
2010 static route_map_result_t
2011 route_set_atomic_aggregate (void *rule, struct prefix *prefix,
2012                             route_map_object_t type, void *object)
2013 {
2014   struct bgp_info *bgp_info;
2015
2016   if (type == RMAP_BGP)
2017     {
2018       bgp_info = object;
2019       bgp_info->attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_ATOMIC_AGGREGATE);
2020     }
2021
2022   return RMAP_OKAY;
2023 }
2024
2025 /* Compile function for atomic aggregate. */
2026 static void *
2027 route_set_atomic_aggregate_compile (const char *arg)
2028 {
2029   return (void *)1;
2030 }
2031
2032 /* Compile function for atomic aggregate. */
2033 static void
2034 route_set_atomic_aggregate_free (void *rule)
2035 {
2036   return;
2037 }
2038
2039 /* Set atomic aggregate rule structure. */
2040 struct route_map_rule_cmd route_set_atomic_aggregate_cmd = 
2041 {
2042   "atomic-aggregate",
2043   route_set_atomic_aggregate,
2044   route_set_atomic_aggregate_compile,
2045   route_set_atomic_aggregate_free,
2046 };
2047
2048 /* `set aggregator as AS A.B.C.D' */
2049 struct aggregator
2050 {
2051   as_t as;
2052   struct in_addr address;
2053 };
2054
2055 static route_map_result_t
2056 route_set_aggregator_as (void *rule, struct prefix *prefix, 
2057                          route_map_object_t type, void *object)
2058 {
2059   struct bgp_info *bgp_info;
2060   struct aggregator *aggregator;
2061   struct attr_extra *ae;
2062
2063   if (type == RMAP_BGP)
2064     {
2065       bgp_info = object;
2066       aggregator = rule;
2067       ae = bgp_attr_extra_get (bgp_info->attr);
2068       
2069       ae->aggregator_as = aggregator->as;
2070       ae->aggregator_addr = aggregator->address;
2071       bgp_info->attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_AGGREGATOR);
2072     }
2073
2074   return RMAP_OKAY;
2075 }
2076
2077 static void *
2078 route_set_aggregator_as_compile (const char *arg)
2079 {
2080   struct aggregator *aggregator;
2081   char as[10];
2082   char address[20];
2083
2084   aggregator = XCALLOC (MTYPE_ROUTE_MAP_COMPILED, sizeof (struct aggregator));
2085   sscanf (arg, "%s %s", as, address);
2086
2087   aggregator->as = strtoul (as, NULL, 10);
2088   inet_aton (address, &aggregator->address);
2089
2090   return aggregator;
2091 }
2092
2093 static void
2094 route_set_aggregator_as_free (void *rule)
2095 {
2096   XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
2097 }
2098
2099 struct route_map_rule_cmd route_set_aggregator_as_cmd = 
2100 {
2101   "aggregator as",
2102   route_set_aggregator_as,
2103   route_set_aggregator_as_compile,
2104   route_set_aggregator_as_free,
2105 };
2106
2107 /* Set tag to object. object must be pointer to struct bgp_info */
2108 static route_map_result_t
2109 route_set_tag (void *rule, struct prefix *prefix,
2110                route_map_object_t type, void *object)
2111 {
2112   route_tag_t *tag;
2113   struct bgp_info *bgp_info;
2114   struct attr_extra *ae;
2115
2116   if (type == RMAP_BGP)
2117     {
2118       tag = rule;
2119       bgp_info = object;
2120       ae = bgp_attr_extra_get (bgp_info->attr);
2121
2122       /* Set tag value */
2123       ae->tag=*tag;
2124
2125     }
2126
2127   return RMAP_OKAY;
2128 }
2129
2130 /* Route map commands for tag set. */
2131 static struct route_map_rule_cmd route_set_tag_cmd =
2132 {
2133   "tag",
2134   route_set_tag,
2135   route_map_rule_tag_compile,
2136   route_map_rule_tag_free,
2137 };
2138
2139
2140 /* `match ipv6 address IP_ACCESS_LIST' */
2141
2142 static route_map_result_t
2143 route_match_ipv6_address (void *rule, struct prefix *prefix, 
2144                           route_map_object_t type, void *object)
2145 {
2146   struct access_list *alist;
2147
2148   if (type == RMAP_BGP)
2149     {
2150       alist = access_list_lookup (AFI_IP6, (char *) rule);
2151       if (alist == NULL)
2152         return RMAP_NOMATCH;
2153     
2154       return (access_list_apply (alist, prefix) == FILTER_DENY ?
2155               RMAP_NOMATCH : RMAP_MATCH);
2156     }
2157   return RMAP_NOMATCH;
2158 }
2159
2160 static void *
2161 route_match_ipv6_address_compile (const char *arg)
2162 {
2163   return XSTRDUP (MTYPE_ROUTE_MAP_COMPILED, arg);
2164 }
2165
2166 static void
2167 route_match_ipv6_address_free (void *rule)
2168 {
2169   XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
2170 }
2171
2172 /* Route map commands for ip address matching. */
2173 struct route_map_rule_cmd route_match_ipv6_address_cmd =
2174 {
2175   "ipv6 address",
2176   route_match_ipv6_address,
2177   route_match_ipv6_address_compile,
2178   route_match_ipv6_address_free
2179 };
2180
2181 /* `match ipv6 next-hop IP_ADDRESS' */
2182
2183 static route_map_result_t
2184 route_match_ipv6_next_hop (void *rule, struct prefix *prefix, 
2185                            route_map_object_t type, void *object)
2186 {
2187   struct in6_addr *addr = rule;
2188   struct bgp_info *bgp_info;
2189
2190   if (type == RMAP_BGP)
2191     {
2192       bgp_info = object;
2193       
2194       if (!bgp_info->attr->extra)
2195         return RMAP_NOMATCH;
2196       
2197       if (IPV6_ADDR_SAME (&bgp_info->attr->extra->mp_nexthop_global, addr))
2198         return RMAP_MATCH;
2199
2200       if (bgp_info->attr->extra->mp_nexthop_len == 32 &&
2201           IPV6_ADDR_SAME (&bgp_info->attr->extra->mp_nexthop_local, addr))
2202         return RMAP_MATCH;
2203
2204       return RMAP_NOMATCH;
2205     }
2206
2207   return RMAP_NOMATCH;
2208 }
2209
2210 static void *
2211 route_match_ipv6_next_hop_compile (const char *arg)
2212 {
2213   struct in6_addr *address;
2214   int ret;
2215
2216   address = XMALLOC (MTYPE_ROUTE_MAP_COMPILED, sizeof (struct in6_addr));
2217
2218   ret = inet_pton (AF_INET6, arg, address);
2219   if (!ret)
2220     {
2221       XFREE (MTYPE_ROUTE_MAP_COMPILED, address);
2222       return NULL;
2223     }
2224
2225   return address;
2226 }
2227
2228 static void
2229 route_match_ipv6_next_hop_free (void *rule)
2230 {
2231   XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
2232 }
2233
2234 struct route_map_rule_cmd route_match_ipv6_next_hop_cmd =
2235 {
2236   "ipv6 next-hop",
2237   route_match_ipv6_next_hop,
2238   route_match_ipv6_next_hop_compile,
2239   route_match_ipv6_next_hop_free
2240 };
2241
2242 /* `match ipv6 address prefix-list PREFIX_LIST' */
2243
2244 static route_map_result_t
2245 route_match_ipv6_address_prefix_list (void *rule, struct prefix *prefix, 
2246                               route_map_object_t type, void *object)
2247 {
2248   struct prefix_list *plist;
2249
2250   if (type == RMAP_BGP)
2251     {
2252       plist = prefix_list_lookup (AFI_IP6, (char *) rule);
2253       if (plist == NULL)
2254         return RMAP_NOMATCH;
2255     
2256       return (prefix_list_apply (plist, prefix) == PREFIX_DENY ?
2257               RMAP_NOMATCH : RMAP_MATCH);
2258     }
2259   return RMAP_NOMATCH;
2260 }
2261
2262 static void *
2263 route_match_ipv6_address_prefix_list_compile (const char *arg)
2264 {
2265   return XSTRDUP (MTYPE_ROUTE_MAP_COMPILED, arg);
2266 }
2267
2268 static void
2269 route_match_ipv6_address_prefix_list_free (void *rule)
2270 {
2271   XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
2272 }
2273
2274 struct route_map_rule_cmd route_match_ipv6_address_prefix_list_cmd =
2275 {
2276   "ipv6 address prefix-list",
2277   route_match_ipv6_address_prefix_list,
2278   route_match_ipv6_address_prefix_list_compile,
2279   route_match_ipv6_address_prefix_list_free
2280 };
2281
2282 /* `set ipv6 nexthop global IP_ADDRESS' */
2283
2284 /* Set nexthop to object.  ojbect must be pointer to struct attr. */
2285 static route_map_result_t
2286 route_set_ipv6_nexthop_global (void *rule, struct prefix *prefix, 
2287                                route_map_object_t type, void *object)
2288 {
2289   struct in6_addr *address;
2290   struct bgp_info *bgp_info;
2291
2292   if (type == RMAP_BGP)
2293     {
2294       /* Fetch routemap's rule information. */
2295       address = rule;
2296       bgp_info = object;
2297     
2298       /* Set next hop value. */ 
2299       (bgp_attr_extra_get (bgp_info->attr))->mp_nexthop_global = *address;
2300     
2301       /* Set nexthop length. */
2302       if (bgp_info->attr->extra->mp_nexthop_len == 0)
2303         bgp_info->attr->extra->mp_nexthop_len = 16;
2304     }
2305
2306   return RMAP_OKAY;
2307 }
2308
2309 /* Route map `ip next-hop' compile function.  Given string is converted
2310    to struct in_addr structure. */
2311 static void *
2312 route_set_ipv6_nexthop_global_compile (const char *arg)
2313 {
2314   int ret;
2315   struct in6_addr *address;
2316
2317   address = XMALLOC (MTYPE_ROUTE_MAP_COMPILED, sizeof (struct in6_addr));
2318
2319   ret = inet_pton (AF_INET6, arg, address);
2320
2321   if (ret == 0)
2322     {
2323       XFREE (MTYPE_ROUTE_MAP_COMPILED, address);
2324       return NULL;
2325     }
2326
2327   return address;
2328 }
2329
2330 /* Free route map's compiled `ip next-hop' value. */
2331 static void
2332 route_set_ipv6_nexthop_global_free (void *rule)
2333 {
2334   XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
2335 }
2336
2337 /* Route map commands for ip nexthop set. */
2338 struct route_map_rule_cmd route_set_ipv6_nexthop_global_cmd =
2339 {
2340   "ipv6 next-hop global",
2341   route_set_ipv6_nexthop_global,
2342   route_set_ipv6_nexthop_global_compile,
2343   route_set_ipv6_nexthop_global_free
2344 };
2345
2346 /* `set ipv6 nexthop local IP_ADDRESS' */
2347
2348 /* Set nexthop to object.  ojbect must be pointer to struct attr. */
2349 static route_map_result_t
2350 route_set_ipv6_nexthop_local (void *rule, struct prefix *prefix, 
2351                               route_map_object_t type, void *object)
2352 {
2353   struct in6_addr *address;
2354   struct bgp_info *bgp_info;
2355
2356   if (type == RMAP_BGP)
2357     {
2358       /* Fetch routemap's rule information. */
2359       address = rule;
2360       bgp_info = object;
2361     
2362       /* Set next hop value. */ 
2363       (bgp_attr_extra_get (bgp_info->attr))->mp_nexthop_local = *address;
2364     
2365       /* Set nexthop length. */
2366       if (bgp_info->attr->extra->mp_nexthop_len != 32)
2367         bgp_info->attr->extra->mp_nexthop_len = 32;
2368     }
2369
2370   return RMAP_OKAY;
2371 }
2372
2373 /* Route map `ip nexthop' compile function.  Given string is converted
2374    to struct in_addr structure. */
2375 static void *
2376 route_set_ipv6_nexthop_local_compile (const char *arg)
2377 {
2378   int ret;
2379   struct in6_addr *address;
2380
2381   address = XMALLOC (MTYPE_ROUTE_MAP_COMPILED, sizeof (struct in6_addr));
2382
2383   ret = inet_pton (AF_INET6, arg, address);
2384
2385   if (ret == 0)
2386     {
2387       XFREE (MTYPE_ROUTE_MAP_COMPILED, address);
2388       return NULL;
2389     }
2390
2391   return address;
2392 }
2393
2394 /* Free route map's compiled `ip nexthop' value. */
2395 static void
2396 route_set_ipv6_nexthop_local_free (void *rule)
2397 {
2398   XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
2399 }
2400
2401 /* Route map commands for ip nexthop set. */
2402 struct route_map_rule_cmd route_set_ipv6_nexthop_local_cmd =
2403 {
2404   "ipv6 next-hop local",
2405   route_set_ipv6_nexthop_local,
2406   route_set_ipv6_nexthop_local_compile,
2407   route_set_ipv6_nexthop_local_free
2408 };
2409
2410 /* `set ipv6 nexthop peer-address' */
2411
2412 /* Set nexthop to object.  ojbect must be pointer to struct attr. */
2413 static route_map_result_t
2414 route_set_ipv6_nexthop_peer (void *rule, struct prefix *prefix,
2415                              route_map_object_t type, void *object)
2416 {
2417   struct in6_addr peer_address;
2418   struct bgp_info *bgp_info;
2419   struct peer *peer;
2420
2421   if (type == RMAP_BGP)
2422     {
2423       /* Fetch routemap's rule information. */
2424       bgp_info = object;
2425       peer = bgp_info->peer;
2426
2427       if ((CHECK_FLAG (peer->rmap_type, PEER_RMAP_TYPE_IN) ||
2428            CHECK_FLAG (peer->rmap_type, PEER_RMAP_TYPE_IMPORT))
2429           && peer->su_remote
2430           && sockunion_family (peer->su_remote) == AF_INET6)
2431         {
2432           peer_address = peer->su_remote->sin6.sin6_addr;
2433         }
2434       else if (CHECK_FLAG (peer->rmap_type, PEER_RMAP_TYPE_OUT)
2435                && peer->su_local
2436                && sockunion_family (peer->su_local) == AF_INET6)
2437         {
2438           peer_address = peer->su_local->sin6.sin6_addr;
2439         }
2440
2441       if (IN6_IS_ADDR_LINKLOCAL(&peer_address))
2442         {
2443           /* Set next hop value. */
2444           (bgp_attr_extra_get (bgp_info->attr))->mp_nexthop_local = peer_address;
2445
2446           /* Set nexthop length. */
2447           if (bgp_info->attr->extra->mp_nexthop_len != 32)
2448             bgp_info->attr->extra->mp_nexthop_len = 32;
2449         }
2450       else
2451         {
2452           /* Set next hop value. */
2453           (bgp_attr_extra_get (bgp_info->attr))->mp_nexthop_global = peer_address;
2454
2455           /* Set nexthop length. */
2456           if (bgp_info->attr->extra->mp_nexthop_len == 0)
2457             bgp_info->attr->extra->mp_nexthop_len = 16;
2458         }
2459     }
2460
2461   return RMAP_OKAY;
2462 }
2463
2464 /* Route map `ip next-hop' compile function.  Given string is converted
2465    to struct in_addr structure. */
2466 static void *
2467 route_set_ipv6_nexthop_peer_compile (const char *arg)
2468 {
2469   int *rins = NULL;
2470
2471   rins = XCALLOC (MTYPE_ROUTE_MAP_COMPILED, sizeof (int));
2472   *rins = 1;
2473
2474   return rins;
2475 }
2476
2477 /* Free route map's compiled `ip next-hop' value. */
2478 static void
2479 route_set_ipv6_nexthop_peer_free (void *rule)
2480 {
2481   XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
2482 }
2483
2484 /* Route map commands for ip nexthop set. */
2485 struct route_map_rule_cmd route_set_ipv6_nexthop_peer_cmd =
2486 {
2487   "ipv6 next-hop peer-address",
2488   route_set_ipv6_nexthop_peer,
2489   route_set_ipv6_nexthop_peer_compile,
2490   route_set_ipv6_nexthop_peer_free
2491 };
2492
2493 /* `set vpnv4 nexthop A.B.C.D' */
2494
2495 static route_map_result_t
2496 route_set_vpnv4_nexthop (void *rule, struct prefix *prefix, 
2497                          route_map_object_t type, void *object)
2498 {
2499   struct in_addr *address;
2500   struct bgp_info *bgp_info;
2501
2502   if (type == RMAP_BGP)
2503     {
2504       /* Fetch routemap's rule information. */
2505       address = rule;
2506       bgp_info = object;
2507     
2508       /* Set next hop value. */ 
2509       (bgp_attr_extra_get (bgp_info->attr))->mp_nexthop_global_in = *address;
2510       (bgp_attr_extra_get (bgp_info->attr))->mp_nexthop_len = 4;
2511     }
2512
2513   return RMAP_OKAY;
2514 }
2515
2516 static void *
2517 route_set_vpnv4_nexthop_compile (const char *arg)
2518 {
2519   int ret;
2520   struct in_addr *address;
2521
2522   address = XMALLOC (MTYPE_ROUTE_MAP_COMPILED, sizeof (struct in_addr));
2523
2524   ret = inet_aton (arg, address);
2525
2526   if (ret == 0)
2527     {
2528       XFREE (MTYPE_ROUTE_MAP_COMPILED, address);
2529       return NULL;
2530     }
2531
2532   return address;
2533 }
2534
2535 static void
2536 route_set_vpnv4_nexthop_free (void *rule)
2537 {
2538   XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
2539 }
2540
2541 /* Route map commands for ip nexthop set. */
2542 struct route_map_rule_cmd route_set_vpnv4_nexthop_cmd =
2543 {
2544   "vpnv4 next-hop",
2545   route_set_vpnv4_nexthop,
2546   route_set_vpnv4_nexthop_compile,
2547   route_set_vpnv4_nexthop_free
2548 };
2549
2550 /* `set originator-id' */
2551
2552 /* For origin set. */
2553 static route_map_result_t
2554 route_set_originator_id (void *rule, struct prefix *prefix, route_map_object_t type, void *object)
2555 {
2556   struct in_addr *address;
2557   struct bgp_info *bgp_info;
2558
2559   if (type == RMAP_BGP) 
2560     {
2561       address = rule;
2562       bgp_info = object;
2563     
2564       bgp_info->attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_ORIGINATOR_ID);
2565       (bgp_attr_extra_get (bgp_info->attr))->originator_id = *address;
2566     }
2567
2568   return RMAP_OKAY;
2569 }
2570
2571 /* Compile function for originator-id set. */
2572 static void *
2573 route_set_originator_id_compile (const char *arg)
2574 {
2575   int ret;
2576   struct in_addr *address;
2577
2578   address = XMALLOC (MTYPE_ROUTE_MAP_COMPILED, sizeof (struct in_addr));
2579
2580   ret = inet_aton (arg, address);
2581
2582   if (ret == 0)
2583     {
2584       XFREE (MTYPE_ROUTE_MAP_COMPILED, address);
2585       return NULL;
2586     }
2587
2588   return address;
2589 }
2590
2591 /* Compile function for originator_id set. */
2592 static void
2593 route_set_originator_id_free (void *rule)
2594 {
2595   XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
2596 }
2597
2598 /* Set originator-id rule structure. */
2599 struct route_map_rule_cmd route_set_originator_id_cmd = 
2600 {
2601   "originator-id",
2602   route_set_originator_id,
2603   route_set_originator_id_compile,
2604   route_set_originator_id_free,
2605 };
2606
2607 /* Add bgp route map rule. */
2608 static int
2609 bgp_route_match_add (struct vty *vty, struct route_map_index *index,
2610                      const char *command, const char *arg)
2611 {
2612   int ret;
2613
2614   ret = route_map_add_match (index, command, arg);
2615   if (ret)
2616     {
2617       switch (ret)
2618         {
2619         case RMAP_RULE_MISSING:
2620           vty_out (vty, "%% BGP Can't find rule.%s", VTY_NEWLINE);
2621           return CMD_WARNING;
2622         case RMAP_COMPILE_ERROR:
2623           vty_out (vty, "%% BGP Argument is malformed.%s", VTY_NEWLINE);
2624           return CMD_WARNING;
2625         }
2626     }
2627   return CMD_SUCCESS;
2628 }
2629
2630 /* Delete bgp route map rule. */
2631 static int
2632 bgp_route_match_delete (struct vty *vty, struct route_map_index *index,
2633                         const char *command, const char *arg)
2634 {
2635   int ret;
2636
2637   ret = route_map_delete_match (index, command, arg);
2638   if (ret)
2639     {
2640       switch (ret)
2641         {
2642         case RMAP_RULE_MISSING:
2643           vty_out (vty, "%% BGP Can't find rule.%s", VTY_NEWLINE);
2644           return CMD_WARNING;
2645         case RMAP_COMPILE_ERROR:
2646           vty_out (vty, "%% BGP Argument is malformed.%s", VTY_NEWLINE);
2647           return CMD_WARNING;
2648         }
2649     }
2650   return CMD_SUCCESS;
2651 }
2652
2653 /* Add bgp route map rule. */
2654 static int
2655 bgp_route_set_add (struct vty *vty, struct route_map_index *index,
2656                    const char *command, const char *arg)
2657 {
2658   int ret;
2659
2660   ret = route_map_add_set (index, command, arg);
2661   if (ret)
2662     {
2663       switch (ret)
2664         {
2665         case RMAP_RULE_MISSING:
2666           vty_out (vty, "%% BGP Can't find rule.%s", VTY_NEWLINE);
2667           return CMD_WARNING;
2668         case RMAP_COMPILE_ERROR:
2669           vty_out (vty, "%% BGP Argument is malformed.%s", VTY_NEWLINE);
2670           return CMD_WARNING;
2671         }
2672     }
2673   return CMD_SUCCESS;
2674 }
2675
2676 /* Delete bgp route map rule. */
2677 static int
2678 bgp_route_set_delete (struct vty *vty, struct route_map_index *index,
2679                       const char *command, const char *arg)
2680 {
2681   int ret;
2682
2683   ret = route_map_delete_set (index, command, arg);
2684   if (ret)
2685     {
2686       switch (ret)
2687         {
2688         case RMAP_RULE_MISSING:
2689           vty_out (vty, "%% BGP Can't find rule.%s", VTY_NEWLINE);
2690           return CMD_WARNING;
2691         case RMAP_COMPILE_ERROR:
2692           vty_out (vty, "%% BGP Argument is malformed.%s", VTY_NEWLINE);
2693           return CMD_WARNING;
2694         }
2695     }
2696   return CMD_SUCCESS;
2697 }
2698
2699 /* Hook function for updating route_map assignment. */
2700 static void
2701 bgp_route_map_update (const char *unused)
2702 {
2703   int i;
2704   afi_t afi;
2705   safi_t safi;
2706   int direct;
2707   struct listnode *node, *nnode;
2708   struct listnode *mnode, *mnnode;
2709   struct bgp *bgp;
2710   struct peer *peer;
2711   struct peer_group *group;
2712   struct bgp_filter *filter;
2713   struct bgp_node *bn;
2714   struct bgp_static *bgp_static;
2715
2716   if (bm->bgp == NULL)          /* may be called during cleanup */
2717     return;
2718
2719   /* For neighbor route-map updates. */
2720   for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
2721     {
2722       for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
2723         {
2724           for (afi = AFI_IP; afi < AFI_MAX; afi++)
2725             for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
2726               {
2727                 filter = &peer->filter[afi][safi];
2728           
2729                for (direct = RMAP_IN; direct < RMAP_MAX; direct++)
2730                   {
2731                     if (filter->map[direct].name)
2732                       filter->map[direct].map = 
2733                         route_map_lookup_by_name (filter->map[direct].name);
2734                     else
2735                       filter->map[direct].map = NULL;
2736                   }
2737
2738                 if (filter->usmap.name)
2739                   filter->usmap.map = route_map_lookup_by_name (filter->usmap.name);
2740                 else
2741                   filter->usmap.map = NULL;
2742               }
2743         }
2744       for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
2745         {
2746           for (afi = AFI_IP; afi < AFI_MAX; afi++)
2747             for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
2748               {
2749                 filter = &group->conf->filter[afi][safi];
2750           
2751                for (direct = RMAP_IN; direct < RMAP_MAX; direct++)
2752                   {
2753                     if (filter->map[direct].name)
2754                       filter->map[direct].map = 
2755                         route_map_lookup_by_name (filter->map[direct].name);
2756                     else
2757                       filter->map[direct].map = NULL;
2758                   }
2759
2760                 if (filter->usmap.name)
2761                   filter->usmap.map = route_map_lookup_by_name (filter->usmap.name);
2762                 else
2763                   filter->usmap.map = NULL;
2764               }
2765         }
2766     }
2767
2768   /* For default-originate route-map updates. */
2769   for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
2770     {
2771       for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
2772         {
2773           for (afi = AFI_IP; afi < AFI_MAX; afi++)
2774             for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
2775               {
2776                 if (peer->default_rmap[afi][safi].name)
2777                   peer->default_rmap[afi][safi].map =
2778                     route_map_lookup_by_name (peer->default_rmap[afi][safi].name);
2779                 else
2780                   peer->default_rmap[afi][safi].map = NULL;
2781               }
2782         }
2783     }
2784
2785   /* For network route-map updates. */
2786   for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
2787     {
2788       for (afi = AFI_IP; afi < AFI_MAX; afi++)
2789         for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
2790           for (bn = bgp_table_top (bgp->route[afi][safi]); bn;
2791                bn = bgp_route_next (bn))
2792             if ((bgp_static = bn->info) != NULL)
2793               {
2794                 if (bgp_static->rmap.name)
2795                   bgp_static->rmap.map =
2796                          route_map_lookup_by_name (bgp_static->rmap.name);
2797                 else
2798                   bgp_static->rmap.map = NULL;
2799               }
2800     }
2801
2802   /* For redistribute route-map updates. */
2803   for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
2804     {
2805       for (i = 0; i < ZEBRA_ROUTE_MAX; i++)
2806         {
2807           if (bgp->rmap[AFI_IP][i].name)
2808             bgp->rmap[AFI_IP][i].map =
2809               route_map_lookup_by_name (bgp->rmap[AFI_IP][i].name);
2810           if (bgp->rmap[AFI_IP6][i].name)
2811             bgp->rmap[AFI_IP6][i].map =
2812               route_map_lookup_by_name (bgp->rmap[AFI_IP6][i].name);
2813         }
2814     }
2815 }
2816
2817 DEFUN (match_peer,
2818        match_peer_cmd,
2819        "match peer (A.B.C.D|X:X::X:X)",
2820        MATCH_STR
2821        "Match peer address\n"
2822        "IP address of peer\n"
2823        "IPv6 address of peer\n")
2824 {
2825   return bgp_route_match_add (vty, vty->index, "peer", argv[0]);
2826 }
2827
2828 DEFUN (match_peer_local,
2829         match_peer_local_cmd,
2830         "match peer local",
2831         MATCH_STR
2832         "Match peer address\n"
2833         "Static or Redistributed routes\n")
2834 {
2835   return bgp_route_match_add (vty, vty->index, "peer", "local");
2836 }
2837
2838 DEFUN (no_match_peer,
2839        no_match_peer_cmd,
2840        "no match peer",
2841        NO_STR
2842        MATCH_STR
2843        "Match peer address\n")
2844 {
2845  if (argc == 0)
2846    return bgp_route_match_delete (vty, vty->index, "peer", NULL);
2847
2848   return bgp_route_match_delete (vty, vty->index, "peer", argv[0]);
2849 }
2850
2851 ALIAS (no_match_peer,
2852        no_match_peer_val_cmd,
2853        "no match peer (A.B.C.D|X:X::X:X)",
2854        NO_STR
2855        MATCH_STR
2856        "Match peer address\n"
2857        "IP address of peer\n"
2858        "IPv6 address of peer\n")
2859
2860 ALIAS (no_match_peer,
2861        no_match_peer_local_cmd,
2862        "no match peer local",
2863        NO_STR
2864        MATCH_STR
2865        "Match peer address\n"
2866        "Static or Redistributed routes\n")
2867
2868 DEFUN (match_ip_address, 
2869        match_ip_address_cmd,
2870        "match ip address (<1-199>|<1300-2699>|WORD)",
2871        MATCH_STR
2872        IP_STR
2873        "Match address of route\n"
2874        "IP access-list number\n"
2875        "IP access-list number (expanded range)\n"
2876        "IP Access-list name\n")
2877 {
2878   return bgp_route_match_add (vty, vty->index, "ip address", argv[0]);
2879 }
2880
2881 DEFUN (no_match_ip_address, 
2882        no_match_ip_address_cmd,
2883        "no match ip address",
2884        NO_STR
2885        MATCH_STR
2886        IP_STR
2887        "Match address of route\n")
2888 {
2889   if (argc == 0)
2890     return bgp_route_match_delete (vty, vty->index, "ip address", NULL);
2891
2892   return bgp_route_match_delete (vty, vty->index, "ip address", argv[0]);
2893 }
2894
2895 ALIAS (no_match_ip_address, 
2896        no_match_ip_address_val_cmd,
2897        "no match ip address (<1-199>|<1300-2699>|WORD)",
2898        NO_STR
2899        MATCH_STR
2900        IP_STR
2901        "Match address of route\n"
2902        "IP access-list number\n"
2903        "IP access-list number (expanded range)\n"
2904        "IP Access-list name\n")
2905
2906 DEFUN (match_ip_next_hop, 
2907        match_ip_next_hop_cmd,
2908        "match ip next-hop (<1-199>|<1300-2699>|WORD)",
2909        MATCH_STR
2910        IP_STR
2911        "Match next-hop address of route\n"
2912        "IP access-list number\n"
2913        "IP access-list number (expanded range)\n"
2914        "IP Access-list name\n")
2915 {
2916   return bgp_route_match_add (vty, vty->index, "ip next-hop", argv[0]);
2917 }
2918
2919 DEFUN (no_match_ip_next_hop,
2920        no_match_ip_next_hop_cmd,
2921        "no match ip next-hop",
2922        NO_STR
2923        MATCH_STR
2924        IP_STR
2925        "Match next-hop address of route\n")
2926 {
2927   if (argc == 0)
2928     return bgp_route_match_delete (vty, vty->index, "ip next-hop", NULL);
2929
2930   return bgp_route_match_delete (vty, vty->index, "ip next-hop", argv[0]);
2931 }
2932
2933 ALIAS (no_match_ip_next_hop,
2934        no_match_ip_next_hop_val_cmd,
2935        "no match ip next-hop (<1-199>|<1300-2699>|WORD)",
2936        NO_STR
2937        MATCH_STR
2938        IP_STR
2939        "Match next-hop address of route\n"
2940        "IP access-list number\n"
2941        "IP access-list number (expanded range)\n"
2942        "IP Access-list name\n")
2943
2944 /* match probability { */
2945
2946 DEFUN (match_probability,
2947        match_probability_cmd,
2948        "match probability <0-100>",
2949        MATCH_STR
2950        "Match portion of routes defined by percentage value\n"
2951        "Percentage of routes\n")
2952 {
2953   return bgp_route_match_add (vty, vty->index, "probability", argv[0]);
2954 }
2955
2956 DEFUN (no_match_probability,
2957        no_match_probability_cmd,
2958        "no match probability",
2959        NO_STR
2960        MATCH_STR
2961        "Match portion of routes defined by percentage value\n")
2962 {
2963   return bgp_route_match_delete (vty, vty->index, "probability", argc ? argv[0] : NULL);
2964 }
2965
2966 ALIAS (no_match_probability,
2967        no_match_probability_val_cmd,
2968        "no match probability <1-99>",
2969        NO_STR
2970        MATCH_STR
2971        "Match portion of routes defined by percentage value\n"
2972        "Percentage of routes\n")
2973
2974 /* } */
2975
2976 DEFUN (match_ip_route_source, 
2977        match_ip_route_source_cmd,
2978        "match ip route-source (<1-199>|<1300-2699>|WORD)",
2979        MATCH_STR
2980        IP_STR
2981        "Match advertising source address of route\n"
2982        "IP access-list number\n"
2983        "IP access-list number (expanded range)\n"
2984        "IP standard access-list name\n")
2985 {
2986   return bgp_route_match_add (vty, vty->index, "ip route-source", argv[0]);
2987 }
2988
2989 DEFUN (no_match_ip_route_source,
2990        no_match_ip_route_source_cmd,
2991        "no match ip route-source",
2992        NO_STR
2993        MATCH_STR
2994        IP_STR
2995        "Match advertising source address of route\n")
2996 {
2997   if (argc == 0)
2998     return bgp_route_match_delete (vty, vty->index, "ip route-source", NULL);
2999
3000   return bgp_route_match_delete (vty, vty->index, "ip route-source", argv[0]);
3001 }
3002
3003 ALIAS (no_match_ip_route_source,
3004        no_match_ip_route_source_val_cmd,
3005        "no match ip route-source (<1-199>|<1300-2699>|WORD)",
3006        NO_STR
3007        MATCH_STR
3008        IP_STR
3009        "Match advertising source address of route\n"
3010        "IP access-list number\n"
3011        "IP access-list number (expanded range)\n"
3012        "IP standard access-list name\n")
3013
3014 DEFUN (match_ip_address_prefix_list, 
3015        match_ip_address_prefix_list_cmd,
3016        "match ip address prefix-list WORD",
3017        MATCH_STR
3018        IP_STR
3019        "Match address of route\n"
3020        "Match entries of prefix-lists\n"
3021        "IP prefix-list name\n")
3022 {
3023   return bgp_route_match_add (vty, vty->index, "ip address prefix-list", argv[0]);
3024 }
3025
3026 DEFUN (no_match_ip_address_prefix_list,
3027        no_match_ip_address_prefix_list_cmd,
3028        "no match ip address prefix-list",
3029        NO_STR
3030        MATCH_STR
3031        IP_STR
3032        "Match address of route\n"
3033        "Match entries of prefix-lists\n")
3034 {
3035   if (argc == 0)
3036     return bgp_route_match_delete (vty, vty->index, "ip address prefix-list", NULL);
3037
3038   return bgp_route_match_delete (vty, vty->index, "ip address prefix-list", argv[0]);
3039 }
3040
3041 ALIAS (no_match_ip_address_prefix_list,
3042        no_match_ip_address_prefix_list_val_cmd,
3043        "no match ip address prefix-list WORD",
3044        NO_STR
3045        MATCH_STR
3046        IP_STR
3047        "Match address of route\n"
3048        "Match entries of prefix-lists\n"
3049        "IP prefix-list name\n")
3050
3051 DEFUN (match_ip_next_hop_prefix_list, 
3052        match_ip_next_hop_prefix_list_cmd,
3053        "match ip next-hop prefix-list WORD",
3054        MATCH_STR
3055        IP_STR
3056        "Match next-hop address of route\n"
3057        "Match entries of prefix-lists\n"
3058        "IP prefix-list name\n")
3059 {
3060   return bgp_route_match_add (vty, vty->index, "ip next-hop prefix-list", argv[0]);
3061 }
3062
3063 DEFUN (no_match_ip_next_hop_prefix_list,
3064        no_match_ip_next_hop_prefix_list_cmd,
3065        "no match ip next-hop prefix-list",
3066        NO_STR
3067        MATCH_STR
3068        IP_STR
3069        "Match next-hop address of route\n"
3070        "Match entries of prefix-lists\n")
3071 {
3072   if (argc == 0)
3073     return bgp_route_match_delete (vty, vty->index, "ip next-hop prefix-list", NULL);
3074
3075   return bgp_route_match_delete (vty, vty->index, "ip next-hop prefix-list", argv[0]);
3076 }
3077
3078 ALIAS (no_match_ip_next_hop_prefix_list,
3079        no_match_ip_next_hop_prefix_list_val_cmd,
3080        "no match ip next-hop prefix-list WORD",
3081        NO_STR
3082        MATCH_STR
3083        IP_STR
3084        "Match next-hop address of route\n"
3085        "Match entries of prefix-lists\n"
3086        "IP prefix-list name\n")
3087
3088 DEFUN (match_ip_route_source_prefix_list, 
3089        match_ip_route_source_prefix_list_cmd,
3090        "match ip route-source prefix-list WORD",
3091        MATCH_STR
3092        IP_STR
3093        "Match advertising source address of route\n"
3094        "Match entries of prefix-lists\n"
3095        "IP prefix-list name\n")
3096 {
3097   return bgp_route_match_add (vty, vty->index, "ip route-source prefix-list", argv[0]);
3098 }
3099
3100 DEFUN (no_match_ip_route_source_prefix_list,
3101        no_match_ip_route_source_prefix_list_cmd,
3102        "no match ip route-source prefix-list",
3103        NO_STR
3104        MATCH_STR
3105        IP_STR
3106        "Match advertising source address of route\n"
3107        "Match entries of prefix-lists\n")
3108 {
3109   if (argc == 0)
3110     return bgp_route_match_delete (vty, vty->index, "ip route-source prefix-list", NULL);
3111
3112   return bgp_route_match_delete (vty, vty->index, "ip route-source prefix-list", argv[0]);
3113 }
3114
3115 ALIAS (no_match_ip_route_source_prefix_list,
3116        no_match_ip_route_source_prefix_list_val_cmd,
3117        "no match ip route-source prefix-list WORD",
3118        NO_STR
3119        MATCH_STR
3120        IP_STR
3121        "Match advertising source address of route\n"
3122        "Match entries of prefix-lists\n"
3123        "IP prefix-list name\n")
3124
3125 DEFUN (match_metric, 
3126        match_metric_cmd,
3127        "match metric <0-4294967295>",
3128        MATCH_STR
3129        "Match metric of route\n"
3130        "Metric value\n")
3131 {
3132   return bgp_route_match_add (vty, vty->index, "metric", argv[0]);
3133 }
3134
3135 DEFUN (no_match_metric,
3136        no_match_metric_cmd,
3137        "no match metric",
3138        NO_STR
3139        MATCH_STR
3140        "Match metric of route\n")
3141 {
3142   if (argc == 0)
3143     return bgp_route_match_delete (vty, vty->index, "metric", NULL);
3144
3145   return bgp_route_match_delete (vty, vty->index, "metric", argv[0]);
3146 }
3147
3148 ALIAS (no_match_metric,
3149        no_match_metric_val_cmd,
3150        "no match metric <0-4294967295>",
3151        NO_STR
3152        MATCH_STR
3153        "Match metric of route\n"
3154        "Metric value\n")
3155
3156 DEFUN (match_local_pref,
3157        match_local_pref_cmd,
3158        "match local-preference <0-4294967295>",
3159        MATCH_STR
3160        "Match local-preference of route\n"
3161        "Metric value\n")
3162 {
3163   return bgp_route_match_add (vty, vty->index, "local-preference", argv[0]);
3164 }
3165
3166 DEFUN (no_match_local_pref,
3167        no_match_local_pref_cmd,
3168        "no match local-preference",
3169        NO_STR
3170        MATCH_STR
3171        "Match local preference of route\n")
3172 {
3173   if (argc == 0)
3174     return bgp_route_match_delete (vty, vty->index, "local-preference", NULL);
3175
3176   return bgp_route_match_delete (vty, vty->index, "local-preference", argv[0]);
3177 }
3178
3179 ALIAS (no_match_local_pref,
3180        no_match_local_pref_val_cmd,
3181        "no match local-preference <0-4294967295>",
3182        NO_STR
3183        MATCH_STR
3184        "Match local preference of route\n"
3185        "Local preference value\n")
3186
3187 DEFUN (match_community, 
3188        match_community_cmd,
3189        "match community (<1-99>|<100-500>|WORD)",
3190        MATCH_STR
3191        "Match BGP community list\n"
3192        "Community-list number (standard)\n"
3193        "Community-list number (expanded)\n"
3194        "Community-list name\n")
3195 {
3196   return bgp_route_match_add (vty, vty->index, "community", argv[0]);
3197 }
3198
3199 DEFUN (match_community_exact, 
3200        match_community_exact_cmd,
3201        "match community (<1-99>|<100-500>|WORD) exact-match",
3202        MATCH_STR
3203        "Match BGP community list\n"
3204        "Community-list number (standard)\n"
3205        "Community-list number (expanded)\n"
3206        "Community-list name\n"
3207        "Do exact matching of communities\n")
3208 {
3209   int ret;
3210   char *argstr;
3211
3212   argstr = XMALLOC (MTYPE_ROUTE_MAP_COMPILED,
3213                     strlen (argv[0]) + strlen ("exact-match") + 2);
3214
3215   sprintf (argstr, "%s exact-match", argv[0]);
3216
3217   ret = bgp_route_match_add (vty, vty->index, "community", argstr);
3218
3219   XFREE (MTYPE_ROUTE_MAP_COMPILED, argstr);
3220
3221   return ret;
3222 }
3223
3224 DEFUN (no_match_community,
3225        no_match_community_cmd,
3226        "no match community",
3227        NO_STR
3228        MATCH_STR
3229        "Match BGP community list\n")
3230 {
3231   return bgp_route_match_delete (vty, vty->index, "community", NULL);
3232 }
3233
3234 ALIAS (no_match_community,
3235        no_match_community_val_cmd,
3236        "no match community (<1-99>|<100-500>|WORD)",
3237        NO_STR
3238        MATCH_STR
3239        "Match BGP community list\n"
3240        "Community-list number (standard)\n"
3241        "Community-list number (expanded)\n"
3242        "Community-list name\n")
3243
3244 ALIAS (no_match_community,
3245        no_match_community_exact_cmd,
3246        "no match community (<1-99>|<100-500>|WORD) exact-match",
3247        NO_STR
3248        MATCH_STR
3249        "Match BGP community list\n"
3250        "Community-list number (standard)\n"
3251        "Community-list number (expanded)\n"
3252        "Community-list name\n"
3253        "Do exact matching of communities\n")
3254
3255 DEFUN (match_lcommunity,
3256        match_lcommunity_cmd,
3257        "match large-community (<1-99>|<100-500>|WORD)",
3258        MATCH_STR
3259        "Match BGP large community list\n"
3260        "Large Community-list number (standard)\n"
3261        "Large Community-list number (expanded)\n"
3262        "Large Community-list name\n")
3263 {
3264   return bgp_route_match_add (vty, vty->index, "large-community", argv[0]);
3265 }
3266
3267 DEFUN (no_match_lcommunity,
3268        no_match_lcommunity_cmd,
3269        "no match large-community (<1-99>|<100-500>|WORD)",
3270        NO_STR
3271        MATCH_STR
3272        "Match BGP large community list\n"
3273        "Large Community-list number (standard)\n"
3274        "Large Community-list number (expanded)\n"
3275        "Large Community-list name\n")
3276 {
3277   return bgp_route_match_delete (vty, vty->index, "large-community", NULL);
3278 }
3279
3280
3281 DEFUN (match_ecommunity, 
3282        match_ecommunity_cmd,
3283        "match extcommunity (<1-99>|<100-500>|WORD)",
3284        MATCH_STR
3285        "Match BGP/VPN extended community list\n"
3286        "Extended community-list number (standard)\n"
3287        "Extended community-list number (expanded)\n"
3288        "Extended community-list name\n")
3289 {
3290   return bgp_route_match_add (vty, vty->index, "extcommunity", argv[0]);
3291 }
3292
3293 DEFUN (no_match_ecommunity,
3294        no_match_ecommunity_cmd,
3295        "no match extcommunity",
3296        NO_STR
3297        MATCH_STR
3298        "Match BGP/VPN extended community list\n")
3299 {
3300   return bgp_route_match_delete (vty, vty->index, "extcommunity", NULL);
3301 }
3302
3303 ALIAS (no_match_ecommunity,
3304        no_match_ecommunity_val_cmd,
3305        "no match extcommunity (<1-99>|<100-500>|WORD)",
3306        NO_STR
3307        MATCH_STR
3308        "Match BGP/VPN extended community list\n"
3309        "Extended community-list number (standard)\n"
3310        "Extended community-list number (expanded)\n"
3311        "Extended community-list name\n")
3312
3313 DEFUN (match_aspath,
3314        match_aspath_cmd,
3315        "match as-path WORD",
3316        MATCH_STR
3317        "Match BGP AS path list\n"
3318        "AS path access-list name\n")
3319 {
3320   return bgp_route_match_add (vty, vty->index, "as-path", argv[0]);
3321 }
3322
3323 DEFUN (no_match_aspath,
3324        no_match_aspath_cmd,
3325        "no match as-path",
3326        NO_STR
3327        MATCH_STR
3328        "Match BGP AS path list\n")
3329 {
3330   return bgp_route_match_delete (vty, vty->index, "as-path", NULL);
3331 }
3332
3333 ALIAS (no_match_aspath,
3334        no_match_aspath_val_cmd,
3335        "no match as-path WORD",
3336        NO_STR
3337        MATCH_STR
3338        "Match BGP AS path list\n"
3339        "AS path access-list name\n")
3340
3341 DEFUN (match_origin,
3342        match_origin_cmd,
3343        "match origin (egp|igp|incomplete)",
3344        MATCH_STR
3345        "BGP origin code\n"
3346        "remote EGP\n"
3347        "local IGP\n"
3348        "unknown heritage\n")
3349 {
3350   if (strncmp (argv[0], "igp", 2) == 0)
3351     return bgp_route_match_add (vty, vty->index, "origin", "igp");
3352   if (strncmp (argv[0], "egp", 1) == 0)
3353     return bgp_route_match_add (vty, vty->index, "origin", "egp");
3354   if (strncmp (argv[0], "incomplete", 2) == 0)
3355     return bgp_route_match_add (vty, vty->index, "origin", "incomplete");
3356
3357   return CMD_WARNING;
3358 }
3359
3360 DEFUN (no_match_origin,
3361        no_match_origin_cmd,
3362        "no match origin",
3363        NO_STR
3364        MATCH_STR
3365        "BGP origin code\n")
3366 {
3367   return bgp_route_match_delete (vty, vty->index, "origin", NULL);
3368 }
3369
3370 ALIAS (no_match_origin,
3371        no_match_origin_val_cmd,
3372        "no match origin (egp|igp|incomplete)",
3373        NO_STR
3374        MATCH_STR
3375        "BGP origin code\n"
3376        "remote EGP\n"
3377        "local IGP\n"
3378        "unknown heritage\n")
3379
3380 DEFUN (match_tag,
3381        match_tag_cmd,
3382        "match tag <1-4294967295>",
3383        MATCH_STR
3384        "Match tag of route\n"
3385        "Tag value\n")
3386 {
3387   return bgp_route_match_add (vty, vty->index, "tag", argv[0]);
3388 }
3389
3390 DEFUN (no_match_tag,
3391        no_match_tag_cmd,
3392        "no match tag",
3393        NO_STR
3394        MATCH_STR
3395        "Match tag of route\n")
3396 {
3397   if (argc == 0)
3398     return bgp_route_match_delete (vty, vty->index, "tag", NULL);
3399
3400   return bgp_route_match_delete (vty, vty->index, "tag", argv[0]);
3401 }
3402
3403 ALIAS (no_match_tag,
3404        no_match_tag_val_cmd,
3405        "no match tag <1-4294967295>",
3406        NO_STR
3407        MATCH_STR
3408        "Match tag of route\n"
3409        "Tag value\n")
3410
3411 DEFUN (set_ip_nexthop,
3412        set_ip_nexthop_cmd,
3413        "set ip next-hop A.B.C.D",
3414        SET_STR
3415        IP_STR
3416        "Next hop address\n"
3417        "IP address of next hop\n")
3418 {
3419   union sockunion su;
3420   int ret;
3421
3422   ret = str2sockunion (argv[0], &su);
3423   if (ret < 0)
3424     {
3425       vty_out (vty, "%% Malformed Next-hop address%s", VTY_NEWLINE);
3426       return CMD_WARNING;
3427     }
3428  
3429   return bgp_route_set_add (vty, vty->index, "ip next-hop", argv[0]);
3430 }
3431
3432 DEFUN (set_ip_nexthop_peer,
3433        set_ip_nexthop_peer_cmd,
3434        "set ip next-hop peer-address",
3435        SET_STR
3436        IP_STR
3437        "Next hop address\n"
3438        "Use peer address (for BGP only)\n")
3439 {
3440   return bgp_route_set_add (vty, vty->index, "ip next-hop", "peer-address");
3441 }
3442
3443 DEFUN_DEPRECATED (no_set_ip_nexthop_peer,
3444        no_set_ip_nexthop_peer_cmd,
3445        "no set ip next-hop peer-address",
3446        NO_STR
3447        SET_STR
3448        IP_STR
3449        "Next hop address\n"
3450        "Use peer address (for BGP only)\n")
3451 {
3452   return bgp_route_set_delete (vty, vty->index, "ip next-hop", NULL);
3453 }
3454
3455
3456 DEFUN (no_set_ip_nexthop,
3457        no_set_ip_nexthop_cmd,
3458        "no set ip next-hop",
3459        NO_STR
3460        SET_STR
3461        "Next hop address\n")
3462 {
3463   if (argc == 0)
3464     return bgp_route_set_delete (vty, vty->index, "ip next-hop", NULL);
3465
3466   return bgp_route_set_delete (vty, vty->index, "ip next-hop", argv[0]);
3467 }
3468
3469 ALIAS (no_set_ip_nexthop,
3470        no_set_ip_nexthop_val_cmd,
3471        "no set ip next-hop A.B.C.D",
3472        NO_STR
3473        SET_STR
3474        IP_STR
3475        "Next hop address\n"
3476        "IP address of next hop\n")
3477
3478 DEFUN (set_metric,
3479        set_metric_cmd,
3480        "set metric <0-4294967295>",
3481        SET_STR
3482        "Metric value for destination routing protocol\n"
3483        "Metric value\n")
3484 {
3485   return bgp_route_set_add (vty, vty->index, "metric", argv[0]);
3486 }
3487
3488 ALIAS (set_metric,
3489        set_metric_addsub_cmd,
3490        "set metric <+/-metric>",
3491        SET_STR
3492        "Metric value for destination routing protocol\n"
3493        "Add or subtract metric\n")
3494
3495 ALIAS (set_metric,
3496        set_metric_rtt_cmd,
3497        "set metric (rtt|+rtt|-rtt)",
3498        SET_STR
3499        "Metric value for destination routing protocol\n"
3500        "Assign round trip time\n"
3501        "Add round trip time\n"
3502        "Subtract round trip time\n")
3503
3504 DEFUN (no_set_metric,
3505        no_set_metric_cmd,
3506        "no set metric",
3507        NO_STR
3508        SET_STR
3509        "Metric value for destination routing protocol\n")
3510 {
3511   if (argc == 0)
3512     return bgp_route_set_delete (vty, vty->index, "metric", NULL);
3513
3514   return bgp_route_set_delete (vty, vty->index, "metric", argv[0]);
3515 }
3516
3517 ALIAS (no_set_metric,
3518        no_set_metric_val_cmd,
3519        "no set metric <0-4294967295>",
3520        NO_STR
3521        SET_STR
3522        "Metric value for destination routing protocol\n"
3523        "Metric value\n")
3524
3525 DEFUN (set_local_pref,
3526        set_local_pref_cmd,
3527        "set local-preference <0-4294967295>",
3528        SET_STR
3529        "BGP local preference path attribute\n"
3530        "Preference value\n")
3531 {
3532   return bgp_route_set_add (vty, vty->index, "local-preference", argv[0]);
3533 }
3534
3535 DEFUN (no_set_local_pref,
3536        no_set_local_pref_cmd,
3537        "no set local-preference",
3538        NO_STR
3539        SET_STR
3540        "BGP local preference path attribute\n")
3541 {
3542   if (argc == 0)
3543     return bgp_route_set_delete (vty, vty->index, "local-preference", NULL);
3544
3545   return bgp_route_set_delete (vty, vty->index, "local-preference", argv[0]);
3546 }
3547
3548 ALIAS (no_set_local_pref,
3549        no_set_local_pref_val_cmd,
3550        "no set local-preference <0-4294967295>",
3551        NO_STR
3552        SET_STR
3553        "BGP local preference path attribute\n"
3554        "Preference value\n")
3555
3556 DEFUN (set_weight,
3557        set_weight_cmd,
3558        "set weight <0-4294967295>",
3559        SET_STR
3560        "BGP weight for routing table\n"
3561        "Weight value\n")
3562 {
3563   return bgp_route_set_add (vty, vty->index, "weight", argv[0]);
3564 }
3565
3566 DEFUN (no_set_weight,
3567        no_set_weight_cmd,
3568        "no set weight",
3569        NO_STR
3570        SET_STR
3571        "BGP weight for routing table\n")
3572 {
3573   if (argc == 0)
3574     return bgp_route_set_delete (vty, vty->index, "weight", NULL);
3575   
3576   return bgp_route_set_delete (vty, vty->index, "weight", argv[0]);
3577 }
3578
3579 ALIAS (no_set_weight,
3580        no_set_weight_val_cmd,
3581        "no set weight <0-4294967295>",
3582        NO_STR
3583        SET_STR
3584        "BGP weight for routing table\n"
3585        "Weight value\n")
3586
3587 DEFUN (set_aspath_prepend,
3588        set_aspath_prepend_cmd,
3589        "set as-path prepend ." CMD_AS_RANGE,
3590        SET_STR
3591        "Transform BGP AS_PATH attribute\n"
3592        "Prepend to the as-path\n"
3593        "AS number\n")
3594 {
3595   int ret;
3596   char *str;
3597
3598   str = argv_concat (argv, argc, 0);
3599   ret = bgp_route_set_add (vty, vty->index, "as-path prepend", str);
3600   XFREE (MTYPE_TMP, str);
3601
3602   return ret;
3603 }
3604
3605 ALIAS (set_aspath_prepend,
3606        set_aspath_prepend_lastas_cmd,
3607        "set as-path prepend (last-as) <1-10>",
3608        SET_STR
3609        "Transform BGP AS_PATH attribute\n"
3610        "Prepend to the as-path\n"
3611        "Use the peer's AS-number\n"
3612        "Number of times to insert")
3613
3614 DEFUN (no_set_aspath_prepend,
3615        no_set_aspath_prepend_cmd,
3616        "no set as-path prepend",
3617        NO_STR
3618        SET_STR
3619        "Transform BGP AS_PATH attribute\n"
3620        "Prepend to the as-path\n")
3621 {
3622   int ret;
3623   char *str;
3624
3625   if (argc == 0)
3626     return bgp_route_set_delete (vty, vty->index, "as-path prepend", NULL);
3627
3628   str = argv_concat (argv, argc, 0);
3629   ret = bgp_route_set_delete (vty, vty->index, "as-path prepend", str);
3630   XFREE (MTYPE_TMP, str);
3631   return ret;
3632 }
3633
3634 ALIAS (no_set_aspath_prepend,
3635        no_set_aspath_prepend_val_cmd,
3636        "no set as-path prepend ." CMD_AS_RANGE,
3637        NO_STR
3638        SET_STR
3639        "Transform BGP AS_PATH attribute\n"
3640        "Prepend to the as-path\n"
3641        "AS number\n")
3642
3643 DEFUN (set_aspath_exclude,
3644        set_aspath_exclude_cmd,
3645        "set as-path exclude ." CMD_AS_RANGE,
3646        SET_STR
3647        "Transform BGP AS-path attribute\n"
3648        "Exclude from the as-path\n"
3649        "AS number\n")
3650 {
3651   int ret;
3652   char *str;
3653
3654   str = argv_concat (argv, argc, 0);
3655   ret = bgp_route_set_add (vty, vty->index, "as-path exclude", str);
3656   XFREE (MTYPE_TMP, str);
3657   return ret;
3658 }
3659
3660 DEFUN (no_set_aspath_exclude,
3661        no_set_aspath_exclude_cmd,
3662        "no set as-path exclude",
3663        NO_STR
3664        SET_STR
3665        "Transform BGP AS_PATH attribute\n"
3666        "Exclude from the as-path\n")
3667 {
3668   int ret;
3669   char *str;
3670
3671   if (argc == 0)
3672     return bgp_route_set_delete (vty, vty->index, "as-path exclude", NULL);
3673
3674   str = argv_concat (argv, argc, 0);
3675   ret = bgp_route_set_delete (vty, vty->index, "as-path exclude", str);
3676   XFREE (MTYPE_TMP, str);
3677   return ret;
3678 }
3679
3680 ALIAS (no_set_aspath_exclude,
3681        no_set_aspath_exclude_val_cmd,
3682        "no set as-path exclude ." CMD_AS_RANGE,
3683        NO_STR
3684        SET_STR
3685        "Transform BGP AS_PATH attribute\n"
3686        "Exclude from the as-path\n"
3687        "AS number\n")
3688
3689 DEFUN (set_community,
3690        set_community_cmd,
3691        "set community .AA:NN",
3692        SET_STR
3693        "BGP community attribute\n"
3694        "Community number in aa:nn format or local-AS|no-advertise|no-export|internet or additive\n")
3695 {
3696   int i;
3697   int first = 0;
3698   int additive = 0;
3699   struct buffer *b;
3700   struct community *com = NULL;
3701   char *str;
3702   char *argstr;
3703   int ret;
3704
3705   b = buffer_new (1024);
3706
3707   for (i = 0; i < argc; i++)
3708     {
3709       if (strncmp (argv[i], "additive", strlen (argv[i])) == 0)
3710         {
3711           additive = 1;
3712           continue;
3713         }
3714
3715       if (first)
3716         buffer_putc (b, ' ');
3717       else
3718         first = 1;
3719
3720       if (strncmp (argv[i], "internet", strlen (argv[i])) == 0)
3721         {
3722           buffer_putstr (b, "internet");
3723           continue;
3724         }
3725       if (strncmp (argv[i], "local-AS", strlen (argv[i])) == 0)
3726         {
3727           buffer_putstr (b, "local-AS");
3728           continue;
3729         }
3730       if (strncmp (argv[i], "no-a", strlen ("no-a")) == 0
3731           && strncmp (argv[i], "no-advertise", strlen (argv[i])) == 0)
3732         {
3733           buffer_putstr (b, "no-advertise");
3734           continue;
3735         }
3736       if (strncmp (argv[i], "no-e", strlen ("no-e"))== 0
3737           && strncmp (argv[i], "no-export", strlen (argv[i])) == 0)
3738         {
3739           buffer_putstr (b, "no-export");
3740           continue;
3741         }
3742       buffer_putstr (b, argv[i]);
3743     }
3744   buffer_putc (b, '\0');
3745
3746   /* Fetch result string then compile it to communities attribute.  */
3747   str = buffer_getstr (b);
3748   buffer_free (b);
3749
3750   if (str)
3751     {
3752       com = community_str2com (str);
3753       XFREE (MTYPE_TMP, str);
3754     }
3755
3756   /* Can't compile user input into communities attribute.  */
3757   if (! com)
3758     {
3759       vty_out (vty, "%% Malformed communities attribute%s", VTY_NEWLINE);
3760       return CMD_WARNING;
3761     }
3762
3763   /* Set communites attribute string.  */
3764   str = community_str (com);
3765
3766   if (additive)
3767     {
3768       argstr = XCALLOC (MTYPE_TMP, strlen (str) + strlen (" additive") + 1);
3769       strcpy (argstr, str);
3770       strcpy (argstr + strlen (str), " additive");
3771       ret =  bgp_route_set_add (vty, vty->index, "community", argstr);
3772       XFREE (MTYPE_TMP, argstr);
3773     }
3774   else
3775     ret =  bgp_route_set_add (vty, vty->index, "community", str);
3776
3777   community_free (com);
3778
3779   return ret;
3780 }
3781
3782 DEFUN (set_community_none,
3783        set_community_none_cmd,
3784        "set community none",
3785        SET_STR
3786        "BGP community attribute\n"
3787        "No community attribute\n")
3788 {
3789   return bgp_route_set_add (vty, vty->index, "community", "none");
3790 }
3791
3792 DEFUN (no_set_community,
3793        no_set_community_cmd,
3794        "no set community",
3795        NO_STR
3796        SET_STR
3797        "BGP community attribute\n")
3798 {
3799   return bgp_route_set_delete (vty, vty->index, "community", NULL);
3800 }
3801
3802 ALIAS (no_set_community,
3803        no_set_community_val_cmd,
3804        "no set community .AA:NN",
3805        NO_STR
3806        SET_STR
3807        "BGP community attribute\n"
3808        "Community number in aa:nn format or local-AS|no-advertise|no-export|internet or additive\n")
3809
3810 ALIAS (no_set_community,
3811        no_set_community_none_cmd,
3812        "no set community none",
3813        NO_STR
3814        SET_STR
3815        "BGP community attribute\n"
3816        "No community attribute\n")
3817
3818 DEFUN (set_community_delete,
3819        set_community_delete_cmd,
3820        "set comm-list (<1-99>|<100-500>|WORD) delete",
3821        SET_STR
3822        "set BGP community list (for deletion)\n"
3823        "Community-list number (standard)\n"
3824        "Community-list number (expanded)\n"
3825        "Community-list name\n"
3826        "Delete matching communities\n")
3827 {
3828   char *str;
3829
3830   str = XCALLOC (MTYPE_TMP, strlen (argv[0]) + strlen (" delete") + 1);
3831   strcpy (str, argv[0]);
3832   strcpy (str + strlen (argv[0]), " delete");
3833
3834   bgp_route_set_add (vty, vty->index, "comm-list", str);
3835
3836   XFREE (MTYPE_TMP, str);
3837   return CMD_SUCCESS;
3838 }
3839
3840 DEFUN (no_set_community_delete,
3841        no_set_community_delete_cmd,
3842        "no set comm-list",
3843        NO_STR
3844        SET_STR
3845        "set BGP community list (for deletion)\n")
3846 {
3847   return bgp_route_set_delete (vty, vty->index, "comm-list", NULL);
3848 }
3849
3850 ALIAS (no_set_community_delete,
3851        no_set_community_delete_val_cmd,
3852        "no set comm-list (<1-99>|<100-500>|WORD) delete",
3853        NO_STR
3854        SET_STR
3855        "set BGP community list (for deletion)\n"
3856        "Community-list number (standard)\n"
3857        "Community-list number (expanded)\n"
3858        "Community-list name\n"
3859        "Delete matching communities\n")
3860
3861
3862 DEFUN (set_lcommunity,
3863        set_lcommunity_cmd,
3864        "set large-community .AA:BB:CC",
3865        SET_STR
3866        "BGP large community attribute\n"
3867        "Large Community number in aa:bb:cc format or additive\n")
3868 {
3869   int ret;
3870   char *str;
3871
3872   str = argv_concat (argv, argc, 0);
3873   ret = bgp_route_set_add (vty, vty->index, "large-community", str);
3874   XFREE (MTYPE_TMP, str);
3875
3876   return ret;
3877 }
3878
3879 DEFUN (set_lcommunity_none,
3880        set_lcommunity_none_cmd,
3881        "set large-community none",
3882        SET_STR
3883        "BGP large community attribute\n"
3884        "No large community attribute\n")
3885 {
3886   return bgp_route_set_add (vty, vty->index, "large-community", "none");
3887 }
3888
3889 DEFUN (no_set_lcommunity,
3890        no_set_lcommunity_cmd,
3891        "no set large-community",
3892        NO_STR
3893        SET_STR
3894        "BGP large community attribute\n"
3895        "Large community\n")
3896 {
3897   return bgp_route_set_delete (vty, vty->index, "large-community", NULL);
3898 }
3899
3900 ALIAS (no_set_lcommunity,
3901        no_set_lcommunity_val_cmd,
3902        "no set large-community .AA:BB:CC",
3903        NO_STR
3904        SET_STR
3905        "BGP large community attribute\n"
3906        "Large community in .AA:BB:CC format or additive\n")
3907
3908 ALIAS (no_set_lcommunity,
3909        no_set_lcommunity_none_cmd,
3910        "no set large-community none",
3911        NO_STR
3912        SET_STR
3913        "BGP community attribute\n"
3914        "No community attribute\n")
3915
3916 DEFUN (set_lcommunity_delete,
3917        set_lcommunity_delete_cmd,
3918        "set large-comm-list (<1-99>|<100-500>|WORD) delete",
3919        SET_STR
3920        "set BGP large community list (for deletion)\n"
3921        "Large Community-list number (standard)\n"
3922        "Large Communitly-list number (expanded)\n"
3923        "Large Community-list name\n"
3924        "Delete matching large communities\n")
3925 {
3926   char *str;
3927
3928   str = XCALLOC (MTYPE_TMP, strlen (argv[0]) + strlen (" delete") + 1);
3929   strcpy (str, argv[0]);
3930   strcpy (str + strlen (argv[0]), " delete");
3931
3932   bgp_route_set_add (vty, vty->index, "large-comm-list", str);
3933
3934   XFREE (MTYPE_TMP, str);
3935   return CMD_SUCCESS;
3936 }
3937
3938 DEFUN (no_set_lcommunity_delete,
3939        no_set_lcommunity_delete_cmd,
3940        "no set large-comm-list",
3941        NO_STR
3942        SET_STR
3943        "set BGP large community list (for deletion)\n")
3944 {
3945   return bgp_route_set_delete (vty, vty->index, "large-comm-list", NULL);
3946 }
3947
3948 ALIAS (no_set_lcommunity_delete,
3949        no_set_lcommunity_delete_val_cmd,
3950        "no set large-comm-list (<1-99>|<100-500>|WORD) delete",
3951        NO_STR
3952        SET_STR
3953        "set BGP large community list (for deletion)\n"
3954        "Large Community-list number (standard)\n"
3955        "Large Communitly-list number (expanded)\n"
3956        "Large Community-list name\n"
3957        "Delete matching large communities\n")
3958
3959 DEFUN (set_ecommunity_rt,
3960        set_ecommunity_rt_cmd,
3961        "set extcommunity rt .ASN:nn_or_IP-address:nn",
3962        SET_STR
3963        "BGP extended community attribute\n"
3964        "Route Target extended community\n"
3965        "VPN extended community\n")
3966 {
3967   int ret;
3968   char *str;
3969
3970   str = argv_concat (argv, argc, 0);
3971   ret = bgp_route_set_add (vty, vty->index, "extcommunity rt", str);
3972   XFREE (MTYPE_TMP, str);
3973
3974   return ret;
3975 }
3976
3977 DEFUN (no_set_ecommunity_rt,
3978        no_set_ecommunity_rt_cmd,
3979        "no set extcommunity rt",
3980        NO_STR
3981        SET_STR
3982        "BGP extended community attribute\n"
3983        "Route Target extended community\n")
3984 {
3985   return bgp_route_set_delete (vty, vty->index, "extcommunity rt", NULL);
3986 }
3987
3988 ALIAS (no_set_ecommunity_rt,
3989        no_set_ecommunity_rt_val_cmd,
3990        "no set extcommunity rt .ASN:nn_or_IP-address:nn",
3991        NO_STR
3992        SET_STR
3993        "BGP extended community attribute\n"
3994        "Route Target extended community\n"
3995        "VPN extended community\n")
3996
3997 DEFUN (set_ecommunity_soo,
3998        set_ecommunity_soo_cmd,
3999        "set extcommunity soo .ASN:nn_or_IP-address:nn",
4000        SET_STR
4001        "BGP extended community attribute\n"
4002        "Site-of-Origin extended community\n"
4003        "VPN extended community\n")
4004 {
4005   int ret;
4006   char *str;
4007
4008   str = argv_concat (argv, argc, 0);
4009   ret = bgp_route_set_add (vty, vty->index, "extcommunity soo", str);
4010   XFREE (MTYPE_TMP, str);
4011   return ret;
4012 }
4013
4014 DEFUN (no_set_ecommunity_soo,
4015        no_set_ecommunity_soo_cmd,
4016        "no set extcommunity soo",
4017        NO_STR
4018        SET_STR
4019        "BGP extended community attribute\n"
4020        "Site-of-Origin extended community\n")
4021 {
4022   return bgp_route_set_delete (vty, vty->index, "extcommunity soo", NULL);
4023 }
4024
4025 ALIAS (no_set_ecommunity_soo,
4026        no_set_ecommunity_soo_val_cmd,
4027        "no set extcommunity soo .ASN:nn_or_IP-address:nn",
4028        NO_STR
4029        SET_STR
4030        "BGP extended community attribute\n"
4031        "Site-of-Origin extended community\n"
4032        "VPN extended community\n")
4033
4034 DEFUN (set_origin,
4035        set_origin_cmd,
4036        "set origin (egp|igp|incomplete)",
4037        SET_STR
4038        "BGP origin code\n"
4039        "remote EGP\n"
4040        "local IGP\n"
4041        "unknown heritage\n")
4042 {
4043   if (strncmp (argv[0], "igp", 2) == 0)
4044     return bgp_route_set_add (vty, vty->index, "origin", "igp");
4045   if (strncmp (argv[0], "egp", 1) == 0)
4046     return bgp_route_set_add (vty, vty->index, "origin", "egp");
4047   if (strncmp (argv[0], "incomplete", 2) == 0)
4048     return bgp_route_set_add (vty, vty->index, "origin", "incomplete");
4049
4050   return CMD_WARNING;
4051 }
4052
4053 DEFUN (no_set_origin,
4054        no_set_origin_cmd,
4055        "no set origin",
4056        NO_STR
4057        SET_STR
4058        "BGP origin code\n")
4059 {
4060   return bgp_route_set_delete (vty, vty->index, "origin", NULL);
4061 }
4062
4063 ALIAS (no_set_origin,
4064        no_set_origin_val_cmd,
4065        "no set origin (egp|igp|incomplete)",
4066        NO_STR
4067        SET_STR
4068        "BGP origin code\n"
4069        "remote EGP\n"
4070        "local IGP\n"
4071        "unknown heritage\n")
4072
4073 DEFUN (set_atomic_aggregate,
4074        set_atomic_aggregate_cmd,
4075        "set atomic-aggregate",
4076        SET_STR
4077        "BGP atomic aggregate attribute\n" )
4078 {
4079   return bgp_route_set_add (vty, vty->index, "atomic-aggregate", NULL);
4080 }
4081
4082 DEFUN (no_set_atomic_aggregate,
4083        no_set_atomic_aggregate_cmd,
4084        "no set atomic-aggregate",
4085        NO_STR
4086        SET_STR
4087        "BGP atomic aggregate attribute\n" )
4088 {
4089   return bgp_route_set_delete (vty, vty->index, "atomic-aggregate", NULL);
4090 }
4091
4092 DEFUN (set_aggregator_as,
4093        set_aggregator_as_cmd,
4094        "set aggregator as " CMD_AS_RANGE " A.B.C.D",
4095        SET_STR
4096        "BGP aggregator attribute\n"
4097        "AS number of aggregator\n"
4098        "AS number\n"
4099        "IP address of aggregator\n")
4100 {
4101   int ret;
4102   as_t as __attribute__((unused)); /* dummy for VTY_GET_INTEGER_RANGE */
4103   struct in_addr address;
4104   char *argstr;
4105
4106   VTY_GET_INTEGER_RANGE ("AS", as, argv[0], 1, BGP_AS4_MAX);
4107   
4108   ret = inet_aton (argv[1], &address);
4109   if (ret == 0)
4110     {
4111       vty_out (vty, "Aggregator IP address is invalid%s", VTY_NEWLINE);
4112       return CMD_WARNING;
4113     }
4114
4115   argstr = XMALLOC (MTYPE_ROUTE_MAP_COMPILED,
4116                     strlen (argv[0]) + strlen (argv[1]) + 2);
4117
4118   sprintf (argstr, "%s %s", argv[0], argv[1]);
4119
4120   ret = bgp_route_set_add (vty, vty->index, "aggregator as", argstr);
4121
4122   XFREE (MTYPE_ROUTE_MAP_COMPILED, argstr);
4123
4124   return ret;
4125 }
4126
4127 DEFUN (no_set_aggregator_as,
4128        no_set_aggregator_as_cmd,
4129        "no set aggregator as",
4130        NO_STR
4131        SET_STR
4132        "BGP aggregator attribute\n"
4133        "AS number of aggregator\n")
4134 {
4135   int ret;
4136   as_t as __attribute__((unused)); /* dummy for VTY_GET_INTEGER_RANGE */
4137   struct in_addr address;
4138   char *argstr;
4139
4140   if (argv == 0)
4141     return bgp_route_set_delete (vty, vty->index, "aggregator as", NULL);
4142   
4143   VTY_GET_INTEGER_RANGE ("AS", as, argv[0], 1, BGP_AS4_MAX);
4144
4145   ret = inet_aton (argv[1], &address);
4146   if (ret == 0)
4147     {
4148       vty_out (vty, "Aggregator IP address is invalid%s", VTY_NEWLINE);
4149       return CMD_WARNING;
4150     }
4151
4152   argstr = XMALLOC (MTYPE_ROUTE_MAP_COMPILED,
4153                     strlen (argv[0]) + strlen (argv[1]) + 2);
4154
4155   sprintf (argstr, "%s %s", argv[0], argv[1]);
4156
4157   ret = bgp_route_set_delete (vty, vty->index, "aggregator as", argstr);
4158
4159   XFREE (MTYPE_ROUTE_MAP_COMPILED, argstr);
4160
4161   return ret;
4162 }
4163
4164 ALIAS (no_set_aggregator_as,
4165        no_set_aggregator_as_val_cmd,
4166        "no set aggregator as " CMD_AS_RANGE " A.B.C.D",
4167        NO_STR
4168        SET_STR
4169        "BGP aggregator attribute\n"
4170        "AS number of aggregator\n"
4171        "AS number\n"
4172        "IP address of aggregator\n")
4173
4174 DEFUN (set_tag,
4175        set_tag_cmd,
4176        "set tag <1-4294967295>",
4177        SET_STR
4178        "Tag value for routing protocol\n"
4179        "Tag value\n")
4180 {
4181   return bgp_route_set_add (vty, vty->index, "tag", argv[0]);
4182 }
4183
4184 DEFUN (no_set_tag,
4185        no_set_tag_cmd,
4186        "no set tag",
4187        NO_STR
4188        SET_STR
4189        "Tag value for routing protocol\n")
4190 {
4191   if (argc == 0)
4192       bgp_route_set_delete(vty, vty->index, "tag", NULL);
4193
4194   return bgp_route_set_delete (vty, vty->index, "tag", argv[0]);
4195 }
4196
4197 ALIAS (no_set_tag,
4198        no_set_tag_val_cmd,
4199        "no set tag <1-4294967295>",
4200        NO_STR
4201        SET_STR
4202        "Tag value for routing protocol\n"
4203        "Tag value\n")
4204
4205
4206 DEFUN (match_ipv6_address, 
4207        match_ipv6_address_cmd,
4208        "match ipv6 address WORD",
4209        MATCH_STR
4210        IPV6_STR
4211        "Match IPv6 address of route\n"
4212        "IPv6 access-list name\n")
4213 {
4214   return bgp_route_match_add (vty, vty->index, "ipv6 address", argv[0]);
4215 }
4216
4217 DEFUN (no_match_ipv6_address, 
4218        no_match_ipv6_address_cmd,
4219        "no match ipv6 address WORD",
4220        NO_STR
4221        MATCH_STR
4222        IPV6_STR
4223        "Match IPv6 address of route\n"
4224        "IPv6 access-list name\n")
4225 {
4226   return bgp_route_match_delete (vty, vty->index, "ipv6 address", argv[0]);
4227 }
4228
4229 DEFUN (match_ipv6_next_hop, 
4230        match_ipv6_next_hop_cmd,
4231        "match ipv6 next-hop X:X::X:X",
4232        MATCH_STR
4233        IPV6_STR
4234        "Match IPv6 next-hop address of route\n"
4235        "IPv6 address of next hop\n")
4236 {
4237   return bgp_route_match_add (vty, vty->index, "ipv6 next-hop", argv[0]);
4238 }
4239
4240 DEFUN (no_match_ipv6_next_hop,
4241        no_match_ipv6_next_hop_cmd,
4242        "no match ipv6 next-hop X:X::X:X",
4243        NO_STR
4244        MATCH_STR
4245        IPV6_STR
4246        "Match IPv6 next-hop address of route\n"
4247        "IPv6 address of next hop\n")
4248 {
4249   return bgp_route_match_delete (vty, vty->index, "ipv6 next-hop", argv[0]);
4250 }
4251
4252 DEFUN (match_ipv6_address_prefix_list, 
4253        match_ipv6_address_prefix_list_cmd,
4254        "match ipv6 address prefix-list WORD",
4255        MATCH_STR
4256        IPV6_STR
4257        "Match address of route\n"
4258        "Match entries of prefix-lists\n"
4259        "IP prefix-list name\n")
4260 {
4261   return bgp_route_match_add (vty, vty->index, "ipv6 address prefix-list", argv[0]);
4262 }
4263
4264 DEFUN (no_match_ipv6_address_prefix_list,
4265        no_match_ipv6_address_prefix_list_cmd,
4266        "no match ipv6 address prefix-list WORD",
4267        NO_STR
4268        MATCH_STR
4269        IPV6_STR
4270        "Match address of route\n"
4271        "Match entries of prefix-lists\n"
4272        "IP prefix-list name\n")
4273 {
4274   return bgp_route_match_delete (vty, vty->index, "ipv6 address prefix-list", argv[0]);
4275 }
4276
4277 DEFUN (set_ipv6_nexthop_peer,
4278        set_ipv6_nexthop_peer_cmd,
4279        "set ipv6 next-hop peer-address",
4280        SET_STR
4281        IPV6_STR
4282        "Next hop address\n"
4283        "Use peer address (for BGP only)\n")
4284 {
4285   return bgp_route_set_add (vty, vty->index, "ipv6 next-hop peer-address", NULL);
4286 }
4287
4288 DEFUN (no_set_ipv6_nexthop_peer,
4289        no_set_ipv6_nexthop_peer_cmd,
4290        "no set ipv6 next-hop peer-address",
4291        NO_STR
4292        SET_STR
4293        IPV6_STR
4294        "IPv6 next-hop address\n"
4295        )
4296 {
4297   return bgp_route_set_delete (vty, vty->index, "ipv6 next-hop", argv[0]);
4298 }
4299
4300 DEFUN (set_ipv6_nexthop_global,
4301        set_ipv6_nexthop_global_cmd,
4302        "set ipv6 next-hop global X:X::X:X",
4303        SET_STR
4304        IPV6_STR
4305        "IPv6 next-hop address\n"
4306        "IPv6 global address\n"
4307        "IPv6 address of next hop\n")
4308 {
4309   return bgp_route_set_add (vty, vty->index, "ipv6 next-hop global", argv[0]);
4310 }
4311
4312 DEFUN (no_set_ipv6_nexthop_global,
4313        no_set_ipv6_nexthop_global_cmd,
4314        "no set ipv6 next-hop global",
4315        NO_STR
4316        SET_STR
4317        IPV6_STR
4318        "IPv6 next-hop address\n"
4319        "IPv6 global address\n")
4320 {
4321   if (argc == 0)
4322     return bgp_route_set_delete (vty, vty->index, "ipv6 next-hop global", NULL);
4323
4324   return bgp_route_set_delete (vty, vty->index, "ipv6 next-hop global", argv[0]);
4325 }
4326
4327 ALIAS (no_set_ipv6_nexthop_global,
4328        no_set_ipv6_nexthop_global_val_cmd,
4329        "no set ipv6 next-hop global X:X::X:X",
4330        NO_STR
4331        SET_STR
4332        IPV6_STR
4333        "IPv6 next-hop address\n"
4334        "IPv6 global address\n"
4335        "IPv6 address of next hop\n")
4336
4337 DEFUN (set_ipv6_nexthop_local,
4338        set_ipv6_nexthop_local_cmd,
4339        "set ipv6 next-hop local X:X::X:X",
4340        SET_STR
4341        IPV6_STR
4342        "IPv6 next-hop address\n"
4343        "IPv6 local address\n"
4344        "IPv6 address of next hop\n")
4345 {
4346   return bgp_route_set_add (vty, vty->index, "ipv6 next-hop local", argv[0]);
4347 }
4348
4349 DEFUN (no_set_ipv6_nexthop_local,
4350        no_set_ipv6_nexthop_local_cmd,
4351        "no set ipv6 next-hop local",
4352        NO_STR
4353        SET_STR
4354        IPV6_STR
4355        "IPv6 next-hop address\n"
4356        "IPv6 local address\n")
4357 {
4358   if (argc == 0)
4359     return bgp_route_set_delete (vty, vty->index, "ipv6 next-hop local", NULL);
4360   
4361   return bgp_route_set_delete (vty, vty->index, "ipv6 next-hop local", argv[0]);
4362 }
4363
4364 ALIAS (no_set_ipv6_nexthop_local,
4365        no_set_ipv6_nexthop_local_val_cmd,
4366        "no set ipv6 next-hop local X:X::X:X",
4367        NO_STR
4368        SET_STR
4369        IPV6_STR
4370        "IPv6 next-hop address\n"
4371        "IPv6 local address\n"
4372        "IPv6 address of next hop\n")
4373
4374 DEFUN (set_vpnv4_nexthop,
4375        set_vpnv4_nexthop_cmd,
4376        "set vpnv4 next-hop A.B.C.D",
4377        SET_STR
4378        "VPNv4 information\n"
4379        "VPNv4 next-hop address\n"
4380        "IP address of next hop\n")
4381 {
4382   return bgp_route_set_add (vty, vty->index, "vpnv4 next-hop", argv[0]);
4383 }
4384
4385 DEFUN (no_set_vpnv4_nexthop,
4386        no_set_vpnv4_nexthop_cmd,
4387        "no set vpnv4 next-hop",
4388        NO_STR
4389        SET_STR
4390        "VPNv4 information\n"
4391        "VPNv4 next-hop address\n")
4392 {
4393   if (argc == 0)
4394     return bgp_route_set_delete (vty, vty->index, "vpnv4 next-hop", NULL);
4395
4396   return bgp_route_set_delete (vty, vty->index, "vpnv4 next-hop", argv[0]);
4397 }
4398
4399 ALIAS (no_set_vpnv4_nexthop,
4400        no_set_vpnv4_nexthop_val_cmd,
4401        "no set vpnv4 next-hop A.B.C.D",
4402        NO_STR
4403        SET_STR
4404        "VPNv4 information\n"
4405        "VPNv4 next-hop address\n"
4406        "IP address of next hop\n")
4407
4408 DEFUN (set_originator_id,
4409        set_originator_id_cmd,
4410        "set originator-id A.B.C.D",
4411        SET_STR
4412        "BGP originator ID attribute\n"
4413        "IP address of originator\n")
4414 {
4415   return bgp_route_set_add (vty, vty->index, "originator-id", argv[0]);
4416 }
4417
4418 DEFUN (no_set_originator_id,
4419        no_set_originator_id_cmd,
4420        "no set originator-id",
4421        NO_STR
4422        SET_STR
4423        "BGP originator ID attribute\n")
4424 {
4425   if (argc == 0)
4426     return bgp_route_set_delete (vty, vty->index, "originator-id", NULL);
4427   
4428   return bgp_route_set_delete (vty, vty->index, "originator-id", argv[0]);
4429 }
4430
4431 ALIAS (no_set_originator_id,
4432        no_set_originator_id_val_cmd,
4433        "no set originator-id A.B.C.D",
4434        NO_STR
4435        SET_STR
4436        "BGP originator ID attribute\n"
4437        "IP address of originator\n")
4438
4439 DEFUN_DEPRECATED (set_pathlimit_ttl,
4440        set_pathlimit_ttl_cmd,
4441        "set pathlimit ttl <1-255>",
4442        SET_STR
4443        "BGP AS-Pathlimit attribute\n"
4444        "Set AS-Path Hop-count TTL\n")
4445 {
4446   return CMD_SUCCESS;
4447 }
4448
4449 DEFUN_DEPRECATED (no_set_pathlimit_ttl,
4450        no_set_pathlimit_ttl_cmd,
4451        "no set pathlimit ttl",
4452        NO_STR
4453        SET_STR
4454        "BGP AS-Pathlimit attribute\n"
4455        "Set AS-Path Hop-count TTL\n")
4456 {
4457   return CMD_SUCCESS;
4458 }
4459
4460 ALIAS (no_set_pathlimit_ttl,
4461        no_set_pathlimit_ttl_val_cmd,
4462        "no set pathlimit ttl <1-255>",
4463        NO_STR
4464        MATCH_STR
4465        "BGP AS-Pathlimit attribute\n"
4466        "Set AS-Path Hop-count TTL\n")
4467
4468 DEFUN_DEPRECATED (match_pathlimit_as,
4469        match_pathlimit_as_cmd,
4470        "match pathlimit as <1-65535>",
4471        MATCH_STR
4472        "BGP AS-Pathlimit attribute\n"
4473        "Match Pathlimit AS number\n")
4474 {
4475   return CMD_SUCCESS;
4476 }
4477
4478 DEFUN_DEPRECATED (no_match_pathlimit_as,
4479        no_match_pathlimit_as_cmd,
4480        "no match pathlimit as",
4481        NO_STR
4482        MATCH_STR
4483        "BGP AS-Pathlimit attribute\n"
4484        "Match Pathlimit AS number\n")
4485 {
4486   return CMD_SUCCESS;
4487 }
4488
4489 ALIAS (no_match_pathlimit_as,
4490        no_match_pathlimit_as_val_cmd,
4491        "no match pathlimit as <1-65535>",
4492        NO_STR
4493        MATCH_STR
4494        "BGP AS-Pathlimit attribute\n"
4495        "Match Pathlimit ASN\n")
4496
4497
4498 /* Initialization of route map. */
4499 void
4500 bgp_route_map_init (void)
4501 {
4502   route_map_init ();
4503   route_map_init_vty ();
4504   route_map_add_hook (bgp_route_map_update);
4505   route_map_delete_hook (bgp_route_map_update);
4506
4507   route_map_install_match (&route_match_peer_cmd);
4508   route_map_install_match (&route_match_local_pref_cmd);
4509   route_map_install_match (&route_match_ip_address_cmd);
4510   route_map_install_match (&route_match_ip_next_hop_cmd);
4511   route_map_install_match (&route_match_ip_route_source_cmd);
4512   route_map_install_match (&route_match_ip_address_prefix_list_cmd);
4513   route_map_install_match (&route_match_ip_next_hop_prefix_list_cmd);
4514   route_map_install_match (&route_match_ip_route_source_prefix_list_cmd);
4515   route_map_install_match (&route_match_aspath_cmd);
4516   route_map_install_match (&route_match_community_cmd);
4517   route_map_install_match (&route_match_lcommunity_cmd);
4518   route_map_install_match (&route_match_ecommunity_cmd);
4519   route_map_install_match (&route_match_local_pref_cmd);
4520   route_map_install_match (&route_match_metric_cmd);
4521   route_map_install_match (&route_match_origin_cmd);
4522   route_map_install_match (&route_match_probability_cmd);
4523   route_map_install_match (&route_match_tag_cmd);
4524
4525   route_map_install_set (&route_set_ip_nexthop_cmd);
4526   route_map_install_set (&route_set_local_pref_cmd);
4527   route_map_install_set (&route_set_weight_cmd);
4528   route_map_install_set (&route_set_metric_cmd);
4529   route_map_install_set (&route_set_aspath_prepend_cmd);
4530   route_map_install_set (&route_set_aspath_exclude_cmd);
4531   route_map_install_set (&route_set_origin_cmd);
4532   route_map_install_set (&route_set_atomic_aggregate_cmd);
4533   route_map_install_set (&route_set_aggregator_as_cmd);
4534   route_map_install_set (&route_set_community_cmd);
4535   route_map_install_set (&route_set_community_delete_cmd);
4536   route_map_install_set (&route_set_lcommunity_cmd);
4537   route_map_install_set (&route_set_lcommunity_delete_cmd);
4538   route_map_install_set (&route_set_vpnv4_nexthop_cmd);
4539   route_map_install_set (&route_set_originator_id_cmd);
4540   route_map_install_set (&route_set_ecommunity_rt_cmd);
4541   route_map_install_set (&route_set_ecommunity_soo_cmd);
4542   route_map_install_set (&route_set_tag_cmd);
4543
4544   install_element (RMAP_NODE, &match_peer_cmd);
4545   install_element (RMAP_NODE, &match_peer_local_cmd);
4546   install_element (RMAP_NODE, &no_match_peer_cmd);
4547   install_element (RMAP_NODE, &no_match_peer_val_cmd);
4548   install_element (RMAP_NODE, &no_match_peer_local_cmd);
4549   install_element (RMAP_NODE, &match_ip_address_cmd);
4550   install_element (RMAP_NODE, &no_match_ip_address_cmd);
4551   install_element (RMAP_NODE, &no_match_ip_address_val_cmd);
4552   install_element (RMAP_NODE, &match_ip_next_hop_cmd);
4553   install_element (RMAP_NODE, &no_match_ip_next_hop_cmd);
4554   install_element (RMAP_NODE, &no_match_ip_next_hop_val_cmd);
4555   install_element (RMAP_NODE, &match_ip_route_source_cmd);
4556   install_element (RMAP_NODE, &no_match_ip_route_source_cmd);
4557   install_element (RMAP_NODE, &no_match_ip_route_source_val_cmd);
4558   install_element (RMAP_NODE, &match_ip_address_prefix_list_cmd);
4559   install_element (RMAP_NODE, &no_match_ip_address_prefix_list_cmd);
4560   install_element (RMAP_NODE, &no_match_ip_address_prefix_list_val_cmd);
4561   install_element (RMAP_NODE, &match_ip_next_hop_prefix_list_cmd);
4562   install_element (RMAP_NODE, &no_match_ip_next_hop_prefix_list_cmd);
4563   install_element (RMAP_NODE, &no_match_ip_next_hop_prefix_list_val_cmd);
4564   install_element (RMAP_NODE, &match_ip_route_source_prefix_list_cmd);
4565   install_element (RMAP_NODE, &no_match_ip_route_source_prefix_list_cmd);
4566   install_element (RMAP_NODE, &no_match_ip_route_source_prefix_list_val_cmd);
4567
4568   install_element (RMAP_NODE, &match_aspath_cmd);
4569   install_element (RMAP_NODE, &no_match_aspath_cmd);
4570   install_element (RMAP_NODE, &no_match_aspath_val_cmd);
4571   install_element (RMAP_NODE, &match_metric_cmd);
4572   install_element (RMAP_NODE, &no_match_metric_cmd);
4573   install_element (RMAP_NODE, &no_match_metric_val_cmd);
4574   install_element (RMAP_NODE, &match_local_pref_cmd);
4575   install_element (RMAP_NODE, &no_match_local_pref_cmd);
4576   install_element (RMAP_NODE, &no_match_local_pref_val_cmd);
4577   install_element (RMAP_NODE, &match_community_cmd);
4578   install_element (RMAP_NODE, &match_community_exact_cmd);
4579   install_element (RMAP_NODE, &no_match_community_cmd);
4580   install_element (RMAP_NODE, &no_match_community_val_cmd);
4581   install_element (RMAP_NODE, &no_match_community_exact_cmd);
4582   install_element (RMAP_NODE, &match_lcommunity_cmd);
4583   install_element (RMAP_NODE, &no_match_lcommunity_cmd);
4584   install_element (RMAP_NODE, &match_ecommunity_cmd);
4585   install_element (RMAP_NODE, &no_match_ecommunity_cmd);
4586   install_element (RMAP_NODE, &no_match_ecommunity_val_cmd);
4587   install_element (RMAP_NODE, &match_origin_cmd);
4588   install_element (RMAP_NODE, &no_match_origin_cmd);
4589   install_element (RMAP_NODE, &no_match_origin_val_cmd);
4590   install_element (RMAP_NODE, &match_probability_cmd);
4591   install_element (RMAP_NODE, &no_match_probability_cmd);
4592   install_element (RMAP_NODE, &no_match_probability_val_cmd);
4593   install_element (RMAP_NODE, &match_tag_cmd);
4594   install_element (RMAP_NODE, &no_match_tag_cmd);
4595   install_element (RMAP_NODE, &no_match_tag_val_cmd);
4596
4597   install_element (RMAP_NODE, &set_ip_nexthop_cmd);
4598   install_element (RMAP_NODE, &set_ip_nexthop_peer_cmd);
4599   install_element (RMAP_NODE, &no_set_ip_nexthop_cmd);
4600   install_element (RMAP_NODE, &no_set_ip_nexthop_val_cmd);
4601   install_element (RMAP_NODE, &set_local_pref_cmd);
4602   install_element (RMAP_NODE, &no_set_local_pref_cmd);
4603   install_element (RMAP_NODE, &no_set_local_pref_val_cmd);
4604   install_element (RMAP_NODE, &set_weight_cmd);
4605   install_element (RMAP_NODE, &no_set_weight_cmd);
4606   install_element (RMAP_NODE, &no_set_weight_val_cmd);
4607   install_element (RMAP_NODE, &set_metric_cmd);
4608   install_element (RMAP_NODE, &set_metric_addsub_cmd);
4609   install_element (RMAP_NODE, &set_metric_rtt_cmd);
4610   install_element (RMAP_NODE, &no_set_metric_cmd);
4611   install_element (RMAP_NODE, &no_set_metric_val_cmd);
4612   install_element (RMAP_NODE, &set_aspath_prepend_cmd);
4613   install_element (RMAP_NODE, &set_aspath_prepend_lastas_cmd);
4614   install_element (RMAP_NODE, &set_aspath_exclude_cmd);
4615   install_element (RMAP_NODE, &no_set_aspath_prepend_cmd);
4616   install_element (RMAP_NODE, &no_set_aspath_prepend_val_cmd);
4617   install_element (RMAP_NODE, &no_set_aspath_exclude_cmd);
4618   install_element (RMAP_NODE, &no_set_aspath_exclude_val_cmd);
4619   install_element (RMAP_NODE, &set_origin_cmd);
4620   install_element (RMAP_NODE, &no_set_origin_cmd);
4621   install_element (RMAP_NODE, &no_set_origin_val_cmd);
4622   install_element (RMAP_NODE, &set_atomic_aggregate_cmd);
4623   install_element (RMAP_NODE, &no_set_atomic_aggregate_cmd);
4624   install_element (RMAP_NODE, &set_aggregator_as_cmd);
4625   install_element (RMAP_NODE, &no_set_aggregator_as_cmd);
4626   install_element (RMAP_NODE, &no_set_aggregator_as_val_cmd);
4627   install_element (RMAP_NODE, &set_community_cmd);
4628   install_element (RMAP_NODE, &set_community_none_cmd);
4629   install_element (RMAP_NODE, &no_set_community_cmd);
4630   install_element (RMAP_NODE, &no_set_community_val_cmd);
4631   install_element (RMAP_NODE, &no_set_community_none_cmd);
4632   install_element (RMAP_NODE, &set_community_delete_cmd);
4633   install_element (RMAP_NODE, &no_set_community_delete_cmd);
4634   install_element (RMAP_NODE, &no_set_community_delete_val_cmd);
4635   install_element (RMAP_NODE, &set_lcommunity_cmd);
4636   install_element (RMAP_NODE, &set_lcommunity_none_cmd);
4637   install_element (RMAP_NODE, &no_set_lcommunity_cmd);
4638   install_element (RMAP_NODE, &no_set_lcommunity_val_cmd);
4639   install_element (RMAP_NODE, &no_set_lcommunity_none_cmd);
4640   install_element (RMAP_NODE, &set_lcommunity_delete_cmd);
4641   install_element (RMAP_NODE, &no_set_lcommunity_delete_cmd);
4642   install_element (RMAP_NODE, &no_set_lcommunity_delete_val_cmd);
4643   install_element (RMAP_NODE, &set_ecommunity_rt_cmd);
4644   install_element (RMAP_NODE, &no_set_ecommunity_rt_cmd);
4645   install_element (RMAP_NODE, &no_set_ecommunity_rt_val_cmd);
4646   install_element (RMAP_NODE, &set_ecommunity_soo_cmd);
4647   install_element (RMAP_NODE, &no_set_ecommunity_soo_cmd);
4648   install_element (RMAP_NODE, &no_set_ecommunity_soo_val_cmd);
4649   install_element (RMAP_NODE, &set_vpnv4_nexthop_cmd);
4650   install_element (RMAP_NODE, &no_set_vpnv4_nexthop_cmd);
4651   install_element (RMAP_NODE, &no_set_vpnv4_nexthop_val_cmd);
4652   install_element (RMAP_NODE, &set_originator_id_cmd);
4653   install_element (RMAP_NODE, &no_set_originator_id_cmd);
4654   install_element (RMAP_NODE, &no_set_originator_id_val_cmd);
4655   install_element (RMAP_NODE, &set_tag_cmd);
4656   install_element (RMAP_NODE, &no_set_tag_cmd);
4657   install_element (RMAP_NODE, &no_set_tag_val_cmd);
4658
4659   route_map_install_match (&route_match_ipv6_address_cmd);
4660   route_map_install_match (&route_match_ipv6_next_hop_cmd);
4661   route_map_install_match (&route_match_ipv6_address_prefix_list_cmd);
4662   route_map_install_set (&route_set_ipv6_nexthop_global_cmd);
4663   route_map_install_set (&route_set_ipv6_nexthop_local_cmd);
4664   route_map_install_set (&route_set_ipv6_nexthop_peer_cmd);
4665
4666   install_element (RMAP_NODE, &match_ipv6_address_cmd);
4667   install_element (RMAP_NODE, &no_match_ipv6_address_cmd);
4668   install_element (RMAP_NODE, &match_ipv6_next_hop_cmd);
4669   install_element (RMAP_NODE, &no_match_ipv6_next_hop_cmd);
4670   install_element (RMAP_NODE, &match_ipv6_address_prefix_list_cmd);
4671   install_element (RMAP_NODE, &no_match_ipv6_address_prefix_list_cmd);
4672   install_element (RMAP_NODE, &set_ipv6_nexthop_global_cmd);
4673   install_element (RMAP_NODE, &no_set_ipv6_nexthop_global_cmd);
4674   install_element (RMAP_NODE, &no_set_ipv6_nexthop_global_val_cmd);
4675   install_element (RMAP_NODE, &set_ipv6_nexthop_local_cmd);
4676   install_element (RMAP_NODE, &no_set_ipv6_nexthop_local_cmd);
4677   install_element (RMAP_NODE, &no_set_ipv6_nexthop_local_val_cmd);
4678   install_element (RMAP_NODE, &set_ipv6_nexthop_peer_cmd);
4679   install_element (RMAP_NODE, &no_set_ipv6_nexthop_peer_cmd);
4680
4681   /* AS-Pathlimit: functionality removed, commands kept for
4682    * compatibility.
4683    */
4684   install_element (RMAP_NODE, &set_pathlimit_ttl_cmd);
4685   install_element (RMAP_NODE, &no_set_pathlimit_ttl_cmd);
4686   install_element (RMAP_NODE, &no_set_pathlimit_ttl_val_cmd);
4687   install_element (RMAP_NODE, &match_pathlimit_as_cmd);
4688   install_element (RMAP_NODE, &no_match_pathlimit_as_cmd);
4689   install_element (RMAP_NODE, &no_match_pathlimit_as_val_cmd);
4690 }