1/* Route filtering function.
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 "prefix.h"
25#include "filter.h"
26#include "memory.h"
27#include "command.h"
28#include "sockunion.h"
29#include "buffer.h"
30
31struct filter_cisco
32{
33  /* Cisco access-list */
34  int extended;
35  struct in_addr addr;
36  struct in_addr addr_mask;
37  struct in_addr mask;
38  struct in_addr mask_mask;
39};
40
41struct filter_zebra
42{
43  /* If this filter is "exact" match then this flag is set. */
44  int exact;
45
46  /* Prefix information. */
47  struct prefix prefix;
48};
49
50/* Filter element of access list */
51struct filter
52{
53  /* For doubly linked list. */
54  struct filter *next;
55  struct filter *prev;
56
57  /* Filter type information. */
58  enum filter_type type;
59
60  /* Cisco access-list */
61  int cisco;
62
63  union
64    {
65      struct filter_cisco cfilter;
66      struct filter_zebra zfilter;
67    } u;
68};
69
70/* List of access_list. */
71struct access_list_list
72{
73  struct access_list *head;
74  struct access_list *tail;
75};
76
77/* Master structure of access_list. */
78struct access_master
79{
80  /* List of access_list which name is number. */
81  struct access_list_list num;
82
83  /* List of access_list which name is string. */
84  struct access_list_list str;
85
86  /* Hook function which is executed when new access_list is added. */
87  void (*add_hook) ();
88
89  /* Hook function which is executed when access_list is deleted. */
90  void (*delete_hook) ();
91};
92
93/* Static structure for IPv4 access_list's master. */
94static struct access_master access_master_ipv4 =
95{
96  {NULL, NULL},
97  {NULL, NULL},
98  NULL,
99  NULL,
100};
101
102#ifdef HAVE_IPV6
103/* Static structure for IPv6 access_list's master. */
104static struct access_master access_master_ipv6 =
105{
106  {NULL, NULL},
107  {NULL, NULL},
108  NULL,
109  NULL,
110};
111#endif /* HAVE_IPV6 */
112
113struct access_master *
114access_master_get (afi_t afi)
115{
116  if (afi == AFI_IP)
117    return &access_master_ipv4;
118#ifdef HAVE_IPV6
119  else if (afi == AFI_IP6)
120    return &access_master_ipv6;
121#endif /* HAVE_IPV6 */
122  return NULL;
123}
124
125/* Allocate new filter structure. */
126struct filter *
127filter_new ()
128{
129  return (struct filter *) XCALLOC (MTYPE_ACCESS_FILTER,
130				    sizeof (struct filter));
131}
132
133void
134filter_free (struct filter *filter)
135{
136  XFREE (MTYPE_ACCESS_FILTER, filter);
137}
138
139/* Return string of filter_type. */
140static char *
141filter_type_str (struct filter *filter)
142{
143  switch (filter->type)
144    {
145    case FILTER_PERMIT:
146      return "permit";
147      break;
148    case FILTER_DENY:
149      return "deny";
150      break;
151    case FILTER_DYNAMIC:
152      return "dynamic";
153      break;
154    default:
155      return "";
156      break;
157    }
158}
159
160/* If filter match to the prefix then return 1. */
161static int
162filter_match_cisco (struct filter *mfilter, struct prefix *p)
163{
164  struct filter_cisco *filter;
165  struct in_addr mask;
166  u_int32_t check_addr;
167  u_int32_t check_mask;
168
169  filter = &mfilter->u.cfilter;
170  check_addr = p->u.prefix4.s_addr & ~filter->addr_mask.s_addr;
171
172  if (filter->extended)
173    {
174      masklen2ip (p->prefixlen, &mask);
175      check_mask = mask.s_addr & ~filter->mask_mask.s_addr;
176
177      if (memcmp (&check_addr, &filter->addr.s_addr, 4) == 0
178          && memcmp (&check_mask, &filter->mask.s_addr, 4) == 0)
179	return 1;
180    }
181  else if (memcmp (&check_addr, &filter->addr.s_addr, 4) == 0)
182    return 1;
183
184  return 0;
185}
186
187/* If filter match to the prefix then return 1. */
188static int
189filter_match_zebra (struct filter *mfilter, struct prefix *p)
190{
191  struct filter_zebra *filter;
192
193  filter = &mfilter->u.zfilter;
194
195  if (filter->prefix.family == p->family)
196    {
197      if (filter->exact)
198	{
199	  if (filter->prefix.prefixlen == p->prefixlen)
200	    return prefix_match (&filter->prefix, p);
201	  else
202	    return 0;
203	}
204      else
205	return prefix_match (&filter->prefix, p);
206    }
207  else
208    return 0;
209}
210
211/* Allocate new access list structure. */
212struct access_list *
213access_list_new ()
214{
215  return (struct access_list *) XCALLOC (MTYPE_ACCESS_LIST,
216					 sizeof (struct access_list));
217}
218
219/* Free allocated access_list. */
220void
221access_list_free (struct access_list *access)
222{
223  XFREE (MTYPE_ACCESS_LIST, access);
224}
225
226/* Delete access_list from access_master and free it. */
227void
228access_list_delete (struct access_list *access)
229{
230  struct filter *filter;
231  struct filter *next;
232  struct access_list_list *list;
233  struct access_master *master;
234
235  for (filter = access->head; filter; filter = next)
236    {
237      next = filter->next;
238      filter_free (filter);
239    }
240
241  master = access->master;
242
243  if (access->type == ACCESS_TYPE_NUMBER)
244    list = &master->num;
245  else
246    list = &master->str;
247
248  if (access->next)
249    access->next->prev = access->prev;
250  else
251    list->tail = access->prev;
252
253  if (access->prev)
254    access->prev->next = access->next;
255  else
256    list->head = access->next;
257
258  if (access->name)
259    XFREE (MTYPE_ACCESS_LIST_STR, access->name);
260
261  if (access->remark)
262    XFREE (MTYPE_TMP, access->remark);
263
264  access_list_free (access);
265}
266
267/* Insert new access list to list of access_list.  Each acceess_list
268   is sorted by the name. */
269struct access_list *
270access_list_insert (afi_t afi, char *name)
271{
272  int i;
273  long number;
274  struct access_list *access;
275  struct access_list *point;
276  struct access_list_list *alist;
277  struct access_master *master;
278
279  master = access_master_get (afi);
280  if (master == NULL)
281    return NULL;
282
283  /* Allocate new access_list and copy given name. */
284  access = access_list_new ();
285  access->name = XSTRDUP (MTYPE_ACCESS_LIST_STR, name);
286  access->master = master;
287
288  /* If name is made by all digit character.  We treat it as
289     number. */
290  for (number = 0, i = 0; i < strlen (name); i++)
291    {
292      if (isdigit ((int) name[i]))
293	number = (number * 10) + (name[i] - '0');
294      else
295	break;
296    }
297
298  /* In case of name is all digit character */
299  if (i == strlen (name))
300    {
301      access->type = ACCESS_TYPE_NUMBER;
302
303      /* Set access_list to number list. */
304      alist = &master->num;
305
306      for (point = alist->head; point; point = point->next)
307	if (atol (point->name) >= number)
308	  break;
309    }
310  else
311    {
312      access->type = ACCESS_TYPE_STRING;
313
314      /* Set access_list to string list. */
315      alist = &master->str;
316
317      /* Set point to insertion point. */
318      for (point = alist->head; point; point = point->next)
319	if (strcmp (point->name, name) >= 0)
320	  break;
321    }
322
323  /* In case of this is the first element of master. */
324  if (alist->head == NULL)
325    {
326      alist->head = alist->tail = access;
327      return access;
328    }
329
330  /* In case of insertion is made at the tail of access_list. */
331  if (point == NULL)
332    {
333      access->prev = alist->tail;
334      alist->tail->next = access;
335      alist->tail = access;
336      return access;
337    }
338
339  /* In case of insertion is made at the head of access_list. */
340  if (point == alist->head)
341    {
342      access->next = alist->head;
343      alist->head->prev = access;
344      alist->head = access;
345      return access;
346    }
347
348  /* Insertion is made at middle of the access_list. */
349  access->next = point;
350  access->prev = point->prev;
351
352  if (point->prev)
353    point->prev->next = access;
354  point->prev = access;
355
356  return access;
357}
358
359/* Lookup access_list from list of access_list by name. */
360struct access_list *
361access_list_lookup (afi_t afi, char *name)
362{
363  struct access_list *access;
364  struct access_master *master;
365
366  if (name == NULL)
367    return NULL;
368
369  master = access_master_get (afi);
370  if (master == NULL)
371    return NULL;
372
373  for (access = master->num.head; access; access = access->next)
374    if (strcmp (access->name, name) == 0)
375      return access;
376
377  for (access = master->str.head; access; access = access->next)
378    if (strcmp (access->name, name) == 0)
379      return access;
380
381  return NULL;
382}
383
384/* Get access list from list of access_list.  If there isn't matched
385   access_list create new one and return it. */
386struct access_list *
387access_list_get (afi_t afi, char *name)
388{
389  struct access_list *access;
390
391  access = access_list_lookup (afi, name);
392  if (access == NULL)
393    access = access_list_insert (afi, name);
394  return access;
395}
396
397/* Apply access list to object (which should be struct prefix *). */
398enum filter_type
399access_list_apply (struct access_list *access, void *object)
400{
401  struct filter *filter;
402  struct prefix *p;
403
404  p = (struct prefix *) object;
405
406  if (access == NULL)
407    return FILTER_DENY;
408
409  for (filter = access->head; filter; filter = filter->next)
410    {
411      if (filter->cisco)
412	{
413	  if (filter_match_cisco (filter, p))
414	    return filter->type;
415	}
416      else
417	{
418	  if (filter_match_zebra (filter, p))
419	    return filter->type;
420	}
421    }
422
423  return FILTER_DENY;
424}
425
426/* Add hook function. */
427void
428access_list_add_hook (void (*func) (struct access_list *access))
429{
430  access_master_ipv4.add_hook = func;
431#ifdef HAVE_IPV6
432  access_master_ipv6.add_hook = func;
433#endif /* HAVE_IPV6 */
434}
435
436/* Delete hook function. */
437void
438access_list_delete_hook (void (*func) (struct access_list *access))
439{
440  access_master_ipv4.delete_hook = func;
441#ifdef HAVE_IPV6
442  access_master_ipv6.delete_hook = func;
443#endif /* HAVE_IPV6 */
444}
445
446/* Add new filter to the end of specified access_list. */
447void
448access_list_filter_add (struct access_list *access, struct filter *filter)
449{
450  filter->next = NULL;
451  filter->prev = access->tail;
452
453  if (access->tail)
454    access->tail->next = filter;
455  else
456    access->head = filter;
457  access->tail = filter;
458
459  /* Run hook function. */
460  if (access->master->add_hook)
461    (*access->master->add_hook) (access);
462}
463
464/* If access_list has no filter then return 1. */
465static int
466access_list_empty (struct access_list *access)
467{
468  if (access->head == NULL && access->tail == NULL)
469    return 1;
470  else
471    return 0;
472}
473
474/* Delete filter from specified access_list.  If there is hook
475   function execute it. */
476void
477access_list_filter_delete (struct access_list *access, struct filter *filter)
478{
479  struct access_master *master;
480
481  master = access->master;
482
483  if (filter->next)
484    filter->next->prev = filter->prev;
485  else
486    access->tail = filter->prev;
487
488  if (filter->prev)
489    filter->prev->next = filter->next;
490  else
491    access->head = filter->next;
492
493  filter_free (filter);
494
495  /* If access_list becomes empty delete it from access_master. */
496  if (access_list_empty (access))
497    access_list_delete (access);
498
499  /* Run hook function. */
500  if (master->delete_hook)
501    (*master->delete_hook) (access);
502}
503
504/*
505  deny    Specify packets to reject
506  permit  Specify packets to forward
507  dynamic ?
508*/
509
510/*
511  Hostname or A.B.C.D  Address to match
512  any                  Any source host
513  host                 A single host address
514*/
515#ifdef FOX_LIST_SUPPORT
516struct filter *
517filter_lookup_cisco (struct access_list *access, struct filter *mnew)
518{
519  struct filter *mfilter;
520  struct filter_cisco *filter;
521  struct filter_cisco *new;
522
523  new = &mnew->u.cfilter;
524
525  for (mfilter = access->head; mfilter; mfilter = mfilter->next)
526    {
527      filter = &mfilter->u.cfilter;
528
529      if (filter->extended)
530	{
531	  if (mfilter->type == mnew->type
532	      && filter->addr.s_addr == new->addr.s_addr
533	      && filter->addr_mask.s_addr == new->addr_mask.s_addr
534	      && filter->mask.s_addr == new->mask.s_addr
535	      && filter->mask_mask.s_addr == new->mask_mask.s_addr)
536	    return mfilter;
537	}
538      else
539	{
540	  if (mfilter->type == mnew->type
541	      && filter->addr.s_addr == new->addr.s_addr
542	      && filter->addr_mask.s_addr == new->addr_mask.s_addr)
543	    return mfilter;
544	}
545    }
546
547  return NULL;
548}
549#endif /*FOX_LIST_SUPPORT*/
550
551struct filter *
552filter_lookup_zebra (struct access_list *access, struct filter *mnew)
553{
554  struct filter *mfilter;
555  struct filter_zebra *filter;
556  struct filter_zebra *new;
557
558  new = &mnew->u.zfilter;
559
560  for (mfilter = access->head; mfilter; mfilter = mfilter->next)
561    {
562      filter = &mfilter->u.zfilter;
563
564      if (filter->exact == new->exact
565	  && mfilter->type == mnew->type
566	  && prefix_same (&filter->prefix, &new->prefix))
567	return mfilter;
568    }
569  return NULL;
570}
571
572int
573vty_access_list_remark_unset (struct vty *vty, afi_t afi, char *name)
574{
575  struct access_list *access;
576
577  access = access_list_lookup (afi, name);
578  if (! access)
579    {
580      vty_out (vty, "%% access-list %s doesn't exist%s", name,
581	       VTY_NEWLINE);
582      return CMD_WARNING;
583    }
584
585  if (access->remark)
586    {
587      XFREE (MTYPE_TMP, access->remark);
588      access->remark = NULL;
589    }
590
591  if (access->head == NULL && access->tail == NULL && access->remark == NULL)
592    access_list_delete (access);
593
594  return CMD_SUCCESS;
595}
596
597#ifdef FOX_LIST_SUPPORT
598int
599filter_set_cisco (struct vty *vty, char *name_str, char *type_str,
600		  char *addr_str, char *addr_mask_str,
601		  char *mask_str, char *mask_mask_str,
602		  int extended, int set)
603{
604  int ret;
605  enum filter_type type;
606  struct filter *mfilter;
607  struct filter_cisco *filter;
608  struct access_list *access;
609  struct in_addr addr;
610  struct in_addr addr_mask;
611  struct in_addr mask;
612  struct in_addr mask_mask;
613
614  /* Check of filter type. */
615  if (strncmp (type_str, "p", 1) == 0)
616    type = FILTER_PERMIT;
617  else if (strncmp (type_str, "d", 1) == 0)
618    type = FILTER_DENY;
619  else
620    {
621      vty_out (vty, "%% filter type must be permit or deny%s", VTY_NEWLINE);
622      return CMD_WARNING;
623    }
624
625  ret = inet_aton (addr_str, &addr);
626  if (ret <= 0)
627    {
628      vty_out (vty, "%%Inconsistent address and mask%s",
629	       VTY_NEWLINE);
630      return CMD_WARNING;
631    }
632
633  ret = inet_aton (addr_mask_str, &addr_mask);
634  if (ret <= 0)
635    {
636      vty_out (vty, "%%Inconsistent address and mask%s",
637	       VTY_NEWLINE);
638      return CMD_WARNING;
639    }
640
641  if (extended)
642    {
643      ret = inet_aton (mask_str, &mask);
644      if (ret <= 0)
645	{
646	  vty_out (vty, "%%Inconsistent address and mask%s",
647		   VTY_NEWLINE);
648	  return CMD_WARNING;
649	}
650
651      ret = inet_aton (mask_mask_str, &mask_mask);
652      if (ret <= 0)
653	{
654	  vty_out (vty, "%%Inconsistent address and mask%s",
655		   VTY_NEWLINE);
656	  return CMD_WARNING;
657	}
658    }
659
660  mfilter = filter_new();
661  mfilter->type = type;
662  mfilter->cisco = 1;
663  filter = &mfilter->u.cfilter;
664  filter->extended = extended;
665  filter->addr.s_addr = addr.s_addr & ~addr_mask.s_addr;
666  filter->addr_mask.s_addr = addr_mask.s_addr;
667
668  if (extended)
669    {
670      filter->mask.s_addr = mask.s_addr & ~mask_mask.s_addr;
671      filter->mask_mask.s_addr = mask_mask.s_addr;
672    }
673
674  /* Install new filter to the access_list. */
675  access = access_list_get (AFI_IP, name_str);
676
677  if (set)
678    {
679      if (filter_lookup_cisco (access, mfilter))
680	filter_free (mfilter);
681      else
682	access_list_filter_add (access, mfilter);
683    }
684  else
685    {
686      struct filter *delete_filter;
687
688      delete_filter = filter_lookup_cisco (access, mfilter);
689      if (delete_filter)
690	access_list_filter_delete (access, delete_filter);
691
692      filter_free (mfilter);
693    }
694
695  return CMD_SUCCESS;
696}
697
698/* Standard access-list */
699DEFUN (access_list_standard,
700       access_list_standard_cmd,
701       "access-list (<1-99>|<1300-1999>) (deny|permit) A.B.C.D A.B.C.D",
702       "Add an access list entry\n"
703       "IP standard access list\n"
704       "IP standard access list (expanded range)\n"
705       "Specify packets to reject\n"
706       "Specify packets to forward\n"
707       "Address to match\n"
708       "Wildcard bits\n")
709{
710  return filter_set_cisco (vty, argv[0], argv[1], argv[2], argv[3],
711			   NULL, NULL, 0, 1);
712}
713
714DEFUN (access_list_standard_nomask,
715       access_list_standard_nomask_cmd,
716       "access-list (<1-99>|<1300-1999>) (deny|permit) A.B.C.D",
717       "Add an access list entry\n"
718       "IP standard access list\n"
719       "IP standard access list (expanded range)\n"
720       "Specify packets to reject\n"
721       "Specify packets to forward\n"
722       "Address to match\n")
723{
724  return filter_set_cisco (vty, argv[0], argv[1], argv[2], "0.0.0.0",
725			   NULL, NULL, 0, 1);
726}
727
728DEFUN (access_list_standard_host,
729       access_list_standard_host_cmd,
730       "access-list (<1-99>|<1300-1999>) (deny|permit) host A.B.C.D",
731       "Add an access list entry\n"
732       "IP standard access list\n"
733       "IP standard access list (expanded range)\n"
734       "Specify packets to reject\n"
735       "Specify packets to forward\n"
736       "A single host address\n"
737       "Address to match\n")
738{
739  return filter_set_cisco (vty, argv[0], argv[1], argv[2], "0.0.0.0",
740			   NULL, NULL, 0, 1);
741}
742
743DEFUN (access_list_standard_any,
744       access_list_standard_any_cmd,
745       "access-list (<1-99>|<1300-1999>) (deny|permit) any",
746       "Add an access list entry\n"
747       "IP standard access list\n"
748       "IP standard access list (expanded range)\n"
749       "Specify packets to reject\n"
750       "Specify packets to forward\n"
751       "Any source host\n")
752{
753  return filter_set_cisco (vty, argv[0], argv[1], "0.0.0.0",
754			   "255.255.255.255", NULL, NULL, 0, 1);
755}
756
757DEFUN (no_access_list_standard,
758       no_access_list_standard_cmd,
759       "no access-list (<1-99>|<1300-1999>) (deny|permit) A.B.C.D A.B.C.D",
760       NO_STR
761       "Add an access list entry\n"
762       "IP standard access list\n"
763       "IP standard access list (expanded range)\n"
764       "Specify packets to reject\n"
765       "Specify packets to forward\n"
766       "Address to match\n"
767       "Wildcard bits\n")
768{
769  return filter_set_cisco (vty, argv[0], argv[1], argv[2], argv[3],
770			   NULL, NULL, 0, 0);
771}
772
773DEFUN (no_access_list_standard_nomask,
774       no_access_list_standard_nomask_cmd,
775       "no access-list (<1-99>|<1300-1999>) (deny|permit) A.B.C.D",
776       NO_STR
777       "Add an access list entry\n"
778       "IP standard access list\n"
779       "IP standard access list (expanded range)\n"
780       "Specify packets to reject\n"
781       "Specify packets to forward\n"
782       "Address to match\n")
783{
784  return filter_set_cisco (vty, argv[0], argv[1], argv[2], "0.0.0.0",
785			   NULL, NULL, 0, 0);
786}
787
788DEFUN (no_access_list_standard_host,
789       no_access_list_standard_host_cmd,
790       "no access-list (<1-99>|<1300-1999>) (deny|permit) host A.B.C.D",
791       NO_STR
792       "Add an access list entry\n"
793       "IP standard access list\n"
794       "IP standard access list (expanded range)\n"
795       "Specify packets to reject\n"
796       "Specify packets to forward\n"
797       "A single host address\n"
798       "Address to match\n")
799{
800  return filter_set_cisco (vty, argv[0], argv[1], argv[2], "0.0.0.0",
801			   NULL, NULL, 0, 0);
802}
803
804DEFUN (no_access_list_standard_any,
805       no_access_list_standard_any_cmd,
806       "no access-list (<1-99>|<1300-1999>) (deny|permit) any",
807       NO_STR
808       "Add an access list entry\n"
809       "IP standard access list\n"
810       "IP standard access list (expanded range)\n"
811       "Specify packets to reject\n"
812       "Specify packets to forward\n"
813       "Any source host\n")
814{
815  return filter_set_cisco (vty, argv[0], argv[1], "0.0.0.0",
816			   "255.255.255.255", NULL, NULL, 0, 0);
817}
818
819/* Extended access-list */
820DEFUN (access_list_extended,
821       access_list_extended_cmd,
822       "access-list (<100-199>|<2000-2699>) (deny|permit) ip A.B.C.D A.B.C.D A.B.C.D A.B.C.D",
823       "Add an access list entry\n"
824       "IP extended access list\n"
825       "IP extended access list (expanded range)\n"
826       "Specify packets to reject\n"
827       "Specify packets to forward\n"
828       "Any Internet Protocol\n"
829       "Source address\n"
830       "Source wildcard bits\n"
831       "Destination address\n"
832       "Destination Wildcard bits\n")
833{
834  return filter_set_cisco (vty, argv[0], argv[1], argv[2],
835			   argv[3], argv[4], argv[5], 1 ,1);
836}
837
838DEFUN (access_list_extended_mask_any,
839       access_list_extended_mask_any_cmd,
840       "access-list (<100-199>|<2000-2699>) (deny|permit) ip A.B.C.D A.B.C.D any",
841       "Add an access list entry\n"
842       "IP extended access list\n"
843       "IP extended access list (expanded range)\n"
844       "Specify packets to reject\n"
845       "Specify packets to forward\n"
846       "Any Internet Protocol\n"
847       "Source address\n"
848       "Source wildcard bits\n"
849       "Any destination host\n")
850{
851  return filter_set_cisco (vty, argv[0], argv[1], argv[2],
852			   argv[3], "0.0.0.0",
853			   "255.255.255.255", 1, 1);
854}
855
856DEFUN (access_list_extended_any_mask,
857       access_list_extended_any_mask_cmd,
858       "access-list (<100-199>|<2000-2699>) (deny|permit) ip any A.B.C.D A.B.C.D",
859       "Add an access list entry\n"
860       "IP extended access list\n"
861       "IP extended access list (expanded range)\n"
862       "Specify packets to reject\n"
863       "Specify packets to forward\n"
864       "Any Internet Protocol\n"
865       "Any source host\n"
866       "Destination address\n"
867       "Destination Wildcard bits\n")
868{
869  return filter_set_cisco (vty, argv[0], argv[1], "0.0.0.0",
870			   "255.255.255.255", argv[2],
871			   argv[3], 1, 1);
872}
873
874DEFUN (access_list_extended_any_any,
875       access_list_extended_any_any_cmd,
876       "access-list (<100-199>|<2000-2699>) (deny|permit) ip any any",
877       "Add an access list entry\n"
878       "IP extended access list\n"
879       "IP extended access list (expanded range)\n"
880       "Specify packets to reject\n"
881       "Specify packets to forward\n"
882       "Any Internet Protocol\n"
883       "Any source host\n"
884       "Any destination host\n")
885{
886  return filter_set_cisco (vty, argv[0], argv[1], "0.0.0.0",
887			   "255.255.255.255", "0.0.0.0",
888			   "255.255.255.255", 1, 1);
889}
890
891DEFUN (access_list_extended_mask_host,
892       access_list_extended_mask_host_cmd,
893       "access-list (<100-199>|<2000-2699>) (deny|permit) ip A.B.C.D A.B.C.D host A.B.C.D",
894       "Add an access list entry\n"
895       "IP extended access list\n"
896       "IP extended access list (expanded range)\n"
897       "Specify packets to reject\n"
898       "Specify packets to forward\n"
899       "Any Internet Protocol\n"
900       "Source address\n"
901       "Source wildcard bits\n"
902       "A single destination host\n"
903       "Destination address\n")
904{
905  return filter_set_cisco (vty, argv[0], argv[1], argv[2],
906			   argv[3], argv[4],
907			   "0.0.0.0", 1, 1);
908}
909
910DEFUN (access_list_extended_host_mask,
911       access_list_extended_host_mask_cmd,
912       "access-list (<100-199>|<2000-2699>) (deny|permit) ip host A.B.C.D A.B.C.D A.B.C.D",
913       "Add an access list entry\n"
914       "IP extended access list\n"
915       "IP extended access list (expanded range)\n"
916       "Specify packets to reject\n"
917       "Specify packets to forward\n"
918       "Any Internet Protocol\n"
919       "A single source host\n"
920       "Source address\n"
921       "Destination address\n"
922       "Destination Wildcard bits\n")
923{
924  return filter_set_cisco (vty, argv[0], argv[1], argv[2],
925			   "0.0.0.0", argv[3],
926			   argv[4], 1, 1);
927}
928
929DEFUN (access_list_extended_host_host,
930       access_list_extended_host_host_cmd,
931       "access-list (<100-199>|<2000-2699>) (deny|permit) ip host A.B.C.D host A.B.C.D",
932       "Add an access list entry\n"
933       "IP extended access list\n"
934       "IP extended access list (expanded range)\n"
935       "Specify packets to reject\n"
936       "Specify packets to forward\n"
937       "Any Internet Protocol\n"
938       "A single source host\n"
939       "Source address\n"
940       "A single destination host\n"
941       "Destination address\n")
942{
943  return filter_set_cisco (vty, argv[0], argv[1], argv[2],
944			   "0.0.0.0", argv[3],
945			   "0.0.0.0", 1, 1);
946}
947
948DEFUN (access_list_extended_any_host,
949       access_list_extended_any_host_cmd,
950       "access-list (<100-199>|<2000-2699>) (deny|permit) ip any host A.B.C.D",
951       "Add an access list entry\n"
952       "IP extended access list\n"
953       "IP extended access list (expanded range)\n"
954       "Specify packets to reject\n"
955       "Specify packets to forward\n"
956       "Any Internet Protocol\n"
957       "Any source host\n"
958       "A single destination host\n"
959       "Destination address\n")
960{
961  return filter_set_cisco (vty, argv[0], argv[1], "0.0.0.0",
962			   "255.255.255.255", argv[2],
963			   "0.0.0.0", 1, 1);
964}
965
966DEFUN (access_list_extended_host_any,
967       access_list_extended_host_any_cmd,
968       "access-list (<100-199>|<2000-2699>) (deny|permit) ip host A.B.C.D any",
969       "Add an access list entry\n"
970       "IP extended access list\n"
971       "IP extended access list (expanded range)\n"
972       "Specify packets to reject\n"
973       "Specify packets to forward\n"
974       "Any Internet Protocol\n"
975       "A single source host\n"
976       "Source address\n"
977       "Any destination host\n")
978{
979  return filter_set_cisco (vty, argv[0], argv[1], argv[2],
980			   "0.0.0.0", "0.0.0.0",
981			   "255.255.255.255", 1, 1);
982}
983
984DEFUN (no_access_list_extended,
985       no_access_list_extended_cmd,
986       "no access-list (<100-199>|<2000-2699>) (deny|permit) ip A.B.C.D A.B.C.D A.B.C.D A.B.C.D",
987       NO_STR
988       "Add an access list entry\n"
989       "IP extended access list\n"
990       "IP extended access list (expanded range)\n"
991       "Specify packets to reject\n"
992       "Specify packets to forward\n"
993       "Any Internet Protocol\n"
994       "Source address\n"
995       "Source wildcard bits\n"
996       "Destination address\n"
997       "Destination Wildcard bits\n")
998{
999  return filter_set_cisco (vty, argv[0], argv[1], argv[2],
1000			   argv[3], argv[4], argv[5], 1, 0);
1001}
1002
1003DEFUN (no_access_list_extended_mask_any,
1004       no_access_list_extended_mask_any_cmd,
1005       "no access-list (<100-199>|<2000-2699>) (deny|permit) ip A.B.C.D A.B.C.D any",
1006       NO_STR
1007       "Add an access list entry\n"
1008       "IP extended access list\n"
1009       "IP extended access list (expanded range)\n"
1010       "Specify packets to reject\n"
1011       "Specify packets to forward\n"
1012       "Any Internet Protocol\n"
1013       "Source address\n"
1014       "Source wildcard bits\n"
1015       "Any destination host\n")
1016{
1017  return filter_set_cisco (vty, argv[0], argv[1], argv[2],
1018			   argv[3], "0.0.0.0",
1019			   "255.255.255.255", 1, 0);
1020}
1021
1022DEFUN (no_access_list_extended_any_mask,
1023       no_access_list_extended_any_mask_cmd,
1024       "no access-list (<100-199>|<2000-2699>) (deny|permit) ip any A.B.C.D A.B.C.D",
1025       NO_STR
1026       "Add an access list entry\n"
1027       "IP extended access list\n"
1028       "IP extended access list (expanded range)\n"
1029       "Specify packets to reject\n"
1030       "Specify packets to forward\n"
1031       "Any Internet Protocol\n"
1032       "Any source host\n"
1033       "Destination address\n"
1034       "Destination Wildcard bits\n")
1035{
1036  return filter_set_cisco (vty, argv[0], argv[1], "0.0.0.0",
1037			   "255.255.255.255", argv[2],
1038			   argv[3], 1, 0);
1039}
1040
1041DEFUN (no_access_list_extended_any_any,
1042       no_access_list_extended_any_any_cmd,
1043       "no access-list (<100-199>|<2000-2699>) (deny|permit) ip any any",
1044       NO_STR
1045       "Add an access list entry\n"
1046       "IP extended access list\n"
1047       "IP extended access list (expanded range)\n"
1048       "Specify packets to reject\n"
1049       "Specify packets to forward\n"
1050       "Any Internet Protocol\n"
1051       "Any source host\n"
1052       "Any destination host\n")
1053{
1054  return filter_set_cisco (vty, argv[0], argv[1], "0.0.0.0",
1055			   "255.255.255.255", "0.0.0.0",
1056			   "255.255.255.255", 1, 0);
1057}
1058
1059DEFUN (no_access_list_extended_mask_host,
1060       no_access_list_extended_mask_host_cmd,
1061       "no access-list (<100-199>|<2000-2699>) (deny|permit) ip A.B.C.D A.B.C.D host A.B.C.D",
1062       NO_STR
1063       "Add an access list entry\n"
1064       "IP extended access list\n"
1065       "IP extended access list (expanded range)\n"
1066       "Specify packets to reject\n"
1067       "Specify packets to forward\n"
1068       "Any Internet Protocol\n"
1069       "Source address\n"
1070       "Source wildcard bits\n"
1071       "A single destination host\n"
1072       "Destination address\n")
1073{
1074  return filter_set_cisco (vty, argv[0], argv[1], argv[2],
1075			   argv[3], argv[4],
1076			   "0.0.0.0", 1, 0);
1077}
1078
1079DEFUN (no_access_list_extended_host_mask,
1080       no_access_list_extended_host_mask_cmd,
1081       "no access-list (<100-199>|<2000-2699>) (deny|permit) ip host A.B.C.D A.B.C.D A.B.C.D",
1082       NO_STR
1083       "Add an access list entry\n"
1084       "IP extended access list\n"
1085       "IP extended access list (expanded range)\n"
1086       "Specify packets to reject\n"
1087       "Specify packets to forward\n"
1088       "Any Internet Protocol\n"
1089       "A single source host\n"
1090       "Source address\n"
1091       "Destination address\n"
1092       "Destination Wildcard bits\n")
1093{
1094  return filter_set_cisco (vty, argv[0], argv[1], argv[2],
1095			   "0.0.0.0", argv[3],
1096			   argv[4], 1, 0);
1097}
1098
1099DEFUN (no_access_list_extended_host_host,
1100       no_access_list_extended_host_host_cmd,
1101       "no access-list (<100-199>|<2000-2699>) (deny|permit) ip host A.B.C.D host A.B.C.D",
1102       NO_STR
1103       "Add an access list entry\n"
1104       "IP extended access list\n"
1105       "IP extended access list (expanded range)\n"
1106       "Specify packets to reject\n"
1107       "Specify packets to forward\n"
1108       "Any Internet Protocol\n"
1109       "A single source host\n"
1110       "Source address\n"
1111       "A single destination host\n"
1112       "Destination address\n")
1113{
1114  return filter_set_cisco (vty, argv[0], argv[1], argv[2],
1115			   "0.0.0.0", argv[3],
1116			   "0.0.0.0", 1, 0);
1117}
1118
1119DEFUN (no_access_list_extended_any_host,
1120       no_access_list_extended_any_host_cmd,
1121       "no access-list (<100-199>|<2000-2699>) (deny|permit) ip any host A.B.C.D",
1122       NO_STR
1123       "Add an access list entry\n"
1124       "IP extended access list\n"
1125       "IP extended access list (expanded range)\n"
1126       "Specify packets to reject\n"
1127       "Specify packets to forward\n"
1128       "Any Internet Protocol\n"
1129       "Any source host\n"
1130       "A single destination host\n"
1131       "Destination address\n")
1132{
1133  return filter_set_cisco (vty, argv[0], argv[1], "0.0.0.0",
1134			   "255.255.255.255", argv[2],
1135			   "0.0.0.0", 1, 0);
1136}
1137
1138DEFUN (no_access_list_extended_host_any,
1139       no_access_list_extended_host_any_cmd,
1140       "no access-list (<100-199>|<2000-2699>) (deny|permit) ip host A.B.C.D any",
1141       NO_STR
1142       "Add an access list entry\n"
1143       "IP extended access list\n"
1144       "IP extended access list (expanded range)\n"
1145       "Specify packets to reject\n"
1146       "Specify packets to forward\n"
1147       "Any Internet Protocol\n"
1148       "A single source host\n"
1149       "Source address\n"
1150       "Any destination host\n")
1151{
1152  return filter_set_cisco (vty, argv[0], argv[1], argv[2],
1153			   "0.0.0.0", "0.0.0.0",
1154			   "255.255.255.255", 1, 0);
1155}
1156#endif /* FOX_LIST_SUPPORT */
1157
1158int
1159filter_set_zebra (struct vty *vty, char *name_str, char *type_str,
1160		  afi_t afi, char *prefix_str, int exact, int set)
1161{
1162  int ret;
1163  enum filter_type type;
1164  struct filter *mfilter;
1165  struct filter_zebra *filter;
1166  struct access_list *access;
1167  struct prefix p;
1168
1169  /* Check of filter type. */
1170  if (strncmp (type_str, "p", 1) == 0)
1171    type = FILTER_PERMIT;
1172  else if (strncmp (type_str, "d", 1) == 0)
1173    type = FILTER_DENY;
1174  else
1175    {
1176      vty_out (vty, "filter type must be [permit|deny]%s", VTY_NEWLINE);
1177      return CMD_WARNING;
1178    }
1179
1180  /* Check string format of prefix and prefixlen. */
1181  if (afi == AFI_IP)
1182    {
1183      ret = str2prefix_ipv4 (prefix_str, (struct prefix_ipv4 *)&p);
1184      if (ret <= 0)
1185	{
1186	  vty_out (vty, "IP address prefix/prefixlen is malformed%s",
1187		   VTY_NEWLINE);
1188	  return CMD_WARNING;
1189	}
1190    }
1191#ifdef HAVE_IPV6
1192  else if (afi == AFI_IP6)
1193    {
1194      ret = str2prefix_ipv6 (prefix_str, (struct prefix_ipv6 *) &p);
1195      if (ret <= 0)
1196	{
1197	  vty_out (vty, "IPv6 address prefix/prefixlen is malformed%s",
1198		   VTY_NEWLINE);
1199		   return CMD_WARNING;
1200	}
1201    }
1202#endif /* HAVE_IPV6 */
1203  else
1204    return CMD_WARNING;
1205
1206  mfilter = filter_new ();
1207  mfilter->type = type;
1208  filter = &mfilter->u.zfilter;
1209  prefix_copy (&filter->prefix, &p);
1210
1211  /* "exact-match" */
1212  if (exact)
1213    filter->exact = 1;
1214
1215  /* Install new filter to the access_list. */
1216  access = access_list_get (afi, name_str);
1217
1218  if (set)
1219    {
1220      if (filter_lookup_zebra (access, mfilter))
1221	filter_free (mfilter);
1222      else
1223	access_list_filter_add (access, mfilter);
1224    }
1225  else
1226    {
1227      struct filter *delete_filter;
1228
1229      delete_filter = filter_lookup_zebra (access, mfilter);
1230      if (delete_filter)
1231        access_list_filter_delete (access, delete_filter);
1232
1233      filter_free (mfilter);
1234    }
1235
1236  return CMD_SUCCESS;
1237}
1238
1239/* Zebra access-list */
1240DEFUN (access_list,
1241       access_list_cmd,
1242       "access-list WORD (deny|permit) A.B.C.D/M",
1243       "Add an access list entry\n"
1244       "IP zebra access-list name\n"
1245       "Specify packets to reject\n"
1246       "Specify packets to forward\n"
1247       "Prefix to match. e.g. 10.0.0.0/8\n")
1248{
1249  return filter_set_zebra (vty, argv[0], argv[1], AFI_IP, argv[2], 0, 1);
1250}
1251
1252DEFUN (access_list_exact,
1253       access_list_exact_cmd,
1254       "access-list WORD (deny|permit) A.B.C.D/M exact-match",
1255       "Add an access list entry\n"
1256       "IP zebra access-list name\n"
1257       "Specify packets to reject\n"
1258       "Specify packets to forward\n"
1259       "Prefix to match. e.g. 10.0.0.0/8\n"
1260       "Exact match of the prefixes\n")
1261{
1262  return filter_set_zebra (vty, argv[0], argv[1], AFI_IP, argv[2], 1, 1);
1263}
1264
1265DEFUN (access_list_any,
1266       access_list_any_cmd,
1267       "access-list WORD (deny|permit) any",
1268       "Add an access list entry\n"
1269       "IP zebra access-list name\n"
1270       "Specify packets to reject\n"
1271       "Specify packets to forward\n"
1272       "Prefix to match. e.g. 10.0.0.0/8\n")
1273{
1274  return filter_set_zebra (vty, argv[0], argv[1], AFI_IP, "0.0.0.0/0", 0, 1);
1275}
1276
1277DEFUN (no_access_list,
1278       no_access_list_cmd,
1279       "no access-list WORD (deny|permit) A.B.C.D/M",
1280       NO_STR
1281       "Add an access list entry\n"
1282       "IP zebra access-list name\n"
1283       "Specify packets to reject\n"
1284       "Specify packets to forward\n"
1285       "Prefix to match. e.g. 10.0.0.0/8\n")
1286{
1287  return filter_set_zebra (vty, argv[0], argv[1], AFI_IP, argv[2], 0, 0);
1288}
1289
1290DEFUN (no_access_list_exact,
1291       no_access_list_exact_cmd,
1292       "no access-list WORD (deny|permit) A.B.C.D/M exact-match",
1293       NO_STR
1294       "Add an access list entry\n"
1295       "IP zebra access-list name\n"
1296       "Specify packets to reject\n"
1297       "Specify packets to forward\n"
1298       "Prefix to match. e.g. 10.0.0.0/8\n"
1299       "Exact match of the prefixes\n")
1300{
1301  return filter_set_zebra (vty, argv[0], argv[1], AFI_IP, argv[2], 1, 0);
1302}
1303
1304DEFUN (no_access_list_any,
1305       no_access_list_any_cmd,
1306       "no access-list WORD (deny|permit) any",
1307       NO_STR
1308       "Add an access list entry\n"
1309       "IP zebra access-list name\n"
1310       "Specify packets to reject\n"
1311       "Specify packets to forward\n"
1312       "Prefix to match. e.g. 10.0.0.0/8\n")
1313{
1314  return filter_set_zebra (vty, argv[0], argv[1], AFI_IP, "0.0.0.0/0", 0, 0);
1315}
1316
1317DEFUN (no_access_list_all,
1318       no_access_list_all_cmd,
1319       "no access-list (<1-99>|<100-199>|<1300-1999>|<2000-2699>|WORD)",
1320       NO_STR
1321       "Add an access list entry\n"
1322       "IP standard access list\n"
1323       "IP extended access list\n"
1324       "IP standard access list (expanded range)\n"
1325       "IP extended access list (expanded range)\n"
1326       "IP zebra access-list name\n")
1327{
1328  struct access_list *access;
1329  struct access_master *master;
1330
1331  /* Looking up access_list. */
1332  access = access_list_lookup (AFI_IP, argv[0]);
1333  if (access == NULL)
1334    {
1335      vty_out (vty, "%% access-list %s doesn't exist%s", argv[0],
1336	       VTY_NEWLINE);
1337      return CMD_WARNING;
1338    }
1339
1340  master = access->master;
1341
1342  /* Delete all filter from access-list. */
1343  access_list_delete (access);
1344
1345  /* Run hook function. */
1346  if (master->delete_hook)
1347    (*master->delete_hook) (access);
1348
1349  return CMD_SUCCESS;
1350}
1351
1352#ifdef FOX_LIST_SUPPORT
1353
1354DEFUN (access_list_remark,
1355       access_list_remark_cmd,
1356       "access-list (<1-99>|<100-199>|<1300-1999>|<2000-2699>|WORD) remark .LINE",
1357       "Add an access list entry\n"
1358       "IP standard access list\n"
1359       "IP extended access list\n"
1360       "IP standard access list (expanded range)\n"
1361       "IP extended access list (expanded range)\n"
1362       "IP zebra access-list\n"
1363       "Access list entry comment\n"
1364       "Comment up to 100 characters\n")
1365{
1366  struct access_list *access;
1367  struct buffer *b;
1368  int i;
1369
1370  access = access_list_get (AFI_IP, argv[0]);
1371
1372  if (access->remark)
1373    {
1374      XFREE (MTYPE_TMP, access->remark);
1375      access->remark = NULL;
1376    }
1377
1378  /* Below is remark get codes. */
1379  b = buffer_new (1024);
1380  for (i = 1; i < argc; i++)
1381    {
1382      buffer_putstr (b, (u_char *)argv[i]);
1383      buffer_putc (b, ' ');
1384    }
1385  buffer_putc (b, '\0');
1386
1387  access->remark = buffer_getstr (b);
1388
1389  buffer_free (b);
1390
1391  return CMD_SUCCESS;
1392}
1393
1394DEFUN (no_access_list_remark,
1395       no_access_list_remark_cmd,
1396       "no access-list (<1-99>|<100-199>|<1300-1999>|<2000-2699>|WORD) remark",
1397       NO_STR
1398       "Add an access list entry\n"
1399       "IP standard access list\n"
1400       "IP extended access list\n"
1401       "IP standard access list (expanded range)\n"
1402       "IP extended access list (expanded range)\n"
1403       "IP zebra access-list\n"
1404       "Access list entry comment\n")
1405{
1406  return vty_access_list_remark_unset (vty, AFI_IP, argv[0]);
1407}
1408
1409ALIAS (no_access_list_remark,
1410       no_access_list_remark_arg_cmd,
1411       "no access-list (<1-99>|<100-199>|<1300-1999>|<2000-2699>|WORD) remark .LINE",
1412       NO_STR
1413       "Add an access list entry\n"
1414       "IP standard access list\n"
1415       "IP extended access list\n"
1416       "IP standard access list (expanded range)\n"
1417       "IP extended access list (expanded range)\n"
1418       "IP zebra access-list\n"
1419       "Access list entry comment\n"
1420       "Comment up to 100 characters\n")
1421#endif /* FOX_LIST_SUPPORT */
1422
1423#ifdef HAVE_IPV6
1424DEFUN (ipv6_access_list,
1425       ipv6_access_list_cmd,
1426       "ipv6 access-list WORD (deny|permit) X:X::X:X/M",
1427       IPV6_STR
1428       "Add an access list entry\n"
1429       "IPv6 zebra access-list\n"
1430       "Specify packets to reject\n"
1431       "Specify packets to forward\n"
1432       "Prefix to match. e.g. 3ffe:506::/32\n")
1433{
1434  return filter_set_zebra (vty, argv[0], argv[1], AFI_IP6, argv[2], 0, 1);
1435}
1436
1437DEFUN (ipv6_access_list_exact,
1438       ipv6_access_list_exact_cmd,
1439       "ipv6 access-list WORD (deny|permit) X:X::X:X/M exact-match",
1440       IPV6_STR
1441       "Add an access list entry\n"
1442       "IPv6 zebra access-list\n"
1443       "Specify packets to reject\n"
1444       "Specify packets to forward\n"
1445       "Prefix to match. e.g. 3ffe:506::/32\n"
1446       "Exact match of the prefixes\n")
1447{
1448  return filter_set_zebra (vty, argv[0], argv[1], AFI_IP6, argv[2], 1, 1);
1449}
1450
1451DEFUN (ipv6_access_list_any,
1452       ipv6_access_list_any_cmd,
1453       "ipv6 access-list WORD (deny|permit) any",
1454       IPV6_STR
1455       "Add an access list entry\n"
1456       "IPv6 zebra access-list\n"
1457       "Specify packets to reject\n"
1458       "Specify packets to forward\n"
1459       "Any prefixi to match\n")
1460{
1461  return filter_set_zebra (vty, argv[0], argv[1], AFI_IP6, "::/0", 0, 1);
1462}
1463
1464DEFUN (no_ipv6_access_list,
1465       no_ipv6_access_list_cmd,
1466       "no ipv6 access-list WORD (deny|permit) X:X::X:X/M",
1467       NO_STR
1468       IPV6_STR
1469       "Add an access list entry\n"
1470       "IPv6 zebra access-list\n"
1471       "Specify packets to reject\n"
1472       "Specify packets to forward\n"
1473       "Prefix to match. e.g. 3ffe:506::/32\n")
1474{
1475  return filter_set_zebra (vty, argv[0], argv[1], AFI_IP6, argv[2], 0, 0);
1476}
1477
1478DEFUN (no_ipv6_access_list_exact,
1479       no_ipv6_access_list_exact_cmd,
1480       "no ipv6 access-list WORD (deny|permit) X:X::X:X/M exact-match",
1481       NO_STR
1482       IPV6_STR
1483       "Add an access list entry\n"
1484       "IPv6 zebra access-list\n"
1485       "Specify packets to reject\n"
1486       "Specify packets to forward\n"
1487       "Prefix to match. e.g. 3ffe:506::/32\n"
1488       "Exact match of the prefixes\n")
1489{
1490  return filter_set_zebra (vty, argv[0], argv[1], AFI_IP6, argv[2], 1, 0);
1491}
1492
1493DEFUN (no_ipv6_access_list_any,
1494       no_ipv6_access_list_any_cmd,
1495       "no ipv6 access-list WORD (deny|permit) any",
1496       NO_STR
1497       IPV6_STR
1498       "Add an access list entry\n"
1499       "IPv6 zebra access-list\n"
1500       "Specify packets to reject\n"
1501       "Specify packets to forward\n"
1502       "Any prefixi to match\n")
1503{
1504  return filter_set_zebra (vty, argv[0], argv[1], AFI_IP6, "::/0", 0, 0);
1505}
1506
1507
1508DEFUN (no_ipv6_access_list_all,
1509       no_ipv6_access_list_all_cmd,
1510       "no ipv6 access-list WORD",
1511       NO_STR
1512       IPV6_STR
1513       "Add an access list entry\n"
1514       "IPv6 zebra access-list\n")
1515{
1516  struct access_list *access;
1517  struct access_master *master;
1518
1519  /* Looking up access_list. */
1520  access = access_list_lookup (AFI_IP6, argv[0]);
1521  if (access == NULL)
1522    {
1523      vty_out (vty, "%% access-list %s doesn't exist%s", argv[0],
1524	       VTY_NEWLINE);
1525      return CMD_WARNING;
1526    }
1527
1528  master = access->master;
1529
1530  /* Delete all filter from access-list. */
1531  access_list_delete (access);
1532
1533  /* Run hook function. */
1534  if (master->delete_hook)
1535    (*master->delete_hook) (access);
1536
1537  return CMD_SUCCESS;
1538}
1539
1540DEFUN (ipv6_access_list_remark,
1541       ipv6_access_list_remark_cmd,
1542       "ipv6 access-list WORD remark .LINE",
1543       IPV6_STR
1544       "Add an access list entry\n"
1545       "IPv6 zebra access-list\n"
1546       "Access list entry comment\n"
1547       "Comment up to 100 characters\n")
1548{
1549  struct access_list *access;
1550  struct buffer *b;
1551  int i;
1552
1553  access = access_list_get (AFI_IP6, argv[0]);
1554
1555  if (access->remark)
1556    {
1557      XFREE (MTYPE_TMP, access->remark);
1558      access->remark = NULL;
1559    }
1560
1561  /* Below is remark get codes. */
1562  b = buffer_new (1024);
1563  for (i = 1; i < argc; i++)
1564    {
1565      buffer_putstr (b, (u_char *)argv[i]);
1566      buffer_putc (b, ' ');
1567    }
1568  buffer_putc (b, '\0');
1569
1570  access->remark = buffer_getstr (b);
1571
1572  buffer_free (b);
1573
1574  return CMD_SUCCESS;
1575}
1576
1577DEFUN (no_ipv6_access_list_remark,
1578       no_ipv6_access_list_remark_cmd,
1579       "no ipv6 access-list WORD remark",
1580       NO_STR
1581       IPV6_STR
1582       "Add an access list entry\n"
1583       "IPv6 zebra access-list\n"
1584       "Access list entry comment\n")
1585{
1586  return vty_access_list_remark_unset (vty, AFI_IP6, argv[0]);
1587}
1588
1589ALIAS (no_ipv6_access_list_remark,
1590       no_ipv6_access_list_remark_arg_cmd,
1591       "no ipv6 access-list WORD remark .LINE",
1592       NO_STR
1593       IPV6_STR
1594       "Add an access list entry\n"
1595       "IPv6 zebra access-list\n"
1596       "Access list entry comment\n"
1597       "Comment up to 100 characters\n")
1598#endif /* HAVE_IPV6 */
1599
1600void config_write_access_zebra (struct vty *, struct filter *);
1601void config_write_access_cisco (struct vty *, struct filter *);
1602
1603/* show access-list command. */
1604int
1605filter_show (struct vty *vty, char *name, afi_t afi)
1606{
1607  struct access_list *access;
1608  struct access_master *master;
1609  struct filter *mfilter;
1610  struct filter_cisco *filter;
1611  int write = 0;
1612
1613  master = access_master_get (afi);
1614  if (master == NULL)
1615    return 0;
1616
1617  for (access = master->num.head; access; access = access->next)
1618    {
1619      if (name && strcmp (access->name, name) != 0)
1620	continue;
1621
1622      write = 1;
1623
1624      for (mfilter = access->head; mfilter; mfilter = mfilter->next)
1625	{
1626	  filter = &mfilter->u.cfilter;
1627
1628	  if (write)
1629	    {
1630	      vty_out (vty, "%s IP%s access list %s%s",
1631		       mfilter->cisco ?
1632		       (filter->extended ? "Extended" : "Standard") : "Zebra",
1633		       afi == AFI_IP6 ? "v6" : "",
1634		       access->name, VTY_NEWLINE);
1635	      write = 0;
1636	    }
1637
1638	  vty_out (vty, "    %s%s", filter_type_str (mfilter),
1639		   mfilter->type == FILTER_DENY ? "  " : "");
1640
1641	  if (! mfilter->cisco)
1642	    config_write_access_zebra (vty, mfilter);
1643	  else if (filter->extended)
1644	    config_write_access_cisco (vty, mfilter);
1645	  else
1646	    {
1647	      if (filter->addr_mask.s_addr == 0xffffffff)
1648		vty_out (vty, " any%s", VTY_NEWLINE);
1649	      else
1650		{
1651		  vty_out (vty, " %s", inet_ntoa (filter->addr));
1652		  if (filter->addr_mask.s_addr != 0)
1653		    vty_out (vty, ", wildcard bits %s", inet_ntoa (filter->addr_mask));
1654		  vty_out (vty, "%s", VTY_NEWLINE);
1655		}
1656	    }
1657	}
1658    }
1659
1660  for (access = master->str.head; access; access = access->next)
1661    {
1662      if (name && strcmp (access->name, name) != 0)
1663	continue;
1664
1665      write = 1;
1666
1667      for (mfilter = access->head; mfilter; mfilter = mfilter->next)
1668	{
1669	  filter = &mfilter->u.cfilter;
1670
1671	  if (write)
1672	    {
1673	      vty_out (vty, "%s IP%s access list %s%s",
1674		       mfilter->cisco ?
1675		       (filter->extended ? "Extended" : "Standard") : "Zebra",
1676		       afi == AFI_IP6 ? "v6" : "",
1677		       access->name, VTY_NEWLINE);
1678	      write = 0;
1679	    }
1680
1681	  vty_out (vty, "    %s%s", filter_type_str (mfilter),
1682		   mfilter->type == FILTER_DENY ? "  " : "");
1683
1684	  if (! mfilter->cisco)
1685	    config_write_access_zebra (vty, mfilter);
1686	  else if (filter->extended)
1687	    config_write_access_cisco (vty, mfilter);
1688	  else
1689	    {
1690	      if (filter->addr_mask.s_addr == 0xffffffff)
1691		vty_out (vty, " any%s", VTY_NEWLINE);
1692	      else
1693		{
1694		  vty_out (vty, " %s", inet_ntoa (filter->addr));
1695		  if (filter->addr_mask.s_addr != 0)
1696		    vty_out (vty, ", wildcard bits %s", inet_ntoa (filter->addr_mask));
1697		  vty_out (vty, "%s", VTY_NEWLINE);
1698		}
1699	    }
1700	}
1701    }
1702  return CMD_SUCCESS;
1703}
1704
1705DEFUN (show_ip_access_list,
1706       show_ip_access_list_cmd,
1707       "show ip access-list",
1708       SHOW_STR
1709       IP_STR
1710       "List IP access lists\n")
1711{
1712  return filter_show (vty, NULL, AFI_IP);
1713}
1714
1715DEFUN (show_ip_access_list_name,
1716       show_ip_access_list_name_cmd,
1717       "show ip access-list (<1-99>|<100-199>|<1300-1999>|<2000-2699>|WORD)",
1718       SHOW_STR
1719       IP_STR
1720       "List IP access lists\n"
1721       "IP standard access list\n"
1722       "IP extended access list\n"
1723       "IP standard access list (expanded range)\n"
1724       "IP extended access list (expanded range)\n"
1725       "IP zebra access-list\n")
1726{
1727  return filter_show (vty, argv[0], AFI_IP);
1728}
1729
1730#ifdef HAVE_IPV6
1731DEFUN (show_ipv6_access_list,
1732       show_ipv6_access_list_cmd,
1733       "show ipv6 access-list",
1734       SHOW_STR
1735       IPV6_STR
1736       "List IPv6 access lists\n")
1737{
1738  return filter_show (vty, NULL, AFI_IP6);
1739}
1740
1741DEFUN (show_ipv6_access_list_name,
1742       show_ipv6_access_list_name_cmd,
1743       "show ipv6 access-list WORD",
1744       SHOW_STR
1745       IPV6_STR
1746       "List IPv6 access lists\n"
1747       "IPv6 zebra access-list\n")
1748{
1749  return filter_show (vty, argv[0], AFI_IP6);
1750}
1751#endif /* HAVE_IPV6 */
1752
1753void
1754config_write_access_cisco (struct vty *vty, struct filter *mfilter)
1755{
1756  struct filter_cisco *filter;
1757
1758  filter = &mfilter->u.cfilter;
1759
1760  if (filter->extended)
1761    {
1762      vty_out (vty, " ip");
1763      if (filter->addr_mask.s_addr == 0xffffffff)
1764	vty_out (vty, " any");
1765      else if (filter->addr_mask.s_addr == 0)
1766	vty_out (vty, " host %s", inet_ntoa (filter->addr));
1767      else
1768	{
1769	  vty_out (vty, " %s", inet_ntoa (filter->addr));
1770	  vty_out (vty, " %s", inet_ntoa (filter->addr_mask));
1771        }
1772
1773      if (filter->mask_mask.s_addr == 0xffffffff)
1774	vty_out (vty, " any");
1775      else if (filter->mask_mask.s_addr == 0)
1776	vty_out (vty, " host %s", inet_ntoa (filter->mask));
1777      else
1778	{
1779	  vty_out (vty, " %s", inet_ntoa (filter->mask));
1780	  vty_out (vty, " %s", inet_ntoa (filter->mask_mask));
1781	}
1782      vty_out (vty, "%s", VTY_NEWLINE);
1783    }
1784  else
1785    {
1786      if (filter->addr_mask.s_addr == 0xffffffff)
1787	vty_out (vty, " any%s", VTY_NEWLINE);
1788      else
1789	{
1790	  vty_out (vty, " %s", inet_ntoa (filter->addr));
1791	  if (filter->addr_mask.s_addr != 0)
1792	    vty_out (vty, " %s", inet_ntoa (filter->addr_mask));
1793	  vty_out (vty, "%s", VTY_NEWLINE);
1794	}
1795    }
1796}
1797
1798void
1799config_write_access_zebra (struct vty *vty, struct filter *mfilter)
1800{
1801  struct filter_zebra *filter;
1802  struct prefix *p;
1803  char buf[BUFSIZ];
1804
1805  filter = &mfilter->u.zfilter;
1806  p = &filter->prefix;
1807
1808  if (p->prefixlen == 0 && ! filter->exact)
1809    vty_out (vty, " any");
1810  else
1811    vty_out (vty, " %s/%d%s",
1812	     inet_ntop (p->family, &p->u.prefix, buf, BUFSIZ),
1813	     p->prefixlen,
1814	     filter->exact ? " exact-match" : "");
1815
1816  vty_out (vty, "%s", VTY_NEWLINE);
1817}
1818
1819int
1820config_write_access (struct vty *vty, afi_t afi)
1821{
1822  struct access_list *access;
1823  struct access_master *master;
1824  struct filter *mfilter;
1825  int write = 0;
1826
1827  master = access_master_get (afi);
1828  if (master == NULL)
1829    return 0;
1830
1831  for (access = master->num.head; access; access = access->next)
1832    {
1833      if (access->remark)
1834	{
1835	  vty_out (vty, "%saccess-list %s remark %s%s",
1836		   afi == AFI_IP ? "" : "ipv6 ",
1837		   access->name, access->remark,
1838		   VTY_NEWLINE);
1839	  write++;
1840	}
1841
1842      for (mfilter = access->head; mfilter; mfilter = mfilter->next)
1843	{
1844	  vty_out (vty, "%saccess-list %s %s",
1845	     afi == AFI_IP ? "" : "ipv6 ",
1846	     access->name,
1847	     filter_type_str (mfilter));
1848
1849	  if (mfilter->cisco)
1850	    config_write_access_cisco (vty, mfilter);
1851	  else
1852	    config_write_access_zebra (vty, mfilter);
1853
1854	  write++;
1855	}
1856    }
1857
1858  for (access = master->str.head; access; access = access->next)
1859    {
1860      if (access->remark)
1861	{
1862	  vty_out (vty, "%saccess-list %s remark %s%s",
1863		   afi == AFI_IP ? "" : "ipv6 ",
1864		   access->name, access->remark,
1865		   VTY_NEWLINE);
1866	  write++;
1867	}
1868
1869      for (mfilter = access->head; mfilter; mfilter = mfilter->next)
1870	{
1871	  vty_out (vty, "%saccess-list %s %s",
1872	     afi == AFI_IP ? "" : "ipv6 ",
1873	     access->name,
1874	     filter_type_str (mfilter));
1875
1876	  if (mfilter->cisco)
1877	    config_write_access_cisco (vty, mfilter);
1878	  else
1879	    config_write_access_zebra (vty, mfilter);
1880
1881	  write++;
1882	}
1883    }
1884  return write;
1885}
1886
1887/* Access-list node. */
1888struct cmd_node access_node =
1889{
1890  ACCESS_NODE,
1891  "",				/* Access list has no interface. */
1892  1
1893};
1894
1895int
1896config_write_access_ipv4 (struct vty *vty)
1897{
1898  return config_write_access (vty, AFI_IP);
1899}
1900
1901void
1902access_list_reset_ipv4 ()
1903{
1904  struct access_list *access;
1905  struct access_list *next;
1906  struct access_master *master;
1907
1908  master = access_master_get (AFI_IP);
1909  if (master == NULL)
1910    return;
1911
1912  for (access = master->num.head; access; access = next)
1913    {
1914      next = access->next;
1915      access_list_delete (access);
1916    }
1917  for (access = master->str.head; access; access = next)
1918    {
1919      next = access->next;
1920      access_list_delete (access);
1921    }
1922
1923  assert (master->num.head == NULL);
1924  assert (master->num.tail == NULL);
1925
1926  assert (master->str.head == NULL);
1927  assert (master->str.tail == NULL);
1928}
1929
1930/* Install vty related command. */
1931void
1932access_list_init_ipv4 ()
1933{
1934  install_node (&access_node, config_write_access_ipv4);
1935
1936#ifdef FOX_LIST_SUPPORT
1937  install_element (ENABLE_NODE, &show_ip_access_list_cmd);
1938  install_element (ENABLE_NODE, &show_ip_access_list_name_cmd);
1939#endif /* FOX_LIST_SUPPORT */
1940
1941  /* Zebra access-list */
1942  install_element (CONFIG_NODE, &access_list_cmd);
1943  install_element (CONFIG_NODE, &access_list_exact_cmd);
1944  install_element (CONFIG_NODE, &access_list_any_cmd);
1945  install_element (CONFIG_NODE, &no_access_list_cmd);
1946  install_element (CONFIG_NODE, &no_access_list_exact_cmd);
1947  install_element (CONFIG_NODE, &no_access_list_any_cmd);
1948
1949#ifdef FOX_LIST_SUPPORT
1950  /* Standard access-list */
1951  install_element (CONFIG_NODE, &access_list_standard_cmd);
1952  install_element (CONFIG_NODE, &access_list_standard_nomask_cmd);
1953  install_element (CONFIG_NODE, &access_list_standard_host_cmd);
1954  install_element (CONFIG_NODE, &access_list_standard_any_cmd);
1955  install_element (CONFIG_NODE, &no_access_list_standard_cmd);
1956  install_element (CONFIG_NODE, &no_access_list_standard_nomask_cmd);
1957  install_element (CONFIG_NODE, &no_access_list_standard_host_cmd);
1958  install_element (CONFIG_NODE, &no_access_list_standard_any_cmd);
1959
1960  /* Extended access-list */
1961  install_element (CONFIG_NODE, &access_list_extended_cmd);
1962  install_element (CONFIG_NODE, &access_list_extended_any_mask_cmd);
1963  install_element (CONFIG_NODE, &access_list_extended_mask_any_cmd);
1964  install_element (CONFIG_NODE, &access_list_extended_any_any_cmd);
1965  install_element (CONFIG_NODE, &access_list_extended_host_mask_cmd);
1966  install_element (CONFIG_NODE, &access_list_extended_mask_host_cmd);
1967  install_element (CONFIG_NODE, &access_list_extended_host_host_cmd);
1968  install_element (CONFIG_NODE, &access_list_extended_any_host_cmd);
1969  install_element (CONFIG_NODE, &access_list_extended_host_any_cmd);
1970  install_element (CONFIG_NODE, &no_access_list_extended_cmd);
1971  install_element (CONFIG_NODE, &no_access_list_extended_any_mask_cmd);
1972  install_element (CONFIG_NODE, &no_access_list_extended_mask_any_cmd);
1973  install_element (CONFIG_NODE, &no_access_list_extended_any_any_cmd);
1974  install_element (CONFIG_NODE, &no_access_list_extended_host_mask_cmd);
1975  install_element (CONFIG_NODE, &no_access_list_extended_mask_host_cmd);
1976  install_element (CONFIG_NODE, &no_access_list_extended_host_host_cmd);
1977  install_element (CONFIG_NODE, &no_access_list_extended_any_host_cmd);
1978  install_element (CONFIG_NODE, &no_access_list_extended_host_any_cmd);
1979
1980  install_element (CONFIG_NODE, &access_list_remark_cmd);
1981  install_element (CONFIG_NODE, &no_access_list_all_cmd);
1982  install_element (CONFIG_NODE, &no_access_list_remark_cmd);
1983  install_element (CONFIG_NODE, &no_access_list_remark_arg_cmd);
1984 #endif /* FOX_LIST_SUPPORT */
1985}
1986
1987#ifdef HAVE_IPV6
1988struct cmd_node access_ipv6_node =
1989{
1990  ACCESS_IPV6_NODE,
1991  "",
1992  1
1993};
1994
1995int
1996config_write_access_ipv6 (struct vty *vty)
1997{
1998  return config_write_access (vty, AFI_IP6);
1999}
2000
2001void
2002access_list_reset_ipv6 ()
2003{
2004  struct access_list *access;
2005  struct access_list *next;
2006  struct access_master *master;
2007
2008  master = access_master_get (AFI_IP6);
2009  if (master == NULL)
2010    return;
2011
2012  for (access = master->num.head; access; access = next)
2013    {
2014      next = access->next;
2015      access_list_delete (access);
2016    }
2017  for (access = master->str.head; access; access = next)
2018    {
2019      next = access->next;
2020      access_list_delete (access);
2021    }
2022
2023  assert (master->num.head == NULL);
2024  assert (master->num.tail == NULL);
2025
2026  assert (master->str.head == NULL);
2027  assert (master->str.tail == NULL);
2028}
2029
2030void
2031access_list_init_ipv6 ()
2032{
2033  install_node (&access_ipv6_node, config_write_access_ipv6);
2034
2035  install_element (ENABLE_NODE, &show_ipv6_access_list_cmd);
2036  install_element (ENABLE_NODE, &show_ipv6_access_list_name_cmd);
2037
2038  install_element (CONFIG_NODE, &ipv6_access_list_cmd);
2039  install_element (CONFIG_NODE, &ipv6_access_list_exact_cmd);
2040  install_element (CONFIG_NODE, &ipv6_access_list_any_cmd);
2041  install_element (CONFIG_NODE, &no_ipv6_access_list_exact_cmd);
2042  install_element (CONFIG_NODE, &no_ipv6_access_list_cmd);
2043  install_element (CONFIG_NODE, &no_ipv6_access_list_any_cmd);
2044
2045  install_element (CONFIG_NODE, &no_ipv6_access_list_all_cmd);
2046  install_element (CONFIG_NODE, &ipv6_access_list_remark_cmd);
2047  install_element (CONFIG_NODE, &no_ipv6_access_list_remark_cmd);
2048  install_element (CONFIG_NODE, &no_ipv6_access_list_remark_arg_cmd);
2049}
2050#endif /* HAVE_IPV6 */
2051
2052void
2053access_list_init ()
2054{
2055  access_list_init_ipv4 ();
2056#ifdef HAVE_IPV6
2057  access_list_init_ipv6();
2058#endif /* HAVE_IPV6 */
2059}
2060
2061void
2062access_list_reset ()
2063{
2064  access_list_reset_ipv4 ();
2065#ifdef HAVE_IPV6
2066  access_list_reset_ipv6();
2067#endif /* HAVE_IPV6 */
2068}
2069