]> git.proxmox.com Git - mirror_frr.git/blob - ldpd/ldp_vty_exec.c
ldpd: provide both a brief and a detailed version of some show commands
[mirror_frr.git] / ldpd / ldp_vty_exec.c
1 /*
2 * Copyright (C) 2016 by Open Source Routing.
3 *
4 * This file is part of GNU Zebra.
5 *
6 * GNU Zebra is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; either version 2, or (at your option) any
9 * later version.
10 *
11 * GNU Zebra is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with GNU Zebra; see the file COPYING. If not, write to the Free
18 * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
19 * 02111-1307, USA.
20 */
21
22 #include <zebra.h>
23 #include <sys/un.h>
24
25 #include "ldpd.h"
26 #include "ldpe.h"
27 #include "lde.h"
28 #include "log.h"
29 #include "ldp_vty.h"
30 #include "lib/json.h"
31
32 #include "command.h"
33 #include "vty.h"
34 #include "mpls.h"
35
36 enum show_command {
37 SHOW_DISC,
38 SHOW_IFACE,
39 SHOW_NBR,
40 SHOW_LIB,
41 SHOW_L2VPN_PW,
42 SHOW_L2VPN_BINDING
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 };
52
53 #define LDPBUFSIZ 65535
54
55 static int show_interface_msg(struct vty *, struct imsg *,
56 struct show_params *);
57 static int show_interface_msg_json(struct imsg *,
58 struct show_params *, json_object *);
59 static int show_discovery_msg(struct vty *, struct imsg *,
60 struct show_params *);
61 static void show_discovery_detail_adj(struct vty *, char *,
62 struct ctl_adj *);
63 static int show_discovery_detail_msg(struct vty *, struct imsg *,
64 struct show_params *);
65 static int show_discovery_msg_json(struct imsg *,
66 struct show_params *, json_object *);
67 static void show_discovery_detail_adj_json(json_object *,
68 struct ctl_adj *);
69 static int show_discovery_detail_msg_json(struct imsg *,
70 struct show_params *, json_object *);
71 static int show_nbr_msg(struct vty *, struct imsg *,
72 struct show_params *);
73 static int show_nbr_msg_json(struct imsg *, struct show_params *,
74 json_object *);
75 static void show_nbr_detail_adj(struct vty *, char *,
76 struct ctl_adj *);
77 static int show_nbr_detail_msg(struct vty *, struct imsg *,
78 struct show_params *);
79 static void show_nbr_detail_adj_json(struct ctl_adj *,
80 json_object *);
81 static int show_nbr_detail_msg_json(struct imsg *,
82 struct show_params *, json_object *);
83 static int show_lib_msg(struct vty *, struct imsg *,
84 struct show_params *);
85 static int show_lib_detail_msg(struct vty *, struct imsg *,
86 struct show_params *);
87 static int show_lib_msg_json(struct imsg *, struct show_params *,
88 json_object *);
89 static int show_lib_detail_msg_json(struct imsg *,
90 struct show_params *, json_object *);
91 static int show_l2vpn_binding_msg(struct vty *, struct imsg *,
92 struct show_params *);
93 static int show_l2vpn_binding_msg_json(struct imsg *,
94 struct show_params *, json_object *);
95 static int show_l2vpn_pw_msg(struct vty *, struct imsg *,
96 struct show_params *);
97 static int show_l2vpn_pw_msg_json(struct imsg *,
98 struct show_params *, json_object *);
99 static int ldp_vty_connect(struct imsgbuf *);
100 static int ldp_vty_dispatch_msg(struct vty *, struct imsg *,
101 enum show_command, struct show_params *,
102 json_object *);
103 static int ldp_vty_dispatch(struct vty *, struct imsgbuf *,
104 enum show_command, struct show_params *);
105 static int ldp_vty_get_af(const char *, int *);
106
107 static int
108 show_interface_msg(struct vty *vty, struct imsg *imsg,
109 struct show_params *params)
110 {
111 struct ctl_iface *iface;
112 char timers[BUFSIZ];
113
114 switch (imsg->hdr.type) {
115 case IMSG_CTL_SHOW_INTERFACE:
116 iface = imsg->data;
117
118 if (params->family != AF_UNSPEC && params->family != iface->af)
119 break;
120
121 snprintf(timers, sizeof(timers), "%u/%u",
122 iface->hello_interval, iface->hello_holdtime);
123
124 vty_out(vty, "%-4s %-11s %-6s %-8s %-12s %3u%s",
125 af_name(iface->af), iface->name,
126 if_state_name(iface->state), iface->uptime == 0 ?
127 "00:00:00" : log_time(iface->uptime), timers,
128 iface->adj_cnt, VTY_NEWLINE);
129 break;
130 case IMSG_CTL_END:
131 vty_out(vty, "%s", VTY_NEWLINE);
132 return (1);
133 default:
134 break;
135 }
136
137 return (0);
138 }
139
140 static int
141 show_interface_msg_json(struct imsg *imsg, struct show_params *params,
142 json_object *json)
143 {
144 struct ctl_iface *iface;
145 json_object *json_iface;
146 char key_name[64];
147
148 switch (imsg->hdr.type) {
149 case IMSG_CTL_SHOW_INTERFACE:
150 iface = imsg->data;
151
152 if (params->family != AF_UNSPEC && params->family != iface->af)
153 break;
154
155 json_iface = json_object_new_object();
156 json_object_string_add(json_iface, "name", iface->name);
157 json_object_string_add(json_iface, "addressFamily",
158 af_name(iface->af));
159 json_object_string_add(json_iface, "state",
160 if_state_name(iface->state));
161 json_object_string_add(json_iface, "upTime",
162 log_time(iface->uptime));
163 json_object_int_add(json_iface, "helloInterval",
164 iface->hello_interval);
165 json_object_int_add(json_iface, "helloHoldtime",
166 iface->hello_holdtime);
167 json_object_int_add(json_iface, "adjacencyCount",
168 iface->adj_cnt);
169
170 sprintf(key_name, "%s: %s", iface->name, af_name(iface->af));
171 json_object_object_add(json, key_name, json_iface);
172 break;
173 case IMSG_CTL_END:
174 return (1);
175 default:
176 break;
177 }
178
179 return (0);
180 }
181
182 static int
183 show_discovery_msg(struct vty *vty, struct imsg *imsg,
184 struct show_params *params)
185 {
186 struct ctl_adj *adj;
187 const char *addr;
188
189 switch (imsg->hdr.type) {
190 case IMSG_CTL_SHOW_DISCOVERY:
191 adj = imsg->data;
192
193 if (params->family != AF_UNSPEC && params->family != adj->af)
194 break;
195
196 vty_out(vty, "%-4s %-15s ", af_name(adj->af),
197 inet_ntoa(adj->id));
198 switch(adj->type) {
199 case HELLO_LINK:
200 vty_out(vty, "%-8s %-15s ", "Link", adj->ifname);
201 break;
202 case HELLO_TARGETED:
203 addr = log_addr(adj->af, &adj->src_addr);
204
205 vty_out(vty, "%-8s %-15s ", "Targeted", addr);
206 if (strlen(addr) > 15)
207 vty_out(vty, "\n%46s", " ");
208 break;
209 }
210 vty_out(vty, "%9u\n", adj->holdtime);
211 break;
212 case IMSG_CTL_END:
213 vty_out(vty, "%s", VTY_NEWLINE);
214 return (1);
215 default:
216 break;
217 }
218
219 return (0);
220 }
221
222 static void
223 show_discovery_detail_adj(struct vty *vty, char *buffer, struct ctl_adj *adj)
224 {
225 size_t buflen = strlen(buffer);
226
227 snprintf(buffer + buflen, LDPBUFSIZ - buflen,
228 " LDP Id: %s:0, Transport address: %s%s",
229 inet_ntoa(adj->id), log_addr(adj->af,
230 &adj->trans_addr), VTY_NEWLINE);
231 buflen = strlen(buffer);
232 snprintf(buffer + buflen, LDPBUFSIZ - buflen,
233 " Hold time: %u sec%s", adj->holdtime, VTY_NEWLINE);
234 }
235
236 static int
237 show_discovery_detail_msg(struct vty *vty, struct imsg *imsg,
238 struct show_params *params)
239 {
240 struct ctl_adj *adj;
241 struct ctl_disc_if *iface;
242 struct ctl_disc_tnbr *tnbr;
243 struct in_addr rtr_id;
244 union ldpd_addr *trans_addr;
245 size_t buflen;
246 static char ifaces_buffer[LDPBUFSIZ];
247 static char tnbrs_buffer[LDPBUFSIZ];
248
249 switch (imsg->hdr.type) {
250 case IMSG_CTL_SHOW_DISCOVERY:
251 ifaces_buffer[0] = '\0';
252 tnbrs_buffer[0] = '\0';
253 break;
254 case IMSG_CTL_SHOW_DISC_IFACE:
255 iface = imsg->data;
256
257 if (params->family != AF_UNSPEC &&
258 ((params->family == AF_INET && !iface->active_v4) ||
259 (params->family == AF_INET6 && !iface->active_v6)))
260 break;
261
262 buflen = strlen(ifaces_buffer);
263 snprintf(ifaces_buffer + buflen, LDPBUFSIZ - buflen,
264 " %s: %s%s", iface->name, (iface->no_adj) ?
265 "xmit" : "xmit/recv", VTY_NEWLINE);
266 break;
267 case IMSG_CTL_SHOW_DISC_TNBR:
268 tnbr = imsg->data;
269
270 if (params->family != AF_UNSPEC && params->family != tnbr->af)
271 break;
272
273 trans_addr = &(ldp_af_conf_get(ldpd_conf,
274 tnbr->af))->trans_addr;
275 buflen = strlen(tnbrs_buffer);
276 snprintf(tnbrs_buffer + buflen, LDPBUFSIZ - buflen,
277 " %s -> %s: %s%s", log_addr(tnbr->af, trans_addr),
278 log_addr(tnbr->af, &tnbr->addr), (tnbr->no_adj) ? "xmit" :
279 "xmit/recv", VTY_NEWLINE);
280 break;
281 case IMSG_CTL_SHOW_DISC_ADJ:
282 adj = imsg->data;
283
284 if (params->family != AF_UNSPEC && params->family != adj->af)
285 break;
286
287 switch(adj->type) {
288 case HELLO_LINK:
289 show_discovery_detail_adj(vty, ifaces_buffer, adj);
290 break;
291 case HELLO_TARGETED:
292 show_discovery_detail_adj(vty, tnbrs_buffer, adj);
293 break;
294 }
295 break;
296 case IMSG_CTL_END:
297 rtr_id.s_addr = ldp_rtr_id_get(ldpd_conf);
298 vty_out(vty, "Local LDP Identifier: %s:0%s", inet_ntoa(rtr_id),
299 VTY_NEWLINE);
300 vty_out(vty, "Discovery Sources:%s", VTY_NEWLINE);
301 vty_out(vty, " Interfaces:%s", VTY_NEWLINE);
302 vty_out(vty, "%s", ifaces_buffer);
303 vty_out(vty, " Targeted Hellos:%s", VTY_NEWLINE);
304 vty_out(vty, "%s", tnbrs_buffer);
305 vty_out(vty, "%s", VTY_NEWLINE);
306 return (1);
307 default:
308 break;
309 }
310
311 return (0);
312 }
313
314 static int
315 show_discovery_msg_json(struct imsg *imsg, struct show_params *params,
316 json_object *json)
317 {
318 struct ctl_adj *adj;
319 json_object *json_array;
320 json_object *json_adj;
321
322 switch (imsg->hdr.type) {
323 case IMSG_CTL_SHOW_DISCOVERY:
324 adj = imsg->data;
325
326 if (params->family != AF_UNSPEC && params->family != adj->af)
327 break;
328
329 json_object_object_get_ex(json, "adjacencies", &json_array);
330 if (!json_array) {
331 json_array = json_object_new_array();
332 json_object_object_add(json, "adjacencies", json_array);
333 }
334
335 json_adj = json_object_new_object();
336 json_object_string_add(json_adj, "addressFamily",
337 af_name(adj->af));
338 json_object_string_add(json_adj, "neighborId",
339 inet_ntoa(adj->id));
340 switch(adj->type) {
341 case HELLO_LINK:
342 json_object_string_add(json_adj, "type", "link");
343 json_object_string_add(json_adj, "interface",
344 adj->ifname);
345 break;
346 case HELLO_TARGETED:
347 json_object_string_add(json_adj, "type", "targeted");
348 json_object_string_add(json_adj, "peer",
349 log_addr(adj->af, &adj->src_addr));
350 break;
351 }
352 json_object_int_add(json_adj, "helloHoldtime", adj->holdtime);
353
354 json_object_array_add(json_array, json_adj);
355 break;
356 case IMSG_CTL_END:
357 return (1);
358 default:
359 break;
360 }
361
362 return (0);
363 }
364
365 static void
366 show_discovery_detail_adj_json(json_object *json, struct ctl_adj *adj)
367 {
368 json_object *json_adj;
369 json_object *json_array;
370
371 json_object_object_get_ex(json, "adjacencies", &json_array);
372 if (!json_array) {
373 json_array = json_object_new_array();
374 json_object_object_add(json, "adjacencies", json_array);
375 }
376
377 json_adj = json_object_new_object();
378 json_object_string_add(json_adj, "id", inet_ntoa(adj->id));
379 json_object_string_add(json_adj, "transportAddress", log_addr(adj->af,
380 &adj->trans_addr));
381 json_object_int_add(json_adj, "holdtime", adj->holdtime);
382 json_object_array_add(json_array, json_adj);
383 }
384
385 static int
386 show_discovery_detail_msg_json(struct imsg *imsg, struct show_params *params,
387 json_object *json)
388 {
389 struct ctl_adj *adj;
390 struct ctl_disc_if *iface;
391 struct ctl_disc_tnbr *tnbr;
392 struct in_addr rtr_id;
393 union ldpd_addr *trans_addr;
394 json_object *json_interface;
395 json_object *json_target;
396 static json_object *json_interfaces;
397 static json_object *json_targets;
398 static json_object *json_container;
399
400 switch (imsg->hdr.type) {
401 case IMSG_CTL_SHOW_DISCOVERY:
402 rtr_id.s_addr = ldp_rtr_id_get(ldpd_conf);
403 json_object_string_add(json, "id", inet_ntoa(rtr_id));
404 json_interfaces = json_object_new_object();
405 json_object_object_add(json, "interfaces", json_interfaces);
406 json_targets = json_object_new_object();
407 json_object_object_add(json, "targetedHellos", json_targets);
408 json_container = NULL;
409 break;
410 case IMSG_CTL_SHOW_DISC_IFACE:
411 iface = imsg->data;
412
413 if (params->family != AF_UNSPEC &&
414 ((params->family == AF_INET && !iface->active_v4) ||
415 (params->family == AF_INET6 && !iface->active_v6)))
416 break;
417
418 json_interface = json_object_new_object();
419 json_object_boolean_true_add(json_interface, "transmit");
420 if (!iface->no_adj)
421 json_object_boolean_true_add(json_interface, "receive");
422
423 json_object_object_add(json_interfaces, iface->name,
424 json_interface);
425 json_container = json_interface;
426 break;
427 case IMSG_CTL_SHOW_DISC_TNBR:
428 tnbr = imsg->data;
429
430 if (params->family != AF_UNSPEC && params->family != tnbr->af)
431 break;
432
433 trans_addr = &(ldp_af_conf_get(ldpd_conf, tnbr->af))->trans_addr;
434
435 json_target = json_object_new_object();
436 json_object_string_add(json_target, "sourceAddress",
437 log_addr(tnbr->af, trans_addr));
438 json_object_boolean_true_add(json_target, "transmit");
439 if (!tnbr->no_adj)
440 json_object_boolean_true_add(json_target, "receive");
441
442 json_object_object_add(json_targets, log_addr(tnbr->af,
443 &tnbr->addr), json_target);
444 json_container = json_target;
445 break;
446 case IMSG_CTL_SHOW_DISC_ADJ:
447 adj = imsg->data;
448
449 if (params->family != AF_UNSPEC && params->family != adj->af)
450 break;
451
452 switch(adj->type) {
453 case HELLO_LINK:
454 show_discovery_detail_adj_json(json_container, adj);
455 break;
456 case HELLO_TARGETED:
457 show_discovery_detail_adj_json(json_container, adj);
458 break;
459 }
460 break;
461 case IMSG_CTL_END:
462 return (1);
463 default:
464 break;
465 }
466
467 return (0);
468 }
469
470 static int
471 show_nbr_msg(struct vty *vty, struct imsg *imsg, struct show_params *params)
472 {
473 struct ctl_nbr *nbr;
474 const char *addr;
475
476 switch (imsg->hdr.type) {
477 case IMSG_CTL_SHOW_NBR:
478 nbr = imsg->data;
479
480 addr = log_addr(nbr->af, &nbr->raddr);
481
482 vty_out(vty, "%-4s %-15s %-11s %-15s",
483 af_name(nbr->af), inet_ntoa(nbr->id),
484 nbr_state_name(nbr->nbr_state), addr);
485 if (strlen(addr) > 15)
486 vty_out(vty, "\n%48s", " ");
487 vty_out(vty, " %8s\n", nbr->uptime == 0 ? "-" :
488 log_time(nbr->uptime));
489 break;
490 case IMSG_CTL_END:
491 return (1);
492 default:
493 break;
494 }
495
496 return (0);
497 }
498
499 static void
500 show_nbr_detail_adj(struct vty *vty, char *buffer, struct ctl_adj *adj)
501 {
502 size_t buflen = strlen(buffer);
503
504 switch (adj->type) {
505 case HELLO_LINK:
506 snprintf(buffer + buflen, LDPBUFSIZ - buflen,
507 " Interface: %s%s", adj->ifname, VTY_NEWLINE);
508 break;
509 case HELLO_TARGETED:
510 snprintf(buffer + buflen, LDPBUFSIZ - buflen,
511 " Targeted Hello: %s%s", log_addr(adj->af,
512 &adj->src_addr), VTY_NEWLINE);
513 break;
514 }
515 }
516
517 static int
518 show_nbr_detail_msg(struct vty *vty, struct imsg *imsg, struct show_params *params)
519 {
520 struct ctl_nbr *nbr;
521 struct ctl_adj *adj;
522 static char v4adjs_buffer[LDPBUFSIZ];
523 static char v6adjs_buffer[LDPBUFSIZ];
524
525 switch (imsg->hdr.type) {
526 case IMSG_CTL_SHOW_NBR:
527 nbr = imsg->data;
528
529 v4adjs_buffer[0] = '\0';
530 v6adjs_buffer[0] = '\0';
531 vty_out(vty, "Peer LDP Identifier: %s:0%s", inet_ntoa(nbr->id),
532 VTY_NEWLINE);
533 vty_out(vty, " TCP connection: %s:%u - %s:%u%s",
534 log_addr(nbr->af, &nbr->laddr), ntohs(nbr->lport),
535 log_addr(nbr->af, &nbr->raddr), ntohs(nbr->rport),
536 VTY_NEWLINE);
537 vty_out(vty, " Session Holdtime: %u sec%s", nbr->holdtime,
538 VTY_NEWLINE);
539 vty_out(vty, " State: %s; Downstream-Unsolicited%s",
540 nbr_state_name(nbr->nbr_state), VTY_NEWLINE);
541 vty_out(vty, " Up time: %s%s", log_time(nbr->uptime),
542 VTY_NEWLINE);
543 break;
544 case IMSG_CTL_SHOW_NBR_DISC:
545 adj = imsg->data;
546
547 switch (adj->af) {
548 case AF_INET:
549 show_nbr_detail_adj(vty, v4adjs_buffer, adj);
550 break;
551 case AF_INET6:
552 show_nbr_detail_adj(vty, v6adjs_buffer, adj);
553 break;
554 default:
555 fatalx("show_nbr_detail_msg: unknown af");
556 }
557 break;
558 case IMSG_CTL_SHOW_NBR_END:
559 vty_out(vty, " LDP Discovery Sources:%s", VTY_NEWLINE);
560 if (v4adjs_buffer[0] != '\0') {
561 vty_out(vty, " IPv4:%s", VTY_NEWLINE);
562 vty_out(vty, "%s", v4adjs_buffer);
563 }
564 if (v6adjs_buffer[0] != '\0') {
565 vty_out(vty, " IPv6:%s", VTY_NEWLINE);
566 vty_out(vty, "%s", v6adjs_buffer);
567 }
568 vty_out(vty, "%s", VTY_NEWLINE);
569 break;
570 case IMSG_CTL_END:
571 return (1);
572 default:
573 break;
574 }
575
576 return (0);
577 }
578
579 static int
580 show_nbr_msg_json(struct imsg *imsg, struct show_params *params,
581 json_object *json)
582 {
583 struct ctl_nbr *nbr;
584 json_object *json_array;
585 json_object *json_nbr;
586
587 switch (imsg->hdr.type) {
588 case IMSG_CTL_SHOW_NBR:
589 nbr = imsg->data;
590
591 json_object_object_get_ex(json, "neighbors", &json_array);
592 if (!json_array) {
593 json_array = json_object_new_array();
594 json_object_object_add(json, "neighbors", json_array);
595 }
596
597 json_nbr = json_object_new_object();
598 json_object_string_add(json_nbr, "addressFamily",
599 af_name(nbr->af));
600 json_object_string_add(json_nbr, "neighborId",
601 inet_ntoa(nbr->id));
602 json_object_string_add(json_nbr, "state",
603 nbr_state_name(nbr->nbr_state));
604 json_object_string_add(json_nbr, "transportAddress",
605 log_addr(nbr->af, &nbr->raddr));
606 json_object_string_add(json_nbr, "upTime",
607 log_time(nbr->uptime));
608
609 json_object_array_add(json_array, json_nbr);
610 break;
611 case IMSG_CTL_END:
612 return (1);
613 default:
614 break;
615 }
616
617 return (0);
618 }
619
620 static void
621 show_nbr_detail_adj_json(struct ctl_adj *adj, json_object *adj_list)
622 {
623 char adj_string[128];
624
625 switch (adj->type) {
626 case HELLO_LINK:
627 strlcpy(adj_string, "interface: ", sizeof(adj_string));
628 strlcat(adj_string, adj->ifname, sizeof(adj_string));
629 break;
630 case HELLO_TARGETED:
631 strlcpy(adj_string, "targetedHello: ", sizeof(adj_string));
632 strlcat(adj_string, log_addr(adj->af, &adj->src_addr),
633 sizeof(adj_string));
634 break;
635 }
636
637 json_object_array_add(adj_list, json_object_new_string(adj_string));
638 }
639
640 static int
641 show_nbr_detail_msg_json(struct imsg *imsg, struct show_params *params,
642 json_object *json)
643 {
644 struct ctl_nbr *nbr;
645 struct ctl_adj *adj;
646 json_object *json_nbr;
647 static json_object *json_nbr_sources;
648 static json_object *json_v4adjs;
649 static json_object *json_v6adjs;
650
651 switch (imsg->hdr.type) {
652 case IMSG_CTL_SHOW_NBR:
653 nbr = imsg->data;
654
655 json_nbr = json_object_new_object();
656 json_object_string_add(json_nbr, "peerId", inet_ntoa(nbr->id));
657 json_object_string_add(json_nbr, "tcpLocalAddress",
658 log_addr(nbr->af, &nbr->laddr));
659 json_object_int_add(json_nbr, "tcpLocalPort",
660 ntohs(nbr->lport));
661 json_object_string_add(json_nbr, "tcpRemoteAddress",
662 log_addr(nbr->af, &nbr->raddr));
663 json_object_int_add(json_nbr, "tcpRemotePort",
664 ntohs(nbr->rport));
665 json_object_int_add(json_nbr, "holdtime", nbr->holdtime);
666 json_object_string_add(json_nbr, "state",
667 nbr_state_name(nbr->nbr_state));
668 json_object_string_add(json_nbr, "upTime",
669 log_time(nbr->uptime));
670 json_object_object_add(json, inet_ntoa(nbr->id), json_nbr);
671
672 json_nbr_sources = json_object_new_object();
673 json_object_object_add(json_nbr, "discoverySources",
674 json_nbr_sources);
675 json_v4adjs = NULL;
676 json_v6adjs = NULL;
677 break;
678 case IMSG_CTL_SHOW_NBR_DISC:
679 adj = imsg->data;
680
681 switch (adj->af) {
682 case AF_INET:
683 if (!json_v4adjs) {
684 json_v4adjs = json_object_new_array();
685 json_object_object_add(json_nbr_sources, "ipv4",
686 json_v4adjs);
687 }
688 show_nbr_detail_adj_json(adj, json_v4adjs);
689 break;
690 case AF_INET6:
691 if (!json_v6adjs) {
692 json_v6adjs = json_object_new_array();
693 json_object_object_add(json_nbr_sources, "ipv6",
694 json_v6adjs);
695 }
696 show_nbr_detail_adj_json(adj, json_v6adjs);
697 break;
698 default:
699 fatalx("show_nbr_detail_msg_json: unknown af");
700 }
701 break;
702 case IMSG_CTL_SHOW_NBR_END:
703 break;
704 case IMSG_CTL_END:
705 return (1);
706 default:
707 break;
708 }
709
710 return (0);
711 }
712
713 static int
714 show_lib_msg(struct vty *vty, struct imsg *imsg, struct show_params *params)
715 {
716 struct ctl_rt *rt;
717 char dstnet[BUFSIZ];
718
719 switch (imsg->hdr.type) {
720 case IMSG_CTL_SHOW_LIB:
721 rt = imsg->data;
722
723 if (params->family != AF_UNSPEC && params->family != rt->af)
724 break;
725
726 snprintf(dstnet, sizeof(dstnet), "%s/%d",
727 log_addr(rt->af, &rt->prefix), rt->prefixlen);
728
729 vty_out(vty, "%-4s %-20s", af_name(rt->af), dstnet);
730 if (strlen(dstnet) > 20)
731 vty_out(vty, "\n%25s", " ");
732 vty_out(vty, " %-15s %-11s %-13s %6s\n", inet_ntoa(rt->nexthop),
733 log_label(rt->local_label), log_label(rt->remote_label),
734 rt->in_use ? "yes" : "no");
735 break;
736 case IMSG_CTL_END:
737 vty_out(vty, "%s", VTY_NEWLINE);
738 return (1);
739 default:
740 break;
741 }
742
743 return (0);
744 }
745
746 static int
747 show_lib_detail_msg(struct vty *vty, struct imsg *imsg, struct show_params *params)
748 {
749 struct ctl_rt *rt;
750 char dstnet[BUFSIZ];
751
752 switch (imsg->hdr.type) {
753 case IMSG_CTL_SHOW_LIB:
754 rt = imsg->data;
755
756 if (params->family != AF_UNSPEC && params->family != rt->af)
757 break;
758
759 snprintf(dstnet, sizeof(dstnet), "%s/%d",
760 log_addr(rt->af, &rt->prefix), rt->prefixlen);
761
762 if (rt->first) {
763 vty_out(vty, "%s%s", dstnet, VTY_NEWLINE);
764 vty_out(vty, "%-8sLocal binding: label: %s%s", "",
765 log_label(rt->local_label), VTY_NEWLINE);
766
767 if (rt->remote_label != NO_LABEL) {
768 vty_out(vty, "%-8sRemote bindings:%s", "",
769 VTY_NEWLINE);
770 vty_out(vty, "%-12sPeer Label%s",
771 "", VTY_NEWLINE);
772 vty_out(vty, "%-12s----------------- "
773 "---------%s", "", VTY_NEWLINE);
774 } else
775 vty_out(vty, "%-8sNo remote bindings%s", "",
776 VTY_NEWLINE);
777 }
778 if (rt->remote_label != NO_LABEL)
779 vty_out(vty, "%12s%-20s%s%s", "", inet_ntoa(rt->nexthop),
780 log_label(rt->remote_label), VTY_NEWLINE);
781 break;
782 case IMSG_CTL_END:
783 vty_out(vty, "%s", VTY_NEWLINE);
784 return (1);
785 default:
786 break;
787 }
788
789 return (0);
790 }
791
792 static int
793 show_lib_msg_json(struct imsg *imsg, struct show_params *params,
794 json_object *json)
795 {
796 struct ctl_rt *rt;
797 json_object *json_array;
798 json_object *json_lib_entry;
799 char dstnet[BUFSIZ];
800
801 switch (imsg->hdr.type) {
802 case IMSG_CTL_SHOW_LIB:
803 rt = imsg->data;
804
805 if (params->family != AF_UNSPEC && params->family != rt->af)
806 break;
807
808 json_object_object_get_ex(json, "bindings", &json_array);
809 if (!json_array) {
810 json_array = json_object_new_array();
811 json_object_object_add(json, "bindings", json_array);
812 }
813
814 json_lib_entry = json_object_new_object();
815 json_object_string_add(json_lib_entry, "addressFamily",
816 af_name(rt->af));
817 snprintf(dstnet, sizeof(dstnet), "%s/%d",
818 log_addr(rt->af, &rt->prefix), rt->prefixlen);
819 json_object_string_add(json_lib_entry, "prefix", dstnet);
820 json_object_string_add(json_lib_entry, "neighborId",
821 inet_ntoa(rt->nexthop));
822 json_object_string_add(json_lib_entry, "localLabel",
823 log_label(rt->local_label));
824 json_object_string_add(json_lib_entry, "remoteLabel",
825 log_label(rt->remote_label));
826 json_object_int_add(json_lib_entry, "inUse", rt->in_use);
827
828 json_object_array_add(json_array, json_lib_entry);
829 break;
830 case IMSG_CTL_END:
831 return (1);
832 default:
833 break;
834 }
835
836 return (0);
837 }
838
839 static int
840 show_lib_detail_msg_json(struct imsg *imsg, struct show_params *params,
841 json_object *json)
842 {
843 struct ctl_rt *rt;
844 char dstnet[BUFSIZ];
845 static json_object *json_binding;
846 static json_object *json_remote_labels;
847 json_object *json_remote_label;
848
849 switch (imsg->hdr.type) {
850 case IMSG_CTL_SHOW_LIB:
851 rt = imsg->data;
852
853 if (params->family != AF_UNSPEC && params->family != rt->af)
854 break;
855
856 snprintf(dstnet, sizeof(dstnet), "%s/%d",
857 log_addr(rt->af, &rt->prefix), rt->prefixlen);
858
859 if (rt->first) {
860 json_binding = json_object_new_object();
861 json_object_string_add(json_binding, "localLabel",
862 log_label(rt->local_label));
863
864 json_remote_labels = json_object_new_array();
865 json_object_object_add(json_binding, "remoteLabels",
866 json_remote_labels);
867 json_object_object_add(json, dstnet, json_binding);
868 }
869
870 if (rt->remote_label != NO_LABEL) {
871 json_remote_label = json_object_new_object();
872 json_object_string_add(json_remote_label, "nexthop",
873 inet_ntoa(rt->nexthop));
874 json_object_string_add(json_remote_label, "label",
875 log_label(rt->remote_label));
876 json_object_array_add(json_remote_labels,
877 json_remote_label);
878 }
879 break;
880 case IMSG_CTL_END:
881 return (1);
882 default:
883 break;
884 }
885
886 return (0);
887 }
888
889 static int
890 show_l2vpn_binding_msg(struct vty *vty, struct imsg *imsg,
891 struct show_params *params)
892 {
893 struct ctl_pw *pw;
894
895 switch (imsg->hdr.type) {
896 case IMSG_CTL_SHOW_L2VPN_BINDING:
897 pw = imsg->data;
898
899 vty_out(vty, " Destination Address: %s, VC ID: %u%s",
900 inet_ntoa(pw->lsr_id), pw->pwid, VTY_NEWLINE);
901
902 /* local binding */
903 if (pw->local_label != NO_LABEL) {
904 vty_out(vty, " Local Label: %u%s", pw->local_label,
905 VTY_NEWLINE);
906 vty_out(vty, "%-8sCbit: %u, VC Type: %s, "
907 "GroupID: %u%s", "", pw->local_cword,
908 pw_type_name(pw->type), pw->local_gid,
909 VTY_NEWLINE);
910 vty_out(vty, "%-8sMTU: %u%s", "", pw->local_ifmtu,
911 VTY_NEWLINE);
912 } else
913 vty_out(vty, " Local Label: unassigned%s",
914 VTY_NEWLINE);
915
916 /* remote binding */
917 if (pw->remote_label != NO_LABEL) {
918 vty_out(vty, " Remote Label: %u%s",
919 pw->remote_label, VTY_NEWLINE);
920 vty_out(vty, "%-8sCbit: %u, VC Type: %s, "
921 "GroupID: %u%s", "", pw->remote_cword,
922 pw_type_name(pw->type), pw->remote_gid,
923 VTY_NEWLINE);
924 vty_out(vty, "%-8sMTU: %u%s", "", pw->remote_ifmtu,
925 VTY_NEWLINE);
926 } else
927 vty_out(vty, " Remote Label: unassigned%s",
928 VTY_NEWLINE);
929 break;
930 case IMSG_CTL_END:
931 vty_out(vty, "%s", VTY_NEWLINE);
932 return (1);
933 default:
934 break;
935 }
936
937 return (0);
938 }
939
940 static int
941 show_l2vpn_binding_msg_json(struct imsg *imsg, struct show_params *params,
942 json_object *json)
943 {
944 struct ctl_pw *pw;
945 json_object *json_pw;
946 char key_name[64];
947
948 switch (imsg->hdr.type) {
949 case IMSG_CTL_SHOW_L2VPN_BINDING:
950 pw = imsg->data;
951
952 json_pw = json_object_new_object();
953 json_object_string_add(json_pw, "destination",
954 inet_ntoa(pw->lsr_id));
955 json_object_int_add(json_pw, "vcId", pw->pwid);
956
957 /* local binding */
958 if (pw->local_label != NO_LABEL) {
959 json_object_int_add(json_pw, "localLabel",
960 pw->local_label);
961 json_object_int_add(json_pw, "localControlWord",
962 pw->local_cword);
963 json_object_string_add(json_pw, "localVcType",
964 pw_type_name(pw->type));
965 json_object_int_add(json_pw, "localGroupID",
966 pw->local_gid);
967 json_object_int_add(json_pw, "localIfMtu",
968 pw->local_ifmtu);
969 } else
970 json_object_string_add(json_pw, "localLabel",
971 "unassigned");
972
973 /* remote binding */
974 if (pw->remote_label != NO_LABEL) {
975 json_object_int_add(json_pw, "remoteLabel",
976 pw->remote_label);
977 json_object_int_add(json_pw, "remoteControlWord",
978 pw->remote_cword);
979 json_object_string_add(json_pw, "remoteVcType",
980 pw_type_name(pw->type));
981 json_object_int_add(json_pw, "remoteGroupID",
982 pw->remote_gid);
983 json_object_int_add(json_pw, "remoteIfMtu",
984 pw->remote_ifmtu);
985 } else
986 json_object_string_add(json_pw, "remoteLabel",
987 "unassigned");
988
989 sprintf(key_name, "%s: %u", inet_ntoa(pw->lsr_id), pw->pwid);
990 json_object_object_add(json, key_name, json_pw);
991 break;
992 case IMSG_CTL_END:
993 return (1);
994 default:
995 break;
996 }
997
998 return (0);
999 }
1000
1001 static int
1002 show_l2vpn_pw_msg(struct vty *vty, struct imsg *imsg, struct show_params *params)
1003 {
1004 struct ctl_pw *pw;
1005
1006 switch (imsg->hdr.type) {
1007 case IMSG_CTL_SHOW_L2VPN_PW:
1008 pw = imsg->data;
1009
1010 vty_out(vty, "%-9s %-15s %-10u %-16s %-10s%s", pw->ifname,
1011 inet_ntoa(pw->lsr_id), pw->pwid, pw->l2vpn_name,
1012 (pw->status ? "UP" : "DOWN"), VTY_NEWLINE);
1013 break;
1014 case IMSG_CTL_END:
1015 vty_out(vty, "%s", VTY_NEWLINE);
1016 return (1);
1017 default:
1018 break;
1019 }
1020
1021 return (0);
1022 }
1023
1024 static int
1025 show_l2vpn_pw_msg_json(struct imsg *imsg, struct show_params *params,
1026 json_object *json)
1027 {
1028 struct ctl_pw *pw;
1029 json_object *json_pw;
1030
1031 switch (imsg->hdr.type) {
1032 case IMSG_CTL_SHOW_L2VPN_PW:
1033 pw = imsg->data;
1034
1035 json_pw = json_object_new_object();
1036 json_object_string_add(json_pw, "peerId", inet_ntoa(pw->lsr_id));
1037 json_object_int_add(json_pw, "vcId", pw->pwid);
1038 json_object_string_add(json_pw, "VpnName", pw->l2vpn_name);
1039 if (pw->status)
1040 json_object_string_add(json_pw, "status", "up");
1041 else
1042 json_object_string_add(json_pw, "status", "down");
1043 json_object_object_add(json, pw->ifname, json_pw);
1044 break;
1045 case IMSG_CTL_END:
1046 return (1);
1047 default:
1048 break;
1049 }
1050
1051 return (0);
1052 }
1053
1054 static int
1055 ldp_vty_connect(struct imsgbuf *ibuf)
1056 {
1057 struct sockaddr_un s_un;
1058 int ctl_sock;
1059
1060 /* connect to ldpd control socket */
1061 if ((ctl_sock = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) {
1062 log_warn("%s: socket", __func__);
1063 return (-1);
1064 }
1065
1066 memset(&s_un, 0, sizeof(s_un));
1067 s_un.sun_family = AF_UNIX;
1068 strlcpy(s_un.sun_path, ctl_sock_path, sizeof(s_un.sun_path));
1069 if (connect(ctl_sock, (struct sockaddr *)&s_un, sizeof(s_un)) == -1) {
1070 log_warn("%s: connect: %s", __func__, ctl_sock_path);
1071 close(ctl_sock);
1072 return (-1);
1073 }
1074
1075 imsg_init(ibuf, ctl_sock);
1076
1077 return (0);
1078 }
1079
1080 static int
1081 ldp_vty_dispatch_msg(struct vty *vty, struct imsg *imsg, enum show_command cmd,
1082 struct show_params *params, json_object *json)
1083 {
1084 int ret;
1085
1086 switch (cmd) {
1087 case SHOW_IFACE:
1088 if (params->json)
1089 ret = show_interface_msg_json(imsg, params, json);
1090 else
1091 ret = show_interface_msg(vty, imsg, params);
1092 break;
1093 case SHOW_DISC:
1094 if (params->detail) {
1095 if (params->json)
1096 ret = show_discovery_detail_msg_json(imsg,
1097 params, json);
1098 else
1099 ret = show_discovery_detail_msg(vty, imsg,
1100 params);
1101 } else {
1102 if (params->json)
1103 ret = show_discovery_msg_json(imsg, params,
1104 json);
1105 else
1106 ret = show_discovery_msg(vty, imsg, params);
1107 }
1108 break;
1109 case SHOW_NBR:
1110 if (params->detail) {
1111 if (params->json)
1112 ret = show_nbr_detail_msg_json(imsg, params,
1113 json);
1114 else
1115 ret = show_nbr_detail_msg(vty, imsg, params);
1116 } else {
1117 if (params->json)
1118 ret = show_nbr_msg_json(imsg, params, json);
1119 else
1120 ret = show_nbr_msg(vty, imsg, params);
1121 }
1122 break;
1123 case SHOW_LIB:
1124 if (params->detail) {
1125 if (params->json)
1126 ret = show_lib_detail_msg_json(imsg, params,
1127 json);
1128 else
1129 ret = show_lib_detail_msg(vty, imsg, params);
1130 } else {
1131 if (params->json)
1132 ret = show_lib_msg_json(imsg, params, json);
1133 else
1134 ret = show_lib_msg(vty, imsg, params);
1135 }
1136 break;
1137 case SHOW_L2VPN_PW:
1138 if (params->json)
1139 ret = show_l2vpn_pw_msg_json(imsg, params, json);
1140 else
1141 ret = show_l2vpn_pw_msg(vty, imsg, params);
1142 break;
1143 case SHOW_L2VPN_BINDING:
1144 if (params->json)
1145 ret = show_l2vpn_binding_msg_json(imsg, params, json);
1146 else
1147 ret = show_l2vpn_binding_msg(vty, imsg, params);
1148 break;
1149 default:
1150 return (0);
1151 }
1152
1153 return (ret);
1154 }
1155
1156 static int
1157 ldp_vty_dispatch(struct vty *vty, struct imsgbuf *ibuf, enum show_command cmd,
1158 struct show_params *params)
1159 {
1160 struct imsg imsg;
1161 int n, done = 0, ret = CMD_SUCCESS;
1162 json_object *json = NULL;
1163
1164 while (ibuf->w.queued)
1165 if (msgbuf_write(&ibuf->w) <= 0 && errno != EAGAIN) {
1166 log_warn("write error");
1167 close(ibuf->fd);
1168 return (CMD_WARNING);
1169 }
1170
1171 if (params->json)
1172 json = json_object_new_object();
1173
1174 while (!done) {
1175 if ((n = imsg_read(ibuf)) == -1 && errno != EAGAIN) {
1176 log_warnx("imsg_read error");
1177 ret = CMD_WARNING;
1178 goto done;
1179 }
1180 if (n == 0) {
1181 log_warnx("pipe closed");
1182 ret = CMD_WARNING;
1183 goto done;
1184 }
1185
1186 while (!done) {
1187 if ((n = imsg_get(ibuf, &imsg)) == -1) {
1188 log_warnx("imsg_get error");
1189 ret = CMD_WARNING;
1190 goto done;
1191 }
1192 if (n == 0)
1193 break;
1194 done = ldp_vty_dispatch_msg(vty, &imsg, cmd, params,
1195 json);
1196 imsg_free(&imsg);
1197 }
1198 }
1199
1200 done:
1201 close(ibuf->fd);
1202 if (json) {
1203 vty_out(vty, "%s%s", json_object_to_json_string_ext(json,
1204 JSON_C_TO_STRING_PRETTY), VTY_NEWLINE);
1205 json_object_free(json);
1206 }
1207
1208 return (ret);
1209 }
1210
1211 static int
1212 ldp_vty_get_af(const char *str, int *af)
1213 {
1214 if (str == NULL) {
1215 *af = AF_UNSPEC;
1216 return (0);
1217 } else if (strcmp(str, "ipv4") == 0) {
1218 *af = AF_INET;
1219 return (0);
1220 } else if (strcmp(str, "ipv6") == 0) {
1221 *af = AF_INET6;
1222 return (0);
1223 }
1224
1225 return (-1);
1226 }
1227
1228 int
1229 ldp_vty_show_binding(struct vty *vty, struct vty_arg *args[])
1230 {
1231 struct imsgbuf ibuf;
1232 struct show_params params;
1233 const char *af_str;
1234 int af;
1235
1236 if (ldp_vty_connect(&ibuf) < 0)
1237 return (CMD_WARNING);
1238
1239 af_str = vty_get_arg_value(args, "address-family");
1240 if (ldp_vty_get_af(af_str, &af) < 0)
1241 return (CMD_ERR_NO_MATCH);
1242
1243 memset(&params, 0, sizeof(params));
1244 params.family = af;
1245 params.detail = vty_get_arg_value(args, "detail") ? 1 : 0;
1246 params.json = vty_get_arg_value(args, "json") ? 1 : 0;
1247
1248 if (!params.detail && !params.json)
1249 vty_out(vty, "%-4s %-20s %-15s %-11s %-13s %6s\n", "AF",
1250 "Destination", "Nexthop", "Local Label", "Remote Label",
1251 "In Use");
1252
1253 imsg_compose(&ibuf, IMSG_CTL_SHOW_LIB, 0, 0, -1, NULL, 0);
1254 return (ldp_vty_dispatch(vty, &ibuf, SHOW_LIB, &params));
1255 }
1256
1257 int
1258 ldp_vty_show_discovery(struct vty *vty, struct vty_arg *args[])
1259 {
1260 struct imsgbuf ibuf;
1261 struct show_params params;
1262 const char *af_str;
1263 int af;
1264
1265 if (ldp_vty_connect(&ibuf) < 0)
1266 return (CMD_WARNING);
1267
1268 af_str = vty_get_arg_value(args, "address-family");
1269 if (ldp_vty_get_af(af_str, &af) < 0)
1270 return (CMD_ERR_NO_MATCH);
1271
1272 memset(&params, 0, sizeof(params));
1273 params.family = af;
1274 params.detail = vty_get_arg_value(args, "detail") ? 1 : 0;
1275 params.json = vty_get_arg_value(args, "json") ? 1 : 0;
1276
1277 if (!params.detail && !params.json)
1278 vty_out(vty, "%-4s %-15s %-8s %-15s %9s\n",
1279 "AF", "ID", "Type", "Source", "Holdtime");
1280
1281 if (params.detail)
1282 imsg_compose(&ibuf, IMSG_CTL_SHOW_DISCOVERY_DTL, 0, 0, -1,
1283 NULL, 0);
1284 else
1285 imsg_compose(&ibuf, IMSG_CTL_SHOW_DISCOVERY, 0, 0, -1, NULL, 0);
1286 return (ldp_vty_dispatch(vty, &ibuf, SHOW_DISC, &params));
1287 }
1288
1289 int
1290 ldp_vty_show_interface(struct vty *vty, struct vty_arg *args[])
1291 {
1292 struct imsgbuf ibuf;
1293 struct show_params params;
1294 unsigned int ifidx = 0;
1295 const char *af_str;
1296 int af;
1297
1298 if (ldp_vty_connect(&ibuf) < 0)
1299 return (CMD_WARNING);
1300
1301 af_str = vty_get_arg_value(args, "address-family");
1302 if (ldp_vty_get_af(af_str, &af) < 0)
1303 return (CMD_ERR_NO_MATCH);
1304
1305 memset(&params, 0, sizeof(params));
1306 params.family = af;
1307 params.json = vty_get_arg_value(args, "json") ? 1 : 0;
1308
1309 /* header */
1310 if (!params.json) {
1311 vty_out(vty, "%-4s %-11s %-6s %-8s %-12s %3s%s", "AF",
1312 "Interface", "State", "Uptime", "Hello Timers", "ac",
1313 VTY_NEWLINE);
1314 }
1315
1316 imsg_compose(&ibuf, IMSG_CTL_SHOW_INTERFACE, 0, 0, -1, &ifidx,
1317 sizeof(ifidx));
1318 return (ldp_vty_dispatch(vty, &ibuf, SHOW_IFACE, &params));
1319 }
1320
1321 int
1322 ldp_vty_show_neighbor(struct vty *vty, struct vty_arg *args[])
1323 {
1324 struct imsgbuf ibuf;
1325 struct show_params params;
1326
1327 if (ldp_vty_connect(&ibuf) < 0)
1328 return (CMD_WARNING);
1329
1330 memset(&params, 0, sizeof(params));
1331 params.detail = vty_get_arg_value(args, "detail") ? 1 : 0;
1332 params.json = vty_get_arg_value(args, "json") ? 1 : 0;
1333
1334 if (!params.detail && !params.json)
1335 vty_out(vty, "%-4s %-15s %-11s %-15s %8s\n",
1336 "AF", "ID", "State", "Remote Address", "Uptime");
1337
1338 imsg_compose(&ibuf, IMSG_CTL_SHOW_NBR, 0, 0, -1, NULL, 0);
1339 return (ldp_vty_dispatch(vty, &ibuf, SHOW_NBR, &params));
1340 }
1341
1342 int
1343 ldp_vty_show_atom_binding(struct vty *vty, struct vty_arg *args[])
1344 {
1345 struct imsgbuf ibuf;
1346 struct show_params params;
1347
1348 if (ldp_vty_connect(&ibuf) < 0)
1349 return (CMD_WARNING);
1350
1351 memset(&params, 0, sizeof(params));
1352 params.json = vty_get_arg_value(args, "json") ? 1 : 0;
1353
1354 imsg_compose(&ibuf, IMSG_CTL_SHOW_L2VPN_BINDING, 0, 0, -1, NULL, 0);
1355 return (ldp_vty_dispatch(vty, &ibuf, SHOW_L2VPN_BINDING, &params));
1356 }
1357
1358 int
1359 ldp_vty_show_atom_vc(struct vty *vty, struct vty_arg *args[])
1360 {
1361 struct imsgbuf ibuf;
1362 struct show_params params;
1363
1364 if (ldp_vty_connect(&ibuf) < 0)
1365 return (CMD_WARNING);
1366
1367 memset(&params, 0, sizeof(params));
1368 params.json = vty_get_arg_value(args, "json") ? 1 : 0;
1369
1370 if (!params.json) {
1371 /* header */
1372 vty_out(vty, "%-9s %-15s %-10s %-16s %-10s%s",
1373 "Interface", "Peer ID", "VC ID", "Name", "Status",
1374 VTY_NEWLINE);
1375 vty_out(vty, "%-9s %-15s %-10s %-16s %-10s%s",
1376 "---------", "---------------", "----------",
1377 "----------------", "----------", VTY_NEWLINE);
1378 }
1379
1380 imsg_compose(&ibuf, IMSG_CTL_SHOW_L2VPN_PW, 0, 0, -1, NULL, 0);
1381 return (ldp_vty_dispatch(vty, &ibuf, SHOW_L2VPN_PW, &params));
1382 }
1383
1384 int
1385 ldp_vty_clear_nbr(struct vty *vty, struct vty_arg *args[])
1386 {
1387 struct imsgbuf ibuf;
1388 const char *addr_str;
1389 struct ctl_nbr nbr;
1390
1391 addr_str = vty_get_arg_value(args, "addr");
1392
1393 memset(&nbr, 0, sizeof(nbr));
1394 if (addr_str &&
1395 (ldp_get_address(addr_str, &nbr.af, &nbr.raddr) == -1 ||
1396 bad_addr(nbr.af, &nbr.raddr))) {
1397 vty_out(vty, "%% Malformed address%s", VTY_NEWLINE);
1398 return (CMD_WARNING);
1399 }
1400
1401 if (ldp_vty_connect(&ibuf) < 0)
1402 return (CMD_WARNING);
1403
1404 imsg_compose(&ibuf, IMSG_CTL_CLEAR_NBR, 0, 0, -1, &nbr, sizeof(nbr));
1405
1406 while (ibuf.w.queued)
1407 if (msgbuf_write(&ibuf.w) <= 0 && errno != EAGAIN) {
1408 log_warn("write error");
1409 close(ibuf.fd);
1410 return (CMD_WARNING);
1411 }
1412
1413 close(ibuf.fd);
1414
1415 return (CMD_SUCCESS);
1416 }