2 * Routines for ICAP packet disassembly
5 * Srishylam Simharajan simha@netapp.com
7 * Wireshark - Network traffic analyzer
8 * By Gerald Combs <gerald@wireshark.org>
9 * Copyright 1998 Gerald Combs
11 * SPDX-License-Identifier: GPL-2.0-or-later
17 #include <epan/packet.h>
18 #include <epan/strutil.h>
19 #include "packet-tls.h"
21 void proto_register_icap(void);
22 void proto_reg_handoff_icap(void);
24 typedef enum _icap_type
{
32 static int proto_icap
;
33 static int hf_icap_response
;
34 static int hf_icap_reqmod
;
35 static int hf_icap_respmod
;
36 static int hf_icap_options
;
37 /* static int hf_icap_other; */
41 static dissector_handle_t http_handle
;
43 #define TCP_PORT_ICAP 1344
44 static int is_icap_message(const unsigned char *data
, int linelen
, icap_type_t
*type
);
46 dissect_icap(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void* data _U_
)
48 proto_tree
*icap_tree
= NULL
;
49 proto_item
*ti
= NULL
;
50 proto_item
*hidden_item
;
53 const unsigned char *line
;
55 const unsigned char *linep
, *lineend
;
58 icap_type_t icap_type
;
61 col_set_str(pinfo
->cinfo
, COL_PROTOCOL
, "ICAP");
64 * Put the first line from the buffer into the summary
65 * if it's an ICAP header (but leave out the
67 * Otherwise, just call it a continuation.
69 * Note that "tvb_find_line_end()" will return a value that
70 * is not longer than what's in the buffer, so the
71 * "tvb_get_ptr()" call won't throw an exception.
73 linelen
= tvb_find_line_end(tvb
, offset
, -1, &next_offset
, false);
74 line
= tvb_get_ptr(tvb
, offset
, linelen
);
75 icap_type
= ICAP_OTHER
; /* type not known yet */
76 if (is_icap_message(line
, linelen
, &icap_type
))
77 col_add_str(pinfo
->cinfo
, COL_INFO
,
78 format_text(pinfo
->pool
, line
, linelen
));
80 col_set_str(pinfo
->cinfo
, COL_INFO
, "Continuation");
83 ti
= proto_tree_add_item(tree
, proto_icap
, tvb
, offset
, -1,
85 icap_tree
= proto_item_add_subtree(ti
, ett_icap
);
89 * Process the packet data, a line at a time.
91 icap_type
= ICAP_OTHER
; /* type not known yet */
92 while (tvb_offset_exists(tvb
, offset
)) {
94 bool loop_done
= false;
96 * Find the end of the line.
98 linelen
= tvb_find_line_end(tvb
, offset
, -1, &next_offset
,
102 * Get a buffer that refers to the line.
104 line
= tvb_get_ptr(tvb
, offset
, linelen
);
105 lineend
= line
+ linelen
;
110 if (is_icap_message(line
, linelen
, &icap_type
)) {
115 * if it looks like a blank line, end of header perhaps?
122 * No. Does it look like a header?
126 while (linep
< lineend
&& (!loop_done
)) {
130 * This must be a CHAR, and must not be a CTL, to be part
131 * of a token; that means it must be printable ASCII.
133 * XXX - what about leading LWS on continuation
136 if (!g_ascii_isprint(c
)) {
160 * It's a separator, so it's not part of a
161 * token, so it's not a field name for the
162 * beginning of a header.
164 * (We don't have to check for HT; that's
165 * already been ruled out by "iscntrl()".)
167 * XXX - what about ' '? HTTP's checks
176 * This ends the token; we consider this
184 * We don't consider this part of an ICAP message,
185 * so we don't display it.
186 * (Yeah, that means we don't display, say, a text/icap
187 * page, but you can get that from the data pane.)
192 proto_tree_add_format_text(icap_tree
, tvb
, offset
, next_offset
- offset
);
193 offset
= next_offset
;
200 hidden_item
= proto_tree_add_boolean(icap_tree
,
201 hf_icap_options
, tvb
, 0, 0, 1);
202 proto_item_set_hidden(hidden_item
);
206 hidden_item
= proto_tree_add_boolean(icap_tree
,
207 hf_icap_reqmod
, tvb
, 0, 0, 1);
208 proto_item_set_hidden(hidden_item
);
212 hidden_item
= proto_tree_add_boolean(icap_tree
,
213 hf_icap_respmod
, tvb
, 0, 0, 1);
214 proto_item_set_hidden(hidden_item
);
218 hidden_item
= proto_tree_add_boolean(icap_tree
,
219 hf_icap_response
, tvb
, 0, 0, 1);
220 proto_item_set_hidden(hidden_item
);
229 datalen
= tvb_reported_length_remaining(tvb
, offset
);
232 new_tvb
= tvb_new_subset_remaining(tvb
, offset
);
233 call_dissector(http_handle
, new_tvb
, pinfo
, icap_tree
);
237 return tvb_captured_length(tvb
);
242 is_icap_message(const unsigned char *data
, int linelen
, icap_type_t
*type
)
244 #define ICAP_COMPARE(string, length, msgtype) { \
245 if (strncmp(data, string, length) == 0) { \
246 if (*type == ICAP_OTHER) \
252 * From draft-elson-opes-icap-01(72).txt
255 ICAP_COMPARE("ICAP/", 5, ICAP_RESPONSE
); /* response */
258 ICAP_COMPARE("REQMOD ", 7, ICAP_REQMOD
); /* request mod */
261 ICAP_COMPARE("OPTIONS ", 8, ICAP_OPTIONS
); /* options */
262 ICAP_COMPARE("RESPMOD ", 8, ICAP_RESPMOD
); /* response mod */
269 proto_register_icap(void)
271 static hf_register_info hf
[] = {
273 { "Response", "icap.response",
274 FT_BOOLEAN
, BASE_NONE
, NULL
, 0x0,
275 "true if ICAP response", HFILL
}},
277 { "Reqmod", "icap.reqmod",
278 FT_BOOLEAN
, BASE_NONE
, NULL
, 0x0,
279 "true if ICAP reqmod", HFILL
}},
281 { "Respmod", "icap.respmod",
282 FT_BOOLEAN
, BASE_NONE
, NULL
, 0x0,
283 "true if ICAP respmod", HFILL
}},
285 { "Options", "icap.options",
286 FT_BOOLEAN
, BASE_NONE
, NULL
, 0x0,
287 "true if ICAP options", HFILL
}},
290 { "Other", "icap.other",
291 FT_BOOLEAN
, BASE_NONE
, NULL
, 0x0,
292 "true if ICAP other", HFILL
}},
295 static int *ett
[] = {
299 proto_icap
= proto_register_protocol("Internet Content Adaptation Protocol", "ICAP", "icap");
300 proto_register_field_array(proto_icap
, hf
, array_length(hf
));
301 proto_register_subtree_array(ett
, array_length(ett
));
306 proto_reg_handoff_icap(void)
308 dissector_handle_t icap_handle
;
310 http_handle
= find_dissector_add_dependency("http", proto_icap
);
312 icap_handle
= register_dissector("icap", dissect_icap
, proto_icap
);
313 dissector_add_uint_with_preference("tcp.port", TCP_PORT_ICAP
, icap_handle
);
315 /* As ICAPS port is not officially assigned by IANA
316 * (de facto standard is 11344), we default to 0
317 * to have "decode as" available */
318 ssl_dissector_add(0, icap_handle
);
322 * Editor modelines - https://www.wireshark.org/tools/modelines.html
327 * indent-tabs-mode: nil
330 * vi: set shiftwidth=4 tabstop=8 expandtab:
331 * :indentSize=4:tabSize=8:noTabs=true: