1 /* -*- mode: c; c-file-style: "openbsd" -*- */
3 * Copyright (c) 2008 Vincent Bernat <bernat@luffy.cx>
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.
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.
21 client_handle_none(struct lldpd
*cfg
, enum hmsg_type
*type
,
22 void *input
, int input_len
, void **output
, int *subscribed
)
24 LLOG_INFO("received noop request from client");
29 /* Return the list of interfaces.
31 Output: list of interface names (lldpd_interface_list)
34 client_handle_get_interfaces(struct lldpd
*cfg
, enum hmsg_type
*type
,
35 void *input
, int input_len
, void **output
, int *subscribed
)
37 struct lldpd_interface
*iff
, *iff_next
;
38 struct lldpd_hardware
*hardware
;
41 /* Build the list of interfaces */
42 struct lldpd_interface_list ifs
;
44 TAILQ_FOREACH(hardware
, &cfg
->g_hardware
, h_entries
) {
45 if ((iff
= (struct lldpd_interface
*)malloc(sizeof(
46 struct lldpd_interface
))) == NULL
)
48 iff
->name
= hardware
->h_ifname
;
49 TAILQ_INSERT_TAIL(&ifs
, iff
, next
);
52 output_len
= marshal_serialize(lldpd_interface_list
, &ifs
, output
);
53 if (output_len
<= 0) {
58 /* Free the temporary list */
59 for (iff
= TAILQ_FIRST(&ifs
);
62 iff_next
= TAILQ_NEXT(iff
, next
);
63 TAILQ_REMOVE(&ifs
, iff
, next
);
70 /* Return all available information related to an interface
71 Input: name of the interface (serialized)
72 Output: Information about the interface (lldpd_hardware)
75 client_handle_get_interface(struct lldpd
*cfg
, enum hmsg_type
*type
,
76 void *input
, int input_len
, void **output
, int *subscribed
)
79 struct lldpd_hardware
*hardware
;
81 /* Get name of the interface */
82 if (marshal_unserialize(string
, input
, input_len
, &name
) <= 0) {
87 /* Search appropriate hardware */
88 TAILQ_FOREACH(hardware
, &cfg
->g_hardware
, h_entries
)
89 if (!strcmp(hardware
->h_ifname
, name
)) {
90 int output_len
= marshal_serialize(lldpd_hardware
, hardware
, output
);
92 if (output_len
<= 0) {
101 LLOG_WARNX("no interface %s found", name
);
106 /* Set some port related settings (policy, location, power)
107 Input: name of the interface, policy/location/power setting to be modified
111 client_handle_set_port(struct lldpd
*cfg
, enum hmsg_type
*type
,
112 void *input
, int input_len
, void **output
, int *subscribed
)
115 struct lldpd_port_set
*set
= NULL
;
116 struct lldpd_hardware
*hardware
= NULL
;
117 #ifdef ENABLE_LLDPMED
118 struct lldpd_med_loc
*loc
= NULL
;
121 if (marshal_unserialize(lldpd_port_set
, input
, input_len
, &set
) <= 0) {
126 LLOG_WARNX("no interface provided");
127 goto set_port_finished
;
130 /* Search the appropriate hardware */
131 TAILQ_FOREACH(hardware
, &cfg
->g_hardware
, h_entries
)
132 if (!strcmp(hardware
->h_ifname
, set
->ifname
)) {
133 struct lldpd_port
*port
= &hardware
->h_lport
;
135 #ifdef ENABLE_LLDPMED
136 if (set
->med_policy
&& set
->med_policy
->type
> 0) {
137 if (set
->med_policy
->type
> LLDP_MED_APPTYPE_LAST
) {
138 LLOG_WARNX("invalid policy provided: %d",
139 set
->med_policy
->type
);
140 goto set_port_finished
;
142 memcpy(&port
->p_med_policy
[set
->med_policy
->type
- 1],
143 set
->med_policy
, sizeof(struct lldpd_med_policy
));
144 port
->p_med_cap_enabled
|= LLDP_MED_CAP_POLICY
;
146 if (set
->med_location
&& set
->med_location
->format
> 0) {
147 char *newdata
= NULL
;
148 if (set
->med_location
->format
> LLDP_MED_LOCFORMAT_LAST
) {
149 LLOG_WARNX("invalid location format provided: %d",
150 set
->med_location
->format
);
151 goto set_port_finished
;
154 &port
->p_med_location
[set
->med_location
->format
- 1];
156 memcpy(loc
, set
->med_location
, sizeof(struct lldpd_med_loc
));
157 if (!loc
->data
|| !(newdata
= malloc(loc
->data_len
))) loc
->data_len
= 0;
158 if (newdata
) memcpy(newdata
, loc
->data
, loc
->data_len
);
160 port
->p_med_cap_enabled
|= LLDP_MED_CAP_LOCATION
;
162 if (set
->med_power
) {
163 memcpy(&port
->p_med_power
, set
->med_power
,
164 sizeof(struct lldpd_med_power
));
165 switch (set
->med_power
->devicetype
) {
166 case LLDP_MED_POW_TYPE_PD
:
167 port
->p_med_cap_enabled
|= LLDP_MED_CAP_MDI_PD
;
168 port
->p_med_cap_enabled
&= ~LLDP_MED_CAP_MDI_PSE
;
170 case LLDP_MED_POW_TYPE_PSE
:
171 port
->p_med_cap_enabled
|= LLDP_MED_CAP_MDI_PSE
;
172 port
->p_med_cap_enabled
&= ~LLDP_MED_CAP_MDI_PD
;
179 memcpy(&port
->p_power
, set
->dot3_power
,
180 sizeof(struct lldpd_dot3_power
));
187 LLOG_WARN("no interface %s found", set
->ifname
);
190 if (!ret
) *type
= NONE
;
192 #ifdef ENABLE_LLDPMED
193 free(set
->med_policy
);
194 if (set
->med_location
) free(set
->med_location
->data
);
195 free(set
->med_location
);
196 free(set
->med_power
);
199 free(set
->dot3_power
);
204 /* Register subscribtion to neighbor changes */
206 client_handle_subscribe(struct lldpd
*cfg
, enum hmsg_type
*type
,
207 void *input
, int input_len
, void **output
, int *subscribed
)
213 struct client_handle
{
215 int (*handle
)(struct lldpd
*, enum hmsg_type
*,
216 void *, int, void **, int *);
219 static struct client_handle client_handles
[] = {
220 { NONE
, client_handle_none
},
221 { GET_INTERFACES
, client_handle_get_interfaces
},
222 { GET_INTERFACE
, client_handle_get_interface
},
223 { SET_PORT
, client_handle_set_port
},
224 { SUBSCRIBE
, client_handle_subscribe
},
228 client_handle_client(struct lldpd
*cfg
,
229 ssize_t(*send
)(void *, int, void *, size_t),
231 enum hmsg_type type
, void *buffer
, size_t n
,
234 struct client_handle
*ch
;
235 void *answer
; size_t len
, sent
;
236 for (ch
= client_handles
; ch
->handle
!= NULL
; ch
++) {
237 if (ch
->type
== type
) {
238 answer
= NULL
; len
= 0;
239 len
= ch
->handle(cfg
, &type
, buffer
, n
, &answer
,
241 sent
= send(out
, type
, answer
, len
);
247 LLOG_WARNX("unknown message request (%d) received",