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