epan/dissectors/pidl/samr/samr.cnf cnf_dissect_lsa_BinaryString => lsarpc_dissect_str...
[wireshark-sm.git] / epan / dissectors / packet-pktap.c
blob201b719f571146177a34e3e73f8c33f9b6dec928
1 /*
2 * packet-pktap.c
3 * Routines for dissecting Apple's PKTAP header
5 * Wireshark - Network traffic analyzer
6 * By Gerald Combs <gerald@wireshark.org>
7 * Copyright 2007 Gerald Combs
9 * SPDX-License-Identifier: GPL-2.0-or-later
12 #include "config.h"
14 #include <epan/packet.h>
15 #include <epan/capture_dissectors.h>
16 #include <epan/expert.h>
17 #include <wsutil/pint.h>
19 #include "packet-eth.h"
21 static dissector_handle_t pcap_pktdata_handle;
23 void proto_register_pktap(void);
24 void proto_reg_handoff_pktap(void);
27 * Apple's PKTAP header.
31 * Minimum header length.
33 * XXX - I'm assuming the header begins with a length field so that it
34 * can be transparently *extended*, not so that fields in the current
35 * header can be *omitted*.
37 #define MIN_PKTAP_HDR_LEN 108
40 * Record types.
42 #define PKT_REC_NONE 0 /* nothing follows the header */
43 #define PKT_REC_PACKET 1 /* a packet follows the header */
45 /* Protocol */
46 static int proto_pktap;
48 static int hf_pktap_hdrlen;
49 static int hf_pktap_rectype;
50 static int hf_pktap_dlt;
51 static int hf_pktap_ifname;
52 static int hf_pktap_flags;
53 static int hf_pktap_pfamily;
54 static int hf_pktap_llhdrlen;
55 static int hf_pktap_lltrlrlen;
56 static int hf_pktap_pid;
57 static int hf_pktap_cmdname;
58 static int hf_pktap_svc_class;
59 static int hf_pktap_iftype;
60 static int hf_pktap_ifunit;
61 static int hf_pktap_epid;
62 static int hf_pktap_ecmdname;
64 static int ett_pktap;
66 static expert_field ei_pktap_hdrlen_too_short;
68 static dissector_handle_t pktap_handle;
69 static capture_dissector_handle_t eth_cap_handle;
72 * XXX - these are only little-endian because they've been created on
73 * little-endian machines; the code in bsd/net/pktap.c in XNU writes
74 * the structure out in host byte order.
76 * We haven't been treating it as host-endian in libpcap and libwiretap,
77 * i.e. we haven't been byte-swapping its members when reading it on
78 * a machine whose byte order differs from the byte order of the machine
79 * on which the file is being read.
81 * Furthermore, the header is extensible, so we don't necessarily know
82 * what fields to swap.
84 * Fortunately, the length of the PKTAP header is a 32-bit field and is
85 * *presumably* never going to be 65536 or greater, so if any of the upper
86 * 16 bits appear to be set, it means we're looking at it in the wrong
87 * byte order, and it's never going to be zero, so those bits *will* be
88 * set if it's >= 65536, so we can determine its byte order.
90 * We should do that here.
93 static bool
94 capture_pktap(const unsigned char *pd, int offset _U_, int len, capture_packet_info_t *cpinfo, const union wtap_pseudo_header *pseudo_header _U_)
96 uint32_t hdrlen, rectype, dlt;
98 hdrlen = pletoh32(pd);
99 if (hdrlen < MIN_PKTAP_HDR_LEN || !BYTES_ARE_IN_FRAME(0, len, hdrlen))
100 return false;
102 rectype = pletoh32(pd+4);
103 if (rectype != PKT_REC_PACKET)
104 return false;
106 dlt = pletoh32(pd+4);
108 /* XXX - We should probably combine this with capture_info.c:capture_info_packet() */
109 switch (dlt) {
111 case 1: /* DLT_EN10MB */
112 return call_capture_dissector(eth_cap_handle, pd, hdrlen, len, cpinfo, pseudo_header);
116 return false;
119 static int
120 dissect_pktap(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
122 proto_tree *pktap_tree = NULL;
123 proto_item *ti = NULL;
124 tvbuff_t *next_tvb;
125 int offset = 0;
126 uint32_t pkt_len, rectype, dlt;
128 col_set_str(pinfo->cinfo, COL_PROTOCOL, "PKTAP");
129 col_clear(pinfo->cinfo, COL_INFO);
131 pkt_len = tvb_get_letohl(tvb, offset);
132 col_add_fstr(pinfo->cinfo, COL_INFO, "PKTAP, %u byte header", pkt_len);
134 /* Dissect the packet */
135 ti = proto_tree_add_item(tree, proto_pktap, tvb, offset, pkt_len, ENC_NA);
136 pktap_tree = proto_item_add_subtree(ti, ett_pktap);
138 proto_tree_add_item(pktap_tree, hf_pktap_hdrlen, tvb, offset, 4,
139 ENC_LITTLE_ENDIAN);
140 if (pkt_len < MIN_PKTAP_HDR_LEN) {
141 proto_tree_add_expert(tree, pinfo, &ei_pktap_hdrlen_too_short,
142 tvb, offset, 4);
143 return tvb_captured_length(tvb);
145 offset += 4;
147 proto_tree_add_item(pktap_tree, hf_pktap_rectype, tvb, offset, 4,
148 ENC_LITTLE_ENDIAN);
149 rectype = tvb_get_letohl(tvb, offset);
150 offset += 4;
151 proto_tree_add_item(pktap_tree, hf_pktap_dlt, tvb, offset, 4,
152 ENC_LITTLE_ENDIAN);
153 dlt = tvb_get_letohl(tvb, offset);
154 offset += 4;
155 proto_tree_add_item(pktap_tree, hf_pktap_ifname, tvb, offset, 24,
156 ENC_ASCII);
157 offset += 24;
158 proto_tree_add_item(pktap_tree, hf_pktap_flags, tvb, offset, 4,
159 ENC_LITTLE_ENDIAN);
160 offset += 4;
161 proto_tree_add_item(pktap_tree, hf_pktap_pfamily, tvb, offset, 4,
162 ENC_LITTLE_ENDIAN);
163 offset += 4;
164 proto_tree_add_item(pktap_tree, hf_pktap_llhdrlen, tvb, offset, 4,
165 ENC_LITTLE_ENDIAN);
166 offset += 4;
167 proto_tree_add_item(pktap_tree, hf_pktap_lltrlrlen, tvb, offset, 4,
168 ENC_LITTLE_ENDIAN);
169 offset += 4;
170 proto_tree_add_item(pktap_tree, hf_pktap_pid, tvb, offset, 4,
171 ENC_LITTLE_ENDIAN);
172 offset += 4;
173 proto_tree_add_item(pktap_tree, hf_pktap_cmdname, tvb, offset, 20,
174 ENC_UTF_8);
175 offset += 20;
176 proto_tree_add_item(pktap_tree, hf_pktap_svc_class, tvb, offset, 4,
177 ENC_LITTLE_ENDIAN);
178 offset += 4;
179 proto_tree_add_item(pktap_tree, hf_pktap_iftype, tvb, offset, 2,
180 ENC_LITTLE_ENDIAN);
181 offset += 2;
182 proto_tree_add_item(pktap_tree, hf_pktap_ifunit, tvb, offset, 2,
183 ENC_LITTLE_ENDIAN);
184 offset += 2;
185 proto_tree_add_item(pktap_tree, hf_pktap_epid, tvb, offset, 4,
186 ENC_LITTLE_ENDIAN);
187 offset += 4;
188 proto_tree_add_item(pktap_tree, hf_pktap_ecmdname, tvb, offset, 20,
189 ENC_UTF_8);
190 /*offset += 20;*/
192 if (rectype == PKT_REC_PACKET) {
193 next_tvb = tvb_new_subset_remaining(tvb, pkt_len);
194 call_dissector_with_data(pcap_pktdata_handle, next_tvb,
195 pinfo, tree, &dlt);
197 return tvb_captured_length(tvb);
200 void
201 proto_register_pktap(void)
203 static hf_register_info hf[] = {
204 { &hf_pktap_hdrlen,
205 { "Header length", "pktap.hdrlen",
206 FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } },
207 { &hf_pktap_rectype,
208 { "Record type", "pktap.rectype",
209 FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } },
210 { &hf_pktap_dlt,
211 { "DLT", "pktap.dlt",
212 FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } },
213 { &hf_pktap_ifname, /* fixed length *and* null-terminated */
214 { "Interface name", "pktap.ifname",
215 FT_STRINGZ, BASE_NONE, NULL, 0x0, NULL, HFILL } },
216 { &hf_pktap_flags,
217 { "Flags", "pktap.flags",
218 FT_UINT32, BASE_HEX, NULL, 0x0, NULL, HFILL } },
219 { &hf_pktap_pfamily,
220 { "Protocol family", "pktap.pfamily",
221 FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } },
222 { &hf_pktap_llhdrlen,
223 { "Link-layer header length", "pktap.llhdrlen",
224 FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } },
225 { &hf_pktap_lltrlrlen,
226 { "Link-layer trailer length", "pktap.lltrlrlen",
227 FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } },
228 { &hf_pktap_pid,
229 { "Process ID", "pktap.pid",
230 FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } },
231 { &hf_pktap_cmdname, /* fixed length *and* null-terminated */
232 { "Command name", "pktap.cmdname",
233 FT_STRINGZ, BASE_NONE, NULL, 0x0, NULL, HFILL } },
234 { &hf_pktap_svc_class,
235 { "Service class", "pktap.svc_class",
236 FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } },
237 { &hf_pktap_iftype,
238 { "Interface type", "pktap.iftype",
239 FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL } },
240 { &hf_pktap_ifunit,
241 { "Interface unit", "pktap.ifunit",
242 FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL } },
243 { &hf_pktap_epid,
244 { "Effective process ID", "pktap.epid",
245 FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } },
246 { &hf_pktap_ecmdname, /* fixed length *and* null-terminated */
247 { "Effective command name", "pktap.ecmdname",
248 FT_STRINGZ, BASE_NONE, NULL, 0x0, NULL, HFILL } },
251 static int *ett[] = {
252 &ett_pktap,
255 static ei_register_info ei[] = {
256 { &ei_pktap_hdrlen_too_short,
257 { "pktap.hdrlen_too_short", PI_MALFORMED, PI_ERROR,
258 "Header length is too short", EXPFILL }},
261 expert_module_t* expert_pktap;
263 proto_pktap = proto_register_protocol("PKTAP packet header", "PKTAP",
264 "pktap");
265 proto_register_field_array(proto_pktap, hf, array_length(hf));
266 proto_register_subtree_array(ett, array_length(ett));
267 expert_pktap = expert_register_protocol(proto_pktap);
268 expert_register_field_array(expert_pktap, ei, array_length(ei));
270 pktap_handle = register_dissector("pktap", dissect_pktap, proto_pktap);
273 void
274 proto_reg_handoff_pktap(void)
276 capture_dissector_handle_t pktap_cap_handle;
278 dissector_add_uint("wtap_encap", WTAP_ENCAP_PKTAP, pktap_handle);
280 pcap_pktdata_handle = find_dissector_add_dependency("pcap_pktdata", proto_pktap);
282 /* XXX - WTAP_ENCAP_USER2 to handle Mavericks' botch wherein it
283 uses DLT_USER2 for PKTAP; if you are using DLT_USER2 for your
284 own purposes, feel free to call your own capture_ routine for
285 WTAP_ENCAP_USER2. */
286 pktap_cap_handle = create_capture_dissector_handle(capture_pktap, proto_pktap);
287 capture_dissector_add_uint("wtap_encap", WTAP_ENCAP_PKTAP, pktap_cap_handle);
288 capture_dissector_add_uint("wtap_encap", WTAP_ENCAP_USER2, pktap_cap_handle);
290 eth_cap_handle = find_capture_dissector("eth");
294 * Editor modelines - https://www.wireshark.org/tools/modelines.html
296 * Local variables:
297 * c-basic-offset: 8
298 * tab-width: 8
299 * indent-tabs-mode: t
300 * End:
302 * vi: set shiftwidth=8 tabstop=8 noexpandtab:
303 * :indentSize=8:tabSize=8:noTabs=false: