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