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