2 * netsniff-ng - the packet sniffing st
3 * By Daniel Borkmann <daniel@netsniff-ng.org>
4 * Copyright 2012, 2013 Tobias Klauser <tklauser@distanz.ch>
5 * Subject to the GPL, version 2.
9 #include <arpa/inet.h> /* for inet_ntop() */
10 #include <netinet/in.h> /* for ntohs()/ntohl() */
19 #define EXTRACT_16BIT(x) ntohs(*((uint16_t *) (x)))
20 #define EXTRACT_32BIT(x) ntohl(*((uint32_t *) (x)))
22 #define LLDP_TLV_TYPE(tlv) (((tlv) & 0xFE00) >> 9)
23 #define LLDP_TLV_LENGTH(tlv) ((tlv) & 0x01FF)
28 #define LLDP_TLV_END 0
29 #define LLDP_TLV_CHASSIS_ID 1
30 #define LLDP_TLV_PORT_ID 2
31 #define LLDP_TLV_TTL 3
32 #define LLDP_TLV_PORT_DESC 4
33 #define LLDP_TLV_SYSTEM_NAME 5
34 #define LLDP_TLV_SYSTEM_DESC 6
35 #define LLDP_TLV_SYSTEM_CAP 7
36 #define LLDP_TLV_MGMT_ADDR 8
37 #define LLDP_TLV_ORG_SPECIFIC 127
42 #define LLDP_CHASSIS_SUBTYPE_CHASSIS 1
43 #define LLDP_CHASSIS_SUBTYPE_IF_ALIAS 2
44 #define LLDP_CHASSIS_SUBTYPE_PORT 3
45 #define LLDP_CHASSIS_SUBTYPE_MAC_ADDR 4
46 #define LLDP_CHASSIS_SUBTYPE_NET_ADDR 5
47 #define LLDP_CHASSIS_SUBTYPE_IF_NAME 6
48 #define LLDP_CHASSIS_SUBTYPE_LOCAL 7
53 #define LLDP_PORT_SUBTYPE_IF_ALIAS 1
54 #define LLDP_PORT_SUBTYPE_PORT_COMP 2
55 #define LLDP_PORT_SUBTYPE_MAC_ADDR 3
56 #define LLDP_PORT_SUBTYPE_NET_ADDR 4
57 #define LLDP_PORT_SUBTYPE_IF_NAME 5
58 #define LLDP_PORT_SUBTYPE_AGENT_CIRC_ID 6
59 #define LLDP_PORT_SUBTYPE_LOCAL 7
62 * System capabilits bit masks
64 #define LLDP_SYSTEM_CAP_OTHER (1 << 0)
65 #define LLDP_SYSTEM_CAP_REPEATER (1 << 1)
66 #define LLDP_SYSTEM_CAP_BRIDGE (1 << 2)
67 #define LLDP_SYSTEM_CAP_WLAN_AP (1 << 3)
68 #define LLDP_SYSTEM_CAP_ROUTER (1 << 4)
69 #define LLDP_SYSTEM_CAP_TELEPHONE (1 << 5)
70 #define LLDP_SYSTEM_CAP_DOCSIS (1 << 6)
71 #define LLDP_SYSTEM_CAP_STATION_ONLY (1 << 7)
74 * IANA address family numbers (only the ones we actually use)
75 * http://www.iana.org/assignments/address-family-numbers/address-family-numbers.txt
77 * TODO: Move these into own header if there are other users?
79 #define IANA_AF_IPV4 1
80 #define IANA_AF_IPV6 2
83 static int lldp_print_net_addr(const uint8_t *addr
, size_t addrlen
)
97 inet_ntop(AF_INET
, addr
, buf
, sizeof(buf
));
103 inet_ntop(AF_INET6
, addr
, buf
, sizeof(buf
));
109 tprintf("%.2x:%.2x:%.2x:%.2x:%.2x:%.2x",
110 addr
[0], addr
[1], addr
[2], addr
[3], addr
[4], addr
[5]);
113 tprintf("unknown address family");
120 static void lldp_print_cap(uint16_t cap
)
122 unsigned int prev
= 0;
124 if (cap
& LLDP_SYSTEM_CAP_OTHER
)
125 tprintf("%sOther", prev
++ ? ", " : "");
126 if (cap
& LLDP_SYSTEM_CAP_REPEATER
)
127 tprintf("%sRepeater", prev
++ ? ", " : "");
128 if (cap
& LLDP_SYSTEM_CAP_BRIDGE
)
129 tprintf("%sBridge", prev
++ ? ", " : "");
130 if (cap
& LLDP_SYSTEM_CAP_WLAN_AP
)
131 tprintf("%sWLAN AP", prev
++ ? ", " : "");
132 if (cap
& LLDP_SYSTEM_CAP_ROUTER
)
133 tprintf("%sRouter", prev
++ ? ", " : "");
134 if (cap
& LLDP_SYSTEM_CAP_TELEPHONE
)
135 tprintf("%sTelephone", prev
++ ? ", " : "");
136 if (cap
& LLDP_SYSTEM_CAP_DOCSIS
)
137 tprintf("%sDOCSIS", prev
++ ? ", " : "");
138 if (cap
& LLDP_SYSTEM_CAP_STATION_ONLY
)
139 tprintf("%sStation only", prev
++ ? ", " : "");
142 static void lldp(struct pkt_buff
*pkt
)
144 bool seen_chassis_id
= false;
147 unsigned int tlv_type
, tlv_len
;
149 uint8_t *tlv_info_str
;
150 uint16_t sys_cap
, en_cap
;
159 while (len
>= sizeof(tlv_hdr
)) {
160 tlv_hdr
= EXTRACT_16BIT(pkt_pull(pkt
, sizeof(tlv_hdr
)));
161 tlv_type
= LLDP_TLV_TYPE(tlv_hdr
);
162 tlv_len
= LLDP_TLV_LENGTH(tlv_hdr
);
164 len
-= sizeof(tlv_hdr
);
166 if (tlv_type
== LLDP_TLV_END
|| tlv_len
== 0)
167 break; /* TODO: check if any (invalid) TLVs follow? */
170 if (!seen_chassis_id
&& tlv_type
!= LLDP_TLV_CHASSIS_ID
)
174 case LLDP_TLV_CHASSIS_ID
:
178 tprintf("Chassis ID");
183 tlv_info_str
= pkt_pull(pkt
, tlv_len
);
184 if (tlv_info_str
== NULL
)
187 subtype
= *tlv_info_str
++;
188 tprintf(" (Subtype %u => ", subtype
);
191 case LLDP_CHASSIS_SUBTYPE_MAC_ADDR
:
195 tprintf("%.2x:%.2x:%.2x:%.2x:%.2x:%.2x",
196 tlv_info_str
[0], tlv_info_str
[1],
197 tlv_info_str
[2], tlv_info_str
[3],
198 tlv_info_str
[4], tlv_info_str
[5]);
200 case LLDP_CHASSIS_SUBTYPE_NET_ADDR
:
201 if (lldp_print_net_addr(tlv_info_str
, tlv_len
))
204 case LLDP_CHASSIS_SUBTYPE_CHASSIS
:
205 case LLDP_CHASSIS_SUBTYPE_IF_ALIAS
:
206 case LLDP_CHASSIS_SUBTYPE_PORT
:
207 case LLDP_CHASSIS_SUBTYPE_IF_NAME
:
208 case LLDP_CHASSIS_SUBTYPE_LOCAL
:
209 tputs_safe((const char *) tlv_info_str
, tlv_len
- 1);
217 seen_chassis_id
= true;
219 case LLDP_TLV_PORT_ID
:
220 tprintf(", Port ID");
225 tlv_info_str
= pkt_pull(pkt
, tlv_len
);
226 if (tlv_info_str
== NULL
)
229 subtype
= *tlv_info_str
++;
230 tprintf(" (Subtype %u => ", subtype
);
233 case LLDP_PORT_SUBTYPE_MAC_ADDR
:
237 tprintf("%.2x:%.2x:%.2x:%.2x:%.2x:%.2x",
238 tlv_info_str
[0], tlv_info_str
[1],
239 tlv_info_str
[2], tlv_info_str
[3],
240 tlv_info_str
[4], tlv_info_str
[5]);
242 case LLDP_PORT_SUBTYPE_NET_ADDR
:
243 if (lldp_print_net_addr(tlv_info_str
, tlv_len
))
246 case LLDP_PORT_SUBTYPE_IF_ALIAS
:
247 case LLDP_PORT_SUBTYPE_PORT_COMP
:
248 case LLDP_PORT_SUBTYPE_IF_NAME
:
249 case LLDP_PORT_SUBTYPE_AGENT_CIRC_ID
:
250 case LLDP_PORT_SUBTYPE_LOCAL
:
251 tputs_safe((const char *) tlv_info_str
, tlv_len
- 1);
266 tlv_info_str
= pkt_pull(pkt
, tlv_len
);
267 if (tlv_info_str
== NULL
)
270 tprintf(" (%u)", EXTRACT_16BIT(tlv_info_str
));
272 case LLDP_TLV_PORT_DESC
:
273 tprintf(", Port desc (");
275 tlv_info_str
= pkt_pull(pkt
, tlv_len
);
276 if (tlv_info_str
== NULL
)
279 tputs_safe((const char *) tlv_info_str
, tlv_len
);
283 case LLDP_TLV_SYSTEM_NAME
:
284 tprintf(", Sys name (");
286 tlv_info_str
= pkt_pull(pkt
, tlv_len
);
287 if (tlv_info_str
== NULL
)
290 tputs_safe((const char *) tlv_info_str
, tlv_len
);
294 case LLDP_TLV_SYSTEM_DESC
:
295 tprintf(", Sys desc (");
297 tlv_info_str
= pkt_pull(pkt
, tlv_len
);
298 if (tlv_info_str
== NULL
)
301 tputs_safe((const char *) tlv_info_str
, tlv_len
);
305 case LLDP_TLV_SYSTEM_CAP
:
306 tprintf(", Sys Cap");
311 tlv_info_str
= pkt_pull(pkt
, tlv_len
);
312 if (tlv_info_str
== NULL
)
315 sys_cap
= EXTRACT_16BIT(tlv_info_str
);
317 en_cap
= EXTRACT_16BIT(tlv_info_str
);
320 lldp_print_cap(sys_cap
);
322 tprintf(" Ena Cap (");
323 lldp_print_cap(en_cap
);
326 case LLDP_TLV_MGMT_ADDR
:
327 tprintf(", Mgmt Addr");
329 if (tlv_len
< 9 || tlv_len
> 167)
334 pkt_pull(pkt
, tlv_len
);
336 case LLDP_TLV_ORG_SPECIFIC
:
337 tprintf(", Org specific");
342 tlv_info_str
= pkt_pull(pkt
, 4);
343 if (tlv_info_str
== NULL
)
346 oui
= ntohl(*((uint32_t *) tlv_info_str
));
347 subtype
= oui
& 0xff;
349 tprintf(" (OUI %s, Subtype %u)", lookup_vendor_str(oui
),
352 /* Just eat it up, we don't know how to interpret it */
353 pkt_pull(pkt
, tlv_len
- 4);
356 pkt_pull(pkt
, tlv_len
);
357 /* TODO: just hexdump? */
364 if (!seen_chassis_id
)
371 tprintf(" INVALID ]\n");
374 static void lldp_less(struct pkt_buff
*pkt
)
376 uint16_t *tmp_tlv
= (uint16_t *) pkt_pull(pkt
, sizeof(uint16_t));
382 /* TODO: What is relevant here? */
385 struct protocol lldp_ops
= {
388 .print_less
= lldp_less
,