]>
Commit | Line | Data |
---|---|---|
eac6e3f0 RW |
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 | ||
31 | #include "command.h" | |
32 | #include "vty.h" | |
33 | #include "mpls.h" | |
34 | ||
35 | enum show_command { | |
36 | SHOW_DISC, | |
37 | SHOW_IFACE, | |
38 | SHOW_NBR, | |
39 | SHOW_LIB, | |
40 | SHOW_L2VPN_PW, | |
41 | SHOW_L2VPN_BINDING | |
42 | }; | |
43 | ||
44 | struct show_filter { | |
45 | int family; | |
46 | union ldpd_addr addr; | |
47 | uint8_t prefixlen; | |
48 | }; | |
49 | ||
50 | #define LDPBUFSIZ 65535 | |
51 | ||
52 | static int show_interface_msg(struct vty *, struct imsg *, | |
53 | struct show_filter *); | |
54 | static void show_discovery_adj(struct vty *, char *, | |
55 | struct ctl_adj *); | |
56 | static int show_discovery_msg(struct vty *, struct imsg *, | |
57 | struct show_filter *); | |
58 | static void show_nbr_adj(struct vty *, char *, struct ctl_adj *); | |
59 | static int show_nbr_msg(struct vty *, struct imsg *, | |
60 | struct show_filter *); | |
61 | static int show_lib_msg(struct vty *, struct imsg *, | |
62 | struct show_filter *); | |
63 | static int show_l2vpn_binding_msg(struct vty *, struct imsg *); | |
64 | static int show_l2vpn_pw_msg(struct vty *, struct imsg *); | |
65 | static int ldp_vty_connect(struct imsgbuf *); | |
66 | static int ldp_vty_dispatch(struct vty *, struct imsgbuf *, | |
67 | enum show_command, struct show_filter *); | |
68 | static int ldp_vty_get_af(const char *, int *); | |
69 | ||
70 | static int | |
71 | show_interface_msg(struct vty *vty, struct imsg *imsg, | |
72 | struct show_filter *filter) | |
73 | { | |
74 | struct ctl_iface *iface; | |
75 | char timers[BUFSIZ]; | |
76 | ||
77 | switch (imsg->hdr.type) { | |
78 | case IMSG_CTL_SHOW_INTERFACE: | |
79 | iface = imsg->data; | |
80 | ||
81 | if (filter->family != AF_UNSPEC && filter->family != iface->af) | |
82 | break; | |
83 | ||
84 | snprintf(timers, sizeof(timers), "%u/%u", | |
85 | iface->hello_interval, iface->hello_holdtime); | |
86 | ||
87 | vty_out(vty, "%-4s %-11s %-6s %-8s %-12s %3u%s", | |
88 | af_name(iface->af), iface->name, | |
89 | if_state_name(iface->state), iface->uptime == 0 ? | |
90 | "00:00:00" : log_time(iface->uptime), timers, | |
91 | iface->adj_cnt, VTY_NEWLINE); | |
92 | break; | |
93 | case IMSG_CTL_END: | |
94 | vty_out(vty, "%s", VTY_NEWLINE); | |
95 | return (1); | |
96 | default: | |
97 | break; | |
98 | } | |
99 | ||
100 | return (0); | |
101 | } | |
102 | ||
103 | static void | |
104 | show_discovery_adj(struct vty *vty, char *buffer, struct ctl_adj *adj) | |
105 | { | |
106 | size_t buflen = strlen(buffer); | |
107 | ||
108 | snprintf(buffer + buflen, LDPBUFSIZ - buflen, | |
109 | " LDP Id: %s:0, Transport address: %s%s", | |
110 | inet_ntoa(adj->id), log_addr(adj->af, | |
111 | &adj->trans_addr), VTY_NEWLINE); | |
112 | buflen = strlen(buffer); | |
113 | snprintf(buffer + buflen, LDPBUFSIZ - buflen, | |
114 | " Hold time: %u sec%s", adj->holdtime, VTY_NEWLINE); | |
115 | } | |
116 | ||
117 | static int | |
118 | show_discovery_msg(struct vty *vty, struct imsg *imsg, | |
119 | struct show_filter *filter) | |
120 | { | |
121 | struct ctl_adj *adj; | |
122 | struct ctl_disc_if *iface; | |
123 | struct ctl_disc_tnbr *tnbr; | |
124 | struct in_addr rtr_id; | |
125 | union ldpd_addr *trans_addr; | |
126 | size_t buflen; | |
127 | static char ifaces_buffer[LDPBUFSIZ]; | |
128 | static char tnbrs_buffer[LDPBUFSIZ]; | |
129 | ||
130 | switch (imsg->hdr.type) { | |
131 | case IMSG_CTL_SHOW_DISCOVERY: | |
132 | ifaces_buffer[0] = '\0'; | |
133 | tnbrs_buffer[0] = '\0'; | |
134 | break; | |
135 | case IMSG_CTL_SHOW_DISC_IFACE: | |
136 | iface = imsg->data; | |
137 | ||
138 | if (filter->family != AF_UNSPEC && | |
139 | ((filter->family == AF_INET && !iface->active_v4) || | |
140 | (filter->family == AF_INET6 && !iface->active_v6))) | |
141 | break; | |
142 | ||
143 | buflen = strlen(ifaces_buffer); | |
144 | snprintf(ifaces_buffer + buflen, LDPBUFSIZ - buflen, | |
145 | " %s: %s%s", iface->name, (iface->no_adj) ? | |
146 | "xmit" : "xmit/recv", VTY_NEWLINE); | |
147 | break; | |
148 | case IMSG_CTL_SHOW_DISC_TNBR: | |
149 | tnbr = imsg->data; | |
150 | ||
151 | if (filter->family != AF_UNSPEC && filter->family != tnbr->af) | |
152 | break; | |
153 | ||
154 | trans_addr = &(ldp_af_conf_get(ldpd_conf, | |
155 | tnbr->af))->trans_addr; | |
156 | buflen = strlen(tnbrs_buffer); | |
157 | snprintf(tnbrs_buffer + buflen, LDPBUFSIZ - buflen, | |
158 | " %s -> %s: %s%s", log_addr(tnbr->af, trans_addr), | |
159 | log_addr(tnbr->af, &tnbr->addr), (tnbr->no_adj) ? "xmit" : | |
160 | "xmit/recv", VTY_NEWLINE); | |
161 | break; | |
162 | case IMSG_CTL_SHOW_DISC_ADJ: | |
163 | adj = imsg->data; | |
164 | ||
165 | if (filter->family != AF_UNSPEC && filter->family != adj->af) | |
166 | break; | |
167 | ||
168 | switch(adj->type) { | |
169 | case HELLO_LINK: | |
170 | show_discovery_adj(vty, ifaces_buffer, adj); | |
171 | break; | |
172 | case HELLO_TARGETED: | |
173 | show_discovery_adj(vty, tnbrs_buffer, adj); | |
174 | break; | |
175 | } | |
176 | break; | |
177 | case IMSG_CTL_END: | |
178 | rtr_id.s_addr = ldp_rtr_id_get(ldpd_conf); | |
179 | vty_out(vty, "Local LDP Identifier: %s:0%s", inet_ntoa(rtr_id), | |
180 | VTY_NEWLINE); | |
181 | vty_out(vty, "Discovery Sources:%s", VTY_NEWLINE); | |
182 | vty_out(vty, " Interfaces:%s", VTY_NEWLINE); | |
183 | vty_out(vty, "%s", ifaces_buffer); | |
184 | vty_out(vty, " Targeted Hellos:%s", VTY_NEWLINE); | |
185 | vty_out(vty, "%s", tnbrs_buffer); | |
186 | vty_out(vty, "%s", VTY_NEWLINE); | |
187 | return (1); | |
188 | default: | |
189 | break; | |
190 | } | |
191 | ||
192 | return (0); | |
193 | } | |
194 | ||
195 | static void | |
196 | show_nbr_adj(struct vty *vty, char *buffer, struct ctl_adj *adj) | |
197 | { | |
198 | size_t buflen = strlen(buffer); | |
199 | ||
200 | switch (adj->type) { | |
201 | case HELLO_LINK: | |
202 | snprintf(buffer + buflen, LDPBUFSIZ - buflen, | |
203 | " Interface: %s%s", adj->ifname, VTY_NEWLINE); | |
204 | break; | |
205 | case HELLO_TARGETED: | |
206 | snprintf(buffer + buflen, LDPBUFSIZ - buflen, | |
207 | " Targeted Hello: %s%s", log_addr(adj->af, | |
208 | &adj->src_addr), VTY_NEWLINE); | |
209 | break; | |
210 | } | |
211 | } | |
212 | ||
213 | static int | |
214 | show_nbr_msg(struct vty *vty, struct imsg *imsg, struct show_filter *filter) | |
215 | { | |
216 | struct ctl_adj *adj; | |
217 | struct ctl_nbr *nbr; | |
218 | static char v4adjs_buffer[LDPBUFSIZ]; | |
219 | static char v6adjs_buffer[LDPBUFSIZ]; | |
220 | ||
221 | switch (imsg->hdr.type) { | |
222 | case IMSG_CTL_SHOW_NBR: | |
223 | nbr = imsg->data; | |
224 | ||
225 | v4adjs_buffer[0] = '\0'; | |
226 | v6adjs_buffer[0] = '\0'; | |
227 | vty_out(vty, "Peer LDP Identifier: %s:0%s", inet_ntoa(nbr->id), | |
228 | VTY_NEWLINE); | |
229 | vty_out(vty, " TCP connection: %s:%u - %s:%u%s", | |
230 | log_addr(nbr->af, &nbr->laddr), ntohs(nbr->lport), | |
231 | log_addr(nbr->af, &nbr->raddr), ntohs(nbr->rport), | |
232 | VTY_NEWLINE); | |
233 | vty_out(vty, " Session Holdtime: %u sec%s", nbr->holdtime, | |
234 | VTY_NEWLINE); | |
235 | vty_out(vty, " State: %s; Downstream-Unsolicited%s", | |
236 | nbr_state_name(nbr->nbr_state), VTY_NEWLINE); | |
237 | vty_out(vty, " Up time: %s%s", log_time(nbr->uptime), | |
238 | VTY_NEWLINE); | |
239 | break; | |
240 | case IMSG_CTL_SHOW_NBR_DISC: | |
241 | adj = imsg->data; | |
242 | ||
243 | switch (adj->af) { | |
244 | case AF_INET: | |
245 | show_nbr_adj(vty, v4adjs_buffer, adj); | |
246 | break; | |
247 | case AF_INET6: | |
248 | show_nbr_adj(vty, v6adjs_buffer, adj); | |
249 | break; | |
250 | default: | |
251 | fatalx("show_nbr_msg: unknown af"); | |
252 | } | |
253 | break; | |
254 | case IMSG_CTL_SHOW_NBR_END: | |
255 | vty_out(vty, " LDP Discovery Sources:%s", VTY_NEWLINE); | |
256 | if (v4adjs_buffer[0] != '\0') { | |
257 | vty_out(vty, " IPv4:%s", VTY_NEWLINE); | |
258 | vty_out(vty, "%s", v4adjs_buffer); | |
259 | } | |
260 | if (v6adjs_buffer[0] != '\0') { | |
261 | vty_out(vty, " IPv6:%s", VTY_NEWLINE); | |
262 | vty_out(vty, "%s", v6adjs_buffer); | |
263 | } | |
264 | vty_out(vty, "%s", VTY_NEWLINE); | |
265 | break; | |
266 | case IMSG_CTL_END: | |
267 | return (1); | |
268 | default: | |
269 | break; | |
270 | } | |
271 | ||
272 | return (0); | |
273 | } | |
274 | ||
275 | static int | |
276 | show_lib_msg(struct vty *vty, struct imsg *imsg, struct show_filter *filter) | |
277 | { | |
278 | struct ctl_rt *rt; | |
279 | char dstnet[BUFSIZ]; | |
280 | ||
281 | switch (imsg->hdr.type) { | |
282 | case IMSG_CTL_SHOW_LIB: | |
283 | rt = imsg->data; | |
284 | ||
285 | if (filter->family != AF_UNSPEC && filter->family != rt->af) | |
286 | break; | |
287 | ||
288 | snprintf(dstnet, sizeof(dstnet), "%s/%d", | |
289 | log_addr(rt->af, &rt->prefix), rt->prefixlen); | |
290 | ||
291 | if (rt->first) { | |
292 | vty_out(vty, "%s%s", dstnet, VTY_NEWLINE); | |
293 | vty_out(vty, "%-8sLocal binding: label: %s%s", "", | |
294 | log_label(rt->local_label), VTY_NEWLINE); | |
295 | ||
296 | if (rt->remote_label != NO_LABEL) { | |
297 | vty_out(vty, "%-8sRemote bindings:%s", "", | |
298 | VTY_NEWLINE); | |
299 | vty_out(vty, "%-12sPeer Label%s", | |
300 | "", VTY_NEWLINE); | |
301 | vty_out(vty, "%-12s----------------- " | |
302 | "---------%s", "", VTY_NEWLINE); | |
303 | } else | |
304 | vty_out(vty, "%-8sNo remote bindings%s", "", | |
305 | VTY_NEWLINE); | |
306 | } | |
307 | if (rt->remote_label != NO_LABEL) | |
308 | vty_out(vty, "%12s%-20s%s%s", "", inet_ntoa(rt->nexthop), | |
309 | log_label(rt->remote_label), VTY_NEWLINE); | |
310 | break; | |
311 | case IMSG_CTL_END: | |
312 | vty_out(vty, "%s", VTY_NEWLINE); | |
313 | return (1); | |
314 | default: | |
315 | break; | |
316 | } | |
317 | ||
318 | return (0); | |
319 | } | |
320 | ||
321 | static int | |
322 | show_l2vpn_binding_msg(struct vty *vty, struct imsg *imsg) | |
323 | { | |
324 | struct ctl_pw *pw; | |
325 | ||
326 | switch (imsg->hdr.type) { | |
327 | case IMSG_CTL_SHOW_L2VPN_BINDING: | |
328 | pw = imsg->data; | |
329 | ||
330 | vty_out(vty, " Destination Address: %s, VC ID: %u%s", | |
331 | inet_ntoa(pw->lsr_id), pw->pwid, VTY_NEWLINE); | |
332 | ||
333 | /* local binding */ | |
334 | if (pw->local_label != NO_LABEL) { | |
335 | vty_out(vty, " Local Label: %u%s", pw->local_label, | |
336 | VTY_NEWLINE); | |
337 | vty_out(vty, "%-8sCbit: %u, VC Type: %s, " | |
338 | "GroupID: %u%s", "", pw->local_cword, | |
339 | pw_type_name(pw->type), pw->local_gid, | |
340 | VTY_NEWLINE); | |
341 | vty_out(vty, "%-8sMTU: %u%s", "", pw->local_ifmtu, | |
342 | VTY_NEWLINE); | |
343 | } else | |
344 | vty_out(vty, " Local Label: unassigned%s", | |
345 | VTY_NEWLINE); | |
346 | ||
347 | /* remote binding */ | |
348 | if (pw->remote_label != NO_LABEL) { | |
349 | vty_out(vty, " Remote Label: %u%s", | |
350 | pw->remote_label, VTY_NEWLINE); | |
351 | vty_out(vty, "%-8sCbit: %u, VC Type: %s, " | |
352 | "GroupID: %u%s", "", pw->remote_cword, | |
353 | pw_type_name(pw->type), pw->remote_gid, | |
354 | VTY_NEWLINE); | |
355 | vty_out(vty, "%-8sMTU: %u%s", "", pw->remote_ifmtu, | |
356 | VTY_NEWLINE); | |
357 | } else | |
358 | vty_out(vty, " Remote Label: unassigned%s", | |
359 | VTY_NEWLINE); | |
360 | break; | |
361 | case IMSG_CTL_END: | |
362 | vty_out(vty, "%s", VTY_NEWLINE); | |
363 | return (1); | |
364 | default: | |
365 | break; | |
366 | } | |
367 | ||
368 | return (0); | |
369 | } | |
370 | ||
371 | static int | |
372 | show_l2vpn_pw_msg(struct vty *vty, struct imsg *imsg) | |
373 | { | |
374 | struct ctl_pw *pw; | |
375 | ||
376 | switch (imsg->hdr.type) { | |
377 | case IMSG_CTL_SHOW_L2VPN_PW: | |
378 | pw = imsg->data; | |
379 | ||
380 | vty_out(vty, "%-9s %-15s %-10u %-16s %-10s%s", pw->ifname, | |
381 | inet_ntoa(pw->lsr_id), pw->pwid, pw->l2vpn_name, | |
382 | (pw->status ? "UP" : "DOWN"), VTY_NEWLINE); | |
383 | break; | |
384 | case IMSG_CTL_END: | |
385 | vty_out(vty, "%s", VTY_NEWLINE); | |
386 | return (1); | |
387 | default: | |
388 | break; | |
389 | } | |
390 | ||
391 | return (0); | |
392 | } | |
393 | ||
394 | static int | |
395 | ldp_vty_connect(struct imsgbuf *ibuf) | |
396 | { | |
397 | struct sockaddr_un s_un; | |
398 | int ctl_sock; | |
399 | ||
400 | /* connect to ldpd control socket */ | |
401 | if ((ctl_sock = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) { | |
402 | log_warn("%s: socket", __func__); | |
403 | return (-1); | |
404 | } | |
405 | ||
406 | memset(&s_un, 0, sizeof(s_un)); | |
407 | s_un.sun_family = AF_UNIX; | |
408 | strlcpy(s_un.sun_path, LDPD_SOCKET, sizeof(s_un.sun_path)); | |
409 | if (connect(ctl_sock, (struct sockaddr *)&s_un, sizeof(s_un)) == -1) { | |
410 | log_warn("%s: connect: %s", __func__, LDPD_SOCKET); | |
411 | close(ctl_sock); | |
412 | return (-1); | |
413 | } | |
414 | ||
415 | imsg_init(ibuf, ctl_sock); | |
416 | ||
417 | return (0); | |
418 | } | |
419 | ||
420 | static int | |
421 | ldp_vty_dispatch(struct vty *vty, struct imsgbuf *ibuf, enum show_command cmd, | |
422 | struct show_filter *filter) | |
423 | { | |
424 | struct imsg imsg; | |
425 | int n, done = 0; | |
426 | ||
427 | while (ibuf->w.queued) | |
428 | if (msgbuf_write(&ibuf->w) <= 0 && errno != EAGAIN) { | |
429 | log_warn("write error"); | |
430 | close(ibuf->fd); | |
431 | return (CMD_WARNING); | |
432 | } | |
433 | ||
434 | while (!done) { | |
435 | if ((n = imsg_read(ibuf)) == -1 && errno != EAGAIN) { | |
436 | log_warnx("imsg_read error"); | |
437 | close(ibuf->fd); | |
438 | return (CMD_WARNING); | |
439 | } | |
440 | if (n == 0) { | |
441 | log_warnx("pipe closed"); | |
442 | close(ibuf->fd); | |
443 | return (CMD_WARNING); | |
444 | } | |
445 | ||
446 | while (!done) { | |
447 | if ((n = imsg_get(ibuf, &imsg)) == -1) { | |
448 | log_warnx("imsg_get error"); | |
449 | close(ibuf->fd); | |
450 | return (CMD_WARNING); | |
451 | } | |
452 | if (n == 0) | |
453 | break; | |
454 | switch (cmd) { | |
455 | case SHOW_IFACE: | |
456 | done = show_interface_msg(vty, &imsg, filter); | |
457 | break; | |
458 | case SHOW_DISC: | |
459 | done = show_discovery_msg(vty, &imsg, filter); | |
460 | break; | |
461 | case SHOW_NBR: | |
462 | done = show_nbr_msg(vty, &imsg, filter); | |
463 | break; | |
464 | case SHOW_LIB: | |
465 | done = show_lib_msg(vty, &imsg, filter); | |
466 | break; | |
467 | case SHOW_L2VPN_PW: | |
468 | done = show_l2vpn_pw_msg(vty, &imsg); | |
469 | break; | |
470 | case SHOW_L2VPN_BINDING: | |
471 | done = show_l2vpn_binding_msg(vty, &imsg); | |
472 | break; | |
473 | default: | |
474 | break; | |
475 | } | |
476 | imsg_free(&imsg); | |
477 | } | |
478 | } | |
479 | ||
480 | close(ibuf->fd); | |
481 | ||
482 | return (CMD_SUCCESS); | |
483 | } | |
484 | ||
485 | static int | |
486 | ldp_vty_get_af(const char *str, int *af) | |
487 | { | |
488 | if (str == NULL) { | |
489 | *af = AF_UNSPEC; | |
490 | return (0); | |
491 | } else if (strcmp(str, "ipv4") == 0) { | |
492 | *af = AF_INET; | |
493 | return (0); | |
494 | } else if (strcmp(str, "ipv6") == 0) { | |
495 | *af = AF_INET6; | |
496 | return (0); | |
497 | } | |
498 | ||
499 | return (-1); | |
500 | } | |
501 | ||
502 | int | |
503 | ldp_vty_show_binding(struct vty *vty, struct vty_arg *args[]) | |
504 | { | |
505 | struct imsgbuf ibuf; | |
506 | struct show_filter filter; | |
507 | const char *af_str; | |
508 | int af; | |
509 | ||
510 | if (ldp_vty_connect(&ibuf) < 0) | |
511 | return (CMD_WARNING); | |
512 | ||
513 | imsg_compose(&ibuf, IMSG_CTL_SHOW_LIB, 0, 0, -1, NULL, 0); | |
514 | ||
515 | af_str = vty_get_arg_value(args, "address-family"); | |
516 | if (ldp_vty_get_af(af_str, &af) < 0) | |
517 | return (CMD_ERR_NO_MATCH); | |
518 | ||
519 | memset(&filter, 0, sizeof(filter)); | |
520 | filter.family = af; | |
521 | ||
522 | return (ldp_vty_dispatch(vty, &ibuf, SHOW_LIB, &filter)); | |
523 | } | |
524 | ||
525 | int | |
526 | ldp_vty_show_discovery(struct vty *vty, struct vty_arg *args[]) | |
527 | { | |
528 | struct imsgbuf ibuf; | |
529 | struct show_filter filter; | |
530 | const char *af_str; | |
531 | int af; | |
532 | ||
533 | if (ldp_vty_connect(&ibuf) < 0) | |
534 | return (CMD_WARNING); | |
535 | ||
536 | imsg_compose(&ibuf, IMSG_CTL_SHOW_DISCOVERY, 0, 0, -1, NULL, 0); | |
537 | ||
538 | af_str = vty_get_arg_value(args, "address-family"); | |
539 | if (ldp_vty_get_af(af_str, &af) < 0) | |
540 | return (CMD_ERR_NO_MATCH); | |
541 | ||
542 | memset(&filter, 0, sizeof(filter)); | |
543 | filter.family = af; | |
544 | ||
545 | return (ldp_vty_dispatch(vty, &ibuf, SHOW_DISC, &filter)); | |
546 | } | |
547 | ||
548 | int | |
549 | ldp_vty_show_interface(struct vty *vty, struct vty_arg *args[]) | |
550 | { | |
551 | struct imsgbuf ibuf; | |
552 | struct show_filter filter; | |
553 | unsigned int ifidx = 0; | |
554 | const char *af_str; | |
555 | int af; | |
556 | ||
557 | if (ldp_vty_connect(&ibuf) < 0) | |
558 | return (CMD_WARNING); | |
559 | ||
560 | imsg_compose(&ibuf, IMSG_CTL_SHOW_INTERFACE, 0, 0, -1, &ifidx, | |
561 | sizeof(ifidx)); | |
562 | ||
563 | af_str = vty_get_arg_value(args, "address-family"); | |
564 | if (ldp_vty_get_af(af_str, &af) < 0) | |
565 | return (CMD_ERR_NO_MATCH); | |
566 | ||
567 | memset(&filter, 0, sizeof(filter)); | |
568 | filter.family = af; | |
569 | ||
570 | /* header */ | |
571 | vty_out(vty, "%-4s %-11s %-6s %-8s %-12s %3s%s", "AF", | |
572 | "Interface", "State", "Uptime", "Hello Timers", "ac", VTY_NEWLINE); | |
573 | ||
574 | return (ldp_vty_dispatch(vty, &ibuf, SHOW_IFACE, &filter)); | |
575 | } | |
576 | ||
577 | int | |
578 | ldp_vty_show_neighbor(struct vty *vty, struct vty_arg *args[]) | |
579 | { | |
580 | struct imsgbuf ibuf; | |
581 | struct show_filter filter; | |
582 | ||
583 | if (ldp_vty_connect(&ibuf) < 0) | |
584 | return (CMD_WARNING); | |
585 | ||
586 | imsg_compose(&ibuf, IMSG_CTL_SHOW_NBR, 0, 0, -1, NULL, 0); | |
587 | ||
588 | /* not used */ | |
589 | memset(&filter, 0, sizeof(filter)); | |
590 | ||
591 | return (ldp_vty_dispatch(vty, &ibuf, SHOW_NBR, &filter)); | |
592 | } | |
593 | ||
594 | int | |
595 | ldp_vty_show_atom_binding(struct vty *vty, struct vty_arg *args[]) | |
596 | { | |
597 | struct imsgbuf ibuf; | |
598 | struct show_filter filter; | |
599 | ||
600 | if (ldp_vty_connect(&ibuf) < 0) | |
601 | return (CMD_WARNING); | |
602 | ||
603 | imsg_compose(&ibuf, IMSG_CTL_SHOW_L2VPN_BINDING, 0, 0, -1, NULL, 0); | |
604 | ||
605 | /* not used */ | |
606 | memset(&filter, 0, sizeof(filter)); | |
607 | ||
608 | return (ldp_vty_dispatch(vty, &ibuf, SHOW_L2VPN_BINDING, &filter)); | |
609 | } | |
610 | ||
611 | int | |
612 | ldp_vty_show_atom_vc(struct vty *vty, struct vty_arg *args[]) | |
613 | { | |
614 | struct imsgbuf ibuf; | |
615 | struct show_filter filter; | |
616 | ||
617 | if (ldp_vty_connect(&ibuf) < 0) | |
618 | return (CMD_WARNING); | |
619 | ||
620 | imsg_compose(&ibuf, IMSG_CTL_SHOW_L2VPN_PW, 0, 0, -1, NULL, 0); | |
621 | ||
622 | /* not used */ | |
623 | memset(&filter, 0, sizeof(filter)); | |
624 | ||
625 | /* header */ | |
626 | vty_out(vty, "%-9s %-15s %-10s %-16s %-10s%s", | |
627 | "Interface", "Peer ID", "VC ID", "Name", "Status", VTY_NEWLINE); | |
628 | vty_out(vty, "%-9s %-15s %-10s %-16s %-10s%s", | |
629 | "---------", "---------------", "----------", | |
630 | "----------------", "----------", VTY_NEWLINE); | |
631 | ||
632 | return (ldp_vty_dispatch(vty, &ibuf, SHOW_L2VPN_PW, &filter)); | |
633 | } | |
634 | ||
635 | int | |
636 | ldp_vty_clear_nbr(struct vty *vty, struct vty_arg *args[]) | |
637 | { | |
638 | struct imsgbuf ibuf; | |
639 | const char *addr_str; | |
640 | struct ctl_nbr nbr; | |
641 | ||
642 | addr_str = vty_get_arg_value(args, "addr"); | |
643 | ||
644 | memset(&nbr, 0, sizeof(nbr)); | |
645 | if (addr_str && | |
646 | (ldp_get_address(addr_str, &nbr.af, &nbr.raddr) == -1 || | |
647 | bad_addr(nbr.af, &nbr.raddr))) { | |
648 | vty_out(vty, "%% Malformed address%s", VTY_NEWLINE); | |
649 | return (CMD_WARNING); | |
650 | } | |
651 | ||
652 | if (ldp_vty_connect(&ibuf) < 0) | |
653 | return (CMD_WARNING); | |
654 | ||
655 | imsg_compose(&ibuf, IMSG_CTL_CLEAR_NBR, 0, 0, -1, &nbr, sizeof(nbr)); | |
656 | ||
657 | while (ibuf.w.queued) | |
658 | if (msgbuf_write(&ibuf.w) <= 0 && errno != EAGAIN) { | |
659 | log_warn("write error"); | |
660 | close(ibuf.fd); | |
661 | return (CMD_WARNING); | |
662 | } | |
663 | ||
664 | close(ibuf.fd); | |
665 | ||
666 | return (CMD_SUCCESS); | |
667 | } |