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