]> git.ipfire.org Git - thirdparty/lldpd.git/blame - src/client/show.c
client: add show interfaces command (#240)
[thirdparty/lldpd.git] / src / client / show.c
CommitLineData
9a775667
VB
1/* -*- mode: c; c-file-style: "openbsd" -*- */
2/*
3 * Copyright (c) 2012 Vincent Bernat <bernat@luffy.cx>
4 *
5 * Permission to use, copy, modify, and/or distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the above
7 * copyright notice and this permission notice appear in all copies.
8 *
9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16 */
17
18#include "client.h"
7efa65c1 19#include <string.h>
a7c54949 20#include <limits.h>
9a775667
VB
21
22/**
23 * Show neighbors.
24 *
25 * The environment will contain the following keys:
26 * - C{ports} list of ports we want to restrict showing.
27 * - C{hidden} if we should show hidden ports.
28 * - C{summary} if we want to show only a summary
29 * - C{detailed} for a detailed overview
30 */
31static int
32cmd_show_neighbors(struct lldpctl_conn_t *conn, struct writer *w,
33 struct cmd_env *env, void *arg)
34{
35 log_debug("lldpctl", "show neighbors data (%s) %s hidden neighbors",
36 cmdenv_get(env, "summary")?"summary":
37 cmdenv_get(env, "detailed")?"detailed":
38 "normal", cmdenv_get(env, "hidden")?"with":"without");
39 if (cmdenv_get(env, "ports"))
40 log_debug("lldpctl", "restrict to the following ports: %s",
41 cmdenv_get(env, "ports"));
42
43 display_interfaces(conn, w, env, !!cmdenv_get(env, "hidden"),
44 cmdenv_get(env, "summary")?DISPLAY_BRIEF:
45 cmdenv_get(env, "detailed")?DISPLAY_DETAILS:
46 DISPLAY_NORMAL);
47
48 return 1;
49}
50
a54f6012
SW
51/**
52 * Show interfaces.
53 *
54 * The environment will contain the following keys:
55 * - C{ports} list of ports we want to restrict showing.
56 * - C{hidden} if we should show hidden ports.
57 * - C{summary} if we want to show only a summary
58 * - C{detailed} for a detailed overview
59 */
60static int
61cmd_show_interfaces(struct lldpctl_conn_t *conn, struct writer *w,
62 struct cmd_env *env, void *arg)
63{
64 log_debug("lldpctl", "show interfaces data (%s) %s hidden interfaces",
65 cmdenv_get(env, "summary")?"summary":
66 cmdenv_get(env, "detailed")?"detailed":
67 "normal", cmdenv_get(env, "hidden")?"with":"without");
68 if (cmdenv_get(env, "ports"))
69 log_debug("lldpctl", "restrict to the following ports: %s",
70 cmdenv_get(env, "ports"));
71
72 display_local_interfaces(conn, w, env, !!cmdenv_get(env, "hidden"),
73 cmdenv_get(env, "summary")?DISPLAY_BRIEF:
74 cmdenv_get(env, "detailed")?DISPLAY_DETAILS:
75 DISPLAY_NORMAL);
76
77 return 1;
78}
79
3407e638
VB
80/**
81 * Show chassis.
82 *
83 * The environment will contain the following keys:
84 * - C{summary} if we want to show only a summary
85 * - C{detailed} for a detailed overview
86 */
87static int
88cmd_show_chassis(struct lldpctl_conn_t *conn, struct writer *w,
89 struct cmd_env *env, void *arg)
90{
91 log_debug("lldpctl", "show chassis data (%s)",
92 cmdenv_get(env, "summary")?"summary":
93 cmdenv_get(env, "detailed")?"detailed":
94 "normal");
95
96 display_local_chassis(conn, w, env,
97 cmdenv_get(env, "summary")?DISPLAY_BRIEF:
98 cmdenv_get(env, "detailed")?DISPLAY_DETAILS:
99 DISPLAY_NORMAL);
100
101 return 1;
102}
103
78356144 104/**
105 * Show stats.
106 *
107 * The environment will contain the following keys:
108 * - C{ports} list of ports we want to restrict showing.
5331eb2d 109 * - C{summary} summary of stats
78356144 110 */
111static int
112cmd_show_interface_stats(struct lldpctl_conn_t *conn, struct writer *w,
113 struct cmd_env *env, void *arg)
114{
115 log_debug("lldpctl", "show stats data");
116 if (cmdenv_get(env, "ports"))
adcb76f8 117 log_debug("lldpctl", "restrict to the following ports: %s",
78356144 118 cmdenv_get(env, "ports"));
5331eb2d 119 if (cmdenv_get(env, "summary"))
44fb3587 120 log_debug("lldpctl", "show summary of stats across ports");
78356144 121
122 display_interfaces_stats(conn, w, env);
123
124 return 1;
125}
126
9a775667
VB
127static int
128cmd_check_no_detailed_nor_summary(struct cmd_env *env, void *arg)
129{
130 if (cmdenv_get(env, "detailed")) return 0;
131 if (cmdenv_get(env, "summary")) return 0;
132 return 1;
133}
134
135/**
136 * Show running configuration.
137 */
138static int
139cmd_show_configuration(struct lldpctl_conn_t *conn, struct writer *w,
140 struct cmd_env *env, void *arg)
141{
142 log_debug("lldpctl", "show running configuration");
143 display_configuration(conn, w);
144 return 1;
145}
146
bd8a8861
VB
147struct watcharg {
148 struct cmd_env *env;
149 struct writer *w;
a7c54949 150 size_t nb;
bd8a8861
VB
151};
152
9a775667
VB
153/**
154 * Callback for the next function to display a new neighbor.
155 */
156static void
157watchcb(lldpctl_conn_t *conn,
158 lldpctl_change_t type,
159 lldpctl_atom_t *interface,
160 lldpctl_atom_t *neighbor,
161 void *data)
162{
bd8a8861
VB
163 struct watcharg *wa = data;
164 struct cmd_env *env = wa->env;
165 struct writer *w = wa->w;
9a775667 166 const char *interfaces = cmdenv_get(env, "ports");
7efa65c1 167 const char *proto_str;
494264f0
ST
168 int protocol = LLDPD_MODE_MAX;
169
9a775667
VB
170 if (interfaces && !contains(interfaces, lldpctl_atom_get_str(interface,
171 lldpctl_k_interface_name)))
172 return;
173
494264f0
ST
174 /* user might have specified protocol to filter display results */
175 proto_str = cmdenv_get(env, "protocol");
176
177 if (proto_str) {
178 log_debug("display", "filter protocol: %s ", proto_str);
179
7efa65c1
VB
180 protocol = 0; /* unsupported */
181 for (lldpctl_map_t *protocol_map =
182 lldpctl_key_get_map(lldpctl_k_port_protocol);
183 protocol_map->string;
184 protocol_map++) {
185 if (!strcasecmp(proto_str, protocol_map->string)) {
186 protocol = protocol_map->value;
187 break;
188 }
189 }
494264f0
ST
190 }
191
9a775667
VB
192 switch (type) {
193 case lldpctl_c_deleted:
194 tag_start(w, "lldp-deleted", "LLDP neighbor deleted");
195 break;
196 case lldpctl_c_updated:
197 tag_start(w, "lldp-updated", "LLDP neighbor updated");
198 break;
199 case lldpctl_c_added:
200 tag_start(w, "lldp-added", "LLDP neighbor added");
201 break;
202 default: return;
203 }
204 display_interface(conn, w, 1, interface, neighbor,
205 cmdenv_get(env, "summary")?DISPLAY_BRIEF:
206 cmdenv_get(env, "detailed")?DISPLAY_DETAILS:
494264f0 207 DISPLAY_NORMAL, protocol);
9a775667 208 tag_end(w);
a7c54949 209 wa->nb++;
9a775667
VB
210}
211
212/**
213 * Watch for neighbor changes.
214 */
215static int
216cmd_watch_neighbors(struct lldpctl_conn_t *conn, struct writer *w,
217 struct cmd_env *env, void *arg)
218{
bd8a8861
VB
219 struct watcharg wa = {
220 .env = env,
a7c54949
VB
221 .w = w,
222 .nb = 0
bd8a8861 223 };
a7c54949
VB
224 const char *limit_str = cmdenv_get(env, "limit");
225 size_t limit = 0;
226
227 if (limit_str) {
228 const char *errstr;
229 limit = strtonum(limit_str, 1, LLONG_MAX, &errstr);
230 if (errstr != NULL) {
231 log_warnx("lldpctl", "specified limit (%s) is %s and ignored",
232 limit_str, errstr);
233 }
234 }
235
9a775667 236 log_debug("lldpctl", "watch for neighbor changes");
bd8a8861 237 if (lldpctl_watch_callback(conn, watchcb, &wa) < 0) {
9a775667
VB
238 log_warnx("lldpctl", "unable to watch for neighbors. %s",
239 lldpctl_last_strerror(conn));
240 return 0;
241 }
9122b2c9 242 while (1) {
9a775667
VB
243 if (lldpctl_watch(conn) < 0) {
244 log_warnx("lldpctl", "unable to watch for neighbors. %s",
245 lldpctl_last_strerror(conn));
9122b2c9 246 return 0;
9a775667 247 }
a7c54949 248 if (limit > 0 && wa.nb >= limit)
9122b2c9 249 return 1;
9a775667
VB
250 }
251 return 0;
252}
253
254/**
3407e638 255 * Register common subcommands for `watch` and `show neighbors` and `show chassis'
9a775667
VB
256 */
257void
3407e638 258register_common_commands(struct cmd_node *root, int neighbor)
9a775667 259{
9a775667
VB
260 /* With more details */
261 commands_new(root,
262 "details",
263 "With more details",
264 cmd_check_no_detailed_nor_summary, cmd_store_env_and_pop, "detailed");
265
266 /* With less details */
267 commands_new(root,
268 "summary",
269 "With less details",
270 cmd_check_no_detailed_nor_summary, cmd_store_env_and_pop, "summary");
271
3407e638
VB
272 if (!neighbor) return;
273
274 /* With hidden neighbors */
275 commands_new(root,
276 "hidden",
277 "Include hidden neighbors",
278 cmd_check_no_env, cmd_store_env_and_pop, "hidden");
279
9a775667 280 /* Some specific port */
e688f90f 281 cmd_restrict_ports(root);
494264f0
ST
282
283 /* Specific protocol */
284 cmd_restrict_protocol(root);
9a775667
VB
285}
286
5331eb2d 287/**
288 * Register sub command summary
289 */
290void
291register_summary_command(struct cmd_node *root)
292{
293 commands_new(root,
294 "summary",
295 "With less details",
296 cmd_check_no_detailed_nor_summary, cmd_store_env_and_pop, "summary");
297}
298
9a775667
VB
299/**
300 * Register subcommands to `show`
301 *
302 * @param root Root node
303 */
304void
305register_commands_show(struct cmd_node *root)
306{
307 struct cmd_node *show = commands_new(
308 root,
309 "show",
310 "Show running system information",
311 NULL, NULL, NULL);
312 struct cmd_node *neighbors = commands_new(
313 show,
314 "neighbors",
315 "Show neighbors data",
316 NULL, NULL, NULL);
317
a54f6012
SW
318 struct cmd_node *interfaces = commands_new(
319 show,
320 "interfaces",
321 "Show interfaces data",
322 NULL, NULL, NULL);
323
3407e638
VB
324 struct cmd_node *chassis = commands_new(
325 show,
326 "chassis",
327 "Show local chassis data",
328 NULL, NULL, NULL);
329
78356144 330 struct cmd_node *stats = commands_new(
331 show,
332 "statistics",
333 "Show statistics",
334 NULL, NULL, NULL);
335
9a775667
VB
336 /* Neighbors data */
337 commands_new(neighbors,
338 NEWLINE,
339 "Show neighbors data",
340 NULL, cmd_show_neighbors, NULL);
341
3407e638
VB
342 register_common_commands(neighbors, 1);
343
a54f6012
SW
344 /* Interfaces data */
345 commands_new(interfaces,
346 NEWLINE,
347 "Show interfaces data",
348 NULL, cmd_show_interfaces, NULL);
349
350 cmd_restrict_ports(interfaces);
351 register_common_commands(interfaces, 0);
352
3407e638
VB
353 /* Chassis data */
354 commands_new(chassis,
355 NEWLINE,
356 "Show local chassis data",
357 NULL, cmd_show_chassis, NULL);
358
359 register_common_commands(chassis, 0);
9a775667 360
78356144 361 /* Stats data */
362 commands_new(stats,
363 NEWLINE,
364 "Show stats data",
365 NULL, cmd_show_interface_stats, NULL);
366
ddfbab08 367 cmd_restrict_ports(stats);
5331eb2d 368 register_summary_command(stats);
78356144 369
9a775667
VB
370 /* Register "show configuration" and "show running-configuration" */
371 commands_new(
372 commands_new(show,
373 "configuration",
374 "Show running configuration",
375 NULL, NULL, NULL),
376 NEWLINE,
377 "Show running configuration",
378 NULL, cmd_show_configuration, NULL);
379 commands_new(
380 commands_new(show,
381 "running-configuration",
382 "Show running configuration",
383 NULL, NULL, NULL),
384 NEWLINE,
385 "Show running configuration",
386 NULL, cmd_show_configuration, NULL);
387}
388
389/**
390 * Register subcommands to `watch`
391 *
392 * @param root Root node
393 */
394void
395register_commands_watch(struct cmd_node *root)
396{
397 struct cmd_node *watch = commands_new(
398 root,
399 "watch",
400 "Monitor neighbor changes",
401 NULL, NULL, NULL);
402
9a775667
VB
403 commands_new(watch,
404 NEWLINE,
405 "Monitor neighbors change",
406 NULL, cmd_watch_neighbors, NULL);
407
a7c54949
VB
408 commands_new(
409 commands_new(watch,
410 "limit",
411 "Don't show more than X events",
412 cmd_check_no_env, NULL, "limit"),
413 NULL,
414 "Stop after getting X events",
415 NULL, cmd_store_env_value_and_pop2, "limit");
416
3407e638 417 register_common_commands(watch, 1);
9a775667 418}