2 * Copyright (c) 2008 Vincent Bernat <bernat@luffy.cx>
4 * Permission to use, copy, modify, and/or distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
20 client_handle_none(struct lldpd
*cfg
, enum hmsg_type
*type
,
21 void *input
, int input_len
, void **output
)
23 LLOG_INFO("received noop request from client");
28 /* Return the list of interfaces.
30 Output: list of interface names (lldpd_interface_list)
33 client_handle_get_interfaces(struct lldpd
*cfg
, enum hmsg_type
*type
,
34 void *input
, int input_len
, void **output
)
36 struct lldpd_interface
*iff
, *iff_next
;
37 struct lldpd_hardware
*hardware
;
40 /* Build the list of interfaces */
41 struct lldpd_interface_list ifs
;
43 TAILQ_FOREACH(hardware
, &cfg
->g_hardware
, h_entries
) {
44 if ((iff
= (struct lldpd_interface
*)malloc(sizeof(
45 struct lldpd_interface
))) == NULL
)
47 iff
->name
= hardware
->h_ifname
;
48 TAILQ_INSERT_TAIL(&ifs
, iff
, next
);
51 output_len
= marshal_serialize(lldpd_interface_list
, &ifs
, output
);
52 if (output_len
<= 0) {
57 /* Free the temporary list */
58 for (iff
= TAILQ_FIRST(&ifs
);
61 iff_next
= TAILQ_NEXT(iff
, next
);
62 TAILQ_REMOVE(&ifs
, iff
, next
);
69 /* Return all available information related to an interface
70 Input: name of the interface (serialized)
71 Output: Information about the interface (lldpd_hardware)
74 client_handle_get_interface(struct lldpd
*cfg
, enum hmsg_type
*type
,
75 void *input
, int input_len
, void **output
)
78 struct lldpd_hardware
*hardware
;
80 /* Get name of the interface */
81 if (marshal_unserialize(string
, input
, input_len
, &name
) <= 0) {
86 /* Search appropriate hardware */
87 TAILQ_FOREACH(hardware
, &cfg
->g_hardware
, h_entries
)
88 if (!strcmp(hardware
->h_ifname
, name
)) {
89 int output_len
= marshal_serialize(lldpd_hardware
, hardware
, output
);
91 if (output_len
<= 0) {
100 LLOG_WARNX("no interface %s found", name
);
105 /* Set some port related settings (policy, location, power)
106 Input: name of the interface, policy/location/power setting to be modified
110 client_handle_set_port(struct lldpd
*cfg
, enum hmsg_type
*type
,
111 void *input
, int input_len
, void **output
)
114 struct lldpd_port_set
*set
= NULL
;
115 struct lldpd_hardware
*hardware
= NULL
;
116 #ifdef ENABLE_LLDPMED
117 struct lldpd_med_loc
*loc
= NULL
;
120 if (marshal_unserialize(lldpd_port_set
, input
, input_len
, &set
) <= 0) {
125 LLOG_WARNX("no interface provided");
126 goto set_port_finished
;
129 /* Search the appropriate hardware */
130 TAILQ_FOREACH(hardware
, &cfg
->g_hardware
, h_entries
)
131 if (!strcmp(hardware
->h_ifname
, set
->ifname
)) {
132 struct lldpd_port
*port
= &hardware
->h_lport
;
133 #ifdef ENABLE_LLDPMED
134 if (set
->med_policy
&& set
->med_policy
->type
> 0) {
135 if (set
->med_policy
->type
> LLDPMED_APPTYPE_LAST
) {
136 LLOG_WARNX("invalid policy provided: %d",
137 set
->med_policy
->type
);
138 goto set_port_finished
;
140 memcpy(&port
->p_med_policy
[set
->med_policy
->type
- 1],
141 set
->med_policy
, sizeof(struct lldpd_med_policy
));
142 port
->p_med_cap_enabled
|= LLDPMED_CAP_POLICY
;
144 if (set
->med_location
&& set
->med_location
->format
> 0) {
145 if (set
->med_location
->format
> LLDPMED_LOCFORMAT_LAST
) {
146 LLOG_WARNX("invalid location format provided: %d",
147 set
->med_location
->format
);
148 goto set_port_finished
;
151 &port
->p_med_location
[set
->med_location
->format
- 1];
153 memcpy(loc
, set
->med_location
, sizeof(struct lldpd_med_loc
));
154 if (!loc
->data
|| !(loc
->data
= strdup(loc
->data
))) loc
->data_len
= 0;
155 port
->p_med_cap_enabled
|= LLDPMED_CAP_LOCATION
;
157 if (set
->med_power
) {
158 memcpy(&port
->p_med_power
, set
->med_power
,
159 sizeof(struct lldpd_med_power
));
160 switch (set
->med_power
->devicetype
) {
161 case LLDPMED_POW_TYPE_PD
:
162 port
->p_med_cap_enabled
|= LLDPMED_CAP_MDI_PD
;
163 port
->p_med_cap_enabled
&= ~LLDPMED_CAP_MDI_PSE
;
165 case LLDPMED_POW_TYPE_PSE
:
166 port
->p_med_cap_enabled
|= LLDPMED_CAP_MDI_PSE
;
167 port
->p_med_cap_enabled
&= ~LLDPMED_CAP_MDI_PD
;
174 memcpy(&port
->p_power
, set
->dot3_power
,
175 sizeof(struct lldpd_dot3_power
));
182 LLOG_WARN("no interface %s found", set
->ifname
);
185 if (!ret
) *type
= NONE
;
187 #ifdef ENABLE_LLDPMED
188 free(set
->med_policy
);
189 if (set
->med_location
) free(set
->med_location
->data
);
190 free(set
->med_location
);
191 free(set
->med_power
);
194 free(set
->dot3_power
);
199 static struct client_handle client_handles
[] = {
200 { NONE
, client_handle_none
},
201 { GET_INTERFACES
, client_handle_get_interfaces
},
202 { GET_INTERFACE
, client_handle_get_interface
},
203 { SET_PORT
, client_handle_set_port
},
207 client_handle_client(struct lldpd
*cfg
, int fd
,
208 enum hmsg_type type
, void *buffer
, int n
)
210 struct client_handle
*ch
;
211 void *answer
; int len
, sent
;
212 for (ch
= client_handles
; ch
->handle
!= NULL
; ch
++) {
213 if (ch
->type
== type
) {
214 answer
= NULL
; len
= 0;
215 len
= ch
->handle(cfg
, &type
, buffer
, n
, &answer
);
216 if ((sent
= ctl_msg_send(fd
, type
, answer
, len
)) == -1)
217 LLOG_WARN("unable to send answer to client");
223 LLOG_WARNX("unknown message request (%d) received",