Annotation of embedaddon/quagga/vtysh/vtysh_config.c, revision 1.1
1.1 ! misho 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: int
! 51: line_cmp (char *c1, char *c2)
! 52: {
! 53: return strcmp (c1, c2);
! 54: }
! 55:
! 56: void
! 57: line_del (char *line)
! 58: {
! 59: XFREE (MTYPE_VTYSH_CONFIG_LINE, line);
! 60: }
! 61:
! 62: 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: int
! 71: config_cmp (struct config *c1, struct config *c2)
! 72: {
! 73: return strcmp (c1->name, c2->name);
! 74: }
! 75:
! 76: 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: 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: 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: 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: 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 ipv4 multicast",
! 173: strlen (" address-family ipv4 multicast")) == 0)
! 174: config = config_get (BGP_IPV4M_NODE, line);
! 175: else if (strncmp (line, " address-family ipv6",
! 176: strlen (" address-family ipv6")) == 0)
! 177: config = config_get (BGP_IPV6_NODE, line);
! 178: else if (config->index == RMAP_NODE ||
! 179: config->index == INTERFACE_NODE ||
! 180: config->index == VTY_NODE)
! 181: config_add_line_uniq (config->line, line);
! 182: else
! 183: config_add_line (config->line, line);
! 184: }
! 185: else
! 186: config_add_line (config_top, line);
! 187: break;
! 188: default:
! 189: if (strncmp (line, "interface", strlen ("interface")) == 0)
! 190: config = config_get (INTERFACE_NODE, line);
! 191: else if (strncmp (line, "router-id", strlen ("router-id")) == 0)
! 192: config = config_get (ZEBRA_NODE, line);
! 193: else if (strncmp (line, "router rip", strlen ("router rip")) == 0)
! 194: config = config_get (RIP_NODE, line);
! 195: else if (strncmp (line, "router ripng", strlen ("router ripng")) == 0)
! 196: config = config_get (RIPNG_NODE, line);
! 197: else if (strncmp (line, "router ospf", strlen ("router ospf")) == 0)
! 198: config = config_get (OSPF_NODE, line);
! 199: else if (strncmp (line, "router ospf6", strlen ("router ospf6")) == 0)
! 200: config = config_get (OSPF6_NODE, line);
! 201: else if (strncmp (line, "router bgp", strlen ("router bgp")) == 0)
! 202: config = config_get (BGP_NODE, line);
! 203: else if (strncmp (line, "router isis", strlen ("router isis")) == 0)
! 204: config = config_get (ISIS_NODE, line);
! 205: else if (strncmp (line, "router bgp", strlen ("router bgp")) == 0)
! 206: config = config_get (BGP_NODE, line);
! 207: else if (strncmp (line, "route-map", strlen ("route-map")) == 0)
! 208: config = config_get (RMAP_NODE, line);
! 209: else if (strncmp (line, "access-list", strlen ("access-list")) == 0)
! 210: config = config_get (ACCESS_NODE, line);
! 211: else if (strncmp (line, "ipv6 access-list",
! 212: strlen ("ipv6 access-list")) == 0)
! 213: config = config_get (ACCESS_IPV6_NODE, line);
! 214: else if (strncmp (line, "ip prefix-list",
! 215: strlen ("ip prefix-list")) == 0)
! 216: config = config_get (PREFIX_NODE, line);
! 217: else if (strncmp (line, "ipv6 prefix-list",
! 218: strlen ("ipv6 prefix-list")) == 0)
! 219: config = config_get (PREFIX_IPV6_NODE, line);
! 220: else if (strncmp (line, "ip as-path access-list",
! 221: strlen ("ip as-path access-list")) == 0)
! 222: config = config_get (AS_LIST_NODE, line);
! 223: else if (strncmp (line, "ip community-list",
! 224: strlen ("ip community-list")) == 0)
! 225: config = config_get (COMMUNITY_LIST_NODE, line);
! 226: else if (strncmp (line, "ip route", strlen ("ip route")) == 0)
! 227: config = config_get (IP_NODE, line);
! 228: else if (strncmp (line, "ipv6 route", strlen ("ipv6 route")) == 0)
! 229: config = config_get (IP_NODE, line);
! 230: else if (strncmp (line, "key", strlen ("key")) == 0)
! 231: config = config_get (KEYCHAIN_NODE, line);
! 232: else if (strncmp (line, "line", strlen ("line")) == 0)
! 233: config = config_get (VTY_NODE, line);
! 234: else if ( (strncmp (line, "ipv6 forwarding",
! 235: strlen ("ipv6 forwarding")) == 0)
! 236: || (strncmp (line, "ip forwarding",
! 237: strlen ("ip forwarding")) == 0) )
! 238: config = config_get (FORWARDING_NODE, line);
! 239: else if (strncmp (line, "service", strlen ("service")) == 0)
! 240: config = config_get (SERVICE_NODE, line);
! 241: else if (strncmp (line, "debug", strlen ("debug")) == 0)
! 242: config = config_get (DEBUG_NODE, line);
! 243: else if (strncmp (line, "password", strlen ("password")) == 0
! 244: || strncmp (line, "enable password",
! 245: strlen ("enable password")) == 0)
! 246: config = config_get (AAA_NODE, line);
! 247: else if (strncmp (line, "ip protocol", strlen ("ip protocol")) == 0)
! 248: config = config_get (PROTOCOL_NODE, line);
! 249: else
! 250: {
! 251: if (strncmp (line, "log", strlen ("log")) == 0
! 252: || strncmp (line, "hostname", strlen ("hostname")) == 0
! 253: )
! 254: config_add_line_uniq (config_top, line);
! 255: else
! 256: config_add_line (config_top, line);
! 257: config = NULL;
! 258: }
! 259: break;
! 260: }
! 261: }
! 262:
! 263: void
! 264: vtysh_config_parse (char *line)
! 265: {
! 266: char *begin;
! 267: char *pnt;
! 268:
! 269: begin = pnt = line;
! 270:
! 271: while (*pnt != '\0')
! 272: {
! 273: if (*pnt == '\n')
! 274: {
! 275: *pnt++ = '\0';
! 276: vtysh_config_parse_line (begin);
! 277: begin = pnt;
! 278: }
! 279: else
! 280: {
! 281: pnt++;
! 282: }
! 283: }
! 284: }
! 285:
! 286: /* Macro to check delimiter is needed between each configuration line
! 287: * or not. */
! 288: #define NO_DELIMITER(I) \
! 289: ((I) == ACCESS_NODE || (I) == PREFIX_NODE || (I) == IP_NODE \
! 290: || (I) == AS_LIST_NODE || (I) == COMMUNITY_LIST_NODE || \
! 291: (I) == ACCESS_IPV6_NODE || (I) == PREFIX_IPV6_NODE \
! 292: || (I) == SERVICE_NODE || (I) == FORWARDING_NODE || (I) == DEBUG_NODE \
! 293: || (I) == AAA_NODE)
! 294:
! 295: /* Display configuration to file pointer. */
! 296: void
! 297: vtysh_config_dump (FILE *fp)
! 298: {
! 299: struct listnode *node, *nnode;
! 300: struct listnode *mnode, *mnnode;
! 301: struct config *config;
! 302: struct list *master;
! 303: char *line;
! 304: unsigned int i;
! 305:
! 306: for (ALL_LIST_ELEMENTS (config_top, node, nnode, line))
! 307: {
! 308: fprintf (fp, "%s\n", line);
! 309: fflush (fp);
! 310: }
! 311: fprintf (fp, "!\n");
! 312: fflush (fp);
! 313:
! 314: for (i = 0; i < vector_active (configvec); i++)
! 315: if ((master = vector_slot (configvec, i)) != NULL)
! 316: {
! 317: for (ALL_LIST_ELEMENTS (master, node, nnode, config))
! 318: {
! 319: fprintf (fp, "%s\n", config->name);
! 320: fflush (fp);
! 321:
! 322: for (ALL_LIST_ELEMENTS (config->line, mnode, mnnode, line))
! 323: {
! 324: fprintf (fp, "%s\n", line);
! 325: fflush (fp);
! 326: }
! 327: if (! NO_DELIMITER (i))
! 328: {
! 329: fprintf (fp, "!\n");
! 330: fflush (fp);
! 331: }
! 332: }
! 333: if (NO_DELIMITER (i))
! 334: {
! 335: fprintf (fp, "!\n");
! 336: fflush (fp);
! 337: }
! 338: }
! 339:
! 340: for (i = 0; i < vector_active (configvec); i++)
! 341: if ((master = vector_slot (configvec, i)) != NULL)
! 342: {
! 343: list_delete (master);
! 344: vector_slot (configvec, i) = NULL;
! 345: }
! 346: list_delete_all_node (config_top);
! 347: }
! 348:
! 349: /* Read up configuration file from file_name. */
! 350: static void
! 351: vtysh_read_file (FILE *confp)
! 352: {
! 353: int ret;
! 354: struct vty *vty;
! 355:
! 356: vty = vty_new ();
! 357: vty->fd = 0; /* stdout */
! 358: vty->type = VTY_TERM;
! 359: vty->node = CONFIG_NODE;
! 360:
! 361: vtysh_execute_no_pager ("enable");
! 362: vtysh_execute_no_pager ("configure terminal");
! 363:
! 364: /* Execute configuration file. */
! 365: ret = vtysh_config_from_file (vty, confp);
! 366:
! 367: vtysh_execute_no_pager ("end");
! 368: vtysh_execute_no_pager ("disable");
! 369:
! 370: vty_close (vty);
! 371:
! 372: if (ret != CMD_SUCCESS)
! 373: {
! 374: switch (ret)
! 375: {
! 376: case CMD_ERR_AMBIGUOUS:
! 377: fprintf (stderr, "Ambiguous command.\n");
! 378: break;
! 379: case CMD_ERR_NO_MATCH:
! 380: fprintf (stderr, "There is no such command.\n");
! 381: break;
! 382: }
! 383: fprintf (stderr, "Error occured during reading below line.\n%s\n",
! 384: vty->buf);
! 385: exit (1);
! 386: }
! 387: }
! 388:
! 389: /* Read up configuration file from config_default_dir. */
! 390: int
! 391: vtysh_read_config (char *config_default_dir)
! 392: {
! 393: FILE *confp = NULL;
! 394:
! 395: confp = fopen (config_default_dir, "r");
! 396: if (confp == NULL)
! 397: return (1);
! 398:
! 399: vtysh_read_file (confp);
! 400: fclose (confp);
! 401: host_config_set (config_default_dir);
! 402:
! 403: return (0);
! 404: }
! 405:
! 406: /* We don't write vtysh specific into file from vtysh. vtysh.conf should
! 407: * be edited by hand. So, we handle only "write terminal" case here and
! 408: * integrate vtysh specific conf with conf from daemons.
! 409: */
! 410: void
! 411: vtysh_config_write ()
! 412: {
! 413: char line[81];
! 414: extern struct host host;
! 415:
! 416: if (host.name)
! 417: {
! 418: sprintf (line, "hostname %s", host.name);
! 419: vtysh_config_parse_line(line);
! 420: }
! 421: if (vtysh_writeconfig_integrated)
! 422: vtysh_config_parse_line ("service integrated-vtysh-config");
! 423: }
! 424:
! 425: void
! 426: vtysh_config_init ()
! 427: {
! 428: config_top = list_new ();
! 429: config_top->del = (void (*) (void *))line_del;
! 430: configvec = vector_init (1);
! 431: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>