summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorOHMURA Kei <ohmura.kei@lab.ntt.co.jp>2012-10-04 10:59:24 +0900
committerFUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>2012-10-04 10:59:24 +0900
commit12e9445c8778516da10fb04b52bf46747c7913e5 (patch)
treefad3fad3df43bfb81a08177ba7eaa70050b795a1
parentb624e6369bc8d6b7ec42b5c491c764c9e799a17a (diff)
packet lib: add icmp.py
Signed-off-by: OHMURA Kei <ohmura.kei@lab.ntt.co.jp> Signed-off-by: FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>
-rw-r--r--ryu/lib/packet/icmp.py112
-rw-r--r--ryu/lib/packet/ipv4.py2
2 files changed, 114 insertions, 0 deletions
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)