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 return XCALLOC (MTYPE_DISTRIBUTE
, sizeof (struct distribute
));
44 /* Free distribute object. */
46 distribute_free (struct distribute
*dist
)
49 XFREE (MTYPE_DISTRIBUTE_IFNAME
, dist
->ifname
);
51 if (dist
->list
[DISTRIBUTE_IN
])
52 free (dist
->list
[DISTRIBUTE_IN
]);
53 if (dist
->list
[DISTRIBUTE_OUT
])
54 free (dist
->list
[DISTRIBUTE_OUT
]);
56 if (dist
->prefix
[DISTRIBUTE_IN
])
57 free (dist
->prefix
[DISTRIBUTE_IN
]);
58 if (dist
->prefix
[DISTRIBUTE_OUT
])
59 free (dist
->prefix
[DISTRIBUTE_OUT
]);
61 XFREE (MTYPE_DISTRIBUTE
, dist
);
64 /* Lookup interface's distribute list. */
66 distribute_lookup (const char *ifname
)
68 struct distribute key
;
69 struct distribute
*dist
;
71 /* temporary reference */
72 key
.ifname
= (char *)ifname
;
74 dist
= hash_lookup (disthash
, &key
);
80 distribute_list_add_hook (void (*func
) (struct distribute
*))
82 distribute_add_hook
= func
;
86 distribute_list_delete_hook (void (*func
) (struct distribute
*))
88 distribute_delete_hook
= func
;
92 distribute_hash_alloc (struct distribute
*arg
)
94 struct distribute
*dist
;
96 dist
= distribute_new ();
98 dist
->ifname
= XSTRDUP (MTYPE_DISTRIBUTE_IFNAME
, arg
->ifname
);
104 /* Make new distribute list and push into hash. */
105 static struct distribute
*
106 distribute_get (const char *ifname
)
108 struct distribute key
;
110 /* temporary reference */
111 key
.ifname
= (char *)ifname
;
113 return hash_get (disthash
, &key
, (void * (*) (void *))distribute_hash_alloc
);
117 distribute_hash_make (struct distribute
*dist
)
123 for (i
= 0; i
< strlen (dist
->ifname
); i
++)
124 key
+= dist
->ifname
[i
];
129 /* If two distribute-list have same value then return 1 else return
130 0. This function is used by hash package. */
132 distribute_cmp (const struct distribute
*dist1
, const struct distribute
*dist2
)
134 if (dist1
->ifname
&& dist2
->ifname
)
135 if (strcmp (dist1
->ifname
, dist2
->ifname
) == 0)
137 if (! dist1
->ifname
&& ! dist2
->ifname
)
142 /* Set access-list name to the distribute list. */
143 static struct distribute
*
144 distribute_list_set (const char *ifname
, enum distribute_type type
,
145 const char *alist_name
)
147 struct distribute
*dist
;
149 dist
= distribute_get (ifname
);
151 if (type
== DISTRIBUTE_IN
)
153 if (dist
->list
[DISTRIBUTE_IN
])
154 free (dist
->list
[DISTRIBUTE_IN
]);
155 dist
->list
[DISTRIBUTE_IN
] = strdup (alist_name
);
157 if (type
== DISTRIBUTE_OUT
)
159 if (dist
->list
[DISTRIBUTE_OUT
])
160 free (dist
->list
[DISTRIBUTE_OUT
]);
161 dist
->list
[DISTRIBUTE_OUT
] = strdup (alist_name
);
164 /* Apply this distribute-list to the interface. */
165 (*distribute_add_hook
) (dist
);
170 /* Unset distribute-list. If matched distribute-list exist then
173 distribute_list_unset (const char *ifname
, enum distribute_type type
,
174 const char *alist_name
)
176 struct distribute
*dist
;
178 dist
= distribute_lookup (ifname
);
182 if (type
== DISTRIBUTE_IN
)
184 if (!dist
->list
[DISTRIBUTE_IN
])
186 if (strcmp (dist
->list
[DISTRIBUTE_IN
], alist_name
) != 0)
189 free (dist
->list
[DISTRIBUTE_IN
]);
190 dist
->list
[DISTRIBUTE_IN
] = NULL
;
193 if (type
== DISTRIBUTE_OUT
)
195 if (!dist
->list
[DISTRIBUTE_OUT
])
197 if (strcmp (dist
->list
[DISTRIBUTE_OUT
], alist_name
) != 0)
200 free (dist
->list
[DISTRIBUTE_OUT
]);
201 dist
->list
[DISTRIBUTE_OUT
] = NULL
;
204 /* Apply this distribute-list to the interface. */
205 (*distribute_delete_hook
) (dist
);
207 /* If both out and in is NULL then free distribute list. */
208 if (dist
->list
[DISTRIBUTE_IN
] == NULL
&&
209 dist
->list
[DISTRIBUTE_OUT
] == NULL
&&
210 dist
->prefix
[DISTRIBUTE_IN
] == NULL
&&
211 dist
->prefix
[DISTRIBUTE_OUT
] == NULL
)
213 hash_release (disthash
, dist
);
214 distribute_free (dist
);
220 /* Set access-list name to the distribute list. */
221 static struct distribute
*
222 distribute_list_prefix_set (const char *ifname
, enum distribute_type type
,
223 const char *plist_name
)
225 struct distribute
*dist
;
227 dist
= distribute_get (ifname
);
229 if (type
== DISTRIBUTE_IN
)
231 if (dist
->prefix
[DISTRIBUTE_IN
])
232 free (dist
->prefix
[DISTRIBUTE_IN
]);
233 dist
->prefix
[DISTRIBUTE_IN
] = strdup (plist_name
);
235 if (type
== DISTRIBUTE_OUT
)
237 if (dist
->prefix
[DISTRIBUTE_OUT
])
238 free (dist
->prefix
[DISTRIBUTE_OUT
]);
239 dist
->prefix
[DISTRIBUTE_OUT
] = strdup (plist_name
);
242 /* Apply this distribute-list to the interface. */
243 (*distribute_add_hook
) (dist
);
248 /* Unset distribute-list. If matched distribute-list exist then
251 distribute_list_prefix_unset (const char *ifname
, enum distribute_type type
,
252 const char *plist_name
)
254 struct distribute
*dist
;
256 dist
= distribute_lookup (ifname
);
260 if (type
== DISTRIBUTE_IN
)
262 if (!dist
->prefix
[DISTRIBUTE_IN
])
264 if (strcmp (dist
->prefix
[DISTRIBUTE_IN
], plist_name
) != 0)
267 free (dist
->prefix
[DISTRIBUTE_IN
]);
268 dist
->prefix
[DISTRIBUTE_IN
] = NULL
;
271 if (type
== DISTRIBUTE_OUT
)
273 if (!dist
->prefix
[DISTRIBUTE_OUT
])
275 if (strcmp (dist
->prefix
[DISTRIBUTE_OUT
], plist_name
) != 0)
278 free (dist
->prefix
[DISTRIBUTE_OUT
]);
279 dist
->prefix
[DISTRIBUTE_OUT
] = NULL
;
282 /* Apply this distribute-list to the interface. */
283 (*distribute_delete_hook
) (dist
);
285 /* If both out and in is NULL then free distribute list. */
286 if (dist
->list
[DISTRIBUTE_IN
] == NULL
&&
287 dist
->list
[DISTRIBUTE_OUT
] == NULL
&&
288 dist
->prefix
[DISTRIBUTE_IN
] == NULL
&&
289 dist
->prefix
[DISTRIBUTE_OUT
] == NULL
)
291 hash_release (disthash
, dist
);
292 distribute_free (dist
);
298 DEFUN (distribute_list_all
,
299 distribute_list_all_cmd
,
300 "distribute-list WORD (in|out)",
301 "Filter networks in routing updates\n"
303 "Filter incoming routing updates\n"
304 "Filter outgoing routing updates\n")
306 enum distribute_type type
;
307 struct distribute
*dist
;
309 /* Check of distribute list type. */
310 if (strncmp (argv
[1], "i", 1) == 0)
311 type
= DISTRIBUTE_IN
;
312 else if (strncmp (argv
[1], "o", 1) == 0)
313 type
= DISTRIBUTE_OUT
;
316 vty_out (vty
, "distribute list direction must be [in|out]%s",
321 /* Get interface name corresponding distribute list. */
322 dist
= distribute_list_set (NULL
, type
, argv
[0]);
327 ALIAS (distribute_list_all
,
328 ipv6_distribute_list_all_cmd
,
329 "distribute-list WORD (in|out)",
330 "Filter networks in routing updates\n"
332 "Filter incoming routing updates\n"
333 "Filter outgoing routing updates\n")
335 DEFUN (no_distribute_list_all
,
336 no_distribute_list_all_cmd
,
337 "no distribute-list WORD (in|out)",
339 "Filter networks in routing updates\n"
341 "Filter incoming routing updates\n"
342 "Filter outgoing routing updates\n")
345 enum distribute_type type
;
347 /* Check of distribute list type. */
348 if (strncmp (argv
[1], "i", 1) == 0)
349 type
= DISTRIBUTE_IN
;
350 else if (strncmp (argv
[1], "o", 1) == 0)
351 type
= DISTRIBUTE_OUT
;
354 vty_out (vty
, "distribute list direction must be [in|out]%s",
359 ret
= distribute_list_unset (NULL
, type
, argv
[0]);
362 vty_out (vty
, "distribute list doesn't exist%s", VTY_NEWLINE
);
368 ALIAS (no_distribute_list_all
,
369 no_ipv6_distribute_list_all_cmd
,
370 "no distribute-list WORD (in|out)",
372 "Filter networks in routing updates\n"
374 "Filter incoming routing updates\n"
375 "Filter outgoing routing updates\n")
377 DEFUN (distribute_list
,
379 "distribute-list WORD (in|out) WORD",
380 "Filter networks in routing updates\n"
382 "Filter incoming routing updates\n"
383 "Filter outgoing routing updates\n"
386 enum distribute_type type
;
387 struct distribute
*dist
;
389 /* Check of distribute list type. */
390 if (strncmp (argv
[1], "i", 1) == 0)
391 type
= DISTRIBUTE_IN
;
392 else if (strncmp (argv
[1], "o", 1) == 0)
393 type
= DISTRIBUTE_OUT
;
396 vty_out (vty
, "distribute list direction must be [in|out]%s", VTY_NEWLINE
);
400 /* Get interface name corresponding distribute list. */
401 dist
= distribute_list_set (argv
[2], type
, argv
[0]);
406 ALIAS (distribute_list
,
407 ipv6_distribute_list_cmd
,
408 "distribute-list WORD (in|out) WORD",
409 "Filter networks in routing updates\n"
411 "Filter incoming routing updates\n"
412 "Filter outgoing routing updates\n"
415 DEFUN (no_districute_list
, no_distribute_list_cmd
,
416 "no distribute-list WORD (in|out) WORD",
418 "Filter networks in routing updates\n"
420 "Filter incoming routing updates\n"
421 "Filter outgoing routing updates\n"
425 enum distribute_type type
;
427 /* Check of distribute list type. */
428 if (strncmp (argv
[1], "i", 1) == 0)
429 type
= DISTRIBUTE_IN
;
430 else if (strncmp (argv
[1], "o", 1) == 0)
431 type
= DISTRIBUTE_OUT
;
434 vty_out (vty
, "distribute list direction must be [in|out]%s", VTY_NEWLINE
);
438 ret
= distribute_list_unset (argv
[2], type
, argv
[0]);
441 vty_out (vty
, "distribute list doesn't exist%s", VTY_NEWLINE
);
447 ALIAS (no_districute_list
, no_ipv6_distribute_list_cmd
,
448 "no distribute-list WORD (in|out) WORD",
450 "Filter networks in routing updates\n"
452 "Filter incoming routing updates\n"
453 "Filter outgoing routing updates\n"
456 DEFUN (districute_list_prefix_all
,
457 distribute_list_prefix_all_cmd
,
458 "distribute-list prefix WORD (in|out)",
459 "Filter networks in routing updates\n"
460 "Filter prefixes in routing updates\n"
461 "Name of an IP prefix-list\n"
462 "Filter incoming routing updates\n"
463 "Filter outgoing routing updates\n")
465 enum distribute_type type
;
466 struct distribute
*dist
;
468 /* Check of distribute list type. */
469 if (strncmp (argv
[1], "i", 1) == 0)
470 type
= DISTRIBUTE_IN
;
471 else if (strncmp (argv
[1], "o", 1) == 0)
472 type
= DISTRIBUTE_OUT
;
475 vty_out (vty
, "distribute list direction must be [in|out]%s",
480 /* Get interface name corresponding distribute list. */
481 dist
= distribute_list_prefix_set (NULL
, type
, argv
[0]);
486 ALIAS (districute_list_prefix_all
,
487 ipv6_distribute_list_prefix_all_cmd
,
488 "distribute-list prefix WORD (in|out)",
489 "Filter networks in routing updates\n"
490 "Filter prefixes in routing updates\n"
491 "Name of an IP prefix-list\n"
492 "Filter incoming routing updates\n"
493 "Filter outgoing routing updates\n")
495 DEFUN (no_districute_list_prefix_all
,
496 no_distribute_list_prefix_all_cmd
,
497 "no distribute-list prefix WORD (in|out)",
499 "Filter networks in routing updates\n"
500 "Filter prefixes in routing updates\n"
501 "Name of an IP prefix-list\n"
502 "Filter incoming routing updates\n"
503 "Filter outgoing routing updates\n")
506 enum distribute_type type
;
508 /* Check of distribute list type. */
509 if (strncmp (argv
[1], "i", 1) == 0)
510 type
= DISTRIBUTE_IN
;
511 else if (strncmp (argv
[1], "o", 1) == 0)
512 type
= DISTRIBUTE_OUT
;
515 vty_out (vty
, "distribute list direction must be [in|out]%s",
520 ret
= distribute_list_prefix_unset (NULL
, type
, argv
[0]);
523 vty_out (vty
, "distribute list doesn't exist%s", VTY_NEWLINE
);
529 ALIAS (no_districute_list_prefix_all
,
530 no_ipv6_distribute_list_prefix_all_cmd
,
531 "no distribute-list prefix WORD (in|out)",
533 "Filter networks in routing updates\n"
534 "Filter prefixes in routing updates\n"
535 "Name of an IP prefix-list\n"
536 "Filter incoming routing updates\n"
537 "Filter outgoing routing updates\n")
539 DEFUN (districute_list_prefix
, distribute_list_prefix_cmd
,
540 "distribute-list prefix WORD (in|out) WORD",
541 "Filter networks in routing updates\n"
542 "Filter prefixes in routing updates\n"
543 "Name of an IP prefix-list\n"
544 "Filter incoming routing updates\n"
545 "Filter outgoing routing updates\n"
548 enum distribute_type type
;
549 struct distribute
*dist
;
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
;
558 vty_out (vty
, "distribute list direction must be [in|out]%s",
563 /* Get interface name corresponding distribute list. */
564 dist
= distribute_list_prefix_set (argv
[2], type
, argv
[0]);
569 ALIAS (districute_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"
578 DEFUN (no_districute_list_prefix
, no_distribute_list_prefix_cmd
,
579 "no distribute-list prefix WORD (in|out) WORD",
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"
589 enum distribute_type type
;
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
;
598 vty_out (vty
, "distribute list direction must be [in|out]%s",
603 ret
= distribute_list_prefix_unset (argv
[2], type
, argv
[0]);
606 vty_out (vty
, "distribute list doesn't exist%s", VTY_NEWLINE
);
612 ALIAS (no_districute_list_prefix
, no_ipv6_distribute_list_prefix_cmd
,
613 "no distribute-list prefix WORD (in|out) WORD",
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"
623 config_show_distribute (struct vty
*vty
)
626 struct hash_backet
*mp
;
627 struct distribute
*dist
;
629 /* Output filter configuration. */
630 dist
= distribute_lookup (NULL
);
631 if (dist
&& (dist
->list
[DISTRIBUTE_OUT
] || dist
->prefix
[DISTRIBUTE_OUT
]))
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
);
643 vty_out (vty
, " Outgoing update filter list for all interface is not set%s", VTY_NEWLINE
);
645 for (i
= 0; i
< disthash
->size
; i
++)
646 for (mp
= disthash
->index
[i
]; mp
; mp
= mp
->next
)
650 if (dist
->list
[DISTRIBUTE_OUT
] || dist
->prefix
[DISTRIBUTE_OUT
])
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
);
664 /* Input filter configuration. */
665 dist
= distribute_lookup (NULL
);
666 if (dist
&& (dist
->list
[DISTRIBUTE_IN
] || dist
->prefix
[DISTRIBUTE_IN
]))
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
);
678 vty_out (vty
, " Incoming update filter list for all interface is not set%s", VTY_NEWLINE
);
680 for (i
= 0; i
< disthash
->size
; i
++)
681 for (mp
= disthash
->index
[i
]; mp
; mp
= mp
->next
)
685 if (dist
->list
[DISTRIBUTE_IN
] || dist
->prefix
[DISTRIBUTE_IN
])
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
);
700 /* Configuration write function. */
702 config_write_distribute (struct vty
*vty
)
705 struct hash_backet
*mp
;
708 for (i
= 0; i
< disthash
->size
; i
++)
709 for (mp
= disthash
->index
[i
]; mp
; mp
= mp
->next
)
711 struct distribute
*dist
;
715 if (dist
->list
[DISTRIBUTE_IN
])
717 vty_out (vty
, " distribute-list %s in %s%s",
718 dist
->list
[DISTRIBUTE_IN
],
719 dist
->ifname
? dist
->ifname
: "",
724 if (dist
->list
[DISTRIBUTE_OUT
])
726 vty_out (vty
, " distribute-list %s out %s%s",
728 dist
->list
[DISTRIBUTE_OUT
],
729 dist
->ifname
? dist
->ifname
: "",
734 if (dist
->prefix
[DISTRIBUTE_IN
])
736 vty_out (vty
, " distribute-list prefix %s in %s%s",
737 dist
->prefix
[DISTRIBUTE_IN
],
738 dist
->ifname
? dist
->ifname
: "",
743 if (dist
->prefix
[DISTRIBUTE_OUT
])
745 vty_out (vty
, " distribute-list prefix %s out %s%s",
746 dist
->prefix
[DISTRIBUTE_OUT
],
747 dist
->ifname
? dist
->ifname
: "",
755 /* Clear all distribute list. */
757 distribute_list_reset ()
759 hash_clean (disthash
, (void (*) (void *)) distribute_free
);
762 /* Initialize distribute list related hash. */
764 distribute_list_init (int node
)
766 disthash
= hash_create ((unsigned int (*) (void *)) distribute_hash_make
,
767 (int (*) (const void *, const void *)) distribute_cmp
);
770 install_element (RIP_NODE
, &distribute_list_all_cmd
);
771 install_element (RIP_NODE
, &no_distribute_list_all_cmd
);
772 install_element (RIP_NODE
, &distribute_list_cmd
);
773 install_element (RIP_NODE
, &no_distribute_list_cmd
);
774 install_element (RIP_NODE
, &distribute_list_prefix_all_cmd
);
775 install_element (RIP_NODE
, &no_distribute_list_prefix_all_cmd
);
776 install_element (RIP_NODE
, &distribute_list_prefix_cmd
);
777 install_element (RIP_NODE
, &no_distribute_list_prefix_cmd
);
779 install_element (RIPNG_NODE
, &ipv6_distribute_list_all_cmd
);
780 install_element (RIPNG_NODE
, &no_ipv6_distribute_list_all_cmd
);
781 install_element (RIPNG_NODE
, &ipv6_distribute_list_cmd
);
782 install_element (RIPNG_NODE
, &no_ipv6_distribute_list_cmd
);
783 install_element (RIPNG_NODE
, &ipv6_distribute_list_prefix_all_cmd
);
784 install_element (RIPNG_NODE
, &no_ipv6_distribute_list_prefix_all_cmd
);
785 install_element (RIPNG_NODE
, &ipv6_distribute_list_prefix_cmd
);
786 install_element (RIPNG_NODE
, &no_ipv6_distribute_list_prefix_cmd
);