]> git.proxmox.com Git - mirror_frr.git/blob - ripd/rip_routemap.c
all: removed all DEFUN command stomps
[mirror_frr.git] / ripd / rip_routemap.c
1 /* RIPv2 routemap.
2 * Copyright (C) 2005 6WIND <alain.ritoux@6wind.com>
3 * Copyright (C) 1999 Kunihiro Ishiguro <kunihiro@zebra.org>
4 *
5 * This file is part of GNU Zebra.
6 *
7 * GNU Zebra is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation; either version 2, or (at your option) any
10 * later version.
11 *
12 * GNU Zebra is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with GNU Zebra; see the file COPYING. If not, write to the Free
19 * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
20 * 02111-1307, USA.
21 */
22
23 #include <zebra.h>
24
25 #include "memory.h"
26 #include "prefix.h"
27 #include "vty.h"
28 #include "routemap.h"
29 #include "command.h"
30 #include "filter.h"
31 #include "log.h"
32 #include "sockunion.h" /* for inet_aton () */
33 #include "plist.h"
34
35 #include "ripd/ripd.h"
36
37 struct rip_metric_modifier
38 {
39 enum
40 {
41 metric_increment,
42 metric_decrement,
43 metric_absolute
44 } type;
45
46 u_char metric;
47 };
48
49 /* Hook function for updating route_map assignment. */
50 /* ARGSUSED */
51 static void
52 rip_route_map_update (const char *notused)
53 {
54 int i;
55
56 if (rip)
57 {
58 for (i = 0; i < ZEBRA_ROUTE_MAX; i++)
59 {
60 if (rip->route_map[i].name)
61 rip->route_map[i].map =
62 route_map_lookup_by_name (rip->route_map[i].name);
63 }
64 }
65 }
66
67 /* `match metric METRIC' */
68 /* Match function return 1 if match is success else return zero. */
69 static route_map_result_t
70 route_match_metric (void *rule, struct prefix *prefix,
71 route_map_object_t type, void *object)
72 {
73 u_int32_t *metric;
74 u_int32_t check;
75 struct rip_info *rinfo;
76
77 if (type == RMAP_RIP)
78 {
79 metric = rule;
80 rinfo = object;
81
82 /* If external metric is available, the route-map should
83 work on this one (for redistribute purpose) */
84 check = (rinfo->external_metric) ? rinfo->external_metric :
85 rinfo->metric;
86 if (check == *metric)
87 return RMAP_MATCH;
88 else
89 return RMAP_NOMATCH;
90 }
91 return RMAP_NOMATCH;
92 }
93
94 /* Route map `match metric' match statement. `arg' is METRIC value */
95 static void *
96 route_match_metric_compile (const char *arg)
97 {
98 u_int32_t *metric;
99
100 metric = XMALLOC (MTYPE_ROUTE_MAP_COMPILED, sizeof (u_int32_t));
101 *metric = atoi (arg);
102
103 if(*metric > 0)
104 return metric;
105
106 XFREE (MTYPE_ROUTE_MAP_COMPILED, metric);
107 return NULL;
108 }
109
110 /* Free route map's compiled `match metric' value. */
111 static void
112 route_match_metric_free (void *rule)
113 {
114 XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
115 }
116
117 /* Route map commands for metric matching. */
118 struct route_map_rule_cmd route_match_metric_cmd =
119 {
120 "metric",
121 route_match_metric,
122 route_match_metric_compile,
123 route_match_metric_free
124 };
125
126 /* `match interface IFNAME' */
127 /* Match function return 1 if match is success else return zero. */
128 static route_map_result_t
129 route_match_interface (void *rule, struct prefix *prefix,
130 route_map_object_t type, void *object)
131 {
132 struct rip_info *rinfo;
133 struct interface *ifp;
134 char *ifname;
135
136 if (type == RMAP_RIP)
137 {
138 ifname = rule;
139 ifp = if_lookup_by_name(ifname);
140
141 if (!ifp)
142 return RMAP_NOMATCH;
143
144 rinfo = object;
145
146 if (rinfo->ifindex_out == ifp->ifindex || rinfo->ifindex == ifp->ifindex)
147 return RMAP_MATCH;
148 else
149 return RMAP_NOMATCH;
150 }
151 return RMAP_NOMATCH;
152 }
153
154 /* Route map `match interface' match statement. `arg' is IFNAME value */
155 /* XXX I don`t know if I need to check does interface exist? */
156 static void *
157 route_match_interface_compile (const char *arg)
158 {
159 return XSTRDUP (MTYPE_ROUTE_MAP_COMPILED, arg);
160 }
161
162 /* Free route map's compiled `match interface' value. */
163 static void
164 route_match_interface_free (void *rule)
165 {
166 XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
167 }
168
169 /* Route map commands for interface matching. */
170 struct route_map_rule_cmd route_match_interface_cmd =
171 {
172 "interface",
173 route_match_interface,
174 route_match_interface_compile,
175 route_match_interface_free
176 };
177
178 /* `match ip next-hop IP_ACCESS_LIST' */
179
180 /* Match function return 1 if match is success else return zero. */
181 static route_map_result_t
182 route_match_ip_next_hop (void *rule, struct prefix *prefix,
183 route_map_object_t type, void *object)
184 {
185 struct access_list *alist;
186 struct rip_info *rinfo;
187 struct prefix_ipv4 p;
188
189 if (type == RMAP_RIP)
190 {
191 rinfo = object;
192 p.family = AF_INET;
193 p.prefix = (rinfo->nexthop.s_addr) ? rinfo->nexthop : rinfo->from;
194 p.prefixlen = IPV4_MAX_BITLEN;
195
196 alist = access_list_lookup (AFI_IP, (char *) rule);
197 if (alist == NULL)
198 return RMAP_NOMATCH;
199
200 return (access_list_apply (alist, &p) == FILTER_DENY ?
201 RMAP_NOMATCH : RMAP_MATCH);
202 }
203 return RMAP_NOMATCH;
204 }
205
206 /* Route map `ip next-hop' match statement. `arg' should be
207 access-list name. */
208 static void *
209 route_match_ip_next_hop_compile (const char *arg)
210 {
211 return XSTRDUP (MTYPE_ROUTE_MAP_COMPILED, arg);
212 }
213
214 /* Free route map's compiled `. */
215 static void
216 route_match_ip_next_hop_free (void *rule)
217 {
218 XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
219 }
220
221 /* Route map commands for ip next-hop matching. */
222 static struct route_map_rule_cmd route_match_ip_next_hop_cmd =
223 {
224 "ip next-hop",
225 route_match_ip_next_hop,
226 route_match_ip_next_hop_compile,
227 route_match_ip_next_hop_free
228 };
229
230 /* `match ip next-hop prefix-list PREFIX_LIST' */
231
232 static route_map_result_t
233 route_match_ip_next_hop_prefix_list (void *rule, struct prefix *prefix,
234 route_map_object_t type, void *object)
235 {
236 struct prefix_list *plist;
237 struct rip_info *rinfo;
238 struct prefix_ipv4 p;
239
240 if (type == RMAP_RIP)
241 {
242 rinfo = object;
243 p.family = AF_INET;
244 p.prefix = (rinfo->nexthop.s_addr) ? rinfo->nexthop : rinfo->from;
245 p.prefixlen = IPV4_MAX_BITLEN;
246
247 plist = prefix_list_lookup (AFI_IP, (char *) rule);
248 if (plist == NULL)
249 return RMAP_NOMATCH;
250
251 return (prefix_list_apply (plist, &p) == PREFIX_DENY ?
252 RMAP_NOMATCH : RMAP_MATCH);
253 }
254 return RMAP_NOMATCH;
255 }
256
257 static void *
258 route_match_ip_next_hop_prefix_list_compile (const char *arg)
259 {
260 return XSTRDUP (MTYPE_ROUTE_MAP_COMPILED, arg);
261 }
262
263 static void
264 route_match_ip_next_hop_prefix_list_free (void *rule)
265 {
266 XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
267 }
268
269 static struct route_map_rule_cmd route_match_ip_next_hop_prefix_list_cmd =
270 {
271 "ip next-hop prefix-list",
272 route_match_ip_next_hop_prefix_list,
273 route_match_ip_next_hop_prefix_list_compile,
274 route_match_ip_next_hop_prefix_list_free
275 };
276
277 /* `match ip address IP_ACCESS_LIST' */
278
279 /* Match function should return 1 if match is success else return
280 zero. */
281 static route_map_result_t
282 route_match_ip_address (void *rule, struct prefix *prefix,
283 route_map_object_t type, void *object)
284 {
285 struct access_list *alist;
286
287 if (type == RMAP_RIP)
288 {
289 alist = access_list_lookup (AFI_IP, (char *) rule);
290 if (alist == NULL)
291 return RMAP_NOMATCH;
292
293 return (access_list_apply (alist, prefix) == FILTER_DENY ?
294 RMAP_NOMATCH : RMAP_MATCH);
295 }
296 return RMAP_NOMATCH;
297 }
298
299 /* Route map `ip address' match statement. `arg' should be
300 access-list name. */
301 static void *
302 route_match_ip_address_compile (const char *arg)
303 {
304 return XSTRDUP (MTYPE_ROUTE_MAP_COMPILED, arg);
305 }
306
307 /* Free route map's compiled `ip address' value. */
308 static void
309 route_match_ip_address_free (void *rule)
310 {
311 XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
312 }
313
314 /* Route map commands for ip address matching. */
315 static struct route_map_rule_cmd route_match_ip_address_cmd =
316 {
317 "ip address",
318 route_match_ip_address,
319 route_match_ip_address_compile,
320 route_match_ip_address_free
321 };
322
323 /* `match ip address prefix-list PREFIX_LIST' */
324
325 static route_map_result_t
326 route_match_ip_address_prefix_list (void *rule, struct prefix *prefix,
327 route_map_object_t type, void *object)
328 {
329 struct prefix_list *plist;
330
331 if (type == RMAP_RIP)
332 {
333 plist = prefix_list_lookup (AFI_IP, (char *) rule);
334 if (plist == NULL)
335 return RMAP_NOMATCH;
336
337 return (prefix_list_apply (plist, prefix) == PREFIX_DENY ?
338 RMAP_NOMATCH : RMAP_MATCH);
339 }
340 return RMAP_NOMATCH;
341 }
342
343 static void *
344 route_match_ip_address_prefix_list_compile (const char *arg)
345 {
346 return XSTRDUP (MTYPE_ROUTE_MAP_COMPILED, arg);
347 }
348
349 static void
350 route_match_ip_address_prefix_list_free (void *rule)
351 {
352 XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
353 }
354
355 static struct route_map_rule_cmd route_match_ip_address_prefix_list_cmd =
356 {
357 "ip address prefix-list",
358 route_match_ip_address_prefix_list,
359 route_match_ip_address_prefix_list_compile,
360 route_match_ip_address_prefix_list_free
361 };
362
363 /* `match tag TAG' */
364 /* Match function return 1 if match is success else return zero. */
365 static route_map_result_t
366 route_match_tag (void *rule, struct prefix *prefix,
367 route_map_object_t type, void *object)
368 {
369 u_short *tag;
370 struct rip_info *rinfo;
371
372 if (type == RMAP_RIP)
373 {
374 tag = rule;
375 rinfo = object;
376
377 /* The information stored by rinfo is host ordered. */
378 if (rinfo->tag == *tag)
379 return RMAP_MATCH;
380 else
381 return RMAP_NOMATCH;
382 }
383 return RMAP_NOMATCH;
384 }
385
386 /* Route map `match tag' match statement. `arg' is TAG value */
387 static void *
388 route_match_tag_compile (const char *arg)
389 {
390 u_short *tag;
391 u_short tmp;
392
393 /* tag value shoud be integer. */
394 if (! all_digit (arg))
395 return NULL;
396
397 tmp = atoi(arg);
398 if (tmp < 1)
399 return NULL;
400
401 tag = XMALLOC (MTYPE_ROUTE_MAP_COMPILED, sizeof (u_short));
402
403 if (!tag)
404 return tag;
405
406 *tag = tmp;
407
408 return tag;
409 }
410
411 /* Free route map's compiled `match tag' value. */
412 static void
413 route_match_tag_free (void *rule)
414 {
415 XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
416 }
417
418 /* Route map commands for tag matching. */
419 struct route_map_rule_cmd route_match_tag_cmd =
420 {
421 "tag",
422 route_match_tag,
423 route_match_tag_compile,
424 route_match_tag_free
425 };
426
427 /* `set metric METRIC' */
428
429 /* Set metric to attribute. */
430 static route_map_result_t
431 route_set_metric (void *rule, struct prefix *prefix,
432 route_map_object_t type, void *object)
433 {
434 if (type == RMAP_RIP)
435 {
436 struct rip_metric_modifier *mod;
437 struct rip_info *rinfo;
438
439 mod = rule;
440 rinfo = object;
441
442 if (mod->type == metric_increment)
443 rinfo->metric_out += mod->metric;
444 else if (mod->type == metric_decrement)
445 rinfo->metric_out -= mod->metric;
446 else if (mod->type == metric_absolute)
447 rinfo->metric_out = mod->metric;
448
449 if ((signed int)rinfo->metric_out < 1)
450 rinfo->metric_out = 1;
451 if (rinfo->metric_out > RIP_METRIC_INFINITY)
452 rinfo->metric_out = RIP_METRIC_INFINITY;
453
454 rinfo->metric_set = 1;
455 }
456 return RMAP_OKAY;
457 }
458
459 /* set metric compilation. */
460 static void *
461 route_set_metric_compile (const char *arg)
462 {
463 int len;
464 const char *pnt;
465 int type;
466 long metric;
467 char *endptr = NULL;
468 struct rip_metric_modifier *mod;
469
470 len = strlen (arg);
471 pnt = arg;
472
473 if (len == 0)
474 return NULL;
475
476 /* Examine first character. */
477 if (arg[0] == '+')
478 {
479 type = metric_increment;
480 pnt++;
481 }
482 else if (arg[0] == '-')
483 {
484 type = metric_decrement;
485 pnt++;
486 }
487 else
488 type = metric_absolute;
489
490 /* Check beginning with digit string. */
491 if (*pnt < '0' || *pnt > '9')
492 return NULL;
493
494 /* Convert string to integer. */
495 metric = strtol (pnt, &endptr, 10);
496
497 if (metric == LONG_MAX || *endptr != '\0')
498 return NULL;
499 if (metric < 0 || metric > RIP_METRIC_INFINITY)
500 return NULL;
501
502 mod = XMALLOC (MTYPE_ROUTE_MAP_COMPILED,
503 sizeof (struct rip_metric_modifier));
504 mod->type = type;
505 mod->metric = metric;
506
507 return mod;
508 }
509
510 /* Free route map's compiled `set metric' value. */
511 static void
512 route_set_metric_free (void *rule)
513 {
514 XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
515 }
516
517 /* Set metric rule structure. */
518 static struct route_map_rule_cmd route_set_metric_cmd =
519 {
520 "metric",
521 route_set_metric,
522 route_set_metric_compile,
523 route_set_metric_free,
524 };
525
526 /* `set ip next-hop IP_ADDRESS' */
527
528 /* Set nexthop to object. ojbect must be pointer to struct attr. */
529 static route_map_result_t
530 route_set_ip_nexthop (void *rule, struct prefix *prefix,
531 route_map_object_t type, void *object)
532 {
533 struct in_addr *address;
534 struct rip_info *rinfo;
535
536 if(type == RMAP_RIP)
537 {
538 /* Fetch routemap's rule information. */
539 address = rule;
540 rinfo = object;
541
542 /* Set next hop value. */
543 rinfo->nexthop_out = *address;
544 }
545
546 return RMAP_OKAY;
547 }
548
549 /* Route map `ip nexthop' compile function. Given string is converted
550 to struct in_addr structure. */
551 static void *
552 route_set_ip_nexthop_compile (const char *arg)
553 {
554 int ret;
555 struct in_addr *address;
556
557 address = XMALLOC (MTYPE_ROUTE_MAP_COMPILED, sizeof (struct in_addr));
558
559 ret = inet_aton (arg, address);
560
561 if (ret == 0)
562 {
563 XFREE (MTYPE_ROUTE_MAP_COMPILED, address);
564 return NULL;
565 }
566
567 return address;
568 }
569
570 /* Free route map's compiled `ip nexthop' value. */
571 static void
572 route_set_ip_nexthop_free (void *rule)
573 {
574 XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
575 }
576
577 /* Route map commands for ip nexthop set. */
578 static struct route_map_rule_cmd route_set_ip_nexthop_cmd =
579 {
580 "ip next-hop",
581 route_set_ip_nexthop,
582 route_set_ip_nexthop_compile,
583 route_set_ip_nexthop_free
584 };
585
586 /* `set tag TAG' */
587
588 /* Set tag to object. ojbect must be pointer to struct attr. */
589 static route_map_result_t
590 route_set_tag (void *rule, struct prefix *prefix,
591 route_map_object_t type, void *object)
592 {
593 u_short *tag;
594 struct rip_info *rinfo;
595
596 if(type == RMAP_RIP)
597 {
598 /* Fetch routemap's rule information. */
599 tag = rule;
600 rinfo = object;
601
602 /* Set next hop value. */
603 rinfo->tag_out = *tag;
604 }
605
606 return RMAP_OKAY;
607 }
608
609 /* Route map `tag' compile function. Given string is converted
610 to u_short. */
611 static void *
612 route_set_tag_compile (const char *arg)
613 {
614 u_short *tag;
615
616 tag = XMALLOC (MTYPE_ROUTE_MAP_COMPILED, sizeof (u_short));
617 *tag = atoi (arg);
618
619 return tag;
620 }
621
622 /* Free route map's compiled `ip nexthop' value. */
623 static void
624 route_set_tag_free (void *rule)
625 {
626 XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
627 }
628
629 /* Route map commands for tag set. */
630 static struct route_map_rule_cmd route_set_tag_cmd =
631 {
632 "tag",
633 route_set_tag,
634 route_set_tag_compile,
635 route_set_tag_free
636 };
637
638 #define MATCH_STR "Match values from routing table\n"
639 #define SET_STR "Set values in destination routing protocol\n"
640
641 void
642 rip_route_map_reset ()
643 {
644 ;
645 }
646
647 /* Route-map init */
648 void
649 rip_route_map_init ()
650 {
651 route_map_init ();
652 route_map_init_vty ();
653 route_map_add_hook (rip_route_map_update);
654 route_map_delete_hook (rip_route_map_update);
655
656 route_map_match_interface_hook (generic_match_add);
657 route_map_no_match_interface_hook (generic_match_delete);
658
659 route_map_match_ip_address_hook (generic_match_add);
660 route_map_no_match_ip_address_hook (generic_match_delete);
661
662 route_map_match_ip_address_prefix_list_hook (generic_match_add);
663 route_map_no_match_ip_address_prefix_list_hook (generic_match_delete);
664
665 route_map_match_ip_next_hop_hook (generic_match_add);
666 route_map_no_match_ip_next_hop_hook (generic_match_delete);
667
668 route_map_match_ip_next_hop_prefix_list_hook (generic_match_add);
669 route_map_no_match_ip_next_hop_prefix_list_hook (generic_match_delete);
670
671 route_map_match_metric_hook (generic_match_add);
672 route_map_no_match_metric_hook (generic_match_delete);
673
674 route_map_match_tag_hook (generic_match_add);
675 route_map_no_match_tag_hook (generic_match_delete);
676
677 route_map_set_ip_nexthop_hook (generic_set_add);
678 route_map_no_set_ip_nexthop_hook (generic_set_delete);
679
680 route_map_set_metric_hook (generic_set_add);
681 route_map_no_set_metric_hook (generic_set_delete);
682
683 route_map_set_tag_hook (generic_set_add);
684 route_map_no_set_tag_hook (generic_set_delete);
685
686 route_map_install_match (&route_match_metric_cmd);
687 route_map_install_match (&route_match_interface_cmd);
688 route_map_install_match (&route_match_ip_next_hop_cmd);
689 route_map_install_match (&route_match_ip_next_hop_prefix_list_cmd);
690 route_map_install_match (&route_match_ip_address_cmd);
691 route_map_install_match (&route_match_ip_address_prefix_list_cmd);
692 route_map_install_match (&route_match_tag_cmd);
693
694 route_map_install_set (&route_set_metric_cmd);
695 route_map_install_set (&route_set_ip_nexthop_cmd);
696 route_map_install_set (&route_set_tag_cmd);
697 }