]>
Commit | Line | Data |
---|---|---|
2fb975da TT |
1 | /* NHRP vty handling |
2 | * Copyright (c) 2014-2015 Timo Teräs | |
3 | * | |
4 | * This file is free software: you may copy, redistribute and/or modify | |
5 | * it under the terms of the GNU General Public License as published by | |
6 | * the Free Software Foundation, either version 2 of the License, or | |
7 | * (at your option) any later version. | |
8 | */ | |
9 | ||
10 | #include "zebra.h" | |
11 | #include "command.h" | |
12 | #include "zclient.h" | |
13 | #include "stream.h" | |
901fda98 | 14 | #include "filter.h" |
87b9e982 | 15 | #include "json.h" |
2fb975da TT |
16 | |
17 | #include "nhrpd.h" | |
18 | #include "netlink.h" | |
19 | ||
612c2c15 | 20 | static int nhrp_config_write(struct vty *vty); |
2fb975da | 21 | static struct cmd_node zebra_node = { |
f4b8291f | 22 | .name = "zebra", |
996c9314 | 23 | .node = ZEBRA_NODE, |
24389580 | 24 | .parent_node = CONFIG_NODE, |
2fb975da | 25 | .prompt = "%s(config-router)# ", |
612c2c15 | 26 | .config_write = nhrp_config_write, |
2fb975da TT |
27 | }; |
28 | ||
819dc8bb | 29 | #define NHRP_DEBUG_FLAGS_CMD "<all|common|event|interface|kernel|route|vici>" |
2fb975da | 30 | |
996c9314 LB |
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" \ | |
2fb975da TT |
38 | "VICI messages\n" |
39 | ||
40 | static const struct message debug_flags_desc[] = { | |
996c9314 LB |
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}}; | |
2fb975da TT |
45 | |
46 | static const struct message interface_flags_desc[] = { | |
996c9314 LB |
47 | {NHRP_IFF_SHORTCUT, "shortcut"}, |
48 | {NHRP_IFF_REDIRECT, "redirect"}, | |
49 | {NHRP_IFF_REG_NO_UNIQUE, "registration no-unique"}, | |
50 | {0}}; | |
2fb975da TT |
51 | |
52 | static int nhrp_vty_return(struct vty *vty, int ret) | |
53 | { | |
996c9314 LB |
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)", | |
2fb975da TT |
65 | }; |
66 | const char *str = NULL; | |
67 | char buf[256]; | |
68 | ||
69 | if (ret == NHRP_OK) | |
70 | return CMD_SUCCESS; | |
71 | ||
6c8ca260 | 72 | if (ret > 0 && ret <= NHRP_ERR_MAX) |
2fb975da TT |
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 | ||
996c9314 | 81 | vty_out(vty, "%% %s\n", str); |
2fb975da | 82 | |
996c9314 LB |
83 | return CMD_WARNING_CONFIG_FAILED; |
84 | ; | |
2fb975da TT |
85 | } |
86 | ||
996c9314 LB |
87 | static int toggle_flag(struct vty *vty, const struct message *flag_desc, |
88 | const char *name, int on_off, unsigned *flags) | |
2fb975da TT |
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 | ||
996c9314 LB |
102 | vty_out(vty, "%% Invalid value %s\n", name); |
103 | return CMD_WARNING_CONFIG_FAILED; | |
104 | ; | |
2fb975da TT |
105 | } |
106 | ||
107 | #ifndef NO_DEBUG | |
108 | ||
87f6dc50 DS |
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") | |
2fb975da TT |
114 | { |
115 | int i; | |
116 | ||
996c9314 | 117 | vty_out(vty, "NHRP debugging status:\n"); |
2fb975da TT |
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 | ||
996c9314 | 125 | vty_out(vty, " NHRP %s debugging is on\n", |
96ade3ed | 126 | debug_flags_desc[i].str); |
2fb975da TT |
127 | } |
128 | ||
cf00164b DS |
129 | cmd_show_lib_debugs(vty); |
130 | ||
2fb975da TT |
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 | { | |
996c9314 LB |
140 | return toggle_flag(vty, debug_flags_desc, argv[2]->text, 1, |
141 | &debug_flags); | |
2fb975da TT |
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 | { | |
996c9314 LB |
151 | return toggle_flag(vty, debug_flags_desc, argv[3]->text, 0, |
152 | &debug_flags); | |
2fb975da TT |
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) { | |
996c9314 | 161 | vty_out(vty, "debug nhrp all\n"); |
2fb975da TT |
162 | } else { |
163 | int i; | |
164 | ||
165 | for (i = 0; debug_flags_desc[i].str != NULL; i++) { | |
166 | if (debug_flags_desc[i].key == NHRP_DEBUG_ALL) | |
167 | continue; | |
168 | if (!(debug_flags & debug_flags_desc[i].key)) | |
169 | continue; | |
996c9314 LB |
170 | vty_out(vty, "debug nhrp %s\n", |
171 | debug_flags_desc[i].str); | |
2fb975da TT |
172 | } |
173 | } | |
996c9314 | 174 | vty_out(vty, "!\n"); |
2fb975da TT |
175 | #endif /* NO_DEBUG */ |
176 | ||
177 | if (nhrp_event_socket_path) { | |
996c9314 | 178 | vty_out(vty, "nhrp event socket %s\n", nhrp_event_socket_path); |
2fb975da TT |
179 | } |
180 | if (netlink_nflog_group) { | |
996c9314 | 181 | vty_out(vty, "nhrp nflog-group %d\n", netlink_nflog_group); |
2fb975da | 182 | } |
9084e209 AL |
183 | if (netlink_mcast_nflog_group) |
184 | vty_out(vty, "nhrp multicast-nflog-group %d\n", | |
185 | netlink_mcast_nflog_group); | |
2fb975da TT |
186 | |
187 | return 0; | |
188 | } | |
189 | ||
190 | #define IP_STR "IP information\n" | |
191 | #define IPV6_STR "IPv6 information\n" | |
819dc8bb | 192 | #define AFI_CMD "<ip|ipv6>" |
2fb975da TT |
193 | #define AFI_STR IP_STR IPV6_STR |
194 | #define NHRP_STR "Next Hop Resolution Protocol functions\n" | |
195 | ||
819dc8bb | 196 | static afi_t cmd_to_afi(const struct cmd_token *tok) |
2fb975da | 197 | { |
819dc8bb | 198 | return strcmp(tok->text, "ipv6") == 0 ? AFI_IP6 : AFI_IP; |
2fb975da TT |
199 | } |
200 | ||
201 | static const char *afi_to_cmd(afi_t afi) | |
202 | { | |
996c9314 LB |
203 | if (afi == AFI_IP6) |
204 | return "ipv6"; | |
2fb975da TT |
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" | |
201f6271 | 213 | "Unix path for the socket\n") |
2fb975da | 214 | { |
819dc8bb | 215 | evmgr_set_socket(argv[3]->arg); |
2fb975da TT |
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" | |
201f6271 | 225 | "Unix path for the socket\n") |
2fb975da TT |
226 | { |
227 | evmgr_set_socket(NULL); | |
228 | return CMD_SUCCESS; | |
229 | } | |
230 | ||
231 | DEFUN(nhrp_nflog_group, nhrp_nflog_group_cmd, | |
819dc8bb | 232 | "nhrp nflog-group (1-65535)", |
2fb975da TT |
233 | NHRP_STR |
234 | "Specify NFLOG group number\n" | |
235 | "NFLOG group number\n") | |
236 | { | |
237 | uint32_t nfgroup; | |
238 | ||
facfee22 | 239 | nfgroup = strtoul(argv[2]->arg, NULL, 10); |
2fb975da TT |
240 | netlink_set_nflog_group(nfgroup); |
241 | ||
242 | return CMD_SUCCESS; | |
243 | } | |
244 | ||
245 | DEFUN(no_nhrp_nflog_group, no_nhrp_nflog_group_cmd, | |
819dc8bb | 246 | "no nhrp nflog-group [(1-65535)]", |
2fb975da TT |
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 | ||
9084e209 AL |
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 | ||
2fb975da | 281 | DEFUN(tunnel_protection, tunnel_protection_cmd, |
819dc8bb | 282 | "tunnel protection vici profile PROFILE [fallback-profile FALLBACK]", |
2fb975da TT |
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 | { | |
819dc8bb | 291 | VTY_DECLVAR_CONTEXT(interface, ifp); |
2fb975da | 292 | |
819dc8bb | 293 | nhrp_interface_set_protection(ifp, argv[4]->arg, |
996c9314 | 294 | argc > 6 ? argv[6]->arg : NULL); |
2fb975da TT |
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 | { | |
819dc8bb | 304 | VTY_DECLVAR_CONTEXT(interface, ifp); |
2fb975da TT |
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 | { | |
819dc8bb DL |
316 | VTY_DECLVAR_CONTEXT(interface, ifp); |
317 | nhrp_interface_set_source(ifp, argv[2]->arg); | |
2fb975da TT |
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 | { | |
819dc8bb | 327 | VTY_DECLVAR_CONTEXT(interface, ifp); |
2fb975da TT |
328 | nhrp_interface_set_source(ifp, NULL); |
329 | return CMD_SUCCESS; | |
330 | } | |
331 | ||
332 | DEFUN(if_nhrp_network_id, if_nhrp_network_id_cmd, | |
819dc8bb | 333 | AFI_CMD " nhrp network-id (1-4294967295)", |
2fb975da TT |
334 | AFI_STR |
335 | NHRP_STR | |
336 | "Enable NHRP and specify network-id\n" | |
337 | "System local ID to specify interface group\n") | |
338 | { | |
819dc8bb | 339 | VTY_DECLVAR_CONTEXT(interface, ifp); |
2fb975da TT |
340 | struct nhrp_interface *nifp = ifp->info; |
341 | afi_t afi = cmd_to_afi(argv[0]); | |
342 | ||
facfee22 | 343 | nifp->afi[afi].network_id = strtoul(argv[3]->arg, NULL, 10); |
2fb975da TT |
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, | |
819dc8bb | 350 | "no " AFI_CMD " nhrp network-id [(1-4294967295)]", |
2fb975da TT |
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 | { | |
819dc8bb | 357 | VTY_DECLVAR_CONTEXT(interface, ifp); |
2fb975da | 358 | struct nhrp_interface *nifp = ifp->info; |
819dc8bb | 359 | afi_t afi = cmd_to_afi(argv[1]); |
2fb975da TT |
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, | |
819dc8bb | 368 | AFI_CMD " nhrp <shortcut|redirect>", |
2fb975da TT |
369 | AFI_STR |
370 | NHRP_STR | |
371 | "Allow shortcut establishment\n" | |
372 | "Send redirect notifications\n") | |
373 | { | |
819dc8bb | 374 | VTY_DECLVAR_CONTEXT(interface, ifp); |
2fb975da TT |
375 | struct nhrp_interface *nifp = ifp->info; |
376 | afi_t afi = cmd_to_afi(argv[0]); | |
377 | ||
996c9314 LB |
378 | return toggle_flag(vty, interface_flags_desc, argv[2]->text, 1, |
379 | &nifp->afi[afi].flags); | |
2fb975da TT |
380 | } |
381 | ||
382 | DEFUN(if_no_nhrp_flags, if_no_nhrp_flags_cmd, | |
819dc8bb | 383 | "no " AFI_CMD " nhrp <shortcut|redirect>", |
2fb975da TT |
384 | NO_STR |
385 | AFI_STR | |
386 | NHRP_STR | |
387 | "Allow shortcut establishment\n" | |
388 | "Send redirect notifications\n") | |
389 | { | |
819dc8bb | 390 | VTY_DECLVAR_CONTEXT(interface, ifp); |
2fb975da | 391 | struct nhrp_interface *nifp = ifp->info; |
819dc8bb | 392 | afi_t afi = cmd_to_afi(argv[1]); |
2fb975da | 393 | |
996c9314 LB |
394 | return toggle_flag(vty, interface_flags_desc, argv[3]->text, 0, |
395 | &nifp->afi[afi].flags); | |
2fb975da TT |
396 | } |
397 | ||
398 | DEFUN(if_nhrp_reg_flags, if_nhrp_reg_flags_cmd, | |
819dc8bb | 399 | AFI_CMD " nhrp registration no-unique", |
2fb975da TT |
400 | AFI_STR |
401 | NHRP_STR | |
402 | "Registration configuration\n" | |
403 | "Don't set unique flag\n") | |
404 | { | |
819dc8bb | 405 | VTY_DECLVAR_CONTEXT(interface, ifp); |
2fb975da TT |
406 | struct nhrp_interface *nifp = ifp->info; |
407 | afi_t afi = cmd_to_afi(argv[0]); | |
408 | char name[256]; | |
819dc8bb | 409 | snprintf(name, sizeof(name), "registration %s", argv[3]->text); |
996c9314 LB |
410 | return toggle_flag(vty, interface_flags_desc, name, 1, |
411 | &nifp->afi[afi].flags); | |
2fb975da TT |
412 | } |
413 | ||
414 | DEFUN(if_no_nhrp_reg_flags, if_no_nhrp_reg_flags_cmd, | |
819dc8bb | 415 | "no " AFI_CMD " nhrp registration no-unique", |
2fb975da TT |
416 | NO_STR |
417 | AFI_STR | |
418 | NHRP_STR | |
419 | "Registration configuration\n" | |
420 | "Don't set unique flag\n") | |
421 | { | |
819dc8bb | 422 | VTY_DECLVAR_CONTEXT(interface, ifp); |
2fb975da | 423 | struct nhrp_interface *nifp = ifp->info; |
819dc8bb | 424 | afi_t afi = cmd_to_afi(argv[1]); |
2fb975da | 425 | char name[256]; |
819dc8bb | 426 | snprintf(name, sizeof(name), "registration %s", argv[4]->text); |
996c9314 LB |
427 | return toggle_flag(vty, interface_flags_desc, name, 0, |
428 | &nifp->afi[afi].flags); | |
2fb975da TT |
429 | } |
430 | ||
431 | DEFUN(if_nhrp_holdtime, if_nhrp_holdtime_cmd, | |
819dc8bb | 432 | AFI_CMD " nhrp holdtime (1-65000)", |
2fb975da TT |
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 | { | |
819dc8bb | 438 | VTY_DECLVAR_CONTEXT(interface, ifp); |
2fb975da TT |
439 | struct nhrp_interface *nifp = ifp->info; |
440 | afi_t afi = cmd_to_afi(argv[0]); | |
441 | ||
facfee22 | 442 | nifp->afi[afi].holdtime = strtoul(argv[3]->arg, NULL, 10); |
2fb975da TT |
443 | nhrp_interface_update(ifp); |
444 | ||
445 | return CMD_SUCCESS; | |
446 | } | |
447 | ||
448 | DEFUN(if_no_nhrp_holdtime, if_no_nhrp_holdtime_cmd, | |
819dc8bb | 449 | "no " AFI_CMD " nhrp holdtime [(1-65000)]", |
2fb975da TT |
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 | { | |
819dc8bb | 456 | VTY_DECLVAR_CONTEXT(interface, ifp); |
2fb975da | 457 | struct nhrp_interface *nifp = ifp->info; |
819dc8bb | 458 | afi_t afi = cmd_to_afi(argv[1]); |
2fb975da TT |
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, | |
819dc8bb | 467 | "ip nhrp mtu <(576-1500)|opennhrp>", |
2fb975da TT |
468 | IP_STR |
469 | NHRP_STR | |
470 | "Configure NHRP advertised MTU\n" | |
471 | "MTU value\n" | |
efd7904e | 472 | "Advertise bound interface MTU similar to OpenNHRP\n") |
2fb975da | 473 | { |
819dc8bb | 474 | VTY_DECLVAR_CONTEXT(interface, ifp); |
2fb975da TT |
475 | struct nhrp_interface *nifp = ifp->info; |
476 | ||
819dc8bb | 477 | if (argv[3]->arg[0] == 'o') { |
2fb975da TT |
478 | nifp->afi[AFI_IP].configured_mtu = -1; |
479 | } else { | |
996c9314 LB |
480 | nifp->afi[AFI_IP].configured_mtu = |
481 | strtoul(argv[3]->arg, NULL, 10); | |
2fb975da TT |
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, | |
819dc8bb | 489 | "no ip nhrp mtu [(576-1500)|opennhrp]", |
2fb975da TT |
490 | NO_STR |
491 | IP_STR | |
492 | NHRP_STR | |
493 | "Configure NHRP advertised MTU\n" | |
494 | "MTU value\n" | |
efd7904e | 495 | "Advertise bound interface MTU similar to OpenNHRP\n") |
2fb975da | 496 | { |
819dc8bb | 497 | VTY_DECLVAR_CONTEXT(interface, ifp); |
2fb975da TT |
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, | |
819dc8bb | 506 | AFI_CMD " nhrp map <A.B.C.D|X:X::X:X> <A.B.C.D|local>", |
2fb975da TT |
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 | { | |
819dc8bb | 515 | VTY_DECLVAR_CONTEXT(interface, ifp); |
2fb975da TT |
516 | afi_t afi = cmd_to_afi(argv[0]); |
517 | union sockunion proto_addr, nbma_addr; | |
fef2ed13 | 518 | struct nhrp_cache_config *cc; |
2fb975da | 519 | struct nhrp_cache *c; |
fef2ed13 | 520 | enum nhrp_cache_type type; |
2fb975da | 521 | |
996c9314 LB |
522 | if (str2sockunion(argv[3]->arg, &proto_addr) < 0 |
523 | || afi2family(afi) != sockunion_family(&proto_addr)) | |
2fb975da TT |
524 | return nhrp_vty_return(vty, NHRP_ERR_PROTOCOL_ADDRESS_MISMATCH); |
525 | ||
fef2ed13 PG |
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 | ||
2fb975da TT |
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; | |
fef2ed13 | 547 | if (type == NHRP_CACHE_LOCAL) |
996c9314 | 548 | nhrp_cache_update_binding(c, NHRP_CACHE_LOCAL, 0, NULL, 0, |
85365e51 | 549 | NULL, NULL); |
fef2ed13 | 550 | else |
2fb975da | 551 | nhrp_cache_update_binding(c, NHRP_CACHE_STATIC, 0, |
996c9314 | 552 | nhrp_peer_get(ifp, &nbma_addr), 0, |
85365e51 | 553 | NULL, NULL); |
2fb975da TT |
554 | return CMD_SUCCESS; |
555 | } | |
556 | ||
2d4eab22 | 557 | DEFUN(if_no_nhrp_map, if_no_nhrp_map_cmd, |
29ff6b5c | 558 | "no " AFI_CMD " nhrp map <A.B.C.D|X:X::X:X> [<A.B.C.D|local>]", |
2d4eab22 TT |
559 | NO_STR |
560 | AFI_STR | |
561 | NHRP_STR | |
562 | "Nexthop Server configuration\n" | |
563 | "IPv4 protocol address\n" | |
29ff6b5c JAG |
564 | "IPv6 protocol address\n" |
565 | "IPv4 NBMA address\n" | |
566 | "Handle protocol address locally\n") | |
2d4eab22 | 567 | { |
996c9314 | 568 | VTY_DECLVAR_CONTEXT(interface, ifp); |
2d4eab22 | 569 | afi_t afi = cmd_to_afi(argv[1]); |
b5503506 | 570 | union sockunion proto_addr, nbma_addr; |
fef2ed13 | 571 | struct nhrp_cache_config *cc; |
2d4eab22 TT |
572 | struct nhrp_cache *c; |
573 | ||
996c9314 LB |
574 | if (str2sockunion(argv[4]->arg, &proto_addr) < 0 |
575 | || afi2family(afi) != sockunion_family(&proto_addr)) | |
2d4eab22 TT |
576 | return nhrp_vty_return(vty, NHRP_ERR_PROTOCOL_ADDRESS_MISMATCH); |
577 | ||
fef2ed13 PG |
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 | ||
2d4eab22 | 583 | c = nhrp_cache_get(ifp, &proto_addr, 0); |
fef2ed13 | 584 | /* silently return */ |
2d4eab22 | 585 | if (!c || !c->map) |
fef2ed13 | 586 | return CMD_SUCCESS; |
2d4eab22 | 587 | |
b5503506 | 588 | nhrp_cache_update_binding(c, c->cur.type, -1, |
00683a14 RD |
589 | nhrp_peer_get(ifp, &nbma_addr), 0, NULL, |
590 | NULL); | |
2d4eab22 TT |
591 | return CMD_SUCCESS; |
592 | } | |
593 | ||
fa31fcf2 AL |
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 | ||
2fb975da | 641 | DEFUN(if_nhrp_nhs, if_nhrp_nhs_cmd, |
819dc8bb | 642 | AFI_CMD " nhrp nhs <A.B.C.D|X:X::X:X|dynamic> nbma <A.B.C.D|FQDN>", |
2fb975da TT |
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" | |
819dc8bb | 649 | "NBMA address\n" |
2fb975da TT |
650 | "IPv4 NBMA address\n" |
651 | "Fully qualified domain name for NBMA address(es)\n") | |
652 | { | |
819dc8bb | 653 | VTY_DECLVAR_CONTEXT(interface, ifp); |
2fb975da TT |
654 | afi_t afi = cmd_to_afi(argv[0]); |
655 | union sockunion proto_addr; | |
656 | int ret; | |
657 | ||
819dc8bb | 658 | if (str2sockunion(argv[3]->arg, &proto_addr) < 0) |
2fb975da TT |
659 | sockunion_family(&proto_addr) = AF_UNSPEC; |
660 | ||
819dc8bb | 661 | ret = nhrp_nhs_add(ifp, afi, &proto_addr, argv[5]->arg); |
2fb975da TT |
662 | return nhrp_vty_return(vty, ret); |
663 | } | |
664 | ||
665 | DEFUN(if_no_nhrp_nhs, if_no_nhrp_nhs_cmd, | |
819dc8bb | 666 | "no " AFI_CMD " nhrp nhs <A.B.C.D|X:X::X:X|dynamic> nbma <A.B.C.D|FQDN>", |
2fb975da TT |
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" | |
819dc8bb | 674 | "NBMA address\n" |
2fb975da TT |
675 | "IPv4 NBMA address\n" |
676 | "Fully qualified domain name for NBMA address(es)\n") | |
677 | { | |
819dc8bb DL |
678 | VTY_DECLVAR_CONTEXT(interface, ifp); |
679 | afi_t afi = cmd_to_afi(argv[1]); | |
2fb975da TT |
680 | union sockunion proto_addr; |
681 | int ret; | |
682 | ||
819dc8bb | 683 | if (str2sockunion(argv[4]->arg, &proto_addr) < 0) |
2fb975da TT |
684 | sockunion_family(&proto_addr) = AF_UNSPEC; |
685 | ||
819dc8bb | 686 | ret = nhrp_nhs_del(ifp, afi, &proto_addr, argv[6]->arg); |
2fb975da TT |
687 | return nhrp_vty_return(vty, ret); |
688 | } | |
689 | ||
690 | struct info_ctx { | |
691 | struct vty *vty; | |
692 | afi_t afi; | |
693 | int count; | |
87b9e982 | 694 | struct json_object *json; |
2fb975da TT |
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; | |
85365e51 | 701 | char buf[3][SU_ADDRSTRLEN]; |
87b9e982 | 702 | struct json_object *json = NULL; |
2fb975da TT |
703 | |
704 | if (ctx->afi != family2afi(sockunion_family(&c->remote_addr))) | |
705 | return; | |
706 | ||
87b9e982 PG |
707 | |
708 | if (!ctx->count && !ctx->json) { | |
00683a14 RD |
709 | vty_out(vty, "%-8s %-8s %-24s %-24s %-24s %-6s %s\n", "Iface", |
710 | "Type", "Protocol", "NBMA", "Claimed NBMA", "Flags", | |
711 | "Identity"); | |
2fb975da TT |
712 | } |
713 | ctx->count++; | |
714 | ||
87b9e982 | 715 | sockunion2str(&c->remote_addr, buf[0], sizeof(buf[0])); |
bcf5673d AL |
716 | if (c->cur.type == NHRP_CACHE_LOCAL) { |
717 | struct nhrp_interface *nifp = c->ifp->info; | |
87b9e982 | 718 | |
bcf5673d AL |
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])); | |
d0c9d09a | 722 | } else { |
bcf5673d AL |
723 | snprintf(buf[1], sizeof(buf[1]), "-"); |
724 | snprintf(buf[2], sizeof(buf[2]), "-"); | |
725 | } | |
85365e51 | 726 | |
bcf5673d AL |
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) | |
0551aead | 739 | != AF_UNSPEC) |
bcf5673d AL |
740 | sockunion2str(&c->cur.remote_nbma_claimed, |
741 | buf[2], sizeof(buf[2])); | |
742 | else | |
743 | snprintf(buf[2], sizeof(buf[2]), "-"); | |
744 | } | |
85365e51 | 745 | |
e0a1fb22 | 746 | if (ctx->json) { |
87b9e982 PG |
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]); | |
85365e51 | 753 | json_object_string_add(json, "claimed_nbma", buf[2]); |
87b9e982 PG |
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 | } | |
85365e51 AL |
779 | vty_out(ctx->vty, "%-8s %-8s %-24s %-24s %-24s %c%c%c %s\n", |
780 | c->ifp->name, | |
2fb975da | 781 | nhrp_cache_type_str[c->cur.type], |
85365e51 | 782 | buf[0], buf[1], buf[2], |
996c9314 | 783 | c->used ? 'U' : ' ', c->t_timeout ? 'T' : ' ', |
2fb975da | 784 | c->t_auth ? 'A' : ' ', |
96ade3ed | 785 | c->cur.peer ? c->cur.peer->vc->remote.id : "-"); |
2fb975da TT |
786 | } |
787 | ||
996c9314 LB |
788 | static void show_ip_nhrp_nhs(struct nhrp_nhs *n, struct nhrp_registration *reg, |
789 | void *pctx) | |
0ca036b4 TT |
790 | { |
791 | struct info_ctx *ctx = pctx; | |
792 | struct vty *vty = ctx->vty; | |
793 | char buf[2][SU_ADDRSTRLEN]; | |
87b9e982 | 794 | struct json_object *json = NULL; |
0ca036b4 | 795 | |
87b9e982 | 796 | if (!ctx->count && !ctx->json) { |
996c9314 LB |
797 | vty_out(vty, "%-8s %-24s %-16s %-16s\n", "Iface", "FQDN", |
798 | "NBMA", "Protocol"); | |
0ca036b4 TT |
799 | } |
800 | ctx->count++; | |
801 | ||
87b9e982 | 802 | if (reg && reg->peer) |
0f8595a9 RD |
803 | sockunion2str(®->peer->vc->remote.nbma, buf[0], |
804 | sizeof(buf[0])); | |
87b9e982 PG |
805 | else |
806 | snprintf(buf[0], sizeof(buf[0]), "-"); | |
807 | sockunion2str(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 | ||
996c9314 | 821 | vty_out(vty, "%-8s %-24s %-16s %-16s\n", n->ifp->name, n->nbma_fqdn, |
87b9e982 | 822 | buf[0], buf[1]); |
0ca036b4 TT |
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]; | |
87b9e982 | 831 | struct json_object *json = NULL; |
0ca036b4 TT |
832 | |
833 | if (!ctx->count) { | |
996c9314 | 834 | vty_out(vty, "%-8s %-24s %-24s %s\n", "Type", "Prefix", "Via", |
96ade3ed | 835 | "Identity"); |
0ca036b4 TT |
836 | } |
837 | ctx->count++; | |
838 | ||
839 | c = s->cache; | |
f07757ae | 840 | buf2[0] = '\0'; |
87b9e982 PG |
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, | |
96ade3ed | 867 | (c && c->cur.peer) ? c->cur.peer->vc->remote.id : ""); |
0ca036b4 TT |
868 | } |
869 | ||
2fb975da TT |
870 | static void show_ip_opennhrp_cache(struct nhrp_cache *c, void *pctx) |
871 | { | |
872 | struct info_ctx *ctx = pctx; | |
87b9e982 PG |
873 | char buf[3][SU_ADDRSTRLEN]; |
874 | struct json_object *json = NULL; | |
875 | ||
2fb975da TT |
876 | |
877 | if (ctx->afi != family2afi(sockunion_family(&c->remote_addr))) | |
878 | return; | |
879 | ||
87b9e982 PG |
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 | } | |
181039f3 | 917 | vty_out(ctx->vty, |
996c9314 LB |
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" : "", | |
87b9e982 | 924 | buf[0], |
996c9314 | 925 | 8 * family2addrsize(sockunion_family(&c->remote_addr))); |
2fb975da | 926 | |
87b9e982 PG |
927 | if (c->cur.peer) |
928 | vty_out(ctx->vty, "NBMA-Address: %s\n", buf[1]); | |
2fb975da | 929 | |
87b9e982 PG |
930 | if (sockunion_family(&c->cur.remote_nbma_natoa) != AF_UNSPEC) |
931 | vty_out(ctx->vty, "NBMA-NAT-OA-Address: %s\n", buf[2]); | |
2fb975da | 932 | |
181039f3 | 933 | vty_out(ctx->vty, "\n\n"); |
2fb975da TT |
934 | } |
935 | ||
2fb975da | 936 | DEFUN(show_ip_nhrp, show_ip_nhrp_cmd, |
87b9e982 | 937 | "show " AFI_CMD " nhrp [cache|nhs|shortcut|opennhrp] [json]", |
2fb975da TT |
938 | SHOW_STR |
939 | AFI_STR | |
940 | "NHRP information\n" | |
941 | "Forwarding cache information\n" | |
0ca036b4 | 942 | "Next hop server information\n" |
2fb975da | 943 | "Shortcut information\n" |
87b9e982 PG |
944 | "opennhrpctl style cache dump\n" |
945 | JSON_STR) | |
2fb975da | 946 | { |
f4e14fdb | 947 | struct vrf *vrf = vrf_lookup_by_id(VRF_DEFAULT); |
2fb975da TT |
948 | struct interface *ifp; |
949 | struct info_ctx ctx = { | |
87b9e982 | 950 | .vty = vty, .afi = cmd_to_afi(argv[1]), .json = NULL |
2fb975da | 951 | }; |
87b9e982 PG |
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 | } | |
819dc8bb | 963 | if (argc <= 3 || argv[3]->text[0] == 'c') { |
451fda4f | 964 | FOR_ALL_INTERFACES (vrf, ifp) |
2fb975da | 965 | nhrp_cache_foreach(ifp, show_ip_nhrp_cache, &ctx); |
0ca036b4 | 966 | } else if (argv[3]->text[0] == 'n') { |
451fda4f | 967 | FOR_ALL_INTERFACES (vrf, ifp) |
0ca036b4 TT |
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 { | |
87b9e982 PG |
972 | if (!ctx.json) |
973 | vty_out(vty, "Status: ok\n\n"); | |
974 | else | |
975 | json_object_string_add(json_vrf, "status", "ok"); | |
976 | ||
2fb975da | 977 | ctx.count++; |
451fda4f | 978 | FOR_ALL_INTERFACES (vrf, ifp) |
2fb975da | 979 | nhrp_cache_foreach(ifp, show_ip_opennhrp_cache, &ctx); |
2fb975da TT |
980 | } |
981 | ||
87b9e982 PG |
982 | if (uj) |
983 | json_object_int_add(json_vrf, "entriesCount", ctx.count); | |
2fb975da | 984 | if (!ctx.count) { |
87b9e982 PG |
985 | if (!ctx.json) |
986 | vty_out(vty, "%% No entries\n"); | |
987 | ret = CMD_WARNING; | |
2fb975da | 988 | } |
87b9e982 PG |
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); | |
3757f964 | 992 | vty_json(vty, json_vrf_path); |
87b9e982 PG |
993 | } |
994 | return ret; | |
2fb975da TT |
995 | } |
996 | ||
87b9e982 PG |
997 | struct dmvpn_cfg { |
998 | struct vty *vty; | |
999 | struct json_object *json; | |
1000 | }; | |
1001 | ||
2fb975da TT |
1002 | static void show_dmvpn_entry(struct nhrp_vc *vc, void *ctx) |
1003 | { | |
87b9e982 PG |
1004 | struct dmvpn_cfg *ctxt = ctx; |
1005 | struct vty *vty; | |
87b9e982 | 1006 | struct json_object *json = NULL; |
2fb975da | 1007 | |
87b9e982 PG |
1008 | if (!ctxt || !ctxt->vty) |
1009 | return; | |
1010 | vty = ctxt->vty; | |
87b9e982 PG |
1011 | if (ctxt->json) { |
1012 | json = json_object_new_object(); | |
47e12884 DA |
1013 | json_object_string_addf(json, "src", "%pSU", &vc->local.nbma); |
1014 | json_object_string_addf(json, "dst", "%pSU", &vc->remote.nbma); | |
87b9e982 PG |
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 { | |
47e12884 DA |
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); | |
87b9e982 | 1029 | } |
2fb975da TT |
1030 | } |
1031 | ||
1032 | DEFUN(show_dmvpn, show_dmvpn_cmd, | |
87b9e982 | 1033 | "show dmvpn [json]", |
2fb975da | 1034 | SHOW_STR |
87b9e982 PG |
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); | |
3757f964 DA |
1052 | if (uj) |
1053 | vty_json(vty, json_path); | |
2fb975da TT |
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; | |
db89e514 | 1060 | if (c->cur.type <= NHRP_CACHE_DYNAMIC) { |
00683a14 RD |
1061 | nhrp_cache_update_binding(c, c->cur.type, -1, NULL, 0, NULL, |
1062 | NULL); | |
2b55509d AL |
1063 | if (ctx) |
1064 | ctx->count++; | |
2fb975da TT |
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, | |
819dc8bb | 1076 | "clear " AFI_CMD " nhrp <cache|shortcut>", |
2fb975da TT |
1077 | CLEAR_STR |
1078 | AFI_STR | |
1079 | NHRP_STR | |
1080 | "Dynamic cache entries\n" | |
1081 | "Shortcut entries\n") | |
1082 | { | |
f4e14fdb | 1083 | struct vrf *vrf = vrf_lookup_by_id(VRF_DEFAULT); |
2fb975da TT |
1084 | struct interface *ifp; |
1085 | struct info_ctx ctx = { | |
996c9314 | 1086 | .vty = vty, .afi = cmd_to_afi(argv[1]), .count = 0, |
2fb975da TT |
1087 | }; |
1088 | ||
819dc8bb | 1089 | if (argc <= 3 || argv[3]->text[0] == 'c') { |
451fda4f | 1090 | FOR_ALL_INTERFACES (vrf, ifp) |
2fb975da TT |
1091 | nhrp_cache_foreach(ifp, clear_nhrp_cache, &ctx); |
1092 | } else { | |
1093 | nhrp_shortcut_foreach(ctx.afi, clear_nhrp_shortcut, &ctx); | |
2b55509d AL |
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); | |
2fb975da TT |
1100 | } |
1101 | ||
1102 | if (!ctx.count) { | |
996c9314 | 1103 | vty_out(vty, "%% No entries\n"); |
2fb975da TT |
1104 | return CMD_WARNING; |
1105 | } | |
1106 | ||
996c9314 | 1107 | vty_out(vty, "%% %d entries cleared\n", ctx.count); |
2fb975da TT |
1108 | return CMD_SUCCESS; |
1109 | } | |
1110 | ||
1111 | struct write_map_ctx { | |
1112 | struct vty *vty; | |
1113 | int family; | |
1114 | const char *aficmd; | |
1115 | }; | |
1116 | ||
0f8595a9 RD |
1117 | static void interface_config_write_nhrp_map(struct nhrp_cache_config *c, |
1118 | void *data) | |
2fb975da TT |
1119 | { |
1120 | struct write_map_ctx *ctx = data; | |
1121 | struct vty *vty = ctx->vty; | |
2fb975da | 1122 | |
996c9314 LB |
1123 | if (sockunion_family(&c->remote_addr) != ctx->family) |
1124 | return; | |
2fb975da | 1125 | |
46d3c185 RD |
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); | |
2fb975da TT |
1131 | } |
1132 | ||
1133 | static int interface_config_write(struct vty *vty) | |
1134 | { | |
f4e14fdb | 1135 | struct vrf *vrf = vrf_lookup_by_id(VRF_DEFAULT); |
2fb975da | 1136 | struct write_map_ctx mapctx; |
2fb975da TT |
1137 | struct interface *ifp; |
1138 | struct nhrp_interface *nifp; | |
1139 | struct nhrp_nhs *nhs; | |
fa31fcf2 | 1140 | struct nhrp_multicast *mcast; |
2fb975da TT |
1141 | const char *aficmd; |
1142 | afi_t afi; | |
2fb975da TT |
1143 | int i; |
1144 | ||
451fda4f | 1145 | FOR_ALL_INTERFACES (vrf, ifp) { |
788a036f | 1146 | if_vty_config_start(vty, ifp); |
2fb975da | 1147 | if (ifp->desc) |
996c9314 | 1148 | vty_out(vty, " description %s\n", ifp->desc); |
2fb975da TT |
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); | |
996c9314 | 1157 | vty_out(vty, "\n"); |
2fb975da TT |
1158 | } |
1159 | if (nifp->source) | |
996c9314 | 1160 | vty_out(vty, " tunnel source %s\n", nifp->source); |
2fb975da TT |
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) | |
996c9314 LB |
1168 | vty_out(vty, " %s nhrp network-id %u\n", aficmd, |
1169 | ad->network_id); | |
2fb975da TT |
1170 | |
1171 | if (ad->holdtime != NHRPD_DEFAULT_HOLDTIME) | |
996c9314 LB |
1172 | vty_out(vty, " %s nhrp holdtime %u\n", aficmd, |
1173 | ad->holdtime); | |
2fb975da TT |
1174 | |
1175 | if (ad->configured_mtu < 0) | |
996c9314 | 1176 | vty_out(vty, " %s nhrp mtu opennhrp\n", aficmd); |
2fb975da | 1177 | else if (ad->configured_mtu) |
996c9314 LB |
1178 | vty_out(vty, " %s nhrp mtu %u\n", aficmd, |
1179 | ad->configured_mtu); | |
2fb975da TT |
1180 | |
1181 | for (i = 0; interface_flags_desc[i].str != NULL; i++) { | |
1182 | if (!(ad->flags & interface_flags_desc[i].key)) | |
1183 | continue; | |
996c9314 LB |
1184 | vty_out(vty, " %s nhrp %s\n", aficmd, |
1185 | interface_flags_desc[i].str); | |
2fb975da TT |
1186 | } |
1187 | ||
996c9314 | 1188 | mapctx = (struct write_map_ctx){ |
2fb975da TT |
1189 | .vty = vty, |
1190 | .family = afi2family(afi), | |
1191 | .aficmd = aficmd, | |
1192 | }; | |
0f8595a9 RD |
1193 | nhrp_cache_config_foreach( |
1194 | ifp, interface_config_write_nhrp_map, &mapctx); | |
2fb975da | 1195 | |
2ab2a761 | 1196 | frr_each (nhrp_nhslist, &ad->nhslist_head, nhs) { |
46d3c185 RD |
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); | |
7a807a20 | 1203 | vty_out(vty, " nbma %s\n", nhs->nbma_fqdn); |
2fb975da | 1204 | } |
fa31fcf2 | 1205 | |
db4db2bb | 1206 | frr_each (nhrp_mcastlist, &ad->mcastlist_head, mcast) { |
46d3c185 RD |
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); | |
fa31fcf2 | 1214 | } |
2fb975da TT |
1215 | } |
1216 | ||
788a036f | 1217 | if_vty_config_end(vty); |
2fb975da TT |
1218 | } |
1219 | ||
1220 | return 0; | |
1221 | } | |
1222 | ||
1223 | void nhrp_config_init(void) | |
1224 | { | |
612c2c15 | 1225 | install_node(&zebra_node); |
2fb975da TT |
1226 | install_default(ZEBRA_NODE); |
1227 | ||
d2057ea3 | 1228 | /* access-list commands */ |
996c9314 | 1229 | access_list_init(); |
d2057ea3 | 1230 | |
2fb975da | 1231 | /* global commands */ |
2fb975da TT |
1232 | install_element(VIEW_NODE, &show_ip_nhrp_cmd); |
1233 | install_element(VIEW_NODE, &show_dmvpn_cmd); | |
2fb975da TT |
1234 | install_element(ENABLE_NODE, &clear_nhrp_cmd); |
1235 | ||
dd73744d IR |
1236 | install_element(ENABLE_NODE, &show_debugging_nhrp_cmd); |
1237 | ||
2fb975da TT |
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); | |
9084e209 AL |
1248 | install_element(CONFIG_NODE, &nhrp_multicast_nflog_group_cmd); |
1249 | install_element(CONFIG_NODE, &no_nhrp_multicast_nflog_group_cmd); | |
2fb975da | 1250 | |
cfc369c4 | 1251 | vrf_cmd_init(NULL); |
f5eef2d5 | 1252 | |
2fb975da | 1253 | /* interface specific commands */ |
9da01b0b | 1254 | if_cmd_init(interface_config_write); |
2fb975da TT |
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); | |
2d4eab22 | 1270 | install_element(INTERFACE_NODE, &if_no_nhrp_map_cmd); |
fa31fcf2 AL |
1271 | install_element(INTERFACE_NODE, &if_nhrp_map_multicast_cmd); |
1272 | install_element(INTERFACE_NODE, &if_no_nhrp_map_multicast_cmd); | |
2fb975da TT |
1273 | install_element(INTERFACE_NODE, &if_nhrp_nhs_cmd); |
1274 | install_element(INTERFACE_NODE, &if_no_nhrp_nhs_cmd); | |
1275 | } |