/* * NHRP configuration. * Copyright (c) 2014 Timo Teräs * * This file is free software: you may copy, redistribute and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation, either version 2 of the License, or (at your * option) any later version. * * This file is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ /* quagga's includes */ #include "zebra.h" #include "command.h" #include "zclient.h" #include "stream.h" #include "nhrpd.h" static struct zclient *zclient; static struct cmd_node zebra_node = { ZEBRA_NODE, "%s(config-router)# ", 1 /* vtysh? yes */ }; static struct cmd_node debug_node = { DEBUG_NODE, "", 1 }; static const struct message debug_type[] = { { NHRP_DEBUG_ALL, "all" }, { NHRP_DEBUG_COMMON, "common" }, { NHRP_DEBUG_KERNEL, "kernel" }, { NHRP_DEBUG_ROUTE, "route" }, { 0, NULL }, }; #if 0 /* Zebra route add and delete treatment (ipv6). */ static int babel_zebra_read_ipv6 (int command, struct zclient *zclient, zebra_size_t length) { struct stream *s; struct zapi_ipv6 api; unsigned long ifindex = -1; struct in6_addr nexthop; struct prefix_ipv6 prefix; s = zclient->ibuf; ifindex = 0; memset (&nexthop, 0, sizeof (struct in6_addr)); memset (&api, 0, sizeof(struct zapi_ipv6)); memset (&prefix, 0, sizeof (struct prefix_ipv6)); /* Type, flags, message. */ api.type = stream_getc (s); api.flags = stream_getc (s); api.message = stream_getc (s); /* IPv6 prefix. */ prefix.family = AF_INET6; prefix.prefixlen = stream_getc (s); stream_get (&prefix.prefix, s, PSIZE (prefix.prefixlen)); /* Nexthop, ifindex, distance, metric. */ if (CHECK_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP)) { api.nexthop_num = stream_getc (s); stream_get (&nexthop, s, sizeof(nexthop)); } if (CHECK_FLAG (api.message, ZAPI_MESSAGE_IFINDEX)) { api.ifindex_num = stream_getc (s); ifindex = stream_getl (s); } if (CHECK_FLAG (api.message, ZAPI_MESSAGE_DISTANCE)) api.distance = stream_getc (s); else api.distance = 0; if (CHECK_FLAG (api.message, ZAPI_MESSAGE_METRIC)) api.metric = stream_getl (s); else api.metric = 0; if (command == ZEBRA_IPV6_ROUTE_ADD) babel_ipv6_route_add(&api, &prefix, ifindex, &nexthop); else babel_ipv6_route_delete(&api, &prefix, ifindex); return 0; } static int babel_zebra_read_ipv4 (int command, struct zclient *zclient, zebra_size_t length) { struct stream *s; struct zapi_ipv4 api; unsigned long ifindex = -1; struct in_addr nexthop; struct prefix_ipv4 prefix; s = zclient->ibuf; ifindex = 0; memset (&nexthop, 0, sizeof (struct in_addr)); memset (&api, 0, sizeof(struct zapi_ipv4)); memset (&prefix, 0, sizeof (struct prefix_ipv4)); /* Type, flags, message. */ api.type = stream_getc (s); api.flags = stream_getc (s); api.message = stream_getc (s); /* IPv6 prefix. */ prefix.family = AF_INET; prefix.prefixlen = stream_getc (s); stream_get (&prefix.prefix, s, PSIZE (prefix.prefixlen)); /* Nexthop, ifindex, distance, metric. */ if (CHECK_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP)) { api.nexthop_num = stream_getc (s); stream_get (&nexthop, s, sizeof(nexthop)); } if (CHECK_FLAG (api.message, ZAPI_MESSAGE_IFINDEX)) { api.ifindex_num = stream_getc (s); ifindex = stream_getl (s); } if (CHECK_FLAG (api.message, ZAPI_MESSAGE_DISTANCE)) api.distance = stream_getc (s); else api.distance = 0; if (CHECK_FLAG (api.message, ZAPI_MESSAGE_METRIC)) api.metric = stream_getl (s); else api.metric = 0; if (command == ZEBRA_IPV6_ROUTE_ADD) { babel_ipv4_route_add(&api, &prefix, ifindex, &nexthop); } else { babel_ipv4_route_delete(&api, &prefix, ifindex); } return 0; } /* [NHRP Command] */ DEFUN(nhrp_redistribute_type, nhrp_redistribute_type_cmd, "redistribute " QUAGGA_REDIST_STR_BABELD, "Redistribute\n" QUAGGA_REDIST_HELP_STR_BABELD) { int type; type = proto_redistnum(AFI_IP6, argv[0]); if (type < 0) type = proto_redistnum(AFI_IP, argv[0]); if (type < 0) { vty_out(vty, "Invalid type %s%s", argv[0], VTY_NEWLINE); return CMD_WARNING; } zclient_redistribute(ZEBRA_REDISTRIBUTE_ADD, zclient, type); return CMD_SUCCESS; } /* [Babel Command] */ DEFUN (no_babel_redistribute_type, no_babel_redistribute_type_cmd, "no redistribute " QUAGGA_REDIST_STR_BABELD, NO_STR "Redistribute\n" QUAGGA_REDIST_HELP_STR_BABELD) { int type; type = proto_redistnum(AFI_IP6, argv[0]); if (type < 0) type = proto_redistnum(AFI_IP, argv[0]); if (type < 0) { vty_out(vty, "Invalid type %s%s", argv[0], VTY_NEWLINE); return CMD_WARNING; } zclient_redistribute (ZEBRA_REDISTRIBUTE_DELETE, zclient, type); /* perhaps should we remove xroutes having the same type... */ return CMD_SUCCESS; } #endif #ifndef NO_DEBUG DEFUN(show_debugging_nhrp, show_debugging_nhrp_cmd, "show debugging nhrp", SHOW_STR "Debugging information\n" "NHRP configuration\n") { int i; vty_out(vty, "NHRP debugging status:%s", VTY_NEWLINE); for (i = 0; debug_type[i].str != NULL; i++) { if (debug_type[i].key == NHRP_DEBUG_ALL) continue; if (!(debug_type[i].key & debug_flags)) continue; vty_out(vty, " NHRP %s debugging is on%s", debug_type[i].str, VTY_NEWLINE); } return CMD_SUCCESS; } static int toggle_debug(struct vty *vty, const char *type, int on_off) { int i; for (i = 0; debug_type[i].str != NULL; i++) { if (strcmp(debug_type[i].str, type) != 0) continue; if (on_off) debug_flags |= debug_type[i].key; else debug_flags &= ~debug_type[i].key; return CMD_SUCCESS; } vty_out(vty, "Invalid type %s%s", type, VTY_NEWLINE); return CMD_WARNING; } DEFUN (debug_nhrp, debug_nhrp_cmd, "debug nhrp (common|kernel|route|all)", "Enable debug messages for specific or all parts.\n" "NHRP information\n" "Common messages (default)\n" "Kernel messages\n" "Route messages\n" "All messages\n") { return toggle_debug(vty, argv[0], 1); } DEFUN (no_debug_nhrp, no_debug_nhrp_cmd, "no debug nhrp (common|kernel|route|all)", NO_STR "Disable debug messages for specific or all parts.\n" "NHRP information\n" "Common messages (default)\n" "Kernel messages\n" "Route messages\n" "All messages\n") { return toggle_debug(vty, argv[0], 0); } #endif /* NO_DEBUG */ static int nhrp_config_write(struct vty *vty) { int lines = 0; #ifndef NO_DEBUG if (debug_flags == NHRP_DEBUG_ALL) { vty_out (vty, "debug nhrp all%s", VTY_NEWLINE); lines++; } else { int i; for (i = 0; debug_type[i].str != NULL; i++) { if (debug_type[i].key == NHRP_DEBUG_ALL) continue; if (!(debug_flags & debug_type[i].key)) continue; vty_out (vty, "debug nhrp %s%s", debug_type[i].str, VTY_NEWLINE); lines++; } } #endif /* NO_DEBUG */ if (lines) { vty_out (vty, "!%s", VTY_NEWLINE); lines++; } if (!zclient->enable) { vty_out (vty, "no router zebra%s", VTY_NEWLINE); lines++; } else if (!zclient->redist[ZEBRA_ROUTE_NHRP]) { vty_out(vty, "router zebra%s", VTY_NEWLINE); vty_out(vty, " no redistribute nhrp%s", VTY_NEWLINE); lines += 2; } return lines; } void nhrp_zebra_init(void) { zclient = zclient_new(); #if 0 zclient->interface_add = babel_interface_add; zclient->interface_delete = babel_interface_delete; zclient->interface_up = babel_interface_up; zclient->interface_down = babel_interface_down; zclient->interface_address_add = babel_interface_address_add; zclient->interface_address_delete = babel_interface_address_delete; zclient->ipv4_route_add = babel_zebra_read_ipv4; zclient->ipv4_route_delete = babel_zebra_read_ipv4; zclient->ipv6_route_add = babel_zebra_read_ipv6; zclient->ipv6_route_delete = babel_zebra_read_ipv6; #endif zclient_init(zclient, ZEBRA_ROUTE_NHRP); install_node(&zebra_node, nhrp_config_write); install_default(ZEBRA_NODE); install_element(VIEW_NODE, &show_debugging_nhrp_cmd); install_element(ENABLE_NODE, &show_debugging_nhrp_cmd); install_element(ENABLE_NODE, &debug_nhrp_cmd); install_element(ENABLE_NODE, &no_debug_nhrp_cmd); install_element(CONFIG_NODE, &debug_nhrp_cmd); install_element(CONFIG_NODE, &no_debug_nhrp_cmd); } void nhrp_zebra_terminate(void) { zclient_stop(zclient); }