This patch fixes the TCP packet parser to return the BGP packet parser class if the TCP src or dst port is the reserved BGP port and enable to parse the entire packet data.
Signed-off-by: IWASE Yusuke <iwase.yusu...@gmail.com> --- ryu/lib/packet/bgp.py | 8 ++++++-- ryu/lib/packet/bmp.py | 10 +++++----- ryu/lib/packet/tcp.py | 10 +++++++++- ryu/services/protocols/bgp/speaker.py | 2 +- ryu/tests/unit/packet/test_bgp.py | 27 +++++++++++++++------------ 5 files changed, 36 insertions(+), 21 deletions(-) diff --git a/ryu/lib/packet/bgp.py b/ryu/lib/packet/bgp.py index 68105a8..99da867 100644 --- a/ryu/lib/packet/bgp.py +++ b/ryu/lib/packet/bgp.py @@ -41,6 +41,8 @@ from ryu.lib.pack_utils import msg_pack_into reduce = six.moves.reduce +TCP_SERVER_PORT = 179 + BGP_MSG_OPEN = 1 BGP_MSG_UPDATE = 2 BGP_MSG_NOTIFICATION = 3 @@ -2238,7 +2240,8 @@ class BGPMessage(packet_base.PacketBase, _TypeDisp): rest = buf[msglen:] subcls = cls._lookup_type(type_) kwargs = subcls.parser(binmsg) - return subcls(marker=marker, len_=len_, type_=type_, **kwargs), rest + return subcls(marker=marker, len_=len_, type_=type_, + **kwargs), None, rest def serialize(self, payload=None, prev=None): # fixup @@ -2661,4 +2664,5 @@ class StreamParser(stream_parser.StreamParser): """ def try_parse(self, data): - return BGPMessage.parser(data) + msg, _, rest = BGPMessage.parser(data) + return msg, rest diff --git a/ryu/lib/packet/bmp.py b/ryu/lib/packet/bmp.py index c25e574..b3a097c 100644 --- a/ryu/lib/packet/bmp.py +++ b/ryu/lib/packet/bmp.py @@ -327,7 +327,7 @@ class BMPRouteMonitoring(BMPPeerMessage): def parser(cls, buf): kwargs, buf = super(BMPRouteMonitoring, cls).parser(buf) - bgp_update, buf = BGPMessage.parser(buf) + bgp_update, _, buf = BGPMessage.parser(buf) kwargs['bgp_update'] = bgp_update @@ -498,11 +498,11 @@ class BMPPeerDownNotification(BMPPeerMessage): buf = buf[struct.calcsize('!B'):] if reason == BMP_PEER_DOWN_REASON_LOCAL_BGP_NOTIFICATION: - data, rest = BGPMessage.parser(buf) + data, _, rest = BGPMessage.parser(buf) elif reason == BMP_PEER_DOWN_REASON_LOCAL_NO_NOTIFICATION: data = struct.unpack_from('!H', six.binary_type(buf)) elif reason == BMP_PEER_DOWN_REASON_REMOTE_BGP_NOTIFICATION: - data, rest = BGPMessage.parser(buf) + data, _, rest = BGPMessage.parser(buf) elif reason == BMP_PEER_DOWN_REASON_REMOTE_NO_NOTIFICATION: data = None else: @@ -609,8 +609,8 @@ class BMPPeerUpNotification(BMPPeerMessage): rest = rest[cls._MIN_LEN:] - sent_open_msg, rest = BGPMessage.parser(rest) - received_open_msg, rest = BGPMessage.parser(rest) + sent_open_msg, _, rest = BGPMessage.parser(rest) + received_open_msg, _, rest = BGPMessage.parser(rest) kwargs['sent_open_message'] = sent_open_msg kwargs['received_open_message'] = received_open_msg diff --git a/ryu/lib/packet/tcp.py b/ryu/lib/packet/tcp.py index 1771b9a..b61ac8c 100644 --- a/ryu/lib/packet/tcp.py +++ b/ryu/lib/packet/tcp.py @@ -19,6 +19,7 @@ import logging from . import packet_base from . import packet_utils +from . import bgp from ryu.lib import stringify @@ -108,6 +109,13 @@ class tcp(packet_base.PacketBase): mask = sum(flags) return (self.bits & mask) == mask + @staticmethod + def get_payload_type(src_port, dst_port): + if bgp.TCP_SERVER_PORT in [src_port, dst_port]: + return bgp.BGPMessage + else: + return None + @classmethod def parser(cls, buf): (src_port, dst_port, seq, ack, offset, bits, window_size, @@ -132,7 +140,7 @@ class tcp(packet_base.PacketBase): msg = cls(src_port, dst_port, seq, ack, offset, bits, window_size, csum, urgent, option) - return msg, None, buf[length:] + return msg, cls.get_payload_type(src_port, dst_port), buf[length:] def serialize(self, payload, prev): offset = self.offset << 4 diff --git a/ryu/services/protocols/bgp/speaker.py b/ryu/services/protocols/bgp/speaker.py index 9c185da..710efa7 100644 --- a/ryu/services/protocols/bgp/speaker.py +++ b/ryu/services/protocols/bgp/speaker.py @@ -350,7 +350,7 @@ class BgpProtocol(Protocol, Activity): # If we have partial message we wait for rest of the message. if len(self._recv_buff) < length: return - msg, rest = BGPMessage.parser(self._recv_buff) + msg, _, rest = BGPMessage.parser(self._recv_buff) self._recv_buff = rest # If we have a valid bgp message we call message handler. diff --git a/ryu/tests/unit/packet/test_bgp.py b/ryu/tests/unit/packet/test_bgp.py index b3c1198..d23b259 100644 --- a/ryu/tests/unit/packet/test_bgp.py +++ b/ryu/tests/unit/packet/test_bgp.py @@ -22,6 +22,7 @@ import unittest from nose.tools import eq_ from nose.tools import ok_ +from ryu.lib import pcaplib from ryu.lib.packet import packet from ryu.lib.packet import bgp from ryu.lib.packet import afi @@ -45,7 +46,7 @@ class Test_bgp(unittest.TestCase): def test_open1(self): msg = bgp.BGPOpen(my_as=30000, bgp_identifier='192.0.2.1') binmsg = msg.serialize() - msg2, rest = bgp.BGPMessage.parser(binmsg) + msg2, _, rest = bgp.BGPMessage.parser(binmsg) eq_(str(msg), str(msg2)) eq_(len(msg), 29) eq_(rest, b'') @@ -67,7 +68,7 @@ class Test_bgp(unittest.TestCase): msg = bgp.BGPOpen(my_as=30000, bgp_identifier='192.0.2.2', opt_param=opt_param) binmsg = msg.serialize() - msg2, rest = bgp.BGPMessage.parser(binmsg) + msg2, _, rest = bgp.BGPMessage.parser(binmsg) eq_(str(msg), str(msg2)) ok_(len(msg) > 29) eq_(rest, b'') @@ -75,7 +76,7 @@ class Test_bgp(unittest.TestCase): def test_update1(self): msg = bgp.BGPUpdate() binmsg = msg.serialize() - msg2, rest = bgp.BGPMessage.parser(binmsg) + msg2, _, rest = bgp.BGPMessage.parser(binmsg) eq_(str(msg), str(msg2)) eq_(len(msg), 23) eq_(rest, b'') @@ -153,7 +154,7 @@ class Test_bgp(unittest.TestCase): path_attributes=path_attributes, nlri=nlri) binmsg = msg.serialize() - msg2, rest = bgp.BGPMessage.parser(binmsg) + msg2, _, rest = bgp.BGPMessage.parser(binmsg) eq_(str(msg), str(msg2)) ok_(len(msg) > 23) eq_(rest, b'') @@ -161,7 +162,7 @@ class Test_bgp(unittest.TestCase): def test_keepalive(self): msg = bgp.BGPKeepAlive() binmsg = msg.serialize() - msg2, rest = bgp.BGPMessage.parser(binmsg) + msg2, _, rest = bgp.BGPMessage.parser(binmsg) eq_(str(msg), str(msg2)) eq_(len(msg), 19) eq_(rest, b'') @@ -170,7 +171,7 @@ class Test_bgp(unittest.TestCase): data = b'hoge' msg = bgp.BGPNotification(error_code=1, error_subcode=2, data=data) binmsg = msg.serialize() - msg2, rest = bgp.BGPMessage.parser(binmsg) + msg2, _, rest = bgp.BGPMessage.parser(binmsg) eq_(str(msg), str(msg2)) eq_(len(msg), 21 + len(data)) eq_(rest, b'') @@ -178,7 +179,7 @@ class Test_bgp(unittest.TestCase): def test_route_refresh(self): msg = bgp.BGPRouteRefresh(afi=afi.IP, safi=safi.MPLS_VPN) binmsg = msg.serialize() - msg2, rest = bgp.BGPMessage.parser(binmsg) + msg2, _, rest = bgp.BGPMessage.parser(binmsg) eq_(str(msg), str(msg2)) eq_(len(msg), 23) eq_(rest, b'') @@ -208,11 +209,13 @@ class Test_bgp(unittest.TestCase): ] for f in files: - print('testing %s' % f) - msg_buf = open(BGP4_PACKET_DATA_DIR + f + '.pcap', 'rb').read() - pkt = packet.Packet(msg_buf) - pkt.serialize() - eq_(msg_buf, pkt.data) + print('\n*** testing %s ...' % f) + for _, buf in pcaplib.Reader( + open(BGP4_PACKET_DATA_DIR + f + '.pcap', 'rb')): + pkt = packet.Packet(buf) + print(pkt) + pkt.serialize() + eq_(buf, pkt.data) def test_json1(self): opt_param = [bgp.BGPOptParamCapabilityUnknown(cap_code=200, -- 2.7.4 ------------------------------------------------------------------------------ _______________________________________________ Ryu-devel mailing list Ryu-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/ryu-devel