2 * Routines for PCNFSD dissection
6 * Wireshark - Network traffic analyzer
7 * By Gerald Combs <gerald@wireshark.org>
8 * Copyright 1998 Gerald Combs
10 * Copied from packet-ypbind.c
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
29 Protocol information comes from the book
30 "NFS Illustrated" by Brent Callaghan, ISBN 0-201-32570-5
38 #include "packet-rpc.h"
39 #include "packet-pcnfsd.h"
40 #include <epan/wmem/wmem.h>
42 static int proto_pcnfsd
= -1;
43 static int hf_pcnfsd_procedure_v1
= -1;
44 static int hf_pcnfsd_procedure_v2
= -1;
45 static int hf_pcnfsd_auth_client
= -1;
46 static int hf_pcnfsd_auth_ident_obscure
= -1;
47 static int hf_pcnfsd_auth_ident_clear
= -1;
48 static int hf_pcnfsd_auth_password_obscure
= -1;
49 static int hf_pcnfsd_auth_password_clear
= -1;
50 static int hf_pcnfsd_comment
= -1;
51 static int hf_pcnfsd_status
= -1;
52 static int hf_pcnfsd_uid
= -1;
53 static int hf_pcnfsd_gid
= -1;
54 static int hf_pcnfsd_gids_count
= -1;
55 static int hf_pcnfsd_homedir
= -1;
56 static int hf_pcnfsd_def_umask
= -1;
57 static int hf_pcnfsd_username
= -1;
60 static gint ett_pcnfsd
= -1;
61 static gint ett_pcnfsd_auth_ident
= -1;
62 static gint ett_pcnfsd_auth_password
= -1;
63 static gint ett_pcnfsd_gids
= -1;
66 dissect_pcnfsd_username(tvbuff_t
*tvb
, int offset
, proto_tree
*tree
)
68 return dissect_rpc_string(tvb
, tree
, hf_pcnfsd_username
, offset
, NULL
);
73 #define MAP_REQ_UNAME 2
74 #define MAP_REQ_GNAME 3
76 static const value_string names_mapreq
[] =
78 { MAP_REQ_UID
, "MAP_REQ_UID" },
79 { MAP_REQ_GID
, "MAP_REQ_GID" },
80 { MAP_REQ_UNAME
, "MAP_REQ_UNAME" },
81 { MAP_REQ_GNAME
, "MAP_REQ_GNAME" },
86 dissect_pcnfsd_mapreq(tvbuff_t
*tvb
, int offset
, proto_tree
*tree
)
90 mapreq
= tvb_get_ntohl(tvb
, offset
+ 0);
93 proto_tree_add_text(tree
, tvb
, offset
, 4, "Request: %s (%u)",
94 val_to_str(mapreq
, names_mapreq
, "%u"), mapreq
);
102 dissect_pcnfsd2_dissect_mapreq_arg_item(tvbuff_t
*tvb
, int offset
,
103 packet_info
*pinfo _U_
, proto_tree
*tree
, void* data _U_
)
105 offset
= dissect_pcnfsd_mapreq(tvb
, offset
, tree
);
107 offset
= dissect_rpc_uint32(tvb
, tree
, hf_pcnfsd_uid
, offset
);
109 offset
= dissect_pcnfsd_username(tvb
, offset
, tree
);
115 dissect_pcnfsd2_mapid_call(tvbuff_t
*tvb
, int offset
, packet_info
*pinfo
,
116 proto_tree
*tree
, void* data _U_
)
118 offset
= dissect_rpc_string(tvb
, tree
, hf_pcnfsd_comment
, offset
, NULL
);
120 offset
= dissect_rpc_list(tvb
, pinfo
, tree
, offset
,
121 dissect_pcnfsd2_dissect_mapreq_arg_item
);
127 #define MAP_RES_UNKNOWN 1
128 #define MAP_RES_DENIED 2
130 static const value_string names_maprstat
[] =
132 { MAP_RES_OK
, "MAP_RES_OK" },
133 { MAP_RES_UNKNOWN
, "MAP_RES_UNKNOWN" },
134 { MAP_RES_DENIED
, "MAP_RES_DENIED" },
139 dissect_pcnfsd2_dissect_mapreq_res_item(tvbuff_t
*tvb
, int offset
,
140 packet_info
*pinfo _U_
, proto_tree
*tree
, void* data _U_
)
144 offset
= dissect_pcnfsd_mapreq(tvb
, offset
, tree
);
146 maprstat
= tvb_get_ntohl(tvb
, offset
+ 0);
149 proto_tree_add_text(tree
, tvb
, offset
, 4, "Status: %s (%u)",
150 val_to_str(maprstat
, names_maprstat
, "%u"), maprstat
);
154 offset
= dissect_rpc_uint32(tvb
, tree
, hf_pcnfsd_uid
, offset
);
156 offset
= dissect_pcnfsd_username(tvb
, offset
, tree
);
162 dissect_pcnfsd2_mapid_reply(tvbuff_t
*tvb
, int offset
, packet_info
*pinfo
,
163 proto_tree
*tree
, void* data _U_
)
165 offset
= dissect_rpc_string(tvb
, tree
, hf_pcnfsd_comment
, offset
, NULL
);
167 offset
= dissect_rpc_list(tvb
, pinfo
, tree
, offset
,
168 dissect_pcnfsd2_dissect_mapreq_res_item
);
173 /* "NFS Illustrated 14.7.13 */
175 pcnfsd_decode_obscure(const char* data
, int len
)
180 decoded_buf
= (char *)wmem_alloc(wmem_packet_scope(), len
);
181 decoded_data
= decoded_buf
;
182 for ( ; len
>0 ; len
--, data
++, decoded_data
++) {
183 *decoded_data
= (*data
^ 0x5b) & 0x7f;
189 /* "NFS Illustrated" 14.7.13 */
191 dissect_pcnfsd2_auth_call(tvbuff_t
*tvb
, int offset
, packet_info
*pinfo _U_
,
192 proto_tree
*tree
, void* data _U_
)
195 const char *ident
= NULL
;
196 const char *ident_decoded
;
197 proto_item
*ident_item
= NULL
;
198 proto_tree
*ident_tree
= NULL
;
199 const char *password
= NULL
;
200 proto_item
*password_item
= NULL
;
201 proto_tree
*password_tree
= NULL
;
203 offset
= dissect_rpc_string(tvb
, tree
,
204 hf_pcnfsd_auth_client
, offset
, NULL
);
207 ident_item
= proto_tree_add_text(tree
, tvb
,
208 offset
, -1, "Authentication Ident");
210 ident_tree
= proto_item_add_subtree(
211 ident_item
, ett_pcnfsd_auth_ident
);
213 newoffset
= dissect_rpc_string(tvb
, ident_tree
,
214 hf_pcnfsd_auth_ident_obscure
, offset
, &ident
);
216 proto_item_set_len(ident_item
, newoffset
-offset
);
220 /* Only attempt to decode the ident if it has been specified */
221 if (strcmp(ident
, RPC_STRING_EMPTY
) != 0)
222 ident_decoded
= pcnfsd_decode_obscure(ident
, (int)strlen(ident
));
224 ident_decoded
= ident
;
227 proto_tree_add_string(ident_tree
,
228 hf_pcnfsd_auth_ident_clear
,
229 tvb
, offset
+4, (gint
)strlen(ident_decoded
), ident_decoded
);
232 proto_item_set_text(ident_item
, "Authentication Ident: %s",
239 password_item
= proto_tree_add_text(tree
, tvb
,
240 offset
, -1, "Authentication Password");
242 password_tree
= proto_item_add_subtree(
243 password_item
, ett_pcnfsd_auth_password
);
245 newoffset
= dissect_rpc_string(tvb
, password_tree
,
246 hf_pcnfsd_auth_password_obscure
, offset
, &password
);
248 proto_item_set_len(password_item
, newoffset
-offset
);
252 /* Only attempt to decode the password if it has been specified */
253 if (strcmp(password
, RPC_STRING_EMPTY
))
254 pcnfsd_decode_obscure(password
, (int)strlen(password
));
257 proto_tree_add_string(password_tree
,
258 hf_pcnfsd_auth_password_clear
,
259 tvb
, offset
+4, (gint
)strlen(password
), password
);
262 proto_item_set_text(password_item
, "Authentication Password: %s",
268 offset
= dissect_rpc_string(tvb
, tree
,
269 hf_pcnfsd_comment
, offset
, NULL
);
275 /* "NFS Illustrated" 14.7.13 */
277 dissect_pcnfsd2_auth_reply(tvbuff_t
*tvb
, int offset
, packet_info
*pinfo _U_
,
278 proto_tree
*tree
, void* data _U_
)
281 proto_item
*gitem
= NULL
;
282 proto_tree
*gtree
= NULL
;
285 offset
= dissect_rpc_uint32(tvb
, tree
, hf_pcnfsd_status
, offset
);
286 offset
= dissect_rpc_uint32(tvb
, tree
, hf_pcnfsd_uid
, offset
);
287 offset
= dissect_rpc_uint32(tvb
, tree
, hf_pcnfsd_gid
, offset
);
288 gids_count
= tvb_get_ntohl(tvb
,offset
+0);
290 gitem
= proto_tree_add_text(tree
, tvb
,
291 offset
, 4+gids_count
*4, "Group IDs: %d", gids_count
);
292 gtree
= proto_item_add_subtree(gitem
, ett_pcnfsd_gids
);
295 proto_tree_add_item(gtree
, hf_pcnfsd_gids_count
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
298 for (gids_i
= 0 ; gids_i
< gids_count
; gids_i
++) {
299 offset
= dissect_rpc_uint32(tvb
, gtree
,
300 hf_pcnfsd_gid
, offset
);
302 offset
= dissect_rpc_string(tvb
, tree
,
303 hf_pcnfsd_homedir
, offset
, NULL
);
304 /* should be signed int32 */
305 offset
= dissect_rpc_uint32(tvb
, tree
, hf_pcnfsd_def_umask
, offset
);
306 offset
= dissect_rpc_string(tvb
, tree
,
307 hf_pcnfsd_comment
, offset
, NULL
);
313 /* "NFS Illustrated", 14.6 */
314 /* proc number, "proc name", dissect_request, dissect_reply */
315 /* NULL as function pointer means: type of arguments is "void". */
316 static const vsff pcnfsd1_proc
[] = {
317 { 0, "NULL", NULL
, NULL
},
318 { 1, "AUTH", NULL
, NULL
},
319 { 2, "PR_INIT", NULL
, NULL
},
320 { 3, "PR_START", NULL
, NULL
},
321 { 0, NULL
, NULL
, NULL
}
323 static const value_string pcnfsd1_proc_vals
[] = {
330 /* end of PCNFS version 1 */
333 /* "NFS Illustrated", 14.7 */
334 static const vsff pcnfsd2_proc
[] = {
335 { 0, "NULL", NULL
, NULL
},
336 { 1, "INFO", NULL
, NULL
},
337 { 2, "PR_INIT", NULL
, NULL
},
338 { 3, "PR_START", NULL
, NULL
},
339 { 4, "PR_LIST", NULL
, NULL
},
340 { 5, "PR_QUEUE", NULL
, NULL
},
341 { 6, "PR_STATUS", NULL
, NULL
},
342 { 7, "PR_CANCEL", NULL
, NULL
},
343 { 8, "PR_ADMIN", NULL
, NULL
},
344 { 9, "PR_REQUEUE", NULL
, NULL
},
345 { 10, "PR_HOLD", NULL
, NULL
},
346 { 11, "PR_RELEASE", NULL
, NULL
},
348 dissect_pcnfsd2_mapid_call
, dissect_pcnfsd2_mapid_reply
},
350 dissect_pcnfsd2_auth_call
, dissect_pcnfsd2_auth_reply
},
351 { 14, "ALERT", NULL
, NULL
},
352 { 0, NULL
, NULL
, NULL
}
354 static const value_string pcnfsd2_proc_vals
[] = {
366 { 11, "PR_RELEASE" },
372 /* end of PCNFS version 2 */
376 proto_register_pcnfsd(void)
378 static hf_register_info hf
[] = {
379 { &hf_pcnfsd_procedure_v1
, {
380 "V1 Procedure", "pcnfsd.procedure_v1", FT_UINT32
, BASE_DEC
,
381 VALS(pcnfsd1_proc_vals
), 0, NULL
, HFILL
}},
382 { &hf_pcnfsd_procedure_v2
, {
383 "V2 Procedure", "pcnfsd.procedure_v2", FT_UINT32
, BASE_DEC
,
384 VALS(pcnfsd2_proc_vals
), 0, NULL
, HFILL
}},
385 { &hf_pcnfsd_auth_client
, {
386 "Authentication Client", "pcnfsd.auth.client", FT_STRING
, BASE_NONE
,
387 NULL
, 0, NULL
, HFILL
}},
388 { &hf_pcnfsd_auth_ident_obscure
, {
389 "Obscure Ident", "pcnfsd.auth.ident.obscure", FT_STRING
, BASE_NONE
,
390 NULL
, 0, "Authentication Obscure Ident", HFILL
}},
391 { &hf_pcnfsd_auth_ident_clear
, {
392 "Clear Ident", "pcnfsd.auth.ident.clear", FT_STRING
, BASE_NONE
,
393 NULL
, 0, "Authentication Clear Ident", HFILL
}},
394 { &hf_pcnfsd_auth_password_obscure
, {
395 "Obscure Password", "pcnfsd.auth.password.obscure", FT_STRING
, BASE_NONE
,
396 NULL
, 0, "Authentication Obscure Password", HFILL
}},
397 { &hf_pcnfsd_auth_password_clear
, {
398 "Clear Password", "pcnfsd.auth.password.clear", FT_STRING
, BASE_NONE
,
399 NULL
, 0, "Authentication Clear Password", HFILL
}},
400 { &hf_pcnfsd_comment
, {
401 "Comment", "pcnfsd.comment", FT_STRING
, BASE_NONE
,
402 NULL
, 0, NULL
, HFILL
}},
403 { &hf_pcnfsd_status
, {
404 "Reply Status", "pcnfsd.status", FT_UINT32
, BASE_DEC
,
405 NULL
, 0, "Status", HFILL
}},
407 "User ID", "pcnfsd.uid", FT_UINT32
, BASE_DEC
,
408 NULL
, 0, NULL
, HFILL
}},
410 "Group ID", "pcnfsd.gid", FT_UINT32
, BASE_DEC
,
411 NULL
, 0, NULL
, HFILL
}},
412 { &hf_pcnfsd_gids_count
, {
413 "Group ID Count", "pcnfsd.gids.count", FT_UINT32
, BASE_DEC
,
414 NULL
, 0, NULL
, HFILL
}},
415 { &hf_pcnfsd_homedir
, {
416 "Home Directory", "pcnfsd.homedir", FT_STRING
, BASE_NONE
,
417 NULL
, 0, NULL
, HFILL
}},
418 { &hf_pcnfsd_def_umask
, {
419 "def_umask", "pcnfsd.def_umask", FT_UINT32
, BASE_OCT
,
420 NULL
, 0, NULL
, HFILL
}},
421 { &hf_pcnfsd_username
, {
422 "User name", "pcnfsd.username", FT_STRING
, BASE_NONE
,
423 NULL
, 0, "pcnfsd.username", HFILL
}},
426 static gint
*ett
[] = {
428 &ett_pcnfsd_auth_ident
,
429 &ett_pcnfsd_auth_password
,
433 proto_pcnfsd
= proto_register_protocol("PC NFS",
435 proto_register_field_array(proto_pcnfsd
, hf
, array_length(hf
));
436 proto_register_subtree_array(ett
, array_length(ett
));
440 proto_reg_handoff_pcnfsd(void)
442 /* Register the protocol as RPC */
443 rpc_init_prog(proto_pcnfsd
, PCNFSD_PROGRAM
, ett_pcnfsd
);
444 /* Register the procedure tables */
445 rpc_init_proc_table(PCNFSD_PROGRAM
, 1, pcnfsd1_proc
, hf_pcnfsd_procedure_v1
);
446 rpc_init_proc_table(PCNFSD_PROGRAM
, 2, pcnfsd2_proc
, hf_pcnfsd_procedure_v2
);