summaryrefslogtreecommitdiffstats
path: root/doc/packet_builder_yaml.asciidoc
blob: ed80358e009c0f421270f25c6ef8f6ea95630510 (plain)
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
Packet Builder Language
=======================
:author: hhaim
:email: <hhaim@cisco.com>
:revnumber: 0.04
:quotes.++:
:numbered:


== change log

include::trex_ga.asciidoc[]


[options="header",cols="^1,^h,a"]
|=================
| Version |  name   |  meaning
| 0.01    |  hhaim |
- first version
| 0.02    | hhaim
|
- change the bool fields to properties
- add external/internal  property
- add const property  ( instead cant_change)
- change  TLV property - now learn the prev header
- add choice of next protocol that is not base on a field ( TCP->IP->TCP)
| 0.03    | ybrustin
|
- add MAC address regexp
- add gui_representation class with data_type, form_type, combobox_values, data_type_regexp items to describe GUI view of field
- rename choice attribute to value_based_next_header
- fixed some typos
| 0.04    | ybrustin
|
- change value_based_next_header, combobox_values (to be consistent with value_based_next_header) to dictionary
- added value_based_next_class for options
- move 'help' attribute to gui_representation
- add link to headers.yaml (references at bottom of the page)

|=================


== A file format for GUI packet builder

=== Introduction

We would like a file that will be read by GUI and will give us the ability to build packets using GUI

The format should be *YAML*


=== High Level Requirement

* Define a YAML object format for dynamic building of packets and a program that change various fields
* Ability to *parse* back the same buffer that was created using this tool (reversibility)
** Ability to load packet from a pcap file and parse it
* Ability to save the packet to a pcap file
* Ability to save the packet and program in JSON format (same JSON-RPC format)
* Set a value for any field of any protocol
* Vary packet fields across packets at run time e.g. changing IP/MAC addresses
* Stack protocols in any arbitrary order define in YAML format

=== Header that should be supported (first phase)

==== L2

* Ethernet
* 802.3
* LLC SNAP
* VLAN (with QinQ) stack
* MPLS stack

==== L3

* ARP
* IPv4
* IPv6 (4x header)
* IP-in-IP a.k.a IP Tunnelling (6over4, 4over6, 4over4, 6over6)

==== L4

* TCP
* UDP
* ICMPv4
* ICMPv6
* IGMP

==== L7  anchor:Payload[]

* Any text based protocol (HTTP, SIP, RTSP, NNTP etc.)
** random string
** repeat string

* Pattern Binary
** repeat of value (e.g 0x55)
** random
** seq (1,2,3,3,4)
** User Hex Dump editor


=== YAML Format

==== Header section

.Default Types  anchor:Types[]
[options="header",cols="1,2,3"]
|=================
| Field Name        |   meaning                                        | size in bits
| bit               |  describe the header object e.g tcp              |  1
| uint8             |  describe the header object e.g tcp              |  8
| uint16            |  the name in the GUI                             |  16
| uint32            |  sub fields of this header                       |  32
| uint64            |  sub fields of this header                       |  64
| other class type  | name of other class. for example, "c-mac-addr"; take fields from there, optionally overload them later  | The size taken from that class
| Payload           |     xref:Payload[Payload]                        | total packet size - all header until now
| vlen_t            | in case of varible size header this include the size to the end of varible size header see example xref:IpvOption[Ipv4Option] |total size of the object
|=================


.Default Data_Type anchor:Data_Type[]
[options="header",cols="1,2"]
|=================
| Field Name               | meaning
| none                     |  use Hex Editor as Types
| ipv4_t                   |  4 decimals 0-255 each
| mac_addr_t               |  ([0-9a-fA-F]\{2\}:)\{5\}[0-9a-fA-F]\{2\}
| ipv4_mask_t              |  should match uint32 type
| ipv6_t                   |  should have 16 bytes field size 8x16
| ipv6_mask_t              |  should have 16 bytes field size 8x16
| another header class     |  sub fields of this header
| char_t                   | array of bytes , look into the array_size of cost string
| var_char_t               | array based on a field value look into
| regexp_t                 |  define a Java function that converts a reg exp string to a buffer see here  xref:GenRegExp[RegExp]
|=================

