1/* RIPng routemap. 2 * Copyright (C) 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 22#include <zebra.h> 23 24#include "if.h" 25#include "memory.h" 26#include "prefix.h" 27#include "routemap.h" 28#include "command.h" 29#include "sockunion.h" 30 31#include "ripngd/ripngd.h" 32 33struct rip_metric_modifier 34{ 35 enum 36 { 37 metric_increment, 38 metric_decrement, 39 metric_absolute 40 } type; 41 42 u_char metric; 43}; 44 45 46static int 47ripng_route_match_add (struct vty *vty, struct route_map_index *index, 48 const char *command, const char *arg) 49{ 50 int ret; 51 52 ret = route_map_add_match (index, command, arg); 53 if (ret) 54 { 55 switch (ret) 56 { 57 case RMAP_RULE_MISSING: 58 vty_out (vty, "Can't find rule.%s", VTY_NEWLINE); 59 return CMD_WARNING; 60 case RMAP_COMPILE_ERROR: 61 vty_out (vty, "Argument is malformed.%s", VTY_NEWLINE); 62 return CMD_WARNING; 63 } 64 } 65 return CMD_SUCCESS; 66} 67 68static int 69ripng_route_match_delete (struct vty *vty, struct route_map_index *index, 70 const char *command, const char *arg) 71{ 72 int ret; 73 74 ret = route_map_delete_match (index, command, arg); 75 if (ret) 76 { 77 switch (ret) 78 { 79 case RMAP_RULE_MISSING: 80 vty_out (vty, "Can't find rule.%s", VTY_NEWLINE); 81 return CMD_WARNING; 82 case RMAP_COMPILE_ERROR: 83 vty_out (vty, "Argument is malformed.%s", VTY_NEWLINE); 84 return CMD_WARNING; 85 } 86 } 87 return CMD_SUCCESS; 88} 89 90static int 91ripng_route_set_add (struct vty *vty, struct route_map_index *index, 92 const char *command, const char *arg) 93{ 94 int ret; 95 96 ret = route_map_add_set (index, command, arg); 97 if (ret) 98 { 99 switch (ret) 100 { 101 case RMAP_RULE_MISSING: 102 vty_out (vty, "Can't find rule.%s", VTY_NEWLINE); 103 return CMD_WARNING; 104 case RMAP_COMPILE_ERROR: 105 vty_out (vty, "Argument is malformed.%s", VTY_NEWLINE); 106 return CMD_WARNING; 107 } 108 } 109 return CMD_SUCCESS; 110} 111 112static int 113ripng_route_set_delete (struct vty *vty, struct route_map_index *index, 114 const char *command, const char *arg) 115{ 116 int ret; 117 118 ret = route_map_delete_set (index, command, arg); 119 if (ret) 120 { 121 switch (ret) 122 { 123 case RMAP_RULE_MISSING: 124 vty_out (vty, "Can't find rule.%s", VTY_NEWLINE); 125 return CMD_WARNING; 126 case RMAP_COMPILE_ERROR: 127 vty_out (vty, "Argument is malformed.%s", VTY_NEWLINE); 128 return CMD_WARNING; 129 } 130 } 131 return CMD_SUCCESS; 132} 133 134/* `match metric METRIC' */ 135/* Match function return 1 if match is success else return zero. */ 136static route_map_result_t 137route_match_metric (void *rule, struct prefix *prefix, 138 route_map_object_t type, void *object) 139{ 140 u_int32_t *metric; 141 struct ripng_info *rinfo; 142 143 if (type == RMAP_RIPNG) 144 { 145 metric = rule; 146 rinfo = object; 147 148 if (rinfo->metric == *metric) 149 return RMAP_MATCH; 150 else 151 return RMAP_NOMATCH; 152 } 153 return RMAP_NOMATCH; 154} 155 156/* Route map `match metric' match statement. `arg' is METRIC value */ 157static void * 158route_match_metric_compile (const char *arg) 159{ 160 u_int32_t *metric; 161 162 metric = XMALLOC (MTYPE_ROUTE_MAP_COMPILED, sizeof (u_int32_t)); 163 *metric = atoi (arg); 164 165 if(*metric > 0) 166 return metric; 167 168 XFREE (MTYPE_ROUTE_MAP_COMPILED, metric); 169 return NULL; 170} 171 172/* Free route map's compiled `match metric' value. */ 173static void 174route_match_metric_free (void *rule) 175{ 176 XFREE (MTYPE_ROUTE_MAP_COMPILED, rule); 177} 178 179/* Route map commands for metric matching. */ 180static struct route_map_rule_cmd route_match_metric_cmd = 181{ 182 "metric", 183 route_match_metric, 184 route_match_metric_compile, 185 route_match_metric_free 186}; 187 188/* `match interface IFNAME' */ 189/* Match function return 1 if match is success else return zero. */ 190static route_map_result_t 191route_match_interface (void *rule, struct prefix *prefix, 192 route_map_object_t type, void *object) 193{ 194 struct ripng_info *rinfo; 195 struct interface *ifp; 196 char *ifname; 197 198 if (type == RMAP_RIPNG) 199 { 200 ifname = rule; 201 ifp = if_lookup_by_name(ifname); 202 203 if (!ifp) 204 return RMAP_NOMATCH; 205 206 rinfo = object; 207 208 if (rinfo->ifindex == ifp->ifindex) 209 return RMAP_MATCH; 210 else 211 return RMAP_NOMATCH; 212 } 213 return RMAP_NOMATCH; 214} 215 216/* Route map `match interface' match statement. `arg' is IFNAME value */ 217static void * 218route_match_interface_compile (const char *arg) 219{ 220 return XSTRDUP (MTYPE_ROUTE_MAP_COMPILED, arg); 221} 222 223static void 224route_match_interface_free (void *rule) 225{ 226 XFREE (MTYPE_ROUTE_MAP_COMPILED, rule); 227} 228 229static struct route_map_rule_cmd route_match_interface_cmd = 230{ 231 "interface", 232 route_match_interface, 233 route_match_interface_compile, 234 route_match_interface_free 235}; 236 237/* `match tag TAG' */ 238/* Match function return 1 if match is success else return zero. */ 239static route_map_result_t 240route_match_tag (void *rule, struct prefix *prefix, 241 route_map_object_t type, void *object) 242{ 243 u_short *tag; 244 struct ripng_info *rinfo; 245 246 if (type == RMAP_RIPNG) 247 { 248 tag = rule; 249 rinfo = object; 250 251 /* The information stored by rinfo is host ordered. */ 252 if (rinfo->tag == *tag) 253 return RMAP_MATCH; 254 else 255 return RMAP_NOMATCH; 256 } 257 return RMAP_NOMATCH; 258} 259 260/* Route map `match tag' match statement. `arg' is TAG value */ 261static void * 262route_match_tag_compile (const char *arg) 263{ 264 u_short *tag; 265 266 tag = XMALLOC (MTYPE_ROUTE_MAP_COMPILED, sizeof (u_short)); 267 *tag = atoi (arg); 268 269 return tag; 270} 271 272/* Free route map's compiled `match tag' value. */ 273static void 274route_match_tag_free (void *rule) 275{ 276 XFREE (MTYPE_ROUTE_MAP_COMPILED, rule); 277} 278 279/* Route map commands for tag matching. */ 280static struct route_map_rule_cmd route_match_tag_cmd = 281{ 282 "tag", 283 route_match_tag, 284 route_match_tag_compile, 285 route_match_tag_free 286}; 287 288/* `set metric METRIC' */ 289 290/* Set metric to attribute. */ 291static route_map_result_t 292route_set_metric (void *rule, struct prefix *prefix, 293 route_map_object_t type, void *object) 294{ 295 if (type == RMAP_RIPNG) 296 { 297 struct rip_metric_modifier *mod; 298 struct ripng_info *rinfo; 299 300 mod = rule; 301 rinfo = object; 302 303 if (mod->type == metric_increment) 304 rinfo->metric_out += mod->metric; 305 else if (mod->type == metric_decrement) 306 rinfo->metric_out-= mod->metric; 307 else if (mod->type == metric_absolute) 308 rinfo->metric_out = mod->metric; 309 310 if (rinfo->metric_out < 1) 311 rinfo->metric_out = 1; 312 if (rinfo->metric_out > RIPNG_METRIC_INFINITY) 313 rinfo->metric_out = RIPNG_METRIC_INFINITY; 314 315 rinfo->metric_set = 1; 316 } 317 return RMAP_OKAY; 318} 319 320/* set metric compilation. */ 321static void * 322route_set_metric_compile (const char *arg) 323{ 324 int len; 325 const char *pnt; 326 int type; 327 long metric; 328 char *endptr = NULL; 329 struct rip_metric_modifier *mod; 330 331 len = strlen (arg); 332 pnt = arg; 333 334 if (len == 0) 335 return NULL; 336 337 /* Examine first character. */ 338 if (arg[0] == '+') 339 { 340 type = metric_increment; 341 pnt++; 342 } 343 else if (arg[0] == '-') 344 { 345 type = metric_decrement; 346 pnt++; 347 } 348 else 349 type = metric_absolute; 350 351 /* Check beginning with digit string. */ 352 if (*pnt < '0' || *pnt > '9') 353 return NULL; 354 355 /* Convert string to integer. */ 356 metric = strtol (pnt, &endptr, 10); 357 358 if (metric == LONG_MAX || *endptr != '\0') 359 return NULL; 360 /* Commented out by Hasso Tepper, to avoid problems in vtysh. */ 361 /* if (metric < 0 || metric > RIPNG_METRIC_INFINITY) */ 362 if (metric < 0) 363 return NULL; 364 365 mod = XMALLOC (MTYPE_ROUTE_MAP_COMPILED, 366 sizeof (struct rip_metric_modifier)); 367 mod->type = type; 368 mod->metric = metric; 369 370 return mod; 371} 372 373/* Free route map's compiled `set metric' value. */ 374static void 375route_set_metric_free (void *rule) 376{ 377 XFREE (MTYPE_ROUTE_MAP_COMPILED, rule); 378} 379 380static struct route_map_rule_cmd route_set_metric_cmd = 381{ 382 "metric", 383 route_set_metric, 384 route_set_metric_compile, 385 route_set_metric_free, 386}; 387 388/* `set ipv6 next-hop local IP_ADDRESS' */ 389 390/* Set nexthop to object. ojbect must be pointer to struct attr. */ 391static route_map_result_t 392route_set_ipv6_nexthop_local (void *rule, struct prefix *prefix, 393 route_map_object_t type, void *object) 394{ 395 struct in6_addr *address; 396 struct ripng_info *rinfo; 397 398 if(type == RMAP_RIPNG) 399 { 400 /* Fetch routemap's rule information. */ 401 address = rule; 402 rinfo = object; 403 404 /* Set next hop value. */ 405 rinfo->nexthop_out = *address; 406 } 407 408 return RMAP_OKAY; 409} 410 411/* Route map `ipv6 nexthop local' compile function. Given string is converted 412 to struct in6_addr structure. */ 413static void * 414route_set_ipv6_nexthop_local_compile (const char *arg) 415{ 416 int ret; 417 struct in6_addr *address; 418 419 address = XMALLOC (MTYPE_ROUTE_MAP_COMPILED, sizeof (struct in6_addr)); 420 421 ret = inet_pton (AF_INET6, arg, address); 422 423 if (ret == 0) 424 { 425 XFREE (MTYPE_ROUTE_MAP_COMPILED, address); 426 return NULL; 427 } 428 429 return address; 430} 431 432/* Free route map's compiled `ipv6 nexthop local' value. */ 433static void 434route_set_ipv6_nexthop_local_free (void *rule) 435{ 436 XFREE (MTYPE_ROUTE_MAP_COMPILED, rule); 437} 438 439/* Route map commands for ipv6 nexthop local set. */ 440static struct route_map_rule_cmd route_set_ipv6_nexthop_local_cmd = 441{ 442 "ipv6 next-hop local", 443 route_set_ipv6_nexthop_local, 444 route_set_ipv6_nexthop_local_compile, 445 route_set_ipv6_nexthop_local_free 446}; 447 448/* `set tag TAG' */ 449 450/* Set tag to object. ojbect must be pointer to struct attr. */ 451static route_map_result_t 452route_set_tag (void *rule, struct prefix *prefix, 453 route_map_object_t type, void *object) 454{ 455 u_short *tag; 456 struct ripng_info *rinfo; 457 458 if(type == RMAP_RIPNG) 459 { 460 /* Fetch routemap's rule information. */ 461 tag = rule; 462 rinfo = object; 463 464 /* Set next hop value. */ 465 rinfo->tag_out = *tag; 466 } 467 468 return RMAP_OKAY; 469} 470 471/* Route map `tag' compile function. Given string is converted 472 to u_short. */ 473static void * 474route_set_tag_compile (const char *arg) 475{ 476 u_short *tag; 477 478 tag = XMALLOC (MTYPE_ROUTE_MAP_COMPILED, sizeof (u_short)); 479 *tag = atoi (arg); 480 481 return tag; 482} 483 484/* Free route map's compiled `ip nexthop' value. */ 485static void 486route_set_tag_free (void *rule) 487{ 488 XFREE (MTYPE_ROUTE_MAP_COMPILED, rule); 489} 490 491/* Route map commands for tag set. */ 492static struct route_map_rule_cmd route_set_tag_cmd = 493{ 494 "tag", 495 route_set_tag, 496 route_set_tag_compile, 497 route_set_tag_free 498}; 499 500#define MATCH_STR "Match values from routing table\n" 501#define SET_STR "Set values in destination routing protocol\n" 502 503DEFUN (match_metric, 504 match_metric_cmd, 505 "match metric <0-4294967295>", 506 MATCH_STR 507 "Match metric of route\n" 508 "Metric value\n") 509{ 510 return ripng_route_match_add (vty, vty->index, "metric", argv[0]); 511} 512 513DEFUN (no_match_metric, 514 no_match_metric_cmd, 515 "no match metric", 516 NO_STR 517 MATCH_STR 518 "Match metric of route\n") 519{ 520 if (argc == 0) 521 return ripng_route_match_delete (vty, vty->index, "metric", NULL); 522 523 return ripng_route_match_delete (vty, vty->index, "metric", argv[0]); 524} 525 526ALIAS (no_match_metric, 527 no_match_metric_val_cmd, 528 "no match metric <0-4294967295>", 529 NO_STR 530 MATCH_STR 531 "Match metric of route\n" 532 "Metric value\n") 533 534DEFUN (match_interface, 535 match_interface_cmd, 536 "match interface WORD", 537 MATCH_STR 538 "Match first hop interface of route\n" 539 "Interface name\n") 540{ 541 return ripng_route_match_add (vty, vty->index, "interface", argv[0]); 542} 543 544DEFUN (no_match_interface, 545 no_match_interface_cmd, 546 "no match interface", 547 NO_STR 548 MATCH_STR 549 "Match first hop interface of route\n") 550{ 551 if (argc == 0) 552 return ripng_route_match_delete (vty, vty->index, "interface", NULL); 553 554 return ripng_route_match_delete (vty, vty->index, "interface", argv[0]); 555} 556 557ALIAS (no_match_interface, 558 no_match_interface_val_cmd, 559 "no match interface WORD", 560 NO_STR 561 MATCH_STR 562 "Match first hop interface of route\n" 563 "Interface name\n") 564 565DEFUN (match_tag, 566 match_tag_cmd, 567 "match tag <0-65535>", 568 MATCH_STR 569 "Match tag of route\n" 570 "Metric value\n") 571{ 572 return ripng_route_match_add (vty, vty->index, "tag", argv[0]); 573} 574 575DEFUN (no_match_tag, 576 no_match_tag_cmd, 577 "no match tag", 578 NO_STR 579 MATCH_STR 580 "Match tag of route\n") 581{ 582 if (argc == 0) 583 return ripng_route_match_delete (vty, vty->index, "tag", NULL); 584 585 return ripng_route_match_delete (vty, vty->index, "tag", argv[0]); 586} 587 588ALIAS (no_match_tag, 589 no_match_tag_val_cmd, 590 "no match tag <0-65535>", 591 NO_STR 592 MATCH_STR 593 "Match tag of route\n" 594 "Metric value\n") 595 596/* set functions */ 597 598DEFUN (set_metric, 599 set_metric_cmd, 600 "set metric <0-4294967295>", 601 "Set value\n" 602 "Metric value for destination routing protocol\n" 603 "Metric value\n") 604{ 605 return ripng_route_set_add (vty, vty->index, "metric", argv[0]); 606} 607 608DEFUN (no_set_metric, 609 no_set_metric_cmd, 610 "no set metric", 611 NO_STR 612 SET_STR 613 "Metric value for destination routing protocol\n") 614{ 615 if (argc == 0) 616 return ripng_route_set_delete (vty, vty->index, "metric", NULL); 617 618 return ripng_route_set_delete (vty, vty->index, "metric", argv[0]); 619} 620 621ALIAS (no_set_metric, 622 no_set_metric_val_cmd, 623 "no set metric <0-4294967295>", 624 NO_STR 625 SET_STR 626 "Metric value for destination routing protocol\n" 627 "Metric value\n") 628 629DEFUN (set_ipv6_nexthop_local, 630 set_ipv6_nexthop_local_cmd, 631 "set ipv6 next-hop local X:X::X:X", 632 SET_STR 633 IPV6_STR 634 "IPv6 next-hop address\n" 635 "IPv6 local address\n" 636 "IPv6 address of next hop\n") 637{ 638 union sockunion su; 639 int ret; 640 641 ret = str2sockunion (argv[0], &su); 642 if (ret < 0) 643 { 644 vty_out (vty, "%% Malformed next-hop local address%s", VTY_NEWLINE); 645 return CMD_WARNING; 646 } 647 648 return ripng_route_set_add (vty, vty->index, "ipv6 next-hop local", argv[0]); 649} 650 651DEFUN (no_set_ipv6_nexthop_local, 652 no_set_ipv6_nexthop_local_cmd, 653 "no set ipv6 next-hop local", 654 NO_STR 655 SET_STR 656 IPV6_STR 657 "IPv6 next-hop address\n" 658 "IPv6 local address\n") 659{ 660 if (argc == 0) 661 return ripng_route_set_delete (vty, vty->index, "ipv6 next-hop local", NULL); 662 663 return ripng_route_set_delete (vty, vty->index, "ipv6 next-hop local", argv[0]); 664} 665 666ALIAS (no_set_ipv6_nexthop_local, 667 no_set_ipv6_nexthop_local_val_cmd, 668 "no set ipv6 next-hop local X:X::X:X", 669 NO_STR 670 SET_STR 671 IPV6_STR 672 "IPv6 next-hop address\n" 673 "IPv6 local address\n" 674 "IPv6 address of next hop\n") 675 676DEFUN (set_tag, 677 set_tag_cmd, 678 "set tag <0-65535>", 679 SET_STR 680 "Tag value for routing protocol\n" 681 "Tag value\n") 682{ 683 return ripng_route_set_add (vty, vty->index, "tag", argv[0]); 684} 685 686DEFUN (no_set_tag, 687 no_set_tag_cmd, 688 "no set tag", 689 NO_STR 690 SET_STR 691 "Tag value for routing protocol\n") 692{ 693 if (argc == 0) 694 return ripng_route_set_delete (vty, vty->index, "tag", NULL); 695 696 return ripng_route_set_delete (vty, vty->index, "tag", argv[0]); 697} 698 699ALIAS (no_set_tag, 700 no_set_tag_val_cmd, 701 "no set tag <0-65535>", 702 NO_STR 703 SET_STR 704 "Tag value for routing protocol\n" 705 "Tag value\n") 706 707void 708ripng_route_map_reset () 709{ 710 /* XXX ??? */ 711 ; 712} 713 714void 715ripng_route_map_init () 716{ 717 route_map_init (); 718 route_map_init_vty (); 719 720 route_map_install_match (&route_match_metric_cmd); 721 route_map_install_match (&route_match_interface_cmd); 722 route_map_install_match (&route_match_tag_cmd); 723 724 route_map_install_set (&route_set_metric_cmd); 725 route_map_install_set (&route_set_ipv6_nexthop_local_cmd); 726 route_map_install_set (&route_set_tag_cmd); 727 728 install_element (RMAP_NODE, &match_metric_cmd); 729 install_element (RMAP_NODE, &no_match_metric_cmd); 730 install_element (RMAP_NODE, &no_match_metric_val_cmd); 731 install_element (RMAP_NODE, &match_interface_cmd); 732 install_element (RMAP_NODE, &no_match_interface_cmd); 733 install_element (RMAP_NODE, &no_match_interface_val_cmd); 734 install_element (RMAP_NODE, &match_tag_cmd); 735 install_element (RMAP_NODE, &no_match_tag_cmd); 736 install_element (RMAP_NODE, &no_match_tag_val_cmd); 737 738 install_element (RMAP_NODE, &set_metric_cmd); 739 install_element (RMAP_NODE, &no_set_metric_cmd); 740 install_element (RMAP_NODE, &no_set_metric_val_cmd); 741 install_element (RMAP_NODE, &set_ipv6_nexthop_local_cmd); 742 install_element (RMAP_NODE, &no_set_ipv6_nexthop_local_cmd); 743 install_element (RMAP_NODE, &no_set_ipv6_nexthop_local_val_cmd); 744 install_element (RMAP_NODE, &set_tag_cmd); 745 install_element (RMAP_NODE, &no_set_tag_cmd); 746 install_element (RMAP_NODE, &no_set_tag_val_cmd); 747} 748