[lib] CID #39, fix leak in error path, vty_describe_command
[jleu-quagga.git] / ripd / rip_zebra.c
blob44f407dde5f1adb85529fa67e096565866b53213
1 /* RIPd and zebra interface.
2 * Copyright (C) 1997, 1999 Kunihiro Ishiguro <kunihiro@zebra.org>
4 * This file is part of GNU Zebra.
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.
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.
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.
22 #include <zebra.h>
24 #include "command.h"
25 #include "prefix.h"
26 #include "stream.h"
27 #include "routemap.h"
28 #include "zclient.h"
29 #include "log.h"
30 #include "ripd/ripd.h"
31 #include "ripd/rip_debug.h"
32 #include "ripd/rip_interface.h"
34 /* All information about zebra. */
35 struct zclient *zclient = NULL;
37 /* RIPd to zebra command interface. */
38 void
39 rip_zebra_ipv4_add (struct prefix_ipv4 *p, struct in_addr *nexthop,
40 u_int32_t metric, u_char distance)
42 struct zapi_ipv4 api;
44 if (zclient->redist[ZEBRA_ROUTE_RIP])
46 api.type = ZEBRA_ROUTE_RIP;
47 api.flags = 0;
48 api.message = 0;
49 SET_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP);
50 api.nexthop_num = 1;
51 api.nexthop = &nexthop;
52 api.ifindex_num = 0;
53 SET_FLAG (api.message, ZAPI_MESSAGE_METRIC);
54 api.metric = metric;
56 if (distance && distance != ZEBRA_RIP_DISTANCE_DEFAULT)
58 SET_FLAG (api.message, ZAPI_MESSAGE_DISTANCE);
59 api.distance = distance;
62 zapi_ipv4_route (ZEBRA_IPV4_ROUTE_ADD, zclient, p, &api);
64 rip_global_route_changes++;
68 void
69 rip_zebra_ipv4_delete (struct prefix_ipv4 *p, struct in_addr *nexthop,
70 u_int32_t metric)
72 struct zapi_ipv4 api;
74 if (zclient->redist[ZEBRA_ROUTE_RIP])
76 api.type = ZEBRA_ROUTE_RIP;
77 api.flags = 0;
78 api.message = 0;
79 SET_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP);
80 api.nexthop_num = 1;
81 api.nexthop = &nexthop;
82 api.ifindex_num = 0;
83 SET_FLAG (api.message, ZAPI_MESSAGE_METRIC);
84 api.metric = metric;
86 zapi_ipv4_route (ZEBRA_IPV4_ROUTE_DELETE, zclient, p, &api);
88 rip_global_route_changes++;
92 /* Zebra route add and delete treatment. */
93 static int
94 rip_zebra_read_ipv4 (int command, struct zclient *zclient, zebra_size_t length)
96 struct stream *s;
97 struct zapi_ipv4 api;
98 unsigned long ifindex;
99 struct in_addr nexthop;
100 struct prefix_ipv4 p;
102 s = zclient->ibuf;
103 ifindex = 0;
104 nexthop.s_addr = 0;
106 /* Type, flags, message. */
107 api.type = stream_getc (s);
108 api.flags = stream_getc (s);
109 api.message = stream_getc (s);
111 /* IPv4 prefix. */
112 memset (&p, 0, sizeof (struct prefix_ipv4));
113 p.family = AF_INET;
114 p.prefixlen = stream_getc (s);
115 stream_get (&p.prefix, s, PSIZE (p.prefixlen));
117 /* Nexthop, ifindex, distance, metric. */
118 if (CHECK_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP))
120 api.nexthop_num = stream_getc (s);
121 nexthop.s_addr = stream_get_ipv4 (s);
123 if (CHECK_FLAG (api.message, ZAPI_MESSAGE_IFINDEX))
125 api.ifindex_num = stream_getc (s);
126 ifindex = stream_getl (s);
128 if (CHECK_FLAG (api.message, ZAPI_MESSAGE_DISTANCE))
129 api.distance = stream_getc (s);
130 else
131 api.distance = 255;
132 if (CHECK_FLAG (api.message, ZAPI_MESSAGE_METRIC))
133 api.metric = stream_getl (s);
134 else
135 api.metric = 0;
137 /* Then fetch IPv4 prefixes. */
138 if (command == ZEBRA_IPV4_ROUTE_ADD)
139 rip_redistribute_add (api.type, RIP_ROUTE_REDISTRIBUTE, &p, ifindex,
140 &nexthop, api.metric, api.distance);
141 else
142 rip_redistribute_delete (api.type, RIP_ROUTE_REDISTRIBUTE, &p, ifindex);
144 return 0;
147 void
148 rip_zclient_reset (void)
150 zclient_reset (zclient);
153 /* RIP route-map set for redistribution */
154 static void
155 rip_routemap_set (int type, const char *name)
157 if (rip->route_map[type].name)
158 free(rip->route_map[type].name);
160 rip->route_map[type].name = strdup (name);
161 rip->route_map[type].map = route_map_lookup_by_name (name);
164 static void
165 rip_redistribute_metric_set (int type, unsigned int metric)
167 rip->route_map[type].metric_config = 1;
168 rip->route_map[type].metric = metric;
171 static int
172 rip_metric_unset (int type, unsigned int metric)
174 #define DONT_CARE_METRIC_RIP 17
175 if (metric != DONT_CARE_METRIC_RIP &&
176 rip->route_map[type].metric != metric)
177 return 1;
178 rip->route_map[type].metric_config = 0;
179 rip->route_map[type].metric = 0;
180 return 0;
183 /* RIP route-map unset for redistribution */
184 static int
185 rip_routemap_unset (int type, const char *name)
187 if (! rip->route_map[type].name ||
188 (name != NULL && strcmp(rip->route_map[type].name,name)))
189 return 1;
191 free (rip->route_map[type].name);
192 rip->route_map[type].name = NULL;
193 rip->route_map[type].map = NULL;
195 return 0;
198 /* Redistribution types */
199 static struct {
200 int type;
201 int str_min_len;
202 const char *str;
203 } redist_type[] = {
204 {ZEBRA_ROUTE_KERNEL, 1, "kernel"},
205 {ZEBRA_ROUTE_CONNECT, 1, "connected"},
206 {ZEBRA_ROUTE_STATIC, 1, "static"},
207 {ZEBRA_ROUTE_OSPF, 1, "ospf"},
208 {ZEBRA_ROUTE_BGP, 1, "bgp"},
209 {0, 0, NULL}
212 DEFUN (router_zebra,
213 router_zebra_cmd,
214 "router zebra",
215 "Enable a routing process\n"
216 "Make connection to zebra daemon\n")
218 vty->node = ZEBRA_NODE;
219 zclient->enable = 1;
220 zclient_start (zclient);
221 return CMD_SUCCESS;
224 DEFUN (no_router_zebra,
225 no_router_zebra_cmd,
226 "no router zebra",
227 NO_STR
228 "Enable a routing process\n"
229 "Make connection to zebra daemon\n")
231 zclient->enable = 0;
232 zclient_stop (zclient);
233 return CMD_SUCCESS;
236 static int
237 rip_redistribute_set (int type)
239 if (zclient->redist[type])
240 return CMD_SUCCESS;
242 zclient->redist[type] = 1;
244 if (zclient->sock > 0)
245 zebra_redistribute_send (ZEBRA_REDISTRIBUTE_ADD, zclient, type);
247 return CMD_SUCCESS;
250 static int
251 rip_redistribute_unset (int type)
253 if (! zclient->redist[type])
254 return CMD_SUCCESS;
256 zclient->redist[type] = 0;
258 if (zclient->sock > 0)
259 zebra_redistribute_send (ZEBRA_REDISTRIBUTE_DELETE, zclient, type);
261 /* Remove the routes from RIP table. */
262 rip_redistribute_withdraw (type);
264 return CMD_SUCCESS;
268 rip_redistribute_check (int type)
270 return (zclient->redist[type]);
273 void
274 rip_redistribute_clean (void)
276 int i;
278 for (i = 0; redist_type[i].str; i++)
280 if (zclient->redist[redist_type[i].type])
282 if (zclient->sock > 0)
283 zebra_redistribute_send (ZEBRA_REDISTRIBUTE_DELETE,
284 zclient, redist_type[i].type);
286 zclient->redist[redist_type[i].type] = 0;
288 /* Remove the routes from RIP table. */
289 rip_redistribute_withdraw (redist_type[i].type);
294 DEFUN (rip_redistribute_rip,
295 rip_redistribute_rip_cmd,
296 "redistribute rip",
297 "Redistribute information from another routing protocol\n"
298 "Routing Information Protocol (RIP)\n")
300 zclient->redist[ZEBRA_ROUTE_RIP] = 1;
301 return CMD_SUCCESS;
304 DEFUN (no_rip_redistribute_rip,
305 no_rip_redistribute_rip_cmd,
306 "no redistribute rip",
307 NO_STR
308 "Redistribute information from another routing protocol\n"
309 "Routing Information Protocol (RIP)\n")
311 zclient->redist[ZEBRA_ROUTE_RIP] = 0;
312 return CMD_SUCCESS;
315 DEFUN (rip_redistribute_type,
316 rip_redistribute_type_cmd,
317 "redistribute (kernel|connected|static|ospf|bgp)",
318 "Redistribute information from another routing protocol\n"
319 "Kernel routes\n"
320 "Connected\n"
321 "Static routes\n"
322 "Open Shortest Path First (OSPF)\n"
323 "Border Gateway Protocol (BGP)\n")
325 int i;
327 for(i = 0; redist_type[i].str; i++)
329 if (strncmp (redist_type[i].str, argv[0],
330 redist_type[i].str_min_len) == 0)
332 zclient_redistribute (ZEBRA_REDISTRIBUTE_ADD, zclient,
333 redist_type[i].type);
334 return CMD_SUCCESS;
338 vty_out(vty, "Invalid type %s%s", argv[0],
339 VTY_NEWLINE);
341 return CMD_WARNING;
344 DEFUN (no_rip_redistribute_type,
345 no_rip_redistribute_type_cmd,
346 "no redistribute (kernel|connected|static|ospf|bgp)",
347 NO_STR
348 "Redistribute information from another routing protocol\n"
349 "Kernel routes\n"
350 "Connected\n"
351 "Static routes\n"
352 "Open Shortest Path First (OSPF)\n"
353 "Border Gateway Protocol (BGP)\n")
355 int i;
357 for (i = 0; redist_type[i].str; i++)
359 if (strncmp(redist_type[i].str, argv[0],
360 redist_type[i].str_min_len) == 0)
362 rip_metric_unset (redist_type[i].type, DONT_CARE_METRIC_RIP);
363 rip_routemap_unset (redist_type[i].type,NULL);
364 rip_redistribute_unset (redist_type[i].type);
365 return CMD_SUCCESS;
369 vty_out(vty, "Invalid type %s%s", argv[0],
370 VTY_NEWLINE);
372 return CMD_WARNING;
375 DEFUN (rip_redistribute_type_routemap,
376 rip_redistribute_type_routemap_cmd,
377 "redistribute (kernel|connected|static|ospf|bgp) route-map WORD",
378 "Redistribute information from another routing protocol\n"
379 "Kernel routes\n"
380 "Connected\n"
381 "Static routes\n"
382 "Open Shortest Path First (OSPF)\n"
383 "Border Gateway Protocol (BGP)\n"
384 "Route map reference\n"
385 "Pointer to route-map entries\n")
387 int i;
389 for (i = 0; redist_type[i].str; i++) {
390 if (strncmp(redist_type[i].str, argv[0],
391 redist_type[i].str_min_len) == 0)
393 rip_routemap_set (redist_type[i].type, argv[1]);
394 zclient_redistribute (ZEBRA_REDISTRIBUTE_ADD, zclient, redist_type[i].type);
395 return CMD_SUCCESS;
399 vty_out(vty, "Invalid type %s%s", argv[0],
400 VTY_NEWLINE);
402 return CMD_WARNING;
405 DEFUN (no_rip_redistribute_type_routemap,
406 no_rip_redistribute_type_routemap_cmd,
407 "no redistribute (kernel|connected|static|ospf|bgp) route-map WORD",
408 NO_STR
409 "Redistribute information from another routing protocol\n"
410 "Kernel routes\n"
411 "Connected\n"
412 "Static routes\n"
413 "Open Shortest Path First (OSPF)\n"
414 "Border Gateway Protocol (BGP)\n"
415 "Route map reference\n"
416 "Pointer to route-map entries\n")
418 int i;
420 for (i = 0; redist_type[i].str; i++)
422 if (strncmp(redist_type[i].str, argv[0],
423 redist_type[i].str_min_len) == 0)
425 if (rip_routemap_unset (redist_type[i].type,argv[1]))
426 return CMD_WARNING;
427 rip_redistribute_unset (redist_type[i].type);
428 return CMD_SUCCESS;
432 vty_out(vty, "Invalid type %s%s", argv[0],
433 VTY_NEWLINE);
435 return CMD_WARNING;
438 DEFUN (rip_redistribute_type_metric,
439 rip_redistribute_type_metric_cmd,
440 "redistribute (kernel|connected|static|ospf|bgp) metric <0-16>",
441 "Redistribute information from another routing protocol\n"
442 "Kernel routes\n"
443 "Connected\n"
444 "Static routes\n"
445 "Open Shortest Path First (OSPF)\n"
446 "Border Gateway Protocol (BGP)\n"
447 "Metric\n"
448 "Metric value\n")
450 int i;
451 int metric;
453 metric = atoi (argv[1]);
455 for (i = 0; redist_type[i].str; i++) {
456 if (strncmp(redist_type[i].str, argv[0],
457 redist_type[i].str_min_len) == 0)
459 rip_redistribute_metric_set (redist_type[i].type, metric);
460 zclient_redistribute (ZEBRA_REDISTRIBUTE_ADD, zclient, redist_type[i].type);
461 return CMD_SUCCESS;
465 vty_out(vty, "Invalid type %s%s", argv[0],
466 VTY_NEWLINE);
468 return CMD_WARNING;
471 DEFUN (no_rip_redistribute_type_metric,
472 no_rip_redistribute_type_metric_cmd,
473 "no redistribute (kernel|connected|static|ospf|bgp) metric <0-16>",
474 NO_STR
475 "Redistribute information from another routing protocol\n"
476 "Kernel routes\n"
477 "Connected\n"
478 "Static routes\n"
479 "Open Shortest Path First (OSPF)\n"
480 "Border Gateway Protocol (BGP)\n"
481 "Metric\n"
482 "Metric value\n")
484 int i;
486 for (i = 0; redist_type[i].str; i++)
488 if (strncmp(redist_type[i].str, argv[0],
489 redist_type[i].str_min_len) == 0)
491 if (rip_metric_unset (redist_type[i].type, atoi(argv[1])))
492 return CMD_WARNING;
493 rip_redistribute_unset (redist_type[i].type);
494 return CMD_SUCCESS;
498 vty_out(vty, "Invalid type %s%s", argv[0],
499 VTY_NEWLINE);
501 return CMD_WARNING;
504 DEFUN (rip_redistribute_type_metric_routemap,
505 rip_redistribute_type_metric_routemap_cmd,
506 "redistribute (kernel|connected|static|ospf|bgp) metric <0-16> route-map WORD",
507 "Redistribute information from another routing protocol\n"
508 "Kernel routes\n"
509 "Connected\n"
510 "Static routes\n"
511 "Open Shortest Path First (OSPF)\n"
512 "Border Gateway Protocol (BGP)\n"
513 "Metric\n"
514 "Metric value\n"
515 "Route map reference\n"
516 "Pointer to route-map entries\n")
518 int i;
519 int metric;
521 metric = atoi (argv[1]);
523 for (i = 0; redist_type[i].str; i++) {
524 if (strncmp(redist_type[i].str, argv[0],
525 redist_type[i].str_min_len) == 0)
527 rip_redistribute_metric_set (redist_type[i].type, metric);
528 rip_routemap_set (redist_type[i].type, argv[2]);
529 zclient_redistribute (ZEBRA_REDISTRIBUTE_ADD, zclient, redist_type[i].type);
530 return CMD_SUCCESS;
534 vty_out(vty, "Invalid type %s%s", argv[0],
535 VTY_NEWLINE);
537 return CMD_WARNING;
541 DEFUN (no_rip_redistribute_type_metric_routemap,
542 no_rip_redistribute_type_metric_routemap_cmd,
543 "no redistribute (kernel|connected|static|ospf|bgp) metric <0-16> route-map WORD",
544 NO_STR
545 "Redistribute information from another routing protocol\n"
546 "Kernel routes\n"
547 "Connected\n"
548 "Static routes\n"
549 "Open Shortest Path First (OSPF)\n"
550 "Border Gateway Protocol (BGP)\n"
551 "Metric\n"
552 "Metric value\n"
553 "Route map reference\n"
554 "Pointer to route-map entries\n")
556 int i;
558 for (i = 0; redist_type[i].str; i++)
560 if (strncmp(redist_type[i].str, argv[0],
561 redist_type[i].str_min_len) == 0)
563 if (rip_metric_unset (redist_type[i].type, atoi(argv[1])))
564 return CMD_WARNING;
565 if (rip_routemap_unset (redist_type[i].type, argv[2]))
567 rip_redistribute_metric_set(redist_type[i].type, atoi(argv[1]));
568 return CMD_WARNING;
570 rip_redistribute_unset (redist_type[i].type);
571 return CMD_SUCCESS;
575 vty_out(vty, "Invalid type %s%s", argv[0],
576 VTY_NEWLINE);
578 return CMD_WARNING;
581 /* Default information originate. */
583 DEFUN (rip_default_information_originate,
584 rip_default_information_originate_cmd,
585 "default-information originate",
586 "Control distribution of default route\n"
587 "Distribute a default route\n")
589 struct prefix_ipv4 p;
591 if (! rip->default_information)
593 memset (&p, 0, sizeof (struct prefix_ipv4));
594 p.family = AF_INET;
596 rip->default_information = 1;
598 rip_redistribute_add (ZEBRA_ROUTE_RIP, RIP_ROUTE_DEFAULT, &p, 0,
599 NULL, 0, 0);
602 return CMD_SUCCESS;
605 DEFUN (no_rip_default_information_originate,
606 no_rip_default_information_originate_cmd,
607 "no default-information originate",
608 NO_STR
609 "Control distribution of default route\n"
610 "Distribute a default route\n")
612 struct prefix_ipv4 p;
614 if (rip->default_information)
616 memset (&p, 0, sizeof (struct prefix_ipv4));
617 p.family = AF_INET;
619 rip->default_information = 0;
621 rip_redistribute_delete (ZEBRA_ROUTE_RIP, RIP_ROUTE_DEFAULT, &p, 0);
624 return CMD_SUCCESS;
627 /* RIP configuration write function. */
628 static int
629 config_write_zebra (struct vty *vty)
631 if (! zclient->enable)
633 vty_out (vty, "no router zebra%s", VTY_NEWLINE);
634 return 1;
636 else if (! zclient->redist[ZEBRA_ROUTE_RIP])
638 vty_out (vty, "router zebra%s", VTY_NEWLINE);
639 vty_out (vty, " no redistribute rip%s", VTY_NEWLINE);
640 return 1;
642 return 0;
646 config_write_rip_redistribute (struct vty *vty, int config_mode)
648 int i;
650 for (i = 0; i < ZEBRA_ROUTE_MAX; i++)
651 if (i != zclient->redist_default && zclient->redist[i])
653 if (config_mode)
655 if (rip->route_map[i].metric_config)
657 if (rip->route_map[i].name)
658 vty_out (vty, " redistribute %s metric %d route-map %s%s",
659 zebra_route_string(i), rip->route_map[i].metric,
660 rip->route_map[i].name,
661 VTY_NEWLINE);
662 else
663 vty_out (vty, " redistribute %s metric %d%s",
664 zebra_route_string(i), rip->route_map[i].metric,
665 VTY_NEWLINE);
667 else
669 if (rip->route_map[i].name)
670 vty_out (vty, " redistribute %s route-map %s%s",
671 zebra_route_string(i), rip->route_map[i].name,
672 VTY_NEWLINE);
673 else
674 vty_out (vty, " redistribute %s%s", zebra_route_string(i),
675 VTY_NEWLINE);
678 else
679 vty_out (vty, " %s", zebra_route_string(i));
681 return 0;
684 /* Zebra node structure. */
685 struct cmd_node zebra_node =
687 ZEBRA_NODE,
688 "%s(config-router)# ",
691 void
692 rip_zclient_init ()
694 /* Set default value to the zebra client structure. */
695 zclient = zclient_new ();
696 zclient_init (zclient, ZEBRA_ROUTE_RIP);
697 zclient->interface_add = rip_interface_add;
698 zclient->interface_delete = rip_interface_delete;
699 zclient->interface_address_add = rip_interface_address_add;
700 zclient->interface_address_delete = rip_interface_address_delete;
701 zclient->ipv4_route_add = rip_zebra_read_ipv4;
702 zclient->ipv4_route_delete = rip_zebra_read_ipv4;
703 zclient->interface_up = rip_interface_up;
704 zclient->interface_down = rip_interface_down;
706 /* Install zebra node. */
707 install_node (&zebra_node, config_write_zebra);
709 /* Install command elements to zebra node. */
710 install_element (CONFIG_NODE, &router_zebra_cmd);
711 install_element (CONFIG_NODE, &no_router_zebra_cmd);
712 install_default (ZEBRA_NODE);
713 install_element (ZEBRA_NODE, &rip_redistribute_rip_cmd);
714 install_element (ZEBRA_NODE, &no_rip_redistribute_rip_cmd);
716 /* Install command elements to rip node. */
717 install_element (RIP_NODE, &rip_redistribute_type_cmd);
718 install_element (RIP_NODE, &rip_redistribute_type_routemap_cmd);
719 install_element (RIP_NODE, &rip_redistribute_type_metric_cmd);
720 install_element (RIP_NODE, &rip_redistribute_type_metric_routemap_cmd);
721 install_element (RIP_NODE, &no_rip_redistribute_type_cmd);
722 install_element (RIP_NODE, &no_rip_redistribute_type_routemap_cmd);
723 install_element (RIP_NODE, &no_rip_redistribute_type_metric_cmd);
724 install_element (RIP_NODE, &no_rip_redistribute_type_metric_routemap_cmd);
725 install_element (RIP_NODE, &rip_default_information_originate_cmd);
726 install_element (RIP_NODE, &no_rip_default_information_originate_cmd);