.Default Form_Type anchor:Form_Type[]
[options="header",cols="1,3"]
|=================
| Field Name          |  meaning
| none                |  simple editing field
| combo_with_edit     |  combo box with predefined choices, can edit the field value manually
| combo_without_edit  |  combo box with predefined choices, can [underline]#not# edit the field value manually
| checkbox            |  toggle bits values, if item is array of bits, display several checkboxes per number of bits
|=================


.Default Gui_Representation anchor:Gui_Representation[]
[options="header",cols="1,^1,5,^1,10"]
|=================
| Field Name         | value type      | meaning                                            | Link                      | Additional info
| help               | string          | the name in the GUI                                |                           |
| data_type          | string          | how to represent data                              | xref:Data_Type[Data_Type] | data_type could get data_type_regexp e.g data_type = "ipv4"; data_type = "regexp" data_type_regexp = "string that define regexp and Java function"
| form_type          | string          | which editing form to use                          | xref:Form_Type[Form_Type] | for example for ip address use combobox with option to edit value manually or choose: key "localhost" value "127.0.0.1" etc.
| combobox_values    | dictionary      | pairs of 'key - value' for combo_with/without_edit |                           |
| data_type_regexp   | string          | in case it is reg_exp the name of the function     | xref:GenRegExp[GenRegExp] |
|=================


.Default Properties    anchor:Properties[]
[options="header",cols="1,7"]
|=================
| Field Name             | meaning
| ipv4_checksum          | auto calculates checksum on this header Ipv4 type
| tcp_checksum           | calculate TCP checksum
| udp_checksum           | calculate UDP checksum
| ipv4_total_length      | calculate ipv4 total length this pkt_size = header  + reset of packet
| tlv                    | TLV length of the header (inlcudes the prev field length) example ip-option, tcp-option
| le                     | little endian. deault is big
| const                  | const field for example the 4 version of ipv4 header - this GUI won't give option to change this field
| external               | marks the header as an external header for the GUI. for example IPv4 is external header and mac-addr is internal header ( compose external header)
|=================


.Field_Type  anchor:Field_Type[]
[options="header",cols="1,^1,30,^1,^1,30"]
|=================
| Field Name         | value type      |  meaning                                           | Default Value | Link | Example
| class              | string          | describe the class type                            |   in case class is defined no need to have name and vise versa           |      | class : tcp
| name               | string          | describe the instance name                         |   in case class is defined no need to have name and vise versa          |      | name : tcp
| array_size         | integer         | how many objects of this type, default value is 1  |  1            |      | array_size : 6 in case of mac-addr
| type               | string          | type, see  Types  define the size                  |   "uint8_t"   |  xref:Types[Types]   | type : "uint32_t" type : "mac_addr"
| gui_representation | dictionary      | description of how to view/edit data in GUI        |           | xref:Gui_Representation[Gui_Representation] | xref:Gui_Representation_Example[Gui_Representation_Example]
| default            | array/value     | default value in the packets , you can override value for subfields in parent see example
| [0 ]x header size  |   |    xref:Overide_Subfields_Example[Overide_Subfields_Example]
| properies          | array of string like masks
| properies of this fields             |  []        | xref:Properties[Properties] | ["le","external"] , ["tlv","le","const"]
| value_based_next_header              | dictionary |   define the next protocol based on a field value                    |  none         | xref:Value_Based_Next_Header[Value_Based_Next_Header]  |
| value_based_next_class               | dictionary |   define the next class based on a field value (useful for options)  |  none         | xref:Value_Based_Next_Class[Value_Based_Next_Class]  |
| next_headers       | string or type  |   a name of class that define the next or just an array                           |  "none"       | xref:Next_headers[Next_headers]  |
| fields             | array           | array of Field_Type                                                               |   []          |        | fields : [  ]
| offset             | integer/string  |   offset into the packet in bits, in case of auto add base of prev fields         |   "auto"      |        |
| option             | string          |   a java code that define a way to calculate varible size                         |   "none"      |        |  |
|=================


