]> git.proxmox.com Git - mirror_frr.git/blame - vtysh/vtysh_config.c
*: add indent control files
[mirror_frr.git] / vtysh / vtysh_config.c
CommitLineData
718e3744 1/* Configuration generator.
896014f4
DL
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 along
17 * with this program; see the file COPYING; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19 */
718e3744 20
21#include <zebra.h>
22
23#include "command.h"
24#include "linklist.h"
25#include "memory.h"
26
27#include "vtysh/vtysh.h"
88177fe3 28#include "vtysh/vtysh_user.h"
718e3744 29
4a1ab8e4
DL
30DEFINE_MGROUP(MVTYSH, "vtysh")
31DEFINE_MTYPE_STATIC(MVTYSH, VTYSH_CONFIG, "Vtysh configuration")
32DEFINE_MTYPE_STATIC(MVTYSH, VTYSH_CONFIG_LINE, "Vtysh configuration line")
33
718e3744 34vector configvec;
35
36struct config
37{
38 /* Configuration node name. */
39 char *name;
40
41 /* Configuration string line. */
42 struct list *line;
43
44 /* Configuration can be nest. */
45 struct config *config;
46
47 /* Index of this config. */
48 u_int32_t index;
49};
50
51struct list *config_top;
95e735b5 52
4201dd11 53static int
718e3744 54line_cmp (char *c1, char *c2)
55{
56 return strcmp (c1, c2);
57}
58
4201dd11 59static void
718e3744 60line_del (char *line)
61{
62 XFREE (MTYPE_VTYSH_CONFIG_LINE, line);
63}
64
4201dd11 65static struct config *
35dece84 66config_new (void)
718e3744 67{
68 struct config *config;
69 config = XCALLOC (MTYPE_VTYSH_CONFIG, sizeof (struct config));
70 return config;
71}
72
4201dd11 73static int
718e3744 74config_cmp (struct config *c1, struct config *c2)
75{
76 return strcmp (c1->name, c2->name);
77}
78
4201dd11 79static void
718e3744 80config_del (struct config* config)
81{
82 list_delete (config->line);
83 if (config->name)
84 XFREE (MTYPE_VTYSH_CONFIG_LINE, config->name);
85 XFREE (MTYPE_VTYSH_CONFIG, config);
86}
87
4201dd11 88static struct config *
dda09522 89config_get (int index, const char *line)
718e3744 90{
91 struct config *config;
92 struct config *config_loop;
93 struct list *master;
1eb8ef25 94 struct listnode *node, *nnode;
718e3744 95
96 config = config_loop = NULL;
97
98 master = vector_lookup_ensure (configvec, index);
99
100 if (! master)
101 {
102 master = list_new ();
103 master->del = (void (*) (void *))config_del;
104 master->cmp = (int (*)(void *, void *)) config_cmp;
105 vector_set_index (configvec, index, master);
106 }
107
1eb8ef25 108 for (ALL_LIST_ELEMENTS (master, node, nnode, config_loop))
718e3744 109 {
110 if (strcmp (config_loop->name, line) == 0)
111 config = config_loop;
112 }
113
114 if (! config)
115 {
116 config = config_new ();
117 config->line = list_new ();
118 config->line->del = (void (*) (void *))line_del;
119 config->line->cmp = (int (*)(void *, void *)) line_cmp;
120 config->name = XSTRDUP (MTYPE_VTYSH_CONFIG_LINE, line);
121 config->index = index;
122 listnode_add (master, config);
123 }
124 return config;
125}
126
127void
dda09522 128config_add_line (struct list *config, const char *line)
718e3744 129{
130 listnode_add (config, XSTRDUP (MTYPE_VTYSH_CONFIG_LINE, line));
131}
132
4201dd11 133static void
dda09522 134config_add_line_uniq (struct list *config, const char *line)
718e3744 135{
1eb8ef25 136 struct listnode *node, *nnode;
718e3744 137 char *pnt;
138
1eb8ef25 139 for (ALL_LIST_ELEMENTS (config, node, nnode, pnt))
718e3744 140 {
141 if (strcmp (pnt, line) == 0)
142 return;
143 }
144 listnode_add_sort (config, XSTRDUP (MTYPE_VTYSH_CONFIG_LINE, line));
145}
146
7526a182 147void
7f059ea6 148vtysh_config_parse_line (void *arg, const char *line)
718e3744 149{
150 char c;
151 static struct config *config = NULL;
152
153 if (! line)
154 return;
155
156 c = line[0];
157
158 if (c == '\0')
159 return;
160
161 /* printf ("[%s]\n", line); */
162
163 switch (c)
164 {
0b960b4d
DW
165 /* Suppress exclamation points ! and commented lines. The !s are generated
166 * dynamically in vtysh_config_dump() */
718e3744 167 case '!':
168 case '#':
169 break;
170 case ' ':
171 /* Store line to current configuration. */
172 if (config)
173 {
95c2af68
DL
174 if (strncmp (line, " link-params", strlen (" link-params")) == 0)
175 {
176 config_add_line (config->line, line);
177 config->index = LINK_PARAMS_NODE;
178 }
179 else if (config->index == LINK_PARAMS_NODE &&
03f99d9a 180 strncmp (line, " exit-link-params", strlen (" exit")) == 0)
95c2af68
DL
181 {
182 config_add_line (config->line, line);
183 config->index = INTERFACE_NODE;
184 }
185 else if (config->index == RMAP_NODE ||
9a7aa8be
DS
186 config->index == INTERFACE_NODE ||
187 config->index == NS_NODE ||
188 config->index == VTY_NODE ||
189 config->index == VRF_NODE)
718e3744 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);
c253dcb5 200 else if (strncmp (line, "logical-router", strlen ("ns")) == 0)
13460c44 201 config = config_get (NS_NODE, line);
e9d94ea7
DS
202 else if (strncmp (line, "vrf", strlen ("vrf")) == 0)
203 config = config_get (VRF_NODE, line);
dfbb9124 204 else if (strncmp (line, "router-id", strlen ("router-id")) == 0)
205 config = config_get (ZEBRA_NODE, line);
718e3744 206 else if (strncmp (line, "router rip", strlen ("router rip")) == 0)
207 config = config_get (RIP_NODE, line);
97e1c4dc 208 else if (strncmp (line, "router ripng", strlen ("router ripng")) == 0)
b094d260 209 config = config_get (RIPNG_NODE, line);
49feff1a
DS
210 else if (strncmp (line, "router eigrp", strlen ("router eigrp")) == 0)
211 config = config_get (EIGRP_NODE, line);
a616ea5f
DS
212 else if (strncmp (line, "router babel", strlen ("router babel")) == 0)
213 config = config_get (BABEL_NODE, line);
718e3744 214 else if (strncmp (line, "router ospf", strlen ("router ospf")) == 0)
b094d260 215 config = config_get (OSPF_NODE, line);
97e1c4dc 216 else if (strncmp (line, "router ospf6", strlen ("router ospf6")) == 0)
b094d260 217 config = config_get (OSPF6_NODE, line);
4fcbf6e2
RW
218 else if (strncmp (line, "mpls ldp", strlen ("mpls ldp")) == 0)
219 config = config_get (LDP_NODE, line);
220 else if (strncmp (line, "l2vpn", strlen ("l2vpn")) == 0)
221 config = config_get (LDP_L2VPN_NODE, line);
718e3744 222 else if (strncmp (line, "router bgp", strlen ("router bgp")) == 0)
223 config = config_get (BGP_NODE, line);
13b8baad 224 else if (strncmp (line, "router isis", strlen ("router isis")) == 0)
c25e458a 225 config = config_get (ISIS_NODE, line);
718e3744 226 else if (strncmp (line, "route-map", strlen ("route-map")) == 0)
227 config = config_get (RMAP_NODE, line);
228 else if (strncmp (line, "access-list", strlen ("access-list")) == 0)
229 config = config_get (ACCESS_NODE, line);
95e735b5 230 else if (strncmp (line, "ipv6 access-list",
231 strlen ("ipv6 access-list")) == 0)
b094d260 232 config = config_get (ACCESS_IPV6_NODE, line);
95e735b5 233 else if (strncmp (line, "ip prefix-list",
234 strlen ("ip prefix-list")) == 0)
718e3744 235 config = config_get (PREFIX_NODE, line);
95e735b5 236 else if (strncmp (line, "ipv6 prefix-list",
237 strlen ("ipv6 prefix-list")) == 0)
b094d260 238 config = config_get (PREFIX_IPV6_NODE, line);
95e735b5 239 else if (strncmp (line, "ip as-path access-list",
240 strlen ("ip as-path access-list")) == 0)
718e3744 241 config = config_get (AS_LIST_NODE, line);
eb2674af
DW
242 else if (strncmp (line, "ip community-list", strlen ("ip community-list")) == 0 ||
243 strncmp (line, "ip extcommunity-list", strlen ("ip extcommunity-list")) == 0)
718e3744 244 config = config_get (COMMUNITY_LIST_NODE, line);
245 else if (strncmp (line, "ip route", strlen ("ip route")) == 0)
246 config = config_get (IP_NODE, line);
97e1c4dc 247 else if (strncmp (line, "ipv6 route", strlen ("ipv6 route")) == 0)
248 config = config_get (IP_NODE, line);
718e3744 249 else if (strncmp (line, "key", strlen ("key")) == 0)
250 config = config_get (KEYCHAIN_NODE, line);
e7168df4 251 else if (strncmp (line, "line", strlen ("line")) == 0)
252 config = config_get (VTY_NODE, line);
253 else if ( (strncmp (line, "ipv6 forwarding",
254 strlen ("ipv6 forwarding")) == 0)
255 || (strncmp (line, "ip forwarding",
256 strlen ("ip forwarding")) == 0) )
257 config = config_get (FORWARDING_NODE, line);
258 else if (strncmp (line, "service", strlen ("service")) == 0)
259 config = config_get (SERVICE_NODE, line);
19dc275e
DS
260 else if (strncmp (line, "debug vrf", strlen ("debug vrf")) == 0)
261 config = config_get (VRF_DEBUG_NODE, line);
dfbb9124 262 else if (strncmp (line, "debug", strlen ("debug")) == 0)
263 config = config_get (DEBUG_NODE, line);
060d438c 264 else if (strncmp (line, "password", strlen ("password")) == 0
265 || strncmp (line, "enable password",
266 strlen ("enable password")) == 0)
267 config = config_get (AAA_NODE, line);
6e79f8bb
CC
268 else if (strncmp (line, "ip protocol", strlen ("ip protocol")) == 0)
269 config = config_get (PROTOCOL_NODE, line);
80b55c57 270 else if (strncmp (line, "ipv6 protocol", strlen ("ipv6 protocol")) == 0)
271 config = config_get (PROTOCOL_NODE, line);
272 else if (strncmp (line, "ip nht", strlen ("ip nht")) == 0)
273 config = config_get (PROTOCOL_NODE, line);
274 else if (strncmp (line, "ipv6 nht", strlen ("ipv6 nht")) == 0)
275 config = config_get (PROTOCOL_NODE, line);
7758e3f3 276 else if (strncmp (line, "mpls", strlen ("mpls")) == 0)
277 config = config_get (MPLS_NODE, line);
718e3744 278 else
279 {
280 if (strncmp (line, "log", strlen ("log")) == 0
281 || strncmp (line, "hostname", strlen ("hostname")) == 0
8efe88ea 282 || strncmp (line, "frr", strlen ("frr")) == 0
62ff928b 283 || strncmp (line, "agentx", strlen ("agentx")) == 0
9a7aa8be 284 || strncmp (line, "no log", strlen ("no log")) == 0
e7168df4 285 )
718e3744 286 config_add_line_uniq (config_top, line);
287 else
288 config_add_line (config_top, line);
289 config = NULL;
290 }
291 break;
292 }
293}
294
718e3744 295/* Macro to check delimiter is needed between each configuration line
95e735b5 296 * or not. */
718e3744 297#define NO_DELIMITER(I) \
298 ((I) == ACCESS_NODE || (I) == PREFIX_NODE || (I) == IP_NODE \
97e1c4dc 299 || (I) == AS_LIST_NODE || (I) == COMMUNITY_LIST_NODE || \
e7168df4 300 (I) == ACCESS_IPV6_NODE || (I) == PREFIX_IPV6_NODE \
060d438c 301 || (I) == SERVICE_NODE || (I) == FORWARDING_NODE || (I) == DEBUG_NODE \
7758e3f3 302 || (I) == AAA_NODE || (I) == VRF_DEBUG_NODE || (I) == MPLS_NODE)
718e3744 303
95e735b5 304/* Display configuration to file pointer. */
718e3744 305void
306vtysh_config_dump (FILE *fp)
307{
1eb8ef25 308 struct listnode *node, *nnode;
309 struct listnode *mnode, *mnnode;
718e3744 310 struct config *config;
311 struct list *master;
312 char *line;
dda09522 313 unsigned int i;
718e3744 314
1eb8ef25 315 for (ALL_LIST_ELEMENTS (config_top, node, nnode, line))
718e3744 316 {
317 fprintf (fp, "%s\n", line);
318 fflush (fp);
319 }
320 fprintf (fp, "!\n");
321 fflush (fp);
322
55468c86 323 for (i = 0; i < vector_active (configvec); i++)
718e3744 324 if ((master = vector_slot (configvec, i)) != NULL)
325 {
9a7aa8be
DS
326 for (ALL_LIST_ELEMENTS (master, node, nnode, config))
327 {
328 /* Don't print empty sections for interface/vrf. Route maps on the
329 * other hand could have a legitimate empty section at the end.
330 */
331 if ((config->index == INTERFACE_NODE || config->index == VRF_NODE)
332 && list_isempty (config->line))
333 continue;
334
335 fprintf (fp, "%s\n", config->name);
336 fflush (fp);
337
338 for (ALL_LIST_ELEMENTS (config->line, mnode, mnnode, line))
339 {
340 fprintf (fp, "%s\n", line);
341 fflush (fp);
342 }
343 if (! NO_DELIMITER (i))
344 {
345 fprintf (fp, "!\n");
346 fflush (fp);
347 }
348 }
349 if (NO_DELIMITER (i))
350 {
351 fprintf (fp, "!\n");
352 fflush (fp);
353 }
718e3744 354 }
355
55468c86 356 for (i = 0; i < vector_active (configvec); i++)
718e3744 357 if ((master = vector_slot (configvec, i)) != NULL)
358 {
9a7aa8be
DS
359 list_delete (master);
360 vector_slot (configvec, i) = NULL;
718e3744 361 }
362 list_delete_all_node (config_top);
363}
364
365/* Read up configuration file from file_name. */
3221dca8 366static int
718e3744 367vtysh_read_file (FILE *confp)
368{
718e3744 369 struct vty *vty;
3221dca8 370 int ret;
718e3744 371
372 vty = vty_new ();
373 vty->fd = 0; /* stdout */
374 vty->type = VTY_TERM;
375 vty->node = CONFIG_NODE;
376
377 vtysh_execute_no_pager ("enable");
378 vtysh_execute_no_pager ("configure terminal");
379
95e735b5 380 /* Execute configuration file. */
3221dca8 381 ret = vtysh_config_from_file (vty, confp);
718e3744 382
383 vtysh_execute_no_pager ("end");
384 vtysh_execute_no_pager ("disable");
385
386 vty_close (vty);
3221dca8
DS
387
388 return (ret);
718e3744 389}
390
e7168df4 391/* Read up configuration file from config_default_dir. */
392int
c0e8c16f 393vtysh_read_config (const char *config_default_dir)
718e3744 394{
718e3744 395 FILE *confp = NULL;
3221dca8 396 int ret;
718e3744 397
e7168df4 398 confp = fopen (config_default_dir, "r");
399 if (confp == NULL)
1db63918
DS
400 {
401 fprintf (stderr, "%% Can't open configuration file %s due to '%s'.\n",
402 config_default_dir, safe_strerror (errno));
403 return (CMD_ERR_NO_FILE);
404 }
67e29abc 405
3221dca8 406 ret = vtysh_read_file (confp);
718e3744 407 fclose (confp);
408
3221dca8 409 return (ret);
718e3744 410}
411
e7168df4 412/* We don't write vtysh specific into file from vtysh. vtysh.conf should
413 * be edited by hand. So, we handle only "write terminal" case here and
414 * integrate vtysh specific conf with conf from daemons.
415 */
718e3744 416void
e7168df4 417vtysh_config_write ()
718e3744 418{
dda09522 419 char line[81];
718e3744 420 extern struct host host;
421
422 if (host.name)
e7168df4 423 {
424 sprintf (line, "hostname %s", host.name);
7f059ea6 425 vtysh_config_parse_line(NULL, line);
e7168df4 426 }
039eaca3 427 if (vtysh_write_integrated == WRITE_INTEGRATED_NO)
7f059ea6 428 vtysh_config_parse_line (NULL, "no service integrated-vtysh-config");
039eaca3 429 if (vtysh_write_integrated == WRITE_INTEGRATED_YES)
7f059ea6 430 vtysh_config_parse_line (NULL, "service integrated-vtysh-config");
a7222276
DS
431
432 user_config_write ();
718e3744 433}
434
435void
436vtysh_config_init ()
437{
438 config_top = list_new ();
439 config_top->del = (void (*) (void *))line_del;
440 configvec = vector_init (1);
441}