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