]> git.ipfire.org Git - thirdparty/lldpd.git/blame - src/client.c
Add smart mode support.
[thirdparty/lldpd.git] / src / client.c
CommitLineData
a552a72e
VB
1/*
2 * Copyright (c) 2008 Vincent Bernat <bernat@luffy.cx>
3 *
4 * Permission to use, copy, modify, and 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
8888d191 19static struct client_handle client_handles[] = {
a552a72e
VB
20 { HMSG_NONE, client_handle_none },
21 { HMSG_GET_INTERFACES, client_handle_get_interfaces },
84853b92 22 { HMSG_GET_NB_PORTS, client_handle_port_related },
740593ff 23 { HMSG_GET_PORT, client_handle_port_related },
84853b92 24 { HMSG_GET_CHASSIS, client_handle_port_related },
740593ff
VB
25#ifdef ENABLE_LLDPMED
26 { HMSG_SET_LOCATION, client_handle_port_related },
86f24df3 27 { HMSG_SET_POLICY, client_handle_port_related },
009ddd23 28 { HMSG_SET_POWER, client_handle_port_related },
740593ff 29#endif
a1347cd8 30#ifdef ENABLE_DOT1
740593ff 31 { HMSG_GET_VLANS, client_handle_port_related },
a1347cd8 32#endif
a552a72e
VB
33 { HMSG_SHUTDOWN, client_handle_shutdown },
34 { 0, NULL } };
35
36void
77d7090e 37client_handle_client(struct lldpd *cfg, struct lldpd_callback *callback,
a552a72e
VB
38 char *buffer, int n)
39{
40 struct hmsg *h; /* Reception */
41 struct hmsg *t; /* Sending */
42 struct client_handle *ch;
43
44 if (n < sizeof(struct hmsg_hdr)) {
45 LLOG_WARNX("too short message request received");
46 return;
47 }
48 h = (struct hmsg *)buffer;
49 n -= sizeof(struct hmsg_hdr);
50 if (n != h->hdr.len) {
51 LLOG_WARNX("incorrect message size received from %d",
52 h->hdr.pid);
53 return;
54 }
55
740593ff 56 if ((t = (struct hmsg*)malloc(MAX_HMSGSIZE)) == NULL) {
a552a72e
VB
57 LLOG_WARNX("unable to allocate memory to answer to %d",
58 h->hdr.pid);
59 return;
60 }
61 ctl_msg_init(t, h->hdr.type);
62 for (ch = client_handles; ch->handle != NULL; ch++) {
63 if (ch->type == h->hdr.type) {
64 ch->handle(cfg, h, t);
65 if (t->hdr.len == -1) {
66 t->hdr.len = 0;
67 t->hdr.type = HMSG_NONE;
68 }
77d7090e 69 if (ctl_msg_send(callback->fd, t) == -1)
a552a72e
VB
70 LLOG_WARN("unable to send answer to client %d",
71 h->hdr.pid);
72 free(t);
73 return;
74 }
75 }
76
77 LLOG_WARNX("unknown message request (%d) received from %d",
78 h->hdr.type, h->hdr.pid);
79 free(t);
80 return;
81}
82
83void
84client_handle_shutdown(struct lldpd *cfg, struct hmsg *r, struct hmsg *s)
85{
86 LLOG_INFO("received shutdown request from client %d",
87 r->hdr.pid);
88 exit(0);
89}
90
91void
92client_handle_none(struct lldpd *cfg, struct hmsg *r, struct hmsg *s)
93{
94 LLOG_INFO("received noop request from client %d",
95 r->hdr.pid);
96 s->hdr.len = -1;
97}
98
99void
100client_handle_get_interfaces(struct lldpd *cfg, struct hmsg *r, struct hmsg *s)
101{
102 struct lldpd_interface *iff, *iff_next;
103 struct lldpd_hardware *hardware;
104 void *p;
105
106 /* Build the list of interfaces */
107 TAILQ_HEAD(, lldpd_interface) ifs;
108 TAILQ_INIT(&ifs);
109 TAILQ_FOREACH(hardware, &cfg->g_hardware, h_entries) {
110 if ((iff = (struct lldpd_interface*)malloc(sizeof(
111 struct lldpd_interface))) == NULL)
112 fatal(NULL);
113 iff->name = hardware->h_ifname;
114 TAILQ_INSERT_TAIL(&ifs, iff, next);
115 }
116
117 p = &s->data;
118 if (ctl_msg_pack_list(STRUCT_LLDPD_INTERFACE, &ifs,
119 sizeof(struct lldpd_interface), s, &p) == -1) {
120 LLOG_WARNX("unable to pack list of interfaces");
121 s->hdr.len = -1;
122 }
123
124 /* Free the temporary list */
125 for (iff = TAILQ_FIRST(&ifs);
126 iff != NULL;
127 iff = iff_next) {
128 iff_next = TAILQ_NEXT(iff, next);
129 TAILQ_REMOVE(&ifs, iff, next);
130 free(iff);
131 }
132}
133
134void
740593ff 135client_handle_port_related(struct lldpd *cfg, struct hmsg *r, struct hmsg *s)
a552a72e
VB
136{
137 char *ifname;
138 struct lldpd_hardware *hardware;
84853b92 139 struct lldpd_port *port;
a552a72e 140 void *p;
740593ff 141 int i;
a552a72e
VB
142
143 ifname = (char*)(&r->data);
740593ff
VB
144 if ((r->hdr.len < IFNAMSIZ) || (ifname[IFNAMSIZ - 1] != 0)) {
145 LLOG_WARNX("bad message format for get port related message (%d)",
146 r->hdr.type);
a552a72e
VB
147 s->hdr.len = -1;
148 return;
149 }
150 TAILQ_FOREACH(hardware, &cfg->g_hardware, h_entries) {
151 if (strncmp(ifname, hardware->h_ifname, IFNAMSIZ) == 0) {
a552a72e 152 switch (r->hdr.type) {
740593ff
VB
153#ifdef ENABLE_LLDPMED
154 case HMSG_SET_LOCATION:
155 p = (char*)&r->data + IFNAMSIZ;
156 for (i=0; i < LLDPMED_LOCFORMAT_LAST; i++) {
157 free(hardware->h_lport.p_med_location[i].data);
158 hardware->h_lport.p_med_location[i].data = NULL;
159 hardware->h_lport.p_med_location[i].format = 0;
160 }
161 if (ctl_msg_unpack_structure(STRUCT_LLDPD_MED_LOC
162 STRUCT_LLDPD_MED_LOC STRUCT_LLDPD_MED_LOC,
163 hardware->h_lport.p_med_location,
164 3*sizeof(struct lldpd_med_loc), r, &p) == -1) {
165 LLOG_WARNX("unable to set location for %s", ifname);
166 s->hdr.len = -1;
167 return;
168 }
169 hardware->h_lport.p_med_cap_enabled |= LLDPMED_CAP_LOCATION;
170 break;
86f24df3
VB
171 case HMSG_SET_POLICY:
172 p = (char*)&r->data + IFNAMSIZ;
173 for (i=0; i < LLDPMED_APPTYPE_LAST; i++) {
174 hardware->h_lport.p_med_policy[i].type = 0;
175 hardware->h_lport.p_med_policy[i].unknown = 0;
176 hardware->h_lport.p_med_policy[i].tagged = 0;
177 hardware->h_lport.p_med_policy[i].vid = 0;
178 hardware->h_lport.p_med_policy[i].priority = 0;
179 hardware->h_lport.p_med_policy[i].dscp = 0;
180 }
181 if (ctl_msg_unpack_structure(
182 STRUCT_LLDPD_MED_POLICY
183 STRUCT_LLDPD_MED_POLICY
184 STRUCT_LLDPD_MED_POLICY
185 STRUCT_LLDPD_MED_POLICY
186 STRUCT_LLDPD_MED_POLICY
187 STRUCT_LLDPD_MED_POLICY
188 STRUCT_LLDPD_MED_POLICY
189 STRUCT_LLDPD_MED_POLICY,
190 hardware->h_lport.p_med_policy,
191 8*sizeof(struct lldpd_med_policy),
192 r, &p) == -1) {
193 LLOG_WARNX("unable to set network policy for %s", ifname);
194 s->hdr.len = -1;
195 return;
196 }
197 hardware->h_lport.p_med_cap_enabled |=
198 LLDPMED_CAP_POLICY;
199 break;
009ddd23
VB
200 case HMSG_SET_POWER:
201 p = (char*)&r->data + IFNAMSIZ;
202 memset(&hardware->h_lport.p_med_power, 0,
203 sizeof(struct lldpd_med_power));
204 if (ctl_msg_unpack_structure(STRUCT_LLDPD_MED_POWER,
205 &hardware->h_lport.p_med_power,
206 sizeof(struct lldpd_med_power),
207 r, &p) == -1) {
208 LLOG_WARNX("unable to set POE-MDI for %s",
209 ifname);
210 s->hdr.len = -1;
211 return;
212 }
213 hardware->h_lport.p_med_cap_enabled &= ~(
214 LLDPMED_CAP_MDI_PD | LLDPMED_CAP_MDI_PSE);
215 switch (hardware->h_lport.p_med_power.devicetype)
216 {
217 case LLDPMED_POW_TYPE_PSE:
218 hardware->h_lport.p_med_cap_enabled |=
219 LLDPMED_CAP_MDI_PSE;
220 break;
221 case LLDPMED_POW_TYPE_PD:
222 hardware->h_lport.p_med_cap_enabled |=
223 LLDPMED_CAP_MDI_PD;
224 break;
225 }
226 break;
740593ff 227#endif
84853b92
VB
228 case HMSG_GET_NB_PORTS:
229 p = &s->data;
230 i = 0;
42b39485
VB
231 TAILQ_FOREACH(port, &hardware->h_rports, p_entries) {
232 if (SMART_HIDDEN(cfg, port)) continue;
233 i++;
234 }
84853b92
VB
235 memcpy(p, &i, sizeof(int));
236 s->hdr.len = sizeof(int);
237 break;
a552a72e 238 case HMSG_GET_VLANS:
84853b92
VB
239 case HMSG_GET_PORT:
240 case HMSG_GET_CHASSIS:
241 /* We read the index which is right after the interface name */
242 if (r->hdr.len < IFNAMSIZ + sizeof(int)) {
243 LLOG_WARNX("too short message format for get "
244 "port related message (%d)", r->hdr.type);
a552a72e
VB
245 s->hdr.len = -1;
246 return;
247 }
84853b92
VB
248 p = (char*)&r->data + IFNAMSIZ;
249 memcpy(&i, p, sizeof(int));
250 p = &s->data;
42b39485
VB
251 TAILQ_FOREACH(port, &hardware->h_rports, p_entries) {
252 if (SMART_HIDDEN(cfg, port)) continue;
253 if (i-- == 0) break;
254 }
84853b92
VB
255 if (!port) {
256 LLOG_INFO("out of range index requested for port "
257 "related information on interface %s for %d",
258 ifname, r->hdr.pid);
a552a72e
VB
259 s->hdr.len = -1;
260 return;
261 }
84853b92
VB
262 p = (char*)&s->data;
263 switch (r->hdr.type) {
264#ifdef ENABLE_DOT1
265 case HMSG_GET_VLANS:
266 if (ctl_msg_pack_list(STRUCT_LLDPD_VLAN,
267 &port->p_vlans,
268 sizeof(struct lldpd_vlan), s, &p) == -1) {
269 LLOG_WARNX("unable to send vlans information for "
270 "interface %s for %d", ifname, r->hdr.pid);
271 s->hdr.len = -1;
272 return;
273 }
274 break;
275#endif
276 case HMSG_GET_PORT:
277 if (ctl_msg_pack_structure(STRUCT_LLDPD_PORT,
278 port,
279 sizeof(struct lldpd_port), s, &p) == -1) {
280 LLOG_WARNX("unable to send port information for "
281 "interface %s for %d", ifname, r->hdr.pid);
282 s->hdr.len = -1;
283 return;
284 }
285 break;
286 case HMSG_GET_CHASSIS:
287 if (ctl_msg_pack_structure(STRUCT_LLDPD_CHASSIS,
288 port->p_chassis,
289 sizeof(struct lldpd_chassis), s, &p) == -1) {
290 LLOG_WARNX("unable to send chassis information "
291 "for interface %s for %d",
292 ifname, r->hdr.pid);
293 s->hdr.len = -1;
294 return;
295 }
296 break;
297 default:
298 LLOG_WARNX("don't know what to do");
a552a72e
VB
299 s->hdr.len = -1;
300 return;
301 }
302 break;
303 default:
304 LLOG_WARNX("don't know what to do");
305 s->hdr.len = -1;
306 return;
307 }
308 return;
309 }
310 }
311 LLOG_WARNX("requested interface %s by %d was not found",
312 ifname, r->hdr.pid);
313 s->hdr.len = -1;
314 return;
315}