]> git.proxmox.com Git - mirror_frr.git/blame - nhrpd/nhrp_vty.c
*: use rb-trees to store interfaces instead of sorted linked-lists
[mirror_frr.git] / nhrpd / nhrp_vty.c
CommitLineData
2fb975da
TT
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"
901fda98 14#include "filter.h"
2fb975da
TT
15
16#include "nhrpd.h"
17#include "netlink.h"
18
19static struct cmd_node zebra_node = {
20 .node = ZEBRA_NODE,
21 .prompt = "%s(config-router)# ",
22 .vtysh = 1,
23};
24
25static struct cmd_node nhrp_interface_node = {
26 .node = INTERFACE_NODE,
27 .prompt = "%s(config-if)# ",
28 .vtysh = 1,
29};
30
819dc8bb 31#define NHRP_DEBUG_FLAGS_CMD "<all|common|event|interface|kernel|route|vici>"
2fb975da
TT
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
42static 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" },
56b40679 50 { 0 }
2fb975da
TT
51};
52
53static 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" },
56b40679 57 { 0 }
2fb975da
TT
58};
59
60static 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
6c8ca260 77 if (ret > 0 && ret <= NHRP_ERR_MAX)
2fb975da
TT
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
5c7571d4 86 vty_out (vty, "%% %s\n", str);
2fb975da 87
f1a05de9 88 return CMD_WARNING_CONFIG_FAILED;;
2fb975da
TT
89}
90
91static 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
5c7571d4 107 vty_out (vty, "%% Invalid value %s\n", name);
f1a05de9 108 return CMD_WARNING_CONFIG_FAILED;;
2fb975da
TT
109}
110
111#ifndef NO_DEBUG
112
87f6dc50
DS
113DEFUN_NOSH(show_debugging_nhrp, show_debugging_nhrp_cmd,
114 "show debugging [nhrp]",
115 SHOW_STR
116 "Debugging information\n"
117 "NHRP configuration\n")
2fb975da
TT
118{
119 int i;
120
5c7571d4 121 vty_out (vty, "NHRP debugging status:\n");
2fb975da
TT
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
5c7571d4 129 vty_out (vty, " NHRP %s debugging is on\n",
96ade3ed 130 debug_flags_desc[i].str);
2fb975da
TT
131 }
132
133 return CMD_SUCCESS;
134}
135
136DEFUN(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{
819dc8bb 142 return toggle_flag(vty, debug_flags_desc, argv[2]->text, 1, &debug_flags);
2fb975da
TT
143}
144
145DEFUN(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{
819dc8bb 152 return toggle_flag(vty, debug_flags_desc, argv[3]->text, 0, &debug_flags);
2fb975da
TT
153}
154
155#endif /* NO_DEBUG */
156
157static int nhrp_config_write(struct vty *vty)
158{
159#ifndef NO_DEBUG
160 if (debug_flags == NHRP_DEBUG_ALL) {
5c7571d4 161 vty_out (vty, "debug nhrp all\n");
2fb975da
TT
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;
5c7571d4 170 vty_out (vty, "debug nhrp %s\n",
96ade3ed 171 debug_flags_desc[i].str);
2fb975da
TT
172 }
173 }
5c7571d4 174 vty_out (vty, "!\n");
2fb975da
TT
175#endif /* NO_DEBUG */
176
177 if (nhrp_event_socket_path) {
5c7571d4 178 vty_out (vty, "nhrp event socket %s\n",
96ade3ed 179 nhrp_event_socket_path);
2fb975da
TT
180 }
181 if (netlink_nflog_group) {
5c7571d4 182 vty_out (vty, "nhrp nflog-group %d\n",
96ade3ed 183 netlink_nflog_group);
2fb975da
TT
184 }
185
186 return 0;
187}
188
189#define IP_STR "IP information\n"
190#define IPV6_STR "IPv6 information\n"
819dc8bb 191#define AFI_CMD "<ip|ipv6>"
2fb975da
TT
192#define AFI_STR IP_STR IPV6_STR
193#define NHRP_STR "Next Hop Resolution Protocol functions\n"
194
819dc8bb 195static afi_t cmd_to_afi(const struct cmd_token *tok)
2fb975da 196{
819dc8bb 197 return strcmp(tok->text, "ipv6") == 0 ? AFI_IP6 : AFI_IP;
2fb975da
TT
198}
199
200static const char *afi_to_cmd(afi_t afi)
201{
202 if (afi == AFI_IP6) return "ipv6";
203 return "ip";
204}
205
206DEFUN(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"
201f6271 211 "Unix path for the socket\n")
2fb975da 212{
819dc8bb 213 evmgr_set_socket(argv[3]->arg);
2fb975da
TT
214 return CMD_SUCCESS;
215}
216
217DEFUN(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"
201f6271 223 "Unix path for the socket\n")
2fb975da
TT
224{
225 evmgr_set_socket(NULL);
226 return CMD_SUCCESS;
227}
228
229DEFUN(nhrp_nflog_group, nhrp_nflog_group_cmd,
819dc8bb 230 "nhrp nflog-group (1-65535)",
2fb975da
TT
231 NHRP_STR
232 "Specify NFLOG group number\n"
233 "NFLOG group number\n")
234{
235 uint32_t nfgroup;
236
facfee22 237 nfgroup = strtoul(argv[2]->arg, NULL, 10);
2fb975da
TT
238 netlink_set_nflog_group(nfgroup);
239
240 return CMD_SUCCESS;
241}
242
243DEFUN(no_nhrp_nflog_group, no_nhrp_nflog_group_cmd,
819dc8bb 244 "no nhrp nflog-group [(1-65535)]",
2fb975da
TT
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
254DEFUN(tunnel_protection, tunnel_protection_cmd,
819dc8bb 255 "tunnel protection vici profile PROFILE [fallback-profile FALLBACK]",
2fb975da
TT
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{
819dc8bb 264 VTY_DECLVAR_CONTEXT(interface, ifp);
2fb975da 265
819dc8bb
DL
266 nhrp_interface_set_protection(ifp, argv[4]->arg,
267 argc > 6 ? argv[6]->arg : NULL);
2fb975da
TT
268 return CMD_SUCCESS;
269}
270
271DEFUN(no_tunnel_protection, no_tunnel_protection_cmd,
272 "no tunnel protection",
273 NO_STR
274 "NHRP/GRE integration\n"
275 "IPsec protection\n")
276{
819dc8bb 277 VTY_DECLVAR_CONTEXT(interface, ifp);
2fb975da
TT
278
279 nhrp_interface_set_protection(ifp, NULL, NULL);
280 return CMD_SUCCESS;
281}
282
283DEFUN(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{
819dc8bb
DL
289 VTY_DECLVAR_CONTEXT(interface, ifp);
290 nhrp_interface_set_source(ifp, argv[2]->arg);
2fb975da
TT
291 return CMD_SUCCESS;
292}
293
294DEFUN(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{
819dc8bb 300 VTY_DECLVAR_CONTEXT(interface, ifp);
2fb975da
TT
301 nhrp_interface_set_source(ifp, NULL);
302 return CMD_SUCCESS;
303}
304
305DEFUN(if_nhrp_network_id, if_nhrp_network_id_cmd,
819dc8bb 306 AFI_CMD " nhrp network-id (1-4294967295)",
2fb975da
TT
307 AFI_STR
308 NHRP_STR
309 "Enable NHRP and specify network-id\n"
310 "System local ID to specify interface group\n")
311{
819dc8bb 312 VTY_DECLVAR_CONTEXT(interface, ifp);
2fb975da
TT
313 struct nhrp_interface *nifp = ifp->info;
314 afi_t afi = cmd_to_afi(argv[0]);
315
facfee22 316 nifp->afi[afi].network_id = strtoul(argv[3]->arg, NULL, 10);
2fb975da
TT
317 nhrp_interface_update(ifp);
318
319 return CMD_SUCCESS;
320}
321
322DEFUN(if_no_nhrp_network_id, if_no_nhrp_network_id_cmd,
819dc8bb 323 "no " AFI_CMD " nhrp network-id [(1-4294967295)]",
2fb975da
TT
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{
819dc8bb 330 VTY_DECLVAR_CONTEXT(interface, ifp);
2fb975da 331 struct nhrp_interface *nifp = ifp->info;
819dc8bb 332 afi_t afi = cmd_to_afi(argv[1]);
2fb975da
TT
333
334 nifp->afi[afi].network_id = 0;
335 nhrp_interface_update(ifp);
336
337 return CMD_SUCCESS;
338}
339
340DEFUN(if_nhrp_flags, if_nhrp_flags_cmd,
819dc8bb 341 AFI_CMD " nhrp <shortcut|redirect>",
2fb975da
TT
342 AFI_STR
343 NHRP_STR
344 "Allow shortcut establishment\n"
345 "Send redirect notifications\n")
346{
819dc8bb 347 VTY_DECLVAR_CONTEXT(interface, ifp);
2fb975da
TT
348 struct nhrp_interface *nifp = ifp->info;
349 afi_t afi = cmd_to_afi(argv[0]);
350
819dc8bb 351 return toggle_flag(vty, interface_flags_desc, argv[2]->text, 1, &nifp->afi[afi].flags);
2fb975da
TT
352}
353
354DEFUN(if_no_nhrp_flags, if_no_nhrp_flags_cmd,
819dc8bb 355 "no " AFI_CMD " nhrp <shortcut|redirect>",
2fb975da
TT
356 NO_STR
357 AFI_STR
358 NHRP_STR
359 "Allow shortcut establishment\n"
360 "Send redirect notifications\n")
361{
819dc8bb 362 VTY_DECLVAR_CONTEXT(interface, ifp);
2fb975da 363 struct nhrp_interface *nifp = ifp->info;
819dc8bb 364 afi_t afi = cmd_to_afi(argv[1]);
2fb975da 365
819dc8bb 366 return toggle_flag(vty, interface_flags_desc, argv[3]->text, 0, &nifp->afi[afi].flags);
2fb975da
TT
367}
368
369DEFUN(if_nhrp_reg_flags, if_nhrp_reg_flags_cmd,
819dc8bb 370 AFI_CMD " nhrp registration no-unique",
2fb975da
TT
371 AFI_STR
372 NHRP_STR
373 "Registration configuration\n"
374 "Don't set unique flag\n")
375{
819dc8bb 376 VTY_DECLVAR_CONTEXT(interface, ifp);
2fb975da
TT
377 struct nhrp_interface *nifp = ifp->info;
378 afi_t afi = cmd_to_afi(argv[0]);
379 char name[256];
819dc8bb 380 snprintf(name, sizeof(name), "registration %s", argv[3]->text);
2fb975da
TT
381 return toggle_flag(vty, interface_flags_desc, name, 1, &nifp->afi[afi].flags);
382}
383
384DEFUN(if_no_nhrp_reg_flags, if_no_nhrp_reg_flags_cmd,
819dc8bb 385 "no " AFI_CMD " nhrp registration no-unique",
2fb975da
TT
386 NO_STR
387 AFI_STR
388 NHRP_STR
389 "Registration configuration\n"
390 "Don't set unique flag\n")
391{
819dc8bb 392 VTY_DECLVAR_CONTEXT(interface, ifp);
2fb975da 393 struct nhrp_interface *nifp = ifp->info;
819dc8bb 394 afi_t afi = cmd_to_afi(argv[1]);
2fb975da 395 char name[256];
819dc8bb 396 snprintf(name, sizeof(name), "registration %s", argv[4]->text);
2fb975da
TT
397 return toggle_flag(vty, interface_flags_desc, name, 0, &nifp->afi[afi].flags);
398}
399
400DEFUN(if_nhrp_holdtime, if_nhrp_holdtime_cmd,
819dc8bb 401 AFI_CMD " nhrp holdtime (1-65000)",
2fb975da
TT
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{
819dc8bb 407 VTY_DECLVAR_CONTEXT(interface, ifp);
2fb975da
TT
408 struct nhrp_interface *nifp = ifp->info;
409 afi_t afi = cmd_to_afi(argv[0]);
410
facfee22 411 nifp->afi[afi].holdtime = strtoul(argv[3]->arg, NULL, 10);
2fb975da
TT
412 nhrp_interface_update(ifp);
413
414 return CMD_SUCCESS;
415}
416
417DEFUN(if_no_nhrp_holdtime, if_no_nhrp_holdtime_cmd,
819dc8bb 418 "no " AFI_CMD " nhrp holdtime [(1-65000)]",
2fb975da
TT
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{
819dc8bb 425 VTY_DECLVAR_CONTEXT(interface, ifp);
2fb975da 426 struct nhrp_interface *nifp = ifp->info;
819dc8bb 427 afi_t afi = cmd_to_afi(argv[1]);
2fb975da
TT
428
429 nifp->afi[afi].holdtime = NHRPD_DEFAULT_HOLDTIME;
430 nhrp_interface_update(ifp);
431
432 return CMD_SUCCESS;
433}
434
435DEFUN(if_nhrp_mtu, if_nhrp_mtu_cmd,
819dc8bb 436 "ip nhrp mtu <(576-1500)|opennhrp>",
2fb975da
TT
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{
819dc8bb 443 VTY_DECLVAR_CONTEXT(interface, ifp);
2fb975da
TT
444 struct nhrp_interface *nifp = ifp->info;
445
819dc8bb 446 if (argv[3]->arg[0] == 'o') {
2fb975da
TT
447 nifp->afi[AFI_IP].configured_mtu = -1;
448 } else {
facfee22
QY
449 nifp->afi[AFI_IP].configured_mtu = strtoul(argv[3]->arg, NULL,
450 10);
2fb975da
TT
451 }
452 nhrp_interface_update_mtu(ifp, AFI_IP);
453
454 return CMD_SUCCESS;
455}
456
457DEFUN(if_no_nhrp_mtu, if_no_nhrp_mtu_cmd,
819dc8bb 458 "no ip nhrp mtu [(576-1500)|opennhrp]",
2fb975da
TT
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{
819dc8bb 466 VTY_DECLVAR_CONTEXT(interface, ifp);
2fb975da
TT
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
474DEFUN(if_nhrp_map, if_nhrp_map_cmd,
819dc8bb 475 AFI_CMD " nhrp map <A.B.C.D|X:X::X:X> <A.B.C.D|local>",
2fb975da
TT
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{
819dc8bb 484 VTY_DECLVAR_CONTEXT(interface, ifp);
2fb975da
TT
485 afi_t afi = cmd_to_afi(argv[0]);
486 union sockunion proto_addr, nbma_addr;
487 struct nhrp_cache *c;
488
819dc8bb 489 if (str2sockunion(argv[3]->arg, &proto_addr) < 0 ||
2fb975da
TT
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;
7e045c3d 498 if (strmatch(argv[4]->text, "local")) {
2fb975da
TT
499 nhrp_cache_update_binding(c, NHRP_CACHE_LOCAL, 0, NULL, 0, NULL);
500 } else{
819dc8bb 501 if (str2sockunion(argv[4]->arg, &nbma_addr) < 0)
2fb975da
TT
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
2d4eab22 510DEFUN(if_no_nhrp_map, if_no_nhrp_map_cmd,
c1c17a0f 511 "no " AFI_CMD " nhrp map <A.B.C.D|X:X::X:X>",
2d4eab22
TT
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
2fb975da 536DEFUN(if_nhrp_nhs, if_nhrp_nhs_cmd,
819dc8bb 537 AFI_CMD " nhrp nhs <A.B.C.D|X:X::X:X|dynamic> nbma <A.B.C.D|FQDN>",
2fb975da
TT
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"
819dc8bb 544 "NBMA address\n"
2fb975da
TT
545 "IPv4 NBMA address\n"
546 "Fully qualified domain name for NBMA address(es)\n")
547{
819dc8bb 548 VTY_DECLVAR_CONTEXT(interface, ifp);
2fb975da
TT
549 afi_t afi = cmd_to_afi(argv[0]);
550 union sockunion proto_addr;
551 int ret;
552
819dc8bb 553 if (str2sockunion(argv[3]->arg, &proto_addr) < 0)
2fb975da
TT
554 sockunion_family(&proto_addr) = AF_UNSPEC;
555
819dc8bb 556 ret = nhrp_nhs_add(ifp, afi, &proto_addr, argv[5]->arg);
2fb975da
TT
557 return nhrp_vty_return(vty, ret);
558}
559
560DEFUN(if_no_nhrp_nhs, if_no_nhrp_nhs_cmd,
819dc8bb 561 "no " AFI_CMD " nhrp nhs <A.B.C.D|X:X::X:X|dynamic> nbma <A.B.C.D|FQDN>",
2fb975da
TT
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"
819dc8bb 569 "NBMA address\n"
2fb975da
TT
570 "IPv4 NBMA address\n"
571 "Fully qualified domain name for NBMA address(es)\n")
572{
819dc8bb
DL
573 VTY_DECLVAR_CONTEXT(interface, ifp);
574 afi_t afi = cmd_to_afi(argv[1]);
2fb975da
TT
575 union sockunion proto_addr;
576 int ret;
577
819dc8bb 578 if (str2sockunion(argv[4]->arg, &proto_addr) < 0)
2fb975da
TT
579 sockunion_family(&proto_addr) = AF_UNSPEC;
580
819dc8bb 581 ret = nhrp_nhs_del(ifp, afi, &proto_addr, argv[6]->arg);
2fb975da
TT
582 return nhrp_vty_return(vty, ret);
583}
584
585struct info_ctx {
586 struct vty *vty;
587 afi_t afi;
588 int count;
589};
590
591static 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) {
5c7571d4 601 vty_out (vty, "%-8s %-8s %-24s %-24s %-6s %s\n",
2fb975da
TT
602 "Iface",
603 "Type",
604 "Protocol",
605 "NBMA",
606 "Flags",
96ade3ed 607 "Identity");
2fb975da
TT
608 }
609 ctx->count++;
610
5c7571d4 611 vty_out(ctx->vty, "%-8s %-8s %-24s %-24s %c%c%c %s\n",
2fb975da
TT
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' : ' ',
96ade3ed 619 c->cur.peer ? c->cur.peer->vc->remote.id : "-");
2fb975da
TT
620}
621
0ca036b4
TT
622static 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) {
5c7571d4 629 vty_out (vty, "%-8s %-24s %-16s %-16s\n",
0ca036b4
TT
630 "Iface",
631 "FQDN",
632 "NBMA",
96ade3ed 633 "Protocol");
0ca036b4
TT
634 }
635 ctx->count++;
636
5c7571d4 637 vty_out (vty, "%-8s %-24s %-16s %-16s\n",
96ade3ed
QY
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]));
0ca036b4
TT
645}
646
647static 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) {
5c7571d4 655 vty_out (vty, "%-8s %-24s %-24s %s\n",
0ca036b4
TT
656 "Type",
657 "Prefix",
658 "Via",
96ade3ed 659 "Identity");
0ca036b4
TT
660 }
661 ctx->count++;
662
663 c = s->cache;
5c7571d4 664 vty_out(ctx->vty, "%-8s %-24s %-24s %s\n",
0ca036b4
TT
665 nhrp_cache_type_str[s->type],
666 prefix2str(s->p, buf1, sizeof buf1),
667 c ? sockunion2str(&c->remote_addr, buf2, sizeof buf2) : "",
96ade3ed 668 (c && c->cur.peer) ? c->cur.peer->vc->remote.id : "");
0ca036b4
TT
669}
670
2fb975da
TT
671static void show_ip_opennhrp_cache(struct nhrp_cache *c, void *pctx)
672{
673 struct info_ctx *ctx = pctx;
2fb975da
TT
674 char buf[SU_ADDRSTRLEN];
675
676 if (ctx->afi != family2afi(sockunion_family(&c->remote_addr)))
677 return;
678
181039f3 679 vty_out(ctx->vty,
625e016d
DL
680 "Type: %s\n"
681 "Flags:%s%s\n"
181039f3 682 "Protocol-Address: %s/%zu\n",
96ade3ed 683 nhrp_cache_type_str[c->cur.type],
96ade3ed
QY
684 (c->cur.peer && c->cur.peer->online) ? " up": "",
685 c->used ? " used": "",
96ade3ed
QY
686 sockunion2str(&c->remote_addr, buf, sizeof buf),
687 8 * family2addrsize(sockunion_family(&c->remote_addr)));
2fb975da
TT
688
689 if (c->cur.peer) {
5c7571d4
DL
690 vty_out(ctx->vty,
691 "NBMA-Address: %s\n",
96ade3ed
QY
692 sockunion2str(&c->cur.peer->vc->remote.nbma,
693 buf, sizeof buf));
2fb975da
TT
694 }
695
696 if (sockunion_family(&c->cur.remote_nbma_natoa) != AF_UNSPEC) {
5c7571d4
DL
697 vty_out(ctx->vty,
698 "NBMA-NAT-OA-Address: %s\n",
96ade3ed 699 sockunion2str(&c->cur.remote_nbma_natoa, buf, sizeof buf));
2fb975da
TT
700 }
701
181039f3 702 vty_out(ctx->vty, "\n\n");
2fb975da
TT
703}
704
2fb975da 705DEFUN(show_ip_nhrp, show_ip_nhrp_cmd,
0ca036b4 706 "show " AFI_CMD " nhrp [cache|nhs|shortcut|opennhrp]",
2fb975da
TT
707 SHOW_STR
708 AFI_STR
709 "NHRP information\n"
710 "Forwarding cache information\n"
0ca036b4 711 "Next hop server information\n"
2fb975da
TT
712 "Shortcut information\n"
713 "opennhrpctl style cache dump\n")
714{
f4e14fdb 715 struct vrf *vrf = vrf_lookup_by_id(VRF_DEFAULT);
2fb975da
TT
716 struct interface *ifp;
717 struct info_ctx ctx = {
718 .vty = vty,
819dc8bb 719 .afi = cmd_to_afi(argv[1]),
2fb975da
TT
720 };
721
819dc8bb 722 if (argc <= 3 || argv[3]->text[0] == 'c') {
f4e14fdb 723 RB_FOREACH (ifp, if_name_head, &vrf->ifaces_by_name)
2fb975da 724 nhrp_cache_foreach(ifp, show_ip_nhrp_cache, &ctx);
0ca036b4 725 } else if (argv[3]->text[0] == 'n') {
f4e14fdb 726 RB_FOREACH (ifp, if_name_head, &vrf->ifaces_by_name)
0ca036b4
TT
727 nhrp_nhs_foreach(ifp, ctx.afi, show_ip_nhrp_nhs, &ctx);
728 } else if (argv[3]->text[0] == 's') {
729 nhrp_shortcut_foreach(ctx.afi, show_ip_nhrp_shortcut, &ctx);
730 } else {
61b7d449 731 vty_out (vty, "Status: ok\n\n");
2fb975da 732 ctx.count++;
f4e14fdb 733 RB_FOREACH (ifp, if_name_head, &vrf->ifaces_by_name)
2fb975da 734 nhrp_cache_foreach(ifp, show_ip_opennhrp_cache, &ctx);
2fb975da
TT
735 }
736
737 if (!ctx.count) {
5c7571d4 738 vty_out (vty, "%% No entries\n");
2fb975da
TT
739 return CMD_WARNING;
740 }
741
742 return CMD_SUCCESS;
743}
744
745static void show_dmvpn_entry(struct nhrp_vc *vc, void *ctx)
746{
747 struct vty *vty = ctx;
748 char buf[2][SU_ADDRSTRLEN];
749
5c7571d4 750 vty_out (vty, "%-24s %-24s %c %-4d %-24s\n",
2fb975da
TT
751 sockunion2str(&vc->local.nbma, buf[0], sizeof buf[0]),
752 sockunion2str(&vc->remote.nbma, buf[1], sizeof buf[1]),
753 notifier_active(&vc->notifier_list) ? 'n' : ' ',
754 vc->ipsec,
96ade3ed 755 vc->remote.id);
2fb975da
TT
756}
757
758DEFUN(show_dmvpn, show_dmvpn_cmd,
759 "show dmvpn",
760 SHOW_STR
761 "DMVPN information\n")
762{
5c7571d4 763 vty_out (vty, "%-24s %-24s %-6s %-4s %-24s\n",
2fb975da
TT
764 "Src",
765 "Dst",
766 "Flags",
767 "SAs",
96ade3ed 768 "Identity");
2fb975da
TT
769
770 nhrp_vc_foreach(show_dmvpn_entry, vty);
771
772 return CMD_SUCCESS;
773}
774
775static void clear_nhrp_cache(struct nhrp_cache *c, void *data)
776{
777 struct info_ctx *ctx = data;
778 if (c->cur.type <= NHRP_CACHE_CACHED) {
779 nhrp_cache_update_binding(c, c->cur.type, -1, NULL, 0, NULL);
780 ctx->count++;
781 }
782}
783
784static void clear_nhrp_shortcut(struct nhrp_shortcut *s, void *data)
785{
786 struct info_ctx *ctx = data;
787 nhrp_shortcut_purge(s, 1);
788 ctx->count++;
789}
790
791DEFUN(clear_nhrp, clear_nhrp_cmd,
819dc8bb 792 "clear " AFI_CMD " nhrp <cache|shortcut>",
2fb975da
TT
793 CLEAR_STR
794 AFI_STR
795 NHRP_STR
796 "Dynamic cache entries\n"
797 "Shortcut entries\n")
798{
f4e14fdb 799 struct vrf *vrf = vrf_lookup_by_id(VRF_DEFAULT);
2fb975da
TT
800 struct interface *ifp;
801 struct info_ctx ctx = {
802 .vty = vty,
819dc8bb 803 .afi = cmd_to_afi(argv[1]),
2fb975da
TT
804 .count = 0,
805 };
806
819dc8bb 807 if (argc <= 3 || argv[3]->text[0] == 'c') {
f4e14fdb 808 RB_FOREACH (ifp, if_name_head, &vrf->ifaces_by_name)
2fb975da
TT
809 nhrp_cache_foreach(ifp, clear_nhrp_cache, &ctx);
810 } else {
811 nhrp_shortcut_foreach(ctx.afi, clear_nhrp_shortcut, &ctx);
812 }
813
814 if (!ctx.count) {
5c7571d4 815 vty_out (vty, "%% No entries\n");
2fb975da
TT
816 return CMD_WARNING;
817 }
818
5c7571d4 819 vty_out (vty, "%% %d entries cleared\n", ctx.count);
2fb975da
TT
820 return CMD_SUCCESS;
821}
822
823struct write_map_ctx {
824 struct vty *vty;
825 int family;
826 const char *aficmd;
827};
828
829static void interface_config_write_nhrp_map(struct nhrp_cache *c, void *data)
830{
831 struct write_map_ctx *ctx = data;
832 struct vty *vty = ctx->vty;
833 char buf[2][SU_ADDRSTRLEN];
834
835 if (!c->map) return;
836 if (sockunion_family(&c->remote_addr) != ctx->family) return;
837
5c7571d4 838 vty_out (vty, " %s nhrp map %s %s\n",
2fb975da
TT
839 ctx->aficmd,
840 sockunion2str(&c->remote_addr, buf[0], sizeof buf[0]),
96ade3ed 841 c->cur.type == NHRP_CACHE_LOCAL ? "local" : sockunion2str(&c->cur.peer->vc->remote.nbma, buf[1], sizeof buf[1]));
2fb975da
TT
842}
843
844static int interface_config_write(struct vty *vty)
845{
f4e14fdb 846 struct vrf *vrf = vrf_lookup_by_id(VRF_DEFAULT);
2fb975da 847 struct write_map_ctx mapctx;
2fb975da
TT
848 struct interface *ifp;
849 struct nhrp_interface *nifp;
850 struct nhrp_nhs *nhs;
851 const char *aficmd;
852 afi_t afi;
853 char buf[SU_ADDRSTRLEN];
854 int i;
855
f4e14fdb 856 RB_FOREACH (ifp, if_name_head, &vrf->ifaces_by_name) {
a8b828f3 857 vty_frame(vty, "interface %s\n", ifp->name);
2fb975da 858 if (ifp->desc)
5c7571d4 859 vty_out (vty, " description %s\n", ifp->desc);
2fb975da
TT
860
861 nifp = ifp->info;
862 if (nifp->ipsec_profile) {
863 vty_out(vty, " tunnel protection vici profile %s",
864 nifp->ipsec_profile);
865 if (nifp->ipsec_fallback_profile)
866 vty_out(vty, " fallback-profile %s",
867 nifp->ipsec_fallback_profile);
6d3c2ed4 868 vty_out (vty, "\n");
2fb975da
TT
869 }
870 if (nifp->source)
5c7571d4 871 vty_out (vty, " tunnel source %s\n",
96ade3ed 872 nifp->source);
2fb975da
TT
873
874 for (afi = 0; afi < AFI_MAX; afi++) {
875 struct nhrp_afi_data *ad = &nifp->afi[afi];
876
877 aficmd = afi_to_cmd(afi);
878
879 if (ad->network_id)
5c7571d4 880 vty_out (vty, " %s nhrp network-id %u\n",
96ade3ed 881 aficmd,ad->network_id);
2fb975da
TT
882
883 if (ad->holdtime != NHRPD_DEFAULT_HOLDTIME)
5c7571d4 884 vty_out (vty, " %s nhrp holdtime %u\n",
96ade3ed 885 aficmd,ad->holdtime);
2fb975da
TT
886
887 if (ad->configured_mtu < 0)
5c7571d4 888 vty_out (vty, " %s nhrp mtu opennhrp\n",
96ade3ed 889 aficmd);
2fb975da 890 else if (ad->configured_mtu)
5c7571d4 891 vty_out (vty, " %s nhrp mtu %u\n",
96ade3ed 892 aficmd,ad->configured_mtu);
2fb975da
TT
893
894 for (i = 0; interface_flags_desc[i].str != NULL; i++) {
895 if (!(ad->flags & interface_flags_desc[i].key))
896 continue;
5c7571d4 897 vty_out (vty, " %s nhrp %s\n",
96ade3ed 898 aficmd, interface_flags_desc[i].str);
2fb975da
TT
899 }
900
901 mapctx = (struct write_map_ctx) {
902 .vty = vty,
903 .family = afi2family(afi),
904 .aficmd = aficmd,
905 };
906 nhrp_cache_foreach(ifp, interface_config_write_nhrp_map, &mapctx);
907
908 list_for_each_entry(nhs, &ad->nhslist_head, nhslist_entry) {
5c7571d4 909 vty_out (vty, " %s nhrp nhs %s nbma %s\n",
2fb975da
TT
910 aficmd,
911 sockunion_family(&nhs->proto_addr) == AF_UNSPEC ? "dynamic" : sockunion2str(&nhs->proto_addr, buf, sizeof buf),
96ade3ed 912 nhs->nbma_fqdn);
2fb975da
TT
913 }
914 }
915
a8b828f3 916 vty_endframe(vty, "!\n");
2fb975da
TT
917 }
918
919 return 0;
920}
921
922void nhrp_config_init(void)
923{
924 install_node(&zebra_node, nhrp_config_write);
925 install_default(ZEBRA_NODE);
926
d2057ea3
QY
927 /* access-list commands */
928 access_list_init ();
929
2fb975da
TT
930 /* global commands */
931 install_element(VIEW_NODE, &show_debugging_nhrp_cmd);
932 install_element(VIEW_NODE, &show_ip_nhrp_cmd);
933 install_element(VIEW_NODE, &show_dmvpn_cmd);
2fb975da
TT
934 install_element(ENABLE_NODE, &clear_nhrp_cmd);
935
936 install_element(ENABLE_NODE, &debug_nhrp_cmd);
937 install_element(ENABLE_NODE, &no_debug_nhrp_cmd);
938
939 install_element(CONFIG_NODE, &debug_nhrp_cmd);
940 install_element(CONFIG_NODE, &no_debug_nhrp_cmd);
941
942 install_element(CONFIG_NODE, &nhrp_event_socket_cmd);
943 install_element(CONFIG_NODE, &no_nhrp_event_socket_cmd);
944 install_element(CONFIG_NODE, &nhrp_nflog_group_cmd);
945 install_element(CONFIG_NODE, &no_nhrp_nflog_group_cmd);
946
947 /* interface specific commands */
948 install_node(&nhrp_interface_node, interface_config_write);
2fb975da 949
819dc8bb 950 if_cmd_init();
2fb975da
TT
951 install_element(INTERFACE_NODE, &tunnel_protection_cmd);
952 install_element(INTERFACE_NODE, &no_tunnel_protection_cmd);
953 install_element(INTERFACE_NODE, &tunnel_source_cmd);
954 install_element(INTERFACE_NODE, &no_tunnel_source_cmd);
955 install_element(INTERFACE_NODE, &if_nhrp_network_id_cmd);
956 install_element(INTERFACE_NODE, &if_no_nhrp_network_id_cmd);
957 install_element(INTERFACE_NODE, &if_nhrp_holdtime_cmd);
958 install_element(INTERFACE_NODE, &if_no_nhrp_holdtime_cmd);
959 install_element(INTERFACE_NODE, &if_nhrp_mtu_cmd);
960 install_element(INTERFACE_NODE, &if_no_nhrp_mtu_cmd);
961 install_element(INTERFACE_NODE, &if_nhrp_flags_cmd);
962 install_element(INTERFACE_NODE, &if_no_nhrp_flags_cmd);
963 install_element(INTERFACE_NODE, &if_nhrp_reg_flags_cmd);
964 install_element(INTERFACE_NODE, &if_no_nhrp_reg_flags_cmd);
965 install_element(INTERFACE_NODE, &if_nhrp_map_cmd);
2d4eab22 966 install_element(INTERFACE_NODE, &if_no_nhrp_map_cmd);
2fb975da
TT
967 install_element(INTERFACE_NODE, &if_nhrp_nhs_cmd);
968 install_element(INTERFACE_NODE, &if_no_nhrp_nhs_cmd);
969}