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