GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: usr.sbin/tcpdump/print-lldp.c Lines: 0 116 0.0 %
Date: 2017-11-13 Branches: 0 74 0.0 %

Line Branch Exec Source
1
/*	$OpenBSD: print-lldp.c,v 1.9 2016/11/28 17:47:15 jca Exp $	*/
2
3
/*
4
 * Copyright (c) 2006 Reyk Floeter <reyk@openbsd.org>
5
 *
6
 * Permission to use, copy, modify, and distribute this software for any
7
 * purpose with or without fee is hereby granted, provided that the above
8
 * copyright notice and this permission notice appear in all copies.
9
 *
10
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17
 */
18
19
#include <sys/time.h>
20
#include <sys/socket.h>
21
22
#include <net/if.h>
23
24
#include <netinet/in.h>
25
#include <netinet/if_ether.h>
26
#include <arpa/inet.h>
27
28
#include <ctype.h>
29
#include <stdio.h>
30
#include <string.h>
31
32
#include "addrtoname.h"
33
#include "extract.h"
34
#include "interface.h"
35
#include "afnum.h"
36
37
enum {
38
	LLDP_TLV_END			= 0,
39
	LLDP_TLV_CHASSIS_ID		= 1,
40
	LLDP_TLV_PORT_ID		= 2,
41
	LLDP_TLV_TTL			= 3,
42
	LLDP_TLV_PORT_DESCR		= 4,
43
	LLDP_TLV_SYSTEM_NAME		= 5,
44
	LLDP_TLV_SYSTEM_DESCR		= 6,
45
	LLDP_TLV_SYSTEM_CAP		= 7,
46
	LLDP_TLV_MANAGEMENT_ADDR	= 8,
47
	LLDP_TLV_ORG			= 127
48
};
49
50
enum {
51
	LLDP_CHASSISID_SUBTYPE_CHASSIS	= 1,
52
	LLDP_CHASSISID_SUBTYPE_IFALIAS	= 2,
53
	LLDP_CHASSISID_SUBTYPE_PORT	= 3,
54
	LLDP_CHASSISID_SUBTYPE_LLADDR	= 4,
55
	LLDP_CHASSISID_SUBTYPE_ADDR	= 5,
56
	LLDP_CHASSISID_SUBTYPE_IFNAME	= 6,
57
	LLDP_CHASSISID_SUBTYPE_LOCAL	= 7
58
};
59
60
enum {
61
	LLDP_PORTID_SUBTYPE_IFALIAS	= 1,
62
	LLDP_PORTID_SUBTYPE_PORT	= 2,
63
	LLDP_PORTID_SUBTYPE_LLADDR	= 3,
64
	LLDP_PORTID_SUBTYPE_ADDR	= 4,
65
	LLDP_PORTID_SUBTYPE_IFNAME	= 5,
66
	LLDP_PORTID_SUBTYPE_AGENTCID	= 6,
67
	LLDP_PORTID_SUBTYPE_LOCAL	= 7
68
};
69
70
#define LLDP_CAP_OTHER          0x01
71
#define LLDP_CAP_REPEATER       0x02
72
#define LLDP_CAP_BRIDGE         0x04
73
#define LLDP_CAP_WLAN           0x08
74
#define LLDP_CAP_ROUTER         0x10
75
#define LLDP_CAP_TELEPHONE      0x20
76
#define LLDP_CAP_DOCSIS         0x40
77
#define LLDP_CAP_STATION        0x80
78
#define LLDP_CAP_BITS								\
79
	"\20\01OTHER\02REPEATER\03BRIDGE\04WLAN\05ROUTER\06TELEPHONE"		\
80
	"\07DOCSIS\10STATION"
