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