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