Ejemplo n.º 1
0
ThreadError AddMplOption(Message &message, Header &header, IpProto nextHeader, uint16_t payloadLength)
{
    ThreadError error = kThreadError_None;
    HopByHopHeader hbhHeader;
    OptionMpl mplOption;

    hbhHeader.SetNextHeader(nextHeader);
    hbhHeader.SetLength(0);
    sMpl.InitOption(mplOption, HostSwap16(header.GetSource().mFields.m16[7]));
    SuccessOrExit(error = message.Prepend(&mplOption, sizeof(mplOption)));
    SuccessOrExit(error = message.Prepend(&hbhHeader, sizeof(hbhHeader)));
    header.SetPayloadLength(sizeof(hbhHeader) + sizeof(mplOption) + payloadLength);
    header.SetNextHeader(kProtoHopOpts);
exit:
    return error;
}
Ejemplo n.º 2
0
ThreadError Ip6::SendDatagram(Message &message, MessageInfo &messageInfo, IpProto ipproto)
{
    ThreadError error = kThreadError_None;
    Header header;
    uint16_t payloadLength = message.GetLength();
    uint16_t checksum;
    const NetifUnicastAddress *source;

    header.Init();
    header.SetPayloadLength(payloadLength);
    header.SetNextHeader(ipproto);
    header.SetHopLimit(messageInfo.mHopLimit ? messageInfo.mHopLimit : kDefaultHopLimit);

    if (messageInfo.GetSockAddr().IsUnspecified())
    {
        VerifyOrExit((source = Netif::SelectSourceAddress(messageInfo)) != NULL, error = kThreadError_Error);
        header.SetSource(source->GetAddress());
    }
    else
    {
        header.SetSource(messageInfo.GetSockAddr());
    }

    header.SetDestination(messageInfo.GetPeerAddr());

    if (header.GetDestination().IsLinkLocal() || header.GetDestination().IsLinkLocalMulticast())
    {
        VerifyOrExit(messageInfo.mInterfaceId != 0, error = kThreadError_Drop);
    }

    if (messageInfo.GetPeerAddr().IsRealmLocalMulticast())
    {
        SuccessOrExit(error = AddMplOption(message, header, ipproto, payloadLength));
    }

    SuccessOrExit(error = message.Prepend(&header, sizeof(header)));

    // compute checksum
    checksum = ComputePseudoheaderChecksum(header.GetSource(), header.GetDestination(),
                                           payloadLength, ipproto);

    switch (ipproto)
    {
    case kProtoUdp:
        SuccessOrExit(error = Udp::UpdateChecksum(message, checksum));
        break;

    case kProtoIcmp6:
        SuccessOrExit(error = Icmp::UpdateChecksum(message, checksum));
        break;

    default:
        break;
    }

exit:

    if (error == kThreadError_None)
    {
        error = HandleDatagram(message, NULL, messageInfo.mInterfaceId, NULL, false);
    }

    return error;
}