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