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