2 * netsniff-ng - the packet sniffing beast
3 * Copyright 2012, 2013 Tobias Klauser <tklauser@distanz.ch>
4 * Subject to the GPL, version 2.
8 #include <arpa/inet.h> /* for inet_ntop() */
9 #include <netinet/in.h> /* for ntohs()/ntohl() */
17 #define EXTRACT_16BIT(x) ntohs(*((uint16_t *) (x)))
18 #define EXTRACT_32BIT(x) ntohl(*((uint32_t *) (x)))
20 #define LLDP_TLV_TYPE(tlv) (((tlv) & 0xFE00) >> 9)
21 #define LLDP_TLV_LENGTH(tlv) ((tlv) & 0x01FF)
26 #define LLDP_TLV_END 0
27 #define LLDP_TLV_CHASSIS_ID 1
28 #define LLDP_TLV_PORT_ID 2
29 #define LLDP_TLV_TTL 3
30 #define LLDP_TLV_PORT_DESC 4
31 #define LLDP_TLV_SYSTEM_NAME 5
32 #define LLDP_TLV_SYSTEM_DESC 6
33 #define LLDP_TLV_SYSTEM_CAP 7
34 #define LLDP_TLV_MGMT_ADDR 8
35 #define LLDP_TLV_ORG_SPECIFIC 127
40 #define LLDP_CHASSIS_SUBTYPE_CHASSIS 1
41 #define LLDP_CHASSIS_SUBTYPE_IF_ALIAS 2
42 #define LLDP_CHASSIS_SUBTYPE_PORT 3
43 #define LLDP_CHASSIS_SUBTYPE_MAC_ADDR 4
44 #define LLDP_CHASSIS_SUBTYPE_NET_ADDR 5
45 #define LLDP_CHASSIS_SUBTYPE_IF_NAME 6
46 #define LLDP_CHASSIS_SUBTYPE_LOCAL 7
51 #define LLDP_PORT_SUBTYPE_IF_ALIAS 1
52 #define LLDP_PORT_SUBTYPE_PORT_COMP 2
53 #define LLDP_PORT_SUBTYPE_MAC_ADDR 3
54 #define LLDP_PORT_SUBTYPE_NET_ADDR 4
55 #define LLDP_PORT_SUBTYPE_IF_NAME 5
56 #define LLDP_PORT_SUBTYPE_AGENT_CIRC_ID 6
57 #define LLDP_PORT_SUBTYPE_LOCAL 7
60 * System capabilits bit masks
62 #define LLDP_SYSTEM_CAP_OTHER (1 << 0)
63 #define LLDP_SYSTEM_CAP_REPEATER (1 << 1)
64 #define LLDP_SYSTEM_CAP_BRIDGE (1 << 2)
65 #define LLDP_SYSTEM_CAP_WLAN_AP (1 << 3)
66 #define LLDP_SYSTEM_CAP_ROUTER (1 << 4)
67 #define LLDP_SYSTEM_CAP_TELEPHONE (1 << 5)
68 #define LLDP_SYSTEM_CAP_DOCSIS (1 << 6)
69 #define LLDP_SYSTEM_CAP_STATION_ONLY (1 << 7)
72 * Interface number subtypes (for Management address TLV)
74 #define LLDP_IFACE_NUM_SUBTYPE_UNKNOWN 1
75 #define LLDP_IFACE_NUM_SUBTYPE_IF_INDEX 2
76 #define LLDP_IFACE_NUM_SUBTYPE_SYS_PORT 3
79 * IANA address family numbers (only the ones we actually use)
80 * http://www.iana.org/assignments/address-family-numbers/address-family-numbers.txt
82 * TODO: Move these into own header if there are other users?
84 #define IANA_AF_IPV4 1
85 #define IANA_AF_IPV6 2
88 static int lldp_print_net_addr(const uint8_t *addr
, size_t addrlen
)
102 if (inet_ntop(AF_INET
, addr
, buf
, sizeof(buf
)) == NULL
) {
103 tprintf("[MALFORMED ADDR]");
112 if (inet_ntop(AF_INET6
, addr
, buf
, sizeof(buf
)) == NULL
) {
113 tprintf("[MALFORMED ADDR]");
122 tprintf("%.2x:%.2x:%.2x:%.2x:%.2x:%.2x",
123 addr
[0], addr
[1], addr
[2], addr
[3], addr
[4], addr
[5]);
126 tprintf("unknown address family");
133 static inline void lldp_print_cap_one(const char *cap
, unsigned int *prev
)
135 tprintf("%s%s", *prev
? ", " : "", cap
);
139 static void lldp_print_cap(uint16_t cap
)
141 unsigned int prev
= 0;
143 if (cap
& LLDP_SYSTEM_CAP_OTHER
)
144 lldp_print_cap_one("Other", &prev
);
145 if (cap
& LLDP_SYSTEM_CAP_REPEATER
)
146 lldp_print_cap_one("Repeater", &prev
);
147 if (cap
& LLDP_SYSTEM_CAP_BRIDGE
)
148 lldp_print_cap_one("Bridge", &prev
);
149 if (cap
& LLDP_SYSTEM_CAP_WLAN_AP
)
150 lldp_print_cap_one("WLAN AP", &prev
);
151 if (cap
& LLDP_SYSTEM_CAP_ROUTER
)
152 lldp_print_cap_one("Router", &prev
);
153 if (cap
& LLDP_SYSTEM_CAP_TELEPHONE
)
154 lldp_print_cap_one("Telephone", &prev
);
155 if (cap
& LLDP_SYSTEM_CAP_DOCSIS
)
156 lldp_print_cap_one("DOCSIS", &prev
);
157 if (cap
& LLDP_SYSTEM_CAP_STATION_ONLY
)
158 lldp_print_cap_one("Station only", &prev
);
161 static void lldp(struct pkt_buff
*pkt
)
163 unsigned int n_tlv
= 0;
164 uint8_t subtype
, mgmt_alen
, mgmt_oidlen
;
166 unsigned int tlv_type
, tlv_len
;
168 uint8_t *tlv_info_str
;
169 uint16_t sys_cap
, en_cap
;
178 while (len
>= sizeof(tlv_hdr
)) {
179 uint8_t *data
= pkt_pull(pkt
, sizeof(tlv_hdr
));
183 tlv_hdr
= EXTRACT_16BIT(data
);
184 tlv_type
= LLDP_TLV_TYPE(tlv_hdr
);
185 tlv_len
= LLDP_TLV_LENGTH(tlv_hdr
);
187 len
-= sizeof(tlv_hdr
);
189 if (tlv_type
== LLDP_TLV_END
&& tlv_len
== 0) {
190 /* Chassis ID, Port ID and TTL are mandatory */
200 case LLDP_TLV_CHASSIS_ID
:
202 * The mandatory chassis ID shall be the first TLV and
203 * shall appear exactly once.
208 tprintf("Chassis ID");
213 tlv_info_str
= pkt_pull(pkt
, tlv_len
);
214 if (tlv_info_str
== NULL
)
217 subtype
= *tlv_info_str
++;
218 tprintf(" (Subtype %u => ", subtype
);
221 case LLDP_CHASSIS_SUBTYPE_MAC_ADDR
:
225 tprintf("%.2x:%.2x:%.2x:%.2x:%.2x:%.2x",
226 tlv_info_str
[0], tlv_info_str
[1],
227 tlv_info_str
[2], tlv_info_str
[3],
228 tlv_info_str
[4], tlv_info_str
[5]);
230 case LLDP_CHASSIS_SUBTYPE_NET_ADDR
:
231 if (lldp_print_net_addr(tlv_info_str
, tlv_len
))
234 case LLDP_CHASSIS_SUBTYPE_CHASSIS
:
235 case LLDP_CHASSIS_SUBTYPE_IF_ALIAS
:
236 case LLDP_CHASSIS_SUBTYPE_PORT
:
237 case LLDP_CHASSIS_SUBTYPE_IF_NAME
:
238 case LLDP_CHASSIS_SUBTYPE_LOCAL
:
239 tputs_safe((const char *) tlv_info_str
, tlv_len
- 1);
248 case LLDP_TLV_PORT_ID
:
250 * The mandatory port ID shall be the second TLV and
251 * shall appear exactly once.
256 tprintf(", Port ID");
261 tlv_info_str
= pkt_pull(pkt
, tlv_len
);
262 if (tlv_info_str
== NULL
)
265 subtype
= *tlv_info_str
++;
266 tprintf(" (Subtype %u => ", subtype
);
269 case LLDP_PORT_SUBTYPE_MAC_ADDR
:
273 tprintf("%.2x:%.2x:%.2x:%.2x:%.2x:%.2x",
274 tlv_info_str
[0], tlv_info_str
[1],
275 tlv_info_str
[2], tlv_info_str
[3],
276 tlv_info_str
[4], tlv_info_str
[5]);
278 case LLDP_PORT_SUBTYPE_NET_ADDR
:
279 if (lldp_print_net_addr(tlv_info_str
, tlv_len
))
282 case LLDP_PORT_SUBTYPE_IF_ALIAS
:
283 case LLDP_PORT_SUBTYPE_PORT_COMP
:
284 case LLDP_PORT_SUBTYPE_IF_NAME
:
285 case LLDP_PORT_SUBTYPE_AGENT_CIRC_ID
:
286 case LLDP_PORT_SUBTYPE_LOCAL
:
287 tputs_safe((const char *) tlv_info_str
, tlv_len
- 1);
298 * The mandatory TTL shall be the third TLV and
299 * shall appear exactly once.
309 tlv_info_str
= pkt_pull(pkt
, tlv_len
);
310 if (tlv_info_str
== NULL
)
313 tprintf(" (%u)", EXTRACT_16BIT(tlv_info_str
));
315 case LLDP_TLV_PORT_DESC
:
316 tprintf(", Port desc (");
318 tlv_info_str
= pkt_pull(pkt
, tlv_len
);
319 if (tlv_info_str
== NULL
)
322 tputs_safe((const char *) tlv_info_str
, tlv_len
);
326 case LLDP_TLV_SYSTEM_NAME
:
327 tprintf(", Sys name (");
329 tlv_info_str
= pkt_pull(pkt
, tlv_len
);
330 if (tlv_info_str
== NULL
)
333 tputs_safe((const char *) tlv_info_str
, tlv_len
);
337 case LLDP_TLV_SYSTEM_DESC
:
338 tprintf(", Sys desc (");
340 tlv_info_str
= pkt_pull(pkt
, tlv_len
);
341 if (tlv_info_str
== NULL
)
344 tputs_safe((const char *) tlv_info_str
, tlv_len
);
348 case LLDP_TLV_SYSTEM_CAP
:
349 tprintf(", Sys Cap");
354 tlv_info_str
= pkt_pull(pkt
, tlv_len
);
355 if (tlv_info_str
== NULL
)
358 sys_cap
= EXTRACT_16BIT(tlv_info_str
);
359 tlv_info_str
+= sizeof(uint16_t);
360 en_cap
= EXTRACT_16BIT(tlv_info_str
);
363 lldp_print_cap(sys_cap
);
365 tprintf(" Ena Cap (");
366 lldp_print_cap(en_cap
);
369 case LLDP_TLV_MGMT_ADDR
:
370 tprintf(", Mgmt Addr (");
372 if (tlv_len
< 9 || tlv_len
> 167)
375 tlv_info_str
= pkt_pull(pkt
, tlv_len
);
376 if (tlv_info_str
== NULL
)
379 mgmt_alen
= *tlv_info_str
;
381 if (tlv_len
- 1 < mgmt_alen
)
384 if (lldp_print_net_addr(tlv_info_str
, mgmt_alen
))
386 tlv_info_str
+= mgmt_alen
;
388 tprintf(", Iface Subtype %d/", *tlv_info_str
);
389 switch (*tlv_info_str
) {
390 case LLDP_IFACE_NUM_SUBTYPE_IF_INDEX
:
393 case LLDP_IFACE_NUM_SUBTYPE_SYS_PORT
:
394 tprintf("System Port Number");
403 if (tlv_len
- mgmt_alen
< sizeof(uint32_t))
405 tprintf(", Iface Number %u", EXTRACT_32BIT(tlv_info_str
));
408 mgmt_oidlen
= *tlv_info_str
;
409 if (tlv_len
- mgmt_alen
- sizeof(uint32_t) < 3 ||
410 tlv_len
- mgmt_alen
- sizeof(uint32_t) - 3 < mgmt_oidlen
)
412 if (mgmt_oidlen
> 0) {
414 tputs_safe((const char *) tlv_info_str
+ 1, mgmt_oidlen
);
419 case LLDP_TLV_ORG_SPECIFIC
:
420 tprintf(", Org specific");
425 tlv_info_str
= pkt_pull(pkt
, 4);
426 if (tlv_info_str
== NULL
)
429 oui
= ntohl(*((uint32_t *) tlv_info_str
));
430 subtype
= oui
& 0xff;
432 tprintf(" (OUI %s, Subtype %u)", lookup_vendor_str(oui
),
435 /* Just eat it up, we don't know how to interpret it */
436 pkt_pull(pkt
, tlv_len
- 4);
439 tprintf(", Unknown TLV %u", tlv_type
);
440 pkt_pull(pkt
, tlv_len
);
453 tprintf(" %sINVALID%s ]\n", colorize_start_full(black
, red
),
457 static void lldp_less(struct pkt_buff
*pkt
)
459 unsigned int len
, n_tlv
= 0;
460 unsigned int tlv_type
, tlv_len
;
465 while (len
>= sizeof(tlv_hdr
)) {
466 uint8_t *data
= pkt_pull(pkt
, sizeof(tlv_hdr
));
470 tlv_hdr
= EXTRACT_16BIT(data
);
471 tlv_type
= LLDP_TLV_TYPE(tlv_hdr
);
472 tlv_len
= LLDP_TLV_LENGTH(tlv_hdr
);
475 len
-= sizeof(tlv_hdr
);
477 if (tlv_type
== LLDP_TLV_END
|| tlv_len
== 0)
482 pkt_pull(pkt
, tlv_len
);
487 tprintf(" %u TLV%s", n_tlv
, n_tlv
== 1 ? "" : "s");
490 struct protocol lldp_ops
= {
493 .print_less
= lldp_less
,