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; }
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; }