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