boolean CTCPConnection::SendSegment (unsigned nFlags, u32 nSequenceNumber, u32 nAcknowledgmentNumber, const void *pData, unsigned nDataLength) { unsigned nDataOffset = 5; assert (nDataOffset * 4 == sizeof (TTCPHeader)); if (nFlags & TCP_FLAG_SYN) { nDataOffset++; } unsigned nHeaderLength = nDataOffset * 4; unsigned nPacketLength = nHeaderLength + nDataLength; // may wrap assert (nPacketLength >= nHeaderLength); assert (nHeaderLength <= FRAME_BUFFER_SIZE); assert (m_pTxBuffer != 0); TTCPHeader *pHeader = (TTCPHeader *) m_pTxBuffer; pHeader->nSourcePort = le2be16 (m_nOwnPort); pHeader->nDestPort = le2be16 (m_nForeignPort); pHeader->nSequenceNumber = le2be32 (nSequenceNumber); pHeader->nAcknowledgmentNumber = nFlags & TCP_FLAG_ACK ? le2be32 (nAcknowledgmentNumber) : 0; pHeader->nDataOffsetFlags = (nDataOffset << TCP_DATA_OFFSET_SHIFT) | nFlags; pHeader->nWindow = le2be16 (m_nRCV_WND); pHeader->nUrgentPointer = le2be16 (m_nSND_UP); if (nFlags & TCP_FLAG_SYN) { TTCPOption *pOption = (TTCPOption *) pHeader->Options; pOption->nKind = TCP_OPTION_MSS; pOption->nLength = 4; pOption->Data[0] = TCP_CONFIG_MSS >> 8; pOption->Data[1] = TCP_CONFIG_MSS & 0xFF; }
int CUDPConnection::SendTo (const void *pData, unsigned nLength, int nFlags, CIPAddress &rForeignIP, u16 nForeignPort) { if (m_nErrno < 0) { int nErrno = m_nErrno; m_nErrno = 0; return nErrno; } if (m_bActiveOpen) { // ignore rForeignIP and nForeignPort return Send (pData, nLength, nFlags); } if ( nFlags != 0 && nFlags != MSG_DONTWAIT) { return -1; } unsigned nPacketLength = sizeof (TUDPHeader) + nLength; // may wrap if ( nPacketLength <= sizeof (TUDPHeader) || nPacketLength > FRAME_BUFFER_SIZE) { return -1; } assert (m_pNetConfig != 0); if ( !m_bBroadcastsAllowed && ( rForeignIP.IsBroadcast () || rForeignIP == *m_pNetConfig->GetBroadcastAddress ())) { return -1; } u8 PacketBuffer[nPacketLength]; TUDPHeader *pHeader = (TUDPHeader *) PacketBuffer; pHeader->nSourcePort = le2be16 (m_nOwnPort); pHeader->nDestPort = le2be16 (nForeignPort); pHeader->nLength = le2be16 (nPacketLength); pHeader->nChecksum = 0; assert (pData != 0); assert (nLength > 0); memcpy (PacketBuffer+sizeof (TUDPHeader), pData, nLength); m_Checksum.SetSourceAddress (*m_pNetConfig->GetIPAddress ()); m_Checksum.SetDestinationAddress (rForeignIP); pHeader->nChecksum = m_Checksum.Calculate (PacketBuffer, nPacketLength); assert (m_pNetworkLayer != 0); boolean bOK = m_pNetworkLayer->Send (rForeignIP, PacketBuffer, nPacketLength, IPPROTO_UDP); return bOK ? nLength : -1; }
int CUDPConnection::Send (const void *pData, unsigned nLength, int nFlags) { if (!m_bActiveOpen) { return -1; } if ( nFlags != 0 && nFlags != MSG_DONTWAIT) { return -1; } unsigned nPacketLength = sizeof (TUDPHeader) + nLength; // may wrap if ( nPacketLength <= sizeof (TUDPHeader) || nPacketLength > FRAME_BUFFER_SIZE) { return -1; } u8 *pPacketBuffer = new u8[nPacketLength]; assert (pPacketBuffer != 0); TUDPHeader *pHeader = (TUDPHeader *) pPacketBuffer; pHeader->nSourcePort = le2be16 (m_nOwnPort); pHeader->nDestPort = le2be16 (m_nForeignPort); pHeader->nLength = le2be16 (nPacketLength); pHeader->nChecksum = 0; assert (pData != 0); assert (nLength > 0); memcpy (pPacketBuffer+sizeof (TUDPHeader), pData, nLength); assert (m_pNetConfig != 0); m_Checksum.SetSourceAddress (*m_pNetConfig->GetIPAddress ()); m_Checksum.SetDestinationAddress (m_ForeignIP); pHeader->nChecksum = m_Checksum.Calculate (pPacketBuffer, nPacketLength); assert (m_pNetworkLayer != 0); boolean bOK = m_pNetworkLayer->Send (m_ForeignIP, pPacketBuffer, nPacketLength, IPPROTO_UDP); delete pPacketBuffer; pPacketBuffer = 0; return bOK ? nLength : -1; }
boolean CTCPRejector::SendSegment (unsigned nFlags, u32 nSequenceNumber, u32 nAcknowledgmentNumber) { assert (!(nFlags & TCP_FLAG_SYN)); unsigned nDataOffset = 5; assert (nDataOffset * 4 == sizeof (TTCPHeader)); unsigned nHeaderLength = nDataOffset * 4; unsigned nPacketLength = nHeaderLength; assert (nHeaderLength <= FRAME_BUFFER_SIZE); assert (m_pTxBuffer != 0); TTCPHeader *pHeader = (TTCPHeader *) m_pTxBuffer; pHeader->nSourcePort = le2be16 (m_nOwnPort); pHeader->nDestPort = le2be16 (m_nForeignPort); pHeader->nSequenceNumber = le2be32 (nSequenceNumber); pHeader->nAcknowledgmentNumber = nFlags & TCP_FLAG_ACK ? le2be32 (nAcknowledgmentNumber) : 0; pHeader->nDataOffsetFlags = (nDataOffset << TCP_DATA_OFFSET_SHIFT) | nFlags; pHeader->nWindow = 0; pHeader->nUrgentPointer = 0; pHeader->nChecksum = 0; // must be 0 for calculation pHeader->nChecksum = m_Checksum.Calculate (m_pTxBuffer, nPacketLength); #ifdef TCP_DEBUG CLogger::Get ()->Write (FromTCP, LogDebug, "tx %c%c%c%c%c%c, seq %u, ack %u, win %u, len %u", nFlags & TCP_FLAG_URGENT ? 'U' : '-', nFlags & TCP_FLAG_ACK ? 'A' : '-', nFlags & TCP_FLAG_PUSH ? 'P' : '-', nFlags & TCP_FLAG_RESET ? 'R' : '-', nFlags & TCP_FLAG_SYN ? 'S' : '-', nFlags & TCP_FLAG_FIN ? 'F' : '-', nSequenceNumber, nFlags & TCP_FLAG_ACK ? nAcknowledgmentNumber : 0, 0, 0); #endif assert (m_pNetworkLayer != 0); return m_pNetworkLayer->Send (m_ForeignIP, m_pTxBuffer, nPacketLength, IPPROTO_TCP); }
boolean CDNSClient::Resolve (const char *pHostname, CIPAddress *pIPAddress) { assert (pHostname != 0); if ('1' <= *pHostname && *pHostname <= '9') { return FALSE; } assert (m_pNetSubSystem != 0); CIPAddress DNSServer (m_pNetSubSystem->GetConfig ()->GetDNSServer ()->Get ()); CSocket Socket (m_pNetSubSystem, IPPROTO_UDP); if (Socket.Connect (DNSServer, 53) != 0) { return FALSE; } u8 Buffer[DNS_MAX_MESSAGE_SIZE]; memset (Buffer, 0, sizeof Buffer); TDNSHeader *pDNSHeader = (TDNSHeader *) Buffer; u16 nXID = s_nXID++; pDNSHeader->nID = le2be16 (nXID); pDNSHeader->nFlags = BE (DNS_FLAGS_OPCODE_QUERY | DNS_FLAGS_RD); pDNSHeader->nQDCount = BE (1); u8 *pQuery = Buffer + sizeof (TDNSHeader); char Hostname[MAX_HOSTNAME_SIZE]; strncpy (Hostname, pHostname, MAX_HOSTNAME_SIZE-1); Hostname[MAX_HOSTNAME_SIZE-1] = '\0'; char *pSavePtr; size_t nLength; char *pLabel = strtok_r (Hostname, ".", &pSavePtr); while (pLabel != 0) { nLength = strlen (pLabel); if ( nLength > 255 || (int) (nLength+1+1) >= DNS_MAX_MESSAGE_SIZE-(pQuery-Buffer)) { return FALSE; } *pQuery++ = (u8) nLength; strcpy ((char *) pQuery, pLabel); pQuery += nLength; pLabel = strtok_r (0, ".", &pSavePtr); } *pQuery++ = '\0'; TDNSQueryTrailer QueryTrailer; QueryTrailer.nQType = BE (DNS_QTYPE_A); QueryTrailer.nQClass = BE (DNS_QCLASS_IN); if ((int) (sizeof QueryTrailer) > DNS_MAX_MESSAGE_SIZE-(pQuery-Buffer)) { return FALSE; } memcpy (pQuery, &QueryTrailer, sizeof QueryTrailer); pQuery += sizeof QueryTrailer; int nSize = pQuery - Buffer; assert (nSize <= DNS_MAX_MESSAGE_SIZE); unsigned char RecvBuffer[DNS_MAX_MESSAGE_SIZE]; int nRecvSize; unsigned nTry = 1; do { if ( nTry++ > 3 || Socket.Send (Buffer, nSize, 0) != nSize) { return FALSE; } CScheduler::Get ()->MsSleep (1000); nRecvSize = Socket.Receive (RecvBuffer, DNS_MAX_MESSAGE_SIZE, MSG_DONTWAIT); assert (nRecvSize < DNS_MAX_MESSAGE_SIZE); } while (nRecvSize < (int) (sizeof (TDNSHeader)+sizeof (TDNSResourceRecordTrailerAIN))); pDNSHeader = (TDNSHeader *) RecvBuffer; if ( pDNSHeader->nID != le2be16 (nXID) || (pDNSHeader->nFlags & BE ( DNS_FLAGS_QR | DNS_FLAGS_OPCODE | DNS_FLAGS_TC | DNS_FLAGS_RCODE)) != BE (DNS_FLAGS_QR | DNS_FLAGS_OPCODE_QUERY | DNS_RCODE_SUCCESS) || pDNSHeader->nQDCount != BE (1) || pDNSHeader->nANCount == BE (0)) { return FALSE; } u8 *pResponse = RecvBuffer + sizeof (TDNSHeader); // parse the query section while ((nLength = *pResponse++) > 0) { pResponse += nLength; if (pResponse-RecvBuffer >= nRecvSize) { return FALSE; } } pResponse += sizeof (TDNSQueryTrailer); if (pResponse-RecvBuffer >= nRecvSize) { return FALSE; } TDNSResourceRecordTrailerAIN RRTrailer; // parse the answer section while (1) { nLength = *pResponse++; if ((nLength & 0xC0) == 0xC0) // check for compression { pResponse++; } else { if (pResponse-RecvBuffer >= nRecvSize) { return FALSE; } while ((nLength = *pResponse++) > 0) { pResponse += nLength; if (pResponse-RecvBuffer >= nRecvSize) { return FALSE; } } } if (pResponse-RecvBuffer > (int) (nRecvSize-sizeof RRTrailer)) { return FALSE; } memcpy (&RRTrailer, pResponse, sizeof RRTrailer); if ( RRTrailer.nType == BE (DNS_QTYPE_A) && RRTrailer.nClass == BE (DNS_QCLASS_IN) && RRTrailer.nRDLength == BE (DNS_RDLENGTH_AIN)) { break; } pResponse += DNS_RR_TRAILER_HEADER_LENGTH + BE (RRTrailer.nRDLength); if (pResponse-RecvBuffer >= nRecvSize) { return FALSE; } } assert (pIPAddress != 0); pIPAddress->Set (RRTrailer.RData); return TRUE; }