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