blob: 583befb360c95a9560c7cc1e9d65e367053b00fe [file] [log] [blame]
paul718e3742002-12-13 20:15:29 +00001/* 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
22#include <zebra.h>
23
24#include "hash.h"
25#include "if.h"
26#include "filter.h"
27#include "command.h"
28#include "distribute.h"
29#include "memory.h"
30
31/* Hash of distribute list. */
32struct hash *disthash;
33
34/* Hook functions. */
35void (*distribute_add_hook) (struct distribute *);
36void (*distribute_delete_hook) (struct distribute *);
David Lamparter6b0655a2014-06-04 06:53:35 +020037
paul8cc41982005-05-06 21:25:49 +000038static struct distribute *
39distribute_new (void)
paul718e3742002-12-13 20:15:29 +000040{
Stephen Hemminger393deb92008-08-18 14:13:29 -070041 return XCALLOC (MTYPE_DISTRIBUTE, sizeof (struct distribute));
paul718e3742002-12-13 20:15:29 +000042}
43
44/* Free distribute object. */
paul8cc41982005-05-06 21:25:49 +000045static void
paul718e3742002-12-13 20:15:29 +000046distribute_free (struct distribute *dist)
47{
Matthieu Boutier2074d672014-09-10 16:50:42 +020048 int i = 0;
paul718e3742002-12-13 20:15:29 +000049 if (dist->ifname)
paul9035efa2004-10-10 11:56:56 +000050 XFREE (MTYPE_DISTRIBUTE_IFNAME, dist->ifname);
paul718e3742002-12-13 20:15:29 +000051
Matthieu Boutier2074d672014-09-10 16:50:42 +020052 for (i=0; i < DISTRIBUTE_MAX; i++)
53 if (dist->list[i])
54 free(dist->list[i]);
paul718e3742002-12-13 20:15:29 +000055
Matthieu Boutier2074d672014-09-10 16:50:42 +020056 for (i=0; i < DISTRIBUTE_MAX; i++)
57 if (dist->prefix[i])
58 free(dist->prefix[i]);
paul718e3742002-12-13 20:15:29 +000059
60 XFREE (MTYPE_DISTRIBUTE, dist);
61}
62
Matthieu Boutier2074d672014-09-10 16:50:42 +020063static void
64distribute_free_if_empty(struct distribute *dist)
65{
66 int i;
67 for (i=0; i < DISTRIBUTE_MAX; i++)
68 if (dist->list[i] != NULL || dist->prefix[i] != NULL)
69 return;
70
71 hash_release (disthash, dist);
72 distribute_free (dist);
73}
74
paul718e3742002-12-13 20:15:29 +000075/* Lookup interface's distribute list. */
76struct distribute *
paul9035efa2004-10-10 11:56:56 +000077distribute_lookup (const char *ifname)
paul718e3742002-12-13 20:15:29 +000078{
79 struct distribute key;
80 struct distribute *dist;
81
paul9035efa2004-10-10 11:56:56 +000082 /* temporary reference */
83 key.ifname = (char *)ifname;
paul718e3742002-12-13 20:15:29 +000084
85 dist = hash_lookup (disthash, &key);
86
87 return dist;
88}
89
90void
91distribute_list_add_hook (void (*func) (struct distribute *))
92{
93 distribute_add_hook = func;
94}
95
96void
97distribute_list_delete_hook (void (*func) (struct distribute *))
98{
99 distribute_delete_hook = func;
100}
101
paul8cc41982005-05-06 21:25:49 +0000102static void *
paul718e3742002-12-13 20:15:29 +0000103distribute_hash_alloc (struct distribute *arg)
104{
105 struct distribute *dist;
106
107 dist = distribute_new ();
108 if (arg->ifname)
paul9035efa2004-10-10 11:56:56 +0000109 dist->ifname = XSTRDUP (MTYPE_DISTRIBUTE_IFNAME, arg->ifname);
paul718e3742002-12-13 20:15:29 +0000110 else
111 dist->ifname = NULL;
112 return dist;
113}
114
115/* Make new distribute list and push into hash. */
paul8cc41982005-05-06 21:25:49 +0000116static struct distribute *
paul9035efa2004-10-10 11:56:56 +0000117distribute_get (const char *ifname)
paul718e3742002-12-13 20:15:29 +0000118{
119 struct distribute key;
120
paul9035efa2004-10-10 11:56:56 +0000121 /* temporary reference */
122 key.ifname = (char *)ifname;
123
paul8cc41982005-05-06 21:25:49 +0000124 return hash_get (disthash, &key, (void * (*) (void *))distribute_hash_alloc);
paul718e3742002-12-13 20:15:29 +0000125}
126
paul8cc41982005-05-06 21:25:49 +0000127static unsigned int
Stephen Hemminger6392aa82010-08-27 14:11:14 -0700128distribute_hash_make (void *arg)
paul718e3742002-12-13 20:15:29 +0000129{
Stephen Hemminger6392aa82010-08-27 14:11:14 -0700130 const struct distribute *dist = arg;
paul718e3742002-12-13 20:15:29 +0000131
Stephen Hemminger6392aa82010-08-27 14:11:14 -0700132 return dist->ifname ? string_hash_make (dist->ifname) : 0;
paul718e3742002-12-13 20:15:29 +0000133}
134
135/* If two distribute-list have same value then return 1 else return
136 0. This function is used by hash package. */
paul8cc41982005-05-06 21:25:49 +0000137static int
Stephen Hemmingerffe11cf2008-08-14 16:25:25 +0100138distribute_cmp (const struct distribute *dist1, const struct distribute *dist2)
paul718e3742002-12-13 20:15:29 +0000139{
140 if (dist1->ifname && dist2->ifname)
141 if (strcmp (dist1->ifname, dist2->ifname) == 0)
142 return 1;
143 if (! dist1->ifname && ! dist2->ifname)
144 return 1;
145 return 0;
146}
David Lamparter6b0655a2014-06-04 06:53:35 +0200147
paul718e3742002-12-13 20:15:29 +0000148/* Set access-list name to the distribute list. */
paul8cc41982005-05-06 21:25:49 +0000149static struct distribute *
Matthieu Boutier2074d672014-09-10 16:50:42 +0200150distribute_list_set (const char *ifname, enum distribute_type type,
paul9035efa2004-10-10 11:56:56 +0000151 const char *alist_name)
paul718e3742002-12-13 20:15:29 +0000152{
153 struct distribute *dist;
154
155 dist = distribute_get (ifname);
156
Matthieu Boutier2074d672014-09-10 16:50:42 +0200157 if (dist->list[type])
158 free (dist->list[type]);
159 dist->list[type] = strdup (alist_name);
paul718e3742002-12-13 20:15:29 +0000160
161 /* Apply this distribute-list to the interface. */
162 (*distribute_add_hook) (dist);
Matthieu Boutier2074d672014-09-10 16:50:42 +0200163
paul718e3742002-12-13 20:15:29 +0000164 return dist;
165}
166
167/* Unset distribute-list. If matched distribute-list exist then
168 return 1. */
paul8cc41982005-05-06 21:25:49 +0000169static int
Matthieu Boutier2074d672014-09-10 16:50:42 +0200170distribute_list_unset (const char *ifname, enum distribute_type type,
paul9035efa2004-10-10 11:56:56 +0000171 const char *alist_name)
paul718e3742002-12-13 20:15:29 +0000172{
173 struct distribute *dist;
174
175 dist = distribute_lookup (ifname);
176 if (!dist)
177 return 0;
178
Matthieu Boutier2074d672014-09-10 16:50:42 +0200179 if (!dist->list[type])
180 return 0;
181 if (strcmp (dist->list[type], alist_name) != 0)
182 return 0;
paul718e3742002-12-13 20:15:29 +0000183
Matthieu Boutier2074d672014-09-10 16:50:42 +0200184 free (dist->list[type]);
185 dist->list[type] = NULL;
paul718e3742002-12-13 20:15:29 +0000186
187 /* Apply this distribute-list to the interface. */
188 (*distribute_delete_hook) (dist);
189
Matthieu Boutier2074d672014-09-10 16:50:42 +0200190 /* If all dist are NULL, then free distribute list. */
191 distribute_free_if_empty(dist);
paul718e3742002-12-13 20:15:29 +0000192 return 1;
193}
194
195/* Set access-list name to the distribute list. */
paul8cc41982005-05-06 21:25:49 +0000196static struct distribute *
paul9035efa2004-10-10 11:56:56 +0000197distribute_list_prefix_set (const char *ifname, enum distribute_type type,
198 const char *plist_name)
paul718e3742002-12-13 20:15:29 +0000199{
200 struct distribute *dist;
201
202 dist = distribute_get (ifname);
203
Matthieu Boutier2074d672014-09-10 16:50:42 +0200204 if (dist->prefix[type])
205 free (dist->prefix[type]);
206 dist->prefix[type] = strdup (plist_name);
paul718e3742002-12-13 20:15:29 +0000207
208 /* Apply this distribute-list to the interface. */
209 (*distribute_add_hook) (dist);
210
211 return dist;
212}
213
214/* Unset distribute-list. If matched distribute-list exist then
215 return 1. */
paul8cc41982005-05-06 21:25:49 +0000216static int
paul9035efa2004-10-10 11:56:56 +0000217distribute_list_prefix_unset (const char *ifname, enum distribute_type type,
218 const char *plist_name)
paul718e3742002-12-13 20:15:29 +0000219{
220 struct distribute *dist;
221
222 dist = distribute_lookup (ifname);
223 if (!dist)
224 return 0;
225
Matthieu Boutier2074d672014-09-10 16:50:42 +0200226 if (!dist->prefix[type])
227 return 0;
228 if (strcmp (dist->prefix[type], plist_name) != 0)
229 return 0;
paul718e3742002-12-13 20:15:29 +0000230
Matthieu Boutier2074d672014-09-10 16:50:42 +0200231 free (dist->prefix[type]);
232 dist->prefix[type] = NULL;
paul718e3742002-12-13 20:15:29 +0000233
234 /* Apply this distribute-list to the interface. */
235 (*distribute_delete_hook) (dist);
236
Matthieu Boutier2074d672014-09-10 16:50:42 +0200237 /* If all dist are NULL, then free distribute list. */
238 distribute_free_if_empty(dist);
paul718e3742002-12-13 20:15:29 +0000239 return 1;
240}
241
242DEFUN (distribute_list_all,
243 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{
250 enum distribute_type type;
paul718e3742002-12-13 20:15:29 +0000251
252 /* Check of distribute list type. */
253 if (strncmp (argv[1], "i", 1) == 0)
Matthieu Boutierdf2ef242014-09-10 16:50:45 +0200254 type = DISTRIBUTE_V4_IN;
paul718e3742002-12-13 20:15:29 +0000255 else if (strncmp (argv[1], "o", 1) == 0)
Matthieu Boutierdf2ef242014-09-10 16:50:45 +0200256 type = DISTRIBUTE_V4_OUT;
paul718e3742002-12-13 20:15:29 +0000257 else
258 {
259 vty_out (vty, "distribute list direction must be [in|out]%s",
260 VTY_NEWLINE);
261 return CMD_WARNING;
262 }
263
264 /* Get interface name corresponding distribute list. */
Stephen Hemminger9206f9e2011-12-18 19:43:40 +0400265 distribute_list_set (NULL, type, argv[0]);
paul718e3742002-12-13 20:15:29 +0000266
267 return CMD_SUCCESS;
268}
269
Matthieu Boutierdf2ef242014-09-10 16:50:45 +0200270DEFUN (ipv6_distribute_list_all,
paulba23a692003-04-19 15:55:08 +0000271 ipv6_distribute_list_all_cmd,
Matthieu Boutierdf2ef242014-09-10 16:50:45 +0200272 "ipv6 distribute-list WORD (in|out)",
273 "Filter networks in routing updates\n"
274 "Access-list name\n"
275 "Filter incoming routing updates\n"
276 "Filter outgoing routing updates\n")
277{
278 enum distribute_type type;
279
280 /* Check of distribute list type. */
281 if (strncmp (argv[1], "i", 1) == 0)
282 type = DISTRIBUTE_V6_IN;
283 else if (strncmp (argv[1], "o", 1) == 0)
284 type = DISTRIBUTE_V6_OUT;
285 else
286 {
287 vty_out (vty, "distribute list direction must be [in|out]%s",
288 VTY_NEWLINE);
289 return CMD_WARNING;
290 }
291
292 /* Get interface name corresponding distribute list. */
293 distribute_list_set (NULL, type, argv[0]);
294
295 return CMD_SUCCESS;
296}
297
298ALIAS (ipv6_distribute_list_all,
299 ipv6_as_v4_distribute_list_all_cmd,
paulba23a692003-04-19 15:55:08 +0000300 "distribute-list WORD (in|out)",
301 "Filter networks in routing updates\n"
302 "Access-list name\n"
303 "Filter incoming routing updates\n"
304 "Filter outgoing routing updates\n")
305
paul718e3742002-12-13 20:15:29 +0000306DEFUN (no_distribute_list_all,
307 no_distribute_list_all_cmd,
308 "no distribute-list WORD (in|out)",
309 NO_STR
310 "Filter networks in routing updates\n"
311 "Access-list name\n"
312 "Filter incoming routing updates\n"
313 "Filter outgoing routing updates\n")
314{
315 int ret;
316 enum distribute_type type;
317
318 /* Check of distribute list type. */
319 if (strncmp (argv[1], "i", 1) == 0)
Matthieu Boutierdf2ef242014-09-10 16:50:45 +0200320 type = DISTRIBUTE_V4_IN;
paul718e3742002-12-13 20:15:29 +0000321 else if (strncmp (argv[1], "o", 1) == 0)
Matthieu Boutierdf2ef242014-09-10 16:50:45 +0200322 type = DISTRIBUTE_V4_OUT;
paul718e3742002-12-13 20:15:29 +0000323 else
324 {
325 vty_out (vty, "distribute list direction must be [in|out]%s",
326 VTY_NEWLINE);
327 return CMD_WARNING;
328 }
329
330 ret = distribute_list_unset (NULL, type, argv[0]);
331 if (! ret)
332 {
333 vty_out (vty, "distribute list doesn't exist%s", VTY_NEWLINE);
334 return CMD_WARNING;
335 }
336 return CMD_SUCCESS;
337}
338
Matthieu Boutierdf2ef242014-09-10 16:50:45 +0200339DEFUN (no_ipv6_distribute_list_all,
paulba23a692003-04-19 15:55:08 +0000340 no_ipv6_distribute_list_all_cmd,
Matthieu Boutierdf2ef242014-09-10 16:50:45 +0200341 "no ipv6 distribute-list WORD (in|out)",
342 NO_STR
343 "Filter networks in routing updates\n"
344 "Access-list name\n"
345 "Filter incoming routing updates\n"
346 "Filter outgoing routing updates\n")
347{
348 int ret;
349 enum distribute_type type;
350
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",
359 VTY_NEWLINE);
360 return CMD_WARNING;
361 }
362
363 ret = distribute_list_unset (NULL, type, argv[0]);
364 if (! ret)
365 {
366 vty_out (vty, "distribute list doesn't exist%s", VTY_NEWLINE);
367 return CMD_WARNING;
368 }
369 return CMD_SUCCESS;
370}
371
372ALIAS (no_ipv6_distribute_list_all,
373 no_ipv6_as_v4_distribute_list_all_cmd,
paulba23a692003-04-19 15:55:08 +0000374 "no distribute-list WORD (in|out)",
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
paul718e3742002-12-13 20:15:29 +0000381DEFUN (distribute_list,
382 distribute_list_cmd,
383 "distribute-list WORD (in|out) WORD",
384 "Filter networks in routing updates\n"
385 "Access-list name\n"
386 "Filter incoming routing updates\n"
387 "Filter outgoing routing updates\n"
388 "Interface name\n")
389{
390 enum distribute_type type;
paul718e3742002-12-13 20:15:29 +0000391
392 /* Check of distribute list type. */
393 if (strncmp (argv[1], "i", 1) == 0)
Matthieu Boutierdf2ef242014-09-10 16:50:45 +0200394 type = DISTRIBUTE_V4_IN;
paul718e3742002-12-13 20:15:29 +0000395 else if (strncmp (argv[1], "o", 1) == 0)
Matthieu Boutierdf2ef242014-09-10 16:50:45 +0200396 type = DISTRIBUTE_V4_OUT;
paul718e3742002-12-13 20:15:29 +0000397 else
398 {
399 vty_out (vty, "distribute list direction must be [in|out]%s", VTY_NEWLINE);
400 return CMD_WARNING;
401 }
402
403 /* Get interface name corresponding distribute list. */
Stephen Hemminger9206f9e2011-12-18 19:43:40 +0400404 distribute_list_set (argv[2], type, argv[0]);
paul718e3742002-12-13 20:15:29 +0000405
406 return CMD_SUCCESS;
Matthieu Boutier2074d672014-09-10 16:50:42 +0200407}
paul718e3742002-12-13 20:15:29 +0000408
Matthieu Boutierdf2ef242014-09-10 16:50:45 +0200409DEFUN (ipv6_distribute_list,
paulba23a692003-04-19 15:55:08 +0000410 ipv6_distribute_list_cmd,
Matthieu Boutierdf2ef242014-09-10 16:50:45 +0200411 "ipv6 distribute-list WORD (in|out) WORD",
412 "Filter networks in routing updates\n"
413 "Access-list name\n"
414 "Filter incoming routing updates\n"
415 "Filter outgoing routing updates\n"
416 "Interface name\n")
417{
418 enum distribute_type type;
419
420 /* Check of distribute list type. */
421 if (strncmp (argv[1], "i", 1) == 0)
422 type = DISTRIBUTE_V6_IN;
423 else if (strncmp (argv[1], "o", 1) == 0)
424 type = DISTRIBUTE_V6_OUT;
425 else
426 {
427 vty_out (vty, "distribute list direction must be [in|out]%s", VTY_NEWLINE);
428 return CMD_WARNING;
429 }
430
431 /* Get interface name corresponding distribute list. */
432 distribute_list_set (argv[2], type, argv[0]);
433
434 return CMD_SUCCESS;
435}
436
437ALIAS (ipv6_distribute_list,
438 ipv6_as_v4_distribute_list_cmd,
paulba23a692003-04-19 15:55:08 +0000439 "distribute-list WORD (in|out) WORD",
440 "Filter networks in routing updates\n"
441 "Access-list name\n"
442 "Filter incoming routing updates\n"
443 "Filter outgoing routing updates\n"
444 "Interface name\n")
445
Denis Ovsienko0ead5c12011-10-14 20:56:19 +0400446DEFUN (no_distribute_list, no_distribute_list_cmd,
paul718e3742002-12-13 20:15:29 +0000447 "no distribute-list WORD (in|out) WORD",
448 NO_STR
449 "Filter networks in routing updates\n"
450 "Access-list name\n"
451 "Filter incoming routing updates\n"
452 "Filter outgoing routing updates\n"
453 "Interface name\n")
454{
455 int ret;
456 enum distribute_type type;
457
458 /* Check of distribute list type. */
459 if (strncmp (argv[1], "i", 1) == 0)
Matthieu Boutierdf2ef242014-09-10 16:50:45 +0200460 type = DISTRIBUTE_V4_IN;
paul718e3742002-12-13 20:15:29 +0000461 else if (strncmp (argv[1], "o", 1) == 0)
Matthieu Boutierdf2ef242014-09-10 16:50:45 +0200462 type = DISTRIBUTE_V4_OUT;
paul718e3742002-12-13 20:15:29 +0000463 else
464 {
465 vty_out (vty, "distribute list direction must be [in|out]%s", VTY_NEWLINE);
466 return CMD_WARNING;
467 }
468
469 ret = distribute_list_unset (argv[2], type, argv[0]);
470 if (! ret)
471 {
472 vty_out (vty, "distribute list doesn't exist%s", VTY_NEWLINE);
473 return CMD_WARNING;
474 }
475 return CMD_SUCCESS;
Matthieu Boutier2074d672014-09-10 16:50:42 +0200476}
paul718e3742002-12-13 20:15:29 +0000477
Matthieu Boutierdf2ef242014-09-10 16:50:45 +0200478DEFUN (no_ipv6_distribute_list,
479 no_ipv6_distribute_list_cmd,
480 "no ipv6 distribute-list WORD (in|out) WORD",
481 NO_STR
482 "Filter networks in routing updates\n"
483 "Access-list name\n"
484 "Filter incoming routing updates\n"
485 "Filter outgoing routing updates\n"
486 "Interface name\n")
487{
488 int ret;
489 enum distribute_type type;
490
491 /* Check of distribute list type. */
492 if (strncmp (argv[1], "i", 1) == 0)
493 type = DISTRIBUTE_V6_IN;
494 else if (strncmp (argv[1], "o", 1) == 0)
495 type = DISTRIBUTE_V6_OUT;
496 else
497 {
498 vty_out (vty, "distribute list direction must be [in|out]%s", VTY_NEWLINE);
499 return CMD_WARNING;
500 }
501
502 ret = distribute_list_unset (argv[2], type, argv[0]);
503 if (! ret)
504 {
505 vty_out (vty, "distribute list doesn't exist%s", VTY_NEWLINE);
506 return CMD_WARNING;
507 }
508 return CMD_SUCCESS;
509}
510
511ALIAS (no_ipv6_distribute_list,
512 no_ipv6_as_v4_distribute_list_cmd,
paulba23a692003-04-19 15:55:08 +0000513 "no distribute-list WORD (in|out) WORD",
514 NO_STR
515 "Filter networks in routing updates\n"
516 "Access-list name\n"
517 "Filter incoming routing updates\n"
518 "Filter outgoing routing updates\n"
519 "Interface name\n")
520
Denis Ovsienko0ead5c12011-10-14 20:56:19 +0400521DEFUN (distribute_list_prefix_all,
paul718e3742002-12-13 20:15:29 +0000522 distribute_list_prefix_all_cmd,
523 "distribute-list prefix WORD (in|out)",
524 "Filter networks in routing updates\n"
525 "Filter prefixes in routing updates\n"
526 "Name of an IP prefix-list\n"
527 "Filter incoming routing updates\n"
528 "Filter outgoing routing updates\n")
529{
530 enum distribute_type type;
paul718e3742002-12-13 20:15:29 +0000531
532 /* Check of distribute list type. */
533 if (strncmp (argv[1], "i", 1) == 0)
Matthieu Boutierdf2ef242014-09-10 16:50:45 +0200534 type = DISTRIBUTE_V4_IN;
paul718e3742002-12-13 20:15:29 +0000535 else if (strncmp (argv[1], "o", 1) == 0)
Matthieu Boutierdf2ef242014-09-10 16:50:45 +0200536 type = DISTRIBUTE_V4_OUT;
paul718e3742002-12-13 20:15:29 +0000537 else
538 {
Matthieu Boutierdf2ef242014-09-10 16:50:45 +0200539 vty_out (vty, "distribute list direction must be [in|out]%s",
paul718e3742002-12-13 20:15:29 +0000540 VTY_NEWLINE);
541 return CMD_WARNING;
542 }
543
544 /* Get interface name corresponding distribute list. */
Stephen Hemminger9206f9e2011-12-18 19:43:40 +0400545 distribute_list_prefix_set (NULL, type, argv[0]);
paul718e3742002-12-13 20:15:29 +0000546
547 return CMD_SUCCESS;
Matthieu Boutier2074d672014-09-10 16:50:42 +0200548}
paul718e3742002-12-13 20:15:29 +0000549
Matthieu Boutierdf2ef242014-09-10 16:50:45 +0200550DEFUN (ipv6_distribute_list_prefix_all,
paulba23a692003-04-19 15:55:08 +0000551 ipv6_distribute_list_prefix_all_cmd,
Matthieu Boutierdf2ef242014-09-10 16:50:45 +0200552 "ipv6 distribute-list prefix WORD (in|out)",
553 "Filter networks in routing updates\n"
554 "Filter prefixes in routing updates\n"
555 "Name of an IP prefix-list\n"
556 "Filter incoming routing updates\n"
557 "Filter outgoing routing updates\n")
558{
559 enum distribute_type type;
560
561 /* Check of distribute list type. */
562 if (strncmp (argv[1], "i", 1) == 0)
563 type = DISTRIBUTE_V6_IN;
564 else if (strncmp (argv[1], "o", 1) == 0)
565 type = DISTRIBUTE_V6_OUT;
566 else
567 {
568 vty_out (vty, "distribute list direction must be [in|out]%s",
569 VTY_NEWLINE);
570 return CMD_WARNING;
571 }
572
573 /* Get interface name corresponding distribute list. */
574 distribute_list_prefix_set (NULL, type, argv[0]);
575
576 return CMD_SUCCESS;
577}
578
579ALIAS (ipv6_distribute_list_prefix_all,
580 ipv6_as_v4_distribute_list_prefix_all_cmd,
paulba23a692003-04-19 15:55:08 +0000581 "distribute-list prefix WORD (in|out)",
582 "Filter networks in routing updates\n"
583 "Filter prefixes in routing updates\n"
584 "Name of an IP prefix-list\n"
585 "Filter incoming routing updates\n"
586 "Filter outgoing routing updates\n")
587
Denis Ovsienko0ead5c12011-10-14 20:56:19 +0400588DEFUN (no_distribute_list_prefix_all,
paul718e3742002-12-13 20:15:29 +0000589 no_distribute_list_prefix_all_cmd,
590 "no distribute-list prefix WORD (in|out)",
591 NO_STR
592 "Filter networks in routing updates\n"
593 "Filter prefixes in routing updates\n"
594 "Name of an IP prefix-list\n"
595 "Filter incoming routing updates\n"
596 "Filter outgoing routing updates\n")
597{
598 int ret;
599 enum distribute_type type;
600
601 /* Check of distribute list type. */
602 if (strncmp (argv[1], "i", 1) == 0)
Matthieu Boutierdf2ef242014-09-10 16:50:45 +0200603 type = DISTRIBUTE_V4_IN;
paul718e3742002-12-13 20:15:29 +0000604 else if (strncmp (argv[1], "o", 1) == 0)
Matthieu Boutierdf2ef242014-09-10 16:50:45 +0200605 type = DISTRIBUTE_V4_OUT;
paul718e3742002-12-13 20:15:29 +0000606 else
607 {
Matthieu Boutierdf2ef242014-09-10 16:50:45 +0200608 vty_out (vty, "distribute list direction must be [in|out]%s",
paul718e3742002-12-13 20:15:29 +0000609 VTY_NEWLINE);
610 return CMD_WARNING;
611 }
612
613 ret = distribute_list_prefix_unset (NULL, type, argv[0]);
614 if (! ret)
615 {
616 vty_out (vty, "distribute list doesn't exist%s", VTY_NEWLINE);
617 return CMD_WARNING;
618 }
619 return CMD_SUCCESS;
Matthieu Boutier2074d672014-09-10 16:50:42 +0200620}
paul718e3742002-12-13 20:15:29 +0000621
Matthieu Boutierdf2ef242014-09-10 16:50:45 +0200622DEFUN (no_ipv6_distribute_list_prefix_all,
paulba23a692003-04-19 15:55:08 +0000623 no_ipv6_distribute_list_prefix_all_cmd,
Matthieu Boutierdf2ef242014-09-10 16:50:45 +0200624 "no ipv6 distribute-list prefix WORD (in|out)",
625 NO_STR
626 "Filter networks in routing updates\n"
627 "Filter prefixes in routing updates\n"
628 "Name of an IP prefix-list\n"
629 "Filter incoming routing updates\n"
630 "Filter outgoing routing updates\n")
631{
632 int ret;
633 enum distribute_type type;
634
635 /* Check of distribute list type. */
636 if (strncmp (argv[1], "i", 1) == 0)
637 type = DISTRIBUTE_V6_IN;
638 else if (strncmp (argv[1], "o", 1) == 0)
639 type = DISTRIBUTE_V6_OUT;
640 else
641 {
642 vty_out (vty, "distribute list direction must be [in|out]%s",
643 VTY_NEWLINE);
644 return CMD_WARNING;
645 }
646
647 ret = distribute_list_prefix_unset (NULL, type, argv[0]);
648 if (! ret)
649 {
650 vty_out (vty, "distribute list doesn't exist%s", VTY_NEWLINE);
651 return CMD_WARNING;
652 }
653 return CMD_SUCCESS;
654}
655
656ALIAS (no_ipv6_distribute_list_prefix_all,
657 no_ipv6_as_v4_distribute_list_prefix_all_cmd,
paulba23a692003-04-19 15:55:08 +0000658 "no distribute-list prefix WORD (in|out)",
659 NO_STR
660 "Filter networks in routing updates\n"
661 "Filter prefixes in routing updates\n"
662 "Name of an IP prefix-list\n"
663 "Filter incoming routing updates\n"
664 "Filter outgoing routing updates\n")
665
Denis Ovsienko0ead5c12011-10-14 20:56:19 +0400666DEFUN (distribute_list_prefix, distribute_list_prefix_cmd,
paul718e3742002-12-13 20:15:29 +0000667 "distribute-list prefix WORD (in|out) WORD",
668 "Filter networks in routing updates\n"
669 "Filter prefixes in routing updates\n"
670 "Name of an IP prefix-list\n"
671 "Filter incoming routing updates\n"
672 "Filter outgoing routing updates\n"
673 "Interface name\n")
674{
675 enum distribute_type type;
paul718e3742002-12-13 20:15:29 +0000676
677 /* Check of distribute list type. */
678 if (strncmp (argv[1], "i", 1) == 0)
Matthieu Boutierdf2ef242014-09-10 16:50:45 +0200679 type = DISTRIBUTE_V4_IN;
paul718e3742002-12-13 20:15:29 +0000680 else if (strncmp (argv[1], "o", 1) == 0)
Matthieu Boutierdf2ef242014-09-10 16:50:45 +0200681 type = DISTRIBUTE_V4_OUT;
paul718e3742002-12-13 20:15:29 +0000682 else
683 {
Matthieu Boutierdf2ef242014-09-10 16:50:45 +0200684 vty_out (vty, "distribute list direction must be [in|out]%s",
paul718e3742002-12-13 20:15:29 +0000685 VTY_NEWLINE);
686 return CMD_WARNING;
687 }
688
689 /* Get interface name corresponding distribute list. */
Stephen Hemminger9206f9e2011-12-18 19:43:40 +0400690 distribute_list_prefix_set (argv[2], type, argv[0]);
paul718e3742002-12-13 20:15:29 +0000691
692 return CMD_SUCCESS;
Matthieu Boutier2074d672014-09-10 16:50:42 +0200693}
paul718e3742002-12-13 20:15:29 +0000694
Matthieu Boutierdf2ef242014-09-10 16:50:45 +0200695DEFUN (ipv6_distribute_list_prefix,
696 ipv6_distribute_list_prefix_cmd,
697 "ipv6 distribute-list prefix WORD (in|out) WORD",
698 "Filter networks in routing updates\n"
699 "Filter prefixes in routing updates\n"
700 "Name of an IP prefix-list\n"
701 "Filter incoming routing updates\n"
702 "Filter outgoing routing updates\n"
703 "Interface name\n")
704{
705 enum distribute_type type;
706
707 /* Check of distribute list type. */
708 if (strncmp (argv[1], "i", 1) == 0)
709 type = DISTRIBUTE_V6_IN;
710 else if (strncmp (argv[1], "o", 1) == 0)
711 type = DISTRIBUTE_V6_OUT;
712 else
713 {
714 vty_out (vty, "distribute list direction must be [in|out]%s",
715 VTY_NEWLINE);
716 return CMD_WARNING;
717 }
718
719 /* Get interface name corresponding distribute list. */
720 distribute_list_prefix_set (argv[2], type, argv[0]);
721
722 return CMD_SUCCESS;
723}
724
725ALIAS (ipv6_distribute_list_prefix,
726 ipv6_as_v4_distribute_list_prefix_cmd,
paulba23a692003-04-19 15:55:08 +0000727 "distribute-list prefix WORD (in|out) WORD",
728 "Filter networks in routing updates\n"
729 "Filter prefixes in routing updates\n"
730 "Name of an IP prefix-list\n"
731 "Filter incoming routing updates\n"
732 "Filter outgoing routing updates\n"
733 "Interface name\n")
734
Denis Ovsienko0ead5c12011-10-14 20:56:19 +0400735DEFUN (no_distribute_list_prefix, no_distribute_list_prefix_cmd,
paul718e3742002-12-13 20:15:29 +0000736 "no distribute-list prefix WORD (in|out) WORD",
737 NO_STR
738 "Filter networks in routing updates\n"
739 "Filter prefixes in routing updates\n"
740 "Name of an IP prefix-list\n"
741 "Filter incoming routing updates\n"
742 "Filter outgoing routing updates\n"
743 "Interface name\n")
744{
745 int ret;
746 enum distribute_type type;
747
748 /* Check of distribute list type. */
749 if (strncmp (argv[1], "i", 1) == 0)
Matthieu Boutierdf2ef242014-09-10 16:50:45 +0200750 type = DISTRIBUTE_V4_IN;
paul718e3742002-12-13 20:15:29 +0000751 else if (strncmp (argv[1], "o", 1) == 0)
Matthieu Boutierdf2ef242014-09-10 16:50:45 +0200752 type = DISTRIBUTE_V4_OUT;
paul718e3742002-12-13 20:15:29 +0000753 else
754 {
Matthieu Boutierdf2ef242014-09-10 16:50:45 +0200755 vty_out (vty, "distribute list direction must be [in|out]%s",
paul718e3742002-12-13 20:15:29 +0000756 VTY_NEWLINE);
757 return CMD_WARNING;
758 }
759
760 ret = distribute_list_prefix_unset (argv[2], type, argv[0]);
761 if (! ret)
762 {
763 vty_out (vty, "distribute list doesn't exist%s", VTY_NEWLINE);
764 return CMD_WARNING;
765 }
766 return CMD_SUCCESS;
Matthieu Boutier2074d672014-09-10 16:50:42 +0200767}
paul718e3742002-12-13 20:15:29 +0000768
Matthieu Boutierdf2ef242014-09-10 16:50:45 +0200769DEFUN (no_ipv6_distribute_list_prefix,
770 no_ipv6_distribute_list_prefix_cmd,
771 "no ipv6 distribute-list prefix WORD (in|out) WORD",
772 NO_STR
773 "Filter networks in routing updates\n"
774 "Filter prefixes in routing updates\n"
775 "Name of an IP prefix-list\n"
776 "Filter incoming routing updates\n"
777 "Filter outgoing routing updates\n"
778 "Interface name\n")
779{
780 int ret;
781 enum distribute_type type;
782
783 /* Check of distribute list type. */
784 if (strncmp (argv[1], "i", 1) == 0)
785 type = DISTRIBUTE_V6_IN;
786 else if (strncmp (argv[1], "o", 1) == 0)
787 type = DISTRIBUTE_V6_OUT;
788 else
789 {
790 vty_out (vty, "distribute list direction must be [in|out]%s",
791 VTY_NEWLINE);
792 return CMD_WARNING;
793 }
794
795 ret = distribute_list_prefix_unset (argv[2], type, argv[0]);
796 if (! ret)
797 {
798 vty_out (vty, "distribute list doesn't exist%s", VTY_NEWLINE);
799 return CMD_WARNING;
800 }
801 return CMD_SUCCESS;
802}
803
804ALIAS (no_ipv6_distribute_list_prefix,
805 no_ipv6_as_v4_distribute_list_prefix_cmd,
paulba23a692003-04-19 15:55:08 +0000806 "no distribute-list prefix WORD (in|out) WORD",
807 NO_STR
808 "Filter networks in routing updates\n"
809 "Filter prefixes in routing updates\n"
810 "Name of an IP prefix-list\n"
811 "Filter incoming routing updates\n"
812 "Filter outgoing routing updates\n"
813 "Interface name\n")
814
Matthieu Boutier2074d672014-09-10 16:50:42 +0200815static int
816distribute_print (struct vty *vty, char *tab[], int is_prefix,
817 enum distribute_type type, int has_print)
818{
819 if (tab[type]) {
820 vty_out (vty, "%s %s%s",
821 has_print ? "," : "",
822 is_prefix ? "(prefix-list) " : "",
823 tab[type]);
824 return 1;
825 }
826 return has_print;
827}
828
paul718e3742002-12-13 20:15:29 +0000829int
830config_show_distribute (struct vty *vty)
831{
hasso8c328f12004-10-05 21:01:23 +0000832 unsigned int i;
Matthieu Boutier2074d672014-09-10 16:50:42 +0200833 int has_print = 0;
paul718e3742002-12-13 20:15:29 +0000834 struct hash_backet *mp;
835 struct distribute *dist;
836
837 /* Output filter configuration. */
838 dist = distribute_lookup (NULL);
Matthieu Boutier2074d672014-09-10 16:50:42 +0200839 vty_out(vty, " Outgoing update filter list for all interface is");
840 has_print = 0;
841 if (dist)
paul718e3742002-12-13 20:15:29 +0000842 {
Matthieu Boutier2074d672014-09-10 16:50:42 +0200843 has_print = distribute_print(vty, dist->list, 0,
Matthieu Boutierdf2ef242014-09-10 16:50:45 +0200844 DISTRIBUTE_V4_OUT, has_print);
Matthieu Boutier2074d672014-09-10 16:50:42 +0200845 has_print = distribute_print(vty, dist->prefix, 1,
Matthieu Boutierdf2ef242014-09-10 16:50:45 +0200846 DISTRIBUTE_V4_OUT, has_print);
847 has_print = distribute_print(vty, dist->list, 0,
848 DISTRIBUTE_V6_OUT, has_print);
849 has_print = distribute_print(vty, dist->prefix, 1,
850 DISTRIBUTE_V6_OUT, has_print);
paul718e3742002-12-13 20:15:29 +0000851 }
Matthieu Boutier2074d672014-09-10 16:50:42 +0200852 if (has_print)
853 vty_out (vty, "%s", VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +0000854 else
Matthieu Boutier2074d672014-09-10 16:50:42 +0200855 vty_out (vty, " not set%s", VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +0000856
857 for (i = 0; i < disthash->size; i++)
858 for (mp = disthash->index[i]; mp; mp = mp->next)
859 {
860 dist = mp->data;
861 if (dist->ifname)
Matthieu Boutier2074d672014-09-10 16:50:42 +0200862 {
863 vty_out (vty, " %s filtered by", dist->ifname);
864 has_print = 0;
865 has_print = distribute_print(vty, dist->list, 0,
Matthieu Boutierdf2ef242014-09-10 16:50:45 +0200866 DISTRIBUTE_V4_OUT, has_print);
Matthieu Boutier2074d672014-09-10 16:50:42 +0200867 has_print = distribute_print(vty, dist->prefix, 1,
Matthieu Boutierdf2ef242014-09-10 16:50:45 +0200868 DISTRIBUTE_V4_OUT, has_print);
869 has_print = distribute_print(vty, dist->list, 0,
870 DISTRIBUTE_V6_OUT, has_print);
871 has_print = distribute_print(vty, dist->prefix, 1,
872 DISTRIBUTE_V6_OUT, has_print);
Matthieu Boutier2074d672014-09-10 16:50:42 +0200873 if (has_print)
874 vty_out (vty, "%s", VTY_NEWLINE);
875 else
876 vty_out(vty, " nothing%s", VTY_NEWLINE);
877 }
paul718e3742002-12-13 20:15:29 +0000878 }
879
880
881 /* Input filter configuration. */
882 dist = distribute_lookup (NULL);
Matthieu Boutier2074d672014-09-10 16:50:42 +0200883 vty_out(vty, " Incoming update filter list for all interface is");
884 has_print = 0;
885 if (dist)
paul718e3742002-12-13 20:15:29 +0000886 {
Matthieu Boutier2074d672014-09-10 16:50:42 +0200887 has_print = distribute_print(vty, dist->list, 0,
Matthieu Boutierdf2ef242014-09-10 16:50:45 +0200888 DISTRIBUTE_V4_IN, has_print);
Matthieu Boutier2074d672014-09-10 16:50:42 +0200889 has_print = distribute_print(vty, dist->prefix, 1,
Matthieu Boutierdf2ef242014-09-10 16:50:45 +0200890 DISTRIBUTE_V4_IN, has_print);
891 has_print = distribute_print(vty, dist->list, 0,
892 DISTRIBUTE_V6_IN, has_print);
893 has_print = distribute_print(vty, dist->prefix, 1,
894 DISTRIBUTE_V6_IN, has_print);
895 }
Matthieu Boutier2074d672014-09-10 16:50:42 +0200896 if (has_print)
897 vty_out (vty, "%s", VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +0000898 else
Matthieu Boutier2074d672014-09-10 16:50:42 +0200899 vty_out (vty, " not set%s", VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +0000900
901 for (i = 0; i < disthash->size; i++)
902 for (mp = disthash->index[i]; mp; mp = mp->next)
903 {
904 dist = mp->data;
Matthieu Boutier2074d672014-09-10 16:50:42 +0200905 if (dist->ifname)
906 {
907 vty_out (vty, " %s filtered by", dist->ifname);
908 has_print = 0;
909 has_print = distribute_print(vty, dist->list, 0,
Matthieu Boutierdf2ef242014-09-10 16:50:45 +0200910 DISTRIBUTE_V4_IN, has_print);
Matthieu Boutier2074d672014-09-10 16:50:42 +0200911 has_print = distribute_print(vty, dist->prefix, 1,
Matthieu Boutierdf2ef242014-09-10 16:50:45 +0200912 DISTRIBUTE_V4_IN, has_print);
913 has_print = distribute_print(vty, dist->list, 0,
914 DISTRIBUTE_V6_IN, has_print);
915 has_print = distribute_print(vty, dist->prefix, 1,
916 DISTRIBUTE_V6_IN, has_print);
Matthieu Boutier2074d672014-09-10 16:50:42 +0200917 if (has_print)
918 vty_out (vty, "%s", VTY_NEWLINE);
919 else
920 vty_out(vty, " nothing%s", VTY_NEWLINE);
921 }
paul718e3742002-12-13 20:15:29 +0000922 }
923 return 0;
924}
925
926/* Configuration write function. */
927int
928config_write_distribute (struct vty *vty)
929{
hasso8c328f12004-10-05 21:01:23 +0000930 unsigned int i;
Matthieu Boutier2074d672014-09-10 16:50:42 +0200931 int j;
Matthieu Boutierdf2ef242014-09-10 16:50:45 +0200932 int output, v6;
paul718e3742002-12-13 20:15:29 +0000933 struct hash_backet *mp;
934 int write = 0;
935
936 for (i = 0; i < disthash->size; i++)
937 for (mp = disthash->index[i]; mp; mp = mp->next)
938 {
939 struct distribute *dist;
940
941 dist = mp->data;
942
Matthieu Boutier2074d672014-09-10 16:50:42 +0200943 for (j=0; j < DISTRIBUTE_MAX; j++)
944 if (dist->list[j]) {
Matthieu Boutierdf2ef242014-09-10 16:50:45 +0200945 output = j == DISTRIBUTE_V4_OUT || j == DISTRIBUTE_V6_OUT;
946 v6 = j == DISTRIBUTE_V6_IN || j == DISTRIBUTE_V6_OUT;
947 vty_out (vty, " %sdistribute-list %s %s %s%s",
948 v6 ? "ipv6 " : "",
Matthieu Boutier2074d672014-09-10 16:50:42 +0200949 dist->list[j],
950 output ? "out" : "in",
paul718e3742002-12-13 20:15:29 +0000951 dist->ifname ? dist->ifname : "",
952 VTY_NEWLINE);
953 write++;
954 }
955
Matthieu Boutier2074d672014-09-10 16:50:42 +0200956 for (j=0; j < DISTRIBUTE_MAX; j++)
957 if (dist->prefix[j]) {
Matthieu Boutierdf2ef242014-09-10 16:50:45 +0200958 output = j == DISTRIBUTE_V4_OUT || j == DISTRIBUTE_V6_OUT;
959 v6 = j == DISTRIBUTE_V6_IN || j == DISTRIBUTE_V6_OUT;
960 vty_out (vty, " %sdistribute-list prefix %s %s %s%s",
961 v6 ? "ipv6 " : "",
Matthieu Boutier2074d672014-09-10 16:50:42 +0200962 dist->prefix[j],
963 output ? "out" : "in",
paul718e3742002-12-13 20:15:29 +0000964 dist->ifname ? dist->ifname : "",
965 VTY_NEWLINE);
966 write++;
967 }
968 }
969 return write;
970}
971
972/* Clear all distribute list. */
973void
974distribute_list_reset ()
975{
976 hash_clean (disthash, (void (*) (void *)) distribute_free);
977}
978
979/* Initialize distribute list related hash. */
980void
981distribute_list_init (int node)
982{
Stephen Hemminger6392aa82010-08-27 14:11:14 -0700983 disthash = hash_create (distribute_hash_make,
Stephen Hemmingerffe11cf2008-08-14 16:25:25 +0100984 (int (*) (const void *, const void *)) distribute_cmp);
Matthieu Boutierdf2ef242014-09-10 16:50:45 +0200985 /* install v4 */
986 if (node == RIP_NODE || node == BABEL_NODE) {
Paul Jakma57345092011-12-25 17:52:09 +0100987 install_element (node, &distribute_list_all_cmd);
988 install_element (node, &no_distribute_list_all_cmd);
989 install_element (node, &distribute_list_cmd);
990 install_element (node, &no_distribute_list_cmd);
991 install_element (node, &distribute_list_prefix_all_cmd);
992 install_element (node, &no_distribute_list_prefix_all_cmd);
993 install_element (node, &distribute_list_prefix_cmd);
994 install_element (node, &no_distribute_list_prefix_cmd);
Matthieu Boutierdf2ef242014-09-10 16:50:45 +0200995 }
996
997 /* install v6 */
998 if (node == RIPNG_NODE || node == BABEL_NODE) {
Paul Jakma57345092011-12-25 17:52:09 +0100999 install_element (node, &ipv6_distribute_list_all_cmd);
1000 install_element (node, &no_ipv6_distribute_list_all_cmd);
1001 install_element (node, &ipv6_distribute_list_cmd);
1002 install_element (node, &no_ipv6_distribute_list_cmd);
1003 install_element (node, &ipv6_distribute_list_prefix_all_cmd);
1004 install_element (node, &no_ipv6_distribute_list_prefix_all_cmd);
1005 install_element (node, &ipv6_distribute_list_prefix_cmd);
1006 install_element (node, &no_ipv6_distribute_list_prefix_cmd);
paulba23a692003-04-19 15:55:08 +00001007 }
Matthieu Boutierdf2ef242014-09-10 16:50:45 +02001008
1009 /* install v4 syntax command for v6 only protocols. */
1010 if (node == RIPNG_NODE) {
1011 install_element (node, &ipv6_as_v4_distribute_list_all_cmd);
1012 install_element (node, &no_ipv6_as_v4_distribute_list_all_cmd);
1013 install_element (node, &ipv6_as_v4_distribute_list_cmd);
1014 install_element (node, &no_ipv6_as_v4_distribute_list_cmd);
1015 install_element (node, &ipv6_as_v4_distribute_list_prefix_all_cmd);
1016 install_element (node, &no_ipv6_as_v4_distribute_list_prefix_all_cmd);
1017 install_element (node, &ipv6_as_v4_distribute_list_prefix_cmd);
1018 install_element (node, &no_ipv6_as_v4_distribute_list_prefix_cmd);
1019 }
paul718e3742002-12-13 20:15:29 +00001020}