]> git.ipfire.org Git - thirdparty/lldpd.git/blame - src/client/conf-lldp.c
lldpd: make custom TLV code optional
[thirdparty/lldpd.git] / src / client / conf-lldp.c
CommitLineData
994b3371
VB
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
21#include "client.h"
22#include "../log.h"
23
24static int
25cmd_txdelay(struct lldpctl_conn_t *conn, struct writer *w,
26 struct cmd_env *env, void *arg)
27{
28 log_debug("lldpctl", "set transmit delay");
29
30 lldpctl_atom_t *config = lldpctl_get_configuration(conn);
31 if (config == NULL) {
32 log_warnx("lldpctl", "unable to get configuration from lldpd. %s",
33 lldpctl_last_strerror(conn));
34 return 0;
35 }
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);
41 return 0;
42 }
43 log_info("lldpctl", "transmit delay set to new value");
44 lldpctl_atom_dec_ref(config);
45 return 1;
46}
47
48static int
49cmd_txhold(struct lldpctl_conn_t *conn, struct writer *w,
50 struct cmd_env *env, void *arg)
51{
52 log_debug("lldpctl", "set transmit hold");
53
54 lldpctl_atom_t *config = lldpctl_get_configuration(conn);
55 if (config == NULL) {
56 log_warnx("lldpctl", "unable to get configuration from lldpd. %s",
57 lldpctl_last_strerror(conn));
58 return 0;
59 }
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);
65 return 0;
66 }
67 log_info("lldpctl", "transmit hold set to new value %s", cmdenv_get(env, "tx-hold"));
68 lldpctl_atom_dec_ref(config);
69 return 1;
70}
71
8e46010c
AA
72static int
73cmd_portid_type_local(struct lldpctl_conn_t *conn, struct writer *w,
74 struct cmd_env *env, void *arg)
75{
76 lldpctl_atom_t *iface;
77 const char *id = cmdenv_get(env, "port-id");
c267d0f2 78 const char *descr = cmdenv_get(env, "port-descr");
8e46010c 79
e119d5dd
AA
80 log_debug("lldpctl", "lldp PortID TLV Subtype Local port-id '%s' port-descr '%s'", id, descr);
81
8e46010c 82 if (!id || !strlen(id)) {
bacc4a6a 83 log_warnx("lldpctl", "no id specified");
8e46010c
AA
84 return 0;
85 }
86
87 while ((iface = cmd_iterate_on_interfaces(conn, env))) {
88 lldpctl_atom_t *port = lldpctl_get_port(iface);
89 if (lldpctl_atom_set_str(port, lldpctl_k_port_id, id) == NULL) {
90 log_warnx("lldpctl", "unable to set LLDP PortID."
91 " %s", lldpctl_last_strerror(conn));
92 }
c267d0f2
AA
93 if (descr && lldpctl_atom_set_str(port, lldpctl_k_port_descr, descr) == NULL) {
94 log_warnx("lldpctl", "unable to set LLDP Port Description."
95 " %s", lldpctl_last_strerror(conn));
96 }
8e46010c
AA
97 lldpctl_atom_dec_ref(port);
98 }
99
100 return 1;
101}
102
8fbd3195
ST
103static int
104cmd_portid_type(struct lldpctl_conn_t *conn, struct writer *w,
105 struct cmd_env *env, void *arg)
106{
107 char *value_str;
cf719ce8 108 int value = -1;
8fbd3195
ST
109
110 log_debug("lldpctl", "lldp PortID TLV Subtype");
111
112 lldpctl_atom_t *config = lldpctl_get_configuration(conn);
113 if (config == NULL) {
114 log_warnx("lldpctl",
115 "unable to get configuration from lldpd. %s",
116 lldpctl_last_strerror(conn));
117 return 0;
118 }
119
120 value_str = arg;
121 for (lldpctl_map_t *b_map =
122 lldpctl_key_get_map(lldpctl_k_config_lldp_portid_type);
123 b_map->string; b_map++) {
124 if (!strcmp(b_map->string, value_str)) {
125 value = b_map->value;
126 break;
127 }
128 }
129
130 if (value == -1) {
131 log_warnx("lldpctl", "invalid value");
132 lldpctl_atom_dec_ref(config);
133 return 0;
134 }
135
136 if (lldpctl_atom_set_int(config,
137 lldpctl_k_config_lldp_portid_type, value) == NULL) {
138 log_warnx("lldpctl", "unable to set LLDP PortID type."
139 " %s", lldpctl_last_strerror(conn));
140 lldpctl_atom_dec_ref(config);
141 return 0;
142 }
143
ff0a278f 144 log_info("lldpctl", "LLDP PortID TLV type set to new value : %s", value_str);
8fbd3195
ST
145 lldpctl_atom_dec_ref(config);
146
147 return 1;
148}
149
ca838758
AA
150static int
151cmd_chassis_cap_advertise(struct lldpctl_conn_t *conn, struct writer *w,
152 struct cmd_env *env, void *arg)
153{
e119d5dd
AA
154 log_debug("lldpctl", "lldp capabilities-advertisements %s", arg?"enable":"disable");
155
ca838758
AA
156 lldpctl_atom_t *config = lldpctl_get_configuration(conn);
157 if (config == NULL) {
158 log_warnx("lldpctl", "unable to get configuration from lldpd. %s",
159 lldpctl_last_strerror(conn));
160 return 0;
161 }
162 if (lldpctl_atom_set_int(config,
163 lldpctl_k_config_chassis_cap_advertise,
164 arg?1:0) == NULL) {
165 log_warnx("lldpctl", "unable to %s chassis capabilities advertisement: %s",
166 arg?"enable":"disable",
167 lldpctl_last_strerror(conn));
168 lldpctl_atom_dec_ref(config);
169 return 0;
170 }
171 log_info("lldpctl", "chassis capabilities advertisement %s",
172 arg?"enabled":"disabled");
173 lldpctl_atom_dec_ref(config);
174 return 1;
175}
176
1c2217aa
AA
177/* FIXME: see about compressing this with other functions */
178static int
179cmd_chassis_mgmt_advertise(struct lldpctl_conn_t *conn, struct writer *w,
180 struct cmd_env *env, void *arg)
181{
e119d5dd
AA
182 log_debug("lldpctl", "lldp management-addresses-advertisements %s", arg?"enable":"disable");
183
1c2217aa
AA
184 lldpctl_atom_t *config = lldpctl_get_configuration(conn);
185 if (config == NULL) {
186 log_warnx("lldpctl", "unable to get configuration from lldpd. %s",
187 lldpctl_last_strerror(conn));
188 return 0;
189 }
190 if (lldpctl_atom_set_int(config,
191 lldpctl_k_config_chassis_mgmt_advertise,
192 arg?1:0) == NULL) {
193 log_warnx("lldpctl", "unable to %s management addresses advertisement: %s",
194 arg?"enable":"disable",
195 lldpctl_last_strerror(conn));
196 lldpctl_atom_dec_ref(config);
197 return 0;
198 }
199 log_info("lldpctl", "management addresses advertisement %s",
200 arg?"enabled":"disabled");
201 lldpctl_atom_dec_ref(config);
202 return 1;
203}
204
fb1b78bb 205#ifdef ENABLE_CUSTOM
41cb7781
AA
206static int
207cmd_custom_tlv_set(struct lldpctl_conn_t *conn, struct writer *w,
208 struct cmd_env *env, void *arg)
209{
210 lldpctl_atom_t *iface;
211 const char *s;
212 uint8_t oui[LLDP_TLV_ORG_OUI_LEN];
213 uint8_t oui_info[LLDP_TLV_ORG_OUI_INFO_MAXLEN];
214 int oui_info_len = 0;
215 uint16_t subtype = 0;
216
217 log_debug("lldpctl", "lldp custom-tlv(s) %s", arg?"set":"clear");
218
219 if (!arg)
220 goto set;
221
222 s = cmdenv_get(env, "oui");
223 if (!s || (
224 sscanf(s, "%02hhx,%02hhx,%02hhx", &oui[0], &oui[1], &oui[2]) != 3 &&
225 sscanf(s, "%02hhX,%02hhX,%02hhX", &oui[0], &oui[1], &oui[2]) != 3) ) {
226 log_warnx("lldpctl", "invalid OUI value '%s'", s);
227 return 0;
228 }
229
230 s = cmdenv_get(env, "subtype");
231 if (!s) {
232 log_warnx("lldpctl", "no subtype specified");
233 return 0;
234 } else {
235 subtype = (uint16_t)atoi(s);
236 if (subtype > 255) {
237 log_warnx("lldpctl", "invalid subtype range value '%s'", s);
238 return 0;
239 }
240 }
241
242 s = cmdenv_get(env, "oui-info");
243 /* This info is optional */
244 if (s) {
245 const char delim[] = ",";
246 char *s_copy = strdup(s);
247 char *token = strtok(s_copy, delim);
248 while (token != NULL) {
249 if (sscanf(token, "%02hhx", &oui_info[oui_info_len]) == 1 ||
250 sscanf(token, "%02hhX", &oui_info[oui_info_len]) == 1)
251 oui_info_len++;
252 if (oui_info_len >= sizeof(oui_info))
253 break;
254 token = strtok(NULL, delim);
255 }
256 free(s_copy);
257 }
258
259set:
260 while ((iface = cmd_iterate_on_interfaces(conn, env))) {
261 lldpctl_atom_t *port = lldpctl_get_port(iface);
262 lldpctl_atom_t *custom_tlvs;
263 if (!arg) {
264 lldpctl_atom_set(port, lldpctl_k_custom_tlvs_clear, NULL);
265 } else if (!(custom_tlvs = lldpctl_atom_get(port, lldpctl_k_custom_tlvs))) {
266 log_warnx("lldpctl", "unable to get custom TLVs for port");
267 } else {
268 lldpctl_atom_t *tlv = lldpctl_atom_create(custom_tlvs);
269 if (!tlv) {
270 log_warnx("lldpctl", "unable to create new custom TLV for port");
271 } else {
272 /* Configure custom TLV */
273 lldpctl_atom_set_buffer(tlv, lldpctl_k_custom_tlv_oui, oui, sizeof(oui));
274 lldpctl_atom_set_int(tlv, lldpctl_k_custom_tlv_oui_subtype, subtype);
275 lldpctl_atom_set_buffer(tlv, lldpctl_k_custom_tlv_oui_info_string, oui_info, oui_info_len);
276
277 /* Assign it to port */
278 lldpctl_atom_set(port, lldpctl_k_custom_tlv, tlv);
279 }
280 }
281 lldpctl_atom_dec_ref(port);
282 }
283
284 return 1;
285}
286
287void
288register_commands_configure_lldp_custom_tlvs(struct cmd_node *configure_lldp)
289{
290 struct cmd_node *configure_custom_tlvs;
291 struct cmd_node *configure_custom_tlvs_basic;
292
293 configure_custom_tlvs =
294 commands_new(configure_lldp,
295 "custom-tlv",
296 "Add custom TLV(s) to be broadcast on ports",
297 NULL, NULL, NULL);
298
299 /* Basic form: 'configure lldp oui 11,22,33 subtype 44' */
300 configure_custom_tlvs_basic =
301 commands_new(
302 commands_new(
303 commands_new(
304 commands_new(configure_custom_tlvs,
305 "oui", "Organizationally Unique Identifier",
306 NULL, NULL, NULL),
307 NULL, "Organizationally Unique Identifier",
308 NULL, cmd_store_env_value, "oui"),
309 "subtype", "Organizationally Defined Subtype",
310 NULL, NULL, NULL),
311 NULL, "Organizationally Defined Subtype",
312 NULL, cmd_store_env_value, "subtype");
313
314 commands_new(configure_custom_tlvs_basic,
315 NEWLINE, "Add custom TLV(s) to be broadcast on ports",
316 NULL, cmd_custom_tlv_set, "enable");
317
318 /* Extended form: 'configure lldp oui 11,22,33 subtype 44 oui-info 55,66,77,...' */
319 commands_new(
320 commands_new(
321 commands_new(configure_custom_tlvs_basic,
322 "oui-info", "Organizationally Unique Identifier",
323 NULL, NULL, NULL),
324 NULL, "OUI Info String",
325 NULL, cmd_store_env_value, "oui-info"),
326 NEWLINE, "Add custom TLV(s) to be broadcast on ports",
327 NULL, cmd_custom_tlv_set, "enable");
328}
fb1b78bb 329#endif /* ENABLE_CUSTOM */
41cb7781 330
994b3371
VB
331/**
332 * Register `configure lldp` commands.
333 *
334 * Those are the commands that are related to the LLDP protocol but not
335 * Dot1/Dot3/MED. Commands not related to LLDP should go in system instead.
336 */
337void
ca838758
AA
338register_commands_configure_lldp(struct cmd_node *configure,
339 struct cmd_node *unconfigure)
994b3371
VB
340{
341 struct cmd_node *configure_lldp = commands_new(
342 configure,
343 "lldp", "LLDP configuration",
344 NULL, NULL, NULL);
ca838758
AA
345 struct cmd_node *unconfigure_lldp = commands_new(
346 unconfigure,
347 "lldp", "LLDP configuration",
348 NULL, NULL, NULL);
994b3371
VB
349
350 commands_new(
351 commands_new(
352 commands_new(configure_lldp,
353 "tx-interval", "Set LLDP transmit delay",
354 cmd_check_no_env, NULL, "ports"),
355 NULL, "LLDP transmit delay in seconds",
356 NULL, cmd_store_env_value, "tx-interval"),
357 NEWLINE, "Set LLDP transmit delay",
358 NULL, cmd_txdelay, NULL);
359
360 commands_new(
361 commands_new(
362 commands_new(configure_lldp,
363 "tx-hold", "Set LLDP transmit hold",
364 cmd_check_no_env, NULL, "ports"),
365 NULL, "LLDP transmit hold in seconds",
366 NULL, cmd_store_env_value, "tx-hold"),
367 NEWLINE, "Set LLDP transmit hold",
368 NULL, cmd_txhold, NULL);
8fbd3195
ST
369
370 /* Now handle the various portid subtypes we can configure. */
371 struct cmd_node *configure_lldp_portid_type = commands_new(
372 configure_lldp,
373 "portidsubtype", "LLDP PortID TLV Subtype ",
374 NULL, NULL, NULL);
375
376 for (lldpctl_map_t *b_map =
377 lldpctl_key_get_map(lldpctl_k_config_lldp_portid_type);
378 b_map->string; b_map++) {
379 if (!strcmp(b_map->string, "ifname")) {
380 commands_new(
381 commands_new(configure_lldp_portid_type,
382 b_map->string, "Interface Name",
383 NULL, NULL, NULL),
384 NEWLINE, NULL,
385 NULL, cmd_portid_type,
386 b_map->string);
8e46010c 387 } else if (!strcmp(b_map->string, "local")) {
c267d0f2
AA
388 struct cmd_node *port_id = commands_new(
389 commands_new(configure_lldp_portid_type,
390 b_map->string, "Local",
391 NULL, NULL, NULL),
ec5a3601 392 NULL, "Port ID",
c267d0f2
AA
393 NULL, cmd_store_env_value, "port-id");
394 commands_new(port_id,
ec5a3601 395 NEWLINE, "Set local port ID",
8e46010c
AA
396 NULL, cmd_portid_type_local,
397 b_map->string);
ec5a3601 398 commands_new(
332f8eea
VB
399 commands_new(
400 commands_new(port_id,
401 "description",
402 "Also set port description",
403 NULL, NULL, NULL),
404 NULL, "Port description",
405 NULL, cmd_store_env_value, "port-descr"),
ec5a3601
VB
406 NEWLINE, "Set local port ID and description",
407 NULL, cmd_portid_type_local, NULL);
8fbd3195
ST
408 } else if (!strcmp(b_map->string, "macaddress")) {
409 commands_new(
410 commands_new(configure_lldp_portid_type,
411 b_map->string, "MAC Address",
412 NULL, NULL, NULL),
413 NEWLINE, NULL,
414 NULL, cmd_portid_type,
415 b_map->string);
416 }
417 }
ca838758
AA
418
419 commands_new(
420 commands_new(configure_lldp,
421 "capabilities-advertisements",
422 "Enable chassis capabilities advertisement",
423 NULL, NULL, NULL),
424 NEWLINE, "Enable chassis capabilities advertisement",
425 NULL, cmd_chassis_cap_advertise, "enable");
426 commands_new(
427 commands_new(unconfigure_lldp,
428 "capabilities-advertisements",
429 "Don't enable chassis capabilities advertisement",
430 NULL, NULL, NULL),
431 NEWLINE, "Don't enable chassis capabilities advertisement",
432 NULL, cmd_chassis_cap_advertise, NULL);
1c2217aa
AA
433
434 commands_new(
435 commands_new(configure_lldp,
436 "management-addresses-advertisements",
437 "Enable management addresses advertisement",
438 NULL, NULL, NULL),
439 NEWLINE, "Enable management addresses advertisement",
440 NULL, cmd_chassis_mgmt_advertise, "enable");
441 commands_new(
442 commands_new(unconfigure_lldp,
443 "management-addresses-advertisements",
444 "Don't enable management addresses advertisement",
445 NULL, NULL, NULL),
446 NEWLINE, "Don't enable management addresses advertisement",
447 NULL, cmd_chassis_mgmt_advertise, NULL);
41cb7781
AA
448
449
fb1b78bb 450#ifdef ENABLE_CUSTOM
41cb7781
AA
451 register_commands_configure_lldp_custom_tlvs(configure_lldp);
452 commands_new(
453 commands_new(unconfigure_lldp,
454 "custom-tlvs",
455 "Clear all (previously set) custom TLVs",
456 NULL, NULL, NULL),
457 NEWLINE, "Clear all (previously set) custom TLVs",
458 NULL, cmd_custom_tlv_set, NULL);
fb1b78bb 459#endif
994b3371 460}