]> git.proxmox.com Git - mirror_frr.git/blob - vtysh/vtysh_config.c
vtysh: fix function prototypes
[mirror_frr.git] / vtysh / vtysh_config.c
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 #include "vtysh/vtysh_user.h"
29
30 vector configvec;
31
32 extern int vtysh_writeconfig_integrated;
33
34 struct config
35 {
36 /* Configuration node name. */
37 char *name;
38
39 /* Configuration string line. */
40 struct list *line;
41
42 /* Configuration can be nest. */
43 struct config *config;
44
45 /* Index of this config. */
46 u_int32_t index;
47 };
48
49 struct list *config_top;
50
51 static int
52 line_cmp (char *c1, char *c2)
53 {
54 return strcmp (c1, c2);
55 }
56
57 static void
58 line_del (char *line)
59 {
60 XFREE (MTYPE_VTYSH_CONFIG_LINE, line);
61 }
62
63 static struct config *
64 config_new (void)
65 {
66 struct config *config;
67 config = XCALLOC (MTYPE_VTYSH_CONFIG, sizeof (struct config));
68 return config;
69 }
70
71 static int
72 config_cmp (struct config *c1, struct config *c2)
73 {
74 return strcmp (c1->name, c2->name);
75 }
76
77 static void
78 config_del (struct config* config)
79 {
80 list_delete (config->line);
81 if (config->name)
82 XFREE (MTYPE_VTYSH_CONFIG_LINE, config->name);
83 XFREE (MTYPE_VTYSH_CONFIG, config);
84 }
85
86 static struct config *
87 config_get (int index, const char *line)
88 {
89 struct config *config;
90 struct config *config_loop;
91 struct list *master;
92 struct listnode *node, *nnode;
93
94 config = config_loop = NULL;
95
96 master = vector_lookup_ensure (configvec, index);
97
98 if (! master)
99 {
100 master = list_new ();
101 master->del = (void (*) (void *))config_del;
102 master->cmp = (int (*)(void *, void *)) config_cmp;
103 vector_set_index (configvec, index, master);
104 }
105
106 for (ALL_LIST_ELEMENTS (master, node, nnode, config_loop))
107 {
108 if (strcmp (config_loop->name, line) == 0)
109 config = config_loop;
110 }
111
112 if (! config)
113 {
114 config = config_new ();
115 config->line = list_new ();
116 config->line->del = (void (*) (void *))line_del;
117 config->line->cmp = (int (*)(void *, void *)) line_cmp;
118 config->name = XSTRDUP (MTYPE_VTYSH_CONFIG_LINE, line);
119 config->index = index;
120 listnode_add (master, config);
121 }
122 return config;
123 }
124
125 void
126 config_add_line (struct list *config, const char *line)
127 {
128 listnode_add (config, XSTRDUP (MTYPE_VTYSH_CONFIG_LINE, line));
129 }
130
131 static void
132 config_add_line_uniq (struct list *config, const char *line)
133 {
134 struct listnode *node, *nnode;
135 char *pnt;
136
137 for (ALL_LIST_ELEMENTS (config, node, nnode, pnt))
138 {
139 if (strcmp (pnt, line) == 0)
140 return;
141 }
142 listnode_add_sort (config, XSTRDUP (MTYPE_VTYSH_CONFIG_LINE, line));
143 }
144
145 static void
146 vtysh_config_parse_line (const char *line)
147 {
148 char c;
149 static struct config *config = NULL;
150
151 if (! line)
152 return;
153
154 c = line[0];
155
156 if (c == '\0')
157 return;
158
159 /* printf ("[%s]\n", line); */
160
161 switch (c)
162 {
163 /* Suppress exclamation points ! and commented lines. The !s are generated
164 * dynamically in vtysh_config_dump() */
165 case '!':
166 case '#':
167 break;
168 case ' ':
169 /* Store line to current configuration. */
170 if (config)
171 {
172 if (config->index == RMAP_NODE ||
173 config->index == INTERFACE_NODE ||
174 config->index == VRF_NODE ||
175 config->index == VTY_NODE)
176 config_add_line_uniq (config->line, line);
177 else
178 config_add_line (config->line, line);
179 }
180 else
181 config_add_line (config_top, line);
182 break;
183 default:
184 if (strncmp (line, "interface", strlen ("interface")) == 0)
185 config = config_get (INTERFACE_NODE, line);
186 else if (strncmp (line, "vrf", strlen ("vrf")) == 0)
187 config = config_get (VRF_NODE, line);
188 else if (strncmp (line, "router-id", strlen ("router-id")) == 0)
189 config = config_get (ZEBRA_NODE, line);
190 else if (strncmp (line, "router rip", strlen ("router rip")) == 0)
191 config = config_get (RIP_NODE, line);
192 else if (strncmp (line, "router ripng", strlen ("router ripng")) == 0)
193 config = config_get (RIPNG_NODE, line);
194 else if (strncmp (line, "router ospf", strlen ("router ospf")) == 0)
195 config = config_get (OSPF_NODE, line);
196 else if (strncmp (line, "router ospf6", strlen ("router ospf6")) == 0)
197 config = config_get (OSPF6_NODE, line);
198 else if (strncmp (line, "router bgp", strlen ("router bgp")) == 0)
199 config = config_get (BGP_NODE, line);
200 else if (strncmp (line, "router isis", strlen ("router isis")) == 0)
201 config = config_get (ISIS_NODE, line);
202 else if (strncmp (line, "route-map", strlen ("route-map")) == 0)
203 config = config_get (RMAP_NODE, line);
204 else if (strncmp (line, "access-list", strlen ("access-list")) == 0)
205 config = config_get (ACCESS_NODE, line);
206 else if (strncmp (line, "ipv6 access-list",
207 strlen ("ipv6 access-list")) == 0)
208 config = config_get (ACCESS_IPV6_NODE, line);
209 else if (strncmp (line, "ip prefix-list",
210 strlen ("ip prefix-list")) == 0)
211 config = config_get (PREFIX_NODE, line);
212 else if (strncmp (line, "ipv6 prefix-list",
213 strlen ("ipv6 prefix-list")) == 0)
214 config = config_get (PREFIX_IPV6_NODE, line);
215 else if (strncmp (line, "ip as-path access-list",
216 strlen ("ip as-path access-list")) == 0)
217 config = config_get (AS_LIST_NODE, line);
218 else if (strncmp (line, "ip community-list", strlen ("ip community-list")) == 0 ||
219 strncmp (line, "ip extcommunity-list", strlen ("ip extcommunity-list")) == 0)
220 config = config_get (COMMUNITY_LIST_NODE, line);
221 else if (strncmp (line, "ip route", strlen ("ip route")) == 0)
222 config = config_get (IP_NODE, line);
223 else if (strncmp (line, "ipv6 route", strlen ("ipv6 route")) == 0)
224 config = config_get (IP_NODE, line);
225 else if (strncmp (line, "key", strlen ("key")) == 0)
226 config = config_get (KEYCHAIN_NODE, line);
227 else if (strncmp (line, "line", strlen ("line")) == 0)
228 config = config_get (VTY_NODE, line);
229 else if ( (strncmp (line, "ipv6 forwarding",
230 strlen ("ipv6 forwarding")) == 0)
231 || (strncmp (line, "ip forwarding",
232 strlen ("ip forwarding")) == 0) )
233 config = config_get (FORWARDING_NODE, line);
234 else if (strncmp (line, "service", strlen ("service")) == 0)
235 config = config_get (SERVICE_NODE, line);
236 else if (strncmp (line, "debug vrf", strlen ("debug vrf")) == 0)
237 config = config_get (VRF_DEBUG_NODE, line);
238 else if (strncmp (line, "debug", strlen ("debug")) == 0)
239 config = config_get (DEBUG_NODE, line);
240 else if (strncmp (line, "password", strlen ("password")) == 0
241 || strncmp (line, "enable password",
242 strlen ("enable password")) == 0)
243 config = config_get (AAA_NODE, line);
244 else if (strncmp (line, "ip protocol", strlen ("ip protocol")) == 0)
245 config = config_get (PROTOCOL_NODE, line);
246 else if (strncmp (line, "ipv6 protocol", strlen ("ipv6 protocol")) == 0)
247 config = config_get (PROTOCOL_NODE, line);
248 else if (strncmp (line, "ip nht", strlen ("ip nht")) == 0)
249 config = config_get (PROTOCOL_NODE, line);
250 else if (strncmp (line, "ipv6 nht", strlen ("ipv6 nht")) == 0)
251 config = config_get (PROTOCOL_NODE, line);
252 else
253 {
254 if (strncmp (line, "log", strlen ("log")) == 0
255 || strncmp (line, "hostname", strlen ("hostname")) == 0
256 )
257 config_add_line_uniq (config_top, line);
258 else
259 config_add_line (config_top, line);
260 config = NULL;
261 }
262 break;
263 }
264 }
265
266 void
267 vtysh_config_parse (char *line)
268 {
269 char *begin;
270 char *pnt;
271
272 begin = pnt = line;
273
274 while (*pnt != '\0')
275 {
276 if (*pnt == '\n')
277 {
278 *pnt++ = '\0';
279 vtysh_config_parse_line (begin);
280 begin = pnt;
281 }
282 else
283 {
284 pnt++;
285 }
286 }
287 }
288
289 /* Macro to check delimiter is needed between each configuration line
290 * or not. */
291 #define NO_DELIMITER(I) \
292 ((I) == ACCESS_NODE || (I) == PREFIX_NODE || (I) == IP_NODE \
293 || (I) == AS_LIST_NODE || (I) == COMMUNITY_LIST_NODE || \
294 (I) == ACCESS_IPV6_NODE || (I) == PREFIX_IPV6_NODE \
295 || (I) == SERVICE_NODE || (I) == FORWARDING_NODE || (I) == DEBUG_NODE \
296 || (I) == AAA_NODE || (I) == VRF_DEBUG_NODE)
297
298 /* Display configuration to file pointer. */
299 void
300 vtysh_config_dump (FILE *fp)
301 {
302 struct listnode *node, *nnode;
303 struct listnode *mnode, *mnnode;
304 struct config *config;
305 struct list *master;
306 char *line;
307 unsigned int i;
308
309 for (ALL_LIST_ELEMENTS (config_top, node, nnode, line))
310 {
311 fprintf (fp, "%s\n", line);
312 fflush (fp);
313 }
314 fprintf (fp, "!\n");
315 fflush (fp);
316
317 for (i = 0; i < vector_active (configvec); i++)
318 if ((master = vector_slot (configvec, i)) != NULL)
319 {
320 for (ALL_LIST_ELEMENTS (master, node, nnode, config))
321 {
322 fprintf (fp, "%s\n", config->name);
323 fflush (fp);
324
325 for (ALL_LIST_ELEMENTS (config->line, mnode, mnnode, line))
326 {
327 fprintf (fp, "%s\n", line);
328 fflush (fp);
329 }
330 if (! NO_DELIMITER (i))
331 {
332 fprintf (fp, "!\n");
333 fflush (fp);
334 }
335 }
336 if (NO_DELIMITER (i))
337 {
338 fprintf (fp, "!\n");
339 fflush (fp);
340 }
341 }
342
343 for (i = 0; i < vector_active (configvec); i++)
344 if ((master = vector_slot (configvec, i)) != NULL)
345 {
346 list_delete (master);
347 vector_slot (configvec, i) = NULL;
348 }
349 list_delete_all_node (config_top);
350 }
351
352 /* Read up configuration file from file_name. */
353 static int
354 vtysh_read_file (FILE *confp)
355 {
356 struct vty *vty;
357 int ret;
358
359 vty = vty_new ();
360 vty->fd = 0; /* stdout */
361 vty->type = VTY_TERM;
362 vty->node = CONFIG_NODE;
363
364 vtysh_execute_no_pager ("enable");
365 vtysh_execute_no_pager ("configure terminal");
366
367 /* Execute configuration file. */
368 ret = vtysh_config_from_file (vty, confp);
369
370 vtysh_execute_no_pager ("end");
371 vtysh_execute_no_pager ("disable");
372
373 vty_close (vty);
374
375 return (ret);
376 }
377
378 /* Read up configuration file from config_default_dir. */
379 int
380 vtysh_read_config (const char *config_default_dir)
381 {
382 FILE *confp = NULL;
383 int ret;
384
385 host_config_set (config_default_dir);
386 confp = fopen (config_default_dir, "r");
387 if (confp == NULL)
388 {
389 fprintf (stderr, "%% Can't open configuration file %s due to '%s'.\n",
390 config_default_dir, safe_strerror (errno));
391 return (CMD_ERR_NO_FILE);
392 }
393
394 ret = vtysh_read_file (confp);
395 fclose (confp);
396
397 return (ret);
398 }
399
400 /* We don't write vtysh specific into file from vtysh. vtysh.conf should
401 * be edited by hand. So, we handle only "write terminal" case here and
402 * integrate vtysh specific conf with conf from daemons.
403 */
404 void
405 vtysh_config_write ()
406 {
407 char line[81];
408 extern struct host host;
409
410 if (host.name)
411 {
412 sprintf (line, "hostname %s", host.name);
413 vtysh_config_parse_line(line);
414 }
415 if (vtysh_writeconfig_integrated)
416 vtysh_config_parse_line ("service integrated-vtysh-config");
417
418 user_config_write ();
419 }
420
421 void
422 vtysh_config_init ()
423 {
424 config_top = list_new ();
425 config_top->del = (void (*) (void *))line_del;
426 configvec = vector_init (1);
427 }