]> git.ipfire.org Git - thirdparty/lldpd.git/blame - src/daemon/client.c
lldp: don't use chassis TTL anymore
[thirdparty/lldpd.git] / src / daemon / client.c
CommitLineData
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 21static ssize_t
f6d20631 22client_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 31static ssize_t
8729d69f
VB
32client_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
45static char*
46xstrdup(const char *str)
47{
48 if (!str) return NULL;
49 return strdup(str);
50}
51
47287a61 52/* Change the global configuration */
324d73a3 53static ssize_t
47287a61
VB
54client_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 210static ssize_t
f6d20631 211client_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*/
253static ssize_t
254client_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 274static ssize_t
f6d20631 275client_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*/
312static ssize_t
313client_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
325static 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 455static ssize_t
f6d20631 456client_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
496set_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 521static ssize_t
4e90a9e0
VB
522client_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
530struct 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 537static 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
549int
e0478a46
VB
550client_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}