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