1 //==========================================================================
5 // Stand-alone networking support for RedBoot
7 //==========================================================================
8 //####ECOSGPLCOPYRIGHTBEGIN####
9 // -------------------------------------------
10 // This file is part of eCos, the Embedded Configurable Operating System.
11 // Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 Red Hat, Inc.
12 // Copyright (C) 2002, 2003 Gary Thomas
14 // eCos is free software; you can redistribute it and/or modify it under
15 // the terms of the GNU General Public License as published by the Free
16 // Software Foundation; either version 2 or (at your option) any later version.
18 // eCos is distributed in the hope that it will be useful, but WITHOUT ANY
19 // WARRANTY; without even the implied warranty of MERCHANTABILITY or
20 // FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
23 // You should have received a copy of the GNU General Public License along
24 // with eCos; if not, write to the Free Software Foundation, Inc.,
25 // 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
27 // As a special exception, if other files instantiate templates or use macros
28 // or inline functions from this file, or you compile this file and link it
29 // with other works to produce a work based on this file, this file does not
30 // by itself cause the resulting work to be covered by the GNU General Public
31 // License. However the source code for this file must still be made available
32 // in accordance with section (3) of the GNU General Public License.
34 // This exception does not invalidate any other reasons why a work based on
35 // this file might be covered by the GNU General Public License.
37 // Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
38 // at http://sources.redhat.com/ecos/ecos-license/
39 // -------------------------------------------
40 //####ECOSGPLCOPYRIGHTEND####
41 //==========================================================================
42 //#####DESCRIPTIONBEGIN####
45 // Contributors: gthomas
50 // This code is part of RedBoot (tm).
52 //####DESCRIPTIONEND####
54 //==========================================================================
59 #include <pkgconf/system.h>
60 #include <pkgconf/redboot.h>
61 #include <cyg/hal/hal_arch.h>
62 #include <cyg/hal/basetype.h>
65 extern bool net_debug;
66 #ifdef CYGPKG_IO_ETH_DRIVERS
67 # include <pkgconf/io_eth_drivers.h>
68 # include <cyg/io/eth/eth_drv.h> // Logical driver interfaces
69 # ifdef CYGDBG_IO_ETH_DRIVERS_DEBUG
70 extern int cyg_io_eth_net_debug;
74 extern unsigned long do_ms_tick(void);
75 extern unsigned long get_ms_ticks(void);
76 #define MS_TICKS() get_ms_ticks()
77 #define MS_TICKS_DELAY() do_ms_tick()
79 /* #define NET_SUPPORT_RARP 1 */
80 #define NET_SUPPORT_ICMP 1
81 #define NET_SUPPORT_UDP 1
82 #define NET_SUPPORT_TCP 1
84 #if (CYG_BYTEORDER == CYG_LSBFIRST)
85 #ifndef __LITTLE_ENDIAN__
86 #define __LITTLE_ENDIAN__
88 extern unsigned long ntohl(unsigned long x);
89 extern unsigned short ntohs(unsigned short x);
95 #define htonl(x) ntohl(x)
96 #define htons(x) ntohs(x)
99 * Minimum ethernet packet length.
101 #define ETH_MIN_PKTLEN 60
102 #define ETH_MAX_PKTLEN (1540-14)
103 #define ETH_HDR_SIZE 14
105 typedef unsigned char enet_addr_t[6];
106 typedef unsigned char ip_addr_t[4];
108 typedef unsigned char octet;
109 typedef unsigned short word;
110 typedef unsigned int dword;
117 typedef struct in_addr {
118 unsigned long s_addr; // IPv4 address
121 // Socket/connection information
123 struct in_addr sin_addr;
124 unsigned short sin_port;
125 unsigned short sin_family;
132 unsigned long tv_sec;
133 unsigned long tv_usec;
137 * Simple timer support structure.
139 typedef void (*tmr_handler_t)(void *user_data);
143 * When expiration time is met or exceeded, the handler is
144 * called and the timer struct is removed from the list.
146 typedef struct _timer {
147 struct _timer *next; /* next timer in list */
148 unsigned long delay; /* expiration time relative to start time */
149 unsigned long start; /* when the timer was set */
150 tmr_handler_t handler; /* user procedure to call when timer 'fires' */
151 void *user_data; /* user pointer passed to above procedure */
159 enet_addr_t destination;
162 #define ETH_TYPE_IP 0x800
163 #define ETH_TYPE_ARP 0x806
164 #define ETH_TYPE_RARP 0x8053
165 } __attribute__((aligned(4),packed)) eth_header_t;
173 #define ARP_HW_ETHER 1
174 #define ARP_HW_EXP_ETHER 2
179 #define ARP_REQUEST 1
181 #define RARP_REQUEST 3
183 enet_addr_t sender_enet;
185 enet_addr_t target_enet;
190 #define ARP_PKT_SIZE (sizeof(arp_header_t) + ETH_HDR_SIZE)
193 * Internet Protocol header.
196 #ifdef __LITTLE_ENDIAN__
209 #define IP_PROTO_ICMP 1
210 #define IP_PROTO_TCP 6
211 #define IP_PROTO_UDP 17
214 ip_addr_t destination;
218 #define IP_PKT_SIZE (60 + ETH_HDR_SIZE)
222 * A IP<->ethernet address mapping.
226 enet_addr_t enet_addr;
249 #ifdef __LITTLE_ENDIAN__
257 #define TCP_FLAG_FIN 1
258 #define TCP_FLAG_SYN 2
259 #define TCP_FLAG_RST 4
260 #define TCP_FLAG_PSH 8
261 #define TCP_FLAG_ACK 16
262 #define TCP_FLAG_URG 32
274 #define ICMP_TYPE_ECHOREPLY 0
275 #define ICMP_TYPE_ECHOREQUEST 8
282 typedef struct _pktbuf {
283 struct _pktbuf *next;
285 ip_header_t *__iphdr; /* pointer to IP header */
286 arp_header_t *__arphdr; /* pointer to ARP header */
288 #define ip_hdr u1.__iphdr
289 #define arp_hdr u1.__arphdr
291 udp_header_t *__udphdr; /* pointer to UDP header */
292 tcp_header_t *__tcphdr; /* pointer to TCP header */
293 icmp_header_t *__icmphdr; /* pointer to ICMP header */
295 #define udp_hdr u2.__udphdr
296 #define tcp_hdr u2.__tcphdr
297 #define icmp_hdr u2.__icmphdr
298 word pkt_bytes; /* number of data bytes in buf */
299 word bufsize; /* size of buf */
301 } __attribute__((aligned(4),packed)) pktbuf_t;
304 /* protocol handler */
305 typedef void (*pkt_handler_t)(pktbuf_t *pkt, eth_header_t *eth_hdr);
308 typedef void (*icmp_handler_t)(pktbuf_t *pkt, ip_route_t *src_route);
310 typedef struct _udp_socket {
311 struct _udp_socket *next;
314 void (*handler)(struct _udp_socket *skt, void *buf, int len,
315 ip_route_t *src_route, word src_port);
319 typedef void (*udp_handler_t)(udp_socket_t *skt, void *buf, int len,
320 ip_route_t *src_route, word src_port);
323 typedef struct _tcp_socket {
324 struct _tcp_socket *next;
325 int state; /* connection state */
330 #define _ESTABLISHED 4
331 #define _CLOSE_WAIT 5
333 #define _FIN_WAIT_1 7
334 #define _FIN_WAIT_2 8
336 #define _TIME_WAIT 10
337 ip_route_t his_addr; /* address of other end of connection */
340 word data_bytes; /* number of data bytes in pkt */
341 char reuse; /* SO_REUSEADDR, no 2MSL */
343 pktbuf_t pkt; /* dedicated xmit packet */
344 pktbuf_t *rxlist; /* list of unread incoming data packets */
345 char *rxptr; /* pointer to next byte to read */
346 int rxcnt; /* bytes left in current read packet */
349 char pktbuf[ETH_MAX_PKTLEN];
353 * Address information for local device
355 #define __local_enet_addr __local_enet_sc->sc_arpcom.esa
356 extern ip_addr_t __local_ip_addr;
357 #ifdef CYGSEM_REDBOOT_NETWORKING_USE_GATEWAY
358 extern ip_addr_t __local_ip_gate;
359 extern ip_addr_t __local_ip_mask;
362 #ifdef CYGPKG_REDBOOT_NETWORKING_DNS
363 #ifdef CYGPKG_REDBOOT_NETWORKING_DNS_DHCP_DOMAIN
364 extern char __bootp_dns_domain[CYGNUM_REDBOOT_NETWORK_DNS_DOMAIN_BUFSIZE];
365 extern cyg_bool __bootp_dns_domain_set;
367 extern struct in_addr __bootp_dns_addr;
368 extern cyg_bool __bootp_dns_set;
373 * Set a timer. Caller is responsible for providing the timer_t struct.
375 extern void __timer_set(timer_t *t, unsigned long delay,
376 tmr_handler_t handler, void *user_data);
379 * Cancel the given timer.
381 extern void __timer_cancel(timer_t *t);
384 * Poll timer list for timer expirations.
386 extern void __timer_poll(void);
389 * Initialize the free list.
391 extern void __pktbuf_init(void);
394 * simple pktbuf allocation.
395 * allocates at least nbytes for packet data including ethernet header.
397 extern pktbuf_t *__pktbuf_alloc(int nbytes);
400 * return a pktbuf for reuse.
402 extern void __pktbuf_free(pktbuf_t *pkt);
405 * Dump packet structures (debug, in case of running out)
407 extern void __pktbuf_dump(void);
411 * Install handlers for ethernet packets.
412 * Returns old handler.
414 extern pkt_handler_t __eth_install_listener(int eth_type,
415 pkt_handler_t handler);
416 extern void __eth_remove_listener(int eth_type);
419 * Non-blocking poll of ethernet link. Processes all pending
422 extern void __enet_poll(void);
425 * Send an ethernet packet.
427 extern void __enet_send(pktbuf_t *pkt, enet_addr_t *dest, int eth_type);
429 #ifdef CYGSEM_REDBOOT_NETWORKING_USE_GATEWAY
431 * return true if addr is on local subnet
433 extern int __ip_addr_local(ip_addr_t *addr);
437 * Handle incoming ARP packets.
439 extern void __arp_handler(pktbuf_t *pkt);
442 * Find the ethernet address of the machine with the given
444 * Return true and fills in 'eth_addr' if successful, false
447 extern int __arp_request(ip_addr_t *ip_addr, enet_addr_t *eth_addr, int allow_self);
450 * Lookup an address from the local ARP cache. If not found,
451 * then call 'arp_request' to find it. [Basically just a cached
452 * version of 'arp_request']
454 extern int __arp_lookup(ip_addr_t *host, ip_route_t *rt);
457 * Do a one's complement checksum.
458 * The data being checksum'd is in network byte order.
459 * The returned checksum is in network byte order.
461 extern unsigned short __sum(word *w, int len, int init_sum);
464 * Compute a partial checksum for the UDP/TCP pseudo header.
466 extern int __pseudo_sum(ip_header_t *ip);
469 * Handle IP packets coming from the polled ethernet interface.
471 extern void __ip_handler(pktbuf_t *pkt, enet_addr_t *src_enet_addr);
476 * The IP data field should contain pkt->pkt_bytes of data.
477 * pkt->[udp|tcp|icmp]_hdr points to the IP data field. Any
478 * IP options are assumed to be already in place in the IP
479 * options field. Returns 0 for success.
481 extern int __ip_send(pktbuf_t *pkt, int protocol, ip_route_t *dest);
486 extern void __tcp_abort(tcp_socket_t *s, unsigned long delay);
489 * Handle incoming ICMP packets.
491 extern void __icmp_handler(pktbuf_t *pkt, ip_route_t *r);
492 extern int __icmp_install_listener(icmp_handler_t handler);
493 extern void __icmp_remove_listener(void);
496 * Handle incoming UDP packets.
498 extern void __udp_handler(pktbuf_t *pkt, ip_route_t *r);
501 * Install a handler for incoming udp packets.
502 * Caller provides the udp_socket_t structure.
503 * Returns zero if successful, -1 if socket is already used.
505 extern int __udp_install_listener(udp_socket_t *s, word port,
506 udp_handler_t handler);
509 * Remove the handler for the given socket.
511 extern void __udp_remove_listener(word port);
516 extern int __udp_send(void *buf, int len, ip_route_t *dest_ip,
517 word dest_port, word src_port);
520 extern int __udp_sendto(void *buf, int len,
521 struct sockaddr_in *server, struct sockaddr_in *local);
523 // Receive a UDP packet
524 extern int __udp_recvfrom(void *buf, int len,
525 struct sockaddr_in *from, struct sockaddr_in *local,
526 struct timeval *timeout);
529 * TCP poll function. Should be called as often as possible.
531 extern void __tcp_poll(void);
534 * Initiate outgoing connection, waiting for at most timeout seconds.
536 extern int __tcp_open(tcp_socket_t *s, struct sockaddr_in *host,
537 word port, int timeout, int *err);
540 * Set up a listening socket on the given port.
543 extern int __tcp_listen(tcp_socket_t *s, word port);
546 * SO_REUSEADDR, no 2MSL.
548 extern void __tcp_so_reuseaddr(tcp_socket_t *s);
551 * Block while waiting for all outstanding socket data to
554 extern void __tcp_drain(tcp_socket_t *s);
557 * Initiate connection close.
559 extern void __tcp_close(tcp_socket_t *s);
562 * Wait until connection has fully closed.
564 extern void __tcp_close_wait(tcp_socket_t *s);
567 * Read up to 'len' bytes without blocking.
568 * Returns number of bytes read.
569 * If connection is closed, returns -1.
571 extern int __tcp_read(tcp_socket_t *s, void *buf, int len);
574 * Write up to 'len' bytes without blocking.
575 * Returns number of bytes written.
576 * If connection is closed, returns -1.
578 extern int __tcp_write(tcp_socket_t *s, void *buf, int len);
581 * Write up to 'len' bytes, blocking until sent (not ACK'd).
582 * Returns number of bytes written.
583 * If connection is closed, returns -1.
585 extern int __tcp_write_block(tcp_socket_t *s, void *buf, int len);
589 * The following are a higher-level tcp socket interface.
593 * Initialize a socket for given port.
595 extern void __skt_init(tcp_socket_t *s, unsigned short port);
598 * Return true if socket connection is closed.
600 #define __skt_is_closed(s) (((tcp_socket_t *)(s))->state == _CLOSED)
603 * Block while listening for an incoming connection.
605 extern void __skt_wait_for_connect(tcp_socket_t *s);
608 * Read up to 'len' bytes from the given socket.
609 * Returns number of bytes read.
612 extern int __skt_read(tcp_socket_t *s, void *buf, int len);
615 * Write 'len' bytes to the given socket.
616 * Returns number of bytes written.
617 * May not write all data if connection closes.
619 extern int __skt_write(tcp_socket_t *s, void *buf, int len);
621 // Initialize the network stack - logical driver layer, etc.
622 extern void net_init(void);
624 // Test for new network I/O connections
625 extern void net_io_test(bool is_idle);
627 // Conversion between IP addresses and printable strings
628 extern bool inet_aton(const char *, in_addr_t *);
629 extern char *inet_ntoa(in_addr_t *);
631 // Network device table access
632 extern const char *net_devname(unsigned index);
633 extern int net_devindex(char *name);
636 /* #define NET_SUPPORT_RARP 1 */
637 #define NET_SUPPORT_ICMP 1
638 #define NET_SUPPORT_UDP 1
639 #define NET_SUPPORT_TCP 1
642 #define BSPLOG(x) { int old_console = start_console(); x; end_console(old_console); }
643 #define bsp_log diag_printf