summaryrefslogtreecommitdiffhomepage
path: root/ryu/lib/packet/icmpv6.py
diff options
context:
space:
mode:
Diffstat (limited to 'ryu/lib/packet/icmpv6.py')
-rw-r--r--ryu/lib/packet/icmpv6.py283
1 files changed, 283 insertions, 0 deletions
diff --git a/ryu/lib/packet/icmpv6.py b/ryu/lib/packet/icmpv6.py
index bef1bd76..4ba1d63d 100644
--- a/ryu/lib/packet/icmpv6.py
+++ b/ryu/lib/packet/icmpv6.py
@@ -34,6 +34,7 @@ ICMPV6_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
+MLDV2_LISTENER_REPORT = 143 # multicast listern report (v2)
# RFC2292 decls
ICMPV6_MEMBERSHIP_QUERY = 130 # group membership query
@@ -64,6 +65,13 @@ ND_OPTION_PI = 3 # Prefix Information
ND_OPTION_RH = 4 # Redirected Header
ND_OPTION_MTU = 5 # MTU
+MODE_IS_INCLUDE = 1
+MODE_IS_EXCLUDE = 2
+CHANGE_TO_INCLUDE_MODE = 3
+CHANGE_TO_EXCLUDE_MODE = 4
+ALLOW_NEW_SOURCES = 5
+BLOCK_OLD_SOURCES = 6
+
class icmpv6(packet_base.PacketBase):
"""ICMPv6 (RFC 2463) header encoder/decoder class.
@@ -87,6 +95,7 @@ class icmpv6(packet_base.PacketBase):
ryu.lib.packet.icmpv6.nd_neighbor object, \
ryu.lib.packet.icmpv6.nd_router_solicit object, \
ryu.lib.packet.icmpv6.nd_router_advert object, \
+ ryu.lib.packet.icmpv6.mld object, \
or a bytearray.
============== ====================
"""
@@ -659,6 +668,280 @@ class echo(stringify.StringifyMixin):
return length
+@icmpv6.register_icmpv6_type(
+ MLD_LISTENER_QUERY, MLD_LISTENER_REPOR, MLD_LISTENER_DONE)
+class mld(stringify.StringifyMixin):
+ """ICMPv6 sub encoder/decoder class for MLD Lister Query,
+ MLD Listener Report, and MLD Listener Done messages. (RFC 2710)
+
+ http://www.ietf.org/rfc/rfc2710.txt
+
+ This is used with ryu.lib.packet.icmpv6.icmpv6.
+
+ An instance has the following attributes at least.
+ Most of them are same to the on-wire counterparts but in host byte order.
+ __init__ takes the corresponding args in this order.
+
+ ============== =========================================
+ Attribute Description
+ ============== =========================================
+ maxresp max response time in millisecond. it is
+ meaningful only in Query Message.
+ address a group address value.
+ ============== =========================================
+ """
+
+ _PACK_STR = '!H2x16s'
+ _MIN_LEN = struct.calcsize(_PACK_STR)
+
+ def __init__(self, maxresp=0, address='::'):
+ self.maxresp = maxresp
+ self.address = address
+
+ @classmethod
+ def parser(cls, buf, offset):
+ if cls._MIN_LEN < len(buf[offset:]):
+ msg = mldv2_query.parser(buf[offset:])
+ else:
+ (maxresp, address) = struct.unpack_from(
+ cls._PACK_STR, buf, offset)
+ msg = cls(maxresp, addrconv.ipv6.bin_to_text(address))
+
+ return msg
+
+ def serialize(self):
+ buf = struct.pack(mld._PACK_STR, self.maxresp,
+ addrconv.ipv6.text_to_bin(self.address))
+ return buf
+
+ def __len__(self):
+ return self._MIN_LEN
+
+
+class mldv2_query(mld):
+ """
+ ICMPv6 sub encoder/decoder class for MLD v2 Lister Query messages.
+ (RFC 3810)
+
+ http://www.ietf.org/rfc/rfc3810.txt
+
+ This is used with ryu.lib.packet.icmpv6.icmpv6.
+
+ An instance has the following attributes at least.
+ Most of them are same to the on-wire counterparts but in host byte order.
+ __init__ takes the corresponding args in this order.
+
+ ============== =========================================
+ Attribute Description
+ ============== =========================================
+ maxresp max response time in millisecond. it is
+ meaningful only in Query Message.
+ address a group address value.
+ s_flg when set to 1, routers suppress the timer
+ process.
+ qrv robustness variable for a querier.
+ qqic an interval time for a querier in unit of
+ seconds.
+ num a number of the multicast servers.
+ srcs a list of IPv6 addresses of the multicast
+ servers.
+ ============== =========================================
+ """
+
+ _PACK_STR = '!H2x16sBBH'
+ _MIN_LEN = struct.calcsize(_PACK_STR)
+
+ def __init__(self, maxresp=0, address='::', s_flg=0, qrv=2,
+ qqic=0, num=0, srcs=None):
+ super(mldv2_query, self).__init__(maxresp, address)
+ self.s_flg = s_flg
+ self.qrv = qrv
+ self.qqic = qqic
+ self.num = num
+ srcs = srcs or []
+ assert isinstance(srcs, list)
+ for src in srcs:
+ assert isinstance(src, str)
+ self.srcs = srcs
+
+ @classmethod
+ def parser(cls, buf):
+ (maxresp, address, s_qrv, qqic, num
+ ) = struct.unpack_from(cls._PACK_STR, buf)
+ s_flg = (s_qrv >> 3) & 0b1
+ qrv = s_qrv & 0b111
+ offset = cls._MIN_LEN
+ srcs = []
+ while 0 < len(buf[offset:]) and num > len(srcs):
+ assert 16 <= len(buf[offset:])
+ (src, ) = struct.unpack_from('16s', buf, offset)
+ srcs.append(addrconv.ipv6.bin_to_text(src))
+ offset += 16
+ assert num == len(srcs)
+ return cls(maxresp, addrconv.ipv6.bin_to_text(address), s_flg,
+ qrv, qqic, num, srcs)
+
+ def serialize(self):
+ s_qrv = self.s_flg << 3 | self.qrv
+ buf = bytearray(struct.pack(self._PACK_STR, self.maxresp,
+ addrconv.ipv6.text_to_bin(self.address), s_qrv,
+ self.qqic, self.num))
+ for src in self.srcs:
+ buf.extend(struct.pack('16s', addrconv.ipv6.text_to_bin(src)))
+ if 0 == self.num:
+ self.num = len(self.srcs)
+ struct.pack_into('!H', buf, 22, self.num)
+ return str(buf)
+
+ def __len__(self):
+ return self._MIN_LEN + len(self.srcs) * 16
+
+
+@icmpv6.register_icmpv6_type(MLDV2_LISTENER_REPORT)
+class mldv2_report(mld):
+ """
+ ICMPv6 sub encoder/decoder class for MLD v2 Lister Report messages.
+ (RFC 3810)
+
+ http://www.ietf.org/rfc/rfc3810.txt
+
+ This is used with ryu.lib.packet.icmpv6.icmpv6.
+
+ An instance has the following attributes at least.
+ Most of them are same to the on-wire counterparts but in host byte order.
+ __init__ takes the corresponding args in this order.
+
+ ============== =========================================
+ Attribute Description
+ ============== =========================================
+ record_num a number of the group records.
+ records a list of ryu.lib.packet.icmpv6.mldv2_report_group.
+ None if no records.
+ ============== =========================================
+ """
+
+ _PACK_STR = '!2xH'
+ _MIN_LEN = struct.calcsize(_PACK_STR)
+ _class_prefixes = ['mldv2_report_group']
+
+ def __init__(self, record_num=0, records=None):
+ self.record_num = record_num
+ records = records or []
+ assert isinstance(records, list)
+ for record in records:
+ assert isinstance(record, mldv2_report_group)
+ self.records = records
+
+ @classmethod
+ def parser(cls, buf, offset):
+ (record_num, ) = struct.unpack_from(cls._PACK_STR, buf, offset)
+ offset += cls._MIN_LEN
+ records = []
+ while 0 < len(buf[offset:]) and record_num > len(records):
+ record = mldv2_report_group.parser(buf[offset:])
+ records.append(record)
+ offset += len(record)
+ assert record_num == len(records)
+ return cls(record_num, records)
+
+ def serialize(self):
+ buf = bytearray(struct.pack(self._PACK_STR, self.record_num))
+ for record in self.records:
+ buf.extend(record.serialize())
+ if 0 == self.record_num:
+ self.record_num = len(self.records)
+ struct.pack_into('!H', buf, 2, self.record_num)
+ return str(buf)
+
+ def __len__(self):
+ records_len = 0
+ for record in self.records:
+ records_len += len(record)
+ return self._MIN_LEN + records_len
+
+
+class mldv2_report_group(stringify.StringifyMixin):
+ """
+ ICMPv6 sub encoder/decoder class for MLD v2 Lister Report Group
+ Record messages. (RFC 3810)
+
+ This is used with ryu.lib.packet.icmpv6.mldv2_report.
+
+ An instance has the following attributes at least.
+ Most of them are same to the on-wire counterparts but in host byte
+ order.
+ __init__ takes the corresponding args in this order.
+
+ =============== ====================================================
+ Attribute Description
+ =============== ====================================================
+ type\_ a group record type for v3.
+ aux_len the length of the auxiliary data in 32-bit words.
+ num a number of the multicast servers.
+ address a group address value.
+ srcs a list of IPv6 addresses of the multicast servers.
+ aux the auxiliary data.
+ =============== ====================================================
+ """
+ _PACK_STR = '!BBH16s'
+ _MIN_LEN = struct.calcsize(_PACK_STR)
+
+ def __init__(self, type_=0, aux_len=0, num=0, address='::',
+ srcs=None, aux=None):
+ self.type_ = type_
+ self.aux_len = aux_len
+ self.num = num
+ self.address = address
+ srcs = srcs or []
+ assert isinstance(srcs, list)
+ for src in srcs:
+ assert isinstance(src, str)
+ self.srcs = srcs
+ self.aux = aux
+
+ @classmethod
+ def parser(cls, buf):
+ (type_, aux_len, num, address
+ ) = struct.unpack_from(cls._PACK_STR, buf)
+ offset = cls._MIN_LEN
+ srcs = []
+ while 0 < len(buf[offset:]) and num > len(srcs):
+ assert 16 <= len(buf[offset:])
+ (src, ) = struct.unpack_from('16s', buf, offset)
+ srcs.append(addrconv.ipv6.bin_to_text(src))
+ offset += 16
+ assert num == len(srcs)
+ aux = None
+ if aux_len:
+ (aux, ) = struct.unpack_from('%ds' % (aux_len * 4), buf, offset)
+ msg = cls(type_, aux_len, num, addrconv.ipv6.bin_to_text(address),
+ srcs, aux)
+ return msg
+
+ def serialize(self):
+ buf = bytearray(struct.pack(self._PACK_STR, self.type_,
+ self.aux_len, self.num,
+ addrconv.ipv6.text_to_bin(self.address)))
+ for src in self.srcs:
+ buf.extend(struct.pack('16s', addrconv.ipv6.text_to_bin(src)))
+ if 0 == self.num:
+ self.num = len(self.srcs)
+ struct.pack_into('!H', buf, 2, self.num)
+ if self.aux is not None:
+ mod = len(self.aux) % 4
+ if mod:
+ self.aux += bytearray(4 - mod)
+ self.aux = str(self.aux)
+ buf.extend(self.aux)
+ if 0 == self.aux_len:
+ self.aux_len = len(self.aux) / 4
+ struct.pack_into('!B', buf, 1, self.aux_len)
+ return str(buf)
+
+ def __len__(self):
+ return self._MIN_LEN + len(self.srcs) * 16 + self.aux_len * 4
+
+
icmpv6.set_classes(icmpv6._ICMPV6_TYPES)
nd_neighbor.set_classes(nd_neighbor._ND_OPTION_TYPES)
nd_router_solicit.set_classes(nd_router_solicit._ND_OPTION_TYPES)