1 /* -*- mode: c; c-file-style: "openbsd" -*- */
3 * Copyright (c) 2013 Vincent Bernat <bernat@luffy.cx>
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.
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.
25 cmd_txdelay(struct lldpctl_conn_t
*conn
, struct writer
*w
,
26 struct cmd_env
*env
, void *arg
)
28 log_debug("lldpctl", "set transmit delay");
30 lldpctl_atom_t
*config
= lldpctl_get_configuration(conn
);
32 log_warnx("lldpctl", "unable to get configuration from lldpd. %s",
33 lldpctl_last_strerror(conn
));
36 if (lldpctl_atom_set_str(config
,
37 lldpctl_k_config_tx_interval
, cmdenv_get(env
, "tx-interval")) == NULL
) {
38 log_warnx("lldpctl", "unable to set transmit delay. %s",
39 lldpctl_last_strerror(conn
));
40 lldpctl_atom_dec_ref(config
);
43 log_info("lldpctl", "transmit delay set to new value");
44 lldpctl_atom_dec_ref(config
);
49 cmd_txhold(struct lldpctl_conn_t
*conn
, struct writer
*w
,
50 struct cmd_env
*env
, void *arg
)
52 log_debug("lldpctl", "set transmit hold");
54 lldpctl_atom_t
*config
= lldpctl_get_configuration(conn
);
56 log_warnx("lldpctl", "unable to get configuration from lldpd. %s",
57 lldpctl_last_strerror(conn
));
60 if (lldpctl_atom_set_str(config
,
61 lldpctl_k_config_tx_hold
, cmdenv_get(env
, "tx-hold")) == NULL
) {
62 log_warnx("lldpctl", "unable to set transmit hold. %s",
63 lldpctl_last_strerror(conn
));
64 lldpctl_atom_dec_ref(config
);
67 log_info("lldpctl", "transmit hold set to new value %s", cmdenv_get(env
, "tx-hold"));
68 lldpctl_atom_dec_ref(config
);
73 cmd_status(struct lldpctl_conn_t
*conn
, struct writer
*w
,
74 struct cmd_env
*env
, void *arg
)
78 const char *status
= cmdenv_get(env
, "status");
80 log_debug("lldpctl", "lldp administrative port status set to '%s'", status
);
82 if (!status
|| !strlen(status
)) {
83 log_warnx("lldpctl", "no status specified");
87 while ((port
= cmd_iterate_on_ports(conn
, env
, &name
))) {
88 if (lldpctl_atom_set_str(port
, lldpctl_k_port_status
, status
) == NULL
) {
89 log_warnx("lldpctl", "unable to set LLDP status for %s."
90 " %s", name
, lldpctl_last_strerror(conn
));
98 cmd_agent_type(struct lldpctl_conn_t
*conn
, struct writer
*w
,
99 struct cmd_env
*env
, void *arg
)
101 const char *str
= arg
;
104 log_debug("lldpctl", "set agent type to '%s'", str
);
106 lldpctl_atom_t
*config
= lldpctl_get_configuration(conn
);
107 if (config
== NULL
) {
109 "unable to get configuration from lldpd. %s",
110 lldpctl_last_strerror(conn
));
114 for (lldpctl_map_t
*b_map
=
115 lldpctl_key_get_map(lldpctl_k_config_lldp_agent_type
);
116 b_map
->string
; b_map
++) {
117 if (!strcmp(b_map
->string
, str
)) {
118 value
= b_map
->value
;
124 log_warnx("lldpctl", "invalid value");
125 lldpctl_atom_dec_ref(config
);
129 if (lldpctl_atom_set_int(config
,
130 lldpctl_k_config_lldp_agent_type
, value
) == NULL
) {
131 log_warnx("lldpctl", "unable to set LLDP agent type."
132 " %s", lldpctl_last_strerror(conn
));
133 lldpctl_atom_dec_ref(config
);
137 log_info("lldpctl", "agent type set to new value : %s", str
);
138 lldpctl_atom_dec_ref(config
);
144 cmd_portid_type_local(struct lldpctl_conn_t
*conn
, struct writer
*w
,
145 struct cmd_env
*env
, void *arg
)
147 lldpctl_atom_t
*port
;
149 const char *id
= cmdenv_get(env
, "port-id");
150 const char *descr
= cmdenv_get(env
, "port-descr");
152 log_debug("lldpctl", "lldp PortID TLV Subtype Local port-id '%s' port-descr '%s'", id
, descr
);
154 if (!id
|| !strlen(id
)) {
155 log_warnx("lldpctl", "no id specified");
159 while ((port
= cmd_iterate_on_ports(conn
, env
, &name
))) {
160 if (lldpctl_atom_set_str(port
, lldpctl_k_port_id
, id
) == NULL
) {
161 log_warnx("lldpctl", "unable to set LLDP PortID for %s."
162 " %s", name
, lldpctl_last_strerror(conn
));
164 if (descr
&& lldpctl_atom_set_str(port
, lldpctl_k_port_descr
, descr
) == NULL
) {
165 log_warnx("lldpctl", "unable to set LLDP Port Description for %s."
166 " %s", name
, lldpctl_last_strerror(conn
));
174 cmd_portid_type(struct lldpctl_conn_t
*conn
, struct writer
*w
,
175 struct cmd_env
*env
, void *arg
)
180 log_debug("lldpctl", "lldp PortID TLV Subtype");
182 lldpctl_atom_t
*config
= lldpctl_get_configuration(conn
);
183 if (config
== NULL
) {
185 "unable to get configuration from lldpd. %s",
186 lldpctl_last_strerror(conn
));
191 for (lldpctl_map_t
*b_map
=
192 lldpctl_key_get_map(lldpctl_k_config_lldp_portid_type
);
193 b_map
->string
; b_map
++) {
194 if (!strcmp(b_map
->string
, value_str
)) {
195 value
= b_map
->value
;
201 log_warnx("lldpctl", "invalid value");
202 lldpctl_atom_dec_ref(config
);
206 if (lldpctl_atom_set_int(config
,
207 lldpctl_k_config_lldp_portid_type
, value
) == NULL
) {
208 log_warnx("lldpctl", "unable to set LLDP PortID type."
209 " %s", lldpctl_last_strerror(conn
));
210 lldpctl_atom_dec_ref(config
);
214 log_info("lldpctl", "LLDP PortID TLV type set to new value : %s", value_str
);
215 lldpctl_atom_dec_ref(config
);
221 cmd_chassis_cap_advertise(struct lldpctl_conn_t
*conn
, struct writer
*w
,
222 struct cmd_env
*env
, void *arg
)
224 log_debug("lldpctl", "lldp capabilities-advertisements %s", arg
?"enable":"disable");
226 lldpctl_atom_t
*config
= lldpctl_get_configuration(conn
);
227 if (config
== NULL
) {
228 log_warnx("lldpctl", "unable to get configuration from lldpd. %s",
229 lldpctl_last_strerror(conn
));
232 if (lldpctl_atom_set_int(config
,
233 lldpctl_k_config_chassis_cap_advertise
,
235 log_warnx("lldpctl", "unable to %s chassis capabilities advertisement: %s",
236 arg
?"enable":"disable",
237 lldpctl_last_strerror(conn
));
238 lldpctl_atom_dec_ref(config
);
241 log_info("lldpctl", "chassis capabilities advertisement %s",
242 arg
?"enabled":"disabled");
243 lldpctl_atom_dec_ref(config
);
247 /* FIXME: see about compressing this with other functions */
249 cmd_chassis_mgmt_advertise(struct lldpctl_conn_t
*conn
, struct writer
*w
,
250 struct cmd_env
*env
, void *arg
)
252 log_debug("lldpctl", "lldp management-addresses-advertisements %s", arg
?"enable":"disable");
254 lldpctl_atom_t
*config
= lldpctl_get_configuration(conn
);
255 if (config
== NULL
) {
256 log_warnx("lldpctl", "unable to get configuration from lldpd. %s",
257 lldpctl_last_strerror(conn
));
260 if (lldpctl_atom_set_int(config
,
261 lldpctl_k_config_chassis_mgmt_advertise
,
263 log_warnx("lldpctl", "unable to %s management addresses advertisement: %s",
264 arg
?"enable":"disable",
265 lldpctl_last_strerror(conn
));
266 lldpctl_atom_dec_ref(config
);
269 log_info("lldpctl", "management addresses advertisement %s",
270 arg
?"enabled":"disabled");
271 lldpctl_atom_dec_ref(config
);
277 cmd_custom_tlv_set(struct lldpctl_conn_t
*conn
, struct writer
*w
,
278 struct cmd_env
*env
, void *arg
)
280 lldpctl_atom_t
*port
;
283 uint8_t oui
[LLDP_TLV_ORG_OUI_LEN
];
284 uint8_t oui_info
[LLDP_TLV_ORG_OUI_INFO_MAXLEN
];
285 int oui_info_len
= 0;
286 uint16_t subtype
= 0;
289 if (!arg
|| !strcmp(arg
, "remove"))
292 log_debug("lldpctl", "lldp custom-tlv(s) %s", op
);
297 s
= cmdenv_get(env
, "oui");
299 sscanf(s
, "%02hhx,%02hhx,%02hhx", &oui
[0], &oui
[1], &oui
[2]) != 3 &&
300 sscanf(s
, "%02hhX,%02hhX,%02hhX", &oui
[0], &oui
[1], &oui
[2]) != 3) ) {
301 log_warnx("lldpctl", "invalid OUI value '%s'", s
);
305 s
= cmdenv_get(env
, "subtype");
307 log_warnx("lldpctl", "no subtype specified");
311 subtype
= strtonum(s
, 0, 255, &errstr
);
312 if (errstr
!= NULL
) {
313 log_warnx("lldpctl", "invalid subtype value `%s': %s",
319 s
= cmdenv_get(env
, "oui-info");
320 /* This info is optional */
322 const char delim
[] = ",";
323 char *s_copy
= strdup(s
);
324 char *token
= strtok(s_copy
, delim
);
325 while (token
!= NULL
) {
326 if (sscanf(token
, "%02hhx", &oui_info
[oui_info_len
]) == 1 ||
327 sscanf(token
, "%02hhX", &oui_info
[oui_info_len
]) == 1)
329 if (oui_info_len
>= sizeof(oui_info
))
331 token
= strtok(NULL
, delim
);
336 s
= cmdenv_get(env
, "replace");
337 /* This info is optional */
338 if (s
) op
= "replace";
341 while ((port
= cmd_iterate_on_ports(conn
, env
, &name
))) {
342 lldpctl_atom_t
*custom_tlvs
;
344 lldpctl_atom_set(port
, lldpctl_k_custom_tlvs_clear
, NULL
);
345 } else if (!(custom_tlvs
= lldpctl_atom_get(port
, lldpctl_k_custom_tlvs
))) {
346 log_warnx("lldpctl", "unable to get custom TLVs for port %s", name
);
348 lldpctl_atom_t
*tlv
= lldpctl_atom_create(custom_tlvs
);
350 log_warnx("lldpctl", "unable to create new custom TLV for port %s",
353 /* Configure custom TLV */
354 lldpctl_atom_set_buffer(tlv
, lldpctl_k_custom_tlv_oui
, oui
, sizeof(oui
));
355 lldpctl_atom_set_int(tlv
, lldpctl_k_custom_tlv_oui_subtype
, subtype
);
356 lldpctl_atom_set_buffer(tlv
, lldpctl_k_custom_tlv_oui_info_string
, oui_info
, oui_info_len
);
357 lldpctl_atom_set_str(tlv
, lldpctl_k_custom_tlv_op
, op
);
359 /* Assign it to port */
360 lldpctl_atom_set(port
, lldpctl_k_custom_tlv
, tlv
);
362 lldpctl_atom_dec_ref(tlv
);
364 lldpctl_atom_dec_ref(custom_tlvs
);
372 cmd_check_no_add_env(struct cmd_env
*env
, void *arg
)
374 const char *what
= arg
;
375 if (cmdenv_get(env
, "add")) return 0;
376 if (cmdenv_get(env
, what
)) return 0;
381 cmd_check_no_replace_env(struct cmd_env
*env
, void *arg
)
383 const char *what
= arg
;
384 if (cmdenv_get(env
, "replace")) return 0;
385 if (cmdenv_get(env
, what
)) return 0;
390 register_commands_configure_lldp_custom_tlvs(struct cmd_node
*configure_lldp
,
391 struct cmd_node
*unconfigure_lldp
)
393 struct cmd_node
*configure_custom_tlvs
;
394 struct cmd_node
*unconfigure_custom_tlvs
;
395 struct cmd_node
*configure_custom_tlvs_basic
;
396 struct cmd_node
*unconfigure_custom_tlvs_basic
;
398 configure_custom_tlvs
=
399 commands_new(configure_lldp
,
401 "Add custom TLV(s) to be broadcast on ports",
404 unconfigure_custom_tlvs
=
405 commands_new(unconfigure_lldp
,
407 "Remove ALL custom TLV(s)",
410 commands_new(unconfigure_custom_tlvs
,
411 NEWLINE
, "Remove ALL custom TLV",
412 NULL
, cmd_custom_tlv_set
, NULL
);
414 commands_new(configure_custom_tlvs
,
415 "add", "Add custom TLV",
416 cmd_check_no_replace_env
, cmd_store_env_and_pop
, "add");
417 commands_new(configure_custom_tlvs
,
418 "replace", "Replace custom TLV",
419 cmd_check_no_add_env
, cmd_store_env_and_pop
, "replace");
421 /* Basic form: 'configure lldp custom-tlv oui 11,22,33 subtype 44' */
422 configure_custom_tlvs_basic
=
426 commands_new(configure_custom_tlvs
,
427 "oui", "Organizationally Unique Identifier",
429 NULL
, "Organizationally Unique Identifier",
430 NULL
, cmd_store_env_value
, "oui"),
431 "subtype", "Organizationally Defined Subtype",
433 NULL
, "Organizationally Defined Subtype",
434 NULL
, cmd_store_env_value
, "subtype");
436 commands_new(configure_custom_tlvs_basic
,
437 NEWLINE
, "Add custom TLV(s) to be broadcast on ports",
438 NULL
, cmd_custom_tlv_set
, "enable");
440 /* Basic form: 'unconfigure lldp custom-tlv oui 11,22,33 subtype 44' */
441 unconfigure_custom_tlvs_basic
=
445 commands_new(unconfigure_custom_tlvs
,
446 "oui", "Organizationally Unique Identifier",
448 NULL
, "Organizationally Unique Identifier",
449 NULL
, cmd_store_env_value
, "oui"),
450 "subtype", "Organizationally Defined Subtype",
452 NULL
, "Organizationally Defined Subtype",
453 NULL
, cmd_store_env_value
, "subtype");
455 commands_new(unconfigure_custom_tlvs_basic
,
456 NEWLINE
, "Remove specific custom TLV",
457 NULL
, cmd_custom_tlv_set
, "remove");
459 /* Extended form: 'configure custom-tlv lldp oui 11,22,33 subtype 44 oui-info 55,66,77,...' */
462 commands_new(configure_custom_tlvs_basic
,
463 "oui-info", "Organizationally Unique Identifier",
465 NULL
, "OUI Info String",
466 NULL
, cmd_store_env_value
, "oui-info"),
467 NEWLINE
, "Add custom TLV(s) to be broadcast on ports",
468 NULL
, cmd_custom_tlv_set
, "enable");
470 #endif /* ENABLE_CUSTOM */
473 cmd_store_status_env_value(struct lldpctl_conn_t
*conn
, struct writer
*w
,
474 struct cmd_env
*env
, void *value
)
476 return cmd_store_something_env_value("status", env
, value
);
480 * Register `configure lldp` commands.
482 * Those are the commands that are related to the LLDP protocol but not
483 * Dot1/Dot3/MED. Commands not related to LLDP should go in system instead.
486 register_commands_configure_lldp(struct cmd_node
*configure
,
487 struct cmd_node
*unconfigure
)
489 struct cmd_node
*configure_lldp
= commands_new(
491 "lldp", "LLDP configuration",
493 struct cmd_node
*unconfigure_lldp
= commands_new(
495 "lldp", "LLDP configuration",
500 commands_new(configure_lldp
,
501 "tx-interval", "Set LLDP transmit delay",
502 cmd_check_no_env
, NULL
, "ports"),
503 NULL
, "LLDP transmit delay in seconds",
504 NULL
, cmd_store_env_value
, "tx-interval"),
505 NEWLINE
, "Set LLDP transmit delay",
506 NULL
, cmd_txdelay
, NULL
);
510 commands_new(configure_lldp
,
511 "tx-hold", "Set LLDP transmit hold",
512 cmd_check_no_env
, NULL
, "ports"),
513 NULL
, "LLDP transmit hold in seconds",
514 NULL
, cmd_store_env_value
, "tx-hold"),
515 NEWLINE
, "Set LLDP transmit hold",
516 NULL
, cmd_txhold
, NULL
);
518 struct cmd_node
*status
= commands_new(configure_lldp
,
519 "status", "Set administrative status",
522 for (lldpctl_map_t
*status_map
=
523 lldpctl_key_get_map(lldpctl_k_port_status
);
526 const char *tag
= strdup(totag(status_map
->string
));
532 NULL
, cmd_store_status_env_value
, status_map
->string
),
533 NEWLINE
, "Set port administrative status",
534 NULL
, cmd_status
, NULL
);
537 /* Configure the various agent type we can configure. */
538 struct cmd_node
*configure_lldp_agent_type
= commands_new(
543 for (lldpctl_map_t
*b_map
=
544 lldpctl_key_get_map(lldpctl_k_config_lldp_agent_type
);
545 b_map
->string
; b_map
++) {
546 const char *tag
= strdup(totag(b_map
->string
));
549 commands_new(configure_lldp_agent_type
,
553 NEWLINE
, "Set LLDP agent type",
554 NULL
, cmd_agent_type
, b_map
->string
);
557 /* Now handle the various portid subtypes we can configure. */
558 struct cmd_node
*configure_lldp_portid_type
= commands_new(
560 "portidsubtype", "LLDP PortID TLV Subtype",
563 for (lldpctl_map_t
*b_map
=
564 lldpctl_key_get_map(lldpctl_k_config_lldp_portid_type
);
565 b_map
->string
; b_map
++) {
566 if (!strcmp(b_map
->string
, "ifname")) {
568 commands_new(configure_lldp_portid_type
,
569 b_map
->string
, "Interface Name",
570 cmd_check_no_env
, NULL
, "ports"),
572 NULL
, cmd_portid_type
,
574 } else if (!strcmp(b_map
->string
, "local")) {
575 struct cmd_node
*port_id
= commands_new(
576 commands_new(configure_lldp_portid_type
,
577 b_map
->string
, "Local",
580 NULL
, cmd_store_env_value
, "port-id");
581 commands_new(port_id
,
582 NEWLINE
, "Set local port ID",
583 NULL
, cmd_portid_type_local
,
587 commands_new(port_id
,
589 "Also set port description",
591 NULL
, "Port description",
592 NULL
, cmd_store_env_value
, "port-descr"),
593 NEWLINE
, "Set local port ID and description",
594 NULL
, cmd_portid_type_local
, NULL
);
595 } else if (!strcmp(b_map
->string
, "macaddress")) {
597 commands_new(configure_lldp_portid_type
,
598 b_map
->string
, "MAC Address",
599 cmd_check_no_env
, NULL
, "ports"),
601 NULL
, cmd_portid_type
,
607 commands_new(configure_lldp
,
608 "capabilities-advertisements",
609 "Enable chassis capabilities advertisement",
610 cmd_check_no_env
, NULL
, "ports"),
611 NEWLINE
, "Enable chassis capabilities advertisement",
612 NULL
, cmd_chassis_cap_advertise
, "enable");
614 commands_new(unconfigure_lldp
,
615 "capabilities-advertisements",
616 "Don't enable chassis capabilities advertisement",
618 NEWLINE
, "Don't enable chassis capabilities advertisement",
619 NULL
, cmd_chassis_cap_advertise
, NULL
);
622 commands_new(configure_lldp
,
623 "management-addresses-advertisements",
624 "Enable management addresses advertisement",
626 NEWLINE
, "Enable management addresses advertisement",
627 NULL
, cmd_chassis_mgmt_advertise
, "enable");
629 commands_new(unconfigure_lldp
,
630 "management-addresses-advertisements",
631 "Don't enable management addresses advertisement",
633 NEWLINE
, "Don't enable management addresses advertisement",
634 NULL
, cmd_chassis_mgmt_advertise
, NULL
);
638 register_commands_configure_lldp_custom_tlvs(configure_lldp
, unconfigure_lldp
);