File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / quagga / lib / filter.c
Revision 1.1.1.2 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Tue Oct 9 09:22:28 2012 UTC (11 years, 9 months ago) by misho
Branches: quagga, MAIN
CVS tags: v0_99_22p0, v0_99_22, v0_99_21, HEAD
quagga

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

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>