lldp_tlv.c
Go to the documentation of this file.
1 /**
2  * @file lldp_tlv.c
3  * @brief TLV parsing and formatting
4  *
5  * @section License
6  *
7  * SPDX-License-Identifier: GPL-2.0-or-later
8  *
9  * Copyright (C) 2010-2024 Oryx Embedded SARL. All rights reserved.
10  *
11  * This file is part of CycloneTCP Open.
12  *
13  * This program is free software; you can redistribute it and/or
14  * modify it under the terms of the GNU General Public License
15  * as published by the Free Software Foundation; either version 2
16  * of the License, or (at your option) any later version.
17  *
18  * This program is distributed in the hope that it will be useful,
19  * but WITHOUT ANY WARRANTY; without even the implied warranty of
20  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21  * GNU General Public License for more details.
22  *
23  * You should have received a copy of the GNU General Public License
24  * along with this program; if not, write to the Free Software Foundation,
25  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
26  *
27  * @author Oryx Embedded SARL (www.oryx-embedded.com)
28  * @version 2.4.0
29  **/
30 
31 //Switch to the appropriate trace level
32 #define TRACE_LEVEL LLDP_TRACE_LEVEL
33 
34 //Dependencies
35 #include "core/net.h"
36 #include "lldp/lldp.h"
37 #include "lldp/lldp_tlv.h"
38 #include "lldp/lldp_debug.h"
39 #include "debug.h"
40 
41 //Check TCP/IP stack configuration
42 #if (LLDP_SUPPORT == ENABLED)
43 
44 
45 /**
46  * @brief Add or replace a TLV
47  * @param[in] lldpdu Pointer to the LLDP data unit
48  * @param[in] type TLV type
49  * @param[in] index TLV occurrence index
50  * @param[in] value TLV information string
51  * @param[in] length Length of the information string, in bytes
52  * @param[in] replace Replace the existing TLV if a match is found
53  * @return Error code
54  **/
55 
56 error_t lldpSetTlv(LldpDataUnit *lldpdu, uint8_t type, uint_t index,
57  const uint8_t *value, size_t length, bool_t replace)
58 {
59  error_t error;
60  uint_t k;
61  size_t oldLen;
62  size_t newLen;
63  LldpTlv tlv;
64  LldpTlvHeader *header;
65 
66  //Initialize occurrence index
67  k = 0;
68 
69  //Extract the first TLV
70  error = lldpGetFirstTlv(lldpdu, &tlv);
71 
72  //Parse the LLDP data unit
73  while(!error)
74  {
75  //Check TLV type
76  if(tlv.type == type)
77  {
78  //Matching occurrence found?
79  if(k++ == index)
80  {
81  //Insert a new TLV or replace the existing TLV
82  break;
83  }
84  }
85  else if(tlv.type > type)
86  {
87  //Insert a new TLV
88  replace = FALSE;
89  break;
90  }
91  else
92  {
93  //Just for sanity
94  }
95 
96  //Extract the next TLV
97  error = lldpGetNextTlv(lldpdu, &tlv);
98  }
99 
100  //The End Of LLDPDU TLV marks the end of the LLDPDU
101  if(error == ERROR_END_OF_STREAM)
102  {
103  //Insert a new TLV
104  replace = FALSE;
105  //Continue processing
106  error = NO_ERROR;
107  }
108 
109  //Check status code
110  if(!error)
111  {
112  //Check whether the current TLV should be replaced
113  if(replace)
114  {
115  //Calculate the length of the existing TLV
116  oldLen = sizeof(LldpTlvHeader) + tlv.length;
117  //Calculate the length of the new TLV
118  newLen = sizeof(LldpTlvHeader) + length;
119 
120  //Ensure that the TLVs do not exceed the maximum length allowed for
121  //the LLDPDU
122  if((lldpdu->length - oldLen + newLen) <= LLDP_MAX_LLDPDU_SIZE)
123  {
124  //Make room for the new TLV
125  if(newLen != oldLen)
126  {
127  osMemmove(lldpdu->data + tlv.pos + newLen, lldpdu->data + tlv.pos + oldLen,
128  lldpdu->length - tlv.pos - oldLen);
129  }
130 
131  //Adjust the length of the LLDPDU
132  lldpdu->length -= oldLen;
133  }
134  else
135  {
136  //Report an error
137  error = ERROR_BUFFER_OVERFLOW;
138  }
139  }
140  else
141  {
142  //Calculate the length of the new TLV
143  newLen = sizeof(LldpTlvHeader) + length;
144 
145  //Ensure that the TLVs do not exceed the maximum length allowed for
146  //the LLDPDU
147  if((lldpdu->length + newLen) <= LLDP_MAX_LLDPDU_SIZE)
148  {
149  //Make room for the new TLV
150  if(tlv.pos < lldpdu->length)
151  {
152  osMemmove(lldpdu->data + tlv.pos + newLen, lldpdu->data + tlv.pos,
153  lldpdu->length - tlv.pos);
154  }
155  }
156  else
157  {
158  //Report an error
159  error = ERROR_BUFFER_OVERFLOW;
160  }
161  }
162  }
163 
164  //Check status code
165  if(!error)
166  {
167  //Point to the buffer where to format the new TLV
168  header = (LldpTlvHeader *) (lldpdu->data + tlv.pos);
169 
170  //Format TLV header
171  header->type = type;
172  header->lengthH = (length >> 8) & 0x01;
173  header->lengthL = length & 0xFF;
174 
175  //Copy the TLV information string
176  if(length > 0)
177  {
178  osMemcpy(header->value, value, length);
179  }
180 
181  //Adjust the length of the LLDPDU
182  lldpdu->length += sizeof(LldpTlvHeader) + length;
183  }
184 
185  //Return status code
186  return error;
187 }
188 
189 
190 /**
191  * @brief Search a LLDPDU for a given TLV
192  * @param[in] lldpdu Pointer to the LLDP data unit
193  * @param[in] type TLV type
194  * @param[in] index TLV occurrence index
195  * @param[out] value TLV information string
196  * @param[out] length Length of the information string, in bytes
197  * @return Error code
198  **/
199 
200 error_t lldpGetTlv(LldpDataUnit *lldpdu, uint8_t type, uint_t index,
201  const uint8_t **value, size_t *length)
202 {
203  error_t error;
204  uint_t k;
205  LldpTlv tlv;
206 
207  //Initialize occurrence index
208  k = 0;
209 
210  //Extract the first TLV
211  error = lldpGetFirstTlv(lldpdu, &tlv);
212 
213  //Parse the LLDP data unit
214  while(!error)
215  {
216  //Check TLV type
217  if(tlv.type == type)
218  {
219  //Matching occurrence found?
220  if(k++ == index)
221  {
222  //The specified TLV has been found
223  *value = tlv.value;
224  *length = tlv.length;
225 
226  //We are done
227  break;
228  }
229  }
230 
231  //Extract the next TLV
232  error = lldpGetNextTlv(lldpdu, &tlv);
233  }
234 
235  //Return status code
236  return error ? ERROR_NOT_FOUND : NO_ERROR;
237 }
238 
239 
240 /**
241  * @brief Extract the first TLV from an LLDPDU
242  * @param[in] lldpdu Pointer to the LLDP data unit
243  * @param[out] tlv Next TLV
244  * @return Error code
245  **/
246 
248 {
249  //Rewind to the beginning of the LLDPDU
250  lldpdu->pos = 0;
251 
252  //Extract the first TLV
253  return lldpGetNextTlv(lldpdu, tlv);
254 }
255 
256 
257 /**
258  * @brief Extract the next TLV from an LLDPDU
259  * @param[in] lldpdu Pointer to the LLDP data unit
260  * @param[out] tlv Next TLV
261  * @return Error code
262  **/
263 
265 {
266  size_t n;
267  LldpTlvHeader *header;
268 
269  //Initialize TLV
270  tlv->pos = lldpdu->pos;
271  tlv->type = 0;
272  tlv->value = 0;
273  tlv->length = 0;
274 
275  //End of LLDPDU detected?
276  if(lldpdu->pos >= lldpdu->length)
277  return ERROR_END_OF_STREAM;
278 
279  //Check whether the TLV extends past the physical end of the frame
280  if((lldpdu->pos + sizeof(LldpTlvHeader)) > lldpdu->length)
281  return ERROR_INVALID_SYNTAX;
282 
283  //Point to the current TLV
284  header = (LldpTlvHeader *) (lldpdu->data + lldpdu->pos);
285 
286  //The least significant bit in the first octet of the TLV format is the
287  //most significant bit of the TLV information string length field
288  n = (header->lengthH << 8) | header->lengthL;
289 
290  //Check TLV length
291  if((lldpdu->pos + sizeof(LldpTlvHeader) + n) > lldpdu->length)
292  return ERROR_INVALID_SYNTAX;
293 
294  //The End Of LLDPDU TLV marks the end of the LLDPDU
295  if(header->type == LLDP_TLV_TYPE_END_OF_LLDPDU)
296  return ERROR_END_OF_STREAM;
297 
298  //Extract TLV parameters
299  tlv->pos = lldpdu->pos;
300  tlv->type = header->type;
301  tlv->value = header->value;
302  tlv->length = n;
303 
304  //Save the position of the next TLV
305  lldpdu->pos += sizeof(LldpTlvHeader) + n;
306 
307  //Successful processing
308  return NO_ERROR;
309 }
310 
311 
312 /**
313  * @brief Remove a TLV from a LLDPDU
314  * @param[in] lldpdu Pointer to the LLDP data unit
315  * @param[in] type TLV type
316  * @param[in] index TLV occurrence index
317  * @return Error code
318  **/
319 
320 error_t lldpDeleteTlv(LldpDataUnit *lldpdu, uint8_t type, uint_t index)
321 {
322  error_t error;
323  uint_t k;
324  LldpTlv tlv;
325 
326  //Initialize occurrence index
327  k = 0;
328 
329  //Extract the first TLV
330  error = lldpGetFirstTlv(lldpdu, &tlv);
331 
332  //Parse the LLDP data unit
333  while(!error)
334  {
335  //Check TLV type
336  if(tlv.type == type)
337  {
338  //Matching occurrence found?
339  if(k++ == index)
340  {
341  //Remove the current TLV
342  osMemmove(lldpdu->data + tlv.pos, lldpdu->data + lldpdu->pos,
343  lldpdu->length - lldpdu->pos);
344 
345  //Adjust the length of the LLDPDU
346  lldpdu->length -= tlv.length;
347 
348  //The specified TLV has been deleted
349  error = NO_ERROR;
350 
351  //We are done
352  break;
353  }
354  }
355 
356  //Extract the next TLV
357  error = lldpGetNextTlv(lldpdu, &tlv);
358  }
359 
360  //The End Of LLDPDU TLV marks the end of the LLDPDU
361  if(error == ERROR_END_OF_STREAM)
362  {
363  error = ERROR_NOT_FOUND;
364  }
365 
366  //Return status code
367  return error;
368 }
369 
370 
371 /**
372  * @brief Decode the contents of a Management Address TLV
373  * @param[in] value Pointer to the TLV value to decode
374  * @param[in] length Length of the TLV value, in bytes
375  * @param[out] mgmtAddr1 First part of the Management Address TLV
376  * @param[out] mgmtAddr2 Second part of the Management Address TLV
377  * @return Error code
378  **/
379 
380 error_t lldpDecodeMgmtAddrTlv(const uint8_t *value, size_t length,
381  const LldpMgmtAddrTlv1 **mgmtAddr1, const LldpMgmtAddrTlv2 **mgmtAddr2)
382 {
383  LldpMgmtAddrTlv1 *part1;
384  LldpMgmtAddrTlv2 *part2;
385 
386  //Malformed TLV?
387  if(length < sizeof(LldpMgmtAddrTlv1))
388  return ERROR_INVALID_SYNTAX;
389 
390  //Point to the first part of the Management Address TLV
391  part1 = (LldpMgmtAddrTlv1 *) value;
392 
393  //Check the length of the management address
394  if(part1->mgmtAddrLen < LLDP_MIN_MGMT_ADDR_LEN ||
395  part1->mgmtAddrLen > LLDP_MAX_MGMT_ADDR_LEN)
396  {
397  return ERROR_INVALID_SYNTAX;
398  }
399 
400  //Malformed TLV?
401  if((sizeof(LldpMgmtAddrTlv1) + sizeof(LldpMgmtAddrTlv2) +
402  part1->mgmtAddrLen - 1) > length)
403  {
404  return ERROR_INVALID_SYNTAX;
405  }
406 
407  //Point to the second part of the Management Address TLV
408  part2 = (LldpMgmtAddrTlv2 *) (part1->mgmtAddr + part1->mgmtAddrLen - 1);
409 
410  //Check the length of the OID
411  if(part2->oidLen > LLDP_MAX_OID_LEN)
412  {
413  return ERROR_INVALID_SYNTAX;
414  }
415 
416  //Malformed TLV?
417  if((sizeof(LldpMgmtAddrTlv1) + sizeof(LldpMgmtAddrTlv2) +
418  part1->mgmtAddrLen - 1 + part2->oidLen) > length)
419  {
420  return ERROR_INVALID_SYNTAX;
421  }
422 
423  //Return a pointer to the first part of the Management Address TLV
424  if(mgmtAddr1 != NULL)
425  {
426  *mgmtAddr1 = part1;
427  }
428 
429  //Return a pointer to the second part of the Management Address TLV
430  if(mgmtAddr2 != NULL)
431  {
432  *mgmtAddr2 = part2;
433  }
434 
435  //Successful processing
436  return NO_ERROR;
437 }
438 
439 
440 /**
441  * @brief Add or replace an organizationally specific TLV
442  * @param[in] lldpdu Pointer to the LLDP data unit
443  * @param[in] oui Organizationally unique identifier
444  * @param[in] subtype Organizationally defined subtype
445  * @param[in] index TLV occurrence index
446  * @param[in] value Organizationally defined information string
447  * @param[in] length Length of the information string, in bytes
448  * @param[in] replace Replace the existing TLV if a match is found
449  * @return Error code
450  **/
451 
452 error_t lldpSetOrgDefTlv(LldpDataUnit *lldpdu, uint32_t oui, uint8_t subtype,
453  uint_t index, const uint8_t *value, size_t length, bool_t replace)
454 {
455  error_t error;
456  size_t k;
457  size_t n;
458  size_t oldLen;
459  size_t newLen;
460  LldpTlv tlv;
461  LldpTlvHeader *header;
462  LldpOrgDefTlv *orgDefTlv;
463 
464  //Initialize occurrence index
465  k = 0;
466 
467  //Extract the first TLV
468  error = lldpGetFirstTlv(lldpdu, &tlv);
469 
470  //Parse the LLDP data unit
471  while(!error)
472  {
473  //Check TLV type
475  {
476  //Malformed organizationally specific TLV?
477  if(tlv.length < sizeof(LldpOrgDefTlv))
478  {
479  error = ERROR_INVALID_SYNTAX;
480  break;
481  }
482 
483  //Point to the organizationally specific tag
484  orgDefTlv = (LldpOrgDefTlv *) tlv.value;
485 
486  //Check organizationally unique identifier
487  if(LOAD24BE(orgDefTlv->oui) == oui)
488  {
489  //Check TLV subtype
490  if(orgDefTlv->subtype == subtype)
491  {
492  //Matching occurrence found?
493  if(k++ == index)
494  {
495  //Insert a new TLV or replace the existing TLV
496  break;
497  }
498  }
499  else if(orgDefTlv->subtype > subtype)
500  {
501  //Insert a new TLV
502  replace = FALSE;
503  break;
504  }
505  else
506  {
507  //Just for sanity
508  }
509  }
510  else if(LOAD24BE(orgDefTlv->oui) > oui)
511  {
512  //Insert a new TLV
513  replace = FALSE;
514  break;
515  }
516  else
517  {
518  //Just for sanity
519  }
520  }
521  else if(tlv.type > LLDP_TLV_TYPE_ORG_DEFINED)
522  {
523  //Insert a new TLV
524  replace = FALSE;
525  break;
526  }
527  else
528  {
529  //Just for sanity
530  }
531 
532  //Extract the next TLV
533  error = lldpGetNextTlv(lldpdu, &tlv);
534  }
535 
536  //The End Of LLDPDU TLV marks the end of the LLDPDU
537  if(error == ERROR_END_OF_STREAM)
538  {
539  //Insert a new TLV
540  replace = FALSE;
541  //Continue processing
542  error = NO_ERROR;
543  }
544 
545  //Check status code
546  if(!error)
547  {
548  //Check whether the current TLV should be replaced
549  if(replace)
550  {
551  //Calculate the length of the existing TLV
552  oldLen = sizeof(LldpTlvHeader) + tlv.length;
553  //Calculate the length of the new TLV
554  newLen = sizeof(LldpTlvHeader) + sizeof(LldpOrgDefTlv) + length;
555 
556  //Ensure that the TLVs do not exceed the maximum length allowed for
557  //the LLDPDU
558  if((lldpdu->length - oldLen + newLen) <= LLDP_MAX_LLDPDU_SIZE)
559  {
560  //Make room for the new TLV
561  if(newLen != oldLen)
562  {
563  osMemmove(lldpdu->data + tlv.pos + newLen, lldpdu->data + tlv.pos + oldLen,
564  lldpdu->length - tlv.pos - oldLen);
565  }
566 
567  //Adjust the length of the LLDPDU
568  lldpdu->length -= oldLen;
569  }
570  else
571  {
572  //Report an error
573  error = ERROR_BUFFER_OVERFLOW;
574  }
575  }
576  else
577  {
578  //Calculate the length of the new TLV
579  newLen = sizeof(LldpTlvHeader) + sizeof(LldpOrgDefTlv) + length;
580 
581  //Ensure that the TLVs do not exceed the maximum length allowed for
582  //the LLDPDU
583  if((lldpdu->length + newLen) <= LLDP_MAX_LLDPDU_SIZE)
584  {
585  //Make room for the new TLV
586  if(tlv.pos < lldpdu->length)
587  {
588  osMemmove(lldpdu->data + tlv.pos + newLen, lldpdu->data + tlv.pos,
589  lldpdu->length - tlv.pos);
590  }
591  }
592  else
593  {
594  //Report an error
595  error = ERROR_BUFFER_OVERFLOW;
596  }
597  }
598  }
599 
600  //Check status code
601  if(!error)
602  {
603  //Calculate the length of the TLV value field
604  n = sizeof(LldpOrgDefTlv) + length;
605 
606  //Point to the buffer where to format the new TLV
607  header = (LldpTlvHeader *) (lldpdu->data + tlv.pos);
608 
609  //Format TLV header
610  header->type = LLDP_TLV_TYPE_ORG_DEFINED;
611  header->lengthH = (n >> 8) & 0x01;
612  header->lengthL = n & 0xFF;
613 
614  //Point to the organizationally specific TLV header
615  orgDefTlv = (LldpOrgDefTlv *) header->value;
616 
617  //The organizationally unique identifier field shall contain the
618  //organization's OUI
619  STORE24BE(oui, orgDefTlv->oui);
620 
621  //The organizationally defined subtype field shall contain a unique
622  //subtype value assigned by the defining organization
623  orgDefTlv->subtype = subtype;
624 
625  //Copy the organizationally defined information string
626  if(length > 0)
627  {
628  osMemcpy(orgDefTlv->value, value, length);
629  }
630 
631  //Adjust the length of the LLDPDU
632  lldpdu->length += sizeof(LldpTlvHeader) + n;
633  }
634 
635  //Return status code
636  return error;
637 }
638 
639 
640 /**
641  * @brief Search an LLDPDU for an organizationally specific TLV
642  * @param[in] lldpdu Pointer to the LLDP data unit
643  * @param[in] oui Organizationally unique identifier
644  * @param[in] subtype Organizationally defined subtype
645  * @param[in] index TLV occurrence index
646  * @param[out] value Organizationally defined information string
647  * @param[out] length Length of the information string, in bytes
648  * @return Error code
649  **/
650 
651 error_t lldpGetOrgDefTlv(LldpDataUnit *lldpdu, uint32_t oui, uint8_t subtype,
652  uint_t index, const uint8_t **value, size_t *length)
653 {
654  error_t error;
655  uint_t k;
656  LldpTlv tlv;
657  const LldpOrgDefTlv *orgDefTlv;
658 
659  //Initialize occurrence index
660  k = 0;
661 
662  //Extract the first TLV
663  error = lldpGetFirstTlv(lldpdu, &tlv);
664 
665  //Parse the LLDP data unit
666  while(!error)
667  {
668  //Check TLV type
670  {
671  //Malformed TLV?
672  if(tlv.length < sizeof(LldpOrgDefTlv))
673  {
674  error = ERROR_INVALID_SYNTAX;
675  break;
676  }
677 
678  //Point to the organizationally specific information
679  orgDefTlv = (const LldpOrgDefTlv *) tlv.value;
680 
681  //Check organizationally unique identifier
682  if(LOAD24BE(orgDefTlv->oui) == oui)
683  {
684  //Check TLV subtype
685  if(orgDefTlv->subtype == subtype)
686  {
687  //Matching occurrence found?
688  if(k++ == index)
689  {
690  //The specified TLV has been found
691  *value = tlv.value + sizeof(LldpOrgDefTlv);
692  *length = tlv.length - sizeof(LldpOrgDefTlv);
693 
694  //We are done
695  break;
696  }
697  }
698  }
699  }
700 
701  //Extract the next TLV
702  error = lldpGetNextTlv(lldpdu, &tlv);
703  }
704 
705  //Return status code
706  return error ? ERROR_NOT_FOUND : NO_ERROR;
707 }
708 
709 
710 /**
711  * @brief Remove an organizationally specific TLV from a LLDPDU
712  * @param[in] lldpdu Pointer to the LLDP data unit
713  * @param[in] oui Organizationally unique identifier
714  * @param[in] subtype Organizationally defined subtype
715  * @param[in] index TLV occurrence index
716  * @return Error code
717  **/
718 
719 error_t lldpDeleteOrgDefTlv(LldpDataUnit *lldpdu, uint32_t oui, uint8_t subtype,
720  uint_t index)
721 {
722  error_t error;
723  uint_t k;
724  LldpTlv tlv;
725  const LldpOrgDefTlv *orgDefTlv;
726 
727  //Initialize occurrence index
728  k = 0;
729 
730  //Extract the first TLV
731  error = lldpGetFirstTlv(lldpdu, &tlv);
732 
733  //Parse the LLDP data unit
734  while(!error)
735  {
736  //Check TLV type
738  {
739  //Malformed TLV?
740  if(tlv.length < sizeof(LldpOrgDefTlv))
741  {
742  error = ERROR_INVALID_SYNTAX;
743  break;
744  }
745 
746  //Point to the organizationally specific tag
747  orgDefTlv = (LldpOrgDefTlv *) tlv.value;
748 
749  //Check organizationally unique identifier
750  if(LOAD24BE(orgDefTlv->oui) == oui)
751  {
752  //Check TLV subtype
753  if(orgDefTlv->subtype == subtype)
754  {
755  //Matching occurrence found?
756  if(k++ == index)
757  {
758  //Remove the current TLV
759  osMemmove(lldpdu->data + tlv.pos, lldpdu->data + lldpdu->pos,
760  lldpdu->length - lldpdu->pos);
761 
762  //Adjust the length of the LLDPDU
763  lldpdu->length -= tlv.length;
764 
765  //We are done
766  break;
767  }
768  }
769  }
770  }
771 
772  //Extract the next TLV
773  error = lldpGetNextTlv(lldpdu, &tlv);
774  }
775 
776  //The End Of LLDPDU TLV marks the end of the LLDPDU
777  if(error == ERROR_END_OF_STREAM)
778  {
779  error = ERROR_NOT_FOUND;
780  }
781 
782  //Return status code
783  return error;
784 }
785 
786 #endif
uint8_t type
Definition: coap_common.h:176
unsigned int uint_t
Definition: compiler_port.h:50
int bool_t
Definition: compiler_port.h:53
#define STORE24BE(a, p)
Definition: cpu_endian.h:273
#define LOAD24BE(p)
Definition: cpu_endian.h:197
Debugging facilities.
uint8_t n
error_t
Error codes.
Definition: error.h:43
@ ERROR_NOT_FOUND
Definition: error.h:147
@ ERROR_END_OF_STREAM
Definition: error.h:210
@ ERROR_INVALID_SYNTAX
Definition: error.h:68
@ NO_ERROR
Success.
Definition: error.h:44
@ ERROR_BUFFER_OVERFLOW
Definition: error.h:142
LLDP (Link Layer Discovery Protocol)
#define LLDP_MAX_LLDPDU_SIZE
Definition: lldp.h:94
#define LldpDataUnit
Definition: lldp.h:36
Data logging functions for debugging purpose (LLDP)
error_t lldpGetNextTlv(LldpDataUnit *lldpdu, LldpTlv *tlv)
Extract the next TLV from an LLDPDU.
Definition: lldp_tlv.c:264
error_t lldpSetTlv(LldpDataUnit *lldpdu, uint8_t type, uint_t index, const uint8_t *value, size_t length, bool_t replace)
Add or replace a TLV.
Definition: lldp_tlv.c:56
error_t lldpDeleteTlv(LldpDataUnit *lldpdu, uint8_t type, uint_t index)
Remove a TLV from a LLDPDU.
Definition: lldp_tlv.c:320
error_t lldpGetTlv(LldpDataUnit *lldpdu, uint8_t type, uint_t index, const uint8_t **value, size_t *length)
Search a LLDPDU for a given TLV.
Definition: lldp_tlv.c:200
error_t lldpGetFirstTlv(LldpDataUnit *lldpdu, LldpTlv *tlv)
Extract the first TLV from an LLDPDU.
Definition: lldp_tlv.c:247
error_t lldpSetOrgDefTlv(LldpDataUnit *lldpdu, uint32_t oui, uint8_t subtype, uint_t index, const uint8_t *value, size_t length, bool_t replace)
Add or replace an organizationally specific TLV.
Definition: lldp_tlv.c:452
error_t lldpGetOrgDefTlv(LldpDataUnit *lldpdu, uint32_t oui, uint8_t subtype, uint_t index, const uint8_t **value, size_t *length)
Search an LLDPDU for an organizationally specific TLV.
Definition: lldp_tlv.c:651
error_t lldpDecodeMgmtAddrTlv(const uint8_t *value, size_t length, const LldpMgmtAddrTlv1 **mgmtAddr1, const LldpMgmtAddrTlv2 **mgmtAddr2)
Decode the contents of a Management Address TLV.
Definition: lldp_tlv.c:380
error_t lldpDeleteOrgDefTlv(LldpDataUnit *lldpdu, uint32_t oui, uint8_t subtype, uint_t index)
Remove an organizationally specific TLV from a LLDPDU.
Definition: lldp_tlv.c:719
TLV parsing and formatting.
LldpMgmtAddrTlv2
Definition: lldp_tlv.h:301
LldpOrgDefTlv
Definition: lldp_tlv.h:313
#define LLDP_MIN_MGMT_ADDR_LEN
Definition: lldp_tlv.h:72
LldpTlvHeader
Definition: lldp_tlv.h:233
uint8_t subtype
Definition: lldp_tlv.h:311
LldpMgmtAddrTlv1
Definition: lldp_tlv.h:288
#define LLDP_MAX_MGMT_ADDR_LEN
Definition: lldp_tlv.h:74
#define LLDP_MAX_OID_LEN
Definition: lldp_tlv.h:79
@ LLDP_TLV_TYPE_END_OF_LLDPDU
End Of LLDPDU.
Definition: lldp_tlv.h:93
@ LLDP_TLV_TYPE_ORG_DEFINED
Organizationally Specific TLVs.
Definition: lldp_tlv.h:102
TCP/IP stack core.
#define osMemmove(dest, src, length)
Definition: os_port.h:147
#define osMemcpy(dest, src, length)
Definition: os_port.h:141
#define FALSE
Definition: os_port.h:46
TLV structure.
Definition: lldp_tlv.h:200
uint8_t type
Definition: lldp_tlv.h:202
size_t pos
Definition: lldp_tlv.h:201
uint8_t * value
Definition: lldp_tlv.h:204
size_t length
Definition: lldp_tlv.h:203
uint8_t length
Definition: tcp.h:368
uint8_t value[]
Definition: tcp.h:369