backing up
[vsorcdistro/.git] / ryu / build / lib.linux-armv7l-2.7 / ryu / lib / packet / ospf.py
diff --git a/ryu/build/lib.linux-armv7l-2.7/ryu/lib/packet/ospf.py b/ryu/build/lib.linux-armv7l-2.7/ryu/lib/packet/ospf.py
new file mode 100644 (file)
index 0000000..5c156c0
--- /dev/null
@@ -0,0 +1,949 @@
+# Copyright (C) 2013 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.
+
+"""
+RFC 2328 OSPF version 2
+"""
+
+from functools import reduce
+import logging
+import struct
+
+import six
+
+from ryu.lib import addrconv
+from ryu.lib.packet import packet_base
+from ryu.lib.packet import packet_utils
+from ryu.lib.packet import stream_parser
+from ryu.lib.stringify import StringifyMixin
+from ryu.lib import type_desc
+
+
+LOG = logging.getLogger(__name__)
+
+_VERSION = 2
+
+OSPF_MSG_UNKNOWN = 0
+OSPF_MSG_HELLO = 1
+OSPF_MSG_DB_DESC = 2
+OSPF_MSG_LS_REQ = 3
+OSPF_MSG_LS_UPD = 4
+OSPF_MSG_LS_ACK = 5
+
+OSPF_UNKNOWN_LSA = 0
+OSPF_ROUTER_LSA = 1
+OSPF_NETWORK_LSA = 2
+OSPF_SUMMARY_LSA = 3
+OSPF_ASBR_SUMMARY_LSA = 4
+OSPF_AS_EXTERNAL_LSA = 5
+OSPF_AS_NSSA_LSA = 7       # RFC 3101
+OSPF_OPAQUE_LINK_LSA = 9   # RFC 5250
+OSPF_OPAQUE_AREA_LSA = 10  # RFC 5250
+OSPF_OPAQUE_AS_LSA = 11    # RFC 5250
+
+OSPF_OPTION_T = 1        # Obsolete
+OSPF_OPTION_E = 1 << 1   # RFC 2328
+OSPF_OPTION_MC = 1 << 2  # RFC 1584
+OSPF_OPTION_NP = 1 << 3  # RFC 3101
+OSPF_OPTION_EA = 1 << 4  # Obsolete
+OSPF_OPTION_DC = 1 << 5  # RFC 2370
+OSPF_OPTION_DN = 1 << 7  # RFC 2567
+
+LSA_LINK_TYPE_P2P = 1
+LSA_LINK_TYPE_TRANSIT = 2
+LSA_LINK_TYPE_STUB = 3
+LSA_LINK_TYPE_VL = 4
+
+ROUTER_LSA_BORDER = 0x01  # The router is an ABR
+ROUTER_LSA_EXTERNAL = 0x02  # The router is an ASBR
+ROUTER_LSA_VIRTUAL = 0x04  # The router has a VL in this area
+ROUTER_LSA_NT = 0x10  # The router always translates Type-7
+ROUTER_LSA_SHORTCUT = 0x20  # Shortcut-ABR specific flag
+
+AS_EXTERNAL_METRIC = 0x80
+
+OSPF_OPAQUE_TYPE_UNKNOWN = 0
+OSPF_OPAQUE_TYPE_EXTENDED_PREFIX_LSA = 7
+OSPF_OPAQUE_TYPE_EXTENDED_LINK_LSA = 8
+
+OSPF_EXTENDED_PREFIX_TLV = 1
+OSPF_EXTENDED_PREFIX_SID_SUBTLV = 2
+
+
+class InvalidChecksum(Exception):
+    pass
+
+
+class LSAHeader(StringifyMixin):
+    _HDR_PACK_STR = '!HBB4s4sIHH'
+    _HDR_LEN = struct.calcsize(_HDR_PACK_STR)
+
+    def __init__(self, ls_age=0, options=0, type_=OSPF_UNKNOWN_LSA,
+                 id_='0.0.0.0', adv_router='0.0.0.0', ls_seqnum=0,
+                 checksum=0, length=0, opaque_type=OSPF_OPAQUE_TYPE_UNKNOWN,
+                 opaque_id=0):
+        self.ls_age = ls_age
+        self.options = options
+        self.type_ = type_
+        if self.type_ < OSPF_OPAQUE_LINK_LSA:
+            self.id_ = id_
+        else:
+            self.opaque_type = opaque_type
+            self.opaque_id = opaque_id
+        self.adv_router = adv_router
+        self.ls_seqnum = ls_seqnum
+        self.checksum = checksum
+        self.length = length
+
+    @classmethod
+    def parser(cls, buf):
+        if len(buf) < cls._HDR_LEN:
+            raise stream_parser.StreamParser.TooSmallException(
+                '%d < %d' % (len(buf), cls._HDR_LEN))
+        (ls_age, options, type_, id_, adv_router, ls_seqnum, checksum,
+         length,) = struct.unpack_from(cls._HDR_PACK_STR, six.binary_type(buf))
+        adv_router = addrconv.ipv4.bin_to_text(adv_router)
+        rest = buf[cls._HDR_LEN:]
+        lsacls = LSA._lookup_type(type_)
+
+        value = {
+            "ls_age": ls_age,
+            "options": options,
+            "type_": type_,
+            "adv_router": adv_router,
+            "ls_seqnum": ls_seqnum,
+            "checksum": checksum,
+            "length": length,
+        }
+
+        if issubclass(lsacls, OpaqueLSA):
+            (id_,) = struct.unpack_from('!I', id_)
+            value['opaque_type'] = (id_ & 0xff000000) >> 24
+            value['opaque_id'] = (id_ & 0xffffff)
+        else:
+            value['id_'] = addrconv.ipv4.bin_to_text(id_)
+
+        return value, rest
+
+    def serialize(self):
+        if self.type_ < OSPF_OPAQUE_LINK_LSA:
+            id_ = addrconv.ipv4.text_to_bin(self.id_)
+        else:
+            id_ = (self.opaque_type << 24) + self.opaque_id
+            (id_,) = struct.unpack_from('4s', struct.pack('!I', id_))
+
+        adv_router = addrconv.ipv4.text_to_bin(self.adv_router)
+        return bytearray(
+            struct.pack(self._HDR_PACK_STR, self.ls_age,
+                        self.options, self.type_, id_, adv_router,
+                        self.ls_seqnum, self.checksum, self.length))
+
+
+class LSA(type_desc.TypeDisp, StringifyMixin):
+    def __init__(self, ls_age=0, options=0, type_=OSPF_UNKNOWN_LSA,
+                 id_='0.0.0.0', adv_router='0.0.0.0', ls_seqnum=0,
+                 checksum=0, length=0, opaque_type=OSPF_OPAQUE_TYPE_UNKNOWN,
+                 opaque_id=0):
+        if type_ < OSPF_OPAQUE_LINK_LSA:
+            self.header = LSAHeader(
+                ls_age=ls_age,
+                options=options,
+                type_=type_,
+                id_=id_,
+                adv_router=adv_router,
+                ls_seqnum=ls_seqnum)
+        else:
+            self.header = LSAHeader(
+                ls_age=ls_age,
+                options=options,
+                type_=type_,
+                adv_router=adv_router,
+                ls_seqnum=ls_seqnum,
+                opaque_type=opaque_type,
+                opaque_id=opaque_id)
+
+        if not (checksum or length):
+            tail = self.serialize_tail()
+            length = self.header._HDR_LEN + len(tail)
+        if not checksum:
+            head = self.header.serialize()
+            checksum = packet_utils.fletcher_checksum(head[2:], 14)
+        self.header.length = length
+        self.header.checksum = checksum
+
+    @classmethod
+    def parser(cls, buf):
+        hdr, rest = LSAHeader.parser(buf)
+        if len(buf) < hdr['length']:
+            raise stream_parser.StreamParser.TooSmallException(
+                '%d < %d' % (len(buf), hdr['length']))
+        # exclude ls_age for checksum calculation
+        csum = packet_utils.fletcher_checksum(buf[2:hdr['length']], 14)
+        if csum != hdr['checksum']:
+            raise InvalidChecksum("header has %d, but calculated value is %d"
+                                  % (hdr['checksum'], csum))
+        subcls = cls._lookup_type(hdr['type_'])
+        body = rest[:hdr['length'] - LSAHeader._HDR_LEN]
+        rest = rest[hdr['length'] - LSAHeader._HDR_LEN:]
+        if issubclass(subcls, OpaqueLSA):
+            kwargs = subcls.parser(body, hdr['opaque_type'])
+        else:
+            kwargs = subcls.parser(body)
+        kwargs.update(hdr)
+        return subcls(**kwargs), subcls, rest
+
+    def serialize(self):
+        tail = self.serialize_tail()
+        self.header.length = self.header._HDR_LEN + len(tail)
+        head = self.header.serialize()
+        # exclude ls_age for checksum calculation
+        csum = packet_utils.fletcher_checksum(head[2:] + tail, 14)
+        self.header.checksum = csum
+        struct.pack_into("!H", head, 16, csum)
+        return head + tail
+
+    def serialize_tail(self):
+        # should be implemented in subclass
+        return b''
+
+
+@LSA.register_type(OSPF_ROUTER_LSA)
+class RouterLSA(LSA):
+    _PACK_STR = '!BBH'
+    _PACK_LEN = struct.calcsize(_PACK_STR)  # 4bytes
+
+    class Link(StringifyMixin):
+        _PACK_STR = '!4s4sBBH'
+        _PACK_LEN = struct.calcsize(_PACK_STR)  # 12bytes
+
+        def __init__(self, id_='0.0.0.0', data='0.0.0.0',
+                     type_=LSA_LINK_TYPE_STUB, tos=0, metric=10):
+            self.id_ = id_
+            self.data = data
+            self.type_ = type_
+            self.tos = tos
+            self.metric = metric
+
+        @classmethod
+        def parser(cls, buf):
+            if len(buf) < cls._PACK_LEN:
+                raise stream_parser.StreamParser.TooSmallException(
+                    '%d < %d' % (len(buf), cls._PACK_LEN))
+            link = buf[:cls._PACK_LEN]
+            rest = buf[cls._PACK_LEN:]
+            (id_, data, type_, tos, metric) = \
+                struct.unpack_from(cls._PACK_STR, six.binary_type(link))
+            id_ = addrconv.ipv4.bin_to_text(id_)
+            data = addrconv.ipv4.bin_to_text(data)
+            return cls(id_, data, type_, tos, metric), rest
+
+        def serialize(self):
+            id_ = addrconv.ipv4.text_to_bin(self.id_)
+            data = addrconv.ipv4.text_to_bin(self.data)
+            return bytearray(
+                struct.pack(self._PACK_STR, id_, data, self.type_, self.tos,
+                            self.metric))
+
+    def __init__(self, ls_age=0, options=0, type_=OSPF_ROUTER_LSA,
+                 id_='0.0.0.0', adv_router='0.0.0.0', ls_seqnum=0,
+                 checksum=None, length=None, flags=0, links=None):
+        links = links if links else []
+        self.flags = flags
+        self.links = links
+        super(RouterLSA, self).__init__(ls_age, options, type_, id_,
+                                        adv_router, ls_seqnum, checksum,
+                                        length)
+
+    @classmethod
+    def parser(cls, buf):
+        links = []
+        hdr = buf[:cls._PACK_LEN]
+        buf = buf[cls._PACK_LEN:]
+        (flags, _, num) = struct.unpack_from(cls._PACK_STR,
+                                             six.binary_type(hdr))
+        while buf:
+            link, buf = cls.Link.parser(buf)
+            links.append(link)
+        assert len(links) == num
+        return {
+            "flags": flags,
+            "links": links,
+        }
+
+    def serialize_tail(self):
+        head = bytearray(
+            struct.pack(self._PACK_STR, self.flags, 0, len(self.links)))
+        try:
+            return head + reduce(lambda a, b: a + b,
+                                 (link.serialize() for link in self.links))
+        except TypeError:
+            return head
+
+
+@LSA.register_type(OSPF_NETWORK_LSA)
+class NetworkLSA(LSA):
+    _PACK_STR = '!4s'
+    _PACK_LEN = struct.calcsize(_PACK_STR)
+
+    def __init__(self, ls_age=0, options=0, type_=OSPF_NETWORK_LSA,
+                 id_='0.0.0.0', adv_router='0.0.0.0', ls_seqnum=0,
+                 checksum=None, length=None, mask='0.0.0.0', routers=None):
+        routers = routers if routers else []
+        self.mask = mask
+        self.routers = routers
+        super(NetworkLSA, self).__init__(ls_age, options, type_, id_,
+                                         adv_router, ls_seqnum, checksum,
+                                         length)
+
+    @classmethod
+    def parser(cls, buf):
+        if len(buf) < cls._PACK_LEN:
+            raise stream_parser.StreamParser.TooSmallException(
+                '%d < %d' % (len(buf), cls._PACK_LEN))
+        binmask = buf[:cls._PACK_LEN]
+        (mask,) = struct.unpack_from(cls._PACK_STR, six.binary_type(binmask))
+        mask = addrconv.ipv4.bin_to_text(mask)
+        buf = buf[cls._PACK_LEN:]
+        routers = []
+        while buf:
+            binrouter = buf[:cls._PACK_LEN]
+            (router,) = struct.unpack_from(cls._PACK_STR,
+                                           six.binary_type(binrouter))
+            router = addrconv.ipv4.bin_to_text(router)
+            routers.append(router)
+            buf = buf[cls._PACK_LEN:]
+        return {
+            "mask": mask,
+            "routers": routers,
+        }
+
+    def serialize_tail(self):
+        mask = addrconv.ipv4.text_to_bin(self.mask)
+        routers = [addrconv.ipv4.text_to_bin(router)
+                   for router in self.routers]
+        return bytearray(
+            struct.pack("!" + "4s" * (1 + len(routers)), mask, *routers))
+
+
+@LSA.register_type(OSPF_SUMMARY_LSA)
+class SummaryLSA(LSA):
+    _PACK_STR = '!4sB3s'
+    _PACK_LEN = struct.calcsize(_PACK_STR)
+
+    def __init__(self, ls_age=0, options=0, type_=OSPF_SUMMARY_LSA,
+                 id_='0.0.0.0', adv_router='0.0.0.0', ls_seqnum=0,
+                 checksum=None, length=None, mask='0.0.0.0', tos=0, metric=0):
+        self.mask = mask
+        self.tos = tos
+        self.metric = metric
+        super(SummaryLSA, self).__init__(ls_age, options, type_, id_,
+                                         adv_router, ls_seqnum, checksum,
+                                         length)
+
+    @classmethod
+    def parser(cls, buf):
+        if len(buf) < cls._PACK_LEN:
+            raise stream_parser.StreamParser.TooSmallException(
+                '%d < %d' % (len(buf), cls._PACK_LEN))
+        buf = buf[:cls._PACK_LEN]
+        (mask, tos, metric) = struct.unpack_from(
+            cls._PACK_STR, six.binary_type(buf))
+        mask = addrconv.ipv4.bin_to_text(mask)
+        metric = type_desc.Int3.to_user(metric)
+        return {
+            "mask": mask,
+            "tos": tos,
+            "metric": metric,
+        }
+
+    def serialize_tail(self):
+        mask = addrconv.ipv4.text_to_bin(self.mask)
+        metric = type_desc.Int3.from_user(self.metric)
+        return bytearray(struct.pack(self._PACK_STR, mask, self.tos, metric))
+
+
+@LSA.register_type(OSPF_ASBR_SUMMARY_LSA)
+class ASBRSummaryLSA(LSA):
+    pass
+
+
+@LSA.register_type(OSPF_AS_EXTERNAL_LSA)
+class ASExternalLSA(LSA):
+    class ExternalNetwork(StringifyMixin):
+        _PACK_STR = '!4sB3s4sI'
+        _PACK_LEN = struct.calcsize(_PACK_STR)
+
+        def __init__(self, mask='0.0.0.0', flags=0, metric=0,
+                     fwd_addr='0.0.0.0', tag=0):
+            self.mask = mask
+            self.flags = flags
+            self.metric = metric
+            self.fwd_addr = fwd_addr
+            self.tag = tag
+
+        @classmethod
+        def parser(cls, buf):
+            if len(buf) < cls._PACK_LEN:
+                raise stream_parser.StreamParser.TooSmallException(
+                    '%d < %d' % (len(buf), cls._PACK_LEN))
+            ext_nw = buf[:cls._PACK_LEN]
+            rest = buf[cls._PACK_LEN:]
+            (mask, flags, metric, fwd_addr,
+             tag) = struct.unpack_from(cls._PACK_STR, six.binary_type(ext_nw))
+            mask = addrconv.ipv4.bin_to_text(mask)
+            metric = type_desc.Int3.to_user(metric)
+            fwd_addr = addrconv.ipv4.bin_to_text(fwd_addr)
+            return cls(mask, flags, metric, fwd_addr, tag), rest
+
+        def serialize(self):
+            mask = addrconv.ipv4.text_to_bin(self.mask)
+            metric = type_desc.Int3.from_user(self.metric)
+            fwd_addr = addrconv.ipv4.text_to_bin(self.fwd_addr)
+            return bytearray(
+                struct.pack(self._PACK_STR, mask, self.flags, metric,
+                            fwd_addr, self.tag))
+
+    def __init__(self, ls_age=0, options=0, type_=OSPF_AS_EXTERNAL_LSA,
+                 id_='0.0.0.0', adv_router='0.0.0.0', ls_seqnum=0,
+                 checksum=None, length=None, extnws=None):
+        extnws = extnws if extnws else []
+        self.extnws = extnws
+        super(ASExternalLSA, self).__init__(ls_age, options, type_, id_,
+                                            adv_router, ls_seqnum, checksum,
+                                            length)
+
+    @classmethod
+    def parser(cls, buf):
+        extnws = []
+        while buf:
+            extnw, buf = cls.ExternalNetwork.parser(buf)
+            extnws.append(extnw)
+        return {
+            "extnws": extnws,
+        }
+
+    def serialize_tail(self):
+        return reduce(lambda a, b: a + b,
+                      (extnw.serialize() for extnw in self.extnws))
+
+
+@LSA.register_type(OSPF_AS_NSSA_LSA)
+class NSSAExternalLSA(LSA):
+    pass
+
+
+class ExtendedPrefixTLV(StringifyMixin, type_desc.TypeDisp):
+    pass
+
+
+@ExtendedPrefixTLV.register_type(OSPF_EXTENDED_PREFIX_TLV)
+class ExtendedPrefixTLV(ExtendedPrefixTLV):
+    _VALUE_PACK_STR = '!HHBBBB4s'
+    _VALUE_PACK_LEN = struct.calcsize(_VALUE_PACK_STR)
+    _VALUE_FIELDS = ['route_type', 'prefix_length', 'address_family', '_pad'
+                     'prefix']
+
+    def __init__(self, type_=OSPF_EXTENDED_PREFIX_TLV, length=0, route_type=0,
+                 address_family=0, prefix='0.0.0.0/0'):
+        self.type_ = type_
+        self.length = length
+        self.route_type = route_type
+        self.address_family = address_family
+        self.prefix = prefix
+
+    @classmethod
+    def parser(cls, buf):
+        rest = buf[cls._VALUE_PACK_LEN:]
+        buf = buf[:cls._VALUE_PACK_LEN]
+        (type_, length, route_type, prefix_length, address_family, _pad,
+         prefix) = struct.unpack_from(cls._VALUE_PACK_STR, buf)
+
+        prefix = addrconv.ipv4.bin_to_text(prefix)
+        prefix = "%s/%d" % (prefix, prefix_length)
+        return cls(type_, length, route_type, address_family, prefix), rest
+
+    def serialize(self):
+        prefix, prefix_length = self.prefix.split('/')
+        prefix = addrconv.ipv4.text_to_bin(prefix)
+        prefix_length = int(prefix_length)
+        return struct.pack(self._VALUE_PACK_STR, OSPF_EXTENDED_PREFIX_TLV,
+                           self._VALUE_PACK_LEN - 4, self.route_type,
+                           prefix_length, self.address_family, 0, prefix)
+
+
+@ExtendedPrefixTLV.register_type(OSPF_EXTENDED_PREFIX_SID_SUBTLV)
+class PrefixSIDSubTLV(ExtendedPrefixTLV):
+    _VALUE_PACK_STR = '!HHBBBBHHI'
+    _VALUE_PACK_LEN = struct.calcsize(_VALUE_PACK_STR)
+    _VALUE_FIELDS = ['flags', 'mt_id', 'algorithm', '_pad', 'range_size',
+                     '_pad', 'index']
+
+    def __init__(self, type_=OSPF_EXTENDED_PREFIX_SID_SUBTLV, length=0,
+                 flags=0, mt_id=0, algorithm=0, range_size=0, index=0):
+        super(PrefixSIDSubTLV, self).__init__()
+        self.type_ = type_
+        self.length = length
+        self.flags = flags
+        self.mt_id = mt_id
+        self.algorithm = algorithm
+        self.range_size = range_size
+        self.index = index
+
+    @classmethod
+    def parser(cls, buf):
+        rest = buf[cls._VALUE_PACK_LEN:]
+        buf = buf[:cls._VALUE_PACK_LEN]
+        (type_, length, flags, mt_id, algorithm, _pad, range_size, _pad,
+         index) = struct.unpack_from(cls._VALUE_PACK_STR, buf)
+
+        return cls(type_, length, flags, mt_id, algorithm, range_size,
+                   index), rest
+
+    def serialize(self):
+        return struct.pack(self._VALUE_PACK_STR,
+                           OSPF_EXTENDED_PREFIX_SID_SUBTLV,
+                           self._VALUE_PACK_LEN - 4, self.flags, self.mt_id,
+                           self.algorithm, 0, self.range_size, 0, self.index)
+
+
+class ExtendedLinkTLV(StringifyMixin, type_desc.TypeDisp):
+    pass
+
+
+class OpaqueBody(StringifyMixin, type_desc.TypeDisp):
+    def __init__(self, tlvs=None):
+        tlvs = tlvs if tlvs else []
+        self.tlvs = tlvs
+
+    def serialize(self):
+        return reduce(lambda a, b: a + b,
+                      (tlv.serialize() for tlv in self.tlvs))
+
+
+@OpaqueBody.register_type(OSPF_OPAQUE_TYPE_EXTENDED_PREFIX_LSA)
+class ExtendedPrefixOpaqueBody(OpaqueBody):
+    @classmethod
+    def parser(cls, buf):
+        buf = six.binary_type(buf)
+        tlvs = []
+        while buf:
+            (type_, length) = struct.unpack_from('!HH', buf)
+            if len(buf[struct.calcsize('!HH'):]) < length:
+                raise stream_parser.StreamParser.TooSmallException(
+                    '%d < %d' % (len(buf), length))
+            tlvcls = ExtendedPrefixTLV._lookup_type(type_)
+            if tlvcls:
+                tlv, buf = tlvcls.parser(buf)
+                tlvs.append(tlv)
+
+        return cls(tlvs)
+
+
+@OpaqueBody.register_type(OSPF_OPAQUE_TYPE_EXTENDED_LINK_LSA)
+class ExtendedLinkOpaqueBody(OpaqueBody):
+    @classmethod
+    def parser(cls, buf):
+        buf = six.binary_type(buf)
+        tlvs = []
+        while buf:
+            (type_, length) = struct.unpack_from('!HH', buf)
+            if len(buf[struct.calcsize('!HH'):]) < length:
+                raise stream_parser.StreamParser.TooSmallException(
+                    '%d < %d' % (len(buf), length))
+            tlvcls = ExtendedLinkTLV._lookup_type(type_)
+            if tlvcls:
+                tlv, buf = tlvcls.parser(buf)
+                tlvs.append(tlv)
+
+        return cls(tlvs)
+
+
+class OpaqueLSA(LSA):
+
+    def __init__(self, data, *args, **kwargs):
+        super(OpaqueLSA, self).__init__(*args, **kwargs)
+        self.data = data
+
+    @classmethod
+    def parser(cls, buf, opaque_type=OSPF_OPAQUE_TYPE_UNKNOWN):
+        opaquecls = OpaqueBody._lookup_type(opaque_type)
+        if opaquecls:
+            data = opaquecls.parser(buf)
+        else:
+            data = buf
+        return {'data': data}
+
+    def serialize_tail(self):
+        if isinstance(self.data, OpaqueBody):
+            return self.data.serialize()
+        else:
+            return self.data
+
+
+@LSA.register_type(OSPF_OPAQUE_LINK_LSA)
+class LocalOpaqueLSA(OpaqueLSA):
+    def __init__(self, ls_age=0, options=0, type_=OSPF_OPAQUE_LINK_LSA,
+                 adv_router='0.0.0.0', ls_seqnum=0, checksum=0, length=0,
+                 opaque_type=OSPF_OPAQUE_TYPE_UNKNOWN, opaque_id=0, data=None):
+        self.data = data
+        super(LocalOpaqueLSA, self).__init__(ls_age, options, type_, 0,
+                                             adv_router, ls_seqnum, checksum,
+                                             length, opaque_type, opaque_id)
+
+
+@LSA.register_type(OSPF_OPAQUE_AREA_LSA)
+class AreaOpaqueLSA(OpaqueLSA):
+    def __init__(self, ls_age=0, options=0, type_=OSPF_OPAQUE_AREA_LSA,
+                 adv_router='0.0.0.0', ls_seqnum=0, checksum=0, length=0,
+                 opaque_type=OSPF_OPAQUE_TYPE_UNKNOWN, opaque_id=0, data=None):
+        self.data = data
+        super(AreaOpaqueLSA, self).__init__(ls_age, options, type_, 0,
+                                            adv_router, ls_seqnum, checksum,
+                                            length, opaque_type, opaque_id)
+
+
+@LSA.register_type(OSPF_OPAQUE_AS_LSA)
+class ASOpaqueLSA(OpaqueLSA):
+    def __init__(self, ls_age=0, options=0, type_=OSPF_OPAQUE_AS_LSA,
+                 adv_router='0.0.0.0', ls_seqnum=0, checksum=0, length=0,
+                 opaque_type=OSPF_OPAQUE_TYPE_UNKNOWN, opaque_id=0, data=None):
+        self.data = data
+        super(ASOpaqueLSA, self).__init__(ls_age, options, type_, 0,
+                                          adv_router, ls_seqnum, checksum,
+                                          length, opaque_type, opaque_id)
+
+
+class OSPFMessage(packet_base.PacketBase, type_desc.TypeDisp):
+    """Base class for OSPF version 2 messages.
+    """
+
+    _HDR_PACK_STR = '!BBH4s4sHHQ'
+    _HDR_LEN = struct.calcsize(_HDR_PACK_STR)
+
+    def __init__(self, type_, length=None, router_id='0.0.0.0',
+                 area_id='0.0.0.0', au_type=1, authentication=0, checksum=None,
+                 version=_VERSION):
+        super(OSPFMessage, self).__init__()
+        self.version = version
+        self.type_ = type_
+        self.length = length
+        self.router_id = router_id
+        self.area_id = area_id
+        self.checksum = checksum
+        self.au_type = au_type
+        self.authentication = authentication
+
+    @classmethod
+    def _parser(cls, buf):
+        if len(buf) < cls._HDR_LEN:
+            raise stream_parser.StreamParser.TooSmallException(
+                '%d < %d' % (len(buf), cls._HDR_LEN))
+        (version, type_, length, router_id, area_id, checksum, au_type,
+         authentication) = struct.unpack_from(cls._HDR_PACK_STR,
+                                              six.binary_type(buf))
+
+        # Exclude checksum and authentication field for checksum validation.
+        if packet_utils.checksum(buf[:12] + buf[14:16] + buf[cls._HDR_LEN:]) \
+                != checksum:
+            raise InvalidChecksum
+
+        if len(buf) < length:
+            raise stream_parser.StreamParser.TooSmallException(
+                '%d < %d' % (len(buf), length))
+
+        router_id = addrconv.ipv4.bin_to_text(router_id)
+        area_id = addrconv.ipv4.bin_to_text(area_id)
+        binmsg = buf[cls._HDR_LEN:length]
+        rest = buf[length:]
+        subcls = cls._lookup_type(type_)
+        kwargs = subcls.parser(binmsg)
+        return subcls(length, router_id, area_id, au_type, int(authentication),
+                      checksum, version, **kwargs), None, rest
+
+    @classmethod
+    def parser(cls, buf):
+        try:
+            return cls._parser(buf)
+        except:
+            return None, None, buf
+
+    def serialize(self, payload=None, prev=None):
+        tail = self.serialize_tail()
+        self.length = self._HDR_LEN + len(tail)
+        head = bytearray(
+            struct.pack(self._HDR_PACK_STR, self.version,
+                        self.type_, self.length,
+                        addrconv.ipv4.text_to_bin(self.router_id),
+                        addrconv.ipv4.text_to_bin(self.area_id), 0,
+                        self.au_type, self.authentication))
+        buf = head + tail
+        csum = packet_utils.checksum(buf[:12] + buf[14:16] +
+                                     buf[self._HDR_LEN:])
+        self.checksum = csum
+        struct.pack_into("!H", buf, 12, csum)
+        return buf
+
+
+# alias
+ospf = OSPFMessage
+
+
+@OSPFMessage.register_type(OSPF_MSG_HELLO)
+class OSPFHello(OSPFMessage):
+
+    _PACK_STR = '!4sHBBI4s4s'  # + neighbors
+    _PACK_LEN = struct.calcsize(_PACK_STR)
+    _MIN_LEN = OSPFMessage._HDR_LEN + _PACK_LEN
+
+    def __init__(self, length=None, router_id='0.0.0.0', area_id='0.0.0.0',
+                 au_type=1, authentication=0, checksum=None, version=_VERSION,
+                 mask='0.0.0.0', hello_interval=10, options=0, priority=1,
+                 dead_interval=40, designated_router='0.0.0.0',
+                 backup_router='0.0.0.0', neighbors=None):
+        neighbors = neighbors if neighbors else []
+        super(OSPFHello, self).__init__(OSPF_MSG_HELLO, length, router_id,
+                                        area_id, au_type, authentication,
+                                        checksum, version)
+        self.mask = mask
+        self.hello_interval = hello_interval
+        self.options = options
+        self.priority = priority
+        self.dead_interval = dead_interval
+        self.designated_router = designated_router
+        self.backup_router = backup_router
+        self.neighbors = neighbors
+
+    @classmethod
+    def parser(cls, buf):
+        (mask, hello_interval, options, priority, dead_interval,
+         designated_router, backup_router) = struct.unpack_from(cls._PACK_STR,
+                                                                six.binary_type(buf))
+        mask = addrconv.ipv4.bin_to_text(mask)
+        designated_router = addrconv.ipv4.bin_to_text(designated_router)
+        backup_router = addrconv.ipv4.bin_to_text(backup_router)
+        neighbors = []
+        binneighbors = buf[cls._PACK_LEN:len(buf)]
+        while binneighbors:
+            n = binneighbors[:4]
+            n = addrconv.ipv4.bin_to_text(six.binary_type(n))
+            binneighbors = binneighbors[4:]
+            neighbors.append(n)
+        return {
+            "mask": mask,
+            "hello_interval": hello_interval,
+            "options": options,
+            "priority": priority,
+            "dead_interval": dead_interval,
+            "designated_router": designated_router,
+            "backup_router": backup_router,
+            "neighbors": neighbors,
+        }
+
+    def serialize_tail(self):
+        head = bytearray(
+            struct.pack(self._PACK_STR,
+                        addrconv.ipv4.text_to_bin(self.mask),
+                        self.hello_interval, self.options, self.priority,
+                        self.dead_interval,
+                        addrconv.ipv4.text_to_bin(self.designated_router),
+                        addrconv.ipv4.text_to_bin(self.backup_router)))
+        try:
+            return head + reduce(lambda a, b: a + b,
+                                 (addrconv.ipv4.text_to_bin(n)
+                                  for n in self.neighbors))
+        except TypeError:
+            return head
+
+
+@OSPFMessage.register_type(OSPF_MSG_DB_DESC)
+class OSPFDBDesc(OSPFMessage):
+
+    _PACK_STR = '!HBBI'  # + LSA_HEADERS
+    _PACK_LEN = struct.calcsize(_PACK_STR)
+    _MIN_LEN = OSPFMessage._HDR_LEN + _PACK_LEN
+
+    def __init__(self, length=None, router_id='0.0.0.0', area_id='0.0.0.0',
+                 au_type=1, authentication=0, checksum=None, version=_VERSION,
+                 mtu=1500, options=0, i_flag=0, m_flag=0, ms_flag=0,
+                 sequence_number=0, lsa_headers=None):
+        lsa_headers = lsa_headers if lsa_headers else []
+        super(OSPFDBDesc, self).__init__(OSPF_MSG_DB_DESC, length, router_id,
+                                         area_id, au_type, authentication,
+                                         checksum, version)
+        self.mtu = mtu
+        self.options = options
+        self.i_flag = i_flag
+        self.m_flag = m_flag
+        self.ms_flag = ms_flag
+        self.sequence_number = sequence_number
+        self.lsa_headers = lsa_headers
+
+    @classmethod
+    def parser(cls, buf):
+        (mtu, options, flags,
+         sequence_number) = struct.unpack_from(cls._PACK_STR, six.binary_type(buf))
+        i_flag = (flags >> 2) & 0x1
+        m_flag = (flags >> 1) & 0x1
+        ms_flag = flags & 0x1
+        lsahdrs = []
+        buf = buf[cls._PACK_LEN:]
+        while buf:
+            kwargs, buf = LSAHeader.parser(buf)
+            lsahdrs.append(LSAHeader(**kwargs))
+        return {
+            "mtu": mtu,
+            "options": options,
+            "i_flag": i_flag,
+            "m_flag": m_flag,
+            "ms_flag": ms_flag,
+            "sequence_number": sequence_number,
+            "lsa_headers": lsahdrs,
+        }
+
+    def serialize_tail(self):
+        flags = ((self.i_flag & 0x1) << 2) ^ \
+                ((self.m_flag & 0x1) << 1) ^ \
+                (self.ms_flag & 0x1)
+        head = bytearray(
+            struct.pack(self._PACK_STR, self.mtu, self.options, flags,
+                        self.sequence_number))
+        try:
+            return head + reduce(lambda a, b: a + b,
+                                 (hdr.serialize() for hdr in self.lsa_headers))
+        except TypeError:
+            return head
+
+
+@OSPFMessage.register_type(OSPF_MSG_LS_REQ)
+class OSPFLSReq(OSPFMessage):
+    _MIN_LEN = OSPFMessage._HDR_LEN
+
+    class Request(StringifyMixin):
+        _PACK_STR = '!I4s4s'
+        _PACK_LEN = struct.calcsize(_PACK_STR)
+
+        def __init__(self, type_=OSPF_UNKNOWN_LSA, id_='0.0.0.0',
+                     adv_router='0.0.0.0'):
+            self.type_ = type_
+            self.id = id_
+            self.adv_router = adv_router
+
+        @classmethod
+        def parser(cls, buf):
+            if len(buf) < cls._PACK_LEN:
+                raise stream_parser.StreamParser.TooSmallException(
+                    '%d < %d' % (len(buf), cls._PACK_LEN))
+            link = buf[:cls._PACK_LEN]
+            rest = buf[cls._PACK_LEN:]
+            (type_, id_, adv_router) = struct.unpack_from(cls._PACK_STR,
+                                                          six.binary_type(link))
+            id_ = addrconv.ipv4.bin_to_text(id_)
+            adv_router = addrconv.ipv4.bin_to_text(adv_router)
+            return cls(type_, id_, adv_router), rest
+
+        def serialize(self):
+            id_ = addrconv.ipv4.text_to_bin(self.id)
+            adv_router = addrconv.ipv4.text_to_bin(self.adv_router)
+            return struct.pack(self._PACK_STR, self.type_, id_, adv_router)
+
+    def __init__(self, length=None, router_id='0.0.0.0', area_id='0.0.0.0',
+                 au_type=1, authentication=0, checksum=None, version=_VERSION,
+                 lsa_requests=None):
+        lsa_requests = lsa_requests if lsa_requests else []
+        super(OSPFLSReq, self).__init__(OSPF_MSG_LS_REQ, length, router_id,
+                                        area_id, au_type, authentication,
+                                        checksum, version)
+        self.lsa_requests = lsa_requests
+
+    @classmethod
+    def parser(cls, buf):
+        reqs = []
+        while buf:
+            req, buf = cls.Request.parser(buf)
+            reqs.append(req)
+        return {
+            "lsa_requests": reqs,
+        }
+
+    def serialize_tail(self):
+        return reduce(lambda a, b: a + b,
+                      (req.serialize() for req in self.lsa_requests))
+
+
+@OSPFMessage.register_type(OSPF_MSG_LS_UPD)
+class OSPFLSUpd(OSPFMessage):
+    _PACK_STR = '!I'
+    _PACK_LEN = struct.calcsize(_PACK_STR)
+    _MIN_LEN = OSPFMessage._HDR_LEN + _PACK_LEN
+
+    def __init__(self, length=None, router_id='0.0.0.0', area_id='0.0.0.0',
+                 au_type=1, authentication=0, checksum=None, version=_VERSION,
+                 lsas=None):
+        lsas = lsas if lsas else []
+        super(OSPFLSUpd, self).__init__(OSPF_MSG_LS_UPD, length, router_id,
+                                        area_id, au_type, authentication,
+                                        checksum, version)
+        self.lsas = lsas
+
+    @classmethod
+    def parser(cls, buf):
+        binnum = buf[:cls._PACK_LEN]
+        (num,) = struct.unpack_from(cls._PACK_STR, six.binary_type(binnum))
+
+        buf = buf[cls._PACK_LEN:]
+        lsas = []
+        while buf:
+            lsa, _cls, buf = LSA.parser(buf)
+            lsas.append(lsa)
+        assert len(lsas) == num
+        return {
+            "lsas": lsas,
+        }
+
+    def serialize_tail(self):
+        head = bytearray(struct.pack(self._PACK_STR, len(self.lsas)))
+        try:
+            return head + reduce(lambda a, b: a + b,
+                                 (lsa.serialize() for lsa in self.lsas))
+        except TypeError:
+            return head
+
+
+@OSPFMessage.register_type(OSPF_MSG_LS_ACK)
+class OSPFLSAck(OSPFMessage):
+    _MIN_LEN = OSPFMessage._HDR_LEN
+
+    def __init__(self, length=None, router_id='0.0.0.0', area_id='0.0.0.0',
+                 au_type=1, authentication=0, checksum=None, version=_VERSION,
+                 lsa_headers=None):
+        lsa_headers = lsa_headers if lsa_headers else []
+        super(OSPFLSAck, self).__init__(OSPF_MSG_LS_ACK, length, router_id,
+                                        area_id, au_type, authentication,
+                                        checksum, version)
+        self.lsa_headers = lsa_headers
+
+    @classmethod
+    def parser(cls, buf):
+        lsahdrs = []
+        while buf:
+            kwargs, buf = LSAHeader.parser(buf)
+            lsahdrs.append(LSAHeader(**kwargs))
+        return {
+            "lsa_headers": lsahdrs,
+        }
+
+    def serialize_tail(self):
+        return reduce(lambda a, b: a + b,
+                      (hdr.serialize() for hdr in self.lsa_headers))