357e58938e8fc0ee0f00cd2005daf6ea74ec0f99
[obnox/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., 59 Temple Place - Suite 330, Boston, MA  02111-1307, 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_jt = -1;
163 static int hf_jf = -1;
164 static int hf_instr_value = -1;
165
166 static int hf_stats_reply = -1;
167 static int hf_ifrecv = -1;
168 static int hf_ifdrop = -1;
169 static int hf_krnldrop = -1;
170 static int hf_srvcapt = -1;
171
172 static int hf_findalldevs_reply = -1;
173 static int hf_findalldevs_if = -1;
174 static int hf_namelen = -1;
175 static int hf_desclen = -1;
176 static int hf_if_flags = -1;
177 static int hf_naddr = -1;
178 static int hf_if_name = -1;
179 static int hf_if_desc = -1;
180
181 static int hf_findalldevs_ifaddr = -1;
182 static int hf_if_addr = -1;
183 static int hf_if_netmask = -1;
184 static int hf_if_broadaddr = -1;
185 static int hf_if_dstaddr = -1;
186 static int hf_if_af = -1;
187 static int hf_if_port = -1;
188 static int hf_if_ip = -1;
189 static int hf_if_padding = -1;
190 static int hf_if_unknown = -1;
191
192 static int hf_sampling_request = -1;
193 static int hf_sampling_method = -1;
194 static int hf_sampling_dummy1 = -1;
195 static int hf_sampling_dummy2 = -1;
196 static int hf_sampling_value = -1;
197
198 static gint ett_rpcap = -1;
199 static gint ett_error = -1;
200 static gint ett_packet = -1;
201 static gint ett_auth_request = -1;
202 static gint ett_open_reply = -1;
203 static gint ett_startcap_request = -1;
204 static gint ett_startcap_reply = -1;
205 static gint ett_startcap_flags = -1;
206 static gint ett_filter = -1;
207 static gint ett_filterbpf_insn = -1;
208 static gint ett_stats_reply = -1;
209 static gint ett_findalldevs_reply = -1;
210 static gint ett_findalldevs_if = -1;
211 static gint ett_findalldevs_ifaddr = -1;
212 static gint ett_ifaddr = -1;
213 static gint ett_sampling_request = -1;
214
215 static dissector_handle_t data_handle;
216
217 /* User definable values */
218 static gboolean rpcap_desegment = TRUE;
219 static gboolean decode_content = TRUE;
220 static guint32 global_linktype = WTAP_ENCAP_UNKNOWN;
221
222 /* Global variables */
223 static guint32 linktype = WTAP_ENCAP_UNKNOWN;
224 static gboolean info_added = FALSE;
225
226 static const true_false_string open_closed = {
227   "Open", "Closed"
228 };
229
230 static const value_string message_type[] = {
231   { RPCAP_MSG_ERROR,              "Error"                       },
232   { RPCAP_MSG_FINDALLIF_REQ,      "Find all interfaces request" },
233   { RPCAP_MSG_OPEN_REQ,           "Open request"                },
234   { RPCAP_MSG_STARTCAP_REQ,       "Start capture request"       },
235   { RPCAP_MSG_UPDATEFILTER_REQ,   "Update filter request"       },
236   { RPCAP_MSG_CLOSE,              "Close"                       },
237   { RPCAP_MSG_PACKET,             "Packet"                      },
238   { RPCAP_MSG_AUTH_REQ,           "Authentication request"      },
239   { RPCAP_MSG_STATS_REQ,          "Statistics request"          },
240   { RPCAP_MSG_ENDCAP_REQ,         "End capture request"         },
241   { RPCAP_MSG_SETSAMPLING_REQ,    "Set sampling request"        },
242   { RPCAP_MSG_FINDALLIF_REPLY,    "Find all interfaces reply"   },
243   { RPCAP_MSG_OPEN_REPLY,         "Open reply"                  },
244   { RPCAP_MSG_STARTCAP_REPLY,     "Start capture reply"         },
245   { RPCAP_MSG_UPDATEFILTER_REPLY, "Update filter reply"         },
246   { RPCAP_MSG_AUTH_REPLY,         "Authentication reply"        },
247   { RPCAP_MSG_STATS_REPLY,        "Statistics reply"            },
248   { RPCAP_MSG_ENDCAP_REPLY,       "End capture reply"           },
249   { RPCAP_MSG_SETSAMPLING_REPLY,  "Set sampling reply"          },
250   { 0,   NULL }
251 };
252
253 static const value_string error_codes[] = {
254   { RPCAP_ERR_NETW,            "Network error"                        },
255   { RPCAP_ERR_INITTIMEOUT,     "Initial timeout has expired"          },
256   { RPCAP_ERR_AUTH,            "Authentication error"                 },
257   { RPCAP_ERR_FINDALLIF,       "Generic findalldevs error"            },
258   { RPCAP_ERR_NOREMOTEIF,      "No remote interfaces"                 },
259   { RPCAP_ERR_OPEN,            "Generic pcap_open error"              },
260   { RPCAP_ERR_UPDATEFILTER,    "Generic updatefilter error"           },
261   { RPCAP_ERR_GETSTATS,        "Generic pcap_stats error"             },
262   { RPCAP_ERR_READEX,          "Generic pcap_next_ex error"           },
263   { RPCAP_ERR_HOSTNOAUTH,      "The host is not authorized"           },
264   { RPCAP_ERR_REMOTEACCEPT,    "Generic pcap_remoteaccept error"      },
265   { RPCAP_ERR_STARTCAPTURE,    "Generic pcap_startcapture error"      },
266   { RPCAP_ERR_ENDCAPTURE,      "Generic pcap_endcapture error"        },
267   { RPCAP_ERR_RUNTIMETIMEOUT,  "Runtime timeout has expired"          },
268   { RPCAP_ERR_SETSAMPLING,     "Error in setting sampling parameters" },
269   { RPCAP_ERR_WRONGMSG,        "Unrecognized message"                 },
270   { RPCAP_ERR_WRONGVER,        "Incompatible version"                 },
271   { 0,   NULL }
272 };
273
274 static const value_string sampling_method[] = {
275   { RPCAP_SAMP_NOSAMP,            "No sampling"      },
276   { RPCAP_SAMP_1_EVERY_N,         "1 every N"        },
277   { RPCAP_SAMP_FIRST_AFTER_N_MS,  "First after N ms" },
278   { 0,   NULL }
279 };
280
281 static const value_string auth_type[] = {
282   { RPCAP_RMTAUTH_NULL, "None"     },
283   { RPCAP_RMTAUTH_PWD,  "Password" },
284   { 0,   NULL }
285 };
286
287 static const value_string address_family[] = {
288   { AF_UNSPEC, "AF_UNSPEC" },
289   { AF_INET,   "AF_INET"   },
290   { 0,   NULL }
291 };
292
293
294 static void rpcap_frame_end (void)
295 {
296   info_added = FALSE;
297 }
298
299
300 static void
301 dissect_rpcap_error (tvbuff_t *tvb, packet_info *pinfo,
302                      proto_tree *parent_tree, gint offset)
303 {
304   proto_item *ti;
305   gint len;
306
307   len = tvb_length_remaining (tvb, offset);
308
309   if (check_col (pinfo->cinfo, COL_INFO)) {
310     col_append_fstr (pinfo->cinfo, COL_INFO, ": %s",
311                      tvb_format_text_wsp (tvb, offset, len));
312   }
313
314   ti = proto_tree_add_item (parent_tree, hf_error, tvb, offset, len, ENC_BIG_ENDIAN);
315   expert_add_info_format (pinfo, ti, PI_SEQUENCE, PI_NOTE,
316                           "Error: %s", tvb_format_text_wsp (tvb, offset, len));
317 }
318
319
320 static gint
321 dissect_rpcap_ifaddr (tvbuff_t *tvb, packet_info *pinfo,
322                       proto_tree *parent_tree, gint offset, int hf_id,
323                       proto_item *parent_item)
324 {
325   proto_tree *tree;
326   proto_item *ti;
327   gchar ipaddr[MAX_ADDR_STR_LEN];
328   guint32 ipv4;
329   guint16 af;
330
331   ti = proto_tree_add_item (parent_tree, hf_id, tvb, offset, 128, ENC_BIG_ENDIAN);
332   tree = proto_item_add_subtree (ti, ett_ifaddr);
333
334   af = tvb_get_ntohs (tvb, offset);
335   proto_tree_add_item (tree, hf_if_af, tvb, offset, 2, ENC_BIG_ENDIAN);
336   offset += 2;
337
338   if (af == AF_INET) {
339     proto_tree_add_item (tree, hf_if_port, tvb, offset, 2, ENC_BIG_ENDIAN);
340     offset += 2;
341
342     ipv4 = tvb_get_ipv4 (tvb, offset);
343     ip_to_str_buf((guint8 *)&ipv4, ipaddr, MAX_ADDR_STR_LEN);
344     proto_item_append_text (ti, ": %s", ipaddr);
345     if (parent_item) {
346       proto_item_append_text (parent_item, ": %s", ipaddr);
347     }
348     proto_tree_add_item (tree, hf_if_ip, tvb, offset, 4, ENC_BIG_ENDIAN);
349     offset += 4;
350
351     proto_tree_add_item (tree, hf_if_padding, tvb, offset, 120, ENC_BIG_ENDIAN);
352     offset += 120;
353   } else {
354     ti = proto_tree_add_item (tree, hf_if_unknown, tvb, offset, 126, ENC_BIG_ENDIAN);
355     if (af != AF_UNSPEC) {
356       expert_add_info_format (pinfo, ti, PI_UNDECODED, PI_CHAT,
357                               "Unknown address family: %d", af);
358     }
359     offset += 126;
360   }
361
362   return offset;
363 }
364
365
366 static gint
367 dissect_rpcap_findalldevs_ifaddr (tvbuff_t *tvb, packet_info *pinfo _U_,
368                                   proto_tree *parent_tree, gint offset)
369 {
370   proto_tree *tree;
371   proto_item *ti;
372   gint boffset = offset;
373
374   ti = proto_tree_add_item (parent_tree, hf_findalldevs_ifaddr, tvb, offset, -1, ENC_NA);
375   tree = proto_item_add_subtree (ti, ett_findalldevs_ifaddr);
376
377   offset = dissect_rpcap_ifaddr (tvb, pinfo, tree, offset, hf_if_addr, ti);
378   offset = dissect_rpcap_ifaddr (tvb, pinfo, tree, offset, hf_if_netmask, NULL);
379   offset = dissect_rpcap_ifaddr (tvb, pinfo, tree, offset, hf_if_broadaddr, NULL);
380   offset = dissect_rpcap_ifaddr (tvb, pinfo, tree, offset, hf_if_dstaddr, NULL);
381
382   proto_item_set_len (ti, offset - boffset);
383
384   return offset;
385 }
386
387
388 static gint
389 dissect_rpcap_findalldevs_if (tvbuff_t *tvb, packet_info *pinfo _U_,
390                               proto_tree *parent_tree, gint offset)
391 {
392   proto_tree *tree;
393   proto_item *ti;
394   guint16 namelen, desclen, naddr, i;
395   gint boffset = offset;
396
397   ti = proto_tree_add_item (parent_tree, hf_findalldevs_if, tvb, offset, -1, ENC_NA);
398   tree = proto_item_add_subtree (ti, ett_findalldevs_if);
399
400   namelen = tvb_get_ntohs (tvb, offset);
401   proto_tree_add_item (tree, hf_namelen, tvb, offset, 2, ENC_BIG_ENDIAN);
402   offset += 2;
403
404   desclen = tvb_get_ntohs (tvb, offset);
405   proto_tree_add_item (tree, hf_desclen, tvb, offset, 2, ENC_BIG_ENDIAN);
406   offset += 2;
407
408   proto_tree_add_item (tree, hf_if_flags, tvb, offset, 4, ENC_BIG_ENDIAN);
409   offset += 4;
410
411   naddr = tvb_get_ntohs (tvb, offset);
412   proto_tree_add_item (tree, hf_naddr, tvb, offset, 2, ENC_BIG_ENDIAN);
413   offset += 2;
414
415   proto_tree_add_item (tree, hf_dummy, tvb, offset, 2, ENC_BIG_ENDIAN);
416   offset += 2;
417
418   if (namelen) {
419     proto_item_append_text (ti, ": %s", tvb_get_ephemeral_string (tvb, offset, namelen));
420     proto_tree_add_item (tree, hf_if_name, tvb, offset, namelen, ENC_BIG_ENDIAN);
421     offset += namelen;
422   }
423
424   if (desclen) {
425     proto_tree_add_item (tree, hf_if_desc, tvb, offset, desclen, ENC_BIG_ENDIAN);
426     offset += desclen;
427   }
428
429   for (i = 0; i < naddr; i++) {
430     offset = dissect_rpcap_findalldevs_ifaddr (tvb, pinfo, tree, offset);
431     if (tvb_length_remaining (tvb, offset) <= 0) {
432       /* No more data in packet */
433       expert_add_info_format (pinfo, ti, PI_MALFORMED, PI_ERROR, "No more data in packet");
434       break;
435     }
436   }
437
438   proto_item_set_len (ti, offset - boffset);
439
440   return offset;
441 }
442
443
444 static void
445 dissect_rpcap_findalldevs_reply (tvbuff_t *tvb, packet_info *pinfo _U_,
446                                  proto_tree *parent_tree, gint offset, guint16 no_devs)
447 {
448   proto_tree *tree;
449   proto_item *ti;
450   guint16 i;
451
452   ti = proto_tree_add_item (parent_tree, hf_findalldevs_reply, tvb, offset, -1, ENC_NA);
453   tree = proto_item_add_subtree (ti, ett_findalldevs_reply);
454
455   for (i = 0; i < no_devs; i++) {
456     offset = dissect_rpcap_findalldevs_if (tvb, pinfo, tree, offset);
457     if (tvb_length_remaining (tvb, offset) <= 0) {
458       /* No more data in packet */
459       expert_add_info_format (pinfo, ti, PI_MALFORMED, PI_ERROR, "No more data in packet");
460       break;
461     }
462   }
463
464   proto_item_append_text (ti, ", %d item%s", no_devs, plurality (no_devs, "", "s"));
465 }
466
467
468 static gint
469 dissect_rpcap_filterbpf_insn (tvbuff_t *tvb, packet_info *pinfo _U_,
470                               proto_tree *parent_tree, gint offset)
471 {
472   proto_tree *tree;
473   proto_item *ti;
474
475   ti = proto_tree_add_item (parent_tree, hf_filterbpf_insn, tvb, offset, 8, ENC_NA);
476   tree = proto_item_add_subtree (ti, ett_filterbpf_insn);
477
478   proto_tree_add_item (tree, hf_code, tvb, offset, 2, ENC_BIG_ENDIAN);
479   offset += 2;
480
481   proto_tree_add_item (tree, hf_jt, tvb, offset, 1, ENC_BIG_ENDIAN);
482   offset += 1;
483
484   proto_tree_add_item (tree, hf_jf, tvb, offset, 1, ENC_BIG_ENDIAN);
485   offset += 1;
486
487   proto_tree_add_item (tree, hf_instr_value, tvb, offset, 4, ENC_BIG_ENDIAN);
488   offset += 4;
489
490   return offset;
491 }
492
493
494 static void
495 dissect_rpcap_filter (tvbuff_t *tvb, packet_info *pinfo,
496                       proto_tree *parent_tree, gint offset)
497 {
498   proto_tree *tree;
499   proto_item *ti;
500   guint32 nitems, i;
501
502   ti = proto_tree_add_item (parent_tree, hf_filter, tvb, offset, -1, ENC_NA);
503   tree = proto_item_add_subtree (ti, ett_filter);
504
505   proto_tree_add_item (tree, hf_filtertype, tvb, offset, 2, ENC_BIG_ENDIAN);
506   offset += 2;
507
508   proto_tree_add_item (tree, hf_dummy, tvb, offset, 2, ENC_BIG_ENDIAN);
509   offset += 2;
510
511   nitems = tvb_get_ntohl (tvb, offset);
512   proto_tree_add_item (tree, hf_nitems, tvb, offset, 4, ENC_BIG_ENDIAN);
513   offset += 4;
514
515   for (i = 0; i < nitems; i++) {
516     offset = dissect_rpcap_filterbpf_insn (tvb, pinfo, tree, offset);
517     if (tvb_length_remaining (tvb, offset) <= 0) {
518       /* No more data in packet */
519       expert_add_info_format (pinfo, ti, PI_MALFORMED, PI_ERROR, "No more data in packet");
520       break;
521     }
522   }
523 }
524
525
526 static void
527 dissect_rpcap_auth_request (tvbuff_t *tvb, packet_info *pinfo _U_,
528                             proto_tree *parent_tree, gint offset)
529 {
530   proto_tree *tree;
531   proto_item *ti;
532   guint16 type, slen1, slen2;
533
534   ti = proto_tree_add_item (parent_tree, hf_auth_request, tvb, offset, -1, ENC_NA);
535   tree = proto_item_add_subtree (ti, ett_auth_request);
536
537   type = tvb_get_ntohs (tvb, offset);
538   proto_tree_add_item (tree, hf_auth_type, tvb, offset, 2, ENC_BIG_ENDIAN);
539   offset += 2;
540
541   proto_tree_add_item (tree, hf_dummy, tvb, offset, 2, ENC_BIG_ENDIAN);
542   offset += 2;
543
544   slen1 = tvb_get_ntohs (tvb, offset);
545   proto_tree_add_item (tree, hf_auth_slen1, tvb, offset, 2, ENC_BIG_ENDIAN);
546   offset += 2;
547
548   slen2 = tvb_get_ntohs (tvb, offset);
549   proto_tree_add_item (tree, hf_auth_slen2, tvb, offset, 2, ENC_BIG_ENDIAN);
550   offset += 2;
551
552   if (type == RPCAP_RMTAUTH_NULL) {
553     proto_item_append_text (ti, " (none)");
554   } else if (type == RPCAP_RMTAUTH_PWD) {
555     guint8 *username, *password;
556
557     username = tvb_get_ephemeral_string (tvb, offset, slen1);
558     proto_tree_add_item (tree, hf_auth_username, tvb, offset, slen1, ENC_BIG_ENDIAN);
559     offset += slen1;
560
561     password = tvb_get_ephemeral_string (tvb, offset, slen2);
562     proto_tree_add_item (tree, hf_auth_password, tvb, offset, slen2, ENC_BIG_ENDIAN);
563     offset += slen2;
564
565     proto_item_append_text (ti, " (%s/%s)", username, password);
566   }
567 }
568
569
570 static void
571 dissect_rpcap_open_request (tvbuff_t *tvb, packet_info *pinfo _U_,
572                             proto_tree *parent_tree, gint offset)
573 {
574   gint len;
575
576   len = tvb_length_remaining (tvb, offset);
577   proto_tree_add_item (parent_tree, hf_open_request, tvb, offset, len, ENC_BIG_ENDIAN);
578 }
579
580
581 static void
582 dissect_rpcap_open_reply (tvbuff_t *tvb, packet_info *pinfo _U_,
583                           proto_tree *parent_tree, gint offset)
584 {
585   proto_tree *tree;
586   proto_item *ti;
587
588   ti = proto_tree_add_item (parent_tree, hf_open_reply, tvb, offset, -1, ENC_NA);
589   tree = proto_item_add_subtree (ti, ett_open_reply);
590
591   linktype = tvb_get_ntohl (tvb, offset);
592   proto_tree_add_item (tree, hf_linktype, tvb, offset, 4, ENC_BIG_ENDIAN);
593   offset += 4;
594
595   proto_tree_add_item (tree, hf_tzoff, tvb, offset, 4, ENC_BIG_ENDIAN);
596 }
597
598
599 static void
600 dissect_rpcap_startcap_request (tvbuff_t *tvb, packet_info *pinfo,
601                                 proto_tree *parent_tree, gint offset)
602 {
603   proto_tree *tree, *field_tree;
604   proto_item *ti, *field_ti;
605   guint16 flags;
606
607   ti = proto_tree_add_item (parent_tree, hf_startcap_request, tvb, offset, -1, ENC_NA);
608   tree = proto_item_add_subtree (ti, ett_startcap_request);
609
610   proto_tree_add_item (tree, hf_snaplen, tvb, offset, 4, ENC_BIG_ENDIAN);
611   offset += 4;
612
613   proto_tree_add_item (tree, hf_read_timeout, tvb, offset, 4, ENC_BIG_ENDIAN);
614   offset += 4;
615
616   flags = tvb_get_ntohs (tvb, offset);
617   field_ti = proto_tree_add_uint_format (tree, hf_flags, tvb, offset, 2, flags, "Flags");
618   field_tree = proto_item_add_subtree (field_ti, ett_startcap_flags);
619   proto_tree_add_item (field_tree, hf_flags_promisc, tvb, offset, 2, ENC_BIG_ENDIAN);
620   proto_tree_add_item (field_tree, hf_flags_dgram, tvb, offset, 2, ENC_BIG_ENDIAN);
621   proto_tree_add_item (field_tree, hf_flags_serveropen, tvb, offset, 2, ENC_BIG_ENDIAN);
622   proto_tree_add_item (field_tree, hf_flags_inbound, tvb, offset, 2, ENC_BIG_ENDIAN);
623   proto_tree_add_item (field_tree, hf_flags_outbound, tvb, offset, 2, ENC_BIG_ENDIAN);
624
625   if (flags & 0x1F) {
626     gchar *flagstr = g_strdup_printf ("%s%s%s%s%s",
627           (flags & FLAG_PROMISC)    ? ", Promiscuous" : "",
628           (flags & FLAG_DGRAM)      ? ", Datagram"    : "",
629           (flags & FLAG_SERVEROPEN) ? ", ServerOpen"  : "",
630           (flags & FLAG_INBOUND)    ? ", Inbound"     : "",
631           (flags & FLAG_OUTBOUND)   ? ", Outbound"    : "");
632     proto_item_append_text (field_ti, ":%s", &flagstr[1]);
633     g_free (flagstr);
634   } else {
635     proto_item_append_text (field_ti, " (none)");
636   }
637   offset += 2;
638
639   proto_tree_add_item (tree, hf_client_port, tvb, offset, 2, ENC_BIG_ENDIAN);
640   offset += 2;
641
642   dissect_rpcap_filter (tvb, pinfo, tree, offset);
643 }
644
645
646 static void
647 dissect_rpcap_startcap_reply (tvbuff_t *tvb, packet_info *pinfo _U_,
648                               proto_tree *parent_tree, gint offset)
649 {
650   proto_tree *tree;
651   proto_item *ti;
652
653   ti = proto_tree_add_item (parent_tree, hf_startcap_reply, tvb, offset, -1, ENC_NA);
654   tree = proto_item_add_subtree (ti, ett_startcap_reply);
655
656   proto_tree_add_item (tree, hf_bufsize, tvb, offset, 4, ENC_BIG_ENDIAN);
657   offset += 4;
658
659   proto_tree_add_item (tree, hf_server_port, tvb, offset, 2, ENC_BIG_ENDIAN);
660   offset += 2;
661
662   proto_tree_add_item (tree, hf_dummy, tvb, offset, 2, ENC_BIG_ENDIAN);
663 }
664
665
666 static void
667 dissect_rpcap_stats_reply (tvbuff_t *tvb, packet_info *pinfo _U_,
668                            proto_tree *parent_tree, gint offset)
669 {
670   proto_tree *tree;
671   proto_item *ti;
672
673   ti = proto_tree_add_item (parent_tree, hf_stats_reply, tvb, offset, 16, ENC_NA);
674   tree = proto_item_add_subtree (ti, ett_stats_reply);
675
676   proto_tree_add_item (tree, hf_ifrecv, tvb, offset, 4, ENC_BIG_ENDIAN);
677   offset += 4;
678
679   proto_tree_add_item (tree, hf_ifdrop, tvb, offset, 4, ENC_BIG_ENDIAN);
680   offset += 4;
681
682   proto_tree_add_item (tree, hf_krnldrop, tvb, offset, 4, ENC_BIG_ENDIAN);
683   offset += 4;
684
685   proto_tree_add_item (tree, hf_srvcapt, tvb, offset, 4, ENC_BIG_ENDIAN);
686 }
687
688
689 static void
690 dissect_rpcap_sampling_request (tvbuff_t *tvb, packet_info *pinfo _U_,
691                                 proto_tree *parent_tree, gint offset)
692 {
693   proto_tree *tree;
694   proto_item *ti;
695   guint32 value;
696   guint8 method;
697
698   ti = proto_tree_add_item (parent_tree, hf_sampling_request, tvb, offset, -1, ENC_NA);
699   tree = proto_item_add_subtree (ti, ett_sampling_request);
700
701   method = tvb_get_guint8 (tvb, offset);
702   proto_tree_add_item (tree, hf_sampling_method, tvb, offset, 1, ENC_BIG_ENDIAN);
703   offset += 1;
704
705   proto_tree_add_item (tree, hf_sampling_dummy1, tvb, offset, 1, ENC_BIG_ENDIAN);
706   offset += 1;
707
708   proto_tree_add_item (tree, hf_sampling_dummy2, tvb, offset, 2, ENC_BIG_ENDIAN);
709   offset += 2;
710
711   value = tvb_get_ntohl (tvb, offset);
712   proto_tree_add_item (tree, hf_sampling_value, tvb, offset, 4, ENC_BIG_ENDIAN);
713   offset += 4;
714
715   switch (method) {
716   case RPCAP_SAMP_NOSAMP:
717     proto_item_append_text (ti, ": None");
718     break;
719   case RPCAP_SAMP_1_EVERY_N:
720     proto_item_append_text (ti, ": 1 every %d", value);
721     break;
722   case RPCAP_SAMP_FIRST_AFTER_N_MS:
723     proto_item_append_text (ti, ": First after %d ms", value);
724     break;
725   default:
726     break;
727   }
728 }
729
730
731 static void
732 dissect_rpcap_packet (tvbuff_t *tvb, packet_info *pinfo, proto_tree *top_tree,
733                       proto_tree *parent_tree, gint offset, proto_item *top_item)
734 {
735   proto_tree *tree;
736   proto_item *ti;
737   nstime_t ts;
738   tvbuff_t *new_tvb;
739   guint caplen, len, frame_no;
740   gint reported_length_remaining;
741
742   ti = proto_tree_add_item (parent_tree, hf_packet, tvb, offset, 20, ENC_NA);
743   tree = proto_item_add_subtree (ti, ett_packet);
744
745   ts.secs = tvb_get_ntohl (tvb, offset);
746   ts.nsecs = tvb_get_ntohl (tvb, offset + 4) * 1000;
747   proto_tree_add_time(tree, hf_timestamp, tvb, offset, 8, &ts);
748   offset += 8;
749
750   caplen = tvb_get_ntohl (tvb, offset);
751   ti = proto_tree_add_item (tree, hf_caplen, tvb, offset, 4, ENC_BIG_ENDIAN);
752   offset += 4;
753
754   len = tvb_get_ntohl (tvb, offset);
755   proto_tree_add_item (tree, hf_len, tvb, offset, 4, ENC_BIG_ENDIAN);
756   offset += 4;
757
758   frame_no = tvb_get_ntohl (tvb, offset);
759   proto_tree_add_item (tree, hf_npkt, tvb, offset, 4, ENC_BIG_ENDIAN);
760   offset += 4;
761
762   proto_item_append_text (ti, ", Frame %u", frame_no);
763   proto_item_append_text (top_item, " Frame %u", frame_no);
764
765   /*
766    * reported_length_remaining should not be -1, as offset is at
767    * most right past the end of the available data in the packet.
768    */
769   reported_length_remaining = tvb_length_remaining (tvb, offset);
770   if (caplen > (guint)reported_length_remaining) {
771     expert_add_info_format (pinfo, ti, PI_MALFORMED, PI_ERROR,
772                           "Caplen is bigger than the remaining message length");
773     return;
774   }
775     
776   new_tvb = tvb_new_subset (tvb, offset, caplen, len);
777   if (decode_content && linktype != WTAP_ENCAP_UNKNOWN) {
778     dissector_try_uint(wtap_encap_dissector_table, linktype, new_tvb, pinfo, top_tree);
779
780     if (!info_added) {
781       /* Only indicate when not added before */
782       /* Indicate RPCAP in the protocol column */
783       col_prepend_fence_fstr(pinfo->cinfo, COL_PROTOCOL, "R|");
784
785       /* Indicate RPCAP in the info column */
786       col_prepend_fence_fstr (pinfo->cinfo, COL_INFO, "Remote | ");
787       info_added = TRUE;
788       register_frame_end_routine(rpcap_frame_end);
789     }
790   } else {
791     if (linktype == WTAP_ENCAP_UNKNOWN) {
792       proto_item_append_text (ti, ", Unknown link-layer type");
793     }
794     call_dissector (data_handle, new_tvb, pinfo, top_tree);
795   }
796 }
797
798
799 static void
800 dissect_rpcap (tvbuff_t *tvb, packet_info *pinfo, proto_tree *top_tree)
801 {
802   proto_tree *tree;
803   proto_item *ti;
804   tvbuff_t *new_tvb;
805   gint len, offset = 0;
806   guint8 msg_type;
807   guint16 msg_value;
808
809   col_set_str (pinfo->cinfo, COL_PROTOCOL, PSNAME);
810
811   col_clear(pinfo->cinfo, COL_INFO);
812
813   ti = proto_tree_add_item (top_tree, proto_rpcap, tvb, offset, -1, ENC_NA);
814   tree = proto_item_add_subtree (ti, ett_rpcap);
815
816   proto_tree_add_item (tree, hf_version, tvb, offset, 1, ENC_BIG_ENDIAN);
817   offset++;
818
819   msg_type = tvb_get_guint8 (tvb, offset);
820   proto_tree_add_item (tree, hf_type, tvb, offset, 1, ENC_BIG_ENDIAN);
821   offset++;
822
823   if (check_col (pinfo->cinfo, COL_INFO)) {
824     col_append_fstr (pinfo->cinfo, COL_INFO, "%s",
825                      val_to_str (msg_type, message_type, "Unknown: %d"));
826   }
827
828   proto_item_append_text (ti, ", %s", val_to_str (msg_type, message_type, "Unknown: %d"));
829
830   msg_value = tvb_get_ntohs (tvb, offset);
831   if (msg_type == RPCAP_MSG_ERROR) {
832     proto_tree_add_item (tree, hf_error_value, tvb, offset, 2, ENC_BIG_ENDIAN);
833   } else {
834     proto_tree_add_item (tree, hf_value, tvb, offset, 2, ENC_BIG_ENDIAN);
835   }
836   offset += 2;
837
838   proto_tree_add_item (tree, hf_plen, tvb, offset, 4, ENC_BIG_ENDIAN);
839   offset += 4;
840
841
842   switch (msg_type) {
843   case RPCAP_MSG_ERROR:
844     dissect_rpcap_error (tvb, pinfo, tree, offset);
845     break;
846   case RPCAP_MSG_OPEN_REQ:
847     dissect_rpcap_open_request (tvb, pinfo, tree, offset);
848     break;
849   case RPCAP_MSG_STARTCAP_REQ:
850     dissect_rpcap_startcap_request (tvb, pinfo, tree, offset);
851     break;
852   case RPCAP_MSG_UPDATEFILTER_REQ:
853     dissect_rpcap_filter (tvb, pinfo, tree, offset);
854     break;
855   case RPCAP_MSG_PACKET:
856     proto_item_set_len (ti, 28);
857     dissect_rpcap_packet (tvb, pinfo, top_tree, tree, offset, ti);
858     break;
859   case RPCAP_MSG_AUTH_REQ:
860     dissect_rpcap_auth_request (tvb, pinfo, tree, offset);
861     break;
862   case RPCAP_MSG_SETSAMPLING_REQ:
863     dissect_rpcap_sampling_request (tvb, pinfo, tree, offset);
864     break;
865   case RPCAP_MSG_FINDALLIF_REPLY:
866     dissect_rpcap_findalldevs_reply (tvb, pinfo, tree, offset, msg_value);
867     break;
868   case RPCAP_MSG_OPEN_REPLY:
869     dissect_rpcap_open_reply (tvb, pinfo, tree, offset);
870     break;
871   case RPCAP_MSG_STARTCAP_REPLY:
872     dissect_rpcap_startcap_reply (tvb, pinfo, tree, offset);
873     break;
874   case RPCAP_MSG_STATS_REPLY:
875     dissect_rpcap_stats_reply (tvb, pinfo, tree, offset);
876     break;
877   default:
878     len = tvb_length_remaining (tvb, offset);
879     if (len) {
880       /* Yet unknown, dump as data */
881       proto_item_set_len (ti, 8);
882       new_tvb = tvb_new_subset (tvb, offset, len, len);
883       call_dissector (data_handle, new_tvb, pinfo, top_tree);
884     }
885     break;
886   }
887 }
888
889
890 static gboolean
891 check_rpcap_heur (tvbuff_t *tvb, gboolean tcp)
892 {
893   gint offset = 0;
894   guint8 version, msg_type;
895   guint16 msg_value;
896   guint32 plen, len, caplen;
897
898   if (tvb_length (tvb) < 8)
899     /* Too short */
900     return FALSE;
901
902   version = tvb_get_guint8 (tvb, offset);
903   if (version != 0)
904     /* Incorrect version */
905     return FALSE;
906   offset++;
907
908   msg_type = tvb_get_guint8 (tvb, offset);
909   if (!tcp && msg_type != 7) {
910     /* UDP is only used for packets */
911     return FALSE;
912   }
913   if (match_strval(msg_type, message_type) == NULL)
914     /* Unknown message type */
915     return FALSE;
916   offset++;
917
918   msg_value = tvb_get_ntohs (tvb, offset);
919   if (msg_value > 0) {
920     if (msg_type == RPCAP_MSG_ERROR) {
921       /* Must have a valid error code */
922       if (match_strval(msg_value, error_codes) == NULL)
923         return FALSE;
924     } else if (msg_type != RPCAP_MSG_FINDALLIF_REPLY) {
925       return FALSE;
926     }
927   }
928   offset += 2;
929
930   plen = tvb_get_ntohl (tvb, offset);
931   /* FIXME: What is the maximum value that can really be seen here? */
932   if (plen > 10000)
933     return FALSE;
934
935   offset += 4;
936   len = (guint32) tvb_length_remaining (tvb, offset);
937
938   switch (msg_type) {
939
940   case RPCAP_MSG_FINDALLIF_REQ:
941   case RPCAP_MSG_UPDATEFILTER_REPLY:
942   case RPCAP_MSG_AUTH_REPLY:
943   case RPCAP_MSG_STATS_REQ:
944   case RPCAP_MSG_CLOSE:
945   case RPCAP_MSG_SETSAMPLING_REPLY:
946   case RPCAP_MSG_ENDCAP_REQ:
947   case RPCAP_MSG_ENDCAP_REPLY:
948     /* Empty payload */
949     if (plen != 0 || len != 0)
950       return FALSE;
951     break;
952
953   case RPCAP_MSG_OPEN_REPLY:
954   case RPCAP_MSG_STARTCAP_REPLY:
955   case RPCAP_MSG_SETSAMPLING_REQ:
956     /* Always 8 bytes */
957     if (plen != 8 || len != 8)
958       return FALSE;
959     break;
960
961   case RPCAP_MSG_STATS_REPLY:
962     /* Always 16 bytes */
963     if (plen != 16 || len != 16)
964       return FALSE;
965     break;
966
967   case RPCAP_MSG_PACKET:
968     /* Must have the frame header */
969     if (plen < 20)
970       return FALSE;
971
972     /* Check if capture length is valid */
973     caplen = tvb_get_ntohl (tvb, offset+8);
974     /* FIXME: Are there cases where a length of 0 may be valid? */
975     if (caplen > len || caplen == 0)
976       return FALSE;
977     break;
978
979   case RPCAP_MSG_FINDALLIF_REPLY:
980     /* May be empty */
981     break;
982   case RPCAP_MSG_ERROR:
983   case RPCAP_MSG_OPEN_REQ:
984   case RPCAP_MSG_STARTCAP_REQ:
985   case RPCAP_MSG_UPDATEFILTER_REQ:
986   case RPCAP_MSG_AUTH_REQ:
987     /* Variable length */
988     if (plen != len)
989       return FALSE;
990     break;
991   default:
992     /* Unknown message type */
993     return FALSE;
994   }
995
996   return TRUE;
997 }
998
999
1000 static guint
1001 get_rpcap_pdu_len (packet_info *pinfo _U_, tvbuff_t *tvb, int offset)
1002 {
1003   return tvb_get_ntohl (tvb, offset + 4) + 8;
1004 }
1005
1006
1007 static gboolean
1008 dissect_rpcap_heur_tcp (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1009 {
1010   if (check_rpcap_heur (tvb, TRUE)) {
1011     /* This is probably a rpcap tcp package */
1012     tcp_dissect_pdus (tvb, pinfo, tree, rpcap_desegment, 8,
1013                       get_rpcap_pdu_len, dissect_rpcap);
1014
1015     return TRUE;
1016   }
1017
1018   return FALSE;
1019 }
1020
1021
1022 static gboolean
1023 dissect_rpcap_heur_udp (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1024 {
1025   if (check_rpcap_heur (tvb, FALSE)) {
1026     /* This is probably a rpcap udp package */
1027     dissect_rpcap (tvb, pinfo, tree);
1028
1029     return TRUE;
1030   }
1031
1032   return FALSE;
1033 }
1034
1035
1036 void
1037 proto_register_rpcap (void)
1038 {
1039   static hf_register_info hf[] = {
1040     /* Common header for all messages */
1041     { &hf_version,
1042       { "Version", "rpcap.version", FT_UINT8, BASE_DEC,
1043         NULL, 0x0, NULL, HFILL } },
1044     { &hf_type,
1045       { "Message type", "rpcap.type", FT_UINT8, BASE_DEC,
1046         VALS(message_type), 0x0, NULL, HFILL } },
1047     { &hf_value,
1048       { "Message value", "rpcap.value", FT_UINT16, BASE_DEC,
1049         NULL, 0x0, NULL, HFILL } },
1050     { &hf_plen,
1051       { "Payload length", "rpcap.len", FT_UINT32, BASE_DEC,
1052         NULL, 0x0, NULL, HFILL } },
1053
1054     /* Error */
1055     { &hf_error,
1056       { "Error", "rpcap.error", FT_STRING, BASE_NONE,
1057         NULL, 0x0, "Error text", HFILL } },
1058     { &hf_error_value,
1059       { "Error value", "rpcap.error_value", FT_UINT16, BASE_DEC,
1060         VALS(error_codes), 0x0, NULL, HFILL } },
1061
1062     /* Packet header */
1063     { &hf_packet,
1064       { "Packet", "rpcap.packet", FT_NONE, BASE_NONE,
1065         NULL, 0x0, "Packet data", HFILL } },
1066     { &hf_timestamp,
1067       { "Arrival time", "rpcap.time", FT_ABSOLUTE_TIME, ABSOLUTE_TIME_LOCAL,
1068         NULL, 0x0, NULL, HFILL } },
1069     { &hf_caplen,
1070       { "Capture length", "rpcap.cap_len", FT_UINT32, BASE_DEC,
1071         NULL, 0x0, NULL, HFILL } },
1072     { &hf_len,
1073       { "Frame length", "rpcap.len", FT_UINT32, BASE_DEC,
1074         NULL, 0x0, "Frame length (off wire)", HFILL } },
1075     { &hf_npkt,
1076       { "Frame number", "rpcap.number", FT_UINT32, BASE_DEC,
1077         NULL, 0x0, NULL, HFILL } },
1078
1079     /* Authentication request */
1080     { &hf_auth_request,
1081       { "Authentication", "rpcap.auth", FT_NONE, BASE_NONE,
1082         NULL, 0x0, NULL, HFILL } },
1083     { &hf_auth_type,
1084       { "Authentication type", "rpcap.auth_type", FT_UINT16, BASE_DEC,
1085         VALS(auth_type), 0x0, NULL, HFILL } },
1086     { &hf_auth_slen1,
1087       { "Authentication item length 1", "rpcap.auth_len1", FT_UINT16, BASE_DEC,
1088         NULL, 0x0, NULL, HFILL } },
1089     { &hf_auth_slen2,
1090       { "Authentication item length 2", "rpcap.auth_len2", FT_UINT16, BASE_DEC,
1091         NULL, 0x0, NULL, HFILL } },
1092     { &hf_auth_username,
1093       { "Username", "rpcap.username", FT_STRING, BASE_NONE,
1094         NULL, 0x0, NULL, HFILL } },
1095     { &hf_auth_password,
1096       { "Password", "rpcap.password", FT_STRING, BASE_NONE,
1097         NULL, 0x0, NULL, HFILL } },
1098
1099     /* Open request */
1100     { &hf_open_request,
1101       { "Open request", "rpcap.open_request", FT_STRING, BASE_NONE,
1102         NULL, 0x0, NULL, HFILL } },
1103
1104     /* Open reply */
1105     { &hf_open_reply,
1106       { "Open reply", "rpcap.open_reply", FT_NONE, BASE_NONE,
1107         NULL, 0x0, NULL, HFILL } },
1108     { &hf_linktype,
1109       { "Link type", "rpcap.linktype", FT_UINT32, BASE_DEC,
1110         NULL, 0x0, NULL, HFILL } },
1111     { &hf_tzoff,
1112       { "Timezone offset", "rpcap.tzoff", FT_UINT32, BASE_DEC,
1113         NULL, 0x0, NULL, HFILL } },
1114
1115     /* Start capture request */
1116     { &hf_startcap_request,
1117       { "Start capture request", "rpcap.startcap_request", FT_NONE, BASE_NONE,
1118         NULL, 0x0, NULL, HFILL } },
1119     { &hf_snaplen,
1120       { "Snap length", "rpcap.snaplen", FT_UINT32, BASE_DEC,
1121         NULL, 0x0, NULL, HFILL } },
1122     { &hf_read_timeout,
1123       { "Read timeout", "rpcap.read_timeout", FT_UINT32, BASE_DEC,
1124         NULL, 0x0, NULL, HFILL } },
1125     { &hf_flags,
1126       { "Flags", "rpcap.flags", FT_UINT16, BASE_DEC,
1127         NULL, 0x0, "Capture flags", HFILL } },
1128     { &hf_flags_promisc,
1129       { "Promiscuous mode", "rpcap.flags.promisc", FT_BOOLEAN, 16,
1130         TFS(&tfs_enabled_disabled), FLAG_PROMISC, NULL, HFILL } },
1131     { &hf_flags_dgram,
1132       { "Use Datagram", "rpcap.flags.dgram", FT_BOOLEAN, 16,
1133         TFS(&tfs_yes_no), FLAG_DGRAM, NULL, HFILL } },
1134     { &hf_flags_serveropen,
1135       { "Server open", "rpcap.flags.serveropen", FT_BOOLEAN, 16,
1136         TFS(&open_closed), FLAG_SERVEROPEN, NULL, HFILL } },
1137     { &hf_flags_inbound,
1138       { "Inbound", "rpcap.flags.inbound", FT_BOOLEAN, 16,
1139         TFS(&tfs_yes_no), FLAG_INBOUND, NULL, HFILL } },
1140     { &hf_flags_outbound,
1141       { "Outbound", "rpcap.flags.outbound", FT_BOOLEAN, 16,
1142         TFS(&tfs_yes_no), FLAG_OUTBOUND, NULL, HFILL } },
1143     { &hf_client_port,
1144       { "Client Port", "rpcap.client_port", FT_UINT16, BASE_DEC,
1145         NULL, 0x0, NULL, HFILL } },
1146
1147     /* Start capture reply */
1148     { &hf_startcap_reply,
1149       { "Start capture reply", "rpcap.startcap_reply", FT_NONE, BASE_NONE,
1150         NULL, 0x0, NULL, HFILL } },
1151     { &hf_bufsize,
1152       { "Buffer size", "rpcap.bufsize", FT_UINT32, BASE_DEC,
1153         NULL, 0x0, NULL, HFILL } },
1154     { &hf_server_port,
1155       { "Server port", "rpcap.server_port", FT_UINT16, BASE_DEC,
1156         NULL, 0x0, NULL, HFILL } },
1157     { &hf_dummy,
1158       { "Dummy", "rpcap.dummy", FT_UINT16, BASE_DEC,
1159         NULL, 0x0, NULL, HFILL } },
1160
1161     /* Filter */
1162     { &hf_filter,
1163       { "Filter", "rpcap.filter", FT_NONE, BASE_NONE,
1164         NULL, 0x0, NULL, HFILL } },
1165     { &hf_filtertype,
1166       { "Filter type", "rpcap.filtertype", FT_UINT16, BASE_DEC,
1167         NULL, 0x0, "Filter type (BPF)", HFILL } },
1168     { &hf_nitems,
1169       { "Number of items", "rpcap.nitems", FT_UINT32, BASE_DEC,
1170         NULL, 0x0, NULL, HFILL } },
1171
1172     /* Filter BPF instruction */
1173     { &hf_filterbpf_insn,
1174       { "Filter BPF instruction", "rpcap.filterbpf_insn", FT_NONE, BASE_NONE,
1175         NULL, 0x0, NULL, HFILL } },
1176     { &hf_code,
1177       { "Op code", "rpcap.opcode", FT_UINT16, BASE_DEC,
1178         NULL, 0x0, "Operation code", HFILL } },
1179     { &hf_jt,
1180       { "JT", "rpcap.jt", FT_UINT8, BASE_DEC,
1181         NULL, 0x0, NULL, HFILL } },
1182     { &hf_jf,
1183       { "JF", "rpcap.jf", FT_UINT8, BASE_DEC,
1184         NULL, 0x0, NULL, HFILL } },
1185     { &hf_instr_value,
1186       { "Instruction value", "rpcap.instr_value", FT_UINT32, BASE_DEC,
1187         NULL, 0x0, "Instruction-Dependent value", HFILL } },
1188
1189     /* Statistics reply */
1190     { &hf_stats_reply,
1191       { "Statistics", "rpcap.stats_reply", FT_NONE, BASE_NONE,
1192         NULL, 0x0, "Statistics reply data", HFILL } },
1193     { &hf_ifrecv,
1194       { "Received by kernel filter", "rpcap.ifrecv", FT_UINT32, BASE_DEC,
1195         NULL, 0x0, "Received by kernel", HFILL } },
1196     { &hf_ifdrop,
1197       { "Dropped by network interface", "rpcap.ifdrop", FT_UINT32, BASE_DEC,
1198         NULL, 0x0, NULL, HFILL } },
1199     { &hf_krnldrop,
1200       { "Dropped by kernel filter", "rpcap.krnldrop", FT_UINT32, BASE_DEC,
1201         NULL, 0x0, NULL, HFILL } },
1202     { &hf_srvcapt,
1203       { "Captured by rpcapd", "rpcap.srvcapt", FT_UINT32, BASE_DEC,
1204         NULL, 0x0, "Captured by RPCAP daemon", HFILL } },
1205
1206     /* Find all devices reply */
1207     { &hf_findalldevs_reply,
1208       { "Find all devices", "rpcap.findalldevs_reply", FT_NONE, BASE_NONE,
1209         NULL, 0x0, NULL, HFILL } },
1210     { &hf_findalldevs_if,
1211       { "Interface", "rpcap.if", FT_NONE, BASE_NONE,
1212         NULL, 0x0, NULL, HFILL } },
1213     { &hf_namelen,
1214       { "Name length", "rpcap.namelen", FT_UINT16, BASE_DEC,
1215         NULL, 0x0, NULL, HFILL } },
1216     { &hf_desclen,
1217       { "Description length", "rpcap.desclen", FT_UINT32, BASE_DEC,
1218         NULL, 0x0, NULL, HFILL } },
1219     { &hf_if_flags,
1220       { "Interface flags", "rpcap.if.flags", FT_UINT32, BASE_DEC,
1221         NULL, 0x0, NULL, HFILL } },
1222     { &hf_naddr,
1223       { "Number of addresses", "rpcap.naddr", FT_UINT32, BASE_DEC,
1224         NULL, 0x0, NULL, HFILL } },
1225     { &hf_if_name,
1226       { "Name", "rpcap.ifname", FT_STRING, BASE_NONE,
1227         NULL, 0x0, "Interface name", HFILL } },
1228     { &hf_if_desc,
1229       { "Description", "rpcap.ifdesc", FT_STRING, BASE_NONE,
1230         NULL, 0x0, "Interface description", HFILL } },
1231
1232     /* Find all devices / Interface addresses */
1233     { &hf_findalldevs_ifaddr,
1234       { "Interface address", "rpcap.ifaddr", FT_NONE, BASE_NONE,
1235         NULL, 0x0, NULL, HFILL } },
1236     { &hf_if_addr,
1237       { "Address", "rpcap.addr", FT_NONE, BASE_NONE,
1238         NULL, 0x0, "Network address", HFILL } },
1239     { &hf_if_netmask,
1240       { "Netmask", "rpcap.netmask", FT_NONE, BASE_NONE,
1241         NULL, 0x0, NULL, HFILL } },
1242     { &hf_if_broadaddr,
1243       { "Broadcast", "rpcap.broadaddr", FT_NONE, BASE_NONE,
1244         NULL, 0x0, NULL, HFILL } },
1245     { &hf_if_dstaddr,
1246       { "P2P destination address", "rpcap.dstaddr", FT_NONE, BASE_NONE,
1247         NULL, 0x0, NULL, HFILL } },
1248     { &hf_if_af,
1249       { "Address family", "rpcap.if.af", FT_UINT16, BASE_HEX,
1250         VALS(address_family), 0x0, NULL, HFILL } },
1251     { &hf_if_port,
1252       { "Port", "rpcap.if.port", FT_UINT16, BASE_DEC,
1253         NULL, 0x0, "Port number", HFILL } },
1254     { &hf_if_ip,
1255       { "IP address", "rpcap.if.ip", FT_IPv4, BASE_NONE,
1256         NULL, 0x0, NULL, HFILL } },
1257     { &hf_if_padding,
1258       { "Padding", "rpcap.if.padding", FT_BYTES, BASE_NONE,
1259         NULL, 0x0, NULL, HFILL } },
1260     { &hf_if_unknown,
1261       { "Unknown address", "rpcap.if.unknown", FT_BYTES, BASE_NONE,
1262         NULL, 0x0, NULL, HFILL } },
1263
1264     /* Sampling request */
1265     { &hf_sampling_request,
1266       { "Sampling", "rpcap.sampling_request", FT_NONE, BASE_NONE,
1267         NULL, 0x0, NULL, HFILL } },
1268     { &hf_sampling_method,
1269       { "Method", "rpcap.sampling_method", FT_UINT8, BASE_DEC,
1270         VALS(sampling_method), 0x0, "Sampling method", HFILL } },
1271     { &hf_sampling_dummy1,
1272       { "Dummy1", "rpcap.dummy", FT_UINT8, BASE_DEC,
1273         NULL, 0x0, NULL, HFILL } },
1274     { &hf_sampling_dummy2,
1275       { "Dummy2", "rpcap.dummy", FT_UINT16, BASE_DEC,
1276         NULL, 0x0, NULL, HFILL } },
1277     { &hf_sampling_value,
1278       { "Value", "rpcap.sampling_value", FT_UINT32, BASE_DEC,
1279         NULL, 0x0, NULL, HFILL } },
1280   };
1281
1282   static gint *ett[] = {
1283     &ett_rpcap,
1284     &ett_error,
1285     &ett_packet,
1286     &ett_auth_request,
1287     &ett_open_reply,
1288     &ett_startcap_request,
1289     &ett_startcap_reply,
1290     &ett_startcap_flags,
1291     &ett_filter,
1292     &ett_filterbpf_insn,
1293     &ett_stats_reply,
1294     &ett_findalldevs_reply,
1295     &ett_findalldevs_if,
1296     &ett_findalldevs_ifaddr,
1297     &ett_ifaddr,
1298     &ett_sampling_request
1299   };
1300
1301   module_t *rpcap_module;
1302
1303   proto_rpcap = proto_register_protocol (PNAME, PSNAME, PFNAME);
1304   register_dissector (PFNAME, dissect_rpcap, proto_rpcap);
1305
1306   proto_register_field_array (proto_rpcap, hf, array_length (hf));
1307   proto_register_subtree_array (ett, array_length (ett));
1308
1309   /* Register our configuration options */
1310   rpcap_module = prefs_register_protocol (proto_rpcap, proto_reg_handoff_rpcap);
1311
1312   prefs_register_bool_preference (rpcap_module, "desegment_pdus",
1313                                   "Reassemble PDUs spanning multiple TCP segments",
1314                                   "Whether the RPCAP dissector should reassemble PDUs"
1315                                   " spanning multiple TCP segments."
1316                                   " To use this option, you must also enable \"Allow subdissectors"
1317                                   " to reassemble TCP streams\" in the TCP protocol settings.",
1318                                   &rpcap_desegment);
1319   prefs_register_bool_preference (rpcap_module, "decode_content",
1320                                   "Decode content according to link-layer type",
1321                                   "Whether the packets should be decoded according to"
1322                                   " the link-layer type.",
1323                                   &decode_content);
1324   prefs_register_uint_preference (rpcap_module, "linktype",
1325                                   "Default link-layer type",
1326                                   "Default link-layer type to use if an Open Reply packet"
1327                                   " has not been received.",
1328                                   10, &global_linktype);
1329 }
1330
1331 void
1332 proto_reg_handoff_rpcap (void)
1333 {
1334   static gboolean rpcap_prefs_initialized = FALSE;
1335
1336   if (!rpcap_prefs_initialized) {
1337     data_handle = find_dissector ("data");
1338     rpcap_prefs_initialized = TRUE;
1339
1340     heur_dissector_add ("tcp", dissect_rpcap_heur_tcp, proto_rpcap);
1341     heur_dissector_add ("udp", dissect_rpcap_heur_udp, proto_rpcap);
1342   }
1343
1344   info_added = FALSE;
1345   linktype = global_linktype;
1346 }
1347
1348 /*
1349  * Editor modelines
1350  *
1351  * Local Variables:
1352  * c-basic-offset: 2
1353  * tab-width: 8
1354  * indent-tabs-mode: t
1355  * End:
1356  *
1357  * ex: set shiftwidth=2 tabstop=8 noexpandtab
1358  * :indentSize=2:tabSize=8:noTabs=false:
1359  */