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
*);
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
)
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 (char *ifname
)
73 struct distribute key
;
74 struct distribute
*dist
;
78 dist
= hash_lookup (disthash
, &key
);
84 distribute_list_add_hook (void (*func
) (struct distribute
*))
86 distribute_add_hook
= func
;
90 distribute_list_delete_hook (void (*func
) (struct distribute
*))
92 distribute_delete_hook
= func
;
96 distribute_hash_alloc (struct distribute
*arg
)
98 struct distribute
*dist
;
100 dist
= distribute_new ();
102 dist
->ifname
= strdup (arg
->ifname
);
108 /* Make new distribute list and push into hash. */
110 distribute_get (char *ifname
)
112 struct distribute key
;
116 return hash_get (disthash
, &key
, distribute_hash_alloc
);
120 distribute_hash_make (struct distribute
*dist
)
127 for (i
= 0; i
< strlen (dist
->ifname
); i
++)
128 key
+= dist
->ifname
[i
];
133 /* If two distribute-list have same value then return 1 else return
134 0. This function is used by hash package. */
136 distribute_cmp (struct distribute
*dist1
, struct distribute
*dist2
)
138 if (dist1
->ifname
&& dist2
->ifname
)
139 if (strcmp (dist1
->ifname
, dist2
->ifname
) == 0)
141 if (! dist1
->ifname
&& ! dist2
->ifname
)
146 /* Set access-list name to the distribute list. */
148 distribute_list_set (char *ifname
, enum distribute_type type
, char *alist_name
)
150 struct distribute
*dist
;
152 dist
= distribute_get (ifname
);
154 if (type
== DISTRIBUTE_IN
)
156 if (dist
->list
[DISTRIBUTE_IN
])
157 free (dist
->list
[DISTRIBUTE_IN
]);
158 dist
->list
[DISTRIBUTE_IN
] = strdup (alist_name
);
160 if (type
== DISTRIBUTE_OUT
)
162 if (dist
->list
[DISTRIBUTE_OUT
])
163 free (dist
->list
[DISTRIBUTE_OUT
]);
164 dist
->list
[DISTRIBUTE_OUT
] = strdup (alist_name
);
167 /* Apply this distribute-list to the interface. */
168 (*distribute_add_hook
) (dist
);
173 /* Unset distribute-list. If matched distribute-list exist then
176 distribute_list_unset (char *ifname
, enum distribute_type type
,
179 struct distribute
*dist
;
181 dist
= distribute_lookup (ifname
);
185 if (type
== DISTRIBUTE_IN
)
187 if (!dist
->list
[DISTRIBUTE_IN
])
189 if (strcmp (dist
->list
[DISTRIBUTE_IN
], alist_name
) != 0)
192 free (dist
->list
[DISTRIBUTE_IN
]);
193 dist
->list
[DISTRIBUTE_IN
] = NULL
;
196 if (type
== DISTRIBUTE_OUT
)
198 if (!dist
->list
[DISTRIBUTE_OUT
])
200 if (strcmp (dist
->list
[DISTRIBUTE_OUT
], alist_name
) != 0)
203 free (dist
->list
[DISTRIBUTE_OUT
]);
204 dist
->list
[DISTRIBUTE_OUT
] = NULL
;
207 /* Apply this distribute-list to the interface. */
208 (*distribute_delete_hook
) (dist
);
210 /* If both out and in is NULL then free distribute list. */
211 if (dist
->list
[DISTRIBUTE_IN
] == NULL
&&
212 dist
->list
[DISTRIBUTE_OUT
] == NULL
&&
213 dist
->prefix
[DISTRIBUTE_IN
] == NULL
&&
214 dist
->prefix
[DISTRIBUTE_OUT
] == NULL
)
216 hash_release (disthash
, dist
);
217 distribute_free (dist
);
223 /* Set access-list name to the distribute list. */
225 distribute_list_prefix_set (char *ifname
, enum distribute_type type
,
228 struct distribute
*dist
;
230 dist
= distribute_get (ifname
);
232 if (type
== DISTRIBUTE_IN
)
234 if (dist
->prefix
[DISTRIBUTE_IN
])
235 free (dist
->prefix
[DISTRIBUTE_IN
]);
236 dist
->prefix
[DISTRIBUTE_IN
] = strdup (plist_name
);
238 if (type
== DISTRIBUTE_OUT
)
240 if (dist
->prefix
[DISTRIBUTE_OUT
])
241 free (dist
->prefix
[DISTRIBUTE_OUT
]);
242 dist
->prefix
[DISTRIBUTE_OUT
] = strdup (plist_name
);
245 /* Apply this distribute-list to the interface. */
246 (*distribute_add_hook
) (dist
);
251 /* Unset distribute-list. If matched distribute-list exist then
254 distribute_list_prefix_unset (char *ifname
, enum distribute_type type
,
257 struct distribute
*dist
;
259 dist
= distribute_lookup (ifname
);
263 if (type
== DISTRIBUTE_IN
)
265 if (!dist
->prefix
[DISTRIBUTE_IN
])
267 if (strcmp (dist
->prefix
[DISTRIBUTE_IN
], plist_name
) != 0)
270 free (dist
->prefix
[DISTRIBUTE_IN
]);
271 dist
->prefix
[DISTRIBUTE_IN
] = NULL
;
274 if (type
== DISTRIBUTE_OUT
)
276 if (!dist
->prefix
[DISTRIBUTE_OUT
])
278 if (strcmp (dist
->prefix
[DISTRIBUTE_OUT
], plist_name
) != 0)
281 free (dist
->prefix
[DISTRIBUTE_OUT
]);
282 dist
->prefix
[DISTRIBUTE_OUT
] = NULL
;
285 /* Apply this distribute-list to the interface. */
286 (*distribute_delete_hook
) (dist
);
288 /* If both out and in is NULL then free distribute list. */
289 if (dist
->list
[DISTRIBUTE_IN
] == NULL
&&
290 dist
->list
[DISTRIBUTE_OUT
] == NULL
&&
291 dist
->prefix
[DISTRIBUTE_IN
] == NULL
&&
292 dist
->prefix
[DISTRIBUTE_OUT
] == NULL
)
294 hash_release (disthash
, dist
);
295 distribute_free (dist
);
301 DEFUN (distribute_list_all
,
302 distribute_list_all_cmd
,
303 "distribute-list WORD (in|out)",
304 "Filter networks in routing updates\n"
306 "Filter incoming routing updates\n"
307 "Filter outgoing routing updates\n")
309 enum distribute_type type
;
310 struct distribute
*dist
;
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
;
319 vty_out (vty
, "distribute list direction must be [in|out]%s",
324 /* Get interface name corresponding distribute list. */
325 dist
= distribute_list_set (NULL
, type
, argv
[0]);
330 ALIAS (distribute_list_all
,
331 ipv6_distribute_list_all_cmd
,
332 "distribute-list WORD (in|out)",
333 "Filter networks in routing updates\n"
335 "Filter incoming routing updates\n"
336 "Filter outgoing routing updates\n");
338 DEFUN (no_distribute_list_all
,
339 no_distribute_list_all_cmd
,
340 "no distribute-list WORD (in|out)",
342 "Filter networks in routing updates\n"
344 "Filter incoming routing updates\n"
345 "Filter outgoing routing updates\n")
348 enum distribute_type type
;
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
;
357 vty_out (vty
, "distribute list direction must be [in|out]%s",
362 ret
= distribute_list_unset (NULL
, type
, argv
[0]);
365 vty_out (vty
, "distribute list doesn't exist%s", VTY_NEWLINE
);
371 ALIAS (no_distribute_list_all
,
372 no_ipv6_distribute_list_all_cmd
,
373 "no distribute-list WORD (in|out)",
375 "Filter networks in routing updates\n"
377 "Filter incoming routing updates\n"
378 "Filter outgoing routing updates\n");
380 DEFUN (distribute_list
,
382 "distribute-list WORD (in|out) WORD",
383 "Filter networks in routing updates\n"
385 "Filter incoming routing updates\n"
386 "Filter outgoing routing updates\n"
389 enum distribute_type type
;
390 struct distribute
*dist
;
392 /* Check of distribute list type. */
393 if (strncmp (argv
[1], "i", 1) == 0)
394 type
= DISTRIBUTE_IN
;
395 else if (strncmp (argv
[1], "o", 1) == 0)
396 type
= DISTRIBUTE_OUT
;
399 vty_out (vty
, "distribute list direction must be [in|out]%s", VTY_NEWLINE
);
403 /* Get interface name corresponding distribute list. */
404 dist
= distribute_list_set (argv
[2], type
, argv
[0]);
409 ALIAS (distribute_list
,
410 ipv6_distribute_list_cmd
,
411 "distribute-list WORD (in|out) WORD",
412 "Filter networks in routing updates\n"
414 "Filter incoming routing updates\n"
415 "Filter outgoing routing updates\n"
418 DEFUN (no_districute_list
,
419 no_distribute_list_cmd
,
420 "no distribute-list WORD (in|out) WORD",
422 "Filter networks in routing updates\n"
424 "Filter incoming routing updates\n"
425 "Filter outgoing routing updates\n"
429 enum distribute_type type
;
431 /* Check of distribute list type. */
432 if (strncmp (argv
[1], "i", 1) == 0)
433 type
= DISTRIBUTE_IN
;
434 else if (strncmp (argv
[1], "o", 1) == 0)
435 type
= DISTRIBUTE_OUT
;
438 vty_out (vty
, "distribute list direction must be [in|out]%s", VTY_NEWLINE
);
442 ret
= distribute_list_unset (argv
[2], type
, argv
[0]);
445 vty_out (vty
, "distribute list doesn't exist%s", VTY_NEWLINE
);
451 ALIAS (no_districute_list
,
452 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
,
575 ipv6_distribute_list_prefix_cmd
,
576 "distribute-list prefix WORD (in|out) WORD",
577 "Filter networks in routing updates\n"
578 "Filter prefixes in routing updates\n"
579 "Name of an IP prefix-list\n"
580 "Filter incoming routing updates\n"
581 "Filter outgoing routing updates\n"
584 DEFUN (no_districute_list_prefix
,
585 no_distribute_list_prefix_cmd
,
586 "no distribute-list prefix WORD (in|out) WORD",
588 "Filter networks in routing updates\n"
589 "Filter prefixes in routing updates\n"
590 "Name of an IP prefix-list\n"
591 "Filter incoming routing updates\n"
592 "Filter outgoing routing updates\n"
596 enum distribute_type type
;
598 /* Check of distribute list type. */
599 if (strncmp (argv
[1], "i", 1) == 0)
600 type
= DISTRIBUTE_IN
;
601 else if (strncmp (argv
[1], "o", 1) == 0)
602 type
= DISTRIBUTE_OUT
;
605 vty_out (vty
, "distribute list direction must be [in|out]%s",
610 ret
= distribute_list_prefix_unset (argv
[2], type
, argv
[0]);
613 vty_out (vty
, "distribute list doesn't exist%s", VTY_NEWLINE
);
619 ALIAS (no_districute_list_prefix
,
620 no_ipv6_distribute_list_prefix_cmd
,
621 "no distribute-list prefix WORD (in|out) WORD",
623 "Filter networks in routing updates\n"
624 "Filter prefixes in routing updates\n"
625 "Name of an IP prefix-list\n"
626 "Filter incoming routing updates\n"
627 "Filter outgoing routing updates\n"
631 config_show_distribute (struct vty
*vty
)
634 struct hash_backet
*mp
;
635 struct distribute
*dist
;
637 /* Output filter configuration. */
638 dist
= distribute_lookup (NULL
);
639 if (dist
&& (dist
->list
[DISTRIBUTE_OUT
] || dist
->prefix
[DISTRIBUTE_OUT
]))
641 vty_out (vty
, " Outgoing update filter list for all interface is");
642 if (dist
->list
[DISTRIBUTE_OUT
])
643 vty_out (vty
, " %s", dist
->list
[DISTRIBUTE_OUT
]);
644 if (dist
->prefix
[DISTRIBUTE_OUT
])
645 vty_out (vty
, "%s (prefix-list) %s",
646 dist
->list
[DISTRIBUTE_OUT
] ? "," : "",
647 dist
->prefix
[DISTRIBUTE_OUT
]);
648 vty_out (vty
, "%s", VTY_NEWLINE
);
651 vty_out (vty
, " Outgoing update filter list for all interface is not set%s", VTY_NEWLINE
);
653 for (i
= 0; i
< disthash
->size
; i
++)
654 for (mp
= disthash
->index
[i
]; mp
; mp
= mp
->next
)
658 if (dist
->list
[DISTRIBUTE_OUT
] || dist
->prefix
[DISTRIBUTE_OUT
])
660 vty_out (vty
, " %s filtered by", dist
->ifname
);
661 if (dist
->list
[DISTRIBUTE_OUT
])
662 vty_out (vty
, " %s", dist
->list
[DISTRIBUTE_OUT
]);
663 if (dist
->prefix
[DISTRIBUTE_OUT
])
664 vty_out (vty
, "%s (prefix-list) %s",
665 dist
->list
[DISTRIBUTE_OUT
] ? "," : "",
666 dist
->prefix
[DISTRIBUTE_OUT
]);
667 vty_out (vty
, "%s", VTY_NEWLINE
);
672 /* Input filter configuration. */
673 dist
= distribute_lookup (NULL
);
674 if (dist
&& (dist
->list
[DISTRIBUTE_IN
] || dist
->prefix
[DISTRIBUTE_IN
]))
676 vty_out (vty
, " Incoming update filter list for all interface is");
677 if (dist
->list
[DISTRIBUTE_IN
])
678 vty_out (vty
, " %s", dist
->list
[DISTRIBUTE_IN
]);
679 if (dist
->prefix
[DISTRIBUTE_IN
])
680 vty_out (vty
, "%s (prefix-list) %s",
681 dist
->list
[DISTRIBUTE_IN
] ? "," : "",
682 dist
->prefix
[DISTRIBUTE_IN
]);
683 vty_out (vty
, "%s", VTY_NEWLINE
);
686 vty_out (vty
, " Incoming update filter list for all interface is not set%s", VTY_NEWLINE
);
688 for (i
= 0; i
< disthash
->size
; i
++)
689 for (mp
= disthash
->index
[i
]; mp
; mp
= mp
->next
)
693 if (dist
->list
[DISTRIBUTE_IN
] || dist
->prefix
[DISTRIBUTE_IN
])
695 vty_out (vty
, " %s filtered by", dist
->ifname
);
696 if (dist
->list
[DISTRIBUTE_IN
])
697 vty_out (vty
, " %s", dist
->list
[DISTRIBUTE_IN
]);
698 if (dist
->prefix
[DISTRIBUTE_IN
])
699 vty_out (vty
, "%s (prefix-list) %s",
700 dist
->list
[DISTRIBUTE_IN
] ? "," : "",
701 dist
->prefix
[DISTRIBUTE_IN
]);
702 vty_out (vty
, "%s", VTY_NEWLINE
);
708 /* Configuration write function. */
710 config_write_distribute (struct vty
*vty
)
713 struct hash_backet
*mp
;
716 for (i
= 0; i
< disthash
->size
; i
++)
717 for (mp
= disthash
->index
[i
]; mp
; mp
= mp
->next
)
719 struct distribute
*dist
;
723 if (dist
->list
[DISTRIBUTE_IN
])
725 vty_out (vty
, " distribute-list %s in %s%s",
726 dist
->list
[DISTRIBUTE_IN
],
727 dist
->ifname
? dist
->ifname
: "",
732 if (dist
->list
[DISTRIBUTE_OUT
])
734 vty_out (vty
, " distribute-list %s out %s%s",
736 dist
->list
[DISTRIBUTE_OUT
],
737 dist
->ifname
? dist
->ifname
: "",
742 if (dist
->prefix
[DISTRIBUTE_IN
])
744 vty_out (vty
, " distribute-list prefix %s in %s%s",
745 dist
->prefix
[DISTRIBUTE_IN
],
746 dist
->ifname
? dist
->ifname
: "",
751 if (dist
->prefix
[DISTRIBUTE_OUT
])
753 vty_out (vty
, " distribute-list prefix %s out %s%s",
754 dist
->prefix
[DISTRIBUTE_OUT
],
755 dist
->ifname
? dist
->ifname
: "",
763 /* Clear all distribute list. */
765 distribute_list_reset ()
767 hash_clean (disthash
, (void (*) (void *)) distribute_free
);
770 /* Initialize distribute list related hash. */
772 distribute_list_init (int node
)
774 disthash
= hash_create (distribute_hash_make
, distribute_cmp
);
776 if (node
== RIP_NODE
)
778 install_element (RIP_NODE
, &distribute_list_all_cmd
);
779 install_element (RIP_NODE
, &no_distribute_list_all_cmd
);
780 install_element (RIP_NODE
, &distribute_list_cmd
);
781 install_element (RIP_NODE
, &no_distribute_list_cmd
);
782 install_element (RIP_NODE
, &distribute_list_prefix_all_cmd
);
783 install_element (RIP_NODE
, &no_distribute_list_prefix_all_cmd
);
784 install_element (RIP_NODE
, &distribute_list_prefix_cmd
);
785 install_element (RIP_NODE
, &no_distribute_list_prefix_cmd
);
789 install_element (RIPNG_NODE
, &ipv6_distribute_list_all_cmd
);
790 install_element (RIPNG_NODE
, &no_ipv6_distribute_list_all_cmd
);
791 install_element (RIPNG_NODE
, &ipv6_distribute_list_cmd
);
792 install_element (RIPNG_NODE
, &no_ipv6_distribute_list_cmd
);
793 install_element (RIPNG_NODE
, &ipv6_distribute_list_prefix_all_cmd
);
794 install_element (RIPNG_NODE
, &no_ipv6_distribute_list_prefix_all_cmd
);
795 install_element (RIPNG_NODE
, &ipv6_distribute_list_prefix_cmd
);
796 install_element (RIPNG_NODE
, &no_ipv6_distribute_list_prefix_cmd
);