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