1/*  *********************************************************************
2    *  Broadcom Common Firmware Environment (CFE)
3    *
4    *  Top-level API to network			File: net_api.c
5    *
6    *  This routine contains the highest-level API to the network
7    *  routines.  The global handle to the network state is right here.
8    *
9    *  Author:  Mitch Lichtenberg (mpl@broadcom.com)
10    *
11    *********************************************************************
12    *
13    *  Copyright 2000,2001,2002,2003
14    *  Broadcom Corporation. All rights reserved.
15    *
16    *  This software is furnished under license and may be used and
17    *  copied only in accordance with the following terms and
18    *  conditions.  Subject to these conditions, you may download,
19    *  copy, install, use, modify and distribute modified or unmodified
20    *  copies of this software in source and/or binary form.  No title
21    *  or ownership is transferred hereby.
22    *
23    *  1) Any source code used, modified or distributed must reproduce
24    *     and retain this copyright notice and list of conditions
25    *     as they appear in the source file.
26    *
27    *  2) No right is granted to use any trade name, trademark, or
28    *     logo of Broadcom Corporation.  The "Broadcom Corporation"
29    *     name may not be used to endorse or promote products derived
30    *     from this software without the prior written permission of
31    *     Broadcom Corporation.
32    *
33    *  3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
34    *     IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
35    *     WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
36    *     PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
37    *     SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
38    *     PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR DIRECT, INDIRECT,
39    *     INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
40    *     (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
41    *     GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
42    *     BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
43    *     OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
44    *     TORT (INCLUDING NEGLIGENCE OR OTHERWISE), EVEN IF ADVISED OF
45    *     THE POSSIBILITY OF SUCH DAMAGE.
46    ********************************************************************* */
47
48
49#include "bsp_config.h"
50
51#include "lib_types.h"
52#include "lib_string.h"
53#include "lib_queue.h"
54#include "lib_malloc.h"
55#include "lib_printf.h"
56
57#include "cfe_iocb.h"
58#include "cfe_devfuncs.h"
59#include "cfe_ioctl.h"
60#include "cfe_timer.h"
61
62#include "cfe_error.h"
63
64#include "net_ebuf.h"
65#include "net_ether.h"
66
67#include "cfe_timer.h"
68
69#include "net_ip.h"
70#include "net_ip_internal.h"
71#include "net_api.h"
72
73#include "env_subr.h"
74
75#if CFG_TCP
76#include "net_tcp.h"
77#endif
78
79
80/*  *********************************************************************
81    *  Structures
82    ********************************************************************* */
83
84/*
85 * Net context.  All the soft context structures of all the
86 * layers of the network stack are bundled here.  There's only one
87 * of these in the system when the network is active.
88 */
89
90typedef struct net_ctx_s {
91    /* Global info */
92    int64_t timer;
93
94    /* device name */
95    char *devname;
96
97    /* Run-time info for IP interface */
98    ip_info_t *ipinfo;
99
100    /* Info for Ethernet interface */
101    ether_info_t *ethinfo;
102
103    /* Info specific to UDP */
104    udp_info_t *udpinfo;
105
106    /* Info specific to ICMP */
107    icmp_info_t *icmpinfo;
108
109#if CFG_TCP
110    /* Info specific to TCP */
111    tcp_info_t *tcpinfo;
112#endif
113} net_ctx_t;
114
115
116/*  *********************************************************************
117    *  Globals
118    ********************************************************************* */
119
120static net_ctx_t *netctx = NULL;
121
122
123/*  *********************************************************************
124    *  UDP INTERFACE
125    ********************************************************************* */
126
127/*  *********************************************************************
128    *  udp_alloc()
129    *
130    *  Allocate an ebuf with fields reserved for the UDP layer.
131    *
132    *  Input parameters:
133    *  	   nothing
134    *
135    *  Return value:
136    *  	   pointer to ebuf, or NULL if no EBUFs are available
137    ********************************************************************* */
138
139ebuf_t *udp_alloc(void)
140{
141    if (!netctx) return NULL;
142    return _udp_alloc(netctx->udpinfo);
143}
144
145/*  *********************************************************************
146    *  udp_free(buf)
147    *
148    *  Return an ebuf to the pool.  The ebuf was presumably allocated
149    *  via udp_alloc() first.
150    *
151    *  Input parameters:
152    *  	   buf - ebuf to return to the pool
153    *
154    *  Return value:
155    *  	   nothing
156    ********************************************************************* */
157void udp_free(ebuf_t *buf)
158{
159    if (!netctx) return;
160    _udp_free(netctx->udpinfo,buf);
161}
162
163/*  *********************************************************************
164    *  udp_socket(port)
165    *
166    *  Open a UDP socket.  Once open, datagrams sent on the socket will
167    *  go to the specified port number.  You can change the port later
168    *  using the "udp_connect" function.
169    *
170    *  Input parameters:
171    *  	   port - port number
172    *
173    *  Return value:
174    *  	   UDP port handle, or -1 if no ports are available.
175    ********************************************************************* */
176
177int udp_socket(uint16_t port)
178{
179    if (!netctx) return -1;
180
181    return _udp_socket(netctx->udpinfo,port);
182}
183
184/*  *********************************************************************
185    *  udp_close(sock)
186    *
187    *  Close a udp socket.  You pass this handle returned from a previous
188    *  call to udp_open.
189    *
190    *  Input parameters:
191    *  	   handle - UDP port handle, from udp_open()
192    *
193    *  Return value:
194    *  	   nothing
195    ********************************************************************* */
196
197void udp_close(int portnum)
198{
199    if (!netctx) return;
200
201    _udp_close(netctx->udpinfo,portnum);
202}
203
204
205/*  *********************************************************************
206    *  udp_send(s,buf,dest)
207    *
208    *  Send a datagram to the specified destination address.  The
209    *  source and destination UDP port numbers are taken from the
210    *  values passed to earlier calls to udp_open, udp_bind, and
211    *  udp_connect.
212    *
213    *  Input parameters:
214    *  	   s - socket handle, from udp_open
215    *  	   buf - ebuf to send (allocated via udp_alloc)
216    *  	   dest - pointer to 4-byte destination IP address
217    *
218    *  Return value:
219    *  	   0 if ok
220    *  	   <0 if an error occured.
221    ********************************************************************* */
222
223int udp_send(int s,ebuf_t *buf,uint8_t *dest)
224{
225    if (!netctx) return -1;
226
227    return _udp_send(netctx->udpinfo,s,buf,dest);
228}
229
230/*  *********************************************************************
231    *  udp_bind(s,port)
232    *
233    *  Re-"bind" the specified udp socket to a new source port.
234    *  This changes the source port number that will be transmitted
235    *  in subsequent calls to udp_send()
236    *
237    *  Input parameters:
238    *  	   s - socket handle
239    *  	   port - new port number
240    *
241    *  Return value:
242    *      0 if ok, else error code
243    ********************************************************************* */
244
245int udp_bind(int s,uint16_t port)
246{
247    if (!netctx) return -1;
248
249    return _udp_bind(netctx->udpinfo,s,port);
250}
251
252
253/*  *********************************************************************
254    *  udp_connect(s,port)
255    *
256    *  Set the port number to be used in the destination port field
257    *  for subsequent calls to udp_send().
258    *
259    *  Input parameters:
260    *  	   s - udp socket handle
261    *  	   port - new destination port number
262    *
263    *  Return value:
264    *  	   0 if ok, else error code
265    ********************************************************************* */
266
267int udp_connect(int s,uint16_t port)
268{
269    if (!netctx) return -1;
270
271    return _udp_connect(netctx->udpinfo,s,port);
272}
273
274/*  *********************************************************************
275    *  udp_recv(s)
276    *
277    *  Return the next packet from the receive queue for this port.
278    *  If no packets are available, NULL is returned.
279    *
280    *  Input parameters:
281    *  	   s - udp port handle
282    *
283    *  Return value:
284    *  	   ebuf (if a packet is available)
285    *  	   NULL (no packet available)
286    ********************************************************************* */
287
288ebuf_t *udp_recv(int s)
289{
290    if (!netctx) return NULL;
291
292    return _udp_recv(netctx->udpinfo,s);
293}
294
295
296/*  *********************************************************************
297    *  udp_recv_with_timeout(s,ticks)
298    *
299    *  Return the next packet from the receive queue for this socket,
300    *  waiting for one to arrive if there are none available.
301    *
302    *  Input parameters:
303    *  	   s - udp socket handle
304    *  	   ticks - number of ticks to wait
305    *
306    *  Return value:
307    *  	   ebuf (if a packet is available)
308    *  	   NULL (no packet available after timeout)
309    ********************************************************************* */
310
311ebuf_t *udp_recv_with_timeout(int s,int ticks)
312{
313    ebuf_t *buf = NULL;
314    int64_t timer;
315
316    if (!netctx) return NULL;
317
318    TIMER_SET(timer,ticks);
319
320    while (!TIMER_EXPIRED(timer)) {
321	POLL();
322	buf = _udp_recv(netctx->udpinfo,s);
323	if (buf) break;
324	}
325
326    return buf;
327}
328
329
330
331#if CFG_TCP
332/*  *********************************************************************
333    *  TCP INTERFACE
334    ********************************************************************* */
335
336
337/*  *********************************************************************
338    *  tcp_socket()
339    *
340    *  Create a new TCP port.
341    *
342    *  Input parameters:
343    *  	   nothing.
344    *
345    *  Return value:
346    *  	   TCP port handle, or <0 if no ports are available.
347    ********************************************************************* */
348
349int tcp_socket(void)
350{
351    if (!netctx) return -1;
352
353    return _tcp_socket(netctx->tcpinfo);
354}
355
356/*  *********************************************************************
357    *  tcp_connect(handle,dest,port)
358    *
359    *  Connect to a remote TCP destination.
360    *
361    *  Input parameters:
362    *  	   handle - returned from tcp_create
363    *  	   dest - destination IP address
364    *  	   port - destination port number
365    *
366    *  Return value:
367    *  	   0 if ok
368    *  	   else error code
369    ********************************************************************* */
370
371int tcp_connect(int s,uint8_t *dest,uint16_t port)
372{
373    int res;
374    unsigned int flags;
375    int connflag;
376
377    if (!netctx) return -1;
378
379    /*
380     * Get socket's blocking status
381     * If nonblocking, just call the tcp stack
382     * and return what it returns.
383     */
384
385    res = _tcp_getflags(netctx->tcpinfo,s,&flags);
386    if (res < 0) return res;
387
388    if (flags & TCPFLG_NBIO) {
389	return _tcp_connect(netctx->tcpinfo,s,dest,port);
390	}
391
392    /*
393     * Otherwise, call connect and poll till the status
394     * changes.  We want to see a transition to the
395     * CONNECTED state, so we loop while we see "CONNECTING"
396     * and return a status based on what it changes to.
397     */
398
399    res = _tcp_connect(netctx->tcpinfo,s,dest,port);
400    if (res < 0) return res;
401    connflag = TCPSTATUS_NOTCONN;
402
403    for (;;) {
404	POLL();
405
406	res = _tcp_status(netctx->tcpinfo,s,&connflag,NULL,NULL);
407	if (res < 0) break;
408
409	if (connflag == TCPSTATUS_CONNECTING) continue;
410	break;
411	}
412
413    if (connflag != TCPSTATUS_CONNECTED) return CFE_ERR_NOTCONN;
414
415    return res;
416}
417
418/*  *********************************************************************
419    *  tcp_close(s)
420    *
421    *  Disconnect a connection (cleanly)
422    *
423    *  Input parameters:
424    *  	   s - handle from tcp_create
425    *
426    *  Return value:
427    *  	   0 if ok
428    *  	   else error
429    ********************************************************************* */
430
431int tcp_close(int s)
432{
433    if (!netctx) return -1;
434
435    return _tcp_close(netctx->tcpinfo,s);
436}
437
438
439
440/*  *********************************************************************
441    *  tcp_send(s,buf,len)
442    *
443    *  Send a buffer to the other TCP, buffering as much data as
444    *  will fit in the send buffer.
445    *
446    *  Input parameters:
447    *  	   s - port handle, from tcp_open
448    *  	   buf - buffer pointer
449    *  	   len - length of buffer to send
450    *
451    *  Return value:
452    *  	   >=0 if ok (number of bytes sent)
453    *  	   <0 if an error occured.
454    ********************************************************************* */
455
456int tcp_send(int s,uint8_t *buf,int len)
457{
458    int flags;
459    int res;
460    int total = 0;
461
462    if (!netctx) return -1;
463
464    /*
465     * Get socket's blocking status
466     * If nonblocking, just call the tcp stack
467     * and return what it returns.
468     */
469
470    res = _tcp_getflags(netctx->tcpinfo,s,&flags);
471    if (res < 0) return res;
472
473    if (flags & TCPFLG_NBIO) {
474	return _tcp_send(netctx->tcpinfo,s,buf,len);
475	}
476
477    /*
478     * The first time we'll check the return code for an
479     * error so we can pass up the failure.
480     */
481
482    res = _tcp_send(netctx->tcpinfo,s,buf,len);
483    if (res < 0) return res;
484
485    buf += res;
486    len -= res;
487    total += res;
488
489    while (len > 0) {
490	/*
491	 * Give the TCP stack and devices a chance to run
492	 */
493
494	POLL();
495
496	/*
497	 * Try to send some more.  If we get an error, get out.
498	 * otherwise, keep going till all the data is gone.
499	 */
500
501	res = _tcp_send(netctx->tcpinfo,s,buf,len);
502	if (res < 0) break;
503	buf += res;
504	len -= res;
505	total += res;
506	}
507
508    /*
509     * If we sent nothing and have an error, return the error.
510     * Otherwise return the amount of data we sent.
511     */
512    if ((total == 0) && (res < 0)) return res;
513    else return total;
514}
515
516/*  *********************************************************************
517    *  tcp_recv(s,buf,len)
518    *
519    *  Receive data from the remote TCP session
520    *
521    *  Input parameters:
522    *  	   s - port handle, from tcp_open
523    *  	   buf - buffer pointer
524    *  	   len - length of buffer to send
525    *
526    *  Return value:
527    *  	   >=0 if ok (number of bytes received)
528    *  	   <0 if an error occured.
529    ********************************************************************* */
530
531int tcp_recv(int s,uint8_t *buf,int len)
532{
533    int flags;
534    int res;
535    int total = 0;
536
537    if (!netctx) return -1;
538
539    /*
540     * Get socket's blocking status
541     * If nonblocking, just call the tcp stack
542     * and return what it returns.
543     */
544
545    res = _tcp_getflags(netctx->tcpinfo,s,&flags);
546    if (res < 0) return res;
547
548    if (flags & TCPFLG_NBIO) {
549	return _tcp_recv(netctx->tcpinfo,s,buf,len);
550	}
551
552    /*
553     * The first time we'll check the return code for an
554     * error so we can pass up the failure.
555     */
556
557    res = _tcp_recv(netctx->tcpinfo,s,buf,len);
558    if (res < 0) return res;
559
560    buf += res;
561    len -= res;
562    total += res;
563
564    while (len > 0) {
565	/*
566	 * Give the TCP stack and devices a chance to run
567	 */
568
569	POLL();
570
571	/*
572	 * Try to receive some more.  If we get an error, get out.
573	 * otherwise, keep going till all the data is gone.
574	 */
575
576	res = _tcp_recv(netctx->tcpinfo,s,buf,len);
577	if (res < 0) break;
578
579	if (res == 0) {
580	    _tcp_status(netctx->tcpinfo,s,&flags,NULL,NULL);
581	    if (flags != TCPSTATUS_CONNECTED) {
582		res = CFE_ERR_NOTCONN;
583		break;
584		}
585	    }
586
587	buf += res;
588	len -= res;
589	total += res;
590	}
591
592    /*
593     * If we sent received and have an error, return the error.
594     * Otherwise return the amount of data we sent.
595     */
596    if ((total == 0) && (res < 0)) return res;
597    else return total;
598
599}
600
601/*  *********************************************************************
602    *  tcp_bind(s,port)
603    *
604    *  Re-"bind" the specified tcp port handle to a new source port.
605    *
606    *  Used for listening sockets.
607    *
608    *  Input parameters:
609    *  	   s - port handle
610    *  	   port - new port number
611    *
612    *  Return value:
613    *      0 if ok, else error code
614    ********************************************************************* */
615
616int tcp_bind(int s,uint16_t port)
617{
618    if (!netctx) return -1;
619
620    return _tcp_bind(netctx->tcpinfo,s,port);
621}
622
623/*  *********************************************************************
624    *  tcp_peeraddr(s,addr,port)
625    *
626    *  Return the address of the remote peer.
627    *
628    *  Input parameters:
629    *  	   s - port handle
630    *      addr - points to 4-byte buffer to receive IP address
631    *  	   port - points to uint16 to receive port number
632    *
633    *  Return value:
634    *      0 if ok, else error code
635    ********************************************************************* */
636
637int tcp_peeraddr(int s,uint8_t *addr,uint16_t *port)
638{
639    if (!netctx) return -1;
640
641    return _tcp_peeraddr(netctx->tcpinfo,s,addr,port);
642}
643
644/*  *********************************************************************
645    *  tcp_setflags(s,addr,flags)
646    *
647    *  Set per-socket flags (nodelay, etc.)
648    *
649    *  Input parameters:
650    *  	   s - port handle
651    *      flags - flags for this socket
652    *
653    *  Return value:
654    *      0 if ok, else error code
655    ********************************************************************* */
656
657int tcp_setflags(int s,unsigned int flags)
658{
659    if (!netctx) return -1;
660
661    return _tcp_setflags(netctx->tcpinfo,s,flags);
662}
663
664/*  *********************************************************************
665    *  tcp_getflags(s,addr,flags)
666    *
667    *  Get per-socket flags (nodelay, etc.)
668    *
669    *  Input parameters:
670    *  	   s - port handle
671    *      flags - flags for this socket
672    *
673    *  Return value:
674    *      0 if ok, else error code
675    ********************************************************************* */
676
677int tcp_getflags(int s,unsigned int *flags)
678{
679    if (!netctx) return -1;
680
681    return _tcp_getflags(netctx->tcpinfo,s,flags);
682}
683
684
685/*  *********************************************************************
686    *  tcp_listen(s)
687    *
688    *  Set the socket into "listen" mode.
689    *
690    *  Input parameters:
691    *  	   s - port handle
692    *	   port - port # to listen on
693    *
694    *  Return value:
695    *  	   0 if ok
696    *  	   else error
697    ********************************************************************* */
698
699int tcp_listen(int s,uint16_t port)
700{
701    if (!netctx) return -1;
702
703    return _tcp_listen(netctx->tcpinfo,s,port);
704}
705
706/*  *********************************************************************
707    *  tcp_status(s,connflag,rxready,rxeof)
708    *
709    *  Return the TCP connection's status
710    *
711    *  Input parameters:
712    *  	   s - port handle
713    *      connflag - points to flag to receive connected status
714    *      rxready - returns # of bytes ready to receive
715    *	   rxeof - returns TRUE if we've been FINed.
716    *
717    *  Return value:
718    *  	   0 if ok
719    *  	   else error
720    ********************************************************************* */
721
722int tcp_status(int s,int *connflag,int *rxready,int *rxeof)
723{
724    if (!netctx) return -1;
725
726    return _tcp_status(netctx->tcpinfo,s,connflag,rxready,rxeof);
727}
728
729/*  *********************************************************************
730    *  tcp_debug(s,arg)
731    *
732    *  Call the debug routine in the tcp stack.
733    *
734    *  Input parameters:
735    *  	   s - socket handle
736    *  	   arg - passed to debug routine
737    *
738    *  Return value:
739    *  	   return value from debug routine
740    ********************************************************************* */
741
742int tcp_debug(int s,int arg)
743{
744    if (!netctx) return -1;
745    return _tcp_debug(netctx->tcpinfo,s,arg);
746}
747
748#endif
749
750/*  *********************************************************************
751    *  ARP FUNCTIONS
752    ********************************************************************* */
753
754
755/*  *********************************************************************
756    *  arp_add(destip,desthw)
757    *
758    *  Add a permanent entry to the ARP table.  This entry will
759    *  persist until deleted or the interface is deactivated.
760    *  This may cause a stale entry to be deleted if the table is full
761    *
762    *  Input parameters:
763    *  	   destip - pointer to 4-byte destination IP address
764    *  	   desthw - pointer to 6-byte destination hardware address
765    *
766    *  Return value:
767    *  	   nothing
768    ********************************************************************* */
769
770void arp_add(uint8_t *destip,uint8_t *desthw)
771{
772    if (netctx) _arp_add(netctx->ipinfo,destip,desthw);
773}
774
775/*  *********************************************************************
776    *  arp_lookup(destip)
777    *
778    *  Look up the hardware address for an IP address.
779    *
780    *  Input parameters:
781    *  	   destip - pointer to 4-byte IP address
782    *
783    *  Return value:
784    *  	   pointer to 6-byte hardware address, or NULL if there are
785    *  	   no matching entries in the table.
786    ********************************************************************* */
787
788uint8_t *arp_lookup(uint8_t *destip)
789{
790    if (!netctx) return NULL;
791    return _arp_lookup(netctx->ipinfo,destip);
792}
793
794
795/*  *********************************************************************
796    *  arp_enumerate(entrynum,ipaddr,hwaddr)
797    *
798    *  Return an entry from the ARP table.
799    *
800    *  Input parameters:
801    *  	   entrynum - entry number to return, starting with zero
802    *  	   ipaddr - pointer to 4 bytes to receive IP address
803    *  	   hwaddr - pointer to 6 bytes to receive hardware address
804    *
805    *  Return value:
806    *  	   0 if ok
807    *  	   else error code
808    ********************************************************************* */
809
810int arp_enumerate(int entrynum,uint8_t *ipaddr,uint8_t *hwaddr)
811{
812    if (!netctx) return -1;
813    return _arp_enumerate(netctx->ipinfo,entrynum,ipaddr,hwaddr);
814}
815
816/*  *********************************************************************
817    *  arp_delete(ipaddr)
818    *
819    *  Delete an entry from the ARP table.
820    *
821    *  Input parameters:
822    *  	   ipaddr - pointer to 4-byte IP address
823    *
824    *  Return value:
825    *  	   0 if ok
826    *  	   else error code
827    ********************************************************************* */
828
829int arp_delete(uint8_t *ipaddr)
830{
831    if (!netctx) return -1;
832    return _arp_delete(netctx->ipinfo,ipaddr);
833}
834
835/*  *********************************************************************
836    *  ICMP FUNCTIONS
837    ********************************************************************* */
838
839/*  *********************************************************************
840    *  icmp_ping(dest,seq,len)
841    *
842    *  Ping a remote host, transmitting the ICMP_ECHO message and
843    *  waiting for the corresponding ICMP_ECHO_REPLY.
844    *
845    *  Input parameters:
846    *  	   dest - pointer to 4-byte destination IP address
847    *  	   seq - sequence number to put in to the ICMP packet
848    *  	   len - length of data to place in ICMP packet
849    *
850    *  Return value:
851    *  	   0 if ok (remote host responded)
852    *  	   else error code
853    ********************************************************************* */
854
855int icmp_ping(uint8_t *dest,int seq,int len)
856{
857    if (!netctx) return -1;
858    return _icmp_ping(netctx->icmpinfo,dest,seq,len);
859}
860
861/*  *********************************************************************
862    *  INIT/CONFIG FUNCTIONS
863    ********************************************************************* */
864
865/*  *********************************************************************
866    *  net_getparam(param)
867    *
868    *  Return a parameter from the current IP configuration.  This is
869    *  the main call to set the IP address, netmask, gateway,
870    *  name server, host name, etc.
871    *
872    *  Input parameters:
873    *  	   param - parameter number (see net_api.h)
874    *
875    *  Return value:
876    *  	   pointer to value of parameter, or NULL if parameter
877    *  	   ID is invalid
878    ********************************************************************* */
879
880uint8_t *net_getparam(int param)
881{
882    if (!netctx) return NULL;
883    if (param == NET_DEVNAME) return (uint8_t *) netctx->devname;
884    return _ip_getparam(netctx->ipinfo,param);
885
886}
887
888/*  *********************************************************************
889    *  net_setparam(param,ptr)
890    *
891    *  Set the value of an IP configuration parameter
892    *
893    *  Input parameters:
894    *  	   param - parameter number (see net_api.h)
895    *  	   ptr - pointer to parameter's new value
896    *
897    *  Return value:
898    *  	   0 if ok
899    *  	   else error code
900    ********************************************************************* */
901
902int net_setparam(int param,uint8_t *ptr)
903{
904    if (!netctx) return NULL;
905    return _ip_setparam(netctx->ipinfo,param,ptr);
906}
907
908/*  *********************************************************************
909    *  net_poll()
910    *
911    *  Process background tasks for the network stack, maintaining
912    *  the ARP table, receive queues, etc.
913    *
914    *  Input parameters:
915    *  	   nothing
916    *
917    *  Return value:
918    *  	   nothing
919    ********************************************************************* */
920
921static void net_poll(void *arg)
922{
923    if (netctx) {
924	eth_poll(netctx->ethinfo);
925	if (TIMER_EXPIRED(netctx->timer)) {
926	    _ip_timer_tick(netctx->ipinfo);
927	    TIMER_SET(netctx->timer,CFE_HZ);
928	    }
929	}
930}
931
932/*  *********************************************************************
933    *  net_init(devname)
934    *
935    *  Initialize the network interface.  This is the main call, once
936    *  completed you should call net_setparam to set up the network
937    *  addresses and stuff.
938    *
939    *  Input parameters:
940    *  	   devname - CFE device name for network device
941    *
942    *  Return value:
943    *  	   0 if ok
944    *  	   else error code
945    ********************************************************************* */
946
947int net_init(char *devname)
948{
949    net_ctx_t *ctx;
950
951    if (netctx) net_uninit();
952
953    ctx = KMALLOC(sizeof(net_ctx_t),0);
954
955    if (!ctx) return -1;
956
957    ctx->devname = strdup(devname);
958
959    ctx->ethinfo = eth_init(devname);
960    if (ctx->ethinfo == NULL) {
961	return -1;
962	}
963
964    ctx->ipinfo = _ip_init(ctx->ethinfo);
965    if (ctx->ipinfo == NULL) {
966	eth_uninit(ctx->ethinfo);
967	return -1;
968	}
969
970    ctx->udpinfo = _udp_init(ctx->ipinfo,ctx->ipinfo);
971    if (ctx->udpinfo == NULL) {
972	_ip_uninit(ctx->ipinfo);
973	eth_uninit(ctx->ethinfo);
974	return -1;
975	}
976
977    ctx->icmpinfo = _icmp_init(ctx->ipinfo);
978    if (ctx->icmpinfo == NULL) {
979	_udp_uninit(ctx->udpinfo);
980	_ip_uninit(ctx->ipinfo);
981	eth_uninit(ctx->ethinfo);
982	return -1;
983	}
984
985    cfe_bg_add(net_poll,ctx);
986    TIMER_SET(ctx->timer,CFE_HZ);
987
988#if CFG_TCP
989    ctx->tcpinfo = _tcp_init(ctx->ipinfo,ctx->ipinfo);
990    cfe_bg_add(_tcp_poll,ctx->tcpinfo);
991#endif
992
993    netctx = ctx;
994
995    return 0;
996}
997
998
999/*  *********************************************************************
1000    *  net_uninit()
1001    *
1002    *  Uninitialize the network, deallocating all resources allocated
1003    *  to the network and closing all open device handles
1004    *
1005    *  Input parameters:
1006    *  	   nothing
1007    *
1008    *  Return value:
1009    *  	   nothing
1010    ********************************************************************* */
1011
1012void net_uninit(void)
1013{
1014    if (netctx) {
1015#if CFG_TCP
1016	cfe_bg_remove(_tcp_poll);
1017	_tcp_uninit(netctx->tcpinfo);
1018#endif
1019	TIMER_CLEAR(netctx->timer);
1020	_icmp_uninit(netctx->icmpinfo);
1021	_udp_uninit(netctx->udpinfo);
1022	_ip_uninit(netctx->ipinfo);
1023	eth_uninit(netctx->ethinfo);
1024	KFREE(netctx->devname);
1025	KFREE(netctx);
1026	netctx = NULL;
1027	cfe_bg_remove(net_poll);
1028	}
1029}
1030
1031
1032/*  *********************************************************************
1033    *  net_setnetvars()
1034    *
1035    *  Set environment variables related to the network.
1036    *
1037    *  Input parameters:
1038    *  	   nothing
1039    *
1040    *  Return value:
1041    *  	   nothing
1042    ********************************************************************* */
1043
1044void net_setnetvars(void)
1045{
1046    char *x;
1047    uint8_t *addr;
1048    char str[60];
1049
1050    /* Clear out all the environment variables */
1051    env_delenv("NET_DEVICE");
1052    env_delenv("NET_IPADDR");
1053    env_delenv("NET_NETMASK");
1054    env_delenv("NET_GATEWAY");
1055    env_delenv("NET_NAMESERVER");
1056    env_delenv("NET_DOMAIN");
1057
1058    x = (char *) net_getparam(NET_DEVNAME);
1059    if (!x) {
1060	return;
1061	}
1062
1063    x = (char *) net_getparam(NET_DEVNAME);
1064    if (x) env_setenv("NET_DEVICE",x,ENV_FLG_BUILTIN);
1065
1066    x = (char *) net_getparam(NET_DOMAIN);
1067    if (x) env_setenv("NET_DOMAIN",x,ENV_FLG_BUILTIN);
1068
1069    addr = net_getparam(NET_IPADDR);
1070    if (addr) {
1071	xsprintf(str,"%I",addr);
1072	env_setenv("NET_IPADDR",str,ENV_FLG_BUILTIN);
1073	}
1074
1075    addr = net_getparam(NET_NETMASK);
1076    if (addr) {
1077	xsprintf(str,"%I",addr);
1078	env_setenv("NET_NETMASK",str,ENV_FLG_BUILTIN);
1079	}
1080
1081    addr = net_getparam(NET_GATEWAY);
1082    if (addr) {
1083	xsprintf(str,"%I",addr);
1084	env_setenv("NET_GATEWAY",str,ENV_FLG_BUILTIN);
1085	}
1086
1087    addr = net_getparam(NET_NAMESERVER);
1088    if (addr) {
1089	xsprintf(str,"%I",addr);
1090	env_setenv("NET_NAMESERVER",str,ENV_FLG_BUILTIN);
1091	}
1092
1093}
1094
1095