2 * Routines for git packet dissection
3 * Copyright 2010, Jelmer Vernooij <jelmer@samba.org>
5 * Wireshark - Network traffic analyzer
6 * By Gerald Combs <gerald@wireshark.org>
7 * Copyright 1998 Gerald Combs
9 * Copied from packet-pop.c
11 * SPDX-License-Identifier: GPL-2.0-or-later
13 * Current testing suite 'case_dissect_git' can be found at
14 * test/suite_dissection.py
19 #include <stdio.h> /* for sscanf() */
21 #include <epan/packet.h>
22 #include <epan/expert.h>
23 #include <epan/prefs.h>
24 #include "packet-tcp.h"
26 void proto_register_git(void);
27 void proto_reg_handoff_git(void);
29 static dissector_handle_t git_handle
;
32 static expert_field ei_git_bad_pkt_len
;
33 static expert_field ei_git_malformed
;
37 static int hf_git_protocol_version
;
38 static int hf_git_packet_type
;
39 static int hf_git_packet_len
;
40 static int hf_git_packet_data
;
41 static int hf_git_sideband_control_code
;
42 static int hf_git_upload_pack_adv
;
43 static int hf_git_upload_pack_req
;
44 static int hf_git_upload_pack_res
;
46 #define PNAME "Git Smart Protocol"
50 #define TCP_PORT_GIT 9418
52 static const value_string packet_type_vals
[] = {
55 { 2, "Response end" },
59 static const value_string version_vals
[] = {
60 { '1', "Git protocol version 1" },
61 { '2', "Git protocol version 2" },
65 #define SIDEBAND_PACKFILE_DATA 0x01
66 #define SIDEBAND_PROGRESS_INFO 0x02
67 #define SIDEBAND_ERROR_INFO 0x03
68 static const value_string sideband_vals
[] = {
69 { SIDEBAND_PACKFILE_DATA
, "Git packfile data" },
70 { SIDEBAND_PROGRESS_INFO
, "Git progress data" },
71 { SIDEBAND_ERROR_INFO
, "Git error data" },
75 /* desegmentation of Git over TCP */
76 static bool git_desegment
= true;
78 static bool get_packet_length(tvbuff_t
*tvb
, int offset
,
83 lenstr
= tvb_get_string_enc(wmem_packet_scope(), tvb
, offset
, 4, ENC_ASCII
);
85 return (sscanf(lenstr
, "%hx", length
) == 1);
89 get_git_pdu_len(packet_info
*pinfo _U_
, tvbuff_t
*tvb
, int offset
, void *data _U_
)
93 if (!get_packet_length(tvb
, offset
, &plen
))
94 return 0; /* No idea what this is */
97 ? 4 // Special packet (e.g., flush-pkt)
101 /* Parse pkt-lines one-by-one
103 * @param tvb The buffer to dissect.
104 * @param pinfo Packet info associated to this buffer.
105 * @param git_tree The git protocol subtree.
106 * @param offset The offset at which to start the dissection.
107 * @return bool After successful/unsuccessful parsing.
109 * This new helper takes the contents of the tvbuffer, updates the
110 * offset, and returns to the caller for subsequent processing of the
111 * remainder of the data.
114 dissect_pkt_line(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*git_tree
,
119 // what type of pkt-line is it?
120 if (!get_packet_length(tvb
, *offset
, &plen
))
122 if (plen
< 4) { // a special packet (e.g., flush-pkt)
124 proto_tree_add_uint(git_tree
, hf_git_packet_type
, tvb
,
128 if (!try_val_to_str(plen
, packet_type_vals
))
129 expert_add_info(pinfo
, ti
, &ei_git_bad_pkt_len
);
133 proto_tree_add_uint(git_tree
, hf_git_packet_len
, tvb
, *offset
, 4, plen
);
138 * Parse out the version of the Git Protocol
140 * The initial server response contains the version of the Git Protocol in use;
141 * 1 or 2. Parsing out this information helps identify the capabilities and
142 * information that can be used with the protocol.
144 if (plen
>= 9 && !tvb_strneql(tvb
, *offset
, "version ", 8)) {
145 proto_tree_add_item(git_tree
, hf_git_protocol_version
, tvb
, *offset
+ 8,
150 * Parse out the sideband control code.
152 * Not all pkt-lines have a sideband control code. With more context from the rest of
153 * the request or response, we would be able to tell whether sideband is expected here;
154 * lacking that, let's assume for now that all pkt-lines starting with \1, \2, or \3
155 * are using sideband.
157 int sideband_code
= tvb_get_uint8(tvb
, *offset
);
159 if (1 <= sideband_code
&& sideband_code
<= 3) {
160 proto_tree_add_uint(git_tree
, hf_git_sideband_control_code
, tvb
, *offset
, 1,
166 proto_tree_add_item(git_tree
, hf_git_packet_data
, tvb
, *offset
, plen
, ENC_NA
);
172 dissect_git_pdu(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void* data _U_
)
174 proto_tree
*git_tree
;
178 col_set_str(pinfo
->cinfo
, COL_PROTOCOL
, PSNAME
);
180 col_set_str(pinfo
->cinfo
, COL_INFO
, PNAME
);
182 ti
= proto_tree_add_item(tree
, proto_git
, tvb
, offset
, -1, ENC_NA
);
183 git_tree
= proto_item_add_subtree(ti
, ett_git
);
185 if (!dissect_pkt_line(tvb
, pinfo
, git_tree
, &offset
))
188 return tvb_captured_length(tvb
);
193 * @param tvb The buffer to dissect.
194 * @param pinfo The Packet Info.
195 * @param tree The protocol tree.
196 * @param hfindex The type of http pack.
197 * @return tvb_length The amount of captured data in the buffer,
198 * returns 0 if parsing failed.
200 * This new helper takes the contents of the tvbuffer sent by http
201 * dissectors, adds the packs to the git subtree and returns the amount
202 * of consumed bytes in the tvb buffer.
205 dissect_http_pkt_lines(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, int hfindex
)
207 proto_tree
*git_tree
;
212 col_set_str(pinfo
->cinfo
, COL_PROTOCOL
, PSNAME
);
214 col_set_str(pinfo
->cinfo
, COL_INFO
, PNAME
);
216 ti
= proto_tree_add_item(tree
, proto_git
, tvb
, offset
, -1, ENC_NA
);
217 git_tree
= proto_item_add_subtree(ti
, ett_git
);
219 proto_tree_add_item(git_tree
, hfindex
, tvb
, offset
,
220 tvb_captured_length(tvb
), ENC_NA
);
222 total_len
= tvb_reported_length(tvb
);
223 while (offset
< total_len
) {
224 /* Add expert info if there is trouble parsing part-way through */
225 if (!dissect_pkt_line(tvb
, pinfo
, git_tree
, &offset
)) {
226 proto_tree_add_expert(git_tree
, pinfo
, &ei_git_malformed
, tvb
, offset
, -1);
231 return tvb_captured_length(tvb
);
235 dissect_git_upload_pack_adv(tvbuff_t
*tvb
, packet_info
*pinfo
,
236 proto_tree
*tree
, void *data _U_
)
238 return dissect_http_pkt_lines(tvb
, pinfo
, tree
, hf_git_upload_pack_adv
);
242 dissect_git_upload_pack_req(tvbuff_t
*tvb
, packet_info
*pinfo
,
243 proto_tree
*tree
, void *data _U_
)
245 return dissect_http_pkt_lines(tvb
, pinfo
, tree
, hf_git_upload_pack_req
);
249 dissect_git_upload_pack_res(tvbuff_t
*tvb
, packet_info
*pinfo
,
250 proto_tree
*tree
, void *data _U_
)
252 return dissect_http_pkt_lines(tvb
, pinfo
, tree
, hf_git_upload_pack_res
);
256 dissect_git(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void* data
)
258 tcp_dissect_pdus(tvb
, pinfo
, tree
, git_desegment
, 4, get_git_pdu_len
,
259 dissect_git_pdu
, data
);
260 return tvb_captured_length(tvb
);
264 proto_register_git(void)
266 static hf_register_info hf
[] = {
267 { &hf_git_protocol_version
,
268 { "Git Protocol Version", "git.version", FT_UINT8
, BASE_NONE
, VALS(version_vals
),
271 { &hf_git_packet_type
,
272 { "Git Packet Type", "git.packet_type", FT_UINT8
, BASE_NONE
, VALS(packet_type_vals
),
275 { &hf_git_packet_len
,
276 { "Packet length", "git.length", FT_UINT16
, BASE_HEX
, NULL
, 0x0, NULL
, HFILL
},
278 { &hf_git_packet_data
,
279 { "Packet data", "git.data", FT_BYTES
, BASE_NONE
, NULL
, 0x0, NULL
, HFILL
},
281 { &hf_git_sideband_control_code
,
282 { "Sideband control code", "git.sideband_control_code", FT_UINT8
,
283 BASE_HEX
, VALS(sideband_vals
), 0, NULL
, HFILL
},
285 { &hf_git_upload_pack_adv
,
286 { "Upload Pack Advertisement", "git.upload_pack_advertisement",
287 FT_BYTES
, BASE_NONE
, NULL
, 0x0, NULL
, HFILL
},
289 { &hf_git_upload_pack_req
,
290 { "Upload Pack Request", "git.upload_pack_request",
291 FT_BYTES
, BASE_NONE
, NULL
, 0x0, NULL
, HFILL
},
293 { &hf_git_upload_pack_res
,
294 { "Upload Pack Result", "git.upload_pack_result",
295 FT_BYTES
, BASE_NONE
, NULL
, 0x0, NULL
, HFILL
},
299 static int *ett
[] = {
303 static ei_register_info ei
[] = {
304 { &ei_git_bad_pkt_len
,
305 { "git.bad_pkt_len", PI_PROTOCOL
, PI_ERROR
,
306 "unrecognized special pkt-len value", EXPFILL
}
309 { "git.malformed", PI_MALFORMED
, PI_ERROR
,
310 "malformed packet", EXPFILL
}
314 module_t
*git_module
;
315 expert_module_t
*expert_git
;
317 proto_git
= proto_register_protocol(PNAME
, PSNAME
, PFNAME
);
318 proto_register_field_array(proto_git
, hf
, array_length(hf
));
319 proto_register_subtree_array(ett
, array_length(ett
));
321 expert_git
= expert_register_protocol(proto_git
);
322 expert_register_field_array(expert_git
, ei
, array_length(ei
));
324 git_handle
= register_dissector(PFNAME
, dissect_git
, proto_git
);
326 git_module
= prefs_register_protocol(proto_git
, NULL
);
328 prefs_register_bool_preference(git_module
, "desegment",
329 "Reassemble GIT messages spanning multiple TCP segments",
330 "Whether the GIT dissector should reassemble messages spanning multiple TCP segments."
331 " To use this option, you must also enable \"Allow subdissectors to reassemble TCP streams\" in the TCP protocol settings.",
336 proto_reg_handoff_git(void)
339 * Add the dissectors for GIT over HTTP
341 * Reference documentation at
342 * https://www.kernel.org/pub/software/scm/git/docs//technical/http-protocol.txt
344 dissector_handle_t git_upload_pack_adv_handle
;
345 dissector_handle_t git_upload_pack_req_handle
;
346 dissector_handle_t git_upload_pack_res_handle
;
348 git_upload_pack_adv_handle
= create_dissector_handle(dissect_git_upload_pack_adv
,
351 git_upload_pack_req_handle
= create_dissector_handle(dissect_git_upload_pack_req
,
354 git_upload_pack_res_handle
= create_dissector_handle(dissect_git_upload_pack_res
,
357 dissector_add_string("media_type",
358 "application/x-git-upload-pack-advertisement",
359 git_upload_pack_adv_handle
);
360 dissector_add_string("media_type",
361 "application/x-git-upload-pack-request",
362 git_upload_pack_req_handle
);
363 dissector_add_string("media_type",
364 "application/x-git-upload-pack-result",
365 git_upload_pack_res_handle
);
367 dissector_add_uint_with_preference("tcp.port", TCP_PORT_GIT
, git_handle
);
371 * Editor modelines - https://www.wireshark.org/tools/modelines.html
376 * indent-tabs-mode: nil
379 * ex: set shiftwidth=2 tabstop=8 expandtab:
380 * :indentSize=2:tabSize=8:noTabs=true: