1 /* packet-drbd.c
2 * Routines for DRBD dissection
3 * By Joel Colledge <joel.colledge@linbit.com>
4 * Copyright 2019, LINBIT Information Technologies GmbH
5 *
6 * Wireshark - Network traffic analyzer
7 * By Gerald Combs <gerald@wireshark.org>
8 * Copyright 1998 Gerald Combs
9 *
10 * SPDX-License-Identifier: GPL-2.0-or-later
11 */
12
13 /*
14 * Wireshark dissector for DRBD - Distributed Replicated Block Device.
15 * The DRBD Linux kernel module sources can be found at https://github.com/LINBIT/drbd-9.0
16 * More information about Linbit and DRBD can be found at https://www.linbit.com/
17 */
18
19 #include <config.h>
20
21 #include <epan/packet.h>
22 #include <epan/prefs.h>
23 #include <epan/dissectors/packet-tcp.h>
24
25 #include <wsutil/str_util.h>
26
27 typedef struct value_payload_decoder {
28 int value;
29 void (*decoder_fn)(tvbuff_t *, proto_tree*);
30 } value_payload_decoder;
31
32 /* Known as SHARED_SECRET_MAX in the DRBD sources */
33 #define DRBD_STRING_MAX 64
34
35 enum drbd_packet {
36 P_DATA = 0x00,
37 P_DATA_REPLY = 0x01,
38 P_RS_DATA_REPLY = 0x02,
39 P_BARRIER = 0x03,
40 P_BITMAP = 0x04,
41 P_BECOME_SYNC_TARGET = 0x05,
42 P_BECOME_SYNC_SOURCE = 0x06,
43 P_UNPLUG_REMOTE = 0x07,
44 P_DATA_REQUEST = 0x08,
45 P_RS_DATA_REQUEST = 0x09,
46 P_SYNC_PARAM = 0x0a,
47 P_PROTOCOL = 0x0b,
48 P_UUIDS = 0x0c,
49 P_SIZES = 0x0d,
50 P_STATE = 0x0e,
51 P_SYNC_UUID = 0x0f,
52 P_AUTH_CHALLENGE = 0x10,
53 P_AUTH_RESPONSE = 0x11,
54 P_STATE_CHG_REQ = 0x12,
55
56 P_PING = 0x13,
57 P_PING_ACK = 0x14,
58 P_RECV_ACK = 0x15,
59 P_WRITE_ACK = 0x16,
60 P_RS_WRITE_ACK = 0x17,
61 P_SUPERSEDED = 0x18,
62 P_NEG_ACK = 0x19,
63 P_NEG_DREPLY = 0x1a,
64 P_NEG_RS_DREPLY = 0x1b,
65 P_BARRIER_ACK = 0x1c,
66 P_STATE_CHG_REPLY = 0x1d,
67
68 P_OV_REQUEST = 0x1e,
69 P_OV_REPLY = 0x1f,
70 P_OV_RESULT = 0x20,
71 P_CSUM_RS_REQUEST = 0x21,
72 P_RS_IS_IN_SYNC = 0x22,
73 P_SYNC_PARAM89 = 0x23,
74 P_COMPRESSED_BITMAP = 0x24,
75
76 P_DELAY_PROBE = 0x27,
77 P_OUT_OF_SYNC = 0x28,
78 P_RS_CANCEL = 0x29,
79 P_CONN_ST_CHG_REQ = 0x2a,
80 P_CONN_ST_CHG_REPLY = 0x2b,
81 P_RETRY_WRITE = 0x2c,
82 P_PROTOCOL_UPDATE = 0x2d,
83 P_TWOPC_PREPARE = 0x2e,
84 P_TWOPC_ABORT = 0x2f,
85
86 P_DAGTAG = 0x30,
87
88 P_TRIM = 0x31,
89
90 P_RS_THIN_REQ = 0x32,
91 P_RS_DEALLOCATED = 0x33,
92
93 P_WSAME = 0x34,
94 P_TWOPC_PREP_RSZ = 0x35,
95 P_ZEROES = 0x36,
96
97 P_PEER_ACK = 0x40,
98 P_PEERS_IN_SYNC = 0x41,
99
100 P_UUIDS110 = 0x42,
101 P_PEER_DAGTAG = 0x43,
102 P_CURRENT_UUID = 0x44,
103
104 P_TWOPC_YES = 0x45,
105 P_TWOPC_NO = 0x46,
106 P_TWOPC_COMMIT = 0x47,
107 P_TWOPC_RETRY = 0x48,
108
109 P_CONFIRM_STABLE = 0x49,
110
111 P_INITIAL_META = 0xfff1,
112 P_INITIAL_DATA = 0xfff2,
113
114 P_CONNECTION_FEATURES = 0xfffe
115 };
116
117 static const value_string packet_names[] = {
118 { P_DATA, "P_DATA" },
119 { P_DATA_REPLY, "P_DATA_REPLY" },
120 { P_RS_DATA_REPLY, "P_RS_DATA_REPLY" },
121 { P_BARRIER, "P_BARRIER" },
122 { P_BITMAP, "P_BITMAP" },
123 { P_BECOME_SYNC_TARGET, "P_BECOME_SYNC_TARGET" },
124 { P_BECOME_SYNC_SOURCE, "P_BECOME_SYNC_SOURCE" },
125 { P_UNPLUG_REMOTE, "P_UNPLUG_REMOTE" },
126 { P_DATA_REQUEST, "P_DATA_REQUEST" },
127 { P_RS_DATA_REQUEST, "P_RS_DATA_REQUEST" },
128 { P_SYNC_PARAM, "P_SYNC_PARAM" },
129 { P_PROTOCOL, "P_PROTOCOL" },
130 { P_UUIDS, "P_UUIDS" },
131 { P_SIZES, "P_SIZES" },
132 { P_STATE, "P_STATE" },
133 { P_SYNC_UUID, "P_SYNC_UUID" },
134 { P_AUTH_CHALLENGE, "P_AUTH_CHALLENGE" },
135 { P_AUTH_RESPONSE, "P_AUTH_RESPONSE" },
136 { P_STATE_CHG_REQ, "P_STATE_CHG_REQ" },
137
138 { P_PING, "P_PING" },
139 { P_PING_ACK, "P_PING_ACK" },
140 { P_RECV_ACK, "P_RECV_ACK" },
141 { P_WRITE_ACK, "P_WRITE_ACK" },
142 { P_RS_WRITE_ACK, "P_RS_WRITE_ACK" },
143 { P_SUPERSEDED, "P_SUPERSEDED" },
144 { P_NEG_ACK, "P_NEG_ACK" },
145 { P_NEG_DREPLY, "P_NEG_DREPLY" },
146 { P_NEG_RS_DREPLY, "P_NEG_RS_DREPLY" },
147 { P_BARRIER_ACK, "P_BARRIER_ACK" },
148 { P_STATE_CHG_REPLY, "P_STATE_CHG_REPLY" },
149
150 { P_OV_REQUEST, "P_OV_REQUEST" },
151 { P_OV_REPLY, "P_OV_REPLY" },
152 { P_OV_RESULT, "P_OV_RESULT" },
153 { P_CSUM_RS_REQUEST, "P_CSUM_RS_REQUEST" },
154 { P_RS_IS_IN_SYNC, "P_RS_IS_IN_SYNC" },
155 { P_SYNC_PARAM89, "P_SYNC_PARAM89" },
156 { P_COMPRESSED_BITMAP, "P_COMPRESSED_BITMAP" },
157
158 { P_DELAY_PROBE, "P_DELAY_PROBE" },
159 { P_OUT_OF_SYNC, "P_OUT_OF_SYNC" },
160 { P_RS_CANCEL, "P_RS_CANCEL" },
161 { P_CONN_ST_CHG_REQ, "P_CONN_ST_CHG_REQ" },
162 { P_CONN_ST_CHG_REPLY, "P_CONN_ST_CHG_REPLY" },
163 { P_RETRY_WRITE, "P_RETRY_WRITE" },
164 { P_PROTOCOL_UPDATE, "P_PROTOCOL_UPDATE" },
165 { P_TWOPC_PREPARE, "P_TWOPC_PREPARE" },
166 { P_TWOPC_ABORT, "P_TWOPC_ABORT" },
167
168 { P_DAGTAG, "P_DAGTAG" },
169
170 { P_TRIM, "P_TRIM" },
171
172 { P_RS_THIN_REQ, "P_RS_THIN_REQ" },
173 { P_RS_DEALLOCATED, "P_RS_DEALLOCATED" },
174
175 { P_WSAME, "P_WSAME" },
176 { P_TWOPC_PREP_RSZ, "P_TWOPC_PREP_RSZ" },
177 { P_ZEROES, "P_ZEROES" },
178
179 { P_PEER_ACK, "P_PEER_ACK" },
180 { P_PEERS_IN_SYNC, "P_PEERS_IN_SYNC" },
181
182 { P_UUIDS110, "P_UUIDS110" },
183 { P_PEER_DAGTAG, "P_PEER_DAGTAG" },
184 { P_CURRENT_UUID, "P_CURRENT_UUID" },
185
186 { P_TWOPC_YES, "P_TWOPC_YES" },
187 { P_TWOPC_NO, "P_TWOPC_NO" },
188 { P_TWOPC_COMMIT, "P_TWOPC_COMMIT" },
189 { P_TWOPC_RETRY, "P_TWOPC_RETRY" },
190
191 { P_CONFIRM_STABLE, "P_CONFIRM_STABLE" },
192
193 { P_INITIAL_META, "P_INITIAL_META" },
194 { P_INITIAL_DATA, "P_INITIAL_DATA" },
195
196 { P_CONNECTION_FEATURES, "P_CONNECTION_FEATURES" },
197 { 0, NULL }
198 };
199
200 #define DRBD_PROT_A 1
201 #define DRBD_PROT_B 2
202 #define DRBD_PROT_C 3
203
204 static const value_string protocol_names[] = {
205 { DRBD_PROT_A, "A" },
206 { DRBD_PROT_B, "B" },
207 { DRBD_PROT_C, "C" },
208 { 0, NULL }
209 };
210
211 #define DRBD_ROLE_UNKNOWN 0
212 #define DRBD_ROLE_PRIMARY 1
213 #define DRBD_ROLE_SECONDARY 2
214
215 static const value_string role_names[] = {
216 { DRBD_ROLE_UNKNOWN, "UNKNOWN" },
217 { DRBD_ROLE_PRIMARY, "PRIMARY" },
218 { DRBD_ROLE_SECONDARY, "SECONDARY" },
219 { 0, NULL }
220 };
221
222 #define DRBD_CONNECTION_STATE_C_STANDALONE 0
223 #define DRBD_CONNECTION_STATE_C_DISCONNECTING 1
224 #define DRBD_CONNECTION_STATE_C_UNCONNECTED 2
225 #define DRBD_CONNECTION_STATE_C_TIMEOUT 3
226 #define DRBD_CONNECTION_STATE_C_BROKEN_PIPE 4
227 #define DRBD_CONNECTION_STATE_C_NETWORK_FAILURE 5
228 #define DRBD_CONNECTION_STATE_C_PROTOCOL_ERROR 6
229 #define DRBD_CONNECTION_STATE_C_TEAR_DOWN 7
230 #define DRBD_CONNECTION_STATE_C_CONNECTING 8
231 #define DRBD_CONNECTION_STATE_C_CONNECTED 9
232 #define DRBD_CONNECTION_STATE_L_ESTABLISHED 10
233 #define DRBD_CONNECTION_STATE_L_STARTING_SYNC_S 11
234 #define DRBD_CONNECTION_STATE_L_STARTING_SYNC_T 12
235 #define DRBD_CONNECTION_STATE_L_WF_BITMAP_S 13
236 #define DRBD_CONNECTION_STATE_L_WF_BITMAP_T 14
237 #define DRBD_CONNECTION_STATE_L_WF_SYNC_UUID 15
238 #define DRBD_CONNECTION_STATE_L_SYNC_SOURCE 16
239 #define DRBD_CONNECTION_STATE_L_SYNC_TARGET 17
240 #define DRBD_CONNECTION_STATE_L_VERIFY_S 18
241 #define DRBD_CONNECTION_STATE_L_VERIFY_T 19
242 #define DRBD_CONNECTION_STATE_L_PAUSED_SYNC_S 20
243 #define DRBD_CONNECTION_STATE_L_PAUSED_SYNC_T 21
244 #define DRBD_CONNECTION_STATE_L_AHEAD 22
245 #define DRBD_CONNECTION_STATE_L_BEHIND 23
246
247 static const value_string connection_state_names[] = {
248 { DRBD_CONNECTION_STATE_C_STANDALONE, "C_STANDALONE" },
249 { DRBD_CONNECTION_STATE_C_DISCONNECTING, "C_DISCONNECTING" },
250 { DRBD_CONNECTION_STATE_C_UNCONNECTED, "C_UNCONNECTED" },
251 { DRBD_CONNECTION_STATE_C_TIMEOUT, "C_TIMEOUT" },
252 { DRBD_CONNECTION_STATE_C_BROKEN_PIPE, "C_BROKEN_PIPE" },
253 { DRBD_CONNECTION_STATE_C_NETWORK_FAILURE, "C_NETWORK_FAILURE" },
254 { DRBD_CONNECTION_STATE_C_PROTOCOL_ERROR, "C_PROTOCOL_ERROR" },
255 { DRBD_CONNECTION_STATE_C_TEAR_DOWN, "C_TEAR_DOWN" },
256 { DRBD_CONNECTION_STATE_C_CONNECTING, "C_CONNECTING" },
257 { DRBD_CONNECTION_STATE_C_CONNECTED, "C_CONNECTED" },
258 { DRBD_CONNECTION_STATE_L_ESTABLISHED, "L_ESTABLISHED" },
259 { DRBD_CONNECTION_STATE_L_STARTING_SYNC_S, "L_STARTING_SYNC_S" },
260 { DRBD_CONNECTION_STATE_L_STARTING_SYNC_T, "L_STARTING_SYNC_T" },
261 { DRBD_CONNECTION_STATE_L_WF_BITMAP_S, "L_WF_BITMAP_S" },
262 { DRBD_CONNECTION_STATE_L_WF_BITMAP_T, "L_WF_BITMAP_T" },
263 { DRBD_CONNECTION_STATE_L_WF_SYNC_UUID, "L_WF_SYNC_UUID" },
264 { DRBD_CONNECTION_STATE_L_SYNC_SOURCE, "L_SYNC_SOURCE" },
265 { DRBD_CONNECTION_STATE_L_SYNC_TARGET, "L_SYNC_TARGET" },
266 { DRBD_CONNECTION_STATE_L_VERIFY_S, "L_VERIFY_S" },
267 { DRBD_CONNECTION_STATE_L_VERIFY_T, "L_VERIFY_T" },
268 { DRBD_CONNECTION_STATE_L_PAUSED_SYNC_S, "L_PAUSED_SYNC_S" },
269 { DRBD_CONNECTION_STATE_L_PAUSED_SYNC_T, "L_PAUSED_SYNC_T" },
270 { DRBD_CONNECTION_STATE_L_AHEAD, "L_AHEAD" },
271 { DRBD_CONNECTION_STATE_L_BEHIND, "L_BEHIND" },
272 { 0, NULL }
273 };
274
275 #define DRBD_DISK_STATE_DISKLESS 0
276 #define DRBD_DISK_STATE_ATTACHING 1
277 #define DRBD_DISK_STATE_DETACHING 2
278 #define DRBD_DISK_STATE_FAILED 3
279 #define DRBD_DISK_STATE_NEGOTIATING 4
280 #define DRBD_DISK_STATE_INCONSISTENT 5
281 #define DRBD_DISK_STATE_OUTDATED 6
282 #define DRBD_DISK_STATE_UNKNOWN 7
283 #define DRBD_DISK_STATE_CONSISTENT 8
284 #define DRBD_DISK_STATE_UP_TO_DATE 9
285
286 static const value_string disk_state_names[] = {
287 { DRBD_DISK_STATE_DISKLESS, "D_DISKLESS" },
288 { DRBD_DISK_STATE_ATTACHING, "D_ATTACHING" },
289 { DRBD_DISK_STATE_DETACHING, "D_DETACHING" },
290 { DRBD_DISK_STATE_FAILED, "D_FAILED" },
291 { DRBD_DISK_STATE_NEGOTIATING, "D_NEGOTIATING" },
292 { DRBD_DISK_STATE_INCONSISTENT, "D_INCONSISTENT" },
293 { DRBD_DISK_STATE_OUTDATED, "D_OUTDATED" },
294 { DRBD_DISK_STATE_UNKNOWN, "D_UNKNOWN" },
295 { DRBD_DISK_STATE_CONSISTENT, "D_CONSISTENT" },
296 { DRBD_DISK_STATE_UP_TO_DATE, "D_UP_TO_DATE" },
297 { 0, NULL }
298 };
299
300 #define STATE_ROLE (0x3 << 0) /* 3/4 primary/secondary/unknown */
301 #define STATE_PEER (0x3 << 2) /* 3/4 primary/secondary/unknown */
302 #define STATE_CONN (0x1f << 4) /* 17/32 cstates */
303 #define STATE_DISK (0xf << 9) /* 8/16 from D_DISKLESS to D_UP_TO_DATE */
304 #define STATE_PDSK (0xf << 13) /* 8/16 from D_DISKLESS to D_UP_TO_DATE */
305 #define STATE_SUSP (0x1 << 17) /* 2/2 IO suspended no/yes (by user) */
306 #define STATE_AFTR_ISP (0x1 << 18) /* isp .. imposed sync pause */
307 #define STATE_PEER_ISP (0x1 << 19)
308 #define STATE_USER_ISP (0x1 << 20)
309 #define STATE_SUSP_NOD (0x1 << 21) /* IO suspended because no data */
310 #define STATE_SUSP_FEN (0x1 << 22) /* IO suspended because fence peer handler runs*/
311 #define STATE_QUORUM (0x1 << 23)
312
313 #define UUID_FLAG_DISCARD_MY_DATA 1
314 #define UUID_FLAG_CRASHED_PRIMARY 2
315 #define UUID_FLAG_INCONSISTENT 4
316 #define UUID_FLAG_SKIP_INITIAL_SYNC 8
317 #define UUID_FLAG_NEW_DATAGEN 16
318 #define UUID_FLAG_STABLE 32
319 #define UUID_FLAG_GOT_STABLE 64
320 #define UUID_FLAG_RESYNC 128
321 #define UUID_FLAG_RECONNECT 256
322 #define UUID_FLAG_DISKLESS_PRIMARY 512
323 #define UUID_FLAG_PRIMARY_LOST_QUORUM 1024
324
325 #define DP_HARDBARRIER 1
326 #define DP_RW_SYNC 2
327 #define DP_MAY_SET_IN_SYNC 4
328 #define DP_UNPLUG 8
329 #define DP_FUA 16
330 #define DP_FLUSH 32
331 #define DP_DISCARD 64
332 #define DP_SEND_RECEIVE_ACK 128
333 #define DP_SEND_WRITE_ACK 256
334 #define DP_WSAME 512
335 #define DP_ZEROES 1024
336
337 static void dissect_drbd_message(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree);
338
339 static void decode_payload_connection_features(tvbuff_t *tvb, proto_tree *tree);
340 static void decode_payload_auth_challenge(tvbuff_t *tvb, proto_tree *tree);
341 static void decode_payload_auth_response(tvbuff_t *tvb, proto_tree *tree);
342 static void decode_payload_data(tvbuff_t *tvb, proto_tree *tree);
343 static void decode_payload_data_reply(tvbuff_t *tvb, proto_tree *tree);
344 static void decode_payload_rs_data_reply(tvbuff_t *tvb, proto_tree *tree);
345 static void decode_payload_barrier(tvbuff_t *tvb, proto_tree *tree);
346 static void decode_payload_data_request(tvbuff_t *tvb, proto_tree *tree);
347 static void decode_payload_sync_param(tvbuff_t *tvb, proto_tree *tree);
348 static void decode_payload_protocol(tvbuff_t *tvb, proto_tree *tree);
349 static void decode_payload_uuids(tvbuff_t *tvb, proto_tree *tree);
350 static void decode_payload_sizes(tvbuff_t *tvb, proto_tree *tree);
351 static void decode_payload_state(tvbuff_t *tvb, proto_tree *tree);
352 static void decode_payload_req_state(tvbuff_t *tvb, proto_tree *tree);
353 static void decode_payload_sync_uuid(tvbuff_t *tvb, proto_tree *tree);
354 static void decode_payload_skip(tvbuff_t *tvb, proto_tree *tree);
355 static void decode_payload_out_of_sync(tvbuff_t *tvb, proto_tree *tree);
356 static void decode_payload_twopc(tvbuff_t *tvb, proto_tree *tree);
357 static void decode_payload_dagtag(tvbuff_t *tvb, proto_tree *tree);
358 static void decode_payload_uuids110(tvbuff_t *tvb, proto_tree *tree);
359 static void decode_payload_peer_dagtag(tvbuff_t *tvb, proto_tree *tree);
360 static void decode_payload_current_uuid(tvbuff_t *tvb, proto_tree *tree);
361 static void decode_payload_data_size(tvbuff_t *tvb, proto_tree *tree);
362 static void decode_payload_data_wsame(tvbuff_t *tvb, proto_tree *tree);
363 static void decode_payload_rs_deallocated(tvbuff_t *tvb, proto_tree *tree);
364
365 static void decode_payload_block_ack(tvbuff_t *tvb, proto_tree *tree);
366 static void decode_payload_barrier_ack(tvbuff_t *tvb, proto_tree *tree);
367 static void decode_payload_confirm_stable(tvbuff_t *tvb, proto_tree *tree);
368 static void decode_payload_rq_s_reply(tvbuff_t *tvb, proto_tree *tree);
369 static void decode_payload_peer_ack(tvbuff_t *tvb, proto_tree *tree);
370 static void decode_payload_peers_in_sync(tvbuff_t *tvb, proto_tree *tree);
371 static void decode_payload_twopc_reply(tvbuff_t *tvb, proto_tree *tree);
372
373 static const value_payload_decoder payload_decoders[] = {
374 { P_CONNECTION_FEATURES, decode_payload_connection_features },
375 { P_AUTH_CHALLENGE, decode_payload_auth_challenge },
376 { P_AUTH_RESPONSE, decode_payload_auth_response },
377 { P_DATA, decode_payload_data },
378 { P_DATA_REPLY, decode_payload_data_reply },
379 { P_RS_DATA_REPLY, decode_payload_rs_data_reply },
380 { P_BARRIER, decode_payload_barrier },
381 { P_BITMAP, NULL }, /* TODO: decode additional data */
382 { P_COMPRESSED_BITMAP, NULL }, /* TODO: decode additional data */
383 { P_UNPLUG_REMOTE, NULL },
384 { P_DATA_REQUEST, decode_payload_data_request },
385 { P_RS_DATA_REQUEST, decode_payload_data_request },
386 { P_SYNC_PARAM, decode_payload_sync_param },
387 { P_SYNC_PARAM89, decode_payload_sync_param },
388 { P_PROTOCOL, decode_payload_protocol },
389 { P_UUIDS, decode_payload_uuids },
390 { P_SIZES, decode_payload_sizes },
391 { P_STATE, decode_payload_state },
392 { P_STATE_CHG_REQ, decode_payload_req_state },
393 { P_SYNC_UUID, decode_payload_sync_uuid },
394 { P_OV_REQUEST, decode_payload_data_request },
395 { P_OV_REPLY, decode_payload_data_request }, /* TODO: decode additional data */
396 { P_CSUM_RS_REQUEST, decode_payload_data_request }, /* TODO: decode additional data */
397 { P_RS_THIN_REQ, decode_payload_data_request },
398 { P_DELAY_PROBE, decode_payload_skip },
399 { P_OUT_OF_SYNC, decode_payload_out_of_sync },
400 { P_CONN_ST_CHG_REQ, decode_payload_req_state },
401 { P_PROTOCOL_UPDATE, decode_payload_protocol }, /* TODO: decode additional data */
402 { P_TWOPC_PREPARE, decode_payload_twopc },
403 { P_TWOPC_PREP_RSZ, decode_payload_twopc },
404 { P_TWOPC_ABORT, decode_payload_twopc },
405 { P_DAGTAG, decode_payload_dagtag },
406 { P_UUIDS110, decode_payload_uuids110 },
407 { P_PEER_DAGTAG, decode_payload_peer_dagtag },
408 { P_CURRENT_UUID, decode_payload_current_uuid },
409 { P_TWOPC_COMMIT, decode_payload_twopc },
410 { P_TRIM, decode_payload_data_size },
411 { P_ZEROES, decode_payload_data_size },
412 { P_RS_DEALLOCATED, decode_payload_rs_deallocated },
413 { P_WSAME, decode_payload_data_wsame },
414
415 { P_PING, NULL },
416 { P_PING_ACK, NULL },
417 { P_RECV_ACK, decode_payload_block_ack },
418 { P_WRITE_ACK, decode_payload_block_ack },
419 { P_RS_WRITE_ACK, decode_payload_block_ack },
420 { P_SUPERSEDED, decode_payload_block_ack },
421 { P_NEG_ACK, decode_payload_block_ack },
422 { P_NEG_DREPLY, decode_payload_block_ack },
423 { P_NEG_RS_DREPLY, decode_payload_block_ack },
424 { P_OV_RESULT, decode_payload_block_ack },
425 { P_BARRIER_ACK, decode_payload_barrier_ack },
426 { P_CONFIRM_STABLE, decode_payload_confirm_stable },
427 { P_STATE_CHG_REPLY, decode_payload_rq_s_reply },
428 { P_RS_IS_IN_SYNC, decode_payload_block_ack },
429 { P_DELAY_PROBE, decode_payload_skip },
430 { P_RS_CANCEL, decode_payload_block_ack },
431 { P_CONN_ST_CHG_REPLY, decode_payload_rq_s_reply },
432 { P_RETRY_WRITE, decode_payload_block_ack },
433 { P_PEER_ACK, decode_payload_peer_ack },
434 { P_PEERS_IN_SYNC, decode_payload_peers_in_sync },
435 { P_TWOPC_YES, decode_payload_twopc_reply },
436 { P_TWOPC_NO, decode_payload_twopc_reply },
437 { P_TWOPC_RETRY, decode_payload_twopc_reply },
438 };
439
440
441 void proto_register_drbd(void);
442 void proto_reg_handoff_drbd(void);
443
444 static dissector_handle_t drbd_handle;
445
446 static int proto_drbd = -1;
447
448 static int hf_drbd_command = -1;
449 static int hf_drbd_length = -1;
450 static int hf_drbd_volume = -1;
451 static int hf_drbd_auth_challenge_nonce = -1;
452 static int hf_drbd_auth_response_hash = -1;
453 static int hf_drbd_sector = -1;
454 static int hf_drbd_block_id = -1;
455 static int hf_drbd_seq_num = -1;
456 static int hf_drbd_dp_flags = -1;
457 static int hf_drbd_data = -1;
458 static int hf_drbd_size = -1;
459 static int hf_drbd_blksize = -1;
460 static int hf_drbd_protocol_min = -1;
461 static int hf_drbd_feature_flags = -1;
462 static int hf_drbd_protocol_max = -1;
463 static int hf_drbd_sender_node_id = -1;
464 static int hf_drbd_receiver_node_id = -1;
465 static int hf_drbd_barrier = -1;
466 static int hf_drbd_set_size = -1;
467 static int hf_drbd_oldest_block_id = -1;
468 static int hf_drbd_youngest_block_id = -1;
469 static int hf_drbd_resync_rate = -1;
470 static int hf_drbd_verify_alg = -1;
471 static int hf_drbd_csums_alg = -1;
472 static int hf_drbd_c_plan_ahead = -1;
473 static int hf_drbd_c_delay_target = -1;
474 static int hf_drbd_c_fill_target = -1;
475 static int hf_drbd_c_max_rate = -1;
476 static int hf_drbd_protocol = -1;
477 static int hf_drbd_after_sb_0p = -1;
478 static int hf_drbd_after_sb_1p = -1;
479 static int hf_drbd_after_sb_2p = -1;
480 static int hf_drbd_conn_flags = -1;
481 static int hf_drbd_two_primaries = -1;
482 static int hf_drbd_integrity_alg = -1;
483 static int hf_drbd_current_uuid = -1;
484 static int hf_drbd_bitmap_uuid = -1;
485 static int hf_drbd_history_uuid_list = -1;
486 static int hf_drbd_history_uuid = -1;
487 static int hf_drbd_dirty_bits = -1;
488 static int hf_drbd_uuid_flags = -1;
489 static int hf_drbd_node_mask = -1;
490 static int hf_drbd_bitmap_uuids_mask = -1;
491 static int hf_drbd_uuid = -1;
492 static int hf_drbd_weak_nodes = -1;
493 static int hf_drbd_physical_block_size = -1;
494 static int hf_drbd_logical_block_size = -1;
495 static int hf_drbd_alignment_offset = -1;
496 static int hf_drbd_io_min = -1;
497 static int hf_drbd_io_opt = -1;
498 static int hf_drbd_discard_enabled = -1;
499 static int hf_drbd_discard_zeroes_data = -1;
500 static int hf_drbd_write_same_capable = -1;
501 static int hf_drbd_d_size = -1;
502 static int hf_drbd_u_size = -1;
503 static int hf_drbd_c_size = -1;
504 static int hf_drbd_max_bio_size = -1;
505 static int hf_drbd_queue_order_type = -1;
506 static int hf_drbd_dds_flags = -1;
507 static int hf_drbd_state = -1;
508 static int hf_drbd_mask = -1;
509 static int hf_drbd_val = -1;
510 static int hf_drbd_retcode = -1;
511 static int hf_drbd_tid = -1;
512 static int hf_drbd_initiator_node_id = -1;
513 static int hf_drbd_target_node_id = -1;
514 static int hf_drbd_nodes_to_reach = -1;
515 static int hf_drbd_reachable_nodes = -1;
516 static int hf_drbd_offset = -1;
517 static int hf_drbd_dagtag = -1;
518 static int hf_drbd_node_id = -1;
519
520 static int hf_drbd_state_role = -1;
521 static int hf_drbd_state_peer = -1;
522 static int hf_drbd_state_conn = -1;
523 static int hf_drbd_state_disk = -1;
524 static int hf_drbd_state_pdsk = -1;
525 static int hf_drbd_state_susp = -1;
526 static int hf_drbd_state_aftr_isp = -1;
527 static int hf_drbd_state_peer_isp = -1;
528 static int hf_drbd_state_user_isp = -1;
529 static int hf_drbd_state_susp_nod = -1;
530 static int hf_drbd_state_susp_fen = -1;
531 static int hf_drbd_state_quorum = -1;
532
533 static int hf_drbd_uuid_flag_discard_my_data = -1;
534 static int hf_drbd_uuid_flag_crashed_primary = -1;
535 static int hf_drbd_uuid_flag_inconsistent = -1;
536 static int hf_drbd_uuid_flag_skip_initial_sync = -1;
537 static int hf_drbd_uuid_flag_new_datagen = -1;
538 static int hf_drbd_uuid_flag_stable = -1;
539 static int hf_drbd_uuid_flag_got_stable = -1;
540 static int hf_drbd_uuid_flag_resync = -1;
541 static int hf_drbd_uuid_flag_reconnect = -1;
542 static int hf_drbd_uuid_flag_diskless_primary = -1;
543 static int hf_drbd_uuid_flag_primary_lost_quorum = -1;
544
545 static int hf_drbd_dp_hardbarrier = -1;
546 static int hf_drbd_dp_rw_sync = -1;
547 static int hf_drbd_dp_may_set_in_sync = -1;
548 static int hf_drbd_dp_unplug = -1;
549 static int hf_drbd_dp_fua = -1;
550 static int hf_drbd_dp_flush = -1;
551 static int hf_drbd_dp_discard = -1;
552 static int hf_drbd_dp_send_receive_ack = -1;
553 static int hf_drbd_dp_send_write_ack = -1;
554 static int hf_drbd_dp_wsame = -1;
555 static int hf_drbd_dp_zeroes = -1;
556
557 static gint ett_drbd = -1;
558 static gint ett_drbd_state = -1;
559 static gint ett_drbd_uuid_flags = -1;
560 static gint ett_drbd_history_uuids = -1;
561 static gint ett_drbd_data_flags = -1;
562
563 static int * const state_fields[] = {
564 &hf_drbd_state_role,
565 &hf_drbd_state_peer,
566 &hf_drbd_state_conn,
567 &hf_drbd_state_disk,
568 &hf_drbd_state_pdsk,
569 &hf_drbd_state_susp,
570 &hf_drbd_state_aftr_isp,
571 &hf_drbd_state_peer_isp,
572 &hf_drbd_state_user_isp,
573 &hf_drbd_state_susp_nod,
574 &hf_drbd_state_susp_fen,
575 &hf_drbd_state_quorum,
576 NULL
577 };
578
579 static int * const uuid_flag_fields[] = {
580 &hf_drbd_uuid_flag_discard_my_data,
581 &hf_drbd_uuid_flag_crashed_primary,
582 &hf_drbd_uuid_flag_inconsistent,
583 &hf_drbd_uuid_flag_skip_initial_sync,
584 &hf_drbd_uuid_flag_new_datagen,
585 &hf_drbd_uuid_flag_stable,
586 &hf_drbd_uuid_flag_got_stable,
587 &hf_drbd_uuid_flag_resync,
588 &hf_drbd_uuid_flag_reconnect,
589 &hf_drbd_uuid_flag_diskless_primary,
590 &hf_drbd_uuid_flag_primary_lost_quorum,
591 NULL
592 };
593
594 static int * const data_flag_fields[] = {
595 &hf_drbd_dp_hardbarrier,
596 &hf_drbd_dp_rw_sync,
597 &hf_drbd_dp_may_set_in_sync,
598 &hf_drbd_dp_unplug,
599 &hf_drbd_dp_fua,
600 &hf_drbd_dp_flush,
601 &hf_drbd_dp_discard,
602 &hf_drbd_dp_send_receive_ack,
603 &hf_drbd_dp_send_write_ack,
604 &hf_drbd_dp_wsame,
605 &hf_drbd_dp_zeroes,
606 NULL
607 };
608
609 #define CHALLENGE_LEN 64
610
is_bit_set_64(guint64 value,int bit)611 static gboolean is_bit_set_64(guint64 value, int bit) {
612 return !!(value & (G_GUINT64_CONSTANT(1) << bit));
613 }
614
615 /*
616 * Length of the frame header.
617 */
618 #define DRBD_FRAME_HEADER_80_LEN 8
619 #define DRBD_FRAME_HEADER_95_LEN 8
620 #define DRBD_FRAME_HEADER_100_LEN 16
621
622 #define DRBD_MAGIC 0x83740267
623 #define DRBD_MAGIC_BIG 0x835a
624 #define DRBD_MAGIC_100 0x8620ec20
625
get_drbd_pdu_len(packet_info * pinfo _U_,tvbuff_t * tvb,int offset,void * data _U_)626 static guint get_drbd_pdu_len(packet_info *pinfo _U_, tvbuff_t *tvb, int offset, void *data _U_)
627 {
628 guint32 magic32;
629 guint16 magic16;
630
631 magic32 = tvb_get_ntohl(tvb, offset);
632
633 if (magic32 == DRBD_MAGIC)
634 return DRBD_FRAME_HEADER_80_LEN + tvb_get_ntohs(tvb, offset + 6);
635
636 if (tvb_reported_length_remaining(tvb, offset) >= DRBD_FRAME_HEADER_100_LEN && magic32 == DRBD_MAGIC_100)
637 return DRBD_FRAME_HEADER_100_LEN + tvb_get_ntohl(tvb, offset + 8);
638
639 magic16 = tvb_get_ntohs(tvb, offset);
640
641 if (magic16 == DRBD_MAGIC_BIG)
642 return DRBD_FRAME_HEADER_95_LEN + tvb_get_ntohl(tvb, offset + 4);
643
644 return 0;
645 }
646
dissect_drbd_pdu(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree _U_,void * data _U_)647 static int dissect_drbd_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree _U_, void* data _U_)
648 {
649 dissect_drbd_message(tvb, pinfo, tree);
650 return tvb_reported_length(tvb);
651 }
652
dissect_drbd(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,void * data)653 static int dissect_drbd(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data)
654 {
655 col_set_str(pinfo->cinfo, COL_PROTOCOL, "DRBD");
656 tcp_dissect_pdus(tvb, pinfo, tree, TRUE, DRBD_FRAME_HEADER_80_LEN,
657 get_drbd_pdu_len, dissect_drbd_pdu, data);
658 return tvb_reported_length(tvb);
659 }
660
test_drbd_protocol(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,void * data _U_)661 static gboolean test_drbd_protocol(tvbuff_t *tvb, packet_info *pinfo,
662 proto_tree *tree, void *data _U_)
663 {
664 guint reported_length = tvb_reported_length(tvb);
665 if (reported_length < DRBD_FRAME_HEADER_80_LEN || tvb_captured_length(tvb) < 4) {
666 return FALSE;
667 }
668
669 gboolean match = FALSE;
670 guint32 magic32 = tvb_get_ntohl(tvb, 0);
671
672 if (magic32 == DRBD_MAGIC)
673 match = TRUE;
674 else if (reported_length >= DRBD_FRAME_HEADER_100_LEN && magic32 == DRBD_MAGIC_100)
675 match = TRUE;
676 else {
677 guint16 magic16 = tvb_get_ntohs(tvb, 0);
678 if (magic16 == DRBD_MAGIC_BIG)
679 match = TRUE;
680 }
681
682 if (match) {
683 conversation_t *conversation = find_or_create_conversation(pinfo);
684 conversation_set_dissector(conversation, drbd_handle);
685 dissect_drbd(tvb, pinfo, tree, data);
686 }
687
688 return match;
689 }
690
691 /**
692 * Returns buffer containing the payload.
693 */
decode_header(tvbuff_t * tvb,proto_tree * pt,guint16 * command)694 static tvbuff_t *decode_header(tvbuff_t *tvb, proto_tree *pt, guint16 *command)
695 {
696 guint32 magic32;
697 guint16 magic16;
698
699 magic32 = tvb_get_ntohl(tvb, 0);
700
701 if (magic32 == DRBD_MAGIC) {
702 *command = tvb_get_ntohs(tvb, 4);
703
704 proto_tree_add_item(pt, hf_drbd_command, tvb, 4, 2, ENC_BIG_ENDIAN);
705 proto_tree_add_item(pt, hf_drbd_length, tvb, 6, 2, ENC_BIG_ENDIAN);
706
707 return tvb_new_subset_remaining(tvb, DRBD_FRAME_HEADER_80_LEN);
708 }
709
710 if (tvb_reported_length(tvb) >= DRBD_FRAME_HEADER_100_LEN && magic32 == DRBD_MAGIC_100) {
711 *command = tvb_get_ntohs(tvb, 6);
712
713 proto_tree_add_item(pt, hf_drbd_volume, tvb, 4, 2, ENC_BIG_ENDIAN);
714 proto_tree_add_item(pt, hf_drbd_command, tvb, 6, 2, ENC_BIG_ENDIAN);
715 proto_tree_add_item(pt, hf_drbd_length, tvb, 8, 4, ENC_BIG_ENDIAN);
716
717 return tvb_new_subset_remaining(tvb, DRBD_FRAME_HEADER_100_LEN);
718 }
719
720 magic16 = tvb_get_ntohs(tvb, 0);
721
722 if (magic16 == DRBD_MAGIC_BIG) {
723 *command = tvb_get_ntohs(tvb, 2);
724
725 proto_tree_add_item(pt, hf_drbd_command, tvb, 2, 2, ENC_BIG_ENDIAN);
726 proto_tree_add_item(pt, hf_drbd_length, tvb, 4, 4, ENC_BIG_ENDIAN);
727
728 return tvb_new_subset_remaining(tvb, DRBD_FRAME_HEADER_95_LEN);
729 }
730
731 return NULL;
732 }
733
dissect_drbd_message(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree)734 static void dissect_drbd_message(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
735 {
736 proto_tree *drbd_tree;
737 proto_item *ti;
738 guint16 command = -1;
739
740 col_set_str(pinfo->cinfo, COL_PROTOCOL, "DRBD");
741 col_clear(pinfo->cinfo, COL_INFO);
742
743 ti = proto_tree_add_item(tree, proto_drbd, tvb, 0, -1, ENC_NA);
744 drbd_tree = proto_item_add_subtree(ti, ett_drbd);
745
746 tvbuff_t *payload_tvb = decode_header(tvb, drbd_tree, &command);
747
748 if (!payload_tvb)
749 return;
750
751 /*
752 * Indicate what kind of message this is.
753 */
754 const gchar *packet_name = val_to_str(command, packet_names, "Unknown (0x%02x)");
755 const gchar *info_text = col_get_text(pinfo->cinfo, COL_INFO);
756 if (!info_text || !info_text[0]) {
757 col_append_ports(pinfo->cinfo, COL_INFO, PT_TCP, pinfo->srcport, pinfo->destport);
758 col_append_fstr(pinfo->cinfo, COL_INFO, " [%s]", packet_name);
759 } else {
760 col_append_sep_fstr(pinfo->cinfo, COL_INFO, " ", "[%s]", packet_name);
761 }
762 col_set_fence(pinfo->cinfo, COL_INFO);
763
764 if (tree == NULL)
765 return;
766
767 proto_item_set_text(ti, "DRBD [%s]", packet_name);
768
769 const value_payload_decoder *payload_decoder = NULL;
770 for (unsigned int i = 0; i < array_length(payload_decoders); i++) {
771 if (payload_decoders[i].value == command) {
772 payload_decoder = &payload_decoders[i];
773 break;
774 }
775 }
776
777 if (payload_decoder && payload_decoder->decoder_fn)
778 (*payload_decoder->decoder_fn) (payload_tvb, drbd_tree);
779 }
780
decode_payload_connection_features(tvbuff_t * tvb,proto_tree * tree)781 static void decode_payload_connection_features(tvbuff_t *tvb, proto_tree *tree)
782 {
783 proto_tree_add_item(tree, hf_drbd_protocol_min, tvb, 0, 4, ENC_BIG_ENDIAN);
784 proto_tree_add_item(tree, hf_drbd_feature_flags, tvb, 4, 4, ENC_BIG_ENDIAN);
785 proto_tree_add_item(tree, hf_drbd_protocol_max, tvb, 8, 4, ENC_BIG_ENDIAN);
786 proto_tree_add_item(tree, hf_drbd_sender_node_id, tvb, 12, 4, ENC_BIG_ENDIAN);
787 proto_tree_add_item(tree, hf_drbd_receiver_node_id, tvb, 16, 4, ENC_BIG_ENDIAN);
788 }
789
decode_payload_auth_challenge(tvbuff_t * tvb _U_,proto_tree * tree _U_)790 static void decode_payload_auth_challenge(tvbuff_t *tvb _U_, proto_tree *tree _U_)
791 {
792 proto_tree_add_bytes_format(tree, hf_drbd_auth_challenge_nonce, tvb, 0, CHALLENGE_LEN, NULL, "Nonce");
793 }
794
decode_payload_auth_response(tvbuff_t * tvb _U_,proto_tree * tree _U_)795 static void decode_payload_auth_response(tvbuff_t *tvb _U_, proto_tree *tree _U_)
796 {
797 proto_tree_add_bytes_format(tree, hf_drbd_auth_response_hash, tvb, 0, -1, NULL, "Hash");
798 }
799
decode_data_common(tvbuff_t * tvb,proto_tree * tree)800 static void decode_data_common(tvbuff_t *tvb, proto_tree *tree)
801 {
802 proto_tree_add_item(tree, hf_drbd_sector, tvb, 0, 8, ENC_BIG_ENDIAN);
803 proto_tree_add_item(tree, hf_drbd_block_id, tvb, 8, 8, ENC_BIG_ENDIAN);
804 proto_tree_add_item(tree, hf_drbd_seq_num, tvb, 16, 4, ENC_BIG_ENDIAN);
805 proto_tree_add_bitmask(tree, tvb, 20, hf_drbd_dp_flags, ett_drbd_data_flags, data_flag_fields, ENC_BIG_ENDIAN);
806 }
807
decode_data_remaining(tvbuff_t * tvb,proto_tree * tree,guint offset)808 static void decode_data_remaining(tvbuff_t *tvb, proto_tree *tree, guint offset)
809 {
810 guint nbytes = tvb_reported_length_remaining(tvb, offset);
811 proto_tree_add_bytes_format(tree, hf_drbd_data, tvb, offset,
812 -1, NULL, "Data (%u byte%s)", nbytes, plurality(nbytes, "", "s"));
813 }
814
decode_payload_data(tvbuff_t * tvb,proto_tree * tree)815 static void decode_payload_data(tvbuff_t *tvb, proto_tree *tree)
816 {
817 decode_data_common(tvb, tree);
818 decode_data_remaining(tvb, tree, 24);
819 }
820
decode_payload_data_reply(tvbuff_t * tvb,proto_tree * tree)821 static void decode_payload_data_reply(tvbuff_t *tvb, proto_tree *tree)
822 {
823 decode_data_common(tvb, tree);
824 decode_data_remaining(tvb, tree, 24);
825 }
826
decode_payload_rs_data_reply(tvbuff_t * tvb,proto_tree * tree)827 static void decode_payload_rs_data_reply(tvbuff_t *tvb, proto_tree *tree)
828 {
829 decode_data_common(tvb, tree);
830 decode_data_remaining(tvb, tree, 24);
831 }
832
decode_payload_barrier(tvbuff_t * tvb,proto_tree * tree)833 static void decode_payload_barrier(tvbuff_t *tvb, proto_tree *tree)
834 {
835 proto_tree_add_item(tree, hf_drbd_barrier, tvb, 0, 4, ENC_BIG_ENDIAN);
836 }
837
decode_payload_data_request(tvbuff_t * tvb,proto_tree * tree)838 static void decode_payload_data_request(tvbuff_t *tvb, proto_tree *tree)
839 {
840 proto_tree_add_item(tree, hf_drbd_sector, tvb, 0, 8, ENC_BIG_ENDIAN);
841 proto_tree_add_item(tree, hf_drbd_block_id, tvb, 8, 8, ENC_BIG_ENDIAN);
842 proto_tree_add_item(tree, hf_drbd_blksize, tvb, 16, 4, ENC_BIG_ENDIAN);
843 }
844
decode_payload_sync_param(tvbuff_t * tvb,proto_tree * tree)845 static void decode_payload_sync_param(tvbuff_t *tvb, proto_tree *tree)
846 {
847 guint length = tvb_reported_length(tvb);
848 guint offset = 0;
849
850 proto_tree_add_item(tree, hf_drbd_resync_rate, tvb, offset, 4, ENC_BIG_ENDIAN);
851 offset += 4;
852 proto_tree_add_item(tree, hf_drbd_verify_alg, tvb, offset, DRBD_STRING_MAX, ENC_ASCII | ENC_NA);
853 offset += DRBD_STRING_MAX;
854
855 if (length >= offset + DRBD_STRING_MAX) {
856 proto_tree_add_item(tree, hf_drbd_csums_alg, tvb, offset, DRBD_STRING_MAX, ENC_ASCII | ENC_NA);
857 offset += DRBD_STRING_MAX;
858 }
859
860 if (length >= offset + 16) {
861 proto_tree_add_item(tree, hf_drbd_c_plan_ahead, tvb, offset, 4, ENC_BIG_ENDIAN);
862 proto_tree_add_item(tree, hf_drbd_c_delay_target, tvb, offset + 4, 4, ENC_BIG_ENDIAN);
863 proto_tree_add_item(tree, hf_drbd_c_fill_target, tvb, offset + 8, 4, ENC_BIG_ENDIAN);
864 proto_tree_add_item(tree, hf_drbd_c_max_rate, tvb, offset + 12, 4, ENC_BIG_ENDIAN);
865 }
866 }
867
decode_payload_protocol(tvbuff_t * tvb,proto_tree * tree)868 static void decode_payload_protocol(tvbuff_t *tvb, proto_tree *tree)
869 {
870 proto_tree_add_item(tree, hf_drbd_protocol, tvb, 0, 4, ENC_BIG_ENDIAN);
871 proto_tree_add_item(tree, hf_drbd_after_sb_0p, tvb, 4, 4, ENC_BIG_ENDIAN);
872 proto_tree_add_item(tree, hf_drbd_after_sb_1p, tvb, 8, 4, ENC_BIG_ENDIAN);
873 proto_tree_add_item(tree, hf_drbd_after_sb_2p, tvb, 12, 4, ENC_BIG_ENDIAN);
874 proto_tree_add_item(tree, hf_drbd_conn_flags, tvb, 16, 4, ENC_BIG_ENDIAN);
875 proto_tree_add_item(tree, hf_drbd_two_primaries, tvb, 20, 4, ENC_BIG_ENDIAN);
876 proto_tree_add_item(tree, hf_drbd_integrity_alg, tvb, 24, -1, ENC_ASCII | ENC_NA);
877 }
878
decode_payload_uuids(tvbuff_t * tvb,proto_tree * tree)879 static void decode_payload_uuids(tvbuff_t *tvb, proto_tree *tree)
880 {
881 proto_tree_add_item(tree, hf_drbd_current_uuid, tvb, 0, 8, ENC_BIG_ENDIAN);
882 proto_tree_add_item(tree, hf_drbd_bitmap_uuid, tvb, 8, 8, ENC_BIG_ENDIAN);
883 proto_tree_add_item(tree, hf_drbd_history_uuid, tvb, 16, 8, ENC_BIG_ENDIAN);
884 proto_tree_add_item(tree, hf_drbd_history_uuid, tvb, 24, 8, ENC_BIG_ENDIAN);
885 proto_tree_add_item(tree, hf_drbd_dirty_bits, tvb, 32, 8, ENC_BIG_ENDIAN);
886 proto_tree_add_bitmask(tree, tvb, 40, hf_drbd_uuid_flags, ett_drbd_uuid_flags, uuid_flag_fields, ENC_BIG_ENDIAN);
887 }
888
decode_payload_sizes(tvbuff_t * tvb,proto_tree * tree)889 static void decode_payload_sizes(tvbuff_t *tvb, proto_tree *tree)
890 {
891 proto_tree_add_item(tree, hf_drbd_d_size, tvb, 0, 8, ENC_BIG_ENDIAN);
892 proto_tree_add_item(tree, hf_drbd_u_size, tvb, 8, 8, ENC_BIG_ENDIAN);
893 proto_tree_add_item(tree, hf_drbd_c_size, tvb, 16, 8, ENC_BIG_ENDIAN);
894 proto_tree_add_item(tree, hf_drbd_max_bio_size, tvb, 24, 4, ENC_BIG_ENDIAN);
895 proto_tree_add_item(tree, hf_drbd_queue_order_type, tvb, 28, 2, ENC_BIG_ENDIAN);
896 proto_tree_add_item(tree, hf_drbd_dds_flags, tvb, 30, 2, ENC_BIG_ENDIAN);
897 proto_tree_add_item(tree, hf_drbd_physical_block_size, tvb, 32, 4, ENC_BIG_ENDIAN);
898 proto_tree_add_item(tree, hf_drbd_logical_block_size, tvb, 36, 4, ENC_BIG_ENDIAN);
899 proto_tree_add_item(tree, hf_drbd_alignment_offset, tvb, 40, 4, ENC_BIG_ENDIAN);
900 proto_tree_add_item(tree, hf_drbd_io_min, tvb, 44, 4, ENC_BIG_ENDIAN);
901 proto_tree_add_item(tree, hf_drbd_io_opt, tvb, 48, 4, ENC_BIG_ENDIAN);
902 proto_tree_add_item(tree, hf_drbd_discard_enabled, tvb, 52, 1, ENC_BIG_ENDIAN);
903 proto_tree_add_item(tree, hf_drbd_discard_zeroes_data, tvb, 53, 1, ENC_BIG_ENDIAN);
904 proto_tree_add_item(tree, hf_drbd_write_same_capable, tvb, 54, 1, ENC_BIG_ENDIAN);
905 }
906
decode_payload_state(tvbuff_t * tvb,proto_tree * tree)907 static void decode_payload_state(tvbuff_t *tvb, proto_tree *tree)
908 {
909 proto_tree_add_bitmask(tree, tvb, 0, hf_drbd_state, ett_drbd_state, state_fields, ENC_BIG_ENDIAN);
910 }
911
decode_payload_req_state(tvbuff_t * tvb,proto_tree * tree)912 static void decode_payload_req_state(tvbuff_t *tvb, proto_tree *tree)
913 {
914 proto_tree_add_item(tree, hf_drbd_mask, tvb, 0, 4, ENC_BIG_ENDIAN);
915 proto_tree_add_item(tree, hf_drbd_val, tvb, 4, 4, ENC_BIG_ENDIAN);
916 }
917
decode_payload_sync_uuid(tvbuff_t * tvb,proto_tree * tree)918 static void decode_payload_sync_uuid(tvbuff_t *tvb, proto_tree *tree)
919 {
920 proto_tree_add_item(tree, hf_drbd_uuid, tvb, 0, 8, ENC_BIG_ENDIAN);
921 }
922
decode_payload_skip(tvbuff_t * tvb,proto_tree * tree)923 static void decode_payload_skip(tvbuff_t *tvb, proto_tree *tree)
924 {
925 proto_tree_add_item(tree, hf_drbd_seq_num, tvb, 0, 4, ENC_BIG_ENDIAN);
926 proto_tree_add_item(tree, hf_drbd_offset, tvb, 4, 4, ENC_BIG_ENDIAN);
927 }
928
decode_payload_out_of_sync(tvbuff_t * tvb,proto_tree * tree)929 static void decode_payload_out_of_sync(tvbuff_t *tvb, proto_tree *tree)
930 {
931 proto_tree_add_item(tree, hf_drbd_sector, tvb, 0, 8, ENC_BIG_ENDIAN);
932 proto_tree_add_item(tree, hf_drbd_blksize, tvb, 8, 4, ENC_BIG_ENDIAN);
933 }
934
decode_payload_twopc(tvbuff_t * tvb,proto_tree * tree)935 static void decode_payload_twopc(tvbuff_t *tvb, proto_tree *tree)
936 {
937 proto_tree_add_item(tree, hf_drbd_tid, tvb, 0, 4, ENC_BIG_ENDIAN);
938 proto_tree_add_item(tree, hf_drbd_initiator_node_id, tvb, 4, 4, ENC_BIG_ENDIAN);
939 proto_tree_add_item(tree, hf_drbd_target_node_id, tvb, 8, 4, ENC_BIG_ENDIAN);
940 proto_tree_add_item(tree, hf_drbd_nodes_to_reach, tvb, 12, 8, ENC_BIG_ENDIAN);
941 /* TODO: Decode further fields based on type */
942 }
943
decode_payload_dagtag(tvbuff_t * tvb,proto_tree * tree)944 static void decode_payload_dagtag(tvbuff_t *tvb, proto_tree *tree)
945 {
946 proto_tree_add_item(tree, hf_drbd_dagtag, tvb, 0, 8, ENC_BIG_ENDIAN);
947 }
948
decode_payload_uuids110(tvbuff_t * tvb,proto_tree * tree)949 static void decode_payload_uuids110(tvbuff_t *tvb, proto_tree *tree)
950 {
951 proto_tree_add_item(tree, hf_drbd_current_uuid, tvb, 0, 8, ENC_BIG_ENDIAN);
952 proto_tree_add_item(tree, hf_drbd_dirty_bits, tvb, 8, 8, ENC_BIG_ENDIAN);
953 proto_tree_add_bitmask(tree, tvb, 16, hf_drbd_uuid_flags, ett_drbd_uuid_flags, uuid_flag_fields, ENC_BIG_ENDIAN);
954 proto_tree_add_item(tree, hf_drbd_node_mask, tvb, 24, 8, ENC_BIG_ENDIAN);
955
956 guint64 bitmap_uuids_mask;
957 proto_tree_add_item_ret_uint64(tree, hf_drbd_bitmap_uuids_mask, tvb, 32, 8, ENC_BIG_ENDIAN, &bitmap_uuids_mask);
958
959 guint offset = 40;
960 for (int i = 0; i < 64; i++) {
961 if (is_bit_set_64(bitmap_uuids_mask, i)) {
962 guint64 bitmap_uuid = tvb_get_ntoh64(tvb, offset);
963 proto_tree_add_uint64_format(tree, hf_drbd_bitmap_uuid, tvb, offset, 8, bitmap_uuid,
964 "Bitmap UUID for node %d: 0x%016" G_GINT64_MODIFIER "x", i, bitmap_uuid);
965 offset += 8;
966 }
967 }
968
969 proto_item *history_uuids = proto_tree_add_item(tree, hf_drbd_history_uuid_list, tvb, offset, -1, ENC_NA);
970 proto_tree *history_tree = proto_item_add_subtree(history_uuids, ett_drbd_history_uuids);
971 guint total_length = tvb_reported_length(tvb);
972 while (offset < total_length) {
973 proto_tree_add_item(history_tree, hf_drbd_history_uuid, tvb, offset, 8, ENC_BIG_ENDIAN);
974 offset += 8;
975 }
976 }
977
decode_payload_peer_dagtag(tvbuff_t * tvb,proto_tree * tree)978 static void decode_payload_peer_dagtag(tvbuff_t *tvb, proto_tree *tree)
979 {
980 proto_tree_add_item(tree, hf_drbd_dagtag, tvb, 0, 8, ENC_BIG_ENDIAN);
981 proto_tree_add_item(tree, hf_drbd_node_id, tvb, 8, 4, ENC_BIG_ENDIAN);
982 }
983
decode_payload_current_uuid(tvbuff_t * tvb,proto_tree * tree)984 static void decode_payload_current_uuid(tvbuff_t *tvb, proto_tree *tree)
985 {
986 proto_tree_add_item(tree, hf_drbd_uuid, tvb, 0, 8, ENC_BIG_ENDIAN);
987 proto_tree_add_item(tree, hf_drbd_weak_nodes, tvb, 8, 8, ENC_BIG_ENDIAN);
988 }
989
decode_payload_data_size(tvbuff_t * tvb,proto_tree * tree)990 static void decode_payload_data_size(tvbuff_t *tvb, proto_tree *tree)
991 {
992 decode_data_common(tvb, tree);
993 proto_tree_add_item(tree, hf_drbd_size, tvb, 24, 4, ENC_BIG_ENDIAN);
994 }
995
decode_payload_data_wsame(tvbuff_t * tvb,proto_tree * tree)996 static void decode_payload_data_wsame(tvbuff_t *tvb, proto_tree *tree)
997 {
998 decode_data_common(tvb, tree);
999 proto_tree_add_item(tree, hf_drbd_size, tvb, 24, 4, ENC_BIG_ENDIAN);
1000 decode_data_remaining(tvb, tree, 28);
1001 }
1002
decode_payload_rs_deallocated(tvbuff_t * tvb,proto_tree * tree)1003 static void decode_payload_rs_deallocated(tvbuff_t *tvb, proto_tree *tree)
1004 {
1005 proto_tree_add_item(tree, hf_drbd_sector, tvb, 0, 8, ENC_BIG_ENDIAN);
1006 proto_tree_add_item(tree, hf_drbd_blksize, tvb, 8, 4, ENC_BIG_ENDIAN);
1007 }
1008
decode_payload_block_ack(tvbuff_t * tvb,proto_tree * tree)1009 static void decode_payload_block_ack(tvbuff_t *tvb, proto_tree *tree)
1010 {
1011 proto_tree_add_item(tree, hf_drbd_sector, tvb, 0, 8, ENC_BIG_ENDIAN);
1012 proto_tree_add_item(tree, hf_drbd_block_id, tvb, 8, 8, ENC_BIG_ENDIAN);
1013 proto_tree_add_item(tree, hf_drbd_blksize, tvb, 16, 4, ENC_BIG_ENDIAN);
1014 proto_tree_add_item(tree, hf_drbd_seq_num, tvb, 20, 4, ENC_BIG_ENDIAN);
1015 }
1016
decode_payload_barrier_ack(tvbuff_t * tvb,proto_tree * tree)1017 static void decode_payload_barrier_ack(tvbuff_t *tvb, proto_tree *tree)
1018 {
1019 proto_tree_add_item(tree, hf_drbd_barrier, tvb, 0, 4, ENC_BIG_ENDIAN);
1020 proto_tree_add_item(tree, hf_drbd_set_size, tvb, 4, 4, ENC_BIG_ENDIAN);
1021 }
1022
decode_payload_confirm_stable(tvbuff_t * tvb,proto_tree * tree)1023 static void decode_payload_confirm_stable(tvbuff_t *tvb, proto_tree *tree)
1024 {
1025 proto_tree_add_item(tree, hf_drbd_oldest_block_id, tvb, 0, 8, ENC_BIG_ENDIAN);
1026 proto_tree_add_item(tree, hf_drbd_youngest_block_id, tvb, 8, 8, ENC_BIG_ENDIAN);
1027 proto_tree_add_item(tree, hf_drbd_set_size, tvb, 16, 4, ENC_BIG_ENDIAN);
1028 }
1029
decode_payload_rq_s_reply(tvbuff_t * tvb,proto_tree * tree)1030 static void decode_payload_rq_s_reply(tvbuff_t *tvb, proto_tree *tree)
1031 {
1032 proto_tree_add_item(tree, hf_drbd_retcode, tvb, 0, 4, ENC_BIG_ENDIAN);
1033 }
1034
decode_payload_peer_ack(tvbuff_t * tvb,proto_tree * tree)1035 static void decode_payload_peer_ack(tvbuff_t *tvb, proto_tree *tree)
1036 {
1037 proto_tree_add_item(tree, hf_drbd_node_mask, tvb, 0, 8, ENC_BIG_ENDIAN);
1038 proto_tree_add_item(tree, hf_drbd_dagtag, tvb, 8, 8, ENC_BIG_ENDIAN);
1039 }
1040
decode_payload_peers_in_sync(tvbuff_t * tvb,proto_tree * tree)1041 static void decode_payload_peers_in_sync(tvbuff_t *tvb, proto_tree *tree)
1042 {
1043 proto_tree_add_item(tree, hf_drbd_sector, tvb, 0, 8, ENC_BIG_ENDIAN);
1044 proto_tree_add_item(tree, hf_drbd_node_mask, tvb, 8, 8, ENC_BIG_ENDIAN);
1045 proto_tree_add_item(tree, hf_drbd_size, tvb, 16, 4, ENC_BIG_ENDIAN);
1046 }
1047
decode_payload_twopc_reply(tvbuff_t * tvb,proto_tree * tree)1048 static void decode_payload_twopc_reply(tvbuff_t *tvb, proto_tree *tree)
1049 {
1050 proto_tree_add_item(tree, hf_drbd_tid, tvb, 0, 4, ENC_BIG_ENDIAN);
1051 proto_tree_add_item(tree, hf_drbd_initiator_node_id, tvb, 4, 4, ENC_BIG_ENDIAN);
1052 proto_tree_add_item(tree, hf_drbd_reachable_nodes, tvb, 8, 8, ENC_BIG_ENDIAN);
1053 /* TODO: Decode further fields based on type */
1054 }
1055
format_node_mask(gchar * s,guint64 value)1056 static void format_node_mask(gchar *s, guint64 value)
1057 {
1058 if (!value) {
1059 (void) g_strlcpy(s, "<none>", ITEM_LABEL_LENGTH);
1060 return;
1061 }
1062
1063 int written = 0;
1064 int run_start = -1;
1065 for (int i = 0; i < 64 && written < ITEM_LABEL_LENGTH; i++) {
1066 gboolean is_set = is_bit_set_64(value, i);
1067
1068 int run_end;
1069 if (!is_set) {
1070 run_end = i;
1071 } else if (i == 63) {
1072 if (run_start == -1)
1073 run_start = i;
1074 run_end = 64;
1075 } else {
1076 run_end = -1;
1077 }
1078
1079 if (run_start != -1 && run_end != -1) {
1080 int run_length = run_end - run_start;
1081 const char *sep = written ? ", " : "";
1082
1083 if (run_length == 1)
1084 written += g_snprintf(s + written, ITEM_LABEL_LENGTH - written, "%s%d", sep, run_start);
1085 else if (run_length == 2)
1086 written += g_snprintf(s + written, ITEM_LABEL_LENGTH - written, "%s%d, %d", sep, run_start, run_start + 1);
1087 else
1088 written += g_snprintf(s + written, ITEM_LABEL_LENGTH - written, "%s%d - %d", sep, run_start, run_end - 1);
1089 }
1090
1091 if (!is_set)
1092 run_start = -1;
1093 else if (run_start == -1)
1094 run_start = i;
1095 }
1096 }
1097
proto_register_drbd(void)1098 void proto_register_drbd(void)
1099 {
1100 static hf_register_info hf[] = {
1101 { &hf_drbd_command, { "Command", "drbd.command", FT_UINT16, BASE_HEX, VALS(packet_names), 0x0, NULL, HFILL }},
1102 { &hf_drbd_length, { "Payload length", "drbd.length", FT_UINT32, BASE_HEX_DEC, NULL, 0x0, NULL, HFILL }},
1103 { &hf_drbd_volume, { "Volume", "drbd.volume", FT_INT16, BASE_DEC, NULL, 0x0, NULL, HFILL }},
1104 { &hf_drbd_auth_challenge_nonce, { "Nonce", "drbd.auth_nonce", FT_BYTES, BASE_NO_DISPLAY_VALUE, NULL, 0x0, NULL, HFILL }},
1105 { &hf_drbd_auth_response_hash, { "Hash", "drbd.auth_hash", FT_BYTES, BASE_NO_DISPLAY_VALUE, NULL, 0x0, NULL, HFILL }},
1106 { &hf_drbd_sector, { "Sector", "drbd.sector", FT_UINT64, BASE_HEX, NULL, 0x0, NULL, HFILL }},
1107 { &hf_drbd_block_id, { "Block ID", "drbd.block_id", FT_UINT64, BASE_HEX, NULL, 0x0, NULL, HFILL }},
1108 { &hf_drbd_seq_num, { "Sequence number", "drbd.seq_num", FT_UINT32, BASE_HEX_DEC, NULL, 0x0, NULL, HFILL }},
1109 { &hf_drbd_dp_flags, { "Data flags", "drbd.dp_flags", FT_UINT32, BASE_HEX, NULL, 0x0, NULL, HFILL }},
1110 { &hf_drbd_data, { "Data", "drbd.data", FT_BYTES, BASE_NO_DISPLAY_VALUE, NULL, 0x0, NULL, HFILL }},
1111 { &hf_drbd_size, { "size", "drbd.size", FT_UINT32, BASE_HEX_DEC, NULL, 0x0, NULL, HFILL }},
1112 { &hf_drbd_blksize, { "blksize", "drbd.blksize", FT_UINT32, BASE_DEC_HEX, NULL, 0x0, NULL, HFILL }},
1113 { &hf_drbd_protocol_min, { "protocol_min", "drbd.protocol_min", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }},
1114 { &hf_drbd_feature_flags, { "feature_flags", "drbd.feature_flags", FT_UINT32, BASE_HEX, NULL, 0x0, NULL, HFILL }},
1115 { &hf_drbd_protocol_max, { "protocol_max", "drbd.protocol_max", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }},
1116 { &hf_drbd_sender_node_id, { "sender_node_id", "drbd.sender_node_id", FT_INT32, BASE_DEC, NULL, 0x0, NULL, HFILL }},
1117 { &hf_drbd_receiver_node_id, { "receiver_node_id", "drbd.receiver_node_id", FT_INT32, BASE_DEC, NULL, 0x0, NULL, HFILL }},
1118 { &hf_drbd_barrier, { "barrier", "drbd.barrier", FT_UINT32, BASE_HEX_DEC, NULL, 0x0, NULL, HFILL }},
1119 { &hf_drbd_set_size, { "set_size", "drbd.set_size", FT_UINT32, BASE_HEX_DEC, NULL, 0x0, NULL, HFILL }},
1120 { &hf_drbd_oldest_block_id, { "oldest_block_id", "drbd.oldest_block_id", FT_UINT64, BASE_HEX, NULL, 0x0, NULL, HFILL }},
1121 { &hf_drbd_youngest_block_id, { "youngest_block_id", "drbd.youngest_block_id", FT_UINT64, BASE_HEX, NULL, 0x0, NULL, HFILL }},
1122 { &hf_drbd_resync_rate, { "resync_rate", "drbd.resync_rate", FT_UINT32, BASE_HEX_DEC, NULL, 0x0, NULL, HFILL }},
1123 { &hf_drbd_verify_alg, { "verify_alg", "drbd.verify_alg", FT_STRINGZ, STR_ASCII, NULL, 0x0, NULL, HFILL }},
1124 { &hf_drbd_csums_alg, { "csums_alg", "drbd.csums_alg", FT_STRINGZ, STR_ASCII, NULL, 0x0, NULL, HFILL }},
1125 { &hf_drbd_c_plan_ahead, { "c_plan_ahead", "drbd.c_plan_ahead", FT_UINT32, BASE_HEX_DEC, NULL, 0x0, NULL, HFILL }},
1126 { &hf_drbd_c_delay_target, { "c_delay_target", "drbd.c_delay_target", FT_UINT32, BASE_HEX_DEC, NULL, 0x0, NULL, HFILL }},
1127 { &hf_drbd_c_fill_target, { "c_fill_target", "drbd.c_fill_target", FT_UINT32, BASE_HEX_DEC, NULL, 0x0, NULL, HFILL }},
1128 { &hf_drbd_c_max_rate, { "c_max_rate", "drbd.c_max_rate", FT_UINT32, BASE_HEX_DEC, NULL, 0x0, NULL, HFILL }},
1129 { &hf_drbd_protocol, { "protocol", "drbd.protocol", FT_UINT32, BASE_HEX, VALS(protocol_names), 0x0, NULL, HFILL }},
1130 { &hf_drbd_after_sb_0p, { "after_sb_0p", "drbd.after_sb_0p", FT_UINT32, BASE_HEX_DEC, NULL, 0x0, NULL, HFILL }},
1131 { &hf_drbd_after_sb_1p, { "after_sb_1p", "drbd.after_sb_1p", FT_UINT32, BASE_HEX_DEC, NULL, 0x0, NULL, HFILL }},
1132 { &hf_drbd_after_sb_2p, { "after_sb_2p", "drbd.after_sb_2p", FT_UINT32, BASE_HEX_DEC, NULL, 0x0, NULL, HFILL }},
1133 { &hf_drbd_conn_flags, { "conn_flags", "drbd.conn_flags", FT_UINT32, BASE_HEX, NULL, 0x0, NULL, HFILL }},
1134 { &hf_drbd_two_primaries, { "two_primaries", "drbd.two_primaries", FT_UINT32, BASE_HEX, NULL, 0x0, NULL, HFILL }},
1135 { &hf_drbd_integrity_alg, { "integrity_alg", "drbd.integrity_alg", FT_STRINGZ, STR_ASCII, NULL, 0x0, NULL, HFILL }},
1136 { &hf_drbd_current_uuid, { "Current UUID", "drbd.current_uuid", FT_UINT64, BASE_HEX, NULL, 0x0, NULL, HFILL }},
1137 { &hf_drbd_bitmap_uuid, { "Bitmap UUID", "drbd.bitmap_uuid", FT_UINT64, BASE_HEX, NULL, 0x0, NULL, HFILL }},
1138 { &hf_drbd_history_uuid_list, { "History UUIDs", "drbd.history_uuids", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL }},
1139 { &hf_drbd_history_uuid, { "History UUID", "drbd.history_uuid", FT_UINT64, BASE_HEX, NULL, 0x0, NULL, HFILL }},
1140 { &hf_drbd_dirty_bits, { "Dirty bits", "drbd.dirty_bits", FT_UINT64, BASE_HEX, NULL, 0x0, NULL, HFILL }},
1141 { &hf_drbd_uuid_flags, { "UUID flags", "drbd.uuid_flags", FT_UINT64, BASE_HEX, NULL, 0x0, NULL, HFILL }},
1142 { &hf_drbd_node_mask, { "Nodes", "drbd.node_mask", FT_UINT64, BASE_CUSTOM, format_node_mask, 0x0, NULL, HFILL }},
1143 { &hf_drbd_bitmap_uuids_mask, { "Bitmap UUID nodes", "drbd.bitmap_uuids_mask", FT_UINT64, BASE_CUSTOM, format_node_mask, 0x0, NULL, HFILL }},
1144 { &hf_drbd_uuid, { "uuid", "drbd.uuid", FT_UINT64, BASE_HEX, NULL, 0x0, NULL, HFILL }},
1145 { &hf_drbd_weak_nodes, { "weak_nodes", "drbd.weak_nodes", FT_UINT64, BASE_CUSTOM, format_node_mask, 0x0, NULL, HFILL }},
1146 { &hf_drbd_physical_block_size, { "physical_block_size", "drbd.physical_block_size", FT_UINT32, BASE_HEX_DEC, NULL, 0x0, NULL, HFILL }},
1147 { &hf_drbd_logical_block_size, { "logical_block_size", "drbd.logical_block_size", FT_UINT32, BASE_HEX_DEC, NULL, 0x0, NULL, HFILL }},
1148 { &hf_drbd_alignment_offset, { "alignment_offset", "drbd.alignment_offset", FT_UINT32, BASE_HEX_DEC, NULL, 0x0, NULL, HFILL }},
1149 { &hf_drbd_io_min, { "io_min", "drbd.io_min", FT_UINT32, BASE_HEX_DEC, NULL, 0x0, NULL, HFILL }},
1150 { &hf_drbd_io_opt, { "io_opt", "drbd.io_opt", FT_UINT32, BASE_HEX_DEC, NULL, 0x0, NULL, HFILL }},
1151 { &hf_drbd_discard_enabled, { "discard_enabled", "drbd.discard_enabled", FT_BOOLEAN, BASE_NONE, NULL, 0x0, NULL, HFILL }},
1152 { &hf_drbd_discard_zeroes_data, { "discard_zeroes_data", "drbd.discard_zeroes_data", FT_BOOLEAN, BASE_NONE, NULL, 0x0, NULL, HFILL }},
1153 { &hf_drbd_write_same_capable, { "write_same_capable", "drbd.write_same_capable", FT_BOOLEAN, BASE_NONE, NULL, 0x0, NULL, HFILL }},
1154 { &hf_drbd_d_size, { "d_size", "drbd.d_size", FT_UINT64, BASE_HEX_DEC, NULL, 0x0, NULL, HFILL }},
1155 { &hf_drbd_u_size, { "u_size", "drbd.u_size", FT_UINT64, BASE_HEX_DEC, NULL, 0x0, NULL, HFILL }},
1156 { &hf_drbd_c_size, { "c_size", "drbd.c_size", FT_UINT64, BASE_HEX_DEC, NULL, 0x0, NULL, HFILL }},
1157 { &hf_drbd_max_bio_size, { "max_bio_size", "drbd.max_bio_size", FT_UINT32, BASE_HEX_DEC, NULL, 0x0, NULL, HFILL }},
1158 { &hf_drbd_queue_order_type, { "queue_order_type", "drbd.queue_order_type", FT_UINT16, BASE_HEX, NULL, 0x0, NULL, HFILL }},
1159 { &hf_drbd_dds_flags, { "dds_flags", "drbd.dds_flags", FT_UINT16, BASE_HEX, NULL, 0x0, NULL, HFILL }},
1160 { &hf_drbd_state, { "state", "drbd.state", FT_UINT32, BASE_HEX, NULL, 0x0, NULL, HFILL }},
1161 { &hf_drbd_mask, { "mask", "drbd.mask", FT_UINT32, BASE_HEX, NULL, 0x0, NULL, HFILL }},
1162 { &hf_drbd_val, { "val", "drbd.val", FT_UINT32, BASE_HEX_DEC, NULL, 0x0, NULL, HFILL }},
1163 { &hf_drbd_retcode, { "retcode", "drbd.retcode", FT_UINT32, BASE_HEX_DEC, NULL, 0x0, NULL, HFILL }},
1164 { &hf_drbd_tid, { "tid", "drbd.tid", FT_UINT32, BASE_DEC_HEX, NULL, 0x0, NULL, HFILL }},
1165 { &hf_drbd_initiator_node_id, { "initiator_node_id", "drbd.initiator_node_id", FT_INT32, BASE_DEC, NULL, 0x0, NULL, HFILL }},
1166 { &hf_drbd_target_node_id, { "target_node_id", "drbd.target_node_id", FT_INT32, BASE_DEC, NULL, 0x0, NULL, HFILL }},
1167 { &hf_drbd_nodes_to_reach, { "nodes_to_reach", "drbd.nodes_to_reach", FT_UINT64, BASE_CUSTOM, format_node_mask, 0x0, NULL, HFILL }},
1168 { &hf_drbd_reachable_nodes, { "reachable_nodes", "drbd.reachable_nodes", FT_UINT64, BASE_CUSTOM, format_node_mask, 0x0, NULL, HFILL }},
1169 { &hf_drbd_offset, { "offset", "drbd.offset", FT_UINT32, BASE_HEX_DEC, NULL, 0x0, NULL, HFILL }},
1170 { &hf_drbd_dagtag, { "dagtag", "drbd.dagtag", FT_UINT64, BASE_HEX_DEC, NULL, 0x0, NULL, HFILL }},
1171 { &hf_drbd_node_id, { "node_id", "drbd.node_id", FT_INT32, BASE_DEC, NULL, 0x0, NULL, HFILL }},
1172
1173 { &hf_drbd_state_role, { "role", "drbd.state.role", FT_UINT32, BASE_DEC, VALS(role_names), STATE_ROLE, NULL, HFILL }},
1174 { &hf_drbd_state_peer, { "peer", "drbd.state.peer", FT_UINT32, BASE_DEC, VALS(role_names), STATE_PEER, NULL, HFILL }},
1175 { &hf_drbd_state_conn, { "conn", "drbd.state.conn", FT_UINT32, BASE_DEC, VALS(connection_state_names), STATE_CONN, NULL, HFILL }},
1176 { &hf_drbd_state_disk, { "disk", "drbd.state.disk", FT_UINT32, BASE_DEC, VALS(disk_state_names), STATE_DISK, NULL, HFILL }},
1177 { &hf_drbd_state_pdsk, { "pdsk", "drbd.state.pdsk", FT_UINT32, BASE_DEC, VALS(disk_state_names), STATE_PDSK, NULL, HFILL }},
1178 { &hf_drbd_state_susp, { "susp", "drbd.state.susp", FT_BOOLEAN, 32, NULL, STATE_SUSP, NULL, HFILL }},
1179 { &hf_drbd_state_aftr_isp, { "aftr_isp", "drbd.state.aftr_isp", FT_BOOLEAN, 32, NULL, STATE_AFTR_ISP, NULL, HFILL }},
1180 { &hf_drbd_state_peer_isp, { "peer_isp", "drbd.state.peer_isp", FT_BOOLEAN, 32, NULL, STATE_PEER_ISP, NULL, HFILL }},
1181 { &hf_drbd_state_user_isp, { "user_isp", "drbd.state.user_isp", FT_BOOLEAN, 32, NULL, STATE_USER_ISP, NULL, HFILL }},
1182 { &hf_drbd_state_susp_nod, { "susp_nod", "drbd.state.susp_nod", FT_BOOLEAN, 32, NULL, STATE_SUSP_NOD, NULL, HFILL }},
1183 { &hf_drbd_state_susp_fen, { "susp_fen", "drbd.state.susp_fen", FT_BOOLEAN, 32, NULL, STATE_SUSP_FEN, NULL, HFILL }},
1184 { &hf_drbd_state_quorum, { "quorum", "drbd.state.quorum", FT_BOOLEAN, 32, NULL, STATE_QUORUM, NULL, HFILL }},
1185
1186 { &hf_drbd_uuid_flag_discard_my_data, { "discard_my_data", "drbd.uuid_flag.discard_my_data", FT_BOOLEAN, 64, NULL, UUID_FLAG_DISCARD_MY_DATA, NULL, HFILL }},
1187 { &hf_drbd_uuid_flag_crashed_primary, { "crashed_primary", "drbd.uuid_flag.crashed_primary", FT_BOOLEAN, 64, NULL, UUID_FLAG_CRASHED_PRIMARY, NULL, HFILL }},
1188 { &hf_drbd_uuid_flag_inconsistent, { "inconsistent", "drbd.uuid_flag.inconsistent", FT_BOOLEAN, 64, NULL, UUID_FLAG_INCONSISTENT, NULL, HFILL }},
1189 { &hf_drbd_uuid_flag_skip_initial_sync, { "skip_initial_sync", "drbd.uuid_flag.skip_initial_sync", FT_BOOLEAN, 64, NULL, UUID_FLAG_SKIP_INITIAL_SYNC, NULL, HFILL }},
1190 { &hf_drbd_uuid_flag_new_datagen, { "new_datagen", "drbd.uuid_flag.new_datagen", FT_BOOLEAN, 64, NULL, UUID_FLAG_NEW_DATAGEN, NULL, HFILL }},
1191 { &hf_drbd_uuid_flag_stable, { "stable", "drbd.uuid_flag.stable", FT_BOOLEAN, 64, NULL, UUID_FLAG_STABLE, NULL, HFILL }},
1192 { &hf_drbd_uuid_flag_got_stable, { "got_stable", "drbd.uuid_flag.got_stable", FT_BOOLEAN, 64, NULL, UUID_FLAG_GOT_STABLE, NULL, HFILL }},
1193 { &hf_drbd_uuid_flag_resync, { "resync", "drbd.uuid_flag.resync", FT_BOOLEAN, 64, NULL, UUID_FLAG_RESYNC, NULL, HFILL }},
1194 { &hf_drbd_uuid_flag_reconnect, { "reconnect", "drbd.uuid_flag.reconnect", FT_BOOLEAN, 64, NULL, UUID_FLAG_RECONNECT, NULL, HFILL }},
1195 { &hf_drbd_uuid_flag_diskless_primary, { "diskless_primary", "drbd.uuid_flag.diskless_primary", FT_BOOLEAN, 64, NULL, UUID_FLAG_DISKLESS_PRIMARY, NULL, HFILL }},
1196 { &hf_drbd_uuid_flag_primary_lost_quorum, { "primary_lost_quorum", "drbd.uuid_flag.primary_lost_quorum", FT_BOOLEAN, 64, NULL, UUID_FLAG_PRIMARY_LOST_QUORUM, NULL, HFILL }},
1197
1198 { &hf_drbd_dp_hardbarrier, { "hardbarrier", "drbd.dp_flag.hardbarrier", FT_BOOLEAN, 32, NULL, DP_HARDBARRIER, NULL, HFILL }},
1199 { &hf_drbd_dp_rw_sync, { "rw_sync", "drbd.dp_flag.rw_sync", FT_BOOLEAN, 32, NULL, DP_RW_SYNC, NULL, HFILL }},
1200 { &hf_drbd_dp_may_set_in_sync, { "may_set_in_sync", "drbd.dp_flag.may_set_in_sync", FT_BOOLEAN, 32, NULL, DP_MAY_SET_IN_SYNC, NULL, HFILL }},
1201 { &hf_drbd_dp_unplug, { "unplug", "drbd.dp_flag.unplug", FT_BOOLEAN, 32, NULL, DP_UNPLUG, NULL, HFILL }},
1202 { &hf_drbd_dp_fua, { "fua", "drbd.dp_flag.fua", FT_BOOLEAN, 32, NULL, DP_FUA, NULL, HFILL }},
1203 { &hf_drbd_dp_flush, { "flush", "drbd.dp_flag.flush", FT_BOOLEAN, 32, NULL, DP_FLUSH, NULL, HFILL }},
1204 { &hf_drbd_dp_discard, { "discard", "drbd.dp_flag.discard", FT_BOOLEAN, 32, NULL, DP_DISCARD, NULL, HFILL }},
1205 { &hf_drbd_dp_send_receive_ack, { "send_receive_ack", "drbd.dp_flag.send_receive_ack", FT_BOOLEAN, 32, NULL, DP_SEND_RECEIVE_ACK, NULL, HFILL }},
1206 { &hf_drbd_dp_send_write_ack, { "send_write_ack", "drbd.dp_flag.send_write_ack", FT_BOOLEAN, 32, NULL, DP_SEND_WRITE_ACK, NULL, HFILL }},
1207 { &hf_drbd_dp_wsame, { "wsame", "drbd.dp_flag.wsame", FT_BOOLEAN, 32, NULL, DP_WSAME, NULL, HFILL }},
1208 { &hf_drbd_dp_zeroes, { "zeroes", "drbd.dp_flag.zeroes", FT_BOOLEAN, 32, NULL, DP_ZEROES, NULL, HFILL }},
1209 };
1210
1211 static gint *ett[] = {
1212 &ett_drbd,
1213 &ett_drbd_state,
1214 &ett_drbd_uuid_flags,
1215 &ett_drbd_history_uuids,
1216 &ett_drbd_data_flags,
1217 };
1218
1219 proto_drbd = proto_register_protocol("DRBD Protocol", "DRBD", "drbd");
1220 proto_register_field_array(proto_drbd, hf, array_length(hf));
1221 proto_register_subtree_array(ett, array_length(ett));
1222 }
1223
proto_reg_handoff_drbd(void)1224 void proto_reg_handoff_drbd(void)
1225 {
1226 drbd_handle = create_dissector_handle(dissect_drbd, proto_drbd);
1227 heur_dissector_add("tcp", test_drbd_protocol, "DRBD over TCP", "drbd_tcp", proto_drbd, HEURISTIC_DISABLE);
1228 }
1229
1230 /*
1231 * Editor modelines - https://www.wireshark.org/tools/modelines.html
1232 *
1233 * Local variables:
1234 * c-basic-offset: 4
1235 * tab-width: 8
1236 * indent-tabs-mode: nil
1237 * End:
1238 *
1239 * vi: set shiftwidth=4 tabstop=8 expandtab:
1240 * :indentSize=4:tabSize=8:noTabs=true:
1241 */
1242