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

/opentcp/udp.c

Go to the documentation of this file.
00001 /*
00002  *Copyright (c) 2000-2002 Viola Systems Ltd.
00003  *All rights reserved.
00004  *
00005  *Redistribution and use in source and binary forms, with or without 
00006  *modification, are permitted provided that the following conditions 
00007  *are met:
00008  *
00009  *1. Redistributions of source code must retain the above copyright 
00010  *notice, this list of conditions and the following disclaimer.
00011  *
00012  *2. Redistributions in binary form must reproduce the above copyright 
00013  *notice, this list of conditions and the following disclaimer in the 
00014  *documentation and/or other materials provided with the distribution.
00015  *
00016  *3. The end-user documentation included with the redistribution, if 
00017  *any, must include the following acknowledgment:
00018  *      "This product includes software developed by Viola 
00019  *      Systems (http://www.violasystems.com/)."
00020  *
00021  *Alternately, this acknowledgment may appear in the software itself, 
00022  *if and wherever such third-party acknowledgments normally appear.
00023  *
00024  *4. The names "OpenTCP" and "Viola Systems" must not be used to 
00025  *endorse or promote products derived from this software without prior 
00026  *written permission. For written permission, please contact 
00027  *opentcp@opentcp.org.
00028  *
00029  *5. Products derived from this software may not be called "OpenTCP", 
00030  *nor may "OpenTCP" appear in their name, without prior written 
00031  *permission of the Viola Systems Ltd.
00032  *
00033  *THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED 
00034  *WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 
00035  *MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 
00036  *IN NO EVENT SHALL VIOLA SYSTEMS LTD. OR ITS CONTRIBUTORS BE LIABLE 
00037  *FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 
00038  *CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 
00039  *SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 
00040  *BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
00041  *WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 
00042  *OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 
00043  *EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00044  *====================================================================
00045  *
00046  *OpenTCP is the unified open source TCP/IP stack available on a series 
00047  *of 8/16-bit microcontrollers, please see <http://www.opentcp.org>.
00048  *
00049  *For more information on how to network-enable your devices, or how to 
00050  *obtain commercial technical support for OpenTCP, please see 
00051  *<http://www.violasystems.com/>.
00052  */
00053 
00077 #include <inet/debug.h>
00078 #include <inet/datatypes.h>
00079 #include <inet/ethernet.h>
00080 #include <inet/ip.h>
00081 #include <inet/tcp_ip.h>
00082 #include <inet/system.h>
00083 
00094 struct ucb udp_socket[NO_OF_UDPSOCKETS];
00095 
00101 struct udp_frame received_udp_packet;
00102 
00118 INT8 udp_init (void)
00119 {
00120         UINT8 i;
00121         struct ucb* soc;
00122         
00123         if( NO_OF_UDPSOCKETS < 0 )
00124                 return(-1);
00125         
00126         if( NO_OF_UDPSOCKETS == 0 )
00127                 return(0);
00128         
00129         UDP_DEBUGOUT("Initializing UDP");
00130         
00131         for(i=0; i < NO_OF_UDPSOCKETS; i++) {
00132                 soc = &udp_socket[i];                   /* Get Socket   */
00133                 
00134                 soc->state = UDP_STATE_FREE;
00135                 soc->tos = 0;
00136                 soc->locport = 0;
00137                 soc->opts = UDP_OPT_SEND_CS | UDP_OPT_CHECK_CS;  
00138                 soc->event_listener = 0;
00139                 
00140                 UDP_DEBUGOUT(".");
00141                 
00142         }
00143         
00144         UDP_DEBUGOUT("\n\rUDP Initialized\n\r");
00145         
00146         /* Return number of sockets initialized */
00147         
00148         return(i+1);
00149 
00150 }
00151 
00175 INT8 udp_getsocket (UINT8 tos, INT32 (*listener)(INT8, UINT8, UINT32, UINT16, UINT16, UINT16), UINT8 opts )
00176 {
00177         INT8 i;
00178         struct ucb* soc;
00179         
00180         if( NO_OF_UDPSOCKETS < 0 )
00181                 return(-1);
00182         
00183         if( NO_OF_UDPSOCKETS == 0 )
00184                 return(-1);
00185         
00186         
00187         if(listener == 0) {
00188                 UDP_DEBUGOUT("ERROR:Event listener function for UDP not specified\r\n");
00189                 return(-1);
00190         }
00191         
00192         UDP_DEBUGOUT("Searching for free UDP socket...\r\n");
00193         
00194         for(i=0; i < NO_OF_UDPSOCKETS; i++) {
00195                 soc = &udp_socket[i];                   /* Get Socket   */
00196         
00197                 if(soc->state == UDP_STATE_FREE) {
00198                         /* We found it  */
00199                         
00200                         UDP_DEBUGOUT("Free socket found\r\n");
00201                         
00202                         soc->state = UDP_STATE_CLOSED;
00203                         soc->tos = tos;
00204                         soc->locport = 0;
00205                         
00206                         soc->opts = 0;
00207                         
00208                         if(opts & UDP_OPT_SEND_CS)
00209                                 soc->opts |= UDP_OPT_SEND_CS;
00210                         if(opts & UDP_OPT_CHECK_CS)
00211                                 soc->opts |= UDP_OPT_CHECK_CS;
00212                         
00213                         soc->event_listener = listener;
00214 
00215                         /* Return handle        */
00216                         
00217                         return(i);
00218                 }
00219         
00220         }
00221         
00222         /* We are there so no socket found      */
00223         
00224         UDP_DEBUGOUT("No UDP socket found\r\n");
00225         return(-1);
00226 
00227 }
00228 
00229 
00244 INT8 udp_releasesocket (INT8 sochandle)
00245 {
00246         struct ucb* soc;
00247         
00248         if( NO_OF_UDPSOCKETS < 0 )
00249                 return(-1);
00250         
00251         if( NO_OF_UDPSOCKETS == 0 )
00252                 return(-1);
00253         
00254         if( sochandle > NO_OF_UDPSOCKETS ) {
00255                 UDP_DEBUGOUT("Socket handle non-valid\r\n");
00256                 return(-1);
00257         }
00258         
00259         if( sochandle < 0 ) {
00260                 UDP_DEBUGOUT("Socket handle non-valid\r\n");
00261                 return(-1);
00262         }
00263         
00264         soc = &udp_socket[sochandle];           /* Get referense        */
00265         
00266         soc->state = UDP_STATE_FREE;
00267         soc->tos = 0;
00268         soc->locport = 0;
00269         soc->opts = UDP_OPT_SEND_CS | UDP_OPT_CHECK_CS; 
00270         soc->event_listener = 0;
00271 
00272         return(sochandle);
00273 
00274 }
00275 
00276 
00291 INT8 udp_open (INT8 sochandle, UINT16 locport)
00292 {
00293         struct ucb* soc;
00294         
00295         if( NO_OF_UDPSOCKETS < 0 )
00296                 return(-1);
00297         
00298         if( NO_OF_UDPSOCKETS == 0 )
00299                 return(-1);
00300         
00301         if( sochandle > NO_OF_UDPSOCKETS ) {
00302                 UDP_DEBUGOUT("Socket handle non-valid\r\n");
00303                 return(-1);
00304         }
00305         
00306         if( sochandle < 0 ) {
00307                 UDP_DEBUGOUT("Socket handle non-valid\r\n");
00308                 return(-1);
00309         }
00310         
00311         if(locport == 0) {
00312                 locport=udp_getfreeport();
00313                 return(-1);
00314         }
00315         
00316         soc = &udp_socket[sochandle];           /* Get referense        */
00317 
00318         soc->state = UDP_STATE_OPENED;
00319         soc->locport = locport;
00320         
00321         return(sochandle);
00322 
00323 }
00324 
00325 
00326 
00340 INT8 udp_close (INT8 sochandle)
00341 {
00342         struct ucb* soc;
00343         
00344         if( NO_OF_UDPSOCKETS < 0 )
00345                 return(-1);
00346         
00347         if( NO_OF_UDPSOCKETS == 0 )
00348                 return(-1);
00349         
00350         if( sochandle > NO_OF_UDPSOCKETS ) {
00351                 UDP_DEBUGOUT("Socket handle non-valid\r\n");
00352                 return(-1);
00353         }
00354         
00355         if( sochandle < 0 ) {
00356                 UDP_DEBUGOUT("Socket handle non-valid\r\n");
00357                 return(-1);
00358         }
00359         
00360         soc = &udp_socket[sochandle];           /* Get referense        */
00361 
00362         soc->state = UDP_STATE_CLOSED;
00363         
00364         return(sochandle);
00365 
00366 }
00367 
00368 
00395 INT16 udp_send (INT8 sochandle, UINT32 remip, UINT16 remport, UINT8* buf, UINT16 blen, UINT16 dlen)
00396 {
00397         struct ucb* soc;
00398         UINT8* user_buf_start;
00399         UINT16 cs;
00400         UINT8 cs_cnt;
00401         INT16 i;
00402         
00403         if( NO_OF_UDPSOCKETS < 0 )
00404                 return(-1);
00405         
00406         if( NO_OF_UDPSOCKETS == 0 )
00407                 return(-1);
00408         
00409         if( sochandle > NO_OF_UDPSOCKETS ) {
00410                 UDP_DEBUGOUT("Socket handle non-valid\r\n");
00411                 return(-1);
00412         }
00413         
00414         if( sochandle < 0 ) {
00415                 UDP_DEBUGOUT("Socket handle non-valid\r\n");
00416                 return(-1);
00417         }
00418         
00419         if(remip == 0) {
00420                 UDP_DEBUGOUT("Remote IP 0 not allowed\r\n");
00421                 return(-1);
00422         }
00423         
00424         if(remport == 0) {
00425                 UDP_DEBUGOUT("Remote port 0 not allowed\r\n");
00426                 return(-1);
00427         }
00428         
00429         if( dlen > blen )
00430                 dlen = blen;
00431         
00432         if( (dlen + UDP_HLEN) > UDP_SEND_MTU)
00433                 dlen = UDP_SEND_MTU - UDP_HLEN;
00434         
00435         soc = &udp_socket[sochandle];           /* Get referense        */
00436 
00437         if(soc->state != UDP_STATE_OPENED ) {
00438                 UDP_DEBUGOUT("UDP Socket Closed\r\n");
00439                 return(-3);
00440         }
00441         
00442         if(soc->locport == 0) {
00443                 UDP_DEBUGOUT("ERROR:Socket local port is zero\r\n");
00444                 return(-1);
00445         }
00446 
00447         user_buf_start = buf;
00448         
00449         buf -= UDP_HLEN;
00450         
00451         /* Put header   */
00452         
00453         *buf++ = (UINT8)(soc->locport >> 8);
00454         *buf++ = (UINT8)soc->locport;
00455         *buf++ = (UINT8)(remport >> 8);
00456         *buf++ = (UINT8)remport;
00457         *buf++ = (UINT8)((dlen + UDP_HLEN) >> 8);
00458         *buf++ = (UINT8)(dlen + UDP_HLEN);
00459         *buf++ = 0;
00460         *buf = 0;
00461         
00462         buf = user_buf_start;
00463         buf -= UDP_HLEN;
00464         
00465         /* Calculate checksum if needed */
00466         
00467         cs = 0;
00468         
00469         if( soc->opts & UDP_OPT_SEND_CS) {
00470                 cs = 0;
00471                 cs_cnt = 0;
00472         
00473                 /* Do it firstly to IP pseudo header    */
00474         
00475                 cs = ip_checksum(cs, (UINT8)(localmachine.localip >> 24), cs_cnt++);    
00476                 cs = ip_checksum(cs, (UINT8)(localmachine.localip >> 16), cs_cnt++);
00477                 cs = ip_checksum(cs, (UINT8)(localmachine.localip >> 8), cs_cnt++);
00478                 cs = ip_checksum(cs, (UINT8)localmachine.localip, cs_cnt++);
00479         
00480                 cs = ip_checksum(cs, (UINT8)(remip >> 24), cs_cnt++);   
00481                 cs = ip_checksum(cs, (UINT8)(remip >> 16), cs_cnt++);
00482                 cs = ip_checksum(cs, (UINT8)(remip >> 8), cs_cnt++);
00483                 cs = ip_checksum(cs, (UINT8)remip, cs_cnt++);   
00484         
00485                 cs = ip_checksum(cs, 0, cs_cnt++);
00486         
00487                 cs = ip_checksum(cs, (UINT8)IP_UDP, cs_cnt++);
00488                 
00489                 cs = ip_checksum(cs, (UINT8)((dlen + UDP_HLEN) >> 8), cs_cnt++);
00490                 cs = ip_checksum(cs, (UINT8)(dlen + UDP_HLEN), cs_cnt++);       
00491         
00492                 /* Go to UDP header + data      */
00493         
00494                 buf = user_buf_start;
00495                 buf -= UDP_HLEN;
00496         
00497                 for(i=0; i < (dlen + UDP_HLEN); i++)
00498                         cs = ip_checksum(cs, *buf++, cs_cnt++);
00499         
00500                 cs = ~ cs;
00501         
00502                 if(cs == 0)
00503                         cs = 0xFFFF;
00504                 
00505                 /* Save checksum in correct place       */
00506                 buf = user_buf_start;
00507                 buf -= UDP_HLEN;
00508                 buf += 6;
00509                 *buf++ = (UINT8)(cs >> 8);
00510                 *buf = (UINT8)cs;       
00511                 
00512                 buf = user_buf_start;
00513                 buf -= UDP_HLEN;
00514                         
00515         }
00516         
00517         /* Send it to IP        */
00518         
00519         UDP_DEBUGOUT("Sending UDP...\r\n");
00520         
00521         i = process_ip_out(remip, IP_UDP, soc->tos, 100, buf, dlen + UDP_HLEN);
00522         
00523         /* Errors?      */
00524         
00525         if( i < 0 )
00526                 return(i);
00527         
00528         UDP_DEBUGOUT("UDP packet sent\r\n");
00529         
00530         return(i - UDP_HLEN);
00531 
00532 
00533 }
00534 
00535 
00536 
00551 INT16 process_udp_in(struct ip_frame* frame, UINT16 len)
00552 {
00553         struct ucb* soc;
00554         UINT16 checksum;
00555         UINT16 i;
00556         INT8 sochandle;
00557                 
00558         /* Is this UDP? */
00559         
00560         UDP_DEBUGOUT("Processing UDP...\n\r");
00561         
00562         if( frame->protocol != IP_UDP ) {
00563                 UDP_DEBUGOUT("ERROR: The protocol is not UDP\n\r");
00564                 return(-1);
00565         }
00566         
00567         /* Start processing the message */
00568         
00569         NETWORK_RECEIVE_INITIALIZE(frame->buf_index);
00570 
00571         received_udp_packet.sport = ((UINT16)RECEIVE_NETWORK_B()) << 8;
00572         received_udp_packet.sport |= RECEIVE_NETWORK_B();
00573         
00574         received_udp_packet.dport = ((UINT16)RECEIVE_NETWORK_B()) << 8;
00575         received_udp_packet.dport |= RECEIVE_NETWORK_B();       
00576         
00577         received_udp_packet.tlen = ((UINT16)RECEIVE_NETWORK_B()) << 8;
00578         received_udp_packet.tlen |= RECEIVE_NETWORK_B();
00579         
00580         received_udp_packet.checksum = ((UINT16)RECEIVE_NETWORK_B()) << 8;
00581         received_udp_packet.checksum |= RECEIVE_NETWORK_B();
00582         
00583         if(received_udp_packet.tlen < UDP_HLEN ) {
00584                 UDP_DEBUGOUT("UDP frame too short\n\r");
00585                 return(-1);
00586         }
00587         
00588         
00589         /* Map UDP socket       */
00590         
00591         sochandle = -1;
00592         
00593         for( i=0; i < NO_OF_UDPSOCKETS; i++) {
00594                 soc = &udp_socket[i];                           /* Get referense        */
00595 
00596                 if(soc->state != UDP_STATE_OPENED )
00597                         continue;
00598                 
00599                 if(soc->locport != received_udp_packet.dport)
00600                         continue;
00601                 
00602                 /* Socket found */
00603                 
00604                 sochandle = i;
00605                 
00606                 break;
00607         }
00608         
00609         if( sochandle < 0 ) {
00610                 UDP_DEBUGOUT("No socket found for received UDP Packet\r\n");
00611                 
00612                 /* TODO: Send ICMP      */
00613                 
00614                 return(-1);
00615         }
00616         
00617         /* Calculate checksum for received packet       */
00618         
00619         if(soc->opts & UDP_OPT_CHECK_CS) {
00620                 if(received_udp_packet.checksum != 0) {
00621                         checksum = 0;
00622                         i = 0;
00623                         
00624                         /* Do it firstly to IP pseudo header    */
00625         
00626                         checksum = ip_checksum(checksum, (UINT8)(localmachine.localip >> 24), (UINT8)i++);      
00627                         checksum = ip_checksum(checksum, (UINT8)(localmachine.localip >> 16), (UINT8)i++);
00628                         checksum = ip_checksum(checksum, (UINT8)(localmachine.localip >> 8), (UINT8)i++);
00629                         checksum = ip_checksum(checksum, (UINT8)localmachine.localip, (UINT8)i++);
00630         
00631                         checksum = ip_checksum(checksum, (UINT8)(frame->sip >> 24), (UINT8)i++);        
00632                         checksum = ip_checksum(checksum, (UINT8)(frame->sip >> 16), (UINT8)i++);
00633                         checksum = ip_checksum(checksum, (UINT8)(frame->sip >> 8), (UINT8)i++);
00634                         checksum = ip_checksum(checksum, (UINT8)frame->sip, (UINT8)i++);        
00635         
00636                         checksum = ip_checksum(checksum, 0, (UINT8)i++);
00637         
00638                         checksum = ip_checksum(checksum, (UINT8)IP_UDP, (UINT8)i++);
00639                 
00640                         checksum = ip_checksum(checksum, (UINT8)(len >> 8), (UINT8)i++);
00641                         checksum = ip_checksum(checksum, (UINT8)len, (UINT8)i++);       
00642 
00643         
00644                         NETWORK_RECEIVE_INITIALIZE(frame->buf_index);
00645         
00646                         for(i=0; i < len; i++)
00647                                 checksum = ip_checksum(checksum, RECEIVE_NETWORK_B(), (UINT8)i);
00648         
00649                         checksum = ~ checksum;
00650         
00651                         if(checksum != IP_GOOD_CS) {
00652                                 UDP_DEBUGOUT("ERROR: UDP Checksum failed!\n\r");
00653                                 return (-1);
00654                         }
00655                 
00656                 }
00657         
00658                 UDP_DEBUGOUT("UDP Checksum OK\n\r");
00659         
00660         }
00661         
00662         
00663         received_udp_packet.buf_index = frame->buf_index + UDP_HLEN;
00664         NETWORK_RECEIVE_INITIALIZE(received_udp_packet.buf_index);
00665         
00666         /* Generate data event  */
00667         
00668         soc->event_listener(sochandle, UDP_EVENT_DATA, frame->sip, received_udp_packet.sport, received_udp_packet.buf_index, received_udp_packet.tlen - UDP_HLEN);
00669         
00670         return(1);
00671 
00672 }
00673 
00685 UINT16 udp_getfreeport (void){
00686         struct ucb* soc;
00687         static UINT16 lastport = 1;
00688         UINT16 start;
00689         UINT16 i;
00690         
00691 
00692         /* Try with every port to every socket untill free found        */
00693                 
00694         for( start = lastport++; start != lastport; lastport++) {
00695                 if(lastport == UDP_PORTS_END)
00696                         lastport = 1;
00697                         
00698                 for(i = 0; i < NO_OF_UDPSOCKETS; i++) {
00699                         soc = &udp_socket[i];                                   /* Get socket   */
00700                         
00701                         if( (soc->state > UDP_STATE_CLOSED) && (soc->locport == lastport) )                     {
00702                                 /* Blaah, this socket has reserved the port, go to next one     */
00703                                 break; 
00704                         }
00705                         
00706                 }       
00707                         
00708                 /* Did we found it?     */
00709                         
00710                 if( i == NO_OF_UDPSOCKETS)
00711                         break; 
00712                         
00713         }
00714                 
00715         if(lastport == start) {
00716                 DEBUGOUT("Out of UDP ports!!\n\r");
00717                 return(0);
00718         }
00719                 
00720         return(lastport);
00721                 
00722 }
00723 
00724 
00725 
00726 
00727 

Generated on Sat Jan 25 17:13:15 2003 for OpenTCP by doxygen1.2.18