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