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