]>
Commit | Line | Data |
---|---|---|
43c02e7b 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" | |
a8105c1b | 18 | #include "frame.h" |
43c02e7b | 19 | |
4bad1937 VB |
20 | #ifdef ENABLE_EDP |
21 | ||
43c02e7b | 22 | #include <stdio.h> |
a8105c1b | 23 | #include <unistd.h> |
43c02e7b VB |
24 | #include <errno.h> |
25 | #include <arpa/inet.h> | |
26 | #include <fnmatch.h> | |
27 | ||
8888d191 | 28 | static int seq = 0; |
43c02e7b VB |
29 | |
30 | int | |
31 | edp_send(struct lldpd *global, struct lldpd_chassis *chassis, | |
32 | struct lldpd_hardware *hardware) | |
33 | { | |
43c02e7b VB |
34 | const u_int8_t mcastaddr[] = EDP_MULTICAST_ADDR; |
35 | const u_int8_t llcorg[] = LLC_ORG_EXTREME; | |
a8105c1b VB |
36 | int length, i, v; |
37 | u_int8_t *packet, *pos, *pos_llc, *pos_len_eh, *pos_len_edp, *pos_edp, *tlv, *end; | |
38 | u_int16_t checksum; | |
a1347cd8 | 39 | #ifdef ENABLE_DOT1 |
43c02e7b | 40 | struct lldpd_vlan *vlan; |
a1347cd8 VB |
41 | unsigned int state = 0; |
42 | #endif | |
43c02e7b | 43 | u_int8_t edp_fakeversion[] = {7, 6, 4, 99}; |
43c02e7b VB |
44 | /* Subsequent XXX can be replaced by other values. We place |
45 | them here to ensure the position of "" to be a bit | |
46 | invariant with version changes. */ | |
47 | char *deviceslot[] = { "eth", "veth", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "", NULL }; | |
48 | ||
a1347cd8 | 49 | #ifdef ENABLE_DOT1 |
43c02e7b | 50 | while (state != 2) { |
a1347cd8 | 51 | #endif |
a8105c1b VB |
52 | length = hardware->h_mtu; |
53 | if ((packet = (u_int8_t*)malloc(length)) == NULL) | |
54 | return ENOMEM; | |
55 | memset(packet, 0, length); | |
56 | pos = packet; | |
57 | v = 0; | |
58 | ||
59 | /* Ethernet header */ | |
60 | if (!( | |
61 | POKE_BYTES(mcastaddr, sizeof(mcastaddr)) && | |
62 | POKE_BYTES(&hardware->h_lladdr, sizeof(hardware->h_lladdr)) && | |
63 | POKE_SAVE(pos_len_eh) && /* We compute the len later */ | |
64 | POKE_UINT16(0))) | |
65 | goto toobig; | |
43c02e7b | 66 | |
a8105c1b VB |
67 | /* LLC */ |
68 | if (!( | |
69 | POKE_SAVE(pos_llc) && /* We need to save our | |
70 | current position to | |
71 | compute ethernet len */ | |
72 | /* SSAP and DSAP */ | |
73 | POKE_UINT8(0xaa) && POKE_UINT8(0xaa) && | |
74 | /* Control field */ | |
75 | POKE_UINT8(0x03) && | |
76 | /* ORG */ | |
77 | POKE_BYTES(llcorg, sizeof(llcorg)) && | |
78 | POKE_UINT16(LLC_PID_EDP))) | |
79 | goto toobig; | |
43c02e7b VB |
80 | |
81 | /* EDP header */ | |
43c02e7b VB |
82 | if ((chassis->c_id_len != ETH_ALEN) || |
83 | (chassis->c_id_subtype != LLDP_CHASSISID_SUBTYPE_LLADDR)) { | |
84 | LLOG_WARNX("local chassis does not use MAC address as chassis ID!?"); | |
a8105c1b | 85 | free(packet); |
43c02e7b VB |
86 | return EINVAL; |
87 | } | |
a8105c1b VB |
88 | if (!( |
89 | POKE_SAVE(pos_edp) && /* Save the start of EDP frame */ | |
90 | POKE_UINT8(1) && POKE_UINT8(0) && | |
91 | POKE_SAVE(pos_len_edp) && /* We compute the len | |
92 | and the checksum | |
93 | later */ | |
94 | POKE_UINT32(0) && /* Len + Checksum */ | |
95 | POKE_UINT16(seq) && | |
96 | POKE_UINT16(0) && | |
98faedcf | 97 | POKE_BYTES(chassis->c_id, ETH_ALEN))) |
a8105c1b VB |
98 | goto toobig; |
99 | seq++; | |
43c02e7b | 100 | |
a1347cd8 | 101 | #ifdef ENABLE_DOT1 |
43c02e7b VB |
102 | switch (state) { |
103 | case 0: | |
a1347cd8 | 104 | #endif |
43c02e7b | 105 | /* Display TLV */ |
a8105c1b VB |
106 | if (!( |
107 | POKE_START_EDP_TLV(EDP_TLV_DISPLAY) && | |
108 | POKE_BYTES(chassis->c_name, strlen(chassis->c_name)) && | |
109 | POKE_UINT8(0) && /* Add a NULL character | |
110 | for better | |
111 | compatibility */ | |
112 | POKE_END_EDP_TLV)) | |
113 | goto toobig; | |
43c02e7b VB |
114 | |
115 | /* Info TLV */ | |
a8105c1b VB |
116 | if (!( |
117 | POKE_START_EDP_TLV(EDP_TLV_INFO))) | |
118 | goto toobig; | |
119 | /* We try to emulate the slot thing */ | |
43c02e7b VB |
120 | for (i=0; deviceslot[i] != NULL; i++) { |
121 | if (strncmp(hardware->h_ifname, deviceslot[i], | |
122 | strlen(deviceslot[i])) == 0) { | |
a8105c1b VB |
123 | if (!( |
124 | POKE_UINT16(i) && | |
125 | POKE_UINT16(atoi(hardware->h_ifname + | |
126 | strlen(deviceslot[i]))))) | |
127 | goto toobig; | |
43c02e7b VB |
128 | break; |
129 | } | |
130 | } | |
a8105c1b VB |
131 | /* If we don't find a "slot", we say that the |
132 | interface is in slot 8 */ | |
ae8f3104 | 133 | if (deviceslot[i] == NULL) { |
a8105c1b VB |
134 | if (!( |
135 | POKE_UINT16(8) && | |
136 | POKE_UINT16(if_nametoindex(hardware->h_ifname)))) | |
137 | goto toobig; | |
43c02e7b | 138 | } |
a8105c1b VB |
139 | if (!( |
140 | POKE_UINT16(0) && /* vchassis */ | |
141 | POKE_UINT32(0) && POKE_UINT16(0) && /* Reserved */ | |
142 | /* Version */ | |
143 | POKE_BYTES(edp_fakeversion, sizeof(edp_fakeversion)) && | |
144 | /* Connections, we say that we won't | |
145 | have more interfaces than this | |
146 | mask. */ | |
147 | POKE_UINT32(0xffffffff) && | |
148 | POKE_UINT32(0) && POKE_UINT32(0) && POKE_UINT32(0) && | |
149 | POKE_END_EDP_TLV)) | |
150 | goto toobig; | |
151 | ||
a1347cd8 | 152 | #ifdef ENABLE_DOT1 |
43c02e7b VB |
153 | break; |
154 | case 1: | |
43c02e7b VB |
155 | TAILQ_FOREACH(vlan, &hardware->h_lport.p_vlans, |
156 | v_entries) { | |
a8105c1b VB |
157 | v++; |
158 | if (!( | |
159 | POKE_START_EDP_TLV(EDP_TLV_VLAN) && | |
160 | POKE_UINT8(0) && /* Flags: no IP address */ | |
161 | POKE_UINT8(0) && /* Reserved */ | |
162 | POKE_UINT16(vlan->v_vid) && | |
163 | POKE_UINT32(0) && /* Reserved */ | |
164 | POKE_UINT32(0) && /* IP address */ | |
165 | /* VLAN name */ | |
166 | POKE_BYTES(vlan->v_name, strlen(vlan->v_name)) && | |
167 | POKE_UINT8(0) && | |
168 | POKE_END_EDP_TLV)) | |
169 | goto toobig; | |
43c02e7b VB |
170 | } |
171 | break; | |
172 | } | |
173 | ||
7c11435e | 174 | if ((state == 1) && (v == 0)) /* No VLAN, no need to send another TLV */ |
43c02e7b | 175 | break; |
a1347cd8 | 176 | #endif |
43c02e7b VB |
177 | |
178 | /* Null TLV */ | |
a8105c1b VB |
179 | if (!( |
180 | POKE_START_EDP_TLV(EDP_TLV_NULL) && | |
181 | POKE_END_EDP_TLV && | |
182 | POKE_SAVE(end))) | |
183 | goto toobig; | |
43c02e7b VB |
184 | |
185 | /* Compute len and checksum */ | |
a8105c1b VB |
186 | i = end - pos_llc; /* Ethernet length */ |
187 | v = end - pos_edp; /* EDP length */ | |
188 | POKE_RESTORE(pos_len_eh); | |
189 | if (!(POKE_UINT16(i))) goto toobig; | |
190 | POKE_RESTORE(pos_len_edp); | |
191 | if (!(POKE_UINT16(v))) goto toobig; | |
192 | checksum = frame_checksum(pos_edp, v, 0); | |
193 | if (!(POKE_UINT16(ntohs(checksum)))) goto toobig; | |
43c02e7b | 194 | |
0bc32943 | 195 | if (write(hardware->h_raw, packet, end - packet) == -1) { |
43c02e7b VB |
196 | LLOG_WARN("unable to send packet on real device for %s", |
197 | hardware->h_ifname); | |
a8105c1b | 198 | free(packet); |
43c02e7b VB |
199 | return ENETDOWN; |
200 | } | |
a8105c1b | 201 | free(packet); |
a1347cd8 VB |
202 | |
203 | #ifdef ENABLE_DOT1 | |
43c02e7b VB |
204 | state++; |
205 | } | |
a1347cd8 | 206 | #endif |
43c02e7b VB |
207 | |
208 | hardware->h_tx_cnt++; | |
43c02e7b | 209 | return 0; |
a8105c1b VB |
210 | toobig: |
211 | free(packet); | |
212 | return E2BIG; | |
43c02e7b VB |
213 | } |
214 | ||
a8105c1b VB |
215 | #define CHECK_TLV_SIZE(x, name) \ |
216 | do { if (tlv_len < (x)) { \ | |
217 | LLOG_WARNX(name " EDP TLV too short received on %s",\ | |
218 | hardware->h_ifname); \ | |
219 | goto malformed; \ | |
220 | } } while (0) | |
221 | ||
43c02e7b VB |
222 | int |
223 | edp_decode(struct lldpd *cfg, char *frame, int s, | |
224 | struct lldpd_hardware *hardware, | |
225 | struct lldpd_chassis **newchassis, struct lldpd_port **newport) | |
226 | { | |
227 | struct lldpd_chassis *chassis; | |
228 | struct lldpd_port *port; | |
a1347cd8 | 229 | #ifdef ENABLE_DOT1 |
a8105c1b | 230 | struct lldpd_vlan *lvlan = NULL, *lvlan_next; |
a1347cd8 | 231 | #endif |
43c02e7b | 232 | const unsigned char edpaddr[] = EDP_MULTICAST_ADDR; |
a8105c1b VB |
233 | int length, gotend = 0, gotvlans = 0, edp_len, tlv_len, tlv_type; |
234 | int edp_port, edp_slot; | |
235 | u_int8_t *pos, *pos_edp, *tlv; | |
236 | u_int8_t version[4]; | |
237 | struct in_addr address; | |
43c02e7b VB |
238 | |
239 | if ((chassis = calloc(1, sizeof(struct lldpd_chassis))) == NULL) { | |
240 | LLOG_WARN("failed to allocate remote chassis"); | |
241 | return -1; | |
242 | } | |
243 | if ((port = calloc(1, sizeof(struct lldpd_port))) == NULL) { | |
244 | LLOG_WARN("failed to allocate remote port"); | |
245 | free(chassis); | |
246 | return -1; | |
247 | } | |
a1347cd8 | 248 | #ifdef ENABLE_DOT1 |
43c02e7b | 249 | TAILQ_INIT(&port->p_vlans); |
a1347cd8 | 250 | #endif |
43c02e7b | 251 | |
a8105c1b VB |
252 | length = s; |
253 | pos = (u_int8_t*)frame; | |
254 | ||
255 | if (length < 2*ETH_ALEN + sizeof(u_int16_t) + 8 /* LLC */ + | |
256 | 10 + ETH_ALEN /* EDP header */) { | |
257 | LLOG_WARNX("too short EDP frame received on %s", hardware->h_ifname); | |
43c02e7b VB |
258 | goto malformed; |
259 | } | |
260 | ||
a8105c1b | 261 | if (PEEK_CMP(edpaddr, sizeof(edpaddr)) != 0) { |
43c02e7b VB |
262 | LLOG_INFO("frame not targeted at EDP multicast address received on %s", |
263 | hardware->h_ifname); | |
264 | goto malformed; | |
265 | } | |
a8105c1b VB |
266 | PEEK_DISCARD(ETH_ALEN); PEEK_DISCARD_UINT16; |
267 | PEEK_DISCARD(6); /* LLC: DSAP + SSAP + control + org */ | |
268 | if (PEEK_UINT16 != LLC_PID_EDP) { | |
43c02e7b VB |
269 | LLOG_DEBUG("incorrect LLC protocol ID received on %s", |
270 | hardware->h_ifname); | |
271 | goto malformed; | |
272 | } | |
273 | ||
a8105c1b VB |
274 | PEEK_SAVE(pos_edp); /* Save the start of EDP packet */ |
275 | if (PEEK_UINT8 != 1) { | |
276 | LLOG_WARNX("incorrect EDP version for frame received on %s", | |
277 | hardware->h_ifname); | |
43c02e7b VB |
278 | goto malformed; |
279 | } | |
a8105c1b VB |
280 | PEEK_DISCARD_UINT8; /* Reserved */ |
281 | edp_len = PEEK_UINT16; | |
282 | PEEK_DISCARD_UINT16; /* Checksum */ | |
283 | PEEK_DISCARD_UINT16; /* Sequence */ | |
284 | if (PEEK_UINT16 != 0) { /* ID Type = 0 = MAC */ | |
43c02e7b VB |
285 | LLOG_WARNX("incorrect device id type for frame received on %s", |
286 | hardware->h_ifname); | |
287 | goto malformed; | |
288 | } | |
a8105c1b | 289 | if (edp_len > length + 10) { |
43c02e7b VB |
290 | LLOG_WARNX("incorrect size for EDP frame received on %s", |
291 | hardware->h_ifname); | |
292 | goto malformed; | |
293 | } | |
294 | chassis->c_ttl = LLDPD_TTL; | |
295 | chassis->c_id_subtype = LLDP_CHASSISID_SUBTYPE_LLADDR; | |
296 | chassis->c_id_len = ETH_ALEN; | |
297 | if ((chassis->c_id = (char *)malloc(ETH_ALEN)) == NULL) { | |
298 | LLOG_WARN("unable to allocate memory for chassis ID"); | |
299 | goto malformed; | |
300 | } | |
a8105c1b VB |
301 | PEEK_BYTES(chassis->c_id, ETH_ALEN); |
302 | ||
303 | /* Let's check checksum */ | |
304 | if (frame_checksum(pos_edp, edp_len, 0) != 0) { | |
43c02e7b VB |
305 | LLOG_WARNX("incorrect EDP checksum for frame received on %s", |
306 | hardware->h_ifname); | |
307 | goto malformed; | |
308 | } | |
309 | ||
a8105c1b VB |
310 | while (length && !gotend) { |
311 | if (length < 4) { | |
43c02e7b VB |
312 | LLOG_WARNX("EDP TLV header is too large for " |
313 | "frame received on %s", | |
314 | hardware->h_ifname); | |
315 | goto malformed; | |
316 | } | |
a8105c1b VB |
317 | if (PEEK_UINT8 != EDP_TLV_MARKER) { |
318 | LLOG_WARNX("incorrect marker starting EDP TLV header for frame " | |
319 | "received on %s", | |
320 | hardware->h_ifname); | |
321 | goto malformed; | |
322 | } | |
323 | tlv_type = PEEK_UINT8; | |
324 | tlv_len = PEEK_UINT16 - 4; | |
325 | PEEK_SAVE(tlv); | |
326 | if ((tlv_len < 0) || (tlv_len > length)) { | |
43c02e7b VB |
327 | LLOG_DEBUG("incorrect size in EDP TLV header for frame " |
328 | "received on %s", | |
329 | hardware->h_ifname); | |
330 | /* Some poor old Extreme Summit are quite bogus */ | |
331 | gotend = 1; | |
332 | break; | |
333 | } | |
a8105c1b | 334 | switch (tlv_type) { |
43c02e7b | 335 | case EDP_TLV_INFO: |
a8105c1b | 336 | CHECK_TLV_SIZE(32, "Info"); |
43c02e7b | 337 | port->p_id_subtype = LLDP_PORTID_SUBTYPE_IFNAME; |
a8105c1b | 338 | edp_slot = PEEK_UINT16; edp_port = PEEK_UINT16; |
43c02e7b | 339 | if (asprintf(&port->p_id, "%d/%d", |
a8105c1b | 340 | edp_slot + 1, edp_port + 1) == -1) { |
43c02e7b VB |
341 | LLOG_WARN("unable to allocate memory for " |
342 | "port ID"); | |
343 | goto malformed; | |
344 | } | |
345 | port->p_id_len = strlen(port->p_id); | |
346 | if (asprintf(&port->p_descr, "Slot %d / Port %d", | |
a8105c1b | 347 | edp_slot + 1, edp_port + 1) == -1) { |
43c02e7b VB |
348 | LLOG_WARN("unable to allocate memory for " |
349 | "port description"); | |
350 | goto malformed; | |
351 | } | |
a8105c1b VB |
352 | PEEK_DISCARD_UINT16; /* vchassis */ |
353 | PEEK_DISCARD(6); /* Reserved */ | |
354 | PEEK_BYTES(version, 4); | |
43c02e7b VB |
355 | if (asprintf(&chassis->c_descr, |
356 | "EDP enabled device, version %d.%d.%d.%d", | |
a8105c1b VB |
357 | version[0], version[1], |
358 | version[2], version[3]) == -1) { | |
43c02e7b VB |
359 | LLOG_WARN("unable to allocate memory for " |
360 | "chassis description"); | |
361 | goto malformed; | |
362 | } | |
363 | break; | |
364 | case EDP_TLV_DISPLAY: | |
a8105c1b | 365 | if ((chassis->c_name = (char *)calloc(1, tlv_len + 1)) == NULL) { |
43c02e7b VB |
366 | LLOG_WARN("unable to allocate memory for chassis " |
367 | "name"); | |
368 | goto malformed; | |
369 | } | |
370 | /* TLV display contains a lot of garbage */ | |
a8105c1b | 371 | PEEK_BYTES(chassis->c_name, tlv_len); |
43c02e7b VB |
372 | break; |
373 | case EDP_TLV_NULL: | |
a8105c1b | 374 | if (tlv_len != 0) { |
43c02e7b VB |
375 | LLOG_WARNX("null tlv with incorrect size in frame " |
376 | "received on %s", | |
377 | hardware->h_ifname); | |
378 | goto malformed; | |
379 | } | |
a8105c1b | 380 | if (length) |
43c02e7b VB |
381 | LLOG_DEBUG("extra data after edp frame on %s", |
382 | hardware->h_ifname); | |
383 | gotend = 1; | |
384 | break; | |
385 | case EDP_TLV_VLAN: | |
a1347cd8 | 386 | #ifdef ENABLE_DOT1 |
a8105c1b | 387 | CHECK_TLV_SIZE(12, "VLAN"); |
43c02e7b VB |
388 | if ((lvlan = (struct lldpd_vlan *)calloc(1, |
389 | sizeof(struct lldpd_vlan))) == NULL) { | |
390 | LLOG_WARN("unable to allocate vlan"); | |
391 | goto malformed; | |
392 | } | |
a8105c1b VB |
393 | PEEK_DISCARD_UINT16; /* Flags + reserved */ |
394 | lvlan->v_vid = PEEK_UINT16; /* VID */ | |
395 | PEEK_DISCARD(4); /* Reserved */ | |
396 | PEEK_BYTES(&address, sizeof(address)); | |
397 | ||
398 | if ((lvlan->v_name = (char *)calloc(1, | |
399 | tlv_len + 1 - 12)) == NULL) { | |
43c02e7b | 400 | LLOG_WARN("unable to allocate vlan name"); |
a8105c1b | 401 | free(lvlan); |
43c02e7b VB |
402 | goto malformed; |
403 | } | |
a8105c1b VB |
404 | PEEK_BYTES(lvlan->v_name, tlv_len - 12); |
405 | ||
406 | if (address.s_addr != INADDR_ANY) { | |
43c02e7b | 407 | if (chassis->c_mgmt.s_addr == INADDR_ANY) |
a8105c1b | 408 | chassis->c_mgmt.s_addr = address.s_addr; |
43c02e7b VB |
409 | else |
410 | /* We need to guess the good one */ | |
411 | if (cfg->g_mgmt_pattern != NULL) { | |
412 | /* We can try to use this to prefer an address */ | |
413 | char *ip; | |
a8105c1b | 414 | ip = inet_ntoa(address); |
43c02e7b VB |
415 | if (fnmatch(cfg->g_mgmt_pattern, |
416 | ip, 0) == 0) | |
a8105c1b | 417 | chassis->c_mgmt.s_addr = address.s_addr; |
43c02e7b VB |
418 | } |
419 | } | |
420 | TAILQ_INSERT_TAIL(&port->p_vlans, | |
421 | lvlan, v_entries); | |
a1347cd8 | 422 | #endif |
43c02e7b VB |
423 | gotvlans = 1; |
424 | break; | |
425 | default: | |
426 | LLOG_DEBUG("unknown EDP TLV type (%d) received on %s", | |
a8105c1b | 427 | tlv_type, hardware->h_ifname); |
37387046 | 428 | hardware->h_rx_unrecognized_cnt++; |
43c02e7b | 429 | } |
a8105c1b | 430 | PEEK_DISCARD(tlv + tlv_len - pos); |
43c02e7b VB |
431 | } |
432 | if ((chassis->c_id == NULL) || | |
433 | (port->p_id == NULL) || | |
434 | (chassis->c_name == NULL) || | |
435 | (chassis->c_descr == NULL) || | |
436 | (port->p_descr == NULL) || | |
437 | (gotend == 0)) { | |
a1347cd8 | 438 | #ifdef ENABLE_DOT1 |
43c02e7b VB |
439 | if (gotvlans && gotend) { |
440 | /* VLAN can be sent in a separate frames. We need to add | |
441 | * those vlans to an existing chassis */ | |
442 | if (hardware->h_rchassis && | |
443 | (hardware->h_rchassis->c_id_subtype == chassis->c_id_subtype) && | |
444 | (hardware->h_rchassis->c_id_len == chassis->c_id_len) && | |
445 | (memcmp(hardware->h_rchassis->c_id, chassis->c_id, | |
446 | chassis->c_id_len) == 0)) { | |
447 | /* We attach the VLANs to current hardware */ | |
448 | lldpd_vlan_cleanup(hardware->h_rport); | |
449 | for (lvlan = TAILQ_FIRST(&port->p_vlans); | |
450 | lvlan != NULL; | |
451 | lvlan = lvlan_next) { | |
452 | lvlan_next = TAILQ_NEXT(lvlan, v_entries); | |
453 | TAILQ_REMOVE(&port->p_vlans, lvlan, v_entries); | |
454 | TAILQ_INSERT_TAIL(&hardware->h_rport->p_vlans, | |
455 | lvlan, v_entries); | |
456 | } | |
457 | /* And the IP address */ | |
458 | hardware->h_rchassis->c_mgmt.s_addr = | |
459 | chassis->c_mgmt.s_addr; | |
460 | } | |
461 | /* We discard the remaining frame */ | |
462 | goto malformed; | |
463 | } | |
a1347cd8 VB |
464 | #else |
465 | if (gotvlans) | |
466 | goto malformed; | |
467 | #endif | |
43c02e7b VB |
468 | LLOG_WARNX("some mandatory tlv are missing for frame received on %s", |
469 | hardware->h_ifname); | |
470 | goto malformed; | |
471 | } | |
472 | *newchassis = chassis; | |
473 | *newport = port; | |
474 | return 1; | |
475 | ||
476 | malformed: | |
d3322e23 | 477 | lldpd_chassis_cleanup(chassis); |
a0edeaf8 | 478 | lldpd_port_cleanup(port, 1); |
43c02e7b VB |
479 | return -1; |
480 | } | |
4bad1937 VB |
481 | |
482 | #endif /* ENABLE_EDP */ |