summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorHenkel, Michael <michael.henkel@hp.com>2013-02-05 23:23:32 +0900
committerFUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>2013-02-05 23:34:43 +0900
commite91758277c902bf11ecb1ae8b68200f290ab49cb (patch)
tree03160c68d639e98f2e710f0cfc83317a21212a6a
parentbed275ec1babab43c8c790c9ad8ba1ae4b8406a2 (diff)
packet lib: add ipv6 ICMP support
Signed-off-by: "Henkel, Michael" <michael.henkel@hp.com> Signed-off-by: FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>
-rw-r--r--ryu/lib/packet/icmp6.py179
-rw-r--r--ryu/lib/packet/ipv6.py2
2 files changed, 181 insertions, 0 deletions
diff --git a/ryu/lib/packet/icmp6.py b/ryu/lib/packet/icmp6.py
new file mode 100644
index 00000000..72e12482
--- /dev/null
+++ b/ryu/lib/packet/icmp6.py
@@ -0,0 +1,179 @@
+# 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
+import sys
+import array
+import binascii
+from . import packet_base
+from . import packet_utils
+from ryu.lib.mac import haddr_to_bin, haddr_to_str
+
+ICMP6_DST_UNREACH = 1 # dest unreachable, codes:
+ICMP6_PACKET_TOO_BIG = 2 # packet too big
+ICMP6_TIME_EXCEEDED = 3 # time exceeded, code:
+ICMP6_PARAM_PROB = 4 # ip6 header bad
+
+ICMP6_ECHO_REQUEST = 128 # echo service
+ICMP6_ECHO_REPLY = 129 # echo reply
+MLD_LISTENER_QUERY = 130 # multicast listener query
+MLD_LISTENER_REPOR = 131 # multicast listener report
+MLD_LISTENER_DONE = 132 # multicast listener done
+
+# RFC2292 decls
+ICMP6_MEMBERSHIP_QUERY = 130 # group membership query
+ICMP6_MEMBERSHIP_REPORT = 131 # group membership report
+ICMP6_MEMBERSHIP_REDUCTION = 132 # group membership termination
+
+ND_ROUTER_SOLICIT = 133 # router solicitation
+ND_ROUTER_ADVERT = 134 # router advertisment
+ND_NEIGHBOR_SOLICIT = 135 # neighbor solicitation
+ND_NEIGHBOR_ADVERT = 136 # neighbor advertisment
+ND_REDIREC = 137 # redirect
+
+ICMP6_ROUTER_RENUMBERING = 138 # router renumbering
+
+ICMP6_WRUREQUEST = 139 # who are you request
+ICMP6_WRUREPLY = 140 # who are you reply
+ICMP6_FQDN_QUERY = 139 # FQDN query
+ICMP6_FQDN_REPLY = 140 # FQDN reply
+ICMP6_NI_QUERY = 139 # node information request
+ICMP6_NI_REPLY = 140 # node information reply
+
+ICMP6_MAXTYPE = 201
+
+
+class icmp6(packet_base.PacketBase):
+ _PACK_STR = '!BBH'
+ _MIN_LEN = struct.calcsize(_PACK_STR)
+ _ICMP6_TYPES = {}
+
+ @staticmethod
+ def register_icmp6_type(*args):
+ def _register_icmp6_type(cls):
+ for type_ in args:
+ icmp6._ICMP6_TYPES[type_] = cls
+ return cls
+ return _register_icmp6_type
+
+ def __init__(self, type_, code, csum, data=None):
+ super(icmp6, self).__init__()
+ 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._ICMP6_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(icmp6._PACK_STR, self.type_,
+ self.code, self.csum))
+
+ if self.data is not None:
+ if self.type_ in icmp6._ICMP6_TYPES:
+ hdr += self.data.serialize()
+ else:
+ hdr += self.data
+ src = prev.src
+ dst = prev.dst
+ nxt = prev.nxt
+ if self.csum == 0:
+ length = len(str(hdr))
+ ph = struct.pack('!16s16sBBH', prev.src, prev.dst, 0, prev.nxt,
+ length)
+ f = ph + hdr + payload
+ if len(f) % 2:
+ f += '\x00'
+ self.csum = socket.htons(packet_utils.checksum(f))
+ struct.pack_into('!H', hdr, 2, self.csum)
+
+ return hdr
+
+
+@icmp6.register_icmp6_type(ND_NEIGHBOR_SOLICIT, ND_NEIGHBOR_ADVERT)
+class nd_s(object):
+ _PACK_STR = '!I16sBB6s'
+ _MIN_LEN = struct.calcsize(_PACK_STR)
+
+ def __init__(self, res, dst, type_, length, hw_src, data=None):
+ self.res = res << 29
+ self.dst = dst
+ self.type_ = type_
+ self.length = length
+ self.hw_src = hw_src
+ self.data = data
+
+ @classmethod
+ def parser(cls, buf, offset):
+ (res, dst, type_, length, hw_src) = struct.unpack_from(cls._PACK_STR,
+ buf, offset)
+ msg = cls(res, dst, type_, length, hw_src)
+ offset += cls._MIN_LEN
+ if len(buf) > offset:
+ msg.data = buf[offset:]
+
+ return msg
+
+ def serialize(self):
+ hdr = bytearray(struct.pack(nd_s._PACK_STR, self.res, self.dst,
+ self.type_, self.length, self.hw_src))
+
+ if self.data is not None:
+ hdr += self.data
+
+ return hdr
+
+
+@icmp6.register_icmp6_type(ICMP6_ECHO_REPLY, ICMP6_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 += bytearray(self.data)
+
+ return hdr
diff --git a/ryu/lib/packet/ipv6.py b/ryu/lib/packet/ipv6.py
index 8fc9d0de..4f1325ea 100644
--- a/ryu/lib/packet/ipv6.py
+++ b/ryu/lib/packet/ipv6.py
@@ -17,6 +17,7 @@ import struct
import socket
from . import packet_base
from . import packet_utils
+from . import icmp6
from . import tcp
from ryu.ofproto import inet
@@ -64,4 +65,5 @@ class ipv6(packet_base.PacketBase):
self.src, self.dst)
return hdr
+ipv6.register_packet_type(icmp6.icmp6, inet.IPPROTO_ICMP6)
ipv6.register_packet_type(tcp.tcp, inet.IPPROTO_TCP)