]> git.ipfire.org Git - thirdparty/lldpd.git/blob - src/client.c
dist: provide a complete changelog
[thirdparty/lldpd.git] / src / client.c
1 /*
2 * Copyright (c) 2008 Vincent Bernat <bernat@luffy.cx>
3 *
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.
7 *
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.
15 */
16
17 #include "lldpd.h"
18
19 static int
20 client_handle_none(struct lldpd *cfg, enum hmsg_type *type,
21 void *input, int input_len, void **output)
22 {
23 LLOG_INFO("received noop request from client");
24 *type = NONE;
25 return 0;
26 }
27
28 /* Return the list of interfaces.
29 Input: nothing.
30 Output: list of interface names (lldpd_interface_list)
31 */
32 static int
33 client_handle_get_interfaces(struct lldpd *cfg, enum hmsg_type *type,
34 void *input, int input_len, void **output)
35 {
36 struct lldpd_interface *iff, *iff_next;
37 struct lldpd_hardware *hardware;
38 int output_len;
39
40 /* Build the list of interfaces */
41 struct lldpd_interface_list ifs;
42 TAILQ_INIT(&ifs);
43 TAILQ_FOREACH(hardware, &cfg->g_hardware, h_entries) {
44 if ((iff = (struct lldpd_interface*)malloc(sizeof(
45 struct lldpd_interface))) == NULL)
46 fatal(NULL);
47 iff->name = hardware->h_ifname;
48 TAILQ_INSERT_TAIL(&ifs, iff, next);
49 }
50
51 output_len = marshal_serialize(lldpd_interface_list, &ifs, output);
52 if (output_len <= 0) {
53 output_len = 0;
54 *type = NONE;
55 }
56
57 /* Free the temporary list */
58 for (iff = TAILQ_FIRST(&ifs);
59 iff != NULL;
60 iff = iff_next) {
61 iff_next = TAILQ_NEXT(iff, next);
62 TAILQ_REMOVE(&ifs, iff, next);
63 free(iff);
64 }
65
66 return output_len;
67 }
68
69 /* Return all available information related to an interface
70 Input: name of the interface (serialized)
71 Output: Information about the interface (lldpd_hardware)
72 */
73 static int
74 client_handle_get_interface(struct lldpd *cfg, enum hmsg_type *type,
75 void *input, int input_len, void **output)
76 {
77 char *name;
78 struct lldpd_hardware *hardware;
79
80 /* Get name of the interface */
81 if (marshal_unserialize(string, input, input_len, &name) <= 0) {
82 *type = NONE;
83 return 0;
84 }
85
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);
90 free(name);
91 if (output_len <= 0) {
92 *type = NONE;
93 free(name);
94 return 0;
95 }
96 return output_len;
97 }
98
99 free(name);
100 LLOG_WARNX("no interface %s found", name);
101 *type = NONE;
102 return 0;
103 }
104
105 /* Set some port related settings (policy, location, power)
106 Input: name of the interface, policy/location/power setting to be modified
107 Output: nothing
108 */
109 static int
110 client_handle_set_port(struct lldpd *cfg, enum hmsg_type *type,
111 void *input, int input_len, void **output)
112 {
113 int ret = 0;
114 struct lldpd_port_set *set = NULL;
115 struct lldpd_hardware *hardware = NULL;
116 #ifdef ENABLE_LLDPMED
117 struct lldpd_med_loc *loc = NULL;
118 #endif
119
120 if (marshal_unserialize(lldpd_port_set, input, input_len, &set) <= 0) {
121 *type = NONE;
122 return 0;
123 }
124 if (!set->ifname) {
125 LLOG_WARNX("no interface provided");
126 goto set_port_finished;
127 }
128
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;
139 }
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;
143 }
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;
149 }
150 loc = \
151 &port->p_med_location[set->med_location->format - 1];
152 free(loc->data);
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;
156 }
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;
164 break;
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;
168 break;
169 }
170 }
171 #endif
172 #ifdef ENABLE_DOT3
173 if (set->dot3_power)
174 memcpy(&port->p_power, set->dot3_power,
175 sizeof(struct lldpd_dot3_power));
176 #endif
177 ret = 1;
178 break;
179 }
180
181 if (ret == 0)
182 LLOG_WARN("no interface %s found", set->ifname);
183
184 set_port_finished:
185 if (!ret) *type = NONE;
186 free(set->ifname);
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);
192 #endif
193 #ifdef ENABLE_DOT3
194 free(set->dot3_power);
195 #endif
196 return 0;
197 }
198
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 },
204 { 0, NULL } };
205
206 int
207 client_handle_client(struct lldpd *cfg, int fd,
208 enum hmsg_type type, void *buffer, int n)
209 {
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");
218 free(answer);
219 return sent;
220 }
221 }
222
223 LLOG_WARNX("unknown message request (%d) received",
224 type);
225 return -1;
226 }