Hi Iwase,
Your comments are welcome! I'll resubmit a patch after fixing it.
Olivier
Le mar. 27 déc. 2016 à 03:52, Iwase Yusuke <[email protected]> a
écrit :
> Hi Olivier,
>
> I'm very sorry for disturbing you again...
>
>
> On 2016年12月16日 22:52, Olivier DESNOE wrote:
> > Following your comments, this 2nd version of the patch adds the ability
> to dissect and generate DHCPv6 packets. I needed it to develop a simple
> LDRA app (as defined in RFC 6221).
> >
> > Signed-off-by: Olivier DESNOE <[email protected]>
> > ---
> > diff --git a/ryu/lib/packet/dhcp6.py b/ryu/lib/packet/dhcp6.py
> > new file mode 100644
> > index 0000000..f572c71
> > --- /dev/null
> > +++ b/ryu/lib/packet/dhcp6.py
> > @@ -0,0 +1,293 @@
> > +# Copyright (C) 2016 Bouygues Telecom.
> > +#
> > +# 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.
> > +
> > +"""
> > +DHCPv6 packet parser/serializer
> > +
> > +RFC 3315
> > +DHCP packet format
> > +
> > + The following diagram illustrates the format of DHCP messages sent
> > + between clients and servers:
> > +
> > + 0 1 2 3
> > + 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
> > + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
> > + | msg_type | transaction_id |
> > + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
> > + | |
> > + . options .
> > + . (variable) .
> > + | |
> > + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
> > +
> > + There are two relay agent messages, which share the following format:
> > +
> > + 0 1 2 3
> > + 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
> > + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
> > + | msg_type | hop_count | |
> > + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
> > + | |
> > + | link_address |
> > + | |
> > + | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-|
> > + | | |
> > + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
> > + | |
> > + | peer_address |
> > + | |
> > + | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-|
> > + | | |
> > + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
> > + . .
> > + . options (variable number and length) .... .
> > + | |
> > + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
> > +
> > +"""
> > +import random
> > +import struct
> > +
> > +from . import packet_base
> > +from ryu.lib import addrconv
> > +from ryu.lib import stringify
> > +
> > +# DHCPv6 message types
> > +DHCPV6_SOLICIT = 1
> > +DHCPV6_ADVERTISE = 2
> > +DHCPV6_REQUEST = 3
> > +DHCPV6_CONFIRM = 4
> > +DHCPV6_RENEW = 5
> > +DHCPV6_REBIND = 6
> > +DHCPV6_REPLY = 7
> > +DHCPV6_RELEASE = 8
> > +DHCPV6_DECLINE = 9
> > +DHCPV6_RECONFIGURE = 10
> > +DHCPV6_INFORMATION_REQUEST = 11
> > +DHCPV6_RELAY_FORW = 12
> > +DHCPV6_RELAY_REPL = 13
> > +
> > +# DHCPv6 option-codes
> > +DHCPV6_OPTION_CLIENTID = 1
> > +DHCPV6_OPTION_SERVERID = 2
> > +DHCPV6_OPTION_IA_NA = 3
> > +DHCPV6_OPTION_IA_TA = 4
> > +DHCPV6_OPTION_IAADDR = 5
> > +DHCPV6_OPTION_ORO = 6
> > +DHCPV6_OPTION_PREFERENCE = 7
> > +DHCPV6_OPTION_ELAPSED_TIME = 8
> > +DHCPV6_OPTION_RELAY_MSG = 9
> > +DHCPV6_OPTION_AUTH = 11
> > +DHCPV6_OPTION_UNICAST = 12
> > +DHCPV6_OPTION_STATUS_CODE = 13
> > +DHCPV6_OPTION_RAPID_COMMIT = 14
> > +DHCPV6_OPTION_USER_CLASS = 15
> > +DHCPV6_OPTION_VENDOR_CLASS = 16
> > +DHCPV6_OPTION_VENDOR_OPTS = 17
> > +DHCPV6_OPTION_INTERFACE_ID = 18
> > +DHCPV6_OPTION_RECONF_MSG = 19
> > +DHCPV6_OPTION_RECONF_ACCEPT = 20
> > +
> > +
> > +class dhcp6(packet_base.PacketBase):
> > + """DHCPv6 (RFC 3315) header encoder/decoder class.
> > +
> > + The serialized packet would looks like the ones described
> > + in the following sections.
> > +
> > + * RFC 3315 DHCP packet format
> > +
> > + 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
> > + ============== ====================
> > + msg_type Identifies the DHCP message type
> > +
> > + * For unrelayed messages only:
> > + transaction_id The transaction ID for this message exchange.
> > +
> > + * For relayed messages only
> > + hop_count Number of relay agents that have relayed this
> > + message.
>
> This seems to cause "ERROR: Malformed table" while building "Packet
> library API
> Reference" for Ryu-Documentation.
>
> $ git diff
> diff --git a/doc/source/library_packet_ref.rst
> b/doc/source/library_packet_ref.rst
> index 87f44a1..4088613 100644
> --- a/doc/source/library_packet_ref.rst
> +++ b/doc/source/library_packet_ref.rst
> @@ -69,6 +69,13 @@ Protocol Header classes
> .. autoclass:: ryu.lib.packet.dhcp.option
> :members:
>
> +.. autoclass:: ryu.lib.packet.dhcp6.dhcp6
> + :members:
> +.. autoclass:: ryu.lib.packet.dhcp6.options
> + :members:
> +.. autoclass:: ryu.lib.packet.dhcp6.option
> + :members:
> +
> .. autoclass:: ryu.lib.packet.vrrp.vrrp
> :members:
> .. autoclass:: ryu.lib.packet.vrrp.vrrpv2
> $
> $
> $ make html
> sphinx-build -b html -d build/doctrees source build/html
> ...(snip)
> /home/iwase/ryu/ryu/lib/packet/dhcp6.py:docstring of
> ryu.lib.packet.dhcp6.dhcp6:18: ERROR: Malformed table.
> Text in column margin in table line 6.
>
> ============== ====================
> Attribute Description
> ============== ====================
> msg_type Identifies the DHCP message type
>
> * For unrelayed messages only:
> transaction_id The transaction ID for this message exchange.
>
> * For relayed messages only
> hop_count Number of relay agents that have relayed this
> message.
> link_address A global or site-local address that will be used by
> the server to identify the link on which the client
> is located.
> peer_address The address of the client or relay agent from which
> the message to be relayed was received.
>
> * For unrelayed and relayed messages:
> options Options carried in this message
> ============== ====================
> /home/iwase/ryu/ryu/lib/packet/dhcp6.py:docstring of
> ryu.lib.packet.dhcp6.option:13: WARNING: Block quote ends without a blank
> line; unexpected unindent.
> /home/iwase/ryu/ryu/lib/packet/dhcp6.py:docstring of
> ryu.lib.packet.dhcp6.option:18: WARNING: Block quote ends without a blank
> line; unexpected unindent.
> ...(snip)
> build succeeded, 3 warnings.
>
> Build finished. The HTML pages are in build/html.
> $
>
>
> > + link_address A global or site-local address that will be used by
> > + the server to identify the link on which the client
> > + is located.
> > + peer_address The address of the client or relay agent from which
> > + the message to be relayed was received.
> > +
> > + * For unrelayed and relayed messages:
> > + options Options carried in this message
> > + ============== ====================
> > + """
> > + _MIN_LEN = 8
> > + _DHCPV6_UNPACK_STR = '!I'
> > + _DHCPV6_RELAY_UNPACK_STR = '!H16s16s'
> > + _DHCPV6_UNPACK_STR_LEN = struct.calcsize(_DHCPV6_UNPACK_STR)
> > + _DHCPV6_RELAY_UNPACK_STR_LEN =
> struct.calcsize(_DHCPV6_RELAY_UNPACK_STR)
> > + _DHCPV6_PACK_STR = '!I'
> > + _DHCPV6_RELAY_PACK_STR = '!H16s16s'
> > +
> > + def __init__(self, msg_type, options, transaction_id=None,
> hop_count=0,
> > + link_address='::', peer_address='::'):
> > + super(dhcp6, self).__init__()
> > + self.msg_type = msg_type
> > + self.options = options
> > + if transaction_id is None:
> > + self.transaction_id = random.randint(0, 0xffffff)
> > + else:
> > + self.transaction_id = transaction_id
> > + self.hop_count = hop_count
> > + self.link_address = link_address
> > + self.peer_address = peer_address
> > +
> > + @classmethod
> > + def parser(cls, buf):
> > + (msg_type, ) = struct.unpack_from('!B', buf)
> > +
> > + buf = b'\x00' + buf[1:] # unpack xid as a 4-byte integer
> > + if msg_type == DHCPV6_RELAY_FORW or msg_type ==
> DHCPV6_RELAY_REPL:
> > + (hop_count, link_address, peer_address) \
> > + = struct.unpack_from(cls._DHCPV6_RELAY_UNPACK_STR, buf)
> > + length = struct.calcsize(cls._DHCPV6_RELAY_UNPACK_STR)
> > + else:
> > + (transaction_id, ) \
> > + = struct.unpack_from(cls._DHCPV6_UNPACK_STR, buf)
> > + length = struct.calcsize(cls._DHCPV6_UNPACK_STR)
> > +
> > + if len(buf) > length:
> > + parse_opt = options.parser(buf[length:])
> > + length += parse_opt.options_len
> > + if msg_type == DHCPV6_RELAY_FORW or msg_type ==
> DHCPV6_RELAY_REPL:
> > + return (cls(msg_type, parse_opt, 0, hop_count,
> > + addrconv.ipv6.bin_to_text(link_address),
> > + addrconv.ipv6.bin_to_text(peer_address)),
> > + None, buf[length:])
> > + else:
> > + return (cls(msg_type, parse_opt, transaction_id),
> > + None, buf[length:])
> > + else:
> > + return None, None, buf
> > +
> > + def serialize(self, payload=None, prev=None):
> > + seri_opt = self.options.serialize()
> > + if (self.msg_type == DHCPV6_RELAY_FORW or
> > + self.msg_type == DHCPV6_RELAY_REPL):
> > + pack_str = '%s%ds' % (self._DHCPV6_RELAY_PACK_STR,
> > + self.options.options_len)
> > + buf = struct.pack(pack_str, self.hop_count,
> > +
> addrconv.ipv6.text_to_bin(self.link_address),
> > +
> addrconv.ipv6.text_to_bin(self.peer_address),
> > + seri_opt)
> > + else:
> > + pack_str = '%s%ds' % (self._DHCPV6_PACK_STR,
> > + self.options.options_len)
> > + buf = struct.pack(pack_str, self.transaction_id, seri_opt)
> > + return struct.pack('!B', self.msg_type) + buf[1:]
> > +
> > +
> > +class options(stringify.StringifyMixin):
> > + """DHCP (RFC 3315) options encoder/decoder class.
> > +
> > + This is used with ryu.lib.packet.dhcp6.dhcp6.
> > +
> > + """
> > +
> > + def __init__(self, option_list=None, options_len=0):
> > + super(options, self).__init__()
> > + if option_list is None:
> > + self.option_list = []
> > + else:
> > + self.option_list = option_list
> > + self.options_len = options_len
> > +
> > + @classmethod
> > + def parser(cls, buf):
> > + opt_parse_list = []
> > + offset = 0
> > + while len(buf) > offset:
> > + opt_buf = buf[offset:]
> > + opt = option.parser(opt_buf)
> > + opt_parse_list.append(opt)
> > + offset += opt.length + 4
> > + return cls(opt_parse_list, len(buf))
> > +
> > + def serialize(self):
> > + seri_opt = ""
> > + for opt in self.option_list:
> > + seri_opt += opt.serialize()
> > + if self.options_len == 0:
> > + self.options_len = len(seri_opt)
> > + return seri_opt
> > +
> > +
> > +class option(stringify.StringifyMixin):
> > + """DHCP (RFC 3315) options encoder/decoder class.
> > +
> > + This is used with ryu.lib.packet.dhcp6.dhcp6.options.
> > +
> > + 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.
> > +
> > + The format of DHCP options is:
> > +
> > + 0 1 2 3
> > + 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
> > + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
> > + | option-code | option-len |
> > + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
> > + | option-data |
> > + | (option-len octets) |
> > + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
> > +
> > + option-code An unsigned integer identifying the specific option
> > + type carried in this option.
> > +
> > + option-len An unsigned integer giving the length of the
> > + option-data field in this option in octets.
> > +
> > + option-data The data for the option; the format of this data
> > + depends on the definition of the option.
> > + """
> > + _UNPACK_STR = '!H'
> > + _UNPACK_STR_LEN = struct.calcsize(_UNPACK_STR)
> > + _PACK_STR = '!HH%ds'
> > +
> > + def __init__(self, code, data, length=0):
> > + super(option, self).__init__()
> > + self.code = code
> > + self.data = data
> > + self.length = length
> > +
> > + @classmethod
> > + def parser(cls, buf):
> > + code = struct.unpack_from(cls._UNPACK_STR, buf)[0]
> > + buf = buf[cls._UNPACK_STR_LEN:]
> > + length = struct.unpack_from(cls._UNPACK_STR, buf)[0]
> > + buf = buf[cls._UNPACK_STR_LEN:]
> > + value_unpack_str = '%ds' % length
> > + data = struct.unpack_from(value_unpack_str, buf)[0]
> > + return cls(code, data, length)
> > +
> > + def serialize(self):
> > + if self.length == 0:
> > + self.length = len(self.data)
> > + options_pack_str = self._PACK_STR % self.length
> > + return struct.pack(options_pack_str, self.code, self.length,
> self.data)
>
> The section of option members seem to be indented with 5 white-spaces.
> Could you check this?
>
> Thanks,
> Iwase
>
>
> > diff --git a/ryu/lib/packet/udp.py b/ryu/lib/packet/udp.py
> > index f39fb90..7d24ee0 100644
> > --- a/ryu/lib/packet/udp.py
> > +++ b/ryu/lib/packet/udp.py
> > @@ -18,6 +18,7 @@ import struct
> > from . import packet_base
> > from . import packet_utils
> > from . import dhcp
> > +from . import dhcp6
> > from . import vxlan
> >
> >
> > @@ -52,11 +53,12 @@ class udp(packet_base.PacketBase):
> >
> > @staticmethod
> > def get_packet_type(src_port, dst_port):
> > - if ((src_port == 68 and dst_port == 67) or
> > - (src_port == 67 and dst_port == 68) or
> > - (src_port == 67 and
> > - dst_port == 67)):
> > + if ((src_port in [67, 68] and dst_port == 67) or
> > + (dst_port in [67, 68] and src_port == 67)):
> > return dhcp.dhcp
> > + if ((src_port in [546, 547] and dst_port == 547) or
> > + (dst_port in [546, 547] and src_port == 547)):
> > + return dhcp6.dhcp6
> > if (dst_port == vxlan.UDP_DST_PORT or
> > dst_port == vxlan.UDP_DST_PORT_OLD):
> > return vxlan.vxlan
> >
> >
> >
> >
> >
> ------------------------------------------------------------------------------
> > Check out the vibrant tech community on one of the world's most
> > engaging tech sites, SlashDot.org! http://sdm.link/slashdot
> > _______________________________________________
> > Ryu-devel mailing list
> > [email protected]
> > https://lists.sourceforge.net/lists/listinfo/ryu-devel
> >
>
------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, SlashDot.org! http://sdm.link/slashdot
_______________________________________________
Ryu-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/ryu-devel