www.pudn.com > zhiyonglou311.rar > Udp.c
//----------------------------------------------------------------------------- // Net UDP.C // // This module handles UDP messages // Refer to RFC 768, 1122 // Also RFC 862 echo, RFC 867 daytime, and RFC 868 time //----------------------------------------------------------------------------- #include#include #include "C8051f.h" #include "net.h" #include "ip.h" #include "cksum.h" #include "serial.h" #include "icmp.h" #include "udp.h" extern UCHAR idata debug; extern ULONG code my_ipaddr; UINT xdata sender_udpport; static ULONG xdata sender_ipaddr; extern char xdata text[]; //------------------------------------------------------------------------ // UDP Echo service - see RFC 862 // This simply echos what it received back to the sender //------------------------------------------------------------------------ void udp_echo_service(UCHAR xdata * inbuf, UINT len) { if (debug) { serial_send("ECHO: Nr chars = "); memset(text, 0, 10); itoa(len, text, 10); serial_send(text); serial_send("\r"); } udp_send(inbuf, ECHO_PORT, len); } //------------------------------------------------------------------------ // This handles outgoing UDP messages // See "TCP/IP Illustrated, Volume 1" Sect 11.1 - 11.3 //------------------------------------------------------------------------ void udp_send(UCHAR xdata * inbuf, UINT port, UINT len) { ULONG idata sum; UINT idata result; UCHAR xdata * outbuf; UDP_HEADER xdata * udp; IP_HEADER xdata * ip; // Allocate memory for entire outgoing message including // eth & IP headers. Total ethernet message length is: // 14 byte eth header + 20 byte IP header + 8 byte UDP header // + length of this data outbuf = (UCHAR xdata *)malloc(42 + len); if (outbuf == NULL) { if (debug) serial_send("UDP: Oops, out of memory\r"); return; } udp = (UDP_HEADER xdata *)(outbuf + 34); ip = (IP_HEADER xdata *)(outbuf + 14); // Direct message back to the senders port. udp->dest_port = sender_udpport; udp->source_port = port; udp->length = 8 + len; udp->checksum = 0; // Fill in data // Important do not free receive buffer prior to this memcpy(&udp->msg_data, (inbuf + 42), len); // Compute checksum including 12 bytes of pseudoheader // Must pre-fill 2 items in outbuf to do this // Direct message back to senders ip address ip->dest_ipaddr = sender_ipaddr; ip->source_ipaddr = my_ipaddr; // Sum source_ipaddr, dest_ipaddr, and entire UDP message sum = (ULONG)cksum(outbuf + 26, 8 + udp->length); // Add in the rest of pseudoheader which is // zero, protocol id, and UDP length sum += (ULONG)0x0011; sum += (ULONG)udp->length; // In case there was a carry, add it back around result = (UINT)(sum + (sum >> 16)); udp->checksum = ~result; if (debug) serial_send("UDP: Sending msg to IP layer\r"); ip_send(outbuf, sender_ipaddr, UDP_TYPE, udp->length); } //------------------------------------------------------------------------ // This handles incoming UDP messages // See "TCP/IP Illustrated, Volume 1" Sect 11.1 - 11.3 //------------------------------------------------------------------------ void udp_rcve(UCHAR xdata * inbuf, UINT len) { UINT idata result; UDP_HEADER xdata * udp; IP_HEADER xdata * ip; ULONG idata sum; // Total of eth & IP headers = 34 bytes udp = (UDP_HEADER xdata *)(inbuf + 34); ip = (IP_HEADER xdata *)(inbuf + 14); // The IP length "len" should be the same as the redundant length // udp->length. TCP/IP Illustrated, Vol 2, Sect 23.7 says to use the // UDP length, unless IP length < UDP length, in which case the frame // should be discarded. if (len < udp->length) return; // If the checksum is zero it means that the sender did not compute // it and we should not try to check it. if (udp->checksum == 0) { if (debug) serial_send("UDP: Sender did not compute cksum\r"); } else { // Compute UDP checksum including 12 byte pseudoheader // Sum source_ipaddr, dest_ipaddr, and entire UDP message sum = (ULONG)cksum(inbuf + 26, 8 + udp->length); // Add in the rest of pseudoheader which is // zero, protocol id, and UDP length sum += (ULONG)0x0011; sum += (ULONG)udp->length; // In case there was a carry, add it back around result = (UINT)(sum + (sum >> 16)); if (result != 0xFFFF) { if (debug) serial_send("UDP: Error, bad cksum\r"); return; } if (debug) serial_send("UDP: Msg rcvd with good cksum\r"); } // Capture sender's port number and ip_addr // to send return message to sender_udpport = udp->source_port; sender_ipaddr = ip->source_ipaddr; // See if any applications are on any ports switch (udp->dest_port) { case ECHO_PORT: // Pass it the payload length udp_echo_service(inbuf, udp->length - 8); break; default: // If no application is registered to handle incoming // UDP message then send ICMP destination unreachable dest_unreach_send(inbuf, ip->source_ipaddr); break; } }