BOOL UDPProcess(NODE_INFO *remoteNode, IP_ADDR *localIP, WORD len) { UDP_HEADER h; UDP_SOCKET s; UDP_PSEUDO_HEADER pseudoHeader; WORD_VAL checksum; /* * Retrieve UDP header. */ //MACGetArray((BYTE*)&h, sizeof(h)); MACGetArray(&h, sizeof(UDP_HEADER)); h.SourcePort = swaps(h.SourcePort); h.DestinationPort = swaps(h.DestinationPort); h.Length = swaps(h.Length) - sizeof(UDP_HEADER); debug_udp("\r\nUDP PROCESS SP=%LX DP=%LX PAYLOAD=%LX ", h.SourcePort, h.DestinationPort, h.Length ); // See if we need to validate the checksum field (0x0000 is disabled) if(h.Checksum) { h.Checksum = swaps(h.Checksum); // Calculate IP pseudoheader checksum. pseudoHeader.SourceAddress = remoteNode->IPAddr; pseudoHeader.DestAddress.v[0] = localIP->v[0]; pseudoHeader.DestAddress.v[1] = localIP->v[1]; pseudoHeader.DestAddress.v[2] = localIP->v[2]; pseudoHeader.DestAddress.v[3] = localIP->v[3]; pseudoHeader.Zero = 0x0; pseudoHeader.Protocol = IP_PROT_UDP; pseudoHeader.Length = len; SwapPseudoHeader(pseudoHeader); checksum.Val = ~CalcIPChecksum(&pseudoHeader, sizeof(pseudoHeader)); // Set UDP packet checksum = pseudo header checksum in MAC RAM. IPSetRxBuffer(6); MACPut(checksum.v[0]); // In case if the end of the RX buffer is reached and a wraparound is needed, set the next address to prevent writing to the wrong address. IPSetRxBuffer(7); MACPut(checksum.v[1]); IPSetRxBuffer(0); // Now calculate UDP packet checksum in NIC RAM - including // pesudo header. checksum.Val = CalcIPBufferChecksum(len); if ( checksum.Val != h.Checksum ) { debug_udp("INVALID-CS "); MACDiscardRx(); return TRUE; } } s = FindMatching_UDP_Socket(&h, remoteNode, localIP); if ( s == INVALID_UDP_SOCKET ) { /* * If there is no matching socket, There is no one to handle * this data. Discard it. */ debug_udp("INVALID-SOCKET "); MACDiscardRx(); } else { UDPSocketInfo[s].RxCount = h.Length; UDPSocketInfo[s].Flags.bFirstRead = TRUE; debug_udp("MATCH AS:%U ", s); /*debug_udp("MAC-%X:%X:%X:%X:%X:%X", remoteNode->MACAddr.v[0], remoteNode->MACAddr.v[1], remoteNode->MACAddr.v[2], remoteNode->MACAddr.v[3], remoteNode->MACAddr.v[4], remoteNode->MACAddr.v[5] );*/ } return TRUE; }
/***************************************************************************** Function: BOOL UDPProcess(NODE_INFO *remoteNode, IP_ADDR *localIP, WORD len) Summary: Handles an incoming UDP segment. Description: This function handles an incoming UDP segment to determine if it is acceptable and should be handed to one of the stack applications for processing. Precondition: UDPInit() has been called an a UDP segment is ready in the MAC buffer. Parameters: remoteNode - The remote node that sent this segment. localIP - The destination IP address for this segment. len - Total length of the UDP segment. Return Values: TRUE - A valid packet is waiting and the stack applications should be called to handle it. FALSE - The packet was discarded. ***************************************************************************/ BOOL UDPProcess(NODE_INFO *remoteNode, IP_ADDR *localIP, WORD len) { UDP_HEADER h; UDP_SOCKET s; PSEUDO_HEADER pseudoHeader; DWORD_VAL checksums; UDPRxCount = 0; // Retrieve UDP header. MACGetArray((BYTE*)&h, sizeof(h)); h.SourcePort = swaps(h.SourcePort); h.DestinationPort = swaps(h.DestinationPort); h.Length = swaps(h.Length) - sizeof(UDP_HEADER); // See if we need to validate the checksum field (0x0000 is disabled) if(h.Checksum) { // Calculate IP pseudoheader checksum. pseudoHeader.SourceAddress = remoteNode->IPAddr; pseudoHeader.DestAddress.Val = localIP->Val; pseudoHeader.Zero = 0x0; pseudoHeader.Protocol = IP_PROT_UDP; pseudoHeader.Length = len; SwapPseudoHeader(pseudoHeader); checksums.w[0] = ~CalcIPChecksum((BYTE*)&pseudoHeader, sizeof(pseudoHeader)); // Now calculate UDP packet checksum in NIC RAM -- should match pseudoHeader IPSetRxBuffer(0); checksums.w[1] = CalcIPBufferChecksum(len); if(checksums.w[0] != checksums.w[1]) { MACDiscardRx(); return FALSE; } } s = FindMatchingSocket(&h, remoteNode, localIP); if(s == INVALID_UDP_SOCKET) { // If there is no matching socket, There is no one to handle // this data. Discard it. MACDiscardRx(); return FALSE; } else { SocketWithRxData = s; UDPRxCount = h.Length; Flags.bFirstRead = 1; Flags.bWasDiscarded = 0; } return TRUE; }
/***************************************************************************** Function: void UDPFlush(void) Summary: Transmits all pending data in a UDP socket. Description: This function builds a UDP packet with the pending TX data and marks it for transmission over the network interface. Since UDP is a frame-based protocol, this function must be called before returning to the main stack loop whenever any data is written. Precondition: UDPIsPutReady() was previously called to specify the current socket, and data has been written to the socket using the UDPPut family of functions. Parameters: None Returns: None Remarks: Note that unlike TCPFlush, UDPFlush must be called before returning to the main stack loop. There is no auto transmit for UDP segments. ***************************************************************************/ void UDPFlush(void) { UDP_HEADER h; UDP_SOCKET_INFO *p; WORD wUDPLength; p = &UDPSocketInfo[activeUDPSocket]; wUDPLength = UDPTxCount + sizeof(UDP_HEADER); // Generate the correct UDP header h.SourcePort = swaps(p->localPort); h.DestinationPort = swaps(p->remotePort); h.Length = swaps(wUDPLength); h.Checksum = 0x0000; // Calculate IP pseudoheader checksum if we are going to enable // the checksum field #if defined(UDP_USE_TX_CHECKSUM) { PSEUDO_HEADER pseudoHeader; pseudoHeader.SourceAddress = AppConfig.MyIPAddr; pseudoHeader.DestAddress = p->remote.remoteNode.IPAddr; pseudoHeader.Zero = 0x0; pseudoHeader.Protocol = IP_PROT_UDP; pseudoHeader.Length = wUDPLength; SwapPseudoHeader(pseudoHeader); h.Checksum = ~CalcIPChecksum((BYTE*)&pseudoHeader, sizeof(pseudoHeader)); } #endif // Position the hardware write pointer where we will need to // begin writing the IP header MACSetWritePtr(BASE_TX_ADDR + sizeof(ETHER_HEADER)); // Write IP header to packet IPPutHeader(&p->remote.remoteNode, IP_PROT_UDP, wUDPLength); // Write UDP header to packet MACPutArray((BYTE*)&h, sizeof(h)); // Calculate the final UDP checksum and write it in, if enabled #if defined(UDP_USE_TX_CHECKSUM) { PTR_BASE wReadPtrSave; WORD wChecksum; wReadPtrSave = MACSetReadPtr(BASE_TX_ADDR + sizeof(ETHER_HEADER) + sizeof(IP_HEADER)); wChecksum = CalcIPBufferChecksum(wUDPLength); if(wChecksum == 0x0000u) wChecksum = 0xFFFF; MACSetReadPtr(wReadPtrSave); MACSetWritePtr(BASE_TX_ADDR + sizeof(ETHER_HEADER) + sizeof(IP_HEADER) + 6); // 6 is the offset to the Checksum field in UDP_HEADER MACPutArray((BYTE*)&wChecksum, sizeof(wChecksum)); } #endif // Transmit the packet MACFlush(); // Reset packet size counter for the next TX operation UDPTxCount = 0; LastPutSocket = INVALID_UDP_SOCKET; }
/** * Performs UDP related tasks. Must continuesly be called. * * @preCondition UDPInit() is already called AND <br> * UDP segment is ready in MAC buffer * * @param remoteNode Remote node info * @param len Total length of UDP semgent * @param destIP The Destination IP Address of the currently received packet * * @return TRUE if this function has completed its task <br> * FALSE otherwise */ BOOL UDPProcess(NODE_INFO *remoteNode, IP_ADDR *destIP, WORD len) { UDP_HEADER h; UDP_SOCKET s; PSEUDO_HEADER pseudoHeader; WORD_VAL checksum; #if defined(UDP_SPEED_OPTIMIZE) BYTE temp; #endif //Retrieve UDP header. The data is read from the current MAC RX Buffer MACGetArray((BYTE*)&h, sizeof(h)); #if defined(UDP_SPEED_OPTIMIZE) temp = h.SourcePort.v[0]; h.SourcePort.v[0] = h.SourcePort.v[1]; h.SourcePort.v[1] = temp; temp = h.DestinationPort.v[0]; h.DestinationPort.v[0] = h.DestinationPort.v[1]; h.DestinationPort.v[1] = temp; //Will an overflow occur after the subtraction? if ((BYTE)sizeof(UDP_HEADER) > h.Length.v[1]) { temp = h.Length.v[0] - 1; } else { temp = h.Length.v[0]; } h.Length.v[0] = h.Length.v[1] - (BYTE)sizeof(UDP_HEADER); h.Length.v[1] = temp; #else h.SourcePort.Val = swaps(h.SourcePort.Val); h.DestinationPort.Val = swaps(h.DestinationPort.Val); h.Length.Val = swaps(h.Length.Val) - sizeof(UDP_HEADER); #endif // See if we need to validate the checksum field (0x0000 is disabled) if(h.Checksum.Val) { #if defined(UDP_SPEED_OPTIMIZE) temp = h.Checksum.v[0]; h.Checksum.v[0] = h.Checksum.v[1]; h.Checksum.v[1] = temp; #else h.Checksum.Val = swaps(h.Checksum.Val); #endif // Calculate IP pseudoheader checksum. pseudoHeader.SourceAddress = remoteNode->IPAddr; pseudoHeader.DestAddress.v[0] = destIP->v[0]; pseudoHeader.DestAddress.v[1] = destIP->v[1]; pseudoHeader.DestAddress.v[2] = destIP->v[2]; pseudoHeader.DestAddress.v[3] = destIP->v[3]; pseudoHeader.Zero = 0x0; pseudoHeader.Protocol = IP_PROT_UDP; pseudoHeader.Length = len; SwapPseudoHeader(pseudoHeader); checksum.Val = ~CalcIPChecksum((BYTE*)&pseudoHeader, sizeof(pseudoHeader)); // Set UCP packet checksum = pseudo header checksum in MAC RAM. IPSetRxBuffer(6); MACPut(checksum.v[0]); // In case if the end of the RX buffer is reached and a wraparound is needed, set the next address to prevent writing to the wrong address. IPSetRxBuffer(7); MACPut(checksum.v[1]); IPSetRxBuffer(0); //Set current receive buffer access pointer to first byte of IP data = first byte of TCP header // Now calculate UDP packet checksum in NIC RAM - including // pesudo header. checksum.Val = CalcIPBufferChecksum(len); if ( checksum.Val != h.Checksum.Val ) { MACDiscardRx(); //Discard the contents of the current RX buffer return TRUE; } } s = FindMatchingSocket(&h, remoteNode, destIP); if ( s == INVALID_UDP_SOCKET ) { // If there is no matching socket, There is no one to handle // this data. Discard it. MACDiscardRx(); //Discard the contents of the current RX buffer } else { UDPSocketInfo[s].RxCount = h.Length.Val; UDPSocketInfo[s].Flags.bFirstRead = TRUE; } return TRUE; }