]> git.proxmox.com Git - mirror_frr.git/blame - ldpd/ldp_vty_exec.c
Merge pull request #13649 from donaldsharp/unlock_the_node_or_else
[mirror_frr.git] / ldpd / ldp_vty_exec.c
CommitLineData
acddc0ed 1// SPDX-License-Identifier: GPL-2.0-or-later
eac6e3f0
RW
2/*
3 * Copyright (C) 2016 by Open Source Routing.
eac6e3f0
RW
4 */
5
6#include <zebra.h>
7#include <sys/un.h>
903a7226 8#include "lib/printfrr.h"
eac6e3f0
RW
9
10#include "ldpd.h"
11#include "ldpe.h"
12#include "lde.h"
13#include "log.h"
14#include "ldp_vty.h"
e8dbef04 15#include "lib/json.h"
eac6e3f0
RW
16
17#include "command.h"
18#include "vty.h"
19#include "mpls.h"
20
21enum show_command {
22 SHOW_DISC,
23 SHOW_IFACE,
24 SHOW_NBR,
25 SHOW_LIB,
26 SHOW_L2VPN_PW,
e1894ff7
KS
27 SHOW_L2VPN_BINDING,
28 SHOW_LDP_SYNC
eac6e3f0
RW
29};
30
a5d10512 31struct show_params {
eac6e3f0
RW
32 int family;
33 union ldpd_addr addr;
34 uint8_t prefixlen;
bc0eb287 35 int detail;
a5d10512 36 int json;
f0722791
RW
37 union {
38 struct {
39 struct in_addr lsr_id;
40 int capabilities;
41 } neighbor;
42 struct {
43 struct prefix prefix;
44 int longer_prefixes;
45 struct in_addr neighbor;
46 uint32_t local_label;
47 uint32_t remote_label;
48 } lib;
49 struct {
50 struct in_addr peer;
51 uint32_t local_label;
52 uint32_t remote_label;
53 char ifname[IFNAMSIZ];
54 uint32_t vcid;
55 } l2vpn;
56 };
eac6e3f0
RW
57};
58
59#define LDPBUFSIZ 65535
60
61static int show_interface_msg(struct vty *, struct imsg *,
a5d10512
RW
62 struct show_params *);
63static int show_interface_msg_json(struct imsg *,
64 struct show_params *, json_object *);
eac6e3f0 65static int show_discovery_msg(struct vty *, struct imsg *,
a5d10512 66 struct show_params *);
bc0eb287 67static void show_discovery_detail_adj(struct vty *, char *,
a5d10512 68 struct ctl_adj *);
bc0eb287
RW
69static int show_discovery_detail_msg(struct vty *, struct imsg *,
70 struct show_params *);
a5d10512
RW
71static int show_discovery_msg_json(struct imsg *,
72 struct show_params *, json_object *);
bc0eb287
RW
73static void show_discovery_detail_adj_json(json_object *,
74 struct ctl_adj *);
75static int show_discovery_detail_msg_json(struct imsg *,
76 struct show_params *, json_object *);
e1894ff7
KS
77static int show_ldp_sync_msg(struct vty *, struct imsg *,
78 struct show_params *);
79static int show_ldp_sync_msg_json(struct imsg *,
80 struct show_params *, json_object *);
99cfc17f 81
eac6e3f0 82static int show_nbr_msg(struct vty *, struct imsg *,
a5d10512 83 struct show_params *);
a5d10512
RW
84static int show_nbr_msg_json(struct imsg *, struct show_params *,
85 json_object *);
bc0eb287
RW
86static void show_nbr_detail_adj(struct vty *, char *,
87 struct ctl_adj *);
88static int show_nbr_detail_msg(struct vty *, struct imsg *,
89 struct show_params *);
90static void show_nbr_detail_adj_json(struct ctl_adj *,
91 json_object *);
92static int show_nbr_detail_msg_json(struct imsg *,
93 struct show_params *, json_object *);
0f7b5df9 94static void show_nbr_capabilities(struct vty *, struct ctl_nbr *);
99cfc17f
RW
95static int show_nbr_capabilities_msg(struct vty *, struct imsg *,
96 struct show_params *);
0f7b5df9
RW
97static void show_nbr_capabilities_json(struct ctl_nbr *,
98 json_object *);
99cfc17f
RW
99static int show_nbr_capabilities_msg_json(struct imsg *,
100 struct show_params *, json_object *);
eac6e3f0 101static int show_lib_msg(struct vty *, struct imsg *,
a5d10512 102 struct show_params *);
bc0eb287
RW
103static int show_lib_detail_msg(struct vty *, struct imsg *,
104 struct show_params *);
a5d10512
RW
105static int show_lib_msg_json(struct imsg *, struct show_params *,
106 json_object *);
bc0eb287
RW
107static int show_lib_detail_msg_json(struct imsg *,
108 struct show_params *, json_object *);
a5d10512
RW
109static int show_l2vpn_binding_msg(struct vty *, struct imsg *,
110 struct show_params *);
111static int show_l2vpn_binding_msg_json(struct imsg *,
112 struct show_params *, json_object *);
113static int show_l2vpn_pw_msg(struct vty *, struct imsg *,
114 struct show_params *);
115static int show_l2vpn_pw_msg_json(struct imsg *,
116 struct show_params *, json_object *);
a5d10512
RW
117static int ldp_vty_dispatch_msg(struct vty *, struct imsg *,
118 enum show_command, struct show_params *,
119 json_object *);
eac6e3f0 120static int ldp_vty_dispatch(struct vty *, struct imsgbuf *,
a5d10512 121 enum show_command, struct show_params *);
eac6e3f0
RW
122static int ldp_vty_get_af(const char *, int *);
123
124static int
125show_interface_msg(struct vty *vty, struct imsg *imsg,
a5d10512 126 struct show_params *params)
eac6e3f0
RW
127{
128 struct ctl_iface *iface;
129 char timers[BUFSIZ];
130
131 switch (imsg->hdr.type) {
132 case IMSG_CTL_SHOW_INTERFACE:
133 iface = imsg->data;
134
a5d10512 135 if (params->family != AF_UNSPEC && params->family != iface->af)
eac6e3f0
RW
136 break;
137
a5d10512
RW
138 snprintf(timers, sizeof(timers), "%u/%u",
139 iface->hello_interval, iface->hello_holdtime);
140
5c7571d4 141 vty_out (vty, "%-4s %-11s %-6s %-8s %-12s %3u\n",
a5d10512
RW
142 af_name(iface->af), iface->name,
143 if_state_name(iface->state), iface->uptime == 0 ?
144 "00:00:00" : log_time(iface->uptime), timers,
96ade3ed 145 iface->adj_cnt);
eac6e3f0
RW
146 break;
147 case IMSG_CTL_END:
6d3c2ed4 148 vty_out (vty, "\n");
eac6e3f0
RW
149 return (1);
150 default:
151 break;
152 }
153
154 return (0);
155}
156
a5d10512
RW
157static int
158show_interface_msg_json(struct imsg *imsg, struct show_params *params,
159 json_object *json)
160{
161 struct ctl_iface *iface;
162 json_object *json_iface;
163 char key_name[64];
164
165 switch (imsg->hdr.type) {
166 case IMSG_CTL_SHOW_INTERFACE:
167 iface = imsg->data;
168
169 if (params->family != AF_UNSPEC && params->family != iface->af)
170 break;
171
172 json_iface = json_object_new_object();
173 json_object_string_add(json_iface, "name", iface->name);
174 json_object_string_add(json_iface, "addressFamily",
175 af_name(iface->af));
176 json_object_string_add(json_iface, "state",
177 if_state_name(iface->state));
178 json_object_string_add(json_iface, "upTime",
179 log_time(iface->uptime));
180 json_object_int_add(json_iface, "helloInterval",
181 iface->hello_interval);
182 json_object_int_add(json_iface, "helloHoldtime",
183 iface->hello_holdtime);
184 json_object_int_add(json_iface, "adjacencyCount",
185 iface->adj_cnt);
186
772270f3
QY
187 snprintf(key_name, sizeof(key_name), "%s: %s", iface->name,
188 af_name(iface->af));
a5d10512
RW
189 json_object_object_add(json, key_name, json_iface);
190 break;
191 case IMSG_CTL_END:
192 return (1);
193 default:
194 break;
195 }
196
197 return (0);
198}
199
e1894ff7
KS
200static int
201show_ldp_sync_msg(struct vty *vty, struct imsg *imsg,
202 struct show_params *params)
203{
204 struct ctl_ldp_sync *iface;
205
206 switch (imsg->hdr.type) {
207 case IMSG_CTL_SHOW_LDP_SYNC:
208 iface = imsg->data;
209
210 vty_out (vty, "%s:\n", iface->name);
211 if (iface->in_sync)
212 vty_out (vty, " Status: initial label exchange complete\n");
213 else
214 vty_out (vty, " Status: label exchange not complete\n");
215
216 if (iface->timer_running) {
217 vty_out (vty, " Wait time: %d seconds (%d seconds left)\n",
218 iface->wait_time, iface->wait_time_remaining);
219 vty_out (vty, " Timer is running\n");
220 } else {
221 vty_out (vty, " Wait time: %d seconds\n",
222 iface->wait_time);
223 vty_out (vty, " Timer is not running\n");
224 }
225
226 if (iface->peer_ldp_id.s_addr)
903a7226
MS
227 vty_out (vty, " Peer LDP Identifier: %pI4:0\n",
228 &iface->peer_ldp_id);
e1894ff7
KS
229
230 break;
231 case IMSG_CTL_END:
232 return (1);
233 default:
234 break;
235 }
236
237 return (0);
238}
239
240static int
241show_ldp_sync_msg_json(struct imsg *imsg, struct show_params *params,
242 json_object *json)
243{
244 struct ctl_ldp_sync *iface;
245 json_object *json_iface;
903a7226 246 char buf[PREFIX_STRLEN];
e1894ff7
KS
247
248 switch (imsg->hdr.type) {
249 case IMSG_CTL_SHOW_LDP_SYNC:
250 iface = imsg->data;
251
252 json_iface = json_object_new_object();
253 json_object_string_add(json_iface, "state",
254 iface->in_sync
255 ? "labelExchangeComplete"
256 : "labelExchangeNotComplete");
257 json_object_int_add(json_iface, "waitTime",
258 iface->wait_time);
259 json_object_int_add(json_iface, "waitTimeRemaining",
260 iface->wait_time_remaining);
261
262 if (iface->timer_running)
263 json_object_boolean_true_add(json_iface, "timerRunning");
264 else
265 json_object_boolean_false_add(json_iface, "timerRunning");
266
267 json_object_string_add(json_iface, "peerLdpId",
268 iface->peer_ldp_id.s_addr ?
903a7226
MS
269 inet_ntop(AF_INET, &iface->peer_ldp_id, buf, sizeof(buf)) :
270 "");
e1894ff7
KS
271
272 json_object_object_add(json, iface->name, json_iface);
273 break;
274 case IMSG_CTL_END:
275 return (1);
276 default:
277 break;
278 }
279
280 return (0);
281}
282
bc0eb287
RW
283static int
284show_discovery_msg(struct vty *vty, struct imsg *imsg,
285 struct show_params *params)
286{
287 struct ctl_adj *adj;
288 const char *addr;
289
290 switch (imsg->hdr.type) {
291 case IMSG_CTL_SHOW_DISCOVERY:
292 adj = imsg->data;
293
294 if (params->family != AF_UNSPEC && params->family != adj->af)
295 break;
296
903a7226 297 vty_out(vty, "%-4s %-15pI4 ", af_name(adj->af), &adj->id);
bc0eb287
RW
298 switch(adj->type) {
299 case HELLO_LINK:
300 vty_out(vty, "%-8s %-15s ", "Link", adj->ifname);
301 break;
302 case HELLO_TARGETED:
303 addr = log_addr(adj->af, &adj->src_addr);
304
305 vty_out(vty, "%-8s %-15s ", "Targeted", addr);
306 if (strlen(addr) > 15)
61b7d449 307 vty_out(vty, "\n%46s", " ");
bc0eb287
RW
308 break;
309 }
5c7571d4 310 vty_out (vty, "%9u\n", adj->holdtime);
bc0eb287
RW
311 break;
312 case IMSG_CTL_END:
6d3c2ed4 313 vty_out (vty, "\n");
bc0eb287
RW
314 return (1);
315 default:
316 break;
317 }
318
319 return (0);
320}
321
eac6e3f0 322static void
bc0eb287 323show_discovery_detail_adj(struct vty *vty, char *buffer, struct ctl_adj *adj)
eac6e3f0
RW
324{
325 size_t buflen = strlen(buffer);
a5d10512 326
903a7226
MS
327 snprintfrr(buffer + buflen, LDPBUFSIZ - buflen,
328 " LSR Id: %pI4:0\n", &adj->id);
0f7b5df9
RW
329 buflen = strlen(buffer);
330 snprintf(buffer + buflen, LDPBUFSIZ - buflen,
625e016d
DL
331 " Source address: %s\n",
332 log_addr(adj->af, &adj->src_addr));
0f7b5df9
RW
333 buflen = strlen(buffer);
334 snprintf(buffer + buflen, LDPBUFSIZ - buflen,
625e016d
DL
335 " Transport address: %s\n",
336 log_addr(adj->af, &adj->trans_addr));
0f7b5df9
RW
337 buflen = strlen(buffer);
338 snprintf(buffer + buflen, LDPBUFSIZ - buflen,
625e016d
DL
339 " Hello hold time: %u secs (due in %u secs)\n",
340 adj->holdtime, adj->holdtime_remaining);
a5d10512
RW
341 buflen = strlen(buffer);
342 snprintf(buffer + buflen, LDPBUFSIZ - buflen,
625e016d
DL
343 " Dual-stack capability TLV: %s\n",
344 (adj->ds_tlv) ? "yes" : "no");
eac6e3f0
RW
345}
346
347static int
bc0eb287 348show_discovery_detail_msg(struct vty *vty, struct imsg *imsg,
a5d10512 349 struct show_params *params)
eac6e3f0
RW
350{
351 struct ctl_adj *adj;
352 struct ctl_disc_if *iface;
353 struct ctl_disc_tnbr *tnbr;
354 struct in_addr rtr_id;
355 union ldpd_addr *trans_addr;
356 size_t buflen;
357 static char ifaces_buffer[LDPBUFSIZ];
358 static char tnbrs_buffer[LDPBUFSIZ];
359
360 switch (imsg->hdr.type) {
361 case IMSG_CTL_SHOW_DISCOVERY:
362 ifaces_buffer[0] = '\0';
363 tnbrs_buffer[0] = '\0';
364 break;
365 case IMSG_CTL_SHOW_DISC_IFACE:
366 iface = imsg->data;
367
a5d10512
RW
368 if (params->family != AF_UNSPEC &&
369 ((params->family == AF_INET && !iface->active_v4) ||
370 (params->family == AF_INET6 && !iface->active_v6)))
eac6e3f0
RW
371 break;
372
a5d10512
RW
373 buflen = strlen(ifaces_buffer);
374 snprintf(ifaces_buffer + buflen, LDPBUFSIZ - buflen,
625e016d
DL
375 " %s: %s\n", iface->name, (iface->no_adj) ?
376 "(no adjacencies)" : "");
a5d10512
RW
377 break;
378 case IMSG_CTL_SHOW_DISC_TNBR:
379 tnbr = imsg->data;
e8dbef04 380
a5d10512
RW
381 if (params->family != AF_UNSPEC && params->family != tnbr->af)
382 break;
e8dbef04 383
a5d10512
RW
384 trans_addr = &(ldp_af_conf_get(ldpd_conf,
385 tnbr->af))->trans_addr;
386 buflen = strlen(tnbrs_buffer);
387 snprintf(tnbrs_buffer + buflen, LDPBUFSIZ - buflen,
625e016d 388 " %s -> %s: %s\n", log_addr(tnbr->af, trans_addr),
0f7b5df9 389 log_addr(tnbr->af, &tnbr->addr), (tnbr->no_adj) ?
625e016d 390 "(no adjacencies)" : "");
a5d10512
RW
391 break;
392 case IMSG_CTL_SHOW_DISC_ADJ:
393 adj = imsg->data;
e8dbef04 394
a5d10512
RW
395 if (params->family != AF_UNSPEC && params->family != adj->af)
396 break;
e8dbef04 397
a5d10512
RW
398 switch(adj->type) {
399 case HELLO_LINK:
bc0eb287 400 show_discovery_detail_adj(vty, ifaces_buffer, adj);
a5d10512
RW
401 break;
402 case HELLO_TARGETED:
bc0eb287 403 show_discovery_detail_adj(vty, tnbrs_buffer, adj);
a5d10512
RW
404 break;
405 }
406 break;
407 case IMSG_CTL_END:
408 rtr_id.s_addr = ldp_rtr_id_get(ldpd_conf);
5c7571d4 409 vty_out (vty, "Local:\n");
903a7226 410 vty_out (vty, " LSR Id: %pI4:0\n",&rtr_id);
2073f929 411 if (CHECK_FLAG(ldpd_conf->ipv4.flags, F_LDPD_AF_ENABLED))
5c7571d4 412 vty_out (vty, " Transport Address (IPv4): %s\n",
96ade3ed 413 log_addr(AF_INET, &ldpd_conf->ipv4.trans_addr));
2073f929 414 if (CHECK_FLAG(ldpd_conf->ipv6.flags, F_LDPD_AF_ENABLED))
5c7571d4 415 vty_out (vty, " Transport Address (IPv6): %s\n",
96ade3ed 416 log_addr(AF_INET6, &ldpd_conf->ipv6.trans_addr));
5c7571d4
DL
417 vty_out (vty, "Discovery Sources:\n");
418 vty_out (vty, " Interfaces:\n");
a5d10512 419 vty_out(vty, "%s", ifaces_buffer);
5c7571d4 420 vty_out (vty, " Targeted Hellos:\n");
a5d10512 421 vty_out(vty, "%s", tnbrs_buffer);
6d3c2ed4 422 vty_out (vty, "\n");
a5d10512
RW
423 return (1);
424 default:
425 break;
426 }
e8dbef04 427
a5d10512
RW
428 return (0);
429}
430
bc0eb287
RW
431static int
432show_discovery_msg_json(struct imsg *imsg, struct show_params *params,
433 json_object *json)
434{
435 struct ctl_adj *adj;
436 json_object *json_array;
437 json_object *json_adj;
438
439 switch (imsg->hdr.type) {
440 case IMSG_CTL_SHOW_DISCOVERY:
441 adj = imsg->data;
442
443 if (params->family != AF_UNSPEC && params->family != adj->af)
444 break;
445
446 json_object_object_get_ex(json, "adjacencies", &json_array);
447 if (!json_array) {
448 json_array = json_object_new_array();
449 json_object_object_add(json, "adjacencies", json_array);
450 }
451
452 json_adj = json_object_new_object();
453 json_object_string_add(json_adj, "addressFamily",
454 af_name(adj->af));
19fee2b7
DA
455 json_object_string_addf(json_adj, "neighborId", "%pI4",
456 &adj->id);
bc0eb287
RW
457 switch(adj->type) {
458 case HELLO_LINK:
459 json_object_string_add(json_adj, "type", "link");
460 json_object_string_add(json_adj, "interface",
461 adj->ifname);
462 break;
463 case HELLO_TARGETED:
464 json_object_string_add(json_adj, "type", "targeted");
465 json_object_string_add(json_adj, "peer",
466 log_addr(adj->af, &adj->src_addr));
467 break;
468 }
469 json_object_int_add(json_adj, "helloHoldtime", adj->holdtime);
470
471 json_object_array_add(json_array, json_adj);
472 break;
473 case IMSG_CTL_END:
474 return (1);
475 default:
476 break;
477 }
478
479 return (0);
480}
481
a5d10512 482static void
bc0eb287 483show_discovery_detail_adj_json(json_object *json, struct ctl_adj *adj)
a5d10512
RW
484{
485 json_object *json_adj;
486 json_object *json_array;
487
488 json_object_object_get_ex(json, "adjacencies", &json_array);
489 if (!json_array) {
490 json_array = json_object_new_array();
491 json_object_object_add(json, "adjacencies", json_array);
492 }
493
494 json_adj = json_object_new_object();
19fee2b7 495 json_object_string_addf(json_adj, "lsrId", "%pI4", &adj->id);
0f7b5df9
RW
496 json_object_string_add(json_adj, "sourceAddress", log_addr(adj->af,
497 &adj->src_addr));
a5d10512
RW
498 json_object_string_add(json_adj, "transportAddress", log_addr(adj->af,
499 &adj->trans_addr));
0f7b5df9
RW
500 json_object_int_add(json_adj, "helloHoldtime", adj->holdtime);
501 json_object_int_add(json_adj, "helloHoldtimeRemaining",
502 adj->holdtime_remaining);
503 json_object_int_add(json_adj, "dualStackCapabilityTlv",
504 adj->ds_tlv);
a5d10512
RW
505 json_object_array_add(json_array, json_adj);
506}
507
508static int
bc0eb287 509show_discovery_detail_msg_json(struct imsg *imsg, struct show_params *params,
a5d10512
RW
510 json_object *json)
511{
512 struct ctl_adj *adj;
513 struct ctl_disc_if *iface;
514 struct ctl_disc_tnbr *tnbr;
515 struct in_addr rtr_id;
516 union ldpd_addr *trans_addr;
517 json_object *json_interface;
518 json_object *json_target;
519 static json_object *json_interfaces;
520 static json_object *json_targets;
521 static json_object *json_container;
522
523 switch (imsg->hdr.type) {
524 case IMSG_CTL_SHOW_DISCOVERY:
525 rtr_id.s_addr = ldp_rtr_id_get(ldpd_conf);
19fee2b7 526 json_object_string_addf(json, "lsrId", "%pI4", &rtr_id);
2073f929 527 if (CHECK_FLAG(ldpd_conf->ipv4.flags, F_LDPD_AF_ENABLED))
0f7b5df9
RW
528 json_object_string_add(json, "transportAddressIPv4",
529 log_addr(AF_INET, &ldpd_conf->ipv4.trans_addr));
2073f929 530 if (CHECK_FLAG(ldpd_conf->ipv6.flags, F_LDPD_AF_ENABLED))
0f7b5df9
RW
531 json_object_string_add(json, "transportAddressIPv6",
532 log_addr(AF_INET6, &ldpd_conf->ipv6.trans_addr));
a5d10512
RW
533 json_interfaces = json_object_new_object();
534 json_object_object_add(json, "interfaces", json_interfaces);
535 json_targets = json_object_new_object();
536 json_object_object_add(json, "targetedHellos", json_targets);
537 json_container = NULL;
eac6e3f0 538 break;
a5d10512
RW
539 case IMSG_CTL_SHOW_DISC_IFACE:
540 iface = imsg->data;
eac6e3f0 541
a5d10512
RW
542 if (params->family != AF_UNSPEC &&
543 ((params->family == AF_INET && !iface->active_v4) ||
544 (params->family == AF_INET6 && !iface->active_v6)))
eac6e3f0
RW
545 break;
546
a5d10512 547 json_interface = json_object_new_object();
a5d10512
RW
548 json_object_object_add(json_interfaces, iface->name,
549 json_interface);
550 json_container = json_interface;
551 break;
552 case IMSG_CTL_SHOW_DISC_TNBR:
553 tnbr = imsg->data;
e8dbef04 554
a5d10512
RW
555 if (params->family != AF_UNSPEC && params->family != tnbr->af)
556 break;
e8dbef04 557
a5d10512 558 trans_addr = &(ldp_af_conf_get(ldpd_conf, tnbr->af))->trans_addr;
e8dbef04 559
a5d10512
RW
560 json_target = json_object_new_object();
561 json_object_string_add(json_target, "sourceAddress",
562 log_addr(tnbr->af, trans_addr));
a5d10512
RW
563 json_object_object_add(json_targets, log_addr(tnbr->af,
564 &tnbr->addr), json_target);
565 json_container = json_target;
eac6e3f0
RW
566 break;
567 case IMSG_CTL_SHOW_DISC_ADJ:
568 adj = imsg->data;
569
a5d10512 570 if (params->family != AF_UNSPEC && params->family != adj->af)
eac6e3f0
RW
571 break;
572
573 switch(adj->type) {
574 case HELLO_LINK:
bc0eb287 575 show_discovery_detail_adj_json(json_container, adj);
eac6e3f0
RW
576 break;
577 case HELLO_TARGETED:
bc0eb287 578 show_discovery_detail_adj_json(json_container, adj);
eac6e3f0
RW
579 break;
580 }
581 break;
582 case IMSG_CTL_END:
a5d10512 583 return (1);
eac6e3f0
RW
584 default:
585 break;
586 }
587
588 return (0);
589}
590
bc0eb287
RW
591static int
592show_nbr_msg(struct vty *vty, struct imsg *imsg, struct show_params *params)
593{
594 struct ctl_nbr *nbr;
595 const char *addr;
596
597 switch (imsg->hdr.type) {
598 case IMSG_CTL_SHOW_NBR:
599 nbr = imsg->data;
600
601 addr = log_addr(nbr->af, &nbr->raddr);
602
903a7226
MS
603 vty_out(vty, "%-4s %-15pI4 %-11s %-15s",
604 af_name(nbr->af), &nbr->id,
605 nbr_state_name(nbr->nbr_state), addr);
bc0eb287 606 if (strlen(addr) > 15)
61b7d449 607 vty_out(vty, "\n%48s", " ");
5c7571d4 608 vty_out (vty, " %8s\n", log_time(nbr->uptime));
bc0eb287
RW
609 break;
610 case IMSG_CTL_END:
611 return (1);
612 default:
613 break;
614 }
615
616 return (0);
617}
618
eac6e3f0 619static void
bc0eb287 620show_nbr_detail_adj(struct vty *vty, char *buffer, struct ctl_adj *adj)
eac6e3f0
RW
621{
622 size_t buflen = strlen(buffer);
623
624 switch (adj->type) {
625 case HELLO_LINK:
a5d10512 626 snprintf(buffer + buflen, LDPBUFSIZ - buflen,
625e016d 627 " Interface: %s\n", adj->ifname);
eac6e3f0
RW
628 break;
629 case HELLO_TARGETED:
a5d10512 630 snprintf(buffer + buflen, LDPBUFSIZ - buflen,
625e016d
DL
631 " Targeted Hello: %s\n", log_addr(adj->af,
632 &adj->src_addr));
eac6e3f0
RW
633 break;
634 }
635}
636
637static int
0f7b5df9
RW
638show_nbr_detail_msg(struct vty *vty, struct imsg *imsg,
639 struct show_params *params)
eac6e3f0 640{
eac6e3f0 641 struct ctl_nbr *nbr;
0f7b5df9 642 struct ldp_stats *stats;
a5d10512 643 struct ctl_adj *adj;
eac6e3f0
RW
644 static char v4adjs_buffer[LDPBUFSIZ];
645 static char v6adjs_buffer[LDPBUFSIZ];
646
647 switch (imsg->hdr.type) {
648 case IMSG_CTL_SHOW_NBR:
649 nbr = imsg->data;
650
a5d10512
RW
651 v4adjs_buffer[0] = '\0';
652 v6adjs_buffer[0] = '\0';
903a7226
MS
653 vty_out (vty, "Peer LDP Identifier: %pI4:0\n",
654 &nbr->id);
5c7571d4 655 vty_out (vty, " TCP connection: %s:%u - %s:%u\n",
a5d10512 656 log_addr(nbr->af, &nbr->laddr), ntohs(nbr->lport),
96ade3ed 657 log_addr(nbr->af, &nbr->raddr),ntohs(nbr->rport));
5c7571d4 658 vty_out (vty, " Authentication: %s\n",
96ade3ed 659 (nbr->auth_method == AUTH_MD5SIG) ? "TCP MD5 Signature" : "none");
3efd0893 660 vty_out(vty, " Session Holdtime: %u secs; KeepAlive interval: %u secs\n", nbr->holdtime,
96ade3ed 661 nbr->holdtime / KEEPALIVE_PER_PERIOD);
5c7571d4 662 vty_out(vty, " State: %s; Downstream-Unsolicited\n",
96ade3ed 663 nbr_state_name(nbr->nbr_state));
5c7571d4 664 vty_out (vty, " Up time: %s\n",log_time(nbr->uptime));
0f7b5df9
RW
665
666 stats = &nbr->stats;
5c7571d4
DL
667 vty_out (vty, " Messages sent/rcvd:\n");
668 vty_out (vty, " - Keepalive Messages: %u/%u\n",
96ade3ed 669 stats->kalive_sent, stats->kalive_rcvd);
5c7571d4 670 vty_out (vty, " - Address Messages: %u/%u\n",
96ade3ed 671 stats->addr_sent, stats->addr_rcvd);
5c7571d4 672 vty_out (vty, " - Address Withdraw Messages: %u/%u\n",
96ade3ed 673 stats->addrwdraw_sent, stats->addrwdraw_rcvd);
5c7571d4 674 vty_out (vty, " - Notification Messages: %u/%u\n",
96ade3ed 675 stats->notif_sent, stats->notif_rcvd);
5c7571d4 676 vty_out (vty, " - Capability Messages: %u/%u\n",
96ade3ed 677 stats->capability_sent, stats->capability_rcvd);
5c7571d4 678 vty_out (vty, " - Label Mapping Messages: %u/%u\n",
96ade3ed 679 stats->labelmap_sent, stats->labelmap_rcvd);
5c7571d4 680 vty_out (vty, " - Label Request Messages: %u/%u\n",
96ade3ed 681 stats->labelreq_sent, stats->labelreq_rcvd);
5c7571d4 682 vty_out (vty, " - Label Withdraw Messages: %u/%u\n",
96ade3ed 683 stats->labelwdraw_sent, stats->labelwdraw_rcvd);
5c7571d4 684 vty_out (vty, " - Label Release Messages: %u/%u\n",
96ade3ed 685 stats->labelrel_sent, stats->labelrel_rcvd);
5c7571d4 686 vty_out (vty, " - Label Abort Request Messages: %u/%u\n",
96ade3ed 687 stats->labelabreq_sent, stats->labelabreq_rcvd);
0f7b5df9
RW
688
689 show_nbr_capabilities(vty, nbr);
eac6e3f0
RW
690 break;
691 case IMSG_CTL_SHOW_NBR_DISC:
692 adj = imsg->data;
693
694 switch (adj->af) {
695 case AF_INET:
bc0eb287 696 show_nbr_detail_adj(vty, v4adjs_buffer, adj);
eac6e3f0
RW
697 break;
698 case AF_INET6:
bc0eb287 699 show_nbr_detail_adj(vty, v6adjs_buffer, adj);
eac6e3f0
RW
700 break;
701 default:
bc0eb287 702 fatalx("show_nbr_detail_msg: unknown af");
a5d10512
RW
703 }
704 break;
705 case IMSG_CTL_SHOW_NBR_END:
5c7571d4 706 vty_out (vty, " LDP Discovery Sources:\n");
a5d10512 707 if (v4adjs_buffer[0] != '\0') {
5c7571d4 708 vty_out (vty, " IPv4:\n");
a5d10512
RW
709 vty_out(vty, "%s", v4adjs_buffer);
710 }
711 if (v6adjs_buffer[0] != '\0') {
5c7571d4 712 vty_out (vty, " IPv6:\n");
a5d10512
RW
713 vty_out(vty, "%s", v6adjs_buffer);
714 }
6d3c2ed4 715 vty_out (vty, "\n");
a5d10512
RW
716 break;
717 case IMSG_CTL_END:
718 return (1);
719 default:
720 break;
721 }
722
723 return (0);
724}
725
bc0eb287
RW
726static int
727show_nbr_msg_json(struct imsg *imsg, struct show_params *params,
728 json_object *json)
729{
730 struct ctl_nbr *nbr;
731 json_object *json_array;
732 json_object *json_nbr;
733
734 switch (imsg->hdr.type) {
735 case IMSG_CTL_SHOW_NBR:
736 nbr = imsg->data;
737
738 json_object_object_get_ex(json, "neighbors", &json_array);
739 if (!json_array) {
740 json_array = json_object_new_array();
741 json_object_object_add(json, "neighbors", json_array);
742 }
743
744 json_nbr = json_object_new_object();
745 json_object_string_add(json_nbr, "addressFamily",
746 af_name(nbr->af));
19fee2b7
DA
747 json_object_string_addf(json_nbr, "neighborId", "%pI4",
748 &nbr->id);
bc0eb287
RW
749 json_object_string_add(json_nbr, "state",
750 nbr_state_name(nbr->nbr_state));
751 json_object_string_add(json_nbr, "transportAddress",
752 log_addr(nbr->af, &nbr->raddr));
753 json_object_string_add(json_nbr, "upTime",
754 log_time(nbr->uptime));
755
756 json_object_array_add(json_array, json_nbr);
757 break;
758 case IMSG_CTL_END:
759 return (1);
760 default:
761 break;
762 }
763
764 return (0);
765}
766
a5d10512 767static void
bc0eb287 768show_nbr_detail_adj_json(struct ctl_adj *adj, json_object *adj_list)
a5d10512
RW
769{
770 char adj_string[128];
771
772 switch (adj->type) {
773 case HELLO_LINK:
774 strlcpy(adj_string, "interface: ", sizeof(adj_string));
775 strlcat(adj_string, adj->ifname, sizeof(adj_string));
776 break;
777 case HELLO_TARGETED:
778 strlcpy(adj_string, "targetedHello: ", sizeof(adj_string));
779 strlcat(adj_string, log_addr(adj->af, &adj->src_addr),
780 sizeof(adj_string));
781 break;
782 }
783
784 json_object_array_add(adj_list, json_object_new_string(adj_string));
785}
786
787static int
bc0eb287 788show_nbr_detail_msg_json(struct imsg *imsg, struct show_params *params,
a5d10512
RW
789 json_object *json)
790{
791 struct ctl_nbr *nbr;
0f7b5df9 792 struct ldp_stats *stats;
a5d10512 793 struct ctl_adj *adj;
903a7226 794 char buf[PREFIX_STRLEN];
a5d10512 795 json_object *json_nbr;
0f7b5df9
RW
796 json_object *json_array;
797 json_object *json_counter;
a5d10512
RW
798 static json_object *json_nbr_sources;
799 static json_object *json_v4adjs;
800 static json_object *json_v6adjs;
801
802 switch (imsg->hdr.type) {
803 case IMSG_CTL_SHOW_NBR:
804 nbr = imsg->data;
805
806 json_nbr = json_object_new_object();
903a7226
MS
807 json_object_object_add(json,
808 inet_ntop(AF_INET, &nbr->id, buf,
809 sizeof(buf)), json_nbr);
19fee2b7 810 json_object_string_addf(json_nbr, "peerId", "%pI4", &nbr->id);
a5d10512
RW
811 json_object_string_add(json_nbr, "tcpLocalAddress",
812 log_addr(nbr->af, &nbr->laddr));
813 json_object_int_add(json_nbr, "tcpLocalPort",
814 ntohs(nbr->lport));
815 json_object_string_add(json_nbr, "tcpRemoteAddress",
816 log_addr(nbr->af, &nbr->raddr));
817 json_object_int_add(json_nbr, "tcpRemotePort",
818 ntohs(nbr->rport));
0f7b5df9
RW
819 json_object_string_add(json_nbr, "authentication",
820 (nbr->auth_method == AUTH_MD5SIG) ? "TCP MD5 Signature" :
821 "none");
822 json_object_int_add(json_nbr, "sessionHoldtime", nbr->holdtime);
823 json_object_int_add(json_nbr, "keepAliveInterval",
824 nbr->holdtime / KEEPALIVE_PER_PERIOD);
a5d10512
RW
825 json_object_string_add(json_nbr, "state",
826 nbr_state_name(nbr->nbr_state));
827 json_object_string_add(json_nbr, "upTime",
828 log_time(nbr->uptime));
a5d10512 829
0f7b5df9
RW
830 /* message_counters */
831 stats = &nbr->stats;
832 json_array = json_object_new_array();
833 json_object_object_add(json_nbr, "sentMessages", json_array);
834 json_counter = json_object_new_object();
835 json_object_int_add(json_counter, "keepalive",
836 stats->kalive_sent);
837 json_object_array_add(json_array, json_counter);
838 json_counter = json_object_new_object();
839 json_object_int_add(json_counter, "address",
840 stats->addr_sent);
841 json_object_array_add(json_array, json_counter);
842 json_counter = json_object_new_object();
843 json_object_int_add(json_counter, "addressWithdraw",
844 stats->addrwdraw_sent);
845 json_object_array_add(json_array, json_counter);
846 json_counter = json_object_new_object();
847 json_object_int_add(json_counter, "notification",
848 stats->notif_sent);
849 json_object_array_add(json_array, json_counter);
850 json_counter = json_object_new_object();
851 json_object_int_add(json_counter, "capability",
852 stats->capability_sent);
853 json_object_array_add(json_array, json_counter);
854 json_counter = json_object_new_object();
855 json_object_int_add(json_counter, "labelMapping",
856 stats->labelmap_sent);
857 json_object_array_add(json_array, json_counter);
858 json_counter = json_object_new_object();
859 json_object_int_add(json_counter, "labelRequest",
860 stats->labelreq_sent);
861 json_object_array_add(json_array, json_counter);
862 json_counter = json_object_new_object();
863 json_object_int_add(json_counter, "labelWithdraw",
864 stats->labelwdraw_sent);
865 json_object_array_add(json_array, json_counter);
866 json_counter = json_object_new_object();
867 json_object_int_add(json_counter, "labelRelease",
868 stats->labelrel_sent);
869 json_object_array_add(json_array, json_counter);
870 json_counter = json_object_new_object();
871 json_object_int_add(json_counter, "labelAbortRequest",
872 stats->labelabreq_sent);
873 json_object_array_add(json_array, json_counter);
874
875 json_array = json_object_new_array();
876 json_object_object_add(json_nbr, "receivedMessages", json_array);
877 json_counter = json_object_new_object();
878 json_object_int_add(json_counter, "keepalive",
879 stats->kalive_rcvd);
880 json_object_array_add(json_array, json_counter);
881 json_counter = json_object_new_object();
882 json_object_int_add(json_counter, "address",
883 stats->addr_rcvd);
884 json_object_array_add(json_array, json_counter);
885 json_counter = json_object_new_object();
886 json_object_int_add(json_counter, "addressWithdraw",
887 stats->addrwdraw_rcvd);
888 json_object_array_add(json_array, json_counter);
889 json_counter = json_object_new_object();
890 json_object_int_add(json_counter, "notification",
891 stats->notif_rcvd);
892 json_object_array_add(json_array, json_counter);
893 json_counter = json_object_new_object();
894 json_object_int_add(json_counter, "capability",
895 stats->capability_rcvd);
896 json_object_array_add(json_array, json_counter);
897 json_counter = json_object_new_object();
898 json_object_int_add(json_counter, "labelMapping",
899 stats->labelmap_rcvd);
900 json_object_array_add(json_array, json_counter);
901 json_counter = json_object_new_object();
902 json_object_int_add(json_counter, "labelRequest",
903 stats->labelreq_rcvd);
904 json_object_array_add(json_array, json_counter);
905 json_counter = json_object_new_object();
906 json_object_int_add(json_counter, "labelWithdraw",
907 stats->labelwdraw_rcvd);
908 json_object_array_add(json_array, json_counter);
909 json_counter = json_object_new_object();
910 json_object_int_add(json_counter, "labelRelease",
911 stats->labelrel_rcvd);
912 json_object_array_add(json_array, json_counter);
913 json_counter = json_object_new_object();
914 json_object_int_add(json_counter, "labelAbortRequest",
915 stats->labelabreq_rcvd);
916 json_object_array_add(json_array, json_counter);
917
918 /* capabilities */
919 show_nbr_capabilities_json(nbr, json_nbr);
920
921 /* discovery sources */
a5d10512
RW
922 json_nbr_sources = json_object_new_object();
923 json_object_object_add(json_nbr, "discoverySources",
924 json_nbr_sources);
925 json_v4adjs = NULL;
926 json_v6adjs = NULL;
927 break;
928 case IMSG_CTL_SHOW_NBR_DISC:
929 adj = imsg->data;
930
931 switch (adj->af) {
932 case AF_INET:
933 if (!json_v4adjs) {
934 json_v4adjs = json_object_new_array();
935 json_object_object_add(json_nbr_sources, "ipv4",
936 json_v4adjs);
937 }
bc0eb287 938 show_nbr_detail_adj_json(adj, json_v4adjs);
a5d10512
RW
939 break;
940 case AF_INET6:
941 if (!json_v6adjs) {
942 json_v6adjs = json_object_new_array();
943 json_object_object_add(json_nbr_sources, "ipv6",
944 json_v6adjs);
945 }
bc0eb287 946 show_nbr_detail_adj_json(adj, json_v6adjs);
a5d10512
RW
947 break;
948 default:
bc0eb287 949 fatalx("show_nbr_detail_msg_json: unknown af");
a5d10512 950 }
eac6e3f0
RW
951 break;
952 case IMSG_CTL_SHOW_NBR_END:
eac6e3f0
RW
953 break;
954 case IMSG_CTL_END:
955 return (1);
956 default:
957 break;
958 }
959
960 return (0);
961}
962
0f7b5df9
RW
963void
964show_nbr_capabilities(struct vty *vty, struct ctl_nbr *nbr)
965{
625e016d
DL
966 vty_out (vty, " Capabilities Sent:\n"
967 " - Dynamic Announcement (0x0506)\n"
968 " - Typed Wildcard (0x050B)\n"
969 " - Unrecognized Notification (0x0603)\n");
5c7571d4 970 vty_out (vty, " Capabilities Received:\n");
2073f929 971 if (CHECK_FLAG(nbr->flags, F_NBR_CAP_DYNAMIC))
5c7571d4 972 vty_out (vty," - Dynamic Announcement (0x0506)\n");
2073f929 973 if (CHECK_FLAG(nbr->flags, F_NBR_CAP_TWCARD))
5c7571d4 974 vty_out (vty, " - Typed Wildcard (0x050B)\n");
2073f929 975 if (CHECK_FLAG(nbr->flags, F_NBR_CAP_UNOTIF))
5c7571d4 976 vty_out (vty," - Unrecognized Notification (0x0603)\n");
0f7b5df9
RW
977}
978
99cfc17f
RW
979static int
980show_nbr_capabilities_msg(struct vty *vty, struct imsg *imsg, struct show_params *params)
981{
982 struct ctl_nbr *nbr;
983
984 switch (imsg->hdr.type) {
985 case IMSG_CTL_SHOW_NBR:
986 nbr = imsg->data;
987
988 if (nbr->nbr_state != NBR_STA_OPER)
989 break;
990
903a7226
MS
991 vty_out (vty, "Peer LDP Identifier: %pI4:0\n",
992 &nbr->id);
0f7b5df9 993 show_nbr_capabilities(vty, nbr);
6d3c2ed4 994 vty_out (vty, "\n");
99cfc17f
RW
995 break;
996 case IMSG_CTL_END:
6d3c2ed4 997 vty_out (vty, "\n");
99cfc17f
RW
998 return (1);
999 default:
1000 break;
1001 }
1002
1003 return (0);
1004}
1005
0f7b5df9
RW
1006static void
1007show_nbr_capabilities_json(struct ctl_nbr *nbr, json_object *json_nbr)
99cfc17f 1008{
99cfc17f
RW
1009 json_object *json_array;
1010 json_object *json_cap;
1011
0f7b5df9
RW
1012 /* sent capabilities */
1013 json_array = json_object_new_array();
1014 json_object_object_add(json_nbr, "sentCapabilities", json_array);
1015
1016 /* Dynamic Announcement (0x0506) */
1017 json_cap = json_object_new_object();
1018 json_object_string_add(json_cap, "description", "Dynamic Announcement");
1019 json_object_string_add(json_cap, "tlvType", "0x0506");
1020 json_object_array_add(json_array, json_cap);
1021
1022 /* Typed Wildcard (0x050B) */
1023 json_cap = json_object_new_object();
1024 json_object_string_add(json_cap, "description", "Typed Wildcard");
1025 json_object_string_add(json_cap, "tlvType", "0x050B");
1026 json_object_array_add(json_array, json_cap);
1027
1028 /* Unrecognized Notification (0x0603) */
1029 json_cap = json_object_new_object();
1030 json_object_string_add(json_cap, "description",
1031 "Unrecognized Notification");
1032 json_object_string_add(json_cap, "tlvType", "0x0603");
1033 json_object_array_add(json_array, json_cap);
1034
1035 /* received capabilities */
1036 json_array = json_object_new_array();
1037 json_object_object_add(json_nbr, "receivedCapabilities", json_array);
1038
1039 /* Dynamic Announcement (0x0506) */
2073f929 1040 if (CHECK_FLAG(nbr->flags, F_NBR_CAP_DYNAMIC)) {
99cfc17f
RW
1041 json_cap = json_object_new_object();
1042 json_object_string_add(json_cap, "description",
1043 "Dynamic Announcement");
0f7b5df9 1044 json_object_string_add(json_cap, "tlvType", "0x0506");
99cfc17f 1045 json_object_array_add(json_array, json_cap);
0f7b5df9 1046 }
99cfc17f 1047
0f7b5df9 1048 /* Typed Wildcard (0x050B) */
2073f929 1049 if (CHECK_FLAG(nbr->flags, F_NBR_CAP_TWCARD)) {
99cfc17f
RW
1050 json_cap = json_object_new_object();
1051 json_object_string_add(json_cap, "description",
1052 "Typed Wildcard");
0f7b5df9 1053 json_object_string_add(json_cap, "tlvType", "0x050B");
99cfc17f 1054 json_object_array_add(json_array, json_cap);
0f7b5df9 1055 }
99cfc17f 1056
0f7b5df9 1057 /* Unrecognized Notification (0x0603) */
2073f929 1058 if (CHECK_FLAG(nbr->flags, F_NBR_CAP_UNOTIF)) {
99cfc17f
RW
1059 json_cap = json_object_new_object();
1060 json_object_string_add(json_cap, "description",
1061 "Unrecognized Notification");
0f7b5df9 1062 json_object_string_add(json_cap, "tlvType", "0x0603");
99cfc17f 1063 json_object_array_add(json_array, json_cap);
0f7b5df9
RW
1064 }
1065}
99cfc17f 1066
0f7b5df9
RW
1067static int
1068show_nbr_capabilities_msg_json(struct imsg *imsg, struct show_params *params,
1069 json_object *json)
1070{
1071 struct ctl_nbr *nbr;
903a7226 1072 char buf[PREFIX_STRLEN];
0f7b5df9 1073 json_object *json_nbr;
99cfc17f 1074
0f7b5df9
RW
1075 switch (imsg->hdr.type) {
1076 case IMSG_CTL_SHOW_NBR:
1077 nbr = imsg->data;
99cfc17f 1078
0f7b5df9
RW
1079 if (nbr->nbr_state != NBR_STA_OPER)
1080 break;
1081
1082 json_nbr = json_object_new_object();
903a7226
MS
1083 json_object_object_add(json, inet_ntop(AF_INET, &nbr->id, buf,
1084 sizeof(buf)), json_nbr);
0f7b5df9 1085 show_nbr_capabilities_json(nbr, json_nbr);
99cfc17f
RW
1086 break;
1087 case IMSG_CTL_END:
1088 return (1);
1089 default:
1090 break;
1091 }
1092
1093 return (0);
1094}
1095
eac6e3f0 1096static int
a5d10512 1097show_lib_msg(struct vty *vty, struct imsg *imsg, struct show_params *params)
eac6e3f0
RW
1098{
1099 struct ctl_rt *rt;
1100 char dstnet[BUFSIZ];
1101
bc0eb287 1102 switch (imsg->hdr.type) {
0f7b5df9 1103 case IMSG_CTL_SHOW_LIB_BEGIN:
f0722791
RW
1104 rt = imsg->data;
1105
1106 if (params->lib.remote_label != NO_LABEL &&
1107 params->lib.remote_label != rt->remote_label)
1108 return (0);
1109 /* FALLTHROUGH */
0f7b5df9 1110 case IMSG_CTL_SHOW_LIB_RCVD:
bc0eb287
RW
1111 rt = imsg->data;
1112
0f7b5df9
RW
1113 if (imsg->hdr.type == IMSG_CTL_SHOW_LIB_BEGIN &&
1114 !rt->no_downstream)
1115 break;
1116
bc0eb287
RW
1117 snprintf(dstnet, sizeof(dstnet), "%s/%d",
1118 log_addr(rt->af, &rt->prefix), rt->prefixlen);
1119
1120 vty_out(vty, "%-4s %-20s", af_name(rt->af), dstnet);
1121 if (strlen(dstnet) > 20)
61b7d449 1122 vty_out(vty, "\n%25s", " ");
903a7226
MS
1123 vty_out (vty, " %-15pI4 %-11s %-13s %6s\n",
1124 &rt->nexthop, log_label(rt->local_label),
1125 log_label(rt->remote_label),
1126 rt->in_use ? "yes" : "no");
bc0eb287
RW
1127 break;
1128 case IMSG_CTL_END:
6d3c2ed4 1129 vty_out (vty, "\n");
bc0eb287
RW
1130 return (1);
1131 default:
1132 break;
1133 }
1134
1135 return (0);
1136}
1137
1138static int
1139show_lib_detail_msg(struct vty *vty, struct imsg *imsg, struct show_params *params)
1140{
f790d62a 1141 struct ctl_rt *rt = NULL;
f0722791 1142 static char dstnet[BUFSIZ];
0f7b5df9
RW
1143 static int upstream, downstream;
1144 size_t buflen;
1145 static char sent_buffer[LDPBUFSIZ];
1146 static char rcvd_buffer[LDPBUFSIZ];
bc0eb287 1147
eac6e3f0 1148 switch (imsg->hdr.type) {
0f7b5df9 1149 case IMSG_CTL_SHOW_LIB_BEGIN:
eac6e3f0 1150 rt = imsg->data;
0f7b5df9 1151
0f7b5df9
RW
1152 upstream = 0;
1153 downstream = 0;
1154 sent_buffer[0] = '\0';
1155 rcvd_buffer[0] = '\0';
eac6e3f0 1156 snprintf(dstnet, sizeof(dstnet), "%s/%d",
a5d10512 1157 log_addr(rt->af, &rt->prefix), rt->prefixlen);
0f7b5df9
RW
1158 break;
1159 case IMSG_CTL_SHOW_LIB_SENT:
f0722791
RW
1160 rt = imsg->data;
1161
0f7b5df9
RW
1162 upstream = 1;
1163 buflen = strlen(sent_buffer);
903a7226
MS
1164 snprintfrr(sent_buffer + buflen, LDPBUFSIZ - buflen,
1165 "%12s%pI4:0\n", "", &rt->nexthop);
0f7b5df9
RW
1166 break;
1167 case IMSG_CTL_SHOW_LIB_RCVD:
f0722791 1168 rt = imsg->data;
0f7b5df9
RW
1169 downstream = 1;
1170 buflen = strlen(rcvd_buffer);
903a7226
MS
1171 snprintfrr(rcvd_buffer + buflen, LDPBUFSIZ - buflen,
1172 "%12s%pI4:0, label %s%s\n", "", &rt->nexthop,
1173 log_label(rt->remote_label),
1174 rt->in_use ? " (in use)" : "");
0f7b5df9
RW
1175 break;
1176 case IMSG_CTL_SHOW_LIB_END:
f0722791
RW
1177 rt = imsg->data;
1178
1179 if (params->lib.remote_label != NO_LABEL &&
1180 !downstream)
1181 break;
1182 vty_out(vty, "%s\n", dstnet);
1183 vty_out(vty, "%-8sLocal binding: label: %s\n", "",
1184 log_label(rt->local_label));
0f7b5df9 1185 if (upstream) {
5c7571d4 1186 vty_out (vty, "%-8sAdvertised to:\n", "");
0f7b5df9 1187 vty_out(vty, "%s", sent_buffer);
a5d10512 1188 }
0f7b5df9 1189 if (downstream) {
5c7571d4 1190 vty_out (vty, "%-8sRemote bindings:\n", "");
0f7b5df9
RW
1191 vty_out(vty, "%s", rcvd_buffer);
1192 } else
5c7571d4 1193 vty_out (vty, "%-8sNo remote bindings\n","");
eac6e3f0
RW
1194 break;
1195 case IMSG_CTL_END:
6d3c2ed4 1196 vty_out (vty, "\n");
eac6e3f0
RW
1197 return (1);
1198 default:
1199 break;
1200 }
1201
1202 return (0);
1203}
1204
1205static int
a5d10512
RW
1206show_lib_msg_json(struct imsg *imsg, struct show_params *params,
1207 json_object *json)
bc0eb287
RW
1208{
1209 struct ctl_rt *rt;
1210 json_object *json_array;
1211 json_object *json_lib_entry;
1212 char dstnet[BUFSIZ];
1213
1214 switch (imsg->hdr.type) {
0f7b5df9
RW
1215 case IMSG_CTL_SHOW_LIB_BEGIN:
1216 case IMSG_CTL_SHOW_LIB_RCVD:
bc0eb287
RW
1217 rt = imsg->data;
1218
0f7b5df9
RW
1219 if (imsg->hdr.type == IMSG_CTL_SHOW_LIB_BEGIN &&
1220 !rt->no_downstream)
bc0eb287
RW
1221 break;
1222
1223 json_object_object_get_ex(json, "bindings", &json_array);
1224 if (!json_array) {
1225 json_array = json_object_new_array();
1226 json_object_object_add(json, "bindings", json_array);
1227 }
1228
1229 json_lib_entry = json_object_new_object();
1230 json_object_string_add(json_lib_entry, "addressFamily",
1231 af_name(rt->af));
1232 snprintf(dstnet, sizeof(dstnet), "%s/%d",
1233 log_addr(rt->af, &rt->prefix), rt->prefixlen);
1234 json_object_string_add(json_lib_entry, "prefix", dstnet);
19fee2b7
DA
1235 json_object_string_addf(json_lib_entry, "neighborId", "%pI4",
1236 &rt->nexthop);
bc0eb287 1237 json_object_string_add(json_lib_entry, "localLabel",
903a7226 1238 log_label(rt->local_label));
bc0eb287 1239 json_object_string_add(json_lib_entry, "remoteLabel",
903a7226 1240 log_label(rt->remote_label));
bc0eb287
RW
1241 json_object_int_add(json_lib_entry, "inUse", rt->in_use);
1242
1243 json_object_array_add(json_array, json_lib_entry);
1244 break;
1245 case IMSG_CTL_END:
1246 return (1);
1247 default:
1248 break;
1249 }
1250
1251 return (0);
1252}
1253
1254static int
1255show_lib_detail_msg_json(struct imsg *imsg, struct show_params *params,
1256 json_object *json)
a5d10512 1257{
f790d62a 1258 struct ctl_rt *rt = NULL;
a5d10512 1259 char dstnet[BUFSIZ];
0f7b5df9
RW
1260 static json_object *json_lib_entry;
1261 static json_object *json_adv_labels;
1262 json_object *json_adv_label;
a5d10512
RW
1263 static json_object *json_remote_labels;
1264 json_object *json_remote_label;
1265
1266 switch (imsg->hdr.type) {
0f7b5df9 1267 case IMSG_CTL_SHOW_LIB_BEGIN:
a5d10512 1268 rt = imsg->data;
a5d10512
RW
1269
1270 snprintf(dstnet, sizeof(dstnet), "%s/%d",
1271 log_addr(rt->af, &rt->prefix), rt->prefixlen);
1272
0f7b5df9
RW
1273 json_lib_entry = json_object_new_object();
1274 json_object_string_add(json_lib_entry, "localLabel",
1275 log_label(rt->local_label));
a5d10512 1276
0f7b5df9
RW
1277 json_adv_labels = json_object_new_array();
1278 json_object_object_add(json_lib_entry, "advertisedTo",
1279 json_adv_labels);
a5d10512 1280
0f7b5df9
RW
1281 json_remote_labels = json_object_new_array();
1282 json_object_object_add(json_lib_entry, "remoteLabels",
1283 json_remote_labels);
1284
1285 json_object_object_add(json, dstnet, json_lib_entry);
1286 break;
1287 case IMSG_CTL_SHOW_LIB_SENT:
f0722791
RW
1288 rt = imsg->data;
1289
0f7b5df9 1290 json_adv_label = json_object_new_object();
19fee2b7
DA
1291 json_object_string_addf(json_adv_label, "neighborId", "%pI4",
1292 &rt->nexthop);
0f7b5df9
RW
1293 json_object_array_add(json_adv_labels, json_adv_label);
1294 break;
1295 case IMSG_CTL_SHOW_LIB_RCVD:
f0722791
RW
1296 rt = imsg->data;
1297
0f7b5df9 1298 json_remote_label = json_object_new_object();
19fee2b7
DA
1299 json_object_string_addf(json_remote_label, "neighborId", "%pI4",
1300 &rt->nexthop);
0f7b5df9 1301 json_object_string_add(json_remote_label, "label",
903a7226 1302 log_label(rt->remote_label));
0f7b5df9
RW
1303 json_object_int_add(json_remote_label, "inUse", rt->in_use);
1304 json_object_array_add(json_remote_labels, json_remote_label);
a5d10512
RW
1305 break;
1306 case IMSG_CTL_END:
1307 return (1);
1308 default:
1309 break;
1310 }
1311
1312 return (0);
1313}
1314
1315static int
1316show_l2vpn_binding_msg(struct vty *vty, struct imsg *imsg,
1317 struct show_params *params)
eac6e3f0
RW
1318{
1319 struct ctl_pw *pw;
1320
1321 switch (imsg->hdr.type) {
1322 case IMSG_CTL_SHOW_L2VPN_BINDING:
1323 pw = imsg->data;
1324
903a7226
MS
1325 vty_out (vty, " Destination Address: %pI4, VC ID: %u\n",
1326 &pw->lsr_id, pw->pwid);
eac6e3f0
RW
1327
1328 /* local binding */
1329 if (pw->local_label != NO_LABEL) {
5c7571d4 1330 vty_out (vty, " Local Label: %u\n",
96ade3ed 1331 pw->local_label);
3efd0893 1332 vty_out (vty, "%-8sCbit: %u, VC Type: %s, GroupID: %u\n", "", pw->local_cword,
96ade3ed 1333 pw_type_name(pw->type),pw->local_gid);
5c7571d4 1334 vty_out (vty, "%-8sMTU: %u\n", "",pw->local_ifmtu);
6bbdd9e9 1335 vty_out (vty, "%-8sLast failure: %s\n", "",
1336 pw_error_code(pw->reason));
eac6e3f0 1337 } else
5c7571d4 1338 vty_out (vty," Local Label: unassigned\n");
eac6e3f0
RW
1339
1340 /* remote binding */
1341 if (pw->remote_label != NO_LABEL) {
5c7571d4 1342 vty_out (vty, " Remote Label: %u\n",
96ade3ed 1343 pw->remote_label);
3efd0893 1344 vty_out (vty, "%-8sCbit: %u, VC Type: %s, GroupID: %u\n", "", pw->remote_cword,
96ade3ed 1345 pw_type_name(pw->type),pw->remote_gid);
5c7571d4 1346 vty_out (vty, "%-8sMTU: %u\n", "",pw->remote_ifmtu);
eac6e3f0 1347 } else
5c7571d4 1348 vty_out (vty," Remote Label: unassigned\n");
eac6e3f0
RW
1349 break;
1350 case IMSG_CTL_END:
6d3c2ed4 1351 vty_out (vty, "\n");
eac6e3f0
RW
1352 return (1);
1353 default:
1354 break;
1355 }
1356
1357 return (0);
1358}
1359
1360static int
a5d10512
RW
1361show_l2vpn_binding_msg_json(struct imsg *imsg, struct show_params *params,
1362 json_object *json)
1363{
1364 struct ctl_pw *pw;
1365 json_object *json_pw;
1366 char key_name[64];
1367
1368 switch (imsg->hdr.type) {
1369 case IMSG_CTL_SHOW_L2VPN_BINDING:
1370 pw = imsg->data;
1371
1372 json_pw = json_object_new_object();
19fee2b7
DA
1373 json_object_string_addf(json_pw, "destination", "%pI4",
1374 &pw->lsr_id);
a5d10512
RW
1375 json_object_int_add(json_pw, "vcId", pw->pwid);
1376
1377 /* local binding */
1378 if (pw->local_label != NO_LABEL) {
1379 json_object_int_add(json_pw, "localLabel",
1380 pw->local_label);
1381 json_object_int_add(json_pw, "localControlWord",
1382 pw->local_cword);
1383 json_object_string_add(json_pw, "localVcType",
1384 pw_type_name(pw->type));
1385 json_object_int_add(json_pw, "localGroupID",
1386 pw->local_gid);
1387 json_object_int_add(json_pw, "localIfMtu",
1388 pw->local_ifmtu);
6bbdd9e9 1389 json_object_string_add(json_pw, "lastFailureReason",
1390 pw_error_code(pw->reason));
a5d10512
RW
1391 } else
1392 json_object_string_add(json_pw, "localLabel",
1393 "unassigned");
1394
1395 /* remote binding */
1396 if (pw->remote_label != NO_LABEL) {
1397 json_object_int_add(json_pw, "remoteLabel",
1398 pw->remote_label);
1399 json_object_int_add(json_pw, "remoteControlWord",
1400 pw->remote_cword);
1401 json_object_string_add(json_pw, "remoteVcType",
1402 pw_type_name(pw->type));
1403 json_object_int_add(json_pw, "remoteGroupID",
1404 pw->remote_gid);
1405 json_object_int_add(json_pw, "remoteIfMtu",
1406 pw->remote_ifmtu);
1407 } else
1408 json_object_string_add(json_pw, "remoteLabel",
1409 "unassigned");
1410
903a7226
MS
1411 snprintfrr(key_name, sizeof(key_name), "%pI4: %u",
1412 &pw->lsr_id, pw->pwid);
a5d10512
RW
1413 json_object_object_add(json, key_name, json_pw);
1414 break;
1415 case IMSG_CTL_END:
1416 return (1);
1417 default:
1418 break;
1419 }
1420
1421 return (0);
1422}
1423
1424static int
1425show_l2vpn_pw_msg(struct vty *vty, struct imsg *imsg, struct show_params *params)
eac6e3f0
RW
1426{
1427 struct ctl_pw *pw;
1428
1429 switch (imsg->hdr.type) {
1430 case IMSG_CTL_SHOW_L2VPN_PW:
1431 pw = imsg->data;
1432
903a7226
MS
1433 vty_out (vty, "%-9s %-15pI4 %-10u %-16s %-10s\n", pw->ifname,
1434 &pw->lsr_id, pw->pwid, pw->l2vpn_name,
1435 (pw->status == PW_FORWARDING ? "UP" : "DOWN"));
eac6e3f0
RW
1436 break;
1437 case IMSG_CTL_END:
6d3c2ed4 1438 vty_out (vty, "\n");
eac6e3f0
RW
1439 return (1);
1440 default:
1441 break;
1442 }
1443
1444 return (0);
1445}
1446
a5d10512
RW
1447static int
1448show_l2vpn_pw_msg_json(struct imsg *imsg, struct show_params *params,
1449 json_object *json)
1450{
1451 struct ctl_pw *pw;
1452 json_object *json_pw;
1453
1454 switch (imsg->hdr.type) {
1455 case IMSG_CTL_SHOW_L2VPN_PW:
1456 pw = imsg->data;
1457
1458 json_pw = json_object_new_object();
19fee2b7 1459 json_object_string_addf(json_pw, "peerId", "%pI4", &pw->lsr_id);
a5d10512 1460 json_object_int_add(json_pw, "vcId", pw->pwid);
77a2f8e5 1461 json_object_string_add(json_pw, "vpnName", pw->l2vpn_name);
fd563cc7 1462 if (pw->status == PW_FORWARDING)
a5d10512
RW
1463 json_object_string_add(json_pw, "status", "up");
1464 else
1465 json_object_string_add(json_pw, "status", "down");
1466 json_object_object_add(json, pw->ifname, json_pw);
1467 break;
1468 case IMSG_CTL_END:
1469 return (1);
1470 default:
1471 break;
1472 }
1473
1474 return (0);
1475}
1476
eac6e3f0
RW
1477static int
1478ldp_vty_connect(struct imsgbuf *ibuf)
1479{
1480 struct sockaddr_un s_un;
1481 int ctl_sock;
1482
1483 /* connect to ldpd control socket */
1484 if ((ctl_sock = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) {
1485 log_warn("%s: socket", __func__);
1486 return (-1);
1487 }
1488
1489 memset(&s_un, 0, sizeof(s_un));
1490 s_un.sun_family = AF_UNIX;
372b8bd3 1491 strlcpy(s_un.sun_path, ctl_sock_path, sizeof(s_un.sun_path));
eac6e3f0 1492 if (connect(ctl_sock, (struct sockaddr *)&s_un, sizeof(s_un)) == -1) {
372b8bd3 1493 log_warn("%s: connect: %s", __func__, ctl_sock_path);
eac6e3f0
RW
1494 close(ctl_sock);
1495 return (-1);
1496 }
1497
1498 imsg_init(ibuf, ctl_sock);
1499
1500 return (0);
1501}
1502
a5d10512 1503static int
f0722791 1504ldp_vty_dispatch_iface(struct vty *vty, struct imsg *imsg,
a5d10512
RW
1505 struct show_params *params, json_object *json)
1506{
bc0eb287
RW
1507 int ret;
1508
f0722791
RW
1509 if (params->json)
1510 ret = show_interface_msg_json(imsg, params, json);
1511 else
1512 ret = show_interface_msg(vty, imsg, params);
1513
1514 return (ret);
1515}
1516
e1894ff7
KS
1517static int
1518ldp_vty_dispatch_ldp_sync(struct vty *vty, struct imsg *imsg,
1519 struct show_params *params, json_object *json)
1520{
1521 int ret;
1522
1523 if (params->json)
1524 ret = show_ldp_sync_msg_json(imsg, params, json);
1525 else
1526 ret = show_ldp_sync_msg(vty, imsg, params);
1527
1528 return (ret);
1529}
1530
f0722791
RW
1531static int
1532ldp_vty_dispatch_disc(struct vty *vty, struct imsg *imsg,
1533 struct show_params *params, json_object *json)
1534{
1535 int ret;
1536
1537 if (params->detail) {
bc0eb287 1538 if (params->json)
f0722791
RW
1539 ret = show_discovery_detail_msg_json(imsg, params,
1540 json);
bc0eb287 1541 else
f0722791
RW
1542 ret = show_discovery_detail_msg(vty, imsg, params);
1543 } else {
1544 if (params->json)
1545 ret = show_discovery_msg_json(imsg, params, json);
1546 else
1547 ret = show_discovery_msg(vty, imsg, params);
1548 }
1549
1550 return (ret);
1551}
1552
1553static int
1554ldp_vty_dispatch_nbr(struct vty *vty, struct imsg *imsg,
1555 struct show_params *params, json_object *json)
1556{
1557 static bool filtered = false;
1558 struct ctl_nbr *nbr;
1559 int ret;
1560
1561 switch (imsg->hdr.type) {
1562 case IMSG_CTL_SHOW_NBR:
1563 filtered = false;
1564 nbr = imsg->data;
1565
1566 if (params->neighbor.lsr_id.s_addr != INADDR_ANY &&
1567 params->neighbor.lsr_id.s_addr != nbr->id.s_addr) {
1568 filtered = true;
1569 return (0);
bc0eb287
RW
1570 }
1571 break;
f0722791
RW
1572 case IMSG_CTL_SHOW_NBR_DISC:
1573 case IMSG_CTL_SHOW_NBR_END:
1574 if (filtered)
1575 return (0);
bc0eb287 1576 break;
f0722791 1577 default:
bc0eb287 1578 break;
f0722791
RW
1579 }
1580
1581 if (params->neighbor.capabilities) {
bc0eb287 1582 if (params->json)
f0722791
RW
1583 ret = show_nbr_capabilities_msg_json(imsg, params,
1584 json);
bc0eb287 1585 else
f0722791
RW
1586 ret = show_nbr_capabilities_msg(vty, imsg, params);
1587 } else if (params->detail) {
1588 if (params->json)
1589 ret = show_nbr_detail_msg_json(imsg, params, json);
1590 else
1591 ret = show_nbr_detail_msg(vty, imsg, params);
1592 } else {
1593 if (params->json)
1594 ret = show_nbr_msg_json(imsg, params, json);
1595 else
1596 ret = show_nbr_msg(vty, imsg, params);
1597 }
1598
1599 return (ret);
1600}
1601
1602static int
1603ldp_vty_dispatch_lib(struct vty *vty, struct imsg *imsg,
1604 struct show_params *params, json_object *json)
1605{
1606 static bool filtered = false;
7f677840 1607 struct ctl_rt *rt = NULL;
f0722791
RW
1608 struct prefix prefix;
1609 int ret;
1610
1611 switch (imsg->hdr.type) {
1612 case IMSG_CTL_SHOW_LIB_BEGIN:
1613 filtered = false;
bc0eb287 1614 break;
f0722791
RW
1615 case IMSG_CTL_SHOW_LIB_SENT:
1616 case IMSG_CTL_SHOW_LIB_RCVD:
1617 case IMSG_CTL_SHOW_LIB_END:
1618 if (filtered)
1619 return (0);
1620 break;
1621 default:
1622 break;
1623 }
1624
1625 switch (imsg->hdr.type) {
1626 case IMSG_CTL_SHOW_LIB_BEGIN:
1627 case IMSG_CTL_SHOW_LIB_SENT:
1628 case IMSG_CTL_SHOW_LIB_RCVD:
1629 case IMSG_CTL_SHOW_LIB_END:
1630 rt = imsg->data;
1631
1632 if (params->family != AF_UNSPEC && params->family != rt->af) {
1633 filtered = true;
1634 return (0);
1635 }
1636
1637 prefix.family = rt->af;
1638 prefix.prefixlen = rt->prefixlen;
1639 memcpy(&prefix.u.val, &rt->prefix, sizeof(prefix.u.val));
1640 if (params->lib.prefix.family != AF_UNSPEC) {
1641 if (!params->lib.longer_prefixes &&
1642 !prefix_same(&params->lib.prefix, &prefix)) {
1643 filtered = true;
1644 return (0);
1645 } else if (params->lib.longer_prefixes &&
1646 !prefix_match(&params->lib.prefix, &prefix)) {
1647 filtered = true;
1648 return (0);
1649 }
1650 }
1651
1652 if (params->lib.local_label != NO_LABEL &&
1653 params->lib.local_label != rt->local_label) {
1654 filtered = true;
1655 return (0);
1656 }
1657 break;
1658 default:
1659 break;
1660 }
1661
1662 switch (imsg->hdr.type) {
1663 case IMSG_CTL_SHOW_LIB_SENT:
1664 case IMSG_CTL_SHOW_LIB_RCVD:
1665 if (params->lib.neighbor.s_addr != INADDR_ANY &&
1666 params->lib.neighbor.s_addr != rt->nexthop.s_addr)
1667 return (0);
1668 break;
1669 default:
1670 break;
1671 }
1672
1673 switch (imsg->hdr.type) {
1674 case IMSG_CTL_SHOW_LIB_RCVD:
1675 if (params->lib.remote_label != NO_LABEL &&
1676 params->lib.remote_label != rt->remote_label)
1677 return (0);
1678 break;
1679 default:
1680 break;
1681 }
1682
1683 if (params->detail) {
bc0eb287 1684 if (params->json)
f0722791 1685 ret = show_lib_detail_msg_json(imsg, params, json);
bc0eb287 1686 else
f0722791
RW
1687 ret = show_lib_detail_msg(vty, imsg, params);
1688 } else {
1689 if (params->json)
1690 ret = show_lib_msg_json(imsg, params, json);
1691 else
1692 ret = show_lib_msg(vty, imsg, params);
1693 }
1694
1695 return (ret);
1696}
1697
1698static int
1699ldp_vty_dispatch_l2vpn_pw(struct vty *vty, struct imsg *imsg,
1700 struct show_params *params, json_object *json)
1701{
1702 struct ctl_pw *pw;
1703 int ret;
1704
1705 switch (imsg->hdr.type) {
1706 case IMSG_CTL_SHOW_L2VPN_PW:
1707 pw = imsg->data;
1708 if (params->l2vpn.peer.s_addr != INADDR_ANY &&
1709 params->l2vpn.peer.s_addr != pw->lsr_id.s_addr)
1710 return (0);
1711 if (params->l2vpn.ifname[0] != '\0' &&
1712 strcmp(params->l2vpn.ifname, pw->ifname))
1713 return (0);
1714 if (params->l2vpn.vcid && params->l2vpn.vcid != pw->pwid)
1715 return (0);
bc0eb287 1716 break;
a5d10512 1717 default:
f0722791 1718 break;
a5d10512 1719 }
bc0eb287 1720
f0722791
RW
1721 if (params->json)
1722 ret = show_l2vpn_pw_msg_json(imsg, params, json);
1723 else
1724 ret = show_l2vpn_pw_msg(vty, imsg, params);
1725
bc0eb287 1726 return (ret);
a5d10512
RW
1727}
1728
f0722791
RW
1729static int
1730ldp_vty_dispatch_l2vpn_binding(struct vty *vty, struct imsg *imsg,
1731 struct show_params *params, json_object *json)
1732{
1733 struct ctl_pw *pw;
1734 int ret;
1735
1736 switch (imsg->hdr.type) {
1737 case IMSG_CTL_SHOW_L2VPN_BINDING:
1738 pw = imsg->data;
1739 if (params->l2vpn.peer.s_addr != INADDR_ANY &&
1740 params->l2vpn.peer.s_addr != pw->lsr_id.s_addr)
1741 return (0);
1742 if (params->l2vpn.local_label != NO_LABEL &&
1743 params->l2vpn.local_label != pw->local_label)
1744 return (0);
1745 if (params->l2vpn.remote_label != NO_LABEL &&
1746 params->l2vpn.remote_label != pw->remote_label)
1747 return (0);
1748 break;
1749 default:
1750 break;
1751 }
1752
1753 if (params->json)
1754 ret = show_l2vpn_binding_msg_json(imsg, params, json);
1755 else
1756 ret = show_l2vpn_binding_msg(vty, imsg, params);
1757
1758 return (ret);
1759}
1760
1761static int
1762ldp_vty_dispatch_msg(struct vty *vty, struct imsg *imsg, enum show_command cmd,
1763 struct show_params *params, json_object *json)
1764{
1765 switch (cmd) {
1766 case SHOW_IFACE:
1767 return (ldp_vty_dispatch_iface(vty, imsg, params, json));
1768 case SHOW_DISC:
1769 return (ldp_vty_dispatch_disc(vty, imsg, params, json));
1770 case SHOW_NBR:
1771 return (ldp_vty_dispatch_nbr(vty, imsg, params, json));
1772 case SHOW_LIB:
1773 return (ldp_vty_dispatch_lib(vty, imsg, params, json));
1774 case SHOW_L2VPN_PW:
1775 return (ldp_vty_dispatch_l2vpn_pw(vty, imsg, params, json));
1776 case SHOW_L2VPN_BINDING:
1777 return (ldp_vty_dispatch_l2vpn_binding(vty, imsg, params,
1778 json));
e1894ff7
KS
1779 case SHOW_LDP_SYNC:
1780 return (ldp_vty_dispatch_ldp_sync(vty, imsg, params, json));
f0722791
RW
1781 default:
1782 return (0);
1783 }
1784}
1785
eac6e3f0
RW
1786static int
1787ldp_vty_dispatch(struct vty *vty, struct imsgbuf *ibuf, enum show_command cmd,
a5d10512 1788 struct show_params *params)
eac6e3f0
RW
1789{
1790 struct imsg imsg;
a5d10512
RW
1791 int n, done = 0, ret = CMD_SUCCESS;
1792 json_object *json = NULL;
eac6e3f0
RW
1793
1794 while (ibuf->w.queued)
1795 if (msgbuf_write(&ibuf->w) <= 0 && errno != EAGAIN) {
1796 log_warn("write error");
1797 close(ibuf->fd);
1798 return (CMD_WARNING);
1799 }
1800
a5d10512
RW
1801 if (params->json)
1802 json = json_object_new_object();
e8dbef04 1803
eac6e3f0
RW
1804 while (!done) {
1805 if ((n = imsg_read(ibuf)) == -1 && errno != EAGAIN) {
1806 log_warnx("imsg_read error");
a5d10512
RW
1807 ret = CMD_WARNING;
1808 goto done;
eac6e3f0
RW
1809 }
1810 if (n == 0) {
1811 log_warnx("pipe closed");
a5d10512
RW
1812 ret = CMD_WARNING;
1813 goto done;
eac6e3f0
RW
1814 }
1815
1816 while (!done) {
1817 if ((n = imsg_get(ibuf, &imsg)) == -1) {
1818 log_warnx("imsg_get error");
a5d10512
RW
1819 ret = CMD_WARNING;
1820 goto done;
eac6e3f0
RW
1821 }
1822 if (n == 0)
1823 break;
a5d10512
RW
1824 done = ldp_vty_dispatch_msg(vty, &imsg, cmd, params,
1825 json);
eac6e3f0
RW
1826 imsg_free(&imsg);
1827 }
1828 }
1829
a5d10512 1830 done:
eac6e3f0 1831 close(ibuf->fd);
a5d10512 1832 if (json) {
038c0a8f 1833 vty_json(vty, json);
a5d10512 1834 }
eac6e3f0 1835
a5d10512 1836 return (ret);
eac6e3f0
RW
1837}
1838
1839static int
1840ldp_vty_get_af(const char *str, int *af)
1841{
1842 if (str == NULL) {
1843 *af = AF_UNSPEC;
1844 return (0);
1845 } else if (strcmp(str, "ipv4") == 0) {
1846 *af = AF_INET;
1847 return (0);
1848 } else if (strcmp(str, "ipv6") == 0) {
1849 *af = AF_INET6;
1850 return (0);
1851 }
1852
1853 return (-1);
1854}
1855
1856int
f0722791
RW
1857ldp_vty_show_binding(struct vty *vty, const char *af_str, const char *prefix,
1858 int longer_prefixes, const char *neighbor, unsigned long local_label,
1859 unsigned long remote_label, const char *detail, const char *json)
eac6e3f0
RW
1860{
1861 struct imsgbuf ibuf;
a5d10512 1862 struct show_params params;
eac6e3f0
RW
1863 int af;
1864
1865 if (ldp_vty_connect(&ibuf) < 0)
1866 return (CMD_WARNING);
1867
eac6e3f0
RW
1868 if (ldp_vty_get_af(af_str, &af) < 0)
1869 return (CMD_ERR_NO_MATCH);
1870
a5d10512
RW
1871 memset(&params, 0, sizeof(params));
1872 params.family = af;
1224e5c4
RW
1873 params.detail = (detail) ? 1 : 0;
1874 params.json = (json) ? 1 : 0;
f0722791
RW
1875 if (prefix) {
1876 (void)str2prefix(prefix, &params.lib.prefix);
1877 params.lib.longer_prefixes = longer_prefixes;
1878 }
1879 if (neighbor &&
1880 (inet_pton(AF_INET, neighbor, &params.lib.neighbor) != 1 ||
1881 bad_addr_v4(params.lib.neighbor))) {
1882 vty_out (vty, "%% Malformed address\n");
1883 return (CMD_SUCCESS);
1884 }
1885 params.lib.local_label = local_label;
1886 params.lib.remote_label = remote_label;
eac6e3f0 1887
bc0eb287 1888 if (!params.detail && !params.json)
5c7571d4 1889 vty_out (vty, "%-4s %-20s %-15s %-11s %-13s %6s\n", "AF",
bc0eb287 1890 "Destination", "Nexthop", "Local Label", "Remote Label",
96ade3ed 1891 "In Use");
bc0eb287 1892
a5d10512
RW
1893 imsg_compose(&ibuf, IMSG_CTL_SHOW_LIB, 0, 0, -1, NULL, 0);
1894 return (ldp_vty_dispatch(vty, &ibuf, SHOW_LIB, &params));
eac6e3f0
RW
1895}
1896
1897int
1224e5c4
RW
1898ldp_vty_show_discovery(struct vty *vty, const char *af_str, const char *detail,
1899 const char *json)
eac6e3f0
RW
1900{
1901 struct imsgbuf ibuf;
a5d10512 1902 struct show_params params;
eac6e3f0
RW
1903 int af;
1904
1905 if (ldp_vty_connect(&ibuf) < 0)
1906 return (CMD_WARNING);
1907
eac6e3f0
RW
1908 if (ldp_vty_get_af(af_str, &af) < 0)
1909 return (CMD_ERR_NO_MATCH);
1910
a5d10512
RW
1911 memset(&params, 0, sizeof(params));
1912 params.family = af;
1224e5c4
RW
1913 params.detail = (detail) ? 1 : 0;
1914 params.json = (json) ? 1 : 0;
eac6e3f0 1915
bc0eb287 1916 if (!params.detail && !params.json)
5c7571d4 1917 vty_out (vty, "%-4s %-15s %-8s %-15s %9s\n",
96ade3ed 1918 "AF", "ID", "Type", "Source", "Holdtime");
bc0eb287
RW
1919
1920 if (params.detail)
1921 imsg_compose(&ibuf, IMSG_CTL_SHOW_DISCOVERY_DTL, 0, 0, -1,
1922 NULL, 0);
1923 else
1924 imsg_compose(&ibuf, IMSG_CTL_SHOW_DISCOVERY, 0, 0, -1, NULL, 0);
a5d10512 1925 return (ldp_vty_dispatch(vty, &ibuf, SHOW_DISC, &params));
eac6e3f0
RW
1926}
1927
1928int
1224e5c4 1929ldp_vty_show_interface(struct vty *vty, const char *af_str, const char *json)
eac6e3f0
RW
1930{
1931 struct imsgbuf ibuf;
a5d10512 1932 struct show_params params;
eac6e3f0 1933 unsigned int ifidx = 0;
eac6e3f0
RW
1934 int af;
1935
1936 if (ldp_vty_connect(&ibuf) < 0)
1937 return (CMD_WARNING);
1938
eac6e3f0
RW
1939 if (ldp_vty_get_af(af_str, &af) < 0)
1940 return (CMD_ERR_NO_MATCH);
1941
a5d10512
RW
1942 memset(&params, 0, sizeof(params));
1943 params.family = af;
1224e5c4 1944 params.json = (json) ? 1 : 0;
eac6e3f0
RW
1945
1946 /* header */
a5d10512 1947 if (!params.json) {
5c7571d4 1948 vty_out (vty, "%-4s %-11s %-6s %-8s %-12s %3s\n", "AF",
96ade3ed 1949 "Interface", "State", "Uptime", "Hello Timers","ac");
a5d10512 1950 }
eac6e3f0 1951
a5d10512
RW
1952 imsg_compose(&ibuf, IMSG_CTL_SHOW_INTERFACE, 0, 0, -1, &ifidx,
1953 sizeof(ifidx));
1954 return (ldp_vty_dispatch(vty, &ibuf, SHOW_IFACE, &params));
eac6e3f0
RW
1955}
1956
99cfc17f 1957int
1224e5c4 1958ldp_vty_show_capabilities(struct vty *vty, const char *json)
99cfc17f 1959{
c740f7d3 1960 if (json) {
99cfc17f
RW
1961 json_object *json;
1962 json_object *json_array;
1963 json_object *json_cap;
1964
1965 json = json_object_new_object();
1966 json_array = json_object_new_array();
1967 json_object_object_add(json, "capabilities", json_array);
1968
1969 /* Dynamic Announcement (0x0506) */
1970 json_cap = json_object_new_object();
1971 json_object_string_add(json_cap, "description",
1972 "Dynamic Announcement");
1973 json_object_string_add(json_cap, "tlvType",
1974 "0x0506");
1975 json_object_array_add(json_array, json_cap);
1976
1977 /* Typed Wildcard (0x050B) */
1978 json_cap = json_object_new_object();
1979 json_object_string_add(json_cap, "description",
1980 "Typed Wildcard");
1981 json_object_string_add(json_cap, "tlvType",
1982 "0x050B");
1983 json_object_array_add(json_array, json_cap);
1984
1985 /* Unrecognized Notification (0x0603) */
1986 json_cap = json_object_new_object();
1987 json_object_string_add(json_cap, "description",
1988 "Unrecognized Notification");
1989 json_object_string_add(json_cap, "tlvType",
1990 "0x0603");
1991 json_object_array_add(json_array, json_cap);
1992
038c0a8f 1993 vty_json(vty, json);
99cfc17f
RW
1994 return (0);
1995 }
1996
181039f3 1997 vty_out (vty,
625e016d
DL
1998 "Supported LDP Capabilities\n"
1999 " * Dynamic Announcement (0x0506)\n"
2000 " * Typed Wildcard (0x050B)\n"
2001 " * Unrecognized Notification (0x0603)\n\n");
99cfc17f
RW
2002
2003 return (0);
2004}
2005
eac6e3f0 2006int
f0722791
RW
2007ldp_vty_show_neighbor(struct vty *vty, const char *lsr_id, int capabilities,
2008 const char *detail, const char *json)
eac6e3f0
RW
2009{
2010 struct imsgbuf ibuf;
a5d10512 2011 struct show_params params;
eac6e3f0
RW
2012
2013 if (ldp_vty_connect(&ibuf) < 0)
2014 return (CMD_WARNING);
2015
a5d10512 2016 memset(&params, 0, sizeof(params));
1224e5c4
RW
2017 params.detail = (detail) ? 1 : 0;
2018 params.json = (json) ? 1 : 0;
f0722791
RW
2019 params.neighbor.capabilities = capabilities;
2020 if (lsr_id &&
2021 (inet_pton(AF_INET, lsr_id, &params.neighbor.lsr_id) != 1 ||
2022 bad_addr_v4(params.neighbor.lsr_id))) {
2023 vty_out (vty, "%% Malformed address\n");
2024 return (CMD_SUCCESS);
2025 }
eac6e3f0 2026
f0722791 2027 if (params.neighbor.capabilities)
99cfc17f
RW
2028 params.detail = 1;
2029
bc0eb287 2030 if (!params.detail && !params.json)
5c7571d4 2031 vty_out (vty, "%-4s %-15s %-11s %-15s %8s\n",
96ade3ed 2032 "AF", "ID", "State", "Remote Address","Uptime");
bc0eb287 2033
a5d10512
RW
2034 imsg_compose(&ibuf, IMSG_CTL_SHOW_NBR, 0, 0, -1, NULL, 0);
2035 return (ldp_vty_dispatch(vty, &ibuf, SHOW_NBR, &params));
eac6e3f0
RW
2036}
2037
e1894ff7
KS
2038int
2039ldp_vty_show_ldp_sync(struct vty *vty, const char *json)
2040{
2041 struct imsgbuf ibuf;
2042 struct show_params params;
2043
2044 if (ldp_vty_connect(&ibuf) < 0)
2045 return (CMD_WARNING);
2046
2047 memset(&params, 0, sizeof(params));
2048 params.json = (json) ? 1 : 0;
2049
2050 imsg_compose(&ibuf, IMSG_CTL_SHOW_LDP_SYNC, 0, 0, -1, NULL, 0);
2051 return (ldp_vty_dispatch(vty, &ibuf, SHOW_LDP_SYNC, &params));
2052}
2053
eac6e3f0 2054int
f0722791
RW
2055ldp_vty_show_atom_binding(struct vty *vty, const char *peer,
2056 unsigned long local_label, unsigned long remote_label, const char *json)
eac6e3f0
RW
2057{
2058 struct imsgbuf ibuf;
a5d10512 2059 struct show_params params;
eac6e3f0
RW
2060
2061 if (ldp_vty_connect(&ibuf) < 0)
2062 return (CMD_WARNING);
2063
a5d10512 2064 memset(&params, 0, sizeof(params));
1224e5c4 2065 params.json = (json) ? 1 : 0;
f0722791
RW
2066 if (peer &&
2067 (inet_pton(AF_INET, peer, &params.l2vpn.peer) != 1 ||
2068 bad_addr_v4(params.l2vpn.peer))) {
2069 vty_out (vty, "%% Malformed address\n");
2070 return (CMD_SUCCESS);
2071 }
2072 params.l2vpn.local_label = local_label;
2073 params.l2vpn.remote_label = remote_label;
eac6e3f0 2074
a5d10512
RW
2075 imsg_compose(&ibuf, IMSG_CTL_SHOW_L2VPN_BINDING, 0, 0, -1, NULL, 0);
2076 return (ldp_vty_dispatch(vty, &ibuf, SHOW_L2VPN_BINDING, &params));
eac6e3f0
RW
2077}
2078
2079int
f0722791
RW
2080ldp_vty_show_atom_vc(struct vty *vty, const char *peer, const char *ifname,
2081 const char *vcid, const char *json)
eac6e3f0
RW
2082{
2083 struct imsgbuf ibuf;
a5d10512 2084 struct show_params params;
eac6e3f0
RW
2085
2086 if (ldp_vty_connect(&ibuf) < 0)
2087 return (CMD_WARNING);
2088
a5d10512 2089 memset(&params, 0, sizeof(params));
1224e5c4 2090 params.json = (json) ? 1 : 0;
f0722791
RW
2091 if (peer &&
2092 (inet_pton(AF_INET, peer, &params.l2vpn.peer) != 1 ||
2093 bad_addr_v4(params.l2vpn.peer))) {
2094 vty_out (vty, "%% Malformed address\n");
2095 return (CMD_SUCCESS);
2096 }
2097 if (ifname)
2098 strlcpy(params.l2vpn.ifname, ifname,
2099 sizeof(params.l2vpn.ifname));
2100 if (vcid)
2101 params.l2vpn.vcid = atoi(vcid);
a5d10512
RW
2102
2103 if (!params.json) {
2104 /* header */
5c7571d4 2105 vty_out (vty, "%-9s %-15s %-10s %-16s %-10s\n",
96ade3ed 2106 "Interface", "Peer ID", "VC ID", "Name","Status");
5c7571d4 2107 vty_out (vty, "%-9s %-15s %-10s %-16s %-10s\n",
a5d10512 2108 "---------", "---------------", "----------",
96ade3ed 2109 "----------------", "----------");
a5d10512 2110 }
eac6e3f0 2111
a5d10512
RW
2112 imsg_compose(&ibuf, IMSG_CTL_SHOW_L2VPN_PW, 0, 0, -1, NULL, 0);
2113 return (ldp_vty_dispatch(vty, &ibuf, SHOW_L2VPN_PW, &params));
eac6e3f0
RW
2114}
2115
2116int
c740f7d3 2117ldp_vty_clear_nbr(struct vty *vty, const char *addr_str)
eac6e3f0
RW
2118{
2119 struct imsgbuf ibuf;
eac6e3f0
RW
2120 struct ctl_nbr nbr;
2121
eac6e3f0
RW
2122 memset(&nbr, 0, sizeof(nbr));
2123 if (addr_str &&
2124 (ldp_get_address(addr_str, &nbr.af, &nbr.raddr) == -1 ||
2125 bad_addr(nbr.af, &nbr.raddr))) {
5c7571d4 2126 vty_out (vty, "%% Malformed address\n");
eac6e3f0
RW
2127 return (CMD_WARNING);
2128 }
2129
2130 if (ldp_vty_connect(&ibuf) < 0)
2131 return (CMD_WARNING);
2132
2133 imsg_compose(&ibuf, IMSG_CTL_CLEAR_NBR, 0, 0, -1, &nbr, sizeof(nbr));
2134
2135 while (ibuf.w.queued)
2136 if (msgbuf_write(&ibuf.w) <= 0 && errno != EAGAIN) {
2137 log_warn("write error");
2138 close(ibuf.fd);
2139 return (CMD_WARNING);
2140 }
2141
2142 close(ibuf.fd);
2143
2144 return (CMD_SUCCESS);
2145}