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