]> git.proxmox.com Git - mirror_frr.git/blob - ldpd/ldp_vty_exec.c
Merge branch 'stable/2.0'
[mirror_frr.git] / ldpd / ldp_vty_exec.c
1 /*
2 * Copyright (C) 2016 by Open Source Routing.
3 *
4 * This file is part of GNU Zebra.
5 *
6 * GNU Zebra is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; either version 2, or (at your option) any
9 * later version.
10 *
11 * GNU Zebra is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
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 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 void show_discovery_adj(struct vty *, char *,
59 struct ctl_adj *);
60 static int show_discovery_msg(struct vty *, struct imsg *,
61 struct show_params *);
62 static void show_discovery_adj_json(json_object *,
63 struct ctl_adj *);
64 static int show_discovery_msg_json(struct imsg *,
65 struct show_params *, json_object *);
66 static void show_nbr_adj(struct vty *, char *, struct ctl_adj *);
67 static int show_nbr_msg(struct vty *, struct imsg *,
68 struct show_params *);
69 static void show_nbr_adj_json(struct ctl_adj *, json_object *);
70 static int show_nbr_msg_json(struct imsg *, struct show_params *,
71 json_object *);
72 static int show_lib_msg(struct vty *, struct imsg *,
73 struct show_params *);
74 static int show_lib_msg_json(struct imsg *, struct show_params *,
75 json_object *);
76 static int show_l2vpn_binding_msg(struct vty *, struct imsg *,
77 struct show_params *);
78 static int show_l2vpn_binding_msg_json(struct imsg *,
79 struct show_params *, json_object *);
80 static int show_l2vpn_pw_msg(struct vty *, struct imsg *,
81 struct show_params *);
82 static int show_l2vpn_pw_msg_json(struct imsg *,
83 struct show_params *, json_object *);
84 static int ldp_vty_connect(struct imsgbuf *);
85 static int ldp_vty_dispatch_msg(struct vty *, struct imsg *,
86 enum show_command, struct show_params *,
87 json_object *);
88 static int ldp_vty_dispatch(struct vty *, struct imsgbuf *,
89 enum show_command, struct show_params *);
90 static int ldp_vty_get_af(const char *, int *);
91
92 static int
93 show_interface_msg(struct vty *vty, struct imsg *imsg,
94 struct show_params *params)
95 {
96 struct ctl_iface *iface;
97 char timers[BUFSIZ];
98
99 switch (imsg->hdr.type) {
100 case IMSG_CTL_SHOW_INTERFACE:
101 iface = imsg->data;
102
103 if (params->family != AF_UNSPEC && params->family != iface->af)
104 break;
105
106 snprintf(timers, sizeof(timers), "%u/%u",
107 iface->hello_interval, iface->hello_holdtime);
108
109 vty_out(vty, "%-4s %-11s %-6s %-8s %-12s %3u%s",
110 af_name(iface->af), iface->name,
111 if_state_name(iface->state), iface->uptime == 0 ?
112 "00:00:00" : log_time(iface->uptime), timers,
113 iface->adj_cnt, VTY_NEWLINE);
114 break;
115 case IMSG_CTL_END:
116 vty_out(vty, "%s", VTY_NEWLINE);
117 return (1);
118 default:
119 break;
120 }
121
122 return (0);
123 }
124
125 static int
126 show_interface_msg_json(struct imsg *imsg, struct show_params *params,
127 json_object *json)
128 {
129 struct ctl_iface *iface;
130 json_object *json_iface;
131 char key_name[64];
132
133 switch (imsg->hdr.type) {
134 case IMSG_CTL_SHOW_INTERFACE:
135 iface = imsg->data;
136
137 if (params->family != AF_UNSPEC && params->family != iface->af)
138 break;
139
140 json_iface = json_object_new_object();
141 json_object_string_add(json_iface, "name", iface->name);
142 json_object_string_add(json_iface, "addressFamily",
143 af_name(iface->af));
144 json_object_string_add(json_iface, "state",
145 if_state_name(iface->state));
146 json_object_string_add(json_iface, "upTime",
147 log_time(iface->uptime));
148 json_object_int_add(json_iface, "helloInterval",
149 iface->hello_interval);
150 json_object_int_add(json_iface, "helloHoldtime",
151 iface->hello_holdtime);
152 json_object_int_add(json_iface, "adjacencyCount",
153 iface->adj_cnt);
154
155 sprintf(key_name, "%s: %s", iface->name, af_name(iface->af));
156 json_object_object_add(json, key_name, json_iface);
157 break;
158 case IMSG_CTL_END:
159 return (1);
160 default:
161 break;
162 }
163
164 return (0);
165 }
166
167 static void
168 show_discovery_adj(struct vty *vty, char *buffer, struct ctl_adj *adj)
169 {
170 size_t buflen = strlen(buffer);
171
172 snprintf(buffer + buflen, LDPBUFSIZ - buflen,
173 " LDP Id: %s:0, Transport address: %s%s",
174 inet_ntoa(adj->id), log_addr(adj->af,
175 &adj->trans_addr), VTY_NEWLINE);
176 buflen = strlen(buffer);
177 snprintf(buffer + buflen, LDPBUFSIZ - buflen,
178 " Hold time: %u sec%s", adj->holdtime, VTY_NEWLINE);
179 }
180
181 static int
182 show_discovery_msg(struct vty *vty, struct imsg *imsg,
183 struct show_params *params)
184 {
185 struct ctl_adj *adj;
186 struct ctl_disc_if *iface;
187 struct ctl_disc_tnbr *tnbr;
188 struct in_addr rtr_id;
189 union ldpd_addr *trans_addr;
190 size_t buflen;
191 static char ifaces_buffer[LDPBUFSIZ];
192 static char tnbrs_buffer[LDPBUFSIZ];
193
194 switch (imsg->hdr.type) {
195 case IMSG_CTL_SHOW_DISCOVERY:
196 ifaces_buffer[0] = '\0';
197 tnbrs_buffer[0] = '\0';
198 break;
199 case IMSG_CTL_SHOW_DISC_IFACE:
200 iface = imsg->data;
201
202 if (params->family != AF_UNSPEC &&
203 ((params->family == AF_INET && !iface->active_v4) ||
204 (params->family == AF_INET6 && !iface->active_v6)))
205 break;
206
207 buflen = strlen(ifaces_buffer);
208 snprintf(ifaces_buffer + buflen, LDPBUFSIZ - buflen,
209 " %s: %s%s", iface->name, (iface->no_adj) ?
210 "xmit" : "xmit/recv", VTY_NEWLINE);
211 break;
212 case IMSG_CTL_SHOW_DISC_TNBR:
213 tnbr = imsg->data;
214
215 if (params->family != AF_UNSPEC && params->family != tnbr->af)
216 break;
217
218 trans_addr = &(ldp_af_conf_get(ldpd_conf,
219 tnbr->af))->trans_addr;
220 buflen = strlen(tnbrs_buffer);
221 snprintf(tnbrs_buffer + buflen, LDPBUFSIZ - buflen,
222 " %s -> %s: %s%s", log_addr(tnbr->af, trans_addr),
223 log_addr(tnbr->af, &tnbr->addr), (tnbr->no_adj) ? "xmit" :
224 "xmit/recv", VTY_NEWLINE);
225 break;
226 case IMSG_CTL_SHOW_DISC_ADJ:
227 adj = imsg->data;
228
229 if (params->family != AF_UNSPEC && params->family != adj->af)
230 break;
231
232 switch(adj->type) {
233 case HELLO_LINK:
234 show_discovery_adj(vty, ifaces_buffer, adj);
235 break;
236 case HELLO_TARGETED:
237 show_discovery_adj(vty, tnbrs_buffer, adj);
238 break;
239 }
240 break;
241 case IMSG_CTL_END:
242 rtr_id.s_addr = ldp_rtr_id_get(ldpd_conf);
243 vty_out(vty, "Local LDP Identifier: %s:0%s", inet_ntoa(rtr_id),
244 VTY_NEWLINE);
245 vty_out(vty, "Discovery Sources:%s", VTY_NEWLINE);
246 vty_out(vty, " Interfaces:%s", VTY_NEWLINE);
247 vty_out(vty, "%s", ifaces_buffer);
248 vty_out(vty, " Targeted Hellos:%s", VTY_NEWLINE);
249 vty_out(vty, "%s", tnbrs_buffer);
250 vty_out(vty, "%s", VTY_NEWLINE);
251 return (1);
252 default:
253 break;
254 }
255
256 return (0);
257 }
258
259 static void
260 show_discovery_adj_json(json_object *json, struct ctl_adj *adj)
261 {
262 json_object *json_adj;
263 json_object *json_array;
264
265 json_object_object_get_ex(json, "adjacencies", &json_array);
266 if (!json_array) {
267 json_array = json_object_new_array();
268 json_object_object_add(json, "adjacencies", json_array);
269 }
270
271 json_adj = json_object_new_object();
272 json_object_string_add(json_adj, "id", inet_ntoa(adj->id));
273 json_object_string_add(json_adj, "transportAddress", log_addr(adj->af,
274 &adj->trans_addr));
275 json_object_int_add(json_adj, "holdtime", adj->holdtime);
276 json_object_array_add(json_array, json_adj);
277 }
278
279 static int
280 show_discovery_msg_json(struct imsg *imsg, struct show_params *params,
281 json_object *json)
282 {
283 struct ctl_adj *adj;
284 struct ctl_disc_if *iface;
285 struct ctl_disc_tnbr *tnbr;
286 struct in_addr rtr_id;
287 union ldpd_addr *trans_addr;
288 json_object *json_interface;
289 json_object *json_target;
290 static json_object *json_interfaces;
291 static json_object *json_targets;
292 static json_object *json_container;
293
294 switch (imsg->hdr.type) {
295 case IMSG_CTL_SHOW_DISCOVERY:
296 rtr_id.s_addr = ldp_rtr_id_get(ldpd_conf);
297 json_object_string_add(json, "id", inet_ntoa(rtr_id));
298 json_interfaces = json_object_new_object();
299 json_object_object_add(json, "interfaces", json_interfaces);
300 json_targets = json_object_new_object();
301 json_object_object_add(json, "targetedHellos", json_targets);
302 json_container = NULL;
303 break;
304 case IMSG_CTL_SHOW_DISC_IFACE:
305 iface = imsg->data;
306
307 if (params->family != AF_UNSPEC &&
308 ((params->family == AF_INET && !iface->active_v4) ||
309 (params->family == AF_INET6 && !iface->active_v6)))
310 break;
311
312 json_interface = json_object_new_object();
313 json_object_boolean_true_add(json_interface, "transmit");
314 if (!iface->no_adj)
315 json_object_boolean_true_add(json_interface, "receive");
316
317 json_object_object_add(json_interfaces, iface->name,
318 json_interface);
319 json_container = json_interface;
320 break;
321 case IMSG_CTL_SHOW_DISC_TNBR:
322 tnbr = imsg->data;
323
324 if (params->family != AF_UNSPEC && params->family != tnbr->af)
325 break;
326
327 trans_addr = &(ldp_af_conf_get(ldpd_conf, tnbr->af))->trans_addr;
328
329 json_target = json_object_new_object();
330 json_object_string_add(json_target, "sourceAddress",
331 log_addr(tnbr->af, trans_addr));
332 json_object_boolean_true_add(json_target, "transmit");
333 if (!tnbr->no_adj)
334 json_object_boolean_true_add(json_target, "receive");
335
336 json_object_object_add(json_targets, log_addr(tnbr->af,
337 &tnbr->addr), json_target);
338 json_container = json_target;
339 break;
340 case IMSG_CTL_SHOW_DISC_ADJ:
341 adj = imsg->data;
342
343 if (params->family != AF_UNSPEC && params->family != adj->af)
344 break;
345
346 switch(adj->type) {
347 case HELLO_LINK:
348 show_discovery_adj_json(json_container, adj);
349 break;
350 case HELLO_TARGETED:
351 show_discovery_adj_json(json_container, adj);
352 break;
353 }
354 break;
355 case IMSG_CTL_END:
356 return (1);
357 default:
358 break;
359 }
360
361 return (0);
362 }
363
364 static void
365 show_nbr_adj(struct vty *vty, char *buffer, struct ctl_adj *adj)
366 {
367 size_t buflen = strlen(buffer);
368
369 switch (adj->type) {
370 case HELLO_LINK:
371 snprintf(buffer + buflen, LDPBUFSIZ - buflen,
372 " Interface: %s%s", adj->ifname, VTY_NEWLINE);
373 break;
374 case HELLO_TARGETED:
375 snprintf(buffer + buflen, LDPBUFSIZ - buflen,
376 " Targeted Hello: %s%s", log_addr(adj->af,
377 &adj->src_addr), VTY_NEWLINE);
378 break;
379 }
380 }
381
382 static int
383 show_nbr_msg(struct vty *vty, struct imsg *imsg, struct show_params *params)
384 {
385 struct ctl_nbr *nbr;
386 struct ctl_adj *adj;
387 static char v4adjs_buffer[LDPBUFSIZ];
388 static char v6adjs_buffer[LDPBUFSIZ];
389
390 switch (imsg->hdr.type) {
391 case IMSG_CTL_SHOW_NBR:
392 nbr = imsg->data;
393
394 v4adjs_buffer[0] = '\0';
395 v6adjs_buffer[0] = '\0';
396 vty_out(vty, "Peer LDP Identifier: %s:0%s", inet_ntoa(nbr->id),
397 VTY_NEWLINE);
398 vty_out(vty, " TCP connection: %s:%u - %s:%u%s",
399 log_addr(nbr->af, &nbr->laddr), ntohs(nbr->lport),
400 log_addr(nbr->af, &nbr->raddr), ntohs(nbr->rport),
401 VTY_NEWLINE);
402 vty_out(vty, " Session Holdtime: %u sec%s", nbr->holdtime,
403 VTY_NEWLINE);
404 vty_out(vty, " State: %s; Downstream-Unsolicited%s",
405 nbr_state_name(nbr->nbr_state), VTY_NEWLINE);
406 vty_out(vty, " Up time: %s%s", log_time(nbr->uptime),
407 VTY_NEWLINE);
408 break;
409 case IMSG_CTL_SHOW_NBR_DISC:
410 adj = imsg->data;
411
412 switch (adj->af) {
413 case AF_INET:
414 show_nbr_adj(vty, v4adjs_buffer, adj);
415 break;
416 case AF_INET6:
417 show_nbr_adj(vty, v6adjs_buffer, adj);
418 break;
419 default:
420 fatalx("show_nbr_msg: unknown af");
421 }
422 break;
423 case IMSG_CTL_SHOW_NBR_END:
424 vty_out(vty, " LDP Discovery Sources:%s", VTY_NEWLINE);
425 if (v4adjs_buffer[0] != '\0') {
426 vty_out(vty, " IPv4:%s", VTY_NEWLINE);
427 vty_out(vty, "%s", v4adjs_buffer);
428 }
429 if (v6adjs_buffer[0] != '\0') {
430 vty_out(vty, " IPv6:%s", VTY_NEWLINE);
431 vty_out(vty, "%s", v6adjs_buffer);
432 }
433 vty_out(vty, "%s", VTY_NEWLINE);
434 break;
435 case IMSG_CTL_END:
436 return (1);
437 default:
438 break;
439 }
440
441 return (0);
442 }
443
444 static void
445 show_nbr_adj_json(struct ctl_adj *adj, json_object *adj_list)
446 {
447 char adj_string[128];
448
449 switch (adj->type) {
450 case HELLO_LINK:
451 strlcpy(adj_string, "interface: ", sizeof(adj_string));
452 strlcat(adj_string, adj->ifname, sizeof(adj_string));
453 break;
454 case HELLO_TARGETED:
455 strlcpy(adj_string, "targetedHello: ", sizeof(adj_string));
456 strlcat(adj_string, log_addr(adj->af, &adj->src_addr),
457 sizeof(adj_string));
458 break;
459 }
460
461 json_object_array_add(adj_list, json_object_new_string(adj_string));
462 }
463
464 static int
465 show_nbr_msg_json(struct imsg *imsg, struct show_params *params,
466 json_object *json)
467 {
468 struct ctl_nbr *nbr;
469 struct ctl_adj *adj;
470 json_object *json_nbr;
471 static json_object *json_nbr_sources;
472 static json_object *json_v4adjs;
473 static json_object *json_v6adjs;
474
475 switch (imsg->hdr.type) {
476 case IMSG_CTL_SHOW_NBR:
477 nbr = imsg->data;
478
479 json_nbr = json_object_new_object();
480 json_object_string_add(json_nbr, "peerId", inet_ntoa(nbr->id));
481 json_object_string_add(json_nbr, "tcpLocalAddress",
482 log_addr(nbr->af, &nbr->laddr));
483 json_object_int_add(json_nbr, "tcpLocalPort",
484 ntohs(nbr->lport));
485 json_object_string_add(json_nbr, "tcpRemoteAddress",
486 log_addr(nbr->af, &nbr->raddr));
487 json_object_int_add(json_nbr, "tcpRemotePort",
488 ntohs(nbr->rport));
489 json_object_int_add(json_nbr, "holdtime", nbr->holdtime);
490 json_object_string_add(json_nbr, "state",
491 nbr_state_name(nbr->nbr_state));
492 json_object_string_add(json_nbr, "upTime",
493 log_time(nbr->uptime));
494 json_object_object_add(json, inet_ntoa(nbr->id), json_nbr);
495
496 json_nbr_sources = json_object_new_object();
497 json_object_object_add(json_nbr, "discoverySources",
498 json_nbr_sources);
499 json_v4adjs = NULL;
500 json_v6adjs = NULL;
501 break;
502 case IMSG_CTL_SHOW_NBR_DISC:
503 adj = imsg->data;
504
505 switch (adj->af) {
506 case AF_INET:
507 if (!json_v4adjs) {
508 json_v4adjs = json_object_new_array();
509 json_object_object_add(json_nbr_sources, "ipv4",
510 json_v4adjs);
511 }
512 show_nbr_adj_json(adj, json_v4adjs);
513 break;
514 case AF_INET6:
515 if (!json_v6adjs) {
516 json_v6adjs = json_object_new_array();
517 json_object_object_add(json_nbr_sources, "ipv6",
518 json_v6adjs);
519 }
520 show_nbr_adj_json(adj, json_v6adjs);
521 break;
522 default:
523 fatalx("show_nbr_msg_json: unknown af");
524 }
525 break;
526 case IMSG_CTL_SHOW_NBR_END:
527 break;
528 case IMSG_CTL_END:
529 return (1);
530 default:
531 break;
532 }
533
534 return (0);
535 }
536
537 static int
538 show_lib_msg(struct vty *vty, struct imsg *imsg, struct show_params *params)
539 {
540 struct ctl_rt *rt;
541 char dstnet[BUFSIZ];
542
543 switch (imsg->hdr.type) {
544 case IMSG_CTL_SHOW_LIB:
545 rt = imsg->data;
546
547 if (params->family != AF_UNSPEC && params->family != rt->af)
548 break;
549
550 snprintf(dstnet, sizeof(dstnet), "%s/%d",
551 log_addr(rt->af, &rt->prefix), rt->prefixlen);
552
553 if (rt->first) {
554 vty_out(vty, "%s%s", dstnet, VTY_NEWLINE);
555 vty_out(vty, "%-8sLocal binding: label: %s%s", "",
556 log_label(rt->local_label), VTY_NEWLINE);
557
558 if (rt->remote_label != NO_LABEL) {
559 vty_out(vty, "%-8sRemote bindings:%s", "",
560 VTY_NEWLINE);
561 vty_out(vty, "%-12sPeer Label%s",
562 "", VTY_NEWLINE);
563 vty_out(vty, "%-12s----------------- "
564 "---------%s", "", VTY_NEWLINE);
565 } else
566 vty_out(vty, "%-8sNo remote bindings%s", "",
567 VTY_NEWLINE);
568 }
569 if (rt->remote_label != NO_LABEL)
570 vty_out(vty, "%12s%-20s%s%s", "", inet_ntoa(rt->nexthop),
571 log_label(rt->remote_label), VTY_NEWLINE);
572 break;
573 case IMSG_CTL_END:
574 vty_out(vty, "%s", VTY_NEWLINE);
575 return (1);
576 default:
577 break;
578 }
579
580 return (0);
581 }
582
583 static int
584 show_lib_msg_json(struct imsg *imsg, struct show_params *params,
585 json_object *json)
586 {
587 struct ctl_rt *rt;
588 char dstnet[BUFSIZ];
589 static json_object *json_binding;
590 static json_object *json_remote_labels;
591 json_object *json_remote_label;
592
593 switch (imsg->hdr.type) {
594 case IMSG_CTL_SHOW_LIB:
595 rt = imsg->data;
596
597 if (params->family != AF_UNSPEC && params->family != rt->af)
598 break;
599
600 snprintf(dstnet, sizeof(dstnet), "%s/%d",
601 log_addr(rt->af, &rt->prefix), rt->prefixlen);
602
603 if (rt->first) {
604 json_binding = json_object_new_object();
605 json_object_string_add(json_binding, "localLabel",
606 log_label(rt->local_label));
607
608 json_remote_labels = json_object_new_array();
609 json_object_object_add(json_binding, "remoteLabels",
610 json_remote_labels);
611 json_object_object_add(json, dstnet, json_binding);
612 }
613
614 if (rt->remote_label != NO_LABEL) {
615 json_remote_label = json_object_new_object();
616 json_object_string_add(json_remote_label, "nexthop",
617 inet_ntoa(rt->nexthop));
618 json_object_string_add(json_remote_label, "label",
619 log_label(rt->remote_label));
620 json_object_array_add(json_remote_labels,
621 json_remote_label);
622 }
623 break;
624 case IMSG_CTL_END:
625 return (1);
626 default:
627 break;
628 }
629
630 return (0);
631 }
632
633 static int
634 show_l2vpn_binding_msg(struct vty *vty, struct imsg *imsg,
635 struct show_params *params)
636 {
637 struct ctl_pw *pw;
638
639 switch (imsg->hdr.type) {
640 case IMSG_CTL_SHOW_L2VPN_BINDING:
641 pw = imsg->data;
642
643 vty_out(vty, " Destination Address: %s, VC ID: %u%s",
644 inet_ntoa(pw->lsr_id), pw->pwid, VTY_NEWLINE);
645
646 /* local binding */
647 if (pw->local_label != NO_LABEL) {
648 vty_out(vty, " Local Label: %u%s", pw->local_label,
649 VTY_NEWLINE);
650 vty_out(vty, "%-8sCbit: %u, VC Type: %s, "
651 "GroupID: %u%s", "", pw->local_cword,
652 pw_type_name(pw->type), pw->local_gid,
653 VTY_NEWLINE);
654 vty_out(vty, "%-8sMTU: %u%s", "", pw->local_ifmtu,
655 VTY_NEWLINE);
656 } else
657 vty_out(vty, " Local Label: unassigned%s",
658 VTY_NEWLINE);
659
660 /* remote binding */
661 if (pw->remote_label != NO_LABEL) {
662 vty_out(vty, " Remote Label: %u%s",
663 pw->remote_label, VTY_NEWLINE);
664 vty_out(vty, "%-8sCbit: %u, VC Type: %s, "
665 "GroupID: %u%s", "", pw->remote_cword,
666 pw_type_name(pw->type), pw->remote_gid,
667 VTY_NEWLINE);
668 vty_out(vty, "%-8sMTU: %u%s", "", pw->remote_ifmtu,
669 VTY_NEWLINE);
670 } else
671 vty_out(vty, " Remote Label: unassigned%s",
672 VTY_NEWLINE);
673 break;
674 case IMSG_CTL_END:
675 vty_out(vty, "%s", VTY_NEWLINE);
676 return (1);
677 default:
678 break;
679 }
680
681 return (0);
682 }
683
684 static int
685 show_l2vpn_binding_msg_json(struct imsg *imsg, struct show_params *params,
686 json_object *json)
687 {
688 struct ctl_pw *pw;
689 json_object *json_pw;
690 char key_name[64];
691
692 switch (imsg->hdr.type) {
693 case IMSG_CTL_SHOW_L2VPN_BINDING:
694 pw = imsg->data;
695
696 json_pw = json_object_new_object();
697 json_object_string_add(json_pw, "destination",
698 inet_ntoa(pw->lsr_id));
699 json_object_int_add(json_pw, "vcId", pw->pwid);
700
701 /* local binding */
702 if (pw->local_label != NO_LABEL) {
703 json_object_int_add(json_pw, "localLabel",
704 pw->local_label);
705 json_object_int_add(json_pw, "localControlWord",
706 pw->local_cword);
707 json_object_string_add(json_pw, "localVcType",
708 pw_type_name(pw->type));
709 json_object_int_add(json_pw, "localGroupID",
710 pw->local_gid);
711 json_object_int_add(json_pw, "localIfMtu",
712 pw->local_ifmtu);
713 } else
714 json_object_string_add(json_pw, "localLabel",
715 "unassigned");
716
717 /* remote binding */
718 if (pw->remote_label != NO_LABEL) {
719 json_object_int_add(json_pw, "remoteLabel",
720 pw->remote_label);
721 json_object_int_add(json_pw, "remoteControlWord",
722 pw->remote_cword);
723 json_object_string_add(json_pw, "remoteVcType",
724 pw_type_name(pw->type));
725 json_object_int_add(json_pw, "remoteGroupID",
726 pw->remote_gid);
727 json_object_int_add(json_pw, "remoteIfMtu",
728 pw->remote_ifmtu);
729 } else
730 json_object_string_add(json_pw, "remoteLabel",
731 "unassigned");
732
733 sprintf(key_name, "%s: %u", inet_ntoa(pw->lsr_id), pw->pwid);
734 json_object_object_add(json, key_name, json_pw);
735 break;
736 case IMSG_CTL_END:
737 return (1);
738 default:
739 break;
740 }
741
742 return (0);
743 }
744
745 static int
746 show_l2vpn_pw_msg(struct vty *vty, struct imsg *imsg, struct show_params *params)
747 {
748 struct ctl_pw *pw;
749
750 switch (imsg->hdr.type) {
751 case IMSG_CTL_SHOW_L2VPN_PW:
752 pw = imsg->data;
753
754 vty_out(vty, "%-9s %-15s %-10u %-16s %-10s%s", pw->ifname,
755 inet_ntoa(pw->lsr_id), pw->pwid, pw->l2vpn_name,
756 (pw->status ? "UP" : "DOWN"), VTY_NEWLINE);
757 break;
758 case IMSG_CTL_END:
759 vty_out(vty, "%s", VTY_NEWLINE);
760 return (1);
761 default:
762 break;
763 }
764
765 return (0);
766 }
767
768 static int
769 show_l2vpn_pw_msg_json(struct imsg *imsg, struct show_params *params,
770 json_object *json)
771 {
772 struct ctl_pw *pw;
773 json_object *json_pw;
774
775 switch (imsg->hdr.type) {
776 case IMSG_CTL_SHOW_L2VPN_PW:
777 pw = imsg->data;
778
779 json_pw = json_object_new_object();
780 json_object_string_add(json_pw, "peerId", inet_ntoa(pw->lsr_id));
781 json_object_int_add(json_pw, "vcId", pw->pwid);
782 json_object_string_add(json_pw, "VpnName", pw->l2vpn_name);
783 if (pw->status)
784 json_object_string_add(json_pw, "status", "up");
785 else
786 json_object_string_add(json_pw, "status", "down");
787 json_object_object_add(json, pw->ifname, json_pw);
788 break;
789 case IMSG_CTL_END:
790 return (1);
791 default:
792 break;
793 }
794
795 return (0);
796 }
797
798 static int
799 ldp_vty_connect(struct imsgbuf *ibuf)
800 {
801 struct sockaddr_un s_un;
802 int ctl_sock;
803
804 /* connect to ldpd control socket */
805 if ((ctl_sock = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) {
806 log_warn("%s: socket", __func__);
807 return (-1);
808 }
809
810 memset(&s_un, 0, sizeof(s_un));
811 s_un.sun_family = AF_UNIX;
812 strlcpy(s_un.sun_path, ctl_sock_path, sizeof(s_un.sun_path));
813 if (connect(ctl_sock, (struct sockaddr *)&s_un, sizeof(s_un)) == -1) {
814 log_warn("%s: connect: %s", __func__, ctl_sock_path);
815 close(ctl_sock);
816 return (-1);
817 }
818
819 imsg_init(ibuf, ctl_sock);
820
821 return (0);
822 }
823
824 static int
825 ldp_vty_dispatch_msg(struct vty *vty, struct imsg *imsg, enum show_command cmd,
826 struct show_params *params, json_object *json)
827 {
828 switch (cmd) {
829 case SHOW_IFACE:
830 if (json)
831 return (show_interface_msg_json(imsg, params, json));
832 return (show_interface_msg(vty, imsg, params));
833 case SHOW_DISC:
834 if (json)
835 return (show_discovery_msg_json(imsg, params, json));
836 return (show_discovery_msg(vty, imsg, params));
837 case SHOW_NBR:
838 if (json)
839 return (show_nbr_msg_json(imsg, params, json));
840 return (show_nbr_msg(vty, imsg, params));
841 case SHOW_LIB:
842 if (json)
843 return (show_lib_msg_json(imsg, params, json));
844 return (show_lib_msg(vty, imsg, params));
845 case SHOW_L2VPN_PW:
846 if (json)
847 return (show_l2vpn_pw_msg_json(imsg, params, json));
848 return (show_l2vpn_pw_msg(vty, imsg, params));
849 case SHOW_L2VPN_BINDING:
850 if (json)
851 return (show_l2vpn_binding_msg_json(imsg, params, json));
852 return (show_l2vpn_binding_msg(vty, imsg, params));
853 default:
854 return (0);
855 }
856 }
857
858 static int
859 ldp_vty_dispatch(struct vty *vty, struct imsgbuf *ibuf, enum show_command cmd,
860 struct show_params *params)
861 {
862 struct imsg imsg;
863 int n, done = 0, ret = CMD_SUCCESS;
864 json_object *json = NULL;
865
866 while (ibuf->w.queued)
867 if (msgbuf_write(&ibuf->w) <= 0 && errno != EAGAIN) {
868 log_warn("write error");
869 close(ibuf->fd);
870 return (CMD_WARNING);
871 }
872
873 if (params->json)
874 json = json_object_new_object();
875
876 while (!done) {
877 if ((n = imsg_read(ibuf)) == -1 && errno != EAGAIN) {
878 log_warnx("imsg_read error");
879 ret = CMD_WARNING;
880 goto done;
881 }
882 if (n == 0) {
883 log_warnx("pipe closed");
884 ret = CMD_WARNING;
885 goto done;
886 }
887
888 while (!done) {
889 if ((n = imsg_get(ibuf, &imsg)) == -1) {
890 log_warnx("imsg_get error");
891 ret = CMD_WARNING;
892 goto done;
893 }
894 if (n == 0)
895 break;
896 done = ldp_vty_dispatch_msg(vty, &imsg, cmd, params,
897 json);
898 imsg_free(&imsg);
899 }
900 }
901
902 done:
903 close(ibuf->fd);
904 if (json) {
905 vty_out(vty, "%s%s", json_object_to_json_string_ext(json,
906 JSON_C_TO_STRING_PRETTY), VTY_NEWLINE);
907 json_object_free(json);
908 }
909
910 return (ret);
911 }
912
913 static int
914 ldp_vty_get_af(const char *str, int *af)
915 {
916 if (str == NULL) {
917 *af = AF_UNSPEC;
918 return (0);
919 } else if (strcmp(str, "ipv4") == 0) {
920 *af = AF_INET;
921 return (0);
922 } else if (strcmp(str, "ipv6") == 0) {
923 *af = AF_INET6;
924 return (0);
925 }
926
927 return (-1);
928 }
929
930 int
931 ldp_vty_show_binding(struct vty *vty, struct vty_arg *args[])
932 {
933 struct imsgbuf ibuf;
934 struct show_params params;
935 const char *af_str;
936 int af;
937
938 if (ldp_vty_connect(&ibuf) < 0)
939 return (CMD_WARNING);
940
941 af_str = vty_get_arg_value(args, "address-family");
942 if (ldp_vty_get_af(af_str, &af) < 0)
943 return (CMD_ERR_NO_MATCH);
944
945 memset(&params, 0, sizeof(params));
946 params.family = af;
947 params.json = vty_get_arg_value(args, "json") ? 1 : 0;
948
949 imsg_compose(&ibuf, IMSG_CTL_SHOW_LIB, 0, 0, -1, NULL, 0);
950 return (ldp_vty_dispatch(vty, &ibuf, SHOW_LIB, &params));
951 }
952
953 int
954 ldp_vty_show_discovery(struct vty *vty, struct vty_arg *args[])
955 {
956 struct imsgbuf ibuf;
957 struct show_params params;
958 const char *af_str;
959 int af;
960
961 if (ldp_vty_connect(&ibuf) < 0)
962 return (CMD_WARNING);
963
964 af_str = vty_get_arg_value(args, "address-family");
965 if (ldp_vty_get_af(af_str, &af) < 0)
966 return (CMD_ERR_NO_MATCH);
967
968 memset(&params, 0, sizeof(params));
969 params.family = af;
970 params.json = vty_get_arg_value(args, "json") ? 1 : 0;
971
972 imsg_compose(&ibuf, IMSG_CTL_SHOW_DISCOVERY, 0, 0, -1, NULL, 0);
973 return (ldp_vty_dispatch(vty, &ibuf, SHOW_DISC, &params));
974 }
975
976 int
977 ldp_vty_show_interface(struct vty *vty, struct vty_arg *args[])
978 {
979 struct imsgbuf ibuf;
980 struct show_params params;
981 unsigned int ifidx = 0;
982 const char *af_str;
983 int af;
984
985 if (ldp_vty_connect(&ibuf) < 0)
986 return (CMD_WARNING);
987
988 af_str = vty_get_arg_value(args, "address-family");
989 if (ldp_vty_get_af(af_str, &af) < 0)
990 return (CMD_ERR_NO_MATCH);
991
992 memset(&params, 0, sizeof(params));
993 params.family = af;
994 params.json = vty_get_arg_value(args, "json") ? 1 : 0;
995
996 /* header */
997 if (!params.json) {
998 vty_out(vty, "%-4s %-11s %-6s %-8s %-12s %3s%s", "AF",
999 "Interface", "State", "Uptime", "Hello Timers", "ac",
1000 VTY_NEWLINE);
1001 }
1002
1003 imsg_compose(&ibuf, IMSG_CTL_SHOW_INTERFACE, 0, 0, -1, &ifidx,
1004 sizeof(ifidx));
1005 return (ldp_vty_dispatch(vty, &ibuf, SHOW_IFACE, &params));
1006 }
1007
1008 int
1009 ldp_vty_show_neighbor(struct vty *vty, struct vty_arg *args[])
1010 {
1011 struct imsgbuf ibuf;
1012 struct show_params params;
1013
1014 if (ldp_vty_connect(&ibuf) < 0)
1015 return (CMD_WARNING);
1016
1017 memset(&params, 0, sizeof(params));
1018 params.json = vty_get_arg_value(args, "json") ? 1 : 0;
1019
1020 imsg_compose(&ibuf, IMSG_CTL_SHOW_NBR, 0, 0, -1, NULL, 0);
1021 return (ldp_vty_dispatch(vty, &ibuf, SHOW_NBR, &params));
1022 }
1023
1024 int
1025 ldp_vty_show_atom_binding(struct vty *vty, struct vty_arg *args[])
1026 {
1027 struct imsgbuf ibuf;
1028 struct show_params params;
1029
1030 if (ldp_vty_connect(&ibuf) < 0)
1031 return (CMD_WARNING);
1032
1033 memset(&params, 0, sizeof(params));
1034 params.json = vty_get_arg_value(args, "json") ? 1 : 0;
1035
1036 imsg_compose(&ibuf, IMSG_CTL_SHOW_L2VPN_BINDING, 0, 0, -1, NULL, 0);
1037 return (ldp_vty_dispatch(vty, &ibuf, SHOW_L2VPN_BINDING, &params));
1038 }
1039
1040 int
1041 ldp_vty_show_atom_vc(struct vty *vty, struct vty_arg *args[])
1042 {
1043 struct imsgbuf ibuf;
1044 struct show_params params;
1045
1046 if (ldp_vty_connect(&ibuf) < 0)
1047 return (CMD_WARNING);
1048
1049 memset(&params, 0, sizeof(params));
1050 params.json = vty_get_arg_value(args, "json") ? 1 : 0;
1051
1052 if (!params.json) {
1053 /* header */
1054 vty_out(vty, "%-9s %-15s %-10s %-16s %-10s%s",
1055 "Interface", "Peer ID", "VC ID", "Name", "Status",
1056 VTY_NEWLINE);
1057 vty_out(vty, "%-9s %-15s %-10s %-16s %-10s%s",
1058 "---------", "---------------", "----------",
1059 "----------------", "----------", VTY_NEWLINE);
1060 }
1061
1062 imsg_compose(&ibuf, IMSG_CTL_SHOW_L2VPN_PW, 0, 0, -1, NULL, 0);
1063 return (ldp_vty_dispatch(vty, &ibuf, SHOW_L2VPN_PW, &params));
1064 }
1065
1066 int
1067 ldp_vty_clear_nbr(struct vty *vty, struct vty_arg *args[])
1068 {
1069 struct imsgbuf ibuf;
1070 const char *addr_str;
1071 struct ctl_nbr nbr;
1072
1073 addr_str = vty_get_arg_value(args, "addr");
1074
1075 memset(&nbr, 0, sizeof(nbr));
1076 if (addr_str &&
1077 (ldp_get_address(addr_str, &nbr.af, &nbr.raddr) == -1 ||
1078 bad_addr(nbr.af, &nbr.raddr))) {
1079 vty_out(vty, "%% Malformed address%s", VTY_NEWLINE);
1080 return (CMD_WARNING);
1081 }
1082
1083 if (ldp_vty_connect(&ibuf) < 0)
1084 return (CMD_WARNING);
1085
1086 imsg_compose(&ibuf, IMSG_CTL_CLEAR_NBR, 0, 0, -1, &nbr, sizeof(nbr));
1087
1088 while (ibuf.w.queued)
1089 if (msgbuf_write(&ibuf.w) <= 0 && errno != EAGAIN) {
1090 log_warn("write error");
1091 close(ibuf.fd);
1092 return (CMD_WARNING);
1093 }
1094
1095 close(ibuf.fd);
1096
1097 return (CMD_SUCCESS);
1098 }