2 * Routines for IGMP/IGAP packet disassembly
3 * 2003, Endoh Akria (see AUTHORS for email)
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.
27 IGAP "Internet Group membership Authentication Protocol"
28 is defined in draft-hayashi-igap-03.txt.
31 Type Subtype Message Msize
32 -----------------------------------------------------
33 ---- 0x02 User password variable
35 ---- 0x04 Result of MD5 calculation 16
36 0x41 0x23 Challenge value ??
37 0x41 0x24 Authentication result code 1
38 0x41 0x25 Accounting status code 1
39 ---- 0x42 User password variable
41 ---- 0x44 Result of MD5 calculation 16
48 #include <epan/packet.h>
49 #include <epan/to_str.h>
50 #include "packet-igmp.h"
51 #include "packet-igap.h"
54 static int proto_igap
= -1;
55 static int hf_type
= -1;
56 static int hf_max_resp
= -1;
57 static int hf_checksum
= -1;
58 static int hf_checksum_bad
= -1;
59 static int hf_maddr
= -1;
60 static int hf_version
= -1;
61 static int hf_subtype
= -1;
62 static int hf_challengeid
= -1;
63 static int hf_asize
= -1;
64 static int hf_msize
= -1;
65 static int hf_account
= -1;
67 static int ett_igap
= -1;
70 static const value_string igap_types
[] = {
71 {IGMP_IGAP_JOIN
, "Membership Report (Join)"},
72 {IGMP_IGAP_QUERY
, "Membership Query"},
73 {IGMP_IGAP_LEAVE
, "Leave Group"},
77 #define IGAP_VERSION_1 0x10
78 static const value_string igap_version
[] = {
79 {IGAP_VERSION_1
, "1"},
83 #define IGAP_SUBTYPE_PASSWORD_JOIN 0x02
84 #define IGAP_SUBTYPE_CHALLENGE_REQUEST_JOIN 0x03
85 #define IGAP_SUBTYPE_CHALLENGE_RESPONSE_JOIN 0x04
86 #define IGAP_SUBTYPE_BASIC_QUERY 0x21
87 #define IGAP_SUBTYPE_CHALLENGE 0x23
88 #define IGAP_SUBTYPE_AUTH_MESSAGE 0x24
89 #define IGAP_SUBTYPE_ACCOUNTING_MESSAGE 0x25
90 #define IGAP_SUBTYPE_BASIC_LEAVE 0x41
91 #define IGAP_SUBTYPE_PASSWORD_LEAVE 0x42
92 #define IGAP_SUBTYPE_CHALLENGE_REQUEST_LEAVE 0x43
93 #define IGAP_SUBTYPE_CHALLENGE_RESPONSE_LEAVE 0x44
94 static const value_string igap_subtypes
[] = {
95 {IGAP_SUBTYPE_PASSWORD_JOIN
, "Password Mechanism Join (Password-Join)"},
96 {IGAP_SUBTYPE_CHALLENGE_REQUEST_JOIN
, "Challenge-Response Mechanism Join Request (Challenge-Request-Join)"},
97 {IGAP_SUBTYPE_CHALLENGE_RESPONSE_JOIN
, "Challenge-Response Mechanism Join Response (Challenge-Response-Join)"},
98 {IGAP_SUBTYPE_BASIC_QUERY
, "Basic Query"},
99 {IGAP_SUBTYPE_CHALLENGE
, "Challenge-Response Mechanism Challenge (Challenge)"},
100 {IGAP_SUBTYPE_AUTH_MESSAGE
, "Authentication Message"},
101 {IGAP_SUBTYPE_ACCOUNTING_MESSAGE
, "Accounting Message"},
102 {IGAP_SUBTYPE_BASIC_LEAVE
, "Basic Leave"},
103 {IGAP_SUBTYPE_PASSWORD_LEAVE
, "Password Mechanism Leave (Password-Leave)"},
104 {IGAP_SUBTYPE_CHALLENGE_REQUEST_LEAVE
, "Challenge-Response Mechanism Leave Challenge Request (Challenge-Request-Leave)"},
105 {IGAP_SUBTYPE_CHALLENGE_RESPONSE_LEAVE
, "Challenge-Response Mechanism Response (Challenge-Response-Leave)"},
109 #define IGAP_AUTH_SUCCESS 0x11
110 #define IGAP_AUTH_FAIL 0x21
111 static const value_string igap_auth_result
[] = {
112 {IGAP_AUTH_SUCCESS
, "Authentication success"},
113 {IGAP_AUTH_FAIL
, "Authentication failure"},
117 #define IGAP_ACCOUNT_START 0x11
118 #define IGAP_ACCOUNT_STOP 0x21
119 static const value_string igap_account_status
[] = {
120 {IGAP_ACCOUNT_START
, "Accounting start"},
121 {IGAP_ACCOUNT_STOP
, "Accounting stop"},
125 #define ACCOUNT_SIZE 16
126 #define MESSAGE_SIZE 64
128 /* This function is only called from the IGMP dissector */
130 dissect_igap(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*parent_tree
, int offset
)
134 guint8 type
, tsecs
, subtype
, asize
, msize
;
135 guchar account
[ACCOUNT_SIZE
+1], message
[MESSAGE_SIZE
+1];
137 if (!proto_is_protocol_enabled(find_protocol_by_id(proto_igap
))) {
138 /* we are not enabled, skip entire packet to be nice
139 to the igmp layer. (so clicking on IGMP will display the data)
141 return offset
+ tvb_length_remaining(tvb
, offset
);
144 item
= proto_tree_add_item(parent_tree
, proto_igap
, tvb
, offset
, -1, ENC_NA
);
145 tree
= proto_item_add_subtree(item
, ett_igap
);
147 col_set_str(pinfo
->cinfo
, COL_PROTOCOL
, "IGAP");
148 col_clear(pinfo
->cinfo
, COL_INFO
);
150 type
= tvb_get_guint8(tvb
, offset
);
151 col_add_str(pinfo
->cinfo
, COL_INFO
,
152 val_to_str(type
, igap_types
, "Unknown Type: 0x%02x"));
153 proto_tree_add_uint(tree
, hf_type
, tvb
, offset
, 1, type
);
156 tsecs
= tvb_get_guint8(tvb
, offset
);
157 proto_tree_add_uint_format_value(tree
, hf_max_resp
, tvb
, offset
, 1, tsecs
,
158 "%.1f sec (0x%02x)", tsecs
* 0.1, tsecs
);
161 igmp_checksum(tree
, tvb
, hf_checksum
, hf_checksum_bad
, pinfo
, 0);
164 proto_tree_add_item(tree
, hf_maddr
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
167 proto_tree_add_uint(tree
, hf_version
, tvb
, offset
, 1,
168 tvb_get_guint8(tvb
, offset
));
171 subtype
= tvb_get_guint8(tvb
, offset
);
172 proto_tree_add_uint(tree
, hf_subtype
, tvb
, offset
, 1, subtype
);
175 proto_tree_add_uint(tree
, hf_challengeid
, tvb
, offset
, 1,
176 tvb_get_guint8(tvb
, offset
));
179 asize
= tvb_get_guint8(tvb
, offset
);
180 proto_tree_add_uint(tree
, hf_asize
, tvb
, offset
, 1, asize
);
183 msize
= tvb_get_guint8(tvb
, offset
);
184 proto_tree_add_uint(tree
, hf_msize
, tvb
, offset
, 1, msize
);
188 if (asize
> ACCOUNT_SIZE
) {
189 /* Bogus account size.
191 asize
= ACCOUNT_SIZE
;
193 tvb_memcpy(tvb
, account
, offset
, asize
);
194 account
[asize
] = '\0';
195 proto_tree_add_string(tree
, hf_account
, tvb
, offset
, asize
, account
);
197 offset
+= ACCOUNT_SIZE
;
200 if (msize
> MESSAGE_SIZE
) {
201 /* Bogus message size.
203 msize
= MESSAGE_SIZE
;
205 tvb_memcpy(tvb
, message
, offset
, msize
);
207 case IGAP_SUBTYPE_PASSWORD_JOIN
:
208 case IGAP_SUBTYPE_PASSWORD_LEAVE
:
209 /* Challenge field is user's password */
210 message
[msize
] = '\0';
211 proto_tree_add_text(tree
, tvb
, offset
, msize
,
212 "User password: %s", message
);
214 case IGAP_SUBTYPE_CHALLENGE_RESPONSE_JOIN
:
215 case IGAP_SUBTYPE_CHALLENGE_RESPONSE_LEAVE
:
216 /* Challenge field is the results of MD5 calculation */
217 proto_tree_add_text(tree
, tvb
, offset
, msize
,
218 "Result of MD5 calculation: 0x%s",
219 bytes_to_str(message
, msize
));
221 case IGAP_SUBTYPE_CHALLENGE
:
222 /* Challenge field is the challenge value */
223 proto_tree_add_text(tree
, tvb
, offset
, msize
,
225 bytes_to_str(message
, msize
));
227 case IGAP_SUBTYPE_AUTH_MESSAGE
:
228 /* Challenge field indicates the result of the authenticaion */
229 proto_tree_add_text(tree
, tvb
, offset
, msize
,
230 "Authentication result: %s (0x%x)",
231 val_to_str_const(message
[0], igap_auth_result
, "Unknown"),
234 case IGAP_SUBTYPE_ACCOUNTING_MESSAGE
:
235 /* Challenge field indicates the accounting status */
236 proto_tree_add_text(tree
, tvb
, offset
, msize
,
237 "Accounting status: %s (0x%x)",
238 val_to_str_const(message
[0], igap_account_status
, "Unknown"),
242 proto_tree_add_text(tree
, tvb
, offset
, msize
,
243 "Message: (Unknown)");
246 offset
+= MESSAGE_SIZE
;
248 if (item
) proto_item_set_len(item
, offset
);
254 proto_register_igap(void)
256 static hf_register_info hf
[] = {
258 { "Type", "igap.type", FT_UINT8
, BASE_HEX
,
259 VALS(igap_types
), 0, "IGAP Packet Type", HFILL
}
263 { "Max Response Time", "igap.max_resp", FT_UINT8
, BASE_DEC
,
264 NULL
, 0, NULL
, HFILL
}
268 { "Checksum", "igap.checksum", FT_UINT16
, BASE_HEX
,
269 NULL
, 0, NULL
, HFILL
}
273 { "Bad Checksum", "igap.checksum_bad", FT_BOOLEAN
, BASE_NONE
,
274 NULL
, 0x0, NULL
, HFILL
}
278 { "Multicast group address", "igap.maddr", FT_IPv4
, BASE_NONE
,
279 NULL
, 0, NULL
, HFILL
}
283 { "Version", "igap.version", FT_UINT8
, BASE_HEX
,
284 VALS(igap_version
), 0, "IGAP protocol version", HFILL
}
288 { "Subtype", "igap.subtype", FT_UINT8
, BASE_HEX
,
289 VALS(igap_subtypes
), 0, NULL
, HFILL
}
293 { "Challenge ID", "igap.challengeid", FT_UINT8
, BASE_HEX
,
294 NULL
, 0, NULL
, HFILL
}
298 { "Account Size", "igap.asize", FT_UINT8
, BASE_DEC
,
299 NULL
, 0, "Length of the User Account field", HFILL
}
303 { "Message Size", "igap.msize", FT_UINT8
, BASE_DEC
,
304 NULL
, 0, "Length of the Message field", HFILL
}
308 { "User Account", "igap.account", FT_STRING
, BASE_NONE
,
309 NULL
, 0, NULL
, HFILL
}
313 static gint
*ett
[] = {
317 proto_igap
= proto_register_protocol
318 ("Internet Group membership Authentication Protocol",
320 proto_register_field_array(proto_igap
, hf
, array_length(hf
));
321 proto_register_subtree_array(ett
, array_length(ett
));