]> git.proxmox.com Git - mirror_frr.git/blob - ripd/rip_routemap.c
*: make consistent & update GPLv2 file headers
[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 along
18 * with this program; see the file COPYING; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
20 */
21
22 #include <zebra.h>
23
24 #include "memory.h"
25 #include "prefix.h"
26 #include "vty.h"
27 #include "routemap.h"
28 #include "command.h"
29 #include "filter.h"
30 #include "log.h"
31 #include "sockunion.h" /* for inet_aton () */
32 #include "plist.h"
33 #include "vrf.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, VRF_DEFAULT);
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 route_tag_t *tag;
370 struct rip_info *rinfo;
371 route_tag_t rinfo_tag;
372
373 if (type == RMAP_RIP)
374 {
375 tag = rule;
376 rinfo = object;
377
378 /* The information stored by rinfo is host ordered. */
379 rinfo_tag = rinfo->tag;
380 if (rinfo_tag == *tag)
381 return RMAP_MATCH;
382 else
383 return RMAP_NOMATCH;
384 }
385 return RMAP_NOMATCH;
386 }
387
388 /* Route map commands for tag matching. */
389 static struct route_map_rule_cmd route_match_tag_cmd =
390 {
391 "tag",
392 route_match_tag,
393 route_map_rule_tag_compile,
394 route_map_rule_tag_free,
395 };
396
397 /* `set metric METRIC' */
398
399 /* Set metric to attribute. */
400 static route_map_result_t
401 route_set_metric (void *rule, struct prefix *prefix,
402 route_map_object_t type, void *object)
403 {
404 if (type == RMAP_RIP)
405 {
406 struct rip_metric_modifier *mod;
407 struct rip_info *rinfo;
408
409 mod = rule;
410 rinfo = object;
411
412 if (mod->type == metric_increment)
413 rinfo->metric_out += mod->metric;
414 else if (mod->type == metric_decrement)
415 rinfo->metric_out -= mod->metric;
416 else if (mod->type == metric_absolute)
417 rinfo->metric_out = mod->metric;
418
419 if ((signed int)rinfo->metric_out < 1)
420 rinfo->metric_out = 1;
421 if (rinfo->metric_out > RIP_METRIC_INFINITY)
422 rinfo->metric_out = RIP_METRIC_INFINITY;
423
424 rinfo->metric_set = 1;
425 }
426 return RMAP_OKAY;
427 }
428
429 /* set metric compilation. */
430 static void *
431 route_set_metric_compile (const char *arg)
432 {
433 int len;
434 const char *pnt;
435 int type;
436 long metric;
437 char *endptr = NULL;
438 struct rip_metric_modifier *mod;
439
440 len = strlen (arg);
441 pnt = arg;
442
443 if (len == 0)
444 return NULL;
445
446 /* Examine first character. */
447 if (arg[0] == '+')
448 {
449 type = metric_increment;
450 pnt++;
451 }
452 else if (arg[0] == '-')
453 {
454 type = metric_decrement;
455 pnt++;
456 }
457 else
458 type = metric_absolute;
459
460 /* Check beginning with digit string. */
461 if (*pnt < '0' || *pnt > '9')
462 return NULL;
463
464 /* Convert string to integer. */
465 metric = strtol (pnt, &endptr, 10);
466
467 if (metric == LONG_MAX || *endptr != '\0')
468 return NULL;
469 if (metric < 0 || metric > RIP_METRIC_INFINITY)
470 return NULL;
471
472 mod = XMALLOC (MTYPE_ROUTE_MAP_COMPILED,
473 sizeof (struct rip_metric_modifier));
474 mod->type = type;
475 mod->metric = metric;
476
477 return mod;
478 }
479
480 /* Free route map's compiled `set metric' value. */
481 static void
482 route_set_metric_free (void *rule)
483 {
484 XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
485 }
486
487 /* Set metric rule structure. */
488 static struct route_map_rule_cmd route_set_metric_cmd =
489 {
490 "metric",
491 route_set_metric,
492 route_set_metric_compile,
493 route_set_metric_free,
494 };
495
496 /* `set ip next-hop IP_ADDRESS' */
497
498 /* Set nexthop to object. ojbect must be pointer to struct attr. */
499 static route_map_result_t
500 route_set_ip_nexthop (void *rule, struct prefix *prefix,
501 route_map_object_t type, void *object)
502 {
503 struct in_addr *address;
504 struct rip_info *rinfo;
505
506 if(type == RMAP_RIP)
507 {
508 /* Fetch routemap's rule information. */
509 address = rule;
510 rinfo = object;
511
512 /* Set next hop value. */
513 rinfo->nexthop_out = *address;
514 }
515
516 return RMAP_OKAY;
517 }
518
519 /* Route map `ip nexthop' compile function. Given string is converted
520 to struct in_addr structure. */
521 static void *
522 route_set_ip_nexthop_compile (const char *arg)
523 {
524 int ret;
525 struct in_addr *address;
526
527 address = XMALLOC (MTYPE_ROUTE_MAP_COMPILED, sizeof (struct in_addr));
528
529 ret = inet_aton (arg, address);
530
531 if (ret == 0)
532 {
533 XFREE (MTYPE_ROUTE_MAP_COMPILED, address);
534 return NULL;
535 }
536
537 return address;
538 }
539
540 /* Free route map's compiled `ip nexthop' value. */
541 static void
542 route_set_ip_nexthop_free (void *rule)
543 {
544 XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
545 }
546
547 /* Route map commands for ip nexthop set. */
548 static struct route_map_rule_cmd route_set_ip_nexthop_cmd =
549 {
550 "ip next-hop",
551 route_set_ip_nexthop,
552 route_set_ip_nexthop_compile,
553 route_set_ip_nexthop_free
554 };
555
556 /* `set tag TAG' */
557
558 /* Set tag to object. ojbect must be pointer to struct attr. */
559 static route_map_result_t
560 route_set_tag (void *rule, struct prefix *prefix,
561 route_map_object_t type, void *object)
562 {
563 route_tag_t *tag;
564 struct rip_info *rinfo;
565
566 if(type == RMAP_RIP)
567 {
568 /* Fetch routemap's rule information. */
569 tag = rule;
570 rinfo = object;
571
572 /* Set next hop value. */
573 rinfo->tag_out = *tag;
574 }
575
576 return RMAP_OKAY;
577 }
578
579 /* Route map commands for tag set. */
580 static struct route_map_rule_cmd route_set_tag_cmd =
581 {
582 "tag",
583 route_set_tag,
584 route_map_rule_tag_compile,
585 route_map_rule_tag_free
586 };
587
588 #define MATCH_STR "Match values from routing table\n"
589 #define SET_STR "Set values in destination routing protocol\n"
590
591 void
592 rip_route_map_reset ()
593 {
594 ;
595 }
596
597 /* Route-map init */
598 void
599 rip_route_map_init ()
600 {
601 route_map_init ();
602
603 route_map_add_hook (rip_route_map_update);
604 route_map_delete_hook (rip_route_map_update);
605
606 route_map_match_interface_hook (generic_match_add);
607 route_map_no_match_interface_hook (generic_match_delete);
608
609 route_map_match_ip_address_hook (generic_match_add);
610 route_map_no_match_ip_address_hook (generic_match_delete);
611
612 route_map_match_ip_address_prefix_list_hook (generic_match_add);
613 route_map_no_match_ip_address_prefix_list_hook (generic_match_delete);
614
615 route_map_match_ip_next_hop_hook (generic_match_add);
616 route_map_no_match_ip_next_hop_hook (generic_match_delete);
617
618 route_map_match_ip_next_hop_prefix_list_hook (generic_match_add);
619 route_map_no_match_ip_next_hop_prefix_list_hook (generic_match_delete);
620
621 route_map_match_metric_hook (generic_match_add);
622 route_map_no_match_metric_hook (generic_match_delete);
623
624 route_map_match_tag_hook (generic_match_add);
625 route_map_no_match_tag_hook (generic_match_delete);
626
627 route_map_set_ip_nexthop_hook (generic_set_add);
628 route_map_no_set_ip_nexthop_hook (generic_set_delete);
629
630 route_map_set_metric_hook (generic_set_add);
631 route_map_no_set_metric_hook (generic_set_delete);
632
633 route_map_set_tag_hook (generic_set_add);
634 route_map_no_set_tag_hook (generic_set_delete);
635
636 route_map_install_match (&route_match_metric_cmd);
637 route_map_install_match (&route_match_interface_cmd);
638 route_map_install_match (&route_match_ip_next_hop_cmd);
639 route_map_install_match (&route_match_ip_next_hop_prefix_list_cmd);
640 route_map_install_match (&route_match_ip_address_cmd);
641 route_map_install_match (&route_match_ip_address_prefix_list_cmd);
642 route_map_install_match (&route_match_tag_cmd);
643
644 route_map_install_set (&route_set_metric_cmd);
645 route_map_install_set (&route_set_ip_nexthop_cmd);
646 route_map_install_set (&route_set_tag_cmd);
647 }