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