forked from wireshark/wireshark
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathREADME.dissector
3695 lines (2844 loc) · 156 KB
/
README.dissector
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
This file is a HOWTO for Wireshark developers interested in writing or working
on Wireshark protocol dissectors. It describes expected code patterns and the
use of some of the important functions and variables.
This file is compiled to give in depth information on Wireshark.
It is by no means all inclusive and complete. Please feel free to send
remarks and patches to the developer mailing list.
If you haven't read README.developer, read that first!
0. Prerequisites.
Before starting to develop a new dissector, a "running" Wireshark build
environment is required - there's no such thing as a standalone "dissector
build toolkit".
How to setup such an environment is platform dependent; detailed
information about these steps can be found in the "Developer's Guide"
(available from: https://www.wireshark.org) and in the INSTALL and
README.md files of the sources root dir.
0.1. Dissector related README files.
You'll find additional dissector related information in the following README
files:
- README.heuristic - what are heuristic dissectors and how to write them
- README.plugins - how to "pluginize" a dissector
- README.request_response_tracking - how to track req./resp. times and such
- README.wmem - how to obtain "memory leak free" memory
0.2 Contributors
James Coe <jammer[AT]cin.net>
Gilbert Ramirez <gram[AT]alumni.rice.edu>
Jeff Foster <jfoste[AT]woodward.com>
Olivier Abad <oabad[AT]cybercable.fr>
Laurent Deniel <laurent.deniel[AT]free.fr>
Gerald Combs <gerald[AT]wireshark.org>
Guy Harris <guy[AT]alum.mit.edu>
Ulf Lamping <ulf.lamping[AT]web.de>
Barbu Paul - Gheorghe <barbu.paul.gheorghe[AT]gmail.com>
1. Setting up your protocol dissector code.
This section provides skeleton code for a protocol dissector. It also explains
the basic functions needed to enter values in the traffic summary columns,
add to the protocol tree, and work with registered header fields.
1.1 Skeleton code.
Wireshark requires certain things when setting up a protocol dissector.
We provide basic skeleton code for a dissector that you can copy to a new file
and fill in. Your dissector should follow the naming convention of "packet-"
followed by the abbreviated name for the protocol. It is recommended that where
possible you keep to the IANA abbreviated name for the protocol, if there is
one, or a commonly-used abbreviation for the protocol, if any.
The skeleton code lives in the file "packet-PROTOABBREV.c" in the same source
directory as this README.
If instead of using the skeleton you base your dissector on an existing real
dissector, please put a little note in the copyright header indicating which
dissector you started with.
Usually, you will put your newly created dissector file into the directory
epan/dissectors/, just like all the other packet-*.c files already in there.
Also, please add your dissector file to the corresponding makefiles,
described in section "1.8 Editing CMakeLists.txt to add your dissector" below.
Dissectors that use the dissector registration API to register with a lower
level protocol (this is the vast majority) don't need to define a prototype in
their .h file. For other dissectors the main dissector routine should have a
prototype in a header file whose name is "packet-", followed by the abbreviated
name for the protocol, followed by ".h"; any dissector file that calls your
dissector should be changed to include that file.
You may not need to include all the headers listed in the skeleton, and you may
need to include additional headers.
1.2 Explanation of needed substitutions in code skeleton.
In the skeleton sample code the following strings should be substituted with
your information.
YOUR_NAME Your name, of course. You do want credit, don't you?
It's the only payment you will receive....
YOUR_EMAIL_ADDRESS Keep those cards and letters coming.
PROTONAME The name of the protocol; this is displayed in the
top-level protocol tree item for that protocol.
PROTOSHORTNAME An abbreviated name for the protocol; this is displayed
in the "Preferences" dialog box if your dissector has
any preferences, in the dialog box of enabled protocols,
and in the dialog box for filter fields when constructing
a filter expression.
PROTOFILTERNAME A name for the protocol for use in filter expressions;
it may contain only letters, digits, hyphens, underscores and
periods. Names should use lower case only. (Support for
upper/mixed case may be removed in the future.)
PROTOABBREV An abbreviation for the protocol; this is used in code and
must be a valid C identifier. Additionally it should follow
any applicable C style guidelines. It is usually the same as
PROTOFILTERNAME with all lower-case letters and
non-alphanumerics replaced with underscores.
LICENSE The license this dissector is under. Please use a SPDX License
identifier.
YEARS The years the above license is valid for.
FIELDNAME The displayed name for the header field.
FIELDFILTERNAME A name for the header field for use in filter expressions;
it may contain only letters, digits, hyphens, underscores and
periods. It must start with PROTOFILTERNAME followed by a dot.
Names should use lower case only. (Support for upper/mixed case
may be removed in the future.)
FIELDABBREV An abbreviation for the header field; this is used in code and
must be a valid C identifier. Additionally it should follow
any applicable C style guidelines. It is usually the same as
FIELDFILTERNAME with all lower-case letters and
non-alphanumerics replaced with underscores.
FIELDTYPE FT_NONE, FT_BOOLEAN, FT_CHAR, FT_UINT8, FT_UINT16, FT_UINT24,
FT_UINT32, FT_UINT40, FT_UINT48, FT_UINT56, FT_UINT64,
FT_INT8, FT_INT16, FT_INT24, FT_INT32, FT_INT40, FT_INT48,
FT_INT56, FT_INT64, FT_FLOAT, FT_DOUBLE, FT_ABSOLUTE_TIME,
FT_RELATIVE_TIME, FT_STRING, FT_STRINGZ, FT_EUI64,
FT_UINT_STRING, FT_ETHER, FT_BYTES, FT_UINT_BYTES, FT_IPv4,
FT_IPv6, FT_IPXNET, FT_FRAMENUM, FT_PROTOCOL, FT_GUID, FT_OID,
FT_REL_OID, FT_AX25, FT_VINES, FT_SYSTEM_ID, FT_FC, FT_FCWWN
FIELDDISPLAY --For FT_UINT{8,16,24,32,40,48,56,64} and
FT_INT{8,16,24,32,40,48,56,64):
BASE_DEC, BASE_HEX, BASE_OCT, BASE_DEC_HEX, BASE_HEX_DEC,
BASE_CUSTOM, or BASE_NONE, possibly ORed with
BASE_RANGE_STRING, BASE_EXT_STRING, BASE_VAL64_STRING,
BASE_ALLOW_ZERO, BASE_UNIT_STRING, BASE_SPECIAL_VALS,
BASE_NO_DISPLAY_VALUE, BASE_SHOW_ASCII_PRINTABLE, or
BASE_SHOW_UTF_8_PRINTABLE
BASE_NONE may be used with a non-NULL FIELDCONVERT when the
numeric value of the field itself is not of significance to
the user (for example, the number is a generated field).
When this is the case the numeric value is not shown to the
user in the protocol decode nor is it used when preparing
filters for the field in question.
BASE_NO_DISPLAY_VALUE will just display the field name with
no value. It is intended for byte arrays (FT_BYTES or
FT_UINT_BYTES) or header fields above a subtree. The
value will still be filterable, just not displayed.
--For FT_UINT16:
BASE_PT_UDP, BASE_PT_TCP, BASE_PT_DCCP or BASE_PT_SCTP
--For FT_UINT24:
BASE_OUI
--For FT_CHAR:
BASE_HEX, BASE_OCT, BASE_CUSTOM, or BASE_NONE, possibly
ORed with BASE_RANGE_STRING, BASE_EXT_STRING or
BASE_VAL64_STRING.
BASE_NONE can be used in the same way as with FT_UINT8.
--For FT_FLOAT, FT_DOUBLE:
BASE_NONE, BASE_DEC, BASE_HEX, BASE_EXP or BASE_CUSTOM.
BASE_NONE uses BASE_DEC or BASE_EXP, similarly to the
%g double format for the printf() function.
--For FT_ABSOLUTE_TIME:
ABSOLUTE_TIME_LOCAL, ABSOLUTE_TIME_UTC, or
ABSOLUTE_TIME_DOY_UTC
--For FT_BOOLEAN:
if BITMASK is non-zero:
Number of bits in the field containing the FT_BOOLEAN
bitfield.
otherwise:
(must be) BASE_NONE
--For FT_STRING, FT_STRINGZ and FT_UINT_STRING:
(must be) BASE_NONE
--For FT_BYTES and FT_UINT_BYTES:
SEP_DOT, SEP_DASH, SEP_COLON, or SEP_SPACE to provide
a separator between bytes; BASE_NONE has no separator
between bytes. These can be ORed with BASE_ALLOW_ZERO,
BASE_SHOW_ASCII_PRINTABLE, or BASE_SHOW_UTF_8_PRINTABLE.
BASE_ALLOW_ZERO displays <none> instead of <MISSING>
for a zero-sized byte array.
BASE_SHOW_ASCII_PRINTABLE will check whether the
field's value consists entirely of printable ASCII
characters and, if so, will display the field's value
as a string, in quotes. The value will still be
filterable as a byte value.
BASE_SHOW_UTF_8_PRINTABLE will check whether the
field's value is valid UTF-8 consisting entirely of
printable characters and, if so, will display the field's
value as a string, in quotes. The value will still be
filterable as a byte value.
--For FT_IPv4:
BASE_NETMASK - Used for IPv4 address that should never
attempted to be resolved (like netmasks)
otherwise:
(must be) BASE_NONE
--For all other types:
BASE_NONE
FIELDCONVERT VALS(x), VALS64(x), RVALS(x), TFS(x), CF_FUNC(x), NULL
BITMASK Used to mask a field not 8-bit aligned or with a size other
than a multiple of 8 bits
FIELDDESCR A brief description of the field, or NULL. [Please do not use ""].
If, for example, PROTONAME is "Internet Bogosity Discovery Protocol",
PROTOSHORTNAME would be "IBDP", and PROTOFILTERNAME would be "ibdp". Try to
conform with IANA names.
1.2.1 Automatic substitution in code skeleton
Instead of manual substitutions in the code skeleton, a tool to automate it can
be found under the tools directory. The script is called tools/generate-dissector.py
and takes all the needed options to generate a compilable dissector. Look at the
above fields to know how to set them. Some assumptions have been made in the
generation to shorten the list of required options. The script patches the
CMakeLists.txt file adding the new dissector in the proper list, alphabetically
sorted.
1.3 The dissector and the data it receives.
1.3.1 Header file.
This is only needed if the dissector doesn't use self-registration to
register itself with the lower level dissector, or if the protocol dissector
wants/needs to expose code to other subdissectors.
The dissector must be declared exactly as follows in the file
packet-PROTOABBREV.h:
int
dissect_PROTOABBREV(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree);
1.3.2 Extracting data from packets.
NOTE: See the file /epan/tvbuff.h for more details.
The "tvb" argument to a dissector points to a buffer containing the raw
data to be analyzed by the dissector; for example, for a protocol
running atop UDP, it contains the UDP payload (but not the UDP header,
or any protocol headers above it). A tvbuffer is an opaque data
structure, the internal data structures are hidden and the data must be
accessed via the tvbuffer accessors.
The accessors are:
Bit accessors for a maximum of 8-bits, 16-bits 32-bits and 64-bits:
guint8 tvb_get_bits8(tvbuff_t *tvb, gint bit_offset, const gint no_of_bits);
guint16 tvb_get_bits16(tvbuff_t *tvb, guint bit_offset, const gint no_of_bits, const guint encoding);
guint32 tvb_get_bits32(tvbuff_t *tvb, guint bit_offset, const gint no_of_bits, const guint encoding);
guint64 tvb_get_bits64(tvbuff_t *tvb, guint bit_offset, const gint no_of_bits, const guint encoding);
Single-byte accessors for 8-bit unsigned integers (guint8) and 8-bit
signed integers (gint8):
guint8 tvb_get_guint8(tvbuff_t *tvb, const gint offset);
gint8 tvb_get_gint8(tvbuff_t *tvb, const gint offset);
Network-to-host-order accessors:
16-bit unsigned (guint16) and signed (gint16) integers:
guint16 tvb_get_ntohs(tvbuff_t *tvb, const gint offset);
gint16 tvb_get_ntohis(tvbuff_t *tvb, const gint offset);
24-bit unsigned and signed integers:
guint32 tvb_get_ntoh24(tvbuff_t *tvb, const gint offset);
gint32 tvb_get_ntohi24(tvbuff_t *tvb, const gint offset);
32-bit unsigned (guint32) and signed (gint32) integers:
guint32 tvb_get_ntohl(tvbuff_t *tvb, const gint offset);
gint32 tvb_get_ntohil(tvbuff_t *tvb, const gint offset);
40-bit unsigned and signed integers:
guint64 tvb_get_ntoh40(tvbuff_t *tvb, const gint offset);
gint64 tvb_get_ntohi40(tvbuff_t *tvb, const gint offset);
48-bit unsigned and signed integers:
guint64 tvb_get_ntoh48(tvbuff_t *tvb, const gint offset);
gint64 tvb_get_ntohi48(tvbuff_t *tvb, const gint offset);
56-bit unsigned and signed integers:
guint64 tvb_get_ntoh56(tvbuff_t *tvb, const gint offset);
gint64 tvb_get_ntohi56(tvbuff_t *tvb, const gint offset);
64-bit unsigned (guint64) and signed (gint64) integers:
guint64 tvb_get_ntoh64(tvbuff_t *tvb, const gint offset);
gint64 tvb_get_ntohi64(tvbuff_t *tvb, const gint offset);
Single-precision and double-precision IEEE floating-point numbers:
gfloat tvb_get_ntohieee_float(tvbuff_t *tvb, const gint offset);
gdouble tvb_get_ntohieee_double(tvbuff_t *tvb, const gint offset);
Little-Endian-to-host-order accessors:
16-bit unsigned (guint16) and signed (gint16) integers:
guint16 tvb_get_letohs(tvbuff_t *tvb, const gint offset);
gint16 tvb_get_letohis(tvbuff_t *tvb, const gint offset);
24-bit unsigned and signed integers:
guint32 tvb_get_letoh24(tvbuff_t *tvb, const gint offset);
gint32 tvb_get_letohi24(tvbuff_t *tvb, const gint offset);
32-bit unsigned (guint32) and signed (gint32) integers:
guint32 tvb_get_letohl(tvbuff_t *tvb, const gint offset);
gint32 tvb_get_letohil(tvbuff_t *tvb, const gint offset);
40-bit unsigned and signed integers:
guint64 tvb_get_letoh40(tvbuff_t *tvb, const gint offset);
gint64 tvb_get_letohi40(tvbuff_t *tvb, const gint offset);
48-bit unsigned and signed integers:
guint64 tvb_get_letoh48(tvbuff_t *tvb, const gint offset);
gint64 tvb_get_letohi48(tvbuff_t *tvb, const gint offset);
56-bit unsigned and signed integers:
guint64 tvb_get_letoh56(tvbuff_t *tvb, const gint offset);
gint64 tvb_get_letohi56(tvbuff_t *tvb, const gint offset);
64-bit unsigned (guint64) and signed (gint64) integers:
guint64 tvb_get_letoh64(tvbuff_t *tvb, const gint offset);
gint64 tvb_get_letohi64(tvbuff_t *tvb, const gint offset);
NOTE: Although each of the integer accessors above return types with
specific sizes, the returned values are subject to C's integer promotion
rules. It's often safer and more useful to use int or guint for 32-bit
and smaller types, and gint64 or guint64 for 40-bit and larger types.
Just because a value occupied 16 bits on the wire or over the air
doesn't mean it will within Wireshark.
Single-precision and double-precision IEEE floating-point numbers:
gfloat tvb_get_letohieee_float(tvbuff_t *tvb, const gint offset);
gdouble tvb_get_letohieee_double(tvbuff_t *tvb, const gint offset);
Encoding-to_host-order accessors:
16-bit unsigned (guint16) and signed (gint16) integers:
guint16 tvb_get_guint16(tvbuff_t *tvb, const gint offset, const guint encoding);
gint16 tvb_get_gint16(tvbuff_t *tvb, const gint offset, const guint encoding);
24-bit unsigned and signed integers:
guint32 tvb_get_guint24(tvbuff_t *tvb, const gint offset, const guint encoding);
gint32 tvb_get_gint24(tvbuff_t *tvb, const gint offset, const guint encoding);
32-bit unsigned (guint32) and signed (gint32) integers:
guint32 tvb_get_guint32(tvbuff_t *tvb, const gint offset, const guint encoding);
gint32 tvb_get_gint32(tvbuff_t *tvb, const gint offset, const guint encoding);
40-bit unsigned and signed integers:
guint64 tvb_get_guint40(tvbuff_t *tvb, const gint offset, const guint encoding);
gint64 tvb_get_gint40(tvbuff_t *tvb, const gint offset, const guint encoding);
48-bit unsigned and signed integers:
guint64 tvb_get_guint48(tvbuff_t *tvb, const gint offset, const guint encoding);
gint64 tvb_get_gint48(tvbuff_t *tvb, const gint offset, const guint encoding);
56-bit unsigned and signed integers:
guint64 tvb_get_guint56(tvbuff_t *tvb, const gint offset, const guint encoding);
gint64 tvb_get_gint56(tvbuff_t *tvb, const gint offset, const guint encoding);
64-bit unsigned (guint64) and signed (gint64) integers:
guint64 tvb_get_guint64(tvbuff_t *tvb, const gint offset, const guint encoding);
gint64 tvb_get_gint64(tvbuff_t *tvb, const gint offset, const guint encoding);
Single-precision and double-precision IEEE floating-point numbers:
gfloat tvb_get_ieee_float(tvbuff_t *tvb, const gint offset, const guint encoding);
gdouble tvb_get_ieee_double(tvbuff_t *tvb, const gint offset, const guint encoding);
"encoding" should be ENC_BIG_ENDIAN for Network-to-host-order,
ENC_LITTLE_ENDIAN for Little-Endian-to-host-order, or ENC_HOST_ENDIAN
for host order.
Accessors for IPv4 and IPv6 addresses:
guint32 tvb_get_ipv4(tvbuff_t *tvb, const gint offset);
void tvb_get_ipv6(tvbuff_t *tvb, const gint offset, ws_in6_addr *addr);
NOTE: IPv4 addresses are not to be converted to host byte order before
being passed to "proto_tree_add_ipv4()". You should use "tvb_get_ipv4()"
to fetch them, not "tvb_get_ntohl()" *OR* "tvb_get_letohl()" - don't,
for example, try to use "tvb_get_ntohl()", find that it gives you the
wrong answer on the PC on which you're doing development, and try
"tvb_get_letohl()" instead, as "tvb_get_letohl()" will give the wrong
answer on big-endian machines.
gchar *tvb_ip_to_str(wmem_allocator_t *scope, tvbuff_t *tvb, const gint offset)
gchar *tvb_ip6_to_str(wmem_allocator_t *scope, tvbuff_t *tvb, const gint offset)
Returns a null-terminated buffer containing a string with IPv4 or IPv6 Address
from the specified tvbuff, starting at the specified offset.
Accessors for GUID:
void tvb_get_ntohguid(tvbuff_t *tvb, const gint offset, e_guid_t *guid);
void tvb_get_letohguid(tvbuff_t *tvb, const gint offset, e_guid_t *guid);
void tvb_get_guid(tvbuff_t *tvb, const gint offset, e_guid_t *guid, const guint encoding);
String accessors:
guint8 *tvb_get_string_enc(wmem_allocator_t *scope, tvbuff_t *tvb, const gint offset, const gint length, const guint encoding);
Returns a null-terminated buffer allocated from the specified scope, containing
data from the specified tvbuff, starting at the specified offset, and containing
the specified length worth of characters. Reads data in the specified encoding
and produces UTF-8 in the buffer. See below for a list of input encoding values.
The buffer is allocated in the given wmem scope (see README.wmem for more
information).
guint8 *tvb_get_stringz_enc(wmem_allocator_t *scope, tvbuff_t *tvb, const gint offset, gint *lengthp, const guint encoding);
Returns a null-terminated buffer allocated from the specified scope,
containing data from the specified tvbuff, starting at the specified
offset, and containing all characters from the tvbuff up to and
including a terminating null character in the tvbuff. Reads data in the
specified encoding and produces UTF-8 in the buffer. See below for a
list of input encoding values. "*lengthp" will be set to the length of
the string, including the terminating null.
The buffer is allocated in the given wmem scope (see README.wmem for more
information).
const guint8 *tvb_get_const_stringz(tvbuff_t *tvb, const gint offset, gint *lengthp);
Returns a null-terminated const buffer containing data from the
specified tvbuff, starting at the specified offset, and containing all
bytes from the tvbuff up to and including a terminating null character
in the tvbuff. "*lengthp" will be set to the length of the string,
including the terminating null.
You do not need to free() this buffer; it will happen automatically once
the next packet is dissected. This function is slightly more efficient
than the others because it does not allocate memory and copy the string,
but it does not do any mapping to UTF-8 or checks for valid octet
sequences.
gint tvb_get_nstringz(tvbuff_t *tvb, const gint offset, const guint bufsize, guint8* buffer);
gint tvb_get_nstringz0(tvbuff_t *tvb, const gint offset, const guint bufsize, guint8* buffer);
Copies bufsize bytes, including the terminating NULL, to buffer. If a NULL
terminator is found before reaching bufsize, only the bytes up to and including
the NULL are copied. Returns the number of bytes copied (not including
terminating NULL), or -1 if the string was truncated in the buffer due to
not having reached the terminating NULL. In this case, the resulting
buffer is not NULL-terminated.
tvb_get_nstringz0() works like tvb_get_nstringz(), but never returns -1 since
the string is guaranteed to have a terminating NULL. If the string was truncated
when copied into buffer, a NULL is placed at the end of buffer to terminate it.
gchar *tvb_get_ts_23_038_7bits_string(wmem_allocator_t *scope, tvbuff_t *tvb,
const gint bit_offset, gint no_of_chars);
tvb_get_ts_23_038_7bits_string() returns a string of a given number of
characters and encoded according to 3GPP TS 23.038 7 bits alphabet.
The buffer is allocated in the given wmem scope (see README.wmem for more
information).
Byte Array Accessors:
gchar *tvb_bytes_to_str(wmem_allocator_t *scope, tvbuff_t *tvb, const gint offset, const gint len);
Formats a bunch of data from a tvbuff as bytes, returning a pointer
to the string with the data formatted as two hex digits for each byte.
The string pointed to is stored in an "wmem_alloc'd" buffer which will be freed
depending on its scope (typically wmem_packet_scope which is freed after the frame).
The formatted string will contain the hex digits for at most the first 16 bytes of
the data. If len is greater than 16 bytes, a trailing "..." will be added to the string.
gchar *tvb_bytes_to_str_punct(wmem_allocator_t *scope, tvbuff_t *tvb,
const gint offset, const gint len, const gchar punct);
This function is similar to tvb_bytes_to_str(...) except that 'punct' is inserted
between the hex representation of each byte.
GByteArray *tvb_get_string_bytes(tvbuff_t *tvb, const gint offset, const gint length,
const guint encoding, GByteArray* bytes, gint *endoff)
Given a tvbuff, an offset into the tvbuff, and a length that starts
at that offset (which may be -1 for "all the way to the end of the
tvbuff"), fetch the hex-decoded byte values of the tvbuff into the
passed-in 'bytes' array, based on the passed-in encoding. In other
words, convert from a hex-ascii string in tvbuff, into the supplied
GByteArray.
gchar *tvb_bcd_dig_to_wmem_packet_str(tvbuff_t *tvb, const gint offset, const gint len, dgt_set_t *dgt, gboolean skip_first);
Given a tvbuff, an offset into the tvbuff, and a length that starts
at that offset (which may be -1 for "all the way to the end of the
tvbuff"), fetch BCD encoded digits from a tvbuff starting from either
the low or high half byte, formatting the digits according to an input digit set,
if NUll a default digit set of 0-9 returning "?" for overdecadic digits will be used.
A pointer to the packet scope allocated string will be returned.
Note: a tvbuff content of 0xf is considered a 'filler' and will end the conversion.
Copying memory:
void* tvb_memcpy(tvbuff_t *tvb, void* target, const gint offset, size_t length);
Copies into the specified target the specified length's worth of data
from the specified tvbuff, starting at the specified offset.
void *tvb_memdup(wmem_allocator_t *scope, tvbuff_t *tvb, const gint offset, size_t length);
Returns a buffer containing a copy of the given TVB bytes. The buffer is
allocated in the given wmem scope (see README.wmem for more information).
Pointer-retrieval:
/* WARNING! Don't use this function. There is almost always a better way.
* It's dangerous because once this pointer is given to the user, there's
* no guarantee that the user will honor the 'length' and not overstep the
* boundaries of the buffer. Also see the warning in the Portability section.
*/
const guint8* tvb_get_ptr(tvbuff_t *tvb, const gint offset, const gint length);
Length query:
Get amount of captured data in the buffer (which is *NOT* necessarily the
length of the packet). You probably want tvb_reported_length instead:
guint tvb_captured_length(const tvbuff_t *tvb);
Get reported length of buffer:
guint tvb_reported_length(const tvbuff_t *tvb);
1.4 Functions to handle columns in the traffic summary window.
The topmost pane of the main window is a list of the packets in the
capture, possibly filtered by a display filter.
Each line corresponds to a packet, and has one or more columns, as
configured by the user.
Many of the columns are handled by code outside individual dissectors;
most dissectors need only specify the value to put in the "Protocol" and
"Info" columns.
Columns are specified by COL_ values; the COL_ value for the "Protocol"
field, typically giving an abbreviated name for the protocol (but not
the all-lower-case abbreviation used elsewhere) is COL_PROTOCOL, and the
COL_ value for the "Info" field, giving a summary of the contents of the
packet for that protocol, is COL_INFO.
The value for a column can be specified with one of several functions,
all of which take the 'fd' argument to the dissector as their first
argument, and the COL_ value for the column as their second argument.
1.4.1 The col_set_str function.
'col_set_str' takes a string as its third argument, and sets the value
for the column to that value. It assumes that the pointer passed to it
points to a string constant or a static "const" array, not to a
variable, as it doesn't copy the string, it merely saves the pointer
value; the argument can itself be a variable, as long as it always
points to a string constant or a static "const" array.
It is more efficient than 'col_add_str' or 'col_add_fstr'; however, if
the dissector will be using 'col_append_str' or 'col_append_fstr" to
append more information to the column, the string will have to be copied
anyway, so it's best to use 'col_add_str' rather than 'col_set_str' in
that case.
For example, to set the "Protocol" column
to "PROTOFILTERNAME":
col_set_str(pinfo->cinfo, COL_PROTOCOL, "PROTOFILTERNAME");
1.4.2 The col_add_str function.
'col_add_str' takes a string as its third argument, and sets the value
for the column to that value. It takes the same arguments as
'col_set_str', but copies the string, so that if the string is, for
example, an automatic variable that won't remain in scope when the
dissector returns, it's safe to use.
1.4.3 The col_add_fstr function.
'col_add_fstr' takes a 'printf'-style format string as its third
argument, and 'printf'-style arguments corresponding to '%' format
items in that string as its subsequent arguments. For example, to set
the "Info" field to "<XXX> request, <N> bytes", where "reqtype" is a
string containing the type of the request in the packet and "n" is an
unsigned integer containing the number of bytes in the request:
col_add_fstr(pinfo->cinfo, COL_INFO, "%s request, %u bytes",
reqtype, n);
Don't use 'col_add_fstr' with a format argument of just "%s" -
'col_add_str', or possibly even 'col_set_str' if the string that matches
the "%s" is a static constant string, will do the same job more
efficiently.
1.4.4 The col_clear function.
If the Info column will be filled with information from the packet, that
means that some data will be fetched from the packet before the Info
column is filled in. If the packet is so small that the data in
question cannot be fetched, the routines to fetch the data will throw an
exception (see the comment at the beginning about tvbuffers improving
the handling of short packets - the tvbuffers keep track of how much
data is in the packet, and throw an exception on an attempt to fetch
data past the end of the packet, so that the dissector won't process
bogus data), causing the Info column not to be filled in.
This means that the Info column will have data for the previous
protocol, which would be confusing if, for example, the Protocol column
had data for this protocol.
Therefore, before a dissector fetches any data whatsoever from the
packet (unless it's a heuristic dissector fetching data to determine
whether the packet is one that it should dissect, in which case it
should check, before fetching the data, whether there's any data to
fetch; if there isn't, it should return FALSE), it should set the
Protocol column and the Info column.
If the Protocol column will ultimately be set to, for example, a value
containing a protocol version number, with the version number being a
field in the packet, the dissector should, before fetching the version
number field or any other field from the packet, set it to a value
without a version number, using 'col_set_str', and should later set it
to a value with the version number after it's fetched the version
number.
If the Info column will ultimately be set to a value containing
information from the packet, the dissector should, before fetching any
fields from the packet, clear the column using 'col_clear' (which is
more efficient than clearing it by calling 'col_set_str' or
'col_add_str' with a null string), and should later set it to the real
string after it's fetched the data to use when doing that.
1.4.5 The col_append_str function.
Sometimes the value of a column, especially the "Info" column, can't be
conveniently constructed at a single point in the dissection process;
for example, it might contain small bits of information from many of the
fields in the packet. 'col_append_str' takes, as arguments, the same
arguments as 'col_add_str', but the string is appended to the end of the
current value for the column, rather than replacing the value for that
column. (Note that no blank separates the appended string from the
string to which it is appended; if you want a blank there, you must add
it yourself as part of the string being appended.)
1.4.6 The col_append_fstr function.
'col_append_fstr' is to 'col_add_fstr' as 'col_append_str' is to
'col_add_str' - it takes, as arguments, the same arguments as
'col_add_fstr', but the formatted string is appended to the end of the
current value for the column, rather than replacing the value for that
column.
1.4.7 The col_append_sep_str and col_append_sep_fstr functions.
In specific situations the developer knows that a column's value will be
created in a stepwise manner, where the appended values are listed. Both
'col_append_sep_str' and 'col_append_sep_fstr' functions will add an item
separator between two consecutive items, and will not add the separator at the
beginning of the column. The remainder of the work both functions do is
identical to what 'col_append_str' and 'col_append_fstr' do.
1.4.8 The col_set_fence and col_prepend_fence_fstr functions.
Sometimes a dissector may be called multiple times for different PDUs in the
same frame (for example in the case of SCTP chunk bundling: several upper
layer data packets may be contained in one SCTP packet). If the upper layer
dissector calls 'col_set_str()' or 'col_clear()' on the Info column when it
begins dissecting each of those PDUs then when the frame is fully dissected
the Info column would contain only the string from the last PDU in the frame.
The 'col_set_fence' function erects a "fence" in the column that prevents
subsequent 'col_...' calls from clearing the data currently in that column.
For example, the SCTP dissector calls 'col_set_fence' on the Info column
after it has called any subdissectors for that chunk so that subdissectors
of any subsequent chunks may only append to the Info column.
'col_prepend_fence_fstr' prepends data before a fence (moving it if
necessary). It will create a fence at the end of the prepended data if the
fence does not already exist.
1.4.9 The col_set_time function.
The 'col_set_time' function takes an nstime value as its third argument.
This nstime value is a relative value and will be added as such to the
column. The fourth argument is the filtername holding this value. This
way, rightclicking on the column makes it possible to build a filter
based on the time-value.
For example:
col_set_time(pinfo->cinfo, COL_REL_TIME, &ts, "s4607.ploc.time");
1.5 Constructing the protocol tree.
The middle pane of the main window, and the topmost pane of a packet
popup window, are constructed from the "protocol tree" for a packet.
The protocol tree, or proto_tree, is a GNode, the N-way tree structure
available within GLIB. Of course the protocol dissectors don't care
what a proto_tree really is; they just pass the proto_tree pointer as an
argument to the routines which allow them to add items and new branches
to the tree.
When a packet is selected in the packet-list pane, or a packet popup
window is created, a new logical protocol tree (proto_tree) is created.
The pointer to the proto_tree (in this case, 'protocol tree'), is passed
to the top-level protocol dissector, and then to all subsequent protocol
dissectors for that packet, and then the GUI tree is drawn via
proto_tree_draw().
The logical proto_tree needs to know detailed information about the protocols
and fields about which information will be collected from the dissection
routines. By strictly defining (or "typing") the data that can be attached to a
proto tree, searching and filtering becomes possible. This means that for
every protocol and field (which I also call "header fields", since they are
fields in the protocol headers) which might be attached to a tree, some
information is needed.
Every dissector routine will need to register its protocols and fields
with the central protocol routines (in proto.c). At first I thought I
might keep all the protocol and field information about all the
dissectors in one file, but decentralization seemed like a better idea.
That one file would have gotten very large; one small change would have
required a re-compilation of the entire file. Also, by allowing
registration of protocols and fields at run-time, loadable modules of
protocol dissectors (perhaps even user-supplied) is feasible.
To do this, each protocol should have a register routine, which will be
called when Wireshark starts. The code to call the register routines is
generated automatically; to arrange that a protocol's register routine
be called at startup:
the file containing a dissector's "register" routine must be
added to "DISSECTOR_SRC" in "epan/dissectors/CMakeLists.txt";
the "register" routine must have a name of the form
"proto_register_XXX";
the "register" routine must take no argument, and return no
value;
the "register" routine's name must appear in the source file
either at the beginning of the line, or preceded only by "void "
at the beginning of the line (that would typically be the
definition) - other white space shouldn't cause a problem, e.g.:
void proto_register_XXX(void) {
...
}
and
void
proto_register_XXX( void )
{
...
}
and so on should work.
For every protocol or field that a dissector wants to register, a variable of
type int needs to be used to keep track of the protocol. The IDs are
needed for establishing parent/child relationships between protocols and
fields, as well as associating data with a particular field so that it
can be stored in the logical tree and displayed in the GUI protocol
tree.
Some dissectors will need to create branches within their tree to help
organize header fields. These branches should be registered as header
fields. Only true protocols should be registered as protocols. This is
so that a display filter user interface knows how to distinguish
protocols from fields.
A protocol is registered with the name of the protocol and its
abbreviation.
Here is how the frame "protocol" is registered.
int proto_frame;
proto_frame = proto_register_protocol (
/* name */ "Frame",
/* short name */ "Frame",
/* abbrev */ "frame" );
A header field is also registered with its name and abbreviation, but
information about its data type is needed. It helps to look at
the header_field_info struct to see what information is expected:
struct header_field_info {
const char *name;
const char *abbrev;
enum ftenum type;
int display;
const void *strings;
guint64 bitmask;
const char *blurb;
.....
};
name (FIELDNAME)
----------------
A string representing the name of the field. This is the name
that will appear in the graphical protocol tree. It must be a non-empty
string.
abbrev (FIELDFILTERNAME)
--------------------
A string with a filter name for the field. The name should start
with the filter name of the parent protocol followed by a period as a
separator. For example, the "src" field in an IP packet would have "ip.src"
as a filter name. It is acceptable to have multiple levels of periods if,
for example, you have fields in your protocol that are then subdivided into
subfields. For example, TRMAC has multiple error fields, so the names
follow this pattern: "trmac.errors.iso", "trmac.errors.noniso", etc.
It must be a non-empty string.
type (FIELDTYPE)
----------------
The type of value this field holds. The current field types are:
FT_NONE No field type. Used for fields that
aren't given a value, and that can only
be tested for presence or absence; a
field that represents a data structure,
with a subtree below it containing
fields for the members of the structure,
or that represents an array with a
subtree below it containing fields for
the members of the array, might be an
FT_NONE field.
FT_PROTOCOL Used for protocols which will be placing
themselves as top-level items in the
"Packet Details" pane of the UI.
FT_BOOLEAN 0 means "false", any other value means
"true".
FT_FRAMENUM A frame number; if this is used, the "Go
To Corresponding Frame" menu item can
work on that field.
FT_CHAR An 8-bit ASCII character. It's treated similarly to an
FT_UINT8, but is displayed as a C-style character
constant.
FT_UINT8 An 8-bit unsigned integer.
FT_UINT16 A 16-bit unsigned integer.
FT_UINT24 A 24-bit unsigned integer.
FT_UINT32 A 32-bit unsigned integer.
FT_UINT40 A 40-bit unsigned integer.
FT_UINT48 A 48-bit unsigned integer.
FT_UINT56 A 56-bit unsigned integer.
FT_UINT64 A 64-bit unsigned integer.
FT_INT8 An 8-bit signed integer.
FT_INT16 A 16-bit signed integer.
FT_INT24 A 24-bit signed integer.
FT_INT32 A 32-bit signed integer.
FT_INT40 A 40-bit signed integer.
FT_INT48 A 48-bit signed integer.
FT_INT56 A 56-bit signed integer.
FT_INT64 A 64-bit signed integer.
FT_FLOAT A single-precision floating point number.
FT_DOUBLE A double-precision floating point number.
FT_ABSOLUTE_TIME An absolute time from some fixed point in time,
displayed as the date, followed by the time, as
hours, minutes, and seconds with 9 digits after
the decimal point.
FT_RELATIVE_TIME Seconds (4 bytes) and nanoseconds (4 bytes)
of time relative to an arbitrary time.
displayed as seconds and 9 digits
after the decimal point.
FT_STRING A string of characters, not necessarily
NULL-terminated, but possibly NULL-padded.
This, and the other string-of-characters
types, are to be used for text strings,
not raw binary data.
FT_STRINGZ A NULL-terminated string of characters.
The string length is normally the length
given in the proto_tree_add_item() call.
However if the length given in the call
is -1, then the length used is that
returned by calling tvb_strsize().
This should only be used if the string,
in the packet, is always terminated with
a NULL character, either because the length
isn't otherwise specified or because a
character count *and* a NULL terminator are
both used.
FT_STRINGZPAD A NULL-padded string of characters.
The length is given in the proto_tree_add_item()
call, but may be larger than the length of
the string, with extra bytes being NULL padding.
This is typically used for fixed-length fields
that contain a string value that might be shorter
than the fixed length.
FT_STRINGZTRUNC A NULL-truncated string of characters.
The length is given in the proto_tree_add_item()
call, but may be larger than the length of
the string, with a NULL character after the last
character of the string, and the remaining bytes
being padding with unspecified contents. This is
typically used for fixed-length fields that contain
a string value that might be shorter than the fixed
length.
FT_UINT_STRING A counted string of characters, consisting
of a count (represented as an integral value,
of width given in the proto_tree_add_item()
call) followed immediately by that number of
characters.
FT_ETHER A six octet string displayed in
Ethernet-address format.
FT_BYTES A string of bytes with arbitrary values;
used for raw binary data.
FT_UINT_BYTES A counted string of bytes, consisting
of a count (represented as an integral value,
of width given in the proto_tree_add_item()
call) followed immediately by that number of
arbitrary values; used for raw binary data.
FT_IPv4 A version 4 IP address (4 bytes) displayed
in dotted-quad IP address format (4
decimal numbers separated by dots).
FT_IPv6 A version 6 IP address (16 bytes) displayed
in standard IPv6 address format.
FT_IPXNET An IPX address displayed in hex as a 6-byte
network number followed by a 6-byte station
address.
FT_GUID A Globally Unique Identifier
FT_OID An ASN.1 Object Identifier
FT_REL_OID An ASN.1 Relative Object Identifier
FT_EUI64 A EUI-64 Address
FT_AX25 A AX-25 Address
FT_VINES A Vines Address
FT_SYSTEM_ID An OSI System-ID
FT_FCWWN A Fibre Channel WWN Address
Some of these field types are still not handled in the display filter
routines, but the most common ones are. The FT_UINT* variables all
represent unsigned integers, and the FT_INT* variables all represent
signed integers; the number on the end represent how many bits are used
to represent the number.
Some constraints are imposed on the header fields depending on the type
(e.g. FT_BYTES) of the field. Fields of type FT_ABSOLUTE_TIME must use
'ABSOLUTE_TIME_{LOCAL,UTC,DOY_UTC}, NULL, 0x0' as values for the
'display, 'strings', and 'bitmask' fields, and all other non-integral
types (i.e.. types that are _not_ FT_INT* and FT_UINT*) must use
'BASE_NONE, NULL, 0x0' as values for the 'display', 'strings', 'bitmask'
fields. The reason is simply that the type itself implicitly defines the
nature of 'display', 'strings', 'bitmask'.
display (FIELDDISPLAY)
----------------------
The display field has a couple of overloaded uses. This is unfortunate,