ripng_routemap.c 16 KB

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