vtysh_config.c
上传用户:xiaozhuqw
上传日期:2009-11-15
资源大小:1338k
文件大小:11k
源码类别:

网络

开发平台:

Unix_Linux

  1. /* Configuration generator.
  2.    Copyright (C) 2000 Kunihiro Ishiguro
  3. This file is part of GNU Zebra.
  4. GNU Zebra is free software; you can redistribute it and/or modify it
  5. under the terms of the GNU General Public License as published by the
  6. Free Software Foundation; either version 2, or (at your option) any
  7. later version.
  8. GNU Zebra is distributed in the hope that it will be useful, but
  9. WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  11. General Public License for more details.
  12. You should have received a copy of the GNU General Public License
  13. along with GNU Zebra; see the file COPYING.  If not, write to the Free
  14. Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
  15. 02111-1307, USA.  */
  16. #include <zebra.h>
  17. #include "command.h"
  18. #include "linklist.h"
  19. #include "memory.h"
  20. #include "vtysh/vtysh.h"
  21. vector configvec;
  22. struct config
  23. {
  24.   /* Configuration node name. */
  25.   char *name;
  26.   /* Configuration string line. */
  27.   struct list *line;
  28.   /* Configuration can be nest. */
  29.   struct config *config;
  30.   /* Index of this config. */
  31.   u_int32_t index;
  32. };
  33. struct list *config_top;
  34. int
  35. line_cmp (char *c1, char *c2)
  36. {
  37.   return strcmp (c1, c2);
  38. }
  39. void
  40. line_del (char *line)
  41. {
  42.   XFREE (MTYPE_VTYSH_CONFIG_LINE, line);
  43. }
  44. struct config *
  45. config_new ()
  46. {
  47.   struct config *config;
  48.   config = XCALLOC (MTYPE_VTYSH_CONFIG, sizeof (struct config));
  49.   return config;
  50. }
  51. int
  52. config_cmp (struct config *c1, struct config *c2)
  53. {
  54.   return strcmp (c1->name, c2->name);
  55. }
  56. void
  57. config_del (struct config* config)
  58. {
  59.   list_delete (config->line);
  60.   if (config->name)
  61.     XFREE (MTYPE_VTYSH_CONFIG_LINE, config->name);
  62.   XFREE (MTYPE_VTYSH_CONFIG, config);
  63. }
  64. struct config *
  65. config_get (int index, char *line)
  66. {
  67.   struct config *config;
  68.   struct config *config_loop;
  69.   struct list *master;
  70.   struct listnode *nn;
  71.   config = config_loop = NULL;
  72.   master = vector_lookup_ensure (configvec, index);
  73.   if (! master)
  74.     {
  75.       master = list_new ();
  76.       master->del = (void (*) (void *))config_del;
  77.       master->cmp = (int (*)(void *, void *)) config_cmp;
  78.       vector_set_index (configvec, index, master);
  79.     }
  80.   
  81.   LIST_LOOP (master, config_loop, nn)
  82.     {
  83.       if (strcmp (config_loop->name, line) == 0)
  84. config = config_loop;
  85.     }
  86.   if (! config)
  87.     {
  88.       config = config_new ();
  89.       config->line = list_new ();
  90.       config->line->del = (void (*) (void *))line_del;
  91.       config->line->cmp = (int (*)(void *, void *)) line_cmp;
  92.       config->name = XSTRDUP (MTYPE_VTYSH_CONFIG_LINE, line);
  93.       config->index = index;
  94.       listnode_add (master, config);
  95.     }
  96.   return config;
  97. }
  98. void
  99. config_add_line (struct list *config, char *line)
  100. {
  101.   listnode_add (config, XSTRDUP (MTYPE_VTYSH_CONFIG_LINE, line));
  102. }
  103. void
  104. config_add_line_uniq (struct list *config, char *line)
  105. {
  106.   struct listnode *nn;
  107.   char *pnt;
  108.   LIST_LOOP (config, pnt, nn)
  109.     {
  110.       if (strcmp (pnt, line) == 0)
  111. return;
  112.     }
  113.   listnode_add_sort (config, XSTRDUP (MTYPE_VTYSH_CONFIG_LINE, line));
  114. }
  115. void
  116. vtysh_config_parse_line (char *line)
  117. {
  118.   char c;
  119.   static struct config *config = NULL;
  120.   if (! line)
  121.     return;
  122.   c = line[0];
  123.   if (c == '')
  124.     return;
  125.   /* printf ("[%s]n", line); */
  126.   switch (c)
  127.     {
  128.     case '!':
  129.     case '#':
  130.       break;
  131.     case ' ':
  132.       /* Store line to current configuration. */
  133.       if (config)
  134. {
  135.   if (strncmp (line, " address-family vpnv4", strlen (" address-family vpnv4")) == 0)
  136.     config = config_get (BGP_VPNV4_NODE, line);
  137.   else if (strncmp (line, " address-family ipv4", strlen (" address-family ipv4")) == 0)
  138.     config = config_get (BGP_IPV4_NODE, line);
  139.   else if (strncmp (line, " address-family ipv4 multicast", strlen (" address-family ipv4 multicast")) == 0)
  140.     config = config_get (BGP_IPV4M_NODE, line);
  141.   else if (strncmp (line, " address-family ipv6", strlen (" address-family ipv6")) == 0)
  142.     config = config_get (BGP_IPV6_NODE, line);
  143.   else if (config->index == RMAP_NODE)
  144.     config_add_line_uniq (config->line, line);
  145.   else
  146.     config_add_line (config->line, line);
  147. }
  148.       else
  149. config_add_line (config_top, line);
  150.       break;
  151.     default:
  152.       if (strncmp (line, "interface", strlen ("interface")) == 0)
  153. config = config_get (INTERFACE_NODE, line);
  154.       else if (strncmp (line, "router rip", strlen ("router rip")) == 0)
  155. config = config_get (RIP_NODE, line);
  156.       else if (strncmp (line, "router ripng", strlen ("router ripng")) == 0)
  157.    config = config_get (RIPNG_NODE, line);
  158.       else if (strncmp (line, "router ospf", strlen ("router ospf")) == 0)
  159.    config = config_get (OSPF_NODE, line);
  160.       else if (strncmp (line, "router ospf6", strlen ("router ospf6")) == 0)
  161.    config = config_get (OSPF6_NODE, line);
  162.       else if (strncmp (line, "router bgp", strlen ("router bgp")) == 0)
  163. config = config_get (BGP_NODE, line);
  164.       else if (strncmp (line, "router", strlen ("router")) == 0)
  165. config = config_get (BGP_NODE, line);
  166.       else if (strncmp (line, "route-map", strlen ("route-map")) == 0)
  167. config = config_get (RMAP_NODE, line);
  168.       else if (strncmp (line, "access-list", strlen ("access-list")) == 0)
  169. config = config_get (ACCESS_NODE, line);
  170.       else if (strncmp (line, "ipv6 access-list", strlen ("ipv6 access-list")) == 0)
  171.    config = config_get (ACCESS_IPV6_NODE, line);
  172.       else if (strncmp (line, "ip prefix-list", strlen ("ip prefix-list")) == 0)
  173. config = config_get (PREFIX_NODE, line);
  174.       else if (strncmp (line, "ipv6 prefix-list", strlen ("ipv6 prefix-list")) == 0)
  175.    config = config_get (PREFIX_IPV6_NODE, line);
  176.       else if (strncmp (line, "ip as-path access-list", strlen ("ip as-path access-list")) == 0)
  177. config = config_get (AS_LIST_NODE, line);
  178.       else if (strncmp (line, "ip community-list", strlen ("ip community-list")) == 0)
  179. config = config_get (COMMUNITY_LIST_NODE, line);
  180.       else if (strncmp (line, "ip route", strlen ("ip route")) == 0)
  181. config = config_get (IP_NODE, line);
  182.       else if (strncmp (line, "ipv6 route", strlen ("ipv6 route")) == 0)
  183.     config = config_get (IP_NODE, line);
  184.       else if (strncmp (line, "key", strlen ("key")) == 0)
  185. config = config_get (KEYCHAIN_NODE, line);
  186.       else
  187. {
  188.   if (strncmp (line, "log", strlen ("log")) == 0
  189.       || strncmp (line, "hostname", strlen ("hostname")) == 0
  190.       || strncmp (line, "password", strlen ("hostname")) == 0)
  191.     config_add_line_uniq (config_top, line);
  192.   else
  193.     config_add_line (config_top, line);
  194.   config = NULL;
  195. }
  196.       break;
  197.     }
  198. }
  199. void
  200. vtysh_config_parse (char *line)
  201. {
  202.   char *begin;
  203.   char *pnt;
  204.   
  205.   begin = pnt = line;
  206.   while (*pnt != '')
  207.     {
  208.       if (*pnt == 'n')
  209. {
  210.   *pnt++ = '';
  211.   vtysh_config_parse_line (begin);
  212.   begin = pnt;
  213. }
  214.       else
  215. {
  216.   pnt++;
  217. }
  218.     }
  219. }
  220. /* Macro to check delimiter is needed between each configuration line
  221.    or not.  */
  222. #define NO_DELIMITER(I)  
  223.   ((I) == ACCESS_NODE || (I) == PREFIX_NODE || (I) == IP_NODE 
  224.    || (I) == AS_LIST_NODE || (I) == COMMUNITY_LIST_NODE || 
  225.    (I) == ACCESS_IPV6_NODE || (I) == PREFIX_IPV6_NODE)
  226. /* Display configuration to file pointer.  */
  227. void
  228. vtysh_config_dump (FILE *fp)
  229. {
  230.   struct listnode *nn;
  231.   struct listnode *nm;
  232.   struct config *config;
  233.   struct list *master;
  234.   char *line;
  235.   int i;
  236.   LIST_LOOP (config_top, line, nn)
  237.     {
  238.       fprintf (fp, "%sn", line);
  239.       fflush (fp);
  240.     }
  241.   fprintf (fp, "!n");
  242.   fflush (fp);
  243.   for (i = 0; i < vector_max (configvec); i++)
  244.     if ((master = vector_slot (configvec, i)) != NULL)
  245.       {
  246. LIST_LOOP (master, config, nn)
  247.   {
  248.     fprintf (fp, "%sn", config->name);
  249.             fflush (fp);
  250.     LIST_LOOP (config->line, line, nm)
  251.       {
  252. fprintf  (fp, "%sn", line);
  253. fflush (fp);
  254.       }
  255.     if (! NO_DELIMITER (i))
  256.       {
  257. fprintf (fp, "!n");
  258. fflush (fp);
  259.       }
  260.   }
  261. if (NO_DELIMITER (i))
  262.   {
  263.     fprintf (fp, "!n");
  264.     fflush (fp);
  265.   }
  266.       }
  267.   for (i = 0; i < vector_max (configvec); i++)
  268.     if ((master = vector_slot (configvec, i)) != NULL)
  269.       {
  270. list_delete (master);
  271. vector_slot (configvec, i) = NULL;
  272.       }
  273.   list_delete_all_node (config_top);
  274. }
  275. /* Read up configuration file from file_name. */
  276. static void
  277. vtysh_read_file (FILE *confp)
  278. {
  279.   int ret;
  280.   struct vty *vty;
  281.   vty = vty_new ();
  282.   vty->fd = 0; /* stdout */
  283.   vty->type = VTY_TERM;
  284.   vty->node = CONFIG_NODE;
  285.   
  286.   vtysh_execute_no_pager ("enable");
  287.   vtysh_execute_no_pager ("configure terminal");
  288.   /* Execute configuration file */
  289.   ret = vtysh_config_from_file (vty, confp);
  290.   vtysh_execute_no_pager ("end");
  291.   vtysh_execute_no_pager ("disable");
  292.   vty_close (vty);
  293.   if (ret != CMD_SUCCESS) 
  294.     {
  295.       switch (ret)
  296. {
  297. case CMD_ERR_AMBIGUOUS:
  298.   fprintf (stderr, "Ambiguous command.n");
  299.   break;
  300. case CMD_ERR_NO_MATCH:
  301.   fprintf (stderr, "There is no such command.n");
  302.   break;
  303. }
  304.       fprintf (stderr, "Error occured during reading below line.n%sn", 
  305.        vty->buf);
  306.       exit (1);
  307.     }
  308. }
  309. /* Read up configuration file from file_name. */
  310. void
  311. vtysh_read_config (char *config_file,
  312.    char *config_current_dir,
  313.    char *config_default_dir)
  314. {
  315.   char *cwd;
  316.   FILE *confp = NULL;
  317.   char *fullpath;
  318.   /* If -f flag specified. */
  319.   if (config_file != NULL)
  320.     {
  321.       if (! IS_DIRECTORY_SEP (config_file[0]))
  322. {
  323.   cwd = getcwd (NULL, MAXPATHLEN);
  324.   fullpath = XMALLOC (MTYPE_TMP, 
  325.       strlen (cwd) + strlen (config_file) + 2);
  326.   sprintf (fullpath, "%s/%s", cwd, config_file);
  327. }
  328.       else
  329. fullpath = config_file;
  330.       confp = fopen (fullpath, "r");
  331.       if (confp == NULL)
  332. {
  333.   fprintf (stderr, "can't open configuration file [%s]n", 
  334.    config_file);
  335.   exit(1);
  336. }
  337.     }
  338.   else
  339.     {
  340.       /* Relative path configuration file open. */
  341.       if (config_current_dir)
  342. confp = fopen (config_current_dir, "r");
  343.       /* If there is no relative path exists, open system default file. */
  344.       if (confp == NULL)
  345. {
  346.   confp = fopen (config_default_dir, "r");
  347.   if (confp == NULL)
  348.     {
  349.       fprintf (stderr, "can't open configuration file [%s]n",
  350.        config_default_dir);
  351.       exit (1);
  352.     }      
  353.   else
  354.     fullpath = config_default_dir;
  355. }
  356.       else
  357. {
  358.   /* Rleative path configuration file. */
  359.   cwd = getcwd (NULL, MAXPATHLEN);
  360.   fullpath = XMALLOC (MTYPE_TMP, 
  361.       strlen (cwd) + strlen (config_current_dir) + 2);
  362.   sprintf (fullpath, "%s/%s", cwd, config_current_dir);
  363. }  
  364.     }  
  365.   vtysh_read_file (confp);
  366.   fclose (confp);
  367.   host_config_set (fullpath);
  368. }
  369. void
  370. vtysh_config_write (FILE *fp)
  371. {
  372.   extern struct host host;
  373.   if (host.name)
  374.     fprintf (fp, "hostname %sn", host.name);
  375.   fprintf (fp, "!n");
  376. }
  377. void
  378. vtysh_config_init ()
  379. {
  380.   config_top = list_new ();
  381.   config_top->del = (void (*) (void *))line_del;
  382.   configvec = vector_init (1);
  383. }