/*
 *  Copyright (c) 2020, The OpenThread Authors.
 *  All rights reserved.
 *
 *  Redistribution and use in source and binary forms, with or without
 *  modification, are permitted provided that the following conditions are met:
 *  1. Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *  2. Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *  3. Neither the name of the copyright holder nor the
 *     names of its contributors may be used to endorse or promote products
 *     derived from this software without specific prior written permission.
 *
 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 *  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 *  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 *  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
 *  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 *  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 *  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 *  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 *  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 *  POSSIBILITY OF SUCH DAMAGE.
 */

/**
 * @file
 *   This file includes definitions for IPv6 Router Advertisement.
 *
 * See RFC 4861: Neighbor Discovery for IP version 6 (https://tools.ietf.org/html/rfc4861).
 *
 */

#ifndef ROUTER_ADVERTISEMENT_HPP_
#define ROUTER_ADVERTISEMENT_HPP_

#include "openthread-core-config.h"

#if OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE

#include <stdint.h>

#include <openthread/netdata.h>
#include <openthread/platform/toolchain.h>

#include "common/encoding.hpp"
#include "common/equatable.hpp"
#include "net/icmp6.hpp"
#include "net/ip6.hpp"
#include "thread/network_data_types.hpp"

using ot::Encoding::BigEndian::HostSwap16;
using ot::Encoding::BigEndian::HostSwap32;

namespace ot {

namespace BorderRouter {

namespace RouterAdv {

/**
 * This class represents the variable length options in Neighbor
 * Discovery messages.
 *
 * @sa PrefixInfoOption
 * @sa RouteInfoOption
 *
 */
OT_TOOL_PACKED_BEGIN
class Option
{
public:
    enum class Type : uint8_t
    {
        kPrefixInfo = 3,  ///< Prefix Information Option.
        kRouteInfo  = 24, ///< Route Information Option.
    };

    static constexpr uint8_t kLengthUnit = 8; ///< The unit of length in octets.

    /**
     * This constructor initializes the option with given type and length.
     *
     * @param[in]  aType    The type of this option.
     * @param[in]  aLength  The length of this option in unit of 8 octets.
     *
     */
    explicit Option(Type aType, uint8_t aLength = 0)
        : mType(aType)
        , mLength(aLength)
    {
    }

    /**
     * This method returns the type of this option.
     *
     * @returns  The option type.
     *
     */
    Type GetType(void) const { return mType; }

    /**
     * This method sets the size of the option (in bytes).
     *
     * Since the option must end on their natural 64-bits boundaries,
     * the actual length set to the option is padded to (aSize + 7) / 8 * 8.
     *
     * @param[in]  aSize  The size of the option in unit of 1 byte.
     *
     */
    void SetSize(uint16_t aSize) { mLength = static_cast<uint8_t>((aSize + kLengthUnit - 1) / kLengthUnit); }

    /**
     * This method returns the size of the option (in bytes).
     *
     * @returns  The size of the option in unit of 1 byte.
     *
     */
    uint16_t GetSize(void) const { return mLength * kLengthUnit; }

    /**
     * This method sets the length of the option (in unit of 8 bytes).
     *
     * @param[in]  aLength  The length of the option in unit of 8 bytes.
     *
     */
    void SetLength(uint8_t aLength) { mLength = aLength; }

    /**
     * This method returns the length of the option (in unit of 8 bytes).
     *
     * @returns  The length of the option in unit of 8 bytes.
     *
     */
    uint16_t GetLength(void) const { return mLength; }

    /**
     * This helper method returns a pointer to the next valid option in the buffer.
     *
     * @param[in]  aCurOption     The current option. Use `nullptr` to get the first option.
     * @param[in]  aBuffer        The buffer within which the options are held.
     * @param[in]  aBufferLength  The length of the buffer.
     *
     * @returns  A pointer to the next option if there are a valid one. Otherwise, `nullptr`.
     *
     */
    static const Option *GetNextOption(const Option *aCurOption, const uint8_t *aBuffer, uint16_t aBufferLength);

    /**
     * This method tells whether this option is valid.
     *
     * @return  A boolean that indicates whether this option is valid.
     *
     */
    bool IsValid(void) const { return mLength > 0; }

private:
    Type    mType;   // Type of the option.
    uint8_t mLength; // Length of the option in unit of 8 octets,
                     // including the `type` and `length` fields.
} OT_TOOL_PACKED_END;

/**
 * This class represents the Prefix Information Option.
 *
 * See section 4.6.2 of RFC 4861 for definition of this option.
 * https://tools.ietf.org/html/rfc4861#section-4.6.2
 *
 */
OT_TOOL_PACKED_BEGIN
class PrefixInfoOption : public Option
{
public:
    /**
     * This constructor initializes this option with zero prefix
     * length, valid lifetime and preferred lifetime.
     *
     */
    PrefixInfoOption(void);

    /**
     * This method returns the on-link flag.
     *
     * @returns  A boolean which indicates whether the on-link flag is set.
     *
     */
    bool GetOnLink(void) const { return (mReserved1 & kOnLinkFlagMask) != 0; }

