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