2 * Routines for IAPP dissection
3 * Copyright 2002, Alfred Arnold <aarnold@elsa.de>
7 * Wireshark - Network traffic analyzer
8 * By Gerald Combs <gerald@wireshark.org>
9 * Copyright 1998 Gerald Combs
11 * This program is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU General Public License
13 * as published by the Free Software Foundation; either version 2
14 * of the License, or (at your option) any later version.
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
28 #include <epan/packet.h>
29 #include <epan/to_str.h>
32 /* Initialize the protocol and registered fields */
33 static int proto_iapp
= -1;
34 static int hf_iapp_version
= -1;
35 static int hf_iapp_type
= -1;
37 /* Initialize the subtree pointers */
38 static gint ett_iapp
= -1;
39 static gint ett_iapp_pdu
= -1;
40 static gint ett_iapp_cap
= -1;
41 static gint ett_iapp_auth
= -1;
43 #define UDP_PORT_IAPP 2313
45 #define IAPP_ANNOUNCE_REQUEST 0
46 #define IAPP_ANNOUNCE_RESPONSE 1
47 #define IAPP_HANDOVER_REQUEST 2
48 #define IAPP_HANDOVER_RESPONSE 3
50 #define IAPP_PDU_SSID 0
51 #define IAPP_PDU_BSSID 1
52 #define IAPP_PDU_OLDBSSID 2
53 #define IAPP_PDU_MSADDR 3
54 #define IAPP_PDU_CAPABILITY 4
55 #define IAPP_PDU_ANNOUNCEINT 5
56 #define IAPP_PDU_HOTIMEOUT 6
57 #define IAPP_PDU_MESSAGEID 7
58 #define IAPP_PDU_PHYTYPE 0x10
59 #define IAPP_PDU_REGDOMAIN 0x11
60 #define IAPP_PDU_CHANNEL 0x12
61 #define IAPP_PDU_BEACONINT 0x13
62 #define IAPP_PDU_OUIIDENT 0x80
63 #define IAPP_PDU_AUTHINFO 0x81
65 #define IAPP_CAP_FORWARDING 0x40
66 #define IAPP_CAP_WEP 0x20
68 #define IAPP_PHY_PROP 0x00
69 #define IAPP_PHY_FHSS 0x01
70 #define IAPP_PHY_DSSS 0x02
71 #define IAPP_PHY_IR 0x03
72 #define IAPP_PHY_OFDM 0x04
74 #define IAPP_DOM_FCC 0x10
75 #define IAPP_DOM_IC 0x20
76 #define IAPP_DOM_ETSI 0x30
77 #define IAPP_DOM_SPAIN 0x31
78 #define IAPP_DOM_FRANCE 0x32
79 #define IAPP_DOM_MKK 0x40
81 #define IAPP_AUTH_STATUS 0x01
82 #define IAPP_AUTH_USERNAME 0x02
83 #define IAPP_AUTH_PROVNAME 0x03
84 #define IAPP_AUTH_RXPKTS 0x04
85 #define IAPP_AUTH_TXPKTS 0x05
86 #define IAPP_AUTH_RXBYTES 0x06
87 #define IAPP_AUTH_TXBYTES 0x07
88 #define IAPP_AUTH_LOGINTIME 0x08
89 #define IAPP_AUTH_TIMELIMIT 0x09
90 #define IAPP_AUTH_VOLLIMIT 0x0a
91 #define IAPP_AUTH_ACCCYCLE 0x0b
92 #define IAPP_AUTH_RXGWORDS 0x0c
93 #define IAPP_AUTH_TXGWORDS 0x0d
94 #define IAPP_AUTH_IPADDR 0x0e
95 #define IAPP_AUTH_TRAILER 0xff
98 typedef struct _e_iapphdr
{
103 typedef struct _e_pduhdr
{
109 static const value_string iapp_vals
[] = {
110 {IAPP_ANNOUNCE_REQUEST
, "Announce Request"},
111 {IAPP_ANNOUNCE_RESPONSE
, "Announce Response"},
112 {IAPP_HANDOVER_REQUEST
, "Handover Request"},
113 {IAPP_HANDOVER_RESPONSE
, "Handover Response"},
116 static const value_string iapp_pdu_type_vals
[] = {
117 {IAPP_PDU_SSID
, "Network Name"},
118 {IAPP_PDU_BSSID
, "BSSID"},
119 {IAPP_PDU_OLDBSSID
, "Old BSSID"},
120 {IAPP_PDU_MSADDR
, "Mobile Station Address"},
121 {IAPP_PDU_CAPABILITY
, "Capabilities"},
122 {IAPP_PDU_ANNOUNCEINT
, "Announce Interval"},
123 {IAPP_PDU_HOTIMEOUT
, "Handover Timeout"},
124 {IAPP_PDU_MESSAGEID
, "Message ID"},
125 {IAPP_PDU_PHYTYPE
, "PHY Type"},
126 {IAPP_PDU_REGDOMAIN
, "Regulatory Domain"},
127 {IAPP_PDU_CHANNEL
, "Radio Channel"},
128 {IAPP_PDU_BEACONINT
, "Beacon Interval"},
129 {IAPP_PDU_OUIIDENT
, "OUI Identifier"},
130 {IAPP_PDU_AUTHINFO
, "ELSA Authentication Info"},
133 static const value_string iapp_cap_vals
[] = {
134 {IAPP_CAP_FORWARDING
, "Forwarding"},
135 {IAPP_CAP_WEP
, "WEP"},
138 static const value_string iapp_phy_vals
[] = {
139 {IAPP_PHY_PROP
, "Proprietary"},
140 {IAPP_PHY_FHSS
, "FHSS"},
141 {IAPP_PHY_DSSS
, "DSSS"},
142 {IAPP_PHY_IR
, "Infrared"},
143 {IAPP_PHY_OFDM
, "OFDM"},
146 static const value_string iapp_dom_vals
[] = {
147 {IAPP_DOM_FCC
, "FCC (USA)"},
148 {IAPP_DOM_IC
, "IC (Canada)"},
149 {IAPP_DOM_ETSI
, "ETSI (Europe)"},
150 {IAPP_DOM_SPAIN
, "Spain"},
151 {IAPP_DOM_FRANCE
, "France"},
152 {IAPP_DOM_MKK
, "MKK (Japan)"},
155 static const value_string iapp_auth_type_vals
[] = {
156 {IAPP_AUTH_STATUS
, "Status"},
157 {IAPP_AUTH_USERNAME
, "User Name"},
158 {IAPP_AUTH_PROVNAME
, "Provider Name"},
159 {IAPP_AUTH_RXPKTS
, "Received Packets"},
160 {IAPP_AUTH_TXPKTS
, "Transmitted Packets"},
161 {IAPP_AUTH_RXBYTES
, "Received Octets"},
162 {IAPP_AUTH_TXBYTES
, "Transmitted Octets"},
163 {IAPP_AUTH_LOGINTIME
, "Session Time"},
164 {IAPP_AUTH_TIMELIMIT
, "Time Limit"},
165 {IAPP_AUTH_VOLLIMIT
, "Volume Limit"},
166 {IAPP_AUTH_ACCCYCLE
, "Accounting Cycle"},
167 {IAPP_AUTH_TRAILER
, "Authenticator"},
168 {IAPP_AUTH_RXGWORDS
, "Received Gigawords"},
169 {IAPP_AUTH_TXGWORDS
, "Transmitted Gigawords"},
170 {IAPP_AUTH_IPADDR
, "Client IP Address"},
174 /* dissect a capability bit field */
176 static void dissect_caps(proto_item
*pitem
, tvbuff_t
*tvb
, int offset
)
179 int bit
, val
, thisbit
;
181 gchar bitval
[4+1+4+1]; /* "xxxx xxxx\0" */
183 captree
= proto_item_add_subtree(pitem
, ett_iapp_cap
);
184 val
= tvb_get_guint8(tvb
, offset
+ 3);
186 for (bit
= 7; bit
>= 0; bit
--)
189 strval
= try_val_to_str(thisbit
, iapp_cap_vals
);
192 other_decode_bitfield_value(bitval
, val
, thisbit
, 8);
193 proto_tree_add_text(captree
, tvb
, offset
+ 3, 1, "%s %s: %s",
194 bitval
, strval
, val
& thisbit
? "Yes" : "No");
200 append_authval_str(proto_item
*ti
, int type
, int len
, tvbuff_t
*tvb
, int offset
)
204 proto_item_append_text(ti
, " Value: ");
208 case IAPP_AUTH_STATUS
:
209 proto_item_append_text(ti
, "%s", tvb_get_guint8(tvb
, offset
+ 3) ? "Authenticated" : "Not authenticated");
211 case IAPP_AUTH_USERNAME
:
212 case IAPP_AUTH_PROVNAME
:
213 proto_item_append_text(ti
, "\"%s\"",
214 tvb_format_text(tvb
, offset
+ 3, len
));
216 case IAPP_AUTH_RXPKTS
:
217 case IAPP_AUTH_TXPKTS
:
218 case IAPP_AUTH_RXBYTES
:
219 case IAPP_AUTH_TXBYTES
:
220 case IAPP_AUTH_RXGWORDS
:
221 case IAPP_AUTH_TXGWORDS
:
222 case IAPP_AUTH_VOLLIMIT
:
223 val
= tvb_get_ntohl(tvb
, offset
+ 3);
224 proto_item_append_text(ti
, "%d", val
);
226 case IAPP_AUTH_LOGINTIME
:
227 case IAPP_AUTH_TIMELIMIT
:
228 case IAPP_AUTH_ACCCYCLE
:
229 val
= tvb_get_ntohl(tvb
, offset
+ 3);
230 proto_item_append_text(ti
, "%d seconds", val
);
232 case IAPP_AUTH_IPADDR
:
233 proto_item_append_text(ti
, "%s", tvb_ip_to_str(tvb
, offset
+ 3));
235 case IAPP_AUTH_TRAILER
:
236 for (z
= 0; z
< len
; z
++)
237 proto_item_append_text(ti
, "%s%02x", z
? " " : "",
238 tvb_get_guint8(tvb
, offset
+ 3 + z
));
243 /* dissect authentication info */
245 static void dissect_authinfo(proto_item
*pitem
, tvbuff_t
*tvb
, int offset
, int sumlen
)
247 proto_tree
*authtree
;
252 authtree
= proto_item_add_subtree(pitem
, ett_iapp_auth
);
256 tvb_memcpy(tvb
, (guint8
*)&pduhdr
, offset
, sizeof(e_pduhdr
));
257 len
= (((int)pduhdr
.pdu_len_h
) << 8) + pduhdr
.pdu_len_l
;
259 ti
= proto_tree_add_text(authtree
, tvb
, offset
, len
+ 3,
261 val_to_str_const(pduhdr
.pdu_type
, iapp_auth_type_vals
,
264 append_authval_str(ti
, pduhdr
.pdu_type
, len
, tvb
, offset
);
271 /* get displayable values of PDU contents */
274 append_pduval_str(proto_item
*ti
, int type
, int len
, tvbuff_t
*tvb
, int offset
,
280 proto_item_append_text(ti
, " Value: ");
285 proto_item_append_text(ti
, "\"%s\"",
286 tvb_format_text(tvb
, offset
+ 3, len
));
289 case IAPP_PDU_OLDBSSID
:
290 case IAPP_PDU_MSADDR
:
291 for (z
= 0; z
< len
; z
++)
292 proto_item_append_text(ti
, "%s%02x", z
? ":" : "",
293 tvb_get_guint8(tvb
, offset
+ 3 + z
));
295 case IAPP_PDU_CAPABILITY
:
299 val
= tvb_get_guint8(tvb
, offset
+ 3);
300 proto_item_append_text(ti
, "%02x (", val
);
301 for (mask
= 0x80; mask
; mask
>>= 1)
304 strval
= try_val_to_str(mask
, iapp_cap_vals
);
308 proto_item_append_text(ti
, " ");
309 proto_item_append_text(ti
, "%s", strval
);
313 proto_item_append_text(ti
, ")");
316 case IAPP_PDU_ANNOUNCEINT
:
317 val
= tvb_get_ntohs(tvb
, offset
+ 3);
318 proto_item_append_text(ti
, "%d seconds", val
);
320 case IAPP_PDU_HOTIMEOUT
:
321 case IAPP_PDU_BEACONINT
:
322 val
= tvb_get_ntohs(tvb
, offset
+ 3);
323 proto_item_append_text(ti
, "%d Kus", val
);
325 case IAPP_PDU_MESSAGEID
:
326 val
= tvb_get_ntohs(tvb
, offset
+ 3);
327 proto_item_append_text(ti
, "%d", val
);
329 case IAPP_PDU_PHYTYPE
:
330 val
= tvb_get_guint8(tvb
, offset
+ 3);
331 strval
= val_to_str_const(val
, iapp_phy_vals
, "Unknown");
332 proto_item_append_text(ti
, "%s", strval
);
333 is_fhss
= (val
== IAPP_PHY_FHSS
);
335 case IAPP_PDU_REGDOMAIN
:
336 val
= tvb_get_guint8(tvb
, offset
+ 3);
337 strval
= val_to_str_const(val
, iapp_dom_vals
, "Unknown");
338 proto_item_append_text(ti
, "%s", strval
);
340 case IAPP_PDU_CHANNEL
:
341 val
= tvb_get_guint8(tvb
, offset
+ 3);
343 proto_item_append_text(ti
, "Pattern set %d, sequence %d",
344 ((val
>> 6) & 3) + 1, (val
& 31) + 1);
346 proto_item_append_text(ti
, "%d", val
);
348 case IAPP_PDU_OUIIDENT
:
349 for (val
= z
= 0; z
< 3; z
++)
350 val
= (val
<< 8) | tvb_get_guint8(tvb
, offset
+ 3 + z
);
351 strval
= val_to_str_const(val
, oui_vals
, "Unknown");
352 proto_item_append_text(ti
, "%s", strval
);
358 /* code to dissect a list of PDUs */
361 dissect_pdus(tvbuff_t
*tvb
, int offset
, proto_tree
*pdutree
, int pdulen
)
370 proto_tree_add_text(pdutree
, tvb
, offset
, 0, "No PDUs found");
377 tvb_memcpy(tvb
, (guint8
*)&pduhdr
, offset
, sizeof(e_pduhdr
));
378 len
= (((int)pduhdr
.pdu_len_h
) << 8) + pduhdr
.pdu_len_l
;
380 ti
= proto_tree_add_text(pdutree
, tvb
, offset
, len
+ 3,
382 val_to_str_const(pduhdr
.pdu_type
, iapp_pdu_type_vals
,
385 is_fhss
= append_pduval_str(ti
, pduhdr
.pdu_type
, len
, tvb
,
388 if (pduhdr
.pdu_type
== IAPP_PDU_CAPABILITY
)
389 dissect_caps(ti
, tvb
, offset
);
391 if (pduhdr
.pdu_type
== IAPP_PDU_AUTHINFO
)
392 dissect_authinfo(ti
, tvb
, offset
+ 3, len
);
399 /* code to dissect an IAPP packet */
401 dissect_iapp(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
)
403 proto_item
*ti
, *pdutf
;
404 proto_tree
*iapp_tree
, *pdutree
;
408 const gchar
*codestrval
;
410 col_set_str(pinfo
->cinfo
, COL_PROTOCOL
, "IAPP");
412 col_clear(pinfo
->cinfo
, COL_INFO
);
414 tvb_memcpy(tvb
, (guint8
*)&ih
, 0, sizeof(e_iapphdr
));
416 ia_version
= (int)ih
.ia_version
;
417 ia_type
= (int)ih
.ia_type
;
418 codestrval
= val_to_str_const(ia_type
, iapp_vals
, "Unknown Packet");
419 col_add_fstr(pinfo
->cinfo
, COL_INFO
, "%s(%d) (version=%d)",
420 codestrval
, ia_type
, ia_version
);
424 ti
= proto_tree_add_item(tree
, proto_iapp
, tvb
, 0, -1, ENC_NA
);
425 iapp_tree
= proto_item_add_subtree(ti
, ett_iapp
);
427 /* common header for all IAPP frames */
429 proto_tree_add_uint(iapp_tree
, hf_iapp_version
, tvb
, 0, 1,
431 proto_tree_add_uint_format_value(iapp_tree
, hf_iapp_type
, tvb
, 1, 1,
432 ih
.ia_type
, "%s(%d)", codestrval
, ia_type
);
434 pdutf
= proto_tree_add_text(iapp_tree
, tvb
, 2, -1,
435 "Protocol data units");
436 pdutree
= proto_item_add_subtree(pdutf
, ett_iapp_pdu
);
440 dissect_pdus(tvb
, 2, pdutree
,
441 tvb_length_remaining(tvb
, 2));
447 /* Register the protocol with Wireshark */
449 /* this format is require because a script is used to build the C function
450 that calls all the protocol registration.
454 proto_register_iapp(void)
457 /* Setup list of header fields See Section 1.6.1 for details*/
458 static hf_register_info hf
[] = {
460 { "Version", "iapp.version", FT_UINT8
, BASE_DEC
, NULL
, 0x00, NULL
, HFILL
}
463 { "Type", "iapp.type", FT_UINT8
, BASE_DEC
, NULL
, 0x00, NULL
, HFILL
}
467 /* Setup protocol subtree array */
468 static gint
*ett
[] = {
475 /* Register the protocol name and description */
476 proto_iapp
= proto_register_protocol("Inter-Access-Point Protocol",
479 /* Required function calls to register the header fields and subtrees used */
480 proto_register_field_array(proto_iapp
, hf
, array_length(hf
));
481 proto_register_subtree_array(ett
, array_length(ett
));
485 /* If this dissector uses sub-dissector registration add a registration routine.
486 This format is required because a script is used to find these routines and
487 create the code that calls these routines.
490 proto_reg_handoff_iapp(void)
492 dissector_handle_t iapp_handle
;
494 iapp_handle
= create_dissector_handle(dissect_iapp
, proto_iapp
);
495 dissector_add_uint("udp.port", UDP_PORT_IAPP
, iapp_handle
);