File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / quagga / vtysh / vtysh_config.c
Revision 1.1.1.3 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Wed Nov 2 10:09:10 2016 UTC (7 years, 8 months ago) by misho
Branches: quagga, MAIN
CVS tags: v1_0_20160315, HEAD
quagga 1.0.20160315

    1: /* Configuration generator.
    2:    Copyright (C) 2000 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 it
    7: under the terms of the GNU General Public License as published by the
    8: Free Software Foundation; either version 2, or (at your option) any
    9: 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 Free
   18: Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
   19: 02111-1307, USA.  */
   20: 
   21: #include <zebra.h>
   22: 
   23: #include "command.h"
   24: #include "linklist.h"
   25: #include "memory.h"
   26: 
   27: #include "vtysh/vtysh.h"
   28: 
   29: vector configvec;
   30: 
   31: extern int vtysh_writeconfig_integrated;
   32: 
   33: struct config
   34: {
   35:   /* Configuration node name. */
   36:   char *name;
   37: 
   38:   /* Configuration string line. */
   39:   struct list *line;
   40: 
   41:   /* Configuration can be nest. */
   42:   struct config *config;
   43: 
   44:   /* Index of this config. */
   45:   u_int32_t index;
   46: };
   47: 
   48: struct list *config_top;
   49: 
   50: static int
   51: line_cmp (char *c1, char *c2)
   52: {
   53:   return strcmp (c1, c2);
   54: }
   55: 
   56: static void
   57: line_del (char *line)
   58: {
   59:   XFREE (MTYPE_VTYSH_CONFIG_LINE, line);
   60: }
   61: 
   62: static struct config *
   63: config_new ()
   64: {
   65:   struct config *config;
   66:   config = XCALLOC (MTYPE_VTYSH_CONFIG, sizeof (struct config));
   67:   return config;
   68: }
   69: 
   70: static int
   71: config_cmp (struct config *c1, struct config *c2)
   72: {
   73:   return strcmp (c1->name, c2->name);
   74: }
   75: 
   76: static void
   77: config_del (struct config* config)
   78: {
   79:   list_delete (config->line);
   80:   if (config->name)
   81:     XFREE (MTYPE_VTYSH_CONFIG_LINE, config->name);
   82:   XFREE (MTYPE_VTYSH_CONFIG, config);
   83: }
   84: 
   85: static struct config *
   86: config_get (int index, const char *line)
   87: {
   88:   struct config *config;
   89:   struct config *config_loop;
   90:   struct list *master;
   91:   struct listnode *node, *nnode;
   92: 
   93:   config = config_loop = NULL;
   94: 
   95:   master = vector_lookup_ensure (configvec, index);
   96: 
   97:   if (! master)
   98:     {
   99:       master = list_new ();
  100:       master->del = (void (*) (void *))config_del;
  101:       master->cmp = (int (*)(void *, void *)) config_cmp;
  102:       vector_set_index (configvec, index, master);
  103:     }
  104:   
  105:   for (ALL_LIST_ELEMENTS (master, node, nnode, config_loop))
  106:     {
  107:       if (strcmp (config_loop->name, line) == 0)
  108: 	config = config_loop;
  109:     }
  110: 
  111:   if (! config)
  112:     {
  113:       config = config_new ();
  114:       config->line = list_new ();
  115:       config->line->del = (void (*) (void *))line_del;
  116:       config->line->cmp = (int (*)(void *, void *)) line_cmp;
  117:       config->name = XSTRDUP (MTYPE_VTYSH_CONFIG_LINE, line);
  118:       config->index = index;
  119:       listnode_add (master, config);
  120:     }
  121:   return config;
  122: }
  123: 
  124: static void
  125: config_add_line (struct list *config, const char *line)
  126: {
  127:   listnode_add (config, XSTRDUP (MTYPE_VTYSH_CONFIG_LINE, line));
  128: }
  129: 
  130: static void
  131: config_add_line_uniq (struct list *config, const char *line)
  132: {
  133:   struct listnode *node, *nnode;
  134:   char *pnt;
  135: 
  136:   for (ALL_LIST_ELEMENTS (config, node, nnode, pnt))
  137:     {
  138:       if (strcmp (pnt, line) == 0)
  139: 	return;
  140:     }
  141:   listnode_add_sort (config, XSTRDUP (MTYPE_VTYSH_CONFIG_LINE, line));
  142: }
  143: 
  144: static void
  145: vtysh_config_parse_line (const char *line)
  146: {
  147:   char c;
  148:   static struct config *config = NULL;
  149: 
  150:   if (! line)
  151:     return;
  152: 
  153:   c = line[0];
  154: 
  155:   if (c == '\0')
  156:     return;
  157: 
  158:   /* printf ("[%s]\n", line); */
  159: 
  160:   switch (c)
  161:     {
  162:     case '!':
  163:     case '#':
  164:       break;
  165:     case ' ':
  166:       /* Store line to current configuration. */
  167:       if (config)
  168: 	{
  169: 	  if (strncmp (line, " address-family vpnv4",
  170: 	      strlen (" address-family vpnv4")) == 0)
  171: 	    config = config_get (BGP_VPNV4_NODE, line);
  172: 	  else if (strncmp (line, " address-family vpn6",
  173: 	      strlen (" address-family vpn6")) == 0)
  174: 	    config = config_get (BGP_VPNV6_NODE, line);
  175: 	  else if (strncmp (line, " address-family encapv6",
  176: 	      strlen (" address-family encapv6")) == 0)
  177: 	    config = config_get (BGP_ENCAPV6_NODE, line);
  178: 	  else if (strncmp (line, " address-family encap",
  179: 	      strlen (" address-family encap")) == 0)
  180: 	    config = config_get (BGP_ENCAP_NODE, line);
  181: 	  else if (strncmp (line, " address-family ipv4 multicast",
  182: 		   strlen (" address-family ipv4 multicast")) == 0)
  183: 	    config = config_get (BGP_IPV4M_NODE, line);
  184: 	  else if (strncmp (line, " address-family ipv6",
  185: 		   strlen (" address-family ipv6")) == 0)
  186: 	    config = config_get (BGP_IPV6_NODE, line);
  187: 	  else if (config->index == RMAP_NODE ||
  188: 	           config->index == INTERFACE_NODE ||
  189: 		   config->index == VTY_NODE)
  190: 	    config_add_line_uniq (config->line, line);
  191: 	  else
  192: 	    config_add_line (config->line, line);
  193: 	}
  194:       else
  195: 	config_add_line (config_top, line);
  196:       break;
  197:     default:
  198:       if (strncmp (line, "interface", strlen ("interface")) == 0)
  199: 	config = config_get (INTERFACE_NODE, line);
  200:       else if (strncmp (line, "router-id", strlen ("router-id")) == 0)
  201: 	config = config_get (ZEBRA_NODE, line);
  202:       else if (strncmp (line, "router rip", strlen ("router rip")) == 0)
  203: 	config = config_get (RIP_NODE, line);
  204:       else if (strncmp (line, "router ripng", strlen ("router ripng")) == 0)
  205: 	config = config_get (RIPNG_NODE, line);
  206:       else if (strncmp (line, "router ospf", strlen ("router ospf")) == 0)
  207: 	config = config_get (OSPF_NODE, line);
  208:       else if (strncmp (line, "router ospf6", strlen ("router ospf6")) == 0)
  209: 	config = config_get (OSPF6_NODE, line);
  210:       else if (strncmp (line, "router bgp", strlen ("router bgp")) == 0)
  211: 	config = config_get (BGP_NODE, line);
  212:       else if (strncmp (line, "router isis", strlen ("router isis")) == 0)
  213:   	config = config_get (ISIS_NODE, line);
  214:       else if (strncmp (line, "router bgp", strlen ("router bgp")) == 0)
  215: 	config = config_get (BGP_NODE, line);
  216:       else if (strncmp (line, "route-map", strlen ("route-map")) == 0)
  217: 	config = config_get (RMAP_NODE, line);
  218:       else if (strncmp (line, "access-list", strlen ("access-list")) == 0)
  219: 	config = config_get (ACCESS_NODE, line);
  220:       else if (strncmp (line, "ipv6 access-list",
  221: 	       strlen ("ipv6 access-list")) == 0)
  222: 	config = config_get (ACCESS_IPV6_NODE, line);
  223:       else if (strncmp (line, "ip prefix-list",
  224: 	       strlen ("ip prefix-list")) == 0)
  225: 	config = config_get (PREFIX_NODE, line);
  226:       else if (strncmp (line, "ipv6 prefix-list",
  227: 	       strlen ("ipv6 prefix-list")) == 0)
  228: 	config = config_get (PREFIX_IPV6_NODE, line);
  229:       else if (strncmp (line, "ip as-path access-list",
  230: 	       strlen ("ip as-path access-list")) == 0)
  231: 	config = config_get (AS_LIST_NODE, line);
  232:       else if (strncmp (line, "ip community-list",
  233: 	       strlen ("ip community-list")) == 0)
  234: 	config = config_get (COMMUNITY_LIST_NODE, line);
  235:       else if (strncmp (line, "ip route", strlen ("ip route")) == 0)
  236: 	config = config_get (IP_NODE, line);
  237:       else if (strncmp (line, "ipv6 route", strlen ("ipv6 route")) == 0)
  238:    	config = config_get (IP_NODE, line);
  239:       else if (strncmp (line, "key", strlen ("key")) == 0)
  240: 	config = config_get (KEYCHAIN_NODE, line);
  241:       else if (strncmp (line, "line", strlen ("line")) == 0)
  242: 	config = config_get (VTY_NODE, line);
  243:       else if ( (strncmp (line, "ipv6 forwarding",
  244: 		 strlen ("ipv6 forwarding")) == 0)
  245: 	       || (strncmp (line, "ip forwarding",
  246: 		   strlen ("ip forwarding")) == 0) )
  247: 	config = config_get (FORWARDING_NODE, line);
  248:       else if (strncmp (line, "service", strlen ("service")) == 0)
  249: 	config = config_get (SERVICE_NODE, line);
  250:       else if (strncmp (line, "debug", strlen ("debug")) == 0)
  251: 	config = config_get (DEBUG_NODE, line);
  252:       else if (strncmp (line, "password", strlen ("password")) == 0
  253: 	       || strncmp (line, "enable password",
  254: 			   strlen ("enable password")) == 0)
  255: 	config = config_get (AAA_NODE, line);
  256:       else if (strncmp (line, "ip protocol", strlen ("ip protocol")) == 0)
  257: 	config = config_get (PROTOCOL_NODE, line);
  258:       else
  259: 	{
  260: 	  if (strncmp (line, "log", strlen ("log")) == 0
  261: 	      || strncmp (line, "hostname", strlen ("hostname")) == 0
  262: 	     )
  263: 	    config_add_line_uniq (config_top, line);
  264: 	  else
  265: 	    config_add_line (config_top, line);
  266: 	  config = NULL;
  267: 	}
  268:       break;
  269:     }
  270: }
  271: 
  272: void
  273: vtysh_config_parse (char *line)
  274: {
  275:   char *begin;
  276:   char *pnt;
  277:   
  278:   begin = pnt = line;
  279: 
  280:   while (*pnt != '\0')
  281:     {
  282:       if (*pnt == '\n')
  283: 	{
  284: 	  *pnt++ = '\0';
  285: 	  vtysh_config_parse_line (begin);
  286: 	  begin = pnt;
  287: 	}
  288:       else
  289: 	{
  290: 	  pnt++;
  291: 	}
  292:     }
  293: }
  294: 
  295: /* Macro to check delimiter is needed between each configuration line
  296:  * or not. */
  297: #define NO_DELIMITER(I)  \
  298:   ((I) == ACCESS_NODE || (I) == PREFIX_NODE || (I) == IP_NODE \
  299:    || (I) == AS_LIST_NODE || (I) == COMMUNITY_LIST_NODE || \
  300:    (I) == ACCESS_IPV6_NODE || (I) == PREFIX_IPV6_NODE \
  301:    || (I) == SERVICE_NODE || (I) == FORWARDING_NODE || (I) == DEBUG_NODE \
  302:    || (I) == AAA_NODE)
  303: 
  304: /* Display configuration to file pointer. */
  305: void
  306: vtysh_config_dump (FILE *fp)
  307: {
  308:   struct listnode *node, *nnode;
  309:   struct listnode *mnode, *mnnode;
  310:   struct config *config;
  311:   struct list *master;
  312:   char *line;
  313:   unsigned int i;
  314: 
  315:   for (ALL_LIST_ELEMENTS (config_top, node, nnode, line))
  316:     {
  317:       fprintf (fp, "%s\n", line);
  318:       fflush (fp);
  319:     }
  320:   fprintf (fp, "!\n");
  321:   fflush (fp);
  322: 
  323:   for (i = 0; i < vector_active (configvec); i++)
  324:     if ((master = vector_slot (configvec, i)) != NULL)
  325:       {
  326: 	for (ALL_LIST_ELEMENTS (master, node, nnode, config))
  327: 	  {
  328: 	    fprintf (fp, "%s\n", config->name);
  329: 	    fflush (fp);
  330: 
  331: 	    for (ALL_LIST_ELEMENTS (config->line, mnode, mnnode, line))
  332: 	      {
  333: 		fprintf  (fp, "%s\n", line);
  334: 		fflush (fp);
  335: 	      }
  336: 	    if (! NO_DELIMITER (i))
  337: 	      {
  338: 		fprintf (fp, "!\n");
  339: 		fflush (fp);
  340: 	      }
  341: 	  }
  342: 	if (NO_DELIMITER (i))
  343: 	  {
  344: 	    fprintf (fp, "!\n");
  345: 	    fflush (fp);
  346: 	  }
  347:       }
  348: 
  349:   for (i = 0; i < vector_active (configvec); i++)
  350:     if ((master = vector_slot (configvec, i)) != NULL)
  351:       {
  352: 	list_delete (master);
  353: 	vector_slot (configvec, i) = NULL;
  354:       }
  355:   list_delete_all_node (config_top);
  356: }
  357: 
  358: /* Read up configuration file from file_name. */
  359: static void
  360: vtysh_read_file (FILE *confp)
  361: {
  362:   int ret;
  363:   struct vty *vty;
  364: 
  365:   vty = vty_new ();
  366:   vty->fd = 0;			/* stdout */
  367:   vty->type = VTY_TERM;
  368:   vty->node = CONFIG_NODE;
  369:   
  370:   vtysh_execute_no_pager ("enable");
  371:   vtysh_execute_no_pager ("configure terminal");
  372: 
  373:   /* Execute configuration file. */
  374:   ret = vtysh_config_from_file (vty, confp);
  375: 
  376:   vtysh_execute_no_pager ("end");
  377:   vtysh_execute_no_pager ("disable");
  378: 
  379:   vty_close (vty);
  380: 
  381:   if (ret != CMD_SUCCESS) 
  382:     {
  383:       switch (ret)
  384: 	{
  385: 	case CMD_ERR_AMBIGUOUS:
  386: 	  fprintf (stderr, "Ambiguous command.\n");
  387: 	  break;
  388: 	case CMD_ERR_NO_MATCH:
  389: 	  fprintf (stderr, "There is no such command.\n");
  390: 	  break;
  391: 	}
  392:       fprintf (stderr, "Error occured during reading below line.\n%s\n", 
  393: 	       vty->buf);
  394:       exit (1);
  395:     }
  396: }
  397: 
  398: /* Read up configuration file from config_default_dir. */
  399: int
  400: vtysh_read_config (char *config_default_dir)
  401: {
  402:   FILE *confp = NULL;
  403: 
  404:   confp = fopen (config_default_dir, "r");
  405:   if (confp == NULL)
  406:     return (1);
  407: 
  408:   vtysh_read_file (confp);
  409:   fclose (confp);
  410:   host_config_set (config_default_dir);
  411: 
  412:   return (0);
  413: }
  414: 
  415: /* We don't write vtysh specific into file from vtysh. vtysh.conf should
  416:  * be edited by hand. So, we handle only "write terminal" case here and
  417:  * integrate vtysh specific conf with conf from daemons.
  418:  */
  419: void
  420: vtysh_config_write ()
  421: {
  422:   char line[81];
  423:   extern struct host host;
  424: 
  425:   if (host.name)
  426:     {
  427:       sprintf (line, "hostname %s", host.name);
  428:       vtysh_config_parse_line(line);
  429:     }
  430:   if (vtysh_writeconfig_integrated)
  431:     vtysh_config_parse_line ("service integrated-vtysh-config");
  432: }
  433: 
  434: void
  435: vtysh_config_init ()
  436: {
  437:   config_top = list_new ();
  438:   config_top->del = (void (*) (void *))line_del;
  439:   configvec = vector_init (1);
  440: }

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