    /**
     * This method sets the on-link (L) flag.
     *
     * @param[in]  aOnLink  A boolean indicates whether the prefix is on-link or off-link.
     *
     */
    void SetOnLink(bool aOnLink);

    /**
     * This method returns the autonomous address-configuration (A) flag.
     *
     * @returns  A boolean which indicates whether the A flag is set.
     *
     */
    bool GetAutoAddrConfig(void) const { return (mReserved1 & kAutoConfigFlagMask) != 0; }

    /**
     * This method sets the autonomous address-configuration (A) flag.
     *
     * @param[in]  aAutoAddrConfig  A boolean indicates whether this prefix can be used
     *                              for SLAAC.
     *
     */
    void SetAutoAddrConfig(bool aAutoAddrConfig);

    /**
     * This method set the valid lifetime of the prefix in seconds.
     *
     * @param[in]  aValidLifetime  The valid lifetime in seconds.
     *
     */
    void SetValidLifetime(uint32_t aValidLifetime) { mValidLifetime = HostSwap32(aValidLifetime); }

    /**
     * THis method returns the valid lifetime of the prefix in seconds.
     *
     * @returns  The valid lifetime in seconds.
     *
     */
    uint32_t GetValidLifetime(void) const { return HostSwap32(mValidLifetime); }

    /**
     * This method sets the preferred lifetime of the prefix in seconds.
     *
     * @param[in]  aPreferredLifetime  The preferred lifetime in seconds.
     *
     */
    void SetPreferredLifetime(uint32_t aPreferredLifetime) { mPreferredLifetime = HostSwap32(aPreferredLifetime); }

    /**
     * THis method returns the preferred lifetime of the prefix in seconds.
     *
     * @returns  The preferred lifetime in seconds.
     *
     */
    uint32_t GetPreferredLifetime(void) const { return HostSwap32(mPreferredLifetime); }

    /**
     * This method sets the prefix.
     *
     * @param[in]  aPrefix  The prefix contained in this option.
     *
     */
    void SetPrefix(const Ip6::Prefix &aPrefix);

    /**
     * This method returns the prefix in this option.
     *
     * @returns  The IPv6 prefix in this option.
     *
     */
    Ip6::Prefix GetPrefix(void) const;

    /**
     * This method tells whether this option is valid.
     *
     * @returns  A boolean indicates whether this option is valid.
     *
     */
    bool IsValid(void) const
    {
        return (GetSize() == sizeof(*this)) && (mPrefixLength <= OT_IP6_ADDRESS_SIZE * CHAR_BIT) &&
               (GetPreferredLifetime() <= GetValidLifetime());
    }

private:
    static constexpr uint8_t kAutoConfigFlagMask = 0x40; // Bit mask of the Automatic Address Configure flag.
    static constexpr uint8_t kOnLinkFlagMask     = 0x80; // Bit mask of the On-link flag.

    uint8_t      mPrefixLength;      // The prefix length in bits.
    uint8_t      mReserved1;         // The reserved field.
    uint32_t     mValidLifetime;     // The valid lifetime of the prefix.
    uint32_t     mPreferredLifetime; // The preferred lifetime of the prefix.
    uint32_t     mReserved2;         // The reserved field.
    Ip6::Address mPrefix;            // The prefix.
} OT_TOOL_PACKED_END;

static_assert(sizeof(PrefixInfoOption) == 32, "invalid PrefixInfoOption structure");

/**
 * This class represents the Route Information Option.
 *
 * See section 2.3 of RFC 4191 for definition of this option.
 * https://tools.ietf.org/html/rfc4191#section-2.3
 *
 */
OT_TOOL_PACKED_BEGIN
class RouteInfoOption : public Option
{
public:
    /**
     * This type represents a route preference.
     *
     */
    typedef NetworkData::RoutePreference RoutePreference;

    /**
     * This constructor initializes this option with zero prefix length.
     *
     */
    RouteInfoOption(void);

    /**
     * This method sets the route preference.
     *
     * @param[in]  aPreference  The route preference.
     *
     */
    void SetPreference(RoutePreference aPreference);

    /**
     * This method returns the route preference.
     *
     * @returns  The route preference.
     *
     */
    RoutePreference GetPreference(void) const;

    /**
     * This method sets the lifetime of the route in seconds.
     *
     * @param[in]  aLifetime  The lifetime of the route in seconds.
     *
     */
    void SetRouteLifetime(uint32_t aLifetime) { mRouteLifetime = HostSwap32(aLifetime); }

    /**
     * This method returns Route Lifetime in seconds.
     *
     * @returns  The Route Lifetime in seconds.
     *
     */
    uint32_t GetRouteLifetime(void) const { return HostSwap32(mRouteLifetime); }

    /**
     * This method sets the prefix.
     *
     * @param[in]  aPrefix  The prefix contained in this option.
     *
     */
    void SetPrefix(const Ip6::Prefix &aPrefix);

