packet lib: tcp: support default parameters and the auto calculation of offset

Signed-off-by: Yuichi Ito <ito.yuichi0@gmail.com>
Signed-off-by: FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>
This commit is contained in:
Yuichi Ito 2013-11-01 14:15:52 +09:00 committed by FUJITA Tomonori
parent e6a4f5897f
commit 96d5be05e0
2 changed files with 68 additions and 12 deletions

View File

@ -33,7 +33,8 @@ class tcp(packet_base.PacketBase):
dst_port Destination Port
seq Sequence Number
ack Acknowledgement Number
offset Data Offset
offset Data Offset \
(0 means automatically-calculate when encoding)
bits Control Bits
window_size Window
csum Checksum \
@ -47,8 +48,8 @@ class tcp(packet_base.PacketBase):
_PACK_STR = '!HHIIBBHHH'
_MIN_LEN = struct.calcsize(_PACK_STR)
def __init__(self, src_port, dst_port, seq, ack, offset,
bits, window_size, csum, urgent, option=None):
def __init__(self, src_port=0, dst_port=0, seq=0, ack=0, offset=0,
bits=0, window_size=0, csum=0, urgent=0, option=None):
super(tcp, self).__init__()
self.src_port = src_port
self.dst_port = dst_port
@ -81,20 +82,30 @@ class tcp(packet_base.PacketBase):
return msg, None, buf[length:]
def serialize(self, payload, prev):
length = len(self)
h = bytearray(length)
offset = self.offset << 4
struct.pack_into(tcp._PACK_STR, h, 0, self.src_port, self.dst_port,
self.seq, self.ack, offset, self.bits,
self.window_size, self.csum, self.urgent)
h = bytearray(struct.pack(
tcp._PACK_STR, self.src_port, self.dst_port, self.seq,
self.ack, offset, self.bits, self.window_size, self.csum,
self.urgent))
if self.option:
assert (length - tcp._MIN_LEN) >= len(self.option)
h[tcp._MIN_LEN:tcp._MIN_LEN + len(self.option)] = self.option
h.extend(self.option)
mod = len(self.option) % 4
if mod:
h.extend(bytearray(4 - mod))
if self.offset:
offset = self.offset << 2
if len(h) < offset:
h.extend(bytearray(offset - len(h)))
if 0 == self.offset:
self.offset = len(h) >> 2
offset = self.offset << 4
struct.pack_into('!B', h, 12, offset)
if self.csum == 0:
total_length = length + len(payload)
total_length = len(h) + len(payload)
self.csum = packet_utils.checksum_ip(prev, total_length,
h + payload)
struct.pack_into('!H', h, 16, self.csum)
return h
return str(h)

View File

@ -138,3 +138,48 @@ class Test_tcp(unittest.TestCase):
def test_malformed_tcp(self):
m_short_buf = self.buf[1:tcp._MIN_LEN]
tcp.parser(m_short_buf)
def test_default_args(self):
prev = ipv4(proto=inet.IPPROTO_TCP)
t = tcp()
buf = t.serialize(bytearray(), prev)
res = struct.unpack(tcp._PACK_STR, buf)
eq_(res[0], 0)
eq_(res[1], 0)
eq_(res[2], 0)
eq_(res[3], 0)
eq_(res[4], 5 << 4)
eq_(res[5], 0)
eq_(res[6], 0)
eq_(res[8], 0)
# with option, without offset
t = tcp(option='\x01\x02\x03')
buf = t.serialize(bytearray(), prev)
res = struct.unpack(tcp._PACK_STR + '4s', buf)
eq_(res[0], 0)
eq_(res[1], 0)
eq_(res[2], 0)
eq_(res[3], 0)
eq_(res[4], 6 << 4)
eq_(res[5], 0)
eq_(res[6], 0)
eq_(res[8], 0)
eq_(res[9], '\x01\x02\x03\x00')
# with option, with long offset
t = tcp(offset=7, option='\x01\x02\x03')
buf = t.serialize(bytearray(), prev)
res = struct.unpack(tcp._PACK_STR + '8s', buf)
eq_(res[0], 0)
eq_(res[1], 0)
eq_(res[2], 0)
eq_(res[3], 0)
eq_(res[4], 7 << 4)
eq_(res[5], 0)
eq_(res[6], 0)
eq_(res[8], 0)
eq_(res[9], '\x01\x02\x03\x00\x00\x00\x00\x00')