123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439 |
- /* 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 <zebra.h>
- #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->index == INTERFACE_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 ripng", strlen ("router ripng")) == 0)
- config = config_get (RIPNG_NODE, line);
- else if (strncmp (line, "router ospf", strlen ("router ospf")) == 0)
- config = config_get (OSPF_NODE, line);
- else if (strncmp (line, "router ospf6", strlen ("router ospf6")) == 0)
- config = config_get (OSPF6_NODE, line);
- else if (strncmp (line, "router bgp", strlen ("router bgp")) == 0)
- config = config_get (BGP_NODE, line);
- else if (strncmp (line, "router isis", strlen ("router bgp")) == 0)
- config = config_get (ISIS_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, "ipv6 access-list", strlen ("ipv6 access-list")) == 0)
- config = config_get (ACCESS_IPV6_NODE, line);
- else if (strncmp (line, "ip prefix-list", strlen ("ip prefix-list")) == 0)
- config = config_get (PREFIX_NODE, line);
- else if (strncmp (line, "ipv6 prefix-list", strlen ("ipv6 prefix-list")) == 0)
- config = config_get (PREFIX_IPV6_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, "ipv6 route", strlen ("ipv6 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 || \
- (I) == ACCESS_IPV6_NODE || (I) == PREFIX_IPV6_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);
- }
|