-
Notifications
You must be signed in to change notification settings - Fork 13
TCP IP
This page describes the use of PacketGen with TCP/IP stack.
The IP stack (or TCP/IP stack) is a network stack based on IP protocol, which is at network level (level 3 in OSI model).
IP is itself often used with a higher protocol (transport level, or level 4):
- Transmission Control Protocol (TCP), which provides reliable, ordered, and error-checked delivery of a stream of octets between applications running on hosts communicating by an IP network,
- User Datagram Protocol (UDP), which is simpler than TCP: this is a connection-less protocol with a minimum of protocol mechanisms. It provides checksums for data integrity but is not reliable, there is no guarantee of ordering delivery.
A IP header consists of a set of fields:
1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-------+-------+---------------+-------------------------------+
|VERSION| IHL | TOS | Total Length |
+-------+-------+---------------+-----+-------------------------+
| ID |flags| Fragment Offset |
+---------------+---------------+-----+-------------------------+
| TTL | Protocol | Checksum |
+---------------+---------------+-------------------------------+
| Source Address |
+---------------------------------------------------------------+
| Destination Address |
+---------------------------------------------------------------+
| Options (if IHL > 5) |
+---------------------------------------------------------------+
- 4-bit protocol version (
IP#version
). Attended value is 4 for IPv4, - 4-bit IP header length (`IP#ihl). Size of IP header in 32-bit words. As a IP header is 20 bytes long, this value should be 5. It may be greater if header has options,
- 8-bit type of service (
IP#tos
), - 16-bit total length (
IP#length
), size of IP packet, including the header, - 16-bit ID (
IP#id
), - 16-bit fragment word (
IP#frag
), used for IP fragmentation, composed of:- 3 1-bit flags:
- a reserved bit (
IP#flag_rsv
), - don't fragment flag (
IP#flag_df
) to forbid fragmentation of this packet, - more fragment flag (
IP#flag_mf
) to indicate a fragment, which is not the last one, of a IP packt,
- a reserved bit (
- a 13-bit fragment offset (
IP#fragment_offset
),
- 3 1-bit flags:
- 8-bit time to live (
IP#ttl
), - 8-bit protocol (
IP#protocol
) to indicate upper protocol (6 for TCP, and 17 for UDP by example), - 16-bit checksum (
IP#checksum
) on the whole IP packet, - 32-bit source IP address (
IP#src
), - 32-bit destination IP address (
IP#dst
), - some options (
IP#options
), - a body (
IP#body
) containing data conveyed by IP.
A IP header may be built this way:
pg> PacketGen::Header::IP.new(ttl: 32, src: '10.0.0.1', dst: '20.0.0.1', flag_df: true)
=> ---- PacketGen::Header::IP -------------------------------------------
Int8 u8: 69 (0x45)
version: 4
ihl: 5
Int8 tos: 0 (0x00)
Int16 length: 20 (0x0014)
Int16 id: 33533 (0x82fd)
Int16 frag: 16384 (0x4000)
flags: DF
frag_offset: 0 (0x0000)
Int8 ttl: 32 (0x20)
Int8 protocol: 0 (0x00)
Int16 checksum: 0 (0x0000)
Addr src: 10.0.0.1
Addr dst: 20.0.0.1
If not specified, id
is a random number.
A IP packet may be created this way:
pkt = PacketGen.gen('IP', ttl: 32, src: '10.0.0.1', dst: '20.0.0.1', flag_df: true)
pkt.is? 'IP' # => true
pkt.ip # => PacketGen::Header::IP
pkt.ip.version # => 4
pkt.ip.length # => 20
pkt.ip.id # => a 16-bit random value
pkt.ip.frag # => 0x4000
pkt.ip.df? # => true
pkt.ip.mf? # => false
pkt.ip.frag_offset # => 0
pkt.ip.ttl # => 32
pkt.ip.protocol # => 0
pkt.ip.checksum # => 0
pkt.ip.dst # => '20.0.0.1'
pkt.ip.src = '20.0.0.2'
pkt.ip.src # => '20.0.0.2'
pkt.body = 'This is a body'
pkt.length # => 20
As you can see, checksum
and length
are not automatically set to correct values. But
they may be set easily with IP#calc_sum
, which computes checksum, and IP#calc_length
which set correct length (taking care of body length). Packet#calc
may be used too:
it automatically calls #calc_sum
and #calc_length
on all headers responding to them:
pg> pkt.calc
pg> pkt
=> -- PacketGen::Packet -------------------------------------------------
---- PacketGen::Header::IP -------------------------------------------
Int8 u8: 69 (0x45)
version: 4
ihl: 5
Int8 tos: 0 (0x00)
Int16 length: 34 (0x0022)
Int16 id: 4640 (0x1220)
Int16 frag: 16384 (0x4000)
flags: DF
frag_offset: 0 (0x0000)
Int8 ttl: 32 (0x20)
Int8 protocol: 0 (0x00)
Int16 checksum: 8378 (0x20ba)
Addr src: 20.0.0.2
Addr dst: 20.0.0.1
---- Body ------------------------------------------------------------
00 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15
----------------------------------------------------------------------
54 68 69 73 20 69 73 20 61 20 62 6f 64 79 This is a body
----------------------------------------------------------------------
See also https://rubydoc.info/gems/packetgen/PacketGen/Header/IP.
A TCP header consists of:
1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-------------------------------+-------------------------------+
| Source Port | Destination Port |
+-------------------------------+-------------------------------+
| Sequence Number |
+---------------------------------------------------------------+
| Acknowledge Number |
+-------+-----+-+-+-+-+-+-+-+-+-+-------------------------------+
| Data | RSV |N|C|E|U|A|P|R|S|F| |
| Offset|0 0 0|S|W|C|R|C|S|S|Y|I| Window Size |
| | | |R|E|G|K|H|T|N|N| |
+-------+-----+-+-+-+-+-+-+-+-+-+-------------------------------+
| Checksum | Urgent Pointer (if URG set) |
+-------------------------------+-------------------------------+
| Options (if data offset > 5) |
+---------------------------------------------------------------+
- 16-bit source port (
TCP#sport
), - 16-bit destination port (
TCP#dport
), - 32-bit sequence number (
TCP#seqnum
), - 32-bit acknowledge number (
TCP#acknum
), - a 16-bit field (
TCP#u16
) composed of:- 4-bit data offset (
TCP#data_offset
), - 3-bit reserved field (
TCP#reserved
), - 9 1-bit flags (
TCP#flags
orTCP#flag_ns
,TCP#flag_cwr
,TCP#flag_ece
,TCP#flag_urg
,TCP#flag_ack
,TCP#flag_psh
,TCP#flag_rst
,TCP#flag_syn
andTCP#flag_fin
),
- 4-bit data offset (
- 16-bit window size (
TCP#window
), - 16-bit checksum (
TCP#checksum
), - 16-bit urgent pointer (
TCP#urg_pointer
), - an optional options field (
TCP#options
), - and a body (
TCP#body
).
A TCP header may be built this way:
pg> PacketGen::Header::TCP.new(dport: 80, sport: 32768 + rand(2**15))
=> ---- PacketGen::Header::TCP ------------------------------------------
Int16 sport: 43959 (0xabb7)
Int16 dport: 80 (0x0050)
Int32 seqnum: 1555880791 (0x5cbcdb57)
Int32 acknum: 0 (0x00000000)
Int16 u16: 20480 (0x5000)
data_offset: 5 (0x5)
reserved: 0
flags: .........
Int16 window: 0 (0x0000)
Int16 checksum: 0 (0x0000)
Int16 urg_pointer: 0 (0x0000)
Options options:
If not specified, seqnum
is a random value.
A TCP over IP packet may be created this way:
pkt = PacketGen.gen('IP', src: '127.0.0.1', dst: '127.0.0.1').
add('TCP', dport: 80, sport: 44158, flag_syn: true)
pkt.is?('IP') # => true
pkt.is?('TCP') # => true
pkt.tcp # => PacketGen::Header::TCP
pkt.tcp.sport # => 44158
pkt.tcp.dport # => 80
pkt.tcp.seqnum # => Integer
pkt.tcp.acknum # => Integer
pkt.tcp.u16 # => 0x5002
pkt.tcp.data_offset # => 5
pkt.tcp.flags # => 0x002
pkt.tcp.flag_ns? # => false
pkt.tcp.flag_cwr? # => false
pkt.tcp.flag_ece? # => false
pkt.tcp.flag_urg? # => false
pkt.tcp.flag_ack? # => false
pkt.tcp.flag_psh? # => false
pkt.tcp.flag_rst? # => false
pkt.tcp.flag_syn? # => true
pkt.tcp.flag_fin? # => false
pkt.tcp.window # => Integer
pkt.tcp.checksum # => Integer
pkt.tcp.urg_pointer # => Integer
pkt.tcp.options # => PacketGen::Header::TCP::Options
pkt.tcp.flag_rst = true
pkt.tcp.sport = 44444
checksum
field may be computed by Header::TCP#calc_sum
. All checksum and
length fields from this packet may be computed at once using pkt.calc
:
pg> pkt.calc
pg> pkt
=> -- PacketGen::Packet -------------------------------------------------
---- PacketGen::Header::IP -------------------------------------------
Int8 u8: 69 (0x45)
version: 4
ihl: 5
Int8 tos: 0 (0x00)
Int16 length: 45 (0x002d)
Int16 id: 25958 (0x6566)
Int16 frag: 0 (0x0000)
flags: none
frag_offset: 0 (0x0000)
Int8 ttl: 64 (0x40)
Int8 protocol: 6 (0x06)
Int16 checksum: 5987 (0x1763)
Addr src: 127.0.0.1
Addr dst: 127.0.0.1
String options: ""
---- PacketGen::Header::TCP ------------------------------------------
Int16 sport: 44444 (0xad9c)
Int16 dport: 80 (0x0050)
Int32 seqnum: 3904665160 (0xe8bc7648)
Int32 acknum: 0 (0x00000000)
Int16 u16: 20486 (0x5006)
data_offset: 5 (0x5)
reserved: 0
flags: ......RS.
Int16 window: 0 (0x0000)
Int16 checksum: 63218 (0xf6f2)
Int16 urg_pointer: 0 (0x0000)
Options options:
TCP options may be easily added:
pg> pkt.tcp.options << { opt: 'MSS', value: 1250 }
pg> pkt.tcp.options << { opt: 'NOP' }
pg> pkt
=> -- PacketGen::Packet -------------------------------------------------
---- PacketGen::Header::IP -------------------------------------------
Int8 u8: 69 (0x45)
version: 4
ihl: 5
Int8 tos: 0 (0x00)
Int16 length: 45 (0x002d)
Int16 id: 25958 (0x6566)
Int16 frag: 0 (0x0000)
flags: none
frag_offset: 0 (0x0000)
Int8 ttl: 64 (0x40)
Int8 protocol: 6 (0x06)
Int16 checksum: 5987 (0x1763)
Addr src: 127.0.0.1
Addr dst: 127.0.0.1
String options: ""
---- PacketGen::Header::TCP ------------------------------------------
Int16 sport: 44444 (0xad9c)
Int16 dport: 80 (0x0050)
Int32 seqnum: 3904665160 (0xe8bc7648)
Int32 acknum: 0 (0x00000000)
Int16 u16: 20486 (0x5006)
data_offset: 5 (0x5)
reserved: 0
flags: ......RS.
Int16 window: 0 (0x0000)
Int16 checksum: 63218 (0xf6f2)
Int16 urg_pointer: 0 (0x0000)
Options options: MSS:1250,NOP
As TCP::Options
an Array
-like object, it responds to Enumerable
API:
pkt.tcp.options.each do |opt|
# opt class is a subclass from Header::TCP::Option
p opt
puts "kind: #{opt.kind}"
puts "length: #{opt.length}"
puts "value: #{opt.value.inspect}"
end
See also https://rubydoc.info/gems/packetgen/PacketGen/Header/TCP.
A UDP header consists of:
1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-------------------------------+-------------------------------+
| Source Port | Destination Port |
+-------------------------------+-------------------------------+
| Length | Checksum |
+-------------------------------+-------------------------------+
- 16-bit source port (
UDP#sport
), - 16-bit destination port (
UDP#dport
), - 16-bit length (
UDP#length
), - 16-bit checksum (
UDP#checksum
), - and a body (
UDP#body
).
A UDP header may be built this way:
pg> PacketGen::Header::UDP.new(dport: 53, sport: 65053)
=> ---- PacketGen::Header::UDP ------------------------------------------
Int16 sport: 65053 (0xfe1d)
Int16 dport: 53 (0x0035)
Int16 length: 8 (0x0008)
Int16 checksum: 0 (0x0000)
A UDP over IP packet may be created this way:
pkt = PacketGen.gen('IP', src: '127.0.0.1', dst: '127.0.0.1').
add('UDP', dport: 80, sport: 44158, body: 'abcd')
pkt.is?('IP') # => true
pkt.is?('UDP') # => true
pkt.udp # => PacketGen::Header::UDP
pkt.udp.sport # => 65053
pkt.udp.dport # => 53
pkt.udp.length # => Integer
pkt.udp.checksum # => Integer
pkt.udp.body # => "abcd"
pkt.body # => "abcd"
pkt.udp.sport = 44444
checksum
and length
fields may be computed by Header::UDP#calc_sum
and
Header::UDP#calc_length
respectively. All checksum and length fields from this
packet may be computed at once using pkt.calc
:
pg> pkt.calc
pg> pkt
=> -- PacketGen::Packet -------------------------------------------------
---- PacketGen::Header::IP -------------------------------------------
Int8 u8: 69 (0x45)
version: 4
ihl: 5
Int8 tos: 0 (0x00)
Int16 length: 32 (0x0020)
Int16 id: 39945 (0x9c09)
Int16 frag: 0 (0x0000)
flags: none
frag_offset: 0 (0x0000)
Int8 ttl: 64 (0x40)
Int8 protocol: 17 (0x11)
Int16 checksum: 57537 (0xe0c1)
Addr src: 127.0.0.1
Addr dst: 127.0.0.1
String options: ""
---- PacketGen::Header::UDP ------------------------------------------
Int16 sport: 44444 (0xad9c)
Int16 dport: 80 (0x0050)
Int16 length: 12 (0x000c)
Int16 checksum: 36640 (0x8f20)
---- Body ------------------------------------------------------------
00 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15
----------------------------------------------------------------------
61 62 63 64 abcd
----------------------------------------------------------------------
See also https://rubydoc.info/gems/packetgen/PacketGen/Header/UDP.
A ICMP header consists of:
1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+---------------+---------------+-------------------------------+
| Type | Code | Checksum |
+---------------+---------------+-------------------------------+
- 8-bit type (
ICMP#type
), - 8-bit code (
ICMP#code
), - 16-bit checksum (
ICMP#checksum
), - and a body (
ICMP#body
).
A ICMP header may be built this way:
pg> PacketGen::Header::ICMP.new(type: 8, code: 0, body: 'PING!')
=> ---- PacketGen::Header::ICMP -----------------------------------------
Int8 type: 8 (0x08)
Int8 code: 0 (0x00)
Int16 checksum: 0 (0x0000)
A ICMP packet may be created this way:
pkt = PacketGen.gen('IP', src: '127.0.0.1', dst: '127.0.0.1').
add('ICMP', type: 8, code: 0, body: 'PING!')
pkt.is?('IP') # => true
pkt.is?('ICMP') # => true
pkt.icmp # => PacketGen::Header::ICMP
pkt.icmp.type # => Integer
pkt.icmp.code # => Integer
pkt.icmp.body # => "PING!"
pkt.body # => "PING!"
pkt.udp.type = 0 # This is now a pong!
As usual, checksum
field may be computed by Header::ICMP#calc_sum
.
All checksum and length fields from a packet may by computed at once using pkt.calc
:
pg> pkt.calc
pg> pkt
=> -- PacketGen::Packet -------------------------------------------------
---- PacketGen::Header::IP -------------------------------------------
Int8 u8: 69 (0x45)
version: 4
ihl: 5
Int8 tos: 0 (0x00)
Int16 length: 29 (0x001d)
Int16 id: 26634 (0x680a)
Int16 frag: 0 (0x0000)
flags: none
frag_offset: 0 (0x0000)
Int8 ttl: 64 (0x40)
Int8 protocol: 1 (0x01)
Int16 checksum: 5332 (0x14d4)
Addr src: 127.0.0.1
Addr dst: 127.0.0.1
String options: ""
---- PacketGen::Header::ICMP -----------------------------------------
Int8 type: 0 (0x08)
Int8 code: 0 (0x00)
Int16 checksum: 16495 (0x406f)
---- Body ------------------------------------------------------------
00 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15
----------------------------------------------------------------------
50 49 4e 47 21 PING!
----------------------------------------------------------------------
See also https://rubydoc.info/gems/packetgen/PacketGen/Header/ICMP.
A IPv6 header consists of a set of fields:
1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-------+---------------+---------------------------------------+
|VERSION| Traffic Class | Flow Label |
+-------+---------------+-------+---------------+---------------+
| Payload Length | Next Header | Hop-Limit |
+-------------------------------+---------------+---------------+
| |
| Source Address |
| (128 bits) |
| |
+---------------------------------------------------------------+
| |
| Destination Address |
| (128 bits) |
| |
+---------------------------------------------------------------+
- 4-bit protocol version (
IPV6#version
). Attended value is 6 for IPv6, - 8-bit traffic class (`IPV6#traffic_class),
- 20-bit flow label (
IPv6#flow_label
), - 16-bit payload length (
IPV6#length
), size of IPV6 payload, excluding the header, - 8-bit next header (
IPV6#next
) to indicate upper protocol (6 for TCP, and 17 for UDP by example, but this may also be IPv6 options), - 8-bit hop-limit (
IPV6#hop
), - 128-bit source IPV6 address (
IPV6#src
), - 128-bit destination IPV6 address (
IPV6#dst
), - a body (
IPV6#body
) containing data conveyed by IPv6.
A IPV6 header may be built this way:
pg> PacketGen::Header::IPv6.new(hop: 32, src: '::1', dst: '::1')
=> ---- PacketGen::Header::IPv6 -----------------------------------------
Int32 u32: 1610612736 (0x60000000)
version: 6
tclass: 0 (0x00)
flow_label: 0 (0x00000)
Int16 length: 0 (0x0000)
Int8 next: 0 (0x00)
Int8 hop: 32 (0x20)
Addr src: ::1
Addr dst: ::1
A IPv6 packet may be created this way:
pkt = PacketGen.gen('IPV6', ttl: 32, src: '10.0.0.1', dst: '20.0.0.1', flag_df: true)
pkt.is? 'IPVv' # => true
pkt.ipv6 # => PacketGen::Header::IPv6
pkt.ipv6.version # => 6
pkt.ipv6.tclass # => Integer
pkt.ipv6.flow_label # => Integer
pkt.ipv6.length # => 0
pkt.ipv6.next # => Integer
pkt.ipv6.hop # => 32
pkt.ipv6.dst # => '::1'
pkt.ipv6.src = '::2'
pkt.ipv6.src # => '::2'
pkt.body = 'This is a body'
pkt.length # => 0
As you can see, length
is not automatically set to correct value. But it may be set
easily with IPv6#calc_length
.
Packet#calc
may be used too: it automatically calls #calc_sum
and #calc_length
on
all headers responding to them:
pg> pkt.calc
pg> pkt
=> -- PacketGen::Packet -------------------------------------------------
---- PacketGen::Header::IPv6 -----------------------------------------
Int32 u32: 1610612736 (0x60000000)
version: 6
tclass: 0 (0x00)
flow_label: 0 (0x00000)
Int16 length: 14 (0x000e)
Int8 next: 0 (0x00)
Int8 hop: 32 (0x20)
Addr src: ::2
Addr dst: ::1
---- Body ------------------------------------------------------------
00 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15
----------------------------------------------------------------------
54 68 69 73 20 69 73 20 61 20 62 6f 64 79 This is a body
----------------------------------------------------------------------
See also https://rubydoc.info/gems/packetgen/PacketGen/Header/IPv6.
TCP and UDP headers may be added to a IPv6 packet:
pg> pkt = PacketGen.gen('IPv6', src: '::1', dst: '::1')
pg> pkt.add('TCP', dport: 80, sport: 51234)
pg> pkt
=> -- PacketGen::Packet -------------------------------------------------
---- PacketGen::Header::IPv6 -----------------------------------------
Int32 u32: 1610612736 (0x60000000)
version: 6
tclass: 0 (0x00)
flow_label: 0 (0x00000)
Int16 length: 0 (0x0000)
Int8 next: 6 (0x06)
Int8 hop: 64 (0x40)
Addr src: ::1
Addr dst: ::1
---- PacketGen::Header::TCP ------------------------------------------
Int16 sport: 51234 (0xc822)
Int16 dport: 80 (0x0050)
Int32 seqnum: 6082437 (0x005ccf85)
Int32 acknum: 0 (0x00000000)
Int16 u16: 20480 (0x5000)
data_offset: 5 (0x5)
reserved: 0
flags: .........
Int16 window: 0 (0x0000)
Int16 checksum: 0 (0x0000)
Int16 urg_pointer: 0 (0x0000)
Options options:
IPv6 comes with a new version of ICMP: ICMPv6 (yes!).
ICMPv6 has the same header than ICMP, but type and code have different meanings. And ICMPv6 has not the same protocol number than ICMP.
In fact, ICMPv6 supports much more features than ICMP, but at packet level, there is no such differences.
Adding a ICMPv6 header to an IPv6 packet is easy:
pg> pkt = PacketGen.gen('IPv6', src: '::1', dst: '::1')
pg> pkt.add('ICMPv6', type: 128, code: 0, body: 'ping')
pg> pkt.calc
pg> pkt
=> -- PacketGen::Packet -------------------------------------------------
---- PacketGen::Header::IPv6 -----------------------------------------
Int32 u32: 1610612736 (0x60000000)
version: 6
tclass: 0 (0x00)
flow_label: 0 (0x00000)
Int16 length: 8 (0x0008)
Int8 next: 58 (0x3a)
Int8 hop: 64 (0x40)
Addr src: ::1
Addr dst: ::1
---- PacketGen::Header::ICMPv6 ---------------------------------------
Int8 type: 128 (0x80)
Int8 code: 0 (0x00)
Int16 checksum: 41194 (0xa0ea)
---- Body ------------------------------------------------------------
00 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15
----------------------------------------------------------------------
70 69 6e 67 ping
----------------------------------------------------------------------
See also https://rubydoc.info/gems/packetgen/PacketGen/Header/ICMPv6.
IP packets may be sent at link level (Ethernet, IEEE 802.11) or at network one (IP).
So, if you want to generate IP packets and let your OS route them, create packets at IP level:
pkt = PacketGen.gen('IP', src: '192.168.1.1', '192.168.1.101').add('TCP', dport: 80)
pkt.body = some_string_containing_http_content
pkt.to_w
But you may still use link level:
# Ethernet
pkt = PacketGen.gen('Eth', src: '00:01:02:03:04:05', dst: '06:07:08:09:0a:0b')
pkt.add('IP', src: '192.168.1.1', '192.168.1.101').add('TCP', dport: 80)
pkt.body = some_string_containing_http_content
pkt.calc
pkt.to_w
# IEEE 802.11
pkt = PacketGen.gen('RadioTap').add('Dot11::Data, src: '00:01:02:03:04:05', dst: '06:07:08:09:0a:0b')
pkt.add('LLC').add('SNAP')
pkt.add('IP', src: '192.168.1.1', '192.168.1.101').add('TCP', dport: 80)
pkt.body = some_string_containing_http_content
pkt.to_w('wlan0', calc: true)
Captured packets will always have a link level header:
-
Eth
one for packets captured from an ethernet interface, -
RadioTap
orDot11
one for packets captured from a IEEE 802.11 interface. If RadioTap header is present, il will always be followed by a Dot11 one.
PacketGen - network packet manipulation library Project Page | Wiki | Issues | API documentation