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