blob: a31830106fa6005f98328628771de52ac1ac2a7a [file] [log] [blame]
paul718e3742002-12-13 20:15:29 +00001/* RIPng routemap.
2 * Copyright (C) 1999 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
22#include <zebra.h>
23
24#include "if.h"
25#include "memory.h"
26#include "prefix.h"
27#include "routemap.h"
28#include "command.h"
hassoa94434b2003-05-25 17:10:12 +000029#include "sockunion.h"
paul718e3742002-12-13 20:15:29 +000030
31#include "ripngd/ripngd.h"
32
paul718e3742002-12-13 20:15:29 +000033struct rip_metric_modifier
34{
35 enum
36 {
37 metric_increment,
38 metric_decrement,
39 metric_absolute
40 } type;
41
42 u_char metric;
43};
44
paul718e3742002-12-13 20:15:29 +000045
46int
47ripng_route_match_add (struct vty *vty, struct route_map_index *index,
hasso7a1d5832004-10-08 06:32:23 +000048 const char *command, char *arg)
paul718e3742002-12-13 20:15:29 +000049{
50 int ret;
51
52 ret = route_map_add_match (index, command, arg);
53 if (ret)
54 {
55 switch (ret)
56 {
57 case RMAP_RULE_MISSING:
58 vty_out (vty, "Can't find rule.%s", VTY_NEWLINE);
59 return CMD_WARNING;
60 break;
61 case RMAP_COMPILE_ERROR:
62 vty_out (vty, "Argument is malformed.%s", VTY_NEWLINE);
63 return CMD_WARNING;
64 break;
65 }
66 }
67 return CMD_SUCCESS;
68}
69
70int
71ripng_route_match_delete (struct vty *vty, struct route_map_index *index,
hasso7a1d5832004-10-08 06:32:23 +000072 const char *command, char *arg)
paul718e3742002-12-13 20:15:29 +000073{
74 int ret;
75
76 ret = route_map_delete_match (index, command, arg);
77 if (ret)
78 {
79 switch (ret)
80 {
81 case RMAP_RULE_MISSING:
82 vty_out (vty, "Can't find rule.%s", VTY_NEWLINE);
83 return CMD_WARNING;
84 break;
85 case RMAP_COMPILE_ERROR:
86 vty_out (vty, "Argument is malformed.%s", VTY_NEWLINE);
87 return CMD_WARNING;
88 break;
89 }
90 }
91 return CMD_SUCCESS;
92}
93
94int
95ripng_route_set_add (struct vty *vty, struct route_map_index *index,
hasso7a1d5832004-10-08 06:32:23 +000096 const char *command, char *arg)
paul718e3742002-12-13 20:15:29 +000097{
98 int ret;
99
100 ret = route_map_add_set (index, command, arg);
101 if (ret)
102 {
103 switch (ret)
104 {
105 case RMAP_RULE_MISSING:
106 vty_out (vty, "Can't find rule.%s", VTY_NEWLINE);
107 return CMD_WARNING;
108 break;
109 case RMAP_COMPILE_ERROR:
110 vty_out (vty, "Argument is malformed.%s", VTY_NEWLINE);
111 return CMD_WARNING;
112 break;
113 }
114 }
115 return CMD_SUCCESS;
116}
117
118int
119ripng_route_set_delete (struct vty *vty, struct route_map_index *index,
hasso7a1d5832004-10-08 06:32:23 +0000120 const char *command, char *arg)
paul718e3742002-12-13 20:15:29 +0000121{
122 int ret;
123
124 ret = route_map_delete_set (index, command, arg);
125 if (ret)
126 {
127 switch (ret)
128 {
129 case RMAP_RULE_MISSING:
130 vty_out (vty, "Can't find rule.%s", VTY_NEWLINE);
131 return CMD_WARNING;
132 break;
133 case RMAP_COMPILE_ERROR:
134 vty_out (vty, "Argument is malformed.%s", VTY_NEWLINE);
135 return CMD_WARNING;
136 break;
137 }
138 }
139 return CMD_SUCCESS;
140}
141
hassoa94434b2003-05-25 17:10:12 +0000142/* `match metric METRIC' */
143/* Match function return 1 if match is success else return zero. */
144route_map_result_t
145route_match_metric (void *rule, struct prefix *prefix,
146 route_map_object_t type, void *object)
147{
148 u_int32_t *metric;
149 struct ripng_info *rinfo;
150
151 if (type == RMAP_RIPNG)
152 {
153 metric = rule;
154 rinfo = object;
155
156 if (rinfo->metric == *metric)
157 return RMAP_MATCH;
158 else
159 return RMAP_NOMATCH;
160 }
161 return RMAP_NOMATCH;
162}
163
164/* Route map `match metric' match statement. `arg' is METRIC value */
165void *
166route_match_metric_compile (char *arg)
167{
168 u_int32_t *metric;
169
170 metric = XMALLOC (MTYPE_ROUTE_MAP_COMPILED, sizeof (u_int32_t));
171 *metric = atoi (arg);
172
173 if(*metric > 0)
174 return metric;
175
176 XFREE (MTYPE_ROUTE_MAP_COMPILED, metric);
177 return NULL;
178}
179
180/* Free route map's compiled `match metric' value. */
181void
182route_match_metric_free (void *rule)
183{
184 XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
185}
186
187/* Route map commands for metric matching. */
188struct route_map_rule_cmd route_match_metric_cmd =
189{
190 "metric",
191 route_match_metric,
192 route_match_metric_compile,
193 route_match_metric_free
194};
195
196/* `match interface IFNAME' */
197/* Match function return 1 if match is success else return zero. */
198route_map_result_t
199route_match_interface (void *rule, struct prefix *prefix,
200 route_map_object_t type, void *object)
201{
202 struct ripng_info *rinfo;
203 struct interface *ifp;
204 char *ifname;
205
206 if (type == RMAP_RIPNG)
207 {
208 ifname = rule;
209 ifp = if_lookup_by_name(ifname);
210
211 if (!ifp)
212 return RMAP_NOMATCH;
213
214 rinfo = object;
215
216 if (rinfo->ifindex == ifp->ifindex)
217 return RMAP_MATCH;
218 else
219 return RMAP_NOMATCH;
220 }
221 return RMAP_NOMATCH;
222}
223
224/* Route map `match interface' match statement. `arg' is IFNAME value */
225void *
226route_match_interface_compile (char *arg)
227{
228 return XSTRDUP (MTYPE_ROUTE_MAP_COMPILED, arg);
229}
230
231void
232route_match_interface_free (void *rule)
233{
234 XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
235}
236
237struct route_map_rule_cmd route_match_interface_cmd =
238{
239 "interface",
240 route_match_interface,
241 route_match_interface_compile,
242 route_match_interface_free
243};
244
245/* `match tag TAG' */
246/* Match function return 1 if match is success else return zero. */
247route_map_result_t
248route_match_tag (void *rule, struct prefix *prefix,
249 route_map_object_t type, void *object)
250{
251 u_short *tag;
252 struct ripng_info *rinfo;
253
254 if (type == RMAP_RIPNG)
255 {
256 tag = rule;
257 rinfo = object;
258
259 /* The information stored by rinfo is host ordered. */
260 if (rinfo->tag == *tag)
261 return RMAP_MATCH;
262 else
263 return RMAP_NOMATCH;
264 }
265 return RMAP_NOMATCH;
266}
267
268/* Route map `match tag' match statement. `arg' is TAG value */
269void *
270route_match_tag_compile (char *arg)
271{
272 u_short *tag;
273
274 tag = XMALLOC (MTYPE_ROUTE_MAP_COMPILED, sizeof (u_short));
275 *tag = atoi (arg);
276
277 return tag;
278}
279
280/* Free route map's compiled `match tag' value. */
281void
282route_match_tag_free (void *rule)
283{
284 XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
285}
286
287/* Route map commands for tag matching. */
288struct route_map_rule_cmd route_match_tag_cmd =
289{
290 "tag",
291 route_match_tag,
292 route_match_tag_compile,
293 route_match_tag_free
294};
295
296/* `set metric METRIC' */
297
298/* Set metric to attribute. */
299route_map_result_t
300route_set_metric (void *rule, struct prefix *prefix,
301 route_map_object_t type, void *object)
302{
303 if (type == RMAP_RIPNG)
304 {
305 struct rip_metric_modifier *mod;
306 struct ripng_info *rinfo;
307
308 mod = rule;
309 rinfo = object;
310
311 if (mod->type == metric_increment)
312 rinfo->metric_out += mod->metric;
313 else if (mod->type == metric_decrement)
314 rinfo->metric_out-= mod->metric;
315 else if (mod->type == metric_absolute)
316 rinfo->metric_out = mod->metric;
317
318 if (rinfo->metric_out < 1)
319 rinfo->metric_out = 1;
320 if (rinfo->metric_out > RIPNG_METRIC_INFINITY)
321 rinfo->metric_out = RIPNG_METRIC_INFINITY;
322
323 rinfo->metric_set = 1;
324 }
325 return RMAP_OKAY;
326}
327
328/* set metric compilation. */
329void *
330route_set_metric_compile (char *arg)
331{
332 int len;
333 char *pnt;
334 int type;
335 long metric;
336 char *endptr = NULL;
337 struct rip_metric_modifier *mod;
338
339 len = strlen (arg);
340 pnt = arg;
341
342 if (len == 0)
343 return NULL;
344
345 /* Examine first character. */
346 if (arg[0] == '+')
347 {
348 type = metric_increment;
349 pnt++;
350 }
351 else if (arg[0] == '-')
352 {
353 type = metric_decrement;
354 pnt++;
355 }
356 else
357 type = metric_absolute;
358
359 /* Check beginning with digit string. */
360 if (*pnt < '0' || *pnt > '9')
361 return NULL;
362
363 /* Convert string to integer. */
364 metric = strtol (pnt, &endptr, 10);
365
366 if (metric == LONG_MAX || *endptr != '\0')
367 return NULL;
368 /* Commented out by Hasso Tepper, to avoid problems in vtysh. */
369 /* if (metric < 0 || metric > RIPNG_METRIC_INFINITY) */
370 if (metric < 0)
371 return NULL;
372
373 mod = XMALLOC (MTYPE_ROUTE_MAP_COMPILED,
374 sizeof (struct rip_metric_modifier));
375 mod->type = type;
376 mod->metric = metric;
377
378 return mod;
379}
380
381/* Free route map's compiled `set metric' value. */
382void
383route_set_metric_free (void *rule)
384{
385 XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
386}
387
388struct route_map_rule_cmd route_set_metric_cmd =
389{
390 "metric",
391 route_set_metric,
392 route_set_metric_compile,
393 route_set_metric_free,
394};
395
396/* `set ipv6 next-hop local IP_ADDRESS' */
397
398/* Set nexthop to object. ojbect must be pointer to struct attr. */
399route_map_result_t
400route_set_ipv6_nexthop_local (void *rule, struct prefix *prefix,
401 route_map_object_t type, void *object)
402{
403 struct in6_addr *address;
404 struct ripng_info *rinfo;
405
406 if(type == RMAP_RIPNG)
407 {
408 /* Fetch routemap's rule information. */
409 address = rule;
410 rinfo = object;
411
412 /* Set next hop value. */
413 rinfo->nexthop_out = *address;
414 }
415
416 return RMAP_OKAY;
417}
418
419/* Route map `ipv6 nexthop local' compile function. Given string is converted
420 to struct in6_addr structure. */
421void *
422route_set_ipv6_nexthop_local_compile (char *arg)
423{
424 int ret;
425 struct in6_addr *address;
426
427 address = XMALLOC (MTYPE_ROUTE_MAP_COMPILED, sizeof (struct in_addr));
428
429 ret = inet_pton (AF_INET6, arg, address);
430
431 if (ret == 0)
432 {
433 XFREE (MTYPE_ROUTE_MAP_COMPILED, address);
434 return NULL;
435 }
436
437 return address;
438}
439
440/* Free route map's compiled `ipv6 nexthop local' value. */
441void
442route_set_ipv6_nexthop_local_free (void *rule)
443{
444 XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
445}
446
447/* Route map commands for ipv6 nexthop local set. */
448struct route_map_rule_cmd route_set_ipv6_nexthop_local_cmd =
449{
450 "ipv6 next-hop local",
451 route_set_ipv6_nexthop_local,
452 route_set_ipv6_nexthop_local_compile,
453 route_set_ipv6_nexthop_local_free
454};
455
456/* `set tag TAG' */
457
458/* Set tag to object. ojbect must be pointer to struct attr. */
459route_map_result_t
460route_set_tag (void *rule, struct prefix *prefix,
461 route_map_object_t type, void *object)
462{
463 u_short *tag;
464 struct ripng_info *rinfo;
465
466 if(type == RMAP_RIPNG)
467 {
468 /* Fetch routemap's rule information. */
469 tag = rule;
470 rinfo = object;
471
472 /* Set next hop value. */
473 rinfo->tag_out = *tag;
474 }
475
476 return RMAP_OKAY;
477}
478
479/* Route map `tag' compile function. Given string is converted
480 to u_short. */
481void *
482route_set_tag_compile (char *arg)
483{
484 u_short *tag;
485
486 tag = XMALLOC (MTYPE_ROUTE_MAP_COMPILED, sizeof (u_short));
487 *tag = atoi (arg);
488
489 return tag;
490}
491
492/* Free route map's compiled `ip nexthop' value. */
493void
494route_set_tag_free (void *rule)
495{
496 XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
497}
498
499/* Route map commands for tag set. */
500struct route_map_rule_cmd route_set_tag_cmd =
501{
502 "tag",
503 route_set_tag,
504 route_set_tag_compile,
505 route_set_tag_free
506};
507
508#define MATCH_STR "Match values from routing table\n"
509#define SET_STR "Set values in destination routing protocol\n"
510
511DEFUN (match_metric,
512 match_metric_cmd,
513 "match metric <0-4294967295>",
514 MATCH_STR
515 "Match metric of route\n"
516 "Metric value\n")
517{
518 return ripng_route_match_add (vty, vty->index, "metric", argv[0]);
519}
520
521DEFUN (no_match_metric,
522 no_match_metric_cmd,
523 "no match metric",
524 NO_STR
525 MATCH_STR
526 "Match metric of route\n")
527{
528 if (argc == 0)
529 return ripng_route_match_delete (vty, vty->index, "metric", NULL);
530
531 return ripng_route_match_delete (vty, vty->index, "metric", argv[0]);
532}
533
534ALIAS (no_match_metric,
535 no_match_metric_val_cmd,
536 "no match metric <0-4294967295>",
537 NO_STR
538 MATCH_STR
539 "Match metric of route\n"
540 "Metric value\n")
541
paul718e3742002-12-13 20:15:29 +0000542DEFUN (match_interface,
543 match_interface_cmd,
544 "match interface WORD",
hassoa94434b2003-05-25 17:10:12 +0000545 MATCH_STR
546 "Match first hop interface of route\n"
paul718e3742002-12-13 20:15:29 +0000547 "Interface name\n")
548{
549 return ripng_route_match_add (vty, vty->index, "interface", argv[0]);
550}
551
552DEFUN (no_match_interface,
553 no_match_interface_cmd,
hassoa94434b2003-05-25 17:10:12 +0000554 "no match interface",
paul718e3742002-12-13 20:15:29 +0000555 NO_STR
hassoa94434b2003-05-25 17:10:12 +0000556 MATCH_STR
557 "Match first hop interface of route\n")
paul718e3742002-12-13 20:15:29 +0000558{
hassoa94434b2003-05-25 17:10:12 +0000559 if (argc == 0)
560 return ripng_route_match_delete (vty, vty->index, "interface", NULL);
561
paul718e3742002-12-13 20:15:29 +0000562 return ripng_route_match_delete (vty, vty->index, "interface", argv[0]);
563}
hassoa94434b2003-05-25 17:10:12 +0000564
565ALIAS (no_match_interface,
566 no_match_interface_val_cmd,
567 "no match interface WORD",
568 NO_STR
569 MATCH_STR
570 "Match first hop interface of route\n"
571 "Interface name\n")
572
573DEFUN (match_tag,
574 match_tag_cmd,
575 "match tag <0-65535>",
576 MATCH_STR
577 "Match tag of route\n"
578 "Metric value\n")
579{
580 return ripng_route_match_add (vty, vty->index, "tag", argv[0]);
581}
582
583DEFUN (no_match_tag,
584 no_match_tag_cmd,
585 "no match tag",
586 NO_STR
587 MATCH_STR
588 "Match tag of route\n")
589{
590 if (argc == 0)
591 return ripng_route_match_delete (vty, vty->index, "tag", NULL);
592
593 return ripng_route_match_delete (vty, vty->index, "tag", argv[0]);
594}
595
596ALIAS (no_match_tag,
597 no_match_tag_val_cmd,
598 "no match tag <0-65535>",
599 NO_STR
600 MATCH_STR
601 "Match tag of route\n"
602 "Metric value\n")
603
604/* set functions */
paul718e3742002-12-13 20:15:29 +0000605
606DEFUN (set_metric,
607 set_metric_cmd,
608 "set metric <0-4294967295>",
609 "Set value\n"
hassoa94434b2003-05-25 17:10:12 +0000610 "Metric value for destination routing protocol\n"
611 "Metric value\n")
paul718e3742002-12-13 20:15:29 +0000612{
613 return ripng_route_set_add (vty, vty->index, "metric", argv[0]);
614}
615
616DEFUN (no_set_metric,
617 no_set_metric_cmd,
paul73ffb252003-04-19 15:49:49 +0000618 "no set metric",
paul718e3742002-12-13 20:15:29 +0000619 NO_STR
paul73ffb252003-04-19 15:49:49 +0000620 SET_STR
621 "Metric value for destination routing protocol\n")
paul718e3742002-12-13 20:15:29 +0000622{
paul73ffb252003-04-19 15:49:49 +0000623 if (argc == 0)
624 return ripng_route_set_delete (vty, vty->index, "metric", NULL);
625
paul718e3742002-12-13 20:15:29 +0000626 return ripng_route_set_delete (vty, vty->index, "metric", argv[0]);
627}
628
paul73ffb252003-04-19 15:49:49 +0000629ALIAS (no_set_metric,
630 no_set_metric_val_cmd,
631 "no set metric <0-4294967295>",
632 NO_STR
633 SET_STR
634 "Metric value for destination routing protocol\n"
635 "Metric value\n")
636
hassoa94434b2003-05-25 17:10:12 +0000637DEFUN (set_ipv6_nexthop_local,
638 set_ipv6_nexthop_local_cmd,
639 "set ipv6 next-hop local X:X::X:X",
640 SET_STR
641 IPV6_STR
642 "IPv6 next-hop address\n"
643 "IPv6 local address\n"
644 "IPv6 address of next hop\n")
645{
646 union sockunion su;
647 int ret;
648
649 ret = str2sockunion (argv[0], &su);
650 if (ret < 0)
651 {
652 vty_out (vty, "%% Malformed next-hop local address%s", VTY_NEWLINE);
653 return CMD_WARNING;
654 }
655
656 return ripng_route_set_add (vty, vty->index, "ipv6 next-hop local", argv[0]);
657}
658
659DEFUN (no_set_ipv6_nexthop_local,
660 no_set_ipv6_nexthop_local_cmd,
661 "no set ipv6 next-hop local",
662 NO_STR
663 SET_STR
664 IPV6_STR
665 "IPv6 next-hop address\n"
666 "IPv6 local address\n")
667{
668 if (argc == 0)
669 return ripng_route_set_delete (vty, vty->index, "ipv6 next-hop local", NULL);
670
671 return ripng_route_set_delete (vty, vty->index, "ipv6 next-hop local", argv[0]);
672}
673
674ALIAS (no_set_ipv6_nexthop_local,
675 no_set_ipv6_nexthop_local_val_cmd,
676 "no set ipv6 next-hop local X:X::X:X",
677 NO_STR
678 SET_STR
679 IPV6_STR
680 "IPv6 next-hop address\n"
681 "IPv6 local address\n"
682 "IPv6 address of next hop\n")
683
684DEFUN (set_tag,
685 set_tag_cmd,
686 "set tag <0-65535>",
687 SET_STR
688 "Tag value for routing protocol\n"
689 "Tag value\n")
690{
691 return ripng_route_set_add (vty, vty->index, "tag", argv[0]);
692}
693
694DEFUN (no_set_tag,
695 no_set_tag_cmd,
696 "no set tag",
697 NO_STR
698 SET_STR
699 "Tag value for routing protocol\n")
700{
701 if (argc == 0)
702 return ripng_route_set_delete (vty, vty->index, "tag", NULL);
703
704 return ripng_route_set_delete (vty, vty->index, "tag", argv[0]);
705}
706
707ALIAS (no_set_tag,
708 no_set_tag_val_cmd,
709 "no set tag <0-65535>",
710 NO_STR
711 SET_STR
712 "Tag value for routing protocol\n"
713 "Tag value\n")
714
715void
716ripng_route_map_reset ()
717{
718 /* XXX ??? */
719 ;
720}
721
paul718e3742002-12-13 20:15:29 +0000722void
723ripng_route_map_init ()
724{
725 route_map_init ();
726 route_map_init_vty ();
727
hassoa94434b2003-05-25 17:10:12 +0000728 route_map_install_match (&route_match_metric_cmd);
729 route_map_install_match (&route_match_interface_cmd);
730 route_map_install_match (&route_match_tag_cmd);
paul718e3742002-12-13 20:15:29 +0000731
hassoa94434b2003-05-25 17:10:12 +0000732 route_map_install_set (&route_set_metric_cmd);
733 route_map_install_set (&route_set_ipv6_nexthop_local_cmd);
734 route_map_install_set (&route_set_tag_cmd);
735
736 install_element (RMAP_NODE, &match_metric_cmd);
737 install_element (RMAP_NODE, &no_match_metric_cmd);
738 install_element (RMAP_NODE, &no_match_metric_val_cmd);
paul718e3742002-12-13 20:15:29 +0000739 install_element (RMAP_NODE, &match_interface_cmd);
740 install_element (RMAP_NODE, &no_match_interface_cmd);
hassoa94434b2003-05-25 17:10:12 +0000741 install_element (RMAP_NODE, &no_match_interface_val_cmd);
742 install_element (RMAP_NODE, &match_tag_cmd);
743 install_element (RMAP_NODE, &no_match_tag_cmd);
744 install_element (RMAP_NODE, &no_match_tag_val_cmd);
paul718e3742002-12-13 20:15:29 +0000745
746 install_element (RMAP_NODE, &set_metric_cmd);
747 install_element (RMAP_NODE, &no_set_metric_cmd);
hassoa94434b2003-05-25 17:10:12 +0000748 install_element (RMAP_NODE, &no_set_metric_val_cmd);
749 install_element (RMAP_NODE, &set_ipv6_nexthop_local_cmd);
750 install_element (RMAP_NODE, &no_set_ipv6_nexthop_local_cmd);
751 install_element (RMAP_NODE, &no_set_ipv6_nexthop_local_val_cmd);
752 install_element (RMAP_NODE, &set_tag_cmd);
753 install_element (RMAP_NODE, &no_set_tag_cmd);
754 install_element (RMAP_NODE, &no_set_tag_val_cmd);
paul718e3742002-12-13 20:15:29 +0000755}