blob: 9b1c69de5bf79ce4194abe85d647d8e9b2c36d67 [file] [log] [blame]
Timo Teräsdafa05e2017-01-19 17:27:01 +02001/* NHRP vty handling
2 * Copyright (c) 2014-2015 Timo Teräs
3 *
4 * This file is free software: you may copy, redistribute and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation, either version 2 of the License, or
7 * (at your option) any later version.
8 */
9
10#include "zebra.h"
11#include "command.h"
12#include "zclient.h"
13#include "stream.h"
14
15#include "nhrpd.h"
16#include "netlink.h"
17
18static struct cmd_node zebra_node = {
19 .node = ZEBRA_NODE,
20 .prompt = "%s(config-router)# ",
21 .vtysh = 1,
22};
23
24static struct cmd_node nhrp_interface_node = {
25 .node = INTERFACE_NODE,
26 .prompt = "%s(config-if)# ",
27 .vtysh = 1,
28};
29
30#define NHRP_DEBUG_FLAGS_CMD "(all|common|event|interface|kernel|route|vici)"
31
32#define NHRP_DEBUG_FLAGS_STR \
33 "All messages\n" \
34 "Common messages (default)\n" \
35 "Event manager messages\n" \
36 "Interface messages\n" \
37 "Kernel messages\n" \
38 "Route messages\n" \
39 "VICI messages\n"
40
41static const struct message debug_flags_desc[] = {
42 { NHRP_DEBUG_ALL, "all" },
43 { NHRP_DEBUG_COMMON, "common" },
44 { NHRP_DEBUG_IF, "interface" },
45 { NHRP_DEBUG_KERNEL, "kernel" },
46 { NHRP_DEBUG_ROUTE, "route" },
47 { NHRP_DEBUG_VICI, "vici" },
48 { NHRP_DEBUG_EVENT, "event" },
49 { 0, NULL },
50};
51
52static const struct message interface_flags_desc[] = {
53 { NHRP_IFF_SHORTCUT, "shortcut" },
54 { NHRP_IFF_REDIRECT, "redirect" },
55 { NHRP_IFF_REG_NO_UNIQUE, "registration no-unique" },
56 { 0, NULL },
57};
58
59static int nhrp_vty_return(struct vty *vty, int ret)
60{
61 static const char * const errmsgs[] = {
62 [NHRP_ERR_FAIL] = "Command failed",
63 [NHRP_ERR_NO_MEMORY] = "Out of memory",
64 [NHRP_ERR_UNSUPPORTED_INTERFACE] = "NHRP not supported on this interface",
65 [NHRP_ERR_NHRP_NOT_ENABLED] = "NHRP not enabled (set 'nhrp network-id' first)",
66 [NHRP_ERR_ENTRY_EXISTS] = "Entry exists already",
67 [NHRP_ERR_ENTRY_NOT_FOUND] = "Entry not found",
68 [NHRP_ERR_PROTOCOL_ADDRESS_MISMATCH] = "Protocol address family does not match command (ip/ipv6 mismatch)",
69 };
70 const char *str = NULL;
71 char buf[256];
72
73 if (ret == NHRP_OK)
74 return CMD_SUCCESS;
75
76 if (ret > 0 && ret <= (int)ZEBRA_NUM_OF(errmsgs))
77 if (errmsgs[ret])
78 str = errmsgs[ret];
79
80 if (!str) {
81 str = buf;
82 snprintf(buf, sizeof(buf), "Unknown error %d", ret);
83 }
84
85 vty_out (vty, "%% %s%s", str, VTY_NEWLINE);
86
87 return CMD_WARNING;
88}
89
90static int toggle_flag(
91 struct vty *vty, const struct message *flag_desc,
92 const char *name, int on_off, unsigned *flags)
93{
94 int i;
95
96 for (i = 0; flag_desc[i].str != NULL; i++) {
97 if (strcmp(flag_desc[i].str, name) != 0)
98 continue;
99 if (on_off)
100 *flags |= flag_desc[i].key;
101 else
102 *flags &= ~flag_desc[i].key;
103 return CMD_SUCCESS;
104 }
105
106 vty_out(vty, "%% Invalid value %s%s", name, VTY_NEWLINE);
107 return CMD_WARNING;
108}
109
110#ifndef NO_DEBUG
111
112DEFUN(show_debugging_nhrp, show_debugging_nhrp_cmd,
113 "show debugging nhrp",
114 SHOW_STR
115 "Debugging information\n"
116 "NHRP configuration\n")
117{
118 int i;
119
120 vty_out(vty, "NHRP debugging status:%s", VTY_NEWLINE);
121
122 for (i = 0; debug_flags_desc[i].str != NULL; i++) {
123 if (debug_flags_desc[i].key == NHRP_DEBUG_ALL)
124 continue;
125 if (!(debug_flags_desc[i].key & debug_flags))
126 continue;
127
128 vty_out(vty, " NHRP %s debugging is on%s",
129 debug_flags_desc[i].str, VTY_NEWLINE);
130 }
131
132 return CMD_SUCCESS;
133}
134
135DEFUN(debug_nhrp, debug_nhrp_cmd,
136 "debug nhrp " NHRP_DEBUG_FLAGS_CMD,
137 "Enable debug messages for specific or all parts.\n"
138 "NHRP information\n"
139 NHRP_DEBUG_FLAGS_STR)
140{
141 return toggle_flag(vty, debug_flags_desc, argv[0], 1, &debug_flags);
142}
143
144DEFUN(no_debug_nhrp, no_debug_nhrp_cmd,
145 "no debug nhrp " NHRP_DEBUG_FLAGS_CMD,
146 NO_STR
147 "Disable debug messages for specific or all parts.\n"
148 "NHRP information\n"
149 NHRP_DEBUG_FLAGS_STR)
150{
151 return toggle_flag(vty, debug_flags_desc, argv[0], 0, &debug_flags);
152}
153
154#endif /* NO_DEBUG */
155
156static int nhrp_config_write(struct vty *vty)
157{
158#ifndef NO_DEBUG
159 if (debug_flags == NHRP_DEBUG_ALL) {
160 vty_out(vty, "debug nhrp all%s", VTY_NEWLINE);
161 } else {
162 int i;
163
164 for (i = 0; debug_flags_desc[i].str != NULL; i++) {
165 if (debug_flags_desc[i].key == NHRP_DEBUG_ALL)
166 continue;
167 if (!(debug_flags & debug_flags_desc[i].key))
168 continue;
169 vty_out(vty, "debug nhrp %s%s", debug_flags_desc[i].str, VTY_NEWLINE);
170 }
171 }
172 vty_out(vty, "!%s", VTY_NEWLINE);
173#endif /* NO_DEBUG */
174
175 if (nhrp_event_socket_path) {
176 vty_out(vty, "nhrp event socket %s%s",
177 nhrp_event_socket_path, VTY_NEWLINE);
178 }
179 if (netlink_nflog_group) {
180 vty_out(vty, "nhrp nflog-group %d%s",
181 netlink_nflog_group, VTY_NEWLINE);
182 }
183
184 return 0;
185}
186
187#define IP_STR "IP information\n"
188#define IPV6_STR "IPv6 information\n"
189#define AFI_CMD "(ip|ipv6)"
190#define AFI_STR IP_STR IPV6_STR
191#define NHRP_STR "Next Hop Resolution Protocol functions\n"
192
193static afi_t cmd_to_afi(const char *cmd)
194{
195 return strncmp(cmd, "ipv6", 4) == 0 ? AFI_IP6 : AFI_IP;
196}
197
198static const char *afi_to_cmd(afi_t afi)
199{
200 if (afi == AFI_IP6) return "ipv6";
201 return "ip";
202}
203
204DEFUN(nhrp_event_socket, nhrp_event_socket_cmd,
205 "nhrp event socket SOCKET",
206 NHRP_STR
207 "Event Manager commands\n"
208 "Event Manager unix socket path\n"
209 "Unix path for the socket")
210{
211 evmgr_set_socket(argv[0]);
212 return CMD_SUCCESS;
213}
214
215DEFUN(no_nhrp_event_socket, no_nhrp_event_socket_cmd,
216 "no nhrp event socket [SOCKET]",
217 NO_STR
218 NHRP_STR
219 "Event Manager commands\n"
220 "Event Manager unix socket path\n"
221 "Unix path for the socket")
222{
223 evmgr_set_socket(NULL);
224 return CMD_SUCCESS;
225}
226
227DEFUN(nhrp_nflog_group, nhrp_nflog_group_cmd,
228 "nhrp nflog-group <1-65535>",
229 NHRP_STR
230 "Specify NFLOG group number\n"
231 "NFLOG group number\n")
232{
233 uint32_t nfgroup;
234
235 VTY_GET_INTEGER_RANGE("nflog-group", nfgroup, argv[0], 1, 65535);
236 netlink_set_nflog_group(nfgroup);
237
238 return CMD_SUCCESS;
239}
240
241DEFUN(no_nhrp_nflog_group, no_nhrp_nflog_group_cmd,
242 "no nhrp nflog-group [<1-65535>]",
243 NO_STR
244 NHRP_STR
245 "Specify NFLOG group number\n"
246 "NFLOG group number\n")
247{
248 netlink_set_nflog_group(0);
249 return CMD_SUCCESS;
250}
251
252DEFUN(tunnel_protection, tunnel_protection_cmd,
253 "tunnel protection vici profile PROFILE {fallback-profile FALLBACK}",
254 "NHRP/GRE integration\n"
255 "IPsec protection\n"
256 "VICI (StrongSwan)\n"
257 "IPsec profile\n"
258 "IPsec profile name\n"
259 "Fallback IPsec profile\n"
260 "Fallback IPsec profile name\n")
261{
262 struct interface *ifp = vty->index;
263
264 nhrp_interface_set_protection(ifp, argv[0], argv[1]);
265 return CMD_SUCCESS;
266}
267
268DEFUN(no_tunnel_protection, no_tunnel_protection_cmd,
269 "no tunnel protection",
270 NO_STR
271 "NHRP/GRE integration\n"
272 "IPsec protection\n")
273{
274 struct interface *ifp = vty->index;
275
276 nhrp_interface_set_protection(ifp, NULL, NULL);
277 return CMD_SUCCESS;
278}
279
280DEFUN(tunnel_source, tunnel_source_cmd,
281 "tunnel source INTERFACE",
282 "NHRP/GRE integration\n"
283 "Tunnel device binding tracking\n"
284 "Interface name\n")
285{
286 struct interface *ifp = vty->index;
287 nhrp_interface_set_source(ifp, argv[0]);
288 return CMD_SUCCESS;
289}
290
291DEFUN(no_tunnel_source, no_tunnel_source_cmd,
292 "no tunnel source",
293 "NHRP/GRE integration\n"
294 "Tunnel device binding tracking\n"
295 "Interface name\n")
296{
297 struct interface *ifp = vty->index;
298 nhrp_interface_set_source(ifp, NULL);
299 return CMD_SUCCESS;
300}
301
302DEFUN(if_nhrp_network_id, if_nhrp_network_id_cmd,
303 AFI_CMD " nhrp network-id <1-4294967295>",
304 AFI_STR
305 NHRP_STR
306 "Enable NHRP and specify network-id\n"
307 "System local ID to specify interface group\n")
308{
309 struct interface *ifp = vty->index;
310 struct nhrp_interface *nifp = ifp->info;
311 afi_t afi = cmd_to_afi(argv[0]);
312
313 VTY_GET_INTEGER_RANGE("network-id", nifp->afi[afi].network_id, argv[1], 1, 4294967295);
314 nhrp_interface_update(ifp);
315
316 return CMD_SUCCESS;
317}
318
319DEFUN(if_no_nhrp_network_id, if_no_nhrp_network_id_cmd,
320 "no " AFI_CMD " nhrp network-id [<1-4294967295>]",
321 NO_STR
322 AFI_STR
323 NHRP_STR
324 "Enable NHRP and specify network-id\n"
325 "System local ID to specify interface group\n")
326{
327 struct interface *ifp = vty->index;
328 struct nhrp_interface *nifp = ifp->info;
329 afi_t afi = cmd_to_afi(argv[0]);
330
331 nifp->afi[afi].network_id = 0;
332 nhrp_interface_update(ifp);
333
334 return CMD_SUCCESS;
335}
336
337DEFUN(if_nhrp_flags, if_nhrp_flags_cmd,
338 AFI_CMD " nhrp (shortcut|redirect)",
339 AFI_STR
340 NHRP_STR
341 "Allow shortcut establishment\n"
342 "Send redirect notifications\n")
343{
344 struct interface *ifp = vty->index;
345 struct nhrp_interface *nifp = ifp->info;
346 afi_t afi = cmd_to_afi(argv[0]);
347
348 return toggle_flag(vty, interface_flags_desc, argv[1], 1, &nifp->afi[afi].flags);
349}
350
351DEFUN(if_no_nhrp_flags, if_no_nhrp_flags_cmd,
352 "no " AFI_CMD " nhrp (shortcut|redirect)",
353 NO_STR
354 AFI_STR
355 NHRP_STR
356 "Allow shortcut establishment\n"
357 "Send redirect notifications\n")
358{
359 struct interface *ifp = vty->index;
360 struct nhrp_interface *nifp = ifp->info;
361 afi_t afi = cmd_to_afi(argv[0]);
362
363 return toggle_flag(vty, interface_flags_desc, argv[1], 0, &nifp->afi[afi].flags);
364}
365
366DEFUN(if_nhrp_reg_flags, if_nhrp_reg_flags_cmd,
367 AFI_CMD " nhrp registration (no-unique)",
368 AFI_STR
369 NHRP_STR
370 "Registration configuration\n"
371 "Don't set unique flag\n")
372{
373 struct interface *ifp = vty->index;
374 struct nhrp_interface *nifp = ifp->info;
375 afi_t afi = cmd_to_afi(argv[0]);
376 char name[256];
377 snprintf(name, sizeof(name), "registration %s", argv[1]);
378 return toggle_flag(vty, interface_flags_desc, name, 1, &nifp->afi[afi].flags);
379}
380
381DEFUN(if_no_nhrp_reg_flags, if_no_nhrp_reg_flags_cmd,
382 "no " AFI_CMD " nhrp registration (no-unique)",
383 NO_STR
384 AFI_STR
385 NHRP_STR
386 "Registration configuration\n"
387 "Don't set unique flag\n")
388{
389 struct interface *ifp = vty->index;
390 struct nhrp_interface *nifp = ifp->info;
391 afi_t afi = cmd_to_afi(argv[0]);
392 char name[256];
393 snprintf(name, sizeof(name), "registration %s", argv[1]);
394 return toggle_flag(vty, interface_flags_desc, name, 0, &nifp->afi[afi].flags);
395}
396
397DEFUN(if_nhrp_holdtime, if_nhrp_holdtime_cmd,
398 AFI_CMD " nhrp holdtime <1-65000>",
399 AFI_STR
400 NHRP_STR
401 "Specify NBMA address validity time\n"
402 "Time in seconds that NBMA addresses are advertised valid\n")
403{
404 struct interface *ifp = vty->index;
405 struct nhrp_interface *nifp = ifp->info;
406 afi_t afi = cmd_to_afi(argv[0]);
407
408 VTY_GET_INTEGER_RANGE("holdtime", nifp->afi[afi].holdtime, argv[1], 1, 65000);
409 nhrp_interface_update(ifp);
410
411 return CMD_SUCCESS;
412}
413
414DEFUN(if_no_nhrp_holdtime, if_no_nhrp_holdtime_cmd,
415 "no " AFI_CMD " nhrp holdtime [1-65000]",
416 NO_STR
417 AFI_STR
418 NHRP_STR
419 "Specify NBMA address validity time\n"
420 "Time in seconds that NBMA addresses are advertised valid\n")
421{
422 struct interface *ifp = vty->index;
423 struct nhrp_interface *nifp = ifp->info;
424 afi_t afi = cmd_to_afi(argv[0]);
425
426 nifp->afi[afi].holdtime = NHRPD_DEFAULT_HOLDTIME;
427 nhrp_interface_update(ifp);
428
429 return CMD_SUCCESS;
430}
431
432DEFUN(if_nhrp_mtu, if_nhrp_mtu_cmd,
433 "ip nhrp mtu (<576-1500>|opennhrp)",
434 IP_STR
435 NHRP_STR
436 "Configure NHRP advertised MTU\n"
437 "MTU value\n"
438 "Advertise bound interface MTU similar to OpenNHRP")
439{
440 struct interface *ifp = vty->index;
441 struct nhrp_interface *nifp = ifp->info;
442
443 if (argv[0][0] == 'o') {
444 nifp->afi[AFI_IP].configured_mtu = -1;
445 } else {
446 VTY_GET_INTEGER_RANGE("mtu", nifp->afi[AFI_IP].configured_mtu, argv[0], 576, 1500);
447 }
448 nhrp_interface_update_mtu(ifp, AFI_IP);
449
450 return CMD_SUCCESS;
451}
452
453DEFUN(if_no_nhrp_mtu, if_no_nhrp_mtu_cmd,
454 "no ip nhrp mtu [(<576-1500>|opennhrp)]",
455 NO_STR
456 IP_STR
457 NHRP_STR
458 "Configure NHRP advertised MTU\n"
459 "MTU value\n"
460 "Advertise bound interface MTU similar to OpenNHRP")
461{
462 struct interface *ifp = vty->index;
463 struct nhrp_interface *nifp = ifp->info;
464
465 nifp->afi[AFI_IP].configured_mtu = 0;
466 nhrp_interface_update_mtu(ifp, AFI_IP);
467 return CMD_SUCCESS;
468}
469
470DEFUN(if_nhrp_map, if_nhrp_map_cmd,
471 AFI_CMD " nhrp map (A.B.C.D|X:X::X:X) (A.B.C.D|local)",
472 AFI_STR
473 NHRP_STR
474 "Nexthop Server configuration\n"
475 "IPv4 protocol address\n"
476 "IPv6 protocol address\n"
477 "IPv4 NBMA address\n"
478 "Handle protocol address locally\n")
479{
480 struct interface *ifp = vty->index;
481 afi_t afi = cmd_to_afi(argv[0]);
482 union sockunion proto_addr, nbma_addr;
483 struct nhrp_cache *c;
484
485 if (str2sockunion(argv[1], &proto_addr) < 0 ||
486 afi2family(afi) != sockunion_family(&proto_addr))
487 return nhrp_vty_return(vty, NHRP_ERR_PROTOCOL_ADDRESS_MISMATCH);
488
489 c = nhrp_cache_get(ifp, &proto_addr, 1);
490 if (!c)
491 return nhrp_vty_return(vty, NHRP_ERR_FAIL);
492
493 c->map = 1;
494 if (strcmp(argv[2], "local") == 0) {
495 nhrp_cache_update_binding(c, NHRP_CACHE_LOCAL, 0, NULL, 0, NULL);
496 } else{
497 if (str2sockunion(argv[2], &nbma_addr) < 0)
498 return nhrp_vty_return(vty, NHRP_ERR_FAIL);
499 nhrp_cache_update_binding(c, NHRP_CACHE_STATIC, 0,
500 nhrp_peer_get(ifp, &nbma_addr), 0, NULL);
501 }
502
503 return CMD_SUCCESS;
504}
505
506DEFUN(if_nhrp_nhs, if_nhrp_nhs_cmd,
507 AFI_CMD " nhrp nhs (A.B.C.D|X:X::X:X|dynamic) nbma (A.B.C.D|FQDN)",
508 AFI_STR
509 NHRP_STR
510 "Nexthop Server configuration\n"
511 "IPv4 protocol address\n"
512 "IPv6 protocol address\n"
513 "Automatic detection of protocol address\n"
514 "IPv4 NBMA address\n"
515 "Fully qualified domain name for NBMA address(es)\n")
516{
517 struct interface *ifp = vty->index;
518 afi_t afi = cmd_to_afi(argv[0]);
519 union sockunion proto_addr;
520 int ret;
521
522 if (str2sockunion(argv[1], &proto_addr) < 0)
523 sockunion_family(&proto_addr) = AF_UNSPEC;
524
525 ret = nhrp_nhs_add(ifp, afi, &proto_addr, argv[2]);
526 return nhrp_vty_return(vty, ret);
527}
528
529DEFUN(if_no_nhrp_nhs, if_no_nhrp_nhs_cmd,
530 "no " AFI_CMD " nhrp nhs (A.B.C.D|X:X::X:X|dynamic) nbma (A.B.C.D|FQDN)",
531 NO_STR
532 AFI_STR
533 NHRP_STR
534 "Nexthop Server configuration\n"
535 "IPv4 protocol address\n"
536 "IPv6 protocol address\n"
537 "Automatic detection of protocol address\n"
538 "IPv4 NBMA address\n"
539 "Fully qualified domain name for NBMA address(es)\n")
540{
541 struct interface *ifp = vty->index;
542 afi_t afi = cmd_to_afi(argv[0]);
543 union sockunion proto_addr;
544 int ret;
545
546 if (str2sockunion(argv[1], &proto_addr) < 0)
547 sockunion_family(&proto_addr) = AF_UNSPEC;
548
549 ret = nhrp_nhs_del(ifp, afi, &proto_addr, argv[2]);
550 return nhrp_vty_return(vty, ret);
551}
552
553struct info_ctx {
554 struct vty *vty;
555 afi_t afi;
556 int count;
557};
558
559static void show_ip_nhrp_cache(struct nhrp_cache *c, void *pctx)
560{
561 struct info_ctx *ctx = pctx;
562 struct vty *vty = ctx->vty;
563 char buf[2][SU_ADDRSTRLEN];
564
565 if (ctx->afi != family2afi(sockunion_family(&c->remote_addr)))
566 return;
567
568 if (!ctx->count) {
569 vty_out(vty, "%-8s %-8s %-24s %-24s %-6s %s%s",
570 "Iface",
571 "Type",
572 "Protocol",
573 "NBMA",
574 "Flags",
575 "Identity",
576 VTY_NEWLINE);
577 }
578 ctx->count++;
579
580 vty_out(ctx->vty, "%-8s %-8s %-24s %-24s %c%c%c %s%s",
581 c->ifp->name,
582 nhrp_cache_type_str[c->cur.type],
583 sockunion2str(&c->remote_addr, buf[0], sizeof buf[0]),
584 c->cur.peer ? sockunion2str(&c->cur.peer->vc->remote.nbma, buf[1], sizeof buf[1]) : "-",
585 c->used ? 'U' : ' ',
586 c->t_timeout ? 'T' : ' ',
587 c->t_auth ? 'A' : ' ',
588 c->cur.peer ? c->cur.peer->vc->remote.id : "-",
589 VTY_NEWLINE);
590}
591
592static void show_ip_opennhrp_cache(struct nhrp_cache *c, void *pctx)
593{
594 struct info_ctx *ctx = pctx;
595 struct vty *vty = ctx->vty;
596 char buf[SU_ADDRSTRLEN];
597
598 if (ctx->afi != family2afi(sockunion_family(&c->remote_addr)))
599 return;
600
601 vty_out(ctx->vty,
602 "Type: %s%s"
603 "Flags:%s%s%s"
604 "Protocol-Address: %s/%zu%s",
605 nhrp_cache_type_str[c->cur.type],
606 VTY_NEWLINE,
607 (c->cur.peer && c->cur.peer->online) ? " up": "",
608 c->used ? " used": "",
609 VTY_NEWLINE,
610 sockunion2str(&c->remote_addr, buf, sizeof buf),
611 8 * family2addrsize(sockunion_family(&c->remote_addr)),
612 VTY_NEWLINE);
613
614 if (c->cur.peer) {
615 vty_out(ctx->vty,
616 "NBMA-Address: %s%s",
617 sockunion2str(&c->cur.peer->vc->remote.nbma, buf, sizeof buf),
618 VTY_NEWLINE);
619 }
620
621 if (sockunion_family(&c->cur.remote_nbma_natoa) != AF_UNSPEC) {
622 vty_out(ctx->vty,
623 "NBMA-NAT-OA-Address: %s%s",
624 sockunion2str(&c->cur.remote_nbma_natoa, buf, sizeof buf),
625 VTY_NEWLINE);
626 }
627
628 vty_out(ctx->vty, "%s", VTY_NEWLINE);
629}
630
631static void show_ip_nhrp_shortcut(struct nhrp_shortcut *s, void *pctx)
632{
633 struct info_ctx *ctx = pctx;
634 struct nhrp_cache *c;
635 struct vty *vty = ctx->vty;
636 char buf1[PREFIX_STRLEN], buf2[SU_ADDRSTRLEN];
637
638 if (!ctx->count) {
639 vty_out(vty, "%-8s %-24s %-24s %s%s",
640 "Type",
641 "Prefix",
642 "Via",
643 "Identity",
644 VTY_NEWLINE);
645 }
646 ctx->count++;
647
648 c = s->cache;
649 vty_out(ctx->vty, "%-8s %-24s %-24s %s%s",
650 nhrp_cache_type_str[s->type],
651 prefix2str(s->p, buf1, sizeof buf1),
652 c ? sockunion2str(&c->remote_addr, buf2, sizeof buf2) : "",
653 (c && c->cur.peer) ? c->cur.peer->vc->remote.id : "",
654 VTY_NEWLINE);
655}
656
657DEFUN(show_ip_nhrp, show_ip_nhrp_cmd,
658 "show " AFI_CMD " nhrp (cache|shortcut|opennhrp|)",
659 SHOW_STR
660 AFI_STR
661 "NHRP information\n"
662 "Forwarding cache information\n"
663 "Shortcut information\n"
664 "opennhrpctl style cache dump\n")
665{
666 struct listnode *node;
667 struct interface *ifp;
668 struct info_ctx ctx = {
669 .vty = vty,
670 .afi = cmd_to_afi(argv[0]),
671 };
672
673 if (!argv[1] || argv[1][0] == 'c') {
674 for (ALL_LIST_ELEMENTS_RO(iflist, node, ifp))
675 nhrp_cache_foreach(ifp, show_ip_nhrp_cache, &ctx);
676 } else if (argv[1][0] == 'o') {
677 vty_out(vty, "Status: ok%s%s", VTY_NEWLINE, VTY_NEWLINE);
678 ctx.count++;
679 for (ALL_LIST_ELEMENTS_RO(iflist, node, ifp))
680 nhrp_cache_foreach(ifp, show_ip_opennhrp_cache, &ctx);
681 } else {
682 nhrp_shortcut_foreach(ctx.afi, show_ip_nhrp_shortcut, &ctx);
683 }
684
685 if (!ctx.count) {
686 vty_out(vty, "%% No entries%s", VTY_NEWLINE);
687 return CMD_WARNING;
688 }
689
690 return CMD_SUCCESS;
691}
692
693static void show_dmvpn_entry(struct nhrp_vc *vc, void *ctx)
694{
695 struct vty *vty = ctx;
696 char buf[2][SU_ADDRSTRLEN];
697
698 vty_out(vty, "%-24s %-24s %c %-4d %-24s%s",
699 sockunion2str(&vc->local.nbma, buf[0], sizeof buf[0]),
700 sockunion2str(&vc->remote.nbma, buf[1], sizeof buf[1]),
701 notifier_active(&vc->notifier_list) ? 'n' : ' ',
702 vc->ipsec,
703 vc->remote.id,
704 VTY_NEWLINE);
705}
706
707DEFUN(show_dmvpn, show_dmvpn_cmd,
708 "show dmvpn",
709 SHOW_STR
710 "DMVPN information\n")
711{
712 vty_out(vty, "%-24s %-24s %-6s %-4s %-24s%s",
713 "Src",
714 "Dst",
715 "Flags",
716 "SAs",
717 "Identity",
718 VTY_NEWLINE);
719
720 nhrp_vc_foreach(show_dmvpn_entry, vty);
721
722 return CMD_SUCCESS;
723}
724
725static void clear_nhrp_cache(struct nhrp_cache *c, void *data)
726{
727 struct info_ctx *ctx = data;
728 if (c->cur.type <= NHRP_CACHE_CACHED) {
729 nhrp_cache_update_binding(c, c->cur.type, -1, NULL, 0, NULL);
730 ctx->count++;
731 }
732}
733
734static void clear_nhrp_shortcut(struct nhrp_shortcut *s, void *data)
735{
736 struct info_ctx *ctx = data;
737 nhrp_shortcut_purge(s, 1);
738 ctx->count++;
739}
740
741DEFUN(clear_nhrp, clear_nhrp_cmd,
742 "clear " AFI_CMD " nhrp (cache|shortcut)",
743 CLEAR_STR
744 AFI_STR
745 NHRP_STR
746 "Dynamic cache entries\n"
747 "Shortcut entries\n")
748{
749 struct listnode *node;
750 struct interface *ifp;
751 struct info_ctx ctx = {
752 .vty = vty,
753 .afi = cmd_to_afi(argv[0]),
754 .count = 0,
755 };
756
757 if (!argv[1] || argv[1][0] == 'c') {
758 for (ALL_LIST_ELEMENTS_RO(iflist, node, ifp))
759 nhrp_cache_foreach(ifp, clear_nhrp_cache, &ctx);
760 } else {
761 nhrp_shortcut_foreach(ctx.afi, clear_nhrp_shortcut, &ctx);
762 }
763
764 if (!ctx.count) {
765 vty_out(vty, "%% No entries%s", VTY_NEWLINE);
766 return CMD_WARNING;
767 }
768
769 vty_out(vty, "%% %d entries cleared%s", ctx.count, VTY_NEWLINE);
770 return CMD_SUCCESS;
771}
772
773struct write_map_ctx {
774 struct vty *vty;
775 int family;
776 const char *aficmd;
777};
778
779static void interface_config_write_nhrp_map(struct nhrp_cache *c, void *data)
780{
781 struct write_map_ctx *ctx = data;
782 struct vty *vty = ctx->vty;
783 char buf[2][SU_ADDRSTRLEN];
784
785 if (!c->map) return;
786 if (sockunion_family(&c->remote_addr) != ctx->family) return;
787
788 vty_out(vty, " %s nhrp map %s %s%s",
789 ctx->aficmd,
790 sockunion2str(&c->remote_addr, buf[0], sizeof buf[0]),
791 c->cur.type == NHRP_CACHE_LOCAL ? "local" :
792 sockunion2str(&c->cur.peer->vc->remote.nbma, buf[1], sizeof buf[1]),
793 VTY_NEWLINE);
794}
795
796static int interface_config_write(struct vty *vty)
797{
798 struct write_map_ctx mapctx;
799 struct listnode *node;
800 struct interface *ifp;
801 struct nhrp_interface *nifp;
802 struct nhrp_nhs *nhs;
803 const char *aficmd;
804 afi_t afi;
805 char buf[SU_ADDRSTRLEN];
806 int i;
807
808 for (ALL_LIST_ELEMENTS_RO(iflist, node, ifp)) {
809 vty_out(vty, "interface %s%s", ifp->name, VTY_NEWLINE);
810 if (ifp->desc)
811 vty_out(vty, " description %s%s", ifp->desc, VTY_NEWLINE);
812
813 nifp = ifp->info;
814 if (nifp->ipsec_profile) {
815 vty_out(vty, " tunnel protection vici profile %s",
816 nifp->ipsec_profile);
817 if (nifp->ipsec_fallback_profile)
818 vty_out(vty, " fallback-profile %s",
819 nifp->ipsec_fallback_profile);
820 vty_out(vty, "%s", VTY_NEWLINE);
821 }
822 if (nifp->source)
823 vty_out(vty, " tunnel source %s%s",
824 nifp->source, VTY_NEWLINE);
825
826 for (afi = 0; afi < AFI_MAX; afi++) {
827 struct nhrp_afi_data *ad = &nifp->afi[afi];
828
829 aficmd = afi_to_cmd(afi);
830
831 if (ad->network_id)
832 vty_out(vty, " %s nhrp network-id %u%s",
833 aficmd, ad->network_id,
834 VTY_NEWLINE);
835
836 if (ad->holdtime != NHRPD_DEFAULT_HOLDTIME)
837 vty_out(vty, " %s nhrp holdtime %u%s",
838 aficmd, ad->holdtime,
839 VTY_NEWLINE);
840
841 if (ad->configured_mtu < 0)
842 vty_out(vty, " %s nhrp mtu opennhrp%s",
843 aficmd, VTY_NEWLINE);
844 else if (ad->configured_mtu)
845 vty_out(vty, " %s nhrp mtu %u%s",
846 aficmd, ad->configured_mtu,
847 VTY_NEWLINE);
848
849 for (i = 0; interface_flags_desc[i].str != NULL; i++) {
850 if (!(ad->flags & interface_flags_desc[i].key))
851 continue;
852 vty_out(vty, " %s nhrp %s%s",
853 aficmd, interface_flags_desc[i].str, VTY_NEWLINE);
854 }
855
856 mapctx = (struct write_map_ctx) {
857 .vty = vty,
858 .family = afi2family(afi),
859 .aficmd = aficmd,
860 };
861 nhrp_cache_foreach(ifp, interface_config_write_nhrp_map, &mapctx);
862
863 list_for_each_entry(nhs, &ad->nhslist_head, nhslist_entry) {
864 vty_out(vty, " %s nhrp nhs %s nbma %s%s",
865 aficmd,
866 sockunion_family(&nhs->proto_addr) == AF_UNSPEC ? "dynamic" : sockunion2str(&nhs->proto_addr, buf, sizeof buf),
867 nhs->nbma_fqdn,
868 VTY_NEWLINE);
869 }
870 }
871
872 vty_out (vty, "!%s", VTY_NEWLINE);
873 }
874
875 return 0;
876}
877
878void nhrp_config_init(void)
879{
880 install_node(&zebra_node, nhrp_config_write);
881 install_default(ZEBRA_NODE);
882
883 /* global commands */
884 install_element(VIEW_NODE, &show_debugging_nhrp_cmd);
885 install_element(VIEW_NODE, &show_ip_nhrp_cmd);
886 install_element(VIEW_NODE, &show_dmvpn_cmd);
887 install_element(ENABLE_NODE, &show_debugging_nhrp_cmd);
888 install_element(ENABLE_NODE, &show_ip_nhrp_cmd);
889 install_element(ENABLE_NODE, &show_dmvpn_cmd);
890 install_element(ENABLE_NODE, &clear_nhrp_cmd);
891
892 install_element(ENABLE_NODE, &debug_nhrp_cmd);
893 install_element(ENABLE_NODE, &no_debug_nhrp_cmd);
894
895 install_element(CONFIG_NODE, &debug_nhrp_cmd);
896 install_element(CONFIG_NODE, &no_debug_nhrp_cmd);
897
898 install_element(CONFIG_NODE, &nhrp_event_socket_cmd);
899 install_element(CONFIG_NODE, &no_nhrp_event_socket_cmd);
900 install_element(CONFIG_NODE, &nhrp_nflog_group_cmd);
901 install_element(CONFIG_NODE, &no_nhrp_nflog_group_cmd);
902
903 /* interface specific commands */
904 install_node(&nhrp_interface_node, interface_config_write);
905 install_default(INTERFACE_NODE);
906
907 install_element(CONFIG_NODE, &interface_cmd);
908 install_element(CONFIG_NODE, &no_interface_cmd);
909 install_element(INTERFACE_NODE, &interface_cmd);
910 install_element(INTERFACE_NODE, &no_interface_cmd);
911 install_element(INTERFACE_NODE, &tunnel_protection_cmd);
912 install_element(INTERFACE_NODE, &no_tunnel_protection_cmd);
913 install_element(INTERFACE_NODE, &tunnel_source_cmd);
914 install_element(INTERFACE_NODE, &no_tunnel_source_cmd);
915 install_element(INTERFACE_NODE, &if_nhrp_network_id_cmd);
916 install_element(INTERFACE_NODE, &if_no_nhrp_network_id_cmd);
917 install_element(INTERFACE_NODE, &if_nhrp_holdtime_cmd);
918 install_element(INTERFACE_NODE, &if_no_nhrp_holdtime_cmd);
919 install_element(INTERFACE_NODE, &if_nhrp_mtu_cmd);
920 install_element(INTERFACE_NODE, &if_no_nhrp_mtu_cmd);
921 install_element(INTERFACE_NODE, &if_nhrp_flags_cmd);
922 install_element(INTERFACE_NODE, &if_no_nhrp_flags_cmd);
923 install_element(INTERFACE_NODE, &if_nhrp_reg_flags_cmd);
924 install_element(INTERFACE_NODE, &if_no_nhrp_reg_flags_cmd);
925 install_element(INTERFACE_NODE, &if_nhrp_map_cmd);
926 install_element(INTERFACE_NODE, &if_nhrp_nhs_cmd);
927 install_element(INTERFACE_NODE, &if_no_nhrp_nhs_cmd);
928}