1411677aeSAaron LI /*
2411677aeSAaron LI * Copyright (c) 2014 The TCPDUMP project
3411677aeSAaron LI * All rights reserved.
4411677aeSAaron LI *
5411677aeSAaron LI * Redistribution and use in source and binary forms, with or without
6411677aeSAaron LI * modification, are permitted provided that the following conditions
7411677aeSAaron LI * are met:
8411677aeSAaron LI * 1. Redistributions of source code must retain the above copyright
9411677aeSAaron LI * notice, this list of conditions and the following disclaimer.
10411677aeSAaron LI * 2. Redistributions in binary form must reproduce the above copyright
11411677aeSAaron LI * notice, this list of conditions and the following disclaimer in the
12411677aeSAaron LI * documentation and/or other materials provided with the distribution.
13411677aeSAaron LI *
14411677aeSAaron LI * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
15411677aeSAaron LI * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
16411677aeSAaron LI * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
17411677aeSAaron LI * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
18411677aeSAaron LI * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
19411677aeSAaron LI * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
20411677aeSAaron LI * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
21411677aeSAaron LI * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
22411677aeSAaron LI * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23411677aeSAaron LI * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
24411677aeSAaron LI * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
25411677aeSAaron LI * POSSIBILITY OF SUCH DAMAGE.
26411677aeSAaron LI */
27411677aeSAaron LI
28411677aeSAaron LI /* \summary: ATA over Ethernet (AoE) protocol printer */
29411677aeSAaron LI
30*ed775ee7SAntonio Huete Jimenez /* specification:
31*ed775ee7SAntonio Huete Jimenez * https://web.archive.org/web/20161025044402/http://brantleycoilecompany.com/AoEr11.pdf
32*ed775ee7SAntonio Huete Jimenez */
33411677aeSAaron LI
34411677aeSAaron LI #ifdef HAVE_CONFIG_H
35*ed775ee7SAntonio Huete Jimenez #include <config.h>
36411677aeSAaron LI #endif
37411677aeSAaron LI
38*ed775ee7SAntonio Huete Jimenez #include "netdissect-stdinc.h"
39411677aeSAaron LI
40*ed775ee7SAntonio Huete Jimenez #define ND_LONGJMP_FROM_TCHECK
41411677aeSAaron LI #include "netdissect.h"
42411677aeSAaron LI #include "extract.h"
43411677aeSAaron LI #include "addrtoname.h"
44411677aeSAaron LI
45411677aeSAaron LI
46411677aeSAaron LI #define AOE_V1 1
47411677aeSAaron LI #define ATA_SECTOR_SIZE 512
48411677aeSAaron LI
49411677aeSAaron LI #define AOEV1_CMD_ISSUE_ATA_COMMAND 0
50411677aeSAaron LI #define AOEV1_CMD_QUERY_CONFIG_INFORMATION 1
51411677aeSAaron LI #define AOEV1_CMD_MAC_MASK_LIST 2
52411677aeSAaron LI #define AOEV1_CMD_RESERVE_RELEASE 3
53411677aeSAaron LI
54411677aeSAaron LI static const struct tok cmdcode_str[] = {
55411677aeSAaron LI { AOEV1_CMD_ISSUE_ATA_COMMAND, "Issue ATA Command" },
56411677aeSAaron LI { AOEV1_CMD_QUERY_CONFIG_INFORMATION, "Query Config Information" },
57411677aeSAaron LI { AOEV1_CMD_MAC_MASK_LIST, "MAC Mask List" },
58411677aeSAaron LI { AOEV1_CMD_RESERVE_RELEASE, "Reserve/Release" },
59411677aeSAaron LI { 0, NULL }
60411677aeSAaron LI };
61411677aeSAaron LI
62411677aeSAaron LI #define AOEV1_COMMON_HDR_LEN 10U /* up to but w/o Arg */
63411677aeSAaron LI #define AOEV1_ISSUE_ARG_LEN 12U /* up to but w/o Data */
64411677aeSAaron LI #define AOEV1_QUERY_ARG_LEN 8U /* up to but w/o Config String */
65411677aeSAaron LI #define AOEV1_MAC_ARG_LEN 4U /* up to but w/o Directive 0 */
66411677aeSAaron LI #define AOEV1_RESERVE_ARG_LEN 2U /* up to but w/o Ethernet address 0 */
67411677aeSAaron LI #define AOEV1_MAX_CONFSTR_LEN 1024U
68411677aeSAaron LI
69411677aeSAaron LI #define AOEV1_FLAG_R 0x08
70411677aeSAaron LI #define AOEV1_FLAG_E 0x04
71411677aeSAaron LI
72411677aeSAaron LI static const struct tok aoev1_flag_str[] = {
73411677aeSAaron LI { AOEV1_FLAG_R, "Response" },
74411677aeSAaron LI { AOEV1_FLAG_E, "Error" },
75*ed775ee7SAntonio Huete Jimenez { 0x02, "MBZ-1" },
76*ed775ee7SAntonio Huete Jimenez { 0x01, "MBZ-0" },
77411677aeSAaron LI { 0, NULL }
78411677aeSAaron LI };
79411677aeSAaron LI
80411677aeSAaron LI static const struct tok aoev1_errcode_str[] = {
81411677aeSAaron LI { 1, "Unrecognized command code" },
82411677aeSAaron LI { 2, "Bad argument parameter" },
83411677aeSAaron LI { 3, "Device unavailable" },
84411677aeSAaron LI { 4, "Config string present" },
85411677aeSAaron LI { 5, "Unsupported version" },
86411677aeSAaron LI { 6, "Target is reserved" },
87411677aeSAaron LI { 0, NULL }
88411677aeSAaron LI };
89411677aeSAaron LI
90411677aeSAaron LI #define AOEV1_AFLAG_E 0x40
91411677aeSAaron LI #define AOEV1_AFLAG_D 0x10
92411677aeSAaron LI #define AOEV1_AFLAG_A 0x02
93411677aeSAaron LI #define AOEV1_AFLAG_W 0x01
94411677aeSAaron LI
95*ed775ee7SAntonio Huete Jimenez static const struct tok aoev1_aflag_bitmap_str[] = {
96*ed775ee7SAntonio Huete Jimenez { 0x80, "MBZ-7" },
97411677aeSAaron LI { AOEV1_AFLAG_E, "Ext48" },
98*ed775ee7SAntonio Huete Jimenez { 0x20, "MBZ-5" },
99411677aeSAaron LI { AOEV1_AFLAG_D, "Device" },
100*ed775ee7SAntonio Huete Jimenez { 0x08, "MBZ-3" },
101*ed775ee7SAntonio Huete Jimenez { 0x04, "MBZ-2" },
102411677aeSAaron LI { AOEV1_AFLAG_A, "Async" },
103411677aeSAaron LI { AOEV1_AFLAG_W, "Write" },
104411677aeSAaron LI { 0, NULL }
105411677aeSAaron LI };
106411677aeSAaron LI
107411677aeSAaron LI static const struct tok aoev1_ccmd_str[] = {
108411677aeSAaron LI { 0, "read config string" },
109411677aeSAaron LI { 1, "test config string" },
110411677aeSAaron LI { 2, "test config string prefix" },
111411677aeSAaron LI { 3, "set config string" },
112411677aeSAaron LI { 4, "force set config string" },
113411677aeSAaron LI { 0, NULL }
114411677aeSAaron LI };
115411677aeSAaron LI
116411677aeSAaron LI static const struct tok aoev1_mcmd_str[] = {
117411677aeSAaron LI { 0, "Read Mac Mask List" },
118411677aeSAaron LI { 1, "Edit Mac Mask List" },
119411677aeSAaron LI { 0, NULL }
120411677aeSAaron LI };
121411677aeSAaron LI
122411677aeSAaron LI static const struct tok aoev1_merror_str[] = {
123411677aeSAaron LI { 1, "Unspecified Error" },
124411677aeSAaron LI { 2, "Bad DCmd directive" },
125411677aeSAaron LI { 3, "Mask list full" },
126411677aeSAaron LI { 0, NULL }
127411677aeSAaron LI };
128411677aeSAaron LI
129411677aeSAaron LI static const struct tok aoev1_dcmd_str[] = {
130411677aeSAaron LI { 0, "No Directive" },
131411677aeSAaron LI { 1, "Add mac address to mask list" },
132411677aeSAaron LI { 2, "Delete mac address from mask list" },
133411677aeSAaron LI { 0, NULL }
134411677aeSAaron LI };
135411677aeSAaron LI
136411677aeSAaron LI static const struct tok aoev1_rcmd_str[] = {
137411677aeSAaron LI { 0, "Read reserve list" },
138411677aeSAaron LI { 1, "Set reserve list" },
139411677aeSAaron LI { 2, "Force set reserve list" },
140411677aeSAaron LI { 0, NULL }
141411677aeSAaron LI };
142411677aeSAaron LI
143411677aeSAaron LI static void
aoev1_issue_print(netdissect_options * ndo,const u_char * cp,u_int len)144411677aeSAaron LI aoev1_issue_print(netdissect_options *ndo,
145*ed775ee7SAntonio Huete Jimenez const u_char *cp, u_int len)
146411677aeSAaron LI {
147411677aeSAaron LI if (len < AOEV1_ISSUE_ARG_LEN)
148411677aeSAaron LI goto invalid;
149411677aeSAaron LI /* AFlags */
150*ed775ee7SAntonio Huete Jimenez ND_PRINT("\n\tAFlags: [%s]",
151*ed775ee7SAntonio Huete Jimenez bittok2str(aoev1_aflag_bitmap_str, "none", GET_U_1(cp)));
152411677aeSAaron LI cp += 1;
153*ed775ee7SAntonio Huete Jimenez len -= 1;
154411677aeSAaron LI /* Err/Feature */
155*ed775ee7SAntonio Huete Jimenez ND_PRINT(", Err/Feature: %u", GET_U_1(cp));
156411677aeSAaron LI cp += 1;
157*ed775ee7SAntonio Huete Jimenez len -= 1;
158411677aeSAaron LI /* Sector Count (not correlated with the length) */
159*ed775ee7SAntonio Huete Jimenez ND_PRINT(", Sector Count: %u", GET_U_1(cp));
160411677aeSAaron LI cp += 1;
161*ed775ee7SAntonio Huete Jimenez len -= 1;
162411677aeSAaron LI /* Cmd/Status */
163*ed775ee7SAntonio Huete Jimenez ND_PRINT(", Cmd/Status: %u", GET_U_1(cp));
164411677aeSAaron LI cp += 1;
165*ed775ee7SAntonio Huete Jimenez len -= 1;
166411677aeSAaron LI /* lba0 */
167*ed775ee7SAntonio Huete Jimenez ND_PRINT("\n\tlba0: %u", GET_U_1(cp));
168411677aeSAaron LI cp += 1;
169*ed775ee7SAntonio Huete Jimenez len -= 1;
170411677aeSAaron LI /* lba1 */
171*ed775ee7SAntonio Huete Jimenez ND_PRINT(", lba1: %u", GET_U_1(cp));
172411677aeSAaron LI cp += 1;
173*ed775ee7SAntonio Huete Jimenez len -= 1;
174411677aeSAaron LI /* lba2 */
175*ed775ee7SAntonio Huete Jimenez ND_PRINT(", lba2: %u", GET_U_1(cp));
176411677aeSAaron LI cp += 1;
177*ed775ee7SAntonio Huete Jimenez len -= 1;
178411677aeSAaron LI /* lba3 */
179*ed775ee7SAntonio Huete Jimenez ND_PRINT(", lba3: %u", GET_U_1(cp));
180411677aeSAaron LI cp += 1;
181*ed775ee7SAntonio Huete Jimenez len -= 1;
182411677aeSAaron LI /* lba4 */
183*ed775ee7SAntonio Huete Jimenez ND_PRINT(", lba4: %u", GET_U_1(cp));
184411677aeSAaron LI cp += 1;
185*ed775ee7SAntonio Huete Jimenez len -= 1;
186411677aeSAaron LI /* lba5 */
187*ed775ee7SAntonio Huete Jimenez ND_PRINT(", lba5: %u", GET_U_1(cp));
188411677aeSAaron LI cp += 1;
189*ed775ee7SAntonio Huete Jimenez len -= 1;
190411677aeSAaron LI /* Reserved */
191*ed775ee7SAntonio Huete Jimenez ND_TCHECK_2(cp);
192411677aeSAaron LI cp += 2;
193*ed775ee7SAntonio Huete Jimenez len -= 2;
194411677aeSAaron LI /* Data */
195*ed775ee7SAntonio Huete Jimenez if (len)
196*ed775ee7SAntonio Huete Jimenez ND_PRINT("\n\tData: %u bytes", len);
197411677aeSAaron LI return;
198411677aeSAaron LI
199411677aeSAaron LI invalid:
200*ed775ee7SAntonio Huete Jimenez nd_print_invalid(ndo);
201*ed775ee7SAntonio Huete Jimenez ND_TCHECK_LEN(cp, len);
202411677aeSAaron LI }
203411677aeSAaron LI
204411677aeSAaron LI static void
aoev1_query_print(netdissect_options * ndo,const u_char * cp,u_int len)205411677aeSAaron LI aoev1_query_print(netdissect_options *ndo,
206*ed775ee7SAntonio Huete Jimenez const u_char *cp, u_int len)
207411677aeSAaron LI {
208411677aeSAaron LI uint16_t cslen;
209411677aeSAaron LI
210411677aeSAaron LI if (len < AOEV1_QUERY_ARG_LEN)
211411677aeSAaron LI goto invalid;
212411677aeSAaron LI /* Buffer Count */
213*ed775ee7SAntonio Huete Jimenez ND_PRINT("\n\tBuffer Count: %u", GET_BE_U_2(cp));
214411677aeSAaron LI cp += 2;
215*ed775ee7SAntonio Huete Jimenez len -= 2;
216411677aeSAaron LI /* Firmware Version */
217*ed775ee7SAntonio Huete Jimenez ND_PRINT(", Firmware Version: %u", GET_BE_U_2(cp));
218411677aeSAaron LI cp += 2;
219*ed775ee7SAntonio Huete Jimenez len -= 2;
220411677aeSAaron LI /* Sector Count */
221*ed775ee7SAntonio Huete Jimenez ND_PRINT(", Sector Count: %u", GET_U_1(cp));
222411677aeSAaron LI cp += 1;
223*ed775ee7SAntonio Huete Jimenez len -= 1;
224411677aeSAaron LI /* AoE/CCmd */
225*ed775ee7SAntonio Huete Jimenez ND_PRINT(", AoE: %u, CCmd: %s", (GET_U_1(cp) & 0xF0) >> 4,
226*ed775ee7SAntonio Huete Jimenez tok2str(aoev1_ccmd_str, "Unknown (0x02x)", GET_U_1(cp) & 0x0F));
227411677aeSAaron LI cp += 1;
228*ed775ee7SAntonio Huete Jimenez len -= 1;
229411677aeSAaron LI /* Config String Length */
230*ed775ee7SAntonio Huete Jimenez cslen = GET_BE_U_2(cp);
231411677aeSAaron LI cp += 2;
232*ed775ee7SAntonio Huete Jimenez len -= 2;
233*ed775ee7SAntonio Huete Jimenez if (cslen > AOEV1_MAX_CONFSTR_LEN || cslen > len)
234411677aeSAaron LI goto invalid;
235411677aeSAaron LI /* Config String */
236411677aeSAaron LI if (cslen) {
237*ed775ee7SAntonio Huete Jimenez ND_PRINT("\n\tConfig String (length %u): ", cslen);
238*ed775ee7SAntonio Huete Jimenez (void)nd_printn(ndo, cp, cslen, NULL);
239411677aeSAaron LI }
240411677aeSAaron LI return;
241411677aeSAaron LI
242411677aeSAaron LI invalid:
243*ed775ee7SAntonio Huete Jimenez nd_print_invalid(ndo);
244*ed775ee7SAntonio Huete Jimenez ND_TCHECK_LEN(cp, len);
245411677aeSAaron LI }
246411677aeSAaron LI
247411677aeSAaron LI static void
aoev1_mac_print(netdissect_options * ndo,const u_char * cp,u_int len)248411677aeSAaron LI aoev1_mac_print(netdissect_options *ndo,
249*ed775ee7SAntonio Huete Jimenez const u_char *cp, u_int len)
250411677aeSAaron LI {
251411677aeSAaron LI uint8_t dircount, i;
252411677aeSAaron LI
253411677aeSAaron LI if (len < AOEV1_MAC_ARG_LEN)
254411677aeSAaron LI goto invalid;
255411677aeSAaron LI /* Reserved */
256411677aeSAaron LI cp += 1;
257*ed775ee7SAntonio Huete Jimenez len -= 1;
258411677aeSAaron LI /* MCmd */
259*ed775ee7SAntonio Huete Jimenez ND_PRINT("\n\tMCmd: %s",
260*ed775ee7SAntonio Huete Jimenez tok2str(aoev1_mcmd_str, "Unknown (0x%02x)", GET_U_1(cp)));
261411677aeSAaron LI cp += 1;
262*ed775ee7SAntonio Huete Jimenez len -= 1;
263411677aeSAaron LI /* MError */
264*ed775ee7SAntonio Huete Jimenez ND_PRINT(", MError: %s",
265*ed775ee7SAntonio Huete Jimenez tok2str(aoev1_merror_str, "Unknown (0x%02x)", GET_U_1(cp)));
266411677aeSAaron LI cp += 1;
267*ed775ee7SAntonio Huete Jimenez len -= 1;
268411677aeSAaron LI /* Dir Count */
269*ed775ee7SAntonio Huete Jimenez dircount = GET_U_1(cp);
270411677aeSAaron LI cp += 1;
271*ed775ee7SAntonio Huete Jimenez len -= 1;
272*ed775ee7SAntonio Huete Jimenez ND_PRINT(", Dir Count: %u", dircount);
273*ed775ee7SAntonio Huete Jimenez if (dircount * 8U > len)
274411677aeSAaron LI goto invalid;
275411677aeSAaron LI /* directives */
276411677aeSAaron LI for (i = 0; i < dircount; i++) {
277411677aeSAaron LI /* Reserved */
278411677aeSAaron LI cp += 1;
279*ed775ee7SAntonio Huete Jimenez len -= 1;
280411677aeSAaron LI /* DCmd */
281*ed775ee7SAntonio Huete Jimenez ND_PRINT("\n\t DCmd: %s",
282*ed775ee7SAntonio Huete Jimenez tok2str(aoev1_dcmd_str, "Unknown (0x%02x)", GET_U_1(cp)));
283411677aeSAaron LI cp += 1;
284*ed775ee7SAntonio Huete Jimenez len -= 1;
285411677aeSAaron LI /* Ethernet Address */
286*ed775ee7SAntonio Huete Jimenez ND_PRINT(", Ethernet Address: %s", GET_ETHERADDR_STRING(cp));
287*ed775ee7SAntonio Huete Jimenez cp += MAC_ADDR_LEN;
288*ed775ee7SAntonio Huete Jimenez len -= MAC_ADDR_LEN;
289411677aeSAaron LI }
290411677aeSAaron LI return;
291411677aeSAaron LI
292411677aeSAaron LI invalid:
293*ed775ee7SAntonio Huete Jimenez nd_print_invalid(ndo);
294*ed775ee7SAntonio Huete Jimenez ND_TCHECK_LEN(cp, len);
295411677aeSAaron LI }
296411677aeSAaron LI
297411677aeSAaron LI static void
aoev1_reserve_print(netdissect_options * ndo,const u_char * cp,u_int len)298411677aeSAaron LI aoev1_reserve_print(netdissect_options *ndo,
299*ed775ee7SAntonio Huete Jimenez const u_char *cp, u_int len)
300411677aeSAaron LI {
301411677aeSAaron LI uint8_t nmacs, i;
302411677aeSAaron LI
303*ed775ee7SAntonio Huete Jimenez if (len < AOEV1_RESERVE_ARG_LEN || (len - AOEV1_RESERVE_ARG_LEN) % MAC_ADDR_LEN)
304411677aeSAaron LI goto invalid;
305411677aeSAaron LI /* RCmd */
306*ed775ee7SAntonio Huete Jimenez ND_PRINT("\n\tRCmd: %s",
307*ed775ee7SAntonio Huete Jimenez tok2str(aoev1_rcmd_str, "Unknown (0x%02x)", GET_U_1(cp)));
308411677aeSAaron LI cp += 1;
309*ed775ee7SAntonio Huete Jimenez len -= 1;
310411677aeSAaron LI /* NMacs (correlated with the length) */
311*ed775ee7SAntonio Huete Jimenez nmacs = GET_U_1(cp);
312411677aeSAaron LI cp += 1;
313*ed775ee7SAntonio Huete Jimenez len -= 1;
314*ed775ee7SAntonio Huete Jimenez ND_PRINT(", NMacs: %u", nmacs);
315*ed775ee7SAntonio Huete Jimenez if (nmacs * MAC_ADDR_LEN != len)
316411677aeSAaron LI goto invalid;
317411677aeSAaron LI /* addresses */
318411677aeSAaron LI for (i = 0; i < nmacs; i++) {
319*ed775ee7SAntonio Huete Jimenez ND_PRINT("\n\tEthernet Address %u: %s", i, GET_ETHERADDR_STRING(cp));
320*ed775ee7SAntonio Huete Jimenez cp += MAC_ADDR_LEN;
321*ed775ee7SAntonio Huete Jimenez len -= MAC_ADDR_LEN;
322411677aeSAaron LI }
323411677aeSAaron LI return;
324411677aeSAaron LI
325411677aeSAaron LI invalid:
326*ed775ee7SAntonio Huete Jimenez nd_print_invalid(ndo);
327*ed775ee7SAntonio Huete Jimenez ND_TCHECK_LEN(cp, len);
328411677aeSAaron LI }
329411677aeSAaron LI
330411677aeSAaron LI /* cp points to the Ver/Flags octet */
331411677aeSAaron LI static void
aoev1_print(netdissect_options * ndo,const u_char * cp,u_int len)332411677aeSAaron LI aoev1_print(netdissect_options *ndo,
333*ed775ee7SAntonio Huete Jimenez const u_char *cp, u_int len)
334411677aeSAaron LI {
335411677aeSAaron LI uint8_t flags, command;
336*ed775ee7SAntonio Huete Jimenez void (*cmd_decoder)(netdissect_options *, const u_char *, u_int);
337411677aeSAaron LI
338411677aeSAaron LI if (len < AOEV1_COMMON_HDR_LEN)
339411677aeSAaron LI goto invalid;
340411677aeSAaron LI /* Flags */
341*ed775ee7SAntonio Huete Jimenez flags = GET_U_1(cp) & 0x0F;
342*ed775ee7SAntonio Huete Jimenez ND_PRINT(", Flags: [%s]", bittok2str(aoev1_flag_str, "none", flags));
343411677aeSAaron LI cp += 1;
344*ed775ee7SAntonio Huete Jimenez len -= 1;
345411677aeSAaron LI if (! ndo->ndo_vflag)
346411677aeSAaron LI return;
347411677aeSAaron LI /* Error */
348411677aeSAaron LI if (flags & AOEV1_FLAG_E)
349*ed775ee7SAntonio Huete Jimenez ND_PRINT("\n\tError: %s",
350*ed775ee7SAntonio Huete Jimenez tok2str(aoev1_errcode_str, "Invalid (%u)", GET_U_1(cp)));
351411677aeSAaron LI cp += 1;
352*ed775ee7SAntonio Huete Jimenez len -= 1;
353411677aeSAaron LI /* Major */
354*ed775ee7SAntonio Huete Jimenez ND_PRINT("\n\tMajor: 0x%04x", GET_BE_U_2(cp));
355411677aeSAaron LI cp += 2;
356*ed775ee7SAntonio Huete Jimenez len -= 2;
357411677aeSAaron LI /* Minor */
358*ed775ee7SAntonio Huete Jimenez ND_PRINT(", Minor: 0x%02x", GET_U_1(cp));
359411677aeSAaron LI cp += 1;
360*ed775ee7SAntonio Huete Jimenez len -= 1;
361411677aeSAaron LI /* Command */
362*ed775ee7SAntonio Huete Jimenez command = GET_U_1(cp);
363411677aeSAaron LI cp += 1;
364*ed775ee7SAntonio Huete Jimenez len -= 1;
365*ed775ee7SAntonio Huete Jimenez ND_PRINT(", Command: %s", tok2str(cmdcode_str, "Unknown (0x%02x)", command));
366411677aeSAaron LI /* Tag */
367*ed775ee7SAntonio Huete Jimenez ND_PRINT(", Tag: 0x%08x", GET_BE_U_4(cp));
368411677aeSAaron LI cp += 4;
369*ed775ee7SAntonio Huete Jimenez len -= 4;
370411677aeSAaron LI /* Arg */
371411677aeSAaron LI cmd_decoder =
372411677aeSAaron LI command == AOEV1_CMD_ISSUE_ATA_COMMAND ? aoev1_issue_print :
373411677aeSAaron LI command == AOEV1_CMD_QUERY_CONFIG_INFORMATION ? aoev1_query_print :
374411677aeSAaron LI command == AOEV1_CMD_MAC_MASK_LIST ? aoev1_mac_print :
375411677aeSAaron LI command == AOEV1_CMD_RESERVE_RELEASE ? aoev1_reserve_print :
376411677aeSAaron LI NULL;
377411677aeSAaron LI if (cmd_decoder != NULL)
378*ed775ee7SAntonio Huete Jimenez cmd_decoder(ndo, cp, len);
379411677aeSAaron LI return;
380411677aeSAaron LI
381411677aeSAaron LI invalid:
382*ed775ee7SAntonio Huete Jimenez nd_print_invalid(ndo);
383*ed775ee7SAntonio Huete Jimenez ND_TCHECK_LEN(cp, len);
384411677aeSAaron LI }
385411677aeSAaron LI
386411677aeSAaron LI void
aoe_print(netdissect_options * ndo,const u_char * cp,const u_int len)387411677aeSAaron LI aoe_print(netdissect_options *ndo,
388411677aeSAaron LI const u_char *cp, const u_int len)
389411677aeSAaron LI {
390411677aeSAaron LI uint8_t ver;
391411677aeSAaron LI
392*ed775ee7SAntonio Huete Jimenez ndo->ndo_protocol = "aoe";
393*ed775ee7SAntonio Huete Jimenez ND_PRINT("AoE length %u", len);
394411677aeSAaron LI
395411677aeSAaron LI if (len < 1)
396411677aeSAaron LI goto invalid;
397411677aeSAaron LI /* Ver/Flags */
398*ed775ee7SAntonio Huete Jimenez ver = (GET_U_1(cp) & 0xF0) >> 4;
399411677aeSAaron LI /* Don't advance cp yet: low order 4 bits are version-specific. */
400*ed775ee7SAntonio Huete Jimenez ND_PRINT(", Ver %u", ver);
401411677aeSAaron LI
402411677aeSAaron LI switch (ver) {
403411677aeSAaron LI case AOE_V1:
404411677aeSAaron LI aoev1_print(ndo, cp, len);
405411677aeSAaron LI break;
406411677aeSAaron LI }
407411677aeSAaron LI return;
408411677aeSAaron LI
409411677aeSAaron LI invalid:
410*ed775ee7SAntonio Huete Jimenez nd_print_invalid(ndo);
411*ed775ee7SAntonio Huete Jimenez ND_TCHECK_LEN(cp, len);
412411677aeSAaron LI }
413411677aeSAaron LI
414