GUI: Fix Tomato RAF theme for all builds. Compilation typo.
[tomato.git] / release / src-rt-6.x.4708 / cfe / cfe / net / net_udp.c
blob144f61aaa6ed06ea616ccbd6797d5325e0445fe5
1 /* *********************************************************************
2 * Broadcom Common Firmware Environment (CFE)
3 *
4 * User Datagram Protocol File: net_udp.c
5 *
6 * This module implements the User Datagram Protocol (RFCxxxx)
7 *
8 * Author: Mitch Lichtenberg (mpl@broadcom.com)
9 *
10 *********************************************************************
12 * Copyright 2000,2001,2002,2003
13 * Broadcom Corporation. All rights reserved.
15 * This software is furnished under license and may be used and
16 * copied only in accordance with the following terms and
17 * conditions. Subject to these conditions, you may download,
18 * copy, install, use, modify and distribute modified or unmodified
19 * copies of this software in source and/or binary form. No title
20 * or ownership is transferred hereby.
22 * 1) Any source code used, modified or distributed must reproduce
23 * and retain this copyright notice and list of conditions
24 * as they appear in the source file.
26 * 2) No right is granted to use any trade name, trademark, or
27 * logo of Broadcom Corporation. The "Broadcom Corporation"
28 * name may not be used to endorse or promote products derived
29 * from this software without the prior written permission of
30 * Broadcom Corporation.
32 * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
33 * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
34 * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
35 * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
36 * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
37 * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR DIRECT, INDIRECT,
38 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
39 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
40 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
41 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
42 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
43 * TORT (INCLUDING NEGLIGENCE OR OTHERWISE), EVEN IF ADVISED OF
44 * THE POSSIBILITY OF SUCH DAMAGE.
45 ********************************************************************* */
49 #include "lib_types.h"
50 #include "lib_string.h"
51 #include "lib_queue.h"
52 #include "lib_malloc.h"
53 #include "lib_printf.h"
55 #include "cfe_timer.h"
57 #include "net_ebuf.h"
58 #include "net_ether.h"
60 #include "net_ip.h"
62 #include "cfe_error.h"
64 /* *********************************************************************
65 * Constants
66 ********************************************************************* */
68 #define UDP_HDR_LENGTH 8
69 #define UDP_PORTBASE 1024
70 #define UDP_MAX_PORTS 4
72 /* *********************************************************************
73 * Types
74 ********************************************************************* */
76 typedef struct udp_port_s udp_port_t;
79 * UDP port structure - describes an open UDP port.
82 struct udp_port_s {
83 uint16_t up_destport; /* destination port number */
84 uint16_t up_srcport; /* source port number */
85 queue_t up_rxqueue; /* queue of received packets */
86 int up_maxqueue; /* max # of elements on rx queue */
87 int up_inuse; /* nonzero if port is in use */
92 * UDP stack information - describes the entire UDP layer.
95 struct udp_info_s {
96 uint16_t ui_portbase;
97 void *ui_ref;
98 ip_info_t *ui_ipinfo;
99 udp_port_t ui_ports[UDP_MAX_PORTS];
102 /* *********************************************************************
103 * Forward declarations
104 ********************************************************************* */
106 static int _udp_rx_callback(void *ref,ebuf_t *buf,uint8_t *destaddr,uint8_t *srcaddr);
109 /* *********************************************************************
110 * udp_find_port(info,port)
112 * Locate an open port. Scan the list of ports looking for one
113 * that is both open and has a matching source port number.
115 * Input parameters:
116 * info - UDP stack information
117 * port - source port # we're looking for
119 * Return value:
120 * udp_port_t pointer or NULL if no port was found
121 ********************************************************************* */
123 static udp_port_t *_udp_find_port(udp_info_t *info,uint16_t port)
125 int idx;
126 udp_port_t *udp = info->ui_ports;
128 for (idx = 0; idx < UDP_MAX_PORTS; idx++) {
129 if (udp->up_inuse && (udp->up_srcport == port)) {
130 return udp;
132 udp++;
135 return NULL;
138 /* *********************************************************************
139 * _udp_socket(info,port)
141 * Open a UDP socket. This is an internal function used by
142 * the network API layer.
144 * Input parameters:
145 * info - UDP stack information
146 * port - port number to open
148 * Return value:
149 * port number (0 based) or an error code (<0) if an error
150 * occured.
151 ********************************************************************* */
153 int _udp_socket(udp_info_t *info,uint16_t port)
155 extern int32_t _getticks(void); /* return value of CP0 COUNT */
156 int idx;
157 udp_port_t *udp;
158 uint16_t srcport = UDP_PORTBASE + (_getticks() & 0xFFF);
160 while (_udp_find_port(info,srcport)) { /* should always exit */
161 srcport++;
162 if (srcport > (UDP_PORTBASE+4096)) srcport = UDP_PORTBASE;
165 udp = info->ui_ports;
167 for (idx = 0; idx < UDP_MAX_PORTS; idx++) {
168 if (!udp->up_inuse) break;
169 udp++;
172 if (idx == UDP_MAX_PORTS) return CFE_ERR_NOHANDLES;
174 udp->up_destport = port;
175 udp->up_srcport = srcport;
176 udp->up_maxqueue = 2;
177 udp->up_inuse = TRUE;
178 q_init(&(udp->up_rxqueue));
180 return idx;
184 /* *********************************************************************
185 * _udp_close(info,s)
187 * Internal function to close an open UDP port. This routine is
188 * called by the high-level network API.
190 * Input parameters:
191 * info - UDP stack information
192 * s - an open UDP socket handle (returned from _udp_open)
194 * Return value:
195 * nothing
196 ********************************************************************* */
198 void _udp_close(udp_info_t *info,int s)
200 udp_port_t *udp = &(info->ui_ports[s]);
201 ebuf_t *buf;
203 while ((buf = (ebuf_t *) q_deqnext(&(udp->up_rxqueue)))) {
204 _ip_free(info->ui_ipinfo,buf);
207 udp->up_srcport = 0;
208 udp->up_destport = 0;
209 udp->up_maxqueue = 0;
210 udp->up_inuse = FALSE;
213 /* *********************************************************************
214 * _udp_send(info,s,buf,dest)
216 * Transmit a UDP datagram. Note that we never send fragmented
217 * datagrams, so all datagrams must be less than the MTU.
219 * Input parameters:
220 * info - UDP stack information
221 * s - an open UDP socket handle (returned from _udp_open)
222 * buf - an ebuf to send
223 * dest - destination IP address
225 * Return value:
226 * 0 if packet was sent
227 * else error code
228 ********************************************************************* */
230 int _udp_send(udp_info_t *info,int s,ebuf_t *buf,uint8_t *dest)
232 udp_port_t *udp = &(info->ui_ports[s]);
233 uint8_t *udphdr;
234 int udplen;
235 uint8_t pseudoheader[12];
236 uint16_t cksum;
239 * Calculate the length of the IP datagram (includes UDP header)
242 udplen = ebuf_length(buf) + UDP_HDR_LENGTH;
245 * Build the pseudoheader, which is part of the checksum calculation
248 _ip_getaddr(info->ui_ipinfo,&pseudoheader[0]);
249 memcpy(&pseudoheader[4],dest,IP_ADDR_LEN);
250 pseudoheader[8] = 0;
251 pseudoheader[9] = IPPROTO_UDP;
252 pseudoheader[10] = (udplen >> 8) & 0xFF;
253 pseudoheader[11] = (udplen & 0xFF);
256 * Back up and build the actual UDP header in the packet
259 ebuf_seek(buf,-UDP_HDR_LENGTH);
260 udphdr = ebuf_ptr(buf);
262 ebuf_put_u16_be(buf,udp->up_srcport);
263 ebuf_put_u16_be(buf,udp->up_destport);
264 ebuf_put_u16_be(buf,udplen);
265 ebuf_put_u16_be(buf,0);
267 ebuf_prepend(buf,UDP_HDR_LENGTH);
270 * Checksum the packet and insert the checksum into the header
273 cksum = ip_chksum(0,pseudoheader,sizeof(pseudoheader));
274 cksum = ip_chksum(cksum,udphdr,udplen);
275 cksum = ~cksum;
276 if (cksum == 0) cksum = 0xFFFF;
277 udphdr[6] = (cksum >> 8) & 0xFF;
278 udphdr[7] = (cksum & 0xFF);
281 * Off it goes!
284 _ip_send(info->ui_ipinfo,buf,dest,IPPROTO_UDP);
286 return 0;
289 /* *********************************************************************
290 * _udp_bind(info,s,port)
292 * Bind a UDP socket to a particular port number. Basically,
293 * all this means is we set the "source" port number.
295 * Input parameters:
296 * info - UDP stack information
297 * s - an open UDP socket (from _udp_open)
298 * port - port number to assign to the UDP socket
300 * Return value:
301 * 0 if ok, else error code
302 ********************************************************************* */
304 int _udp_bind(udp_info_t *info,int s,uint16_t port)
306 udp_port_t *udp = &(info->ui_ports[s]);
308 if (_udp_find_port(info,port)) return CFE_ERR_ALREADYBOUND;
310 udp->up_srcport = port;
312 return 0;
316 /* *********************************************************************
317 * _udp_connect(info,s,port)
319 * "connect" a UDP socket to a particular port number. Basically,
320 * this just sets the "destination" port number. It is used for
321 * protocols like TFTP where the destination port number changes
322 * after the port is open.
324 * Input parameters:
325 * info - UDP stack information
326 * s - an open UDP socket (from _udp_open)
327 * port - port number to assign to the UDP socket
329 * Return value:
330 * 0 if ok
331 * else error code
332 ********************************************************************* */
334 int _udp_connect(udp_info_t *info,int s,uint16_t port)
336 udp_port_t *udp = &(info->ui_ports[s]);
338 udp->up_destport = port;
340 return 0;
343 /* *********************************************************************
344 * _udp_rx_callback(ref,buf,destaddr,srcaddr)
346 * Receive callback routine from the IP layer. When an IP
347 * packet of protocol type "UDP" is received, this routine gets
348 * called.
350 * Input parameters:
351 * ref - reference data (pointer to our UDP stack info)
352 * buf - the ebuf, currently pointing at the UDP header
353 * destaddr - the destination IP address (usually our IP address)
354 * srcaddr - the source IP address
356 * Return value:
357 * ETH_KEEP to keep (not deallocate) the packet
358 * ETH_DROP to deallocate the packet.
359 ********************************************************************* */
361 static int _udp_rx_callback(void *ref,ebuf_t *buf,uint8_t *destaddr,uint8_t *srcaddr)
363 uint8_t pseudoheader[12];
364 int udplen;
365 uint16_t calccksum;
366 uint16_t origcksum;
367 uint8_t *udphdr;
368 uint16_t srcport;
369 uint16_t dstport;
370 uint16_t udplen2;
371 udp_port_t *udp;
372 udp_info_t *info = (udp_info_t *) ref;
377 * get a pointer to the UDP header
380 udplen = ebuf_length(buf);
381 udphdr = ebuf_ptr(buf);
384 * see if we are checking checksums (cksum field != 0)
387 if ((udphdr[6] | udphdr[7]) != 0) {
390 * construct the pseudoheader for the cksum calculation
393 memcpy(&pseudoheader[0],srcaddr,IP_ADDR_LEN);
394 memcpy(&pseudoheader[4],destaddr,IP_ADDR_LEN);
395 pseudoheader[8] = 0;
396 pseudoheader[9] = IPPROTO_UDP;
397 pseudoheader[10] = (udplen >> 8) & 0xFF;
398 pseudoheader[11] = (udplen & 0xFF);
400 origcksum = ((uint16_t) udphdr[6] << 8) | (uint16_t) udphdr[7];
401 udphdr[6] = udphdr[7] = 0;
403 calccksum = ip_chksum(0,pseudoheader,sizeof(pseudoheader));
404 calccksum = ip_chksum(calccksum,udphdr,udplen);
405 if (calccksum != 0xffff) {
406 calccksum = ~calccksum;
409 if (calccksum != origcksum) {
410 return ETH_DROP;
414 /* Read the other UDP header fields from the packet */
416 ebuf_get_u16_be(buf,srcport);
417 ebuf_get_u16_be(buf,dstport);
418 ebuf_get_u16_be(buf,udplen2);
419 ebuf_skip(buf,2);
422 * It's no good if the lengths don't match. The length
423 * reported by IP should be the length in the UDP header + 8
426 if (udplen2 != (uint16_t) udplen) {
427 return ETH_DROP;
431 * Okay, start looking for a matching port
434 udp = _udp_find_port(info,dstport);
435 if (!udp) {
436 return ETH_DROP; /* drop packet if no matching port */
439 buf->eb_usrdata = (int) srcport;
440 buf->eb_usrptr = srcaddr;
443 * Drop packet if queue is full
446 if (q_count(&(udp->up_rxqueue)) >= udp->up_maxqueue) {
447 return ETH_DROP;
451 * Add to receive queue
454 ebuf_setlength(buf,udplen2-UDP_HDR_LENGTH);
455 q_enqueue(&(udp->up_rxqueue),(queue_t *) buf);
457 return ETH_KEEP;
461 /* *********************************************************************
462 * _udp_recv(info,s)
464 * Receive a packet from the specified UDP socket.
466 * Input parameters:
467 * info - UDP stack information
468 * s - an open UDP socket handle (from _udp_open)
470 * Return value:
471 * an ebuf, or NULL if no packets have been received.
472 ********************************************************************* */
474 ebuf_t *_udp_recv(udp_info_t *info,int s)
476 ebuf_t *buf;
477 udp_port_t *udp = &(info->ui_ports[s]);
479 buf = (ebuf_t *) q_deqnext(&(udp->up_rxqueue));
481 return buf;
485 /* *********************************************************************
486 * _udp_init(ipi,ref)
488 * Initialize the UDP module. This routine registers our
489 * protocol with the IP layer.
491 * Input parameters:
492 * ipi - IP information (including our IP address, etc.)
493 * ref - reference data, stored in our UDP stack structure
495 * Return value:
496 * udp_info_t (allocated) or NULL if something went wrong.
497 ********************************************************************* */
499 udp_info_t *_udp_init(ip_info_t *ipi,void *ref)
501 udp_info_t *info;
502 udp_port_t *udp;
503 int idx;
506 * Allocate some memory for our structure
509 info = KMALLOC(sizeof(udp_info_t),0);
511 if (info == NULL) return NULL;
513 memset(info,0,sizeof(udp_info_t));
516 * Fill in the fields.
519 info->ui_ref = ref;
520 info->ui_ipinfo = ipi;
521 udp = info->ui_ports;
522 for (idx = 0; idx < UDP_MAX_PORTS; idx++) {
523 udp->up_inuse = FALSE;
524 q_init(&(udp->up_rxqueue));
525 udp++;
529 * Register our protocol with IP
532 _ip_register(ipi,IPPROTO_UDP,_udp_rx_callback,info);
534 return info;
538 /* *********************************************************************
539 * _udp_uninit(info)
541 * Uninitialize the UDP module, deregistering ourselves from the
542 * IP layer.
544 * Input parameters:
545 * info - UDP stack information
547 * Return value:
548 * nothing
549 ********************************************************************* */
551 void _udp_uninit(udp_info_t *info)
553 int idx;
554 udp_port_t *udp;
555 ebuf_t *buf;
558 * Unregister from IP
561 _ip_deregister(info->ui_ipinfo,IPPROTO_UDP);
564 * Free up any packets that were waiting
567 udp = info->ui_ports;
568 for (idx = 0; idx < UDP_MAX_PORTS; idx++) {
569 if (udp->up_inuse) {
570 while ((buf = (ebuf_t *) q_deqnext(&(udp->up_rxqueue)))) {
571 _ip_free(info->ui_ipinfo,buf);
574 udp++;
578 * Free the stack info
581 KFREE(info);
584 /* *********************************************************************
585 * _udp_alloc(info)
587 * Allocate a buffer for use with UDP. This routine obtains an
588 * ebuf and adjusts its header to include room for the UDP
589 * header.
591 * Input parameters:
592 * info - UDP stack information
594 * Return value:
595 * ebuf, or NULL if there are none left
596 ********************************************************************* */
598 ebuf_t *_udp_alloc(udp_info_t *info)
600 ebuf_t *buf;
603 * Get an ebuf
606 buf = _ip_alloc(info->ui_ipinfo);
608 if (!buf) return NULL;
611 * make room for the udp header
614 ebuf_seek(buf,UDP_HDR_LENGTH);
615 ebuf_setlength(buf,0);
617 return buf;
620 /* *********************************************************************
621 * _udp_free(info,buf)
623 * Return an ebuf to the pool.
625 * Input parameters:
626 * info - UDP stack info
627 * buf - an ebuf
629 * Return value:
630 * nothing
631 ********************************************************************* */
633 void _udp_free(udp_info_t *info,ebuf_t *buf)
635 _ip_free(info->ui_ipinfo,buf);