From 12e9445c8778516da10fb04b52bf46747c7913e5 Mon Sep 17 00:00:00 2001 From: OHMURA Kei Date: Thu, 4 Oct 2012 10:59:24 +0900 Subject: [PATCH] packet lib: add icmp.py Signed-off-by: OHMURA Kei Signed-off-by: FUJITA Tomonori --- ryu/lib/packet/icmp.py | 112 +++++++++++++++++++++++++++++++++++++++++ ryu/lib/packet/ipv4.py | 2 + 2 files changed, 114 insertions(+) create mode 100644 ryu/lib/packet/icmp.py diff --git a/ryu/lib/packet/icmp.py b/ryu/lib/packet/icmp.py new file mode 100644 index 00000000..cce7e979 --- /dev/null +++ b/ryu/lib/packet/icmp.py @@ -0,0 +1,112 @@ +# Copyright (C) 2012 Nippon Telegraph and Telephone Corporation. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +# implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import struct +import socket +from . import packet_base +from . import packet_utils + + +ICMP_ECHO_REPLY = 0 +ICMP_DEST_UNREACH = 3 +ICMP_SRC_QUENCH = 4 +ICMP_REDIRECT = 5 +ICMP_ECHO_REQUEST = 8 + + +class icmp(packet_base.PacketBase): + _PACK_STR = '!BBH' + _MIN_LEN = struct.calcsize(_PACK_STR) + _ICMP_TYPES = {} + + @staticmethod + def register_icmp_type(*args): + def _register_icmp_type(cls): + for type_ in args: + icmp._ICMP_TYPES[type_] = cls + return cls + return _register_icmp_type + + def __init__(self, type_, code, csum, data=None): + super(icmp, self).__init__() + print 'icmp._ICMP_TYPES:', icmp._ICMP_TYPES + self.type = type_ + self.code = code + self.csum = csum + self.data = data + + @classmethod + def parser(cls, buf): + (type_, code, csum) = struct.unpack_from(cls._PACK_STR, buf) + msg = cls(type_, code, csum) + offset = cls._MIN_LEN + + if len(buf) > offset: + cls_ = cls._ICMP_TYPES.get(type_, None) + if cls_: + msg.data = cls_.parser(buf, offset) + else: + msg.data = buf[offset:] + + return msg, None + + def serialize(self, payload, prev): + hdr = bytearray(struct.pack(icmp._PACK_STR, self.type, + self.code, self.csum)) + + if self.data is not None: + if self.type in icmp._ICMP_TYPES: + hdr += self.data.serialize() + else: + hdr += self.data + + if self.csum == 0: + if len(hdr) % 2: + hdr += '\0' + self.csum = socket.htons(packet_utils.checksum(hdr)) + struct.pack_into('!H', hdr, 2, self.csum) + + return hdr + + +@icmp.register_icmp_type(ICMP_ECHO_REPLY, ICMP_ECHO_REQUEST) +class echo(object): + _PACK_STR = '!HH' + _MIN_LEN = struct.calcsize(_PACK_STR) + + def __init__(self, id_, seq, data=None): + self.id = id_ + self.seq = seq + self.data = data + + @classmethod + def parser(cls, buf, offset): + (id_, seq) = struct.unpack_from(cls._PACK_STR, buf, offset) + msg = cls(id_, seq) + offset += cls._MIN_LEN + + if len(buf) > offset: + msg.data = buf[offset:] + + return msg + + def serialize(self): + hdr = bytearray(struct.pack(Echo._PACK_STR, self.id, + self.seq)) + + if self.data is not None: + hdr += self.data + + return hdr diff --git a/ryu/lib/packet/ipv4.py b/ryu/lib/packet/ipv4.py index 21d227ad..d3cc4b3e 100644 --- a/ryu/lib/packet/ipv4.py +++ b/ryu/lib/packet/ipv4.py @@ -17,6 +17,7 @@ import struct import socket from . import packet_base from . import packet_utils +from . import icmp from . import udp from . import tcp from ryu.ofproto import inet @@ -79,5 +80,6 @@ class ipv4(packet_base.PacketBase): struct.pack_into('!H', hdr, 10, self.csum) return hdr +ipv4.register_packet_type(icmp.icmp, inet.IPPROTO_ICMP) ipv4.register_packet_type(tcp.tcp, inet.IPPROTO_TCP) ipv4.register_packet_type(udp.udp, inet.IPPROTO_UDP)