81
82
enum {
83
	LLDP_MGMT_IFACE_UNKNOWN	= 1,
84
	LLDP_MGMT_IFACE_IFINDEX	= 2,
85
	LLDP_MGMT_IFACE_SYSPORT	= 3
86
};
87
88
static const char *afnumber[] = AFNUM_NAME_STR;
89
90
void		 lldp_print_str(u_int8_t *, int);
91
const char	*lldp_print_addr(int, const void *);
92
void		 lldp_print_id(int, u_int8_t *, int);
93
94
void
95
lldp_print_str(u_int8_t *str, int len)
96
{
97
	int i;
98
	printf("\"");
99
	for (i = 0; i < len; i++)
100
		printf("%c", isprint(str[i]) ? str[i] : '.');
101
	printf("\"");
102
}
103
104
const char *
105
lldp_print_addr(int af, const void *addr)
106
{
107
	static char buf[48];
108
	if (inet_ntop(af, addr, buf, sizeof(buf)) == NULL)
109
		return ("?");
110
	return (buf);
111
}
112
113
void
114
lldp_print_id(int type, u_int8_t *ptr, int len)
115
{
116
	u_int8_t id;
117
	u_int8_t *data;
118
119
	id = *(u_int8_t *)ptr;
120
	len -= sizeof(u_int8_t);
121
	data = ptr + sizeof(u_int8_t);
122
	if (len <= 0)
123
		return;
124
125
	if (type == LLDP_TLV_CHASSIS_ID) {
126
		switch (id) {
127
		case LLDP_CHASSISID_SUBTYPE_CHASSIS:
128
			printf("chassis ");
129
			lldp_print_str(data, len);
130
			break;
131
		case LLDP_CHASSISID_SUBTYPE_IFALIAS:
132
			printf("ifalias");
133
			break;
134
		case LLDP_CHASSISID_SUBTYPE_PORT:
135
			printf("port");
136
			break;
137
		case LLDP_CHASSISID_SUBTYPE_LLADDR:
138
			printf("lladdr %s", etheraddr_string(data));
139
			break;
140
		case LLDP_CHASSISID_SUBTYPE_ADDR:
141
			printf("addr");
142
			break;
143
		case LLDP_CHASSISID_SUBTYPE_IFNAME:
144
			printf("ifname ");
145
			lldp_print_str(data, len);
146
			break;
147
		case LLDP_CHASSISID_SUBTYPE_LOCAL:
148
			printf("local ");
149
			lldp_print_str(data, len);
150
			break;
151
		default:
152
			printf("unknown 0x%02x", id);
153
			break;
154
		}
155
156
	} else if (type == LLDP_TLV_PORT_ID) {
157
		switch (id) {
158
		case LLDP_PORTID_SUBTYPE_IFALIAS:
159
			printf("ifalias");
160
			break;
161
		case LLDP_PORTID_SUBTYPE_PORT:
162
			printf("port");
163
			break;
164
		case LLDP_PORTID_SUBTYPE_LLADDR:
165
			printf("lladdr %s", etheraddr_string(data));
166
			break;
167
		case LLDP_PORTID_SUBTYPE_ADDR:
168
			printf("addr");
169
			break;
170
		case LLDP_PORTID_SUBTYPE_IFNAME:
171
			printf("ifname ");
172
			lldp_print_str(data, len);
173
			break;
174
		case LLDP_PORTID_SUBTYPE_AGENTCID:
175
			printf("agentcid");
176
			break;
177
		case LLDP_PORTID_SUBTYPE_LOCAL:
178
			printf("local ");
179
			lldp_print_str(data, len);
180
			break;
181
		default:
182
			printf("unknown 0x%02x", id);
183
			break;
184
		}
185
	}
186
}
187
188
void
189
lldp_print(const u_char *p, u_int len)
190
{
191
	u_int16_t tlv;
192
	u_int8_t *ptr = (u_int8_t *)p, v = 0;
193
	int n, type, vlen, alen;
194
195
	printf("LLDP");
196
197
#define _ptrinc(_v)	ptr += (_v); vlen -= (_v);
198
199
	for (n = 0; n < len;) {
200
		TCHECK2(*ptr, sizeof(tlv));
201
202
		tlv = EXTRACT_16BITS(ptr);
203
		type = (tlv & 0xfe00) >> 9;
204
		vlen = tlv & 0x1ff;
205
		n += vlen;
206
207
		ptr += sizeof(tlv);
208
		TCHECK2(*ptr, vlen);
209
210
		switch (type) {
211
		case LLDP_TLV_END:
212
			goto done;
213
			break;
214
215
		case LLDP_TLV_CHASSIS_ID:
216
			printf(", ChassisId: ");
217
			lldp_print_id(type, ptr, vlen);
218
			break;
219
220
		case LLDP_TLV_PORT_ID:
221
			printf(", PortId: ");
222
			lldp_print_id(type, ptr, vlen);
223
			break;
224
225
		case LLDP_TLV_TTL:
226
			printf(", TTL: ");
227
			TCHECK2(*ptr, 2);
228
			printf("%ds", EXTRACT_16BITS(ptr));
229
			break;
230
231
		case LLDP_TLV_PORT_DESCR:
232
			printf(", PortDescr: ");
233
			lldp_print_str(ptr, vlen);
234
			break;
235
236
		case LLDP_TLV_SYSTEM_NAME:
237
			printf(", SysName: ");
238
			lldp_print_str(ptr, vlen);
239
			break;
240
241
		case LLDP_TLV_SYSTEM_DESCR:
242
			printf(", SysDescr: ");
243
			lldp_print_str(ptr, vlen);
244
			break;
245
246
		case LLDP_TLV_SYSTEM_CAP:
247
			printf(", CAP:");
248
			TCHECK2(*ptr, 4);
249
			printb(" available", EXTRACT_16BITS(ptr),
250
			    LLDP_CAP_BITS);
251
			_ptrinc(sizeof(u_int16_t));
252
			printb(" enabled", EXTRACT_16BITS(ptr),
253
			    LLDP_CAP_BITS);
254
			break;
255
256
		case LLDP_TLV_MANAGEMENT_ADDR:
257
			printf(", MgmtAddr:");
258
			TCHECK2(*ptr, 2);
259
			alen = *ptr - sizeof(u_int8_t);
260
			_ptrinc(sizeof(u_int8_t));
261
			v = *ptr;
262
			_ptrinc(sizeof(u_int8_t));
263
			if (v < AFNUM_MAX)
264
				printf(" %s", afnumber[v]);
265
			else
266
				printf(" type %d", v);
267
			TCHECK2(*ptr, alen);
268
			switch (v) {
269
			case AFNUM_INET:
270
				if (alen != sizeof(struct in_addr))
271
					goto trunc;
272
				printf(" %s",
273
				    lldp_print_addr(AF_INET, ptr));
274
				break;
275
			case AFNUM_INET6:
276
				if (alen != sizeof(struct in6_addr))
277
					goto trunc;
278
				printf(" %s",
279
				    lldp_print_addr(AF_INET6, ptr));
280
				break;
281
			}
282
			_ptrinc(alen);
283
			v = *(u_int8_t *)ptr;
284
			break;
285
286
		case LLDP_TLV_ORG:
287
			printf(", Org");
288
			break;
289
290
		default:
291
			printf(", type %d length %d", type, vlen);
292
			break;
293
		}
294
		ptr += vlen;
295
	}
296
297
 done:
298
	return;
299
300
 trunc:
301
	printf(" [|LLDP]");
302
}
303