]> git.ipfire.org Git - thirdparty/lldpd.git/blob - src/client.c
d32b4490e8d419ab36321f1e94b617a3f5995bca
[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
39 /* Build the list of interfaces */
40 struct lldpd_interface_list ifs;
41 TAILQ_INIT(&ifs);
42 TAILQ_FOREACH(hardware, &cfg->g_hardware, h_entries) {
43 if ((iff = (struct lldpd_interface*)malloc(sizeof(
44 struct lldpd_interface))) == NULL)
45 fatal(NULL);
46 iff->name = hardware->h_ifname;
47 TAILQ_INSERT_TAIL(&ifs, iff, next);
48 }
49
50 int output_len = marshal_serialize(lldpd_interface_list, &ifs, output);
51 if (output_len <= 0) {
52 output_len = 0;
53 *type = NONE;
54 }
55
56 /* Free the temporary list */
57 for (iff = TAILQ_FIRST(&ifs);
58 iff != NULL;
59 iff = iff_next) {
60 iff_next = TAILQ_NEXT(iff, next);
61 TAILQ_REMOVE(&ifs, iff, next);
62 free(iff);
63 }
64
65 return output_len;
66 }
67
68 /* Return all available information related to an interface
69 Input: name of the interface (serialized)
70 Output: Information about the interface (lldpd_hardware)
71 */
72 static int
73 client_handle_get_interface(struct lldpd *cfg, enum hmsg_type *type,
74 void *input, int input_len, void **output)
75 {
76 /* Get name of the interface */
77 char *name;
78 if (marshal_unserialize(string, input, input_len, &name) <= 0) {
79 *type = NONE;
80 return 0;
81 }
82
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);
88 free(name);
89 if (output_len <= 0) {
90 *type = NONE;
91 free(name);
92 return 0;
93 }
94 return output_len;
95 }
96
97 free(name);
98 LLOG_WARNX("no interface %s found", name);
99 *type = NONE;
100 return 0;
101 }
102
103 /* Set some port related settings (policy, location, power)
104 Input: name of the interface, policy/location/power setting to be modified
105 Output: nothing
106 */
107 static int
108 client_handle_set_port(struct lldpd *cfg, enum hmsg_type *type,
109 void *input, int input_len, void **output)
110 {
111 int ret = 0;
112 struct lldpd_port_set *set;
113
114 if (marshal_unserialize(lldpd_port_set, input, input_len, &set) <= 0) {
115 *type = NONE;
116 return 0;
117 }
118 if (!set->ifname) {
119 LLOG_WARNX("no interface provided");
120 goto set_port_finished;
121 }
122
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;
134 }
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;
138 }
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;
144 }
145 struct lldpd_med_loc *loc = \
146 &port->p_med_location[set->med_location->format - 1];
147 free(loc->data);
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;
151 }
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;
159 break;
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;
163 break;
164 }
165 }
166 #endif
167 #ifdef ENABLE_DOT3
168 if (set->dot3_power)
169 memcpy(&port->p_power, set->dot3_power,
170 sizeof(struct lldpd_dot3_power));
171 #endif
172 ret = 1;
173 break;
174 }
175
176 if (ret == 0)
177 LLOG_WARN("no interface %s found", set->ifname);
178
179 set_port_finished:
180 if (!ret) *type = NONE;
181 free(set->ifname);
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);
187 #endif
188 #ifdef ENABLE_DOT3
189 free(set->dot3_power);
190 #endif
191 return 0;
192 }
193
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 },
199 { 0, NULL } };
200
201 int
202 client_handle_client(struct lldpd *cfg, int fd,
203 enum hmsg_type type, void *buffer, int n)
204 {
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");
213 free(answer);
214 return sent;
215 }
216 }
217
218 LLOG_WARNX("unknown message request (%d) received",
219 type);
220 return -1;
221 }