]> git.proxmox.com Git - mirror_frr.git/blame - ldpd/ldp_vty_exec.c
Merge pull request #5412 from opensourcerouting/bfdd-vrf-fix
[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
196 sprintf(key_name, "%s: %s", iface->name, af_name(iface->af));
197 json_object_object_add(json, key_name, json_iface);
198 break;
199 case IMSG_CTL_END:
200 return (1);
201 default:
202 break;
203 }
204
205 return (0);
206}
207
bc0eb287
RW
208static int
209show_discovery_msg(struct vty *vty, struct imsg *imsg,
210 struct show_params *params)
211{
212 struct ctl_adj *adj;
213 const char *addr;
214
215 switch (imsg->hdr.type) {
216 case IMSG_CTL_SHOW_DISCOVERY:
217 adj = imsg->data;
218
219 if (params->family != AF_UNSPEC && params->family != adj->af)
220 break;
221
222 vty_out(vty, "%-4s %-15s ", af_name(adj->af),
223 inet_ntoa(adj->id));
224 switch(adj->type) {
225 case HELLO_LINK:
226 vty_out(vty, "%-8s %-15s ", "Link", adj->ifname);
227 break;
228 case HELLO_TARGETED:
229 addr = log_addr(adj->af, &adj->src_addr);
230
231 vty_out(vty, "%-8s %-15s ", "Targeted", addr);
232 if (strlen(addr) > 15)
61b7d449 233 vty_out(vty, "\n%46s", " ");
bc0eb287
RW
234 break;
235 }
5c7571d4 236 vty_out (vty, "%9u\n", adj->holdtime);
bc0eb287
RW
237 break;
238 case IMSG_CTL_END:
6d3c2ed4 239 vty_out (vty, "\n");
bc0eb287
RW
240 return (1);
241 default:
242 break;
243 }
244
245 return (0);
246}
247
eac6e3f0 248static void
bc0eb287 249show_discovery_detail_adj(struct vty *vty, char *buffer, struct ctl_adj *adj)
eac6e3f0
RW
250{
251 size_t buflen = strlen(buffer);
a5d10512
RW
252
253 snprintf(buffer + buflen, LDPBUFSIZ - buflen,
625e016d 254 " LSR Id: %s:0\n", inet_ntoa(adj->id));
0f7b5df9
RW
255 buflen = strlen(buffer);
256 snprintf(buffer + buflen, LDPBUFSIZ - buflen,
625e016d
DL
257 " Source address: %s\n",
258 log_addr(adj->af, &adj->src_addr));
0f7b5df9
RW
259 buflen = strlen(buffer);
260 snprintf(buffer + buflen, LDPBUFSIZ - buflen,
625e016d
DL
261 " Transport address: %s\n",
262 log_addr(adj->af, &adj->trans_addr));
0f7b5df9
RW
263 buflen = strlen(buffer);
264 snprintf(buffer + buflen, LDPBUFSIZ - buflen,
625e016d
DL
265 " Hello hold time: %u secs (due in %u secs)\n",
266 adj->holdtime, adj->holdtime_remaining);
a5d10512
RW
267 buflen = strlen(buffer);
268 snprintf(buffer + buflen, LDPBUFSIZ - buflen,
625e016d
DL
269 " Dual-stack capability TLV: %s\n",
270 (adj->ds_tlv) ? "yes" : "no");
eac6e3f0
RW
271}
272
273static int
bc0eb287 274show_discovery_detail_msg(struct vty *vty, struct imsg *imsg,
a5d10512 275 struct show_params *params)
eac6e3f0
RW
276{
277 struct ctl_adj *adj;
278 struct ctl_disc_if *iface;
279 struct ctl_disc_tnbr *tnbr;
280 struct in_addr rtr_id;
281 union ldpd_addr *trans_addr;
282 size_t buflen;
283 static char ifaces_buffer[LDPBUFSIZ];
284 static char tnbrs_buffer[LDPBUFSIZ];
285
286 switch (imsg->hdr.type) {
287 case IMSG_CTL_SHOW_DISCOVERY:
288 ifaces_buffer[0] = '\0';
289 tnbrs_buffer[0] = '\0';
290 break;
291 case IMSG_CTL_SHOW_DISC_IFACE:
292 iface = imsg->data;
293
a5d10512
RW
294 if (params->family != AF_UNSPEC &&
295 ((params->family == AF_INET && !iface->active_v4) ||
296 (params->family == AF_INET6 && !iface->active_v6)))
eac6e3f0
RW
297 break;
298
a5d10512
RW
299 buflen = strlen(ifaces_buffer);
300 snprintf(ifaces_buffer + buflen, LDPBUFSIZ - buflen,
625e016d
DL
301 " %s: %s\n", iface->name, (iface->no_adj) ?
302 "(no adjacencies)" : "");
a5d10512
RW
303 break;
304 case IMSG_CTL_SHOW_DISC_TNBR:
305 tnbr = imsg->data;
e8dbef04 306
a5d10512
RW
307 if (params->family != AF_UNSPEC && params->family != tnbr->af)
308 break;
e8dbef04 309
a5d10512
RW
310 trans_addr = &(ldp_af_conf_get(ldpd_conf,
311 tnbr->af))->trans_addr;
312 buflen = strlen(tnbrs_buffer);
313 snprintf(tnbrs_buffer + buflen, LDPBUFSIZ - buflen,
625e016d 314 " %s -> %s: %s\n", log_addr(tnbr->af, trans_addr),
0f7b5df9 315 log_addr(tnbr->af, &tnbr->addr), (tnbr->no_adj) ?
625e016d 316 "(no adjacencies)" : "");
a5d10512
RW
317 break;
318 case IMSG_CTL_SHOW_DISC_ADJ:
319 adj = imsg->data;
e8dbef04 320
a5d10512
RW
321 if (params->family != AF_UNSPEC && params->family != adj->af)
322 break;
e8dbef04 323
a5d10512
RW
324 switch(adj->type) {
325 case HELLO_LINK:
bc0eb287 326 show_discovery_detail_adj(vty, ifaces_buffer, adj);
a5d10512
RW
327 break;
328 case HELLO_TARGETED:
bc0eb287 329 show_discovery_detail_adj(vty, tnbrs_buffer, adj);
a5d10512
RW
330 break;
331 }
332 break;
333 case IMSG_CTL_END:
334 rtr_id.s_addr = ldp_rtr_id_get(ldpd_conf);
5c7571d4
DL
335 vty_out (vty, "Local:\n");
336 vty_out (vty, " LSR Id: %s:0\n",inet_ntoa(rtr_id));
0f7b5df9 337 if (ldpd_conf->ipv4.flags & F_LDPD_AF_ENABLED)
5c7571d4 338 vty_out (vty, " Transport Address (IPv4): %s\n",
96ade3ed 339 log_addr(AF_INET, &ldpd_conf->ipv4.trans_addr));
0f7b5df9 340 if (ldpd_conf->ipv6.flags & F_LDPD_AF_ENABLED)
5c7571d4 341 vty_out (vty, " Transport Address (IPv6): %s\n",
96ade3ed 342 log_addr(AF_INET6, &ldpd_conf->ipv6.trans_addr));
5c7571d4
DL
343 vty_out (vty, "Discovery Sources:\n");
344 vty_out (vty, " Interfaces:\n");
a5d10512 345 vty_out(vty, "%s", ifaces_buffer);
5c7571d4 346 vty_out (vty, " Targeted Hellos:\n");
a5d10512 347 vty_out(vty, "%s", tnbrs_buffer);
6d3c2ed4 348 vty_out (vty, "\n");
a5d10512
RW
349 return (1);
350 default:
351 break;
352 }
e8dbef04 353
a5d10512
RW
354 return (0);
355}
356
bc0eb287
RW
357static int
358show_discovery_msg_json(struct imsg *imsg, struct show_params *params,
359 json_object *json)
360{
361 struct ctl_adj *adj;
362 json_object *json_array;
363 json_object *json_adj;
364
365 switch (imsg->hdr.type) {
366 case IMSG_CTL_SHOW_DISCOVERY:
367 adj = imsg->data;
368
369 if (params->family != AF_UNSPEC && params->family != adj->af)
370 break;
371
372 json_object_object_get_ex(json, "adjacencies", &json_array);
373 if (!json_array) {
374 json_array = json_object_new_array();
375 json_object_object_add(json, "adjacencies", json_array);
376 }
377
378 json_adj = json_object_new_object();
379 json_object_string_add(json_adj, "addressFamily",
380 af_name(adj->af));
381 json_object_string_add(json_adj, "neighborId",
382 inet_ntoa(adj->id));
383 switch(adj->type) {
384 case HELLO_LINK:
385 json_object_string_add(json_adj, "type", "link");
386 json_object_string_add(json_adj, "interface",
387 adj->ifname);
388 break;
389 case HELLO_TARGETED:
390 json_object_string_add(json_adj, "type", "targeted");
391 json_object_string_add(json_adj, "peer",
392 log_addr(adj->af, &adj->src_addr));
393 break;
394 }
395 json_object_int_add(json_adj, "helloHoldtime", adj->holdtime);
396
397 json_object_array_add(json_array, json_adj);
398 break;
399 case IMSG_CTL_END:
400 return (1);
401 default:
402 break;
403 }
404
405 return (0);
406}
407
a5d10512 408static void
bc0eb287 409show_discovery_detail_adj_json(json_object *json, struct ctl_adj *adj)
a5d10512
RW
410{
411 json_object *json_adj;
412 json_object *json_array;
413
414 json_object_object_get_ex(json, "adjacencies", &json_array);
415 if (!json_array) {
416 json_array = json_object_new_array();
417 json_object_object_add(json, "adjacencies", json_array);
418 }
419
420 json_adj = json_object_new_object();
0f7b5df9
RW
421 json_object_string_add(json_adj, "lsrId", inet_ntoa(adj->id));
422 json_object_string_add(json_adj, "sourceAddress", log_addr(adj->af,
423 &adj->src_addr));
a5d10512
RW
424 json_object_string_add(json_adj, "transportAddress", log_addr(adj->af,
425 &adj->trans_addr));
0f7b5df9
RW
426 json_object_int_add(json_adj, "helloHoldtime", adj->holdtime);
427 json_object_int_add(json_adj, "helloHoldtimeRemaining",
428 adj->holdtime_remaining);
429 json_object_int_add(json_adj, "dualStackCapabilityTlv",
430 adj->ds_tlv);
a5d10512
RW
431 json_object_array_add(json_array, json_adj);
432}
433
434static int
bc0eb287 435show_discovery_detail_msg_json(struct imsg *imsg, struct show_params *params,
a5d10512
RW
436 json_object *json)
437{
438 struct ctl_adj *adj;
439 struct ctl_disc_if *iface;
440 struct ctl_disc_tnbr *tnbr;
441 struct in_addr rtr_id;
442 union ldpd_addr *trans_addr;
443 json_object *json_interface;
444 json_object *json_target;
445 static json_object *json_interfaces;
446 static json_object *json_targets;
447 static json_object *json_container;
448
449 switch (imsg->hdr.type) {
450 case IMSG_CTL_SHOW_DISCOVERY:
451 rtr_id.s_addr = ldp_rtr_id_get(ldpd_conf);
0f7b5df9
RW
452 json_object_string_add(json, "lsrId", inet_ntoa(rtr_id));
453 if (ldpd_conf->ipv4.flags & F_LDPD_AF_ENABLED)
454 json_object_string_add(json, "transportAddressIPv4",
455 log_addr(AF_INET, &ldpd_conf->ipv4.trans_addr));
456 if (ldpd_conf->ipv6.flags & F_LDPD_AF_ENABLED)
457 json_object_string_add(json, "transportAddressIPv6",
458 log_addr(AF_INET6, &ldpd_conf->ipv6.trans_addr));
a5d10512
RW
459 json_interfaces = json_object_new_object();
460 json_object_object_add(json, "interfaces", json_interfaces);
461 json_targets = json_object_new_object();
462 json_object_object_add(json, "targetedHellos", json_targets);
463 json_container = NULL;
eac6e3f0 464 break;
a5d10512
RW
465 case IMSG_CTL_SHOW_DISC_IFACE:
466 iface = imsg->data;
eac6e3f0 467
a5d10512
RW
468 if (params->family != AF_UNSPEC &&
469 ((params->family == AF_INET && !iface->active_v4) ||
470 (params->family == AF_INET6 && !iface->active_v6)))
eac6e3f0
RW
471 break;
472
a5d10512 473 json_interface = json_object_new_object();
a5d10512
RW
474 json_object_object_add(json_interfaces, iface->name,
475 json_interface);
476 json_container = json_interface;
477 break;
478 case IMSG_CTL_SHOW_DISC_TNBR:
479 tnbr = imsg->data;
e8dbef04 480
a5d10512
RW
481 if (params->family != AF_UNSPEC && params->family != tnbr->af)
482 break;
e8dbef04 483
a5d10512 484 trans_addr = &(ldp_af_conf_get(ldpd_conf, tnbr->af))->trans_addr;
e8dbef04 485
a5d10512
RW
486 json_target = json_object_new_object();
487 json_object_string_add(json_target, "sourceAddress",
488 log_addr(tnbr->af, trans_addr));
a5d10512
RW
489 json_object_object_add(json_targets, log_addr(tnbr->af,
490 &tnbr->addr), json_target);
491 json_container = json_target;
eac6e3f0
RW
492 break;
493 case IMSG_CTL_SHOW_DISC_ADJ:
494 adj = imsg->data;
495
a5d10512 496 if (params->family != AF_UNSPEC && params->family != adj->af)
eac6e3f0
RW
497 break;
498
499 switch(adj->type) {
500 case HELLO_LINK:
bc0eb287 501 show_discovery_detail_adj_json(json_container, adj);
eac6e3f0
RW
502 break;
503 case HELLO_TARGETED:
bc0eb287 504 show_discovery_detail_adj_json(json_container, adj);
eac6e3f0
RW
505 break;
506 }
507 break;
508 case IMSG_CTL_END:
a5d10512 509 return (1);
eac6e3f0
RW
510 default:
511 break;
512 }
513
514 return (0);
515}
516
bc0eb287
RW
517static int
518show_nbr_msg(struct vty *vty, struct imsg *imsg, struct show_params *params)
519{
520 struct ctl_nbr *nbr;
521 const char *addr;
522
523 switch (imsg->hdr.type) {
524 case IMSG_CTL_SHOW_NBR:
525 nbr = imsg->data;
526
527 addr = log_addr(nbr->af, &nbr->raddr);
528
529 vty_out(vty, "%-4s %-15s %-11s %-15s",
530 af_name(nbr->af), inet_ntoa(nbr->id),
531 nbr_state_name(nbr->nbr_state), addr);
532 if (strlen(addr) > 15)
61b7d449 533 vty_out(vty, "\n%48s", " ");
5c7571d4 534 vty_out (vty, " %8s\n", log_time(nbr->uptime));
bc0eb287
RW
535 break;
536 case IMSG_CTL_END:
537 return (1);
538 default:
539 break;
540 }
541
542 return (0);
543}
544
eac6e3f0 545static void
bc0eb287 546show_nbr_detail_adj(struct vty *vty, char *buffer, struct ctl_adj *adj)
eac6e3f0
RW
547{
548 size_t buflen = strlen(buffer);
549
550 switch (adj->type) {
551 case HELLO_LINK:
a5d10512 552 snprintf(buffer + buflen, LDPBUFSIZ - buflen,
625e016d 553 " Interface: %s\n", adj->ifname);
eac6e3f0
RW
554 break;
555 case HELLO_TARGETED:
a5d10512 556 snprintf(buffer + buflen, LDPBUFSIZ - buflen,
625e016d
DL
557 " Targeted Hello: %s\n", log_addr(adj->af,
558 &adj->src_addr));
eac6e3f0
RW
559 break;
560 }
561}
562
563static int
0f7b5df9
RW
564show_nbr_detail_msg(struct vty *vty, struct imsg *imsg,
565 struct show_params *params)
eac6e3f0 566{
eac6e3f0 567 struct ctl_nbr *nbr;
0f7b5df9 568 struct ldp_stats *stats;
a5d10512 569 struct ctl_adj *adj;
eac6e3f0
RW
570 static char v4adjs_buffer[LDPBUFSIZ];
571 static char v6adjs_buffer[LDPBUFSIZ];
572
573 switch (imsg->hdr.type) {
574 case IMSG_CTL_SHOW_NBR:
575 nbr = imsg->data;
576
a5d10512
RW
577 v4adjs_buffer[0] = '\0';
578 v6adjs_buffer[0] = '\0';
5c7571d4 579 vty_out (vty, "Peer LDP Identifier: %s:0\n",
96ade3ed 580 inet_ntoa(nbr->id));
5c7571d4 581 vty_out (vty, " TCP connection: %s:%u - %s:%u\n",
a5d10512 582 log_addr(nbr->af, &nbr->laddr), ntohs(nbr->lport),
96ade3ed 583 log_addr(nbr->af, &nbr->raddr),ntohs(nbr->rport));
5c7571d4 584 vty_out (vty, " Authentication: %s\n",
96ade3ed 585 (nbr->auth_method == AUTH_MD5SIG) ? "TCP MD5 Signature" : "none");
181039f3
DL
586 vty_out(vty, " Session Holdtime: %u secs; "
587 "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);
181039f3
DL
1254 vty_out (vty, "%-8sCbit: %u, VC Type: %s, "
1255 "GroupID: %u\n", "", pw->local_cword,
96ade3ed 1256 pw_type_name(pw->type),pw->local_gid);
5c7571d4 1257 vty_out (vty, "%-8sMTU: %u\n", "",pw->local_ifmtu);
eac6e3f0 1258 } else
5c7571d4 1259 vty_out (vty," Local Label: unassigned\n");
eac6e3f0
RW
1260
1261 /* remote binding */
1262 if (pw->remote_label != NO_LABEL) {
5c7571d4 1263 vty_out (vty, " Remote Label: %u\n",
96ade3ed 1264 pw->remote_label);
181039f3
DL
1265 vty_out (vty, "%-8sCbit: %u, VC Type: %s, "
1266 "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);
1311 } else
1312 json_object_string_add(json_pw, "localLabel",
1313 "unassigned");
1314
1315 /* remote binding */
1316 if (pw->remote_label != NO_LABEL) {
1317 json_object_int_add(json_pw, "remoteLabel",
1318 pw->remote_label);
1319 json_object_int_add(json_pw, "remoteControlWord",
1320 pw->remote_cword);
1321 json_object_string_add(json_pw, "remoteVcType",
1322 pw_type_name(pw->type));
1323 json_object_int_add(json_pw, "remoteGroupID",
1324 pw->remote_gid);
1325 json_object_int_add(json_pw, "remoteIfMtu",
1326 pw->remote_ifmtu);
1327 } else
1328 json_object_string_add(json_pw, "remoteLabel",
1329 "unassigned");
1330
1331 sprintf(key_name, "%s: %u", inet_ntoa(pw->lsr_id), pw->pwid);
1332 json_object_object_add(json, key_name, json_pw);
1333 break;
1334 case IMSG_CTL_END:
1335 return (1);
1336 default:
1337 break;
1338 }
1339
1340 return (0);
1341}
1342
1343static int
1344show_l2vpn_pw_msg(struct vty *vty, struct imsg *imsg, struct show_params *params)
eac6e3f0
RW
1345{
1346 struct ctl_pw *pw;
1347
1348 switch (imsg->hdr.type) {
1349 case IMSG_CTL_SHOW_L2VPN_PW:
1350 pw = imsg->data;
1351
5c7571d4 1352 vty_out (vty, "%-9s %-15s %-10u %-16s %-10s\n", pw->ifname,
eac6e3f0 1353 inet_ntoa(pw->lsr_id), pw->pwid, pw->l2vpn_name,
96ade3ed 1354 (pw->status ? "UP" : "DOWN"));
eac6e3f0
RW
1355 break;
1356 case IMSG_CTL_END:
6d3c2ed4 1357 vty_out (vty, "\n");
eac6e3f0
RW
1358 return (1);
1359 default:
1360 break;
1361 }
1362
1363 return (0);
1364}
1365
a5d10512
RW
1366static int
1367show_l2vpn_pw_msg_json(struct imsg *imsg, struct show_params *params,
1368 json_object *json)
1369{
1370 struct ctl_pw *pw;
1371 json_object *json_pw;
1372
1373 switch (imsg->hdr.type) {
1374 case IMSG_CTL_SHOW_L2VPN_PW:
1375 pw = imsg->data;
1376
1377 json_pw = json_object_new_object();
1378 json_object_string_add(json_pw, "peerId", inet_ntoa(pw->lsr_id));
1379 json_object_int_add(json_pw, "vcId", pw->pwid);
1380 json_object_string_add(json_pw, "VpnName", pw->l2vpn_name);
1381 if (pw->status)
1382 json_object_string_add(json_pw, "status", "up");
1383 else
1384 json_object_string_add(json_pw, "status", "down");
1385 json_object_object_add(json, pw->ifname, json_pw);
1386 break;
1387 case IMSG_CTL_END:
1388 return (1);
1389 default:
1390 break;
1391 }
1392
1393 return (0);
1394}
1395
eac6e3f0
RW
1396static int
1397ldp_vty_connect(struct imsgbuf *ibuf)
1398{
1399 struct sockaddr_un s_un;
1400 int ctl_sock;
1401
1402 /* connect to ldpd control socket */
1403 if ((ctl_sock = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) {
1404 log_warn("%s: socket", __func__);
1405 return (-1);
1406 }
1407
1408 memset(&s_un, 0, sizeof(s_un));
1409 s_un.sun_family = AF_UNIX;
372b8bd3 1410 strlcpy(s_un.sun_path, ctl_sock_path, sizeof(s_un.sun_path));
eac6e3f0 1411 if (connect(ctl_sock, (struct sockaddr *)&s_un, sizeof(s_un)) == -1) {
372b8bd3 1412 log_warn("%s: connect: %s", __func__, ctl_sock_path);
eac6e3f0
RW
1413 close(ctl_sock);
1414 return (-1);
1415 }
1416
1417 imsg_init(ibuf, ctl_sock);
1418
1419 return (0);
1420}
1421
a5d10512 1422static int
f0722791 1423ldp_vty_dispatch_iface(struct vty *vty, struct imsg *imsg,
a5d10512
RW
1424 struct show_params *params, json_object *json)
1425{
bc0eb287
RW
1426 int ret;
1427
f0722791
RW
1428 if (params->json)
1429 ret = show_interface_msg_json(imsg, params, json);
1430 else
1431 ret = show_interface_msg(vty, imsg, params);
1432
1433 return (ret);
1434}
1435
1436static int
1437ldp_vty_dispatch_disc(struct vty *vty, struct imsg *imsg,
1438 struct show_params *params, json_object *json)
1439{
1440 int ret;
1441
1442 if (params->detail) {
bc0eb287 1443 if (params->json)
f0722791
RW
1444 ret = show_discovery_detail_msg_json(imsg, params,
1445 json);
bc0eb287 1446 else
f0722791
RW
1447 ret = show_discovery_detail_msg(vty, imsg, params);
1448 } else {
1449 if (params->json)
1450 ret = show_discovery_msg_json(imsg, params, json);
1451 else
1452 ret = show_discovery_msg(vty, imsg, params);
1453 }
1454
1455 return (ret);
1456}
1457
1458static int
1459ldp_vty_dispatch_nbr(struct vty *vty, struct imsg *imsg,
1460 struct show_params *params, json_object *json)
1461{
1462 static bool filtered = false;
1463 struct ctl_nbr *nbr;
1464 int ret;
1465
1466 switch (imsg->hdr.type) {
1467 case IMSG_CTL_SHOW_NBR:
1468 filtered = false;
1469 nbr = imsg->data;
1470
1471 if (params->neighbor.lsr_id.s_addr != INADDR_ANY &&
1472 params->neighbor.lsr_id.s_addr != nbr->id.s_addr) {
1473 filtered = true;
1474 return (0);
bc0eb287
RW
1475 }
1476 break;
f0722791
RW
1477 case IMSG_CTL_SHOW_NBR_DISC:
1478 case IMSG_CTL_SHOW_NBR_END:
1479 if (filtered)
1480 return (0);
bc0eb287 1481 break;
f0722791 1482 default:
bc0eb287 1483 break;
f0722791
RW
1484 }
1485
1486 if (params->neighbor.capabilities) {
bc0eb287 1487 if (params->json)
f0722791
RW
1488 ret = show_nbr_capabilities_msg_json(imsg, params,
1489 json);
bc0eb287 1490 else
f0722791
RW
1491 ret = show_nbr_capabilities_msg(vty, imsg, params);
1492 } else if (params->detail) {
1493 if (params->json)
1494 ret = show_nbr_detail_msg_json(imsg, params, json);
1495 else
1496 ret = show_nbr_detail_msg(vty, imsg, params);
1497 } else {
1498 if (params->json)
1499 ret = show_nbr_msg_json(imsg, params, json);
1500 else
1501 ret = show_nbr_msg(vty, imsg, params);
1502 }
1503
1504 return (ret);
1505}
1506
1507static int
1508ldp_vty_dispatch_lib(struct vty *vty, struct imsg *imsg,
1509 struct show_params *params, json_object *json)
1510{
1511 static bool filtered = false;
7f677840 1512 struct ctl_rt *rt = NULL;
f0722791
RW
1513 struct prefix prefix;
1514 int ret;
1515
1516 switch (imsg->hdr.type) {
1517 case IMSG_CTL_SHOW_LIB_BEGIN:
1518 filtered = false;
bc0eb287 1519 break;
f0722791
RW
1520 case IMSG_CTL_SHOW_LIB_SENT:
1521 case IMSG_CTL_SHOW_LIB_RCVD:
1522 case IMSG_CTL_SHOW_LIB_END:
1523 if (filtered)
1524 return (0);
1525 break;
1526 default:
1527 break;
1528 }
1529
1530 switch (imsg->hdr.type) {
1531 case IMSG_CTL_SHOW_LIB_BEGIN:
1532 case IMSG_CTL_SHOW_LIB_SENT:
1533 case IMSG_CTL_SHOW_LIB_RCVD:
1534 case IMSG_CTL_SHOW_LIB_END:
1535 rt = imsg->data;
1536
1537 if (params->family != AF_UNSPEC && params->family != rt->af) {
1538 filtered = true;
1539 return (0);
1540 }
1541
1542 prefix.family = rt->af;
1543 prefix.prefixlen = rt->prefixlen;
1544 memcpy(&prefix.u.val, &rt->prefix, sizeof(prefix.u.val));
1545 if (params->lib.prefix.family != AF_UNSPEC) {
1546 if (!params->lib.longer_prefixes &&
1547 !prefix_same(&params->lib.prefix, &prefix)) {
1548 filtered = true;
1549 return (0);
1550 } else if (params->lib.longer_prefixes &&
1551 !prefix_match(&params->lib.prefix, &prefix)) {
1552 filtered = true;
1553 return (0);
1554 }
1555 }
1556
1557 if (params->lib.local_label != NO_LABEL &&
1558 params->lib.local_label != rt->local_label) {
1559 filtered = true;
1560 return (0);
1561 }
1562 break;
1563 default:
1564 break;
1565 }
1566
1567 switch (imsg->hdr.type) {
1568 case IMSG_CTL_SHOW_LIB_SENT:
1569 case IMSG_CTL_SHOW_LIB_RCVD:
1570 if (params->lib.neighbor.s_addr != INADDR_ANY &&
1571 params->lib.neighbor.s_addr != rt->nexthop.s_addr)
1572 return (0);
1573 break;
1574 default:
1575 break;
1576 }
1577
1578 switch (imsg->hdr.type) {
1579 case IMSG_CTL_SHOW_LIB_RCVD:
1580 if (params->lib.remote_label != NO_LABEL &&
1581 params->lib.remote_label != rt->remote_label)
1582 return (0);
1583 break;
1584 default:
1585 break;
1586 }
1587
1588 if (params->detail) {
bc0eb287 1589 if (params->json)
f0722791 1590 ret = show_lib_detail_msg_json(imsg, params, json);
bc0eb287 1591 else
f0722791
RW
1592 ret = show_lib_detail_msg(vty, imsg, params);
1593 } else {
1594 if (params->json)
1595 ret = show_lib_msg_json(imsg, params, json);
1596 else
1597 ret = show_lib_msg(vty, imsg, params);
1598 }
1599
1600 return (ret);
1601}
1602
1603static int
1604ldp_vty_dispatch_l2vpn_pw(struct vty *vty, struct imsg *imsg,
1605 struct show_params *params, json_object *json)
1606{
1607 struct ctl_pw *pw;
1608 int ret;
1609
1610 switch (imsg->hdr.type) {
1611 case IMSG_CTL_SHOW_L2VPN_PW:
1612 pw = imsg->data;
1613 if (params->l2vpn.peer.s_addr != INADDR_ANY &&
1614 params->l2vpn.peer.s_addr != pw->lsr_id.s_addr)
1615 return (0);
1616 if (params->l2vpn.ifname[0] != '\0' &&
1617 strcmp(params->l2vpn.ifname, pw->ifname))
1618 return (0);
1619 if (params->l2vpn.vcid && params->l2vpn.vcid != pw->pwid)
1620 return (0);
bc0eb287 1621 break;
a5d10512 1622 default:
f0722791 1623 break;
a5d10512 1624 }
bc0eb287 1625
f0722791
RW
1626 if (params->json)
1627 ret = show_l2vpn_pw_msg_json(imsg, params, json);
1628 else
1629 ret = show_l2vpn_pw_msg(vty, imsg, params);
1630
bc0eb287 1631 return (ret);
a5d10512
RW
1632}
1633
f0722791
RW
1634static int
1635ldp_vty_dispatch_l2vpn_binding(struct vty *vty, struct imsg *imsg,
1636 struct show_params *params, json_object *json)
1637{
1638 struct ctl_pw *pw;
1639 int ret;
1640
1641 switch (imsg->hdr.type) {
1642 case IMSG_CTL_SHOW_L2VPN_BINDING:
1643 pw = imsg->data;
1644 if (params->l2vpn.peer.s_addr != INADDR_ANY &&
1645 params->l2vpn.peer.s_addr != pw->lsr_id.s_addr)
1646 return (0);
1647 if (params->l2vpn.local_label != NO_LABEL &&
1648 params->l2vpn.local_label != pw->local_label)
1649 return (0);
1650 if (params->l2vpn.remote_label != NO_LABEL &&
1651 params->l2vpn.remote_label != pw->remote_label)
1652 return (0);
1653 break;
1654 default:
1655 break;
1656 }
1657
1658 if (params->json)
1659 ret = show_l2vpn_binding_msg_json(imsg, params, json);
1660 else
1661 ret = show_l2vpn_binding_msg(vty, imsg, params);
1662
1663 return (ret);
1664}
1665
1666static int
1667ldp_vty_dispatch_msg(struct vty *vty, struct imsg *imsg, enum show_command cmd,
1668 struct show_params *params, json_object *json)
1669{
1670 switch (cmd) {
1671 case SHOW_IFACE:
1672 return (ldp_vty_dispatch_iface(vty, imsg, params, json));
1673 case SHOW_DISC:
1674 return (ldp_vty_dispatch_disc(vty, imsg, params, json));
1675 case SHOW_NBR:
1676 return (ldp_vty_dispatch_nbr(vty, imsg, params, json));
1677 case SHOW_LIB:
1678 return (ldp_vty_dispatch_lib(vty, imsg, params, json));
1679 case SHOW_L2VPN_PW:
1680 return (ldp_vty_dispatch_l2vpn_pw(vty, imsg, params, json));
1681 case SHOW_L2VPN_BINDING:
1682 return (ldp_vty_dispatch_l2vpn_binding(vty, imsg, params,
1683 json));
1684 default:
1685 return (0);
1686 }
1687}
1688
eac6e3f0
RW
1689static int
1690ldp_vty_dispatch(struct vty *vty, struct imsgbuf *ibuf, enum show_command cmd,
a5d10512 1691 struct show_params *params)
eac6e3f0
RW
1692{
1693 struct imsg imsg;
a5d10512
RW
1694 int n, done = 0, ret = CMD_SUCCESS;
1695 json_object *json = NULL;
eac6e3f0
RW
1696
1697 while (ibuf->w.queued)
1698 if (msgbuf_write(&ibuf->w) <= 0 && errno != EAGAIN) {
1699 log_warn("write error");
1700 close(ibuf->fd);
1701 return (CMD_WARNING);
1702 }
1703
a5d10512
RW
1704 if (params->json)
1705 json = json_object_new_object();
e8dbef04 1706
eac6e3f0
RW
1707 while (!done) {
1708 if ((n = imsg_read(ibuf)) == -1 && errno != EAGAIN) {
1709 log_warnx("imsg_read error");
a5d10512
RW
1710 ret = CMD_WARNING;
1711 goto done;
eac6e3f0
RW
1712 }
1713 if (n == 0) {
1714 log_warnx("pipe closed");
a5d10512
RW
1715 ret = CMD_WARNING;
1716 goto done;
eac6e3f0
RW
1717 }
1718
1719 while (!done) {
1720 if ((n = imsg_get(ibuf, &imsg)) == -1) {
1721 log_warnx("imsg_get error");
a5d10512
RW
1722 ret = CMD_WARNING;
1723 goto done;
eac6e3f0
RW
1724 }
1725 if (n == 0)
1726 break;
a5d10512
RW
1727 done = ldp_vty_dispatch_msg(vty, &imsg, cmd, params,
1728 json);
eac6e3f0
RW
1729 imsg_free(&imsg);
1730 }
1731 }
1732
a5d10512 1733 done:
eac6e3f0 1734 close(ibuf->fd);
a5d10512 1735 if (json) {
5c7571d4 1736 vty_out (vty, "%s\n",
96ade3ed 1737 json_object_to_json_string_ext(json, JSON_C_TO_STRING_PRETTY));
a5d10512
RW
1738 json_object_free(json);
1739 }
eac6e3f0 1740
a5d10512 1741 return (ret);
eac6e3f0
RW
1742}
1743
1744static int
1745ldp_vty_get_af(const char *str, int *af)
1746{
1747 if (str == NULL) {
1748 *af = AF_UNSPEC;
1749 return (0);
1750 } else if (strcmp(str, "ipv4") == 0) {
1751 *af = AF_INET;
1752 return (0);
1753 } else if (strcmp(str, "ipv6") == 0) {
1754 *af = AF_INET6;
1755 return (0);
1756 }
1757
1758 return (-1);
1759}
1760
1761int
f0722791
RW
1762ldp_vty_show_binding(struct vty *vty, const char *af_str, const char *prefix,
1763 int longer_prefixes, const char *neighbor, unsigned long local_label,
1764 unsigned long remote_label, const char *detail, const char *json)
eac6e3f0
RW
1765{
1766 struct imsgbuf ibuf;
a5d10512 1767 struct show_params params;
eac6e3f0
RW
1768 int af;
1769
1770 if (ldp_vty_connect(&ibuf) < 0)
1771 return (CMD_WARNING);
1772
eac6e3f0
RW
1773 if (ldp_vty_get_af(af_str, &af) < 0)
1774 return (CMD_ERR_NO_MATCH);
1775
a5d10512
RW
1776 memset(&params, 0, sizeof(params));
1777 params.family = af;
1224e5c4
RW
1778 params.detail = (detail) ? 1 : 0;
1779 params.json = (json) ? 1 : 0;
f0722791
RW
1780 if (prefix) {
1781 (void)str2prefix(prefix, &params.lib.prefix);
1782 params.lib.longer_prefixes = longer_prefixes;
1783 }
1784 if (neighbor &&
1785 (inet_pton(AF_INET, neighbor, &params.lib.neighbor) != 1 ||
1786 bad_addr_v4(params.lib.neighbor))) {
1787 vty_out (vty, "%% Malformed address\n");
1788 return (CMD_SUCCESS);
1789 }
1790 params.lib.local_label = local_label;
1791 params.lib.remote_label = remote_label;
eac6e3f0 1792
bc0eb287 1793 if (!params.detail && !params.json)
5c7571d4 1794 vty_out (vty, "%-4s %-20s %-15s %-11s %-13s %6s\n", "AF",
bc0eb287 1795 "Destination", "Nexthop", "Local Label", "Remote Label",
96ade3ed 1796 "In Use");
bc0eb287 1797
a5d10512
RW
1798 imsg_compose(&ibuf, IMSG_CTL_SHOW_LIB, 0, 0, -1, NULL, 0);
1799 return (ldp_vty_dispatch(vty, &ibuf, SHOW_LIB, &params));
eac6e3f0
RW
1800}
1801
1802int
1224e5c4
RW
1803ldp_vty_show_discovery(struct vty *vty, const char *af_str, const char *detail,
1804 const char *json)
eac6e3f0
RW
1805{
1806 struct imsgbuf ibuf;
a5d10512 1807 struct show_params params;
eac6e3f0
RW
1808 int af;
1809
1810 if (ldp_vty_connect(&ibuf) < 0)
1811 return (CMD_WARNING);
1812
eac6e3f0
RW
1813 if (ldp_vty_get_af(af_str, &af) < 0)
1814 return (CMD_ERR_NO_MATCH);
1815
a5d10512
RW
1816 memset(&params, 0, sizeof(params));
1817 params.family = af;
1224e5c4
RW
1818 params.detail = (detail) ? 1 : 0;
1819 params.json = (json) ? 1 : 0;
eac6e3f0 1820
bc0eb287 1821 if (!params.detail && !params.json)
5c7571d4 1822 vty_out (vty, "%-4s %-15s %-8s %-15s %9s\n",
96ade3ed 1823 "AF", "ID", "Type", "Source", "Holdtime");
bc0eb287
RW
1824
1825 if (params.detail)
1826 imsg_compose(&ibuf, IMSG_CTL_SHOW_DISCOVERY_DTL, 0, 0, -1,
1827 NULL, 0);
1828 else
1829 imsg_compose(&ibuf, IMSG_CTL_SHOW_DISCOVERY, 0, 0, -1, NULL, 0);
a5d10512 1830 return (ldp_vty_dispatch(vty, &ibuf, SHOW_DISC, &params));
eac6e3f0
RW
1831}
1832
1833int
1224e5c4 1834ldp_vty_show_interface(struct vty *vty, const char *af_str, const char *json)
eac6e3f0
RW
1835{
1836 struct imsgbuf ibuf;
a5d10512 1837 struct show_params params;
eac6e3f0 1838 unsigned int ifidx = 0;
eac6e3f0
RW
1839 int af;
1840
1841 if (ldp_vty_connect(&ibuf) < 0)
1842 return (CMD_WARNING);
1843
eac6e3f0
RW
1844 if (ldp_vty_get_af(af_str, &af) < 0)
1845 return (CMD_ERR_NO_MATCH);
1846
a5d10512
RW
1847 memset(&params, 0, sizeof(params));
1848 params.family = af;
1224e5c4 1849 params.json = (json) ? 1 : 0;
eac6e3f0
RW
1850
1851 /* header */
a5d10512 1852 if (!params.json) {
5c7571d4 1853 vty_out (vty, "%-4s %-11s %-6s %-8s %-12s %3s\n", "AF",
96ade3ed 1854 "Interface", "State", "Uptime", "Hello Timers","ac");
a5d10512 1855 }
eac6e3f0 1856
a5d10512
RW
1857 imsg_compose(&ibuf, IMSG_CTL_SHOW_INTERFACE, 0, 0, -1, &ifidx,
1858 sizeof(ifidx));
1859 return (ldp_vty_dispatch(vty, &ibuf, SHOW_IFACE, &params));
eac6e3f0
RW
1860}
1861
99cfc17f 1862int
1224e5c4 1863ldp_vty_show_capabilities(struct vty *vty, const char *json)
99cfc17f 1864{
c740f7d3 1865 if (json) {
99cfc17f
RW
1866 json_object *json;
1867 json_object *json_array;
1868 json_object *json_cap;
1869
1870 json = json_object_new_object();
1871 json_array = json_object_new_array();
1872 json_object_object_add(json, "capabilities", json_array);
1873
1874 /* Dynamic Announcement (0x0506) */
1875 json_cap = json_object_new_object();
1876 json_object_string_add(json_cap, "description",
1877 "Dynamic Announcement");
1878 json_object_string_add(json_cap, "tlvType",
1879 "0x0506");
1880 json_object_array_add(json_array, json_cap);
1881
1882 /* Typed Wildcard (0x050B) */
1883 json_cap = json_object_new_object();
1884 json_object_string_add(json_cap, "description",
1885 "Typed Wildcard");
1886 json_object_string_add(json_cap, "tlvType",
1887 "0x050B");
1888 json_object_array_add(json_array, json_cap);
1889
1890 /* Unrecognized Notification (0x0603) */
1891 json_cap = json_object_new_object();
1892 json_object_string_add(json_cap, "description",
1893 "Unrecognized Notification");
1894 json_object_string_add(json_cap, "tlvType",
1895 "0x0603");
1896 json_object_array_add(json_array, json_cap);
1897
5c7571d4 1898 vty_out (vty, "%s\n",
96ade3ed 1899 json_object_to_json_string_ext(json, JSON_C_TO_STRING_PRETTY));
99cfc17f
RW
1900 json_object_free(json);
1901 return (0);
1902 }
1903
181039f3 1904 vty_out (vty,
625e016d
DL
1905 "Supported LDP Capabilities\n"
1906 " * Dynamic Announcement (0x0506)\n"
1907 " * Typed Wildcard (0x050B)\n"
1908 " * Unrecognized Notification (0x0603)\n\n");
99cfc17f
RW
1909
1910 return (0);
1911}
1912
eac6e3f0 1913int
f0722791
RW
1914ldp_vty_show_neighbor(struct vty *vty, const char *lsr_id, int capabilities,
1915 const char *detail, const char *json)
eac6e3f0
RW
1916{
1917 struct imsgbuf ibuf;
a5d10512 1918 struct show_params params;
eac6e3f0
RW
1919
1920 if (ldp_vty_connect(&ibuf) < 0)
1921 return (CMD_WARNING);
1922
a5d10512 1923 memset(&params, 0, sizeof(params));
1224e5c4
RW
1924 params.detail = (detail) ? 1 : 0;
1925 params.json = (json) ? 1 : 0;
f0722791
RW
1926 params.neighbor.capabilities = capabilities;
1927 if (lsr_id &&
1928 (inet_pton(AF_INET, lsr_id, &params.neighbor.lsr_id) != 1 ||
1929 bad_addr_v4(params.neighbor.lsr_id))) {
1930 vty_out (vty, "%% Malformed address\n");
1931 return (CMD_SUCCESS);
1932 }
eac6e3f0 1933
f0722791 1934 if (params.neighbor.capabilities)
99cfc17f
RW
1935 params.detail = 1;
1936
bc0eb287 1937 if (!params.detail && !params.json)
5c7571d4 1938 vty_out (vty, "%-4s %-15s %-11s %-15s %8s\n",
96ade3ed 1939 "AF", "ID", "State", "Remote Address","Uptime");
bc0eb287 1940
a5d10512
RW
1941 imsg_compose(&ibuf, IMSG_CTL_SHOW_NBR, 0, 0, -1, NULL, 0);
1942 return (ldp_vty_dispatch(vty, &ibuf, SHOW_NBR, &params));
eac6e3f0
RW
1943}
1944
1945int
f0722791
RW
1946ldp_vty_show_atom_binding(struct vty *vty, const char *peer,
1947 unsigned long local_label, unsigned long remote_label, const char *json)
eac6e3f0
RW
1948{
1949 struct imsgbuf ibuf;
a5d10512 1950 struct show_params params;
eac6e3f0
RW
1951
1952 if (ldp_vty_connect(&ibuf) < 0)
1953 return (CMD_WARNING);
1954
a5d10512 1955 memset(&params, 0, sizeof(params));
1224e5c4 1956 params.json = (json) ? 1 : 0;
f0722791
RW
1957 if (peer &&
1958 (inet_pton(AF_INET, peer, &params.l2vpn.peer) != 1 ||
1959 bad_addr_v4(params.l2vpn.peer))) {
1960 vty_out (vty, "%% Malformed address\n");
1961 return (CMD_SUCCESS);
1962 }
1963 params.l2vpn.local_label = local_label;
1964 params.l2vpn.remote_label = remote_label;
eac6e3f0 1965
a5d10512
RW
1966 imsg_compose(&ibuf, IMSG_CTL_SHOW_L2VPN_BINDING, 0, 0, -1, NULL, 0);
1967 return (ldp_vty_dispatch(vty, &ibuf, SHOW_L2VPN_BINDING, &params));
eac6e3f0
RW
1968}
1969
1970int
f0722791
RW
1971ldp_vty_show_atom_vc(struct vty *vty, const char *peer, const char *ifname,
1972 const char *vcid, const char *json)
eac6e3f0
RW
1973{
1974 struct imsgbuf ibuf;
a5d10512 1975 struct show_params params;
eac6e3f0
RW
1976
1977 if (ldp_vty_connect(&ibuf) < 0)
1978 return (CMD_WARNING);
1979
a5d10512 1980 memset(&params, 0, sizeof(params));
1224e5c4 1981 params.json = (json) ? 1 : 0;
f0722791
RW
1982 if (peer &&
1983 (inet_pton(AF_INET, peer, &params.l2vpn.peer) != 1 ||
1984 bad_addr_v4(params.l2vpn.peer))) {
1985 vty_out (vty, "%% Malformed address\n");
1986 return (CMD_SUCCESS);
1987 }
1988 if (ifname)
1989 strlcpy(params.l2vpn.ifname, ifname,
1990 sizeof(params.l2vpn.ifname));
1991 if (vcid)
1992 params.l2vpn.vcid = atoi(vcid);
a5d10512
RW
1993
1994 if (!params.json) {
1995 /* header */
5c7571d4 1996 vty_out (vty, "%-9s %-15s %-10s %-16s %-10s\n",
96ade3ed 1997 "Interface", "Peer ID", "VC ID", "Name","Status");
5c7571d4 1998 vty_out (vty, "%-9s %-15s %-10s %-16s %-10s\n",
a5d10512 1999 "---------", "---------------", "----------",
96ade3ed 2000 "----------------", "----------");
a5d10512 2001 }
eac6e3f0 2002
a5d10512
RW
2003 imsg_compose(&ibuf, IMSG_CTL_SHOW_L2VPN_PW, 0, 0, -1, NULL, 0);
2004 return (ldp_vty_dispatch(vty, &ibuf, SHOW_L2VPN_PW, &params));
eac6e3f0
RW
2005}
2006
2007int
c740f7d3 2008ldp_vty_clear_nbr(struct vty *vty, const char *addr_str)
eac6e3f0
RW
2009{
2010 struct imsgbuf ibuf;
eac6e3f0
RW
2011 struct ctl_nbr nbr;
2012
eac6e3f0
RW
2013 memset(&nbr, 0, sizeof(nbr));
2014 if (addr_str &&
2015 (ldp_get_address(addr_str, &nbr.af, &nbr.raddr) == -1 ||
2016 bad_addr(nbr.af, &nbr.raddr))) {
5c7571d4 2017 vty_out (vty, "%% Malformed address\n");
eac6e3f0
RW
2018 return (CMD_WARNING);
2019 }
2020
2021 if (ldp_vty_connect(&ibuf) < 0)
2022 return (CMD_WARNING);
2023
2024 imsg_compose(&ibuf, IMSG_CTL_CLEAR_NBR, 0, 0, -1, &nbr, sizeof(nbr));
2025
2026 while (ibuf.w.queued)
2027 if (msgbuf_write(&ibuf.w) <= 0 && errno != EAGAIN) {
2028 log_warn("write error");
2029 close(ibuf.fd);
2030 return (CMD_WARNING);
2031 }
2032
2033 close(ibuf.fd);
2034
2035 return (CMD_SUCCESS);
2036}