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