distribute.c 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020
  1. /* Distribute list functions
  2. * Copyright (C) 1998, 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
  7. * it under the terms of the GNU General Public License as published
  8. * by the Free Software Foundation; either version 2, or (at your
  9. * option) any 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
  18. * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
  19. * Boston, MA 02111-1307, USA.
  20. */
  21. #include <zebra.h>
  22. #include "hash.h"
  23. #include "if.h"
  24. #include "filter.h"
  25. #include "command.h"
  26. #include "distribute.h"
  27. #include "memory.h"
  28. /* Hash of distribute list. */
  29. struct hash *disthash;
  30. /* Hook functions. */
  31. void (*distribute_add_hook) (struct distribute *);
  32. void (*distribute_delete_hook) (struct distribute *);
  33. static struct distribute *
  34. distribute_new (void)
  35. {
  36. return XCALLOC (MTYPE_DISTRIBUTE, sizeof (struct distribute));
  37. }
  38. /* Free distribute object. */
  39. static void
  40. distribute_free (struct distribute *dist)
  41. {
  42. int i = 0;
  43. if (dist->ifname)
  44. XFREE (MTYPE_DISTRIBUTE_IFNAME, dist->ifname);
  45. for (i=0; i < DISTRIBUTE_MAX; i++)
  46. if (dist->list[i])
  47. free(dist->list[i]);
  48. for (i=0; i < DISTRIBUTE_MAX; i++)
  49. if (dist->prefix[i])
  50. free(dist->prefix[i]);
  51. XFREE (MTYPE_DISTRIBUTE, dist);
  52. }
  53. static void
  54. distribute_free_if_empty(struct distribute *dist)
  55. {
  56. int i;
  57. for (i=0; i < DISTRIBUTE_MAX; i++)
  58. if (dist->list[i] != NULL || dist->prefix[i] != NULL)
  59. return;
  60. hash_release (disthash, dist);
  61. distribute_free (dist);
  62. }
  63. /* Lookup interface's distribute list. */
  64. struct distribute *
  65. distribute_lookup (const char *ifname)
  66. {
  67. struct distribute key;
  68. struct distribute *dist;
  69. /* temporary reference */
  70. key.ifname = (char *)ifname;
  71. dist = hash_lookup (disthash, &key);
  72. return dist;
  73. }
  74. void
  75. distribute_list_add_hook (void (*func) (struct distribute *))
  76. {
  77. distribute_add_hook = func;
  78. }
  79. void
  80. distribute_list_delete_hook (void (*func) (struct distribute *))
  81. {
  82. distribute_delete_hook = func;
  83. }
  84. static void *
  85. distribute_hash_alloc (struct distribute *arg)
  86. {
  87. struct distribute *dist;
  88. dist = distribute_new ();
  89. if (arg->ifname)
  90. dist->ifname = XSTRDUP (MTYPE_DISTRIBUTE_IFNAME, arg->ifname);
  91. else
  92. dist->ifname = NULL;
  93. return dist;
  94. }
  95. /* Make new distribute list and push into hash. */
  96. static struct distribute *
  97. distribute_get (const char *ifname)
  98. {
  99. struct distribute key;
  100. /* temporary reference */
  101. key.ifname = (char *)ifname;
  102. return hash_get (disthash, &key, (void * (*) (void *))distribute_hash_alloc);
  103. }
  104. static unsigned int
  105. distribute_hash_make (void *arg)
  106. {
  107. const struct distribute *dist = arg;
  108. return dist->ifname ? string_hash_make (dist->ifname) : 0;
  109. }
  110. /* If two distribute-list have same value then return 1 else return
  111. 0. This function is used by hash package. */
  112. static int
  113. distribute_cmp (const struct distribute *dist1, const struct distribute *dist2)
  114. {
  115. if (dist1->ifname && dist2->ifname)
  116. if (strcmp (dist1->ifname, dist2->ifname) == 0)
  117. return 1;
  118. if (! dist1->ifname && ! dist2->ifname)
  119. return 1;
  120. return 0;
  121. }
  122. /* Set access-list name to the distribute list. */
  123. static struct distribute *
  124. distribute_list_set (const char *ifname, enum distribute_type type,
  125. const char *alist_name)
  126. {
  127. struct distribute *dist;
  128. dist = distribute_get (ifname);
  129. if (dist->list[type])
  130. free (dist->list[type]);
  131. dist->list[type] = strdup (alist_name);
  132. /* Apply this distribute-list to the interface. */
  133. (*distribute_add_hook) (dist);
  134. return dist;
  135. }
  136. /* Unset distribute-list. If matched distribute-list exist then
  137. return 1. */
  138. static int
  139. distribute_list_unset (const char *ifname, enum distribute_type type,
  140. const char *alist_name)
  141. {
  142. struct distribute *dist;
  143. dist = distribute_lookup (ifname);
  144. if (!dist)
  145. return 0;
  146. if (!dist->list[type])
  147. return 0;
  148. if (strcmp (dist->list[type], alist_name) != 0)
  149. return 0;
  150. free (dist->list[type]);
  151. dist->list[type] = NULL;
  152. /* Apply this distribute-list to the interface. */
  153. (*distribute_delete_hook) (dist);
  154. /* If all dist are NULL, then free distribute list. */
  155. distribute_free_if_empty(dist);
  156. return 1;
  157. }
  158. /* Set access-list name to the distribute list. */
  159. static struct distribute *
  160. distribute_list_prefix_set (const char *ifname, enum distribute_type type,
  161. const char *plist_name)
  162. {
  163. struct distribute *dist;
  164. dist = distribute_get (ifname);
  165. if (dist->prefix[type])
  166. free (dist->prefix[type]);
  167. dist->prefix[type] = strdup (plist_name);
  168. /* Apply this distribute-list to the interface. */
  169. (*distribute_add_hook) (dist);
  170. return dist;
  171. }
  172. /* Unset distribute-list. If matched distribute-list exist then
  173. return 1. */
  174. static int
  175. distribute_list_prefix_unset (const char *ifname, enum distribute_type type,
  176. const char *plist_name)
  177. {
  178. struct distribute *dist;
  179. dist = distribute_lookup (ifname);
  180. if (!dist)
  181. return 0;
  182. if (!dist->prefix[type])
  183. return 0;
  184. if (strcmp (dist->prefix[type], plist_name) != 0)
  185. return 0;
  186. free (dist->prefix[type]);
  187. dist->prefix[type] = NULL;
  188. /* Apply this distribute-list to the interface. */
  189. (*distribute_delete_hook) (dist);
  190. /* If all dist are NULL, then free distribute list. */
  191. distribute_free_if_empty(dist);
  192. return 1;
  193. }
  194. DEFUN (distribute_list_all,
  195. distribute_list_all_cmd,
  196. "distribute-list WORD (in|out)",
  197. "Filter networks in routing updates\n"
  198. "Access-list name\n"
  199. "Filter incoming routing updates\n"
  200. "Filter outgoing routing updates\n")
  201. {
  202. enum distribute_type type;
  203. /* Check of distribute list type. */
  204. if (strncmp (argv[1], "i", 1) == 0)
  205. type = DISTRIBUTE_V4_IN;
  206. else if (strncmp (argv[1], "o", 1) == 0)
  207. type = DISTRIBUTE_V4_OUT;
  208. else
  209. {
  210. vty_out (vty, "distribute list direction must be [in|out]%s",
  211. VTY_NEWLINE);
  212. return CMD_WARNING;
  213. }
  214. /* Get interface name corresponding distribute list. */
  215. distribute_list_set (NULL, type, argv[0]);
  216. return CMD_SUCCESS;
  217. }
  218. DEFUN (ipv6_distribute_list_all,
  219. ipv6_distribute_list_all_cmd,
  220. "ipv6 distribute-list WORD (in|out)",
  221. "Filter networks in routing updates\n"
  222. "Access-list name\n"
  223. "Filter incoming routing updates\n"
  224. "Filter outgoing routing updates\n")
  225. {
  226. enum distribute_type type;
  227. /* Check of distribute list type. */
  228. if (strncmp (argv[1], "i", 1) == 0)
  229. type = DISTRIBUTE_V6_IN;
  230. else if (strncmp (argv[1], "o", 1) == 0)
  231. type = DISTRIBUTE_V6_OUT;
  232. else
  233. {
  234. vty_out (vty, "distribute list direction must be [in|out]%s",
  235. VTY_NEWLINE);
  236. return CMD_WARNING;
  237. }
  238. /* Get interface name corresponding distribute list. */
  239. distribute_list_set (NULL, type, argv[0]);
  240. return CMD_SUCCESS;
  241. }
  242. ALIAS (ipv6_distribute_list_all,
  243. ipv6_as_v4_distribute_list_all_cmd,
  244. "distribute-list WORD (in|out)",
  245. "Filter networks in routing updates\n"
  246. "Access-list name\n"
  247. "Filter incoming routing updates\n"
  248. "Filter outgoing routing updates\n")
  249. DEFUN (no_distribute_list_all,
  250. no_distribute_list_all_cmd,
  251. "no distribute-list WORD (in|out)",
  252. NO_STR
  253. "Filter networks in routing updates\n"
  254. "Access-list name\n"
  255. "Filter incoming routing updates\n"
  256. "Filter outgoing routing updates\n")
  257. {
  258. int ret;
  259. enum distribute_type type;
  260. /* Check of distribute list type. */
  261. if (strncmp (argv[1], "i", 1) == 0)
  262. type = DISTRIBUTE_V4_IN;
  263. else if (strncmp (argv[1], "o", 1) == 0)
  264. type = DISTRIBUTE_V4_OUT;
  265. else
  266. {
  267. vty_out (vty, "distribute list direction must be [in|out]%s",
  268. VTY_NEWLINE);
  269. return CMD_WARNING;
  270. }
  271. ret = distribute_list_unset (NULL, type, argv[0]);
  272. if (! ret)
  273. {
  274. vty_out (vty, "distribute list doesn't exist%s", VTY_NEWLINE);
  275. return CMD_WARNING;
  276. }
  277. return CMD_SUCCESS;
  278. }
  279. DEFUN (no_ipv6_distribute_list_all,
  280. no_ipv6_distribute_list_all_cmd,
  281. "no ipv6 distribute-list WORD (in|out)",
  282. NO_STR
  283. "Filter networks in routing updates\n"
  284. "Access-list name\n"
  285. "Filter incoming routing updates\n"
  286. "Filter outgoing routing updates\n")
  287. {
  288. int ret;
  289. enum distribute_type type;
  290. /* Check of distribute list type. */
  291. if (strncmp (argv[1], "i", 1) == 0)
  292. type = DISTRIBUTE_V6_IN;
  293. else if (strncmp (argv[1], "o", 1) == 0)
  294. type = DISTRIBUTE_V6_OUT;
  295. else
  296. {
  297. vty_out (vty, "distribute list direction must be [in|out]%s",
  298. VTY_NEWLINE);
  299. return CMD_WARNING;
  300. }
  301. ret = distribute_list_unset (NULL, type, argv[0]);
  302. if (! ret)
  303. {
  304. vty_out (vty, "distribute list doesn't exist%s", VTY_NEWLINE);
  305. return CMD_WARNING;
  306. }
  307. return CMD_SUCCESS;
  308. }
  309. ALIAS (no_ipv6_distribute_list_all,
  310. no_ipv6_as_v4_distribute_list_all_cmd,
  311. "no distribute-list WORD (in|out)",
  312. NO_STR
  313. "Filter networks in routing updates\n"
  314. "Access-list name\n"
  315. "Filter incoming routing updates\n"
  316. "Filter outgoing routing updates\n")
  317. DEFUN (distribute_list,
  318. distribute_list_cmd,
  319. "distribute-list WORD (in|out) WORD",
  320. "Filter networks in routing updates\n"
  321. "Access-list name\n"
  322. "Filter incoming routing updates\n"
  323. "Filter outgoing routing updates\n"
  324. "Interface name\n")
  325. {
  326. enum distribute_type type;
  327. /* Check of distribute list type. */
  328. if (strncmp (argv[1], "i", 1) == 0)
  329. type = DISTRIBUTE_V4_IN;
  330. else if (strncmp (argv[1], "o", 1) == 0)
  331. type = DISTRIBUTE_V4_OUT;
  332. else
  333. {
  334. vty_out (vty, "distribute list direction must be [in|out]%s", VTY_NEWLINE);
  335. return CMD_WARNING;
  336. }
  337. /* Get interface name corresponding distribute list. */
  338. distribute_list_set (argv[2], type, argv[0]);
  339. return CMD_SUCCESS;
  340. }
  341. DEFUN (ipv6_distribute_list,
  342. ipv6_distribute_list_cmd,
  343. "ipv6 distribute-list WORD (in|out) WORD",
  344. "Filter networks in routing updates\n"
  345. "Access-list name\n"
  346. "Filter incoming routing updates\n"
  347. "Filter outgoing routing updates\n"
  348. "Interface name\n")
  349. {
  350. enum distribute_type type;
  351. /* Check of distribute list type. */
  352. if (strncmp (argv[1], "i", 1) == 0)
  353. type = DISTRIBUTE_V6_IN;
  354. else if (strncmp (argv[1], "o", 1) == 0)
  355. type = DISTRIBUTE_V6_OUT;
  356. else
  357. {
  358. vty_out (vty, "distribute list direction must be [in|out]%s", VTY_NEWLINE);
  359. return CMD_WARNING;
  360. }
  361. /* Get interface name corresponding distribute list. */
  362. distribute_list_set (argv[2], type, argv[0]);
  363. return CMD_SUCCESS;
  364. }
  365. ALIAS (ipv6_distribute_list,
  366. ipv6_as_v4_distribute_list_cmd,
  367. "distribute-list WORD (in|out) WORD",
  368. "Filter networks in routing updates\n"
  369. "Access-list name\n"
  370. "Filter incoming routing updates\n"
  371. "Filter outgoing routing updates\n"
  372. "Interface name\n")
  373. DEFUN (no_distribute_list, no_distribute_list_cmd,
  374. "no distribute-list WORD (in|out) WORD",
  375. NO_STR
  376. "Filter networks in routing updates\n"
  377. "Access-list name\n"
  378. "Filter incoming routing updates\n"
  379. "Filter outgoing routing updates\n"
  380. "Interface name\n")
  381. {
  382. int ret;
  383. enum distribute_type type;
  384. /* Check of distribute list type. */
  385. if (strncmp (argv[1], "i", 1) == 0)
  386. type = DISTRIBUTE_V4_IN;
  387. else if (strncmp (argv[1], "o", 1) == 0)
  388. type = DISTRIBUTE_V4_OUT;
  389. else
  390. {
  391. vty_out (vty, "distribute list direction must be [in|out]%s", VTY_NEWLINE);
  392. return CMD_WARNING;
  393. }
  394. ret = distribute_list_unset (argv[2], type, argv[0]);
  395. if (! ret)
  396. {
  397. vty_out (vty, "distribute list doesn't exist%s", VTY_NEWLINE);
  398. return CMD_WARNING;
  399. }
  400. return CMD_SUCCESS;
  401. }
  402. DEFUN (no_ipv6_distribute_list,
  403. no_ipv6_distribute_list_cmd,
  404. "no ipv6 distribute-list WORD (in|out) WORD",
  405. NO_STR
  406. "Filter networks in routing updates\n"
  407. "Access-list name\n"
  408. "Filter incoming routing updates\n"
  409. "Filter outgoing routing updates\n"
  410. "Interface name\n")
  411. {
  412. int ret;
  413. enum distribute_type type;
  414. /* Check of distribute list type. */
  415. if (strncmp (argv[1], "i", 1) == 0)
  416. type = DISTRIBUTE_V6_IN;
  417. else if (strncmp (argv[1], "o", 1) == 0)
  418. type = DISTRIBUTE_V6_OUT;
  419. else
  420. {
  421. vty_out (vty, "distribute list direction must be [in|out]%s", VTY_NEWLINE);
  422. return CMD_WARNING;
  423. }
  424. ret = distribute_list_unset (argv[2], type, argv[0]);
  425. if (! ret)
  426. {
  427. vty_out (vty, "distribute list doesn't exist%s", VTY_NEWLINE);
  428. return CMD_WARNING;
  429. }
  430. return CMD_SUCCESS;
  431. }
  432. ALIAS (no_ipv6_distribute_list,
  433. no_ipv6_as_v4_distribute_list_cmd,
  434. "no distribute-list WORD (in|out) WORD",
  435. NO_STR
  436. "Filter networks in routing updates\n"
  437. "Access-list name\n"
  438. "Filter incoming routing updates\n"
  439. "Filter outgoing routing updates\n"
  440. "Interface name\n")
  441. DEFUN (distribute_list_prefix_all,
  442. distribute_list_prefix_all_cmd,
  443. "distribute-list prefix WORD (in|out)",
  444. "Filter networks in routing updates\n"
  445. "Filter prefixes in routing updates\n"
  446. "Name of an IP prefix-list\n"
  447. "Filter incoming routing updates\n"
  448. "Filter outgoing routing updates\n")
  449. {
  450. enum distribute_type type;
  451. /* Check of distribute list type. */
  452. if (strncmp (argv[1], "i", 1) == 0)
  453. type = DISTRIBUTE_V4_IN;
  454. else if (strncmp (argv[1], "o", 1) == 0)
  455. type = DISTRIBUTE_V4_OUT;
  456. else
  457. {
  458. vty_out (vty, "distribute list direction must be [in|out]%s",
  459. VTY_NEWLINE);
  460. return CMD_WARNING;
  461. }
  462. /* Get interface name corresponding distribute list. */
  463. distribute_list_prefix_set (NULL, type, argv[0]);
  464. return CMD_SUCCESS;
  465. }
  466. DEFUN (ipv6_distribute_list_prefix_all,
  467. ipv6_distribute_list_prefix_all_cmd,
  468. "ipv6 distribute-list prefix WORD (in|out)",
  469. "Filter networks in routing updates\n"
  470. "Filter prefixes in routing updates\n"
  471. "Name of an IP prefix-list\n"
  472. "Filter incoming routing updates\n"
  473. "Filter outgoing routing updates\n")
  474. {
  475. enum distribute_type type;
  476. /* Check of distribute list type. */
  477. if (strncmp (argv[1], "i", 1) == 0)
  478. type = DISTRIBUTE_V6_IN;
  479. else if (strncmp (argv[1], "o", 1) == 0)
  480. type = DISTRIBUTE_V6_OUT;
  481. else
  482. {
  483. vty_out (vty, "distribute list direction must be [in|out]%s",
  484. VTY_NEWLINE);
  485. return CMD_WARNING;
  486. }
  487. /* Get interface name corresponding distribute list. */
  488. distribute_list_prefix_set (NULL, type, argv[0]);
  489. return CMD_SUCCESS;
  490. }
  491. ALIAS (ipv6_distribute_list_prefix_all,
  492. ipv6_as_v4_distribute_list_prefix_all_cmd,
  493. "distribute-list prefix WORD (in|out)",
  494. "Filter networks in routing updates\n"
  495. "Filter prefixes in routing updates\n"
  496. "Name of an IP prefix-list\n"
  497. "Filter incoming routing updates\n"
  498. "Filter outgoing routing updates\n")
  499. DEFUN (no_distribute_list_prefix_all,
  500. no_distribute_list_prefix_all_cmd,
  501. "no distribute-list prefix WORD (in|out)",
  502. NO_STR
  503. "Filter networks in routing updates\n"
  504. "Filter prefixes in routing updates\n"
  505. "Name of an IP prefix-list\n"
  506. "Filter incoming routing updates\n"
  507. "Filter outgoing routing updates\n")
  508. {
  509. int ret;
  510. enum distribute_type type;
  511. /* Check of distribute list type. */
  512. if (strncmp (argv[1], "i", 1) == 0)
  513. type = DISTRIBUTE_V4_IN;
  514. else if (strncmp (argv[1], "o", 1) == 0)
  515. type = DISTRIBUTE_V4_OUT;
  516. else
  517. {
  518. vty_out (vty, "distribute list direction must be [in|out]%s",
  519. VTY_NEWLINE);
  520. return CMD_WARNING;
  521. }
  522. ret = distribute_list_prefix_unset (NULL, type, argv[0]);
  523. if (! ret)
  524. {
  525. vty_out (vty, "distribute list doesn't exist%s", VTY_NEWLINE);
  526. return CMD_WARNING;
  527. }
  528. return CMD_SUCCESS;
  529. }
  530. DEFUN (no_ipv6_distribute_list_prefix_all,
  531. no_ipv6_distribute_list_prefix_all_cmd,
  532. "no ipv6 distribute-list prefix WORD (in|out)",
  533. NO_STR
  534. "Filter networks in routing updates\n"
  535. "Filter prefixes in routing updates\n"
  536. "Name of an IP prefix-list\n"
  537. "Filter incoming routing updates\n"
  538. "Filter outgoing routing updates\n")
  539. {
  540. int ret;
  541. enum distribute_type type;
  542. /* Check of distribute list type. */
  543. if (strncmp (argv[1], "i", 1) == 0)
  544. type = DISTRIBUTE_V6_IN;
  545. else if (strncmp (argv[1], "o", 1) == 0)
  546. type = DISTRIBUTE_V6_OUT;
  547. else
  548. {
  549. vty_out (vty, "distribute list direction must be [in|out]%s",
  550. VTY_NEWLINE);
  551. return CMD_WARNING;
  552. }
  553. ret = distribute_list_prefix_unset (NULL, type, argv[0]);
  554. if (! ret)
  555. {
  556. vty_out (vty, "distribute list doesn't exist%s", VTY_NEWLINE);
  557. return CMD_WARNING;
  558. }
  559. return CMD_SUCCESS;
  560. }
  561. ALIAS (no_ipv6_distribute_list_prefix_all,
  562. no_ipv6_as_v4_distribute_list_prefix_all_cmd,
  563. "no distribute-list prefix WORD (in|out)",
  564. NO_STR
  565. "Filter networks in routing updates\n"
  566. "Filter prefixes in routing updates\n"
  567. "Name of an IP prefix-list\n"
  568. "Filter incoming routing updates\n"
  569. "Filter outgoing routing updates\n")
  570. DEFUN (distribute_list_prefix, distribute_list_prefix_cmd,
  571. "distribute-list prefix WORD (in|out) WORD",
  572. "Filter networks in routing updates\n"
  573. "Filter prefixes in routing updates\n"
  574. "Name of an IP prefix-list\n"
  575. "Filter incoming routing updates\n"
  576. "Filter outgoing routing updates\n"
  577. "Interface name\n")
  578. {
  579. enum distribute_type type;
  580. /* Check of distribute list type. */
  581. if (strncmp (argv[1], "i", 1) == 0)
  582. type = DISTRIBUTE_V4_IN;
  583. else if (strncmp (argv[1], "o", 1) == 0)
  584. type = DISTRIBUTE_V4_OUT;
  585. else
  586. {
  587. vty_out (vty, "distribute list direction must be [in|out]%s",
  588. VTY_NEWLINE);
  589. return CMD_WARNING;
  590. }
  591. /* Get interface name corresponding distribute list. */
  592. distribute_list_prefix_set (argv[2], type, argv[0]);
  593. return CMD_SUCCESS;
  594. }
  595. DEFUN (ipv6_distribute_list_prefix,
  596. ipv6_distribute_list_prefix_cmd,
  597. "ipv6 distribute-list prefix WORD (in|out) WORD",
  598. "Filter networks in routing updates\n"
  599. "Filter prefixes in routing updates\n"
  600. "Name of an IP prefix-list\n"
  601. "Filter incoming routing updates\n"
  602. "Filter outgoing routing updates\n"
  603. "Interface name\n")
  604. {
  605. enum distribute_type type;
  606. /* Check of distribute list type. */
  607. if (strncmp (argv[1], "i", 1) == 0)
  608. type = DISTRIBUTE_V6_IN;
  609. else if (strncmp (argv[1], "o", 1) == 0)
  610. type = DISTRIBUTE_V6_OUT;
  611. else
  612. {
  613. vty_out (vty, "distribute list direction must be [in|out]%s",
  614. VTY_NEWLINE);
  615. return CMD_WARNING;
  616. }
  617. /* Get interface name corresponding distribute list. */
  618. distribute_list_prefix_set (argv[2], type, argv[0]);
  619. return CMD_SUCCESS;
  620. }
  621. ALIAS (ipv6_distribute_list_prefix,
  622. ipv6_as_v4_distribute_list_prefix_cmd,
  623. "distribute-list prefix WORD (in|out) WORD",
  624. "Filter networks in routing updates\n"
  625. "Filter prefixes in routing updates\n"
  626. "Name of an IP prefix-list\n"
  627. "Filter incoming routing updates\n"
  628. "Filter outgoing routing updates\n"
  629. "Interface name\n")
  630. DEFUN (no_distribute_list_prefix, no_distribute_list_prefix_cmd,
  631. "no distribute-list prefix WORD (in|out) WORD",
  632. NO_STR
  633. "Filter networks in routing updates\n"
  634. "Filter prefixes in routing updates\n"
  635. "Name of an IP prefix-list\n"
  636. "Filter incoming routing updates\n"
  637. "Filter outgoing routing updates\n"
  638. "Interface name\n")
  639. {
  640. int ret;
  641. enum distribute_type type;
  642. /* Check of distribute list type. */
  643. if (strncmp (argv[1], "i", 1) == 0)
  644. type = DISTRIBUTE_V4_IN;
  645. else if (strncmp (argv[1], "o", 1) == 0)
  646. type = DISTRIBUTE_V4_OUT;
  647. else
  648. {
  649. vty_out (vty, "distribute list direction must be [in|out]%s",
  650. VTY_NEWLINE);
  651. return CMD_WARNING;
  652. }
  653. ret = distribute_list_prefix_unset (argv[2], type, argv[0]);
  654. if (! ret)
  655. {
  656. vty_out (vty, "distribute list doesn't exist%s", VTY_NEWLINE);
  657. return CMD_WARNING;
  658. }
  659. return CMD_SUCCESS;
  660. }
  661. DEFUN (no_ipv6_distribute_list_prefix,
  662. no_ipv6_distribute_list_prefix_cmd,
  663. "no ipv6 distribute-list prefix WORD (in|out) WORD",
  664. NO_STR
  665. "Filter networks in routing updates\n"
  666. "Filter prefixes in routing updates\n"
  667. "Name of an IP prefix-list\n"
  668. "Filter incoming routing updates\n"
  669. "Filter outgoing routing updates\n"
  670. "Interface name\n")
  671. {
  672. int ret;
  673. enum distribute_type type;
  674. /* Check of distribute list type. */
  675. if (strncmp (argv[1], "i", 1) == 0)
  676. type = DISTRIBUTE_V6_IN;
  677. else if (strncmp (argv[1], "o", 1) == 0)
  678. type = DISTRIBUTE_V6_OUT;
  679. else
  680. {
  681. vty_out (vty, "distribute list direction must be [in|out]%s",
  682. VTY_NEWLINE);
  683. return CMD_WARNING;
  684. }
  685. ret = distribute_list_prefix_unset (argv[2], type, argv[0]);
  686. if (! ret)
  687. {
  688. vty_out (vty, "distribute list doesn't exist%s", VTY_NEWLINE);
  689. return CMD_WARNING;
  690. }
  691. return CMD_SUCCESS;
  692. }
  693. ALIAS (no_ipv6_distribute_list_prefix,
  694. no_ipv6_as_v4_distribute_list_prefix_cmd,
  695. "no distribute-list prefix WORD (in|out) WORD",
  696. NO_STR
  697. "Filter networks in routing updates\n"
  698. "Filter prefixes in routing updates\n"
  699. "Name of an IP prefix-list\n"
  700. "Filter incoming routing updates\n"
  701. "Filter outgoing routing updates\n"
  702. "Interface name\n")
  703. static int
  704. distribute_print (struct vty *vty, char *tab[], int is_prefix,
  705. enum distribute_type type, int has_print)
  706. {
  707. if (tab[type]) {
  708. vty_out (vty, "%s %s%s",
  709. has_print ? "," : "",
  710. is_prefix ? "(prefix-list) " : "",
  711. tab[type]);
  712. return 1;
  713. }
  714. return has_print;
  715. }
  716. int
  717. config_show_distribute (struct vty *vty)
  718. {
  719. unsigned int i;
  720. int has_print = 0;
  721. struct hash_backet *mp;
  722. struct distribute *dist;
  723. /* Output filter configuration. */
  724. dist = distribute_lookup (NULL);
  725. vty_out(vty, " Outgoing update filter list for all interface is");
  726. has_print = 0;
  727. if (dist)
  728. {
  729. has_print = distribute_print(vty, dist->list, 0,
  730. DISTRIBUTE_V4_OUT, has_print);
  731. has_print = distribute_print(vty, dist->prefix, 1,
  732. DISTRIBUTE_V4_OUT, has_print);
  733. has_print = distribute_print(vty, dist->list, 0,
  734. DISTRIBUTE_V6_OUT, has_print);
  735. has_print = distribute_print(vty, dist->prefix, 1,
  736. DISTRIBUTE_V6_OUT, has_print);
  737. }
  738. if (has_print)
  739. vty_out (vty, "%s", VTY_NEWLINE);
  740. else
  741. vty_out (vty, " not set%s", VTY_NEWLINE);
  742. for (i = 0; i < disthash->size; i++)
  743. for (mp = disthash->index[i]; mp; mp = mp->next)
  744. {
  745. dist = mp->data;
  746. if (dist->ifname)
  747. {
  748. vty_out (vty, " %s filtered by", dist->ifname);
  749. has_print = 0;
  750. has_print = distribute_print(vty, dist->list, 0,
  751. DISTRIBUTE_V4_OUT, has_print);
  752. has_print = distribute_print(vty, dist->prefix, 1,
  753. DISTRIBUTE_V4_OUT, has_print);
  754. has_print = distribute_print(vty, dist->list, 0,
  755. DISTRIBUTE_V6_OUT, has_print);
  756. has_print = distribute_print(vty, dist->prefix, 1,
  757. DISTRIBUTE_V6_OUT, has_print);
  758. if (has_print)
  759. vty_out (vty, "%s", VTY_NEWLINE);
  760. else
  761. vty_out(vty, " nothing%s", VTY_NEWLINE);
  762. }
  763. }
  764. /* Input filter configuration. */
  765. dist = distribute_lookup (NULL);
  766. vty_out(vty, " Incoming update filter list for all interface is");
  767. has_print = 0;
  768. if (dist)
  769. {
  770. has_print = distribute_print(vty, dist->list, 0,
  771. DISTRIBUTE_V4_IN, has_print);
  772. has_print = distribute_print(vty, dist->prefix, 1,
  773. DISTRIBUTE_V4_IN, has_print);
  774. has_print = distribute_print(vty, dist->list, 0,
  775. DISTRIBUTE_V6_IN, has_print);
  776. has_print = distribute_print(vty, dist->prefix, 1,
  777. DISTRIBUTE_V6_IN, has_print);
  778. }
  779. if (has_print)
  780. vty_out (vty, "%s", VTY_NEWLINE);
  781. else
  782. vty_out (vty, " not set%s", VTY_NEWLINE);
  783. for (i = 0; i < disthash->size; i++)
  784. for (mp = disthash->index[i]; mp; mp = mp->next)
  785. {
  786. dist = mp->data;
  787. if (dist->ifname)
  788. {
  789. vty_out (vty, " %s filtered by", dist->ifname);
  790. has_print = 0;
  791. has_print = distribute_print(vty, dist->list, 0,
  792. DISTRIBUTE_V4_IN, has_print);
  793. has_print = distribute_print(vty, dist->prefix, 1,
  794. DISTRIBUTE_V4_IN, has_print);
  795. has_print = distribute_print(vty, dist->list, 0,
  796. DISTRIBUTE_V6_IN, has_print);
  797. has_print = distribute_print(vty, dist->prefix, 1,
  798. DISTRIBUTE_V6_IN, has_print);
  799. if (has_print)
  800. vty_out (vty, "%s", VTY_NEWLINE);
  801. else
  802. vty_out(vty, " nothing%s", VTY_NEWLINE);
  803. }
  804. }
  805. return 0;
  806. }
  807. /* Configuration write function. */
  808. int
  809. config_write_distribute (struct vty *vty)
  810. {
  811. unsigned int i;
  812. int j;
  813. int output, v6;
  814. struct hash_backet *mp;
  815. int write = 0;
  816. for (i = 0; i < disthash->size; i++)
  817. for (mp = disthash->index[i]; mp; mp = mp->next)
  818. {
  819. struct distribute *dist;
  820. dist = mp->data;
  821. for (j=0; j < DISTRIBUTE_MAX; j++)
  822. if (dist->list[j]) {
  823. output = j == DISTRIBUTE_V4_OUT || j == DISTRIBUTE_V6_OUT;
  824. v6 = j == DISTRIBUTE_V6_IN || j == DISTRIBUTE_V6_OUT;
  825. vty_out (vty, " %sdistribute-list %s %s %s%s",
  826. v6 ? "ipv6 " : "",
  827. dist->list[j],
  828. output ? "out" : "in",
  829. dist->ifname ? dist->ifname : "",
  830. VTY_NEWLINE);
  831. write++;
  832. }
  833. for (j=0; j < DISTRIBUTE_MAX; j++)
  834. if (dist->prefix[j]) {
  835. output = j == DISTRIBUTE_V4_OUT || j == DISTRIBUTE_V6_OUT;
  836. v6 = j == DISTRIBUTE_V6_IN || j == DISTRIBUTE_V6_OUT;
  837. vty_out (vty, " %sdistribute-list prefix %s %s %s%s",
  838. v6 ? "ipv6 " : "",
  839. dist->prefix[j],
  840. output ? "out" : "in",
  841. dist->ifname ? dist->ifname : "",
  842. VTY_NEWLINE);
  843. write++;
  844. }
  845. }
  846. return write;
  847. }
  848. /* Clear all distribute list. */
  849. void
  850. distribute_list_reset ()
  851. {
  852. hash_clean (disthash, (void (*) (void *)) distribute_free);
  853. }
  854. /* Initialize distribute list related hash. */
  855. void
  856. distribute_list_init (int node)
  857. {
  858. disthash = hash_create (distribute_hash_make,
  859. (int (*) (const void *, const void *)) distribute_cmp);
  860. /* install v4 */
  861. if (node == RIP_NODE || node == BABEL_NODE) {
  862. install_element (node, &distribute_list_all_cmd);
  863. install_element (node, &no_distribute_list_all_cmd);
  864. install_element (node, &distribute_list_cmd);
  865. install_element (node, &no_distribute_list_cmd);
  866. install_element (node, &distribute_list_prefix_all_cmd);
  867. install_element (node, &no_distribute_list_prefix_all_cmd);
  868. install_element (node, &distribute_list_prefix_cmd);
  869. install_element (node, &no_distribute_list_prefix_cmd);
  870. }
  871. /* install v6 */
  872. if (node == RIPNG_NODE || node == BABEL_NODE) {
  873. install_element (node, &ipv6_distribute_list_all_cmd);
  874. install_element (node, &no_ipv6_distribute_list_all_cmd);
  875. install_element (node, &ipv6_distribute_list_cmd);
  876. install_element (node, &no_ipv6_distribute_list_cmd);
  877. install_element (node, &ipv6_distribute_list_prefix_all_cmd);
  878. install_element (node, &no_ipv6_distribute_list_prefix_all_cmd);
  879. install_element (node, &ipv6_distribute_list_prefix_cmd);
  880. install_element (node, &no_ipv6_distribute_list_prefix_cmd);
  881. }
  882. /* install v4 syntax command for v6 only protocols. */
  883. if (node == RIPNG_NODE) {
  884. install_element (node, &ipv6_as_v4_distribute_list_all_cmd);
  885. install_element (node, &no_ipv6_as_v4_distribute_list_all_cmd);
  886. install_element (node, &ipv6_as_v4_distribute_list_cmd);
  887. install_element (node, &no_ipv6_as_v4_distribute_list_cmd);
  888. install_element (node, &ipv6_as_v4_distribute_list_prefix_all_cmd);
  889. install_element (node, &no_ipv6_as_v4_distribute_list_prefix_all_cmd);
  890. install_element (node, &ipv6_as_v4_distribute_list_prefix_cmd);
  891. install_element (node, &no_ipv6_as_v4_distribute_list_prefix_cmd);
  892. }
  893. }