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