summaryrefslogtreecommitdiff
path: root/src/libnet_build_lldp.c
blob: 14f011c71a5c00f310dc1f9197e1a1f429635033 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
#include "common.h"

LIBNET_API
libnet_ptag_t libnet_build_lldp_chassis(const uint8_t subtype,
const uint8_t *const value,const uint8_t value_s, libnet_t *l,
libnet_ptag_t ptag)
{
  assert(value != NULL && "Chassis ID string cannot be a NULL");
  assert((value_s != 0) && "Chassis ID string length must be greater or equal to 1");
  assert(LIBNET_LLDP_TLV_HDR_SIZE == 0x02 && "TLV header size must be a 2 bytes");
  assert(LIBNET_LLDP_SUBTYPE_SIZE == 0x01 && "Subtype field size must be 1 byte");

  uint32_t n, h;
  libnet_pblock_t *p;
  struct libnet_lldp_hdr hdr;
  memset(&hdr, 0, sizeof(struct libnet_lldp_hdr));

  if (l == NULL)
  {
    return (-1);
  }

  if(value == NULL)
  {
    snprintf(l->err_buf, LIBNET_ERRBUF_SIZE,
    "%s(): Chassis ID string is NULL", __func__);
    return (-1);
  }

  if(value_s == 0)
  {
      snprintf(l->err_buf, LIBNET_ERRBUF_SIZE,
      "%s(): Incorrect Chassis ID string length", __func__);
      return (-1);
  }

  /* size of memory block */
  n = h =  LIBNET_LLDP_TLV_HDR_SIZE + /* TLV Header size */
           LIBNET_LLDP_SUBTYPE_SIZE + /* Chassis ID subtype size */
           value_s;                   /* Chassis ID string length */

  LIBNET_LLDP_TLV_SET_TYPE(hdr.tlv_info, LIBNET_LLDP_CHASSIS_ID);
  LIBNET_LLDP_TLV_SET_LEN(hdr.tlv_info, value_s + LIBNET_LLDP_SUBTYPE_SIZE);

  /*
   *  Find the existing protocol block if a ptag is specified, or create
   *  a new one.
   */
  p = libnet_pblock_probe(l, ptag, n, LIBNET_PBLOCK_LLDP_CHASSIS_H);
  if (p == NULL)
  {
    return (-1);
  }

  const uint16_t type_and_len = htons(hdr.tlv_info);
  if (libnet_pblock_append(l, p, &type_and_len, sizeof(type_and_len)) == -1)
  {
    goto bad;
  }

  if (libnet_pblock_append(l, p, &subtype, sizeof(subtype)) == -1)
  {
    goto bad;
  }

  if (libnet_pblock_append(l, p, value, value_s) == -1)
  {
    goto bad;
  }

  return (ptag ? ptag
               : libnet_pblock_update(l, p, h, LIBNET_PBLOCK_LLDP_CHASSIS_H));
bad:
  libnet_pblock_delete(l, p);
  return (-1);
}

/**
 * Local Variables:
 *  indent-tabs-mode: nil
 *  c-file-style: "stroustrup"
 * End:
 */