isis_routemap.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566
  1. /*
  2. * IS-IS Rout(e)ing protocol - isis_routemap.c
  3. *
  4. * Copyright (C) 2013-2015 Christian Franke <chris@opensourcerouting.org>
  5. *
  6. * This program 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 Free
  8. * Software Foundation; either version 2 of the License, or (at your option)
  9. * any later version.
  10. *
  11. * This program is distributed in the hope that it will be useful,but WITHOUT
  12. * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13. * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
  14. * more details.
  15. * You should have received a copy of the GNU General Public License along
  16. * with this program; if not, write to the Free Software Foundation, Inc.,
  17. * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  18. */
  19. #include <zebra.h>
  20. #include "command.h"
  21. #include "filter.h"
  22. #include "hash.h"
  23. #include "if.h"
  24. #include "linklist.h"
  25. #include "log.h"
  26. #include "memory.h"
  27. #include "prefix.h"
  28. #include "plist.h"
  29. #include "routemap.h"
  30. #include "table.h"
  31. #include "thread.h"
  32. #include "vty.h"
  33. #include "isis_constants.h"
  34. #include "isis_common.h"
  35. #include "isis_flags.h"
  36. #include "dict.h"
  37. #include "isisd.h"
  38. #include "isis_misc.h"
  39. #include "isis_adjacency.h"
  40. #include "isis_circuit.h"
  41. #include "isis_tlv.h"
  42. #include "isis_pdu.h"
  43. #include "isis_lsp.h"
  44. #include "isis_spf.h"
  45. #include "isis_route.h"
  46. #include "isis_zebra.h"
  47. #include "isis_routemap.h"
  48. static route_map_result_t
  49. route_match_ip_address(void *rule, struct prefix *prefix,
  50. route_map_object_t type, void *object)
  51. {
  52. struct access_list *alist;
  53. if (type != RMAP_ISIS)
  54. return RMAP_NOMATCH;
  55. alist = access_list_lookup(AFI_IP, (char*)rule);
  56. if (access_list_apply(alist, prefix) != FILTER_DENY)
  57. return RMAP_MATCH;
  58. return RMAP_NOMATCH;
  59. }
  60. static void *
  61. route_match_ip_address_compile(const char *arg)
  62. {
  63. return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg);
  64. }
  65. static void
  66. route_match_ip_address_free(void *rule)
  67. {
  68. XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
  69. }
  70. static struct route_map_rule_cmd route_match_ip_address_cmd =
  71. {
  72. "ip address",
  73. route_match_ip_address,
  74. route_match_ip_address_compile,
  75. route_match_ip_address_free
  76. };
  77. /* ------------------------------------------------------------*/
  78. static route_map_result_t
  79. route_match_ip_address_prefix_list(void *rule, struct prefix *prefix,
  80. route_map_object_t type, void *object)
  81. {
  82. struct prefix_list *plist;
  83. if (type != RMAP_ISIS)
  84. return RMAP_NOMATCH;
  85. plist = prefix_list_lookup(AFI_IP, (char*)rule);
  86. if (prefix_list_apply(plist, prefix) != PREFIX_DENY)
  87. return RMAP_MATCH;
  88. return RMAP_NOMATCH;
  89. }
  90. static void *
  91. route_match_ip_address_prefix_list_compile(const char *arg)
  92. {
  93. return XSTRDUP (MTYPE_ROUTE_MAP_COMPILED, arg);
  94. }
  95. static void
  96. route_match_ip_address_prefix_list_free (void *rule)
  97. {
  98. XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
  99. }
  100. struct route_map_rule_cmd route_match_ip_address_prefix_list_cmd =
  101. {
  102. "ip address prefix-list",
  103. route_match_ip_address_prefix_list,
  104. route_match_ip_address_prefix_list_compile,
  105. route_match_ip_address_prefix_list_free
  106. };
  107. /* ------------------------------------------------------------*/
  108. static route_map_result_t
  109. route_match_ipv6_address(void *rule, struct prefix *prefix,
  110. route_map_object_t type, void *object)
  111. {
  112. struct access_list *alist;
  113. if (type != RMAP_ISIS)
  114. return RMAP_NOMATCH;
  115. alist = access_list_lookup(AFI_IP6, (char*)rule);
  116. if (access_list_apply(alist, prefix) != FILTER_DENY)
  117. return RMAP_MATCH;
  118. return RMAP_NOMATCH;
  119. }
  120. static void *
  121. route_match_ipv6_address_compile(const char *arg)
  122. {
  123. return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg);
  124. }
  125. static void
  126. route_match_ipv6_address_free(void *rule)
  127. {
  128. XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
  129. }
  130. static struct route_map_rule_cmd route_match_ipv6_address_cmd =
  131. {
  132. "ipv6 address",
  133. route_match_ipv6_address,
  134. route_match_ipv6_address_compile,
  135. route_match_ipv6_address_free
  136. };
  137. /* ------------------------------------------------------------*/
  138. static route_map_result_t
  139. route_match_ipv6_address_prefix_list(void *rule, struct prefix *prefix,
  140. route_map_object_t type, void *object)
  141. {
  142. struct prefix_list *plist;
  143. if (type != RMAP_ISIS)
  144. return RMAP_NOMATCH;
  145. plist = prefix_list_lookup(AFI_IP6, (char*)rule);
  146. if (prefix_list_apply(plist, prefix) != PREFIX_DENY)
  147. return RMAP_MATCH;
  148. return RMAP_NOMATCH;
  149. }
  150. static void *
  151. route_match_ipv6_address_prefix_list_compile(const char *arg)
  152. {
  153. return XSTRDUP (MTYPE_ROUTE_MAP_COMPILED, arg);
  154. }
  155. static void
  156. route_match_ipv6_address_prefix_list_free (void *rule)
  157. {
  158. XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
  159. }
  160. struct route_map_rule_cmd route_match_ipv6_address_prefix_list_cmd =
  161. {
  162. "ipv6 address prefix-list",
  163. route_match_ipv6_address_prefix_list,
  164. route_match_ipv6_address_prefix_list_compile,
  165. route_match_ipv6_address_prefix_list_free
  166. };
  167. /* ------------------------------------------------------------*/
  168. static route_map_result_t
  169. route_set_metric(void *rule, struct prefix *prefix,
  170. route_map_object_t type, void *object)
  171. {
  172. uint32_t *metric;
  173. struct isis_ext_info *info;
  174. if (type == RMAP_ISIS)
  175. {
  176. metric = rule;
  177. info = object;
  178. info->metric = *metric;
  179. }
  180. return RMAP_OKAY;
  181. }
  182. static void *
  183. route_set_metric_compile(const char *arg)
  184. {
  185. unsigned long metric;
  186. char *endp;
  187. uint32_t *ret;
  188. metric = strtoul(arg, &endp, 10);
  189. if (arg[0] == '\0' || *endp != '\0' || metric > MAX_WIDE_PATH_METRIC)
  190. return NULL;
  191. ret = XCALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(*ret));
  192. *ret = metric;
  193. return ret;
  194. }
  195. static void
  196. route_set_metric_free(void *rule)
  197. {
  198. XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
  199. }
  200. static struct route_map_rule_cmd route_set_metric_cmd =
  201. {
  202. "metric",
  203. route_set_metric,
  204. route_set_metric_compile,
  205. route_set_metric_free
  206. };
  207. /* ------------------------------------------------------------*/
  208. static int
  209. isis_route_match_add(struct vty *vty, struct route_map_index *index,
  210. const char *command, const char *arg)
  211. {
  212. int ret;
  213. ret = route_map_add_match (index, command, arg);
  214. if (ret)
  215. {
  216. switch (ret)
  217. {
  218. case RMAP_RULE_MISSING:
  219. vty_out (vty, "%% Can't find rule.%s", VTY_NEWLINE);
  220. return CMD_WARNING;
  221. case RMAP_COMPILE_ERROR:
  222. vty_out (vty, "%% Argument is malformed.%s", VTY_NEWLINE);
  223. return CMD_WARNING;
  224. }
  225. }
  226. return CMD_SUCCESS;
  227. }
  228. static int
  229. isis_route_match_delete(struct vty *vty, struct route_map_index *index,
  230. const char *command, const char *arg)
  231. {
  232. int ret;
  233. ret = route_map_delete_match (index, command, arg);
  234. if (ret)
  235. {
  236. switch (ret)
  237. {
  238. case RMAP_RULE_MISSING:
  239. vty_out (vty, "%% Can't find rule.%s", VTY_NEWLINE);
  240. return CMD_WARNING;
  241. case RMAP_COMPILE_ERROR:
  242. vty_out (vty, "%% Argument is malformed.%s", VTY_NEWLINE);
  243. return CMD_WARNING;
  244. }
  245. }
  246. return CMD_SUCCESS;
  247. }
  248. static int
  249. isis_route_set_add(struct vty *vty, struct route_map_index *index,
  250. const char *command, const char *arg)
  251. {
  252. int ret;
  253. ret = route_map_add_set(index, command, arg);
  254. if (ret)
  255. {
  256. switch (ret)
  257. {
  258. case RMAP_RULE_MISSING:
  259. vty_out (vty, "%% Can't find rule.%s", VTY_NEWLINE);
  260. return CMD_WARNING;
  261. case RMAP_COMPILE_ERROR:
  262. vty_out (vty, "%% Argument is malformed.%s", VTY_NEWLINE);
  263. return CMD_WARNING;
  264. }
  265. }
  266. return CMD_SUCCESS;
  267. }
  268. static int
  269. isis_route_set_delete (struct vty *vty, struct route_map_index *index,
  270. const char *command, const char *arg)
  271. {
  272. int ret;
  273. ret = route_map_delete_set (index, command, arg);
  274. if (ret)
  275. {
  276. switch (ret)
  277. {
  278. case RMAP_RULE_MISSING:
  279. vty_out (vty, "%% Can't find rule.%s", VTY_NEWLINE);
  280. return CMD_WARNING;
  281. case RMAP_COMPILE_ERROR:
  282. vty_out (vty, "%% Argument is malformed.%s", VTY_NEWLINE);
  283. return CMD_WARNING;
  284. }
  285. }
  286. return CMD_SUCCESS;
  287. }
  288. /* ------------------------------------------------------------*/
  289. DEFUN(match_ip_address,
  290. match_ip_address_cmd,
  291. "match ip address (<1-199>|<1300-2699>|WORD)",
  292. MATCH_STR
  293. IP_STR
  294. "Match address of route\n"
  295. "IP access-list number\n"
  296. "IP access-list number (expanded range)\n"
  297. "IP Access-list name\n")
  298. {
  299. return isis_route_match_add(vty, vty->index, "ip address", argv[0]);
  300. }
  301. DEFUN(no_match_ip_address,
  302. no_match_ip_address_val_cmd,
  303. "no match ip address (<1-199>|<1300-2699>|WORD)",
  304. NO_STR
  305. MATCH_STR
  306. IP_STR
  307. "Match address of route\n"
  308. "IP access-list number\n"
  309. "IP access-list number (expanded range)\n"
  310. "IP Access-list name\n")
  311. {
  312. if (argc == 0)
  313. return isis_route_match_delete(vty, vty->index, "ip address", NULL);
  314. return isis_route_match_delete(vty, vty->index, "ip address", argv[0]);
  315. }
  316. ALIAS(no_match_ip_address,
  317. no_match_ip_address_cmd,
  318. "no match ip address",
  319. NO_STR
  320. MATCH_STR
  321. IP_STR
  322. "Match address of route\n"
  323. );
  324. /* ------------------------------------------------------------*/
  325. DEFUN(match_ip_address_prefix_list,
  326. match_ip_address_prefix_list_cmd,
  327. "match ip address prefix-list WORD",
  328. MATCH_STR
  329. IP_STR
  330. "Match address of route\n"
  331. "Match entries of prefix-lists\n"
  332. "IP prefix-list name\n")
  333. {
  334. return isis_route_match_add(vty, vty->index, "ip address prefix-list", argv[0]);
  335. }
  336. DEFUN(no_match_ip_address_prefix_list,
  337. no_match_ip_address_prefix_list_cmd,
  338. "no match ip address prefix-list",
  339. NO_STR
  340. MATCH_STR
  341. IP_STR
  342. "Match address of route\n"
  343. "Match entries of prefix-lists\n")
  344. {
  345. if (argc == 0)
  346. return isis_route_match_delete (vty, vty->index, "ip address prefix-list", NULL);
  347. return isis_route_match_delete (vty, vty->index, "ip address prefix-list", argv[0]);
  348. }
  349. ALIAS(no_match_ip_address_prefix_list,
  350. no_match_ip_address_prefix_list_val_cmd,
  351. "no match ip address prefix-list WORD",
  352. NO_STR
  353. MATCH_STR
  354. IP_STR
  355. "Match address of route\n"
  356. "Match entries of prefix-lists\n"
  357. "IP prefix-list name\n"
  358. );
  359. /* ------------------------------------------------------------*/
  360. DEFUN(match_ipv6_address,
  361. match_ipv6_address_cmd,
  362. "match ipv6 address WORD",
  363. MATCH_STR
  364. IPV6_STR
  365. "Match IPv6 address of route\n"
  366. "IPv6 access-list name\n")
  367. {
  368. return isis_route_match_add(vty, vty->index, "ipv6 address", argv[0]);
  369. }
  370. DEFUN(no_match_ipv6_address,
  371. no_match_ipv6_address_val_cmd,
  372. "no match ipv6 address WORD",
  373. NO_STR
  374. MATCH_STR
  375. IPV6_STR
  376. "Match IPv6 address of route\n"
  377. "IPv6 access-list name\n")
  378. {
  379. if (argc == 0)
  380. return isis_route_match_delete(vty, vty->index, "ipv6 address", NULL);
  381. return isis_route_match_delete(vty, vty->index, "ipv6 address", argv[0]);
  382. }
  383. ALIAS(no_match_ipv6_address,
  384. no_match_ipv6_address_cmd,
  385. "no match ipv6 address",
  386. NO_STR
  387. MATCH_STR
  388. IPV6_STR
  389. "Match IPv6 address of route\n"
  390. );
  391. /* ------------------------------------------------------------*/
  392. DEFUN(match_ipv6_address_prefix_list,
  393. match_ipv6_address_prefix_list_cmd,
  394. "match ipv6 address prefix-list WORD",
  395. MATCH_STR
  396. IPV6_STR
  397. "Match address of route\n"
  398. "Match entries of prefix-lists\n"
  399. "IP prefix-list name\n")
  400. {
  401. return isis_route_match_add(vty, vty->index, "ipv6 address prefix-list", argv[0]);
  402. }
  403. DEFUN(no_match_ipv6_address_prefix_list,
  404. no_match_ipv6_address_prefix_list_cmd,
  405. "no match ipv6 address prefix-list",
  406. NO_STR
  407. MATCH_STR
  408. IPV6_STR
  409. "Match address of route\n"
  410. "Match entries of prefix-lists\n")
  411. {
  412. if (argc == 0)
  413. return isis_route_match_delete (vty, vty->index, "ipv6 address prefix-list", NULL);
  414. return isis_route_match_delete (vty, vty->index, "ipv6 address prefix-list", argv[0]);
  415. }
  416. ALIAS(no_match_ipv6_address_prefix_list,
  417. no_match_ipv6_address_prefix_list_val_cmd,
  418. "no match ipv6 address prefix-list WORD",
  419. NO_STR
  420. MATCH_STR
  421. IPV6_STR
  422. "Match address of route\n"
  423. "Match entries of prefix-lists\n"
  424. "IP prefix-list name\n"
  425. );
  426. /* ------------------------------------------------------------*/
  427. /* set metric already exists e.g. in the ospf routemap. vtysh doesn't cope well with different
  428. * commands at the same node, therefore add set metric with the same 32-bit range as ospf and
  429. * verify that the input is a valid isis metric */
  430. DEFUN(set_metric,
  431. set_metric_cmd,
  432. "set metric <0-4294967295>",
  433. SET_STR
  434. "Metric vale for destination routing protocol\n"
  435. "Metric value\n")
  436. {
  437. return isis_route_set_add(vty, vty->index, "metric", argv[0]);
  438. }
  439. DEFUN(no_set_metric,
  440. no_set_metric_val_cmd,
  441. "no set metric <0-4294967295>",
  442. NO_STR
  443. SET_STR
  444. "Metric value for destination routing protocol\n"
  445. "Metric value\n")
  446. {
  447. if (argc == 0)
  448. return isis_route_set_delete(vty, vty->index, "metric", NULL);
  449. return isis_route_set_delete(vty, vty->index, "metric", argv[0]);
  450. }
  451. ALIAS(no_set_metric,
  452. no_set_metric_cmd,
  453. "no set metric",
  454. NO_STR
  455. SET_STR
  456. "Metric vale for destination routing protocol\n"
  457. );
  458. void
  459. isis_route_map_init(void)
  460. {
  461. route_map_init();
  462. route_map_init_vty();
  463. route_map_install_match(&route_match_ip_address_cmd);
  464. install_element(RMAP_NODE, &match_ip_address_cmd);
  465. install_element(RMAP_NODE, &no_match_ip_address_val_cmd);
  466. install_element(RMAP_NODE, &no_match_ip_address_cmd);
  467. route_map_install_match(&route_match_ip_address_prefix_list_cmd);
  468. install_element(RMAP_NODE, &match_ip_address_prefix_list_cmd);
  469. install_element(RMAP_NODE, &no_match_ip_address_prefix_list_val_cmd);
  470. install_element(RMAP_NODE, &no_match_ip_address_prefix_list_cmd);
  471. route_map_install_match(&route_match_ipv6_address_cmd);
  472. install_element(RMAP_NODE, &match_ipv6_address_cmd);
  473. install_element(RMAP_NODE, &no_match_ipv6_address_val_cmd);
  474. install_element(RMAP_NODE, &no_match_ipv6_address_cmd);
  475. route_map_install_match(&route_match_ipv6_address_prefix_list_cmd);
  476. install_element(RMAP_NODE, &match_ipv6_address_prefix_list_cmd);
  477. install_element(RMAP_NODE, &no_match_ipv6_address_prefix_list_val_cmd);
  478. install_element(RMAP_NODE, &no_match_ipv6_address_prefix_list_cmd);
  479. route_map_install_set(&route_set_metric_cmd);
  480. install_element(RMAP_NODE, &set_metric_cmd);
  481. install_element(RMAP_NODE, &no_set_metric_val_cmd);
  482. install_element(RMAP_NODE, &no_set_metric_cmd);
  483. }