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