    /**
     * This method returns the prefix in this option.
     *
     * @returns  The IPv6 prefix in this option.
     *
     */
    Ip6::Prefix GetPrefix(void) const;

    /**
     * This method tells whether this option is valid.
     *
     * @returns  A boolean indicates whether this option is valid.
     *
     */
    bool IsValid(void) const;

private:
    static constexpr uint8_t kPreferenceOffset = 3;
    static constexpr uint8_t kPreferenceMask   = 3 << kPreferenceOffset;

    uint8_t      mPrefixLength;  // The prefix length in bits.
    uint8_t      mReserved;      // The reserved field.
    uint32_t     mRouteLifetime; // The lifetime in seconds.
    Ip6::Address mPrefix;        // The prefix.
} OT_TOOL_PACKED_END;

static_assert(sizeof(RouteInfoOption) == 24, "invalid RouteInfoOption structure");

/**
 * This class implements the Router Advertisement message.
 *
 * See section 4.2 of RFC 4861 for definition of this message.
 * https://tools.ietf.org/html/rfc4861#section-4.2
 *
 */
OT_TOOL_PACKED_BEGIN
class RouterAdvMessage : public Unequatable<RouterAdvMessage>
{
public:
    /**
     * This constructor initializes the Router Advertisement message with
     * zero router lifetime, reachable time and retransmission timer.
     *
     */
    RouterAdvMessage(void) { SetToDefault(); }

    /**
     * This method sets the RA message to default values.
     *
     */
    void SetToDefault(void);

    /**
     * This method sets the checksum value.
     *
     * @param[in]  aChecksum  The checksum value.
     *
     */
    void SetChecksum(uint16_t aChecksum) { mHeader.SetChecksum(aChecksum); }

    /**
     * This method sets the Router Lifetime in seconds.
     *
     * Zero Router Lifetime means we are not a default router.
     *
     * @param[in]  aRouterLifetime  The router lifetime in seconds.
     *
     */
    void SetRouterLifetime(uint16_t aRouterLifetime)
    {
        mHeader.mData.m16[kRouteLifetimeIdx] = HostSwap16(aRouterLifetime);
    }

    /**
     * This method returns the Router Lifetime.
     *
     * Zero Router Lifetime means we are not a default router.
     *
     * @returns  The router lifetime in seconds.
     *
     */
    uint16_t GetRouterLifetime(void) const { return HostSwap16(mHeader.mData.m16[kRouteLifetimeIdx]); }

    /**
     * This method returns the Managed Address Configuration ('m') flag.
     *
     * @returns  A boolean which indicates whether the 'm' flag is set.
     *
     */
    bool GetManagedAddrConfig(void) const { return (mHeader.mData.m8[kReservedIdx] & kManagedAddressConfigMask) != 0; }

    /**
     * This method overloads the assignment operator.
     *
     */
    const RouterAdvMessage &operator=(const RouterAdvMessage &aOther);

    /**
     * This method overloads operator `==` to evaluate whether or not
     * two instances of `RouterAdvMessage` are equal.
     *
     * @param[in]  aOther  The other `RouterAdvMessage` instance to compare with.
     *
     * @retval TRUE   If the two `RouterAdvMessage` instances are equal.
     * @retval FALSE  If the two `RouterAdvMessage` instances are not equal.
     *
     */
    bool operator==(const RouterAdvMessage &aOther) const;

private:
    // The index of Route Lifetime in ICMPv6 Header Data. In unit of 2 octets.
    static constexpr uint8_t kRouteLifetimeIdx = 1;

    // The index of Reserved byte in ICMPv6 Header Data. In unit of 1 octet.
    static constexpr uint8_t kReservedIdx = 1;

    // The bitmask of the Managed Address Configuration ('m') flag.
    static constexpr uint8_t kManagedAddressConfigMask = 0x80;

    Ip6::Icmp::Header mHeader;        // The common ICMPv6 header.
    uint32_t          mReachableTime; // The reachable time. In milliseconds.
    uint32_t          mRetransTimer;  // The retransmission timer. In milliseconds.
} OT_TOOL_PACKED_END;

static_assert(sizeof(RouterAdvMessage) == 16, "invalid RouterAdvMessage structure");

/**
 * This class implements the Router Solicitation message.
 *
 * See section 4.1 of RFC 4861 for definition of this message.
 * https://tools.ietf.org/html/rfc4861#section-4.1
 *
 */
OT_TOOL_PACKED_BEGIN
class RouterSolicitMessage
{
public:
    /**
     * This constructor initializes the Router Solicitation message.
     *
     */
    RouterSolicitMessage(void);

private:
    Ip6::Icmp::Header mHeader; // The common ICMPv6 header.
} OT_TOOL_PACKED_END;

static_assert(sizeof(RouterSolicitMessage) == 8, "invalid RouterSolicitMessage structure");

} // namespace RouterAdv

} // namespace BorderRouter

} // namespace ot

#endif // OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE

#endif // ROUTER_ADVERTISEMENT_HPP_
