Age | Commit message (Collapse) | Author | Files | Lines |
|
Add trafgen_l7.c module with DNS proto header generation with
support of filling DNS query/answer/authority/additional sections
as sub headers.
Introcuded new concept as 'sub header' which is needed to easy handle
DNS sections which might be added on-demand, and to simplify using
sub-header as regular header with a fields, offset, etc. There is a
parent header which contains array of pointers of sub-headers, and the
array is ordered as they are located in the parent header. The
sub-headers mostly encapsulated by the parent header which 'knows'
the semantic of them. The new proto_hdr->push_sub_header(...) callback
was added to tell the parent header to push the sub-header's fields,
sub-header also may have proto_ops which must be filled by the parent.
This sub-header concept might be used in the future if it will be needed
to support DHCP, WLAN headers.
There are 4 kinds of DNS sub-headers - query, answer, authority,
additional. 'id' of each sub-header is used to only differentiate these
types of sections. These sections have strict order inside DNS header,
and there was added the proto_hdr_move_sub_header(...) to sort them in
required order.
Actually there are only 2 proto_hdr's which describes 4 DNS sections -
query & rrecord, because rrecord covers another 3 - answer, auhority,
additional which have the same layout.
Signed-off-by: Vadim Kochan <vadim4j@gmail.com>
Signed-off-by: Tobias Klauser <tklauser@distanz.ch>
|
|
It is quite tricky to set field value with a variable length
(i.e. DNS query name), to make it possible the field
needs to be added to header with 'len=0' in that case there
will be no any payload allocation, but only while setting the field
value the packet will be appended with a real length bytes and after
the field needs to be relocated to the right place.
Also add 'len' parameter to *_set_bytes(...) functoins to have better
control over it.
Signed-off-by: Vadim Kochan <vadim4j@gmail.com>
Signed-off-by: Tobias Klauser <tklauser@distanz.ch>
|
|
Use proto_field_set_xxx(field, ...) instead of
proto_hdr_field_set_xxx(hdr, fid, ...) to be more generic and do not
depend on 'hdr' variable.
Signed-off-by: Vadim Kochan <vadim4j@gmail.com>
Signed-off-by: Tobias Klauser <tklauser@distanz.ch>
|
|
tun interface does not have Ethernet header so lets push Ethernet
header only if device supports this.
Signed-off-by: Vadim Kochan <vadim4j@gmail.com>
Signed-off-by: Tobias Klauser <tklauser@distanz.ch>
|
|
Extend proto field expression to:
proto_field[{index}:{len}] = {func}
which allows to specify function on the field offset via index
and value length (default is 1 - 1 byte). This rule is optional.
It was needed to keep of proto_field's copies in packet_dyn->fields
instead of original fields which allows to scpecify different functions
on the different parts of same field, also the copy of original
proto_field allows to set custom length/pkt_offset which makes such
field behave as virtual sub-field of the original one with different
length/pkt_offset but point to the same piece of header.
Signed-off-by: Vadim Kochan <vadim4j@gmail.com>
Signed-off-by: Tobias Klauser <tklauser@distanz.ch>
|
|
Add proto_field_xxx functions to set/get value via specified
proto_field only.
It is good to have such API in case if application needs to set/get
value for some custom proto_field instance.
Signed-off-by: Vadim Kochan <vadim4j@gmail.com>
Signed-off-by: Tobias Klauser <tklauser@distanz.ch>
|
|
Rename all proto_field_xxx(...) functions to proto_hdr_field(...).
It is good for 2 reasons:
1) proto_hdr_field_xxx naming is more consistent as
it is related to proto_hdr API.
2) It makes possible to introduce proto_field_xxx API
which will operate only with struct proto_field.
Signed-off-by: Vadim Kochan <vadim4j@gmail.com>
Signed-off-by: Tobias Klauser <tklauser@distanz.ch>
|
|
Add PFC header fields setting (prio vector, time per priority).
By default Ethernet header is pushed with required fields.
Signed-off-by: Vadim Kochan <vadim4j@gmail.com>
Signed-off-by: Tobias Klauser <tklauser@distanz.ch>
|
|
Add EEE802.3X Ethernet MAC Control PAUSE frame proto header with two
fields - opcode & time.
By default Ethernet header is pushed on header init.
Signed-off-by: Vadim Kochan <vadim4j@gmail.com>
Signed-off-by: Tobias Klauser <tklauser@distanz.ch>
|
|
Changed parsing logic of field value expression to be more generic. Such
approach will allow to easy extend field value expression to support
dynamic field functions.
Signed-off-by: Vadim Kochan <vadim4j@gmail.com>
Signed-off-by: Tobias Klauser <tklauser@distanz.ch>
|
|
Added proto_upper_header() function to fetch upper proto header.
It will be used by IPv4/IPv6 proto header to notify UDP/TCP proto
headers to invalidate L4 csum when L3 pseudo header field was changed.
Signed-off-by: Vadim Kochan <vadim4j@gmail.com>
Signed-off-by: Tobias Klauser <tklauser@distanz.ch>
|
|
Extended struct proto_hdr with 'index' field which is used for faster
lookup of lower header without doing a loop.
Signed-off-by: Vadim Kochan <vadim4j@gmail.com>
Signed-off-by: Tobias Klauser <tklauser@distanz.ch>
|
|
Handle 'field_changed' callback to check if IPv4 csum is needed to be
recalculated, if so - update it on 'packet_update' event.
Added 'is_csum_valid' to proto_hdr struct to check if csum needs to be
updated.
Signed-off-by: Vadim Kochan <vadim4j@gmail.com>
Signed-off-by: Tobias Klauser <tklauser@distanz.ch>
|
|
Add dynamic proto field function which can generate random value in
specified range (default 0 - MAX_UINT32).
Signed-off-by: Vadim Kochan <vadim4j@gmail.com>
Signed-off-by: Tobias Klauser <tklauser@distanz.ch>
|
|
Implement incrementing of proto field at runtime with min & max
parameters, by default if the 'min' parameter is not specified then
original value is used. For fields which len is greater than 4 - last 4
bytes are incremented as 4 byte value (this trick is used to increment
MAC/IPv6 addresses).
Signed-off-by: Vadim Kochan <vadim4j@gmail.com>
Signed-off-by: Tobias Klauser <tklauser@distanz.ch>
|
|
Add basic infrastructure for update proto field value at runtime by
dynamic field function.
Extended 'struct packet_dyn' with proto fields which has dynamically
changing values at runtime.
Added 'field_changed' callback for proto header which may be used for
check if csum updating is needed. This callback is called after field
was changed at runtime.
Added 'packet_update' callback to let proto header know when to apply
final proto header changes at runtime (e.g. - csum update).
Signed-off-by: Vadim Kochan <vadim4j@gmail.com>
Signed-off-by: Tobias Klauser <tklauser@distanz.ch>
|
|
Currently struct proto_hdr is used twofold:
1) Statically define protocol behavior, i.e. all the *_hdr definitions in
trafgen_l{2,3,4}.c which map a protocol id/layer to a set of callback
functions.
2) For each packet created at parse time the struct is memcpy()'ed
(including all the static information from 1) and then used to store
dynamic information at parse/run time.
Thus, struct proto_hdr members such as the proto id, layer and the
pointers callback functions get copied for each created packet (in
addition to the other fields which get changed during parsing). Also,
static/dynamic information get mixed and we e.g. can't make the protocol
definitions const to ensure they'll not get changed by mistake.
Rather than copying the struct proto_hdr for every packet, clearly
separate the two purposes defined above by splitting struct proto_hdr
into two structs:
1) struct proto_ops for the static (const) protocol behavior definition
2) struct proto_hdr (reduced) for dynamic information
struct proto_hdr keeps a pointer to the corresponding proto_ops instance
and uses it to execute the corresponding callbacks.
Reference: https://groups.google.com/forum/#!msg/netsniff-ng/20RvwJdh50Y/eMkbmKSaBgAJ
Acked-by: Vadim Kochan <vadim4j@gmail.com>
Signed-off-by: Tobias Klauser <tklauser@distanz.ch>
|
|
Make the __proto_field_set_bytes() take a const uint8_t *bytes pointer
and also changed all callers accordingly.
Signed-off-by: Tobias Klauser <tklauser@distanz.ch>
|
|
Protocols are registered early at startup and aren't changed at runtime.
In order to speed up lookup while parsing, store the pointers to the
protocol definitions (struct proto_hdr) in an array, indexed by protocol
id rather than in a linked list.
Signed-off-by: Tobias Klauser <tklauser@distanz.ch>
|
|
Use a module variable to access the proto context instead of storing a
pointer in every header.
Signed-off-by: Tobias Klauser <tklauser@distanz.ch>
|
|
Using of current_packet() is not possible for dynamically updated fields
so we need to keep the packet index in proto_hdr struct to reference the
correct packet.
Signed-off-by: Vadim Kochan <vadim4j@gmail.com>
Signed-off-by: Tobias Klauser <tklauser@distanz.ch>
|
|
It is potentially dangerous to use the user specified IHL field for
csum calculation, as it might lead to read buffer overflows.
Instead introduce and use the len field in struct proto_hdr which is
calculated automatically after the header is built.
Signed-off-by: Vadim Kochan <vadim4j@gmail.com>
[tk: reword commit message]
Signed-off-by: Tobias Klauser <tklauser@distanz.ch>
|
|
Support for generating ICMPv4 headers using the 'icmp4()/icmpv4()'
trafgen generation functions.
Fields supported:
type Set type field (default 0: Echo reply)
Supported keywords: echorequest, echoreply
code Set code field (default 0)
csum Set checksum field (calculated by default)
mtu Set mtu field for destination unreachable (default 0)
seq Set sequence field (default 0)
id Set identifier field (default 0)
addr Set redirect address (default 0.0.0.0)
Example (send ping request):
{ icmpv4(echorequest, seq=1, id=1326) }
Signed-off-by: Vadim Kochan <vadim4j@gmail.com>
[tk: squash commits, consistency between functionality and docu]
Signed-off-by: Tobias Klauser <tklauser@distanz.ch>
|
|
Support for generating simple ICMPv6 headers using the 'icmp6()/icmpv6()'
trafgen generation function.
Fields supported:
mtype Message type (default: 0)
Supported keywords: echorequest, echoreply
code Code (default: 0)
csum Message checksum (calculated by default)
Examples:
{ eth(), ipv6(daddr=::1), icmpv6(echorequest), 42, 42, 0, 0 }'
If not explicitely specified, the lower header is initialized as Ethernet.
Suggested-by: Daniel Borkmann <daniel@iogearbox.net>
Signed-off-by: Tobias Klauser <tklauser@distanz.ch>
|
|
Support for generating simple IPv6 headers using the 'ip6()/ipv6()'
trafgen generation function.
Fields supported:
ver|version Version (default: 6)
tc|tclass Traffic class (default: 0)
fl|flow Flow Label (default: 0)
len|length Payload length (calculated by default)
nh|nexthdr Type of next header (default: 0)
hl|hoplimit|ttl Hop Limit, TTL (default: 0)
sa|saddr Source IPv6 address (default: device address)
da|daddr Destination IPv6 address (default: 0:0:0:0:0:0:0:0)
Examples:
{ eth(), ipv6(daddr=1:2:3:4:5:6:7:8) }
{ ipv6(tc=2, hl=3, daddr=::1) }
{ eth(), ipv6(nh=58, sa=2001:db8::, da=::1), 128, 0, 0x52, 0x03, 0, 0, 0, 0 }
If not explicitely specified, the lower header is initialized as Ethernet.
Signed-off-by: Tobias Klauser <tklauser@distanz.ch>
|
|
Add support for MPLS header creating with fields:
Label, TClass, Bottom-Stack, TTL
By default S-field is set to 1 (last label), but resets to 0
if lower MPLS header is added.
Signed-off-by: Vadim Kochan <vadim4j@gmail.com>
Signed-off-by: Tobias Klauser <tklauser@distanz.ch>
|
|
After commit 88b359d2aa7e ("trafgen: proto: Simplify getting lower
protocol after init") proto_current_header() is no longer used outside
trafgen_proto.c, so make it static.
Signed-off-by: Tobias Klauser <tklauser@distanz.ch>
|
|
Add generation of VLAN header with supported fields:
TPID, DEI/CFI, PCP, VID
Changed struct proto_field.offset uint16_t -> int16_t to make
TPID offset -2 to point to ether type.
Signed-off-by: Vadim Kochan <vadim4j@gmail.com>
Signed-off-by: Tobias Klauser <tklauser@distanz.ch>
|
|
Add set_next_proto callback to proto_hdr struct to allow lower
protocol set next protocol id by enum proto_id.
Extended proto_lower_default_add(...) function to take upper protocol
to delegate it's id to lower protocol to set next protocol field.
Signed-off-by: Vadim Kochan <vadim4j@gmail.com>
Signed-off-by: Tobias Klauser <tklauser@distanz.ch>
|
|
Change proto_header_init(...) and proto_lower_default_add(...)
functions to return struct proto_hdr * to do not call
proto_current_header(...) after, so it makes more sense to get struct
proto_hdr * right after initializing protocol by id.
Signed-off-by: Vadim Kochan <vadim4j@gmail.com>
Signed-off-by: Tobias Klauser <tklauser@distanz.ch>
|
|
It's not changed inside the function, so mark it as const. Also adjust
the header guards.
Signed-off-by: Tobias Klauser <tklauser@distanz.ch>
|
|
Add helper which fills a device's ipv4 addr to the specified protocol field.
It will be used by protocols like ARP, IPv4, etc.
Signed-off-by: Vadim Kochan <vadim4j@gmail.com>
Signed-off-by: Tobias Klauser <tklauser@distanz.ch>
|
|
Add helper function to set device's MAC address to protocol field which may
be used by Ethernet & ARP protocol header generation functions.
Signed-off-by: Vadim Kochan <vadim4j@gmail.com>
Signed-off-by: Tobias Klauser <tklauser@distanz.ch>
|
|
Add new trafgen_proto.c module with basic protocol header fields
generation logic. This will allow to support protocol specific keywords
in the trafgen configuration language.
Each protocol must implement struct proto_hdr and register it to the
global proto list.
Protocol headers consist of a set of fields, and each field must be
described via struct proto_field by specifying unique id, length and
offset (relative to the header start). Fields smaller than 8 bits can be
described via left shift & mask.
The following callbacks are invoked to perform special actions to build
the header during parsing:
1) header_init - required fields must be added to the packet and
initialized with default values.
2) header_finish - it is invoked when header is specified, all user
specified fields are set.
3) packet_finish - callback is invoked from upper to lower header
to calculate fields depending on upper layers such as total
length or checksum.
The protocol generation API provides convenience protocol field
setters/getters to to be used in the parser while crafting the packet.
Signed-off-by: Vadim Kochan <vadim4j@gmail.com>
[tk: wordsmithing on commit message, minor variable type changes]
Signed-off-by: Tobias Klauser <tklauser@distanz.ch>
|