From 718e3744195351130f4ce7dbe0613f4b3e23df93 Mon Sep 17 00:00:00 2001 From: paul Date: Fri, 13 Dec 2002 20:15:29 +0000 Subject: Initial revision --- vtysh/vtysh_config.c | 426 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 426 insertions(+) create mode 100644 vtysh/vtysh_config.c (limited to 'vtysh/vtysh_config.c') diff --git a/vtysh/vtysh_config.c b/vtysh/vtysh_config.c new file mode 100644 index 00000000..b9c9ad6d --- /dev/null +++ b/vtysh/vtysh_config.c @@ -0,0 +1,426 @@ +/* Configuration generator. + Copyright (C) 2000 Kunihiro Ishiguro + +This file is part of GNU Zebra. + +GNU Zebra is free software; you can redistribute it and/or modify it +under the terms of the GNU General Public License as published by the +Free Software Foundation; either version 2, or (at your option) any +later version. + +GNU Zebra is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Zebra; see the file COPYING. If not, write to the Free +Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA +02111-1307, USA. */ + +#include + +#include "command.h" +#include "linklist.h" +#include "memory.h" + +#include "vtysh/vtysh.h" + +vector configvec; + +struct config +{ + /* Configuration node name. */ + char *name; + + /* Configuration string line. */ + struct list *line; + + /* Configuration can be nest. */ + struct config *config; + + /* Index of this config. */ + u_int32_t index; +}; + +struct list *config_top; + +int +line_cmp (char *c1, char *c2) +{ + return strcmp (c1, c2); +} + +void +line_del (char *line) +{ + XFREE (MTYPE_VTYSH_CONFIG_LINE, line); +} + +struct config * +config_new () +{ + struct config *config; + config = XCALLOC (MTYPE_VTYSH_CONFIG, sizeof (struct config)); + return config; +} + +int +config_cmp (struct config *c1, struct config *c2) +{ + return strcmp (c1->name, c2->name); +} + +void +config_del (struct config* config) +{ + list_delete (config->line); + if (config->name) + XFREE (MTYPE_VTYSH_CONFIG_LINE, config->name); + XFREE (MTYPE_VTYSH_CONFIG, config); +} + +struct config * +config_get (int index, char *line) +{ + struct config *config; + struct config *config_loop; + struct list *master; + struct listnode *nn; + + config = config_loop = NULL; + + master = vector_lookup_ensure (configvec, index); + + if (! master) + { + master = list_new (); + master->del = (void (*) (void *))config_del; + master->cmp = (int (*)(void *, void *)) config_cmp; + vector_set_index (configvec, index, master); + } + + LIST_LOOP (master, config_loop, nn) + { + if (strcmp (config_loop->name, line) == 0) + config = config_loop; + } + + if (! config) + { + config = config_new (); + config->line = list_new (); + config->line->del = (void (*) (void *))line_del; + config->line->cmp = (int (*)(void *, void *)) line_cmp; + config->name = XSTRDUP (MTYPE_VTYSH_CONFIG_LINE, line); + config->index = index; + listnode_add (master, config); + } + return config; +} + +void +config_add_line (struct list *config, char *line) +{ + listnode_add (config, XSTRDUP (MTYPE_VTYSH_CONFIG_LINE, line)); +} + +void +config_add_line_uniq (struct list *config, char *line) +{ + struct listnode *nn; + char *pnt; + + LIST_LOOP (config, pnt, nn) + { + if (strcmp (pnt, line) == 0) + return; + } + listnode_add_sort (config, XSTRDUP (MTYPE_VTYSH_CONFIG_LINE, line)); +} + +void +vtysh_config_parse_line (char *line) +{ + char c; + static struct config *config = NULL; + + if (! line) + return; + + c = line[0]; + + if (c == '\0') + return; + + /* printf ("[%s]\n", line); */ + + switch (c) + { + case '!': + case '#': + break; + case ' ': + /* Store line to current configuration. */ + if (config) + { + if (strncmp (line, " address-family vpnv4", strlen (" address-family vpnv4")) == 0) + config = config_get (BGP_VPNV4_NODE, line); + else if (strncmp (line, " address-family ipv4 multicast", strlen (" address-family ipv4 multicast")) == 0) + config = config_get (BGP_IPV4M_NODE, line); + else if (strncmp (line, " address-family ipv6", strlen (" address-family ipv6")) == 0) + config = config_get (BGP_IPV6_NODE, line); + else if (config->index == RMAP_NODE) + config_add_line_uniq (config->line, line); + else + config_add_line (config->line, line); + } + else + config_add_line (config_top, line); + break; + default: + if (strncmp (line, "interface", strlen ("interface")) == 0) + config = config_get (INTERFACE_NODE, line); + else if (strncmp (line, "router rip", strlen ("router rip")) == 0) + config = config_get (RIP_NODE, line); + else if (strncmp (line, "router ospf", strlen ("router ospf")) == 0) + config = config_get (OSPF_NODE, line); + else if (strncmp (line, "router bgp", strlen ("router bgp")) == 0) + config = config_get (BGP_NODE, line); + else if (strncmp (line, "router", strlen ("router")) == 0) + config = config_get (BGP_NODE, line); + else if (strncmp (line, "route-map", strlen ("route-map")) == 0) + config = config_get (RMAP_NODE, line); + else if (strncmp (line, "access-list", strlen ("access-list")) == 0) + config = config_get (ACCESS_NODE, line); + else if (strncmp (line, "ip prefix-list", strlen ("ip prefix-list")) == 0) + config = config_get (PREFIX_NODE, line); + else if (strncmp (line, "ip as-path access-list", strlen ("ip as-path access-list")) == 0) + config = config_get (AS_LIST_NODE, line); + else if (strncmp (line, "ip community-list", strlen ("ip community-list")) == 0) + config = config_get (COMMUNITY_LIST_NODE, line); + else if (strncmp (line, "ip route", strlen ("ip route")) == 0) + config = config_get (IP_NODE, line); + else if (strncmp (line, "key", strlen ("key")) == 0) + config = config_get (KEYCHAIN_NODE, line); + else + { + if (strncmp (line, "log", strlen ("log")) == 0 + || strncmp (line, "hostname", strlen ("hostname")) == 0 + || strncmp (line, "password", strlen ("hostname")) == 0) + config_add_line_uniq (config_top, line); + else + config_add_line (config_top, line); + config = NULL; + } + break; + } +} + +void +vtysh_config_parse (char *line) +{ + char *begin; + char *pnt; + + begin = pnt = line; + + while (*pnt != '\0') + { + if (*pnt == '\n') + { + *pnt++ = '\0'; + vtysh_config_parse_line (begin); + begin = pnt; + } + else + { + pnt++; + } + } +} + +/* Macro to check delimiter is needed between each configuration line + or not. */ +#define NO_DELIMITER(I) \ + ((I) == ACCESS_NODE || (I) == PREFIX_NODE || (I) == IP_NODE \ + || (I) == AS_LIST_NODE || (I) == COMMUNITY_LIST_NODE) + +/* Display configuration to file pointer. */ +void +vtysh_config_dump (FILE *fp) +{ + struct listnode *nn; + struct listnode *nm; + struct config *config; + struct list *master; + char *line; + int i; + + LIST_LOOP (config_top, line, nn) + { + fprintf (fp, "%s\n", line); + fflush (fp); + } + fprintf (fp, "!\n"); + fflush (fp); + + for (i = 0; i < vector_max (configvec); i++) + if ((master = vector_slot (configvec, i)) != NULL) + { + LIST_LOOP (master, config, nn) + { + fprintf (fp, "%s\n", config->name); + fflush (fp); + + LIST_LOOP (config->line, line, nm) + { + fprintf (fp, "%s\n", line); + fflush (fp); + } + if (! NO_DELIMITER (i)) + { + fprintf (fp, "!\n"); + fflush (fp); + } + } + if (NO_DELIMITER (i)) + { + fprintf (fp, "!\n"); + fflush (fp); + } + } + + for (i = 0; i < vector_max (configvec); i++) + if ((master = vector_slot (configvec, i)) != NULL) + { + list_delete (master); + vector_slot (configvec, i) = NULL; + } + list_delete_all_node (config_top); +} + +/* Read up configuration file from file_name. */ +static void +vtysh_read_file (FILE *confp) +{ + int ret; + struct vty *vty; + + vty = vty_new (); + vty->fd = 0; /* stdout */ + vty->type = VTY_TERM; + vty->node = CONFIG_NODE; + + vtysh_execute_no_pager ("enable"); + vtysh_execute_no_pager ("configure terminal"); + + /* Execute configuration file */ + ret = vtysh_config_from_file (vty, confp); + + vtysh_execute_no_pager ("end"); + vtysh_execute_no_pager ("disable"); + + vty_close (vty); + + if (ret != CMD_SUCCESS) + { + switch (ret) + { + case CMD_ERR_AMBIGUOUS: + fprintf (stderr, "Ambiguous command.\n"); + break; + case CMD_ERR_NO_MATCH: + fprintf (stderr, "There is no such command.\n"); + break; + } + fprintf (stderr, "Error occured during reading below line.\n%s\n", + vty->buf); + exit (1); + } +} + +/* Read up configuration file from file_name. */ +void +vtysh_read_config (char *config_file, + char *config_current_dir, + char *config_default_dir) +{ + char *cwd; + FILE *confp = NULL; + char *fullpath; + + /* If -f flag specified. */ + if (config_file != NULL) + { + if (! IS_DIRECTORY_SEP (config_file[0])) + { + cwd = getcwd (NULL, MAXPATHLEN); + fullpath = XMALLOC (MTYPE_TMP, + strlen (cwd) + strlen (config_file) + 2); + sprintf (fullpath, "%s/%s", cwd, config_file); + } + else + fullpath = config_file; + + confp = fopen (fullpath, "r"); + + if (confp == NULL) + { + fprintf (stderr, "can't open configuration file [%s]\n", + config_file); + exit(1); + } + } + else + { + /* Relative path configuration file open. */ + if (config_current_dir) + confp = fopen (config_current_dir, "r"); + + /* If there is no relative path exists, open system default file. */ + if (confp == NULL) + { + confp = fopen (config_default_dir, "r"); + if (confp == NULL) + { + fprintf (stderr, "can't open configuration file [%s]\n", + config_default_dir); + exit (1); + } + else + fullpath = config_default_dir; + } + else + { + /* Rleative path configuration file. */ + cwd = getcwd (NULL, MAXPATHLEN); + fullpath = XMALLOC (MTYPE_TMP, + strlen (cwd) + strlen (config_current_dir) + 2); + sprintf (fullpath, "%s/%s", cwd, config_current_dir); + } + } + vtysh_read_file (confp); + + fclose (confp); + + host_config_set (fullpath); +} + +void +vtysh_config_write (FILE *fp) +{ + extern struct host host; + + if (host.name) + fprintf (fp, "hostname %s\n", host.name); + fprintf (fp, "!\n"); +} + +void +vtysh_config_init () +{ + config_top = list_new (); + config_top->del = (void (*) (void *))line_del; + configvec = vector_init (1); +} -- cgit v1.2.1