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
;
39 /* Build the list of interfaces */
40 struct lldpd_interface_list ifs
;
42 TAILQ_FOREACH(hardware
, &cfg
->g_hardware
, h_entries
) {
43 if ((iff
= (struct lldpd_interface
*)malloc(sizeof(
44 struct lldpd_interface
))) == NULL
)
46 iff
->name
= hardware
->h_ifname
;
47 TAILQ_INSERT_TAIL(&ifs
, iff
, next
);
50 int output_len
= marshal_serialize(lldpd_interface_list
, &ifs
, output
);
51 if (output_len
<= 0) {
56 /* Free the temporary list */
57 for (iff
= TAILQ_FIRST(&ifs
);
60 iff_next
= TAILQ_NEXT(iff
, next
);
61 TAILQ_REMOVE(&ifs
, iff
, next
);
68 /* Return all available information related to an interface
69 Input: name of the interface (serialized)
70 Output: Information about the interface (lldpd_hardware)
73 client_handle_get_interface(struct lldpd
*cfg
, enum hmsg_type
*type
,
74 void *input
, int input_len
, void **output
)
76 /* Get name of the interface */
78 if (marshal_unserialize(string
, input
, input_len
, &name
) <= 0) {
83 /* Search appropriate hardware */
84 struct lldpd_hardware
*hardware
;
85 TAILQ_FOREACH(hardware
, &cfg
->g_hardware
, h_entries
)
86 if (!strcmp(hardware
->h_ifname
, name
)) {
87 int output_len
= marshal_serialize(lldpd_hardware
, hardware
, output
);
89 if (output_len
<= 0) {
98 LLOG_WARNX("no interface %s found", name
);
103 /* Set some port related settings (policy, location, power)
104 Input: name of the interface, policy/location/power setting to be modified
108 client_handle_set_port(struct lldpd
*cfg
, enum hmsg_type
*type
,
109 void *input
, int input_len
, void **output
)
112 struct lldpd_port_set
*set
;
114 if (marshal_unserialize(lldpd_port_set
, input
, input_len
, &set
) <= 0) {
119 LLOG_WARNX("no interface provided");
120 goto set_port_finished
;
123 /* Search the appropriate hardware */
124 struct lldpd_hardware
*hardware
;
125 TAILQ_FOREACH(hardware
, &cfg
->g_hardware
, h_entries
)
126 if (!strcmp(hardware
->h_ifname
, set
->ifname
)) {
127 struct lldpd_port
*port
= &hardware
->h_lport
;
128 #ifdef ENABLE_LLDPMED
129 if (set
->med_policy
&& set
->med_policy
->type
> 0) {
130 if (set
->med_policy
->type
> LLDPMED_APPTYPE_LAST
) {
131 LLOG_WARNX("invalid policy provided: %d",
132 set
->med_policy
->type
);
133 goto set_port_finished
;
135 memcpy(&port
->p_med_policy
[set
->med_policy
->type
- 1],
136 set
->med_policy
, sizeof(struct lldpd_med_policy
));
137 port
->p_med_cap_enabled
|= LLDPMED_CAP_POLICY
;
139 if (set
->med_location
&& set
->med_location
->format
> 0) {
140 if (set
->med_location
->format
> LLDPMED_LOCFORMAT_LAST
) {
141 LLOG_WARNX("invalid location format provided: %d",
142 set
->med_location
->format
);
143 goto set_port_finished
;
145 struct lldpd_med_loc
*loc
= \
146 &port
->p_med_location
[set
->med_location
->format
- 1];
148 memcpy(loc
, set
->med_location
, sizeof(struct lldpd_med_loc
));
149 if (!loc
->data
|| !(loc
->data
= strdup(loc
->data
))) loc
->data_len
= 0;
150 port
->p_med_cap_enabled
|= LLDPMED_CAP_LOCATION
;
152 if (set
->med_power
) {
153 memcpy(&port
->p_med_power
, set
->med_power
,
154 sizeof(struct lldpd_med_power
));
155 switch (set
->med_power
->devicetype
) {
156 case LLDPMED_POW_TYPE_PD
:
157 port
->p_med_cap_enabled
|= LLDPMED_CAP_MDI_PD
;
158 port
->p_med_cap_enabled
&= ~LLDPMED_CAP_MDI_PSE
;
160 case LLDPMED_POW_TYPE_PSE
:
161 port
->p_med_cap_enabled
|= LLDPMED_CAP_MDI_PSE
;
162 port
->p_med_cap_enabled
&= ~LLDPMED_CAP_MDI_PD
;
169 memcpy(&port
->p_power
, set
->dot3_power
,
170 sizeof(struct lldpd_dot3_power
));
177 LLOG_WARN("no interface %s found", set
->ifname
);
180 if (!ret
) *type
= NONE
;
182 #ifdef ENABLE_LLDPMED
183 free(set
->med_policy
);
184 if (set
->med_location
) free(set
->med_location
->data
);
185 free(set
->med_location
);
186 free(set
->med_power
);
189 free(set
->dot3_power
);
194 static struct client_handle client_handles
[] = {
195 { NONE
, client_handle_none
},
196 { GET_INTERFACES
, client_handle_get_interfaces
},
197 { GET_INTERFACE
, client_handle_get_interface
},
198 { SET_PORT
, client_handle_set_port
},
202 client_handle_client(struct lldpd
*cfg
, int fd
,
203 enum hmsg_type type
, void *buffer
, int n
)
205 struct client_handle
*ch
;
206 void *answer
; int len
, sent
;
207 for (ch
= client_handles
; ch
->handle
!= NULL
; ch
++) {
208 if (ch
->type
== type
) {
209 answer
= NULL
; len
= 0;
210 len
= ch
->handle(cfg
, &type
, buffer
, n
, &answer
);
211 if ((sent
= ctl_msg_send(fd
, type
, answer
, len
)) == -1)
212 LLOG_WARN("unable to send answer to client");
218 LLOG_WARNX("unknown message request (%d) received",