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