]> git.ipfire.org Git - thirdparty/lldpd.git/blame - src/client/conf-med.c
client: spell fix
[thirdparty/lldpd.git] / src / client / conf-med.c
CommitLineData
4b292b55
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 <unistd.h>
19#include <string.h>
20
21#include "client.h"
22#include "../log.h"
23
9a775667 24static int
8b549648 25_cmd_medlocation(struct lldpctl_conn_t *conn, struct cmd_env *env, int format)
4b292b55 26{
9da663f7
VB
27 lldpctl_atom_t *port;
28 const char *name;
29 while ((port = cmd_iterate_on_ports(conn, env, &name))) {
9a775667
VB
30 lldpctl_atom_t *med_location = NULL, *med_locations = NULL;
31 const char *what = NULL;
32 int ok = 0;
33
34 med_locations = lldpctl_atom_get(port, lldpctl_k_port_med_locations);
35 if (med_locations == NULL) {
8b549648
VB
36 log_warnx("lldpctl",
37 "unable to set LLDP-MED location: support seems unavailable");
9da663f7 38 continue; /* Iterator needs to be run until end */
9a775667
VB
39 }
40
41 med_location = lldpctl_atom_iter_value(med_locations,
42 lldpctl_atom_iter_next(med_locations,
43 lldpctl_atom_iter(med_locations)));
44
45 switch (format) {
46 case LLDP_MED_LOCFORMAT_COORD:
8b549648
VB
47 if ((what = "format",
48 lldpctl_atom_set_int(med_location,
49 lldpctl_k_med_location_format, format)) == NULL ||
50 (what = "latitude",
51 lldpctl_atom_set_str(med_location,
52 lldpctl_k_med_location_latitude,
53 cmdenv_get(env, "latitude"))) == NULL ||
54 (what = "longitude",
55 lldpctl_atom_set_str(med_location,
56 lldpctl_k_med_location_longitude,
57 cmdenv_get(env, "longitude"))) == NULL ||
58 (what = "altitude",
59 lldpctl_atom_set_str(med_location,
60 lldpctl_k_med_location_altitude,
61 cmdenv_get(env, "altitude"))) == NULL ||
62 (what = "altitude unit",
63 lldpctl_atom_set_str(med_location,
64 lldpctl_k_med_location_altitude_unit,
65 cmdenv_get(env, "altitude-unit"))) == NULL ||
66 (what = "datum",
67 lldpctl_atom_set_str(med_location,
68 lldpctl_k_med_location_geoid,
69 cmdenv_get(env, "datum"))) == NULL)
9a775667
VB
70 log_warnx("lldpctl",
71 "unable to set LLDP MED location value for %s on %s. %s.",
72 what, name, lldpctl_last_strerror(conn));
8b549648
VB
73 else
74 ok = 1;
9a775667
VB
75 break;
76 case LLDP_MED_LOCFORMAT_CIVIC:
8b549648
VB
77 if ((what = "format",
78 lldpctl_atom_set_int(med_location,
79 lldpctl_k_med_location_format, format)) == NULL ||
80 (what = "country",
81 lldpctl_atom_set_str(med_location,
82 lldpctl_k_med_location_country,
83 cmdenv_get(env, "country"))) == NULL) {
9a775667
VB
84 log_warnx("lldpctl",
85 "unable to set LLDP MED location value for %s on %s. %s.",
86 what, name, lldpctl_last_strerror(conn));
87 break;
88 }
89 ok = 1;
90 for (lldpctl_map_t *addr_map =
91 lldpctl_key_get_map(lldpctl_k_med_civicaddress_type);
8b549648 92 addr_map->string; addr_map++) {
9a775667
VB
93 lldpctl_atom_t *cael, *caels;
94 const char *value = cmdenv_get(env, addr_map->string);
95 if (!value) continue;
96
8b549648
VB
97 caels = lldpctl_atom_get(med_location,
98 lldpctl_k_med_location_ca_elements);
9a775667
VB
99 cael = lldpctl_atom_create(caels);
100
8b549648
VB
101 if (lldpctl_atom_set_str(cael,
102 lldpctl_k_med_civicaddress_type,
9a775667 103 addr_map->string) == NULL ||
8b549648
VB
104 lldpctl_atom_set_str(cael,
105 lldpctl_k_med_civicaddress_value,
9a775667
VB
106 value) == NULL ||
107 lldpctl_atom_set(med_location,
108 lldpctl_k_med_location_ca_elements,
109 cael) == NULL) {
8b549648
VB
110 log_warnx("lldpctl",
111 "unable to add a civic address element `%s`. %s",
112 addr_map->string,
113 lldpctl_last_strerror(conn));
114 ok = 0;
9a775667
VB
115 }
116
117 lldpctl_atom_dec_ref(cael);
118 lldpctl_atom_dec_ref(caels);
119 if (!ok) break;
120 }
121 break;
122 case LLDP_MED_LOCFORMAT_ELIN:
123 if (lldpctl_atom_set_int(med_location,
124 lldpctl_k_med_location_format, format) == NULL ||
125 lldpctl_atom_set_str(med_location,
8b549648
VB
126 lldpctl_k_med_location_elin,
127 cmdenv_get(env, "elin")) == NULL)
128 log_warnx("lldpctl",
129 "unable to set LLDP MED location on %s. %s", name,
130 lldpctl_last_strerror(conn));
131 else
132 ok = 1;
9a775667
VB
133 break;
134 }
135 if (ok) {
136 if (lldpctl_atom_set(port, lldpctl_k_port_med_locations,
137 med_location) == NULL) {
8b549648
VB
138 log_warnx("lldpctl",
139 "unable to set LLDP MED location on %s. %s.", name,
140 lldpctl_last_strerror(conn));
9a775667 141 } else
8b549648
VB
142 log_info("lldpctl",
143 "LLDP-MED location has been set for port %s", name);
9a775667
VB
144 }
145
9a775667
VB
146 lldpctl_atom_dec_ref(med_location);
147 lldpctl_atom_dec_ref(med_locations);
4b292b55 148 }
9a775667
VB
149 return 1;
150}
4b292b55 151
9a775667
VB
152static int
153cmd_medlocation_coordinate(struct lldpctl_conn_t *conn, struct writer *w,
f540397c 154 struct cmd_env *env, const void *arg)
9a775667
VB
155{
156 log_debug("lldpctl", "set MED location coordinate");
157 return _cmd_medlocation(conn, env, LLDP_MED_LOCFORMAT_COORD);
158}
4b292b55 159
9a775667
VB
160static int
161cmd_medlocation_address(struct lldpctl_conn_t *conn, struct writer *w,
f540397c 162 struct cmd_env *env, const void *arg)
9a775667
VB
163{
164 log_debug("lldpctl", "set MED location address");
165 return _cmd_medlocation(conn, env, LLDP_MED_LOCFORMAT_CIVIC);
166}
167
168static int
8b549648 169cmd_medlocation_elin(struct lldpctl_conn_t *conn, struct writer *w, struct cmd_env *env,
f540397c 170 const void *arg)
9a775667
VB
171{
172 log_debug("lldpctl", "set MED location ELIN");
173 return _cmd_medlocation(conn, env, LLDP_MED_LOCFORMAT_ELIN);
174}
175
176static int
8b549648 177cmd_medpolicy(struct lldpctl_conn_t *conn, struct writer *w, struct cmd_env *env,
f540397c 178 const void *arg)
9a775667
VB
179{
180 log_debug("lldpctl", "set MED policy");
181 lldpctl_atom_t *iface;
182 while ((iface = cmd_iterate_on_interfaces(conn, env))) {
8b549648
VB
183 const char *name =
184 lldpctl_atom_get_str(iface, lldpctl_k_interface_name);
9a775667
VB
185 lldpctl_atom_t *port = lldpctl_get_port(iface);
186 lldpctl_atom_t *med_policy = NULL, *med_policies = NULL;
187 const char *what = NULL;
188
189 med_policies = lldpctl_atom_get(port, lldpctl_k_port_med_policies);
190 if (med_policies == NULL) {
8b549648
VB
191 log_warnx("lldpctl",
192 "unable to set LLDP-MED policies: support seems unavailable");
9a775667
VB
193 goto end;
194 }
195
196 med_policy = lldpctl_atom_iter_value(med_policies,
197 lldpctl_atom_iter_next(med_policies,
198 lldpctl_atom_iter(med_policies)));
199
8b549648
VB
200 if ((what = "application",
201 lldpctl_atom_set_str(med_policy, lldpctl_k_med_policy_type,
9a775667 202 cmdenv_get(env, "application"))) == NULL ||
8b549648
VB
203 (what = "unknown flag",
204 lldpctl_atom_set_int(med_policy, lldpctl_k_med_policy_unknown,
205 cmdenv_get(env, "unknown") ? 1 : 0)) == NULL ||
206 (what = "tagged flag",
207 lldpctl_atom_set_int(med_policy, lldpctl_k_med_policy_tagged,
208 cmdenv_get(env, "tagged") ? 1 : 0)) == NULL ||
9a775667 209 (what = "vlan",
8b549648
VB
210 cmdenv_get(env, "vlan") ?
211 lldpctl_atom_set_str(med_policy, lldpctl_k_med_policy_vid,
212 cmdenv_get(env, "vlan")) :
213 lldpctl_atom_set_int(med_policy, lldpctl_k_med_policy_vid,
214 0)) == NULL ||
9a775667 215 (what = "priority",
8b549648
VB
216 cmdenv_get(env, "priority") ?
217 lldpctl_atom_set_str(med_policy,
218 lldpctl_k_med_policy_priority,
219 cmdenv_get(env, "priority")) :
220 lldpctl_atom_set_int(med_policy,
221 lldpctl_k_med_policy_priority, 0)) == NULL ||
9a775667 222 (what = "dscp",
8b549648
VB
223 cmdenv_get(env, "dscp") ?
224 lldpctl_atom_set_str(med_policy, lldpctl_k_med_policy_dscp,
225 cmdenv_get(env, "dscp")) :
226 lldpctl_atom_set_int(med_policy, lldpctl_k_med_policy_dscp,
227 0)) == NULL)
9a775667
VB
228 log_warnx("lldpctl",
229 "unable to set LLDP MED policy value for %s on %s. %s.",
230 what, name, lldpctl_last_strerror(conn));
231 else {
232 if (lldpctl_atom_set(port, lldpctl_k_port_med_policies,
233 med_policy) == NULL) {
8b549648
VB
234 log_warnx("lldpctl",
235 "unable to set LLDP MED policy on %s. %s.", name,
236 lldpctl_last_strerror(conn));
9a775667 237 } else
8b549648
VB
238 log_info("lldpctl",
239 "LLDP-MED policy has been set for port %s", name);
9a775667
VB
240 }
241
242 end:
243 lldpctl_atom_dec_ref(med_policy);
244 lldpctl_atom_dec_ref(med_policies);
245 lldpctl_atom_dec_ref(port);
4b292b55 246 }
9a775667 247 return 1;
4b292b55
VB
248}
249
9a775667
VB
250/**
251 * Register `configure med location coordinate` commands.
252 */
253static void
254register_commands_medloc_coord(struct cmd_node *configure_medlocation)
255{
256 /* MED location coordinate (set) */
8b549648
VB
257 struct cmd_node *configure_medloc_coord = commands_new(configure_medlocation,
258 "coordinate", "MED location coordinate configuration", NULL, NULL, NULL);
259 commands_new(configure_medloc_coord, NEWLINE,
260 "Configure MED location coordinates", cmd_check_env,
261 cmd_medlocation_coordinate,
9a775667 262 "latitude,longitude,altitude,altitude-unit,datum");
8b549648
VB
263 commands_new(commands_new(configure_medloc_coord, "latitude",
264 "Specify latitude", cmd_check_no_env, NULL, "latitude"),
265 NULL, "Latitude as xx.yyyyN or xx.yyyyS", NULL,
266 cmd_store_env_value_and_pop2, "latitude");
267 commands_new(commands_new(configure_medloc_coord, "longitude",
268 "Specify longitude", cmd_check_no_env, NULL, "longitude"),
269 NULL, "Longitude as xx.yyyyE or xx.yyyyW", NULL,
270 cmd_store_env_value_and_pop2, "longitude");
271 struct cmd_node *altitude =
272 commands_new(commands_new(configure_medloc_coord, "altitude",
273 "Specify altitude", cmd_check_no_env, NULL, "altitude"),
274 NULL, "Altitude", NULL, cmd_store_env_value, "altitude");
275 commands_new(altitude, "m", "meters", NULL, cmd_store_env_value_and_pop3,
276 "altitude-unit");
277 commands_new(altitude, "f", "floors", NULL, cmd_store_env_value_and_pop3,
278 "altitude-unit");
279
280 struct cmd_node *datum = commands_new(configure_medloc_coord, "datum",
281 "Specify datum", cmd_check_no_env, NULL, "datum");
9a775667
VB
282 for (lldpctl_map_t *datum_map =
283 lldpctl_key_get_map(lldpctl_k_med_location_geoid);
8b549648
VB
284 datum_map->string; datum_map++)
285 commands_new(datum, datum_map->string, NULL, NULL,
286 cmd_store_env_value_and_pop2, "datum");
4b292b55
VB
287}
288
289/**
9a775667 290 * Register `configure med location address` commands.
4b292b55 291 */
9a775667
VB
292static void
293register_commands_medloc_addr(struct cmd_node *configure_medlocation)
4b292b55 294{
9a775667 295 /* MED location address (set) */
8b549648
VB
296 struct cmd_node *configure_medloc_addr = commands_new(configure_medlocation,
297 "address", "MED location address configuration", NULL, NULL, NULL);
298 commands_new(configure_medloc_addr, NEWLINE, "Configure MED location address",
299 cmd_check_env, cmd_medlocation_address, "country");
4b292b55 300
9a775667 301 /* Country */
8b549648
VB
302 commands_new(commands_new(configure_medloc_addr, "country",
303 "Specify country (mandatory)", cmd_check_no_env, NULL,
304 "country"),
305 NULL, "Country as a two-letter code", NULL, cmd_store_env_value_and_pop2,
306 "country");
9a775667
VB
307
308 /* Other fields */
309 for (lldpctl_map_t *addr_map =
310 lldpctl_key_get_map(lldpctl_k_med_civicaddress_type);
8b549648 311 addr_map->string; addr_map++) {
87f48451
VB
312 const char *tag = strdup(totag(addr_map->string));
313 SUPPRESS_LEAK(tag);
8b549648
VB
314 commands_new(commands_new(configure_medloc_addr, tag, addr_map->string,
315 cmd_check_no_env, NULL, addr_map->string),
316 NULL, addr_map->string, NULL, cmd_store_env_value_and_pop2,
317 addr_map->string);
87f48451 318 }
4b292b55
VB
319}
320
321/**
9a775667 322 * Register `configure med location elin` commands.
4b292b55 323 */
9a775667
VB
324static void
325register_commands_medloc_elin(struct cmd_node *configure_medlocation)
326{
327 /* MED location elin (set) */
8b549648
VB
328 commands_new(commands_new(commands_new(configure_medlocation, "elin",
329 "MED location ELIN configuration", NULL, NULL,
330 NULL),
331 NULL, "ELIN number", NULL, cmd_store_env_value, "elin"),
332 NEWLINE, "Set MED location ELIN number", NULL, cmd_medlocation_elin, NULL);
9a775667
VB
333}
334
335/**
336 * Register `configure med location` commands.
337 */
338static void
0a138003 339register_commands_medloc(struct cmd_node *configure_med)
9a775667 340{
8b549648
VB
341 struct cmd_node *configure_medlocation = commands_new(configure_med, "location",
342 "MED location configuration", NULL, NULL, NULL);
9a775667
VB
343
344 register_commands_medloc_coord(configure_medlocation);
345 register_commands_medloc_addr(configure_medlocation);
346 register_commands_medloc_elin(configure_medlocation);
9a775667
VB
347}
348
4b292b55 349static int
f540397c 350cmd_check_application_but_no(struct cmd_env *env, const void *arg)
4b292b55 351{
9a775667
VB
352 const char *what = arg;
353 if (!cmdenv_get(env, "application")) return 0;
354 if (cmdenv_get(env, what)) return 0;
355 return 1;
356}
357static int
9a775667 358cmd_store_app_env_value_and_pop2(struct lldpctl_conn_t *conn, struct writer *w,
f540397c 359 struct cmd_env *env, const void *value)
9a775667
VB
360{
361 return cmd_store_something_env_value_and_pop2("application", env, value);
362}
363static int
9a775667 364cmd_store_prio_env_value_and_pop2(struct lldpctl_conn_t *conn, struct writer *w,
f540397c 365 struct cmd_env *env, const void *value)
9a775667
VB
366{
367 return cmd_store_something_env_value_and_pop2("priority", env, value);
368}
4b292b55 369
9a775667
VB
370/**
371 * Register `configure med policy` commands.
372 */
373static void
0a138003 374register_commands_medpol(struct cmd_node *configure_med)
9a775667 375{
8b549648
VB
376 struct cmd_node *configure_medpolicy = commands_new(configure_med, "policy",
377 "MED policy configuration", NULL, NULL, NULL);
9a775667 378
8b549648
VB
379 commands_new(configure_medpolicy, NEWLINE, "Apply new MED policy",
380 cmd_check_env, cmd_medpolicy, "application");
9a775667
VB
381
382 /* Application */
383 struct cmd_node *configure_application =
8b549648
VB
384 commands_new(configure_medpolicy, "application", "MED policy application",
385 cmd_check_no_env, NULL, "application");
386
387 for (lldpctl_map_t *pol_map = lldpctl_key_get_map(lldpctl_k_med_policy_type);
388 pol_map->string; pol_map++) {
87f48451
VB
389 char *tag = strdup(totag(pol_map->string));
390 SUPPRESS_LEAK(tag);
8b549648
VB
391 commands_new(configure_application, tag, pol_map->string, NULL,
392 cmd_store_app_env_value_and_pop2, pol_map->string);
9a775667
VB
393 }
394
395 /* Remaining keywords */
8b549648
VB
396 commands_new(configure_medpolicy, "unknown", "Set unknown flag",
397 cmd_check_application_but_no, cmd_store_env_and_pop, "unknown");
398 commands_new(configure_medpolicy, "tagged", "Set tagged flag",
399 cmd_check_application_but_no, cmd_store_env_and_pop, "tagged");
400 commands_new(commands_new(configure_medpolicy, "vlan", "VLAN advertising",
401 cmd_check_application_but_no, NULL, "vlan"),
402 NULL, "VLAN ID to advertise", NULL, cmd_store_env_value_and_pop2, "vlan");
403 commands_new(commands_new(configure_medpolicy, "dscp", "DiffServ advertising",
404 cmd_check_application_but_no, NULL, "dscp"),
405 NULL, "DSCP value to advertise (between 0 and 63)", NULL,
406 cmd_store_env_value_and_pop2, "dscp");
407 struct cmd_node *priority = commands_new(configure_medpolicy, "priority",
408 "MED policy priority", cmd_check_application_but_no, NULL, "priority");
9a775667
VB
409 for (lldpctl_map_t *prio_map =
410 lldpctl_key_get_map(lldpctl_k_med_policy_priority);
8b549648 411 prio_map->string; prio_map++) {
87f48451
VB
412 char *tag = strdup(totag(prio_map->string));
413 SUPPRESS_LEAK(tag);
8b549648
VB
414 commands_new(priority, tag, prio_map->string, NULL,
415 cmd_store_prio_env_value_and_pop2, prio_map->string);
4b292b55 416 }
9a775667 417}
4b292b55 418
486a6133 419static int
8b549648 420cmd_faststart(struct lldpctl_conn_t *conn, struct writer *w, struct cmd_env *env,
f540397c 421 const void *arg)
486a6133
VB
422{
423 log_debug("lldpctl", "configure fast interval support");
424
425 lldpctl_atom_t *config = lldpctl_get_configuration(conn);
426 if (config == NULL) {
427 log_warnx("lldpctl", "unable to get configuration from lldpd. %s",
428 lldpctl_last_strerror(conn));
429 return 0;
430 }
431
f540397c 432 const char *action = arg;
486a6133 433 if ((!strcmp(action, "enable") &&
8b549648
VB
434 (lldpctl_atom_set_int(config, lldpctl_k_config_fast_start_enabled, 1) ==
435 NULL)) ||
486a6133 436 (!strcmp(action, "disable") &&
8b549648
VB
437 (lldpctl_atom_set_int(config, lldpctl_k_config_fast_start_enabled, 0) ==
438 NULL)) ||
486a6133 439 (!strcmp(action, "delay") &&
8b549648
VB
440 (lldpctl_atom_set_str(config, lldpctl_k_config_fast_start_interval,
441 cmdenv_get(env, "tx-interval")) == NULL))) {
486a6133
VB
442 log_warnx("lldpctl", "unable to setup fast start. %s",
443 lldpctl_last_strerror(conn));
444 lldpctl_atom_dec_ref(config);
445 return 0;
446 }
ebe2af6a 447 log_info("lldpctl", "configuration for fast start applied");
486a6133
VB
448 lldpctl_atom_dec_ref(config);
449 return 1;
450}
451
452/**
453 * Register "configure med fast-start *"
454 */
455static void
456register_commands_medfast(struct cmd_node *med, struct cmd_node *nomed)
457{
8b549648
VB
458 struct cmd_node *configure_fast = commands_new(med, "fast-start",
459 "Fast start configuration", cmd_check_no_env, NULL, "ports");
460 struct cmd_node *unconfigure_fast = commands_new(nomed, "fast-start",
461 "Fast start configuration", cmd_check_no_env, NULL, "ports");
486a6133
VB
462
463 /* Enable */
8b549648
VB
464 commands_new(commands_new(configure_fast, "enable", "Enable fast start", NULL,
465 NULL, NULL),
466 NEWLINE, "Enable fast start", NULL, cmd_faststart, "enable");
486a6133
VB
467
468 /* Set TX delay */
8b549648
VB
469 commands_new(commands_new(commands_new(configure_fast, "tx-interval",
470 "Set LLDP fast transmit delay", NULL, NULL, NULL),
471 NULL, "LLDP fast transmit delay in seconds", NULL,
472 cmd_store_env_value, "tx-interval"),
473 NEWLINE, "Set LLDP fast transmit delay", NULL, cmd_faststart, "delay");
486a6133
VB
474
475 /* Disable */
8b549648
VB
476 commands_new(commands_new(unconfigure_fast, NEWLINE, "Disable fast start", NULL,
477 cmd_faststart, "disable"),
478 NEWLINE, "Disable fast start", NULL, cmd_faststart, "disable");
486a6133
VB
479}
480
9a775667 481/**
e15f96d2 482 * Register "configure med *"
9a775667
VB
483 */
484void
8b549648
VB
485register_commands_configure_med(struct cmd_node *configure,
486 struct cmd_node *unconfigure)
9a775667 487{
8b549648
VB
488 if (lldpctl_key_get_map(lldpctl_k_med_policy_type)[0].string == NULL) return;
489
490 struct cmd_node *configure_med =
491 commands_new(configure, "med", "MED configuration", NULL, NULL, NULL);
492 struct cmd_node *unconfigure_med =
493 commands_new(unconfigure, "med", "MED configuration", NULL, NULL, NULL);
9a775667 494
e15f96d2
VB
495 register_commands_medloc(configure_med);
496 register_commands_medpol(configure_med);
497 register_commands_medpow(configure_med);
486a6133 498 register_commands_medfast(configure_med, unconfigure_med);
4b292b55 499}