]>
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 | ||
2fb975da | 573 | DEFUN(if_nhrp_nhs, if_nhrp_nhs_cmd, |
819dc8bb | 574 | AFI_CMD " nhrp nhs <A.B.C.D|X:X::X:X|dynamic> nbma <A.B.C.D|FQDN>", |
2fb975da TT |
575 | AFI_STR |
576 | NHRP_STR | |
577 | "Nexthop Server configuration\n" | |
578 | "IPv4 protocol address\n" | |
579 | "IPv6 protocol address\n" | |
580 | "Automatic detection of protocol address\n" | |
819dc8bb | 581 | "NBMA address\n" |
2fb975da TT |
582 | "IPv4 NBMA address\n" |
583 | "Fully qualified domain name for NBMA address(es)\n") | |
584 | { | |
819dc8bb | 585 | VTY_DECLVAR_CONTEXT(interface, ifp); |
2fb975da TT |
586 | afi_t afi = cmd_to_afi(argv[0]); |
587 | union sockunion proto_addr; | |
588 | int ret; | |
589 | ||
819dc8bb | 590 | if (str2sockunion(argv[3]->arg, &proto_addr) < 0) |
2fb975da TT |
591 | sockunion_family(&proto_addr) = AF_UNSPEC; |
592 | ||
819dc8bb | 593 | ret = nhrp_nhs_add(ifp, afi, &proto_addr, argv[5]->arg); |
2fb975da TT |
594 | return nhrp_vty_return(vty, ret); |
595 | } | |
596 | ||
597 | DEFUN(if_no_nhrp_nhs, if_no_nhrp_nhs_cmd, | |
819dc8bb | 598 | "no " AFI_CMD " nhrp nhs <A.B.C.D|X:X::X:X|dynamic> nbma <A.B.C.D|FQDN>", |
2fb975da TT |
599 | NO_STR |
600 | AFI_STR | |
601 | NHRP_STR | |
602 | "Nexthop Server configuration\n" | |
603 | "IPv4 protocol address\n" | |
604 | "IPv6 protocol address\n" | |
605 | "Automatic detection of protocol address\n" | |
819dc8bb | 606 | "NBMA address\n" |
2fb975da TT |
607 | "IPv4 NBMA address\n" |
608 | "Fully qualified domain name for NBMA address(es)\n") | |
609 | { | |
819dc8bb DL |
610 | VTY_DECLVAR_CONTEXT(interface, ifp); |
611 | afi_t afi = cmd_to_afi(argv[1]); | |
2fb975da TT |
612 | union sockunion proto_addr; |
613 | int ret; | |
614 | ||
819dc8bb | 615 | if (str2sockunion(argv[4]->arg, &proto_addr) < 0) |
2fb975da TT |
616 | sockunion_family(&proto_addr) = AF_UNSPEC; |
617 | ||
819dc8bb | 618 | ret = nhrp_nhs_del(ifp, afi, &proto_addr, argv[6]->arg); |
2fb975da TT |
619 | return nhrp_vty_return(vty, ret); |
620 | } | |
621 | ||
622 | struct info_ctx { | |
623 | struct vty *vty; | |
624 | afi_t afi; | |
625 | int count; | |
87b9e982 | 626 | struct json_object *json; |
2fb975da TT |
627 | }; |
628 | ||
629 | static void show_ip_nhrp_cache(struct nhrp_cache *c, void *pctx) | |
630 | { | |
631 | struct info_ctx *ctx = pctx; | |
632 | struct vty *vty = ctx->vty; | |
85365e51 | 633 | char buf[3][SU_ADDRSTRLEN]; |
87b9e982 | 634 | struct json_object *json = NULL; |
2fb975da TT |
635 | |
636 | if (ctx->afi != family2afi(sockunion_family(&c->remote_addr))) | |
637 | return; | |
638 | ||
87b9e982 PG |
639 | |
640 | if (!ctx->count && !ctx->json) { | |
00683a14 RD |
641 | vty_out(vty, "%-8s %-8s %-24s %-24s %-24s %-6s %s\n", "Iface", |
642 | "Type", "Protocol", "NBMA", "Claimed NBMA", "Flags", | |
643 | "Identity"); | |
2fb975da TT |
644 | } |
645 | ctx->count++; | |
646 | ||
87b9e982 | 647 | sockunion2str(&c->remote_addr, buf[0], sizeof(buf[0])); |
bcf5673d AL |
648 | if (c->cur.type == NHRP_CACHE_LOCAL) { |
649 | struct nhrp_interface *nifp = c->ifp->info; | |
87b9e982 | 650 | |
bcf5673d AL |
651 | if (sockunion_family(&nifp->nbma) != AF_UNSPEC) { |
652 | sockunion2str(&nifp->nbma, buf[1], sizeof(buf[1])); | |
653 | sockunion2str(&nifp->nbma, buf[2], sizeof(buf[2])); | |
654 | } | |
655 | else { | |
656 | snprintf(buf[1], sizeof(buf[1]), "-"); | |
657 | snprintf(buf[2], sizeof(buf[2]), "-"); | |
658 | } | |
85365e51 | 659 | |
bcf5673d AL |
660 | /* if we are behind NAT then update NBMA field */ |
661 | if (sockunion_family(&nifp->nat_nbma) != AF_UNSPEC) | |
662 | sockunion2str(&nifp->nat_nbma, buf[1], sizeof(buf[1])); | |
663 | } else { | |
664 | if (c->cur.peer) | |
665 | sockunion2str(&c->cur.peer->vc->remote.nbma, | |
666 | buf[1], sizeof(buf[1])); | |
667 | else | |
668 | snprintf(buf[1], sizeof(buf[1]), "-"); | |
669 | ||
670 | if (c->cur.peer | |
671 | && sockunion_family(&c->cur.remote_nbma_claimed) | |
0551aead | 672 | != AF_UNSPEC) |
bcf5673d AL |
673 | sockunion2str(&c->cur.remote_nbma_claimed, |
674 | buf[2], sizeof(buf[2])); | |
675 | else | |
676 | snprintf(buf[2], sizeof(buf[2]), "-"); | |
677 | } | |
85365e51 | 678 | |
e0a1fb22 | 679 | if (ctx->json) { |
87b9e982 PG |
680 | json = json_object_new_object(); |
681 | json_object_string_add(json, "interface", c->ifp->name); | |
682 | json_object_string_add(json, "type", | |
683 | nhrp_cache_type_str[c->cur.type]); | |
684 | json_object_string_add(json, "protocol", buf[0]); | |
685 | json_object_string_add(json, "nbma", buf[1]); | |
85365e51 | 686 | json_object_string_add(json, "claimed_nbma", buf[2]); |
87b9e982 PG |
687 | |
688 | if (c->used) | |
689 | json_object_boolean_true_add(json, "used"); | |
690 | else | |
691 | json_object_boolean_false_add(json, "used"); | |
692 | ||
693 | if (c->t_timeout) | |
694 | json_object_boolean_true_add(json, "timeout"); | |
695 | else | |
696 | json_object_boolean_false_add(json, "timeout"); | |
697 | ||
698 | if (c->t_auth) | |
699 | json_object_boolean_true_add(json, "auth"); | |
700 | else | |
701 | json_object_boolean_false_add(json, "auth"); | |
702 | ||
703 | if (c->cur.peer) | |
704 | json_object_string_add(json, "identity", | |
705 | c->cur.peer->vc->remote.id); | |
706 | else | |
707 | json_object_string_add(json, "identity", "-"); | |
708 | ||
709 | json_object_array_add(ctx->json, json); | |
710 | return; | |
711 | } | |
85365e51 AL |
712 | vty_out(ctx->vty, "%-8s %-8s %-24s %-24s %-24s %c%c%c %s\n", |
713 | c->ifp->name, | |
2fb975da | 714 | nhrp_cache_type_str[c->cur.type], |
85365e51 | 715 | buf[0], buf[1], buf[2], |
996c9314 | 716 | c->used ? 'U' : ' ', c->t_timeout ? 'T' : ' ', |
2fb975da | 717 | c->t_auth ? 'A' : ' ', |
96ade3ed | 718 | c->cur.peer ? c->cur.peer->vc->remote.id : "-"); |
2fb975da TT |
719 | } |
720 | ||
996c9314 LB |
721 | static void show_ip_nhrp_nhs(struct nhrp_nhs *n, struct nhrp_registration *reg, |
722 | void *pctx) | |
0ca036b4 TT |
723 | { |
724 | struct info_ctx *ctx = pctx; | |
725 | struct vty *vty = ctx->vty; | |
726 | char buf[2][SU_ADDRSTRLEN]; | |
87b9e982 | 727 | struct json_object *json = NULL; |
0ca036b4 | 728 | |
87b9e982 | 729 | if (!ctx->count && !ctx->json) { |
996c9314 LB |
730 | vty_out(vty, "%-8s %-24s %-16s %-16s\n", "Iface", "FQDN", |
731 | "NBMA", "Protocol"); | |
0ca036b4 TT |
732 | } |
733 | ctx->count++; | |
734 | ||
87b9e982 PG |
735 | if (reg && reg->peer) |
736 | sockunion2str(®->peer->vc->remote.nbma, | |
737 | buf[0], sizeof(buf[0])); | |
738 | else | |
739 | snprintf(buf[0], sizeof(buf[0]), "-"); | |
740 | sockunion2str(reg ? ®->proto_addr : &n->proto_addr, buf[1], | |
741 | sizeof(buf[1])); | |
742 | ||
743 | if (ctx->json) { | |
744 | json = json_object_new_object(); | |
745 | json_object_string_add(json, "interface", n->ifp->name); | |
746 | json_object_string_add(json, "fqdn", n->nbma_fqdn); | |
747 | json_object_string_add(json, "nbma", buf[0]); | |
748 | json_object_string_add(json, "protocol", buf[1]); | |
749 | ||
750 | json_object_array_add(ctx->json, json); | |
751 | return; | |
752 | } | |
753 | ||
996c9314 | 754 | vty_out(vty, "%-8s %-24s %-16s %-16s\n", n->ifp->name, n->nbma_fqdn, |
87b9e982 | 755 | buf[0], buf[1]); |
0ca036b4 TT |
756 | } |
757 | ||
758 | static void show_ip_nhrp_shortcut(struct nhrp_shortcut *s, void *pctx) | |
759 | { | |
760 | struct info_ctx *ctx = pctx; | |
761 | struct nhrp_cache *c; | |
762 | struct vty *vty = ctx->vty; | |
763 | char buf1[PREFIX_STRLEN], buf2[SU_ADDRSTRLEN]; | |
87b9e982 | 764 | struct json_object *json = NULL; |
0ca036b4 TT |
765 | |
766 | if (!ctx->count) { | |
996c9314 | 767 | vty_out(vty, "%-8s %-24s %-24s %s\n", "Type", "Prefix", "Via", |
96ade3ed | 768 | "Identity"); |
0ca036b4 TT |
769 | } |
770 | ctx->count++; | |
771 | ||
772 | c = s->cache; | |
87b9e982 PG |
773 | if (c) |
774 | sockunion2str(&c->remote_addr, buf2, sizeof(buf2)); | |
775 | prefix2str(s->p, buf1, sizeof(buf1)); | |
776 | ||
777 | if (ctx->json) { | |
778 | json = json_object_new_object(); | |
779 | json_object_string_add(json, "type", | |
780 | nhrp_cache_type_str[s->type]); | |
781 | json_object_string_add(json, "prefix", buf1); | |
782 | ||
783 | if (c) | |
784 | json_object_string_add(json, "via", buf2); | |
785 | ||
786 | if (c && c->cur.peer) | |
787 | json_object_string_add(json, "identity", | |
788 | c->cur.peer->vc->remote.id); | |
789 | else | |
790 | json_object_string_add(json, "identity", ""); | |
791 | ||
792 | json_object_array_add(ctx->json, json); | |
793 | return; | |
794 | } | |
795 | ||
796 | vty_out(ctx->vty, "%-8s %-24s %-24s %s\n", | |
797 | nhrp_cache_type_str[s->type], | |
798 | buf1, buf2, | |
96ade3ed | 799 | (c && c->cur.peer) ? c->cur.peer->vc->remote.id : ""); |
0ca036b4 TT |
800 | } |
801 | ||
2fb975da TT |
802 | static void show_ip_opennhrp_cache(struct nhrp_cache *c, void *pctx) |
803 | { | |
804 | struct info_ctx *ctx = pctx; | |
87b9e982 PG |
805 | char buf[3][SU_ADDRSTRLEN]; |
806 | struct json_object *json = NULL; | |
807 | ||
2fb975da TT |
808 | |
809 | if (ctx->afi != family2afi(sockunion_family(&c->remote_addr))) | |
810 | return; | |
811 | ||
87b9e982 PG |
812 | sockunion2str(&c->remote_addr, buf[0], sizeof(buf[0])); |
813 | if (c->cur.peer) | |
814 | sockunion2str(&c->cur.peer->vc->remote.nbma, buf[1], | |
815 | sizeof(buf[1])); | |
816 | if (sockunion_family(&c->cur.remote_nbma_natoa) != AF_UNSPEC) | |
817 | sockunion2str(&c->cur.remote_nbma_natoa, buf[2], | |
818 | sizeof(buf[2])); | |
819 | if (ctx->json) { | |
820 | json = json_object_new_object(); | |
821 | json_object_string_add(json, "type", | |
822 | nhrp_cache_type_str[c->cur.type]); | |
823 | ||
824 | if (c->cur.peer && c->cur.peer->online) | |
825 | json_object_boolean_true_add(json, "up"); | |
826 | else | |
827 | json_object_boolean_false_add(json, "up"); | |
828 | ||
829 | if (c->used) | |
830 | json_object_boolean_true_add(json, "used"); | |
831 | else | |
832 | json_object_boolean_false_add(json, "used"); | |
833 | ||
834 | json_object_string_add(json, "protocolAddress", buf[0]); | |
835 | json_object_int_add(json, "protocolAddressSize", | |
836 | 8 * family2addrsize(sockunion_family | |
837 | (&c->remote_addr))); | |
838 | ||
839 | if (c->cur.peer) | |
840 | json_object_string_add(json, "nbmaAddress", buf[1]); | |
841 | ||
842 | if (sockunion_family(&c->cur.remote_nbma_natoa) != AF_UNSPEC) | |
843 | json_object_string_add(json, "nbmaNatOaAddress", | |
844 | buf[2]); | |
845 | ||
846 | json_object_array_add(ctx->json, json); | |
847 | return; | |
848 | } | |
181039f3 | 849 | vty_out(ctx->vty, |
996c9314 LB |
850 | "Type: %s\n" |
851 | "Flags:%s%s\n" | |
852 | "Protocol-Address: %s/%zu\n", | |
853 | nhrp_cache_type_str[c->cur.type], | |
854 | (c->cur.peer && c->cur.peer->online) ? " up" : "", | |
855 | c->used ? " used" : "", | |
87b9e982 | 856 | buf[0], |
996c9314 | 857 | 8 * family2addrsize(sockunion_family(&c->remote_addr))); |
2fb975da | 858 | |
87b9e982 PG |
859 | if (c->cur.peer) |
860 | vty_out(ctx->vty, "NBMA-Address: %s\n", buf[1]); | |
2fb975da | 861 | |
87b9e982 PG |
862 | if (sockunion_family(&c->cur.remote_nbma_natoa) != AF_UNSPEC) |
863 | vty_out(ctx->vty, "NBMA-NAT-OA-Address: %s\n", buf[2]); | |
2fb975da | 864 | |
181039f3 | 865 | vty_out(ctx->vty, "\n\n"); |
2fb975da TT |
866 | } |
867 | ||
2fb975da | 868 | DEFUN(show_ip_nhrp, show_ip_nhrp_cmd, |
87b9e982 | 869 | "show " AFI_CMD " nhrp [cache|nhs|shortcut|opennhrp] [json]", |
2fb975da TT |
870 | SHOW_STR |
871 | AFI_STR | |
872 | "NHRP information\n" | |
873 | "Forwarding cache information\n" | |
0ca036b4 | 874 | "Next hop server information\n" |
2fb975da | 875 | "Shortcut information\n" |
87b9e982 PG |
876 | "opennhrpctl style cache dump\n" |
877 | JSON_STR) | |
2fb975da | 878 | { |
f4e14fdb | 879 | struct vrf *vrf = vrf_lookup_by_id(VRF_DEFAULT); |
2fb975da TT |
880 | struct interface *ifp; |
881 | struct info_ctx ctx = { | |
87b9e982 | 882 | .vty = vty, .afi = cmd_to_afi(argv[1]), .json = NULL |
2fb975da | 883 | }; |
87b9e982 PG |
884 | bool uj = use_json(argc, argv); |
885 | struct json_object *json_path = NULL; | |
886 | struct json_object *json_vrf = NULL, *json_vrf_path = NULL; | |
887 | int ret = CMD_SUCCESS; | |
888 | ||
889 | if (uj) { | |
890 | json_vrf = json_object_new_object(); | |
891 | json_vrf_path = json_object_new_object(); | |
892 | json_path = json_object_new_array(); | |
893 | ctx.json = json_path; | |
894 | } | |
819dc8bb | 895 | if (argc <= 3 || argv[3]->text[0] == 'c') { |
451fda4f | 896 | FOR_ALL_INTERFACES (vrf, ifp) |
2fb975da | 897 | nhrp_cache_foreach(ifp, show_ip_nhrp_cache, &ctx); |
0ca036b4 | 898 | } else if (argv[3]->text[0] == 'n') { |
451fda4f | 899 | FOR_ALL_INTERFACES (vrf, ifp) |
0ca036b4 TT |
900 | nhrp_nhs_foreach(ifp, ctx.afi, show_ip_nhrp_nhs, &ctx); |
901 | } else if (argv[3]->text[0] == 's') { | |
902 | nhrp_shortcut_foreach(ctx.afi, show_ip_nhrp_shortcut, &ctx); | |
903 | } else { | |
87b9e982 PG |
904 | if (!ctx.json) |
905 | vty_out(vty, "Status: ok\n\n"); | |
906 | else | |
907 | json_object_string_add(json_vrf, "status", "ok"); | |
908 | ||
2fb975da | 909 | ctx.count++; |
451fda4f | 910 | FOR_ALL_INTERFACES (vrf, ifp) |
2fb975da | 911 | nhrp_cache_foreach(ifp, show_ip_opennhrp_cache, &ctx); |
2fb975da TT |
912 | } |
913 | ||
87b9e982 PG |
914 | if (uj) |
915 | json_object_int_add(json_vrf, "entriesCount", ctx.count); | |
2fb975da | 916 | if (!ctx.count) { |
87b9e982 PG |
917 | if (!ctx.json) |
918 | vty_out(vty, "%% No entries\n"); | |
919 | ret = CMD_WARNING; | |
2fb975da | 920 | } |
87b9e982 PG |
921 | if (uj) { |
922 | json_object_object_add(json_vrf_path, "attr", json_vrf); | |
923 | json_object_object_add(json_vrf_path, "table", ctx.json); | |
924 | vty_out(vty, "%s", | |
925 | json_object_to_json_string_ext( | |
926 | json_vrf_path, JSON_C_TO_STRING_PRETTY)); | |
927 | json_object_free(json_vrf_path); | |
928 | } | |
929 | return ret; | |
2fb975da TT |
930 | } |
931 | ||
87b9e982 PG |
932 | struct dmvpn_cfg { |
933 | struct vty *vty; | |
934 | struct json_object *json; | |
935 | }; | |
936 | ||
2fb975da TT |
937 | static void show_dmvpn_entry(struct nhrp_vc *vc, void *ctx) |
938 | { | |
87b9e982 PG |
939 | struct dmvpn_cfg *ctxt = ctx; |
940 | struct vty *vty; | |
2fb975da | 941 | char buf[2][SU_ADDRSTRLEN]; |
87b9e982 | 942 | struct json_object *json = NULL; |
2fb975da | 943 | |
87b9e982 PG |
944 | if (!ctxt || !ctxt->vty) |
945 | return; | |
946 | vty = ctxt->vty; | |
947 | sockunion2str(&vc->local.nbma, buf[0], sizeof(buf[0])); | |
948 | sockunion2str(&vc->remote.nbma, buf[1], sizeof(buf[1])); | |
949 | if (ctxt->json) { | |
950 | json = json_object_new_object(); | |
951 | json_object_string_add(json, "src", buf[0]); | |
952 | json_object_string_add(json, "dst", buf[1]); | |
953 | ||
954 | if (notifier_active(&vc->notifier_list)) | |
955 | json_object_boolean_true_add(json, "notifierActive"); | |
956 | else | |
957 | json_object_boolean_false_add(json, "notifierActive"); | |
958 | ||
959 | json_object_int_add(json, "sas", vc->ipsec); | |
960 | json_object_string_add(json, "identity", vc->remote.id); | |
961 | json_object_array_add(ctxt->json, json); | |
962 | } else { | |
963 | vty_out(vty, "%-24s %-24s %c %-4d %-24s\n", | |
964 | buf[0], buf[1], notifier_active(&vc->notifier_list) ? | |
965 | 'n' : ' ', vc->ipsec, vc->remote.id); | |
966 | } | |
2fb975da TT |
967 | } |
968 | ||
969 | DEFUN(show_dmvpn, show_dmvpn_cmd, | |
87b9e982 | 970 | "show dmvpn [json]", |
2fb975da | 971 | SHOW_STR |
87b9e982 PG |
972 | "DMVPN information\n" |
973 | JSON_STR) | |
974 | { | |
975 | bool uj = use_json(argc, argv); | |
976 | struct dmvpn_cfg ctxt; | |
977 | struct json_object *json_path = NULL; | |
978 | ||
979 | ctxt.vty = vty; | |
980 | if (!uj) { | |
981 | ctxt.json = NULL; | |
982 | vty_out(vty, "%-24s %-24s %-6s %-4s %-24s\n", | |
983 | "Src", "Dst", "Flags", "SAs", "Identity"); | |
984 | } else { | |
985 | json_path = json_object_new_array(); | |
986 | ctxt.json = json_path; | |
987 | } | |
988 | nhrp_vc_foreach(show_dmvpn_entry, &ctxt); | |
989 | if (uj) { | |
990 | vty_out(vty, "%s", | |
991 | json_object_to_json_string_ext( | |
992 | json_path, JSON_C_TO_STRING_PRETTY)); | |
993 | json_object_free(json_path); | |
994 | } | |
2fb975da TT |
995 | return CMD_SUCCESS; |
996 | } | |
997 | ||
998 | static void clear_nhrp_cache(struct nhrp_cache *c, void *data) | |
999 | { | |
1000 | struct info_ctx *ctx = data; | |
db89e514 | 1001 | if (c->cur.type <= NHRP_CACHE_DYNAMIC) { |
00683a14 RD |
1002 | nhrp_cache_update_binding(c, c->cur.type, -1, NULL, 0, NULL, |
1003 | NULL); | |
2fb975da TT |
1004 | ctx->count++; |
1005 | } | |
1006 | } | |
1007 | ||
1008 | static void clear_nhrp_shortcut(struct nhrp_shortcut *s, void *data) | |
1009 | { | |
1010 | struct info_ctx *ctx = data; | |
1011 | nhrp_shortcut_purge(s, 1); | |
1012 | ctx->count++; | |
1013 | } | |
1014 | ||
1015 | DEFUN(clear_nhrp, clear_nhrp_cmd, | |
819dc8bb | 1016 | "clear " AFI_CMD " nhrp <cache|shortcut>", |
2fb975da TT |
1017 | CLEAR_STR |
1018 | AFI_STR | |
1019 | NHRP_STR | |
1020 | "Dynamic cache entries\n" | |
1021 | "Shortcut entries\n") | |
1022 | { | |
f4e14fdb | 1023 | struct vrf *vrf = vrf_lookup_by_id(VRF_DEFAULT); |
2fb975da TT |
1024 | struct interface *ifp; |
1025 | struct info_ctx ctx = { | |
996c9314 | 1026 | .vty = vty, .afi = cmd_to_afi(argv[1]), .count = 0, |
2fb975da TT |
1027 | }; |
1028 | ||
819dc8bb | 1029 | if (argc <= 3 || argv[3]->text[0] == 'c') { |
451fda4f | 1030 | FOR_ALL_INTERFACES (vrf, ifp) |
2fb975da TT |
1031 | nhrp_cache_foreach(ifp, clear_nhrp_cache, &ctx); |
1032 | } else { | |
1033 | nhrp_shortcut_foreach(ctx.afi, clear_nhrp_shortcut, &ctx); | |
1034 | } | |
1035 | ||
1036 | if (!ctx.count) { | |
996c9314 | 1037 | vty_out(vty, "%% No entries\n"); |
2fb975da TT |
1038 | return CMD_WARNING; |
1039 | } | |
1040 | ||
996c9314 | 1041 | vty_out(vty, "%% %d entries cleared\n", ctx.count); |
2fb975da TT |
1042 | return CMD_SUCCESS; |
1043 | } | |
1044 | ||
1045 | struct write_map_ctx { | |
1046 | struct vty *vty; | |
1047 | int family; | |
1048 | const char *aficmd; | |
1049 | }; | |
1050 | ||
fef2ed13 | 1051 | static void interface_config_write_nhrp_map(struct nhrp_cache_config *c, void *data) |
2fb975da TT |
1052 | { |
1053 | struct write_map_ctx *ctx = data; | |
1054 | struct vty *vty = ctx->vty; | |
1055 | char buf[2][SU_ADDRSTRLEN]; | |
1056 | ||
996c9314 LB |
1057 | if (sockunion_family(&c->remote_addr) != ctx->family) |
1058 | return; | |
2fb975da | 1059 | |
996c9314 | 1060 | vty_out(vty, " %s nhrp map %s %s\n", ctx->aficmd, |
0d6f7fd6 | 1061 | sockunion2str(&c->remote_addr, buf[0], sizeof(buf[0])), |
fef2ed13 PG |
1062 | c->type == NHRP_CACHE_LOCAL |
1063 | ? "local" : sockunion2str(&c->nbma, buf[1], sizeof(buf[1]))); | |
2fb975da TT |
1064 | } |
1065 | ||
1066 | static int interface_config_write(struct vty *vty) | |
1067 | { | |
f4e14fdb | 1068 | struct vrf *vrf = vrf_lookup_by_id(VRF_DEFAULT); |
2fb975da | 1069 | struct write_map_ctx mapctx; |
2fb975da TT |
1070 | struct interface *ifp; |
1071 | struct nhrp_interface *nifp; | |
1072 | struct nhrp_nhs *nhs; | |
1073 | const char *aficmd; | |
1074 | afi_t afi; | |
1075 | char buf[SU_ADDRSTRLEN]; | |
1076 | int i; | |
1077 | ||
451fda4f | 1078 | FOR_ALL_INTERFACES (vrf, ifp) { |
a8b828f3 | 1079 | vty_frame(vty, "interface %s\n", ifp->name); |
2fb975da | 1080 | if (ifp->desc) |
996c9314 | 1081 | vty_out(vty, " description %s\n", ifp->desc); |
2fb975da TT |
1082 | |
1083 | nifp = ifp->info; | |
1084 | if (nifp->ipsec_profile) { | |
1085 | vty_out(vty, " tunnel protection vici profile %s", | |
1086 | nifp->ipsec_profile); | |
1087 | if (nifp->ipsec_fallback_profile) | |
1088 | vty_out(vty, " fallback-profile %s", | |
1089 | nifp->ipsec_fallback_profile); | |
996c9314 | 1090 | vty_out(vty, "\n"); |
2fb975da TT |
1091 | } |
1092 | if (nifp->source) | |
996c9314 | 1093 | vty_out(vty, " tunnel source %s\n", nifp->source); |
2fb975da TT |
1094 | |
1095 | for (afi = 0; afi < AFI_MAX; afi++) { | |
1096 | struct nhrp_afi_data *ad = &nifp->afi[afi]; | |
1097 | ||
1098 | aficmd = afi_to_cmd(afi); | |
1099 | ||
1100 | if (ad->network_id) | |
996c9314 LB |
1101 | vty_out(vty, " %s nhrp network-id %u\n", aficmd, |
1102 | ad->network_id); | |
2fb975da TT |
1103 | |
1104 | if (ad->holdtime != NHRPD_DEFAULT_HOLDTIME) | |
996c9314 LB |
1105 | vty_out(vty, " %s nhrp holdtime %u\n", aficmd, |
1106 | ad->holdtime); | |
2fb975da TT |
1107 | |
1108 | if (ad->configured_mtu < 0) | |
996c9314 | 1109 | vty_out(vty, " %s nhrp mtu opennhrp\n", aficmd); |
2fb975da | 1110 | else if (ad->configured_mtu) |
996c9314 LB |
1111 | vty_out(vty, " %s nhrp mtu %u\n", aficmd, |
1112 | ad->configured_mtu); | |
2fb975da TT |
1113 | |
1114 | for (i = 0; interface_flags_desc[i].str != NULL; i++) { | |
1115 | if (!(ad->flags & interface_flags_desc[i].key)) | |
1116 | continue; | |
996c9314 LB |
1117 | vty_out(vty, " %s nhrp %s\n", aficmd, |
1118 | interface_flags_desc[i].str); | |
2fb975da TT |
1119 | } |
1120 | ||
996c9314 | 1121 | mapctx = (struct write_map_ctx){ |
2fb975da TT |
1122 | .vty = vty, |
1123 | .family = afi2family(afi), | |
1124 | .aficmd = aficmd, | |
1125 | }; | |
fef2ed13 PG |
1126 | nhrp_cache_config_foreach(ifp, interface_config_write_nhrp_map, |
1127 | &mapctx); | |
2fb975da | 1128 | |
996c9314 LB |
1129 | list_for_each_entry(nhs, &ad->nhslist_head, |
1130 | nhslist_entry) | |
1131 | { | |
1132 | vty_out(vty, " %s nhrp nhs %s nbma %s\n", | |
2fb975da | 1133 | aficmd, |
996c9314 LB |
1134 | sockunion_family(&nhs->proto_addr) |
1135 | == AF_UNSPEC | |
1136 | ? "dynamic" | |
1137 | : sockunion2str( | |
1138 | &nhs->proto_addr, buf, | |
0d6f7fd6 | 1139 | sizeof(buf)), |
96ade3ed | 1140 | nhs->nbma_fqdn); |
2fb975da TT |
1141 | } |
1142 | } | |
1143 | ||
a8b828f3 | 1144 | vty_endframe(vty, "!\n"); |
2fb975da TT |
1145 | } |
1146 | ||
1147 | return 0; | |
1148 | } | |
1149 | ||
1150 | void nhrp_config_init(void) | |
1151 | { | |
612c2c15 | 1152 | install_node(&zebra_node); |
2fb975da TT |
1153 | install_default(ZEBRA_NODE); |
1154 | ||
d2057ea3 | 1155 | /* access-list commands */ |
996c9314 | 1156 | access_list_init(); |
d2057ea3 | 1157 | |
2fb975da | 1158 | /* global commands */ |
2fb975da TT |
1159 | install_element(VIEW_NODE, &show_ip_nhrp_cmd); |
1160 | install_element(VIEW_NODE, &show_dmvpn_cmd); | |
2fb975da TT |
1161 | install_element(ENABLE_NODE, &clear_nhrp_cmd); |
1162 | ||
dd73744d IR |
1163 | install_element(ENABLE_NODE, &show_debugging_nhrp_cmd); |
1164 | ||
2fb975da TT |
1165 | install_element(ENABLE_NODE, &debug_nhrp_cmd); |
1166 | install_element(ENABLE_NODE, &no_debug_nhrp_cmd); | |
1167 | ||
1168 | install_element(CONFIG_NODE, &debug_nhrp_cmd); | |
1169 | install_element(CONFIG_NODE, &no_debug_nhrp_cmd); | |
1170 | ||
1171 | install_element(CONFIG_NODE, &nhrp_event_socket_cmd); | |
1172 | install_element(CONFIG_NODE, &no_nhrp_event_socket_cmd); | |
1173 | install_element(CONFIG_NODE, &nhrp_nflog_group_cmd); | |
1174 | install_element(CONFIG_NODE, &no_nhrp_nflog_group_cmd); | |
1175 | ||
1176 | /* interface specific commands */ | |
612c2c15 | 1177 | install_node(&nhrp_interface_node); |
2fb975da | 1178 | |
819dc8bb | 1179 | if_cmd_init(); |
2fb975da TT |
1180 | install_element(INTERFACE_NODE, &tunnel_protection_cmd); |
1181 | install_element(INTERFACE_NODE, &no_tunnel_protection_cmd); | |
1182 | install_element(INTERFACE_NODE, &tunnel_source_cmd); | |
1183 | install_element(INTERFACE_NODE, &no_tunnel_source_cmd); | |
1184 | install_element(INTERFACE_NODE, &if_nhrp_network_id_cmd); | |
1185 | install_element(INTERFACE_NODE, &if_no_nhrp_network_id_cmd); | |
1186 | install_element(INTERFACE_NODE, &if_nhrp_holdtime_cmd); | |
1187 | install_element(INTERFACE_NODE, &if_no_nhrp_holdtime_cmd); | |
1188 | install_element(INTERFACE_NODE, &if_nhrp_mtu_cmd); | |
1189 | install_element(INTERFACE_NODE, &if_no_nhrp_mtu_cmd); | |
1190 | install_element(INTERFACE_NODE, &if_nhrp_flags_cmd); | |
1191 | install_element(INTERFACE_NODE, &if_no_nhrp_flags_cmd); | |
1192 | install_element(INTERFACE_NODE, &if_nhrp_reg_flags_cmd); | |
1193 | install_element(INTERFACE_NODE, &if_no_nhrp_reg_flags_cmd); | |
1194 | install_element(INTERFACE_NODE, &if_nhrp_map_cmd); | |
2d4eab22 | 1195 | install_element(INTERFACE_NODE, &if_no_nhrp_map_cmd); |
2fb975da TT |
1196 | install_element(INTERFACE_NODE, &if_nhrp_nhs_cmd); |
1197 | install_element(INTERFACE_NODE, &if_no_nhrp_nhs_cmd); | |
1198 | } |