]> git.ipfire.org Git - thirdparty/lldpd.git/blame - src/daemon/client.c
snmp: don't send traps when SNMP is not enabled
[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"
19
f6d20631
VB
20static int
21client_handle_none(struct lldpd *cfg, enum hmsg_type *type,
4e90a9e0 22 void *input, int input_len, void **output, int *subscribed)
a552a72e 23{
f6d20631
VB
24 LLOG_INFO("received noop request from client");
25 *type = NONE;
26 return 0;
a552a72e
VB
27}
28
8729d69f
VB
29/* Return the global configuration */
30static int
31client_handle_get_configuration(struct lldpd *cfg, enum hmsg_type *type,
32 void *input, int input_len, void **output, int *subscribed)
33{
34 ssize_t output_len;
35 output_len = marshal_serialize(lldpd_config, &cfg->g_config, output);
36 if (output_len <= 0) {
37 output_len = 0;
38 *type = NONE;
39 }
40 return output_len;
41}
42
47287a61
VB
43/* Change the global configuration */
44static int
45client_handle_set_configuration(struct lldpd *cfg, enum hmsg_type *type,
46 void *input, int input_len, void **output, int *subscribed)
47{
48 struct lldpd_config *config;
49
50 /* Get the proposed configuration. */
51 if (marshal_unserialize(lldpd_config, input, input_len, &config) <= 0) {
52 *type = NONE;
53 return 0;
54 }
55
56 /* What needs to be done? Currently, we only support setting the
57 * transmit delay. */
8843f168
VB
58 if (config->c_tx_interval > 0) {
59 cfg->g_config.c_tx_interval = config->c_tx_interval;
47287a61 60 }
8843f168 61 if (config->c_tx_interval < 0) {
47287a61
VB
62 LLOG_DEBUG("client asked for immediate retransmission");
63 levent_send_now(cfg);
64 }
65
66 lldpd_config_cleanup(config);
67
68 return 0;
69}
70
f6d20631
VB
71/* Return the list of interfaces.
72 Input: nothing.
73 Output: list of interface names (lldpd_interface_list)
74*/
75static int
76client_handle_get_interfaces(struct lldpd *cfg, enum hmsg_type *type,
4e90a9e0 77 void *input, int input_len, void **output, int *subscribed)
a552a72e
VB
78{
79 struct lldpd_interface *iff, *iff_next;
80 struct lldpd_hardware *hardware;
5fd6695c 81 int output_len;
a552a72e
VB
82
83 /* Build the list of interfaces */
f6d20631 84 struct lldpd_interface_list ifs;
a552a72e
VB
85 TAILQ_INIT(&ifs);
86 TAILQ_FOREACH(hardware, &cfg->g_hardware, h_entries) {
87 if ((iff = (struct lldpd_interface*)malloc(sizeof(
88 struct lldpd_interface))) == NULL)
89 fatal(NULL);
90 iff->name = hardware->h_ifname;
91 TAILQ_INSERT_TAIL(&ifs, iff, next);
92 }
93
5fd6695c 94 output_len = marshal_serialize(lldpd_interface_list, &ifs, output);
f6d20631
VB
95 if (output_len <= 0) {
96 output_len = 0;
97 *type = NONE;
a552a72e
VB
98 }
99
100 /* Free the temporary list */
101 for (iff = TAILQ_FIRST(&ifs);
102 iff != NULL;
103 iff = iff_next) {
104 iff_next = TAILQ_NEXT(iff, next);
105 TAILQ_REMOVE(&ifs, iff, next);
106 free(iff);
107 }
f6d20631
VB
108
109 return output_len;
a552a72e
VB
110}
111
f6d20631
VB
112/* Return all available information related to an interface
113 Input: name of the interface (serialized)
114 Output: Information about the interface (lldpd_hardware)
115*/
116static int
117client_handle_get_interface(struct lldpd *cfg, enum hmsg_type *type,
4e90a9e0 118 void *input, int input_len, void **output, int *subscribed)
a552a72e 119{
f6d20631 120 char *name;
5fd6695c
VB
121 struct lldpd_hardware *hardware;
122
123 /* Get name of the interface */
f6d20631
VB
124 if (marshal_unserialize(string, input, input_len, &name) <= 0) {
125 *type = NONE;
126 return 0;
127 }
128
129 /* Search appropriate hardware */
f6d20631
VB
130 TAILQ_FOREACH(hardware, &cfg->g_hardware, h_entries)
131 if (!strcmp(hardware->h_ifname, name)) {
132 int output_len = marshal_serialize(lldpd_hardware, hardware, output);
133 free(name);
134 if (output_len <= 0) {
135 *type = NONE;
136 free(name);
137 return 0;
138 }
139 return output_len;
140 }
141
142 free(name);
143 LLOG_WARNX("no interface %s found", name);
144 *type = NONE;
145 return 0;
146}
147
148/* Set some port related settings (policy, location, power)
149 Input: name of the interface, policy/location/power setting to be modified
150 Output: nothing
151*/
152static int
153client_handle_set_port(struct lldpd *cfg, enum hmsg_type *type,
4e90a9e0 154 void *input, int input_len, void **output, int *subscribed)
f6d20631
VB
155{
156 int ret = 0;
5fd6695c
VB
157 struct lldpd_port_set *set = NULL;
158 struct lldpd_hardware *hardware = NULL;
2a836f02 159#ifdef ENABLE_LLDPMED
5fd6695c 160 struct lldpd_med_loc *loc = NULL;
2a836f02 161#endif
a552a72e 162
f6d20631
VB
163 if (marshal_unserialize(lldpd_port_set, input, input_len, &set) <= 0) {
164 *type = NONE;
165 return 0;
a552a72e 166 }
f6d20631
VB
167 if (!set->ifname) {
168 LLOG_WARNX("no interface provided");
169 goto set_port_finished;
170 }
171
172 /* Search the appropriate hardware */
f6d20631
VB
173 TAILQ_FOREACH(hardware, &cfg->g_hardware, h_entries)
174 if (!strcmp(hardware->h_ifname, set->ifname)) {
175 struct lldpd_port *port = &hardware->h_lport;
4b292b55 176 (void)port;
740593ff 177#ifdef ENABLE_LLDPMED
f6d20631 178 if (set->med_policy && set->med_policy->type > 0) {
4b292b55 179 if (set->med_policy->type > LLDP_MED_APPTYPE_LAST) {
f6d20631
VB
180 LLOG_WARNX("invalid policy provided: %d",
181 set->med_policy->type);
182 goto set_port_finished;
183 }
184 memcpy(&port->p_med_policy[set->med_policy->type - 1],
185 set->med_policy, sizeof(struct lldpd_med_policy));
4b292b55 186 port->p_med_cap_enabled |= LLDP_MED_CAP_POLICY;
f6d20631
VB
187 }
188 if (set->med_location && set->med_location->format > 0) {
4b292b55
VB
189 char *newdata = NULL;
190 if (set->med_location->format > LLDP_MED_LOCFORMAT_LAST) {
f6d20631
VB
191 LLOG_WARNX("invalid location format provided: %d",
192 set->med_location->format);
193 goto set_port_finished;
194 }
5fd6695c 195 loc = \
f6d20631
VB
196 &port->p_med_location[set->med_location->format - 1];
197 free(loc->data);
198 memcpy(loc, set->med_location, sizeof(struct lldpd_med_loc));
4b292b55
VB
199 if (!loc->data || !(newdata = malloc(loc->data_len))) loc->data_len = 0;
200 if (newdata) memcpy(newdata, loc->data, loc->data_len);
201 loc->data = newdata;
202 port->p_med_cap_enabled |= LLDP_MED_CAP_LOCATION;
f6d20631
VB
203 }
204 if (set->med_power) {
205 memcpy(&port->p_med_power, set->med_power,
206 sizeof(struct lldpd_med_power));
207 switch (set->med_power->devicetype) {
4b292b55
VB
208 case LLDP_MED_POW_TYPE_PD:
209 port->p_med_cap_enabled |= LLDP_MED_CAP_MDI_PD;
210 port->p_med_cap_enabled &= ~LLDP_MED_CAP_MDI_PSE;
f6d20631 211 break;
4b292b55
VB
212 case LLDP_MED_POW_TYPE_PSE:
213 port->p_med_cap_enabled |= LLDP_MED_CAP_MDI_PSE;
214 port->p_med_cap_enabled &= ~LLDP_MED_CAP_MDI_PD;
f6d20631
VB
215 break;
216 }
217 }
42ee7382
VB
218#endif
219#ifdef ENABLE_DOT3
f6d20631
VB
220 if (set->dot3_power)
221 memcpy(&port->p_power, set->dot3_power,
222 sizeof(struct lldpd_dot3_power));
740593ff 223#endif
f6d20631
VB
224 ret = 1;
225 break;
226 }
227
228 if (ret == 0)
229 LLOG_WARN("no interface %s found", set->ifname);
230
231set_port_finished:
232 if (!ret) *type = NONE;
233 free(set->ifname);
4b292b55 234#ifdef ENABLE_LLDPMED
f6d20631
VB
235 free(set->med_policy);
236 if (set->med_location) free(set->med_location->data);
237 free(set->med_location);
238 free(set->med_power);
84853b92 239#endif
f6d20631
VB
240#ifdef ENABLE_DOT3
241 free(set->dot3_power);
242#endif
243 return 0;
244}
245
4e90a9e0
VB
246/* Register subscribtion to neighbor changes */
247static int
248client_handle_subscribe(struct lldpd *cfg, enum hmsg_type *type,
249 void *input, int input_len, void **output, int *subscribed)
250{
251 *subscribed = 1;
252 return 0;
253}
254
255struct client_handle {
256 enum hmsg_type type;
257 int (*handle)(struct lldpd*, enum hmsg_type *,
258 void *, int, void **, int *);
259};
260
f6d20631 261static struct client_handle client_handles[] = {
4e90a9e0 262 { NONE, client_handle_none },
8729d69f 263 { GET_CONFIG, client_handle_get_configuration },
47287a61 264 { SET_CONFIG, client_handle_set_configuration },
4e90a9e0
VB
265 { GET_INTERFACES, client_handle_get_interfaces },
266 { GET_INTERFACE, client_handle_get_interface },
267 { SET_PORT, client_handle_set_port },
268 { SUBSCRIBE, client_handle_subscribe },
269 { 0, NULL } };
f6d20631
VB
270
271int
e0478a46
VB
272client_handle_client(struct lldpd *cfg,
273 ssize_t(*send)(void *, int, void *, size_t),
274 void *out,
4e90a9e0
VB
275 enum hmsg_type type, void *buffer, size_t n,
276 int *subscribed)
f6d20631
VB
277{
278 struct client_handle *ch;
e0478a46 279 void *answer; size_t len, sent;
f6d20631
VB
280 for (ch = client_handles; ch->handle != NULL; ch++) {
281 if (ch->type == type) {
282 answer = NULL; len = 0;
4e90a9e0
VB
283 len = ch->handle(cfg, &type, buffer, n, &answer,
284 subscribed);
e0478a46 285 sent = send(out, type, answer, len);
f6d20631
VB
286 free(answer);
287 return sent;
a552a72e
VB
288 }
289 }
e0478a46 290
f6d20631
VB
291 LLOG_WARNX("unknown message request (%d) received",
292 type);
293 return -1;
a552a72e 294}