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