]>
Commit | Line | Data |
---|---|---|
718e3744 | 1 | /* RIPv2 routemap. |
fbf5d033 | 2 | * Copyright (C) 2005 6WIND <alain.ritoux@6wind.com> |
718e3744 | 3 | * Copyright (C) 1999 Kunihiro Ishiguro <kunihiro@zebra.org> |
4 | * | |
5 | * This file is part of GNU Zebra. | |
6 | * | |
7 | * GNU Zebra is free software; you can redistribute it and/or modify it | |
8 | * under the terms of the GNU General Public License as published by the | |
9 | * Free Software Foundation; either version 2, or (at your option) any | |
10 | * later version. | |
11 | * | |
12 | * GNU Zebra is distributed in the hope that it will be useful, but | |
13 | * WITHOUT ANY WARRANTY; without even the implied warranty of | |
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
15 | * General Public License for more details. | |
16 | * | |
896014f4 DL |
17 | * You should have received a copy of the GNU General Public License along |
18 | * with this program; see the file COPYING; if not, write to the Free Software | |
19 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | |
718e3744 | 20 | */ |
21 | ||
22 | #include <zebra.h> | |
23 | ||
24 | #include "memory.h" | |
25 | #include "prefix.h" | |
82f97584 | 26 | #include "vty.h" |
718e3744 | 27 | #include "routemap.h" |
28 | #include "command.h" | |
29 | #include "filter.h" | |
30 | #include "log.h" | |
d62a17ae | 31 | #include "sockunion.h" /* for inet_aton () */ |
718e3744 | 32 | #include "plist.h" |
1306c09a | 33 | #include "vrf.h" |
718e3744 | 34 | |
35 | #include "ripd/ripd.h" | |
6b0655a2 | 36 | |
d62a17ae | 37 | struct rip_metric_modifier { |
38 | enum { metric_increment, metric_decrement, metric_absolute } type; | |
6a74c5f9 | 39 | bool used; |
d7c0a89a | 40 | uint8_t metric; |
16705130 | 41 | }; |
718e3744 | 42 | |
718e3744 | 43 | /* `match metric METRIC' */ |
44 | /* Match function return 1 if match is success else return zero. */ | |
2789041a LK |
45 | static route_map_result_t route_match_metric(void *rule, |
46 | const struct prefix *prefix, | |
47 | route_map_object_t type, | |
48 | void *object) | |
d62a17ae | 49 | { |
d7c0a89a QY |
50 | uint32_t *metric; |
51 | uint32_t check; | |
d62a17ae | 52 | struct rip_info *rinfo; |
53 | ||
54 | if (type == RMAP_RIP) { | |
55 | metric = rule; | |
56 | rinfo = object; | |
57 | ||
58 | /* If external metric is available, the route-map should | |
59 | work on this one (for redistribute purpose) */ | |
60 | check = (rinfo->external_metric) ? rinfo->external_metric | |
61 | : rinfo->metric; | |
62 | if (check == *metric) | |
63 | return RMAP_MATCH; | |
64 | else | |
65 | return RMAP_NOMATCH; | |
66 | } | |
718e3744 | 67 | return RMAP_NOMATCH; |
718e3744 | 68 | } |
69 | ||
70 | /* Route map `match metric' match statement. `arg' is METRIC value */ | |
d62a17ae | 71 | static void *route_match_metric_compile(const char *arg) |
718e3744 | 72 | { |
d7c0a89a | 73 | uint32_t *metric; |
718e3744 | 74 | |
d7c0a89a | 75 | metric = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(uint32_t)); |
d62a17ae | 76 | *metric = atoi(arg); |
718e3744 | 77 | |
d62a17ae | 78 | if (*metric > 0) |
79 | return metric; | |
718e3744 | 80 | |
d62a17ae | 81 | XFREE(MTYPE_ROUTE_MAP_COMPILED, metric); |
82 | return NULL; | |
718e3744 | 83 | } |
84 | ||
85 | /* Free route map's compiled `match metric' value. */ | |
d62a17ae | 86 | static void route_match_metric_free(void *rule) |
718e3744 | 87 | { |
d62a17ae | 88 | XFREE(MTYPE_ROUTE_MAP_COMPILED, rule); |
718e3744 | 89 | } |
90 | ||
91 | /* Route map commands for metric matching. */ | |
d62a17ae | 92 | struct route_map_rule_cmd route_match_metric_cmd = { |
93 | "metric", route_match_metric, route_match_metric_compile, | |
94 | route_match_metric_free}; | |
718e3744 | 95 | |
96 | /* `match interface IFNAME' */ | |
97 | /* Match function return 1 if match is success else return zero. */ | |
2789041a LK |
98 | static route_map_result_t route_match_interface(void *rule, |
99 | const struct prefix *prefix, | |
100 | route_map_object_t type, | |
101 | void *object) | |
718e3744 | 102 | { |
d62a17ae | 103 | struct rip_info *rinfo; |
104 | struct interface *ifp; | |
105 | char *ifname; | |
718e3744 | 106 | |
d62a17ae | 107 | if (type == RMAP_RIP) { |
108 | ifname = rule; | |
a36898e7 | 109 | ifp = if_lookup_by_name(ifname, VRF_DEFAULT); |
718e3744 | 110 | |
d62a17ae | 111 | if (!ifp) |
112 | return RMAP_NOMATCH; | |
718e3744 | 113 | |
d62a17ae | 114 | rinfo = object; |
718e3744 | 115 | |
d62a17ae | 116 | if (rinfo->ifindex_out == ifp->ifindex |
dd127197 | 117 | || rinfo->nh.ifindex == ifp->ifindex) |
d62a17ae | 118 | return RMAP_MATCH; |
119 | else | |
120 | return RMAP_NOMATCH; | |
121 | } | |
718e3744 | 122 | return RMAP_NOMATCH; |
718e3744 | 123 | } |
124 | ||
125 | /* Route map `match interface' match statement. `arg' is IFNAME value */ | |
126 | /* XXX I don`t know if I need to check does interface exist? */ | |
d62a17ae | 127 | static void *route_match_interface_compile(const char *arg) |
718e3744 | 128 | { |
d62a17ae | 129 | return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg); |
718e3744 | 130 | } |
131 | ||
132 | /* Free route map's compiled `match interface' value. */ | |
d62a17ae | 133 | static void route_match_interface_free(void *rule) |
718e3744 | 134 | { |
d62a17ae | 135 | XFREE(MTYPE_ROUTE_MAP_COMPILED, rule); |
718e3744 | 136 | } |
137 | ||
138 | /* Route map commands for interface matching. */ | |
d62a17ae | 139 | struct route_map_rule_cmd route_match_interface_cmd = { |
140 | "interface", route_match_interface, route_match_interface_compile, | |
141 | route_match_interface_free}; | |
718e3744 | 142 | |
143 | /* `match ip next-hop IP_ACCESS_LIST' */ | |
144 | ||
145 | /* Match function return 1 if match is success else return zero. */ | |
2789041a LK |
146 | static route_map_result_t route_match_ip_next_hop(void *rule, |
147 | const struct prefix *prefix, | |
148 | route_map_object_t type, | |
149 | void *object) | |
d62a17ae | 150 | { |
151 | struct access_list *alist; | |
152 | struct rip_info *rinfo; | |
153 | struct prefix_ipv4 p; | |
154 | ||
155 | if (type == RMAP_RIP) { | |
156 | rinfo = object; | |
157 | p.family = AF_INET; | |
996c9314 LB |
158 | p.prefix = (rinfo->nh.gate.ipv4.s_addr) ? rinfo->nh.gate.ipv4 |
159 | : rinfo->from; | |
d62a17ae | 160 | p.prefixlen = IPV4_MAX_BITLEN; |
161 | ||
162 | alist = access_list_lookup(AFI_IP, (char *)rule); | |
163 | if (alist == NULL) | |
164 | return RMAP_NOMATCH; | |
165 | ||
166 | return (access_list_apply(alist, &p) == FILTER_DENY | |
167 | ? RMAP_NOMATCH | |
168 | : RMAP_MATCH); | |
169 | } | |
718e3744 | 170 | return RMAP_NOMATCH; |
718e3744 | 171 | } |
172 | ||
173 | /* Route map `ip next-hop' match statement. `arg' should be | |
174 | access-list name. */ | |
d62a17ae | 175 | static void *route_match_ip_next_hop_compile(const char *arg) |
718e3744 | 176 | { |
d62a17ae | 177 | return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg); |
718e3744 | 178 | } |
179 | ||
180 | /* Free route map's compiled `. */ | |
d62a17ae | 181 | static void route_match_ip_next_hop_free(void *rule) |
718e3744 | 182 | { |
d62a17ae | 183 | XFREE(MTYPE_ROUTE_MAP_COMPILED, rule); |
718e3744 | 184 | } |
185 | ||
186 | /* Route map commands for ip next-hop matching. */ | |
d62a17ae | 187 | static struct route_map_rule_cmd route_match_ip_next_hop_cmd = { |
188 | "ip next-hop", route_match_ip_next_hop, route_match_ip_next_hop_compile, | |
189 | route_match_ip_next_hop_free}; | |
6b0655a2 | 190 | |
718e3744 | 191 | /* `match ip next-hop prefix-list PREFIX_LIST' */ |
192 | ||
2789041a | 193 | static route_map_result_t |
123214ef | 194 | route_match_ip_next_hop_prefix_list(void *rule, const struct prefix *prefix, |
d62a17ae | 195 | route_map_object_t type, void *object) |
718e3744 | 196 | { |
d62a17ae | 197 | struct prefix_list *plist; |
198 | struct rip_info *rinfo; | |
199 | struct prefix_ipv4 p; | |
200 | ||
201 | if (type == RMAP_RIP) { | |
202 | rinfo = object; | |
203 | p.family = AF_INET; | |
996c9314 LB |
204 | p.prefix = (rinfo->nh.gate.ipv4.s_addr) ? rinfo->nh.gate.ipv4 |
205 | : rinfo->from; | |
d62a17ae | 206 | p.prefixlen = IPV4_MAX_BITLEN; |
207 | ||
208 | plist = prefix_list_lookup(AFI_IP, (char *)rule); | |
209 | if (plist == NULL) | |
210 | return RMAP_NOMATCH; | |
211 | ||
212 | return (prefix_list_apply(plist, &p) == PREFIX_DENY | |
213 | ? RMAP_NOMATCH | |
214 | : RMAP_MATCH); | |
215 | } | |
216 | return RMAP_NOMATCH; | |
718e3744 | 217 | } |
218 | ||
d62a17ae | 219 | static void *route_match_ip_next_hop_prefix_list_compile(const char *arg) |
718e3744 | 220 | { |
d62a17ae | 221 | return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg); |
718e3744 | 222 | } |
223 | ||
d62a17ae | 224 | static void route_match_ip_next_hop_prefix_list_free(void *rule) |
718e3744 | 225 | { |
d62a17ae | 226 | XFREE(MTYPE_ROUTE_MAP_COMPILED, rule); |
718e3744 | 227 | } |
228 | ||
d62a17ae | 229 | static struct route_map_rule_cmd route_match_ip_next_hop_prefix_list_cmd = { |
230 | "ip next-hop prefix-list", route_match_ip_next_hop_prefix_list, | |
231 | route_match_ip_next_hop_prefix_list_compile, | |
232 | route_match_ip_next_hop_prefix_list_free}; | |
6b0655a2 | 233 | |
b6c0e913 DA |
234 | /* `match ip next-hop type <blackhole>' */ |
235 | ||
236 | static route_map_result_t | |
237 | route_match_ip_next_hop_type(void *rule, const struct prefix *prefix, | |
238 | route_map_object_t type, void *object) | |
239 | { | |
240 | struct rip_info *rinfo; | |
241 | ||
242 | if (type == RMAP_RIP && prefix->family == AF_INET) { | |
243 | rinfo = (struct rip_info *)object; | |
244 | if (!rinfo) | |
245 | return RMAP_DENYMATCH; | |
246 | ||
247 | if (rinfo->nh.type == NEXTHOP_TYPE_BLACKHOLE) | |
248 | return RMAP_MATCH; | |
249 | } | |
250 | return RMAP_NOMATCH; | |
251 | } | |
252 | ||
253 | static void *route_match_ip_next_hop_type_compile(const char *arg) | |
254 | { | |
255 | return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg); | |
256 | } | |
257 | ||
258 | static void route_match_ip_next_hop_type_free(void *rule) | |
259 | { | |
260 | XFREE(MTYPE_ROUTE_MAP_COMPILED, rule); | |
261 | } | |
262 | ||
263 | static struct route_map_rule_cmd route_match_ip_next_hop_type_cmd = { | |
264 | "ip next-hop type", route_match_ip_next_hop_type, | |
265 | route_match_ip_next_hop_type_compile, | |
266 | route_match_ip_next_hop_type_free}; | |
267 | ||
718e3744 | 268 | /* `match ip address IP_ACCESS_LIST' */ |
269 | ||
270 | /* Match function should return 1 if match is success else return | |
271 | zero. */ | |
2789041a LK |
272 | static route_map_result_t route_match_ip_address(void *rule, |
273 | const struct prefix *prefix, | |
274 | route_map_object_t type, | |
275 | void *object) | |
718e3744 | 276 | { |
d62a17ae | 277 | struct access_list *alist; |
718e3744 | 278 | |
d62a17ae | 279 | if (type == RMAP_RIP) { |
280 | alist = access_list_lookup(AFI_IP, (char *)rule); | |
281 | if (alist == NULL) | |
282 | return RMAP_NOMATCH; | |
283 | ||
284 | return (access_list_apply(alist, prefix) == FILTER_DENY | |
285 | ? RMAP_NOMATCH | |
286 | : RMAP_MATCH); | |
287 | } | |
718e3744 | 288 | return RMAP_NOMATCH; |
718e3744 | 289 | } |
290 | ||
291 | /* Route map `ip address' match statement. `arg' should be | |
292 | access-list name. */ | |
d62a17ae | 293 | static void *route_match_ip_address_compile(const char *arg) |
718e3744 | 294 | { |
d62a17ae | 295 | return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg); |
718e3744 | 296 | } |
297 | ||
298 | /* Free route map's compiled `ip address' value. */ | |
d62a17ae | 299 | static void route_match_ip_address_free(void *rule) |
718e3744 | 300 | { |
d62a17ae | 301 | XFREE(MTYPE_ROUTE_MAP_COMPILED, rule); |
718e3744 | 302 | } |
303 | ||
304 | /* Route map commands for ip address matching. */ | |
d62a17ae | 305 | static struct route_map_rule_cmd route_match_ip_address_cmd = { |
306 | "ip address", route_match_ip_address, route_match_ip_address_compile, | |
307 | route_match_ip_address_free}; | |
6b0655a2 | 308 | |
718e3744 | 309 | /* `match ip address prefix-list PREFIX_LIST' */ |
310 | ||
2789041a | 311 | static route_map_result_t |
123214ef | 312 | route_match_ip_address_prefix_list(void *rule, const struct prefix *prefix, |
d62a17ae | 313 | route_map_object_t type, void *object) |
718e3744 | 314 | { |
d62a17ae | 315 | struct prefix_list *plist; |
718e3744 | 316 | |
d62a17ae | 317 | if (type == RMAP_RIP) { |
318 | plist = prefix_list_lookup(AFI_IP, (char *)rule); | |
319 | if (plist == NULL) | |
320 | return RMAP_NOMATCH; | |
321 | ||
322 | return (prefix_list_apply(plist, prefix) == PREFIX_DENY | |
323 | ? RMAP_NOMATCH | |
324 | : RMAP_MATCH); | |
325 | } | |
718e3744 | 326 | return RMAP_NOMATCH; |
718e3744 | 327 | } |
328 | ||
d62a17ae | 329 | static void *route_match_ip_address_prefix_list_compile(const char *arg) |
718e3744 | 330 | { |
d62a17ae | 331 | return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg); |
718e3744 | 332 | } |
333 | ||
d62a17ae | 334 | static void route_match_ip_address_prefix_list_free(void *rule) |
718e3744 | 335 | { |
d62a17ae | 336 | XFREE(MTYPE_ROUTE_MAP_COMPILED, rule); |
718e3744 | 337 | } |
338 | ||
d62a17ae | 339 | static struct route_map_rule_cmd route_match_ip_address_prefix_list_cmd = { |
340 | "ip address prefix-list", route_match_ip_address_prefix_list, | |
341 | route_match_ip_address_prefix_list_compile, | |
342 | route_match_ip_address_prefix_list_free}; | |
16705130 | 343 | |
344 | /* `match tag TAG' */ | |
345 | /* Match function return 1 if match is success else return zero. */ | |
2789041a LK |
346 | static route_map_result_t route_match_tag(void *rule, const struct prefix *p, |
347 | route_map_object_t type, void *object) | |
d62a17ae | 348 | { |
349 | route_tag_t *tag; | |
350 | struct rip_info *rinfo; | |
351 | route_tag_t rinfo_tag; | |
352 | ||
353 | if (type == RMAP_RIP) { | |
354 | tag = rule; | |
355 | rinfo = object; | |
356 | ||
357 | /* The information stored by rinfo is host ordered. */ | |
358 | rinfo_tag = rinfo->tag; | |
359 | if (rinfo_tag == *tag) | |
360 | return RMAP_MATCH; | |
361 | else | |
362 | return RMAP_NOMATCH; | |
363 | } | |
16705130 | 364 | return RMAP_NOMATCH; |
16705130 | 365 | } |
366 | ||
16705130 | 367 | /* Route map commands for tag matching. */ |
d62a17ae | 368 | static struct route_map_rule_cmd route_match_tag_cmd = { |
9d303b37 | 369 | "tag", route_match_tag, route_map_rule_tag_compile, |
d62a17ae | 370 | route_map_rule_tag_free, |
16705130 | 371 | }; |
6b0655a2 | 372 | |
718e3744 | 373 | /* `set metric METRIC' */ |
374 | ||
375 | /* Set metric to attribute. */ | |
2789041a LK |
376 | static route_map_result_t route_set_metric(void *rule, |
377 | const struct prefix *prefix, | |
378 | route_map_object_t type, | |
379 | void *object) | |
d62a17ae | 380 | { |
381 | if (type == RMAP_RIP) { | |
382 | struct rip_metric_modifier *mod; | |
383 | struct rip_info *rinfo; | |
384 | ||
385 | mod = rule; | |
386 | rinfo = object; | |
387 | ||
6a74c5f9 DS |
388 | if (!mod->used) |
389 | return RMAP_OKAY; | |
390 | ||
d62a17ae | 391 | if (mod->type == metric_increment) |
392 | rinfo->metric_out += mod->metric; | |
393 | else if (mod->type == metric_decrement) | |
394 | rinfo->metric_out -= mod->metric; | |
395 | else if (mod->type == metric_absolute) | |
396 | rinfo->metric_out = mod->metric; | |
397 | ||
398 | if ((signed int)rinfo->metric_out < 1) | |
399 | rinfo->metric_out = 1; | |
400 | if (rinfo->metric_out > RIP_METRIC_INFINITY) | |
401 | rinfo->metric_out = RIP_METRIC_INFINITY; | |
402 | ||
403 | rinfo->metric_set = 1; | |
404 | } | |
405 | return RMAP_OKAY; | |
718e3744 | 406 | } |
407 | ||
408 | /* set metric compilation. */ | |
d62a17ae | 409 | static void *route_set_metric_compile(const char *arg) |
410 | { | |
411 | int len; | |
412 | const char *pnt; | |
d62a17ae | 413 | long metric; |
414 | char *endptr = NULL; | |
415 | struct rip_metric_modifier *mod; | |
416 | ||
6a74c5f9 DS |
417 | mod = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, |
418 | sizeof(struct rip_metric_modifier)); | |
419 | mod->used = false; | |
420 | ||
d62a17ae | 421 | len = strlen(arg); |
422 | pnt = arg; | |
423 | ||
424 | if (len == 0) | |
6a74c5f9 | 425 | return mod; |
d62a17ae | 426 | |
427 | /* Examine first character. */ | |
428 | if (arg[0] == '+') { | |
6a74c5f9 | 429 | mod->type = metric_increment; |
d62a17ae | 430 | pnt++; |
431 | } else if (arg[0] == '-') { | |
6a74c5f9 | 432 | mod->type = metric_decrement; |
d62a17ae | 433 | pnt++; |
434 | } else | |
6a74c5f9 | 435 | mod->type = metric_absolute; |
d62a17ae | 436 | |
437 | /* Check beginning with digit string. */ | |
438 | if (*pnt < '0' || *pnt > '9') | |
6a74c5f9 | 439 | return mod; |
d62a17ae | 440 | |
441 | /* Convert string to integer. */ | |
442 | metric = strtol(pnt, &endptr, 10); | |
443 | ||
3679c9fa | 444 | if (*endptr != '\0' || metric < 0) { |
6a74c5f9 DS |
445 | return mod; |
446 | } | |
447 | if (metric > RIP_METRIC_INFINITY) { | |
996c9314 LB |
448 | zlog_info( |
449 | "%s: Metric specified: %ld is greater than RIP_METRIC_INFINITY, using INFINITY instead", | |
450 | __PRETTY_FUNCTION__, metric); | |
6a74c5f9 DS |
451 | mod->metric = RIP_METRIC_INFINITY; |
452 | } else | |
453 | mod->metric = metric; | |
d62a17ae | 454 | |
6a74c5f9 | 455 | mod->used = true; |
d62a17ae | 456 | |
457 | return mod; | |
718e3744 | 458 | } |
459 | ||
460 | /* Free route map's compiled `set metric' value. */ | |
d62a17ae | 461 | static void route_set_metric_free(void *rule) |
718e3744 | 462 | { |
d62a17ae | 463 | XFREE(MTYPE_ROUTE_MAP_COMPILED, rule); |
718e3744 | 464 | } |
465 | ||
466 | /* Set metric rule structure. */ | |
d62a17ae | 467 | static struct route_map_rule_cmd route_set_metric_cmd = { |
9d303b37 | 468 | "metric", route_set_metric, route_set_metric_compile, |
d62a17ae | 469 | route_set_metric_free, |
718e3744 | 470 | }; |
471 | ||
472 | /* `set ip next-hop IP_ADDRESS' */ | |
473 | ||
474 | /* Set nexthop to object. ojbect must be pointer to struct attr. */ | |
2789041a | 475 | static route_map_result_t route_set_ip_nexthop(void *rule, |
123214ef | 476 | const struct prefix *prefix, |
d62a17ae | 477 | route_map_object_t type, |
478 | void *object) | |
718e3744 | 479 | { |
d62a17ae | 480 | struct in_addr *address; |
481 | struct rip_info *rinfo; | |
482 | ||
483 | if (type == RMAP_RIP) { | |
484 | /* Fetch routemap's rule information. */ | |
485 | address = rule; | |
486 | rinfo = object; | |
487 | ||
488 | /* Set next hop value. */ | |
489 | rinfo->nexthop_out = *address; | |
490 | } | |
491 | ||
492 | return RMAP_OKAY; | |
718e3744 | 493 | } |
494 | ||
495 | /* Route map `ip nexthop' compile function. Given string is converted | |
496 | to struct in_addr structure. */ | |
d62a17ae | 497 | static void *route_set_ip_nexthop_compile(const char *arg) |
718e3744 | 498 | { |
d62a17ae | 499 | int ret; |
500 | struct in_addr *address; | |
718e3744 | 501 | |
d62a17ae | 502 | address = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(struct in_addr)); |
718e3744 | 503 | |
d62a17ae | 504 | ret = inet_aton(arg, address); |
718e3744 | 505 | |
d62a17ae | 506 | if (ret == 0) { |
507 | XFREE(MTYPE_ROUTE_MAP_COMPILED, address); | |
508 | return NULL; | |
509 | } | |
718e3744 | 510 | |
d62a17ae | 511 | return address; |
718e3744 | 512 | } |
513 | ||
514 | /* Free route map's compiled `ip nexthop' value. */ | |
d62a17ae | 515 | static void route_set_ip_nexthop_free(void *rule) |
718e3744 | 516 | { |
d62a17ae | 517 | XFREE(MTYPE_ROUTE_MAP_COMPILED, rule); |
718e3744 | 518 | } |
519 | ||
520 | /* Route map commands for ip nexthop set. */ | |
d62a17ae | 521 | static struct route_map_rule_cmd route_set_ip_nexthop_cmd = { |
522 | "ip next-hop", route_set_ip_nexthop, route_set_ip_nexthop_compile, | |
523 | route_set_ip_nexthop_free}; | |
16705130 | 524 | |
525 | /* `set tag TAG' */ | |
526 | ||
527 | /* Set tag to object. ojbect must be pointer to struct attr. */ | |
2789041a LK |
528 | static route_map_result_t route_set_tag(void *rule, const struct prefix *prefix, |
529 | route_map_object_t type, void *object) | |
16705130 | 530 | { |
d62a17ae | 531 | route_tag_t *tag; |
532 | struct rip_info *rinfo; | |
533 | ||
534 | if (type == RMAP_RIP) { | |
535 | /* Fetch routemap's rule information. */ | |
536 | tag = rule; | |
537 | rinfo = object; | |
538 | ||
539 | /* Set next hop value. */ | |
540 | rinfo->tag_out = *tag; | |
541 | } | |
542 | ||
543 | return RMAP_OKAY; | |
16705130 | 544 | } |
545 | ||
16705130 | 546 | /* Route map commands for tag set. */ |
d62a17ae | 547 | static struct route_map_rule_cmd route_set_tag_cmd = { |
548 | "tag", route_set_tag, route_map_rule_tag_compile, | |
549 | route_map_rule_tag_free}; | |
6b0655a2 | 550 | |
718e3744 | 551 | #define MATCH_STR "Match values from routing table\n" |
552 | #define SET_STR "Set values in destination routing protocol\n" | |
553 | ||
718e3744 | 554 | /* Route-map init */ |
4d762f26 | 555 | void rip_route_map_init(void) |
718e3744 | 556 | { |
d62a17ae | 557 | route_map_init(); |
718e3744 | 558 | |
d62a17ae | 559 | route_map_match_interface_hook(generic_match_add); |
560 | route_map_no_match_interface_hook(generic_match_delete); | |
82f97584 | 561 | |
d62a17ae | 562 | route_map_match_ip_address_hook(generic_match_add); |
563 | route_map_no_match_ip_address_hook(generic_match_delete); | |
82f97584 | 564 | |
d62a17ae | 565 | route_map_match_ip_address_prefix_list_hook(generic_match_add); |
566 | route_map_no_match_ip_address_prefix_list_hook(generic_match_delete); | |
82f97584 | 567 | |
d62a17ae | 568 | route_map_match_ip_next_hop_hook(generic_match_add); |
569 | route_map_no_match_ip_next_hop_hook(generic_match_delete); | |
82f97584 | 570 | |
d62a17ae | 571 | route_map_match_ip_next_hop_prefix_list_hook(generic_match_add); |
572 | route_map_no_match_ip_next_hop_prefix_list_hook(generic_match_delete); | |
82f97584 | 573 | |
b6c0e913 DA |
574 | route_map_match_ip_next_hop_type_hook(generic_match_add); |
575 | route_map_no_match_ip_next_hop_type_hook(generic_match_delete); | |
576 | ||
d62a17ae | 577 | route_map_match_metric_hook(generic_match_add); |
578 | route_map_no_match_metric_hook(generic_match_delete); | |
82f97584 | 579 | |
d62a17ae | 580 | route_map_match_tag_hook(generic_match_add); |
581 | route_map_no_match_tag_hook(generic_match_delete); | |
82f97584 | 582 | |
d62a17ae | 583 | route_map_set_ip_nexthop_hook(generic_set_add); |
584 | route_map_no_set_ip_nexthop_hook(generic_set_delete); | |
82f97584 | 585 | |
d62a17ae | 586 | route_map_set_metric_hook(generic_set_add); |
587 | route_map_no_set_metric_hook(generic_set_delete); | |
82f97584 | 588 | |
d62a17ae | 589 | route_map_set_tag_hook(generic_set_add); |
590 | route_map_no_set_tag_hook(generic_set_delete); | |
82f97584 | 591 | |
d62a17ae | 592 | route_map_install_match(&route_match_metric_cmd); |
593 | route_map_install_match(&route_match_interface_cmd); | |
594 | route_map_install_match(&route_match_ip_next_hop_cmd); | |
595 | route_map_install_match(&route_match_ip_next_hop_prefix_list_cmd); | |
b6c0e913 | 596 | route_map_install_match(&route_match_ip_next_hop_type_cmd); |
d62a17ae | 597 | route_map_install_match(&route_match_ip_address_cmd); |
598 | route_map_install_match(&route_match_ip_address_prefix_list_cmd); | |
599 | route_map_install_match(&route_match_tag_cmd); | |
718e3744 | 600 | |
d62a17ae | 601 | route_map_install_set(&route_set_metric_cmd); |
602 | route_map_install_set(&route_set_ip_nexthop_cmd); | |
603 | route_map_install_set(&route_set_tag_cmd); | |
718e3744 | 604 | } |