Update Free Software Foundation address.
[metze/wireshark/wip.git] / epan / dissectors / packet-rpcap.c
1 /* packet-rpcap.c
2  *
3  * Routines for RPCAP message formats.
4  *
5  * Copyright 2008, Stig Bjorlykke <stig@bjorlykke.org>, Thales Norway AS
6  *
7  * $Id$
8  *
9  * Wireshark - Network traffic analyzer
10  * By Gerald Combs <gerald@wireshark.org>
11  * Copyright 1998 Gerald Combs
12  *
13  * This program is free software; you can redistribute it and/or
14  * modify it under the terms of the GNU General Public License
15  * as published by the Free Software Foundation; either version 2
16  * of the License, or (at your option) any later version.
17  *
18  * This program is distributed in the hope that it will be useful,
19  * but WITHOUT ANY WARRANTY; without even the implied warranty of
20  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21  * GNU General Public License for more details.
22  *
23  * You should have received a copy of the GNU General Public License
24  * along with this program; if not, write to the Free Software
25  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
26  */
27
28 #ifdef HAVE_CONFIG_H
29 #include "config.h"
30 #endif
31
32 #ifdef HAVE_SYS_TYPES_H
33 #include <sys/types.h>
34 #endif
35
36 #ifdef HAVE_SYS_SOCKET_H
37 #include <sys/socket.h>
38 #endif
39
40 #ifdef HAVE_WINSOCK2_H
41 #include <winsock2.h>
42 #endif
43
44 #include <epan/packet.h>
45 #include <epan/prefs.h>
46 #include <epan/to_str.h>
47 #include <epan/expert.h>
48
49 #include <wiretap/wtap.h>
50
51 #include "packet-frame.h"
52 #include "packet-tcp.h"
53
54 #define PNAME  "Remote Packet Capture"
55 #define PSNAME "RPCAP"
56 #define PFNAME "rpcap"
57
58 #define RPCAP_MSG_ERROR               1
59 #define RPCAP_MSG_FINDALLIF_REQ       2
60 #define RPCAP_MSG_OPEN_REQ            3
61 #define RPCAP_MSG_STARTCAP_REQ        4
62 #define RPCAP_MSG_UPDATEFILTER_REQ    5
63 #define RPCAP_MSG_CLOSE               6
64 #define RPCAP_MSG_PACKET              7
65 #define RPCAP_MSG_AUTH_REQ            8
66 #define RPCAP_MSG_STATS_REQ           9
67 #define RPCAP_MSG_ENDCAP_REQ          10
68 #define RPCAP_MSG_SETSAMPLING_REQ     11
69
70 #define RPCAP_MSG_FINDALLIF_REPLY     (128+RPCAP_MSG_FINDALLIF_REQ)
71 #define RPCAP_MSG_OPEN_REPLY          (128+RPCAP_MSG_OPEN_REQ)
72 #define RPCAP_MSG_STARTCAP_REPLY      (128+RPCAP_MSG_STARTCAP_REQ)
73 #define RPCAP_MSG_UPDATEFILTER_REPLY  (128+RPCAP_MSG_UPDATEFILTER_REQ)
74 #define RPCAP_MSG_AUTH_REPLY          (128+RPCAP_MSG_AUTH_REQ)
75 #define RPCAP_MSG_STATS_REPLY         (128+RPCAP_MSG_STATS_REQ)
76 #define RPCAP_MSG_ENDCAP_REPLY        (128+RPCAP_MSG_ENDCAP_REQ)
77 #define RPCAP_MSG_SETSAMPLING_REPLY   (128+RPCAP_MSG_SETSAMPLING_REQ)
78
79 #define RPCAP_ERR_NETW            1
80 #define RPCAP_ERR_INITTIMEOUT     2
81 #define RPCAP_ERR_AUTH            3
82 #define RPCAP_ERR_FINDALLIF       4
83 #define RPCAP_ERR_NOREMOTEIF      5
84 #define RPCAP_ERR_OPEN            6
85 #define RPCAP_ERR_UPDATEFILTER    7
86 #define RPCAP_ERR_GETSTATS        8
87 #define RPCAP_ERR_READEX          9
88 #define RPCAP_ERR_HOSTNOAUTH      10
89 #define RPCAP_ERR_REMOTEACCEPT    11
90 #define RPCAP_ERR_STARTCAPTURE    12
91 #define RPCAP_ERR_ENDCAPTURE      13
92 #define RPCAP_ERR_RUNTIMETIMEOUT  14
93 #define RPCAP_ERR_SETSAMPLING     15
94 #define RPCAP_ERR_WRONGMSG        16
95 #define RPCAP_ERR_WRONGVER        17
96
97 #define RPCAP_SAMP_NOSAMP            0
98 #define RPCAP_SAMP_1_EVERY_N         1
99 #define RPCAP_SAMP_FIRST_AFTER_N_MS  2
100
101 #define RPCAP_RMTAUTH_NULL  0
102 #define RPCAP_RMTAUTH_PWD   1
103
104 #define FLAG_PROMISC     0x0001
105 #define FLAG_DGRAM       0x0002
106 #define FLAG_SERVEROPEN  0x0004
107 #define FLAG_INBOUND     0x0008
108 #define FLAG_OUTBOUND    0x0010
109
110 void proto_reg_handoff_rpcap (void);
111
112 static int proto_rpcap = -1;
113
114 static int hf_version = -1;
115 static int hf_type = -1;
116 static int hf_value = -1;
117 static int hf_plen = -1;
118
119 static int hf_error = -1;
120 static int hf_error_value = -1;
121
122 static int hf_packet = -1;
123 static int hf_timestamp = -1;
124 static int hf_caplen = -1;
125 static int hf_len = -1;
126 static int hf_npkt = -1;
127
128 static int hf_auth_request = -1;
129 static int hf_auth_type = -1;
130 static int hf_auth_slen1 = -1;
131 static int hf_auth_slen2 = -1;
132 static int hf_auth_username = -1;
133 static int hf_auth_password = -1;
134
135 static int hf_open_request = -1;
136
137 static int hf_open_reply = -1;
138 static int hf_linktype = -1;
139 static int hf_tzoff = -1;
140
141 static int hf_startcap_request = -1;
142 static int hf_snaplen = -1;
143 static int hf_read_timeout = -1;
144 static int hf_flags = -1;
145 static int hf_flags_promisc = -1;
146 static int hf_flags_dgram = -1;
147 static int hf_flags_serveropen = -1;
148 static int hf_flags_inbound = -1;
149 static int hf_flags_outbound = -1;
150 static int hf_client_port = -1;
151 static int hf_startcap_reply = -1;
152 static int hf_bufsize = -1;
153 static int hf_server_port = -1;
154 static int hf_dummy = -1;
155
156 static int hf_filter = -1;
157 static int hf_filtertype = -1;
158 static int hf_nitems = -1;
159
160 static int hf_filterbpf_insn = -1;
161 static int hf_code = -1;
162 static int hf_code_class = -1;
163 static int hf_code_fields = -1;
164 static int hf_code_ld_size = -1;
165 static int hf_code_ld_mode = -1;
166 static int hf_code_alu_op = -1;
167 static int hf_code_jmp_op = -1;
168 static int hf_code_src = -1;
169 static int hf_code_rval = -1;
170 static int hf_code_misc_op = -1;
171 static int hf_jt = -1;
172 static int hf_jf = -1;
173 static int hf_instr_value = -1;
174
175 static int hf_stats_reply = -1;
176 static int hf_ifrecv = -1;
177 static int hf_ifdrop = -1;
178 static int hf_krnldrop = -1;
179 static int hf_srvcapt = -1;
180
181 static int hf_findalldevs_reply = -1;
182 static int hf_findalldevs_if = -1;
183 static int hf_namelen = -1;
184 static int hf_desclen = -1;
185 static int hf_if_flags = -1;
186 static int hf_naddr = -1;
187 static int hf_if_name = -1;
188 static int hf_if_desc = -1;
189
190 static int hf_findalldevs_ifaddr = -1;
191 static int hf_if_addr = -1;
192 static int hf_if_netmask = -1;
193 static int hf_if_broadaddr = -1;
194 static int hf_if_dstaddr = -1;
195 static int hf_if_af = -1;
196 static int hf_if_port = -1;
197 static int hf_if_ip = -1;
198 static int hf_if_padding = -1;
199 static int hf_if_unknown = -1;
200
201 static int hf_sampling_request = -1;
202 static int hf_sampling_method = -1;
203 static int hf_sampling_dummy1 = -1;
204 static int hf_sampling_dummy2 = -1;
205 static int hf_sampling_value = -1;
206
207 static gint ett_rpcap = -1;
208 static gint ett_error = -1;
209 static gint ett_packet = -1;
210 static gint ett_auth_request = -1;
211 static gint ett_open_reply = -1;
212 static gint ett_startcap_request = -1;
213 static gint ett_startcap_reply = -1;
214 static gint ett_startcap_flags = -1;
215 static gint ett_filter = -1;
216 static gint ett_filterbpf_insn = -1;
217 static gint ett_filterbpf_insn_code = -1;
218 static gint ett_stats_reply = -1;
219 static gint ett_findalldevs_reply = -1;
220 static gint ett_findalldevs_if = -1;
221 static gint ett_findalldevs_ifaddr = -1;
222 static gint ett_ifaddr = -1;
223 static gint ett_sampling_request = -1;
224
225 static dissector_handle_t data_handle;
226
227 /* User definable values */
228 static gboolean rpcap_desegment = TRUE;
229 static gboolean decode_content = TRUE;
230 static guint32 global_linktype = WTAP_ENCAP_UNKNOWN;
231
232 /* Global variables */
233 static guint32 linktype = WTAP_ENCAP_UNKNOWN;
234 static gboolean info_added = FALSE;
235
236 static const true_false_string open_closed = {
237   "Open", "Closed"
238 };
239
240 static const value_string message_type[] = {
241   { RPCAP_MSG_ERROR,              "Error"                       },
242   { RPCAP_MSG_FINDALLIF_REQ,      "Find all interfaces request" },
243   { RPCAP_MSG_OPEN_REQ,           "Open request"                },
244   { RPCAP_MSG_STARTCAP_REQ,       "Start capture request"       },
245   { RPCAP_MSG_UPDATEFILTER_REQ,   "Update filter request"       },
246   { RPCAP_MSG_CLOSE,              "Close"                       },
247   { RPCAP_MSG_PACKET,             "Packet"                      },
248   { RPCAP_MSG_AUTH_REQ,           "Authentication request"      },
249   { RPCAP_MSG_STATS_REQ,          "Statistics request"          },
250   { RPCAP_MSG_ENDCAP_REQ,         "End capture request"         },
251   { RPCAP_MSG_SETSAMPLING_REQ,    "Set sampling request"        },
252   { RPCAP_MSG_FINDALLIF_REPLY,    "Find all interfaces reply"   },
253   { RPCAP_MSG_OPEN_REPLY,         "Open reply"                  },
254   { RPCAP_MSG_STARTCAP_REPLY,     "Start capture reply"         },
255   { RPCAP_MSG_UPDATEFILTER_REPLY, "Update filter reply"         },
256   { RPCAP_MSG_AUTH_REPLY,         "Authentication reply"        },
257   { RPCAP_MSG_STATS_REPLY,        "Statistics reply"            },
258   { RPCAP_MSG_ENDCAP_REPLY,       "End capture reply"           },
259   { RPCAP_MSG_SETSAMPLING_REPLY,  "Set sampling reply"          },
260   { 0,   NULL }
261 };
262
263 static const value_string error_codes[] = {
264   { RPCAP_ERR_NETW,            "Network error"                        },
265   { RPCAP_ERR_INITTIMEOUT,     "Initial timeout has expired"          },
266   { RPCAP_ERR_AUTH,            "Authentication error"                 },
267   { RPCAP_ERR_FINDALLIF,       "Generic findalldevs error"            },
268   { RPCAP_ERR_NOREMOTEIF,      "No remote interfaces"                 },
269   { RPCAP_ERR_OPEN,            "Generic pcap_open error"              },
270   { RPCAP_ERR_UPDATEFILTER,    "Generic updatefilter error"           },
271   { RPCAP_ERR_GETSTATS,        "Generic pcap_stats error"             },
272   { RPCAP_ERR_READEX,          "Generic pcap_next_ex error"           },
273   { RPCAP_ERR_HOSTNOAUTH,      "The host is not authorized"           },
274   { RPCAP_ERR_REMOTEACCEPT,    "Generic pcap_remoteaccept error"      },
275   { RPCAP_ERR_STARTCAPTURE,    "Generic pcap_startcapture error"      },
276   { RPCAP_ERR_ENDCAPTURE,      "Generic pcap_endcapture error"        },
277   { RPCAP_ERR_RUNTIMETIMEOUT,  "Runtime timeout has expired"          },
278   { RPCAP_ERR_SETSAMPLING,     "Error in setting sampling parameters" },
279   { RPCAP_ERR_WRONGMSG,        "Unrecognized message"                 },
280   { RPCAP_ERR_WRONGVER,        "Incompatible version"                 },
281   { 0,   NULL }
282 };
283
284 static const value_string sampling_method[] = {
285   { RPCAP_SAMP_NOSAMP,            "No sampling"      },
286   { RPCAP_SAMP_1_EVERY_N,         "1 every N"        },
287   { RPCAP_SAMP_FIRST_AFTER_N_MS,  "First after N ms" },
288   { 0,   NULL }
289 };
290
291 static const value_string auth_type[] = {
292   { RPCAP_RMTAUTH_NULL, "None"     },
293   { RPCAP_RMTAUTH_PWD,  "Password" },
294   { 0,   NULL }
295 };
296
297 static const value_string address_family[] = {
298   { AF_UNSPEC, "AF_UNSPEC" },
299   { AF_INET,   "AF_INET"   },
300   { 0,   NULL }
301 };
302
303 static const value_string bpf_class[] = {
304   { 0x00, "ld"   },
305   { 0x01, "ldx"  },
306   { 0x02, "st"   },
307   { 0x03, "stx"  },
308   { 0x04, "alu"  },
309   { 0x05, "jmp"  },
310   { 0x06, "ret"  },
311   { 0x07, "misc" },
312   { 0, NULL }
313 };
314
315 static const value_string bpf_size[] = {
316   { 0x00, "w" },
317   { 0x01, "h" },
318   { 0x02, "b" },
319   { 0, NULL }
320 };
321
322 static const value_string bpf_mode[] = {
323   { 0x00, "imm" },
324   { 0x01, "abs" },
325   { 0x02, "ind" },
326   { 0x03, "mem" },
327   { 0x04, "len" },
328   { 0x05, "msh" },
329   { 0, NULL }
330 };
331
332 static const value_string bpf_alu_op[] = {
333   { 0x00, "add" },
334   { 0x01, "sub" },
335   { 0x02, "mul" },
336   { 0x03, "div" },
337   { 0x04, "or"  },
338   { 0x05, "and" },
339   { 0x06, "lsh" },
340   { 0x07, "rsh" },
341   { 0x08, "neg" },
342   { 0, NULL }
343 };
344
345 static const value_string bpf_jmp_op[] = {
346   { 0x00, "ja"   },
347   { 0x01, "jeq"  },
348   { 0x02, "jgt"  },
349   { 0x03, "jge"  },
350   { 0x04, "jset" },
351   { 0, NULL }
352 };
353
354 static const value_string bpf_src[] = {
355   { 0x00, "k" },
356   { 0x01, "x" },
357   { 0, NULL }
358 };
359
360 static const value_string bpf_rval[] = {
361   { 0x00, "k" },
362   { 0x01, "x" },
363   { 0x02, "a" },
364   { 0, NULL }
365 };
366
367 static const value_string bpf_misc_op[] = {
368   { 0x00, "tax" },
369   { 0x10, "txa" },
370   { 0, NULL }
371 };
372
373
374 static void rpcap_frame_end (void)
375 {
376   info_added = FALSE;
377 }
378
379
380 static void
381 dissect_rpcap_error (tvbuff_t *tvb, packet_info *pinfo,
382                      proto_tree *parent_tree, gint offset)
383 {
384   proto_item *ti;
385   gint len;
386
387   len = tvb_length_remaining (tvb, offset);
388
389   if (check_col (pinfo->cinfo, COL_INFO)) {
390     col_append_fstr (pinfo->cinfo, COL_INFO, ": %s",
391                      tvb_format_text_wsp (tvb, offset, len));
392   }
393
394   ti = proto_tree_add_item (parent_tree, hf_error, tvb, offset, len, ENC_ASCII|ENC_NA);
395   expert_add_info_format (pinfo, ti, PI_SEQUENCE, PI_NOTE,
396                           "Error: %s", tvb_format_text_wsp (tvb, offset, len));
397 }
398
399
400 static gint
401 dissect_rpcap_ifaddr (tvbuff_t *tvb, packet_info *pinfo,
402                       proto_tree *parent_tree, gint offset, int hf_id,
403                       proto_item *parent_item)
404 {
405   proto_tree *tree;
406   proto_item *ti;
407   gchar ipaddr[MAX_ADDR_STR_LEN];
408   guint32 ipv4;
409   guint16 af;
410
411   ti = proto_tree_add_item (parent_tree, hf_id, tvb, offset, 128, ENC_BIG_ENDIAN);
412   tree = proto_item_add_subtree (ti, ett_ifaddr);
413
414   af = tvb_get_ntohs (tvb, offset);
415   proto_tree_add_item (tree, hf_if_af, tvb, offset, 2, ENC_BIG_ENDIAN);
416   offset += 2;
417
418   if (af == AF_INET) {
419     proto_tree_add_item (tree, hf_if_port, tvb, offset, 2, ENC_BIG_ENDIAN);
420     offset += 2;
421
422     ipv4 = tvb_get_ipv4 (tvb, offset);
423     ip_to_str_buf((guint8 *)&ipv4, ipaddr, MAX_ADDR_STR_LEN);
424     proto_item_append_text (ti, ": %s", ipaddr);
425     if (parent_item) {
426       proto_item_append_text (parent_item, ": %s", ipaddr);
427     }
428     proto_tree_add_item (tree, hf_if_ip, tvb, offset, 4, ENC_BIG_ENDIAN);
429     offset += 4;
430
431     proto_tree_add_item (tree, hf_if_padding, tvb, offset, 120, ENC_NA);
432     offset += 120;
433   } else {
434     ti = proto_tree_add_item (tree, hf_if_unknown, tvb, offset, 126, ENC_NA);
435     if (af != AF_UNSPEC) {
436       expert_add_info_format (pinfo, ti, PI_UNDECODED, PI_CHAT,
437                               "Unknown address family: %d", af);
438     }
439     offset += 126;
440   }
441
442   return offset;
443 }
444
445
446 static gint
447 dissect_rpcap_findalldevs_ifaddr (tvbuff_t *tvb, packet_info *pinfo _U_,
448                                   proto_tree *parent_tree, gint offset)
449 {
450   proto_tree *tree;
451   proto_item *ti;
452   gint boffset = offset;
453
454   ti = proto_tree_add_item (parent_tree, hf_findalldevs_ifaddr, tvb, offset, -1, ENC_NA);
455   tree = proto_item_add_subtree (ti, ett_findalldevs_ifaddr);
456
457   offset = dissect_rpcap_ifaddr (tvb, pinfo, tree, offset, hf_if_addr, ti);
458   offset = dissect_rpcap_ifaddr (tvb, pinfo, tree, offset, hf_if_netmask, NULL);
459   offset = dissect_rpcap_ifaddr (tvb, pinfo, tree, offset, hf_if_broadaddr, NULL);
460   offset = dissect_rpcap_ifaddr (tvb, pinfo, tree, offset, hf_if_dstaddr, NULL);
461
462   proto_item_set_len (ti, offset - boffset);
463
464   return offset;
465 }
466
467
468 static gint
469 dissect_rpcap_findalldevs_if (tvbuff_t *tvb, packet_info *pinfo _U_,
470                               proto_tree *parent_tree, gint offset)
471 {
472   proto_tree *tree;
473   proto_item *ti;
474   guint16 namelen, desclen, naddr, i;
475   gint boffset = offset;
476
477   ti = proto_tree_add_item (parent_tree, hf_findalldevs_if, tvb, offset, -1, ENC_NA);
478   tree = proto_item_add_subtree (ti, ett_findalldevs_if);
479
480   namelen = tvb_get_ntohs (tvb, offset);
481   proto_tree_add_item (tree, hf_namelen, tvb, offset, 2, ENC_BIG_ENDIAN);
482   offset += 2;
483
484   desclen = tvb_get_ntohs (tvb, offset);
485   proto_tree_add_item (tree, hf_desclen, tvb, offset, 2, ENC_BIG_ENDIAN);
486   offset += 2;
487
488   proto_tree_add_item (tree, hf_if_flags, tvb, offset, 4, ENC_BIG_ENDIAN);
489   offset += 4;
490
491   naddr = tvb_get_ntohs (tvb, offset);
492   proto_tree_add_item (tree, hf_naddr, tvb, offset, 2, ENC_BIG_ENDIAN);
493   offset += 2;
494
495   proto_tree_add_item (tree, hf_dummy, tvb, offset, 2, ENC_BIG_ENDIAN);
496   offset += 2;
497
498   if (namelen) {
499     proto_item_append_text (ti, ": %s", tvb_get_ephemeral_string (tvb, offset, namelen));
500     proto_tree_add_item (tree, hf_if_name, tvb, offset, namelen, ENC_ASCII|ENC_NA);
501     offset += namelen;
502   }
503
504   if (desclen) {
505     proto_tree_add_item (tree, hf_if_desc, tvb, offset, desclen, ENC_ASCII|ENC_NA);
506     offset += desclen;
507   }
508
509   for (i = 0; i < naddr; i++) {
510     offset = dissect_rpcap_findalldevs_ifaddr (tvb, pinfo, tree, offset);
511     if (tvb_length_remaining (tvb, offset) < 0) {
512       /* No more data in packet */
513       expert_add_info_format (pinfo, ti, PI_MALFORMED, PI_ERROR, "No more data in packet");
514       break;
515     }
516   }
517
518   proto_item_set_len (ti, offset - boffset);
519
520   return offset;
521 }
522
523
524 static void
525 dissect_rpcap_findalldevs_reply (tvbuff_t *tvb, packet_info *pinfo _U_,
526                                  proto_tree *parent_tree, gint offset, guint16 no_devs)
527 {
528   proto_tree *tree;
529   proto_item *ti;
530   guint16 i;
531
532   ti = proto_tree_add_item (parent_tree, hf_findalldevs_reply, tvb, offset, -1, ENC_NA);
533   tree = proto_item_add_subtree (ti, ett_findalldevs_reply);
534
535   for (i = 0; i < no_devs; i++) {
536     offset = dissect_rpcap_findalldevs_if (tvb, pinfo, tree, offset);
537     if (tvb_length_remaining (tvb, offset) < 0) {
538       /* No more data in packet */
539       expert_add_info_format (pinfo, ti, PI_MALFORMED, PI_ERROR, "No more data in packet");
540       break;
541     }
542   }
543
544   proto_item_append_text (ti, ", %d item%s", no_devs, plurality (no_devs, "", "s"));
545 }
546
547
548 static gint
549 dissect_rpcap_filterbpf_insn (tvbuff_t *tvb, packet_info *pinfo _U_,
550                               proto_tree *parent_tree, gint offset)
551 {
552   proto_tree *tree, *code_tree;
553   proto_item *ti, *code_ti;
554   guint8 class;
555
556   ti = proto_tree_add_item (parent_tree, hf_filterbpf_insn, tvb, offset, 8, ENC_NA);
557   tree = proto_item_add_subtree (ti, ett_filterbpf_insn);
558
559   code_ti = proto_tree_add_item (tree, hf_code, tvb, offset, 2, ENC_BIG_ENDIAN);
560   code_tree = proto_item_add_subtree (code_ti, ett_filterbpf_insn_code);
561   proto_tree_add_item (code_tree, hf_code_class, tvb, offset, 2, ENC_BIG_ENDIAN);
562   class = tvb_get_guint8 (tvb, offset + 1) & 0x07;
563   proto_item_append_text (ti, ": %s", val_to_str (class, bpf_class, ""));
564   switch (class) {
565   case 0x00: /* ld */
566   case 0x01: /* ldx */
567     proto_tree_add_item (code_tree, hf_code_ld_size, tvb, offset, 2, ENC_BIG_ENDIAN);
568     proto_tree_add_item (code_tree, hf_code_ld_mode, tvb, offset, 2, ENC_BIG_ENDIAN);
569     break;
570   case 0x04: /* alu */
571     proto_tree_add_item (code_tree, hf_code_src, tvb, offset, 2, ENC_BIG_ENDIAN);
572     proto_tree_add_item (code_tree, hf_code_alu_op, tvb, offset, 2, ENC_BIG_ENDIAN);
573     break;
574   case 0x05: /* jmp */
575     proto_tree_add_item (code_tree, hf_code_src, tvb, offset, 2, ENC_BIG_ENDIAN);
576     proto_tree_add_item (code_tree, hf_code_jmp_op, tvb, offset, 2, ENC_BIG_ENDIAN);
577     break;
578   case 0x06: /* ret */
579     proto_tree_add_item (code_tree, hf_code_rval, tvb, offset, 2, ENC_BIG_ENDIAN);
580     break;
581   case 0x07: /* misc */
582     proto_tree_add_item (code_tree, hf_code_misc_op, tvb, offset, 2, ENC_BIG_ENDIAN);
583     break;
584   default:
585     proto_tree_add_item (code_tree, hf_code_fields, tvb, offset, 2, ENC_BIG_ENDIAN);
586     break;
587   }
588   offset += 2;
589
590   proto_tree_add_item (tree, hf_jt, tvb, offset, 1, ENC_BIG_ENDIAN);
591   offset += 1;
592
593   proto_tree_add_item (tree, hf_jf, tvb, offset, 1, ENC_BIG_ENDIAN);
594   offset += 1;
595
596   proto_tree_add_item (tree, hf_instr_value, tvb, offset, 4, ENC_BIG_ENDIAN);
597   offset += 4;
598
599   return offset;
600 }
601
602
603 static void
604 dissect_rpcap_filter (tvbuff_t *tvb, packet_info *pinfo,
605                       proto_tree *parent_tree, gint offset)
606 {
607   proto_tree *tree;
608   proto_item *ti;
609   guint32 nitems, i;
610
611   ti = proto_tree_add_item (parent_tree, hf_filter, tvb, offset, -1, ENC_NA);
612   tree = proto_item_add_subtree (ti, ett_filter);
613
614   proto_tree_add_item (tree, hf_filtertype, tvb, offset, 2, ENC_BIG_ENDIAN);
615   offset += 2;
616
617   proto_tree_add_item (tree, hf_dummy, tvb, offset, 2, ENC_BIG_ENDIAN);
618   offset += 2;
619
620   nitems = tvb_get_ntohl (tvb, offset);
621   proto_tree_add_item (tree, hf_nitems, tvb, offset, 4, ENC_BIG_ENDIAN);
622   offset += 4;
623
624   for (i = 0; i < nitems; i++) {
625     offset = dissect_rpcap_filterbpf_insn (tvb, pinfo, tree, offset);
626     if (tvb_length_remaining (tvb, offset) < 0) {
627       /* No more data in packet */
628       expert_add_info_format (pinfo, ti, PI_MALFORMED, PI_ERROR, "No more data in packet");
629       break;
630     }
631   }
632 }
633
634
635 static int
636 dissect_rpcap_auth_request (tvbuff_t *tvb, packet_info *pinfo _U_,
637                             proto_tree *parent_tree, gint offset)
638 {
639   proto_tree *tree;
640   proto_item *ti;
641   guint16 type, slen1, slen2;
642
643   ti = proto_tree_add_item (parent_tree, hf_auth_request, tvb, offset, -1, ENC_NA);
644   tree = proto_item_add_subtree (ti, ett_auth_request);
645
646   type = tvb_get_ntohs (tvb, offset);
647   proto_tree_add_item (tree, hf_auth_type, tvb, offset, 2, ENC_BIG_ENDIAN);
648   offset += 2;
649
650   proto_tree_add_item (tree, hf_dummy, tvb, offset, 2, ENC_BIG_ENDIAN);
651   offset += 2;
652
653   slen1 = tvb_get_ntohs (tvb, offset);
654   proto_tree_add_item (tree, hf_auth_slen1, tvb, offset, 2, ENC_BIG_ENDIAN);
655   offset += 2;
656
657   slen2 = tvb_get_ntohs (tvb, offset);
658   proto_tree_add_item (tree, hf_auth_slen2, tvb, offset, 2, ENC_BIG_ENDIAN);
659   offset += 2;
660
661   if (type == RPCAP_RMTAUTH_NULL) {
662     proto_item_append_text (ti, " (none)");
663   } else if (type == RPCAP_RMTAUTH_PWD) {
664     guint8 *username, *password;
665
666     username = tvb_get_ephemeral_string (tvb, offset, slen1);
667     proto_tree_add_item (tree, hf_auth_username, tvb, offset, slen1, ENC_ASCII|ENC_NA);
668     offset += slen1;
669
670     password = tvb_get_ephemeral_string (tvb, offset, slen2);
671     proto_tree_add_item (tree, hf_auth_password, tvb, offset, slen2, ENC_ASCII|ENC_NA);
672     offset += slen2;
673
674     proto_item_append_text (ti, " (%s/%s)", username, password);
675   }
676   return offset;
677 }
678
679
680 static void
681 dissect_rpcap_open_request (tvbuff_t *tvb, packet_info *pinfo _U_,
682                             proto_tree *parent_tree, gint offset)
683 {
684   gint len;
685
686   len = tvb_length_remaining (tvb, offset);
687   proto_tree_add_item (parent_tree, hf_open_request, tvb, offset, len, ENC_ASCII|ENC_NA);
688 }
689
690
691 static void
692 dissect_rpcap_open_reply (tvbuff_t *tvb, packet_info *pinfo _U_,
693                           proto_tree *parent_tree, gint offset)
694 {
695   proto_tree *tree;
696   proto_item *ti;
697
698   ti = proto_tree_add_item (parent_tree, hf_open_reply, tvb, offset, -1, ENC_NA);
699   tree = proto_item_add_subtree (ti, ett_open_reply);
700
701   linktype = tvb_get_ntohl (tvb, offset);
702   proto_tree_add_item (tree, hf_linktype, tvb, offset, 4, ENC_BIG_ENDIAN);
703   offset += 4;
704
705   proto_tree_add_item (tree, hf_tzoff, tvb, offset, 4, ENC_BIG_ENDIAN);
706 }
707
708
709 static void
710 dissect_rpcap_startcap_request (tvbuff_t *tvb, packet_info *pinfo,
711                                 proto_tree *parent_tree, gint offset)
712 {
713   proto_tree *tree, *field_tree;
714   proto_item *ti, *field_ti;
715   guint16 flags;
716
717   ti = proto_tree_add_item (parent_tree, hf_startcap_request, tvb, offset, -1, ENC_NA);
718   tree = proto_item_add_subtree (ti, ett_startcap_request);
719
720   proto_tree_add_item (tree, hf_snaplen, tvb, offset, 4, ENC_BIG_ENDIAN);
721   offset += 4;
722
723   proto_tree_add_item (tree, hf_read_timeout, tvb, offset, 4, ENC_BIG_ENDIAN);
724   offset += 4;
725
726   flags = tvb_get_ntohs (tvb, offset);
727   field_ti = proto_tree_add_uint_format (tree, hf_flags, tvb, offset, 2, flags, "Flags");
728   field_tree = proto_item_add_subtree (field_ti, ett_startcap_flags);
729   proto_tree_add_item (field_tree, hf_flags_promisc, tvb, offset, 2, ENC_BIG_ENDIAN);
730   proto_tree_add_item (field_tree, hf_flags_dgram, tvb, offset, 2, ENC_BIG_ENDIAN);
731   proto_tree_add_item (field_tree, hf_flags_serveropen, tvb, offset, 2, ENC_BIG_ENDIAN);
732   proto_tree_add_item (field_tree, hf_flags_inbound, tvb, offset, 2, ENC_BIG_ENDIAN);
733   proto_tree_add_item (field_tree, hf_flags_outbound, tvb, offset, 2, ENC_BIG_ENDIAN);
734
735   if (flags & 0x1F) {
736     gchar *flagstr = g_strdup_printf ("%s%s%s%s%s",
737           (flags & FLAG_PROMISC)    ? ", Promiscuous" : "",
738           (flags & FLAG_DGRAM)      ? ", Datagram"    : "",
739           (flags & FLAG_SERVEROPEN) ? ", ServerOpen"  : "",
740           (flags & FLAG_INBOUND)    ? ", Inbound"     : "",
741           (flags & FLAG_OUTBOUND)   ? ", Outbound"    : "");
742     proto_item_append_text (field_ti, ":%s", &flagstr[1]);
743     g_free (flagstr);
744   } else {
745     proto_item_append_text (field_ti, " (none)");
746   }
747   offset += 2;
748
749   proto_tree_add_item (tree, hf_client_port, tvb, offset, 2, ENC_BIG_ENDIAN);
750   offset += 2;
751
752   dissect_rpcap_filter (tvb, pinfo, tree, offset);
753 }
754
755
756 static void
757 dissect_rpcap_startcap_reply (tvbuff_t *tvb, packet_info *pinfo _U_,
758                               proto_tree *parent_tree, gint offset)
759 {
760   proto_tree *tree;
761   proto_item *ti;
762
763   ti = proto_tree_add_item (parent_tree, hf_startcap_reply, tvb, offset, -1, ENC_NA);
764   tree = proto_item_add_subtree (ti, ett_startcap_reply);
765
766   proto_tree_add_item (tree, hf_bufsize, tvb, offset, 4, ENC_BIG_ENDIAN);
767   offset += 4;
768
769   proto_tree_add_item (tree, hf_server_port, tvb, offset, 2, ENC_BIG_ENDIAN);
770   offset += 2;
771
772   proto_tree_add_item (tree, hf_dummy, tvb, offset, 2, ENC_BIG_ENDIAN);
773 }
774
775
776 static void
777 dissect_rpcap_stats_reply (tvbuff_t *tvb, packet_info *pinfo _U_,
778                            proto_tree *parent_tree, gint offset)
779 {
780   proto_tree *tree;
781   proto_item *ti;
782
783   ti = proto_tree_add_item (parent_tree, hf_stats_reply, tvb, offset, 16, ENC_NA);
784   tree = proto_item_add_subtree (ti, ett_stats_reply);
785
786   proto_tree_add_item (tree, hf_ifrecv, tvb, offset, 4, ENC_BIG_ENDIAN);
787   offset += 4;
788
789   proto_tree_add_item (tree, hf_ifdrop, tvb, offset, 4, ENC_BIG_ENDIAN);
790   offset += 4;
791
792   proto_tree_add_item (tree, hf_krnldrop, tvb, offset, 4, ENC_BIG_ENDIAN);
793   offset += 4;
794
795   proto_tree_add_item (tree, hf_srvcapt, tvb, offset, 4, ENC_BIG_ENDIAN);
796 }
797
798
799 static int
800 dissect_rpcap_sampling_request (tvbuff_t *tvb, packet_info *pinfo _U_,
801                                 proto_tree *parent_tree, gint offset)
802 {
803   proto_tree *tree;
804   proto_item *ti;
805   guint32 value;
806   guint8 method;
807
808   ti = proto_tree_add_item (parent_tree, hf_sampling_request, tvb, offset, -1, ENC_NA);
809   tree = proto_item_add_subtree (ti, ett_sampling_request);
810
811   method = tvb_get_guint8 (tvb, offset);
812   proto_tree_add_item (tree, hf_sampling_method, tvb, offset, 1, ENC_BIG_ENDIAN);
813   offset += 1;
814
815   proto_tree_add_item (tree, hf_sampling_dummy1, tvb, offset, 1, ENC_BIG_ENDIAN);
816   offset += 1;
817
818   proto_tree_add_item (tree, hf_sampling_dummy2, tvb, offset, 2, ENC_BIG_ENDIAN);
819   offset += 2;
820
821   value = tvb_get_ntohl (tvb, offset);
822   proto_tree_add_item (tree, hf_sampling_value, tvb, offset, 4, ENC_BIG_ENDIAN);
823   offset += 4;
824
825   switch (method) {
826   case RPCAP_SAMP_NOSAMP:
827     proto_item_append_text (ti, ": None");
828     break;
829   case RPCAP_SAMP_1_EVERY_N:
830     proto_item_append_text (ti, ": 1 every %d", value);
831     break;
832   case RPCAP_SAMP_FIRST_AFTER_N_MS:
833     proto_item_append_text (ti, ": First after %d ms", value);
834     break;
835   default:
836     break;
837   }
838   return offset;
839 }
840
841
842 static void
843 dissect_rpcap_packet (tvbuff_t *tvb, packet_info *pinfo, proto_tree *top_tree,
844                       proto_tree *parent_tree, gint offset, proto_item *top_item)
845 {
846   proto_tree *tree;
847   proto_item *ti;
848   nstime_t ts;
849   tvbuff_t *new_tvb;
850   guint caplen, len, frame_no;
851   gint reported_length_remaining;
852
853   ti = proto_tree_add_item (parent_tree, hf_packet, tvb, offset, 20, ENC_NA);
854   tree = proto_item_add_subtree (ti, ett_packet);
855
856   ts.secs = tvb_get_ntohl (tvb, offset);
857   ts.nsecs = tvb_get_ntohl (tvb, offset + 4) * 1000;
858   proto_tree_add_time(tree, hf_timestamp, tvb, offset, 8, &ts);
859   offset += 8;
860
861   caplen = tvb_get_ntohl (tvb, offset);
862   ti = proto_tree_add_item (tree, hf_caplen, tvb, offset, 4, ENC_BIG_ENDIAN);
863   offset += 4;
864
865   len = tvb_get_ntohl (tvb, offset);
866   proto_tree_add_item (tree, hf_len, tvb, offset, 4, ENC_BIG_ENDIAN);
867   offset += 4;
868
869   frame_no = tvb_get_ntohl (tvb, offset);
870   proto_tree_add_item (tree, hf_npkt, tvb, offset, 4, ENC_BIG_ENDIAN);
871   offset += 4;
872
873   proto_item_append_text (ti, ", Frame %u", frame_no);
874   proto_item_append_text (top_item, " Frame %u", frame_no);
875
876   /*
877    * reported_length_remaining should not be -1, as offset is at
878    * most right past the end of the available data in the packet.
879    */
880   reported_length_remaining = tvb_length_remaining (tvb, offset);
881   if (caplen > (guint)reported_length_remaining) {
882     expert_add_info_format (pinfo, ti, PI_MALFORMED, PI_ERROR,
883                           "Caplen is bigger than the remaining message length");
884     return;
885   }
886
887   new_tvb = tvb_new_subset (tvb, offset, caplen, len);
888   if (decode_content && linktype != WTAP_ENCAP_UNKNOWN) {
889     dissector_try_uint(wtap_encap_dissector_table, linktype, new_tvb, pinfo, top_tree);
890
891     if (!info_added) {
892       /* Only indicate when not added before */
893       /* Indicate RPCAP in the protocol column */
894       col_prepend_fence_fstr(pinfo->cinfo, COL_PROTOCOL, "R|");
895
896       /* Indicate RPCAP in the info column */
897       col_prepend_fence_fstr (pinfo->cinfo, COL_INFO, "Remote | ");
898       info_added = TRUE;
899       register_frame_end_routine(rpcap_frame_end);
900     }
901   } else {
902     if (linktype == WTAP_ENCAP_UNKNOWN) {
903       proto_item_append_text (ti, ", Unknown link-layer type");
904     }
905     call_dissector (data_handle, new_tvb, pinfo, top_tree);
906   }
907 }
908
909
910 static void
911 dissect_rpcap (tvbuff_t *tvb, packet_info *pinfo, proto_tree *top_tree)
912 {
913   proto_tree *tree;
914   proto_item *ti;
915   tvbuff_t *new_tvb;
916   gint len, offset = 0;
917   guint8 msg_type;
918   guint16 msg_value;
919
920   col_set_str (pinfo->cinfo, COL_PROTOCOL, PSNAME);
921
922   col_clear(pinfo->cinfo, COL_INFO);
923
924   ti = proto_tree_add_item (top_tree, proto_rpcap, tvb, offset, -1, ENC_NA);
925   tree = proto_item_add_subtree (ti, ett_rpcap);
926
927   proto_tree_add_item (tree, hf_version, tvb, offset, 1, ENC_BIG_ENDIAN);
928   offset++;
929
930   msg_type = tvb_get_guint8 (tvb, offset);
931   proto_tree_add_item (tree, hf_type, tvb, offset, 1, ENC_BIG_ENDIAN);
932   offset++;
933
934   if (check_col (pinfo->cinfo, COL_INFO)) {
935     col_append_fstr (pinfo->cinfo, COL_INFO, "%s",
936                      val_to_str (msg_type, message_type, "Unknown: %d"));
937   }
938
939   proto_item_append_text (ti, ", %s", val_to_str (msg_type, message_type, "Unknown: %d"));
940
941   msg_value = tvb_get_ntohs (tvb, offset);
942   if (msg_type == RPCAP_MSG_ERROR) {
943     proto_tree_add_item (tree, hf_error_value, tvb, offset, 2, ENC_BIG_ENDIAN);
944   } else {
945     proto_tree_add_item (tree, hf_value, tvb, offset, 2, ENC_BIG_ENDIAN);
946   }
947   offset += 2;
948
949   proto_tree_add_item (tree, hf_plen, tvb, offset, 4, ENC_BIG_ENDIAN);
950   offset += 4;
951
952
953   switch (msg_type) {
954   case RPCAP_MSG_ERROR:
955     dissect_rpcap_error (tvb, pinfo, tree, offset);
956     break;
957   case RPCAP_MSG_OPEN_REQ:
958     dissect_rpcap_open_request (tvb, pinfo, tree, offset);
959     break;
960   case RPCAP_MSG_STARTCAP_REQ:
961     dissect_rpcap_startcap_request (tvb, pinfo, tree, offset);
962     break;
963   case RPCAP_MSG_UPDATEFILTER_REQ:
964     dissect_rpcap_filter (tvb, pinfo, tree, offset);
965     break;
966   case RPCAP_MSG_PACKET:
967     proto_item_set_len (ti, 28);
968     dissect_rpcap_packet (tvb, pinfo, top_tree, tree, offset, ti);
969     break;
970   case RPCAP_MSG_AUTH_REQ:
971     dissect_rpcap_auth_request (tvb, pinfo, tree, offset);
972     break;
973   case RPCAP_MSG_SETSAMPLING_REQ:
974     dissect_rpcap_sampling_request (tvb, pinfo, tree, offset);
975     break;
976   case RPCAP_MSG_FINDALLIF_REPLY:
977     dissect_rpcap_findalldevs_reply (tvb, pinfo, tree, offset, msg_value);
978     break;
979   case RPCAP_MSG_OPEN_REPLY:
980     dissect_rpcap_open_reply (tvb, pinfo, tree, offset);
981     break;
982   case RPCAP_MSG_STARTCAP_REPLY:
983     dissect_rpcap_startcap_reply (tvb, pinfo, tree, offset);
984     break;
985   case RPCAP_MSG_STATS_REPLY:
986     dissect_rpcap_stats_reply (tvb, pinfo, tree, offset);
987     break;
988   default:
989     len = tvb_length_remaining (tvb, offset);
990     if (len) {
991       /* Yet unknown, dump as data */
992       proto_item_set_len (ti, 8);
993       new_tvb = tvb_new_subset (tvb, offset, len, len);
994       call_dissector (data_handle, new_tvb, pinfo, top_tree);
995     }
996     break;
997   }
998 }
999
1000
1001 static gboolean
1002 check_rpcap_heur (tvbuff_t *tvb, gboolean tcp)
1003 {
1004   gint offset = 0;
1005   guint8 version, msg_type;
1006   guint16 msg_value;
1007   guint32 plen, len, caplen;
1008
1009   if (tvb_length (tvb) < 8)
1010     /* Too short */
1011     return FALSE;
1012
1013   version = tvb_get_guint8 (tvb, offset);
1014   if (version != 0)
1015     /* Incorrect version */
1016     return FALSE;
1017   offset++;
1018
1019   msg_type = tvb_get_guint8 (tvb, offset);
1020   if (!tcp && msg_type != 7) {
1021     /* UDP is only used for packets */
1022     return FALSE;
1023   }
1024   if (match_strval(msg_type, message_type) == NULL)
1025     /* Unknown message type */
1026     return FALSE;
1027   offset++;
1028
1029   msg_value = tvb_get_ntohs (tvb, offset);
1030   if (msg_value > 0) {
1031     if (msg_type == RPCAP_MSG_ERROR) {
1032       /* Must have a valid error code */
1033       if (match_strval(msg_value, error_codes) == NULL)
1034         return FALSE;
1035     } else if (msg_type != RPCAP_MSG_FINDALLIF_REPLY) {
1036       return FALSE;
1037     }
1038   }
1039   offset += 2;
1040
1041   plen = tvb_get_ntohl (tvb, offset);
1042   offset += 4;
1043   len = (guint32) tvb_length_remaining (tvb, offset);
1044
1045   switch (msg_type) {
1046
1047   case RPCAP_MSG_FINDALLIF_REQ:
1048   case RPCAP_MSG_UPDATEFILTER_REPLY:
1049   case RPCAP_MSG_AUTH_REPLY:
1050   case RPCAP_MSG_STATS_REQ:
1051   case RPCAP_MSG_CLOSE:
1052   case RPCAP_MSG_SETSAMPLING_REPLY:
1053   case RPCAP_MSG_ENDCAP_REQ:
1054   case RPCAP_MSG_ENDCAP_REPLY:
1055     /* Empty payload */
1056     if (plen != 0 || len != 0)
1057       return FALSE;
1058     break;
1059
1060   case RPCAP_MSG_OPEN_REPLY:
1061   case RPCAP_MSG_STARTCAP_REPLY:
1062   case RPCAP_MSG_SETSAMPLING_REQ:
1063     /* Always 8 bytes */
1064     if (plen != 8 || len != 8)
1065       return FALSE;
1066     break;
1067
1068   case RPCAP_MSG_STATS_REPLY:
1069     /* Always 16 bytes */
1070     if (plen != 16 || len != 16)
1071       return FALSE;
1072     break;
1073
1074   case RPCAP_MSG_PACKET:
1075     /* Must have the frame header */
1076     if (plen < 20)
1077       return FALSE;
1078
1079     /* Check if capture length is valid */
1080     caplen = tvb_get_ntohl (tvb, offset+8);
1081     /* Always 20 bytes less than packet length */
1082     if (caplen != (plen - 20) || caplen > 65535)
1083       return FALSE;
1084     break;
1085
1086   case RPCAP_MSG_FINDALLIF_REPLY:
1087   case RPCAP_MSG_ERROR:
1088   case RPCAP_MSG_OPEN_REQ:
1089   case RPCAP_MSG_STARTCAP_REQ:
1090   case RPCAP_MSG_UPDATEFILTER_REQ:
1091   case RPCAP_MSG_AUTH_REQ:
1092     /* Variable length */
1093     if (plen != len)
1094       return FALSE;
1095     break;
1096   default:
1097     /* Unknown message type */
1098     return FALSE;
1099   }
1100
1101   return TRUE;
1102 }
1103
1104
1105 static guint
1106 get_rpcap_pdu_len (packet_info *pinfo _U_, tvbuff_t *tvb, int offset)
1107 {
1108   return tvb_get_ntohl (tvb, offset + 4) + 8;
1109 }
1110
1111
1112 static gboolean
1113 dissect_rpcap_heur_tcp (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1114 {
1115   if (check_rpcap_heur (tvb, TRUE)) {
1116     /* This is probably a rpcap tcp package */
1117     tcp_dissect_pdus (tvb, pinfo, tree, rpcap_desegment, 8,
1118                       get_rpcap_pdu_len, dissect_rpcap);
1119
1120     return TRUE;
1121   }
1122
1123   return FALSE;
1124 }
1125
1126
1127 static gboolean
1128 dissect_rpcap_heur_udp (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1129 {
1130   if (check_rpcap_heur (tvb, FALSE)) {
1131     /* This is probably a rpcap udp package */
1132     dissect_rpcap (tvb, pinfo, tree);
1133
1134     return TRUE;
1135   }
1136
1137   return FALSE;
1138 }
1139
1140
1141 void
1142 proto_register_rpcap (void)
1143 {
1144   static hf_register_info hf[] = {
1145     /* Common header for all messages */
1146     { &hf_version,
1147       { "Version", "rpcap.version", FT_UINT8, BASE_DEC,
1148         NULL, 0x0, NULL, HFILL } },
1149     { &hf_type,
1150       { "Message type", "rpcap.type", FT_UINT8, BASE_DEC,
1151         VALS(message_type), 0x0, NULL, HFILL } },
1152     { &hf_value,
1153       { "Message value", "rpcap.value", FT_UINT16, BASE_DEC,
1154         NULL, 0x0, NULL, HFILL } },
1155     { &hf_plen,
1156       { "Payload length", "rpcap.len", FT_UINT32, BASE_DEC,
1157         NULL, 0x0, NULL, HFILL } },
1158
1159     /* Error */
1160     { &hf_error,
1161       { "Error", "rpcap.error", FT_STRING, BASE_NONE,
1162         NULL, 0x0, "Error text", HFILL } },
1163     { &hf_error_value,
1164       { "Error value", "rpcap.error_value", FT_UINT16, BASE_DEC,
1165         VALS(error_codes), 0x0, NULL, HFILL } },
1166
1167     /* Packet header */
1168     { &hf_packet,
1169       { "Packet", "rpcap.packet", FT_NONE, BASE_NONE,
1170         NULL, 0x0, "Packet data", HFILL } },
1171     { &hf_timestamp,
1172       { "Arrival time", "rpcap.time", FT_ABSOLUTE_TIME, ABSOLUTE_TIME_LOCAL,
1173         NULL, 0x0, NULL, HFILL } },
1174     { &hf_caplen,
1175       { "Capture length", "rpcap.cap_len", FT_UINT32, BASE_DEC,
1176         NULL, 0x0, NULL, HFILL } },
1177     { &hf_len,
1178       { "Frame length", "rpcap.len", FT_UINT32, BASE_DEC,
1179         NULL, 0x0, "Frame length (off wire)", HFILL } },
1180     { &hf_npkt,
1181       { "Frame number", "rpcap.number", FT_UINT32, BASE_DEC,
1182         NULL, 0x0, NULL, HFILL } },
1183
1184     /* Authentication request */
1185     { &hf_auth_request,
1186       { "Authentication", "rpcap.auth", FT_NONE, BASE_NONE,
1187         NULL, 0x0, NULL, HFILL } },
1188     { &hf_auth_type,
1189       { "Authentication type", "rpcap.auth_type", FT_UINT16, BASE_DEC,
1190         VALS(auth_type), 0x0, NULL, HFILL } },
1191     { &hf_auth_slen1,
1192       { "Authentication item length 1", "rpcap.auth_len1", FT_UINT16, BASE_DEC,
1193         NULL, 0x0, NULL, HFILL } },
1194     { &hf_auth_slen2,
1195       { "Authentication item length 2", "rpcap.auth_len2", FT_UINT16, BASE_DEC,
1196         NULL, 0x0, NULL, HFILL } },
1197     { &hf_auth_username,
1198       { "Username", "rpcap.username", FT_STRING, BASE_NONE,
1199         NULL, 0x0, NULL, HFILL } },
1200     { &hf_auth_password,
1201       { "Password", "rpcap.password", FT_STRING, BASE_NONE,
1202         NULL, 0x0, NULL, HFILL } },
1203
1204     /* Open request */
1205     { &hf_open_request,
1206       { "Open request", "rpcap.open_request", FT_STRING, BASE_NONE,
1207         NULL, 0x0, NULL, HFILL } },
1208
1209     /* Open reply */
1210     { &hf_open_reply,
1211       { "Open reply", "rpcap.open_reply", FT_NONE, BASE_NONE,
1212         NULL, 0x0, NULL, HFILL } },
1213     { &hf_linktype,
1214       { "Link type", "rpcap.linktype", FT_UINT32, BASE_DEC,
1215         NULL, 0x0, NULL, HFILL } },
1216     { &hf_tzoff,
1217       { "Timezone offset", "rpcap.tzoff", FT_UINT32, BASE_DEC,
1218         NULL, 0x0, NULL, HFILL } },
1219
1220     /* Start capture request */
1221     { &hf_startcap_request,
1222       { "Start capture request", "rpcap.startcap_request", FT_NONE, BASE_NONE,
1223         NULL, 0x0, NULL, HFILL } },
1224     { &hf_snaplen,
1225       { "Snap length", "rpcap.snaplen", FT_UINT32, BASE_DEC,
1226         NULL, 0x0, NULL, HFILL } },
1227     { &hf_read_timeout,
1228       { "Read timeout", "rpcap.read_timeout", FT_UINT32, BASE_DEC,
1229         NULL, 0x0, NULL, HFILL } },
1230     { &hf_flags,
1231       { "Flags", "rpcap.flags", FT_UINT16, BASE_DEC,
1232         NULL, 0x0, "Capture flags", HFILL } },
1233     { &hf_flags_promisc,
1234       { "Promiscuous mode", "rpcap.flags.promisc", FT_BOOLEAN, 16,
1235         TFS(&tfs_enabled_disabled), FLAG_PROMISC, NULL, HFILL } },
1236     { &hf_flags_dgram,
1237       { "Use Datagram", "rpcap.flags.dgram", FT_BOOLEAN, 16,
1238         TFS(&tfs_yes_no), FLAG_DGRAM, NULL, HFILL } },
1239     { &hf_flags_serveropen,
1240       { "Server open", "rpcap.flags.serveropen", FT_BOOLEAN, 16,
1241         TFS(&open_closed), FLAG_SERVEROPEN, NULL, HFILL } },
1242     { &hf_flags_inbound,
1243       { "Inbound", "rpcap.flags.inbound", FT_BOOLEAN, 16,
1244         TFS(&tfs_yes_no), FLAG_INBOUND, NULL, HFILL } },
1245     { &hf_flags_outbound,
1246       { "Outbound", "rpcap.flags.outbound", FT_BOOLEAN, 16,
1247         TFS(&tfs_yes_no), FLAG_OUTBOUND, NULL, HFILL } },
1248     { &hf_client_port,
1249       { "Client Port", "rpcap.client_port", FT_UINT16, BASE_DEC,
1250         NULL, 0x0, NULL, HFILL } },
1251
1252     /* Start capture reply */
1253     { &hf_startcap_reply,
1254       { "Start capture reply", "rpcap.startcap_reply", FT_NONE, BASE_NONE,
1255         NULL, 0x0, NULL, HFILL } },
1256     { &hf_bufsize,
1257       { "Buffer size", "rpcap.bufsize", FT_UINT32, BASE_DEC,
1258         NULL, 0x0, NULL, HFILL } },
1259     { &hf_server_port,
1260       { "Server port", "rpcap.server_port", FT_UINT16, BASE_DEC,
1261         NULL, 0x0, NULL, HFILL } },
1262     { &hf_dummy,
1263       { "Dummy", "rpcap.dummy", FT_UINT16, BASE_DEC,
1264         NULL, 0x0, NULL, HFILL } },
1265
1266     /* Filter */
1267     { &hf_filter,
1268       { "Filter", "rpcap.filter", FT_NONE, BASE_NONE,
1269         NULL, 0x0, NULL, HFILL } },
1270     { &hf_filtertype,
1271       { "Filter type", "rpcap.filtertype", FT_UINT16, BASE_DEC,
1272         NULL, 0x0, "Filter type (BPF)", HFILL } },
1273     { &hf_nitems,
1274       { "Number of items", "rpcap.nitems", FT_UINT32, BASE_DEC,
1275         NULL, 0x0, NULL, HFILL } },
1276
1277     /* Filter BPF instruction */
1278     { &hf_filterbpf_insn,
1279       { "Filter BPF instruction", "rpcap.filterbpf_insn", FT_NONE, BASE_NONE,
1280         NULL, 0x0, NULL, HFILL } },
1281     { &hf_code,
1282       { "Op code", "rpcap.opcode", FT_UINT16, BASE_HEX,
1283         NULL, 0x0, "Operation code", HFILL } },
1284     { &hf_code_class,
1285       { "Class", "rpcap.opcode.class", FT_UINT16, BASE_HEX,
1286         VALS(bpf_class), 0x07, "Instruction Class", HFILL } },
1287     { &hf_code_fields,
1288       { "Fields", "rpcap.opcode.fields", FT_UINT16, BASE_HEX,
1289         NULL, 0xF8, "Class Fields", HFILL } },
1290     { &hf_code_ld_size,
1291       { "Size", "rpcap.opcode.size", FT_UINT16, BASE_HEX,
1292         VALS(bpf_size), 0x18, NULL, HFILL } },
1293     { &hf_code_ld_mode,
1294       { "Mode", "rpcap.opcode.mode", FT_UINT16, BASE_HEX,
1295         VALS(bpf_mode), 0xE0, NULL, HFILL } },
1296     { &hf_code_alu_op,
1297       { "Op", "rpcap.opcode.aluop", FT_UINT16, BASE_HEX,
1298         VALS(bpf_alu_op), 0xF0, NULL, HFILL } },
1299     { &hf_code_jmp_op,
1300       { "Op", "rpcap.opcode.jmpop", FT_UINT16, BASE_HEX,
1301         VALS(bpf_jmp_op), 0xF0, NULL, HFILL } },
1302     { &hf_code_src,
1303       { "Src", "rpcap.opcode.src", FT_UINT16, BASE_HEX,
1304         VALS(bpf_src), 0x08, NULL, HFILL } },
1305     { &hf_code_rval,
1306       { "Rval", "rpcap.opcode.rval", FT_UINT16, BASE_HEX,
1307         VALS(bpf_rval), 0x18, NULL, HFILL } },
1308     { &hf_code_misc_op,
1309       { "Op", "rpcap.opcode.miscop", FT_UINT16, BASE_HEX,
1310         VALS(bpf_misc_op), 0xF8, NULL, HFILL } },
1311     { &hf_jt,
1312       { "JT", "rpcap.jt", FT_UINT8, BASE_DEC,
1313         NULL, 0x0, NULL, HFILL } },
1314     { &hf_jf,
1315       { "JF", "rpcap.jf", FT_UINT8, BASE_DEC,
1316         NULL, 0x0, NULL, HFILL } },
1317     { &hf_instr_value,
1318       { "Instruction value", "rpcap.instr_value", FT_UINT32, BASE_DEC,
1319         NULL, 0x0, "Instruction-Dependent value", HFILL } },
1320
1321     /* Statistics reply */
1322     { &hf_stats_reply,
1323       { "Statistics", "rpcap.stats_reply", FT_NONE, BASE_NONE,
1324         NULL, 0x0, "Statistics reply data", HFILL } },
1325     { &hf_ifrecv,
1326       { "Received by kernel filter", "rpcap.ifrecv", FT_UINT32, BASE_DEC,
1327         NULL, 0x0, "Received by kernel", HFILL } },
1328     { &hf_ifdrop,
1329       { "Dropped by network interface", "rpcap.ifdrop", FT_UINT32, BASE_DEC,
1330         NULL, 0x0, NULL, HFILL } },
1331     { &hf_krnldrop,
1332       { "Dropped by kernel filter", "rpcap.krnldrop", FT_UINT32, BASE_DEC,
1333         NULL, 0x0, NULL, HFILL } },
1334     { &hf_srvcapt,
1335       { "Captured by rpcapd", "rpcap.srvcapt", FT_UINT32, BASE_DEC,
1336         NULL, 0x0, "Captured by RPCAP daemon", HFILL } },
1337
1338     /* Find all devices reply */
1339     { &hf_findalldevs_reply,
1340       { "Find all devices", "rpcap.findalldevs_reply", FT_NONE, BASE_NONE,
1341         NULL, 0x0, NULL, HFILL } },
1342     { &hf_findalldevs_if,
1343       { "Interface", "rpcap.if", FT_NONE, BASE_NONE,
1344         NULL, 0x0, NULL, HFILL } },
1345     { &hf_namelen,
1346       { "Name length", "rpcap.namelen", FT_UINT16, BASE_DEC,
1347         NULL, 0x0, NULL, HFILL } },
1348     { &hf_desclen,
1349       { "Description length", "rpcap.desclen", FT_UINT32, BASE_DEC,
1350         NULL, 0x0, NULL, HFILL } },
1351     { &hf_if_flags,
1352       { "Interface flags", "rpcap.if.flags", FT_UINT32, BASE_DEC,
1353         NULL, 0x0, NULL, HFILL } },
1354     { &hf_naddr,
1355       { "Number of addresses", "rpcap.naddr", FT_UINT32, BASE_DEC,
1356         NULL, 0x0, NULL, HFILL } },
1357     { &hf_if_name,
1358       { "Name", "rpcap.ifname", FT_STRING, BASE_NONE,
1359         NULL, 0x0, "Interface name", HFILL } },
1360     { &hf_if_desc,
1361       { "Description", "rpcap.ifdesc", FT_STRING, BASE_NONE,
1362         NULL, 0x0, "Interface description", HFILL } },
1363
1364     /* Find all devices / Interface addresses */
1365     { &hf_findalldevs_ifaddr,
1366       { "Interface address", "rpcap.ifaddr", FT_NONE, BASE_NONE,
1367         NULL, 0x0, NULL, HFILL } },
1368     { &hf_if_addr,
1369       { "Address", "rpcap.addr", FT_NONE, BASE_NONE,
1370         NULL, 0x0, "Network address", HFILL } },
1371     { &hf_if_netmask,
1372       { "Netmask", "rpcap.netmask", FT_NONE, BASE_NONE,
1373         NULL, 0x0, NULL, HFILL } },
1374     { &hf_if_broadaddr,
1375       { "Broadcast", "rpcap.broadaddr", FT_NONE, BASE_NONE,
1376         NULL, 0x0, NULL, HFILL } },
1377     { &hf_if_dstaddr,
1378       { "P2P destination address", "rpcap.dstaddr", FT_NONE, BASE_NONE,
1379         NULL, 0x0, NULL, HFILL } },
1380     { &hf_if_af,
1381       { "Address family", "rpcap.if.af", FT_UINT16, BASE_HEX,
1382         VALS(address_family), 0x0, NULL, HFILL } },
1383     { &hf_if_port,
1384       { "Port", "rpcap.if.port", FT_UINT16, BASE_DEC,
1385         NULL, 0x0, "Port number", HFILL } },
1386     { &hf_if_ip,
1387       { "IP address", "rpcap.if.ip", FT_IPv4, BASE_NONE,
1388         NULL, 0x0, NULL, HFILL } },
1389     { &hf_if_padding,
1390       { "Padding", "rpcap.if.padding", FT_BYTES, BASE_NONE,
1391         NULL, 0x0, NULL, HFILL } },
1392     { &hf_if_unknown,
1393       { "Unknown address", "rpcap.if.unknown", FT_BYTES, BASE_NONE,
1394         NULL, 0x0, NULL, HFILL } },
1395
1396     /* Sampling request */
1397     { &hf_sampling_request,
1398       { "Sampling", "rpcap.sampling_request", FT_NONE, BASE_NONE,
1399         NULL, 0x0, NULL, HFILL } },
1400     { &hf_sampling_method,
1401       { "Method", "rpcap.sampling_method", FT_UINT8, BASE_DEC,
1402         VALS(sampling_method), 0x0, "Sampling method", HFILL } },
1403     { &hf_sampling_dummy1,
1404       { "Dummy1", "rpcap.dummy", FT_UINT8, BASE_DEC,
1405         NULL, 0x0, NULL, HFILL } },
1406     { &hf_sampling_dummy2,
1407       { "Dummy2", "rpcap.dummy", FT_UINT16, BASE_DEC,
1408         NULL, 0x0, NULL, HFILL } },
1409     { &hf_sampling_value,
1410       { "Value", "rpcap.sampling_value", FT_UINT32, BASE_DEC,
1411         NULL, 0x0, NULL, HFILL } },
1412   };
1413
1414   static gint *ett[] = {
1415     &ett_rpcap,
1416     &ett_error,
1417     &ett_packet,
1418     &ett_auth_request,
1419     &ett_open_reply,
1420     &ett_startcap_request,
1421     &ett_startcap_reply,
1422     &ett_startcap_flags,
1423     &ett_filter,
1424     &ett_filterbpf_insn,
1425     &ett_filterbpf_insn_code,
1426     &ett_stats_reply,
1427     &ett_findalldevs_reply,
1428     &ett_findalldevs_if,
1429     &ett_findalldevs_ifaddr,
1430     &ett_ifaddr,
1431     &ett_sampling_request
1432   };
1433
1434   module_t *rpcap_module;
1435
1436   proto_rpcap = proto_register_protocol (PNAME, PSNAME, PFNAME);
1437   register_dissector (PFNAME, dissect_rpcap, proto_rpcap);
1438
1439   proto_register_field_array (proto_rpcap, hf, array_length (hf));
1440   proto_register_subtree_array (ett, array_length (ett));
1441
1442   /* Register our configuration options */
1443   rpcap_module = prefs_register_protocol (proto_rpcap, proto_reg_handoff_rpcap);
1444
1445   prefs_register_bool_preference (rpcap_module, "desegment_pdus",
1446                                   "Reassemble PDUs spanning multiple TCP segments",
1447                                   "Whether the RPCAP dissector should reassemble PDUs"
1448                                   " spanning multiple TCP segments."
1449                                   " To use this option, you must also enable \"Allow subdissectors"
1450                                   " to reassemble TCP streams\" in the TCP protocol settings.",
1451                                   &rpcap_desegment);
1452   prefs_register_bool_preference (rpcap_module, "decode_content",
1453                                   "Decode content according to link-layer type",
1454                                   "Whether the packets should be decoded according to"
1455                                   " the link-layer type.",
1456                                   &decode_content);
1457   prefs_register_uint_preference (rpcap_module, "linktype",
1458                                   "Default link-layer type",
1459                                   "Default link-layer type to use if an Open Reply packet"
1460                                   " has not been received.",
1461                                   10, &global_linktype);
1462 }
1463
1464 void
1465 proto_reg_handoff_rpcap (void)
1466 {
1467   static gboolean rpcap_prefs_initialized = FALSE;
1468
1469   if (!rpcap_prefs_initialized) {
1470     data_handle = find_dissector ("data");
1471     rpcap_prefs_initialized = TRUE;
1472
1473     heur_dissector_add ("tcp", dissect_rpcap_heur_tcp, proto_rpcap);
1474     heur_dissector_add ("udp", dissect_rpcap_heur_udp, proto_rpcap);
1475   }
1476
1477   info_added = FALSE;
1478   linktype = global_linktype;
1479 }
1480
1481 /*
1482  * Editor modelines
1483  *
1484  * Local Variables:
1485  * c-basic-offset: 2
1486  * tab-width: 8
1487  * indent-tabs-mode: t
1488  * End:
1489  *
1490  * ex: set shiftwidth=2 tabstop=8 noexpandtab:
1491  * :indentSize=2:tabSize=8:noTabs=false:
1492  */