]> git.proxmox.com Git - mirror_frr.git/blame - ldpd/ldp_vty_exec.c
Merge pull request #6358 from donaldsharp/zebra_onlink
[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");
181039f3
DL
587 vty_out(vty, " Session Holdtime: %u secs; "
588 "KeepAlive interval: %u secs\n", nbr->holdtime,
96ade3ed 589 nbr->holdtime / KEEPALIVE_PER_PERIOD);
5c7571d4 590 vty_out(vty, " State: %s; Downstream-Unsolicited\n",
96ade3ed 591 nbr_state_name(nbr->nbr_state));
5c7571d4 592 vty_out (vty, " Up time: %s\n",log_time(nbr->uptime));
0f7b5df9
RW
593
594 stats = &nbr->stats;
5c7571d4
DL
595 vty_out (vty, " Messages sent/rcvd:\n");
596 vty_out (vty, " - Keepalive Messages: %u/%u\n",
96ade3ed 597 stats->kalive_sent, stats->kalive_rcvd);
5c7571d4 598 vty_out (vty, " - Address Messages: %u/%u\n",
96ade3ed 599 stats->addr_sent, stats->addr_rcvd);
5c7571d4 600 vty_out (vty, " - Address Withdraw Messages: %u/%u\n",
96ade3ed 601 stats->addrwdraw_sent, stats->addrwdraw_rcvd);
5c7571d4 602 vty_out (vty, " - Notification Messages: %u/%u\n",
96ade3ed 603 stats->notif_sent, stats->notif_rcvd);
5c7571d4 604 vty_out (vty, " - Capability Messages: %u/%u\n",
96ade3ed 605 stats->capability_sent, stats->capability_rcvd);
5c7571d4 606 vty_out (vty, " - Label Mapping Messages: %u/%u\n",
96ade3ed 607 stats->labelmap_sent, stats->labelmap_rcvd);
5c7571d4 608 vty_out (vty, " - Label Request Messages: %u/%u\n",
96ade3ed 609 stats->labelreq_sent, stats->labelreq_rcvd);
5c7571d4 610 vty_out (vty, " - Label Withdraw Messages: %u/%u\n",
96ade3ed 611 stats->labelwdraw_sent, stats->labelwdraw_rcvd);
5c7571d4 612 vty_out (vty, " - Label Release Messages: %u/%u\n",
96ade3ed 613 stats->labelrel_sent, stats->labelrel_rcvd);
5c7571d4 614 vty_out (vty, " - Label Abort Request Messages: %u/%u\n",
96ade3ed 615 stats->labelabreq_sent, stats->labelabreq_rcvd);
0f7b5df9
RW
616
617 show_nbr_capabilities(vty, nbr);
eac6e3f0
RW
618 break;
619 case IMSG_CTL_SHOW_NBR_DISC:
620 adj = imsg->data;
621
622 switch (adj->af) {
623 case AF_INET:
bc0eb287 624 show_nbr_detail_adj(vty, v4adjs_buffer, adj);
eac6e3f0
RW
625 break;
626 case AF_INET6:
bc0eb287 627 show_nbr_detail_adj(vty, v6adjs_buffer, adj);
eac6e3f0
RW
628 break;
629 default:
bc0eb287 630 fatalx("show_nbr_detail_msg: unknown af");
a5d10512
RW
631 }
632 break;
633 case IMSG_CTL_SHOW_NBR_END:
5c7571d4 634 vty_out (vty, " LDP Discovery Sources:\n");
a5d10512 635 if (v4adjs_buffer[0] != '\0') {
5c7571d4 636 vty_out (vty, " IPv4:\n");
a5d10512
RW
637 vty_out(vty, "%s", v4adjs_buffer);
638 }
639 if (v6adjs_buffer[0] != '\0') {
5c7571d4 640 vty_out (vty, " IPv6:\n");
a5d10512
RW
641 vty_out(vty, "%s", v6adjs_buffer);
642 }
6d3c2ed4 643 vty_out (vty, "\n");
a5d10512
RW
644 break;
645 case IMSG_CTL_END:
646 return (1);
647 default:
648 break;
649 }
650
651 return (0);
652}
653
bc0eb287
RW
654static int
655show_nbr_msg_json(struct imsg *imsg, struct show_params *params,
656 json_object *json)
657{
658 struct ctl_nbr *nbr;
659 json_object *json_array;
660 json_object *json_nbr;
661
662 switch (imsg->hdr.type) {
663 case IMSG_CTL_SHOW_NBR:
664 nbr = imsg->data;
665
666 json_object_object_get_ex(json, "neighbors", &json_array);
667 if (!json_array) {
668 json_array = json_object_new_array();
669 json_object_object_add(json, "neighbors", json_array);
670 }
671
672 json_nbr = json_object_new_object();
673 json_object_string_add(json_nbr, "addressFamily",
674 af_name(nbr->af));
675 json_object_string_add(json_nbr, "neighborId",
676 inet_ntoa(nbr->id));
677 json_object_string_add(json_nbr, "state",
678 nbr_state_name(nbr->nbr_state));
679 json_object_string_add(json_nbr, "transportAddress",
680 log_addr(nbr->af, &nbr->raddr));
681 json_object_string_add(json_nbr, "upTime",
682 log_time(nbr->uptime));
683
684 json_object_array_add(json_array, json_nbr);
685 break;
686 case IMSG_CTL_END:
687 return (1);
688 default:
689 break;
690 }
691
692 return (0);
693}
694
a5d10512 695static void
bc0eb287 696show_nbr_detail_adj_json(struct ctl_adj *adj, json_object *adj_list)
a5d10512
RW
697{
698 char adj_string[128];
699
700 switch (adj->type) {
701 case HELLO_LINK:
702 strlcpy(adj_string, "interface: ", sizeof(adj_string));
703 strlcat(adj_string, adj->ifname, sizeof(adj_string));
704 break;
705 case HELLO_TARGETED:
706 strlcpy(adj_string, "targetedHello: ", sizeof(adj_string));
707 strlcat(adj_string, log_addr(adj->af, &adj->src_addr),
708 sizeof(adj_string));
709 break;
710 }
711
712 json_object_array_add(adj_list, json_object_new_string(adj_string));
713}
714
715static int
bc0eb287 716show_nbr_detail_msg_json(struct imsg *imsg, struct show_params *params,
a5d10512
RW
717 json_object *json)
718{
719 struct ctl_nbr *nbr;
0f7b5df9 720 struct ldp_stats *stats;
a5d10512
RW
721 struct ctl_adj *adj;
722 json_object *json_nbr;
0f7b5df9
RW
723 json_object *json_array;
724 json_object *json_counter;
a5d10512
RW
725 static json_object *json_nbr_sources;
726 static json_object *json_v4adjs;
727 static json_object *json_v6adjs;
728
729 switch (imsg->hdr.type) {
730 case IMSG_CTL_SHOW_NBR:
731 nbr = imsg->data;
732
733 json_nbr = json_object_new_object();
0f7b5df9
RW
734 json_object_object_add(json, inet_ntoa(nbr->id), json_nbr);
735
a5d10512
RW
736 json_object_string_add(json_nbr, "peerId", inet_ntoa(nbr->id));
737 json_object_string_add(json_nbr, "tcpLocalAddress",
738 log_addr(nbr->af, &nbr->laddr));
739 json_object_int_add(json_nbr, "tcpLocalPort",
740 ntohs(nbr->lport));
741 json_object_string_add(json_nbr, "tcpRemoteAddress",
742 log_addr(nbr->af, &nbr->raddr));
743 json_object_int_add(json_nbr, "tcpRemotePort",
744 ntohs(nbr->rport));
0f7b5df9
RW
745 json_object_string_add(json_nbr, "authentication",
746 (nbr->auth_method == AUTH_MD5SIG) ? "TCP MD5 Signature" :
747 "none");
748 json_object_int_add(json_nbr, "sessionHoldtime", nbr->holdtime);
749 json_object_int_add(json_nbr, "keepAliveInterval",
750 nbr->holdtime / KEEPALIVE_PER_PERIOD);
a5d10512
RW
751 json_object_string_add(json_nbr, "state",
752 nbr_state_name(nbr->nbr_state));
753 json_object_string_add(json_nbr, "upTime",
754 log_time(nbr->uptime));
a5d10512 755
0f7b5df9
RW
756 /* message_counters */
757 stats = &nbr->stats;
758 json_array = json_object_new_array();
759 json_object_object_add(json_nbr, "sentMessages", json_array);
760 json_counter = json_object_new_object();
761 json_object_int_add(json_counter, "keepalive",
762 stats->kalive_sent);
763 json_object_array_add(json_array, json_counter);
764 json_counter = json_object_new_object();
765 json_object_int_add(json_counter, "address",
766 stats->addr_sent);
767 json_object_array_add(json_array, json_counter);
768 json_counter = json_object_new_object();
769 json_object_int_add(json_counter, "addressWithdraw",
770 stats->addrwdraw_sent);
771 json_object_array_add(json_array, json_counter);
772 json_counter = json_object_new_object();
773 json_object_int_add(json_counter, "notification",
774 stats->notif_sent);
775 json_object_array_add(json_array, json_counter);
776 json_counter = json_object_new_object();
777 json_object_int_add(json_counter, "capability",
778 stats->capability_sent);
779 json_object_array_add(json_array, json_counter);
780 json_counter = json_object_new_object();
781 json_object_int_add(json_counter, "labelMapping",
782 stats->labelmap_sent);
783 json_object_array_add(json_array, json_counter);
784 json_counter = json_object_new_object();
785 json_object_int_add(json_counter, "labelRequest",
786 stats->labelreq_sent);
787 json_object_array_add(json_array, json_counter);
788 json_counter = json_object_new_object();
789 json_object_int_add(json_counter, "labelWithdraw",
790 stats->labelwdraw_sent);
791 json_object_array_add(json_array, json_counter);
792 json_counter = json_object_new_object();
793 json_object_int_add(json_counter, "labelRelease",
794 stats->labelrel_sent);
795 json_object_array_add(json_array, json_counter);
796 json_counter = json_object_new_object();
797 json_object_int_add(json_counter, "labelAbortRequest",
798 stats->labelabreq_sent);
799 json_object_array_add(json_array, json_counter);
800
801 json_array = json_object_new_array();
802 json_object_object_add(json_nbr, "receivedMessages", json_array);
803 json_counter = json_object_new_object();
804 json_object_int_add(json_counter, "keepalive",
805 stats->kalive_rcvd);
806 json_object_array_add(json_array, json_counter);
807 json_counter = json_object_new_object();
808 json_object_int_add(json_counter, "address",
809 stats->addr_rcvd);
810 json_object_array_add(json_array, json_counter);
811 json_counter = json_object_new_object();
812 json_object_int_add(json_counter, "addressWithdraw",
813 stats->addrwdraw_rcvd);
814 json_object_array_add(json_array, json_counter);
815 json_counter = json_object_new_object();
816 json_object_int_add(json_counter, "notification",
817 stats->notif_rcvd);
818 json_object_array_add(json_array, json_counter);
819 json_counter = json_object_new_object();
820 json_object_int_add(json_counter, "capability",
821 stats->capability_rcvd);
822 json_object_array_add(json_array, json_counter);
823 json_counter = json_object_new_object();
824 json_object_int_add(json_counter, "labelMapping",
825 stats->labelmap_rcvd);
826 json_object_array_add(json_array, json_counter);
827 json_counter = json_object_new_object();
828 json_object_int_add(json_counter, "labelRequest",
829 stats->labelreq_rcvd);
830 json_object_array_add(json_array, json_counter);
831 json_counter = json_object_new_object();
832 json_object_int_add(json_counter, "labelWithdraw",
833 stats->labelwdraw_rcvd);
834 json_object_array_add(json_array, json_counter);
835 json_counter = json_object_new_object();
836 json_object_int_add(json_counter, "labelRelease",
837 stats->labelrel_rcvd);
838 json_object_array_add(json_array, json_counter);
839 json_counter = json_object_new_object();
840 json_object_int_add(json_counter, "labelAbortRequest",
841 stats->labelabreq_rcvd);
842 json_object_array_add(json_array, json_counter);
843
844 /* capabilities */
845 show_nbr_capabilities_json(nbr, json_nbr);
846
847 /* discovery sources */
a5d10512
RW
848 json_nbr_sources = json_object_new_object();
849 json_object_object_add(json_nbr, "discoverySources",
850 json_nbr_sources);
851 json_v4adjs = NULL;
852 json_v6adjs = NULL;
853 break;
854 case IMSG_CTL_SHOW_NBR_DISC:
855 adj = imsg->data;
856
857 switch (adj->af) {
858 case AF_INET:
859 if (!json_v4adjs) {
860 json_v4adjs = json_object_new_array();
861 json_object_object_add(json_nbr_sources, "ipv4",
862 json_v4adjs);
863 }
bc0eb287 864 show_nbr_detail_adj_json(adj, json_v4adjs);
a5d10512
RW
865 break;
866 case AF_INET6:
867 if (!json_v6adjs) {
868 json_v6adjs = json_object_new_array();
869 json_object_object_add(json_nbr_sources, "ipv6",
870 json_v6adjs);
871 }
bc0eb287 872 show_nbr_detail_adj_json(adj, json_v6adjs);
a5d10512
RW
873 break;
874 default:
bc0eb287 875 fatalx("show_nbr_detail_msg_json: unknown af");
a5d10512 876 }
eac6e3f0
RW
877 break;
878 case IMSG_CTL_SHOW_NBR_END:
eac6e3f0
RW
879 break;
880 case IMSG_CTL_END:
881 return (1);
882 default:
883 break;
884 }
885
886 return (0);
887}
888
0f7b5df9
RW
889void
890show_nbr_capabilities(struct vty *vty, struct ctl_nbr *nbr)
891{
625e016d
DL
892 vty_out (vty, " Capabilities Sent:\n"
893 " - Dynamic Announcement (0x0506)\n"
894 " - Typed Wildcard (0x050B)\n"
895 " - Unrecognized Notification (0x0603)\n");
5c7571d4 896 vty_out (vty, " Capabilities Received:\n");
0f7b5df9 897 if (nbr->flags & F_NBR_CAP_DYNAMIC)
5c7571d4 898 vty_out (vty," - Dynamic Announcement (0x0506)\n");
0f7b5df9 899 if (nbr->flags & F_NBR_CAP_TWCARD)
5c7571d4 900 vty_out (vty, " - Typed Wildcard (0x050B)\n");
0f7b5df9 901 if (nbr->flags & F_NBR_CAP_UNOTIF)
5c7571d4 902 vty_out (vty," - Unrecognized Notification (0x0603)\n");
0f7b5df9
RW
903}
904
99cfc17f
RW
905static int
906show_nbr_capabilities_msg(struct vty *vty, struct imsg *imsg, struct show_params *params)
907{
908 struct ctl_nbr *nbr;
909
910 switch (imsg->hdr.type) {
911 case IMSG_CTL_SHOW_NBR:
912 nbr = imsg->data;
913
914 if (nbr->nbr_state != NBR_STA_OPER)
915 break;
916
5c7571d4 917 vty_out (vty, "Peer LDP Identifier: %s:0\n",
96ade3ed 918 inet_ntoa(nbr->id));
0f7b5df9 919 show_nbr_capabilities(vty, nbr);
6d3c2ed4 920 vty_out (vty, "\n");
99cfc17f
RW
921 break;
922 case IMSG_CTL_END:
6d3c2ed4 923 vty_out (vty, "\n");
99cfc17f
RW
924 return (1);
925 default:
926 break;
927 }
928
929 return (0);
930}
931
0f7b5df9
RW
932static void
933show_nbr_capabilities_json(struct ctl_nbr *nbr, json_object *json_nbr)
99cfc17f 934{
99cfc17f
RW
935 json_object *json_array;
936 json_object *json_cap;
937
0f7b5df9
RW
938 /* sent capabilities */
939 json_array = json_object_new_array();
940 json_object_object_add(json_nbr, "sentCapabilities", json_array);
941
942 /* Dynamic Announcement (0x0506) */
943 json_cap = json_object_new_object();
944 json_object_string_add(json_cap, "description", "Dynamic Announcement");
945 json_object_string_add(json_cap, "tlvType", "0x0506");
946 json_object_array_add(json_array, json_cap);
947
948 /* Typed Wildcard (0x050B) */
949 json_cap = json_object_new_object();
950 json_object_string_add(json_cap, "description", "Typed Wildcard");
951 json_object_string_add(json_cap, "tlvType", "0x050B");
952 json_object_array_add(json_array, json_cap);
953
954 /* Unrecognized Notification (0x0603) */
955 json_cap = json_object_new_object();
956 json_object_string_add(json_cap, "description",
957 "Unrecognized Notification");
958 json_object_string_add(json_cap, "tlvType", "0x0603");
959 json_object_array_add(json_array, json_cap);
960
961 /* received capabilities */
962 json_array = json_object_new_array();
963 json_object_object_add(json_nbr, "receivedCapabilities", json_array);
964
965 /* Dynamic Announcement (0x0506) */
966 if (nbr->flags & F_NBR_CAP_DYNAMIC) {
99cfc17f
RW
967 json_cap = json_object_new_object();
968 json_object_string_add(json_cap, "description",
969 "Dynamic Announcement");
0f7b5df9 970 json_object_string_add(json_cap, "tlvType", "0x0506");
99cfc17f 971 json_object_array_add(json_array, json_cap);
0f7b5df9 972 }
99cfc17f 973
0f7b5df9
RW
974 /* Typed Wildcard (0x050B) */
975 if (nbr->flags & F_NBR_CAP_TWCARD) {
99cfc17f
RW
976 json_cap = json_object_new_object();
977 json_object_string_add(json_cap, "description",
978 "Typed Wildcard");
0f7b5df9 979 json_object_string_add(json_cap, "tlvType", "0x050B");
99cfc17f 980 json_object_array_add(json_array, json_cap);
0f7b5df9 981 }
99cfc17f 982
0f7b5df9
RW
983 /* Unrecognized Notification (0x0603) */
984 if (nbr->flags & F_NBR_CAP_UNOTIF) {
99cfc17f
RW
985 json_cap = json_object_new_object();
986 json_object_string_add(json_cap, "description",
987 "Unrecognized Notification");
0f7b5df9 988 json_object_string_add(json_cap, "tlvType", "0x0603");
99cfc17f 989 json_object_array_add(json_array, json_cap);
0f7b5df9
RW
990 }
991}
99cfc17f 992
0f7b5df9
RW
993static int
994show_nbr_capabilities_msg_json(struct imsg *imsg, struct show_params *params,
995 json_object *json)
996{
997 struct ctl_nbr *nbr;
998 json_object *json_nbr;
99cfc17f 999
0f7b5df9
RW
1000 switch (imsg->hdr.type) {
1001 case IMSG_CTL_SHOW_NBR:
1002 nbr = imsg->data;
99cfc17f 1003
0f7b5df9
RW
1004 if (nbr->nbr_state != NBR_STA_OPER)
1005 break;
1006
1007 json_nbr = json_object_new_object();
1008 json_object_object_add(json, inet_ntoa(nbr->id), json_nbr);
1009 show_nbr_capabilities_json(nbr, json_nbr);
99cfc17f
RW
1010 break;
1011 case IMSG_CTL_END:
1012 return (1);
1013 default:
1014 break;
1015 }
1016
1017 return (0);
1018}
1019
eac6e3f0 1020static int
a5d10512 1021show_lib_msg(struct vty *vty, struct imsg *imsg, struct show_params *params)
eac6e3f0
RW
1022{
1023 struct ctl_rt *rt;
1024 char dstnet[BUFSIZ];
1025
bc0eb287 1026 switch (imsg->hdr.type) {
0f7b5df9 1027 case IMSG_CTL_SHOW_LIB_BEGIN:
f0722791
RW
1028 rt = imsg->data;
1029
1030 if (params->lib.remote_label != NO_LABEL &&
1031 params->lib.remote_label != rt->remote_label)
1032 return (0);
1033 /* FALLTHROUGH */
0f7b5df9 1034 case IMSG_CTL_SHOW_LIB_RCVD:
bc0eb287
RW
1035 rt = imsg->data;
1036
0f7b5df9
RW
1037 if (imsg->hdr.type == IMSG_CTL_SHOW_LIB_BEGIN &&
1038 !rt->no_downstream)
1039 break;
1040
bc0eb287
RW
1041 snprintf(dstnet, sizeof(dstnet), "%s/%d",
1042 log_addr(rt->af, &rt->prefix), rt->prefixlen);
1043
1044 vty_out(vty, "%-4s %-20s", af_name(rt->af), dstnet);
1045 if (strlen(dstnet) > 20)
61b7d449 1046 vty_out(vty, "\n%25s", " ");
5c7571d4 1047 vty_out (vty, " %-15s %-11s %-13s %6s\n", inet_ntoa(rt->nexthop),
bc0eb287 1048 log_label(rt->local_label), log_label(rt->remote_label),
96ade3ed 1049 rt->in_use ? "yes" : "no");
bc0eb287
RW
1050 break;
1051 case IMSG_CTL_END:
6d3c2ed4 1052 vty_out (vty, "\n");
bc0eb287
RW
1053 return (1);
1054 default:
1055 break;
1056 }
1057
1058 return (0);
1059}
1060
1061static int
1062show_lib_detail_msg(struct vty *vty, struct imsg *imsg, struct show_params *params)
1063{
f790d62a 1064 struct ctl_rt *rt = NULL;
f0722791 1065 static char dstnet[BUFSIZ];
0f7b5df9
RW
1066 static int upstream, downstream;
1067 size_t buflen;
1068 static char sent_buffer[LDPBUFSIZ];
1069 static char rcvd_buffer[LDPBUFSIZ];
bc0eb287 1070
eac6e3f0 1071 switch (imsg->hdr.type) {
0f7b5df9 1072 case IMSG_CTL_SHOW_LIB_BEGIN:
eac6e3f0 1073 rt = imsg->data;
0f7b5df9 1074
0f7b5df9
RW
1075 upstream = 0;
1076 downstream = 0;
1077 sent_buffer[0] = '\0';
1078 rcvd_buffer[0] = '\0';
eac6e3f0 1079 snprintf(dstnet, sizeof(dstnet), "%s/%d",
a5d10512 1080 log_addr(rt->af, &rt->prefix), rt->prefixlen);
0f7b5df9
RW
1081 break;
1082 case IMSG_CTL_SHOW_LIB_SENT:
f0722791
RW
1083 rt = imsg->data;
1084
0f7b5df9
RW
1085 upstream = 1;
1086 buflen = strlen(sent_buffer);
1087 snprintf(sent_buffer + buflen, LDPBUFSIZ - buflen,
625e016d 1088 "%12s%s:0\n", "", inet_ntoa(rt->nexthop));
0f7b5df9
RW
1089 break;
1090 case IMSG_CTL_SHOW_LIB_RCVD:
f0722791 1091 rt = imsg->data;
0f7b5df9
RW
1092 downstream = 1;
1093 buflen = strlen(rcvd_buffer);
1094 snprintf(rcvd_buffer + buflen, LDPBUFSIZ - buflen,
625e016d 1095 "%12s%s:0, label %s%s\n", "", inet_ntoa(rt->nexthop),
0f7b5df9 1096 log_label(rt->remote_label),
625e016d 1097 rt->in_use ? " (in use)" : "");
0f7b5df9
RW
1098 break;
1099 case IMSG_CTL_SHOW_LIB_END:
f0722791
RW
1100 rt = imsg->data;
1101
1102 if (params->lib.remote_label != NO_LABEL &&
1103 !downstream)
1104 break;
1105 vty_out(vty, "%s\n", dstnet);
1106 vty_out(vty, "%-8sLocal binding: label: %s\n", "",
1107 log_label(rt->local_label));
0f7b5df9 1108 if (upstream) {
5c7571d4 1109 vty_out (vty, "%-8sAdvertised to:\n", "");
0f7b5df9 1110 vty_out(vty, "%s", sent_buffer);
a5d10512 1111 }
0f7b5df9 1112 if (downstream) {
5c7571d4 1113 vty_out (vty, "%-8sRemote bindings:\n", "");
0f7b5df9
RW
1114 vty_out(vty, "%s", rcvd_buffer);
1115 } else
5c7571d4 1116 vty_out (vty, "%-8sNo remote bindings\n","");
eac6e3f0
RW
1117 break;
1118 case IMSG_CTL_END:
6d3c2ed4 1119 vty_out (vty, "\n");
eac6e3f0
RW
1120 return (1);
1121 default:
1122 break;
1123 }
1124
1125 return (0);
1126}
1127
1128static int
a5d10512
RW
1129show_lib_msg_json(struct imsg *imsg, struct show_params *params,
1130 json_object *json)
bc0eb287
RW
1131{
1132 struct ctl_rt *rt;
1133 json_object *json_array;
1134 json_object *json_lib_entry;
1135 char dstnet[BUFSIZ];
1136
1137 switch (imsg->hdr.type) {
0f7b5df9
RW
1138 case IMSG_CTL_SHOW_LIB_BEGIN:
1139 case IMSG_CTL_SHOW_LIB_RCVD:
bc0eb287
RW
1140 rt = imsg->data;
1141
0f7b5df9
RW
1142 if (imsg->hdr.type == IMSG_CTL_SHOW_LIB_BEGIN &&
1143 !rt->no_downstream)
bc0eb287
RW
1144 break;
1145
1146 json_object_object_get_ex(json, "bindings", &json_array);
1147 if (!json_array) {
1148 json_array = json_object_new_array();
1149 json_object_object_add(json, "bindings", json_array);
1150 }
1151
1152 json_lib_entry = json_object_new_object();
1153 json_object_string_add(json_lib_entry, "addressFamily",
1154 af_name(rt->af));
1155 snprintf(dstnet, sizeof(dstnet), "%s/%d",
1156 log_addr(rt->af, &rt->prefix), rt->prefixlen);
1157 json_object_string_add(json_lib_entry, "prefix", dstnet);
1158 json_object_string_add(json_lib_entry, "neighborId",
1159 inet_ntoa(rt->nexthop));
1160 json_object_string_add(json_lib_entry, "localLabel",
1161 log_label(rt->local_label));
1162 json_object_string_add(json_lib_entry, "remoteLabel",
1163 log_label(rt->remote_label));
1164 json_object_int_add(json_lib_entry, "inUse", rt->in_use);
1165
1166 json_object_array_add(json_array, json_lib_entry);
1167 break;
1168 case IMSG_CTL_END:
1169 return (1);
1170 default:
1171 break;
1172 }
1173
1174 return (0);
1175}
1176
1177static int
1178show_lib_detail_msg_json(struct imsg *imsg, struct show_params *params,
1179 json_object *json)
a5d10512 1180{
f790d62a 1181 struct ctl_rt *rt = NULL;
a5d10512 1182 char dstnet[BUFSIZ];
0f7b5df9
RW
1183 static json_object *json_lib_entry;
1184 static json_object *json_adv_labels;
1185 json_object *json_adv_label;
a5d10512
RW
1186 static json_object *json_remote_labels;
1187 json_object *json_remote_label;
1188
1189 switch (imsg->hdr.type) {
0f7b5df9 1190 case IMSG_CTL_SHOW_LIB_BEGIN:
a5d10512 1191 rt = imsg->data;
a5d10512
RW
1192
1193 snprintf(dstnet, sizeof(dstnet), "%s/%d",
1194 log_addr(rt->af, &rt->prefix), rt->prefixlen);
1195
0f7b5df9
RW
1196 json_lib_entry = json_object_new_object();
1197 json_object_string_add(json_lib_entry, "localLabel",
1198 log_label(rt->local_label));
a5d10512 1199
0f7b5df9
RW
1200 json_adv_labels = json_object_new_array();
1201 json_object_object_add(json_lib_entry, "advertisedTo",
1202 json_adv_labels);
a5d10512 1203
0f7b5df9
RW
1204 json_remote_labels = json_object_new_array();
1205 json_object_object_add(json_lib_entry, "remoteLabels",
1206 json_remote_labels);
1207
1208 json_object_object_add(json, dstnet, json_lib_entry);
1209 break;
1210 case IMSG_CTL_SHOW_LIB_SENT:
f0722791
RW
1211 rt = imsg->data;
1212
0f7b5df9
RW
1213 json_adv_label = json_object_new_object();
1214 json_object_string_add(json_adv_label, "neighborId",
1215 inet_ntoa(rt->nexthop));
1216 json_object_array_add(json_adv_labels, json_adv_label);
1217 break;
1218 case IMSG_CTL_SHOW_LIB_RCVD:
f0722791
RW
1219 rt = imsg->data;
1220
0f7b5df9
RW
1221 json_remote_label = json_object_new_object();
1222 json_object_string_add(json_remote_label, "neighborId",
1223 inet_ntoa(rt->nexthop));
1224 json_object_string_add(json_remote_label, "label",
1225 log_label(rt->remote_label));
1226 json_object_int_add(json_remote_label, "inUse", rt->in_use);
1227 json_object_array_add(json_remote_labels, json_remote_label);
a5d10512
RW
1228 break;
1229 case IMSG_CTL_END:
1230 return (1);
1231 default:
1232 break;
1233 }
1234
1235 return (0);
1236}
1237
1238static int
1239show_l2vpn_binding_msg(struct vty *vty, struct imsg *imsg,
1240 struct show_params *params)
eac6e3f0
RW
1241{
1242 struct ctl_pw *pw;
1243
1244 switch (imsg->hdr.type) {
1245 case IMSG_CTL_SHOW_L2VPN_BINDING:
1246 pw = imsg->data;
1247
5c7571d4 1248 vty_out (vty, " Destination Address: %s, VC ID: %u\n",
96ade3ed 1249 inet_ntoa(pw->lsr_id), pw->pwid);
eac6e3f0
RW
1250
1251 /* local binding */
1252 if (pw->local_label != NO_LABEL) {
5c7571d4 1253 vty_out (vty, " Local Label: %u\n",
96ade3ed 1254 pw->local_label);
181039f3
DL
1255 vty_out (vty, "%-8sCbit: %u, VC Type: %s, "
1256 "GroupID: %u\n", "", pw->local_cword,
96ade3ed 1257 pw_type_name(pw->type),pw->local_gid);
5c7571d4 1258 vty_out (vty, "%-8sMTU: %u\n", "",pw->local_ifmtu);
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);
181039f3
DL
1266 vty_out (vty, "%-8sCbit: %u, VC Type: %s, "
1267 "GroupID: %u\n", "", pw->remote_cword,
96ade3ed 1268 pw_type_name(pw->type),pw->remote_gid);
5c7571d4 1269 vty_out (vty, "%-8sMTU: %u\n", "",pw->remote_ifmtu);
eac6e3f0 1270 } else
5c7571d4 1271 vty_out (vty," Remote Label: unassigned\n");
eac6e3f0
RW
1272 break;
1273 case IMSG_CTL_END:
6d3c2ed4 1274 vty_out (vty, "\n");
eac6e3f0
RW
1275 return (1);
1276 default:
1277 break;
1278 }
1279
1280 return (0);
1281}
1282
1283static int
a5d10512
RW
1284show_l2vpn_binding_msg_json(struct imsg *imsg, struct show_params *params,
1285 json_object *json)
1286{
1287 struct ctl_pw *pw;
1288 json_object *json_pw;
1289 char key_name[64];
1290
1291 switch (imsg->hdr.type) {
1292 case IMSG_CTL_SHOW_L2VPN_BINDING:
1293 pw = imsg->data;
1294
1295 json_pw = json_object_new_object();
1296 json_object_string_add(json_pw, "destination",
1297 inet_ntoa(pw->lsr_id));
1298 json_object_int_add(json_pw, "vcId", pw->pwid);
1299
1300 /* local binding */
1301 if (pw->local_label != NO_LABEL) {
1302 json_object_int_add(json_pw, "localLabel",
1303 pw->local_label);
1304 json_object_int_add(json_pw, "localControlWord",
1305 pw->local_cword);
1306 json_object_string_add(json_pw, "localVcType",
1307 pw_type_name(pw->type));
1308 json_object_int_add(json_pw, "localGroupID",
1309 pw->local_gid);
1310 json_object_int_add(json_pw, "localIfMtu",
1311 pw->local_ifmtu);
1312 } else
1313 json_object_string_add(json_pw, "localLabel",
1314 "unassigned");
1315
1316 /* remote binding */
1317 if (pw->remote_label != NO_LABEL) {
1318 json_object_int_add(json_pw, "remoteLabel",
1319 pw->remote_label);
1320 json_object_int_add(json_pw, "remoteControlWord",
1321 pw->remote_cword);
1322 json_object_string_add(json_pw, "remoteVcType",
1323 pw_type_name(pw->type));
1324 json_object_int_add(json_pw, "remoteGroupID",
1325 pw->remote_gid);
1326 json_object_int_add(json_pw, "remoteIfMtu",
1327 pw->remote_ifmtu);
1328 } else
1329 json_object_string_add(json_pw, "remoteLabel",
1330 "unassigned");
1331
772270f3
QY
1332 snprintf(key_name, sizeof(key_name), "%s: %u",
1333 inet_ntoa(pw->lsr_id), pw->pwid);
a5d10512
RW
1334 json_object_object_add(json, key_name, json_pw);
1335 break;
1336 case IMSG_CTL_END:
1337 return (1);
1338 default:
1339 break;
1340 }
1341
1342 return (0);
1343}
1344
1345static int
1346show_l2vpn_pw_msg(struct vty *vty, struct imsg *imsg, struct show_params *params)
eac6e3f0
RW
1347{
1348 struct ctl_pw *pw;
1349
1350 switch (imsg->hdr.type) {
1351 case IMSG_CTL_SHOW_L2VPN_PW:
1352 pw = imsg->data;
1353
5c7571d4 1354 vty_out (vty, "%-9s %-15s %-10u %-16s %-10s\n", pw->ifname,
eac6e3f0 1355 inet_ntoa(pw->lsr_id), pw->pwid, pw->l2vpn_name,
96ade3ed 1356 (pw->status ? "UP" : "DOWN"));
eac6e3f0
RW
1357 break;
1358 case IMSG_CTL_END:
6d3c2ed4 1359 vty_out (vty, "\n");
eac6e3f0
RW
1360 return (1);
1361 default:
1362 break;
1363 }
1364
1365 return (0);
1366}
1367
a5d10512
RW
1368static int
1369show_l2vpn_pw_msg_json(struct imsg *imsg, struct show_params *params,
1370 json_object *json)
1371{
1372 struct ctl_pw *pw;
1373 json_object *json_pw;
1374
1375 switch (imsg->hdr.type) {
1376 case IMSG_CTL_SHOW_L2VPN_PW:
1377 pw = imsg->data;
1378
1379 json_pw = json_object_new_object();
1380 json_object_string_add(json_pw, "peerId", inet_ntoa(pw->lsr_id));
1381 json_object_int_add(json_pw, "vcId", pw->pwid);
1382 json_object_string_add(json_pw, "VpnName", pw->l2vpn_name);
1383 if (pw->status)
1384 json_object_string_add(json_pw, "status", "up");
1385 else
1386 json_object_string_add(json_pw, "status", "down");
1387 json_object_object_add(json, pw->ifname, json_pw);
1388 break;
1389 case IMSG_CTL_END:
1390 return (1);
1391 default:
1392 break;
1393 }
1394
1395 return (0);
1396}
1397
eac6e3f0
RW
1398static int
1399ldp_vty_connect(struct imsgbuf *ibuf)
1400{
1401 struct sockaddr_un s_un;
1402 int ctl_sock;
1403
1404 /* connect to ldpd control socket */
1405 if ((ctl_sock = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) {
1406 log_warn("%s: socket", __func__);
1407 return (-1);
1408 }
1409
1410 memset(&s_un, 0, sizeof(s_un));
1411 s_un.sun_family = AF_UNIX;
372b8bd3 1412 strlcpy(s_un.sun_path, ctl_sock_path, sizeof(s_un.sun_path));
eac6e3f0 1413 if (connect(ctl_sock, (struct sockaddr *)&s_un, sizeof(s_un)) == -1) {
372b8bd3 1414 log_warn("%s: connect: %s", __func__, ctl_sock_path);
eac6e3f0
RW
1415 close(ctl_sock);
1416 return (-1);
1417 }
1418
1419 imsg_init(ibuf, ctl_sock);
1420
1421 return (0);
1422}
1423
a5d10512 1424static int
f0722791 1425ldp_vty_dispatch_iface(struct vty *vty, struct imsg *imsg,
a5d10512
RW
1426 struct show_params *params, json_object *json)
1427{
bc0eb287
RW
1428 int ret;
1429
f0722791
RW
1430 if (params->json)
1431 ret = show_interface_msg_json(imsg, params, json);
1432 else
1433 ret = show_interface_msg(vty, imsg, params);
1434
1435 return (ret);
1436}
1437
1438static int
1439ldp_vty_dispatch_disc(struct vty *vty, struct imsg *imsg,
1440 struct show_params *params, json_object *json)
1441{
1442 int ret;
1443
1444 if (params->detail) {
bc0eb287 1445 if (params->json)
f0722791
RW
1446 ret = show_discovery_detail_msg_json(imsg, params,
1447 json);
bc0eb287 1448 else
f0722791
RW
1449 ret = show_discovery_detail_msg(vty, imsg, params);
1450 } else {
1451 if (params->json)
1452 ret = show_discovery_msg_json(imsg, params, json);
1453 else
1454 ret = show_discovery_msg(vty, imsg, params);
1455 }
1456
1457 return (ret);
1458}
1459
1460static int
1461ldp_vty_dispatch_nbr(struct vty *vty, struct imsg *imsg,
1462 struct show_params *params, json_object *json)
1463{
1464 static bool filtered = false;
1465 struct ctl_nbr *nbr;
1466 int ret;
1467
1468 switch (imsg->hdr.type) {
1469 case IMSG_CTL_SHOW_NBR:
1470 filtered = false;
1471 nbr = imsg->data;
1472
1473 if (params->neighbor.lsr_id.s_addr != INADDR_ANY &&
1474 params->neighbor.lsr_id.s_addr != nbr->id.s_addr) {
1475 filtered = true;
1476 return (0);
bc0eb287
RW
1477 }
1478 break;
f0722791
RW
1479 case IMSG_CTL_SHOW_NBR_DISC:
1480 case IMSG_CTL_SHOW_NBR_END:
1481 if (filtered)
1482 return (0);
bc0eb287 1483 break;
f0722791 1484 default:
bc0eb287 1485 break;
f0722791
RW
1486 }
1487
1488 if (params->neighbor.capabilities) {
bc0eb287 1489 if (params->json)
f0722791
RW
1490 ret = show_nbr_capabilities_msg_json(imsg, params,
1491 json);
bc0eb287 1492 else
f0722791
RW
1493 ret = show_nbr_capabilities_msg(vty, imsg, params);
1494 } else if (params->detail) {
1495 if (params->json)
1496 ret = show_nbr_detail_msg_json(imsg, params, json);
1497 else
1498 ret = show_nbr_detail_msg(vty, imsg, params);
1499 } else {
1500 if (params->json)
1501 ret = show_nbr_msg_json(imsg, params, json);
1502 else
1503 ret = show_nbr_msg(vty, imsg, params);
1504 }
1505
1506 return (ret);
1507}
1508
1509static int
1510ldp_vty_dispatch_lib(struct vty *vty, struct imsg *imsg,
1511 struct show_params *params, json_object *json)
1512{
1513 static bool filtered = false;
7f677840 1514 struct ctl_rt *rt = NULL;
f0722791
RW
1515 struct prefix prefix;
1516 int ret;
1517
1518 switch (imsg->hdr.type) {
1519 case IMSG_CTL_SHOW_LIB_BEGIN:
1520 filtered = false;
bc0eb287 1521 break;
f0722791
RW
1522 case IMSG_CTL_SHOW_LIB_SENT:
1523 case IMSG_CTL_SHOW_LIB_RCVD:
1524 case IMSG_CTL_SHOW_LIB_END:
1525 if (filtered)
1526 return (0);
1527 break;
1528 default:
1529 break;
1530 }
1531
1532 switch (imsg->hdr.type) {
1533 case IMSG_CTL_SHOW_LIB_BEGIN:
1534 case IMSG_CTL_SHOW_LIB_SENT:
1535 case IMSG_CTL_SHOW_LIB_RCVD:
1536 case IMSG_CTL_SHOW_LIB_END:
1537 rt = imsg->data;
1538
1539 if (params->family != AF_UNSPEC && params->family != rt->af) {
1540 filtered = true;
1541 return (0);
1542 }
1543
1544 prefix.family = rt->af;
1545 prefix.prefixlen = rt->prefixlen;
1546 memcpy(&prefix.u.val, &rt->prefix, sizeof(prefix.u.val));
1547 if (params->lib.prefix.family != AF_UNSPEC) {
1548 if (!params->lib.longer_prefixes &&
1549 !prefix_same(&params->lib.prefix, &prefix)) {
1550 filtered = true;
1551 return (0);
1552 } else if (params->lib.longer_prefixes &&
1553 !prefix_match(&params->lib.prefix, &prefix)) {
1554 filtered = true;
1555 return (0);
1556 }
1557 }
1558
1559 if (params->lib.local_label != NO_LABEL &&
1560 params->lib.local_label != rt->local_label) {
1561 filtered = true;
1562 return (0);
1563 }
1564 break;
1565 default:
1566 break;
1567 }
1568
1569 switch (imsg->hdr.type) {
1570 case IMSG_CTL_SHOW_LIB_SENT:
1571 case IMSG_CTL_SHOW_LIB_RCVD:
1572 if (params->lib.neighbor.s_addr != INADDR_ANY &&
1573 params->lib.neighbor.s_addr != rt->nexthop.s_addr)
1574 return (0);
1575 break;
1576 default:
1577 break;
1578 }
1579
1580 switch (imsg->hdr.type) {
1581 case IMSG_CTL_SHOW_LIB_RCVD:
1582 if (params->lib.remote_label != NO_LABEL &&
1583 params->lib.remote_label != rt->remote_label)
1584 return (0);
1585 break;
1586 default:
1587 break;
1588 }
1589
1590 if (params->detail) {
bc0eb287 1591 if (params->json)
f0722791 1592 ret = show_lib_detail_msg_json(imsg, params, json);
bc0eb287 1593 else
f0722791
RW
1594 ret = show_lib_detail_msg(vty, imsg, params);
1595 } else {
1596 if (params->json)
1597 ret = show_lib_msg_json(imsg, params, json);
1598 else
1599 ret = show_lib_msg(vty, imsg, params);
1600 }
1601
1602 return (ret);
1603}
1604
1605static int
1606ldp_vty_dispatch_l2vpn_pw(struct vty *vty, struct imsg *imsg,
1607 struct show_params *params, json_object *json)
1608{
1609 struct ctl_pw *pw;
1610 int ret;
1611
1612 switch (imsg->hdr.type) {
1613 case IMSG_CTL_SHOW_L2VPN_PW:
1614 pw = imsg->data;
1615 if (params->l2vpn.peer.s_addr != INADDR_ANY &&
1616 params->l2vpn.peer.s_addr != pw->lsr_id.s_addr)
1617 return (0);
1618 if (params->l2vpn.ifname[0] != '\0' &&
1619 strcmp(params->l2vpn.ifname, pw->ifname))
1620 return (0);
1621 if (params->l2vpn.vcid && params->l2vpn.vcid != pw->pwid)
1622 return (0);
bc0eb287 1623 break;
a5d10512 1624 default:
f0722791 1625 break;
a5d10512 1626 }
bc0eb287 1627
f0722791
RW
1628 if (params->json)
1629 ret = show_l2vpn_pw_msg_json(imsg, params, json);
1630 else
1631 ret = show_l2vpn_pw_msg(vty, imsg, params);
1632
bc0eb287 1633 return (ret);
a5d10512
RW
1634}
1635
f0722791
RW
1636static int
1637ldp_vty_dispatch_l2vpn_binding(struct vty *vty, struct imsg *imsg,
1638 struct show_params *params, json_object *json)
1639{
1640 struct ctl_pw *pw;
1641 int ret;
1642
1643 switch (imsg->hdr.type) {
1644 case IMSG_CTL_SHOW_L2VPN_BINDING:
1645 pw = imsg->data;
1646 if (params->l2vpn.peer.s_addr != INADDR_ANY &&
1647 params->l2vpn.peer.s_addr != pw->lsr_id.s_addr)
1648 return (0);
1649 if (params->l2vpn.local_label != NO_LABEL &&
1650 params->l2vpn.local_label != pw->local_label)
1651 return (0);
1652 if (params->l2vpn.remote_label != NO_LABEL &&
1653 params->l2vpn.remote_label != pw->remote_label)
1654 return (0);
1655 break;
1656 default:
1657 break;
1658 }
1659
1660 if (params->json)
1661 ret = show_l2vpn_binding_msg_json(imsg, params, json);
1662 else
1663 ret = show_l2vpn_binding_msg(vty, imsg, params);
1664
1665 return (ret);
1666}
1667
1668static int
1669ldp_vty_dispatch_msg(struct vty *vty, struct imsg *imsg, enum show_command cmd,
1670 struct show_params *params, json_object *json)
1671{
1672 switch (cmd) {
1673 case SHOW_IFACE:
1674 return (ldp_vty_dispatch_iface(vty, imsg, params, json));
1675 case SHOW_DISC:
1676 return (ldp_vty_dispatch_disc(vty, imsg, params, json));
1677 case SHOW_NBR:
1678 return (ldp_vty_dispatch_nbr(vty, imsg, params, json));
1679 case SHOW_LIB:
1680 return (ldp_vty_dispatch_lib(vty, imsg, params, json));
1681 case SHOW_L2VPN_PW:
1682 return (ldp_vty_dispatch_l2vpn_pw(vty, imsg, params, json));
1683 case SHOW_L2VPN_BINDING:
1684 return (ldp_vty_dispatch_l2vpn_binding(vty, imsg, params,
1685 json));
1686 default:
1687 return (0);
1688 }
1689}
1690
eac6e3f0
RW
1691static int
1692ldp_vty_dispatch(struct vty *vty, struct imsgbuf *ibuf, enum show_command cmd,
a5d10512 1693 struct show_params *params)
eac6e3f0
RW
1694{
1695 struct imsg imsg;
a5d10512
RW
1696 int n, done = 0, ret = CMD_SUCCESS;
1697 json_object *json = NULL;
eac6e3f0
RW
1698
1699 while (ibuf->w.queued)
1700 if (msgbuf_write(&ibuf->w) <= 0 && errno != EAGAIN) {
1701 log_warn("write error");
1702 close(ibuf->fd);
1703 return (CMD_WARNING);
1704 }
1705
a5d10512
RW
1706 if (params->json)
1707 json = json_object_new_object();
e8dbef04 1708
eac6e3f0
RW
1709 while (!done) {
1710 if ((n = imsg_read(ibuf)) == -1 && errno != EAGAIN) {
1711 log_warnx("imsg_read error");
a5d10512
RW
1712 ret = CMD_WARNING;
1713 goto done;
eac6e3f0
RW
1714 }
1715 if (n == 0) {
1716 log_warnx("pipe closed");
a5d10512
RW
1717 ret = CMD_WARNING;
1718 goto done;
eac6e3f0
RW
1719 }
1720
1721 while (!done) {
1722 if ((n = imsg_get(ibuf, &imsg)) == -1) {
1723 log_warnx("imsg_get error");
a5d10512
RW
1724 ret = CMD_WARNING;
1725 goto done;
eac6e3f0
RW
1726 }
1727 if (n == 0)
1728 break;
a5d10512
RW
1729 done = ldp_vty_dispatch_msg(vty, &imsg, cmd, params,
1730 json);
eac6e3f0
RW
1731 imsg_free(&imsg);
1732 }
1733 }
1734
a5d10512 1735 done:
eac6e3f0 1736 close(ibuf->fd);
a5d10512 1737 if (json) {
5c7571d4 1738 vty_out (vty, "%s\n",
96ade3ed 1739 json_object_to_json_string_ext(json, JSON_C_TO_STRING_PRETTY));
a5d10512
RW
1740 json_object_free(json);
1741 }
eac6e3f0 1742
a5d10512 1743 return (ret);
eac6e3f0
RW
1744}
1745
1746static int
1747ldp_vty_get_af(const char *str, int *af)
1748{
1749 if (str == NULL) {
1750 *af = AF_UNSPEC;
1751 return (0);
1752 } else if (strcmp(str, "ipv4") == 0) {
1753 *af = AF_INET;
1754 return (0);
1755 } else if (strcmp(str, "ipv6") == 0) {
1756 *af = AF_INET6;
1757 return (0);
1758 }
1759
1760 return (-1);
1761}
1762
1763int
f0722791
RW
1764ldp_vty_show_binding(struct vty *vty, const char *af_str, const char *prefix,
1765 int longer_prefixes, const char *neighbor, unsigned long local_label,
1766 unsigned long remote_label, const char *detail, const char *json)
eac6e3f0
RW
1767{
1768 struct imsgbuf ibuf;
a5d10512 1769 struct show_params params;
eac6e3f0
RW
1770 int af;
1771
1772 if (ldp_vty_connect(&ibuf) < 0)
1773 return (CMD_WARNING);
1774
eac6e3f0
RW
1775 if (ldp_vty_get_af(af_str, &af) < 0)
1776 return (CMD_ERR_NO_MATCH);
1777
a5d10512
RW
1778 memset(&params, 0, sizeof(params));
1779 params.family = af;
1224e5c4
RW
1780 params.detail = (detail) ? 1 : 0;
1781 params.json = (json) ? 1 : 0;
f0722791
RW
1782 if (prefix) {
1783 (void)str2prefix(prefix, &params.lib.prefix);
1784 params.lib.longer_prefixes = longer_prefixes;
1785 }
1786 if (neighbor &&
1787 (inet_pton(AF_INET, neighbor, &params.lib.neighbor) != 1 ||
1788 bad_addr_v4(params.lib.neighbor))) {
1789 vty_out (vty, "%% Malformed address\n");
1790 return (CMD_SUCCESS);
1791 }
1792 params.lib.local_label = local_label;
1793 params.lib.remote_label = remote_label;
eac6e3f0 1794
bc0eb287 1795 if (!params.detail && !params.json)
5c7571d4 1796 vty_out (vty, "%-4s %-20s %-15s %-11s %-13s %6s\n", "AF",
bc0eb287 1797 "Destination", "Nexthop", "Local Label", "Remote Label",
96ade3ed 1798 "In Use");
bc0eb287 1799
a5d10512
RW
1800 imsg_compose(&ibuf, IMSG_CTL_SHOW_LIB, 0, 0, -1, NULL, 0);
1801 return (ldp_vty_dispatch(vty, &ibuf, SHOW_LIB, &params));
eac6e3f0
RW
1802}
1803
1804int
1224e5c4
RW
1805ldp_vty_show_discovery(struct vty *vty, const char *af_str, const char *detail,
1806 const char *json)
eac6e3f0
RW
1807{
1808 struct imsgbuf ibuf;
a5d10512 1809 struct show_params params;
eac6e3f0
RW
1810 int af;
1811
1812 if (ldp_vty_connect(&ibuf) < 0)
1813 return (CMD_WARNING);
1814
eac6e3f0
RW
1815 if (ldp_vty_get_af(af_str, &af) < 0)
1816 return (CMD_ERR_NO_MATCH);
1817
a5d10512
RW
1818 memset(&params, 0, sizeof(params));
1819 params.family = af;
1224e5c4
RW
1820 params.detail = (detail) ? 1 : 0;
1821 params.json = (json) ? 1 : 0;
eac6e3f0 1822
bc0eb287 1823 if (!params.detail && !params.json)
5c7571d4 1824 vty_out (vty, "%-4s %-15s %-8s %-15s %9s\n",
96ade3ed 1825 "AF", "ID", "Type", "Source", "Holdtime");
bc0eb287
RW
1826
1827 if (params.detail)
1828 imsg_compose(&ibuf, IMSG_CTL_SHOW_DISCOVERY_DTL, 0, 0, -1,
1829 NULL, 0);
1830 else
1831 imsg_compose(&ibuf, IMSG_CTL_SHOW_DISCOVERY, 0, 0, -1, NULL, 0);
a5d10512 1832 return (ldp_vty_dispatch(vty, &ibuf, SHOW_DISC, &params));
eac6e3f0
RW
1833}
1834
1835int
1224e5c4 1836ldp_vty_show_interface(struct vty *vty, const char *af_str, const char *json)
eac6e3f0
RW
1837{
1838 struct imsgbuf ibuf;
a5d10512 1839 struct show_params params;
eac6e3f0 1840 unsigned int ifidx = 0;
eac6e3f0
RW
1841 int af;
1842
1843 if (ldp_vty_connect(&ibuf) < 0)
1844 return (CMD_WARNING);
1845
eac6e3f0
RW
1846 if (ldp_vty_get_af(af_str, &af) < 0)
1847 return (CMD_ERR_NO_MATCH);
1848
a5d10512
RW
1849 memset(&params, 0, sizeof(params));
1850 params.family = af;
1224e5c4 1851 params.json = (json) ? 1 : 0;
eac6e3f0
RW
1852
1853 /* header */
a5d10512 1854 if (!params.json) {
5c7571d4 1855 vty_out (vty, "%-4s %-11s %-6s %-8s %-12s %3s\n", "AF",
96ade3ed 1856 "Interface", "State", "Uptime", "Hello Timers","ac");
a5d10512 1857 }
eac6e3f0 1858
a5d10512
RW
1859 imsg_compose(&ibuf, IMSG_CTL_SHOW_INTERFACE, 0, 0, -1, &ifidx,
1860 sizeof(ifidx));
1861 return (ldp_vty_dispatch(vty, &ibuf, SHOW_IFACE, &params));
eac6e3f0
RW
1862}
1863
99cfc17f 1864int
1224e5c4 1865ldp_vty_show_capabilities(struct vty *vty, const char *json)
99cfc17f 1866{
c740f7d3 1867 if (json) {
99cfc17f
RW
1868 json_object *json;
1869 json_object *json_array;
1870 json_object *json_cap;
1871
1872 json = json_object_new_object();
1873 json_array = json_object_new_array();
1874 json_object_object_add(json, "capabilities", json_array);
1875
1876 /* Dynamic Announcement (0x0506) */
1877 json_cap = json_object_new_object();
1878 json_object_string_add(json_cap, "description",
1879 "Dynamic Announcement");
1880 json_object_string_add(json_cap, "tlvType",
1881 "0x0506");
1882 json_object_array_add(json_array, json_cap);
1883
1884 /* Typed Wildcard (0x050B) */
1885 json_cap = json_object_new_object();
1886 json_object_string_add(json_cap, "description",
1887 "Typed Wildcard");
1888 json_object_string_add(json_cap, "tlvType",
1889 "0x050B");
1890 json_object_array_add(json_array, json_cap);
1891
1892 /* Unrecognized Notification (0x0603) */
1893 json_cap = json_object_new_object();
1894 json_object_string_add(json_cap, "description",
1895 "Unrecognized Notification");
1896 json_object_string_add(json_cap, "tlvType",
1897 "0x0603");
1898 json_object_array_add(json_array, json_cap);
1899
5c7571d4 1900 vty_out (vty, "%s\n",
96ade3ed 1901 json_object_to_json_string_ext(json, JSON_C_TO_STRING_PRETTY));
99cfc17f
RW
1902 json_object_free(json);
1903 return (0);
1904 }
1905
181039f3 1906 vty_out (vty,
625e016d
DL
1907 "Supported LDP Capabilities\n"
1908 " * Dynamic Announcement (0x0506)\n"
1909 " * Typed Wildcard (0x050B)\n"
1910 " * Unrecognized Notification (0x0603)\n\n");
99cfc17f
RW
1911
1912 return (0);
1913}
1914
eac6e3f0 1915int
f0722791
RW
1916ldp_vty_show_neighbor(struct vty *vty, const char *lsr_id, int capabilities,
1917 const char *detail, const char *json)
eac6e3f0
RW
1918{
1919 struct imsgbuf ibuf;
a5d10512 1920 struct show_params params;
eac6e3f0
RW
1921
1922 if (ldp_vty_connect(&ibuf) < 0)
1923 return (CMD_WARNING);
1924
a5d10512 1925 memset(&params, 0, sizeof(params));
1224e5c4
RW
1926 params.detail = (detail) ? 1 : 0;
1927 params.json = (json) ? 1 : 0;
f0722791
RW
1928 params.neighbor.capabilities = capabilities;
1929 if (lsr_id &&
1930 (inet_pton(AF_INET, lsr_id, &params.neighbor.lsr_id) != 1 ||
1931 bad_addr_v4(params.neighbor.lsr_id))) {
1932 vty_out (vty, "%% Malformed address\n");
1933 return (CMD_SUCCESS);
1934 }
eac6e3f0 1935
f0722791 1936 if (params.neighbor.capabilities)
99cfc17f
RW
1937 params.detail = 1;
1938
bc0eb287 1939 if (!params.detail && !params.json)
5c7571d4 1940 vty_out (vty, "%-4s %-15s %-11s %-15s %8s\n",
96ade3ed 1941 "AF", "ID", "State", "Remote Address","Uptime");
bc0eb287 1942
a5d10512
RW
1943 imsg_compose(&ibuf, IMSG_CTL_SHOW_NBR, 0, 0, -1, NULL, 0);
1944 return (ldp_vty_dispatch(vty, &ibuf, SHOW_NBR, &params));
eac6e3f0
RW
1945}
1946
1947int
f0722791
RW
1948ldp_vty_show_atom_binding(struct vty *vty, const char *peer,
1949 unsigned long local_label, unsigned long remote_label, const char *json)
eac6e3f0
RW
1950{
1951 struct imsgbuf ibuf;
a5d10512 1952 struct show_params params;
eac6e3f0
RW
1953
1954 if (ldp_vty_connect(&ibuf) < 0)
1955 return (CMD_WARNING);
1956
a5d10512 1957 memset(&params, 0, sizeof(params));
1224e5c4 1958 params.json = (json) ? 1 : 0;
f0722791
RW
1959 if (peer &&
1960 (inet_pton(AF_INET, peer, &params.l2vpn.peer) != 1 ||
1961 bad_addr_v4(params.l2vpn.peer))) {
1962 vty_out (vty, "%% Malformed address\n");
1963 return (CMD_SUCCESS);
1964 }
1965 params.l2vpn.local_label = local_label;
1966 params.l2vpn.remote_label = remote_label;
eac6e3f0 1967
a5d10512
RW
1968 imsg_compose(&ibuf, IMSG_CTL_SHOW_L2VPN_BINDING, 0, 0, -1, NULL, 0);
1969 return (ldp_vty_dispatch(vty, &ibuf, SHOW_L2VPN_BINDING, &params));
eac6e3f0
RW
1970}
1971
1972int
f0722791
RW
1973ldp_vty_show_atom_vc(struct vty *vty, const char *peer, const char *ifname,
1974 const char *vcid, const char *json)
eac6e3f0
RW
1975{
1976 struct imsgbuf ibuf;
a5d10512 1977 struct show_params params;
eac6e3f0
RW
1978
1979 if (ldp_vty_connect(&ibuf) < 0)
1980 return (CMD_WARNING);
1981
a5d10512 1982 memset(&params, 0, sizeof(params));
1224e5c4 1983 params.json = (json) ? 1 : 0;
f0722791
RW
1984 if (peer &&
1985 (inet_pton(AF_INET, peer, &params.l2vpn.peer) != 1 ||
1986 bad_addr_v4(params.l2vpn.peer))) {
1987 vty_out (vty, "%% Malformed address\n");
1988 return (CMD_SUCCESS);
1989 }
1990 if (ifname)
1991 strlcpy(params.l2vpn.ifname, ifname,
1992 sizeof(params.l2vpn.ifname));
1993 if (vcid)
1994 params.l2vpn.vcid = atoi(vcid);
a5d10512
RW
1995
1996 if (!params.json) {
1997 /* header */
5c7571d4 1998 vty_out (vty, "%-9s %-15s %-10s %-16s %-10s\n",
96ade3ed 1999 "Interface", "Peer ID", "VC ID", "Name","Status");
5c7571d4 2000 vty_out (vty, "%-9s %-15s %-10s %-16s %-10s\n",
a5d10512 2001 "---------", "---------------", "----------",
96ade3ed 2002 "----------------", "----------");
a5d10512 2003 }
eac6e3f0 2004
a5d10512
RW
2005 imsg_compose(&ibuf, IMSG_CTL_SHOW_L2VPN_PW, 0, 0, -1, NULL, 0);
2006 return (ldp_vty_dispatch(vty, &ibuf, SHOW_L2VPN_PW, &params));
eac6e3f0
RW
2007}
2008
2009int
c740f7d3 2010ldp_vty_clear_nbr(struct vty *vty, const char *addr_str)
eac6e3f0
RW
2011{
2012 struct imsgbuf ibuf;
eac6e3f0
RW
2013 struct ctl_nbr nbr;
2014
eac6e3f0
RW
2015 memset(&nbr, 0, sizeof(nbr));
2016 if (addr_str &&
2017 (ldp_get_address(addr_str, &nbr.af, &nbr.raddr) == -1 ||
2018 bad_addr(nbr.af, &nbr.raddr))) {
5c7571d4 2019 vty_out (vty, "%% Malformed address\n");
eac6e3f0
RW
2020 return (CMD_WARNING);
2021 }
2022
2023 if (ldp_vty_connect(&ibuf) < 0)
2024 return (CMD_WARNING);
2025
2026 imsg_compose(&ibuf, IMSG_CTL_CLEAR_NBR, 0, 0, -1, &nbr, sizeof(nbr));
2027
2028 while (ibuf.w.queued)
2029 if (msgbuf_write(&ibuf.w) <= 0 && errno != EAGAIN) {
2030 log_warn("write error");
2031 close(ibuf.fd);
2032 return (CMD_WARNING);
2033 }
2034
2035 close(ibuf.fd);
2036
2037 return (CMD_SUCCESS);
2038}