Main Page   Modules   Alphabetical List   Data Structures   File List   Data Fields   Globals   Related Pages  

udp.c

Go to the documentation of this file.
00001 /*!     \file network/udp.c
00002  *      \brief UDP (User Datagram Protocol) layer.
00003  *      \author Andrea Righi <drizzt@inwind.it>
00004  *      \date Last update:\n
00005  *              2003-01-21 Andrea Righi:
00006  *                      Suppressed deferencing type-punned pointer
00007  *                      warning.
00008  *      \note Copyright (&copy;) 2003 Andrea Righi
00009  */
00010 
00011 #include <const.h>
00012 #include <errno.h>
00013 
00014 #include <kernel/console.h>
00015 
00016 #include <net/ip.h>
00017 #include <net/network.h>
00018 
00019 #include <net/udp.h>
00020 
00021 //! \brief
00022 //!     Calculate the UDP checksum (calculated with the whole
00023 //!     packet).
00024 //! \param buff The UDP packet.
00025 //! \param len The UDP packet length.
00026 //! \param src_addr The IP source address (in network format).
00027 //! \param dest_addr The IP destination address (in network format).
00028 //! \return The result of the checksum.
00029 uint16_t udp_checksum(const void *buff, size_t len, in_addr_t src_addr, in_addr_t dest_addr)
00030 {
00031         const uint16_t *buf=buff;
00032         uint16_t *ip_src=(void *)&src_addr, *ip_dst=(void *)&dest_addr;
00033         uint32_t sum;
00034         size_t length=len;
00035 
00036         // Calculate the sum                                            //
00037         sum = 0;
00038         while (len > 1)
00039         {
00040                 sum += *buf++;
00041                 if (sum & 0x80000000)
00042                         sum = (sum & 0xFFFF) + (sum >> 16);
00043                 len -= 2;
00044         }
00045 
00046         if ( len & 1 )
00047                 // Add the padding if the packet lenght is odd          //
00048                 sum += *((uint8_t *)buf);
00049 
00050         // Add the pseudo-header                                        //
00051         sum += *(ip_src++);
00052         sum += *ip_src;
00053 
00054         sum += *(ip_dst++);
00055         sum += *ip_dst;
00056 
00057         sum += htons(IPPROTO_UDP);
00058         sum += htons(length);
00059 
00060         // Add the carries                                              //
00061         while (sum >> 16)
00062                 sum = (sum & 0xFFFF) + (sum >> 16);
00063 
00064         // Return the one's complement of sum                           //
00065         return ( (uint16_t)(~sum)  );
00066 }
00067 
00068 //! \brief
00069 //!     Process an UDP packet received from the IP layer.
00070 //! \param packet The UDP packet.
00071 //! \param ip_src The IP source address (in network format).
00072 //! \param ip_dst The IP destination address (in network format).
00073 void to_udp_layer(udp_t *packet, in_addr_t ip_src, in_addr_t ip_dst)
00074 {
00075         int i;
00076         bool chk;
00077         uint16_t len = ntohs(packet->udp_len) - sizeof(udp_t);
00078 
00079         // For UDP packets the checksum is optional; a value of 0 in    //
00080         // the checksum means the checksum is not used. A value of      //
00081         // 0xFFFF means the checksum is used and its value is 0.        //
00082         if ( packet->udp_chk != 0 )
00083         {
00084                 // The checksum is used                                 //
00085                 if ( packet->udp_chk == 0xFFFF )
00086                         packet->udp_chk = 0x0000;
00087 
00088                 // Calculate the checksum                               //
00089                 chk = udp_checksum(
00090                                 packet,
00091                                 ntohs(packet->udp_len),
00092                                 ip_src,
00093                                 ip_dst
00094                                 );
00095                 if ( chk )
00096                 {
00097                         kprintf("\n\rUDP checksum error! %04X", chk);
00098                         return;
00099                 }
00100         }
00101 
00102         // Dump the UDP packet                                          //
00103         kprintf(        "\n\rUDP packet received (%u bytes of data)"
00104                 "\n\rsender  = %u.%u.%u.%u:%u"
00105                 "\n\rreceiver= %u.%u.%u.%u:%u",
00106                 len,
00107 
00108                 IP_A(ntohl(ip_src)), IP_B(ntohl(ip_src)),
00109                 IP_C(ntohl(ip_src)), IP_D(ntohl(ip_src)),
00110                 ntohs(packet->udp_src),
00111 
00112                 IP_A(ntohl(ip_dst)), IP_B(ntohl(ip_dst)),
00113                 IP_C(ntohl(ip_dst)), IP_D(ntohl(ip_dst)),
00114                 ntohs(packet->udp_dst)
00115         );
00116 
00117         kprintf("\n\rData:\n\r");
00118         for(i=0; i<len; i++)
00119                 kputchar( (((uint8_t *)packet)+sizeof(udp_t))[i]  );
00120 }
00121 
00122 //! \brief Receive an UDP packet.
00123 //! \param buf The buffer where the received packet will be copied.
00124 //! \param len The maximum size of the buffer.
00125 //! \param flags Flags.
00126 //! \return The size of the packet received in bytes.
00127 /**
00128  *      \todo
00129  *      Routine not implemented!
00130  *      For now return protocol not available error.
00131  */
00132 int recv_udp_packet(udp_t *buf, size_t len, int flags)
00133 {
00134         return( -ENOPROTOOPT );
00135 }

Generated on Fri Feb 20 15:32:16 2004 for Minirighi by doxygen1.2.18