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