1 /* -*- mode: c; c-file-style: "openbsd" -*- */
2 /*
3 * Copyright (c) 2013 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 <unistd.h>
19 #include <string.h>
20 #include <sys/utsname.h>
21
22 #include "client.h"
23 #include "../log.h"
24
25 static int
cmd_iface_pattern(struct lldpctl_conn_t * conn,struct writer * w,struct cmd_env * env,void * arg)26 cmd_iface_pattern(struct lldpctl_conn_t *conn, struct writer *w,
27 struct cmd_env *env, void *arg)
28 {
29 log_debug("lldpctl", "set iface pattern");
30
31 lldpctl_atom_t *config = lldpctl_get_configuration(conn);
32 if (config == NULL) {
33 log_warnx("lldpctl", "unable to get configuration from lldpd. %s",
34 lldpctl_last_strerror(conn));
35 return 0;
36 }
37
38 const char *value = cmdenv_get(env, "iface-pattern");
39 if (lldpctl_atom_set_str(config,
40 lldpctl_k_config_iface_pattern,
41 value) == NULL) {
42 log_warnx("lldpctl", "unable to set iface-pattern. %s",
43 lldpctl_last_strerror(conn));
44 lldpctl_atom_dec_ref(config);
45 return 0;
46 }
47 log_info("lldpctl", "iface-pattern set to new value %s",
48 value?value:"(none)");
49 lldpctl_atom_dec_ref(config);
50 return 1;
51 }
52
53 static int
cmd_perm_iface_pattern(struct lldpctl_conn_t * conn,struct writer * w,struct cmd_env * env,void * arg)54 cmd_perm_iface_pattern(struct lldpctl_conn_t *conn, struct writer *w,
55 struct cmd_env *env, void *arg)
56 {
57 log_debug("lldpctl", "set permanent iface pattern");
58
59 lldpctl_atom_t *config = lldpctl_get_configuration(conn);
60 if (config == NULL) {
61 log_warnx("lldpctl", "unable to get configuration from lldpd. %s",
62 lldpctl_last_strerror(conn));
63 return 0;
64 }
65
66 const char *value = cmdenv_get(env, "iface-pattern");
67 if (lldpctl_atom_set_str(config,
68 lldpctl_k_config_perm_iface_pattern,
69 value) == NULL) {
70 log_warnx("lldpctl", "unable to set permanent iface pattern. %s",
71 lldpctl_last_strerror(conn));
72 lldpctl_atom_dec_ref(config);
73 return 0;
74 }
75 log_info("lldpctl", "permanent iface pattern set to new value %s",
76 value?value:"(none)");
77 lldpctl_atom_dec_ref(config);
78 return 1;
79 }
80
81 static int
cmd_iface_promisc(struct lldpctl_conn_t * conn,struct writer * w,struct cmd_env * env,void * arg)82 cmd_iface_promisc(struct lldpctl_conn_t *conn, struct writer *w,
83 struct cmd_env *env, void *arg)
84 {
85 lldpctl_atom_t *config = lldpctl_get_configuration(conn);
86 if (config == NULL) {
87 log_warnx("lldpctl", "unable to get configuration from lldpd. %s",
88 lldpctl_last_strerror(conn));
89 return 0;
90 }
91 if (lldpctl_atom_set_int(config,
92 lldpctl_k_config_iface_promisc,
93 arg?1:0) == NULL) {
94 log_warnx("lldpctl", "unable to %s promiscuous mode: %s",
95 arg?"enable":"disable",
96 lldpctl_last_strerror(conn));
97 lldpctl_atom_dec_ref(config);
98 return 0;
99 }
100 log_info("lldpctl", "interface promiscuous mode %s",
101 arg?"enabled":"disabled");
102 lldpctl_atom_dec_ref(config);
103 return 1;
104 }
105
106 static int
cmd_system_description(struct lldpctl_conn_t * conn,struct writer * w,struct cmd_env * env,void * arg)107 cmd_system_description(struct lldpctl_conn_t *conn, struct writer *w,
108 struct cmd_env *env, void *arg)
109 {
110 int platform = 0;
111 const char *what = arg;
112 const char *value;
113 if (!strcmp(what, "system")) {
114 value = cmdenv_get(env, "description");
115 } else {
116 value = cmdenv_get(env, "platform");
117 platform = 1;
118 }
119 log_debug("lldpctl", "set %s description", what);
120 lldpctl_atom_t *config = lldpctl_get_configuration(conn);
121 if (config == NULL) {
122 log_warnx("lldpctl", "unable to get configuration from lldpd. %s",
123 lldpctl_last_strerror(conn));
124 return 0;
125 }
126 if (lldpctl_atom_set_str(config,
127 platform?lldpctl_k_config_platform:lldpctl_k_config_description,
128 value) == NULL) {
129 log_warnx("lldpctl", "unable to set description. %s",
130 lldpctl_last_strerror(conn));
131 lldpctl_atom_dec_ref(config);
132 return 0;
133 }
134 log_info("lldpctl", "description set to new value %s",
135 value?value:"(none)");
136 lldpctl_atom_dec_ref(config);
137 return 1;
138 }
139
140 static int
cmd_system_chassisid(struct lldpctl_conn_t * conn,struct writer * w,struct cmd_env * env,void * arg)141 cmd_system_chassisid(struct lldpctl_conn_t *conn, struct writer *w,
142 struct cmd_env *env, void *arg)
143 {
144 const char *value;
145 value = cmdenv_get(env, "description");
146 log_debug("lldpctl", "set chassis ID");
147 lldpctl_atom_t *config = lldpctl_get_configuration(conn);
148 if (config == NULL) {
149 log_warnx("lldpctl", "unable to get configuration from lldpd. %s",
150 lldpctl_last_strerror(conn));
151 return 0;
152 }
153 if (lldpctl_atom_set_str(config,
154 lldpctl_k_config_cid_string,
155 value) == NULL) {
156 log_warnx("lldpctl", "unable to set chassis ID. %s",
157 lldpctl_last_strerror(conn));
158 lldpctl_atom_dec_ref(config);
159 return 0;
160 }
161 log_info("lldpctl", "chassis ID set to new value %s",
162 value?value:"(none)");
163 lldpctl_atom_dec_ref(config);
164 return 1;
165 }
166
167 static int
cmd_management(struct lldpctl_conn_t * conn,struct writer * w,struct cmd_env * env,void * arg)168 cmd_management(struct lldpctl_conn_t *conn, struct writer *w,
169 struct cmd_env *env, void *arg)
170 {
171 log_debug("lldpctl", "set management pattern");
172
173 lldpctl_atom_t *config = lldpctl_get_configuration(conn);
174 if (config == NULL) {
175 log_warnx("lldpctl", "unable to get configuration from lldpd. %s",
176 lldpctl_last_strerror(conn));
177 return 0;
178 }
179
180 const char *value = cmdenv_get(env, "management-pattern");
181 if (lldpctl_atom_set_str(config,
182 lldpctl_k_config_mgmt_pattern, value) == NULL) {
183 log_warnx("lldpctl", "unable to set management pattern. %s",
184 lldpctl_last_strerror(conn));
185 lldpctl_atom_dec_ref(config);
186 return 0;
187 }
188 log_info("lldpctl", "management pattern set to new value %s",
189 value?value:"(none)");
190 lldpctl_atom_dec_ref(config);
191 return 1;
192 }
193
194 static int
cmd_hostname(struct lldpctl_conn_t * conn,struct writer * w,struct cmd_env * env,void * arg)195 cmd_hostname(struct lldpctl_conn_t *conn, struct writer *w,
196 struct cmd_env *env, void *arg)
197 {
198 struct utsname un;
199 log_debug("lldpctl", "set system name");
200
201 lldpctl_atom_t *config = lldpctl_get_configuration(conn);
202 if (config == NULL) {
203 log_warnx("lldpctl", "unable to get configuration from lldpd. %s",
204 lldpctl_last_strerror(conn));
205 return 0;
206 }
207
208 const char *value = cmdenv_get(env, "hostname");
209 if (value && strlen(value) == 1 && value[0] == '.') {
210 if (uname(&un) < 0) {
211 log_warn("lldpctl", "cannot get node name");
212 return 0;
213 }
214 value = un.nodename;
215 }
216 if (lldpctl_atom_set_str(config,
217 lldpctl_k_config_hostname, value) == NULL) {
218 log_warnx("lldpctl", "unable to set system name. %s",
219 lldpctl_last_strerror(conn));
220 lldpctl_atom_dec_ref(config);
221 return 0;
222 }
223 log_info("lldpctl", "system name set to new value %s",
224 value?value:"(none)");
225 lldpctl_atom_dec_ref(config);
226 return 1;
227 }
228
229 static int
cmd_update_descriptions(struct lldpctl_conn_t * conn,struct writer * w,struct cmd_env * env,void * arg)230 cmd_update_descriptions(struct lldpctl_conn_t *conn, struct writer *w,
231 struct cmd_env *env, void *arg)
232 {
233 lldpctl_atom_t *config = lldpctl_get_configuration(conn);
234 if (config == NULL) {
235 log_warnx("lldpctl", "unable to get configuration from lldpd. %s",
236 lldpctl_last_strerror(conn));
237 return 0;
238 }
239 if (lldpctl_atom_set_int(config,
240 lldpctl_k_config_ifdescr_update,
241 arg?1:0) == NULL) {
242 log_warnx("lldpctl", "unable to %s interface description update: %s",
243 arg?"enable":"disable",
244 lldpctl_last_strerror(conn));
245 lldpctl_atom_dec_ref(config);
246 return 0;
247 }
248 log_info("lldpctl", "interface description update %s",
249 arg?"enabled":"disabled");
250 lldpctl_atom_dec_ref(config);
251 return 1;
252 }
253
254 static int
cmd_bondslave_srcmac_type(struct lldpctl_conn_t * conn,struct writer * w,struct cmd_env * env,void * arg)255 cmd_bondslave_srcmac_type(struct lldpctl_conn_t *conn, struct writer *w,
256 struct cmd_env *env, void *arg)
257 {
258 char *value_str;
259 int value = -1;
260
261 log_debug("lldpctl", "bond slave src mac");
262
263 lldpctl_atom_t *config = lldpctl_get_configuration(conn);
264 if (config == NULL) {
265 log_warnx("lldpctl",
266 "unable to get configuration from lldpd. %s",
267 lldpctl_last_strerror(conn));
268 return 0;
269 }
270
271 value_str = arg;
272 for (lldpctl_map_t *b_map =
273 lldpctl_key_get_map(lldpctl_k_config_bond_slave_src_mac_type);
274 b_map->string; b_map++) {
275 if (!strcmp(b_map->string, value_str)) {
276 value = b_map->value;
277 break;
278 }
279 }
280
281 if (value == -1) {
282 log_warnx("lldpctl", "invalid value");
283 return 0;
284 }
285
286 if (lldpctl_atom_set_int(config,
287 lldpctl_k_config_bond_slave_src_mac_type, value) == NULL) {
288 log_warnx("lldpctl", "unable to set bond slave src mac type."
289 " %s", lldpctl_last_strerror(conn));
290 lldpctl_atom_dec_ref(config);
291 return 0;
292 }
293
294 log_info("lldpctl", "bond slave src mac set to new value: %s",
295 value_str);
296 lldpctl_atom_dec_ref(config);
297
298 return 1;
299 }
300
301 static int
cmd_maxneighs(struct lldpctl_conn_t * conn,struct writer * w,struct cmd_env * env,void * arg)302 cmd_maxneighs(struct lldpctl_conn_t *conn, struct writer *w,
303 struct cmd_env *env, void *arg)
304 {
305 log_debug("lldpctl", "set maximum neighbors");
306
307 lldpctl_atom_t *config = lldpctl_get_configuration(conn);
308 if (config == NULL) {
309 log_warnx("lldpctl", "unable to get configuration from lldpd. %s",
310 lldpctl_last_strerror(conn));
311 return 0;
312 }
313 if (lldpctl_atom_set_str(config,
314 lldpctl_k_config_max_neighbors, cmdenv_get(env, "max-neighbors")) == NULL) {
315 log_warnx("lldpctl", "unable to set maximum of neighbors. %s",
316 lldpctl_last_strerror(conn));
317 lldpctl_atom_dec_ref(config);
318 return 0;
319 }
320 log_info("lldpctl", "maximum neighbors set to new value %s", cmdenv_get(env, "max-neighbors"));
321 lldpctl_atom_dec_ref(config);
322 return 1;
323 }
324
325 /**
326 * Register `configure system bond-slave-src-mac-type`
327 */
328 static void
register_commands_srcmac_type(struct cmd_node * configure)329 register_commands_srcmac_type(struct cmd_node *configure)
330 {
331 struct cmd_node *bond_slave_src_mac_type =
332 commands_new(configure,
333 "bond-slave-src-mac-type",
334 "Set LLDP bond slave source MAC type",
335 NULL, NULL, NULL);
336
337 for (lldpctl_map_t *b_map =
338 lldpctl_key_get_map(lldpctl_k_config_bond_slave_src_mac_type);
339 b_map->string; b_map++) {
340 if (!strcmp(b_map->string, "real")) {
341 commands_new(
342 commands_new(bond_slave_src_mac_type,
343 b_map->string, "Real mac",
344 NULL, NULL, NULL),
345 NEWLINE, NULL,
346 NULL, cmd_bondslave_srcmac_type,
347 b_map->string);
348 } else if (!strcmp(b_map->string, "zero")) {
349 commands_new(
350 commands_new(bond_slave_src_mac_type,
351 b_map->string, "All zero mac",
352 NULL, NULL, NULL),
353 NEWLINE, NULL,
354 NULL, cmd_bondslave_srcmac_type,
355 b_map->string);
356 } else if (!strcmp(b_map->string, "fixed")) {
357 commands_new(
358 commands_new(bond_slave_src_mac_type,
359 b_map->string, "Fixed value (3Com card)",
360 NULL, NULL, NULL),
361 NEWLINE, NULL,
362 NULL, cmd_bondslave_srcmac_type,
363 b_map->string);
364 } else if (!strcmp(b_map->string, "local")) {
365 commands_new(
366 commands_new(bond_slave_src_mac_type,
367 b_map->string, "Real Mac with locally "
368 "administered bit set",
369 NULL, NULL, NULL),
370 NEWLINE, NULL,
371 NULL, cmd_bondslave_srcmac_type,
372 b_map->string);
373 }
374 }
375 }
376
377 /**
378 * Register `configure system` commands.
379 *
380 * Those are the commands to configure protocol-independant stuff.
381 */
382 void
register_commands_configure_system(struct cmd_node * configure,struct cmd_node * unconfigure)383 register_commands_configure_system(struct cmd_node *configure,
384 struct cmd_node *unconfigure)
385 {
386 struct cmd_node *configure_system = commands_new(
387 configure,
388 "system", "System configuration",
389 cmd_check_no_env, NULL, "ports");
390 struct cmd_node *unconfigure_system = commands_new(
391 unconfigure,
392 "system", "System configuration",
393 cmd_check_no_env, NULL, "ports");
394 struct cmd_node *configure_interface = commands_new(
395 configure_system,
396 "interface", "Interface related items",
397 NULL, NULL, NULL);
398 struct cmd_node *unconfigure_interface = commands_new(
399 unconfigure_system,
400 "interface", "Interface related items",
401 NULL, NULL, NULL);
402
403 commands_new(
404 commands_new(
405 commands_new(configure_system,
406 "description", "Override chassis description",
407 NULL, NULL, NULL),
408 NULL, "Chassis description",
409 NULL, cmd_store_env_value, "description"),
410 NEWLINE, "Override chassis description",
411 NULL, cmd_system_description, "system");
412 commands_new(
413 commands_new(unconfigure_system,
414 "description", "Don't override chassis description",
415 NULL, NULL, NULL),
416 NEWLINE, "Don't override chassis description",
417 NULL, cmd_system_description, "system");
418
419 commands_new(
420 commands_new(
421 commands_new(configure_system,
422 "chassisid", "Override chassis ID",
423 NULL, NULL, NULL),
424 NULL, "Chassis ID",
425 NULL, cmd_store_env_value, "description"),
426 NEWLINE, "Override chassis ID",
427 NULL, cmd_system_chassisid, "system");
428 commands_new(
429 commands_new(unconfigure_system,
430 "chassisid", "Don't override chassis ID",
431 NULL, NULL, NULL),
432 NEWLINE, "Don't override chassis ID",
433 NULL, cmd_system_chassisid, "system");
434
435 commands_new(
436 commands_new(
437 commands_new(configure_system,
438 "platform", "Override platform description",
439 NULL, NULL, NULL),
440 NULL, "Platform description (CDP)",
441 NULL, cmd_store_env_value, "platform"),
442 NEWLINE, "Override platform description",
443 NULL, cmd_system_description, "platform");
444 commands_new(
445 commands_new(unconfigure_system,
446 "platform", "Don't override platform description",
447 NULL, NULL, NULL),
448 NEWLINE, "Don't override platform description",
449 NULL, cmd_system_description, "platform");
450
451 commands_new(
452 commands_new(
453 commands_new(configure_system,
454 "hostname", "Override system name",
455 NULL, NULL, NULL),
456 NULL, "System name",
457 NULL, cmd_store_env_value, "hostname"),
458 NEWLINE, "Override system name",
459 NULL, cmd_hostname, NULL);
460 commands_new(
461 commands_new(unconfigure_system,
462 "hostname", "Don't override system name",
463 NULL, NULL, NULL),
464 NEWLINE, "Don't override system name",
465 NULL, cmd_hostname, NULL);
466
467 commands_new(
468 commands_new(
469 commands_new(configure_system,
470 "max-neighbors", "Set maximum number of neighbors per port",
471 cmd_check_no_env, NULL, "ports"),
472 NULL, "Maximum number of neighbors",
473 NULL, cmd_store_env_value, "max-neighbors"),
474 NEWLINE, "Set maximum number of neighbors per port",
475 NULL, cmd_maxneighs, NULL);
476
477 commands_new(
478 commands_new(
479 commands_new(
480 commands_new(
481 commands_new(configure_system,
482 "ip", "IP related options",
483 NULL, NULL, NULL),
484 "management", "IP management related options",
485 NULL, NULL, NULL),
486 "pattern", "Set IP management pattern",
487 NULL, NULL, NULL),
488 NULL, "IP management pattern (comma-separated list of wildcards)",
489 NULL, cmd_store_env_value, "management-pattern"),
490 NEWLINE, "Set IP management pattern",
491 NULL, cmd_management, NULL);
492 commands_new(
493 commands_new(
494 commands_new(
495 commands_new(unconfigure_system,
496 "ip", "IP related options",
497 NULL, NULL, NULL),
498 "management", "IP management related options",
499 NULL, NULL, NULL),
500 "pattern", "Delete any IP management pattern",
501 NULL, NULL, NULL),
502 NEWLINE, "Delete any IP management pattern",
503 NULL, cmd_management, NULL);
504
505 commands_new(
506 commands_new(
507 commands_new(configure_interface,
508 "pattern", "Set active interface pattern",
509 NULL, NULL, NULL),
510 NULL, "Interface pattern (comma-separated list of wildcards)",
511 NULL, cmd_store_env_value, "iface-pattern"),
512 NEWLINE, "Set active interface pattern",
513 NULL, cmd_iface_pattern, NULL);
514 commands_new(
515 commands_new(unconfigure_interface,
516 "pattern", "Delete any interface pattern",
517 NULL, NULL, NULL),
518 NEWLINE, "Clear interface pattern",
519 NULL, cmd_iface_pattern, NULL);
520
521 commands_new(
522 commands_new(
523 commands_new(configure_interface,
524 "permanent", "Set permanent interface pattern",
525 NULL, NULL, NULL),
526 NULL, "Permanent interface pattern (comma-separated list of wildcards)",
527 NULL, cmd_store_env_value, "iface-pattern"),
528 NEWLINE, "Set permanent interface pattern",
529 NULL, cmd_perm_iface_pattern, NULL);
530 commands_new(
531 commands_new(unconfigure_interface,
532 "permanent", "Clear permanent interface pattern",
533 NULL, NULL, NULL),
534 NEWLINE, "Delete any interface pattern",
535 NULL, cmd_perm_iface_pattern, NULL);
536
537 commands_new(
538 commands_new(configure_interface,
539 "description", "Update interface descriptions with neighbor name",
540 NULL, NULL, NULL),
541 NEWLINE, "Update interface descriptions with neighbor name",
542 NULL, cmd_update_descriptions, "enable");
543 commands_new(
544 commands_new(unconfigure_interface,
545 "description", "Don't update interface descriptions with neighbor name",
546 NULL, NULL, NULL),
547 NEWLINE, "Don't update interface descriptions with neighbor name",
548 NULL, cmd_update_descriptions, NULL);
549
550 commands_new(
551 commands_new(configure_interface,
552 "promiscuous", "Enable promiscuous mode on managed interfaces",
553 NULL, NULL, NULL),
554 NEWLINE, "Enable promiscuous mode on managed interfaces",
555 NULL, cmd_iface_promisc, "enable");
556 commands_new(
557 commands_new(unconfigure_interface,
558 "promiscuous", "Don't enable promiscuous mode on managed interfaces",
559 NULL, NULL, NULL),
560 NEWLINE, "Don't enable promiscuous mode on managed interfaces",
561 NULL, cmd_iface_promisc, NULL);
562
563 register_commands_srcmac_type(configure_system);
564 }
565
566