]> git.proxmox.com Git - mirror_frr.git/blame - vtysh/vtysh_config.c
2005-04-07 Paul Jakma <paul.jakma@sun.com>
[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
29vector configvec;
30
e7168df4 31extern int vtysh_writeconfig_integrated;
32
718e3744 33struct 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
48struct list *config_top;
95e735b5 49
718e3744 50int
51line_cmp (char *c1, char *c2)
52{
53 return strcmp (c1, c2);
54}
55
56void
57line_del (char *line)
58{
59 XFREE (MTYPE_VTYSH_CONFIG_LINE, line);
60}
61
62struct config *
63config_new ()
64{
65 struct config *config;
66 config = XCALLOC (MTYPE_VTYSH_CONFIG, sizeof (struct config));
67 return config;
68}
69
70int
71config_cmp (struct config *c1, struct config *c2)
72{
73 return strcmp (c1->name, c2->name);
74}
75
76void
77config_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
85struct config *
dda09522 86config_get (int index, const char *line)
718e3744 87{
88 struct config *config;
89 struct config *config_loop;
90 struct list *master;
1eb8ef25 91 struct listnode *node, *nnode;
718e3744 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
1eb8ef25 105 for (ALL_LIST_ELEMENTS (master, node, nnode, config_loop))
718e3744 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
124void
dda09522 125config_add_line (struct list *config, const char *line)
718e3744 126{
127 listnode_add (config, XSTRDUP (MTYPE_VTYSH_CONFIG_LINE, line));
128}
129
130void
dda09522 131config_add_line_uniq (struct list *config, const char *line)
718e3744 132{
1eb8ef25 133 struct listnode *node, *nnode;
718e3744 134 char *pnt;
135
1eb8ef25 136 for (ALL_LIST_ELEMENTS (config, node, nnode, pnt))
718e3744 137 {
138 if (strcmp (pnt, line) == 0)
139 return;
140 }
141 listnode_add_sort (config, XSTRDUP (MTYPE_VTYSH_CONFIG_LINE, line));
142}
143
144void
dda09522 145vtysh_config_parse_line (const char *line)
718e3744 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 {
95e735b5 169 if (strncmp (line, " address-family vpnv4",
170 strlen (" address-family vpnv4")) == 0)
718e3744 171 config = config_get (BGP_VPNV4_NODE, line);
95e735b5 172 else if (strncmp (line, " address-family ipv4 multicast",
173 strlen (" address-family ipv4 multicast")) == 0)
718e3744 174 config = config_get (BGP_IPV4M_NODE, line);
95e735b5 175 else if (strncmp (line, " address-family ipv6",
176 strlen (" address-family ipv6")) == 0)
718e3744 177 config = config_get (BGP_IPV6_NODE, line);
95e735b5 178 else if (config->index == RMAP_NODE ||
e7168df4 179 config->index == INTERFACE_NODE ||
180 config->index == VTY_NODE)
718e3744 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);
dfbb9124 191 else if (strncmp (line, "router-id", strlen ("router-id")) == 0)
192 config = config_get (ZEBRA_NODE, line);
718e3744 193 else if (strncmp (line, "router rip", strlen ("router rip")) == 0)
194 config = config_get (RIP_NODE, line);
97e1c4dc 195 else if (strncmp (line, "router ripng", strlen ("router ripng")) == 0)
b094d260 196 config = config_get (RIPNG_NODE, line);
718e3744 197 else if (strncmp (line, "router ospf", strlen ("router ospf")) == 0)
b094d260 198 config = config_get (OSPF_NODE, line);
97e1c4dc 199 else if (strncmp (line, "router ospf6", strlen ("router ospf6")) == 0)
b094d260 200 config = config_get (OSPF6_NODE, line);
718e3744 201 else if (strncmp (line, "router bgp", strlen ("router bgp")) == 0)
202 config = config_get (BGP_NODE, line);
13b8baad 203 else if (strncmp (line, "router isis", strlen ("router isis")) == 0)
c25e458a 204 config = config_get (ISIS_NODE, line);
dfbb9124 205 else if (strncmp (line, "router bgp", strlen ("router bgp")) == 0)
718e3744 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);
95e735b5 211 else if (strncmp (line, "ipv6 access-list",
212 strlen ("ipv6 access-list")) == 0)
b094d260 213 config = config_get (ACCESS_IPV6_NODE, line);
95e735b5 214 else if (strncmp (line, "ip prefix-list",
215 strlen ("ip prefix-list")) == 0)
718e3744 216 config = config_get (PREFIX_NODE, line);
95e735b5 217 else if (strncmp (line, "ipv6 prefix-list",
218 strlen ("ipv6 prefix-list")) == 0)
b094d260 219 config = config_get (PREFIX_IPV6_NODE, line);
95e735b5 220 else if (strncmp (line, "ip as-path access-list",
221 strlen ("ip as-path access-list")) == 0)
718e3744 222 config = config_get (AS_LIST_NODE, line);
95e735b5 223 else if (strncmp (line, "ip community-list",
224 strlen ("ip community-list")) == 0)
718e3744 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);
97e1c4dc 228 else if (strncmp (line, "ipv6 route", strlen ("ipv6 route")) == 0)
229 config = config_get (IP_NODE, line);
718e3744 230 else if (strncmp (line, "key", strlen ("key")) == 0)
231 config = config_get (KEYCHAIN_NODE, line);
e7168df4 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);
dfbb9124 241 else if (strncmp (line, "debug", strlen ("debug")) == 0)
242 config = config_get (DEBUG_NODE, line);
060d438c 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);
718e3744 247 else
248 {
249 if (strncmp (line, "log", strlen ("log")) == 0
250 || strncmp (line, "hostname", strlen ("hostname")) == 0
e7168df4 251 )
718e3744 252 config_add_line_uniq (config_top, line);
253 else
254 config_add_line (config_top, line);
255 config = NULL;
256 }
257 break;
258 }
259}
260
261void
262vtysh_config_parse (char *line)
263{
264 char *begin;
265 char *pnt;
266
267 begin = pnt = line;
268
269 while (*pnt != '\0')
270 {
271 if (*pnt == '\n')
272 {
273 *pnt++ = '\0';
274 vtysh_config_parse_line (begin);
275 begin = pnt;
276 }
277 else
278 {
279 pnt++;
280 }
281 }
282}
283
284/* Macro to check delimiter is needed between each configuration line
95e735b5 285 * or not. */
718e3744 286#define NO_DELIMITER(I) \
287 ((I) == ACCESS_NODE || (I) == PREFIX_NODE || (I) == IP_NODE \
97e1c4dc 288 || (I) == AS_LIST_NODE || (I) == COMMUNITY_LIST_NODE || \
e7168df4 289 (I) == ACCESS_IPV6_NODE || (I) == PREFIX_IPV6_NODE \
060d438c 290 || (I) == SERVICE_NODE || (I) == FORWARDING_NODE || (I) == DEBUG_NODE \
291 || (I) == AAA_NODE)
718e3744 292
95e735b5 293/* Display configuration to file pointer. */
718e3744 294void
295vtysh_config_dump (FILE *fp)
296{
1eb8ef25 297 struct listnode *node, *nnode;
298 struct listnode *mnode, *mnnode;
718e3744 299 struct config *config;
300 struct list *master;
301 char *line;
dda09522 302 unsigned int i;
718e3744 303
1eb8ef25 304 for (ALL_LIST_ELEMENTS (config_top, node, nnode, line))
718e3744 305 {
306 fprintf (fp, "%s\n", line);
307 fflush (fp);
308 }
309 fprintf (fp, "!\n");
310 fflush (fp);
311
55468c86 312 for (i = 0; i < vector_active (configvec); i++)
718e3744 313 if ((master = vector_slot (configvec, i)) != NULL)
314 {
1eb8ef25 315 for (ALL_LIST_ELEMENTS (master, node, nnode, config))
718e3744 316 {
317 fprintf (fp, "%s\n", config->name);
b094d260 318 fflush (fp);
718e3744 319
1eb8ef25 320 for (ALL_LIST_ELEMENTS (config->line, mnode, mnnode, line))
718e3744 321 {
322 fprintf (fp, "%s\n", line);
323 fflush (fp);
324 }
325 if (! NO_DELIMITER (i))
326 {
327 fprintf (fp, "!\n");
328 fflush (fp);
329 }
330 }
331 if (NO_DELIMITER (i))
332 {
333 fprintf (fp, "!\n");
334 fflush (fp);
335 }
336 }
337
55468c86 338 for (i = 0; i < vector_active (configvec); i++)
718e3744 339 if ((master = vector_slot (configvec, i)) != NULL)
340 {
341 list_delete (master);
342 vector_slot (configvec, i) = NULL;
343 }
344 list_delete_all_node (config_top);
345}
346
347/* Read up configuration file from file_name. */
348static void
349vtysh_read_file (FILE *confp)
350{
351 int ret;
352 struct vty *vty;
353
354 vty = vty_new ();
355 vty->fd = 0; /* stdout */
356 vty->type = VTY_TERM;
357 vty->node = CONFIG_NODE;
358
359 vtysh_execute_no_pager ("enable");
360 vtysh_execute_no_pager ("configure terminal");
361
95e735b5 362 /* Execute configuration file. */
718e3744 363 ret = vtysh_config_from_file (vty, confp);
364
365 vtysh_execute_no_pager ("end");
366 vtysh_execute_no_pager ("disable");
367
368 vty_close (vty);
369
370 if (ret != CMD_SUCCESS)
371 {
372 switch (ret)
373 {
374 case CMD_ERR_AMBIGUOUS:
375 fprintf (stderr, "Ambiguous command.\n");
376 break;
377 case CMD_ERR_NO_MATCH:
378 fprintf (stderr, "There is no such command.\n");
379 break;
380 }
381 fprintf (stderr, "Error occured during reading below line.\n%s\n",
382 vty->buf);
383 exit (1);
384 }
385}
386
e7168df4 387/* Read up configuration file from config_default_dir. */
388int
389vtysh_read_config (char *config_default_dir)
718e3744 390{
718e3744 391 FILE *confp = NULL;
718e3744 392
e7168df4 393 confp = fopen (config_default_dir, "r");
394 if (confp == NULL)
395 return (1);
67e29abc 396
718e3744 397 vtysh_read_file (confp);
718e3744 398 fclose (confp);
e7168df4 399 host_config_set (config_default_dir);
718e3744 400
e7168df4 401 return (0);
718e3744 402}
403
e7168df4 404/* We don't write vtysh specific into file from vtysh. vtysh.conf should
405 * be edited by hand. So, we handle only "write terminal" case here and
406 * integrate vtysh specific conf with conf from daemons.
407 */
718e3744 408void
e7168df4 409vtysh_config_write ()
718e3744 410{
dda09522 411 char line[81];
718e3744 412 extern struct host host;
413
414 if (host.name)
e7168df4 415 {
416 sprintf (line, "hostname %s", host.name);
417 vtysh_config_parse_line(line);
418 }
419 if (vtysh_writeconfig_integrated)
420 vtysh_config_parse_line ("service integrated-vtysh-config");
718e3744 421}
422
423void
424vtysh_config_init ()
425{
426 config_top = list_new ();
427 config_top->del = (void (*) (void *))line_del;
428 configvec = vector_init (1);
429}