1 /* Distribute list functions
2 * Copyright (C) 1998, 1999 Kunihiro Ishiguro
4 * This file is part of GNU Zebra.
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.
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.
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.
28 #include "distribute.h"
31 /* Hash of distribute list. */
32 struct hash
*disthash
;
35 void (*distribute_add_hook
) (struct distribute
*);
36 void (*distribute_delete_hook
) (struct distribute
*);
38 static struct distribute
*
41 struct distribute
*new;
43 new = XMALLOC (MTYPE_DISTRIBUTE
, sizeof (struct distribute
));
44 memset (new, 0, sizeof (struct distribute
));
49 /* Free distribute object. */
51 distribute_free (struct distribute
*dist
)
54 XFREE (MTYPE_DISTRIBUTE_IFNAME
, dist
->ifname
);
56 if (dist
->list
[DISTRIBUTE_IN
])
57 free (dist
->list
[DISTRIBUTE_IN
]);
58 if (dist
->list
[DISTRIBUTE_OUT
])
59 free (dist
->list
[DISTRIBUTE_OUT
]);
61 if (dist
->prefix
[DISTRIBUTE_IN
])
62 free (dist
->prefix
[DISTRIBUTE_IN
]);
63 if (dist
->prefix
[DISTRIBUTE_OUT
])
64 free (dist
->prefix
[DISTRIBUTE_OUT
]);
66 XFREE (MTYPE_DISTRIBUTE
, dist
);
69 /* Lookup interface's distribute list. */
71 distribute_lookup (const char *ifname
)
73 struct distribute key
;
74 struct distribute
*dist
;
76 /* temporary reference */
77 key
.ifname
= (char *)ifname
;
79 dist
= hash_lookup (disthash
, &key
);
85 distribute_list_add_hook (void (*func
) (struct distribute
*))
87 distribute_add_hook
= func
;
91 distribute_list_delete_hook (void (*func
) (struct distribute
*))
93 distribute_delete_hook
= func
;
97 distribute_hash_alloc (struct distribute
*arg
)
99 struct distribute
*dist
;
101 dist
= distribute_new ();
103 dist
->ifname
= XSTRDUP (MTYPE_DISTRIBUTE_IFNAME
, arg
->ifname
);
109 /* Make new distribute list and push into hash. */
110 static struct distribute
*
111 distribute_get (const char *ifname
)
113 struct distribute key
;
115 /* temporary reference */
116 key
.ifname
= (char *)ifname
;
118 return hash_get (disthash
, &key
, (void * (*) (void *))distribute_hash_alloc
);
122 distribute_hash_make (struct distribute
*dist
)
128 for (i
= 0; i
< strlen (dist
->ifname
); i
++)
129 key
+= dist
->ifname
[i
];
134 /* If two distribute-list have same value then return 1 else return
135 0. This function is used by hash package. */
137 distribute_cmp (struct distribute
*dist1
, struct distribute
*dist2
)
139 if (dist1
->ifname
&& dist2
->ifname
)
140 if (strcmp (dist1
->ifname
, dist2
->ifname
) == 0)
142 if (! dist1
->ifname
&& ! dist2
->ifname
)
147 /* Set access-list name to the distribute list. */
148 static struct distribute
*
149 distribute_list_set (const char *ifname
, enum distribute_type type
,
150 const char *alist_name
)
152 struct distribute
*dist
;
154 dist
= distribute_get (ifname
);
156 if (type
== DISTRIBUTE_IN
)
158 if (dist
->list
[DISTRIBUTE_IN
])
159 free (dist
->list
[DISTRIBUTE_IN
]);
160 dist
->list
[DISTRIBUTE_IN
] = strdup (alist_name
);
162 if (type
== DISTRIBUTE_OUT
)
164 if (dist
->list
[DISTRIBUTE_OUT
])
165 free (dist
->list
[DISTRIBUTE_OUT
]);
166 dist
->list
[DISTRIBUTE_OUT
] = strdup (alist_name
);
169 /* Apply this distribute-list to the interface. */
170 (*distribute_add_hook
) (dist
);
175 /* Unset distribute-list. If matched distribute-list exist then
178 distribute_list_unset (const char *ifname
, enum distribute_type type
,
179 const char *alist_name
)
181 struct distribute
*dist
;
183 dist
= distribute_lookup (ifname
);
187 if (type
== DISTRIBUTE_IN
)
189 if (!dist
->list
[DISTRIBUTE_IN
])
191 if (strcmp (dist
->list
[DISTRIBUTE_IN
], alist_name
) != 0)
194 free (dist
->list
[DISTRIBUTE_IN
]);
195 dist
->list
[DISTRIBUTE_IN
] = NULL
;
198 if (type
== DISTRIBUTE_OUT
)
200 if (!dist
->list
[DISTRIBUTE_OUT
])
202 if (strcmp (dist
->list
[DISTRIBUTE_OUT
], alist_name
) != 0)
205 free (dist
->list
[DISTRIBUTE_OUT
]);
206 dist
->list
[DISTRIBUTE_OUT
] = NULL
;
209 /* Apply this distribute-list to the interface. */
210 (*distribute_delete_hook
) (dist
);
212 /* If both out and in is NULL then free distribute list. */
213 if (dist
->list
[DISTRIBUTE_IN
] == NULL
&&
214 dist
->list
[DISTRIBUTE_OUT
] == NULL
&&
215 dist
->prefix
[DISTRIBUTE_IN
] == NULL
&&
216 dist
->prefix
[DISTRIBUTE_OUT
] == NULL
)
218 hash_release (disthash
, dist
);
219 distribute_free (dist
);
225 /* Set access-list name to the distribute list. */
226 static struct distribute
*
227 distribute_list_prefix_set (const char *ifname
, enum distribute_type type
,
228 const char *plist_name
)
230 struct distribute
*dist
;
232 dist
= distribute_get (ifname
);
234 if (type
== DISTRIBUTE_IN
)
236 if (dist
->prefix
[DISTRIBUTE_IN
])
237 free (dist
->prefix
[DISTRIBUTE_IN
]);
238 dist
->prefix
[DISTRIBUTE_IN
] = strdup (plist_name
);
240 if (type
== DISTRIBUTE_OUT
)
242 if (dist
->prefix
[DISTRIBUTE_OUT
])
243 free (dist
->prefix
[DISTRIBUTE_OUT
]);
244 dist
->prefix
[DISTRIBUTE_OUT
] = strdup (plist_name
);
247 /* Apply this distribute-list to the interface. */
248 (*distribute_add_hook
) (dist
);
253 /* Unset distribute-list. If matched distribute-list exist then
256 distribute_list_prefix_unset (const char *ifname
, enum distribute_type type
,
257 const char *plist_name
)
259 struct distribute
*dist
;
261 dist
= distribute_lookup (ifname
);
265 if (type
== DISTRIBUTE_IN
)
267 if (!dist
->prefix
[DISTRIBUTE_IN
])
269 if (strcmp (dist
->prefix
[DISTRIBUTE_IN
], plist_name
) != 0)
272 free (dist
->prefix
[DISTRIBUTE_IN
]);
273 dist
->prefix
[DISTRIBUTE_IN
] = NULL
;
276 if (type
== DISTRIBUTE_OUT
)
278 if (!dist
->prefix
[DISTRIBUTE_OUT
])
280 if (strcmp (dist
->prefix
[DISTRIBUTE_OUT
], plist_name
) != 0)
283 free (dist
->prefix
[DISTRIBUTE_OUT
]);
284 dist
->prefix
[DISTRIBUTE_OUT
] = NULL
;
287 /* Apply this distribute-list to the interface. */
288 (*distribute_delete_hook
) (dist
);
290 /* If both out and in is NULL then free distribute list. */
291 if (dist
->list
[DISTRIBUTE_IN
] == NULL
&&
292 dist
->list
[DISTRIBUTE_OUT
] == NULL
&&
293 dist
->prefix
[DISTRIBUTE_IN
] == NULL
&&
294 dist
->prefix
[DISTRIBUTE_OUT
] == NULL
)
296 hash_release (disthash
, dist
);
297 distribute_free (dist
);
303 DEFUN (distribute_list_all
,
304 distribute_list_all_cmd
,
305 "distribute-list WORD (in|out)",
306 "Filter networks in routing updates\n"
308 "Filter incoming routing updates\n"
309 "Filter outgoing routing updates\n")
311 enum distribute_type type
;
312 struct distribute
*dist
;
314 /* Check of distribute list type. */
315 if (strncmp (argv
[1], "i", 1) == 0)
316 type
= DISTRIBUTE_IN
;
317 else if (strncmp (argv
[1], "o", 1) == 0)
318 type
= DISTRIBUTE_OUT
;
321 vty_out (vty
, "distribute list direction must be [in|out]%s",
326 /* Get interface name corresponding distribute list. */
327 dist
= distribute_list_set (NULL
, type
, argv
[0]);
332 ALIAS (distribute_list_all
,
333 ipv6_distribute_list_all_cmd
,
334 "distribute-list WORD (in|out)",
335 "Filter networks in routing updates\n"
337 "Filter incoming routing updates\n"
338 "Filter outgoing routing updates\n")
340 DEFUN (no_distribute_list_all
,
341 no_distribute_list_all_cmd
,
342 "no distribute-list WORD (in|out)",
344 "Filter networks in routing updates\n"
346 "Filter incoming routing updates\n"
347 "Filter outgoing routing updates\n")
350 enum distribute_type type
;
352 /* Check of distribute list type. */
353 if (strncmp (argv
[1], "i", 1) == 0)
354 type
= DISTRIBUTE_IN
;
355 else if (strncmp (argv
[1], "o", 1) == 0)
356 type
= DISTRIBUTE_OUT
;
359 vty_out (vty
, "distribute list direction must be [in|out]%s",
364 ret
= distribute_list_unset (NULL
, type
, argv
[0]);
367 vty_out (vty
, "distribute list doesn't exist%s", VTY_NEWLINE
);
373 ALIAS (no_distribute_list_all
,
374 no_ipv6_distribute_list_all_cmd
,
375 "no distribute-list WORD (in|out)",
377 "Filter networks in routing updates\n"
379 "Filter incoming routing updates\n"
380 "Filter outgoing routing updates\n")
382 DEFUN (distribute_list
,
384 "distribute-list WORD (in|out) WORD",
385 "Filter networks in routing updates\n"
387 "Filter incoming routing updates\n"
388 "Filter outgoing routing updates\n"
391 enum distribute_type type
;
392 struct distribute
*dist
;
394 /* Check of distribute list type. */
395 if (strncmp (argv
[1], "i", 1) == 0)
396 type
= DISTRIBUTE_IN
;
397 else if (strncmp (argv
[1], "o", 1) == 0)
398 type
= DISTRIBUTE_OUT
;
401 vty_out (vty
, "distribute list direction must be [in|out]%s", VTY_NEWLINE
);
405 /* Get interface name corresponding distribute list. */
406 dist
= distribute_list_set (argv
[2], type
, argv
[0]);
411 ALIAS (distribute_list
,
412 ipv6_distribute_list_cmd
,
413 "distribute-list WORD (in|out) WORD",
414 "Filter networks in routing updates\n"
416 "Filter incoming routing updates\n"
417 "Filter outgoing routing updates\n"
420 DEFUN (no_districute_list
, no_distribute_list_cmd
,
421 "no distribute-list WORD (in|out) WORD",
423 "Filter networks in routing updates\n"
425 "Filter incoming routing updates\n"
426 "Filter outgoing routing updates\n"
430 enum distribute_type type
;
432 /* Check of distribute list type. */
433 if (strncmp (argv
[1], "i", 1) == 0)
434 type
= DISTRIBUTE_IN
;
435 else if (strncmp (argv
[1], "o", 1) == 0)
436 type
= DISTRIBUTE_OUT
;
439 vty_out (vty
, "distribute list direction must be [in|out]%s", VTY_NEWLINE
);
443 ret
= distribute_list_unset (argv
[2], type
, argv
[0]);
446 vty_out (vty
, "distribute list doesn't exist%s", VTY_NEWLINE
);
452 ALIAS (no_districute_list
, no_ipv6_distribute_list_cmd
,
453 "no distribute-list WORD (in|out) WORD",
455 "Filter networks in routing updates\n"
457 "Filter incoming routing updates\n"
458 "Filter outgoing routing updates\n"
461 DEFUN (districute_list_prefix_all
,
462 distribute_list_prefix_all_cmd
,
463 "distribute-list prefix WORD (in|out)",
464 "Filter networks in routing updates\n"
465 "Filter prefixes in routing updates\n"
466 "Name of an IP prefix-list\n"
467 "Filter incoming routing updates\n"
468 "Filter outgoing routing updates\n")
470 enum distribute_type type
;
471 struct distribute
*dist
;
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
;
480 vty_out (vty
, "distribute list direction must be [in|out]%s",
485 /* Get interface name corresponding distribute list. */
486 dist
= distribute_list_prefix_set (NULL
, type
, argv
[0]);
491 ALIAS (districute_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")
500 DEFUN (no_districute_list_prefix_all
,
501 no_distribute_list_prefix_all_cmd
,
502 "no distribute-list prefix WORD (in|out)",
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")
511 enum distribute_type type
;
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
;
520 vty_out (vty
, "distribute list direction must be [in|out]%s",
525 ret
= distribute_list_prefix_unset (NULL
, type
, argv
[0]);
528 vty_out (vty
, "distribute list doesn't exist%s", VTY_NEWLINE
);
534 ALIAS (no_districute_list_prefix_all
,
535 no_ipv6_distribute_list_prefix_all_cmd
,
536 "no distribute-list prefix WORD (in|out)",
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")
544 DEFUN (districute_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"
553 enum distribute_type type
;
554 struct distribute
*dist
;
556 /* Check of distribute list type. */
557 if (strncmp (argv
[1], "i", 1) == 0)
558 type
= DISTRIBUTE_IN
;
559 else if (strncmp (argv
[1], "o", 1) == 0)
560 type
= DISTRIBUTE_OUT
;
563 vty_out (vty
, "distribute list direction must be [in|out]%s",
568 /* Get interface name corresponding distribute list. */
569 dist
= distribute_list_prefix_set (argv
[2], type
, argv
[0]);
574 ALIAS (districute_list_prefix
, ipv6_distribute_list_prefix_cmd
,
575 "distribute-list prefix WORD (in|out) WORD",
576 "Filter networks in routing updates\n"
577 "Filter prefixes in routing updates\n"
578 "Name of an IP prefix-list\n"
579 "Filter incoming routing updates\n"
580 "Filter outgoing routing updates\n"
583 DEFUN (no_districute_list_prefix
, no_distribute_list_prefix_cmd
,
584 "no distribute-list prefix WORD (in|out) WORD",
586 "Filter networks in routing updates\n"
587 "Filter prefixes in routing updates\n"
588 "Name of an IP prefix-list\n"
589 "Filter incoming routing updates\n"
590 "Filter outgoing routing updates\n"
594 enum distribute_type type
;
596 /* Check of distribute list type. */
597 if (strncmp (argv
[1], "i", 1) == 0)
598 type
= DISTRIBUTE_IN
;
599 else if (strncmp (argv
[1], "o", 1) == 0)
600 type
= DISTRIBUTE_OUT
;
603 vty_out (vty
, "distribute list direction must be [in|out]%s",
608 ret
= distribute_list_prefix_unset (argv
[2], type
, argv
[0]);
611 vty_out (vty
, "distribute list doesn't exist%s", VTY_NEWLINE
);
617 ALIAS (no_districute_list_prefix
, no_ipv6_distribute_list_prefix_cmd
,
618 "no distribute-list prefix WORD (in|out) WORD",
620 "Filter networks in routing updates\n"
621 "Filter prefixes in routing updates\n"
622 "Name of an IP prefix-list\n"
623 "Filter incoming routing updates\n"
624 "Filter outgoing routing updates\n"
628 config_show_distribute (struct vty
*vty
)
631 struct hash_backet
*mp
;
632 struct distribute
*dist
;
634 /* Output filter configuration. */
635 dist
= distribute_lookup (NULL
);
636 if (dist
&& (dist
->list
[DISTRIBUTE_OUT
] || dist
->prefix
[DISTRIBUTE_OUT
]))
638 vty_out (vty
, " Outgoing update filter list for all interface is");
639 if (dist
->list
[DISTRIBUTE_OUT
])
640 vty_out (vty
, " %s", dist
->list
[DISTRIBUTE_OUT
]);
641 if (dist
->prefix
[DISTRIBUTE_OUT
])
642 vty_out (vty
, "%s (prefix-list) %s",
643 dist
->list
[DISTRIBUTE_OUT
] ? "," : "",
644 dist
->prefix
[DISTRIBUTE_OUT
]);
645 vty_out (vty
, "%s", VTY_NEWLINE
);
648 vty_out (vty
, " Outgoing update filter list for all interface is not set%s", VTY_NEWLINE
);
650 for (i
= 0; i
< disthash
->size
; i
++)
651 for (mp
= disthash
->index
[i
]; mp
; mp
= mp
->next
)
655 if (dist
->list
[DISTRIBUTE_OUT
] || dist
->prefix
[DISTRIBUTE_OUT
])
657 vty_out (vty
, " %s filtered by", dist
->ifname
);
658 if (dist
->list
[DISTRIBUTE_OUT
])
659 vty_out (vty
, " %s", dist
->list
[DISTRIBUTE_OUT
]);
660 if (dist
->prefix
[DISTRIBUTE_OUT
])
661 vty_out (vty
, "%s (prefix-list) %s",
662 dist
->list
[DISTRIBUTE_OUT
] ? "," : "",
663 dist
->prefix
[DISTRIBUTE_OUT
]);
664 vty_out (vty
, "%s", VTY_NEWLINE
);
669 /* Input filter configuration. */
670 dist
= distribute_lookup (NULL
);
671 if (dist
&& (dist
->list
[DISTRIBUTE_IN
] || dist
->prefix
[DISTRIBUTE_IN
]))
673 vty_out (vty
, " Incoming update filter list for all interface is");
674 if (dist
->list
[DISTRIBUTE_IN
])
675 vty_out (vty
, " %s", dist
->list
[DISTRIBUTE_IN
]);
676 if (dist
->prefix
[DISTRIBUTE_IN
])
677 vty_out (vty
, "%s (prefix-list) %s",
678 dist
->list
[DISTRIBUTE_IN
] ? "," : "",
679 dist
->prefix
[DISTRIBUTE_IN
]);
680 vty_out (vty
, "%s", VTY_NEWLINE
);
683 vty_out (vty
, " Incoming update filter list for all interface is not set%s", VTY_NEWLINE
);
685 for (i
= 0; i
< disthash
->size
; i
++)
686 for (mp
= disthash
->index
[i
]; mp
; mp
= mp
->next
)
690 if (dist
->list
[DISTRIBUTE_IN
] || dist
->prefix
[DISTRIBUTE_IN
])
692 vty_out (vty
, " %s filtered by", dist
->ifname
);
693 if (dist
->list
[DISTRIBUTE_IN
])
694 vty_out (vty
, " %s", dist
->list
[DISTRIBUTE_IN
]);
695 if (dist
->prefix
[DISTRIBUTE_IN
])
696 vty_out (vty
, "%s (prefix-list) %s",
697 dist
->list
[DISTRIBUTE_IN
] ? "," : "",
698 dist
->prefix
[DISTRIBUTE_IN
]);
699 vty_out (vty
, "%s", VTY_NEWLINE
);
705 /* Configuration write function. */
707 config_write_distribute (struct vty
*vty
)
710 struct hash_backet
*mp
;
713 for (i
= 0; i
< disthash
->size
; i
++)
714 for (mp
= disthash
->index
[i
]; mp
; mp
= mp
->next
)
716 struct distribute
*dist
;
720 if (dist
->list
[DISTRIBUTE_IN
])
722 vty_out (vty
, " distribute-list %s in %s%s",
723 dist
->list
[DISTRIBUTE_IN
],
724 dist
->ifname
? dist
->ifname
: "",
729 if (dist
->list
[DISTRIBUTE_OUT
])
731 vty_out (vty
, " distribute-list %s out %s%s",
733 dist
->list
[DISTRIBUTE_OUT
],
734 dist
->ifname
? dist
->ifname
: "",
739 if (dist
->prefix
[DISTRIBUTE_IN
])
741 vty_out (vty
, " distribute-list prefix %s in %s%s",
742 dist
->prefix
[DISTRIBUTE_IN
],
743 dist
->ifname
? dist
->ifname
: "",
748 if (dist
->prefix
[DISTRIBUTE_OUT
])
750 vty_out (vty
, " distribute-list prefix %s out %s%s",
751 dist
->prefix
[DISTRIBUTE_OUT
],
752 dist
->ifname
? dist
->ifname
: "",
760 /* Clear all distribute list. */
762 distribute_list_reset ()
764 hash_clean (disthash
, (void (*) (void *)) distribute_free
);
767 /* Initialize distribute list related hash. */
769 distribute_list_init (int node
)
771 disthash
= hash_create ((unsigned int (*) (void *)) distribute_hash_make
,
772 (int (*) (void *, void *)) distribute_cmp
);
775 install_element (RIP_NODE
, &distribute_list_all_cmd
);
776 install_element (RIP_NODE
, &no_distribute_list_all_cmd
);
777 install_element (RIP_NODE
, &distribute_list_cmd
);
778 install_element (RIP_NODE
, &no_distribute_list_cmd
);
779 install_element (RIP_NODE
, &distribute_list_prefix_all_cmd
);
780 install_element (RIP_NODE
, &no_distribute_list_prefix_all_cmd
);
781 install_element (RIP_NODE
, &distribute_list_prefix_cmd
);
782 install_element (RIP_NODE
, &no_distribute_list_prefix_cmd
);
784 install_element (RIPNG_NODE
, &ipv6_distribute_list_all_cmd
);
785 install_element (RIPNG_NODE
, &no_ipv6_distribute_list_all_cmd
);
786 install_element (RIPNG_NODE
, &ipv6_distribute_list_cmd
);
787 install_element (RIPNG_NODE
, &no_ipv6_distribute_list_cmd
);
788 install_element (RIPNG_NODE
, &ipv6_distribute_list_prefix_all_cmd
);
789 install_element (RIPNG_NODE
, &no_ipv6_distribute_list_prefix_all_cmd
);
790 install_element (RIPNG_NODE
, &ipv6_distribute_list_prefix_cmd
);
791 install_element (RIPNG_NODE
, &no_ipv6_distribute_list_prefix_cmd
);