void Reliable::sendCumAck() { UdpHeader header; header.control = 0; header.length = sizeof( header ); header.srcId = m_connection->GetSelfTag(); header.dstId = m_connection->GetRemoteTag(); header.seq = 0; header.ack = m_sendCumAck; header.Set( UdpHeader::ACK ); m_connection->SendRaw( (void*)&header, sizeof( header ) ); }
otError UdpSocket::SendTo(Message &aMessage, const MessageInfo &aMessageInfo) { otError error = OT_ERROR_NONE; MessageInfo messageInfoLocal; UdpHeader udpHeader; messageInfoLocal = aMessageInfo; if (messageInfoLocal.GetSockAddr().IsUnspecified()) { messageInfoLocal.SetSockAddr(GetSockName().GetAddress()); } if (GetSockName().mPort == 0) { GetSockName().mPort = static_cast<Udp *>(mTransport)->GetEphemeralPort(); } if (messageInfoLocal.GetPeerAddr().IsUnspecified()) { VerifyOrExit(!GetPeerName().GetAddress().IsUnspecified(), error = OT_ERROR_INVALID_ARGS); messageInfoLocal.SetPeerAddr(GetPeerName().GetAddress()); } if (messageInfoLocal.mPeerPort == 0) { VerifyOrExit(GetPeerName().mPort != 0, error = OT_ERROR_INVALID_ARGS); messageInfoLocal.mPeerPort = GetPeerName().mPort; } udpHeader.SetSourcePort(GetSockName().mPort); udpHeader.SetDestinationPort(messageInfoLocal.mPeerPort); udpHeader.SetLength(sizeof(udpHeader) + aMessage.GetLength()); udpHeader.SetChecksum(0); SuccessOrExit(error = aMessage.Prepend(&udpHeader, sizeof(udpHeader))); aMessage.SetOffset(0); SuccessOrExit(error = static_cast<Udp *>(mTransport)->SendDatagram(aMessage, messageInfoLocal, kProtoUdp)); exit: return error; }
bool Filter::Accept(Message &aMessage) const { bool rval = false; Header ip6; UdpHeader udp; TcpHeader tcp; uint16_t dstport; // Allow all received IPv6 datagrams with link security enabled if (aMessage.IsLinkSecurityEnabled()) { ExitNow(rval = true); } // Read IPv6 header VerifyOrExit(sizeof(ip6) == aMessage.Read(0, sizeof(ip6), &ip6)); // Allow only link-local unicast or multicast VerifyOrExit(ip6.GetDestination().IsLinkLocal() || ip6.GetDestination().IsLinkLocalMulticast()); switch (ip6.GetNextHeader()) { case kProtoUdp: // Read the UDP header and get the dst port VerifyOrExit(sizeof(udp) == aMessage.Read(sizeof(ip6), sizeof(udp), &udp)); dstport = udp.GetDestinationPort(); // Allow MLE traffic if (dstport == Mle::kUdpPort) { ExitNow(rval = true); } break; case kProtoTcp: // Read the TCP header and get the dst port VerifyOrExit(sizeof(tcp) == aMessage.Read(sizeof(ip6), sizeof(tcp), &tcp)); dstport = tcp.GetDestinationPort(); break; default: // Allow UDP or TCP traffic only ExitNow(); } // Check against allowed unsecure port list for (int i = 0; i < kMaxUnsecurePorts; i++) { if (mUnsecurePorts[i] != 0 && mUnsecurePorts[i] == dstport) { ExitNow(rval = true); } } exit: return rval; }
otError Udp::HandleMessage(Message &aMessage, MessageInfo &aMessageInfo) { otError error = OT_ERROR_NONE; UdpHeader udpHeader; uint16_t payloadLength; uint16_t checksum; payloadLength = aMessage.GetLength() - aMessage.GetOffset(); // check length VerifyOrExit(payloadLength >= sizeof(UdpHeader), error = OT_ERROR_PARSE); // verify checksum checksum = Ip6::ComputePseudoheaderChecksum(aMessageInfo.GetPeerAddr(), aMessageInfo.GetSockAddr(), payloadLength, kProtoUdp); checksum = aMessage.UpdateChecksum(checksum, aMessage.GetOffset(), payloadLength); #ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION VerifyOrExit(checksum == 0xffff, error = OT_ERROR_DROP); #endif VerifyOrExit(aMessage.Read(aMessage.GetOffset(), sizeof(udpHeader), &udpHeader) == sizeof(udpHeader), error = OT_ERROR_PARSE); aMessage.MoveOffset(sizeof(udpHeader)); aMessageInfo.mPeerPort = udpHeader.GetSourcePort(); aMessageInfo.mSockPort = udpHeader.GetDestinationPort(); // find socket for (UdpSocket *socket = mSockets; socket; socket = socket->GetNext()) { if (socket->GetSockName().mPort != udpHeader.GetDestinationPort()) { continue; } if (socket->GetSockName().mScopeId != 0 && socket->GetSockName().mScopeId != aMessageInfo.mInterfaceId) { continue; } if (!aMessageInfo.GetSockAddr().IsMulticast() && !socket->GetSockName().GetAddress().IsUnspecified() && socket->GetSockName().GetAddress() != aMessageInfo.GetSockAddr()) { continue; } // verify source if connected socket if (socket->GetPeerName().mPort != 0) { if (socket->GetPeerName().mPort != udpHeader.GetSourcePort()) { continue; } if (!socket->GetPeerName().GetAddress().IsUnspecified() && socket->GetPeerName().GetAddress() != aMessageInfo.GetPeerAddr()) { continue; } } socket->HandleUdpReceive(aMessage, aMessageInfo); } exit: return error; }
void Reliable::OnRecv( const UdpHeader& header, void* data, uint len ) { K_ASSERT( data != 0 ); K_ASSERT( len > 0 ); K_ASSERT( header.length < len ); K_ASSERT( header.IsSet( UdpHeader::RLE) ); if ( header.seq <= m_sendCumAck ) { LOG( FT_DEBUG, _T("Reliable::OnRecv> self[%d] remote[%d] dup %d checked by m_sendCumAck %d"), m_connection->GetSelfTag(), m_connection->GetRemoteTag(), header.seq, m_sendCumAck ); return; } byte* p = (byte*)data; byte* head = (byte*)(p + header.length); // save payload only data = (void*)head; len = len - header.length; LOG( FT_DEBUG, _T("Reliable::OnRecv> self[%d] remote[%d] seq %d"), m_connection->GetSelfTag(), m_connection->GetRemoteTag(), header.seq ); // if in sequence if ( header.seq == m_sendCumAck + 1 ) { LOG( FT_DEBUG, _T("Reliable::OnRecv> In order %d"), header.seq ); m_communicator->OnRecv( m_connection->GetRemoteTag(), data, len ); ++m_sendCumAck; clearIfExists( m_sendCumAck ); K_ASSERT( header.seq == m_sendCumAck ); m_cumAckInterval = CUMULATIVE_ACK_INTERVAL; } else { LOG( FT_DEBUG, _T("Reliable::OnRecv> Out of order %d"), header.seq ); if ( isDuplicateRecv( header.seq ) ) { LOG( FT_DEBUG, _T("Reliable::OnRecv> Dup %d check by search"), header.seq ); return; } UdpRecvBlock* rv = allocRecvBlock(); rv->ordered = false; rv->seq = header.seq; rv->ackCount = 0; if ( header.IsSet( UdpHeader::ORD ) ) { rv->ordered = true; rv->data = allocData( len ); rv->len = len; ::memcpy( rv->data, data, len ); } else { m_communicator->OnRecv( m_connection->GetRemoteTag(), data, len ); } K_ASSERT( rv->seq > m_sendCumAck ); insertRecvBlock( rv ); runRecvBlockList(); // only 1 eak is used. // send immediately when not in order sendEak( header.seq ); m_tickCumulativeAck.Reset(); } }