[lib] CID #39, fix leak in error path, vty_describe_command
[jleu-quagga.git] / ripngd / ripng_routemap.c
blob1570c78b478387471407ddbd732104e080a1dfaa
1 /* RIPng routemap.
2 * Copyright (C) 1999 Kunihiro Ishiguro
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 "if.h"
25 #include "memory.h"
26 #include "prefix.h"
27 #include "routemap.h"
28 #include "command.h"
29 #include "sockunion.h"
31 #include "ripngd/ripngd.h"
33 struct rip_metric_modifier
35 enum
37 metric_increment,
38 metric_decrement,
39 metric_absolute
40 } type;
42 u_char metric;
46 int
47 ripng_route_match_add (struct vty *vty, struct route_map_index *index,
48 const char *command, const char *arg)
50 int ret;
52 ret = route_map_add_match (index, command, arg);
53 if (ret)
55 switch (ret)
57 case RMAP_RULE_MISSING:
58 vty_out (vty, "Can't find rule.%s", VTY_NEWLINE);
59 return CMD_WARNING;
60 case RMAP_COMPILE_ERROR:
61 vty_out (vty, "Argument is malformed.%s", VTY_NEWLINE);
62 return CMD_WARNING;
65 return CMD_SUCCESS;
68 int
69 ripng_route_match_delete (struct vty *vty, struct route_map_index *index,
70 const char *command, const char *arg)
72 int ret;
74 ret = route_map_delete_match (index, command, arg);
75 if (ret)
77 switch (ret)
79 case RMAP_RULE_MISSING:
80 vty_out (vty, "Can't find rule.%s", VTY_NEWLINE);
81 return CMD_WARNING;
82 case RMAP_COMPILE_ERROR:
83 vty_out (vty, "Argument is malformed.%s", VTY_NEWLINE);
84 return CMD_WARNING;
87 return CMD_SUCCESS;
90 int
91 ripng_route_set_add (struct vty *vty, struct route_map_index *index,
92 const char *command, const char *arg)
94 int ret;
96 ret = route_map_add_set (index, command, arg);
97 if (ret)
99 switch (ret)
101 case RMAP_RULE_MISSING:
102 vty_out (vty, "Can't find rule.%s", VTY_NEWLINE);
103 return CMD_WARNING;
104 case RMAP_COMPILE_ERROR:
105 vty_out (vty, "Argument is malformed.%s", VTY_NEWLINE);
106 return CMD_WARNING;
109 return CMD_SUCCESS;
113 ripng_route_set_delete (struct vty *vty, struct route_map_index *index,
114 const char *command, const char *arg)
116 int ret;
118 ret = route_map_delete_set (index, command, arg);
119 if (ret)
121 switch (ret)
123 case RMAP_RULE_MISSING:
124 vty_out (vty, "Can't find rule.%s", VTY_NEWLINE);
125 return CMD_WARNING;
126 case RMAP_COMPILE_ERROR:
127 vty_out (vty, "Argument is malformed.%s", VTY_NEWLINE);
128 return CMD_WARNING;
131 return CMD_SUCCESS;
134 /* `match metric METRIC' */
135 /* Match function return 1 if match is success else return zero. */
136 route_map_result_t
137 route_match_metric (void *rule, struct prefix *prefix,
138 route_map_object_t type, void *object)
140 u_int32_t *metric;
141 struct ripng_info *rinfo;
143 if (type == RMAP_RIPNG)
145 metric = rule;
146 rinfo = object;
148 if (rinfo->metric == *metric)
149 return RMAP_MATCH;
150 else
151 return RMAP_NOMATCH;
153 return RMAP_NOMATCH;
156 /* Route map `match metric' match statement. `arg' is METRIC value */
157 void *
158 route_match_metric_compile (const char *arg)
160 u_int32_t *metric;
162 metric = XMALLOC (MTYPE_ROUTE_MAP_COMPILED, sizeof (u_int32_t));
163 *metric = atoi (arg);
165 if(*metric > 0)
166 return metric;
168 XFREE (MTYPE_ROUTE_MAP_COMPILED, metric);
169 return NULL;
172 /* Free route map's compiled `match metric' value. */
173 void
174 route_match_metric_free (void *rule)
176 XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
179 /* Route map commands for metric matching. */
180 struct route_map_rule_cmd route_match_metric_cmd =
182 "metric",
183 route_match_metric,
184 route_match_metric_compile,
185 route_match_metric_free
188 /* `match interface IFNAME' */
189 /* Match function return 1 if match is success else return zero. */
190 route_map_result_t
191 route_match_interface (void *rule, struct prefix *prefix,
192 route_map_object_t type, void *object)
194 struct ripng_info *rinfo;
195 struct interface *ifp;
196 char *ifname;
198 if (type == RMAP_RIPNG)
200 ifname = rule;
201 ifp = if_lookup_by_name(ifname);
203 if (!ifp)
204 return RMAP_NOMATCH;
206 rinfo = object;
208 if (rinfo->ifindex == ifp->ifindex)
209 return RMAP_MATCH;
210 else
211 return RMAP_NOMATCH;
213 return RMAP_NOMATCH;
216 /* Route map `match interface' match statement. `arg' is IFNAME value */
217 void *
218 route_match_interface_compile (const char *arg)
220 return XSTRDUP (MTYPE_ROUTE_MAP_COMPILED, arg);
223 void
224 route_match_interface_free (void *rule)
226 XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
229 struct route_map_rule_cmd route_match_interface_cmd =
231 "interface",
232 route_match_interface,
233 route_match_interface_compile,
234 route_match_interface_free
237 /* `match tag TAG' */
238 /* Match function return 1 if match is success else return zero. */
239 route_map_result_t
240 route_match_tag (void *rule, struct prefix *prefix,
241 route_map_object_t type, void *object)
243 u_short *tag;
244 struct ripng_info *rinfo;
246 if (type == RMAP_RIPNG)
248 tag = rule;
249 rinfo = object;
251 /* The information stored by rinfo is host ordered. */
252 if (rinfo->tag == *tag)
253 return RMAP_MATCH;
254 else
255 return RMAP_NOMATCH;
257 return RMAP_NOMATCH;
260 /* Route map `match tag' match statement. `arg' is TAG value */
261 void *
262 route_match_tag_compile (const char *arg)
264 u_short *tag;
266 tag = XMALLOC (MTYPE_ROUTE_MAP_COMPILED, sizeof (u_short));
267 *tag = atoi (arg);
269 return tag;
272 /* Free route map's compiled `match tag' value. */
273 void
274 route_match_tag_free (void *rule)
276 XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
279 /* Route map commands for tag matching. */
280 struct route_map_rule_cmd route_match_tag_cmd =
282 "tag",
283 route_match_tag,
284 route_match_tag_compile,
285 route_match_tag_free
288 /* `set metric METRIC' */
290 /* Set metric to attribute. */
291 route_map_result_t
292 route_set_metric (void *rule, struct prefix *prefix,
293 route_map_object_t type, void *object)
295 if (type == RMAP_RIPNG)
297 struct rip_metric_modifier *mod;
298 struct ripng_info *rinfo;
300 mod = rule;
301 rinfo = object;
303 if (mod->type == metric_increment)
304 rinfo->metric_out += mod->metric;
305 else if (mod->type == metric_decrement)
306 rinfo->metric_out-= mod->metric;
307 else if (mod->type == metric_absolute)
308 rinfo->metric_out = mod->metric;
310 if (rinfo->metric_out < 1)
311 rinfo->metric_out = 1;
312 if (rinfo->metric_out > RIPNG_METRIC_INFINITY)
313 rinfo->metric_out = RIPNG_METRIC_INFINITY;
315 rinfo->metric_set = 1;
317 return RMAP_OKAY;
320 /* set metric compilation. */
321 void *
322 route_set_metric_compile (const char *arg)
324 int len;
325 const char *pnt;
326 int type;
327 long metric;
328 char *endptr = NULL;
329 struct rip_metric_modifier *mod;
331 len = strlen (arg);
332 pnt = arg;
334 if (len == 0)
335 return NULL;
337 /* Examine first character. */
338 if (arg[0] == '+')
340 type = metric_increment;
341 pnt++;
343 else if (arg[0] == '-')
345 type = metric_decrement;
346 pnt++;
348 else
349 type = metric_absolute;
351 /* Check beginning with digit string. */
352 if (*pnt < '0' || *pnt > '9')
353 return NULL;
355 /* Convert string to integer. */
356 metric = strtol (pnt, &endptr, 10);
358 if (metric == LONG_MAX || *endptr != '\0')
359 return NULL;
360 /* Commented out by Hasso Tepper, to avoid problems in vtysh. */
361 /* if (metric < 0 || metric > RIPNG_METRIC_INFINITY) */
362 if (metric < 0)
363 return NULL;
365 mod = XMALLOC (MTYPE_ROUTE_MAP_COMPILED,
366 sizeof (struct rip_metric_modifier));
367 mod->type = type;
368 mod->metric = metric;
370 return mod;
373 /* Free route map's compiled `set metric' value. */
374 void
375 route_set_metric_free (void *rule)
377 XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
380 struct route_map_rule_cmd route_set_metric_cmd =
382 "metric",
383 route_set_metric,
384 route_set_metric_compile,
385 route_set_metric_free,
388 /* `set ipv6 next-hop local IP_ADDRESS' */
390 /* Set nexthop to object. ojbect must be pointer to struct attr. */
391 route_map_result_t
392 route_set_ipv6_nexthop_local (void *rule, struct prefix *prefix,
393 route_map_object_t type, void *object)
395 struct in6_addr *address;
396 struct ripng_info *rinfo;
398 if(type == RMAP_RIPNG)
400 /* Fetch routemap's rule information. */
401 address = rule;
402 rinfo = object;
404 /* Set next hop value. */
405 rinfo->nexthop_out = *address;
408 return RMAP_OKAY;
411 /* Route map `ipv6 nexthop local' compile function. Given string is converted
412 to struct in6_addr structure. */
413 void *
414 route_set_ipv6_nexthop_local_compile (const char *arg)
416 int ret;
417 struct in6_addr *address;
419 address = XMALLOC (MTYPE_ROUTE_MAP_COMPILED, sizeof (struct in6_addr));
421 ret = inet_pton (AF_INET6, arg, address);
423 if (ret == 0)
425 XFREE (MTYPE_ROUTE_MAP_COMPILED, address);
426 return NULL;
429 return address;
432 /* Free route map's compiled `ipv6 nexthop local' value. */
433 void
434 route_set_ipv6_nexthop_local_free (void *rule)
436 XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
439 /* Route map commands for ipv6 nexthop local set. */
440 struct route_map_rule_cmd route_set_ipv6_nexthop_local_cmd =
442 "ipv6 next-hop local",
443 route_set_ipv6_nexthop_local,
444 route_set_ipv6_nexthop_local_compile,
445 route_set_ipv6_nexthop_local_free
448 /* `set tag TAG' */
450 /* Set tag to object. ojbect must be pointer to struct attr. */
451 route_map_result_t
452 route_set_tag (void *rule, struct prefix *prefix,
453 route_map_object_t type, void *object)
455 u_short *tag;
456 struct ripng_info *rinfo;
458 if(type == RMAP_RIPNG)
460 /* Fetch routemap's rule information. */
461 tag = rule;
462 rinfo = object;
464 /* Set next hop value. */
465 rinfo->tag_out = *tag;
468 return RMAP_OKAY;
471 /* Route map `tag' compile function. Given string is converted
472 to u_short. */
473 void *
474 route_set_tag_compile (const char *arg)
476 u_short *tag;
478 tag = XMALLOC (MTYPE_ROUTE_MAP_COMPILED, sizeof (u_short));
479 *tag = atoi (arg);
481 return tag;
484 /* Free route map's compiled `ip nexthop' value. */
485 void
486 route_set_tag_free (void *rule)
488 XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
491 /* Route map commands for tag set. */
492 struct route_map_rule_cmd route_set_tag_cmd =
494 "tag",
495 route_set_tag,
496 route_set_tag_compile,
497 route_set_tag_free
500 #define MATCH_STR "Match values from routing table\n"
501 #define SET_STR "Set values in destination routing protocol\n"
503 DEFUN (match_metric,
504 match_metric_cmd,
505 "match metric <0-4294967295>",
506 MATCH_STR
507 "Match metric of route\n"
508 "Metric value\n")
510 return ripng_route_match_add (vty, vty->index, "metric", argv[0]);
513 DEFUN (no_match_metric,
514 no_match_metric_cmd,
515 "no match metric",
516 NO_STR
517 MATCH_STR
518 "Match metric of route\n")
520 if (argc == 0)
521 return ripng_route_match_delete (vty, vty->index, "metric", NULL);
523 return ripng_route_match_delete (vty, vty->index, "metric", argv[0]);
526 ALIAS (no_match_metric,
527 no_match_metric_val_cmd,
528 "no match metric <0-4294967295>",
529 NO_STR
530 MATCH_STR
531 "Match metric of route\n"
532 "Metric value\n")
534 DEFUN (match_interface,
535 match_interface_cmd,
536 "match interface WORD",
537 MATCH_STR
538 "Match first hop interface of route\n"
539 "Interface name\n")
541 return ripng_route_match_add (vty, vty->index, "interface", argv[0]);
544 DEFUN (no_match_interface,
545 no_match_interface_cmd,
546 "no match interface",
547 NO_STR
548 MATCH_STR
549 "Match first hop interface of route\n")
551 if (argc == 0)
552 return ripng_route_match_delete (vty, vty->index, "interface", NULL);
554 return ripng_route_match_delete (vty, vty->index, "interface", argv[0]);
557 ALIAS (no_match_interface,
558 no_match_interface_val_cmd,
559 "no match interface WORD",
560 NO_STR
561 MATCH_STR
562 "Match first hop interface of route\n"
563 "Interface name\n")
565 DEFUN (match_tag,
566 match_tag_cmd,
567 "match tag <0-65535>",
568 MATCH_STR
569 "Match tag of route\n"
570 "Metric value\n")
572 return ripng_route_match_add (vty, vty->index, "tag", argv[0]);
575 DEFUN (no_match_tag,
576 no_match_tag_cmd,
577 "no match tag",
578 NO_STR
579 MATCH_STR
580 "Match tag of route\n")
582 if (argc == 0)
583 return ripng_route_match_delete (vty, vty->index, "tag", NULL);
585 return ripng_route_match_delete (vty, vty->index, "tag", argv[0]);
588 ALIAS (no_match_tag,
589 no_match_tag_val_cmd,
590 "no match tag <0-65535>",
591 NO_STR
592 MATCH_STR
593 "Match tag of route\n"
594 "Metric value\n")
596 /* set functions */
598 DEFUN (set_metric,
599 set_metric_cmd,
600 "set metric <0-4294967295>",
601 "Set value\n"
602 "Metric value for destination routing protocol\n"
603 "Metric value\n")
605 return ripng_route_set_add (vty, vty->index, "metric", argv[0]);
608 DEFUN (no_set_metric,
609 no_set_metric_cmd,
610 "no set metric",
611 NO_STR
612 SET_STR
613 "Metric value for destination routing protocol\n")
615 if (argc == 0)
616 return ripng_route_set_delete (vty, vty->index, "metric", NULL);
618 return ripng_route_set_delete (vty, vty->index, "metric", argv[0]);
621 ALIAS (no_set_metric,
622 no_set_metric_val_cmd,
623 "no set metric <0-4294967295>",
624 NO_STR
625 SET_STR
626 "Metric value for destination routing protocol\n"
627 "Metric value\n")
629 DEFUN (set_ipv6_nexthop_local,
630 set_ipv6_nexthop_local_cmd,
631 "set ipv6 next-hop local X:X::X:X",
632 SET_STR
633 IPV6_STR
634 "IPv6 next-hop address\n"
635 "IPv6 local address\n"
636 "IPv6 address of next hop\n")
638 union sockunion su;
639 int ret;
641 ret = str2sockunion (argv[0], &su);
642 if (ret < 0)
644 vty_out (vty, "%% Malformed next-hop local address%s", VTY_NEWLINE);
645 return CMD_WARNING;
648 return ripng_route_set_add (vty, vty->index, "ipv6 next-hop local", argv[0]);
651 DEFUN (no_set_ipv6_nexthop_local,
652 no_set_ipv6_nexthop_local_cmd,
653 "no set ipv6 next-hop local",
654 NO_STR
655 SET_STR
656 IPV6_STR
657 "IPv6 next-hop address\n"
658 "IPv6 local address\n")
660 if (argc == 0)
661 return ripng_route_set_delete (vty, vty->index, "ipv6 next-hop local", NULL);
663 return ripng_route_set_delete (vty, vty->index, "ipv6 next-hop local", argv[0]);
666 ALIAS (no_set_ipv6_nexthop_local,
667 no_set_ipv6_nexthop_local_val_cmd,
668 "no set ipv6 next-hop local X:X::X:X",
669 NO_STR
670 SET_STR
671 IPV6_STR
672 "IPv6 next-hop address\n"
673 "IPv6 local address\n"
674 "IPv6 address of next hop\n")
676 DEFUN (set_tag,
677 set_tag_cmd,
678 "set tag <0-65535>",
679 SET_STR
680 "Tag value for routing protocol\n"
681 "Tag value\n")
683 return ripng_route_set_add (vty, vty->index, "tag", argv[0]);
686 DEFUN (no_set_tag,
687 no_set_tag_cmd,
688 "no set tag",
689 NO_STR
690 SET_STR
691 "Tag value for routing protocol\n")
693 if (argc == 0)
694 return ripng_route_set_delete (vty, vty->index, "tag", NULL);
696 return ripng_route_set_delete (vty, vty->index, "tag", argv[0]);
699 ALIAS (no_set_tag,
700 no_set_tag_val_cmd,
701 "no set tag <0-65535>",
702 NO_STR
703 SET_STR
704 "Tag value for routing protocol\n"
705 "Tag value\n")
707 void
708 ripng_route_map_reset ()
710 /* XXX ??? */
714 void
715 ripng_route_map_init ()
717 route_map_init ();
718 route_map_init_vty ();
720 route_map_install_match (&route_match_metric_cmd);
721 route_map_install_match (&route_match_interface_cmd);
722 route_map_install_match (&route_match_tag_cmd);
724 route_map_install_set (&route_set_metric_cmd);
725 route_map_install_set (&route_set_ipv6_nexthop_local_cmd);
726 route_map_install_set (&route_set_tag_cmd);
728 install_element (RMAP_NODE, &match_metric_cmd);
729 install_element (RMAP_NODE, &no_match_metric_cmd);
730 install_element (RMAP_NODE, &no_match_metric_val_cmd);
731 install_element (RMAP_NODE, &match_interface_cmd);
732 install_element (RMAP_NODE, &no_match_interface_cmd);
733 install_element (RMAP_NODE, &no_match_interface_val_cmd);
734 install_element (RMAP_NODE, &match_tag_cmd);
735 install_element (RMAP_NODE, &no_match_tag_cmd);
736 install_element (RMAP_NODE, &no_match_tag_val_cmd);
738 install_element (RMAP_NODE, &set_metric_cmd);
739 install_element (RMAP_NODE, &no_set_metric_cmd);
740 install_element (RMAP_NODE, &no_set_metric_val_cmd);
741 install_element (RMAP_NODE, &set_ipv6_nexthop_local_cmd);
742 install_element (RMAP_NODE, &no_set_ipv6_nexthop_local_cmd);
743 install_element (RMAP_NODE, &no_set_ipv6_nexthop_local_val_cmd);
744 install_element (RMAP_NODE, &set_tag_cmd);
745 install_element (RMAP_NODE, &no_set_tag_cmd);
746 install_element (RMAP_NODE, &no_set_tag_val_cmd);