/*
 *  Copyright (c) 2016, 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 implements DHCPv6 Server.
 */

#define WPP_NAME "dhcp6_server.tmh"

#include <openthread/config.h>

#include "dhcp6_server.hpp"

#include <openthread/types.h>

#include "common/code_utils.hpp"
#include "common/encoding.hpp"
#include "common/logging.hpp"
#include "thread/mle.hpp"
#include "thread/thread_netif.hpp"

#if OPENTHREAD_ENABLE_DHCP6_SERVER

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

namespace ot {
namespace Dhcp6 {

Dhcp6Server::Dhcp6Server(ThreadNetif &aThreadNetif):
    ThreadNetifLocator(aThreadNetif),
    mSocket(aThreadNetif.GetIp6().mUdp)
{
    for (uint8_t i = 0; i < OPENTHREAD_CONFIG_NUM_DHCP_PREFIXES; i++)
    {
        memset(&(mPrefixAgents[i]), 0, sizeof(PrefixAgent));
        memset(&mAgentsAloc[i], 0, sizeof(mAgentsAloc[i]));
    }

    mPrefixAgentsCount = 0;
    mPrefixAgentsMask = 0;
}

otError Dhcp6Server::UpdateService(void)
{
    ThreadNetif &netif = GetNetif();
    otError error = OT_ERROR_NONE;
    bool found;
    uint8_t i;
    uint16_t rloc16 = netif.GetMle().GetRloc16();
    Ip6::Address *address = NULL;
    otNetworkDataIterator iterator;
    otBorderRouterConfig config;
    Lowpan::Context lowpanContext;

    // remove dhcp agent aloc and prefix delegation
    for (i = 0; i < OPENTHREAD_CONFIG_NUM_DHCP_PREFIXES; i++)
    {
        found = false;

        if (!mAgentsAloc[i].mValid)
        {
            continue;
        }

        address = &(mAgentsAloc[i].GetAddress());
        iterator = OT_NETWORK_DATA_ITERATOR_INIT;

        while (netif.GetNetworkDataLeader().GetNextOnMeshPrefix(&iterator, rloc16, &config) == OT_ERROR_NONE)
        {
            if (!config.mDhcp)
            {
                continue;
            }

            netif.GetNetworkDataLeader().GetContext(*static_cast<const Ip6::Address *>(&(config.mPrefix.mPrefix)),
                                                    lowpanContext);

            if (address->mFields.m8[15] == lowpanContext.mContextId)
            {
                // still in network data
                found = true;
                break;
            }
        }

        if (!found)
        {
            netif.GetNetworkDataLeader().GetContext(address->mFields.m8[15], lowpanContext);
            netif.RemoveUnicastAddress(mAgentsAloc[i]);
            mAgentsAloc[i].mValid = false;
            RemovePrefixAgent(lowpanContext.mPrefix);
        }
    }

    // add dhcp agent aloc and prefix delegation
    iterator = OT_NETWORK_DATA_ITERATOR_INIT;

    while (netif.GetNetworkDataLeader().GetNextOnMeshPrefix(&iterator, rloc16, &config) == OT_ERROR_NONE)
    {
        found = false;

        if (!config.mDhcp)
        {
            continue;
        }

        netif.GetNetworkDataLeader().GetContext(*static_cast<const Ip6::Address *>(&config.mPrefix.mPrefix),
                                                lowpanContext);

        for (i = 0; i < OPENTHREAD_CONFIG_NUM_DHCP_PREFIXES; i++)
        {
            address = &(mAgentsAloc[i].GetAddress());

            if ((mAgentsAloc[i].mValid) && (address->mFields.m8[15] == lowpanContext.mContextId))
            {
                found = true;
                break;
            }
        }

        // alreay added
        if (found)
        {
            continue;
        }

        for (i = 0; i < OPENTHREAD_CONFIG_NUM_DHCP_PREFIXES; i++)
        {
            if (!mAgentsAloc[i].mValid)
            {
                address = &(mAgentsAloc[i].GetAddress());
                memcpy(address, netif.GetMle().GetMeshLocalPrefix(), 8);
                address->mFields.m16[4] = HostSwap16(0x0000);
                address->mFields.m16[5] = HostSwap16(0x00ff);
                address->mFields.m16[6] = HostSwap16(0xfe00);
                address->mFields.m8[14] = Ip6::Address::kAloc16Mask;
                address->mFields.m8[15] = lowpanContext.mContextId;
                mAgentsAloc[i].mPrefixLength = 128;
                mAgentsAloc[i].mPreferred = true;
                mAgentsAloc[i].mValid = true;
                netif.AddUnicastAddress(mAgentsAloc[i]);
                AddPrefixAgent(config.mPrefix);
                break;
            }
        }

        // if no available Dhcp Agent Aloc resources
        if (i == OPENTHREAD_CONFIG_NUM_DHCP_PREFIXES)
        {
            ExitNow(error = OT_ERROR_NO_BUFS);
        }
    }

    if (mPrefixAgentsCount > 0)
    {
        Start();
    }
    else
    {
        Stop();
    }

exit:
    return error;
}

otError Dhcp6Server::Start(void)
{
    Ip6::SockAddr sockaddr;
    sockaddr.mPort = kDhcpServerPort;
    mSocket.Open(&Dhcp6Server::HandleUdpReceive, this);
    mSocket.Bind(sockaddr);

    return OT_ERROR_NONE;
}

otError Dhcp6Server::Stop(void)
{
    mSocket.Close();
    return OT_ERROR_NONE;
}

otError Dhcp6Server::AddPrefixAgent(otIp6Prefix &aIp6Prefix)
{
    otError error = OT_ERROR_NO_BUFS;

    for (uint8_t i = 0; i < OPENTHREAD_CONFIG_NUM_DHCP_PREFIXES; i++)
    {
        if (mPrefixAgents[i].GetPrefix()->mLength != 0)
        {
            continue;
        }

        mPrefixAgents[i].SetPrefix(aIp6Prefix);
        mPrefixAgentsCount++;
        ExitNow(error = OT_ERROR_NONE);
    }

exit:
    return error;
}

otError Dhcp6Server::RemovePrefixAgent(const uint8_t *aIp6Address)
{
    otError error = OT_ERROR_NOT_FOUND;
    otIp6Prefix *prefix = NULL;

    for (uint8_t i = 0; i < OPENTHREAD_CONFIG_NUM_DHCP_PREFIXES; i++)
    {
        prefix = mPrefixAgents[i].GetPrefix();

        if (prefix->mLength == 0)
        {
            continue;
        }

        if (otIp6PrefixMatch(&(prefix->mPrefix), reinterpret_cast<const otIp6Address *>(aIp6Address)) >= prefix->mLength)
        {
            memset(&(mPrefixAgents[i]), 0, sizeof(PrefixAgent));
            mPrefixAgentsCount--;
            ExitNow(error = OT_ERROR_NONE);
        }
    }

exit:
    return error;
}

void Dhcp6Server::HandleUdpReceive(void *aContext, otMessage *aMessage, const otMessageInfo *aMessageInfo)
{
    Dhcp6Server *obj = static_cast<Dhcp6Server *>(aContext);
    obj->HandleUdpReceive(*static_cast<Message *>(aMessage), *static_cast<const Ip6::MessageInfo *>(aMessageInfo));
}

void Dhcp6Server::HandleUdpReceive(Message &aMessage, const Ip6::MessageInfo &aMessageInfo)
{
    Dhcp6Header header;
    otIp6Address dst = aMessageInfo.mPeerAddr;

    VerifyOrExit(aMessage.Read(aMessage.GetOffset(), sizeof(header), &header) == sizeof(header));
    aMessage.MoveOffset(sizeof(header));

    // discard if not solicit type
    VerifyOrExit((header.GetType() == kTypeSolicit));

    ProcessSolicit(aMessage, dst, header.GetTransactionId());

exit:
    return;
}

void Dhcp6Server::ProcessSolicit(Message &aMessage, otIp6Address &aDst, uint8_t *aTransactionId)
{
    IaNa iana;
    ClientIdentifier clientIdentifier;
    uint16_t optionOffset;
    uint16_t offset = aMessage.GetOffset();
    uint16_t length = aMessage.GetLength() - aMessage.GetOffset();

    // Client Identifier (discard if not present)
    VerifyOrExit((optionOffset = FindOption(aMessage, offset, length, kOptionClientIdentifier)) > 0);
    SuccessOrExit(ProcessClientIdentifier(aMessage, optionOffset, clientIdentifier));

    // Server Identifier (assuming Rapid Commit, discard if present)
    VerifyOrExit(FindOption(aMessage, offset, length, kOptionServerIdentifier) == 0);

    // Rapid Commit (assuming Rapid Commit, discard if not present)
    VerifyOrExit(FindOption(aMessage, offset, length, kOptionRapidCommit) > 0);

    // Elapsed Time if present
    if ((optionOffset = FindOption(aMessage, offset, length, kOptionElapsedTime)) > 0)
    {
        SuccessOrExit(ProcessElapsedTime(aMessage, optionOffset));
    }

    // IA_NA (discard if not present)
    VerifyOrExit((optionOffset = FindOption(aMessage, offset, length, kOptionIaNa)) > 0);
    SuccessOrExit(ProcessIaNa(aMessage, optionOffset, iana));

    SuccessOrExit(SendReply(aDst, aTransactionId, clientIdentifier, iana));

exit:
    return;
}

uint16_t Dhcp6Server::FindOption(Message &aMessage, uint16_t aOffset, uint16_t aLength, Code aCode)
{
    uint16_t end = aOffset + aLength;

    while (aOffset <= end)
    {
        Dhcp6Option option;
        VerifyOrExit(aMessage.Read(aOffset, sizeof(option), &option) == sizeof(option));

        if (option.GetCode() == aCode)
        {
            return aOffset;
        }

        aOffset += sizeof(option) + option.GetLength();
    }

exit:
    return 0;
}
otError Dhcp6Server::ProcessClientIdentifier(Message &aMessage, uint16_t aOffset, ClientIdentifier &aClient)
{
    otError error = OT_ERROR_NONE;

    VerifyOrExit(((aMessage.Read(aOffset, sizeof(aClient), &aClient) == sizeof(aClient)) &&
                  (aClient.GetLength() == (sizeof(aClient) - sizeof(Dhcp6Option))) &&
                  (aClient.GetDuidType() == kDuidLL) &&
                  (aClient.GetDuidHardwareType() == kHardwareTypeEui64)),
                 error = OT_ERROR_PARSE);
exit:
    return error;
}

otError Dhcp6Server::ProcessElapsedTime(Message &aMessage, uint16_t aOffset)
{
    otError error = OT_ERROR_NONE;
    ElapsedTime option;

    VerifyOrExit(((aMessage.Read(aOffset, sizeof(option), &option) == sizeof(option)) &&
                  (option.GetLength() == ((sizeof(option) - sizeof(Dhcp6Option))))),
                 error = OT_ERROR_PARSE);
exit:
    return error;
}

otError Dhcp6Server::ProcessIaNa(Message &aMessage, uint16_t aOffset, IaNa &aIaNa)
{
    otError error = OT_ERROR_NONE;
    uint16_t optionOffset;
    uint16_t length;

    VerifyOrExit((aMessage.Read(aOffset, sizeof(aIaNa), &aIaNa) == sizeof(aIaNa)), error = OT_ERROR_PARSE);

    aOffset += sizeof(aIaNa);
    length = aIaNa.GetLength() + sizeof(Dhcp6Option) - sizeof(IaNa);

    VerifyOrExit(length <= aMessage.GetLength() - aOffset, error = OT_ERROR_PARSE);

    mPrefixAgentsMask = 0;

    while (length > 0)
    {
        VerifyOrExit((optionOffset = FindOption(aMessage, aOffset, length, kOptionIaAddress)) > 0);
        SuccessOrExit(error = ProcessIaAddress(aMessage, optionOffset));

        length -= ((optionOffset - aOffset) + sizeof(IaAddress));
        aOffset = optionOffset + sizeof(IaAddress);
    }

exit:
    return error;
}

otError Dhcp6Server::ProcessIaAddress(Message &aMessage, uint16_t aOffset)
{
    otError error = OT_ERROR_NONE;
    otIp6Prefix *prefix = NULL;
    IaAddress option;

    VerifyOrExit(((aMessage.Read(aOffset, sizeof(option), &option) == sizeof(option)) &&
                  option.GetLength() == (sizeof(option) - sizeof(Dhcp6Option))),
                 error = OT_ERROR_PARSE);

    // mask matching prefix
    for (uint8_t i = 0; i < OPENTHREAD_CONFIG_NUM_DHCP_PREFIXES; i++)
    {
        prefix = mPrefixAgents[i].GetPrefix();

        if (prefix->mLength == 0)
        {
            continue;
        }

        if (otIp6PrefixMatch(option.GetAddress(), &(prefix->mPrefix)) >= prefix->mLength)
        {
            mPrefixAgentsMask |= (1 << i);
            break;
        }
    }

exit:
    return error;
}

otError Dhcp6Server::SendReply(otIp6Address &aDst, uint8_t *aTransactionId, ClientIdentifier &aClient, IaNa &aIaNa)
{
    otError error = OT_ERROR_NONE;
    Ip6::MessageInfo messageInfo;
    Message *message;

    VerifyOrExit((message = mSocket.NewMessage(0)) != NULL, error = OT_ERROR_NO_BUFS);
    SuccessOrExit(error = AppendHeader(*message, aTransactionId));
    SuccessOrExit(error = AppendServerIdentifier(*message));
    SuccessOrExit(error = AppendClientIdentifier(*message, aClient));
    SuccessOrExit(error = AppendIaNa(*message, aIaNa));
    SuccessOrExit(error = AppendStatusCode(*message, kStatusSuccess));
    SuccessOrExit(error = AppendIaAddress(*message, aClient));
    SuccessOrExit(error = AppendRapidCommit(*message));

    memset(&messageInfo, 0, sizeof(messageInfo));
    memcpy(&messageInfo.GetPeerAddr().mFields.m8, &aDst, sizeof(otIp6Address));
    messageInfo.mPeerPort = kDhcpClientPort;
    SuccessOrExit(error = mSocket.SendTo(*message, messageInfo));

exit:

    if (message != NULL && error != OT_ERROR_NONE)
    {
        message->Free();
    }

    return error;
}

otError Dhcp6Server::AppendHeader(Message &aMessage, uint8_t *aTransactionId)
{
    Dhcp6Header header;

    header.Init();
    header.SetType(kTypeReply);
    header.SetTransactionId(aTransactionId);
    return aMessage.Append(&header, sizeof(header));
}

otError Dhcp6Server::AppendClientIdentifier(Message &aMessage, ClientIdentifier &aClient)
{
    return aMessage.Append(&aClient, sizeof(aClient));
}

otError Dhcp6Server::AppendServerIdentifier(Message &aMessage)
{
    otError error = OT_ERROR_NONE;
    ServerIdentifier option;

    option.Init();
    option.SetDuidType(kDuidLL);
    option.SetDuidHardwareType(kHardwareTypeEui64);
    option.SetDuidLinkLayerAddress(GetNetif().GetMac().GetExtAddress());
    SuccessOrExit(error = aMessage.Append(&option, sizeof(option)));

exit:
    return error;
}

otError Dhcp6Server::AppendIaNa(Message &aMessage, IaNa &aIaNa)
{
    otError error = OT_ERROR_NONE;
    uint16_t length = 0;

    if (mPrefixAgentsMask)
    {
        for (uint8_t i = 0; i < OPENTHREAD_CONFIG_NUM_DHCP_PREFIXES; i++)
        {
            if ((mPrefixAgentsMask & (1 << i)))
            {
                length += sizeof(IaAddress);
            }
        }
    }
    else
    {
        length += sizeof(IaAddress) * mPrefixAgentsCount;
    }

    length += sizeof(IaNa) + sizeof(StatusCode) - sizeof(Dhcp6Option);

    aIaNa.SetLength(length);
    aIaNa.SetT1(OT_DHCP6_DEFAULT_IA_NA_T1);
    aIaNa.SetT2(OT_DHCP6_DEFAULT_IA_NA_T2);
    SuccessOrExit(error = aMessage.Append(&aIaNa, sizeof(IaNa)));

exit:
    return error;
}

otError Dhcp6Server::AppendStatusCode(Message &aMessage, Status aStatus)
{
    StatusCode option;

    option.Init();
    option.SetStatusCode(aStatus);
    return aMessage.Append(&option, sizeof(option));
}

otError Dhcp6Server::AppendIaAddress(Message &aMessage, ClientIdentifier &aClient)
{
    otError error = OT_ERROR_NONE;
    otIp6Prefix *prefix = NULL;

    // if specified, only apply specified prefixes
    if (mPrefixAgentsMask)
    {
        for (uint8_t i = 0; i < OPENTHREAD_CONFIG_NUM_DHCP_PREFIXES; i++)
        {
            if (mPrefixAgentsMask & (1 << i))
            {
                prefix = mPrefixAgents[i].GetPrefix();
                SuccessOrExit(error = AddIaAddress(aMessage, *prefix, aClient));
            }
        }
    }
    else  // if not specified, apply all configured prefixes
    {
        for (uint8_t i = 0; i < OPENTHREAD_CONFIG_NUM_DHCP_PREFIXES; i++)
        {
            prefix = mPrefixAgents[i].GetPrefix();

            if (prefix->mLength == 0)
            {
                continue;
            }

            SuccessOrExit(error = AddIaAddress(aMessage, *prefix, aClient));
        }
    }

exit:
    return error;
}

otError Dhcp6Server::AddIaAddress(Message &aMessage, otIp6Prefix &aIp6Prefix, ClientIdentifier &aClient)
{
    otError error = OT_ERROR_NONE;
    IaAddress option;

    option.Init();
    memcpy((option.GetAddress()->mFields.m8), &(aIp6Prefix.mPrefix), 8);
    memcpy(&(option.GetAddress()->mFields.m8[8]), aClient.GetDuidLinkLayerAddress(), sizeof(Mac::ExtAddress));
    option.SetPreferredLifetime(OT_DHCP6_DEFAULT_PREFERRED_LIFETIME);
    option.SetValidLifetime(OT_DHCP6_DEFAULT_VALID_LIFETIME);
    SuccessOrExit(error = aMessage.Append(&option, sizeof(option)));
exit:
    return error;
}

otError Dhcp6Server::AppendRapidCommit(Message &aMessage)
{
    RapidCommit option;

    option.Init();
    return aMessage.Append(&option, sizeof(option));
}

}  // namespace Dhcp6
}  // namespace ot

#endif //  OPENTHREAD_ENABLE_DHCP6_SERVER
