MoonGen
 All Files Functions Variables Pages
tcp.lua
Go to the documentation of this file.
1 ------------------------------------------------------------------------
2 --- @file tcp.lua
3 --- @brief Transmission control protocol (TCP) utility.
4 --- Utility functions for the tcp_header struct
5 --- defined in \ref headers.lua . \n
6 --- Includes:
7 --- - TCP constants
8 --- - TCP header utility
9 --- - Definition of TCP packets
10 ------------------------------------------------------------------------
11 
12 local ffi = require "ffi"
13 local pkt = require "packet"
14 
15 require "utils"
16 require "headers"
17 
18 local ntoh, hton = ntoh, hton
19 local ntoh16, hton16 = ntoh16, hton16
20 local bor, band, bnot, rshift, lshift= bit.bor, bit.band, bit.bnot, bit.rshift, bit.lshift
21 local istype = ffi.istype
22 local format = string.format
23 
24 
25 ------------------------------------------------------------------------------
26 ---- TCP constants
27 ------------------------------------------------------------------------------
28 
29 
30 ------------------------------------------------------------------------------
31 ---- TCP header
32 ------------------------------------------------------------------------------
33 
34 --- Module for tcp_header struct (see \ref headers.lua).
35 local tcpHeader = {}
36 tcpHeader.__index = tcpHeader
37 
38 --- Set the source port.
39 --- @param int Port as 16 bit integer.
40 function tcpHeader:setSrcPort(int)
41  int = int or 1025
42  self.src = hton16(int)
43 end
44 
45 --- Retrieve the source port.
46 --- @return Port as 16 bit integer.
47 function tcpHeader:getSrcPort()
48  return hton16(self.src)
49 end
50 
51 --- Retrieve the source port.
52 --- @return Port in string format.
53 function tcpHeader:getSrcPortString()
54  return self:getSrcPort()
55 end
56 
57 --- Set the destination port.
58 --- @param int Port as 16 bit integer.
59 function tcpHeader:setDstPort(int)
60  int = int or 1024
61  self.dst = hton16(int)
62 end
63 
64 --- Retrieve the destination port.
65 --- @return Port as 16 bit integer.
66 function tcpHeader:getDstPort()
67  return hton16(self.dst)
68 end
69 
70 --- Retrieve the destination port.
71 --- @return Port in string format.
72 function tcpHeader:getDstPortString()
73  return self:getDstPort()
74 end
75 
76 --- Set the sequence number.
77 --- @param int Sequence number as 8 bit integer.
78 function tcpHeader:setSeqNumber(int)
79  int = int or 0
80  self.seq = hton(int)
81 end
82 
83 --- Retrieve the sequence number.
84 --- @return Seq number as 8 bit integer.
85 function tcpHeader:getSeqNumber()
86  return hton(self.seq)
87 end
88 
89 --- Retrieve the sequence number.
90 --- @return Sequence number in string format.
92  return self:getSeqNumber()
93 end
94 
95 --- Set the acknowledgement number.
96 --- @param int Ack number as 8 bit integer.
97 function tcpHeader:setAckNumber(int)
98  int = int or 0
99  self.ack = hton(int)
100 end
101 
102 --- Retrieve the acknowledgement number.
103 --- @return Seq number as 8 bit integer.
104 function tcpHeader:getAckNumber()
105  return hton(self.ack)
106 end
107 
108 --- Retrieve the acknowledgement number.
109 --- @return Ack number in string format.
110 function tcpHeader:getAckNumberString()
111  return self:getAckNumber()
112 end
113 
114 --- Set the data offset.
115 --- @param int Offset as 4 bit integer. Header size is counted in 32 bit words (min. 5 (no options), max. 15)
116 function tcpHeader:setDataOffset(int)
117  int = int or 5
118  int = band(lshift(int, 4), 0xf0) -- fill to 8 bits
119 
120  old = self.offset
121  old = band(old, 0x0f) -- remove old value
122 
123  self.offset = bor(old, int)
124 end
125 
126 --- Retrieve the data offset.
127 --- @return Offset as 4 bit integer.
128 function tcpHeader:getDataOffset()
129  return band(rshift(self.offset, 4), 0x0f)
130 end
131 
132 --- Retrieve the data offset.
133 --- @return Offset in string format.
135  return format("0x%01x", self:getDataOffset())
136 end
137 
138 --- Set the reserved field.
139 --- @param int Reserved field as 6 bit integer.
140 function tcpHeader:setReserved(int)
141  int = int or 0
142  -- offset | flags
143  -- XXXXOOOO OOXXXXXX
144  -- reserved
145 
146  -- first, offset field
147  off = band(rshift(int, 2), 0x0f) -- fill to 8 bits (4 highest to 4 lowest bits)
148 
149  old = self.offset
150  old = band(old, 0xf0) -- remove old value
151 
152  self.offset = bor(old, off)
153 
154  -- secondly, flags field
155  fla = lshift(int, 6) -- fill to 8 bits (2 lowest to 2 highest bits)
156 
157  old = self.flags
158  old = band(old, 0x3f) -- remove old values
159 
160  self.flags = bor(old, fla)
161 end
162 
163 --- Retrieve the reserved field.
164 --- @return Reserved field as 6 bit integer.
165 function tcpHeader:getReserved()
166  res = lshift(band(self.offset, 0x0f), 2) -- 4 lowest from offset to 4 highest from reserved
167  res = bor(res, rshift(self.flags, 6)) -- 2 highest from flags to 2 lowest from reserved
168  return res
169 end
170 
171 --- Retrieve the reserved field.
172 --- @return Reserved field in string format.
173 function tcpHeader:getReservedString()
174  return format("0x%02x", self:getReserved())
175 end
176 
177 --- Set the flags.
178 --- @param int Flags as 6 bit integer.
179 --- @todo TODO RFC 3168 specifies new CWR and ECE flags (reserved reduced to 4 bit)
180 function tcpHeader:setFlags(int)
181  int = int or 0
182 
183  int = band(int, 0x3f) -- fill to 8 bits
184 
185  old = self.flags
186  old = band(old, 0xc0) -- remove old values
187 
188  self.flags = bor(old, int)
189 end
190 
191 --- Retrieve the flags.
192 --- @return Flags as 6 bit integer.
193 function tcpHeader:getFlags()
194  return band(self.flags, 0x3f)
195 end
196 
197 --- Retrieve the flags.
198 --- @return Flags in string format.
199 function tcpHeader:getFlagsString()
200  return format("0x%02x", self:getFlags())
201 end
202 
203 --- Set the Urg flag.
204 function tcpHeader:setUrg()
205  self.flags = bor(self.flags, 0x20)
206 end
207 
208 --- Unset the Urg flag.
209 function tcpHeader:unsetUrg()
210  self.flags = band(self.flags, 0xdf)
211 end
212 
213 --- Retrieve the Urg flag.
214 --- @return Flag as 1 bit integer.
215 function tcpHeader:getUrg()
216  return rshift(band(self.flags, 0x20), 5)
217 end
218 
219 --- Retrieve the Urg flag.
220 --- @return Flag in string format.
221 function tcpHeader:getUrgString()
222  if self:getUrg() == 1 then
223  return "URG"
224  else
225  return "X"
226  end
227 end
228 
229 --- Set the Ack flag.
230 function tcpHeader:setAck()
231  self.flags = bor(self.flags, 0x10)
232 end
233 
234 --- Unset the Ack flag.
235 function tcpHeader:unsetAck()
236  self.flags = band(self.flags, 0xef)
237 end
238 
239 --- Retrieve the Ack flag.
240 --- @return Flag as 1 bit integer.
241 function tcpHeader:getAck()
242  return rshift(band(self.flags, 0x10), 4)
243 end
244 
245 --- Retrieve the Ack flag.
246 --- @return Flag in string format.
247 function tcpHeader:getAckString()
248  if self:getAck() == 1 then
249  return "ACK"
250  else
251  return "X"
252  end
253 end
254 
255 --- Set the Psh flag.
256 function tcpHeader:setPsh()
257  self.flags = bor(self.flags, 0x08)
258 end
259 
260 --- Unset the Psh flag.
261 function tcpHeader:unsetPsh()
262  self.flags = band(self.flags, 0xf7)
263 end
264 
265 --- Retrieve the Psh flag.
266 --- @return Flag as 1 bit integer.
267 function tcpHeader:getPsh()
268  return rshift(band(self.flags, 0x08), 3)
269 end
270 
271 --- Retrieve the Psh flag.
272 --- @return Flag in string format.
273 function tcpHeader:getPshString()
274  if self:getPsh() == 1 then
275  return "PSH"
276  else
277  return "X"
278  end
279 end
280 
281 --- Set the Rst flag.
282 function tcpHeader:setRst()
283  self.flags = bor(self.flags, 0x04)
284 end
285 
286 --- Unset the Rst flag.
287 function tcpHeader:unsetRst()
288  self.flags = band(self.flags, 0xfb)
289 end
290 
291 --- Retrieve the Rst flag.
292 --- @return Flag as 1 bit integer.
293 function tcpHeader:getRst()
294  return rshift(band(self.flags, 0x04), 2)
295 end
296 
297 --- Retrieve the Rst flag.
298 --- @return Flag in string format.
300  if self:getRst() == 1 then
301  return "RST"
302  else
303  return "X"
304  end
305 end
306 
307 --- Set the Syn flag.
308 function tcpHeader:setSyn()
309  self.flags = bor(self.flags, 0x02)
310 end
311 
312 --- Unset the Syn flag.
313 function tcpHeader:unsetSyn()
314  self.flags = band(self.flags, 0xfd)
315 end
316 
317 --- Retrieve the Syn flag.
318 --- @return Flag as 1 bit integer.
319 function tcpHeader:getSyn()
320  return rshift(band(self.flags, 0x02), 1)
321 end
322 
323 --- Retrieve the Syn flag.
324 --- @return Flag in string format.
325 function tcpHeader:getSynString()
326  if self:getSyn() == 1 then
327  return "SYN"
328  else
329  return "X"
330  end
331 end
332 
333 --- Set the Fin flag.
334 function tcpHeader:setFin()
335  self.flags = bor(self.flags, 0x01)
336 end
337 
338 --- Unset the Fin flag.
339 function tcpHeader:unsetFin()
340  self.flags = band(self.flags, 0xfe)
341 end
342 
343 --- Retrieve the Fin flag.
344 --- @return Flag as 1 bit integer.
345 function tcpHeader:getFin()
346  return band(self.flags, 0x01)
347 end
348 
349 --- Retrieve the Fin flag.
350 --- @return Flag in string format.
351 function tcpHeader:getFinString()
352  if self:getFin() == 1 then
353  return "FIN"
354  else
355  return "X"
356  end
357 end
358 
359 --- Set the window field.
360 --- @param int Window as 16 bit integer.
361 function tcpHeader:setWindow(int)
362  int = int or 0
363  self.window = hton16(int)
364 end
365 
366 --- Retrieve the window field.
367 --- @return Window as 16 bit integer.
368 function tcpHeader:getWindow()
369  return hton16(self.window)
370 end
371 
372 --- Retrieve the window field.
373 --- @return Window in string format.
374 function tcpHeader:getWindowString()
375  return self:getWindow()
376 end
377 
378 --- Set the checksum.
379 --- @param int Checksum as 16 bit integer.
380 function tcpHeader:setChecksum(int)
381  int = int or 0
382  self.cs = hton16(int)
383 end
384 
385 --- Calculate the checksum.
386 --- @param len Number of bytes to calculate the checksum over.
387 --- @todo FIXME NYI
388 function tcpHeader:calculateChecksum(len)
389 end
390 
391 --- Retrieve the checksum.
392 --- @return Checksum as 16 bit integer.
393 function tcpHeader:getChecksum()
394  return hton16(self.cs)
395 end
396 
397 --- Retrieve the checksum.
398 --- @return Checksum in string format.
399 function tcpHeader:getChecksumString()
400  return format("0x%04x", self:getChecksum())
401 end
402 
403 --- Set the urgent pointer.
404 --- @param int Urgent pointer as 16 bit integer.
405 function tcpHeader:setUrgentPointer(int)
406  int = int or 0
407  self.urg = hton16(int)
408 end
409 
410 --- Retrieve the urgent pointer.
411 --- @return Urgent pointer as 16 bit integer.
412 function tcpHeader:getUrgentPointer()
413  return hton16(self.urg)
414 end
415 
416 --- Retrieve the urgent pointer.
417 --- @return Urgent pointer in string format.
419  return self:getUrgentPointer()
420 end
421 
422 -- TODO how do we want to handle options (problem is tcp header variable length array of uint8[] followed by payload variable length array (uint8[]))
423 --[[function tcpHeader:setOptions(int)
424  int = int or
425  self. = int
426 end--]]
427 
428 --- Set all members of the ip header.
429 --- Per default, all members are set to default values specified in the respective set function.
430 --- Optional named arguments can be used to set a member to a user-provided value.
431 --- @param args Table of named arguments. Available arguments: Src, Dst, SeqNumber, AckNumber, DataOffset, Reserved, Flags, Urg, Ack, Psh, Rst, Syn, Fin, Window, Checksum, UrgentPointer
432 --- @param pre prefix for namedArgs. Default 'tcp'.
433 --- @code
434 --- fill() --- only default values
435 --- fill{ tcpSrc=1234, ipTTL=100 } --- all members are set to default values with the exception of tcpSrc
436 --- @endcode
437 function tcpHeader:fill(args, pre)
438  args = args or {}
439  pre = pre or "tcp"
440 
441  self:setSrcPort(args[pre .. "Src"])
442  self:setDstPort(args[pre .. "Dst"])
443  self:setSeqNumber(args[pre .. "SeqNumber"])
444  self:setAckNumber(args[pre .. "AckNumber"])
445  self:setDataOffset(args[pre .. "DataOffset"])
446  self:setReserved(args[pre .. "Reserved"])
447  self:setFlags(args[pre .. "Flags"])
448  if args[pre .. "Urg"] and args[pre .. "Urg"] ~= 0 then
449  self:setUrg()
450  end
451  if args[pre .. "Ack"] and args[pre .. "Ack"] ~= 0 then
452  self:setAck()
453  end
454  if args[pre .. "Psh"] and args[pre .. "Psh"] ~= 0 then
455  self:setPsh()
456  end
457  if args[pre .. "Rst"] and args[pre .. "Rst"] ~= 0 then
458  self:setRst()
459  end
460  if args[pre .. "Syn"] and args[pre .. "Syn"] ~= 0 then
461  self:setSyn()
462  end
463  if args[pre .. "Fin"] and args[pre .. "Fin"] ~= 0 then
464  self:setFin()
465  end
466  self:setWindow(args[pre .. "Window"])
467  self:setChecksum(args[pre .. "Checksum"])
468  self:setUrgentPointer(args[pre .. "UrgentPointer"])
469 end
470 
471 --- Retrieve the values of all members.
472 --- @return Table of named arguments. For a list of arguments see "See also".
473 --- @see tcpHeader:fill
474 function tcpHeader:get(pre)
475  pre = pre or "tcp"
476 
477  local args = {}
478  args[pre .. "Src"] = self:getSrcPort()
479  args[pre .. "Dst"] = self:getDstPort()
480  args[pre .. "SeqNumber"] = self:getSeqNumber()
481  args[pre .. "AckNumber"] = self:getAckNumber()
482  args[pre .. "DataOffset"] = self:getDataOffset()
483  args[pre .. "Reserved"] = self:getReserved()
484  args[pre .. "Flags"] = self:getFlags()
485  args[pre .. "Urg"] = self:getUrg()
486  args[pre .. "Ack"] = self:getAck()
487  args[pre .. "Psh"] = self:getPsh()
488  args[pre .. "Rst"] = self:getRst()
489  args[pre .. "Syn"] = self:getSyn()
490  args[pre .. "Fin"] = self:getFin()
491  args[pre .. "Window"] = self:getWindow()
492  args[pre .. "Checksum"] = self:getChecksum()
493  args[pre .. "UrgentPointer"] = self:getUrgentPointer()
494 
495  return args
496 end
497 
498 --- Retrieve the values of all members.
499 --- @return Values in string format.
500 function tcpHeader:getString()
501  return "TCP " .. self:getSrcPortString()
502  .. " > " .. self:getDstPortString()
503  .. " seq# " .. self:getSeqNumberString()
504  .. " ack# " .. self:getAckNumberString()
505  .. " offset " .. self:getDataOffsetString()
506  .. " reserved " .. self:getReservedString()
507  .. " flags " .. self:getFlagsString()
508  .. " [" .. self:getUrgString()
509  .. "|" .. self:getAckString()
510  .. "|" .. self:getPshString()
511  .. "|" .. self:getRstString()
512  .. "|" .. self:getSynString()
513  .. "|" .. self:getFinString()
514  .."] win " .. self:getWindowString()
515  .. " cksum " .. self:getChecksumString()
516  .. " urg " .. self:getUrgentPointerString()
517 end
518 
519 --- Resolve which header comes after this one (in a packet).
520 --- For instance: in tcp/udp based on the ports.
521 --- This function must exist and is only used when get/dump is executed on
522 --- an unknown (mbuf not yet casted to e.g. tcpv6 packet) packet (mbuf)
523 --- @return String next header (e.g. 'udp', 'icmp', nil)
524 function tcpHeader:resolveNextHeader()
525  return nil
526 end
527 
528 --- Change the default values for namedArguments (for fill/get).
529 --- This can be used to for instance calculate a length value based on the total packet length.
530 --- See proto/ip4.setDefaultNamedArgs as an example.
531 --- This function must exist and is only used by packet.fill.
532 --- @param pre The prefix used for the namedArgs, e.g. 'tcp'
533 --- @param namedArgs Table of named arguments (see See Also)
534 --- @param nextHeader The header following after this header in a packet
535 --- @param accumulatedLength The so far accumulated length for previous headers in a packet
536 --- @return Table of namedArgs
537 --- @see tcpHeader:fill
538 function tcpHeader:setDefaultNamedArgs(pre, namedArgs, nextHeader, accumulatedLength)
539  return namedArgs
540 end
541 
542 
543 ----------------------------------------------------------------------------------
544 ---- Packets
545 ----------------------------------------------------------------------------------
546 
547 --- Cast the packet to a Tcp (IP4) packet
548 pkt.getTcp4Packet = packetCreate("eth", "ip4", "tcp")
549 --- Cast the packet to a Tcp (IP6) packet
550 pkt.getTcp6Packet = packetCreate("eth", "ip6", "tcp")
551 --- Cast the packet to a Tcp packet, either using IP4 (nil/true) or IP6 (false), depending on the passed boolean.
552 pkt.getTcpPacket = function(self, ip4)
553  ip4 = ip4 == nil or ip4
554  if ip4 then
555  return pkt.getTcp4Packet(self)
556  else
557  return pkt.getTcp6Packet(self)
558  end
559 end
560 
561 ------------------------------------------------------------------------------------
562 ---- Metatypes
563 ------------------------------------------------------------------------------------
564 
565 ffi.metatype("struct tcp_header", tcpHeader)
function tcpHeader getAckString()
Retrieve the Ack flag.
function tcpHeader resolveNextHeader()
Resolve which header comes after this one (in a packet).
local ffi
low-level dpdk wrapper
Definition: dpdkc.lua:6
function tcpHeader setDstPort(int)
Set the destination port.
function tcpHeader setSyn()
Set the Syn flag.
function checksum(data, len)
Calculate a 16 bit checksum.
function tcpHeader setUrgentPointer(int)
Set the urgent pointer.
function tcpHeader setAck()
Set the Ack flag.
function tcpHeader unsetFin()
Unset the Fin flag.
function tcpHeader unsetUrg()
Unset the Urg flag.
function packetCreate(...)
Create struct and functions for a new packet.
function tcpHeader setReserved(int)
Set the reserved field.
function tcpHeader getUrgentPointer()
Retrieve the urgent pointer.
function mod band(mask1, mask2, result)
Bitwise and.
function tcpHeader setPsh()
Set the Psh flag.
function tcpHeader get(pre)
Retrieve the values of all members.
function pkt dump(bytes)
Dumps the packet data cast to the best fitting packet struct.
function tcpHeader getFin()
Retrieve the Fin flag.
function tcpHeader unsetAck()
Unset the Ack flag.
function tcpHeader getAck()
Retrieve the Ack flag.
function tcpHeader unsetRst()
Unset the Rst flag.
function tcpHeader setWindow(int)
Set the window field.
function ipsecICV set(icv)
Set the IPsec ICV.
function mod new(n)
function tcpHeader getReservedString()
Retrieve the reserved field.
function tcpHeader setFin()
Set the Fin flag.
function tcpHeader getDataOffset()
Retrieve the data offset.
local udp
Udp protocol constants.
Definition: udp.lua:23
function tcpHeader getChecksumString()
Retrieve the checksum.
function tcpHeader getSrcPortString()
Retrieve the source port.
local tcpHeader
Module for tcp_header struct (see headers.lua).
Definition: tcp.lua:25
function tcpHeader getFlagsString()
Retrieve the flags.
function tcpHeader getDstPort()
Retrieve the destination port.
function mod bor(mask1, mask2, result)
Bitwise or.
function tcpHeader setSrcPort(int)
Set the source port.
function tcpHeader getDataOffsetString()
Retrieve the data offset.
function tcpHeader getRst()
Retrieve the Rst flag.
function tcpHeader getUrgentPointerString()
Retrieve the urgent pointer.
function tcpHeader getSeqNumberString()
Retrieve the sequence number.
function tcpHeader getWindowString()
Retrieve the window field.
function tcpHeader getFlags()
Retrieve the flags.
function tcpHeader getDstPortString()
Retrieve the destination port.
function tcpHeader getSeqNumber()
Retrieve the sequence number.
function tcpHeader getSrcPort()
Retrieve the source port.
function tcpHeader setSeqNumber(int)
Set the sequence number.
function tcpHeader getSyn()
Retrieve the Syn flag.
function tcpHeader getPshString()
Retrieve the Psh flag.
function tcpHeader getReserved()
Retrieve the reserved field.
function tcpHeader fill(args, pre)
Set all members of the ip header.
function tcpHeader unsetSyn()
Unset the Syn flag.
function tcpHeader setDefaultNamedArgs(pre, namedArgs, nextHeader, accumulatedLength)
Change the default values for namedArguments (for fill/get).
function tcpHeader getString()
Retrieve the values of all members.
function tcpHeader setRst()
Set the Rst flag.
pkt getTcp6Packet
Cast the packet to a Tcp (IP6) packet.
Definition: tcp.lua:299
pkt getTcp4Packet
Cast the packet to a Tcp (IP4) packet.
Definition: tcp.lua:297
function tcpHeader getUrgString()
Retrieve the Urg flag.
local eth
Ethernet protocol constants.
Definition: ethernet.lua:24
local ip6
IP6 protocol constants.
Definition: ip6.lua:25
function tcpHeader setUrg()
Set the Urg flag.
function tcpHeader setAckNumber(int)
Set the acknowledgement number.
function tcpHeader getAckNumberString()
Retrieve the acknowledgement number.
local ip
IP4 protocol constants.
Definition: ip4.lua:25
pkt getTcpPacket
Cast the packet to a Tcp packet, either using IP4 (nil/true) or IP6 (false), depending on the passed ...
Definition: tcp.lua:301
function tcpHeader getPsh()
Retrieve the Psh flag.
local pkt
Module for packets (rte_mbuf)
Definition: packet.lua:20
function mod bnot(mask, result)
Bitwise not.
function tcpHeader getFinString()
Retrieve the Fin flag.
n
Create a new array of memory buffers (initialized to nil).
Definition: memory.lua:76
function tcpHeader setDataOffset(int)
Set the data offset.
function tcpHeader setFlags(int)
Set the flags.
function tcpHeader getSynString()
Retrieve the Syn flag.
function tcpHeader getAckNumber()
Retrieve the acknowledgement number.
function tcpHeader calculateChecksum(len)
Calculate the checksum.
function tcpHeader getRstString()
Retrieve the Rst flag.
local icmp
Icmp4 protocol constants.
Definition: icmp.lua:25
function tcpHeader setChecksum(int)
Set the checksum.
function tcpHeader getChecksum()
Retrieve the checksum.
function tcpHeader unsetPsh()
Unset the Psh flag.
function tcpHeader getUrg()
Retrieve the Urg flag.
function tcpHeader getWindow()
Retrieve the window field.