]> git.ipfire.org Git - thirdparty/lldpd.git/blob - src/lib/atoms/config.c
02836088e3b802093a454e064dcf0fdc36e38d05
[thirdparty/lldpd.git] / src / lib / atoms / config.c
1 /* -*- mode: c; c-file-style: "openbsd" -*- */
2 /*
3 * Copyright (c) 2015 Vincent Bernat <vincent@bernat.im>
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 <stdio.h>
19 #include <stdarg.h>
20 #include <string.h>
21 #include <arpa/inet.h>
22
23 #include "../lldpctl.h"
24 #include "../log.h"
25 #include "atom.h"
26 #include "helpers.h"
27
28 static struct atom_map bond_slave_src_mac_map = {
29 .key = lldpctl_k_config_bond_slave_src_mac_type,
30 .map = {
31 { LLDP_BOND_SLAVE_SRC_MAC_TYPE_REAL, "real"},
32 { LLDP_BOND_SLAVE_SRC_MAC_TYPE_ZERO, "zero"},
33 { LLDP_BOND_SLAVE_SRC_MAC_TYPE_FIXED, "fixed"},
34 { LLDP_BOND_SLAVE_SRC_MAC_TYPE_LOCALLY_ADMINISTERED, "local" },
35 { LLDP_BOND_SLAVE_SRC_MAC_TYPE_UNKNOWN, NULL},
36 },
37 };
38
39 static struct atom_map lldp_portid_map = {
40 .key = lldpctl_k_config_lldp_portid_type,
41 .map = {
42 { LLDP_PORTID_SUBTYPE_IFNAME, "ifname"},
43 { LLDP_PORTID_SUBTYPE_LLADDR, "macaddress"},
44 { LLDP_PORTID_SUBTYPE_LOCAL, "local"},
45 { LLDP_PORTID_SUBTYPE_UNKNOWN, NULL},
46 },
47 };
48
49 static struct atom_map lldp_agent_map = {
50 .key = lldpctl_k_config_lldp_agent_type,
51 .map = {
52 { LLDP_AGENT_TYPE_NEAREST_BRIDGE, "nearest bridge"},
53 { LLDP_AGENT_TYPE_NEAREST_NONTPMR_BRIDGE, "nearest non-TPMR bridge"},
54 { LLDP_AGENT_TYPE_NEAREST_CUSTOMER_BRIDGE, "nearest customer bridge"},
55 { LLDP_AGENT_TYPE_UNKNOWN, NULL},
56 },
57 };
58
59 ATOM_MAP_REGISTER(bond_slave_src_mac_map, 1);
60 ATOM_MAP_REGISTER(lldp_portid_map, 2);
61 ATOM_MAP_REGISTER(lldp_agent_map, 3);
62
63 static int
64 _lldpctl_atom_new_config(lldpctl_atom_t *atom, va_list ap)
65 {
66 struct _lldpctl_atom_config_t *c =
67 (struct _lldpctl_atom_config_t *)atom;
68 c->config = va_arg(ap, struct lldpd_config *);
69 return 1;
70 }
71
72 static void
73 _lldpctl_atom_free_config(lldpctl_atom_t *atom)
74 {
75 struct _lldpctl_atom_config_t *c =
76 (struct _lldpctl_atom_config_t *)atom;
77 lldpd_config_cleanup(c->config);
78 free(c->config);
79 }
80
81 static const char*
82 _lldpctl_atom_get_str_config(lldpctl_atom_t *atom, lldpctl_key_t key)
83 {
84 char *res = NULL;
85 struct _lldpctl_atom_config_t *c =
86 (struct _lldpctl_atom_config_t *)atom;
87 switch (key) {
88 case lldpctl_k_config_mgmt_pattern:
89 res = c->config->c_mgmt_pattern; break;
90 case lldpctl_k_config_iface_pattern:
91 res = c->config->c_iface_pattern; break;
92 case lldpctl_k_config_cid_pattern:
93 res = c->config->c_cid_pattern; break;
94 case lldpctl_k_config_cid_string:
95 res = c->config->c_cid_string; break;
96 case lldpctl_k_config_description:
97 res = c->config->c_description; break;
98 case lldpctl_k_config_platform:
99 res = c->config->c_platform; break;
100 case lldpctl_k_config_hostname:
101 res = c->config->c_hostname; break;
102 case lldpctl_k_config_bond_slave_src_mac_type:
103 return map_lookup(bond_slave_src_mac_map.map,
104 c->config->c_bond_slave_src_mac_type);
105 case lldpctl_k_config_lldp_portid_type:
106 return map_lookup(lldp_portid_map.map,
107 c->config->c_lldp_portid_type);
108 case lldpctl_k_config_lldp_agent_type:
109 return map_lookup(lldp_agent_map.map,
110 c->config->c_lldp_agent_type);
111 default:
112 SET_ERROR(atom->conn, LLDPCTL_ERR_NOT_EXIST);
113 return NULL;
114 }
115 return res?res:"";
116 }
117
118 static struct _lldpctl_atom_config_t*
119 __lldpctl_atom_set_str_config(struct _lldpctl_atom_config_t *c,
120 char **local, char **global,
121 const char *value) {
122 if (value) {
123 char *aval = NULL;
124 size_t len = strlen(value) + 1;
125 aval = _lldpctl_alloc_in_atom((lldpctl_atom_t *)c, len);
126 if (!aval) return NULL;
127 memcpy(aval, value, len);
128 *local = aval;
129 free(*global); *global = strdup(aval);
130 } else {
131 free(*global);
132 *local = *global = NULL;
133 }
134 return c;
135 }
136
137 static lldpctl_atom_t*
138 _lldpctl_atom_set_str_config(lldpctl_atom_t *atom, lldpctl_key_t key,
139 const char *value)
140 {
141 struct _lldpctl_atom_config_t *c =
142 (struct _lldpctl_atom_config_t *)atom;
143 struct lldpd_config config;
144 memcpy(&config, c->config, sizeof(struct lldpd_config));
145 char *canary = NULL;
146 int rc;
147
148 switch (key) {
149 case lldpctl_k_config_iface_pattern:
150 if (!__lldpctl_atom_set_str_config(c,
151 &config.c_iface_pattern, &c->config->c_iface_pattern,
152 value))
153 return NULL;
154 break;
155 case lldpctl_k_config_mgmt_pattern:
156 if (!__lldpctl_atom_set_str_config(c,
157 &config.c_mgmt_pattern, &c->config->c_mgmt_pattern,
158 value))
159 return NULL;
160 break;
161 case lldpctl_k_config_cid_string:
162 if (!__lldpctl_atom_set_str_config(c,
163 &config.c_cid_string, &c->config->c_cid_string,
164 value))
165 return NULL;
166 break;
167 case lldpctl_k_config_description:
168 if (!__lldpctl_atom_set_str_config(c,
169 &config.c_description, &c->config->c_description,
170 value))
171 return NULL;
172 break;
173 case lldpctl_k_config_platform:
174 if (!__lldpctl_atom_set_str_config(c,
175 &config.c_platform, &c->config->c_platform,
176 value))
177 return NULL;
178 break;
179 case lldpctl_k_config_hostname:
180 if (!__lldpctl_atom_set_str_config(c,
181 &config.c_hostname, &c->config->c_hostname,
182 value))
183 return NULL;
184 break;
185 default:
186 SET_ERROR(atom->conn, LLDPCTL_ERR_NOT_EXIST);
187 return NULL;
188 }
189
190 if (asprintf(&canary, "%d%s", key, value?value:"(NULL)") == -1) {
191 SET_ERROR(atom->conn, LLDPCTL_ERR_NOMEM);
192 return NULL;
193 }
194 rc = _lldpctl_do_something(atom->conn,
195 CONN_STATE_SET_CONFIG_SEND, CONN_STATE_SET_CONFIG_RECV,
196 canary,
197 SET_CONFIG, &config, &MARSHAL_INFO(lldpd_config),
198 NULL, NULL);
199 free(canary);
200 if (rc == 0) return atom;
201
202 #undef SET_STR
203
204 return NULL;
205 }
206
207 static long int
208 _lldpctl_atom_get_int_config(lldpctl_atom_t *atom, lldpctl_key_t key)
209 {
210 struct _lldpctl_atom_config_t *c =
211 (struct _lldpctl_atom_config_t *)atom;
212 switch (key) {
213 case lldpctl_k_config_paused:
214 return c->config->c_paused;
215 case lldpctl_k_config_tx_interval:
216 return c->config->c_tx_interval;
217 case lldpctl_k_config_receiveonly:
218 return c->config->c_receiveonly;
219 case lldpctl_k_config_advertise_version:
220 return c->config->c_advertise_version;
221 case lldpctl_k_config_ifdescr_update:
222 return c->config->c_set_ifdescr;
223 case lldpctl_k_config_iface_promisc:
224 return c->config->c_promisc;
225 case lldpctl_k_config_chassis_cap_advertise:
226 return c->config->c_cap_advertise;
227 case lldpctl_k_config_chassis_mgmt_advertise:
228 return c->config->c_mgmt_advertise;
229 #ifdef ENABLE_LLDPMED
230 case lldpctl_k_config_lldpmed_noinventory:
231 return c->config->c_noinventory;
232 case lldpctl_k_config_fast_start_enabled:
233 return c->config->c_enable_fast_start;
234 case lldpctl_k_config_fast_start_interval:
235 return c->config->c_tx_fast_interval;
236 #endif
237 case lldpctl_k_config_tx_hold:
238 return c->config->c_tx_hold;
239 default:
240 return SET_ERROR(atom->conn, LLDPCTL_ERR_NOT_EXIST);
241 }
242 }
243
244 static lldpctl_atom_t*
245 _lldpctl_atom_set_int_config(lldpctl_atom_t *atom, lldpctl_key_t key,
246 long int value)
247 {
248 int rc;
249 char *canary = NULL;
250 struct _lldpctl_atom_config_t *c =
251 (struct _lldpctl_atom_config_t *)atom;
252 struct lldpd_config config;
253 memcpy(&config, c->config, sizeof(struct lldpd_config));
254
255 switch (key) {
256 case lldpctl_k_config_paused:
257 config.c_paused = c->config->c_paused = value;
258 break;
259 case lldpctl_k_config_tx_interval:
260 config.c_tx_interval = value;
261 if (value > 0) c->config->c_tx_interval = value;
262 break;
263 case lldpctl_k_config_ifdescr_update:
264 config.c_set_ifdescr = c->config->c_set_ifdescr = value;
265 break;
266 case lldpctl_k_config_iface_promisc:
267 config.c_promisc = c->config->c_promisc = value;
268 break;
269 case lldpctl_k_config_chassis_cap_advertise:
270 config.c_cap_advertise = c->config->c_cap_advertise = value;
271 break;
272 case lldpctl_k_config_chassis_mgmt_advertise:
273 config.c_mgmt_advertise = c->config->c_mgmt_advertise = value;
274 break;
275 #ifdef ENABLE_LLDPMED
276 case lldpctl_k_config_fast_start_enabled:
277 config.c_enable_fast_start = c->config->c_enable_fast_start = value;
278 break;
279 case lldpctl_k_config_fast_start_interval:
280 config.c_tx_fast_interval = c->config->c_tx_fast_interval = value;
281 break;
282 #endif
283 case lldpctl_k_config_tx_hold:
284 config.c_tx_hold = value;
285 if (value > 0) c->config->c_tx_hold = value;
286 break;
287 case lldpctl_k_config_bond_slave_src_mac_type:
288 config.c_bond_slave_src_mac_type = value;
289 c->config->c_bond_slave_src_mac_type = value;
290 break;
291 case lldpctl_k_config_lldp_portid_type:
292 config.c_lldp_portid_type = value;
293 c->config->c_lldp_portid_type = value;
294 break;
295 case lldpctl_k_config_lldp_agent_type:
296 config.c_lldp_agent_type = value;
297 c->config->c_lldp_agent_type = value;
298 break;
299 default:
300 SET_ERROR(atom->conn, LLDPCTL_ERR_NOT_EXIST);
301 return NULL;
302 }
303
304 if (asprintf(&canary, "%d%ld", key, value) == -1) {
305 SET_ERROR(atom->conn, LLDPCTL_ERR_NOMEM);
306 return NULL;
307 }
308 rc = _lldpctl_do_something(atom->conn,
309 CONN_STATE_SET_CONFIG_SEND, CONN_STATE_SET_CONFIG_RECV,
310 canary,
311 SET_CONFIG, &config, &MARSHAL_INFO(lldpd_config),
312 NULL, NULL);
313 free(canary);
314 if (rc == 0) return atom;
315 return NULL;
316 }
317
318 static struct atom_builder config =
319 { atom_config, sizeof(struct _lldpctl_atom_config_t),
320 .init = _lldpctl_atom_new_config,
321 .free = _lldpctl_atom_free_config,
322 .get_str = _lldpctl_atom_get_str_config,
323 .set_str = _lldpctl_atom_set_str_config,
324 .get_int = _lldpctl_atom_get_int_config,
325 .set_int = _lldpctl_atom_set_int_config };
326
327 ATOM_BUILDER_REGISTER(config, 1);