blob: 9b1c69de5bf79ce4194abe85d647d8e9b2c36d67 [file] [log] [blame]
/* NHRP vty handling
* Copyright (c) 2014-2015 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.
*/
#include "zebra.h"
#include "command.h"
#include "zclient.h"
#include "stream.h"
#include "nhrpd.h"
#include "netlink.h"
static struct cmd_node zebra_node = {
.node = ZEBRA_NODE,
.prompt = "%s(config-router)# ",
.vtysh = 1,
};
static struct cmd_node nhrp_interface_node = {
.node = INTERFACE_NODE,
.prompt = "%s(config-if)# ",
.vtysh = 1,
};
#define NHRP_DEBUG_FLAGS_CMD "(all|common|event|interface|kernel|route|vici)"
#define NHRP_DEBUG_FLAGS_STR \
"All messages\n" \
"Common messages (default)\n" \
"Event manager messages\n" \
"Interface messages\n" \
"Kernel messages\n" \
"Route messages\n" \
"VICI messages\n"
static const struct message debug_flags_desc[] = {
{ NHRP_DEBUG_ALL, "all" },
{ NHRP_DEBUG_COMMON, "common" },
{ NHRP_DEBUG_IF, "interface" },
{ NHRP_DEBUG_KERNEL, "kernel" },
{ NHRP_DEBUG_ROUTE, "route" },
{ NHRP_DEBUG_VICI, "vici" },
{ NHRP_DEBUG_EVENT, "event" },
{ 0, NULL },
};
static const struct message interface_flags_desc[] = {
{ NHRP_IFF_SHORTCUT, "shortcut" },
{ NHRP_IFF_REDIRECT, "redirect" },
{ NHRP_IFF_REG_NO_UNIQUE, "registration no-unique" },
{ 0, NULL },
};
static int nhrp_vty_return(struct vty *vty, int ret)
{
static const char * const errmsgs[] = {
[NHRP_ERR_FAIL] = "Command failed",
[NHRP_ERR_NO_MEMORY] = "Out of memory",
[NHRP_ERR_UNSUPPORTED_INTERFACE] = "NHRP not supported on this interface",
[NHRP_ERR_NHRP_NOT_ENABLED] = "NHRP not enabled (set 'nhrp network-id' first)",
[NHRP_ERR_ENTRY_EXISTS] = "Entry exists already",
[NHRP_ERR_ENTRY_NOT_FOUND] = "Entry not found",
[NHRP_ERR_PROTOCOL_ADDRESS_MISMATCH] = "Protocol address family does not match command (ip/ipv6 mismatch)",
};
const char *str = NULL;
char buf[256];
if (ret == NHRP_OK)
return CMD_SUCCESS;
if (ret > 0 && ret <= (int)ZEBRA_NUM_OF(errmsgs))
if (errmsgs[ret])
str = errmsgs[ret];
if (!str) {
str = buf;
snprintf(buf, sizeof(buf), "Unknown error %d", ret);
}
vty_out (vty, "%% %s%s", str, VTY_NEWLINE);
return CMD_WARNING;
}
static int toggle_flag(
struct vty *vty, const struct message *flag_desc,
const char *name, int on_off, unsigned *flags)
{
int i;
for (i = 0; flag_desc[i].str != NULL; i++) {
if (strcmp(flag_desc[i].str, name) != 0)
continue;
if (on_off)
*flags |= flag_desc[i].key;
else
*flags &= ~flag_desc[i].key;
return CMD_SUCCESS;
}
vty_out(vty, "%% Invalid value %s%s", name, VTY_NEWLINE);
return CMD_WARNING;
}
#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_flags_desc[i].str != NULL; i++) {
if (debug_flags_desc[i].key == NHRP_DEBUG_ALL)
continue;
if (!(debug_flags_desc[i].key & debug_flags))
continue;
vty_out(vty, " NHRP %s debugging is on%s",
debug_flags_desc[i].str, VTY_NEWLINE);
}
return CMD_SUCCESS;
}
DEFUN(debug_nhrp, debug_nhrp_cmd,
"debug nhrp " NHRP_DEBUG_FLAGS_CMD,
"Enable debug messages for specific or all parts.\n"
"NHRP information\n"
NHRP_DEBUG_FLAGS_STR)
{
return toggle_flag(vty, debug_flags_desc, argv[0], 1, &debug_flags);
}
DEFUN(no_debug_nhrp, no_debug_nhrp_cmd,
"no debug nhrp " NHRP_DEBUG_FLAGS_CMD,
NO_STR
"Disable debug messages for specific or all parts.\n"
"NHRP information\n"
NHRP_DEBUG_FLAGS_STR)
{
return toggle_flag(vty, debug_flags_desc, argv[0], 0, &debug_flags);
}
#endif /* NO_DEBUG */
static int nhrp_config_write(struct vty *vty)
{
#ifndef NO_DEBUG
if (debug_flags == NHRP_DEBUG_ALL) {
vty_out(vty, "debug nhrp all%s", VTY_NEWLINE);
} else {
int i;
for (i = 0; debug_flags_desc[i].str != NULL; i++) {
if (debug_flags_desc[i].key == NHRP_DEBUG_ALL)
continue;
if (!(debug_flags & debug_flags_desc[i].key))
continue;
vty_out(vty, "debug nhrp %s%s", debug_flags_desc[i].str, VTY_NEWLINE);
}
}
vty_out(vty, "!%s", VTY_NEWLINE);
#endif /* NO_DEBUG */
if (nhrp_event_socket_path) {
vty_out(vty, "nhrp event socket %s%s",
nhrp_event_socket_path, VTY_NEWLINE);
}
if (netlink_nflog_group) {
vty_out(vty, "nhrp nflog-group %d%s",
netlink_nflog_group, VTY_NEWLINE);
}
return 0;
}
#define IP_STR "IP information\n"
#define IPV6_STR "IPv6 information\n"
#define AFI_CMD "(ip|ipv6)"
#define AFI_STR IP_STR IPV6_STR
#define NHRP_STR "Next Hop Resolution Protocol functions\n"
static afi_t cmd_to_afi(const char *cmd)
{
return strncmp(cmd, "ipv6", 4) == 0 ? AFI_IP6 : AFI_IP;
}
static const char *afi_to_cmd(afi_t afi)
{
if (afi == AFI_IP6) return "ipv6";
return "ip";
}
DEFUN(nhrp_event_socket, nhrp_event_socket_cmd,
"nhrp event socket SOCKET",
NHRP_STR
"Event Manager commands\n"
"Event Manager unix socket path\n"
"Unix path for the socket")
{
evmgr_set_socket(argv[0]);
return CMD_SUCCESS;
}
DEFUN(no_nhrp_event_socket, no_nhrp_event_socket_cmd,
"no nhrp event socket [SOCKET]",
NO_STR
NHRP_STR
"Event Manager commands\n"
"Event Manager unix socket path\n"
"Unix path for the socket")
{
evmgr_set_socket(NULL);
return CMD_SUCCESS;
}
DEFUN(nhrp_nflog_group, nhrp_nflog_group_cmd,
"nhrp nflog-group <1-65535>",
NHRP_STR
"Specify NFLOG group number\n"
"NFLOG group number\n")
{
uint32_t nfgroup;
VTY_GET_INTEGER_RANGE("nflog-group", nfgroup, argv[0], 1, 65535);
netlink_set_nflog_group(nfgroup);
return CMD_SUCCESS;
}
DEFUN(no_nhrp_nflog_group, no_nhrp_nflog_group_cmd,
"no nhrp nflog-group [<1-65535>]",
NO_STR
NHRP_STR
"Specify NFLOG group number\n"
"NFLOG group number\n")
{
netlink_set_nflog_group(0);
return CMD_SUCCESS;
}
DEFUN(tunnel_protection, tunnel_protection_cmd,
"tunnel protection vici profile PROFILE {fallback-profile FALLBACK}",
"NHRP/GRE integration\n"
"IPsec protection\n"
"VICI (StrongSwan)\n"
"IPsec profile\n"
"IPsec profile name\n"
"Fallback IPsec profile\n"
"Fallback IPsec profile name\n")
{
struct interface *ifp = vty->index;
nhrp_interface_set_protection(ifp, argv[0], argv[1]);
return CMD_SUCCESS;
}
DEFUN(no_tunnel_protection, no_tunnel_protection_cmd,
"no tunnel protection",
NO_STR
"NHRP/GRE integration\n"
"IPsec protection\n")
{
struct interface *ifp = vty->index;
nhrp_interface_set_protection(ifp, NULL, NULL);
return CMD_SUCCESS;
}
DEFUN(tunnel_source, tunnel_source_cmd,
"tunnel source INTERFACE",
"NHRP/GRE integration\n"
"Tunnel device binding tracking\n"
"Interface name\n")
{
struct interface *ifp = vty->index;
nhrp_interface_set_source(ifp, argv[0]);
return CMD_SUCCESS;
}
DEFUN(no_tunnel_source, no_tunnel_source_cmd,
"no tunnel source",
"NHRP/GRE integration\n"
"Tunnel device binding tracking\n"
"Interface name\n")
{
struct interface *ifp = vty->index;
nhrp_interface_set_source(ifp, NULL);
return CMD_SUCCESS;
}
DEFUN(if_nhrp_network_id, if_nhrp_network_id_cmd,
AFI_CMD " nhrp network-id <1-4294967295>",
AFI_STR
NHRP_STR
"Enable NHRP and specify network-id\n"
"System local ID to specify interface group\n")
{
struct interface *ifp = vty->index;
struct nhrp_interface *nifp = ifp->info;
afi_t afi = cmd_to_afi(argv[0]);
VTY_GET_INTEGER_RANGE("network-id", nifp->afi[afi].network_id, argv[1], 1, 4294967295);
nhrp_interface_update(ifp);
return CMD_SUCCESS;
}
DEFUN(if_no_nhrp_network_id, if_no_nhrp_network_id_cmd,
"no " AFI_CMD " nhrp network-id [<1-4294967295>]",
NO_STR
AFI_STR
NHRP_STR
"Enable NHRP and specify network-id\n"
"System local ID to specify interface group\n")
{
struct interface *ifp = vty->index;
struct nhrp_interface *nifp = ifp->info;
afi_t afi = cmd_to_afi(argv[0]);
nifp->afi[afi].network_id = 0;
nhrp_interface_update(ifp);
return CMD_SUCCESS;
}
DEFUN(if_nhrp_flags, if_nhrp_flags_cmd,
AFI_CMD " nhrp (shortcut|redirect)",
AFI_STR
NHRP_STR
"Allow shortcut establishment\n"
"Send redirect notifications\n")
{
struct interface *ifp = vty->index;
struct nhrp_interface *nifp = ifp->info;
afi_t afi = cmd_to_afi(argv[0]);
return toggle_flag(vty, interface_flags_desc, argv[1], 1, &nifp->afi[afi].flags);
}
DEFUN(if_no_nhrp_flags, if_no_nhrp_flags_cmd,
"no " AFI_CMD " nhrp (shortcut|redirect)",
NO_STR
AFI_STR
NHRP_STR
"Allow shortcut establishment\n"
"Send redirect notifications\n")
{
struct interface *ifp = vty->index;
struct nhrp_interface *nifp = ifp->info;
afi_t afi = cmd_to_afi(argv[0]);
return toggle_flag(vty, interface_flags_desc, argv[1], 0, &nifp->afi[afi].flags);
}
DEFUN(if_nhrp_reg_flags, if_nhrp_reg_flags_cmd,
AFI_CMD " nhrp registration (no-unique)",
AFI_STR
NHRP_STR
"Registration configuration\n"
"Don't set unique flag\n")
{
struct interface *ifp = vty->index;
struct nhrp_interface *nifp = ifp->info;
afi_t afi = cmd_to_afi(argv[0]);
char name[256];
snprintf(name, sizeof(name), "registration %s", argv[1]);
return toggle_flag(vty, interface_flags_desc, name, 1, &nifp->afi[afi].flags);
}
DEFUN(if_no_nhrp_reg_flags, if_no_nhrp_reg_flags_cmd,
"no " AFI_CMD " nhrp registration (no-unique)",
NO_STR
AFI_STR
NHRP_STR
"Registration configuration\n"
"Don't set unique flag\n")
{
struct interface *ifp = vty->index;
struct nhrp_interface *nifp = ifp->info;
afi_t afi = cmd_to_afi(argv[0]);
char name[256];
snprintf(name, sizeof(name), "registration %s", argv[1]);
return toggle_flag(vty, interface_flags_desc, name, 0, &nifp->afi[afi].flags);
}
DEFUN(if_nhrp_holdtime, if_nhrp_holdtime_cmd,
AFI_CMD " nhrp holdtime <1-65000>",
AFI_STR
NHRP_STR
"Specify NBMA address validity time\n"
"Time in seconds that NBMA addresses are advertised valid\n")
{
struct interface *ifp = vty->index;
struct nhrp_interface *nifp = ifp->info;
afi_t afi = cmd_to_afi(argv[0]);
VTY_GET_INTEGER_RANGE("holdtime", nifp->afi[afi].holdtime, argv[1], 1, 65000);
nhrp_interface_update(ifp);
return CMD_SUCCESS;
}
DEFUN(if_no_nhrp_holdtime, if_no_nhrp_holdtime_cmd,
"no " AFI_CMD " nhrp holdtime [1-65000]",
NO_STR
AFI_STR
NHRP_STR
"Specify NBMA address validity time\n"
"Time in seconds that NBMA addresses are advertised valid\n")
{
struct interface *ifp = vty->index;
struct nhrp_interface *nifp = ifp->info;
afi_t afi = cmd_to_afi(argv[0]);
nifp->afi[afi].holdtime = NHRPD_DEFAULT_HOLDTIME;
nhrp_interface_update(ifp);
return CMD_SUCCESS;
}
DEFUN(if_nhrp_mtu, if_nhrp_mtu_cmd,
"ip nhrp mtu (<576-1500>|opennhrp)",
IP_STR
NHRP_STR
"Configure NHRP advertised MTU\n"
"MTU value\n"
"Advertise bound interface MTU similar to OpenNHRP")
{
struct interface *ifp = vty->index;
struct nhrp_interface *nifp = ifp->info;
if (argv[0][0] == 'o') {
nifp->afi[AFI_IP].configured_mtu = -1;
} else {
VTY_GET_INTEGER_RANGE("mtu", nifp->afi[AFI_IP].configured_mtu, argv[0], 576, 1500);
}
nhrp_interface_update_mtu(ifp, AFI_IP);
return CMD_SUCCESS;
}
DEFUN(if_no_nhrp_mtu, if_no_nhrp_mtu_cmd,
"no ip nhrp mtu [(<576-1500>|opennhrp)]",
NO_STR
IP_STR
NHRP_STR
"Configure NHRP advertised MTU\n"
"MTU value\n"
"Advertise bound interface MTU similar to OpenNHRP")
{
struct interface *ifp = vty->index;
struct nhrp_interface *nifp = ifp->info;
nifp->afi[AFI_IP].configured_mtu = 0;
nhrp_interface_update_mtu(ifp, AFI_IP);
return CMD_SUCCESS;
}
DEFUN(if_nhrp_map, if_nhrp_map_cmd,
AFI_CMD " nhrp map (A.B.C.D|X:X::X:X) (A.B.C.D|local)",
AFI_STR
NHRP_STR
"Nexthop Server configuration\n"
"IPv4 protocol address\n"
"IPv6 protocol address\n"
"IPv4 NBMA address\n"
"Handle protocol address locally\n")
{
struct interface *ifp = vty->index;
afi_t afi = cmd_to_afi(argv[0]);
union sockunion proto_addr, nbma_addr;
struct nhrp_cache *c;
if (str2sockunion(argv[1], &proto_addr) < 0 ||
afi2family(afi) != sockunion_family(&proto_addr))
return nhrp_vty_return(vty, NHRP_ERR_PROTOCOL_ADDRESS_MISMATCH);
c = nhrp_cache_get(ifp, &proto_addr, 1);
if (!c)
return nhrp_vty_return(vty, NHRP_ERR_FAIL);
c->map = 1;
if (strcmp(argv[2], "local") == 0) {
nhrp_cache_update_binding(c, NHRP_CACHE_LOCAL, 0, NULL, 0, NULL);
} else{
if (str2sockunion(argv[2], &nbma_addr) < 0)
return nhrp_vty_return(vty, NHRP_ERR_FAIL);
nhrp_cache_update_binding(c, NHRP_CACHE_STATIC, 0,
nhrp_peer_get(ifp, &nbma_addr), 0, NULL);
}
return CMD_SUCCESS;
}
DEFUN(if_nhrp_nhs, if_nhrp_nhs_cmd,
AFI_CMD " nhrp nhs (A.B.C.D|X:X::X:X|dynamic) nbma (A.B.C.D|FQDN)",
AFI_STR
NHRP_STR
"Nexthop Server configuration\n"
"IPv4 protocol address\n"
"IPv6 protocol address\n"
"Automatic detection of protocol address\n"
"IPv4 NBMA address\n"
"Fully qualified domain name for NBMA address(es)\n")
{
struct interface *ifp = vty->index;
afi_t afi = cmd_to_afi(argv[0]);
union sockunion proto_addr;
int ret;
if (str2sockunion(argv[1], &proto_addr) < 0)
sockunion_family(&proto_addr) = AF_UNSPEC;
ret = nhrp_nhs_add(ifp, afi, &proto_addr, argv[2]);
return nhrp_vty_return(vty, ret);
}
DEFUN(if_no_nhrp_nhs, if_no_nhrp_nhs_cmd,
"no " AFI_CMD " nhrp nhs (A.B.C.D|X:X::X:X|dynamic) nbma (A.B.C.D|FQDN)",
NO_STR
AFI_STR
NHRP_STR
"Nexthop Server configuration\n"
"IPv4 protocol address\n"
"IPv6 protocol address\n"
"Automatic detection of protocol address\n"
"IPv4 NBMA address\n"
"Fully qualified domain name for NBMA address(es)\n")
{
struct interface *ifp = vty->index;
afi_t afi = cmd_to_afi(argv[0]);
union sockunion proto_addr;
int ret;
if (str2sockunion(argv[1], &proto_addr) < 0)
sockunion_family(&proto_addr) = AF_UNSPEC;
ret = nhrp_nhs_del(ifp, afi, &proto_addr, argv[2]);
return nhrp_vty_return(vty, ret);
}
struct info_ctx {
struct vty *vty;
afi_t afi;
int count;
};
static void show_ip_nhrp_cache(struct nhrp_cache *c, void *pctx)
{
struct info_ctx *ctx = pctx;
struct vty *vty = ctx->vty;
char buf[2][SU_ADDRSTRLEN];
if (ctx->afi != family2afi(sockunion_family(&c->remote_addr)))
return;
if (!ctx->count) {
vty_out(vty, "%-8s %-8s %-24s %-24s %-6s %s%s",
"Iface",
"Type",
"Protocol",
"NBMA",
"Flags",
"Identity",
VTY_NEWLINE);
}
ctx->count++;
vty_out(ctx->vty, "%-8s %-8s %-24s %-24s %c%c%c %s%s",
c->ifp->name,
nhrp_cache_type_str[c->cur.type],
sockunion2str(&c->remote_addr, buf[0], sizeof buf[0]),
c->cur.peer ? sockunion2str(&c->cur.peer->vc->remote.nbma, buf[1], sizeof buf[1]) : "-",
c->used ? 'U' : ' ',
c->t_timeout ? 'T' : ' ',
c->t_auth ? 'A' : ' ',
c->cur.peer ? c->cur.peer->vc->remote.id : "-",
VTY_NEWLINE);
}
static void show_ip_opennhrp_cache(struct nhrp_cache *c, void *pctx)
{
struct info_ctx *ctx = pctx;
struct vty *vty = ctx->vty;
char buf[SU_ADDRSTRLEN];
if (ctx->afi != family2afi(sockunion_family(&c->remote_addr)))
return;
vty_out(ctx->vty,
"Type: %s%s"
"Flags:%s%s%s"
"Protocol-Address: %s/%zu%s",
nhrp_cache_type_str[c->cur.type],
VTY_NEWLINE,
(c->cur.peer && c->cur.peer->online) ? " up": "",
c->used ? " used": "",
VTY_NEWLINE,
sockunion2str(&c->remote_addr, buf, sizeof buf),
8 * family2addrsize(sockunion_family(&c->remote_addr)),
VTY_NEWLINE);
if (c->cur.peer) {
vty_out(ctx->vty,
"NBMA-Address: %s%s",
sockunion2str(&c->cur.peer->vc->remote.nbma, buf, sizeof buf),
VTY_NEWLINE);
}
if (sockunion_family(&c->cur.remote_nbma_natoa) != AF_UNSPEC) {
vty_out(ctx->vty,
"NBMA-NAT-OA-Address: %s%s",
sockunion2str(&c->cur.remote_nbma_natoa, buf, sizeof buf),
VTY_NEWLINE);
}
vty_out(ctx->vty, "%s", VTY_NEWLINE);
}
static void show_ip_nhrp_shortcut(struct nhrp_shortcut *s, void *pctx)
{
struct info_ctx *ctx = pctx;
struct nhrp_cache *c;
struct vty *vty = ctx->vty;
char buf1[PREFIX_STRLEN], buf2[SU_ADDRSTRLEN];
if (!ctx->count) {
vty_out(vty, "%-8s %-24s %-24s %s%s",
"Type",
"Prefix",
"Via",
"Identity",
VTY_NEWLINE);
}
ctx->count++;
c = s->cache;
vty_out(ctx->vty, "%-8s %-24s %-24s %s%s",
nhrp_cache_type_str[s->type],
prefix2str(s->p, buf1, sizeof buf1),
c ? sockunion2str(&c->remote_addr, buf2, sizeof buf2) : "",
(c && c->cur.peer) ? c->cur.peer->vc->remote.id : "",
VTY_NEWLINE);
}
DEFUN(show_ip_nhrp, show_ip_nhrp_cmd,
"show " AFI_CMD " nhrp (cache|shortcut|opennhrp|)",
SHOW_STR
AFI_STR
"NHRP information\n"
"Forwarding cache information\n"
"Shortcut information\n"
"opennhrpctl style cache dump\n")
{
struct listnode *node;
struct interface *ifp;
struct info_ctx ctx = {
.vty = vty,
.afi = cmd_to_afi(argv[0]),
};
if (!argv[1] || argv[1][0] == 'c') {
for (ALL_LIST_ELEMENTS_RO(iflist, node, ifp))
nhrp_cache_foreach(ifp, show_ip_nhrp_cache, &ctx);
} else if (argv[1][0] == 'o') {
vty_out(vty, "Status: ok%s%s", VTY_NEWLINE, VTY_NEWLINE);
ctx.count++;
for (ALL_LIST_ELEMENTS_RO(iflist, node, ifp))
nhrp_cache_foreach(ifp, show_ip_opennhrp_cache, &ctx);
} else {
nhrp_shortcut_foreach(ctx.afi, show_ip_nhrp_shortcut, &ctx);
}
if (!ctx.count) {
vty_out(vty, "%% No entries%s", VTY_NEWLINE);
return CMD_WARNING;
}
return CMD_SUCCESS;
}
static void show_dmvpn_entry(struct nhrp_vc *vc, void *ctx)
{
struct vty *vty = ctx;
char buf[2][SU_ADDRSTRLEN];
vty_out(vty, "%-24s %-24s %c %-4d %-24s%s",
sockunion2str(&vc->local.nbma, buf[0], sizeof buf[0]),
sockunion2str(&vc->remote.nbma, buf[1], sizeof buf[1]),
notifier_active(&vc->notifier_list) ? 'n' : ' ',
vc->ipsec,
vc->remote.id,
VTY_NEWLINE);
}
DEFUN(show_dmvpn, show_dmvpn_cmd,
"show dmvpn",
SHOW_STR
"DMVPN information\n")
{
vty_out(vty, "%-24s %-24s %-6s %-4s %-24s%s",
"Src",
"Dst",
"Flags",
"SAs",
"Identity",
VTY_NEWLINE);
nhrp_vc_foreach(show_dmvpn_entry, vty);
return CMD_SUCCESS;
}
static void clear_nhrp_cache(struct nhrp_cache *c, void *data)
{
struct info_ctx *ctx = data;
if (c->cur.type <= NHRP_CACHE_CACHED) {
nhrp_cache_update_binding(c, c->cur.type, -1, NULL, 0, NULL);
ctx->count++;
}
}
static void clear_nhrp_shortcut(struct nhrp_shortcut *s, void *data)
{
struct info_ctx *ctx = data;
nhrp_shortcut_purge(s, 1);
ctx->count++;
}
DEFUN(clear_nhrp, clear_nhrp_cmd,
"clear " AFI_CMD " nhrp (cache|shortcut)",
CLEAR_STR
AFI_STR
NHRP_STR
"Dynamic cache entries\n"
"Shortcut entries\n")
{
struct listnode *node;
struct interface *ifp;
struct info_ctx ctx = {
.vty = vty,
.afi = cmd_to_afi(argv[0]),
.count = 0,
};
if (!argv[1] || argv[1][0] == 'c') {
for (ALL_LIST_ELEMENTS_RO(iflist, node, ifp))
nhrp_cache_foreach(ifp, clear_nhrp_cache, &ctx);
} else {
nhrp_shortcut_foreach(ctx.afi, clear_nhrp_shortcut, &ctx);
}
if (!ctx.count) {
vty_out(vty, "%% No entries%s", VTY_NEWLINE);
return CMD_WARNING;
}
vty_out(vty, "%% %d entries cleared%s", ctx.count, VTY_NEWLINE);
return CMD_SUCCESS;
}
struct write_map_ctx {
struct vty *vty;
int family;
const char *aficmd;
};
static void interface_config_write_nhrp_map(struct nhrp_cache *c, void *data)
{
struct write_map_ctx *ctx = data;
struct vty *vty = ctx->vty;
char buf[2][SU_ADDRSTRLEN];
if (!c->map) return;
if (sockunion_family(&c->remote_addr) != ctx->family) return;
vty_out(vty, " %s nhrp map %s %s%s",
ctx->aficmd,
sockunion2str(&c->remote_addr, buf[0], sizeof buf[0]),
c->cur.type == NHRP_CACHE_LOCAL ? "local" :
sockunion2str(&c->cur.peer->vc->remote.nbma, buf[1], sizeof buf[1]),
VTY_NEWLINE);
}
static int interface_config_write(struct vty *vty)
{
struct write_map_ctx mapctx;
struct listnode *node;
struct interface *ifp;
struct nhrp_interface *nifp;
struct nhrp_nhs *nhs;
const char *aficmd;
afi_t afi;
char buf[SU_ADDRSTRLEN];
int i;
for (ALL_LIST_ELEMENTS_RO(iflist, node, ifp)) {
vty_out(vty, "interface %s%s", ifp->name, VTY_NEWLINE);
if (ifp->desc)
vty_out(vty, " description %s%s", ifp->desc, VTY_NEWLINE);
nifp = ifp->info;
if (nifp->ipsec_profile) {
vty_out(vty, " tunnel protection vici profile %s",
nifp->ipsec_profile);
if (nifp->ipsec_fallback_profile)
vty_out(vty, " fallback-profile %s",
nifp->ipsec_fallback_profile);
vty_out(vty, "%s", VTY_NEWLINE);
}
if (nifp->source)
vty_out(vty, " tunnel source %s%s",
nifp->source, VTY_NEWLINE);
for (afi = 0; afi < AFI_MAX; afi++) {
struct nhrp_afi_data *ad = &nifp->afi[afi];
aficmd = afi_to_cmd(afi);
if (ad->network_id)
vty_out(vty, " %s nhrp network-id %u%s",
aficmd, ad->network_id,
VTY_NEWLINE);
if (ad->holdtime != NHRPD_DEFAULT_HOLDTIME)
vty_out(vty, " %s nhrp holdtime %u%s",
aficmd, ad->holdtime,
VTY_NEWLINE);
if (ad->configured_mtu < 0)
vty_out(vty, " %s nhrp mtu opennhrp%s",
aficmd, VTY_NEWLINE);
else if (ad->configured_mtu)
vty_out(vty, " %s nhrp mtu %u%s",
aficmd, ad->configured_mtu,
VTY_NEWLINE);
for (i = 0; interface_flags_desc[i].str != NULL; i++) {
if (!(ad->flags & interface_flags_desc[i].key))
continue;
vty_out(vty, " %s nhrp %s%s",
aficmd, interface_flags_desc[i].str, VTY_NEWLINE);
}
mapctx = (struct write_map_ctx) {
.vty = vty,
.family = afi2family(afi),
.aficmd = aficmd,
};
nhrp_cache_foreach(ifp, interface_config_write_nhrp_map, &mapctx);
list_for_each_entry(nhs, &ad->nhslist_head, nhslist_entry) {
vty_out(vty, " %s nhrp nhs %s nbma %s%s",
aficmd,
sockunion_family(&nhs->proto_addr) == AF_UNSPEC ? "dynamic" : sockunion2str(&nhs->proto_addr, buf, sizeof buf),
nhs->nbma_fqdn,
VTY_NEWLINE);
}
}
vty_out (vty, "!%s", VTY_NEWLINE);
}
return 0;
}
void nhrp_config_init(void)
{
install_node(&zebra_node, nhrp_config_write);
install_default(ZEBRA_NODE);
/* global commands */
install_element(VIEW_NODE, &show_debugging_nhrp_cmd);
install_element(VIEW_NODE, &show_ip_nhrp_cmd);
install_element(VIEW_NODE, &show_dmvpn_cmd);
install_element(ENABLE_NODE, &show_debugging_nhrp_cmd);
install_element(ENABLE_NODE, &show_ip_nhrp_cmd);
install_element(ENABLE_NODE, &show_dmvpn_cmd);
install_element(ENABLE_NODE, &clear_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);
install_element(CONFIG_NODE, &nhrp_event_socket_cmd);
install_element(CONFIG_NODE, &no_nhrp_event_socket_cmd);
install_element(CONFIG_NODE, &nhrp_nflog_group_cmd);
install_element(CONFIG_NODE, &no_nhrp_nflog_group_cmd);
/* interface specific commands */
install_node(&nhrp_interface_node, interface_config_write);
install_default(INTERFACE_NODE);
install_element(CONFIG_NODE, &interface_cmd);
install_element(CONFIG_NODE, &no_interface_cmd);
install_element(INTERFACE_NODE, &interface_cmd);
install_element(INTERFACE_NODE, &no_interface_cmd);
install_element(INTERFACE_NODE, &tunnel_protection_cmd);
install_element(INTERFACE_NODE, &no_tunnel_protection_cmd);
install_element(INTERFACE_NODE, &tunnel_source_cmd);
install_element(INTERFACE_NODE, &no_tunnel_source_cmd);
install_element(INTERFACE_NODE, &if_nhrp_network_id_cmd);
install_element(INTERFACE_NODE, &if_no_nhrp_network_id_cmd);
install_element(INTERFACE_NODE, &if_nhrp_holdtime_cmd);
install_element(INTERFACE_NODE, &if_no_nhrp_holdtime_cmd);
install_element(INTERFACE_NODE, &if_nhrp_mtu_cmd);
install_element(INTERFACE_NODE, &if_no_nhrp_mtu_cmd);
install_element(INTERFACE_NODE, &if_nhrp_flags_cmd);
install_element(INTERFACE_NODE, &if_no_nhrp_flags_cmd);
install_element(INTERFACE_NODE, &if_nhrp_reg_flags_cmd);
install_element(INTERFACE_NODE, &if_no_nhrp_reg_flags_cmd);
install_element(INTERFACE_NODE, &if_nhrp_map_cmd);
install_element(INTERFACE_NODE, &if_nhrp_nhs_cmd);
install_element(INTERFACE_NODE, &if_no_nhrp_nhs_cmd);
}