]> git.proxmox.com Git - mirror_frr.git/blame - vtysh/vtysh_config.c
vtysh: vtysh-warnings.patch
[mirror_frr.git] / vtysh / vtysh_config.c
CommitLineData
718e3744 1/* Configuration generator.
2 Copyright (C) 2000 Kunihiro Ishiguro
3
4This file is part of GNU Zebra.
5
6GNU Zebra is free software; you can redistribute it and/or modify it
7under the terms of the GNU General Public License as published by the
8Free Software Foundation; either version 2, or (at your option) any
9later version.
10
11GNU Zebra is distributed in the hope that it will be useful, but
12WITHOUT ANY WARRANTY; without even the implied warranty of
13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14General Public License for more details.
15
16You should have received a copy of the GNU General Public License
17along with GNU Zebra; see the file COPYING. If not, write to the Free
18Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
1902111-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
c0e8c16f
DS
29/*
30 * Compiler is warning about prototypes not being declared.
31 * The DEFUNSH and DEFUN macro's are messing with the
32 * compiler I believe. This is just to make it happy.
33 */
34int line_cmp(char *, char*);
35void line_del(char *);
36struct config *config_new(void);
37int config_cmp(struct config *, struct config *);
38void config_del(struct config *);
39struct config *config_get(int, const char *);
40void config_add_line(struct list *, const char *);
41void config_add_line_uniq(struct list *, const char *);
42void vtysh_config_parse_line(const char *);
43
718e3744 44vector configvec;
45
e7168df4 46extern int vtysh_writeconfig_integrated;
47
718e3744 48struct config
49{
50 /* Configuration node name. */
51 char *name;
52
53 /* Configuration string line. */
54 struct list *line;
55
56 /* Configuration can be nest. */
57 struct config *config;
58
59 /* Index of this config. */
60 u_int32_t index;
61};
62
63struct list *config_top;
95e735b5 64
718e3744 65int
66line_cmp (char *c1, char *c2)
67{
68 return strcmp (c1, c2);
69}
70
71void
72line_del (char *line)
73{
74 XFREE (MTYPE_VTYSH_CONFIG_LINE, line);
75}
76
77struct config *
78config_new ()
79{
80 struct config *config;
81 config = XCALLOC (MTYPE_VTYSH_CONFIG, sizeof (struct config));
82 return config;
83}
84
85int
86config_cmp (struct config *c1, struct config *c2)
87{
88 return strcmp (c1->name, c2->name);
89}
90
91void
92config_del (struct config* config)
93{
94 list_delete (config->line);
95 if (config->name)
96 XFREE (MTYPE_VTYSH_CONFIG_LINE, config->name);
97 XFREE (MTYPE_VTYSH_CONFIG, config);
98}
99
100struct config *
dda09522 101config_get (int index, const char *line)
718e3744 102{
103 struct config *config;
104 struct config *config_loop;
105 struct list *master;
1eb8ef25 106 struct listnode *node, *nnode;
718e3744 107
108 config = config_loop = NULL;
109
110 master = vector_lookup_ensure (configvec, index);
111
112 if (! master)
113 {
114 master = list_new ();
115 master->del = (void (*) (void *))config_del;
116 master->cmp = (int (*)(void *, void *)) config_cmp;
117 vector_set_index (configvec, index, master);
118 }
119
1eb8ef25 120 for (ALL_LIST_ELEMENTS (master, node, nnode, config_loop))
718e3744 121 {
122 if (strcmp (config_loop->name, line) == 0)
123 config = config_loop;
124 }
125
126 if (! config)
127 {
128 config = config_new ();
129 config->line = list_new ();
130 config->line->del = (void (*) (void *))line_del;
131 config->line->cmp = (int (*)(void *, void *)) line_cmp;
132 config->name = XSTRDUP (MTYPE_VTYSH_CONFIG_LINE, line);
133 config->index = index;
134 listnode_add (master, config);
135 }
136 return config;
137}
138
139void
dda09522 140config_add_line (struct list *config, const char *line)
718e3744 141{
142 listnode_add (config, XSTRDUP (MTYPE_VTYSH_CONFIG_LINE, line));
143}
144
145void
dda09522 146config_add_line_uniq (struct list *config, const char *line)
718e3744 147{
1eb8ef25 148 struct listnode *node, *nnode;
718e3744 149 char *pnt;
150
1eb8ef25 151 for (ALL_LIST_ELEMENTS (config, node, nnode, pnt))
718e3744 152 {
153 if (strcmp (pnt, line) == 0)
154 return;
155 }
156 listnode_add_sort (config, XSTRDUP (MTYPE_VTYSH_CONFIG_LINE, line));
157}
158
159void
dda09522 160vtysh_config_parse_line (const char *line)
718e3744 161{
162 char c;
163 static struct config *config = NULL;
164
165 if (! line)
166 return;
167
168 c = line[0];
169
170 if (c == '\0')
171 return;
172
173 /* printf ("[%s]\n", line); */
174
175 switch (c)
176 {
177 case '!':
178 case '#':
179 break;
180 case ' ':
181 /* Store line to current configuration. */
182 if (config)
183 {
95e735b5 184 if (strncmp (line, " address-family vpnv4",
185 strlen (" address-family vpnv4")) == 0)
718e3744 186 config = config_get (BGP_VPNV4_NODE, line);
95e735b5 187 else if (strncmp (line, " address-family ipv4 multicast",
188 strlen (" address-family ipv4 multicast")) == 0)
718e3744 189 config = config_get (BGP_IPV4M_NODE, line);
95e735b5 190 else if (strncmp (line, " address-family ipv6",
191 strlen (" address-family ipv6")) == 0)
718e3744 192 config = config_get (BGP_IPV6_NODE, line);
95e735b5 193 else if (config->index == RMAP_NODE ||
e7168df4 194 config->index == INTERFACE_NODE ||
195 config->index == VTY_NODE)
718e3744 196 config_add_line_uniq (config->line, line);
197 else
198 config_add_line (config->line, line);
199 }
200 else
201 config_add_line (config_top, line);
202 break;
203 default:
204 if (strncmp (line, "interface", strlen ("interface")) == 0)
205 config = config_get (INTERFACE_NODE, line);
dfbb9124 206 else if (strncmp (line, "router-id", strlen ("router-id")) == 0)
207 config = config_get (ZEBRA_NODE, line);
718e3744 208 else if (strncmp (line, "router rip", strlen ("router rip")) == 0)
209 config = config_get (RIP_NODE, line);
97e1c4dc 210 else if (strncmp (line, "router ripng", strlen ("router ripng")) == 0)
b094d260 211 config = config_get (RIPNG_NODE, line);
718e3744 212 else if (strncmp (line, "router ospf", strlen ("router ospf")) == 0)
b094d260 213 config = config_get (OSPF_NODE, line);
97e1c4dc 214 else if (strncmp (line, "router ospf6", strlen ("router ospf6")) == 0)
b094d260 215 config = config_get (OSPF6_NODE, line);
feb6c53e
JC
216 else if (strncmp (line, "router babel", strlen ("router babel")) == 0)
217 config = config_get (BABEL_NODE, line);
718e3744 218 else if (strncmp (line, "router bgp", strlen ("router bgp")) == 0)
219 config = config_get (BGP_NODE, line);
13b8baad 220 else if (strncmp (line, "router isis", strlen ("router isis")) == 0)
c25e458a 221 config = config_get (ISIS_NODE, line);
dfbb9124 222 else if (strncmp (line, "router bgp", strlen ("router bgp")) == 0)
718e3744 223 config = config_get (BGP_NODE, line);
224 else if (strncmp (line, "route-map", strlen ("route-map")) == 0)
225 config = config_get (RMAP_NODE, line);
226 else if (strncmp (line, "access-list", strlen ("access-list")) == 0)
227 config = config_get (ACCESS_NODE, line);
95e735b5 228 else if (strncmp (line, "ipv6 access-list",
229 strlen ("ipv6 access-list")) == 0)
b094d260 230 config = config_get (ACCESS_IPV6_NODE, line);
95e735b5 231 else if (strncmp (line, "ip prefix-list",
232 strlen ("ip prefix-list")) == 0)
718e3744 233 config = config_get (PREFIX_NODE, line);
95e735b5 234 else if (strncmp (line, "ipv6 prefix-list",
235 strlen ("ipv6 prefix-list")) == 0)
b094d260 236 config = config_get (PREFIX_IPV6_NODE, line);
95e735b5 237 else if (strncmp (line, "ip as-path access-list",
238 strlen ("ip as-path access-list")) == 0)
718e3744 239 config = config_get (AS_LIST_NODE, line);
95e735b5 240 else if (strncmp (line, "ip community-list",
241 strlen ("ip community-list")) == 0)
718e3744 242 config = config_get (COMMUNITY_LIST_NODE, line);
243 else if (strncmp (line, "ip route", strlen ("ip route")) == 0)
244 config = config_get (IP_NODE, line);
97e1c4dc 245 else if (strncmp (line, "ipv6 route", strlen ("ipv6 route")) == 0)
246 config = config_get (IP_NODE, line);
718e3744 247 else if (strncmp (line, "key", strlen ("key")) == 0)
248 config = config_get (KEYCHAIN_NODE, line);
e7168df4 249 else if (strncmp (line, "line", strlen ("line")) == 0)
250 config = config_get (VTY_NODE, line);
251 else if ( (strncmp (line, "ipv6 forwarding",
252 strlen ("ipv6 forwarding")) == 0)
253 || (strncmp (line, "ip forwarding",
254 strlen ("ip forwarding")) == 0) )
255 config = config_get (FORWARDING_NODE, line);
256 else if (strncmp (line, "service", strlen ("service")) == 0)
257 config = config_get (SERVICE_NODE, line);
dfbb9124 258 else if (strncmp (line, "debug", strlen ("debug")) == 0)
259 config = config_get (DEBUG_NODE, line);
060d438c 260 else if (strncmp (line, "password", strlen ("password")) == 0
261 || strncmp (line, "enable password",
262 strlen ("enable password")) == 0)
263 config = config_get (AAA_NODE, line);
6e79f8bb
CC
264 else if (strncmp (line, "ip protocol", strlen ("ip protocol")) == 0)
265 config = config_get (PROTOCOL_NODE, line);
718e3744 266 else
267 {
268 if (strncmp (line, "log", strlen ("log")) == 0
269 || strncmp (line, "hostname", strlen ("hostname")) == 0
e7168df4 270 )
718e3744 271 config_add_line_uniq (config_top, line);
272 else
273 config_add_line (config_top, line);
274 config = NULL;
275 }
276 break;
277 }
278}
279
280void
281vtysh_config_parse (char *line)
282{
283 char *begin;
284 char *pnt;
285
286 begin = pnt = line;
287
288 while (*pnt != '\0')
289 {
290 if (*pnt == '\n')
291 {
292 *pnt++ = '\0';
293 vtysh_config_parse_line (begin);
294 begin = pnt;
295 }
296 else
297 {
298 pnt++;
299 }
300 }
301}
302
303/* Macro to check delimiter is needed between each configuration line
95e735b5 304 * or not. */
718e3744 305#define NO_DELIMITER(I) \
306 ((I) == ACCESS_NODE || (I) == PREFIX_NODE || (I) == IP_NODE \
97e1c4dc 307 || (I) == AS_LIST_NODE || (I) == COMMUNITY_LIST_NODE || \
e7168df4 308 (I) == ACCESS_IPV6_NODE || (I) == PREFIX_IPV6_NODE \
060d438c 309 || (I) == SERVICE_NODE || (I) == FORWARDING_NODE || (I) == DEBUG_NODE \
310 || (I) == AAA_NODE)
718e3744 311
95e735b5 312/* Display configuration to file pointer. */
718e3744 313void
314vtysh_config_dump (FILE *fp)
315{
1eb8ef25 316 struct listnode *node, *nnode;
317 struct listnode *mnode, *mnnode;
718e3744 318 struct config *config;
319 struct list *master;
320 char *line;
dda09522 321 unsigned int i;
718e3744 322
1eb8ef25 323 for (ALL_LIST_ELEMENTS (config_top, node, nnode, line))
718e3744 324 {
325 fprintf (fp, "%s\n", line);
326 fflush (fp);
327 }
328 fprintf (fp, "!\n");
329 fflush (fp);
330
55468c86 331 for (i = 0; i < vector_active (configvec); i++)
718e3744 332 if ((master = vector_slot (configvec, i)) != NULL)
333 {
1eb8ef25 334 for (ALL_LIST_ELEMENTS (master, node, nnode, config))
718e3744 335 {
336 fprintf (fp, "%s\n", config->name);
b094d260 337 fflush (fp);
718e3744 338
1eb8ef25 339 for (ALL_LIST_ELEMENTS (config->line, mnode, mnnode, line))
718e3744 340 {
341 fprintf (fp, "%s\n", line);
342 fflush (fp);
343 }
344 if (! NO_DELIMITER (i))
345 {
346 fprintf (fp, "!\n");
347 fflush (fp);
348 }
349 }
350 if (NO_DELIMITER (i))
351 {
352 fprintf (fp, "!\n");
353 fflush (fp);
354 }
355 }
356
55468c86 357 for (i = 0; i < vector_active (configvec); i++)
718e3744 358 if ((master = vector_slot (configvec, i)) != NULL)
359 {
360 list_delete (master);
361 vector_slot (configvec, i) = NULL;
362 }
363 list_delete_all_node (config_top);
364}
365
366/* Read up configuration file from file_name. */
367static void
368vtysh_read_file (FILE *confp)
369{
370 int ret;
371 struct vty *vty;
372
373 vty = vty_new ();
374 vty->fd = 0; /* stdout */
375 vty->type = VTY_TERM;
376 vty->node = CONFIG_NODE;
377
378 vtysh_execute_no_pager ("enable");
379 vtysh_execute_no_pager ("configure terminal");
380
95e735b5 381 /* Execute configuration file. */
718e3744 382 ret = vtysh_config_from_file (vty, confp);
383
384 vtysh_execute_no_pager ("end");
385 vtysh_execute_no_pager ("disable");
386
387 vty_close (vty);
388
389 if (ret != CMD_SUCCESS)
390 {
391 switch (ret)
392 {
393 case CMD_ERR_AMBIGUOUS:
394 fprintf (stderr, "Ambiguous command.\n");
395 break;
396 case CMD_ERR_NO_MATCH:
397 fprintf (stderr, "There is no such command.\n");
398 break;
399 }
400 fprintf (stderr, "Error occured during reading below line.\n%s\n",
401 vty->buf);
402 exit (1);
403 }
404}
405
e7168df4 406/* Read up configuration file from config_default_dir. */
407int
c0e8c16f 408vtysh_read_config (const char *config_default_dir)
718e3744 409{
718e3744 410 FILE *confp = NULL;
718e3744 411
e7168df4 412 confp = fopen (config_default_dir, "r");
413 if (confp == NULL)
414 return (1);
67e29abc 415
718e3744 416 vtysh_read_file (confp);
718e3744 417 fclose (confp);
e7168df4 418 host_config_set (config_default_dir);
718e3744 419
e7168df4 420 return (0);
718e3744 421}
422
e7168df4 423/* We don't write vtysh specific into file from vtysh. vtysh.conf should
424 * be edited by hand. So, we handle only "write terminal" case here and
425 * integrate vtysh specific conf with conf from daemons.
426 */
718e3744 427void
e7168df4 428vtysh_config_write ()
718e3744 429{
dda09522 430 char line[81];
718e3744 431 extern struct host host;
432
433 if (host.name)
e7168df4 434 {
435 sprintf (line, "hostname %s", host.name);
436 vtysh_config_parse_line(line);
437 }
438 if (vtysh_writeconfig_integrated)
439 vtysh_config_parse_line ("service integrated-vtysh-config");
718e3744 440}
441
442void
443vtysh_config_init ()
444{
445 config_top = list_new ();
446 config_top->del = (void (*) (void *))line_del;
447 configvec = vector_init (1);
448}