/src/wireshark/epan/dissectors/packet-pcnfsd.c
Line | Count | Source |
1 | | /* packet-pcnfsd.c |
2 | | * Routines for PCNFSD dissection |
3 | | * |
4 | | * Wireshark - Network traffic analyzer |
5 | | * By Gerald Combs <gerald@wireshark.org> |
6 | | * Copyright 1998 Gerald Combs |
7 | | * |
8 | | * Copied from packet-ypbind.c |
9 | | * |
10 | | * SPDX-License-Identifier: GPL-2.0-or-later |
11 | | */ |
12 | | |
13 | | |
14 | | /* |
15 | | Protocol information comes from the book |
16 | | "NFS Illustrated" by Brent Callaghan, ISBN 0-201-32570-5 |
17 | | */ |
18 | | |
19 | | |
20 | | #include "config.h" |
21 | | |
22 | | |
23 | | #include "packet-rpc.h" |
24 | | #include "packet-pcnfsd.h" |
25 | | |
26 | | void proto_register_pcnfsd(void); |
27 | | void proto_reg_handoff_pcnfsd(void); |
28 | | |
29 | | static int proto_pcnfsd; |
30 | | static int hf_pcnfsd_procedure_v1; |
31 | | static int hf_pcnfsd_procedure_v2; |
32 | | static int hf_pcnfsd_auth_client; |
33 | | static int hf_pcnfsd_auth_ident_obscure; |
34 | | static int hf_pcnfsd_auth_ident_clear; |
35 | | static int hf_pcnfsd_auth_password; |
36 | | static int hf_pcnfsd_auth_password_obscure; |
37 | | static int hf_pcnfsd_auth_password_clear; |
38 | | static int hf_pcnfsd_comment; |
39 | | static int hf_pcnfsd_status; |
40 | | static int hf_pcnfsd_uid; |
41 | | static int hf_pcnfsd_gid; |
42 | | static int hf_pcnfsd_gids_count; |
43 | | static int hf_pcnfsd_homedir; |
44 | | static int hf_pcnfsd_def_umask; |
45 | | static int hf_pcnfsd_mapreq; |
46 | | static int hf_pcnfsd_mapreq_status; |
47 | | static int hf_pcnfsd_username; |
48 | | |
49 | | |
50 | | static int ett_pcnfsd; |
51 | | static int ett_pcnfsd_auth_ident; |
52 | | static int ett_pcnfsd_auth_password; |
53 | | static int ett_pcnfsd_gids; |
54 | | |
55 | | static int |
56 | | dissect_pcnfsd_username(tvbuff_t *tvb, packet_info* pinfo, unsigned offset, proto_tree *tree) |
57 | 0 | { |
58 | 0 | return dissect_rpc_string(tvb, pinfo, tree, hf_pcnfsd_username, offset, NULL); |
59 | 0 | } |
60 | | |
61 | | #define MAP_REQ_UID 0 |
62 | | #define MAP_REQ_GID 1 |
63 | | #define MAP_REQ_UNAME 2 |
64 | | #define MAP_REQ_GNAME 3 |
65 | | |
66 | | static const value_string names_mapreq[] = |
67 | | { |
68 | | { MAP_REQ_UID, "MAP_REQ_UID" }, |
69 | | { MAP_REQ_GID, "MAP_REQ_GID" }, |
70 | | { MAP_REQ_UNAME, "MAP_REQ_UNAME" }, |
71 | | { MAP_REQ_GNAME, "MAP_REQ_GNAME" }, |
72 | | { 0, NULL } |
73 | | }; |
74 | | |
75 | | static int |
76 | | dissect_pcnfsd2_dissect_mapreq_arg_item(tvbuff_t *tvb, unsigned offset, packet_info *pinfo, proto_tree *tree, void* data _U_) |
77 | 0 | { |
78 | 0 | proto_tree_add_item(tree, hf_pcnfsd_mapreq, tvb, offset, 4, ENC_BIG_ENDIAN); |
79 | 0 | offset += 4; |
80 | |
|
81 | 0 | offset = dissect_rpc_uint32(tvb, tree, hf_pcnfsd_uid, offset); |
82 | |
|
83 | 0 | offset = dissect_pcnfsd_username(tvb, pinfo, offset, tree); |
84 | |
|
85 | 0 | return offset; |
86 | 0 | } |
87 | | |
88 | | static int |
89 | | dissect_pcnfsd2_mapid_call(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_) |
90 | 0 | { |
91 | 0 | unsigned offset = 0; |
92 | 0 | offset = dissect_rpc_string(tvb, pinfo, tree, hf_pcnfsd_comment, offset, NULL); |
93 | |
|
94 | 0 | offset = dissect_rpc_list(tvb, pinfo, tree, offset, |
95 | 0 | dissect_pcnfsd2_dissect_mapreq_arg_item, NULL); |
96 | |
|
97 | 0 | return offset; |
98 | 0 | } |
99 | | |
100 | | #define MAP_RES_OK 0 |
101 | | #define MAP_RES_UNKNOWN 1 |
102 | | #define MAP_RES_DENIED 2 |
103 | | |
104 | | static const value_string names_maprstat[] = |
105 | | { |
106 | | { MAP_RES_OK, "MAP_RES_OK" }, |
107 | | { MAP_RES_UNKNOWN, "MAP_RES_UNKNOWN" }, |
108 | | { MAP_RES_DENIED, "MAP_RES_DENIED" }, |
109 | | { 0, NULL } |
110 | | }; |
111 | | |
112 | | static int |
113 | | dissect_pcnfsd2_dissect_mapreq_res_item(tvbuff_t *tvb, unsigned offset, packet_info *pinfo, proto_tree *tree, void* data _U_) |
114 | 0 | { |
115 | 0 | proto_tree_add_item(tree, hf_pcnfsd_mapreq, tvb, offset, 4, ENC_BIG_ENDIAN); |
116 | 0 | offset += 4; |
117 | |
|
118 | 0 | proto_tree_add_item(tree, hf_pcnfsd_mapreq_status, tvb, offset, 4, ENC_BIG_ENDIAN); |
119 | 0 | offset += 4; |
120 | |
|
121 | 0 | offset = dissect_rpc_uint32(tvb, tree, hf_pcnfsd_uid, offset); |
122 | |
|
123 | 0 | offset = dissect_pcnfsd_username(tvb, pinfo, offset, tree); |
124 | |
|
125 | 0 | return offset; |
126 | 0 | } |
127 | | |
128 | | static int |
129 | | dissect_pcnfsd2_mapid_reply(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_) |
130 | 0 | { |
131 | 0 | unsigned offset = 0; |
132 | 0 | offset = dissect_rpc_string(tvb, pinfo, tree, hf_pcnfsd_comment, offset, NULL); |
133 | |
|
134 | 0 | offset = dissect_rpc_list(tvb, pinfo, tree, offset, |
135 | 0 | dissect_pcnfsd2_dissect_mapreq_res_item, NULL); |
136 | |
|
137 | 0 | return offset; |
138 | 0 | } |
139 | | |
140 | | /* "NFS Illustrated 14.7.13 */ |
141 | | static wmem_strbuf_t* |
142 | | pcnfsd_decode_obscure(wmem_allocator_t *pool, const char* data, size_t len) |
143 | 0 | { |
144 | 0 | wmem_strbuf_t *decoded_buf; |
145 | |
|
146 | 0 | decoded_buf = wmem_strbuf_new_sized(pool, len + 1); |
147 | 0 | for ( ; len>0 ; len--, data++) { |
148 | | /* dissect_rpc_string/dissect_rpc_opaque_data already called |
149 | | * tvb_get_string_enc(..., ENC_ASCII), which replaced any non-ASCII |
150 | | * with UTF-8 REPLACEMENT CHARACTER, so leave unchanged any byte |
151 | | * with the high bit set. |
152 | | * XXX - It might be easier to get the raw bytes and deobfuscate |
153 | | * prior to making UTF-8. |
154 | | */ |
155 | 0 | if (*data & 0x80) { |
156 | 0 | wmem_strbuf_append_c(decoded_buf, *data); |
157 | 0 | } else { |
158 | 0 | wmem_strbuf_append_c(decoded_buf, *data ^ 0x5b); |
159 | 0 | } |
160 | 0 | } |
161 | | /* Return the wmem_strbuf_t for clarity, since the deobfuscation can |
162 | | * place an internal '\0' byte. (We could just use the original string |
163 | | * length, but this makes it more apparent.) */ |
164 | 0 | return decoded_buf; |
165 | 0 | } |
166 | | |
167 | | |
168 | | /* "NFS Illustrated" 14.7.13 */ |
169 | | static int |
170 | | dissect_pcnfsd2_auth_call(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_) |
171 | 0 | { |
172 | 0 | unsigned newoffset; |
173 | 0 | const char *ident = NULL; |
174 | 0 | wmem_strbuf_t *ident_decoded; |
175 | 0 | proto_item *ident_item; |
176 | 0 | proto_tree *ident_tree; |
177 | 0 | const char *password = NULL; |
178 | 0 | wmem_strbuf_t *password_decoded; |
179 | 0 | proto_item *password_item = NULL; |
180 | 0 | proto_tree *password_tree = NULL; |
181 | 0 | unsigned offset = 0; |
182 | |
|
183 | 0 | offset = dissect_rpc_string(tvb, pinfo, tree, |
184 | 0 | hf_pcnfsd_auth_client, offset, NULL); |
185 | |
|
186 | 0 | ident_tree = proto_tree_add_subtree(tree, tvb, |
187 | 0 | offset, -1, ett_pcnfsd_auth_ident, &ident_item, "Authentication Ident"); |
188 | | |
189 | | /* XXX - Because this is obfuscated with a XOR pattern, it really needs |
190 | | * to retrieve the raw bytes and XOR them first; the obfuscation can place |
191 | | * a '\0' in the middle of the string if the unobfuscated identity or |
192 | | * password has a '[' (ASCII 0x5b) , so the counted string length in the |
193 | | * frame should be used, not strlen(). |
194 | | */ |
195 | 0 | newoffset = dissect_rpc_string(tvb, pinfo, ident_tree, |
196 | 0 | hf_pcnfsd_auth_ident_obscure, offset, &ident); |
197 | 0 | proto_item_set_len(ident_item, newoffset-offset); |
198 | |
|
199 | 0 | if (ident && ident_tree) { |
200 | | /* Only attempt to decode the ident if it has been specified */ |
201 | 0 | if (strcmp(ident, RPC_STRING_EMPTY) != 0) |
202 | 0 | ident_decoded = pcnfsd_decode_obscure(pinfo->pool, ident, strlen(ident)); |
203 | 0 | else |
204 | 0 | ident_decoded = wmem_strbuf_new(pinfo->pool, ident); |
205 | |
|
206 | 0 | proto_tree_add_string(ident_tree, |
207 | 0 | hf_pcnfsd_auth_ident_clear, |
208 | 0 | tvb, offset+4, |
209 | 0 | (int)wmem_strbuf_get_len(ident_decoded), |
210 | 0 | wmem_strbuf_get_str(ident_decoded)); |
211 | |
|
212 | 0 | wmem_strbuf_destroy(ident_decoded); |
213 | 0 | } |
214 | 0 | if (ident_item) { |
215 | 0 | proto_item_set_text(ident_item, "Authentication Ident: %s", |
216 | 0 | ident); |
217 | 0 | } |
218 | |
|
219 | 0 | offset = newoffset; |
220 | |
|
221 | 0 | password_item = proto_tree_add_string_format(tree, hf_pcnfsd_auth_password, |
222 | 0 | tvb, 0, 0, "", "Authentication Password"); |
223 | 0 | password_tree = proto_item_add_subtree(password_item, ett_pcnfsd_auth_password); |
224 | |
|
225 | 0 | newoffset = dissect_rpc_string(tvb, pinfo, password_tree, |
226 | 0 | hf_pcnfsd_auth_password_obscure, offset, &password); |
227 | 0 | if (password_item) { |
228 | 0 | proto_item_set_len(password_item, newoffset-offset); |
229 | 0 | } |
230 | |
|
231 | 0 | if (password && password_tree) { |
232 | | /* Only attempt to decode the password if it has been specified */ |
233 | 0 | if (strcmp(password, RPC_STRING_EMPTY)) |
234 | 0 | password_decoded = pcnfsd_decode_obscure(pinfo->pool, password, strlen(password)); |
235 | 0 | else |
236 | 0 | password_decoded = wmem_strbuf_new(pinfo->pool, password); |
237 | |
|
238 | 0 | proto_tree_add_string(password_tree, |
239 | 0 | hf_pcnfsd_auth_password_clear, |
240 | 0 | tvb, offset+4, |
241 | 0 | (int)wmem_strbuf_get_len(password_decoded), |
242 | 0 | wmem_strbuf_get_str(password_decoded)); |
243 | |
|
244 | 0 | wmem_strbuf_destroy(password_decoded); |
245 | 0 | } |
246 | 0 | if (password_item) { |
247 | 0 | proto_item_set_text(password_item, "Authentication Password: %s", |
248 | 0 | password); |
249 | 0 | } |
250 | |
|
251 | 0 | offset = newoffset; |
252 | |
|
253 | 0 | offset = dissect_rpc_string(tvb, pinfo, tree, |
254 | 0 | hf_pcnfsd_comment, offset, NULL); |
255 | |
|
256 | 0 | return offset; |
257 | 0 | } |
258 | | |
259 | | |
260 | | /* "NFS Illustrated" 14.7.13 */ |
261 | | static int |
262 | | dissect_pcnfsd2_auth_reply(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_) |
263 | 0 | { |
264 | 0 | int gids_count; |
265 | 0 | proto_tree *gtree; |
266 | 0 | int gids_i; |
267 | 0 | unsigned offset = 0; |
268 | |
|
269 | 0 | offset = dissect_rpc_uint32(tvb, tree, hf_pcnfsd_status, offset); |
270 | 0 | offset = dissect_rpc_uint32(tvb, tree, hf_pcnfsd_uid, offset); |
271 | 0 | offset = dissect_rpc_uint32(tvb, tree, hf_pcnfsd_gid, offset); |
272 | 0 | gids_count = tvb_get_ntohl(tvb,offset+0); |
273 | 0 | gtree = proto_tree_add_subtree_format(tree, tvb, |
274 | 0 | offset, 4+gids_count*4, ett_pcnfsd_gids, NULL, "Group IDs: %d", gids_count); |
275 | |
|
276 | 0 | proto_tree_add_item(gtree, hf_pcnfsd_gids_count, tvb, offset, 4, ENC_BIG_ENDIAN); |
277 | |
|
278 | 0 | offset += 4; |
279 | 0 | for (gids_i = 0 ; gids_i < gids_count ; gids_i++) { |
280 | 0 | offset = dissect_rpc_uint32(tvb, gtree, |
281 | 0 | hf_pcnfsd_gid, offset); |
282 | 0 | } |
283 | 0 | offset = dissect_rpc_string(tvb, pinfo, tree, |
284 | 0 | hf_pcnfsd_homedir, offset, NULL); |
285 | | /* should be signed int32 */ |
286 | 0 | offset = dissect_rpc_uint32(tvb, tree, hf_pcnfsd_def_umask, offset); |
287 | 0 | offset = dissect_rpc_string(tvb, pinfo, tree, |
288 | 0 | hf_pcnfsd_comment, offset, NULL); |
289 | |
|
290 | 0 | return offset; |
291 | 0 | } |
292 | | |
293 | | |
294 | | /* "NFS Illustrated", 14.6 */ |
295 | | /* proc number, "proc name", dissect_request, dissect_reply */ |
296 | | static const vsff pcnfsd1_proc[] = { |
297 | | { 0, "NULL", dissect_rpc_void, dissect_rpc_void }, |
298 | | { 1, "AUTH", dissect_rpc_unknown, dissect_rpc_unknown }, |
299 | | { 2, "PR_INIT", dissect_rpc_unknown, dissect_rpc_unknown }, |
300 | | { 3, "PR_START", dissect_rpc_unknown, dissect_rpc_unknown }, |
301 | | { 0, NULL, NULL, NULL } |
302 | | }; |
303 | | static const value_string pcnfsd1_proc_vals[] = { |
304 | | { 0, "NULL" }, |
305 | | { 1, "AUTH" }, |
306 | | { 2, "PR_INIT" }, |
307 | | { 3, "PR_START" }, |
308 | | { 0, NULL } |
309 | | }; |
310 | | /* end of PCNFS version 1 */ |
311 | | |
312 | | |
313 | | /* "NFS Illustrated", 14.7 */ |
314 | | static const vsff pcnfsd2_proc[] = { |
315 | | { 0, "NULL", |
316 | | dissect_rpc_void, dissect_rpc_void }, |
317 | | { 1, "INFO", dissect_rpc_unknown, dissect_rpc_unknown }, |
318 | | { 2, "PR_INIT", dissect_rpc_unknown, dissect_rpc_unknown }, |
319 | | { 3, "PR_START", dissect_rpc_unknown, dissect_rpc_unknown }, |
320 | | { 4, "PR_LIST", dissect_rpc_unknown, dissect_rpc_unknown }, |
321 | | { 5, "PR_QUEUE", dissect_rpc_unknown, dissect_rpc_unknown }, |
322 | | { 6, "PR_STATUS", dissect_rpc_unknown, dissect_rpc_unknown }, |
323 | | { 7, "PR_CANCEL", dissect_rpc_unknown, dissect_rpc_unknown }, |
324 | | { 8, "PR_ADMIN", dissect_rpc_unknown, dissect_rpc_unknown }, |
325 | | { 9, "PR_REQUEUE", dissect_rpc_unknown, dissect_rpc_unknown }, |
326 | | { 10, "PR_HOLD", dissect_rpc_unknown, dissect_rpc_unknown }, |
327 | | { 11, "PR_RELEASE", dissect_rpc_unknown, dissect_rpc_unknown }, |
328 | | { 12, "MAPID", |
329 | | dissect_pcnfsd2_mapid_call, dissect_pcnfsd2_mapid_reply }, |
330 | | { 13, "AUTH", |
331 | | dissect_pcnfsd2_auth_call, dissect_pcnfsd2_auth_reply }, |
332 | | { 14, "ALERT", dissect_rpc_unknown, dissect_rpc_unknown }, |
333 | | { 0, NULL, NULL, NULL } |
334 | | }; |
335 | | static const value_string pcnfsd2_proc_vals[] = { |
336 | | { 0, "NULL" }, |
337 | | { 1, "INFO" }, |
338 | | { 2, "PR_INIT" }, |
339 | | { 3, "PR_START" }, |
340 | | { 4, "PR_LIST" }, |
341 | | { 5, "PR_QUEUE" }, |
342 | | { 6, "PR_STATUS" }, |
343 | | { 7, "PR_CANCEL" }, |
344 | | { 8, "PR_ADMIN" }, |
345 | | { 9, "PR_REQUEUE" }, |
346 | | { 10, "PR_HOLD" }, |
347 | | { 11, "PR_RELEASE" }, |
348 | | { 12, "MAPID" }, |
349 | | { 13, "AUTH" }, |
350 | | { 14, "ALERT" }, |
351 | | { 0, NULL } |
352 | | }; |
353 | | /* end of PCNFS version 2 */ |
354 | | |
355 | | static const rpc_prog_vers_info pcnfsd_vers_info[] = { |
356 | | { 1, pcnfsd1_proc, &hf_pcnfsd_procedure_v1 }, |
357 | | { 2, pcnfsd2_proc, &hf_pcnfsd_procedure_v2 }, |
358 | | }; |
359 | | |
360 | | void |
361 | | proto_register_pcnfsd(void) |
362 | 15 | { |
363 | 15 | static hf_register_info hf[] = { |
364 | 15 | { &hf_pcnfsd_procedure_v1, { |
365 | 15 | "V1 Procedure", "pcnfsd.procedure_v1", FT_UINT32, BASE_DEC, |
366 | 15 | VALS(pcnfsd1_proc_vals), 0, NULL, HFILL }}, |
367 | 15 | { &hf_pcnfsd_procedure_v2, { |
368 | 15 | "V2 Procedure", "pcnfsd.procedure_v2", FT_UINT32, BASE_DEC, |
369 | 15 | VALS(pcnfsd2_proc_vals), 0, NULL, HFILL }}, |
370 | 15 | { &hf_pcnfsd_auth_client, { |
371 | 15 | "Authentication Client", "pcnfsd.auth.client", FT_STRING, BASE_NONE, |
372 | 15 | NULL, 0, NULL, HFILL }}, |
373 | 15 | { &hf_pcnfsd_auth_ident_obscure, { |
374 | 15 | "Obscure Ident", "pcnfsd.auth.ident.obscure", FT_STRING, BASE_NONE, |
375 | 15 | NULL, 0, "Authentication Obscure Ident", HFILL }}, |
376 | 15 | { &hf_pcnfsd_auth_ident_clear, { |
377 | 15 | "Clear Ident", "pcnfsd.auth.ident.clear", FT_STRING, BASE_NONE, |
378 | 15 | NULL, 0, "Authentication Clear Ident", HFILL }}, |
379 | 15 | { &hf_pcnfsd_auth_password, { |
380 | 15 | "Password", "pcnfsd.auth.password", FT_STRING, BASE_NONE, |
381 | 15 | NULL, 0, NULL, HFILL }}, |
382 | 15 | { &hf_pcnfsd_auth_password_obscure, { |
383 | 15 | "Obscure Password", "pcnfsd.auth.password.obscure", FT_STRING, BASE_NONE, |
384 | 15 | NULL, 0, "Authentication Obscure Password", HFILL }}, |
385 | 15 | { &hf_pcnfsd_auth_password_clear, { |
386 | 15 | "Clear Password", "pcnfsd.auth.password.clear", FT_STRING, BASE_NONE, |
387 | 15 | NULL, 0, "Authentication Clear Password", HFILL }}, |
388 | 15 | { &hf_pcnfsd_comment, { |
389 | 15 | "Comment", "pcnfsd.comment", FT_STRING, BASE_NONE, |
390 | 15 | NULL, 0, NULL, HFILL }}, |
391 | 15 | { &hf_pcnfsd_status, { |
392 | 15 | "Reply Status", "pcnfsd.status", FT_UINT32, BASE_DEC, |
393 | 15 | NULL, 0, NULL, HFILL }}, |
394 | 15 | { &hf_pcnfsd_uid, { |
395 | 15 | "User ID", "pcnfsd.uid", FT_UINT32, BASE_DEC, |
396 | 15 | NULL, 0, NULL, HFILL }}, |
397 | 15 | { &hf_pcnfsd_gid, { |
398 | 15 | "Group ID", "pcnfsd.gid", FT_UINT32, BASE_DEC, |
399 | 15 | NULL, 0, NULL, HFILL }}, |
400 | 15 | { &hf_pcnfsd_gids_count, { |
401 | 15 | "Group ID Count", "pcnfsd.gids.count", FT_UINT32, BASE_DEC, |
402 | 15 | NULL, 0, NULL, HFILL }}, |
403 | 15 | { &hf_pcnfsd_homedir, { |
404 | 15 | "Home Directory", "pcnfsd.homedir", FT_STRING, BASE_NONE, |
405 | 15 | NULL, 0, NULL, HFILL }}, |
406 | 15 | { &hf_pcnfsd_def_umask, { |
407 | 15 | "def_umask", "pcnfsd.def_umask", FT_UINT32, BASE_OCT, |
408 | 15 | NULL, 0, NULL, HFILL }}, |
409 | 15 | { &hf_pcnfsd_mapreq, { |
410 | 15 | "Request", "pcnfsd.mapreq", FT_UINT32, BASE_DEC, |
411 | 15 | VALS(names_mapreq), 0, NULL, HFILL }}, |
412 | 15 | { &hf_pcnfsd_mapreq_status, { |
413 | 15 | "Status", "pcnfsd.mapreq_status", FT_UINT32, BASE_DEC, |
414 | 15 | VALS(names_maprstat), 0, NULL, HFILL }}, |
415 | 15 | { &hf_pcnfsd_username, { |
416 | 15 | "User name", "pcnfsd.username", FT_STRING, BASE_NONE, |
417 | 15 | NULL, 0, "pcnfsd.username", HFILL }}, |
418 | 15 | }; |
419 | | |
420 | 15 | static int *ett[] = { |
421 | 15 | &ett_pcnfsd, |
422 | 15 | &ett_pcnfsd_auth_ident, |
423 | 15 | &ett_pcnfsd_auth_password, |
424 | 15 | &ett_pcnfsd_gids |
425 | 15 | }; |
426 | | |
427 | 15 | proto_pcnfsd = proto_register_protocol("PC NFS", "PCNFSD", "pcnfsd"); |
428 | 15 | proto_register_field_array(proto_pcnfsd, hf, array_length(hf)); |
429 | 15 | proto_register_subtree_array(ett, array_length(ett)); |
430 | 15 | } |
431 | | |
432 | | void |
433 | | proto_reg_handoff_pcnfsd(void) |
434 | 15 | { |
435 | | /* Register the protocol as RPC */ |
436 | 15 | rpc_init_prog(proto_pcnfsd, PCNFSD_PROGRAM, ett_pcnfsd, |
437 | | G_N_ELEMENTS(pcnfsd_vers_info), pcnfsd_vers_info); |
438 | 15 | } |
439 | | |
440 | | /* |
441 | | * Editor modelines - https://www.wireshark.org/tools/modelines.html |
442 | | * |
443 | | * Local variables: |
444 | | * c-basic-offset: 4 |
445 | | * tab-width: 8 |
446 | | * indent-tabs-mode: nil |
447 | | * End: |
448 | | * |
449 | | * vi: set shiftwidth=4 tabstop=8 expandtab: |
450 | | * :indentSize=4:tabSize=8:noTabs=true: |
451 | | */ |