]>
Commit | Line | Data |
---|---|---|
4b292b55 | 1 | /* -*- mode: c; c-file-style: "openbsd" -*- */ |
a552a72e VB |
2 | /* |
3 | * Copyright (c) 2008 Vincent Bernat <bernat@luffy.cx> | |
4 | * | |
51434125 | 5 | * Permission to use, copy, modify, and/or distribute this software for any |
a552a72e VB |
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 "lldpd.h" | |
bdfe4193 | 19 | #include "trace.h" |
a552a72e | 20 | |
324d73a3 | 21 | static ssize_t |
f6d20631 | 22 | client_handle_none(struct lldpd *cfg, enum hmsg_type *type, |
4e90a9e0 | 23 | void *input, int input_len, void **output, int *subscribed) |
a552a72e | 24 | { |
6f8925be | 25 | log_info("rpc", "received noop request from client"); |
f6d20631 VB |
26 | *type = NONE; |
27 | return 0; | |
a552a72e VB |
28 | } |
29 | ||
8729d69f | 30 | /* Return the global configuration */ |
324d73a3 | 31 | static ssize_t |
8729d69f VB |
32 | client_handle_get_configuration(struct lldpd *cfg, enum hmsg_type *type, |
33 | void *input, int input_len, void **output, int *subscribed) | |
34 | { | |
35 | ssize_t output_len; | |
6f8925be | 36 | log_debug("rpc", "client requested configuration"); |
985a4cb5 | 37 | output_len = lldpd_config_serialize(&cfg->g_config, output); |
8729d69f VB |
38 | if (output_len <= 0) { |
39 | output_len = 0; | |
40 | *type = NONE; | |
41 | } | |
42 | return output_len; | |
43 | } | |
44 | ||
6dd83015 VB |
45 | static char* |
46 | xstrdup(const char *str) | |
47 | { | |
48 | if (!str) return NULL; | |
49 | return strdup(str); | |
50 | } | |
51 | ||
47287a61 | 52 | /* Change the global configuration */ |
324d73a3 | 53 | static ssize_t |
47287a61 VB |
54 | client_handle_set_configuration(struct lldpd *cfg, enum hmsg_type *type, |
55 | void *input, int input_len, void **output, int *subscribed) | |
56 | { | |
57 | struct lldpd_config *config; | |
58 | ||
6f8925be | 59 | log_debug("rpc", "client request a change in configuration"); |
47287a61 | 60 | /* Get the proposed configuration. */ |
985a4cb5 | 61 | if (lldpd_config_unserialize(input, input_len, &config) <= 0) { |
47287a61 VB |
62 | *type = NONE; |
63 | return 0; | |
64 | } | |
e4c51716 VB |
65 | |
66 | #define CHANGED(w) (config->w != cfg->g_config.w) | |
6dd83015 VB |
67 | #define CHANGED_STR(w) (!(config->w == cfg->g_config.w || \ |
68 | (config->w && cfg->g_config.w && !strcmp(config->w, cfg->g_config.w)))) | |
e4c51716 | 69 | |
e4ff3ed5 | 70 | /* What needs to be done? Transmit delay? */ |
63b4f1ee | 71 | if (CHANGED(c_tx_interval) && config->c_tx_interval != 0) { |
e4c51716 VB |
72 | if (config->c_tx_interval < 0) { |
73 | log_debug("rpc", "client asked for immediate retransmission"); | |
74 | levent_send_now(cfg); | |
75 | } else { | |
63b4f1ee VB |
76 | log_debug("rpc", "client change transmit interval to %d", |
77 | config->c_tx_interval); | |
78 | cfg->g_config.c_tx_interval = config->c_tx_interval; | |
71b0f981 | 79 | cfg->g_config.c_ttl = cfg->g_config.c_tx_interval * |
e4c51716 VB |
80 | cfg->g_config.c_tx_hold; |
81 | } | |
82 | } | |
63b4f1ee VB |
83 | if (CHANGED(c_tx_hold) && config->c_tx_hold > 0) { |
84 | log_debug("rpc", "client change transmit hold to %d", | |
85 | config->c_tx_hold); | |
86 | cfg->g_config.c_tx_hold = config->c_tx_hold; | |
71b0f981 | 87 | cfg->g_config.c_ttl = cfg->g_config.c_tx_interval * |
63b4f1ee VB |
88 | cfg->g_config.c_tx_hold; |
89 | } | |
e4c51716 VB |
90 | if (CHANGED(c_lldp_portid_type) && |
91 | config->c_lldp_portid_type > LLDP_PORTID_SUBTYPE_UNKNOWN && | |
92 | config->c_lldp_portid_type <= LLDP_PORTID_SUBTYPE_MAX) { | |
93 | log_debug("rpc", "change lldp portid tlv subtype to %d", | |
94 | config->c_lldp_portid_type); | |
95 | cfg->g_config.c_lldp_portid_type = config->c_lldp_portid_type; | |
96 | levent_update_now(cfg); | |
8fbd3195 | 97 | } |
1eadc9a1 VB |
98 | if (CHANGED(c_lldp_agent_type) && |
99 | config->c_lldp_agent_type > LLDP_AGENT_TYPE_UNKNOWN && | |
100 | config->c_lldp_agent_type <= LLDP_AGENT_TYPE_MAX) { | |
101 | log_debug("rpc", "change lldp agent type to %d", | |
102 | config->c_lldp_agent_type); | |
103 | cfg->g_config.c_lldp_agent_type = config->c_lldp_agent_type; | |
104 | levent_update_now(cfg); | |
105 | } | |
e4ff3ed5 | 106 | /* Pause/resume */ |
e4c51716 | 107 | if (CHANGED(c_paused)) { |
e4ff3ed5 VB |
108 | log_debug("rpc", "client asked to %s lldpd", |
109 | config->c_paused?"pause":"resume"); | |
110 | cfg->g_config.c_paused = config->c_paused; | |
111 | levent_send_now(cfg); | |
112 | } | |
47287a61 | 113 | |
486a6133 | 114 | #ifdef ENABLE_LLDPMED |
e4c51716 VB |
115 | if (CHANGED(c_enable_fast_start)) { |
116 | cfg->g_config.c_enable_fast_start = config->c_enable_fast_start; | |
486a6133 VB |
117 | log_debug("rpc", "client asked to %s fast start", |
118 | cfg->g_config.c_enable_fast_start?"enable":"disable"); | |
119 | } | |
e4c51716 VB |
120 | if (CHANGED(c_tx_fast_interval) && |
121 | config->c_tx_fast_interval > 0) { | |
486a6133 VB |
122 | log_debug("rpc", "change fast interval to %d", config->c_tx_fast_interval); |
123 | cfg->g_config.c_tx_fast_interval = config->c_tx_fast_interval; | |
124 | } | |
125 | #endif | |
e4c51716 | 126 | if (CHANGED_STR(c_iface_pattern)) { |
6dd83015 VB |
127 | log_debug("rpc", "change interface pattern to %s", |
128 | config->c_iface_pattern?config->c_iface_pattern:"(NULL)"); | |
e26a25ca | 129 | free(cfg->g_config.c_iface_pattern); |
6dd83015 | 130 | cfg->g_config.c_iface_pattern = xstrdup(config->c_iface_pattern); |
e681c859 | 131 | levent_update_now(cfg); |
346a0f69 | 132 | } |
e4c51716 | 133 | if (CHANGED_STR(c_mgmt_pattern)) { |
6dd83015 VB |
134 | log_debug("rpc", "change management pattern to %s", |
135 | config->c_mgmt_pattern?config->c_mgmt_pattern:"(NULL)"); | |
622d14bb | 136 | free(cfg->g_config.c_mgmt_pattern); |
6dd83015 | 137 | cfg->g_config.c_mgmt_pattern = xstrdup(config->c_mgmt_pattern); |
622d14bb VB |
138 | levent_update_now(cfg); |
139 | } | |
e4c51716 | 140 | if (CHANGED_STR(c_description)) { |
6dd83015 VB |
141 | log_debug("rpc", "change chassis description to %s", |
142 | config->c_description?config->c_description:"(NULL)"); | |
decaec0d | 143 | free(cfg->g_config.c_description); |
6dd83015 | 144 | cfg->g_config.c_description = xstrdup(config->c_description); |
decaec0d VB |
145 | levent_update_now(cfg); |
146 | } | |
e4c51716 | 147 | if (CHANGED_STR(c_platform)) { |
6dd83015 VB |
148 | log_debug("rpc", "change platform description to %s", |
149 | config->c_platform?config->c_platform:"(NULL)"); | |
3f70e118 | 150 | free(cfg->g_config.c_platform); |
6dd83015 | 151 | cfg->g_config.c_platform = xstrdup(config->c_platform); |
3f70e118 VB |
152 | levent_update_now(cfg); |
153 | } | |
e4c51716 | 154 | if (CHANGED_STR(c_hostname)) { |
6dd83015 | 155 | log_debug("rpc", "change system name to %s", |
491ec12e | 156 | config->c_hostname?config->c_hostname:"(NULL)"); |
ce347d29 | 157 | free(cfg->g_config.c_hostname); |
6dd83015 | 158 | cfg->g_config.c_hostname = xstrdup(config->c_hostname); |
ce347d29 JJ |
159 | levent_update_now(cfg); |
160 | } | |
e4c51716 | 161 | if (CHANGED(c_set_ifdescr)) { |
bb37268d VB |
162 | log_debug("rpc", "%s setting of interface description based on discovered neighbors", |
163 | config->c_set_ifdescr?"enable":"disable"); | |
164 | cfg->g_config.c_set_ifdescr = config->c_set_ifdescr; | |
165 | levent_update_now(cfg); | |
166 | } | |
e4c51716 | 167 | if (CHANGED(c_promisc)) { |
f84199dd VB |
168 | log_debug("rpc", "%s promiscuous mode on managed interfaces", |
169 | config->c_promisc?"enable":"disable"); | |
170 | cfg->g_config.c_promisc = config->c_promisc; | |
171 | levent_update_now(cfg); | |
172 | } | |
ca838758 AA |
173 | if (CHANGED(c_cap_advertise)) { |
174 | log_debug("rpc", "%s chassis capabilities advertisement", | |
ad05be32 | 175 | config->c_cap_advertise?"enable":"disable"); |
ca838758 | 176 | cfg->g_config.c_cap_advertise = config->c_cap_advertise; |
1c2217aa AA |
177 | levent_update_now(cfg); |
178 | } | |
179 | if (CHANGED(c_mgmt_advertise)) { | |
180 | log_debug("rpc", "%s management addresses advertisement", | |
ad05be32 | 181 | config->c_mgmt_advertise?"enable":"disable"); |
1c2217aa | 182 | cfg->g_config.c_mgmt_advertise = config->c_mgmt_advertise; |
ca838758 AA |
183 | levent_update_now(cfg); |
184 | } | |
e4c51716 | 185 | if (CHANGED(c_bond_slave_src_mac_type)) { |
5813918a VB |
186 | if (config->c_bond_slave_src_mac_type > |
187 | LLDP_BOND_SLAVE_SRC_MAC_TYPE_UNKNOWN && | |
188 | config->c_bond_slave_src_mac_type <= | |
189 | LLDP_BOND_SLAVE_SRC_MAC_TYPE_MAX) { | |
190 | log_debug("rpc", "change bond src mac type to %d", | |
191 | config->c_bond_slave_src_mac_type); | |
192 | cfg->g_config.c_bond_slave_src_mac_type = | |
193 | config->c_bond_slave_src_mac_type; | |
194 | } else { | |
195 | log_info("rpc", "Invalid bond slave src mac type: %d\n", | |
196 | config->c_bond_slave_src_mac_type); | |
197 | } | |
dfbd7185 | 198 | } |
486a6133 | 199 | |
47287a61 | 200 | lldpd_config_cleanup(config); |
aba549a8 | 201 | free(config); |
47287a61 VB |
202 | |
203 | return 0; | |
204 | } | |
205 | ||
f6d20631 VB |
206 | /* Return the list of interfaces. |
207 | Input: nothing. | |
208 | Output: list of interface names (lldpd_interface_list) | |
209 | */ | |
324d73a3 | 210 | static ssize_t |
f6d20631 | 211 | client_handle_get_interfaces(struct lldpd *cfg, enum hmsg_type *type, |
4e90a9e0 | 212 | void *input, int input_len, void **output, int *subscribed) |
a552a72e VB |
213 | { |
214 | struct lldpd_interface *iff, *iff_next; | |
215 | struct lldpd_hardware *hardware; | |
324d73a3 | 216 | ssize_t output_len; |
a552a72e VB |
217 | |
218 | /* Build the list of interfaces */ | |
f6d20631 | 219 | struct lldpd_interface_list ifs; |
6f8925be VB |
220 | |
221 | log_debug("rpc", "client request the list of interfaces"); | |
a552a72e VB |
222 | TAILQ_INIT(&ifs); |
223 | TAILQ_FOREACH(hardware, &cfg->g_hardware, h_entries) { | |
224 | if ((iff = (struct lldpd_interface*)malloc(sizeof( | |
225 | struct lldpd_interface))) == NULL) | |
6f8925be | 226 | fatal("rpc", NULL); |
a552a72e VB |
227 | iff->name = hardware->h_ifname; |
228 | TAILQ_INSERT_TAIL(&ifs, iff, next); | |
229 | } | |
230 | ||
985a4cb5 | 231 | output_len = lldpd_interface_list_serialize(&ifs, output); |
f6d20631 VB |
232 | if (output_len <= 0) { |
233 | output_len = 0; | |
234 | *type = NONE; | |
a552a72e VB |
235 | } |
236 | ||
237 | /* Free the temporary list */ | |
238 | for (iff = TAILQ_FIRST(&ifs); | |
239 | iff != NULL; | |
240 | iff = iff_next) { | |
241 | iff_next = TAILQ_NEXT(iff, next); | |
242 | TAILQ_REMOVE(&ifs, iff, next); | |
243 | free(iff); | |
244 | } | |
f6d20631 VB |
245 | |
246 | return output_len; | |
a552a72e VB |
247 | } |
248 | ||
99ef55d3 VB |
249 | /* Return the local chassis. |
250 | Input: nothing. | |
251 | Output: local chassis (lldpd_chassis) | |
252 | */ | |
253 | static ssize_t | |
254 | client_handle_get_local_chassis(struct lldpd *cfg, enum hmsg_type *type, | |
255 | void *input, int input_len, void **output, int *subscribed) | |
256 | { | |
9da663f7 | 257 | struct lldpd_chassis *chassis = LOCAL_CHASSIS(cfg); |
99ef55d3 VB |
258 | ssize_t output_len; |
259 | ||
260 | log_debug("rpc", "client request the local chassis"); | |
261 | output_len = lldpd_chassis_serialize(chassis, output); | |
262 | if (output_len <= 0) { | |
263 | output_len = 0; | |
264 | *type = NONE; | |
265 | } | |
266 | ||
267 | return output_len; | |
268 | } | |
269 | ||
f6d20631 VB |
270 | /* Return all available information related to an interface |
271 | Input: name of the interface (serialized) | |
272 | Output: Information about the interface (lldpd_hardware) | |
273 | */ | |
324d73a3 | 274 | static ssize_t |
f6d20631 | 275 | client_handle_get_interface(struct lldpd *cfg, enum hmsg_type *type, |
4e90a9e0 | 276 | void *input, int input_len, void **output, int *subscribed) |
a552a72e | 277 | { |
f6d20631 | 278 | char *name; |
5fd6695c | 279 | struct lldpd_hardware *hardware; |
a8da1864 | 280 | void *p; |
5fd6695c VB |
281 | |
282 | /* Get name of the interface */ | |
a8da1864 | 283 | if (marshal_unserialize(string, input, input_len, &p) <= 0) { |
f6d20631 VB |
284 | *type = NONE; |
285 | return 0; | |
286 | } | |
a8da1864 | 287 | name = p; |
f6d20631 VB |
288 | |
289 | /* Search appropriate hardware */ | |
6f8925be | 290 | log_debug("rpc", "client request interface %s", name); |
f6d20631 VB |
291 | TAILQ_FOREACH(hardware, &cfg->g_hardware, h_entries) |
292 | if (!strcmp(hardware->h_ifname, name)) { | |
324d73a3 | 293 | ssize_t output_len = lldpd_hardware_serialize(hardware, output); |
f6d20631 VB |
294 | free(name); |
295 | if (output_len <= 0) { | |
296 | *type = NONE; | |
f6d20631 VB |
297 | return 0; |
298 | } | |
299 | return output_len; | |
300 | } | |
301 | ||
6f8925be | 302 | log_warnx("rpc", "no interface %s found", name); |
e4dea55d | 303 | free(name); |
f6d20631 VB |
304 | *type = NONE; |
305 | return 0; | |
306 | } | |
307 | ||
9da663f7 VB |
308 | /* Return all available information related to an interface |
309 | Input: name of the interface (serialized) | |
310 | Output: Information about the interface (lldpd_hardware) | |
311 | */ | |
312 | static ssize_t | |
313 | client_handle_get_default_port(struct lldpd *cfg, enum hmsg_type *type, | |
314 | void *input, int input_len, void **output, int *subscribed) | |
315 | { | |
316 | log_debug("rpc", "client request the default local port"); | |
317 | ssize_t output_len = lldpd_port_serialize(cfg->g_default_local_port, output); | |
318 | if (output_len <= 0) { | |
319 | *type = NONE; | |
320 | return 0; | |
321 | } | |
322 | return output_len; | |
323 | } | |
324 | ||
84a3104b VB |
325 | static int |
326 | _client_handle_set_port(struct lldpd *cfg, | |
327 | struct lldpd_port *port, struct lldpd_port_set *set) | |
328 | { | |
329 | #ifdef ENABLE_LLDPMED | |
330 | struct lldpd_med_loc *loc = NULL; | |
331 | #endif | |
332 | if (set->local_id) { | |
333 | log_debug("rpc", "requested change to Port ID"); | |
334 | free(port->p_id); | |
335 | port->p_id = strdup(set->local_id); | |
336 | port->p_id_len = strlen(set->local_id); | |
337 | port->p_id_subtype = LLDP_PORTID_SUBTYPE_LOCAL; | |
e1717397 | 338 | port->p_descr_force = 0; |
84a3104b VB |
339 | } |
340 | if (set->local_descr) { | |
341 | log_debug("rpc", "requested change to Port Description"); | |
342 | free(port->p_descr); | |
343 | port->p_descr = strdup(set->local_descr); | |
e1717397 | 344 | port->p_descr_force = 1; |
84a3104b | 345 | } |
e7331ce9 VB |
346 | switch (set->rxtx) { |
347 | case LLDPD_RXTX_TXONLY: | |
348 | log_debug("rpc", "requested TX only mode"); | |
349 | port->p_disable_rx = 1; | |
350 | port->p_disable_tx = 0; | |
351 | break; | |
352 | case LLDPD_RXTX_RXONLY: | |
353 | log_debug("rpc", "requested RX only mode"); | |
354 | port->p_disable_rx = 0; | |
355 | port->p_disable_tx = 1; | |
356 | break; | |
357 | case LLDPD_RXTX_BOTH: | |
358 | log_debug("rpc", "requested RX/TX mode"); | |
359 | port->p_disable_rx = port->p_disable_tx = 0; | |
360 | break; | |
361 | case LLDPD_RXTX_DISABLED: | |
362 | log_debug("rpc", "requested disabled mode"); | |
363 | port->p_disable_rx = port->p_disable_tx = 1; | |
364 | break; | |
365 | } | |
84a3104b VB |
366 | #ifdef ENABLE_LLDPMED |
367 | if (set->med_policy && set->med_policy->type > 0) { | |
368 | log_debug("rpc", "requested change to MED policy"); | |
369 | if (set->med_policy->type > LLDP_MED_APPTYPE_LAST) { | |
370 | log_warnx("rpc", "invalid policy provided: %d", | |
371 | set->med_policy->type); | |
372 | return -1; | |
373 | } | |
374 | memcpy(&port->p_med_policy[set->med_policy->type - 1], | |
375 | set->med_policy, sizeof(struct lldpd_med_policy)); | |
376 | port->p_med_cap_enabled |= LLDP_MED_CAP_POLICY; | |
377 | } | |
378 | if (set->med_location && set->med_location->format > 0) { | |
379 | char *newdata = NULL; | |
380 | log_debug("rpc", "requested change to MED location"); | |
381 | if (set->med_location->format > LLDP_MED_LOCFORMAT_LAST) { | |
382 | log_warnx("rpc", "invalid location format provided: %d", | |
383 | set->med_location->format); | |
384 | return -1; | |
385 | } | |
386 | loc = \ | |
387 | &port->p_med_location[set->med_location->format - 1]; | |
388 | free(loc->data); | |
389 | memcpy(loc, set->med_location, sizeof(struct lldpd_med_loc)); | |
390 | if (!loc->data || !(newdata = malloc(loc->data_len))) loc->data_len = 0; | |
391 | if (newdata) memcpy(newdata, loc->data, loc->data_len); | |
392 | loc->data = newdata; | |
393 | port->p_med_cap_enabled |= LLDP_MED_CAP_LOCATION; | |
394 | } | |
395 | if (set->med_power) { | |
396 | log_debug("rpc", "requested change to MED power"); | |
397 | memcpy(&port->p_med_power, set->med_power, | |
398 | sizeof(struct lldpd_med_power)); | |
399 | switch (set->med_power->devicetype) { | |
400 | case LLDP_MED_POW_TYPE_PD: | |
401 | port->p_med_cap_enabled |= LLDP_MED_CAP_MDI_PD; | |
402 | port->p_med_cap_enabled &= ~LLDP_MED_CAP_MDI_PSE; | |
403 | break; | |
404 | case LLDP_MED_POW_TYPE_PSE: | |
405 | port->p_med_cap_enabled |= LLDP_MED_CAP_MDI_PSE; | |
406 | port->p_med_cap_enabled &= ~LLDP_MED_CAP_MDI_PD; | |
407 | break; | |
408 | } | |
409 | } | |
410 | #endif | |
411 | #ifdef ENABLE_DOT3 | |
412 | if (set->dot3_power) { | |
413 | log_debug("rpc", "requested change to Dot3 power"); | |
414 | memcpy(&port->p_power, set->dot3_power, | |
415 | sizeof(struct lldpd_dot3_power)); | |
416 | } | |
417 | #endif | |
418 | #ifdef ENABLE_CUSTOM | |
419 | if (set->custom_list_clear) { | |
420 | log_debug("rpc", "requested custom TLVs clear"); | |
421 | lldpd_custom_list_cleanup(port); | |
422 | } else { | |
423 | if (set->custom) { | |
7c26c8b4 | 424 | log_info("rpc", "custom TLV op %s oui %02x:%02x:%02x subtype %x", |
92a6d7f9 VB |
425 | (set->custom_tlv_op == CUSTOM_TLV_REMOVE)?"remove": |
426 | (set->custom_tlv_op == CUSTOM_TLV_ADD)?"add": | |
427 | "replace", | |
428 | set->custom->oui[0], | |
429 | set->custom->oui[1], | |
430 | set->custom->oui[2], | |
431 | set->custom->subtype); | |
7c26c8b4 | 432 | switch (set->custom_tlv_op) { |
433 | case CUSTOM_TLV_REMOVE: | |
434 | lldpd_custom_tlv_cleanup(port, set->custom); | |
435 | break; | |
436 | case CUSTOM_TLV_ADD: | |
437 | lldpd_custom_tlv_add(port, set->custom); | |
438 | break; | |
439 | case CUSTOM_TLV_REPLACE: | |
440 | default: | |
441 | lldpd_custom_tlv_cleanup(port, set->custom); | |
442 | lldpd_custom_tlv_add(port, set->custom); | |
443 | break; | |
444 | } | |
84a3104b VB |
445 | } |
446 | } | |
447 | #endif | |
448 | return 0; | |
449 | } | |
450 | ||
f6d20631 VB |
451 | /* Set some port related settings (policy, location, power) |
452 | Input: name of the interface, policy/location/power setting to be modified | |
453 | Output: nothing | |
454 | */ | |
324d73a3 | 455 | static ssize_t |
f6d20631 | 456 | client_handle_set_port(struct lldpd *cfg, enum hmsg_type *type, |
4e90a9e0 | 457 | void *input, int input_len, void **output, int *subscribed) |
f6d20631 VB |
458 | { |
459 | int ret = 0; | |
5fd6695c VB |
460 | struct lldpd_port_set *set = NULL; |
461 | struct lldpd_hardware *hardware = NULL; | |
a552a72e | 462 | |
985a4cb5 | 463 | if (lldpd_port_set_unserialize(input, input_len, &set) <= 0) { |
f6d20631 VB |
464 | *type = NONE; |
465 | return 0; | |
a552a72e | 466 | } |
f6d20631 | 467 | if (!set->ifname) { |
6f8925be | 468 | log_warnx("rpc", "no interface provided"); |
f6d20631 VB |
469 | goto set_port_finished; |
470 | } | |
471 | ||
472 | /* Search the appropriate hardware */ | |
9da663f7 VB |
473 | if (strlen(set->ifname) == 0) { |
474 | log_debug("rpc", "client request change to default port"); | |
475 | if (_client_handle_set_port(cfg, cfg->g_default_local_port, set) == -1) | |
476 | goto set_port_finished; | |
477 | ret = 1; | |
478 | } else { | |
479 | log_debug("rpc", "client request change to port %s", set->ifname); | |
480 | TAILQ_FOREACH(hardware, &cfg->g_hardware, h_entries) { | |
481 | if (!strcmp(hardware->h_ifname, set->ifname)) { | |
482 | struct lldpd_port *port = &hardware->h_lport; | |
483 | if (_client_handle_set_port(cfg, port, set) == -1) | |
484 | goto set_port_finished; | |
485 | ret = 1; | |
486 | break; | |
487 | } | |
488 | } | |
489 | } | |
f6d20631 VB |
490 | |
491 | if (ret == 0) | |
6f8925be | 492 | log_warn("rpc", "no interface %s found", set->ifname); |
bbd094f4 VB |
493 | else |
494 | levent_update_now(cfg); | |
f6d20631 VB |
495 | |
496 | set_port_finished: | |
497 | if (!ret) *type = NONE; | |
498 | free(set->ifname); | |
8e46010c | 499 | free(set->local_id); |
c267d0f2 | 500 | free(set->local_descr); |
4b292b55 | 501 | #ifdef ENABLE_LLDPMED |
f6d20631 VB |
502 | free(set->med_policy); |
503 | if (set->med_location) free(set->med_location->data); | |
504 | free(set->med_location); | |
505 | free(set->med_power); | |
84853b92 | 506 | #endif |
f6d20631 VB |
507 | #ifdef ENABLE_DOT3 |
508 | free(set->dot3_power); | |
6cff1e66 AA |
509 | #endif |
510 | #ifdef ENABLE_CUSTOM | |
8caf4341 AA |
511 | if (set->custom) { |
512 | free(set->custom->oui_info); | |
513 | free(set->custom); | |
514 | } | |
f6d20631 | 515 | #endif |
809498b5 | 516 | free(set); |
f6d20631 VB |
517 | return 0; |
518 | } | |
519 | ||
4e90a9e0 | 520 | /* Register subscribtion to neighbor changes */ |
324d73a3 | 521 | static ssize_t |
4e90a9e0 VB |
522 | client_handle_subscribe(struct lldpd *cfg, enum hmsg_type *type, |
523 | void *input, int input_len, void **output, int *subscribed) | |
524 | { | |
6f8925be | 525 | log_debug("rpc", "client subscribe to changes"); |
4e90a9e0 VB |
526 | *subscribed = 1; |
527 | return 0; | |
528 | } | |
529 | ||
530 | struct client_handle { | |
531 | enum hmsg_type type; | |
bdfe4193 | 532 | const char *name; |
324d73a3 | 533 | ssize_t (*handle)(struct lldpd*, enum hmsg_type *, |
4e90a9e0 VB |
534 | void *, int, void **, int *); |
535 | }; | |
536 | ||
f6d20631 | 537 | static struct client_handle client_handles[] = { |
bdfe4193 VB |
538 | { NONE, "None", client_handle_none }, |
539 | { GET_CONFIG, "Get configuration", client_handle_get_configuration }, | |
540 | { SET_CONFIG, "Set configuration", client_handle_set_configuration }, | |
541 | { GET_INTERFACES, "Get interfaces", client_handle_get_interfaces }, | |
542 | { GET_INTERFACE, "Get interface", client_handle_get_interface }, | |
9da663f7 | 543 | { GET_DEFAULT_PORT, "Get default port", client_handle_get_default_port }, |
99ef55d3 | 544 | { GET_CHASSIS, "Get local chassis", client_handle_get_local_chassis }, |
bdfe4193 VB |
545 | { SET_PORT, "Set port", client_handle_set_port }, |
546 | { SUBSCRIBE, "Subscribe", client_handle_subscribe }, | |
4e90a9e0 | 547 | { 0, NULL } }; |
f6d20631 VB |
548 | |
549 | int | |
e0478a46 VB |
550 | client_handle_client(struct lldpd *cfg, |
551 | ssize_t(*send)(void *, int, void *, size_t), | |
552 | void *out, | |
4e90a9e0 VB |
553 | enum hmsg_type type, void *buffer, size_t n, |
554 | int *subscribed) | |
f6d20631 VB |
555 | { |
556 | struct client_handle *ch; | |
324d73a3 | 557 | void *answer; ssize_t len, sent; |
6f8925be VB |
558 | |
559 | log_debug("rpc", "handle client request"); | |
f6d20631 VB |
560 | for (ch = client_handles; ch->handle != NULL; ch++) { |
561 | if (ch->type == type) { | |
bdfe4193 | 562 | TRACE(LLDPD_CLIENT_REQUEST(ch->name)); |
281a5cd4 | 563 | answer = NULL; |
4e90a9e0 VB |
564 | len = ch->handle(cfg, &type, buffer, n, &answer, |
565 | subscribed); | |
e0478a46 | 566 | sent = send(out, type, answer, len); |
f6d20631 VB |
567 | free(answer); |
568 | return sent; | |
a552a72e VB |
569 | } |
570 | } | |
e0478a46 | 571 | |
6f8925be | 572 | log_warnx("rpc", "unknown message request (%d) received", |
f6d20631 VB |
573 | type); |
574 | return -1; | |
a552a72e | 575 | } |