Annotation of embedaddon/quagga/vtysh/vtysh_config.c, revision 1.1.1.3

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: 
1.1.1.3 ! misho      50: static int
1.1       misho      51: line_cmp (char *c1, char *c2)
                     52: {
                     53:   return strcmp (c1, c2);
                     54: }
                     55: 
1.1.1.3 ! misho      56: static void
1.1       misho      57: line_del (char *line)
                     58: {
                     59:   XFREE (MTYPE_VTYSH_CONFIG_LINE, line);
                     60: }
                     61: 
1.1.1.3 ! misho      62: static struct config *
1.1       misho      63: config_new ()
                     64: {
                     65:   struct config *config;
                     66:   config = XCALLOC (MTYPE_VTYSH_CONFIG, sizeof (struct config));
                     67:   return config;
                     68: }
                     69: 
1.1.1.3 ! misho      70: static int
1.1       misho      71: config_cmp (struct config *c1, struct config *c2)
                     72: {
                     73:   return strcmp (c1->name, c2->name);
                     74: }
                     75: 
1.1.1.3 ! misho      76: static void
1.1       misho      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: 
1.1.1.3 ! misho      85: static struct config *
1.1       misho      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: 
1.1.1.3 ! misho     124: static void
1.1       misho     125: config_add_line (struct list *config, const char *line)
                    126: {
                    127:   listnode_add (config, XSTRDUP (MTYPE_VTYSH_CONFIG_LINE, line));
                    128: }
                    129: 
1.1.1.3 ! misho     130: static void
1.1       misho     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: 
1.1.1.3 ! misho     144: static void
1.1       misho     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);
1.1.1.3 ! misho     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);
1.1       misho     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>