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

Line Branch Exec Source
1
/* 	$OpenBSD: print-slow.c,v 1.4 2015/11/16 00:16:39 mmcc Exp $ 	*/
2
3
/*
4
 * Copyright (c) 1998-2005 The TCPDUMP project
5
 *
6
 * Redistribution and use in source and binary forms, with or without
7
 * modification, are permitted provided that: (1) source code
8
 * distributions retain the above copyright notice and this paragraph
9
 * in its entirety, and (2) distributions including binary code include
10
 * the above copyright notice and this paragraph in its entirety in
11
 * the documentation or other materials provided with the distribution.
12
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND
13
 * WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT
14
 * LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
15
 * FOR A PARTICULAR PURPOSE.
16
 *
17
 * support for the IEEE "slow protocols" LACP, MARKER as per 802.3ad
18
 *
19
 * Original code by Hannes Gredler (hannes@juniper.net)
20
 */
21
22
#include <sys/time.h>
23
#include <sys/socket.h>
24
#include <sys/file.h>
25
#include <sys/ioctl.h>
26
27
#include <net/if.h>
28
29
#include <netinet/in.h>
30
#include <netinet/ip.h>
31
#include <netinet/if_ether.h>
32
#include <stdio.h>
33
#include <stdlib.h>
34
#include <string.h>
35
36
#include "interface.h"
37
#include "extract.h"
38
#include "addrtoname.h"
39
40
41
struct slow_common_header {
42
	u_int8_t proto_subtype;
43
	u_int8_t version;
44
};
45
46
#define	SLOW_PROTO_LACP                     1
47
#define	SLOW_PROTO_MARKER                   2
48
49
#define	LACP_VERSION                        1
50
#define	MARKER_VERSION                      1
51
52
static const struct tok slow_proto_values[] = {
53
	{ SLOW_PROTO_LACP, "LACP" },
54
	{ SLOW_PROTO_MARKER, "MARKER" },
55
	{ 0, NULL}
56
};
57
58
struct tlv_header_t {
59
	u_int8_t type;
60
	u_int8_t length;
61
};
62
63
#define LACP_TLV_TERMINATOR     0x00
64
#define LACP_TLV_ACTOR_INFO     0x01
65
#define LACP_TLV_PARTNER_INFO   0x02
66
#define LACP_TLV_COLLECTOR_INFO 0x03
67
68
#define MARKER_TLV_TERMINATOR   0x00
69
#define MARKER_TLV_MARKER_INFO  0x01
70
#define MARKER_TLV_MARKER_RESP  0x02
71
72
static const struct tok slow_tlv_values[] = {
73
	{ (SLOW_PROTO_LACP << 8) + LACP_TLV_TERMINATOR, "Terminator"},
74
	{ (SLOW_PROTO_LACP << 8) + LACP_TLV_ACTOR_INFO, "Actor Information"},
75
	{ (SLOW_PROTO_LACP << 8) + LACP_TLV_PARTNER_INFO,
76
	    "Partner Information"},
77
	{ (SLOW_PROTO_LACP << 8) + LACP_TLV_COLLECTOR_INFO,
78
	    "Collector Information"},
79
80
	{ (SLOW_PROTO_MARKER << 8) + MARKER_TLV_TERMINATOR, "Terminator"},
81
	{ (SLOW_PROTO_MARKER << 8) + MARKER_TLV_MARKER_INFO,
82
	    "Marker Information"},
83
	{ (SLOW_PROTO_MARKER << 8) + MARKER_TLV_MARKER_RESP,
84
	    "Marker Response Information"},
85
	{ 0, NULL}
86
};
87
88
struct lacp_tlv_actor_partner_info_t {
89
	u_int8_t sys_pri[2];
90
	u_int8_t sys[ETHER_ADDR_LEN];
91
	u_int8_t key[2];
92
	u_int8_t port_pri[2];
93
	u_int8_t port[2];
94
	u_int8_t state;
95
	u_int8_t pad[3];
96
};
97
98
#define ACTOR_PARTNER_BITS \
99
"\020\1Activity\2Timeout\3Aggregation\4Synchronization\5Collecting\
100
\6Distributing\7Default\10Expired"
101
102
struct lacp_tlv_collector_info_t {
103
	u_int8_t max_delay[2];
104
	u_int8_t pad[12];
105
};
106
107
struct marker_tlv_marker_info_t {
108
	u_int8_t req_port[2];
109
	u_int8_t req_sys[ETHER_ADDR_LEN];
110
	u_int8_t req_trans_id[4];
111
	u_int8_t pad[2];
112
};
113
114
struct lacp_marker_tlv_terminator_t {
115
	u_int8_t pad[50];
116
};
117
118
void
119
slow_print(const u_char *pptr, u_int len)
120
{
121
122
	const struct slow_common_header *slow_com_header;
123
	const struct tlv_header_t *tlv_header;
124
	const u_char *tptr, *tlv_tptr;
125
	u_int tlv_len, tlen, tlv_tlen;
126
127
	union {
128
		struct lacp_marker_tlv_terminator_t *marker_terminator;
129
		struct lacp_tlv_actor_partner_info_t *actor_partner_info;
130
		struct lacp_tlv_collector_info_t *collector_info;
131
		struct marker_tlv_marker_info_t *marker_tlv_marker_info;
132
	} tlv_ptr;
133
134
	tptr = pptr;
135
	slow_com_header = (const struct slow_common_header *)pptr;
136
	TCHECK(*slow_com_header);
137
138
	/*
139
	 * Sanity checking of the header.
140
	 */
141
	if (slow_com_header->proto_subtype == SLOW_PROTO_LACP &&
142
		slow_com_header->version != LACP_VERSION) {
143
		printf("LACP version %u packet not supported",
144
		    slow_com_header->version);
145
		return;
146
	}
147
	if (slow_com_header->proto_subtype == SLOW_PROTO_MARKER &&
148
		slow_com_header->version != MARKER_VERSION) {
149
		printf("MARKER version %u packet not supported",
150
		    slow_com_header->version);
151
		return;
152
	}
153
154
	printf("%sv%u, length: %u",
155
	    tok2str(slow_proto_values, "unknown (%u)",
156
	    slow_com_header->proto_subtype), slow_com_header->version, len);
157
158
	if (!vflag)
159
		return;
160
161
	/* ok they seem to want to know everything - lets fully decode it */
162
	tlen = len - sizeof(struct slow_common_header);
163
	tptr += sizeof(const struct slow_common_header);
164
165
	while (tlen > 0) {
166
		/* did we capture enough for fully decoding the tlv header ? */
167
		TCHECK2(*tptr, sizeof(struct tlv_header_t));
168
		tlv_header = (const struct tlv_header_t *)tptr;
169
		tlv_len = tlv_header->length;
170
171
		/* End of message */
172
		if (tlv_header->type == LACP_TLV_TERMINATOR ||
173
		    tlv_header->type == MARKER_TLV_TERMINATOR)
174
			return;
175
176
		printf("\n\t%s TLV (0x%02x), length: %u",
177
		    tok2str(slow_tlv_values, "Unknown",
178
		    (slow_com_header->proto_subtype << 8) + tlv_header->type),
179
		    tlv_header->type, tlv_len);
180
181
		if (tlv_len < sizeof(struct tlv_header_t) || tlv_len > tlen) {
182
			printf("\n\tInvalid TLV length: %u", tlv_len);
183
			return;
184
		}
185
186
		tlv_tptr = tptr + sizeof(struct tlv_header_t);
187
		tlv_tlen = tlv_len - sizeof(struct tlv_header_t);
188
189
		/* did we capture enough for fully decoding the tlv ? */
190
		TCHECK2(*tptr, tlv_len);
191
192
		switch((slow_com_header->proto_subtype << 8) +
193
		    tlv_header->type) {
194
195
		/* those two TLVs have the same structure -> fall through */
196
		case ((SLOW_PROTO_LACP << 8) + LACP_TLV_ACTOR_INFO):
197
		case ((SLOW_PROTO_LACP << 8) + LACP_TLV_PARTNER_INFO):
198
			tlv_ptr.actor_partner_info =
199
			    (struct lacp_tlv_actor_partner_info_t *)tlv_tptr;
200
			if (tlv_tlen != sizeof(*tlv_ptr.actor_partner_info)) {
201
				printf("\n\tInvalid partner/actor info length %u",
202
				    tlv_tlen);
203
				break;
204
			}
205
206
			printf("\n\t  System %s, System Priority %u, Key %u"
207
			    ", Port %u, Port Priority %u\n\t  ",
208
			    etheraddr_string(tlv_ptr.actor_partner_info->sys),
209
			    EXTRACT_16BITS(tlv_ptr.actor_partner_info->sys_pri),
210
			    EXTRACT_16BITS(tlv_ptr.actor_partner_info->key),
211
			    EXTRACT_16BITS(tlv_ptr.actor_partner_info->port),
212
			    EXTRACT_16BITS(tlv_ptr.actor_partner_info->
213
			    port_pri));
214
			printb("State", tlv_ptr.actor_partner_info->state,
215
			    ACTOR_PARTNER_BITS);
216
			break;
217
218
		case ((SLOW_PROTO_LACP << 8) + LACP_TLV_COLLECTOR_INFO):
219
			tlv_ptr.collector_info =
220
			    (struct lacp_tlv_collector_info_t *)tlv_tptr;
221
			if (tlv_tlen != sizeof(*tlv_ptr.collector_info)) {
222
				printf("\n\tInvalid collector info length %u",
223
				    tlv_tlen);
224
				break;
225
			}
226
227
			printf("\n\t  Max Delay %u",
228
			    EXTRACT_16BITS(tlv_ptr.collector_info->max_delay));
229
			break;
230
231
		case ((SLOW_PROTO_MARKER << 8) + MARKER_TLV_MARKER_INFO):
232
		case ((SLOW_PROTO_MARKER << 8) + MARKER_TLV_MARKER_RESP):
233
			tlv_ptr.marker_tlv_marker_info =
234
			    (struct marker_tlv_marker_info_t *)tlv_tptr;
235
			if (tlv_tlen !=
236
			    sizeof(*tlv_ptr.marker_tlv_marker_info)) {
237
				printf("\n\tInvalid marker info/resp length %u",
238
				    tlv_tlen);
239
				break;
240
			}
241
242
			printf("\n\t  Request System %s, Request Port %u,"
243
			    " Request Transaction ID 0x%08x",
244
			    etheraddr_string(tlv_ptr.marker_tlv_marker_info->
245
			    req_sys),
246
			    EXTRACT_16BITS(tlv_ptr.marker_tlv_marker_info->
247
			    req_port),
248
			    EXTRACT_32BITS(tlv_ptr.marker_tlv_marker_info->
249
			    req_trans_id));
250
			break;
251
252
		default:
253
			if (vflag > 1)
254
				printf("\n\t Unknown TLV type: 0x%x \n",
255
				    (slow_com_header->proto_subtype << 8) +
256
				    tlv_header->type);
257
			break;
258
		}
259
260
		tptr += tlv_len;
261
		tlen -= tlv_len;
262
	}
263
264
    return;
265
trunc:
266
    printf("\n\t[|slow]");
267
}