1: /* zebra routemap.
2: * Copyright (C) 2006 IBM Corporation
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 "memory.h"
25: #include "prefix.h"
26: #include "rib.h"
27: #include "routemap.h"
28: #include "command.h"
29: #include "filter.h"
30: #include "plist.h"
31: #include "vrf.h"
32:
33: #include "zebra/zserv.h"
34:
35: /* Add zebra route map rule */
36: static int
37: zebra_route_match_add(struct vty *vty, struct route_map_index *index,
38: const char *command, const char *arg)
39: {
40: int ret;
41:
42: ret = route_map_add_match (index, command, arg);
43: if (ret)
44: {
45: switch (ret)
46: {
47: case RMAP_RULE_MISSING:
48: vty_out (vty, "%% Can't find rule.%s", VTY_NEWLINE);
49: return CMD_WARNING;
50: case RMAP_COMPILE_ERROR:
51: vty_out (vty, "%% Argument is malformed.%s", VTY_NEWLINE);
52: return CMD_WARNING;
53: }
54: }
55: return CMD_SUCCESS;
56: }
57:
58: /* Delete zebra route map rule. */
59: static int
60: zebra_route_match_delete (struct vty *vty, struct route_map_index *index,
61: const char *command, const char *arg)
62: {
63: int ret;
64:
65: ret = route_map_delete_match (index, command, arg);
66: if (ret)
67: {
68: switch (ret)
69: {
70: case RMAP_RULE_MISSING:
71: vty_out (vty, "%% Can't find rule.%s", VTY_NEWLINE);
72: return CMD_WARNING;
73: case RMAP_COMPILE_ERROR:
74: vty_out (vty, "%% Argument is malformed.%s", VTY_NEWLINE);
75: return CMD_WARNING;
76: }
77: }
78: return CMD_SUCCESS;
79: }
80:
81: /* Add zebra route map rule. */
82: static int
83: zebra_route_set_add (struct vty *vty, struct route_map_index *index,
84: const char *command, const char *arg)
85: {
86: int ret;
87:
88: ret = route_map_add_set (index, command, arg);
89: if (ret)
90: {
91: switch (ret)
92: {
93: case RMAP_RULE_MISSING:
94: vty_out (vty, "%% Can't find rule.%s", VTY_NEWLINE);
95: return CMD_WARNING;
96: case RMAP_COMPILE_ERROR:
97: vty_out (vty, "%% Argument is malformed.%s", VTY_NEWLINE);
98: return CMD_WARNING;
99: }
100: }
101: return CMD_SUCCESS;
102: }
103:
104: /* Delete zebra route map rule. */
105: static int
106: zebra_route_set_delete (struct vty *vty, struct route_map_index *index,
107: const char *command, const char *arg)
108: {
109: int ret;
110:
111: ret = route_map_delete_set (index, command, arg);
112: if (ret)
113: {
114: switch (ret)
115: {
116: case RMAP_RULE_MISSING:
117: vty_out (vty, "%% Can't find rule.%s", VTY_NEWLINE);
118: return CMD_WARNING;
119: case RMAP_COMPILE_ERROR:
120: vty_out (vty, "%% Argument is malformed.%s", VTY_NEWLINE);
121: return CMD_WARNING;
122: }
123: }
124: return CMD_SUCCESS;
125: }
126:
127:
128: /* `match interface IFNAME' */
129: /* Match function return 1 if match is success else return zero. */
130: static route_map_result_t
131: route_match_interface (void *rule, struct prefix *prefix,
132: route_map_object_t type, void *object)
133: {
134: struct nexthop_vrfid *nh_vrf;
135: struct nexthop *nexthop;
136: char *ifname = rule;
137: ifindex_t ifindex;
138:
139: if (type == RMAP_ZEBRA)
140: {
141: if (strcasecmp(ifname, "any") == 0)
142: return RMAP_MATCH;
143: nh_vrf = object;
144: if (!nh_vrf)
145: return RMAP_NOMATCH;
146: ifindex = ifname2ifindex_vrf (ifname, nh_vrf->vrf_id);
147: if (ifindex == 0)
148: return RMAP_NOMATCH;
149: nexthop = nh_vrf->nexthop;
150: if (!nexthop)
151: return RMAP_NOMATCH;
152: if (nexthop->ifindex == ifindex)
153: return RMAP_MATCH;
154: }
155: return RMAP_NOMATCH;
156: }
157:
158: /* Route map `match interface' match statement. `arg' is IFNAME value */
159: static void *
160: route_match_interface_compile (const char *arg)
161: {
162: return XSTRDUP (MTYPE_ROUTE_MAP_COMPILED, arg);
163: }
164:
165: /* Free route map's compiled `match interface' value. */
166: static void
167: route_match_interface_free (void *rule)
168: {
169: XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
170: }
171:
172: /* Route map commands for interface matching */
173: struct route_map_rule_cmd route_match_interface_cmd =
174: {
175: "interface",
176: route_match_interface,
177: route_match_interface_compile,
178: route_match_interface_free
179: };
180:
181: DEFUN (match_interface,
182: match_interface_cmd,
183: "match interface WORD",
184: MATCH_STR
185: "match first hop interface of route\n"
186: "Interface name\n")
187: {
188: return zebra_route_match_add (vty, vty->index, "interface", argv[0]);
189: }
190:
191: DEFUN (no_match_interface,
192: no_match_interface_cmd,
193: "no match interface",
194: NO_STR
195: MATCH_STR
196: "Match first hop interface of route\n")
197: {
198: if (argc == 0)
199: return zebra_route_match_delete (vty, vty->index, "interface", NULL);
200:
201: return zebra_route_match_delete (vty, vty->index, "interface", argv[0]);
202: }
203:
204: ALIAS (no_match_interface,
205: no_match_interface_val_cmd,
206: "no match interface WORD",
207: NO_STR
208: MATCH_STR
209: "Match first hop interface of route\n"
210: "Interface name\n")
211:
212: DEFUN (match_ip_next_hop,
213: match_ip_next_hop_cmd,
214: "match ip next-hop (<1-199>|<1300-2699>|WORD)",
215: MATCH_STR
216: IP_STR
217: "Match next-hop address of route\n"
218: "IP access-list number\n"
219: "IP access-list number (expanded range)\n"
220: "IP Access-list name\n")
221: {
222: return zebra_route_match_add (vty, vty->index, "ip next-hop", argv[0]);
223: }
224:
225: DEFUN (no_match_ip_next_hop,
226: no_match_ip_next_hop_cmd,
227: "no match ip next-hop",
228: NO_STR
229: MATCH_STR
230: IP_STR
231: "Match next-hop address of route\n")
232: {
233: if (argc == 0)
234: return zebra_route_match_delete (vty, vty->index, "ip next-hop", NULL);
235:
236: return zebra_route_match_delete (vty, vty->index, "ip next-hop", argv[0]);
237: }
238:
239: ALIAS (no_match_ip_next_hop,
240: no_match_ip_next_hop_val_cmd,
241: "no match ip next-hop (<1-199>|<1300-2699>|WORD)",
242: NO_STR
243: MATCH_STR
244: IP_STR
245: "Match next-hop address of route\n"
246: "IP access-list number\n"
247: "IP access-list number (expanded range)\n"
248: "IP Access-list name\n")
249:
250: DEFUN (match_ip_next_hop_prefix_list,
251: match_ip_next_hop_prefix_list_cmd,
252: "match ip next-hop prefix-list WORD",
253: MATCH_STR
254: IP_STR
255: "Match next-hop address of route\n"
256: "Match entries of prefix-lists\n"
257: "IP prefix-list name\n")
258: {
259: return zebra_route_match_add (vty, vty->index, "ip next-hop prefix-list", argv[0]);
260: }
261:
262: DEFUN (no_match_ip_next_hop_prefix_list,
263: no_match_ip_next_hop_prefix_list_cmd,
264: "no match ip next-hop prefix-list",
265: NO_STR
266: MATCH_STR
267: IP_STR
268: "Match next-hop address of route\n"
269: "Match entries of prefix-lists\n")
270: {
271: if (argc == 0)
272: return zebra_route_match_delete (vty, vty->index, "ip next-hop prefix-list", NULL);
273:
274: return zebra_route_match_delete (vty, vty->index, "ip next-hop prefix-list", argv[0]);
275: }
276:
277: ALIAS (no_match_ip_next_hop_prefix_list,
278: no_match_ip_next_hop_prefix_list_val_cmd,
279: "no match ip next-hop prefix-list WORD",
280: NO_STR
281: MATCH_STR
282: IP_STR
283: "Match next-hop address of route\n"
284: "Match entries of prefix-lists\n"
285: "IP prefix-list name\n")
286:
287: DEFUN (match_ip_address,
288: match_ip_address_cmd,
289: "match ip address (<1-199>|<1300-2699>|WORD)",
290: MATCH_STR
291: IP_STR
292: "Match address of route\n"
293: "IP access-list number\n"
294: "IP access-list number (expanded range)\n"
295: "IP Access-list name\n")
296:
297: {
298: return zebra_route_match_add (vty, vty->index, "ip address", argv[0]);
299: }
300:
301: DEFUN (no_match_ip_address,
302: no_match_ip_address_cmd,
303: "no match ip address",
304: NO_STR
305: MATCH_STR
306: IP_STR
307: "Match address of route\n")
308: {
309: if (argc == 0)
310: return zebra_route_match_delete (vty, vty->index, "ip address", NULL);
311:
312: return zebra_route_match_delete (vty, vty->index, "ip address", argv[0]);
313: }
314:
315: ALIAS (no_match_ip_address,
316: no_match_ip_address_val_cmd,
317: "no match ip address (<1-199>|<1300-2699>|WORD)",
318: NO_STR
319: MATCH_STR
320: IP_STR
321: "Match address of route\n"
322: "IP access-list number\n"
323: "IP access-list number (expanded range)\n"
324: "IP Access-list name\n")
325:
326: DEFUN (match_ip_address_prefix_list,
327: match_ip_address_prefix_list_cmd,
328: "match ip address prefix-list WORD",
329: MATCH_STR
330: IP_STR
331: "Match address of route\n"
332: "Match entries of prefix-lists\n"
333: "IP prefix-list name\n")
334: {
335: return zebra_route_match_add (vty, vty->index, "ip address prefix-list", argv[0]);
336: }
337:
338: DEFUN (no_match_ip_address_prefix_list,
339: no_match_ip_address_prefix_list_cmd,
340: "no match ip address prefix-list",
341: NO_STR
342: MATCH_STR
343: IP_STR
344: "Match address of route\n"
345: "Match entries of prefix-lists\n")
346: {
347: if (argc == 0)
348: return zebra_route_match_delete (vty, vty->index, "ip address prefix-list", NULL);
349:
350: return zebra_route_match_delete (vty, vty->index, "ip address prefix-list", argv[0]);
351: }
352:
353: ALIAS (no_match_ip_address_prefix_list,
354: no_match_ip_address_prefix_list_val_cmd,
355: "no match ip address prefix-list WORD",
356: NO_STR
357: MATCH_STR
358: IP_STR
359: "Match address of route\n"
360: "Match entries of prefix-lists\n"
361: "IP prefix-list name\n")
362:
363: /* set functions */
364:
365: DEFUN (set_src,
366: set_src_cmd,
367: "set src A.B.C.D",
368: SET_STR
369: "src address for route\n"
370: "src address\n")
371: {
372: struct in_addr src;
373: struct interface *pif = NULL;
374: vrf_iter_t iter;
375:
376: if (inet_pton(AF_INET, argv[0], &src) <= 0)
377: {
378: vty_out (vty, "%% not a local address%s", VTY_NEWLINE);
379: return CMD_WARNING;
380: }
381:
382: for (iter = vrf_first (); iter != VRF_ITER_INVALID; iter = vrf_next (iter))
383: if ((pif = if_lookup_exact_address_vrf (src, vrf_iter2id (iter))) != NULL)
384: break;
385:
386: if (!pif)
387: {
388: vty_out (vty, "%% not a local address%s", VTY_NEWLINE);
389: return CMD_WARNING;
390: }
391:
392: return zebra_route_set_add (vty, vty->index, "src", argv[0]);
393: }
394:
395: DEFUN (no_set_src,
396: no_set_src_cmd,
397: "no set src",
398: NO_STR
399: SET_STR
400: "Source address for route\n")
401: {
402: if (argc == 0)
403: return zebra_route_set_delete (vty, vty->index, "src", NULL);
404:
405: return zebra_route_set_delete (vty, vty->index, "src", argv[0]);
406: }
407:
408: ALIAS (no_set_src,
409: no_set_src_val_cmd,
410: "no set src (A.B.C.D)",
411: NO_STR
412: SET_STR
413: "src address for route\n"
414: "src address\n")
415:
416: /*XXXXXXXXXXXXXXXXXXXXXXXXXXXX*/
417:
418: /* `match ip next-hop IP_ACCESS_LIST' */
419:
420: /* Match function return 1 if match is success else return zero. */
421: static route_map_result_t
422: route_match_ip_next_hop (void *rule, struct prefix *prefix,
423: route_map_object_t type, void *object)
424: {
425: struct access_list *alist;
426: struct nexthop *nexthop;
427: struct prefix_ipv4 p;
428:
429: if (type == RMAP_ZEBRA)
430: {
431: nexthop = object;
432: switch (nexthop->type) {
433: case NEXTHOP_TYPE_IFINDEX:
434: case NEXTHOP_TYPE_IFNAME:
435: /* Interface routes can't match ip next-hop */
436: return RMAP_NOMATCH;
437: case NEXTHOP_TYPE_IPV4_IFINDEX:
438: case NEXTHOP_TYPE_IPV4_IFNAME:
439: case NEXTHOP_TYPE_IPV4:
440: p.family = AF_INET;
441: p.prefix = nexthop->gate.ipv4;
442: p.prefixlen = IPV4_MAX_BITLEN;
443: break;
444: default:
445: return RMAP_NOMATCH;
446: }
447: alist = access_list_lookup (AFI_IP, (char *) rule);
448: if (alist == NULL)
449: return RMAP_NOMATCH;
450:
451: return (access_list_apply (alist, &p) == FILTER_DENY ?
452: RMAP_NOMATCH : RMAP_MATCH);
453: }
454: return RMAP_NOMATCH;
455: }
456:
457: /* Route map `ip next-hop' match statement. `arg' should be
458: access-list name. */
459: static void *
460: route_match_ip_next_hop_compile (const char *arg)
461: {
462: return XSTRDUP (MTYPE_ROUTE_MAP_COMPILED, arg);
463: }
464:
465: /* Free route map's compiled `. */
466: static void
467: route_match_ip_next_hop_free (void *rule)
468: {
469: XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
470: }
471:
472: /* Route map commands for ip next-hop matching. */
473: static struct route_map_rule_cmd route_match_ip_next_hop_cmd =
474: {
475: "ip next-hop",
476: route_match_ip_next_hop,
477: route_match_ip_next_hop_compile,
478: route_match_ip_next_hop_free
479: };
480:
481: /* `match ip next-hop prefix-list PREFIX_LIST' */
482:
483: static route_map_result_t
484: route_match_ip_next_hop_prefix_list (void *rule, struct prefix *prefix,
485: route_map_object_t type, void *object)
486: {
487: struct prefix_list *plist;
488: struct nexthop *nexthop;
489: struct prefix_ipv4 p;
490:
491: if (type == RMAP_ZEBRA)
492: {
493: nexthop = object;
494: switch (nexthop->type) {
495: case NEXTHOP_TYPE_IFINDEX:
496: case NEXTHOP_TYPE_IFNAME:
497: /* Interface routes can't match ip next-hop */
498: return RMAP_NOMATCH;
499: case NEXTHOP_TYPE_IPV4_IFINDEX:
500: case NEXTHOP_TYPE_IPV4_IFNAME:
501: case NEXTHOP_TYPE_IPV4:
502: p.family = AF_INET;
503: p.prefix = nexthop->gate.ipv4;
504: p.prefixlen = IPV4_MAX_BITLEN;
505: break;
506: default:
507: return RMAP_NOMATCH;
508: }
509: plist = prefix_list_lookup (AFI_IP, (char *) rule);
510: if (plist == NULL)
511: return RMAP_NOMATCH;
512:
513: return (prefix_list_apply (plist, &p) == PREFIX_DENY ?
514: RMAP_NOMATCH : RMAP_MATCH);
515: }
516: return RMAP_NOMATCH;
517: }
518:
519: static void *
520: route_match_ip_next_hop_prefix_list_compile (const char *arg)
521: {
522: return XSTRDUP (MTYPE_ROUTE_MAP_COMPILED, arg);
523: }
524:
525: static void
526: route_match_ip_next_hop_prefix_list_free (void *rule)
527: {
528: XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
529: }
530:
531: static struct route_map_rule_cmd route_match_ip_next_hop_prefix_list_cmd =
532: {
533: "ip next-hop prefix-list",
534: route_match_ip_next_hop_prefix_list,
535: route_match_ip_next_hop_prefix_list_compile,
536: route_match_ip_next_hop_prefix_list_free
537: };
538:
539: /* `match ip address IP_ACCESS_LIST' */
540:
541: /* Match function should return 1 if match is success else return
542: zero. */
543: static route_map_result_t
544: route_match_ip_address (void *rule, struct prefix *prefix,
545: route_map_object_t type, void *object)
546: {
547: struct access_list *alist;
548:
549: if (type == RMAP_ZEBRA)
550: {
551: alist = access_list_lookup (AFI_IP, (char *) rule);
552: if (alist == NULL)
553: return RMAP_NOMATCH;
554:
555: return (access_list_apply (alist, prefix) == FILTER_DENY ?
556: RMAP_NOMATCH : RMAP_MATCH);
557: }
558: return RMAP_NOMATCH;
559: }
560:
561: /* Route map `ip address' match statement. `arg' should be
562: access-list name. */
563: static void *
564: route_match_ip_address_compile (const char *arg)
565: {
566: return XSTRDUP (MTYPE_ROUTE_MAP_COMPILED, arg);
567: }
568:
569: /* Free route map's compiled `ip address' value. */
570: static void
571: route_match_ip_address_free (void *rule)
572: {
573: XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
574: }
575:
576: /* Route map commands for ip address matching. */
577: static struct route_map_rule_cmd route_match_ip_address_cmd =
578: {
579: "ip address",
580: route_match_ip_address,
581: route_match_ip_address_compile,
582: route_match_ip_address_free
583: };
584:
585: /* `match ip address prefix-list PREFIX_LIST' */
586:
587: static route_map_result_t
588: route_match_ip_address_prefix_list (void *rule, struct prefix *prefix,
589: route_map_object_t type, void *object)
590: {
591: struct prefix_list *plist;
592:
593: if (type == RMAP_ZEBRA)
594: {
595: plist = prefix_list_lookup (AFI_IP, (char *) rule);
596: if (plist == NULL)
597: return RMAP_NOMATCH;
598:
599: return (prefix_list_apply (plist, prefix) == PREFIX_DENY ?
600: RMAP_NOMATCH : RMAP_MATCH);
601: }
602: return RMAP_NOMATCH;
603: }
604:
605: static void *
606: route_match_ip_address_prefix_list_compile (const char *arg)
607: {
608: return XSTRDUP (MTYPE_ROUTE_MAP_COMPILED, arg);
609: }
610:
611: static void
612: route_match_ip_address_prefix_list_free (void *rule)
613: {
614: XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
615: }
616:
617: static struct route_map_rule_cmd route_match_ip_address_prefix_list_cmd =
618: {
619: "ip address prefix-list",
620: route_match_ip_address_prefix_list,
621: route_match_ip_address_prefix_list_compile,
622: route_match_ip_address_prefix_list_free
623: };
624:
625:
626: /* `set src A.B.C.D' */
627:
628: /* Set src. */
629: static route_map_result_t
630: route_set_src (void *rule, struct prefix *prefix,
631: route_map_object_t type, void *object)
632: {
633: if (type == RMAP_ZEBRA)
634: {
635: struct nexthop *nexthop;
636:
637: nexthop = object;
638: nexthop->src = *(union g_addr *)rule;
639: }
640: return RMAP_OKAY;
641: }
642:
643: /* set src compilation. */
644: static void *
645: route_set_src_compile (const char *arg)
646: {
647: union g_addr src, *psrc;
648:
649: if (inet_pton(AF_INET, arg, &src.ipv4) != 1
650: #ifdef HAVE_IPV6
651: && inet_pton(AF_INET6, arg, &src.ipv6) != 1
652: #endif /* HAVE_IPV6 */
653: )
654: return NULL;
655:
656: psrc = XMALLOC (MTYPE_ROUTE_MAP_COMPILED, sizeof (union g_addr));
657: *psrc = src;
658:
659: return psrc;
660: }
661:
662: /* Free route map's compiled `set src' value. */
663: static void
664: route_set_src_free (void *rule)
665: {
666: XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
667: }
668:
669: /* Set src rule structure. */
670: static struct route_map_rule_cmd route_set_src_cmd =
671: {
672: "src",
673: route_set_src,
674: route_set_src_compile,
675: route_set_src_free,
676: };
677:
678: void
679: zebra_route_map_init ()
680: {
681: route_map_init ();
682: route_map_init_vty ();
683:
684: route_map_install_match (&route_match_interface_cmd);
685: route_map_install_match (&route_match_ip_next_hop_cmd);
686: route_map_install_match (&route_match_ip_next_hop_prefix_list_cmd);
687: route_map_install_match (&route_match_ip_address_cmd);
688: route_map_install_match (&route_match_ip_address_prefix_list_cmd);
689: /* */
690: route_map_install_set (&route_set_src_cmd);
691: /* */
692: install_element (RMAP_NODE, &match_interface_cmd);
693: install_element (RMAP_NODE, &no_match_interface_cmd);
694: install_element (RMAP_NODE, &no_match_interface_val_cmd);
695: install_element (RMAP_NODE, &match_ip_next_hop_cmd);
696: install_element (RMAP_NODE, &no_match_ip_next_hop_cmd);
697: install_element (RMAP_NODE, &no_match_ip_next_hop_val_cmd);
698: install_element (RMAP_NODE, &match_ip_next_hop_prefix_list_cmd);
699: install_element (RMAP_NODE, &no_match_ip_next_hop_prefix_list_cmd);
700: install_element (RMAP_NODE, &no_match_ip_next_hop_prefix_list_val_cmd);
701: install_element (RMAP_NODE, &match_ip_address_cmd);
702: install_element (RMAP_NODE, &no_match_ip_address_cmd);
703: install_element (RMAP_NODE, &no_match_ip_address_val_cmd);
704: install_element (RMAP_NODE, &match_ip_address_prefix_list_cmd);
705: install_element (RMAP_NODE, &no_match_ip_address_prefix_list_cmd);
706: install_element (RMAP_NODE, &no_match_ip_address_prefix_list_val_cmd);
707: /* */
708: install_element (RMAP_NODE, &set_src_cmd);
709: install_element (RMAP_NODE, &no_set_src_cmd);
710: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>