]> git.proxmox.com Git - mirror_frr.git/blob - nhrpd/nhrp_vty.c
zebra: vrf: remove VRF-move static route updating
[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
15 #include "nhrpd.h"
16 #include "netlink.h"
17
18 static struct cmd_node zebra_node = {
19 .node = ZEBRA_NODE,
20 .prompt = "%s(config-router)# ",
21 .vtysh = 1,
22 };
23
24 static 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
41 static 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 }
50 };
51
52 static 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 }
57 };
58
59 static 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
90 static 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
112 DEFUN(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
135 DEFUN(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[2]->text, 1, &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, &debug_flags);
152 }
153
154 #endif /* NO_DEBUG */
155
156 static 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
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) return "ipv6";
201 return "ip";
202 }
203
204 DEFUN(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[3]->arg);
212 return CMD_SUCCESS;
213 }
214
215 DEFUN(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
227 DEFUN(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[2]->arg, 1, 65535);
236 netlink_set_nflog_group(nfgroup);
237
238 return CMD_SUCCESS;
239 }
240
241 DEFUN(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
252 DEFUN(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 VTY_DECLVAR_CONTEXT(interface, ifp);
263
264 nhrp_interface_set_protection(ifp, argv[4]->arg,
265 argc > 6 ? argv[6]->arg : NULL);
266 return CMD_SUCCESS;
267 }
268
269 DEFUN(no_tunnel_protection, no_tunnel_protection_cmd,
270 "no tunnel protection",
271 NO_STR
272 "NHRP/GRE integration\n"
273 "IPsec protection\n")
274 {
275 VTY_DECLVAR_CONTEXT(interface, ifp);
276
277 nhrp_interface_set_protection(ifp, NULL, NULL);
278 return CMD_SUCCESS;
279 }
280
281 DEFUN(tunnel_source, tunnel_source_cmd,
282 "tunnel source INTERFACE",
283 "NHRP/GRE integration\n"
284 "Tunnel device binding tracking\n"
285 "Interface name\n")
286 {
287 VTY_DECLVAR_CONTEXT(interface, ifp);
288 nhrp_interface_set_source(ifp, argv[2]->arg);
289 return CMD_SUCCESS;
290 }
291
292 DEFUN(no_tunnel_source, no_tunnel_source_cmd,
293 "no tunnel source",
294 "NHRP/GRE integration\n"
295 "Tunnel device binding tracking\n"
296 "Interface name\n")
297 {
298 VTY_DECLVAR_CONTEXT(interface, ifp);
299 nhrp_interface_set_source(ifp, NULL);
300 return CMD_SUCCESS;
301 }
302
303 DEFUN(if_nhrp_network_id, if_nhrp_network_id_cmd,
304 AFI_CMD " nhrp network-id (1-4294967295)",
305 AFI_STR
306 NHRP_STR
307 "Enable NHRP and specify network-id\n"
308 "System local ID to specify interface group\n")
309 {
310 VTY_DECLVAR_CONTEXT(interface, ifp);
311 struct nhrp_interface *nifp = ifp->info;
312 afi_t afi = cmd_to_afi(argv[0]);
313
314 VTY_GET_INTEGER_RANGE("network-id", nifp->afi[afi].network_id, argv[3]->arg, 1, 4294967295);
315 nhrp_interface_update(ifp);
316
317 return CMD_SUCCESS;
318 }
319
320 DEFUN(if_no_nhrp_network_id, if_no_nhrp_network_id_cmd,
321 "no " AFI_CMD " nhrp network-id [(1-4294967295)]",
322 NO_STR
323 AFI_STR
324 NHRP_STR
325 "Enable NHRP and specify network-id\n"
326 "System local ID to specify interface group\n")
327 {
328 VTY_DECLVAR_CONTEXT(interface, ifp);
329 struct nhrp_interface *nifp = ifp->info;
330 afi_t afi = cmd_to_afi(argv[1]);
331
332 nifp->afi[afi].network_id = 0;
333 nhrp_interface_update(ifp);
334
335 return CMD_SUCCESS;
336 }
337
338 DEFUN(if_nhrp_flags, if_nhrp_flags_cmd,
339 AFI_CMD " nhrp <shortcut|redirect>",
340 AFI_STR
341 NHRP_STR
342 "Allow shortcut establishment\n"
343 "Send redirect notifications\n")
344 {
345 VTY_DECLVAR_CONTEXT(interface, ifp);
346 struct nhrp_interface *nifp = ifp->info;
347 afi_t afi = cmd_to_afi(argv[0]);
348
349 return toggle_flag(vty, interface_flags_desc, argv[2]->text, 1, &nifp->afi[afi].flags);
350 }
351
352 DEFUN(if_no_nhrp_flags, if_no_nhrp_flags_cmd,
353 "no " AFI_CMD " nhrp <shortcut|redirect>",
354 NO_STR
355 AFI_STR
356 NHRP_STR
357 "Allow shortcut establishment\n"
358 "Send redirect notifications\n")
359 {
360 VTY_DECLVAR_CONTEXT(interface, ifp);
361 struct nhrp_interface *nifp = ifp->info;
362 afi_t afi = cmd_to_afi(argv[1]);
363
364 return toggle_flag(vty, interface_flags_desc, argv[3]->text, 0, &nifp->afi[afi].flags);
365 }
366
367 DEFUN(if_nhrp_reg_flags, if_nhrp_reg_flags_cmd,
368 AFI_CMD " nhrp registration no-unique",
369 AFI_STR
370 NHRP_STR
371 "Registration configuration\n"
372 "Don't set unique flag\n")
373 {
374 VTY_DECLVAR_CONTEXT(interface, ifp);
375 struct nhrp_interface *nifp = ifp->info;
376 afi_t afi = cmd_to_afi(argv[0]);
377 char name[256];
378 snprintf(name, sizeof(name), "registration %s", argv[3]->text);
379 return toggle_flag(vty, interface_flags_desc, name, 1, &nifp->afi[afi].flags);
380 }
381
382 DEFUN(if_no_nhrp_reg_flags, if_no_nhrp_reg_flags_cmd,
383 "no " AFI_CMD " nhrp registration no-unique",
384 NO_STR
385 AFI_STR
386 NHRP_STR
387 "Registration configuration\n"
388 "Don't set unique flag\n")
389 {
390 VTY_DECLVAR_CONTEXT(interface, ifp);
391 struct nhrp_interface *nifp = ifp->info;
392 afi_t afi = cmd_to_afi(argv[1]);
393 char name[256];
394 snprintf(name, sizeof(name), "registration %s", argv[4]->text);
395 return toggle_flag(vty, interface_flags_desc, name, 0, &nifp->afi[afi].flags);
396 }
397
398 DEFUN(if_nhrp_holdtime, if_nhrp_holdtime_cmd,
399 AFI_CMD " nhrp holdtime (1-65000)",
400 AFI_STR
401 NHRP_STR
402 "Specify NBMA address validity time\n"
403 "Time in seconds that NBMA addresses are advertised valid\n")
404 {
405 VTY_DECLVAR_CONTEXT(interface, ifp);
406 struct nhrp_interface *nifp = ifp->info;
407 afi_t afi = cmd_to_afi(argv[0]);
408
409 VTY_GET_INTEGER_RANGE("holdtime", nifp->afi[afi].holdtime, argv[3]->arg, 1, 65000);
410 nhrp_interface_update(ifp);
411
412 return CMD_SUCCESS;
413 }
414
415 DEFUN(if_no_nhrp_holdtime, if_no_nhrp_holdtime_cmd,
416 "no " AFI_CMD " nhrp holdtime [(1-65000)]",
417 NO_STR
418 AFI_STR
419 NHRP_STR
420 "Specify NBMA address validity time\n"
421 "Time in seconds that NBMA addresses are advertised valid\n")
422 {
423 VTY_DECLVAR_CONTEXT(interface, ifp);
424 struct nhrp_interface *nifp = ifp->info;
425 afi_t afi = cmd_to_afi(argv[1]);
426
427 nifp->afi[afi].holdtime = NHRPD_DEFAULT_HOLDTIME;
428 nhrp_interface_update(ifp);
429
430 return CMD_SUCCESS;
431 }
432
433 DEFUN(if_nhrp_mtu, if_nhrp_mtu_cmd,
434 "ip nhrp mtu <(576-1500)|opennhrp>",
435 IP_STR
436 NHRP_STR
437 "Configure NHRP advertised MTU\n"
438 "MTU value\n"
439 "Advertise bound interface MTU similar to OpenNHRP")
440 {
441 VTY_DECLVAR_CONTEXT(interface, ifp);
442 struct nhrp_interface *nifp = ifp->info;
443
444 if (argv[3]->arg[0] == 'o') {
445 nifp->afi[AFI_IP].configured_mtu = -1;
446 } else {
447 VTY_GET_INTEGER_RANGE("mtu", nifp->afi[AFI_IP].configured_mtu, argv[3]->arg, 576, 1500);
448 }
449 nhrp_interface_update_mtu(ifp, AFI_IP);
450
451 return CMD_SUCCESS;
452 }
453
454 DEFUN(if_no_nhrp_mtu, if_no_nhrp_mtu_cmd,
455 "no ip nhrp mtu [(576-1500)|opennhrp]",
456 NO_STR
457 IP_STR
458 NHRP_STR
459 "Configure NHRP advertised MTU\n"
460 "MTU value\n"
461 "Advertise bound interface MTU similar to OpenNHRP")
462 {
463 VTY_DECLVAR_CONTEXT(interface, ifp);
464 struct nhrp_interface *nifp = ifp->info;
465
466 nifp->afi[AFI_IP].configured_mtu = 0;
467 nhrp_interface_update_mtu(ifp, AFI_IP);
468 return CMD_SUCCESS;
469 }
470
471 DEFUN(if_nhrp_map, if_nhrp_map_cmd,
472 AFI_CMD " nhrp map <A.B.C.D|X:X::X:X> <A.B.C.D|local>",
473 AFI_STR
474 NHRP_STR
475 "Nexthop Server configuration\n"
476 "IPv4 protocol address\n"
477 "IPv6 protocol address\n"
478 "IPv4 NBMA address\n"
479 "Handle protocol address locally\n")
480 {
481 VTY_DECLVAR_CONTEXT(interface, ifp);
482 afi_t afi = cmd_to_afi(argv[0]);
483 union sockunion proto_addr, nbma_addr;
484 struct nhrp_cache *c;
485
486 if (str2sockunion(argv[3]->arg, &proto_addr) < 0 ||
487 afi2family(afi) != sockunion_family(&proto_addr))
488 return nhrp_vty_return(vty, NHRP_ERR_PROTOCOL_ADDRESS_MISMATCH);
489
490 c = nhrp_cache_get(ifp, &proto_addr, 1);
491 if (!c)
492 return nhrp_vty_return(vty, NHRP_ERR_FAIL);
493
494 c->map = 1;
495 if (strcmp(argv[4]->text, "local") == 0) {
496 nhrp_cache_update_binding(c, NHRP_CACHE_LOCAL, 0, NULL, 0, NULL);
497 } else{
498 if (str2sockunion(argv[4]->arg, &nbma_addr) < 0)
499 return nhrp_vty_return(vty, NHRP_ERR_FAIL);
500 nhrp_cache_update_binding(c, NHRP_CACHE_STATIC, 0,
501 nhrp_peer_get(ifp, &nbma_addr), 0, NULL);
502 }
503
504 return CMD_SUCCESS;
505 }
506
507 DEFUN(if_no_nhrp_map, if_no_nhrp_map_cmd,
508 "no " AFI_CMD " nhrp map <A.B.C.D|X:X::X:X>",
509 NO_STR
510 AFI_STR
511 NHRP_STR
512 "Nexthop Server configuration\n"
513 "IPv4 protocol address\n"
514 "IPv6 protocol address\n")
515 {
516 VTY_DECLVAR_CONTEXT(interface,ifp);
517 afi_t afi = cmd_to_afi(argv[1]);
518 union sockunion proto_addr;
519 struct nhrp_cache *c;
520
521 if (str2sockunion(argv[4]->arg, &proto_addr) < 0 ||
522 afi2family(afi) != sockunion_family(&proto_addr))
523 return nhrp_vty_return(vty, NHRP_ERR_PROTOCOL_ADDRESS_MISMATCH);
524
525 c = nhrp_cache_get(ifp, &proto_addr, 0);
526 if (!c || !c->map)
527 return nhrp_vty_return(vty, NHRP_ERR_ENTRY_NOT_FOUND);
528
529 nhrp_cache_update_binding(c, c->cur.type, -1, NULL, 0, NULL);
530 return CMD_SUCCESS;
531 }
532
533 DEFUN(if_nhrp_nhs, if_nhrp_nhs_cmd,
534 AFI_CMD " nhrp nhs <A.B.C.D|X:X::X:X|dynamic> nbma <A.B.C.D|FQDN>",
535 AFI_STR
536 NHRP_STR
537 "Nexthop Server configuration\n"
538 "IPv4 protocol address\n"
539 "IPv6 protocol address\n"
540 "Automatic detection of protocol address\n"
541 "NBMA address\n"
542 "IPv4 NBMA address\n"
543 "Fully qualified domain name for NBMA address(es)\n")
544 {
545 VTY_DECLVAR_CONTEXT(interface, ifp);
546 afi_t afi = cmd_to_afi(argv[0]);
547 union sockunion proto_addr;
548 int ret;
549
550 if (str2sockunion(argv[3]->arg, &proto_addr) < 0)
551 sockunion_family(&proto_addr) = AF_UNSPEC;
552
553 ret = nhrp_nhs_add(ifp, afi, &proto_addr, argv[5]->arg);
554 return nhrp_vty_return(vty, ret);
555 }
556
557 DEFUN(if_no_nhrp_nhs, if_no_nhrp_nhs_cmd,
558 "no " AFI_CMD " nhrp nhs <A.B.C.D|X:X::X:X|dynamic> nbma <A.B.C.D|FQDN>",
559 NO_STR
560 AFI_STR
561 NHRP_STR
562 "Nexthop Server configuration\n"
563 "IPv4 protocol address\n"
564 "IPv6 protocol address\n"
565 "Automatic detection of protocol address\n"
566 "NBMA address\n"
567 "IPv4 NBMA address\n"
568 "Fully qualified domain name for NBMA address(es)\n")
569 {
570 VTY_DECLVAR_CONTEXT(interface, ifp);
571 afi_t afi = cmd_to_afi(argv[1]);
572 union sockunion proto_addr;
573 int ret;
574
575 if (str2sockunion(argv[4]->arg, &proto_addr) < 0)
576 sockunion_family(&proto_addr) = AF_UNSPEC;
577
578 ret = nhrp_nhs_del(ifp, afi, &proto_addr, argv[6]->arg);
579 return nhrp_vty_return(vty, ret);
580 }
581
582 struct info_ctx {
583 struct vty *vty;
584 afi_t afi;
585 int count;
586 };
587
588 static void show_ip_nhrp_cache(struct nhrp_cache *c, void *pctx)
589 {
590 struct info_ctx *ctx = pctx;
591 struct vty *vty = ctx->vty;
592 char buf[2][SU_ADDRSTRLEN];
593
594 if (ctx->afi != family2afi(sockunion_family(&c->remote_addr)))
595 return;
596
597 if (!ctx->count) {
598 vty_out(vty, "%-8s %-8s %-24s %-24s %-6s %s%s",
599 "Iface",
600 "Type",
601 "Protocol",
602 "NBMA",
603 "Flags",
604 "Identity",
605 VTY_NEWLINE);
606 }
607 ctx->count++;
608
609 vty_out(ctx->vty, "%-8s %-8s %-24s %-24s %c%c%c %s%s",
610 c->ifp->name,
611 nhrp_cache_type_str[c->cur.type],
612 sockunion2str(&c->remote_addr, buf[0], sizeof buf[0]),
613 c->cur.peer ? sockunion2str(&c->cur.peer->vc->remote.nbma, buf[1], sizeof buf[1]) : "-",
614 c->used ? 'U' : ' ',
615 c->t_timeout ? 'T' : ' ',
616 c->t_auth ? 'A' : ' ',
617 c->cur.peer ? c->cur.peer->vc->remote.id : "-",
618 VTY_NEWLINE);
619 }
620
621 static void show_ip_nhrp_nhs(struct nhrp_nhs *n, struct nhrp_registration *reg, void *pctx)
622 {
623 struct info_ctx *ctx = pctx;
624 struct vty *vty = ctx->vty;
625 char buf[2][SU_ADDRSTRLEN];
626
627 if (!ctx->count) {
628 vty_out(vty, "%-8s %-24s %-16s %-16s%s",
629 "Iface",
630 "FQDN",
631 "NBMA",
632 "Protocol",
633 VTY_NEWLINE);
634 }
635 ctx->count++;
636
637 vty_out(vty, "%-8s %-24s %-16s %-16s%s",
638 n->ifp->name,
639 n->nbma_fqdn,
640 (reg && reg->peer) ? sockunion2str(&reg->peer->vc->remote.nbma, buf[0], sizeof buf[0]) : "-",
641 sockunion2str(reg ? &reg->proto_addr : &n->proto_addr, buf[1], sizeof buf[1]),
642 VTY_NEWLINE);
643 }
644
645 static void show_ip_nhrp_shortcut(struct nhrp_shortcut *s, void *pctx)
646 {
647 struct info_ctx *ctx = pctx;
648 struct nhrp_cache *c;
649 struct vty *vty = ctx->vty;
650 char buf1[PREFIX_STRLEN], buf2[SU_ADDRSTRLEN];
651
652 if (!ctx->count) {
653 vty_out(vty, "%-8s %-24s %-24s %s%s",
654 "Type",
655 "Prefix",
656 "Via",
657 "Identity",
658 VTY_NEWLINE);
659 }
660 ctx->count++;
661
662 c = s->cache;
663 vty_out(ctx->vty, "%-8s %-24s %-24s %s%s",
664 nhrp_cache_type_str[s->type],
665 prefix2str(s->p, buf1, sizeof buf1),
666 c ? sockunion2str(&c->remote_addr, buf2, sizeof buf2) : "",
667 (c && c->cur.peer) ? c->cur.peer->vc->remote.id : "",
668 VTY_NEWLINE);
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_out(ctx->vty,
681 "Type: %s%s"
682 "Flags:%s%s%s"
683 "Protocol-Address: %s/%zu%s",
684 nhrp_cache_type_str[c->cur.type],
685 VTY_NEWLINE,
686 (c->cur.peer && c->cur.peer->online) ? " up": "",
687 c->used ? " used": "",
688 VTY_NEWLINE,
689 sockunion2str(&c->remote_addr, buf, sizeof buf),
690 8 * family2addrsize(sockunion_family(&c->remote_addr)),
691 VTY_NEWLINE);
692
693 if (c->cur.peer) {
694 vty_out(ctx->vty,
695 "NBMA-Address: %s%s",
696 sockunion2str(&c->cur.peer->vc->remote.nbma, buf, sizeof buf),
697 VTY_NEWLINE);
698 }
699
700 if (sockunion_family(&c->cur.remote_nbma_natoa) != AF_UNSPEC) {
701 vty_out(ctx->vty,
702 "NBMA-NAT-OA-Address: %s%s",
703 sockunion2str(&c->cur.remote_nbma_natoa, buf, sizeof buf),
704 VTY_NEWLINE);
705 }
706
707 vty_out(ctx->vty, "%s", VTY_NEWLINE);
708 }
709
710 DEFUN(show_ip_nhrp, show_ip_nhrp_cmd,
711 "show " AFI_CMD " nhrp [cache|nhs|shortcut|opennhrp]",
712 SHOW_STR
713 AFI_STR
714 "NHRP information\n"
715 "Forwarding cache information\n"
716 "Next hop server information\n"
717 "Shortcut information\n"
718 "opennhrpctl style cache dump\n")
719 {
720 struct listnode *node;
721 struct interface *ifp;
722 struct info_ctx ctx = {
723 .vty = vty,
724 .afi = cmd_to_afi(argv[1]),
725 };
726
727 if (argc <= 3 || argv[3]->text[0] == 'c') {
728 for (ALL_LIST_ELEMENTS_RO(vrf_iflist(VRF_DEFAULT), node, ifp))
729 nhrp_cache_foreach(ifp, show_ip_nhrp_cache, &ctx);
730 } else if (argv[3]->text[0] == 'n') {
731 for (ALL_LIST_ELEMENTS_RO(vrf_iflist(VRF_DEFAULT), node, ifp))
732 nhrp_nhs_foreach(ifp, ctx.afi, show_ip_nhrp_nhs, &ctx);
733 } else if (argv[3]->text[0] == 's') {
734 nhrp_shortcut_foreach(ctx.afi, show_ip_nhrp_shortcut, &ctx);
735 } else {
736 vty_out(vty, "Status: ok%s%s", VTY_NEWLINE, VTY_NEWLINE);
737 ctx.count++;
738 for (ALL_LIST_ELEMENTS_RO(vrf_iflist(VRF_DEFAULT), node, ifp))
739 nhrp_cache_foreach(ifp, show_ip_opennhrp_cache, &ctx);
740 }
741
742 if (!ctx.count) {
743 vty_out(vty, "%% No entries%s", VTY_NEWLINE);
744 return CMD_WARNING;
745 }
746
747 return CMD_SUCCESS;
748 }
749
750 static void show_dmvpn_entry(struct nhrp_vc *vc, void *ctx)
751 {
752 struct vty *vty = ctx;
753 char buf[2][SU_ADDRSTRLEN];
754
755 vty_out(vty, "%-24s %-24s %c %-4d %-24s%s",
756 sockunion2str(&vc->local.nbma, buf[0], sizeof buf[0]),
757 sockunion2str(&vc->remote.nbma, buf[1], sizeof buf[1]),
758 notifier_active(&vc->notifier_list) ? 'n' : ' ',
759 vc->ipsec,
760 vc->remote.id,
761 VTY_NEWLINE);
762 }
763
764 DEFUN(show_dmvpn, show_dmvpn_cmd,
765 "show dmvpn",
766 SHOW_STR
767 "DMVPN information\n")
768 {
769 vty_out(vty, "%-24s %-24s %-6s %-4s %-24s%s",
770 "Src",
771 "Dst",
772 "Flags",
773 "SAs",
774 "Identity",
775 VTY_NEWLINE);
776
777 nhrp_vc_foreach(show_dmvpn_entry, vty);
778
779 return CMD_SUCCESS;
780 }
781
782 static void clear_nhrp_cache(struct nhrp_cache *c, void *data)
783 {
784 struct info_ctx *ctx = data;
785 if (c->cur.type <= NHRP_CACHE_CACHED) {
786 nhrp_cache_update_binding(c, c->cur.type, -1, NULL, 0, NULL);
787 ctx->count++;
788 }
789 }
790
791 static void clear_nhrp_shortcut(struct nhrp_shortcut *s, void *data)
792 {
793 struct info_ctx *ctx = data;
794 nhrp_shortcut_purge(s, 1);
795 ctx->count++;
796 }
797
798 DEFUN(clear_nhrp, clear_nhrp_cmd,
799 "clear " AFI_CMD " nhrp <cache|shortcut>",
800 CLEAR_STR
801 AFI_STR
802 NHRP_STR
803 "Dynamic cache entries\n"
804 "Shortcut entries\n")
805 {
806 struct listnode *node;
807 struct interface *ifp;
808 struct info_ctx ctx = {
809 .vty = vty,
810 .afi = cmd_to_afi(argv[1]),
811 .count = 0,
812 };
813
814 if (argc <= 3 || argv[3]->text[0] == 'c') {
815 for (ALL_LIST_ELEMENTS_RO(vrf_iflist(VRF_DEFAULT), node, ifp))
816 nhrp_cache_foreach(ifp, clear_nhrp_cache, &ctx);
817 } else {
818 nhrp_shortcut_foreach(ctx.afi, clear_nhrp_shortcut, &ctx);
819 }
820
821 if (!ctx.count) {
822 vty_out(vty, "%% No entries%s", VTY_NEWLINE);
823 return CMD_WARNING;
824 }
825
826 vty_out(vty, "%% %d entries cleared%s", ctx.count, VTY_NEWLINE);
827 return CMD_SUCCESS;
828 }
829
830 struct write_map_ctx {
831 struct vty *vty;
832 int family;
833 const char *aficmd;
834 };
835
836 static void interface_config_write_nhrp_map(struct nhrp_cache *c, void *data)
837 {
838 struct write_map_ctx *ctx = data;
839 struct vty *vty = ctx->vty;
840 char buf[2][SU_ADDRSTRLEN];
841
842 if (!c->map) return;
843 if (sockunion_family(&c->remote_addr) != ctx->family) return;
844
845 vty_out(vty, " %s nhrp map %s %s%s",
846 ctx->aficmd,
847 sockunion2str(&c->remote_addr, buf[0], sizeof buf[0]),
848 c->cur.type == NHRP_CACHE_LOCAL ? "local" :
849 sockunion2str(&c->cur.peer->vc->remote.nbma, buf[1], sizeof buf[1]),
850 VTY_NEWLINE);
851 }
852
853 static int interface_config_write(struct vty *vty)
854 {
855 struct write_map_ctx mapctx;
856 struct listnode *node;
857 struct interface *ifp;
858 struct nhrp_interface *nifp;
859 struct nhrp_nhs *nhs;
860 const char *aficmd;
861 afi_t afi;
862 char buf[SU_ADDRSTRLEN];
863 int i;
864
865 for (ALL_LIST_ELEMENTS_RO(vrf_iflist(VRF_DEFAULT), node, ifp)) {
866 vty_out(vty, "interface %s%s", ifp->name, VTY_NEWLINE);
867 if (ifp->desc)
868 vty_out(vty, " description %s%s", ifp->desc, VTY_NEWLINE);
869
870 nifp = ifp->info;
871 if (nifp->ipsec_profile) {
872 vty_out(vty, " tunnel protection vici profile %s",
873 nifp->ipsec_profile);
874 if (nifp->ipsec_fallback_profile)
875 vty_out(vty, " fallback-profile %s",
876 nifp->ipsec_fallback_profile);
877 vty_out(vty, "%s", VTY_NEWLINE);
878 }
879 if (nifp->source)
880 vty_out(vty, " tunnel source %s%s",
881 nifp->source, VTY_NEWLINE);
882
883 for (afi = 0; afi < AFI_MAX; afi++) {
884 struct nhrp_afi_data *ad = &nifp->afi[afi];
885
886 aficmd = afi_to_cmd(afi);
887
888 if (ad->network_id)
889 vty_out(vty, " %s nhrp network-id %u%s",
890 aficmd, ad->network_id,
891 VTY_NEWLINE);
892
893 if (ad->holdtime != NHRPD_DEFAULT_HOLDTIME)
894 vty_out(vty, " %s nhrp holdtime %u%s",
895 aficmd, ad->holdtime,
896 VTY_NEWLINE);
897
898 if (ad->configured_mtu < 0)
899 vty_out(vty, " %s nhrp mtu opennhrp%s",
900 aficmd, VTY_NEWLINE);
901 else if (ad->configured_mtu)
902 vty_out(vty, " %s nhrp mtu %u%s",
903 aficmd, ad->configured_mtu,
904 VTY_NEWLINE);
905
906 for (i = 0; interface_flags_desc[i].str != NULL; i++) {
907 if (!(ad->flags & interface_flags_desc[i].key))
908 continue;
909 vty_out(vty, " %s nhrp %s%s",
910 aficmd, interface_flags_desc[i].str, VTY_NEWLINE);
911 }
912
913 mapctx = (struct write_map_ctx) {
914 .vty = vty,
915 .family = afi2family(afi),
916 .aficmd = aficmd,
917 };
918 nhrp_cache_foreach(ifp, interface_config_write_nhrp_map, &mapctx);
919
920 list_for_each_entry(nhs, &ad->nhslist_head, nhslist_entry) {
921 vty_out(vty, " %s nhrp nhs %s nbma %s%s",
922 aficmd,
923 sockunion_family(&nhs->proto_addr) == AF_UNSPEC ? "dynamic" : sockunion2str(&nhs->proto_addr, buf, sizeof buf),
924 nhs->nbma_fqdn,
925 VTY_NEWLINE);
926 }
927 }
928
929 vty_out (vty, "!%s", VTY_NEWLINE);
930 }
931
932 return 0;
933 }
934
935 void nhrp_config_init(void)
936 {
937 install_node(&zebra_node, nhrp_config_write);
938 install_default(ZEBRA_NODE);
939
940 /* access-list commands */
941 access_list_init ();
942
943 /* global commands */
944 install_element(VIEW_NODE, &show_debugging_nhrp_cmd);
945 install_element(VIEW_NODE, &show_ip_nhrp_cmd);
946 install_element(VIEW_NODE, &show_dmvpn_cmd);
947 install_element(ENABLE_NODE, &clear_nhrp_cmd);
948
949 install_element(ENABLE_NODE, &debug_nhrp_cmd);
950 install_element(ENABLE_NODE, &no_debug_nhrp_cmd);
951
952 install_element(CONFIG_NODE, &debug_nhrp_cmd);
953 install_element(CONFIG_NODE, &no_debug_nhrp_cmd);
954
955 install_element(CONFIG_NODE, &nhrp_event_socket_cmd);
956 install_element(CONFIG_NODE, &no_nhrp_event_socket_cmd);
957 install_element(CONFIG_NODE, &nhrp_nflog_group_cmd);
958 install_element(CONFIG_NODE, &no_nhrp_nflog_group_cmd);
959
960 /* interface specific commands */
961 install_node(&nhrp_interface_node, interface_config_write);
962
963 if_cmd_init();
964 install_element(INTERFACE_NODE, &tunnel_protection_cmd);
965 install_element(INTERFACE_NODE, &no_tunnel_protection_cmd);
966 install_element(INTERFACE_NODE, &tunnel_source_cmd);
967 install_element(INTERFACE_NODE, &no_tunnel_source_cmd);
968 install_element(INTERFACE_NODE, &if_nhrp_network_id_cmd);
969 install_element(INTERFACE_NODE, &if_no_nhrp_network_id_cmd);
970 install_element(INTERFACE_NODE, &if_nhrp_holdtime_cmd);
971 install_element(INTERFACE_NODE, &if_no_nhrp_holdtime_cmd);
972 install_element(INTERFACE_NODE, &if_nhrp_mtu_cmd);
973 install_element(INTERFACE_NODE, &if_no_nhrp_mtu_cmd);
974 install_element(INTERFACE_NODE, &if_nhrp_flags_cmd);
975 install_element(INTERFACE_NODE, &if_no_nhrp_flags_cmd);
976 install_element(INTERFACE_NODE, &if_nhrp_reg_flags_cmd);
977 install_element(INTERFACE_NODE, &if_no_nhrp_reg_flags_cmd);
978 install_element(INTERFACE_NODE, &if_nhrp_map_cmd);
979 install_element(INTERFACE_NODE, &if_no_nhrp_map_cmd);
980 install_element(INTERFACE_NODE, &if_nhrp_nhs_cmd);
981 install_element(INTERFACE_NODE, &if_no_nhrp_nhs_cmd);
982 }