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