.Field_Type  anchor:ConstHeadesClass[]
[options="header",cols="^1,^10"]
|=================
| Field Name | value type
| "root"     | the root pointer to the start of blocks L2/802.3 etc
| "end"      | end TLV headers
| "payload"   | the rest of the packets as buffer/string etc
|=================


.Next_headers anchor:Next_headers[]
Example of Next_headers
[source,python]
----

 - class : "next-example-t-1"
   gui_representation:
       help : "next-example-t-1"
   next_headers : ["ipv4", "ipv6, "tcp"]

# option 1 define in the header itself
 - class : "tcp"
   gui_representation:
       help : "TCP header"
   properies : ["external"]
   next_headers : ["ipv4", "ipv6, "tcp"]
   fields :
        - name : "ver"

# option 2 define throw a class
 - class : "tcp"
   gui_representation:
       help : "TCP header"
   properies : ["external"]
   next_headers : "next-example-t-1" #
   fields :
        - name : "ver"
----


.Value_Based_Next_Header anchor:Value_Based_Next_Header[]
Example of value_based_next_header
[source,python]
----
        value_based_next_header:
            0x0800: 'ipv4'# name of an external or internal class , the GUI should distinct betwean internal and external
            0x0806: 'arp'
            0x86DD: 'ipv6'
            0x8100: 'vlan'
            0x8847: 'mpls unicast'
            default: 'payload' # if no match for any of above

----


.Generic RegExp Edit Field anchor:GenRegExp[]

This will define a regexp that match for user input and how to converts it to buffer of bytes

[source,python]
----

class MyClass : public RegExpBase {
  public:


  string get_reg_exp_string( ) {
    return ((\d){1-3})[.]((\d){1-3})[.]((\d){1-3})[.]((\d){1-3}))
  }

  # in case of match
  buffer get_buffer(){
     g= [get_group()[1].to_int()*256,get_group()[1].to_int()]
     # return list
     return (g)
  }

}

----



==== Relations between object headers

There would be a root object to point to possible starting headers


[source,python]
----

-  class : "root"
   gui_representation:
       help  : "Root"
   next_headers  : [ "ethernet", "llc", "_802-3"]
----

So in a way you could define a tree like this

[source,python]
----

root -> L2 (  Ethernet   , 802.3 , LLC SNAP  )
                |( by field )
                |
                  ------------------------------------- ( VLAN (with QinQ), MPLS , ipv4, ipv6,     ARP , ICMP )
                                                                                  |   |               |     |
                                                                                  |   ipv4/ipv6       -     -
                                                                                  |     |
                                                                                  |    |
  [Possibility - Ethernet/802.3/LLC SNAP)                                          |    UDP/TCP/Pyload
 Object                                                                            |     |
  for each option there tree of all the option                                      --- -
----


==== Rules

* The size of the header and offset is automatically defined in default by the order of the fields ( inc by type size multiply by array_size)
* It can be overrided by offset field ( put offset in the object ) and then an more advanced field can be shown earlier in the GUI
* The packet size is defined before the headers.  Header Should not be allowed to be added if the size + header size is bigger than packet size
* "Payload" is predefined Fields that take the reset of the packet and user can edit it ( see xref:Payload[Payload] )
* There would be a spare field in the Stream object so GUI could add more metadata for reconstructing the builder types
  for example in this example Ethrenet/IP/TCP/IP/TCP  you can't extrac from buffer alone that Payload is IP/TCP only the builder known that in build time.
* Ip total length need to keep the total_pkt_size - this ip header . this should work for internal header too.
* When GUI add header ("external") the total size of this header should be calculated ( varible size should be given a default - ipv4)


=== Examples


==== TLV (Ip option) anchor:IpvOption[], value_based_next_class anchor:Value_Based_Next_Class[]


IP-option see link:http://tools.ietf.org/html/rfc791[ip_option]

0 : END

1 : Length 1

other : Byte : Length ( +first) |option



[source,python]
----

 - class : "ip_option_131"
   gui_representation:
       help  : "ip_option"
   fields :
         - name : "length"    # tree with leaf of bits
           gui_representation:
               help : "length"
           type : uint8
           properties : ["tlv"] # the length include the prev field size (8 byte)

         - name : "pointer"    # tree with leaf of bits
           type : uint8

         - name : "buffer"    # tree with leaf of bits
           type : "tlv_reset"

 - class : "default_ip4_option_tlv"
   gui_representation:
       help  : "ip_option"
   fields :
         - name : "length"    # tree with leaf of bits
           gui_representation:
               help : "length"
           type : uint8
           properties : "tlv" # the length include the prev field size (8 byte)

         - name : "buffer"    # tree with leaf of bits
           type : "vlen_t"


 - class : "ip_option"
   gui_representation:
       help  : "ip_option"
   type : uint8
   default : [0x01]
   value_based_next_class :
       0x00  : "end"   # reserve name for ending the loop
       0x01  : "ip_option"   # back to this header
       0x131 : "ip_option_131"
       0x0812: "gre"
       default : "default_ip4_option_tlv"


----

* case of varible length field ip_option example



==== Example TCP/IP


[source,python]
----

 - class : "c-mac-addr"
   type : "uint8"
   array_size : 6
   default : [0x00, 0x00, 0x01, 0x00, 0x00, 0x00]
   gui_representation:
      data_type  : "mac-addr_t" # format ([0-9a-fA-F]{2}:){5}[0-9a-fA-F]{2}
      help  : "Mac addrees"


 - class : "ethernet"
   gui_representation:
       help : "Ethernet-L2"
   properties: ['external']
   fields :
        - name : "Dst"
          gui_representation:
              help : "destination mac"
          type : "c-mac-addr"

        - name : "Src"
          gui_representation:
              help : "source mac"
          type : "c-mac-addr"

        - name: "Ethertype"
          gui_representation:
              help: "Ethertype"
          type: "uint16"
          default: [0x0800]
          value_based_next_header :
                0x0800  : "ipv4"
                0x86DD  : "ipv6"
                0x8100  : "vlan"
                0x8847  : "mpls" #unicast
                default : "payload"


 - class : "ipv4"
   gui_representation:
       help : "Ipv4"
   fields :
        - name : "ver"
          gui_representation:
              help : "Version"
          type : "bit"
          array_size : 4
          default : [0, 1, 0, 0]
          properties : ["const"]

         - name : "ihl"
          type : "bit"
          array_size : 4
          default : [0, 1, 1, 1]
          properties : ["ipv4_ihl"]
          gui_representation:
              help : "IHL"
              form_type: "checkbox"

          ..

         - name : "hdr_chsum"
          gui_representation:
              help : "Header Checksum"
          default : [0x00,0x00]
          properties : ["ipv4_check_sum", "const"]

         - name : "total_len"
          gui_representation:
              help : "Total Length"
          default : [0x00,0x00]
          properties : ["ipv4_total_len", "const"] # auto calculate total_size-offset_header

         - name : "protocol"
          type : uint8
          default : 0x06
          value_based_next_header : &ipv4_next_header
               0x06  : "tcp"
               0x11  : "udp"
               0x29  : "ipv6"
               0x2F  : "gre"
               default : "payload"
          gui_representation:
              help : "IPv4 next Protocol"
              form_type: "combo_without_edit"
              combobox_values:
                <<: *ipv4_next_header # take same choices as value_based_next_header

         - name : "src_addr"
          type : uint32
          default : [16, 0, 0, 0]
          gui_representation:
              help : "Source Address"
              data_type  : "ipv4" # reserve

         - name : "dst_addr"
          default : [48, 0, 0, 0]
          type : uint32
          gui_representation:
              help : "Destination Address"
              data_type  : "ipv4" # reserve
              form_type : "combo_with_edit"
              combobox_values:
                    [127, 0, 0, 1]: 'localhost'
                    [255, 255, 255, 255]: 'broadcast'


 - class : "tcp"
   gui_representation:
       help : "TCP"
   properties : ["external"]
   fields :
         - name : "src_port"
          gui_representation:
              help : "Source Port"
          default : [0x30,0x00]
          type : uint16

         - name : "dest_port"
          gui_representation:
              help : "Source Port"
          default : [0x30,0x00]
          type : uint16

         - name : "seq"
          gui_representation:
              help : "Seq Number"
          type : uint32
          default : [0x30,0x00,00,00]

         - name : "ack"
          gui_representation:
              help : "Ack Number"
          type : uint32
          default : [0x30,0x00,00,00]

        ...

         - name : "flags"    # tree with leaf of bits
          gui_representation:
              help : "Ack Number"
          type : uint8
          default : [0x30]
          fields :
                 - name : "urg"
                  help : "URG"
                  type  : bit
                  default : [0x0]

                 - name : "ack"
                  help : "ACK"
                  type  : bit
                  default : [0x1]
                  ..

         - name : "checksum"
          gui_representation:
              help : "TCP Checksum"
          type : uint16
          default : [0x00,0x00]
          properties : ["tcp_checksum"] # auto calculate total_size-offset_header


-  class : "root" # reserve
   gui_representation:
       help  : "Root"
   next_headers : [ "ethrenet" ,"llc","_802-3"]
---------------------------


==== Overide subfields example anchor:Overide_Subfields_Example[]

In this example parent class default value overrides default values of sub-fields ( 2 different mac-addr)

[source,python]
----

 - class : "c-mac-addr"
   type : "uint8"
   array_size : 6
   gui_representation:
      help  : "Mac addrees"
      data_type  : "mac-addr_t" # format ([0-9a-fA-F]{2}:){5}[0-9a-fA-F]{2}
   default : [0x00,0x00,0x01,0x00,0x00,0x00]


 - class : "ethernet"
   gui_representation:
       help : "Ethernet-L2"
   properties : ["external"]
   default : [0x00,0x01,0x01,0x00,0x00,0x00, 0x00,0x02,0x02,0x00,0x00,0x00 ,0x08,00] # change the default of sub-fields . it is const size
   fields :
        - name : "Dst"
          gui_representation:
              help : "destination mac"
          type : "c-mac-addr"

        - name : "Src"
          gui_representation:
              help : "source mac"
          type : "c-mac-addr"

        - name : "ip_protocol"
          type : "uint16_t"
          default : [0x08,0x00]
          value_based_next_header :
                0x0800  : "ipv4"
                0x86DD  : "ipv6"
                0x8100  : "vlan"
                0x8847  : "mpls unicast"
                default : "payload"
----

==== Gui Representation example anchor:Gui_Representation_Example[]
[underline]#In YAML:#
[source,python]
----
  - name: 'Flags'
    type: 'bit'
    array_size: 3
    gui_representation:
        help: 'IPv4 Flags'
        form_type: 'checkbox' # can check each bit


  - name: 'dst_addr'
    default: [48, 0, 0, 0]
    type: uint32
    gui_representation:
        help: 'IPv4 Destination Address'
        data_type: 'ipv4_t' # special representation case, show as 4 decimal numbers
        form_type: 'combo_with_edit' # can choose from pre-defined values or edit manually
        combobox_values:
            [127, 0, 0, 1]: 'localhost'
            [255, 255, 255, 255]: 'broadcast'


  - name: 'protocol'
    type: uint8
    default: 0x06
    value_based_next_header: &ipv4_next_header
        0x06: 'tcp'
        0x11: 'udp'
        default : "payload"
    gui_representation:
        help: 'IPv4 Protocol Field'
        form_type: 'combo_without_edit' # choose from supported protocols, no manual edit
        combobox_values:
            <<: *ipv4_next_header # take same choices as value_based_next_header
----

[underline]#In GUI:#

checkbox for bits:

image:images/checkbox.jpg[]

editing in combo-box:

image:images/combo_button_editing.jpg[]

choosing from predefined values:

image:images/combo_button_choosing.jpg[]

==== Union base

TBD



=== Resource
*  link:yaml/headers.yaml[headers.yaml]
*  link:https://wireedit.com/[WireEdit]
*  link:http://ostinato.org/[ostinato]
*  link:http://www.slideshare.net/nlekh/ixiaexplorer[IxExplorer]