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:
parent
e6a4f5897f
commit
96d5be05e0
@ -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)
|
||||
|
@ -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')
|
||||
|
Loading…
Reference in New Issue
Block a user