distribute.c 28 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021
  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. }