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