The Assimilation Project
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
cdp_min.c
Go to the documentation of this file.
1 
25 #include <stdio.h>
26 
27 #ifdef _MSC_VER
28 # include <winsock.h>
29 #else
30 # include <netinet/in.h>
31 #endif
32 
33 #include <cdp.h>
34 #include <tlvhelper.h>
59 #define CDP_OVERHEAD 22
61 #define CDP_VERSSZ 1
63 #define CDP_TTLSZ 1
65 #define CDP_CKSUMSZ 2
67 #define CDPINITHDRSZ (CDP_OVERHEAD+CDP_VERSSZ+CDP_TTLSZ+CDP_CKSUMSZ) /* 26 */
69 
77 #define CDPTLV_TYPESZ 2
79 #define CDPTLV_LENSZ 2
81 #define CDPTLV_TYPELENSZ (CDPTLV_TYPESZ+CDPTLV_LENSZ) /* 4 */
83 
85 
92 WINEXPORT gboolean
93 is_valid_cdp_packet(const void* packet,
94  const void* pktend)
95 {
96  const unsigned reqtypes [] = {1}; // The set of required initial TLV types
97  // The LLDP list is slighly more impressive ;-)
98  unsigned j = 0;
99  const void* tlv_vp; // Pointer to a TLV entry in the CDP packet.
100  const void* next = NULL;
101  unsigned vers;
102 
103 
104  if ((const void *)((const unsigned char *)packet+CDPTLV_TYPELENSZ) > pktend || packet == NULL) {
105  fprintf(stderr, "BAD1 packet: %p, pktend: %p\n", packet, pktend);
106  return FALSE;
107  }
108  /* Heuristic - at this writing, version could be 1 or 2 - Cisco currently defaults to 2 ... */
109  if ((vers=get_cdp_vers(packet, pktend)) < 1 || vers > 4
110  || get_cdp_ttl(packet, pktend) < 3) {
111  /*fprintf(stderr, "BAD2 packet: %p, pktend: %p\n", packet, pktend);*/
112  return FALSE;
113  }
114 
115  for (tlv_vp = get_cdptlv_first(packet, pktend)
116  ; NULL != tlv_vp && tlv_vp < pktend
117  ; tlv_vp = next) {
118  unsigned ttype;
119  unsigned length;
120 
121  if ((const void *)((const unsigned char *)tlv_vp+CDPTLV_TYPELENSZ) > pktend) {
122  return FALSE;
123  }
124  ttype = get_cdptlv_type(tlv_vp, pktend);
125  length = get_cdptlv_len (tlv_vp, pktend);
126  next = (const void *)((const unsigned char *)tlv_vp + length);
127  if (next > pktend
128  || length < CDPTLV_TYPELENSZ
129  || (j < DIMOF(reqtypes) && ttype != reqtypes[j])) {
130  /*fprintf(stderr, "BAD3 packet: %p, pktend: %p\n", packet, pktend);*/
131  return FALSE;
132  }
133  j += 1;
134  }
135  // The only way to exit that loop without returning FALSE is if tlp_vp == pktend
136  return TRUE;
137 }
138 
141 WINEXPORT guint8
142 get_cdp_vers(const void* pktptr,
143  const void* pktend)
144 {
145  const unsigned char * pkt_uc = pktptr;
146  return tlv_get_guint8(pkt_uc+CDP_OVERHEAD, pktend);
147 }
148 
152 WINEXPORT guint8
153 get_cdp_ttl(const void* pktptr,
154  const void* pktend)
155 {
156  const unsigned char * pkt_uc = pktptr;
157  return tlv_get_guint8(pkt_uc+CDP_OVERHEAD+1, pktend);
158 }
162 WINEXPORT guint16
163 get_cdp_cksum(const void* pktptr,
164  const void* pktend)
165 {
166  const unsigned char * pkt_uc = pktptr;
167  return tlv_get_guint16(pkt_uc+CDP_OVERHEAD+2, pktend);
168 }
169 
172 WINEXPORT guint16
173 get_cdptlv_type(const void* tlv_vp,
174  const void* pktend)
176 {
177  return tlv_get_guint16(tlv_vp, pktend);
178 }
179 
182 WINEXPORT gsize
183 get_cdptlv_len(const void* tlv_vp,
184  const void* pktend)
186 {
187  const unsigned char* tlv_uc = tlv_vp;
188  return tlv_get_guint16(tlv_uc+2, pktend);
189 }
193 WINEXPORT gsize
194 get_cdptlv_vlen(const void* tlv_vp,
195  const void* pktend)
197 {
198  return (unsigned)(get_cdptlv_len(tlv_vp, pktend) - CDPTLV_TYPELENSZ);
199 }
200 
205 WINEXPORT const void *
206 get_cdptlv_body(const void* tlv_vp,
207  const void* pktend)
209 {
210  g_return_val_if_fail(tlv_vp < pktend, NULL);
211  return (const void*)((const unsigned char *)tlv_vp + CDPTLV_TYPELENSZ);
212 }
216 WINEXPORT const void *
217 get_cdptlv_first(const void* pkt,
218  const void* pktend)
219 {
220  gsize len = (const char *)pktend - (const char *)pkt;
221  const unsigned char* ret = (const unsigned char*)pkt;
222  unsigned vers;
223  if (ret == NULL || len < (CDPINITHDRSZ + CDPTLV_TYPELENSZ)
224  /* Note that these version and ttl constraints are heuristics, not absolutes */
225  || (vers=get_cdp_vers(ret, pktend)) < 1 || vers > 5
226  || get_cdp_ttl(ret, pktend) < 2) {
227  return NULL;
228  }
229  ret += CDPINITHDRSZ;
230  if ((ret + get_cdptlv_len(ret, pktend)) > (const unsigned char *)pktend) {
231  return NULL;
232  }
233  return (const void *)ret;
234 }
238 WINEXPORT const void *
239 get_cdptlv_next(const void* tlv_vp,
240  const void* tlv_vpend)
241 {
242  const unsigned char* nexttlv;
243  const unsigned char* nextend;
244  if (tlv_vp == NULL) {
245  return NULL;
246  }
247  nexttlv = (const unsigned char*)tlv_vp + get_cdptlv_len(tlv_vp, tlv_vpend);
248  if ((const void *)(nexttlv + CDPTLV_TYPELENSZ) > tlv_vpend) {
249  // In an ideal world nexttlv would exactly equal tlv_vpend...
250  return NULL;
251  }
252  /* Watch out for malformed packets! (BLACKHAT, PARANOIA) */
253  nextend = nexttlv + get_cdptlv_len(nexttlv, tlv_vpend);
254  return ((const void *)nextend > tlv_vpend) ? NULL : nexttlv;
255 }
256 
257 
260 WINEXPORT const void*
261 get_cdp_chassis_id(gconstpointer packet,
262  gssize* idlength,
263  gconstpointer pktend)
264 {
265  const void * tlv_vp;
266  for (tlv_vp=get_cdptlv_first(packet, pktend);
267  tlv_vp != NULL;
268  tlv_vp = get_cdptlv_next(tlv_vp, pktend)) {
269  if (get_cdptlv_type(tlv_vp, pktend) == CDP_TLV_DEVID) {
270  *idlength = get_cdptlv_vlen(tlv_vp, pktend);
271  return get_cdptlv_body(tlv_vp, pktend);
272  }
273  tlv_vp = get_cdptlv_next(tlv_vp, pktend);
274  }
275  return NULL;
276 }
277 
278 
281 WINEXPORT const void*
282 get_cdp_port_id(gconstpointer packet,
283  gssize* idlength,
284  gconstpointer pktend)
285 {
286  const void * tlv_vp;
287  for (tlv_vp=get_cdptlv_first(packet, pktend);
288  tlv_vp != NULL;
289  tlv_vp = get_cdptlv_next(tlv_vp, pktend)) {
290  if (get_cdptlv_type(tlv_vp, pktend) == CDP_TLV_PORTID) {
291  *idlength = get_cdptlv_vlen(tlv_vp, pktend);
292  return get_cdptlv_body(tlv_vp, pktend);
293  }
294  tlv_vp = get_cdptlv_next(tlv_vp, pktend);
295  }
296  return NULL;
297 }
WINEXPORT const void * get_cdptlv_next(const void *tlv_vp, const void *tlv_vpend)
Locate the next CDP TLV triple (iterator).
Definition: cdp_min.c:239
#define CDPTLV_TYPELENSZ
Overhead - offset to the beginning of the CDP TLV Value.
Definition: cdp_min.c:82
WINEXPORT guint16 get_cdptlv_type(const void *tlv_vp, const void *pktend)
Return type from the given TLV triplet in a CDP packet.
Definition: cdp_min.c:173
WINEXPORT guint8 get_cdp_ttl(const void *pktptr, const void *pktend)
Return the time to live for this CDP packet.
Definition: cdp_min.c:153
WINEXPORT guint16 get_cdp_cksum(const void *pktptr, const void *pktend)
Return the 16-bit checksum for this CDP packet.
Definition: cdp_min.c:163
WINEXPORT gsize get_cdptlv_vlen(const void *tlv_vp, const void *pktend)
Return length of the value blob int a given TLV triplet in a CDP packet - value size only...
Definition: cdp_min.c:194
#define CDP_TLV_PORTID
The port from which the CDP update has been sent.
Definition: cdp.h:36
WINEXPORT gboolean is_valid_cdp_packet(const void *packet, const void *pktend)
Check to see if this is a valid CDP packet.
Definition: cdp_min.c:93
guint8 tlv_get_guint8(const void *vitem, const void *bufend)
Retrieve an unsigned 8 bit integer from the given location with error checking.
Definition: tlvhelper.c:30
WINEXPORT const void * get_cdp_port_id(gconstpointer packet, gssize *idlength, gconstpointer pktend)
get the port ID associated with this CDP packet
Definition: cdp_min.c:282
WINEXPORT const void * get_cdptlv_first(const void *pkt, const void *pktend)
Return the first CDP TLV triple in a CDP packet.
Definition: cdp_min.c:217
#define WINEXPORT
Definition: projectcommon.h:45
WINEXPORT gsize get_cdptlv_len(const void *tlv_vp, const void *pktend)
Return size of the given TLV triplet.
Definition: cdp_min.c:183
WINEXPORT const void * get_cdp_chassis_id(gconstpointer packet, gssize *idlength, gconstpointer pktend)
Get the chassis ID associated with this CDP packet.
Definition: cdp_min.c:261
#define CDP_TLV_DEVID
Hostname of the device or hardware serial number in ASCII.
Definition: cdp.h:33
#define DIMOF(a)
Definition: lldp_min.c:30
TLV helper interfaces definitions.
WINEXPORT guint8 get_cdp_vers(const void *pktptr, const void *pktend)
Return the CDP protocol version for this packet.
Definition: cdp_min.c:142
Header file for various basic CDP (Cisco Discovery Protocol definitions and accessor functions...
WINEXPORT const void * get_cdptlv_body(const void *tlv_vp, const void *pktend)
Return the body (value) blob of a CDP TLV triplet.
Definition: cdp_min.c:206
#define CDP_OVERHEAD
Number of bytes before the CDP packet itself starts.
Definition: cdp_min.c:60
guint16 tlv_get_guint16(const void *vitem, const void *bufend)
Retrieve an unsigned 16 bit integer from the given location with error checking and without caring ab...
Definition: tlvhelper.c:53
#define CDPINITHDRSZ
Start of the TLV (type, length, value) portion of a CDP packet.
Definition: cdp_min.c:68