Revert "TODO epan/dissectors/asn1/kerberos/packet-kerberos-template.c new GSS flags"
[wireshark-sm.git] / epan / dissectors / packet-iapp.c
blob92059ce95d851dd877a634f0073650056a963469
1 /* packet-iapp.c
2 * Routines for IAPP dissection
3 * Copyright 2002, Alfred Arnold <aarnold@elsa.de>
5 * Wireshark - Network traffic analyzer
6 * By Gerald Combs <gerald@wireshark.org>
7 * Copyright 1998 Gerald Combs
9 * SPDX-License-Identifier: GPL-2.0-or-later
12 #include "config.h"
14 #include <epan/packet.h>
15 #include <epan/expert.h>
16 #include <epan/tfs.h>
17 #include <wsutil/array.h>
19 void proto_register_iapp(void);
20 void proto_reg_handoff_iapp(void);
22 static dissector_handle_t iapp_handle;
24 /* Initialize the protocol and registered fields */
25 static int proto_iapp;
26 static int hf_iapp_version;
27 static int hf_iapp_type;
28 static int hf_iapp_cap_forwarding;
29 static int hf_iapp_cap_wep;
30 static int hf_iapp_auth_status;
31 static int hf_iapp_auth_string;
32 static int hf_iapp_auth_uint;
33 static int hf_iapp_auth_ipaddr;
34 static int hf_iapp_auth_trailer;
35 static int hf_iapp_pdu_ssid;
36 static int hf_iapp_pdu_bytes;
37 static int hf_iapp_pdu_uint;
38 static int hf_iapp_pdu_phytype;
39 static int hf_iapp_pdu_regdomain;
40 static int hf_iapp_pdu_oui_ident;
42 /* Initialize the subtree pointers */
43 static int ett_iapp;
44 static int ett_iapp_pdu;
45 static int ett_iapp_subpdu;
46 static int ett_iapp_cap;
47 static int ett_iapp_auth;
48 static int ett_iapp_authinfo;
50 static expert_field ei_iapp_no_pdus;
52 #define UDP_PORT_IAPP 2313
54 #define IAPP_ANNOUNCE_REQUEST 0
55 #define IAPP_ANNOUNCE_RESPONSE 1
56 #define IAPP_HANDOVER_REQUEST 2
57 #define IAPP_HANDOVER_RESPONSE 3
59 #define IAPP_PDU_SSID 0
60 #define IAPP_PDU_BSSID 1
61 #define IAPP_PDU_OLDBSSID 2
62 #define IAPP_PDU_MSADDR 3
63 #define IAPP_PDU_CAPABILITY 4
64 #define IAPP_PDU_ANNOUNCEINT 5
65 #define IAPP_PDU_HOTIMEOUT 6
66 #define IAPP_PDU_MESSAGEID 7
67 #define IAPP_PDU_PHYTYPE 0x10
68 #define IAPP_PDU_REGDOMAIN 0x11
69 #define IAPP_PDU_CHANNEL 0x12
70 #define IAPP_PDU_BEACONINT 0x13
71 #define IAPP_PDU_OUIIDENT 0x80
72 #define IAPP_PDU_AUTHINFO 0x81
74 #define IAPP_CAP_FORWARDING 0x40
75 #define IAPP_CAP_WEP 0x20
77 #define IAPP_PHY_PROP 0x00
78 #define IAPP_PHY_FHSS 0x01
79 #define IAPP_PHY_DSSS 0x02
80 #define IAPP_PHY_IR 0x03
81 #define IAPP_PHY_OFDM 0x04
83 #define IAPP_DOM_FCC 0x10
84 #define IAPP_DOM_IC 0x20
85 #define IAPP_DOM_ETSI 0x30
86 #define IAPP_DOM_SPAIN 0x31
87 #define IAPP_DOM_FRANCE 0x32
88 #define IAPP_DOM_MKK 0x40
90 #define IAPP_AUTH_STATUS 0x01
91 #define IAPP_AUTH_USERNAME 0x02
92 #define IAPP_AUTH_PROVNAME 0x03
93 #define IAPP_AUTH_RXPKTS 0x04
94 #define IAPP_AUTH_TXPKTS 0x05
95 #define IAPP_AUTH_RXBYTES 0x06
96 #define IAPP_AUTH_TXBYTES 0x07
97 #define IAPP_AUTH_LOGINTIME 0x08
98 #define IAPP_AUTH_TIMELIMIT 0x09
99 #define IAPP_AUTH_VOLLIMIT 0x0a
100 #define IAPP_AUTH_ACCCYCLE 0x0b
101 #define IAPP_AUTH_RXGWORDS 0x0c
102 #define IAPP_AUTH_TXGWORDS 0x0d
103 #define IAPP_AUTH_IPADDR 0x0e
104 #define IAPP_AUTH_TRAILER 0xff
106 static const value_string iapp_vals[] = {
107 {IAPP_ANNOUNCE_REQUEST, "Announce Request"},
108 {IAPP_ANNOUNCE_RESPONSE, "Announce Response"},
109 {IAPP_HANDOVER_REQUEST, "Handover Request"},
110 {IAPP_HANDOVER_RESPONSE, "Handover Response"},
111 {0, NULL}
114 static const value_string iapp_pdu_type_vals[] = {
115 {IAPP_PDU_SSID, "Network Name"},
116 {IAPP_PDU_BSSID, "BSSID"},
117 {IAPP_PDU_OLDBSSID, "Old BSSID"},
118 {IAPP_PDU_MSADDR, "Mobile Station Address"},
119 {IAPP_PDU_CAPABILITY, "Capabilities"},
120 {IAPP_PDU_ANNOUNCEINT, "Announce Interval"},
121 {IAPP_PDU_HOTIMEOUT, "Handover Timeout"},
122 {IAPP_PDU_MESSAGEID, "Message ID"},
123 {IAPP_PDU_PHYTYPE, "PHY Type"},
124 {IAPP_PDU_REGDOMAIN, "Regulatory Domain"},
125 {IAPP_PDU_CHANNEL, "Radio Channel"},
126 {IAPP_PDU_BEACONINT, "Beacon Interval"},
127 {IAPP_PDU_OUIIDENT, "OUI Identifier"},
128 {IAPP_PDU_AUTHINFO, "ELSA Authentication Info"},
129 {0, NULL}
132 static const value_string iapp_phy_vals[] = {
133 {IAPP_PHY_PROP, "Proprietary"},
134 {IAPP_PHY_FHSS, "FHSS"},
135 {IAPP_PHY_DSSS, "DSSS"},
136 {IAPP_PHY_IR, "Infrared"},
137 {IAPP_PHY_OFDM, "OFDM"},
138 {0, NULL}
141 static const value_string iapp_dom_vals[] = {
142 {IAPP_DOM_FCC, "FCC (USA)"},
143 {IAPP_DOM_IC, "IC (Canada)"},
144 {IAPP_DOM_ETSI, "ETSI (Europe)"},
145 {IAPP_DOM_SPAIN, "Spain"},
146 {IAPP_DOM_FRANCE, "France"},
147 {IAPP_DOM_MKK, "MKK (Japan)"},
148 {0, NULL}
151 static const value_string iapp_auth_type_vals[] = {
152 {IAPP_AUTH_STATUS, "Status"},
153 {IAPP_AUTH_USERNAME, "User Name"},
154 {IAPP_AUTH_PROVNAME, "Provider Name"},
155 {IAPP_AUTH_RXPKTS, "Received Packets"},
156 {IAPP_AUTH_TXPKTS, "Transmitted Packets"},
157 {IAPP_AUTH_RXBYTES, "Received Octets"},
158 {IAPP_AUTH_TXBYTES, "Transmitted Octets"},
159 {IAPP_AUTH_LOGINTIME, "Session Time"},
160 {IAPP_AUTH_TIMELIMIT, "Time Limit"},
161 {IAPP_AUTH_VOLLIMIT, "Volume Limit"},
162 {IAPP_AUTH_ACCCYCLE, "Accounting Cycle"},
163 {IAPP_AUTH_TRAILER, "Authenticator"},
164 {IAPP_AUTH_RXGWORDS, "Received Gigawords"},
165 {IAPP_AUTH_TXGWORDS, "Transmitted Gigawords"},
166 {IAPP_AUTH_IPADDR, "Client IP Address"},
167 {0, NULL}
171 /* dissect a capability bit field */
173 static void dissect_caps(proto_tree *tree, tvbuff_t *tvb, int offset)
175 proto_tree *captree;
177 captree = proto_tree_add_subtree(tree, tvb, offset, 1, ett_iapp_cap, NULL, "Capabilities");
178 proto_tree_add_item(captree, hf_iapp_cap_forwarding, tvb, offset, 1, ENC_NA);
179 proto_tree_add_item(captree, hf_iapp_cap_wep, tvb, offset, 1, ENC_NA);
182 static void
183 add_authval_str(proto_tree *tree, int type, int len, tvbuff_t *tvb, int offset)
185 int val;
187 switch (type)
189 case IAPP_AUTH_STATUS:
190 val = tvb_get_uint8(tvb, offset);
191 proto_tree_add_uint_format_value(tree, hf_iapp_auth_status, tvb, offset, 1, val, "%s", val ? "Authenticated" : "Not authenticated");
192 break;
193 case IAPP_AUTH_USERNAME:
194 case IAPP_AUTH_PROVNAME:
195 proto_tree_add_item(tree, hf_iapp_auth_string, tvb, offset, 1, ENC_ASCII);
196 break;
197 case IAPP_AUTH_RXPKTS:
198 case IAPP_AUTH_TXPKTS:
199 case IAPP_AUTH_RXBYTES:
200 case IAPP_AUTH_TXBYTES:
201 case IAPP_AUTH_RXGWORDS:
202 case IAPP_AUTH_TXGWORDS:
203 case IAPP_AUTH_VOLLIMIT:
204 proto_tree_add_item(tree, hf_iapp_auth_uint, tvb, offset, 4, ENC_BIG_ENDIAN);
205 break;
206 case IAPP_AUTH_LOGINTIME:
207 case IAPP_AUTH_TIMELIMIT:
208 case IAPP_AUTH_ACCCYCLE:
209 val = tvb_get_ntohl(tvb, offset);
210 proto_tree_add_uint_format_value(tree, hf_iapp_auth_uint, tvb, offset, 4, val, "%d seconds", val);
211 break;
212 case IAPP_AUTH_IPADDR:
213 proto_tree_add_item(tree, hf_iapp_auth_ipaddr, tvb, offset, 4, ENC_BIG_ENDIAN);
214 break;
215 case IAPP_AUTH_TRAILER:
216 proto_tree_add_item(tree, hf_iapp_auth_trailer, tvb, offset, len, ENC_NA);
217 break;
221 /* dissect authentication info */
223 static void dissect_authinfo(proto_item *pitem, tvbuff_t *tvb, int offset, int sumlen)
225 proto_tree *authtree, *value_tree;
226 uint8_t pdu_type;
227 uint16_t len;
229 authtree = proto_item_add_subtree(pitem, ett_iapp_auth);
231 while (sumlen > 0)
233 pdu_type = tvb_get_uint8(tvb, offset);
234 len = tvb_get_ntohs(tvb, offset+1);
236 value_tree = proto_tree_add_subtree_format(authtree, tvb, offset, len + 3,
237 ett_iapp_authinfo, NULL, "%s (%d)",
238 val_to_str_const(pdu_type, iapp_auth_type_vals, "Unknown PDU Type"),
239 pdu_type);
240 add_authval_str(value_tree, pdu_type, len, tvb, offset+3);
242 sumlen -= (len + 3);
243 offset += (len + 3);
247 /* get displayable values of PDU contents */
249 static bool
250 append_pduval_str(proto_tree *tree, int type, int len, tvbuff_t *tvb, int offset,
251 bool is_fhss)
253 int val;
255 switch (type)
257 case IAPP_PDU_SSID:
258 proto_tree_add_item(tree, hf_iapp_pdu_ssid, tvb, offset, len, ENC_ASCII);
259 break;
260 case IAPP_PDU_BSSID:
261 case IAPP_PDU_OLDBSSID:
262 case IAPP_PDU_MSADDR:
263 proto_tree_add_item(tree, hf_iapp_pdu_bytes, tvb, offset, len, ENC_NA);
264 break;
265 case IAPP_PDU_CAPABILITY:
266 dissect_caps(tree, tvb, offset);
267 break;
268 case IAPP_PDU_ANNOUNCEINT:
269 val = tvb_get_ntohs(tvb, offset);
270 proto_tree_add_uint_format_value(tree, hf_iapp_pdu_uint, tvb, offset, 2, val, "%d seconds", val);
271 break;
272 case IAPP_PDU_HOTIMEOUT:
273 case IAPP_PDU_BEACONINT:
274 val = tvb_get_ntohs(tvb, offset);
275 proto_tree_add_uint_format_value(tree, hf_iapp_pdu_uint, tvb, offset, 2, val, "%d Kus", val);
276 break;
277 case IAPP_PDU_MESSAGEID:
278 proto_tree_add_item(tree, hf_iapp_pdu_uint, tvb, offset, 2, ENC_BIG_ENDIAN);
279 break;
280 case IAPP_PDU_PHYTYPE:
281 proto_tree_add_item(tree, hf_iapp_pdu_phytype, tvb, offset, 1, ENC_BIG_ENDIAN);
282 is_fhss = (tvb_get_uint8(tvb, offset) == IAPP_PHY_FHSS);
283 break;
284 case IAPP_PDU_REGDOMAIN:
285 proto_tree_add_item(tree, hf_iapp_pdu_regdomain, tvb, offset, 1, ENC_BIG_ENDIAN);
286 break;
287 case IAPP_PDU_CHANNEL:
288 if (is_fhss)
290 val = tvb_get_uint8(tvb, offset);
291 proto_tree_add_uint_format(tree, hf_iapp_pdu_uint, tvb, offset, 1, val,
292 "Pattern set %d, sequence %d", ((val >> 6) & 3) + 1, (val & 31) + 1);
294 else
295 proto_tree_add_item(tree, hf_iapp_pdu_uint, tvb, offset, 1, ENC_BIG_ENDIAN);
296 break;
297 case IAPP_PDU_OUIIDENT:
298 proto_tree_add_item(tree, hf_iapp_pdu_oui_ident, tvb, offset, 3, ENC_BIG_ENDIAN);
299 break;
301 return is_fhss;
304 /* code to dissect a list of PDUs */
306 static void
307 dissect_pdus(tvbuff_t *tvb, packet_info *pinfo, int offset, proto_tree *pdutree, proto_item *pduitem, int pdulen)
309 uint8_t pdu_type;
310 uint16_t len;
311 proto_item *ti;
312 bool is_fhss;
313 proto_tree *subtree;
315 if (!pdulen)
317 expert_add_info(pinfo, pduitem, &ei_iapp_no_pdus);
318 return;
321 is_fhss = false;
322 while (pdulen > 0)
324 pdu_type = tvb_get_uint8(tvb, offset);
325 len = tvb_get_ntohs(tvb, offset+1);
327 subtree = proto_tree_add_subtree_format(pdutree, tvb, offset, len + 3,
328 ett_iapp_subpdu, &ti, "%s (%d)",
329 val_to_str_const(pdu_type, iapp_pdu_type_vals, "Unknown PDU Type"),
330 pdu_type);
331 is_fhss = append_pduval_str(subtree, pdu_type, len, tvb,
332 offset+3, is_fhss);
334 if (pdu_type == IAPP_PDU_AUTHINFO)
335 dissect_authinfo(ti, tvb, offset + 3, len);
337 pdulen -= (len + 3);
338 offset += (len + 3);
342 /* code to dissect an IAPP packet */
343 static int
344 dissect_iapp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
346 proto_item *ti, *pduitem;
347 proto_tree *iapp_tree, *pdutree;
348 uint8_t ia_version;
349 uint8_t ia_type;
350 const char *codestrval;
352 col_set_str(pinfo->cinfo, COL_PROTOCOL, "IAPP");
354 col_clear(pinfo->cinfo, COL_INFO);
356 ia_version = tvb_get_uint8(tvb, 0);
357 ia_type = tvb_get_uint8(tvb, 1);
359 codestrval = val_to_str_const(ia_type, iapp_vals, "Unknown Packet");
360 col_add_fstr(pinfo->cinfo, COL_INFO, "%s(%d) (version=%d)", codestrval, ia_type, ia_version);
362 ti = proto_tree_add_item(tree, proto_iapp, tvb, 0, -1, ENC_NA);
363 iapp_tree = proto_item_add_subtree(ti, ett_iapp);
365 /* common header for all IAPP frames */
367 proto_tree_add_item(iapp_tree, hf_iapp_version, tvb, 0, 1, ENC_BIG_ENDIAN);
368 proto_tree_add_item(iapp_tree, hf_iapp_type, tvb, 1, 1, ENC_BIG_ENDIAN);
370 pdutree = proto_tree_add_subtree(iapp_tree, tvb, 2, -1,
371 ett_iapp_pdu, &pduitem, "Protocol data units");
373 dissect_pdus(tvb, pinfo, 2, pdutree, pduitem,
374 tvb_captured_length_remaining(tvb, 2));
376 return tvb_captured_length(tvb);
380 /* Register the protocol with Wireshark */
382 /* this format is require because a script is used to build the C function
383 that calls all the protocol registration.
386 void
387 proto_register_iapp(void)
390 static hf_register_info hf[] = {
391 { &hf_iapp_version,
392 { "Version", "iapp.version", FT_UINT8, BASE_DEC, NULL, 0x00, NULL, HFILL }
394 { &hf_iapp_type,
395 { "Type", "iapp.type", FT_UINT8, BASE_DEC, VALS(iapp_vals), 0x00, NULL, HFILL }
397 { &hf_iapp_cap_forwarding,
398 { "Forwarding", "iapp.cap.forwarding", FT_BOOLEAN, 8, TFS(&tfs_yes_no), IAPP_CAP_FORWARDING, NULL, HFILL }
400 { &hf_iapp_cap_wep,
401 { "WEP", "iapp.cap.wep", FT_BOOLEAN, 8, TFS(&tfs_yes_no), IAPP_CAP_WEP, NULL, HFILL }
403 { &hf_iapp_auth_status,
404 { "Status", "iapp.auth.status", FT_UINT8, BASE_DEC, NULL, 0x00, NULL, HFILL }
406 { &hf_iapp_auth_uint,
407 { "Value", "iapp.auth.uint", FT_UINT32, BASE_DEC, NULL, 0x00, NULL, HFILL }
409 { &hf_iapp_auth_string,
410 { "Value", "iapp.auth.string", FT_STRING, BASE_NONE, NULL, 0x00, NULL, HFILL }
412 { &hf_iapp_auth_ipaddr,
413 { "IP Address", "iapp.auth.ipaddr", FT_IPv4, BASE_NONE, NULL, 0x00, NULL, HFILL }
415 { &hf_iapp_auth_trailer,
416 { "Trailer", "iapp.auth.trailer", FT_BYTES, BASE_NONE, NULL, 0x00, NULL, HFILL }
418 { &hf_iapp_pdu_ssid,
419 { "SSID", "iapp.pdu.ssid", FT_STRING, BASE_NONE, NULL, 0x00, NULL, HFILL }
421 { &hf_iapp_pdu_bytes,
422 { "Value", "iapp.pdu.bytes", FT_BYTES, BASE_NONE, NULL, 0x00, NULL, HFILL }
424 { &hf_iapp_pdu_uint,
425 { "Value", "iapp.pdu.uint", FT_UINT32, BASE_DEC, NULL, 0x00, NULL, HFILL }
427 { &hf_iapp_pdu_phytype,
428 { "PHY Type", "iapp.pdu.phytype", FT_UINT8, BASE_DEC, VALS(iapp_phy_vals), 0x00, NULL, HFILL }
430 { &hf_iapp_pdu_regdomain,
431 { "Reg domain", "iapp.pdu.regdomain", FT_UINT8, BASE_DEC, VALS(iapp_dom_vals), 0x00, NULL, HFILL }
433 { &hf_iapp_pdu_oui_ident,
434 { "OUI", "iapp.pdu.oui_ident", FT_UINT24, BASE_OUI, NULL, 0x00, NULL, HFILL }
438 static int *ett[] = {
439 &ett_iapp,
440 &ett_iapp_pdu,
441 &ett_iapp_subpdu,
442 &ett_iapp_cap,
443 &ett_iapp_auth,
444 &ett_iapp_authinfo
447 static ei_register_info ei[] = {
448 { &ei_iapp_no_pdus, { "iapp.no_pdus", PI_PROTOCOL, PI_NOTE, "No PDUs found", EXPFILL }},
451 expert_module_t* expert_iapp;
453 /* Register the protocol name and description */
454 proto_iapp = proto_register_protocol("Inter-Access-Point Protocol", "IAPP", "iapp");
456 /* Required function calls to register the header fields and subtrees used */
457 proto_register_field_array(proto_iapp, hf, array_length(hf));
458 proto_register_subtree_array(ett, array_length(ett));
459 expert_iapp = expert_register_protocol(proto_iapp);
460 expert_register_field_array(expert_iapp, ei, array_length(ei));
462 iapp_handle = register_dissector("iapp", dissect_iapp, proto_iapp);
466 /* If this dissector uses sub-dissector registration add a registration routine.
467 This format is required because a script is used to find these routines and
468 create the code that calls these routines.
470 void
471 proto_reg_handoff_iapp(void)
473 dissector_add_uint_with_preference("udp.port", UDP_PORT_IAPP, iapp_handle);
476 * Editor modelines - https://www.wireshark.org/tools/modelines.html
478 * Local variables:
479 * c-basic-offset: 4
480 * tab-width: 8
481 * indent-tabs-mode: nil
482 * End:
484 * vi: set shiftwidth=4 tabstop=8 expandtab:
485 * :indentSize=4:tabSize=8:noTabs=true: