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