1 /* NHRP vty handling
2 * Copyright (c) 2014-2015 Timo Teräs
3 *
4 * This file is free software: you may copy, redistribute and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation, either version 2 of the License, or
7 * (at your option) any later version.
8 */
9
10 #include "zebra.h"
11 #include "command.h"
12 #include "zclient.h"
13 #include "stream.h"
14
15 #include "nhrpd.h"
16 #include "netlink.h"
17
18 static struct cmd_node zebra_node = {
19 .node = ZEBRA_NODE,
20 .prompt = "%s(config-router)# ",
21 .vtysh = 1,
22 };
23
24 static struct cmd_node nhrp_interface_node = {
25 .node = INTERFACE_NODE,
26 .prompt = "%s(config-if)# ",
27 .vtysh = 1,
28 };
29
30 #define NHRP_DEBUG_FLAGS_CMD "(all|common|event|interface|kernel|route|vici)"
31
32 #define NHRP_DEBUG_FLAGS_STR \
33 "All messages\n" \
34 "Common messages (default)\n" \
35 "Event manager messages\n" \
36 "Interface messages\n" \
37 "Kernel messages\n" \
38 "Route messages\n" \
39 "VICI messages\n"
40
41 static const struct message debug_flags_desc[] = {
42 { NHRP_DEBUG_ALL, "all" },
43 { NHRP_DEBUG_COMMON, "common" },
44 { NHRP_DEBUG_IF, "interface" },
45 { NHRP_DEBUG_KERNEL, "kernel" },
46 { NHRP_DEBUG_ROUTE, "route" },
47 { NHRP_DEBUG_VICI, "vici" },
48 { NHRP_DEBUG_EVENT, "event" },
49 { 0, NULL },
50 };
51
52 static const struct message interface_flags_desc[] = {
53 { NHRP_IFF_SHORTCUT, "shortcut" },
54 { NHRP_IFF_REDIRECT, "redirect" },
55 { NHRP_IFF_REG_NO_UNIQUE, "registration no-unique" },
56 { 0, NULL },
57 };
58
nhrp_vty_return(struct vty * vty,int ret)59 static int nhrp_vty_return(struct vty *vty, int ret)
60 {
61 static const char * const errmsgs[] = {
62 [NHRP_ERR_FAIL] = "Command failed",
63 [NHRP_ERR_NO_MEMORY] = "Out of memory",
64 [NHRP_ERR_UNSUPPORTED_INTERFACE] = "NHRP not supported on this interface",
65 [NHRP_ERR_NHRP_NOT_ENABLED] = "NHRP not enabled (set 'nhrp network-id' first)",
66 [NHRP_ERR_ENTRY_EXISTS] = "Entry exists already",
67 [NHRP_ERR_ENTRY_NOT_FOUND] = "Entry not found",
68 [NHRP_ERR_PROTOCOL_ADDRESS_MISMATCH] = "Protocol address family does not match command (ip/ipv6 mismatch)",
69 };
70 const char *str = NULL;
71 char buf[256];
72
73 if (ret == NHRP_OK)
74 return CMD_SUCCESS;
75
76 if (ret > 0 && ret <= (int)ZEBRA_NUM_OF(errmsgs))
77 if (errmsgs[ret])
78 str = errmsgs[ret];
79
80 if (!str) {
81 str = buf;
82 snprintf(buf, sizeof(buf), "Unknown error %d", ret);
83 }
84
85 vty_out (vty, "%% %s%s", str, VTY_NEWLINE);
86
87 return CMD_WARNING;
88 }
89
toggle_flag(struct vty * vty,const struct message * flag_desc,const char * name,int on_off,unsigned * flags)90 static int toggle_flag(
91 struct vty *vty, const struct message *flag_desc,
92 const char *name, int on_off, unsigned *flags)
93 {
94 int i;
95
96 for (i = 0; flag_desc[i].str != NULL; i++) {
97 if (strcmp(flag_desc[i].str, name) != 0)
98 continue;
99 if (on_off)
100 *flags |= flag_desc[i].key;
101 else
102 *flags &= ~flag_desc[i].key;
103 return CMD_SUCCESS;
104 }
105
106 vty_out(vty, "%% Invalid value %s%s", name, VTY_NEWLINE);
107 return CMD_WARNING;
108 }
109
110 #ifndef NO_DEBUG
111
112 DEFUN(show_debugging_nhrp, show_debugging_nhrp_cmd,
113 "show debugging nhrp",
114 SHOW_STR
115 "Debugging information\n"
116 "NHRP configuration\n")
117 {
118 int i;
119
120 vty_out(vty, "NHRP debugging status:%s", VTY_NEWLINE);
121
122 for (i = 0; debug_flags_desc[i].str != NULL; i++) {
123 if (debug_flags_desc[i].key == NHRP_DEBUG_ALL)
124 continue;
125 if (!(debug_flags_desc[i].key & debug_flags))
126 continue;
127
128 vty_out(vty, " NHRP %s debugging is on%s",
129 debug_flags_desc[i].str, VTY_NEWLINE);
130 }
131
132 return CMD_SUCCESS;
133 }
134
135 DEFUN(debug_nhrp, debug_nhrp_cmd,
136 "debug nhrp " NHRP_DEBUG_FLAGS_CMD,
137 "Enable debug messages for specific or all parts.\n"
138 "NHRP information\n"
139 NHRP_DEBUG_FLAGS_STR)
140 {
141 return toggle_flag(vty, debug_flags_desc, argv[0], 1, &debug_flags);
142 }
143
144 DEFUN(no_debug_nhrp, no_debug_nhrp_cmd,
145 "no debug nhrp " NHRP_DEBUG_FLAGS_CMD,
146 NO_STR
147 "Disable debug messages for specific or all parts.\n"
148 "NHRP information\n"
149 NHRP_DEBUG_FLAGS_STR)
150 {
151 return toggle_flag(vty, debug_flags_desc, argv[0], 0, &debug_flags);
152 }
153
154 #endif /* NO_DEBUG */
155
nhrp_config_write(struct vty * vty)156 static int nhrp_config_write(struct vty *vty)
157 {
158 #ifndef NO_DEBUG
159 if (debug_flags == NHRP_DEBUG_ALL) {
160 vty_out(vty, "debug nhrp all%s", VTY_NEWLINE);
161 } else {
162 int i;
163
164 for (i = 0; debug_flags_desc[i].str != NULL; i++) {
165 if (debug_flags_desc[i].key == NHRP_DEBUG_ALL)
166 continue;
167 if (!(debug_flags & debug_flags_desc[i].key))
168 continue;
169 vty_out(vty, "debug nhrp %s%s", debug_flags_desc[i].str, VTY_NEWLINE);
170 }
171 }
172 vty_out(vty, "!%s", VTY_NEWLINE);
173 #endif /* NO_DEBUG */
174
175 if (nhrp_event_socket_path) {
176 vty_out(vty, "nhrp event socket %s%s",
177 nhrp_event_socket_path, VTY_NEWLINE);
178 }
179 if (netlink_nflog_group) {
180 vty_out(vty, "nhrp nflog-group %d%s",
181 netlink_nflog_group, VTY_NEWLINE);
182 }
183
184 return 0;
185 }
186
187 #define IP_STR "IP information\n"
188 #define IPV6_STR "IPv6 information\n"
189 #define AFI_CMD "(ip|ipv6)"
190 #define AFI_STR IP_STR IPV6_STR
191 #define NHRP_STR "Next Hop Resolution Protocol functions\n"
192
cmd_to_afi(const char * cmd)193 static afi_t cmd_to_afi(const char *cmd)
194 {
195 return strncmp(cmd, "ipv6", 4) == 0 ? AFI_IP6 : AFI_IP;
196 }
197
afi_to_cmd(afi_t afi)198 static const char *afi_to_cmd(afi_t afi)
199 {
200 if (afi == AFI_IP6) return "ipv6";
201 return "ip";
202 }
203
204 DEFUN(nhrp_event_socket, nhrp_event_socket_cmd,
205 "nhrp event socket SOCKET",
206 NHRP_STR
207 "Event Manager commands\n"
208 "Event Manager unix socket path\n"
209 "Unix path for the socket\n")
210 {
211 evmgr_set_socket(argv[0]);
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 VTY_GET_INTEGER_RANGE("nflog-group", nfgroup, argv[0], 1, 65535);
236 netlink_set_nflog_group(nfgroup);
237
238 return CMD_SUCCESS;
239 }
240
241 DEFUN(no_nhrp_nflog_group, no_nhrp_nflog_group_cmd,
242 "no nhrp nflog-group [<1-65535>]",
243 NO_STR
244 NHRP_STR
245 "Specify NFLOG group number\n"
246 "NFLOG group number\n")
247 {
248 netlink_set_nflog_group(0);
249 return CMD_SUCCESS;
250 }
251
252 DEFUN(tunnel_protection, tunnel_protection_cmd,
253 "tunnel protection vici profile PROFILE {fallback-profile FALLBACK}",
254 "NHRP/GRE integration\n"
255 "IPsec protection\n"
256 "VICI (StrongSwan)\n"
257 "IPsec profile\n"
258 "IPsec profile name\n"
259 "Fallback IPsec profile\n"
260 "Fallback IPsec profile name\n")
261 {
262 struct interface *ifp = vty->index;
263
264 nhrp_interface_set_protection(ifp, argv[0], argv[1]);
265 return CMD_SUCCESS;
266 }
267
268 DEFUN(no_tunnel_protection, no_tunnel_protection_cmd,
269 "no tunnel protection",
270 NO_STR
271 "NHRP/GRE integration\n"
272 "IPsec protection\n")
273 {
274 struct interface *ifp = vty->index;
275
276 nhrp_interface_set_protection(ifp, NULL, NULL);
277 return CMD_SUCCESS;
278 }
279
280 DEFUN(tunnel_source, tunnel_source_cmd,
281 "tunnel source INTERFACE",
282 "NHRP/GRE integration\n"
283 "Tunnel device binding tracking\n"
284 "Interface name\n")
285 {
286 struct interface *ifp = vty->index;
287 nhrp_interface_set_source(ifp, argv[0]);
288 return CMD_SUCCESS;
289 }
290
291 DEFUN(no_tunnel_source, no_tunnel_source_cmd,
292 "no tunnel source",
293 "NHRP/GRE integration\n"
294 "Tunnel device binding tracking\n"
295 "Interface name\n")
296 {
297 struct interface *ifp = vty->index;
298 nhrp_interface_set_source(ifp, NULL);
299 return CMD_SUCCESS;
300 }
301
302 DEFUN(if_nhrp_network_id, if_nhrp_network_id_cmd,
303 AFI_CMD " nhrp network-id <1-4294967295>",
304 AFI_STR
305 NHRP_STR
306 "Enable NHRP and specify network-id\n"
307 "System local ID to specify interface group\n")
308 {
309 struct interface *ifp = vty->index;
310 struct nhrp_interface *nifp = ifp->info;
311 afi_t afi = cmd_to_afi(argv[0]);
312
313 VTY_GET_INTEGER_RANGE("network-id", nifp->afi[afi].network_id, argv[1], 1, 4294967295);
314 nhrp_interface_update(ifp);
315
316 return CMD_SUCCESS;
317 }
318
319 DEFUN(if_no_nhrp_network_id, if_no_nhrp_network_id_cmd,
320 "no " AFI_CMD " nhrp network-id [<1-4294967295>]",
321 NO_STR
322 AFI_STR
323 NHRP_STR
324 "Enable NHRP and specify network-id\n"
325 "System local ID to specify interface group\n")
326 {
327 struct interface *ifp = vty->index;
328 struct nhrp_interface *nifp = ifp->info;
329 afi_t afi = cmd_to_afi(argv[0]);
330
331 nifp->afi[afi].network_id = 0;
332 nhrp_interface_update(ifp);
333
334 return CMD_SUCCESS;
335 }
336
337 DEFUN(if_nhrp_flags, if_nhrp_flags_cmd,
338 AFI_CMD " nhrp (shortcut|redirect)",
339 AFI_STR
340 NHRP_STR
341 "Allow shortcut establishment\n"
342 "Send redirect notifications\n")
343 {
344 struct interface *ifp = vty->index;
345 struct nhrp_interface *nifp = ifp->info;
346 afi_t afi = cmd_to_afi(argv[0]);
347
348 return toggle_flag(vty, interface_flags_desc, argv[1], 1, &nifp->afi[afi].flags);
349 }
350
351 DEFUN(if_no_nhrp_flags, if_no_nhrp_flags_cmd,
352 "no " AFI_CMD " nhrp (shortcut|redirect)",
353 NO_STR
354 AFI_STR
355 NHRP_STR
356 "Allow shortcut establishment\n"
357 "Send redirect notifications\n")
358 {
359 struct interface *ifp = vty->index;
360 struct nhrp_interface *nifp = ifp->info;
361 afi_t afi = cmd_to_afi(argv[0]);
362
363 return toggle_flag(vty, interface_flags_desc, argv[1], 0, &nifp->afi[afi].flags);
364 }
365
366 DEFUN(if_nhrp_reg_flags, if_nhrp_reg_flags_cmd,
367 AFI_CMD " nhrp registration (no-unique)",
368 AFI_STR
369 NHRP_STR
370 "Registration configuration\n"
371 "Don't set unique flag\n")
372 {
373 struct interface *ifp = vty->index;
374 struct nhrp_interface *nifp = ifp->info;
375 afi_t afi = cmd_to_afi(argv[0]);
376 char name[256];
377 snprintf(name, sizeof(name), "registration %s", argv[1]);
378 return toggle_flag(vty, interface_flags_desc, name, 1, &nifp->afi[afi].flags);
379 }
380
381 DEFUN(if_no_nhrp_reg_flags, if_no_nhrp_reg_flags_cmd,
382 "no " AFI_CMD " nhrp registration (no-unique)",
383 NO_STR
384 AFI_STR
385 NHRP_STR
386 "Registration configuration\n"
387 "Don't set unique flag\n")
388 {
389 struct interface *ifp = vty->index;
390 struct nhrp_interface *nifp = ifp->info;
391 afi_t afi = cmd_to_afi(argv[0]);
392 char name[256];
393 snprintf(name, sizeof(name), "registration %s", argv[1]);
394 return toggle_flag(vty, interface_flags_desc, name, 0, &nifp->afi[afi].flags);
395 }
396
397 DEFUN(if_nhrp_holdtime, if_nhrp_holdtime_cmd,
398 AFI_CMD " nhrp holdtime <1-65000>",
399 AFI_STR
400 NHRP_STR
401 "Specify NBMA address validity time\n"
402 "Time in seconds that NBMA addresses are advertised valid\n")
403 {
404 struct interface *ifp = vty->index;
405 struct nhrp_interface *nifp = ifp->info;
406 afi_t afi = cmd_to_afi(argv[0]);
407
408 VTY_GET_INTEGER_RANGE("holdtime", nifp->afi[afi].holdtime, argv[1], 1, 65000);
409 nhrp_interface_update(ifp);
410
411 return CMD_SUCCESS;
412 }
413
414 DEFUN(if_no_nhrp_holdtime, if_no_nhrp_holdtime_cmd,
415 "no " AFI_CMD " nhrp holdtime [1-65000]",
416 NO_STR
417 AFI_STR
418 NHRP_STR
419 "Specify NBMA address validity time\n"
420 "Time in seconds that NBMA addresses are advertised valid\n")
421 {
422 struct interface *ifp = vty->index;
423 struct nhrp_interface *nifp = ifp->info;
424 afi_t afi = cmd_to_afi(argv[0]);
425
426 nifp->afi[afi].holdtime = NHRPD_DEFAULT_HOLDTIME;
427 nhrp_interface_update(ifp);
428
429 return CMD_SUCCESS;
430 }
431
432 DEFUN(if_nhrp_mtu, if_nhrp_mtu_cmd,
433 "ip nhrp mtu (<576-1500>|opennhrp)",
434 IP_STR
435 NHRP_STR
436 "Configure NHRP advertised MTU\n"
437 "MTU value\n"
438 "Advertise bound interface MTU similar to OpenNHRP")
439 {
440 struct interface *ifp = vty->index;
441 struct nhrp_interface *nifp = ifp->info;
442
443 if (argv[0][0] == 'o') {
444 nifp->afi[AFI_IP].configured_mtu = -1;
445 } else {
446 VTY_GET_INTEGER_RANGE("mtu", nifp->afi[AFI_IP].configured_mtu, argv[0], 576, 1500);
447 }
448 nhrp_interface_update_mtu(ifp, AFI_IP);
449
450 return CMD_SUCCESS;
451 }
452
453 DEFUN(if_no_nhrp_mtu, if_no_nhrp_mtu_cmd,
454 "no ip nhrp mtu [(<576-1500>|opennhrp)]",
455 NO_STR
456 IP_STR
457 NHRP_STR
458 "Configure NHRP advertised MTU\n"
459 "MTU value\n"
460 "Advertise bound interface MTU similar to OpenNHRP")
461 {
462 struct interface *ifp = vty->index;
463 struct nhrp_interface *nifp = ifp->info;
464
465 nifp->afi[AFI_IP].configured_mtu = 0;
466 nhrp_interface_update_mtu(ifp, AFI_IP);
467 return CMD_SUCCESS;
468 }
469
470 DEFUN(if_nhrp_map, if_nhrp_map_cmd,
471 AFI_CMD " nhrp map (A.B.C.D|X:X::X:X) (A.B.C.D|local)",
472 AFI_STR
473 NHRP_STR
474 "Nexthop Server configuration\n"
475 "IPv4 protocol address\n"
476 "IPv6 protocol address\n"
477 "IPv4 NBMA address\n"
478 "Handle protocol address locally\n")
479 {
480 struct interface *ifp = vty->index;
481 afi_t afi = cmd_to_afi(argv[0]);
482 union sockunion proto_addr, nbma_addr;
483 struct nhrp_cache *c;
484
485 if (str2sockunion(argv[1], &proto_addr) < 0 ||
486 afi2family(afi) != sockunion_family(&proto_addr))
487 return nhrp_vty_return(vty, NHRP_ERR_PROTOCOL_ADDRESS_MISMATCH);
488
489 c = nhrp_cache_get(ifp, &proto_addr, 1);
490 if (!c)
491 return nhrp_vty_return(vty, NHRP_ERR_FAIL);
492
493 c->map = 1;
494 if (strcmp(argv[2], "local") == 0) {
495 nhrp_cache_update_binding(c, NHRP_CACHE_LOCAL, 0, NULL, 0, NULL);
496 } else{
497 if (str2sockunion(argv[2], &nbma_addr) < 0)
498 return nhrp_vty_return(vty, NHRP_ERR_FAIL);
499 nhrp_cache_update_binding(c, NHRP_CACHE_STATIC, 0,
500 nhrp_peer_get(ifp, &nbma_addr), 0, NULL);
501 }
502
503 return CMD_SUCCESS;
504 }
505
506 DEFUN(if_no_nhrp_map, if_no_nhrp_map_cmd,
507 "no " AFI_CMD " nhrp map (A.B.C.D|X:X::X:X)",
508 NO_STR
509 AFI_STR
510 NHRP_STR
511 "Nexthop Server configuration\n"
512 "IPv4 protocol address\n"
513 "IPv6 protocol address\n")
514 {
515 struct interface *ifp = vty->index;
516 afi_t afi = cmd_to_afi(argv[0]);
517 union sockunion proto_addr;
518 struct nhrp_cache *c;
519
520 if (str2sockunion(argv[1], &proto_addr) < 0 ||
521 afi2family(afi) != sockunion_family(&proto_addr))
522 return nhrp_vty_return(vty, NHRP_ERR_PROTOCOL_ADDRESS_MISMATCH);
523
524 c = nhrp_cache_get(ifp, &proto_addr, 0);
525 if (!c || !c->map)
526 return nhrp_vty_return(vty, NHRP_ERR_ENTRY_NOT_FOUND);
527
528 nhrp_cache_update_binding(c, c->cur.type, -1, NULL, 0, NULL);
529 return CMD_SUCCESS;
530 }
531
532 DEFUN(if_nhrp_nhs, if_nhrp_nhs_cmd,
533 AFI_CMD " nhrp nhs (A.B.C.D|X:X::X:X|dynamic) nbma (A.B.C.D|FQDN)",
534 AFI_STR
535 NHRP_STR
536 "Nexthop Server configuration\n"
537 "IPv4 protocol address\n"
538 "IPv6 protocol address\n"
539 "Automatic detection of protocol address\n"
540 "IPv4 NBMA address\n"
541 "Fully qualified domain name for NBMA address(es)\n")
542 {
543 struct interface *ifp = vty->index;
544 afi_t afi = cmd_to_afi(argv[0]);
545 union sockunion proto_addr;
546 int ret;
547
548 if (str2sockunion(argv[1], &proto_addr) < 0)
549 sockunion_family(&proto_addr) = AF_UNSPEC;
550
551 ret = nhrp_nhs_add(ifp, afi, &proto_addr, argv[2]);
552 return nhrp_vty_return(vty, ret);
553 }
554
555 DEFUN(if_no_nhrp_nhs, if_no_nhrp_nhs_cmd,
556 "no " AFI_CMD " nhrp nhs (A.B.C.D|X:X::X:X|dynamic) nbma (A.B.C.D|FQDN)",
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 "Automatic detection of protocol address\n"
564 "IPv4 NBMA address\n"
565 "Fully qualified domain name for NBMA address(es)\n")
566 {
567 struct interface *ifp = vty->index;
568 afi_t afi = cmd_to_afi(argv[0]);
569 union sockunion proto_addr;
570 int ret;
571
572 if (str2sockunion(argv[1], &proto_addr) < 0)
573 sockunion_family(&proto_addr) = AF_UNSPEC;
574
575 ret = nhrp_nhs_del(ifp, afi, &proto_addr, argv[2]);
576 return nhrp_vty_return(vty, ret);
577 }
578
579 struct info_ctx {
580 struct vty *vty;
581 afi_t afi;
582 int count;
583 };
584
show_ip_nhrp_cache(struct nhrp_cache * c,void * pctx)585 static void show_ip_nhrp_cache(struct nhrp_cache *c, void *pctx)
586 {
587 struct info_ctx *ctx = pctx;
588 struct vty *vty = ctx->vty;
589 char buf[2][SU_ADDRSTRLEN];
590
591 if (ctx->afi != family2afi(sockunion_family(&c->remote_addr)))
592 return;
593
594 if (!ctx->count) {
595 vty_out(vty, "%-8s %-8s %-24s %-24s %-6s %s%s",
596 "Iface",
597 "Type",
598 "Protocol",
599 "NBMA",
600 "Flags",
601 "Identity",
602 VTY_NEWLINE);
603 }
604 ctx->count++;
605
606 vty_out(ctx->vty, "%-8s %-8s %-24s %-24s %c%c%c %s%s",
607 c->ifp->name,
608 nhrp_cache_type_str[c->cur.type],
609 sockunion2str(&c->remote_addr, buf[0], sizeof buf[0]),
610 c->cur.peer ? sockunion2str(&c->cur.peer->vc->remote.nbma, buf[1], sizeof buf[1]) : "-",
611 c->used ? 'U' : ' ',
612 c->t_timeout ? 'T' : ' ',
613 c->t_auth ? 'A' : ' ',
614 c->cur.peer ? c->cur.peer->vc->remote.id : "-",
615 VTY_NEWLINE);
616 }
617
show_ip_nhrp_nhs(struct nhrp_nhs * n,struct nhrp_registration * reg,void * pctx)618 static void show_ip_nhrp_nhs(struct nhrp_nhs *n, struct nhrp_registration *reg, void *pctx)
619 {
620 struct info_ctx *ctx = pctx;
621 struct vty *vty = ctx->vty;
622 char buf[2][SU_ADDRSTRLEN];
623
624 if (!ctx->count) {
625 vty_out(vty, "%-8s %-24s %-16s %-16s%s",
626 "Iface",
627 "FQDN",
628 "NBMA",
629 "Protocol",
630 VTY_NEWLINE);
631 }
632 ctx->count++;
633
634 vty_out(vty, "%-8s %-24s %-16s %-16s%s",
635 n->ifp->name,
636 n->nbma_fqdn,
637 (reg && reg->peer) ? sockunion2str(®->peer->vc->remote.nbma, buf[0], sizeof buf[0]) : "-",
638 sockunion2str(reg ? ®->proto_addr : &n->proto_addr, buf[1], sizeof buf[1]),
639 VTY_NEWLINE);
640 }
641
show_ip_nhrp_shortcut(struct nhrp_shortcut * s,void * pctx)642 static void show_ip_nhrp_shortcut(struct nhrp_shortcut *s, void *pctx)
643 {
644 struct info_ctx *ctx = pctx;
645 struct nhrp_cache *c;
646 struct vty *vty = ctx->vty;
647 char buf1[PREFIX_STRLEN], buf2[SU_ADDRSTRLEN];
648
649 if (!ctx->count) {
650 vty_out(vty, "%-8s %-24s %-24s %s%s",
651 "Type",
652 "Prefix",
653 "Via",
654 "Identity",
655 VTY_NEWLINE);
656 }
657 ctx->count++;
658
659 c = s->cache;
660 vty_out(ctx->vty, "%-8s %-24s %-24s %s%s",
661 nhrp_cache_type_str[s->type],
662 prefix2str(s->p, buf1, sizeof buf1),
663 c ? sockunion2str(&c->remote_addr, buf2, sizeof buf2) : "",
664 (c && c->cur.peer) ? c->cur.peer->vc->remote.id : "",
665 VTY_NEWLINE);
666 }
667
show_ip_opennhrp_cache(struct nhrp_cache * c,void * pctx)668 static void show_ip_opennhrp_cache(struct nhrp_cache *c, void *pctx)
669 {
670 struct info_ctx *ctx = pctx;
671 struct vty *vty = ctx->vty;
672 char buf[SU_ADDRSTRLEN];
673
674 if (ctx->afi != family2afi(sockunion_family(&c->remote_addr)))
675 return;
676
677 vty_out(ctx->vty,
678 "Type: %s%s"
679 "Flags:%s%s%s"
680 "Protocol-Address: %s/%zu%s",
681 nhrp_cache_type_str[c->cur.type],
682 VTY_NEWLINE,
683 (c->cur.peer && c->cur.peer->online) ? " up": "",
684 c->used ? " used": "",
685 VTY_NEWLINE,
686 sockunion2str(&c->remote_addr, buf, sizeof buf),
687 8 * family2addrsize(sockunion_family(&c->remote_addr)),
688 VTY_NEWLINE);
689
690 if (c->cur.peer) {
691 vty_out(ctx->vty,
692 "NBMA-Address: %s%s",
693 sockunion2str(&c->cur.peer->vc->remote.nbma, buf, sizeof buf),
694 VTY_NEWLINE);
695 }
696
697 if (sockunion_family(&c->cur.remote_nbma_natoa) != AF_UNSPEC) {
698 vty_out(ctx->vty,
699 "NBMA-NAT-OA-Address: %s%s",
700 sockunion2str(&c->cur.remote_nbma_natoa, buf, sizeof buf),
701 VTY_NEWLINE);
702 }
703
704 vty_out(ctx->vty, "%s", VTY_NEWLINE);
705 }
706
707 DEFUN(show_ip_nhrp, show_ip_nhrp_cmd,
708 "show " AFI_CMD " nhrp (cache|nhs|shortcut|opennhrp|)",
709 SHOW_STR
710 AFI_STR
711 "NHRP information\n"
712 "Forwarding cache information\n"
713 "Next hop server information\n"
714 "Shortcut information\n"
715 "opennhrpctl style cache dump\n")
716 {
717 struct listnode *node;
718 struct interface *ifp;
719 struct info_ctx ctx = {
720 .vty = vty,
721 .afi = cmd_to_afi(argv[0]),
722 };
723
724 if (!argv[1] || argv[1][0] == 'c') {
725 for (ALL_LIST_ELEMENTS_RO(iflist, node, ifp))
726 nhrp_cache_foreach(ifp, show_ip_nhrp_cache, &ctx);
727 } else if (argv[1][0] == 'n') {
728 for (ALL_LIST_ELEMENTS_RO(iflist, node, ifp))
729 nhrp_nhs_foreach(ifp, ctx.afi, show_ip_nhrp_nhs, &ctx);
730 } else if (argv[1][0] == 's') {
731 nhrp_shortcut_foreach(ctx.afi, show_ip_nhrp_shortcut, &ctx);
732 } else {
733 vty_out(vty, "Status: ok%s%s", VTY_NEWLINE, VTY_NEWLINE);
734 ctx.count++;
735 for (ALL_LIST_ELEMENTS_RO(iflist, node, ifp))
736 nhrp_cache_foreach(ifp, show_ip_opennhrp_cache, &ctx);
737 }
738
739 if (!ctx.count) {
740 vty_out(vty, "%% No entries%s", VTY_NEWLINE);
741 return CMD_WARNING;
742 }
743
744 return CMD_SUCCESS;
745 }
746
show_dmvpn_entry(struct nhrp_vc * vc,void * ctx)747 static void show_dmvpn_entry(struct nhrp_vc *vc, void *ctx)
748 {
749 struct vty *vty = ctx;
750 char buf[2][SU_ADDRSTRLEN];
751
752 vty_out(vty, "%-24s %-24s %c %-4d %-24s%s",
753 sockunion2str(&vc->local.nbma, buf[0], sizeof buf[0]),
754 sockunion2str(&vc->remote.nbma, buf[1], sizeof buf[1]),
755 notifier_active(&vc->notifier_list) ? 'n' : ' ',
756 vc->ipsec,
757 vc->remote.id,
758 VTY_NEWLINE);
759 }
760
761 DEFUN(show_dmvpn, show_dmvpn_cmd,
762 "show dmvpn",
763 SHOW_STR
764 "DMVPN information\n")
765 {
766 vty_out(vty, "%-24s %-24s %-6s %-4s %-24s%s",
767 "Src",
768 "Dst",
769 "Flags",
770 "SAs",
771 "Identity",
772 VTY_NEWLINE);
773
774 nhrp_vc_foreach(show_dmvpn_entry, vty);
775
776 return CMD_SUCCESS;
777 }
778
clear_nhrp_cache(struct nhrp_cache * c,void * data)779 static void clear_nhrp_cache(struct nhrp_cache *c, void *data)
780 {
781 struct info_ctx *ctx = data;
782 if (c->cur.type <= NHRP_CACHE_CACHED) {
783 nhrp_cache_update_binding(c, c->cur.type, -1, NULL, 0, NULL);
784 ctx->count++;
785 }
786 }
787
clear_nhrp_shortcut(struct nhrp_shortcut * s,void * data)788 static void clear_nhrp_shortcut(struct nhrp_shortcut *s, void *data)
789 {
790 struct info_ctx *ctx = data;
791 nhrp_shortcut_purge(s, 1);
792 ctx->count++;
793 }
794
795 DEFUN(clear_nhrp, clear_nhrp_cmd,
796 "clear " AFI_CMD " nhrp (cache|shortcut)",
797 CLEAR_STR
798 AFI_STR
799 NHRP_STR
800 "Dynamic cache entries\n"
801 "Shortcut entries\n")
802 {
803 struct listnode *node;
804 struct interface *ifp;
805 struct info_ctx ctx = {
806 .vty = vty,
807 .afi = cmd_to_afi(argv[0]),
808 .count = 0,
809 };
810
811 if (!argv[1] || argv[1][0] == 'c') {
812 for (ALL_LIST_ELEMENTS_RO(iflist, node, ifp))
813 nhrp_cache_foreach(ifp, clear_nhrp_cache, &ctx);
814 } else {
815 nhrp_shortcut_foreach(ctx.afi, clear_nhrp_shortcut, &ctx);
816 }
817
818 if (!ctx.count) {
819 vty_out(vty, "%% No entries%s", VTY_NEWLINE);
820 return CMD_WARNING;
821 }
822
823 vty_out(vty, "%% %d entries cleared%s", ctx.count, VTY_NEWLINE);
824 return CMD_SUCCESS;
825 }
826
827 struct write_map_ctx {
828 struct vty *vty;
829 int family;
830 const char *aficmd;
831 };
832
interface_config_write_nhrp_map(struct nhrp_cache * c,void * data)833 static void interface_config_write_nhrp_map(struct nhrp_cache *c, void *data)
834 {
835 struct write_map_ctx *ctx = data;
836 struct vty *vty = ctx->vty;
837 char buf[2][SU_ADDRSTRLEN];
838
839 if (!c->map) return;
840 if (sockunion_family(&c->remote_addr) != ctx->family) return;
841
842 vty_out(vty, " %s nhrp map %s %s%s",
843 ctx->aficmd,
844 sockunion2str(&c->remote_addr, buf[0], sizeof buf[0]),
845 c->cur.type == NHRP_CACHE_LOCAL ? "local" :
846 sockunion2str(&c->cur.peer->vc->remote.nbma, buf[1], sizeof buf[1]),
847 VTY_NEWLINE);
848 }
849
interface_config_write(struct vty * vty)850 static int interface_config_write(struct vty *vty)
851 {
852 struct write_map_ctx mapctx;
853 struct listnode *node;
854 struct interface *ifp;
855 struct nhrp_interface *nifp;
856 struct nhrp_nhs *nhs;
857 const char *aficmd;
858 afi_t afi;
859 char buf[SU_ADDRSTRLEN];
860 int i;
861
862 for (ALL_LIST_ELEMENTS_RO(iflist, node, ifp)) {
863 vty_out(vty, "interface %s%s", ifp->name, VTY_NEWLINE);
864 if (ifp->desc)
865 vty_out(vty, " description %s%s", ifp->desc, VTY_NEWLINE);
866
867 nifp = ifp->info;
868 if (nifp->ipsec_profile) {
869 vty_out(vty, " tunnel protection vici profile %s",
870 nifp->ipsec_profile);
871 if (nifp->ipsec_fallback_profile)
872 vty_out(vty, " fallback-profile %s",
873 nifp->ipsec_fallback_profile);
874 vty_out(vty, "%s", VTY_NEWLINE);
875 }
876 if (nifp->source)
877 vty_out(vty, " tunnel source %s%s",
878 nifp->source, VTY_NEWLINE);
879
880 for (afi = 0; afi < AFI_MAX; afi++) {
881 struct nhrp_afi_data *ad = &nifp->afi[afi];
882
883 aficmd = afi_to_cmd(afi);
884
885 if (ad->network_id)
886 vty_out(vty, " %s nhrp network-id %u%s",
887 aficmd, ad->network_id,
888 VTY_NEWLINE);
889
890 if (ad->holdtime != NHRPD_DEFAULT_HOLDTIME)
891 vty_out(vty, " %s nhrp holdtime %u%s",
892 aficmd, ad->holdtime,
893 VTY_NEWLINE);
894
895 if (ad->configured_mtu < 0)
896 vty_out(vty, " %s nhrp mtu opennhrp%s",
897 aficmd, VTY_NEWLINE);
898 else if (ad->configured_mtu)
899 vty_out(vty, " %s nhrp mtu %u%s",
900 aficmd, ad->configured_mtu,
901 VTY_NEWLINE);
902
903 for (i = 0; interface_flags_desc[i].str != NULL; i++) {
904 if (!(ad->flags & interface_flags_desc[i].key))
905 continue;
906 vty_out(vty, " %s nhrp %s%s",
907 aficmd, interface_flags_desc[i].str, VTY_NEWLINE);
908 }
909
910 mapctx = (struct write_map_ctx) {
911 .vty = vty,
912 .family = afi2family(afi),
913 .aficmd = aficmd,
914 };
915 nhrp_cache_foreach(ifp, interface_config_write_nhrp_map, &mapctx);
916
917 list_for_each_entry(nhs, &ad->nhslist_head, nhslist_entry) {
918 vty_out(vty, " %s nhrp nhs %s nbma %s%s",
919 aficmd,
920 sockunion_family(&nhs->proto_addr) == AF_UNSPEC ? "dynamic" : sockunion2str(&nhs->proto_addr, buf, sizeof buf),
921 nhs->nbma_fqdn,
922 VTY_NEWLINE);
923 }
924 }
925
926 vty_out (vty, "!%s", VTY_NEWLINE);
927 }
928
929 return 0;
930 }
931
nhrp_config_init(void)932 void nhrp_config_init(void)
933 {
934 install_node(&zebra_node, nhrp_config_write);
935 install_default(ZEBRA_NODE);
936
937 /* global commands */
938 install_element(VIEW_NODE, &show_debugging_nhrp_cmd);
939 install_element(VIEW_NODE, &show_ip_nhrp_cmd);
940 install_element(VIEW_NODE, &show_dmvpn_cmd);
941 install_element(ENABLE_NODE, &show_debugging_nhrp_cmd);
942 install_element(ENABLE_NODE, &show_ip_nhrp_cmd);
943 install_element(ENABLE_NODE, &show_dmvpn_cmd);
944 install_element(ENABLE_NODE, &clear_nhrp_cmd);
945
946 install_element(ENABLE_NODE, &debug_nhrp_cmd);
947 install_element(ENABLE_NODE, &no_debug_nhrp_cmd);
948
949 install_element(CONFIG_NODE, &debug_nhrp_cmd);
950 install_element(CONFIG_NODE, &no_debug_nhrp_cmd);
951
952 install_element(CONFIG_NODE, &nhrp_event_socket_cmd);
953 install_element(CONFIG_NODE, &no_nhrp_event_socket_cmd);
954 install_element(CONFIG_NODE, &nhrp_nflog_group_cmd);
955 install_element(CONFIG_NODE, &no_nhrp_nflog_group_cmd);
956
957 /* interface specific commands */
958 install_node(&nhrp_interface_node, interface_config_write);
959 install_default(INTERFACE_NODE);
960
961 install_element(CONFIG_NODE, &interface_cmd);
962 install_element(CONFIG_NODE, &no_interface_cmd);
963 install_element(INTERFACE_NODE, &interface_cmd);
964 install_element(INTERFACE_NODE, &no_interface_cmd);
965 install_element(INTERFACE_NODE, &tunnel_protection_cmd);
966 install_element(INTERFACE_NODE, &no_tunnel_protection_cmd);
967 install_element(INTERFACE_NODE, &tunnel_source_cmd);
968 install_element(INTERFACE_NODE, &no_tunnel_source_cmd);
969 install_element(INTERFACE_NODE, &if_nhrp_network_id_cmd);
970 install_element(INTERFACE_NODE, &if_no_nhrp_network_id_cmd);
971 install_element(INTERFACE_NODE, &if_nhrp_holdtime_cmd);
972 install_element(INTERFACE_NODE, &if_no_nhrp_holdtime_cmd);
973 install_element(INTERFACE_NODE, &if_nhrp_mtu_cmd);
974 install_element(INTERFACE_NODE, &if_no_nhrp_mtu_cmd);
975 install_element(INTERFACE_NODE, &if_nhrp_flags_cmd);
976 install_element(INTERFACE_NODE, &if_no_nhrp_flags_cmd);
977 install_element(INTERFACE_NODE, &if_nhrp_reg_flags_cmd);
978 install_element(INTERFACE_NODE, &if_no_nhrp_reg_flags_cmd);
979 install_element(INTERFACE_NODE, &if_nhrp_map_cmd);
980 install_element(INTERFACE_NODE, &if_no_nhrp_map_cmd);
981 install_element(INTERFACE_NODE, &if_nhrp_nhs_cmd);
982 install_element(INTERFACE_NODE, &if_no_nhrp_nhs_cmd);
983 }
984