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