]> git.kernelconcepts.de Git - karo-tx-redboot.git/blob - packages/redboot/v2_0/src/net/ip.c
unified MX27, MX25, MX37 trees
[karo-tx-redboot.git] / packages / redboot / v2_0 / src / net / ip.c
1 //==========================================================================
2 //
3 //      net/ip.c
4 //
5 //      Stand-alone IP networking support for RedBoot
6 //
7 //==========================================================================
8 //####ECOSGPLCOPYRIGHTBEGIN####
9 // -------------------------------------------
10 // This file is part of eCos, the Embedded Configurable Operating System.
11 // Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
12 // Copyright (C) 2002 Gary Thomas
13 //
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.
17 //
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
21 // for more details.
22 //
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.
26 //
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.
33 //
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.
36 //
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####
43 //
44 // Author(s):    gthomas
45 // Contributors: gthomas
46 // Date:         2000-07-14
47 // Purpose:      
48 // Description:  
49 //              
50 // This code is part of RedBoot (tm).
51 //
52 //####DESCRIPTIONEND####
53 //
54 //==========================================================================
55
56 #include <net/net.h>
57
58 #ifndef CYGDAT_REDBOOT_DEFAULT_IP_ADDR
59 # define CYGDAT_REDBOOT_DEFAULT_IP_ADDR 0, 0, 0, 0
60 #endif
61 #ifndef CYGDAT_REDBOOT_DEFAULT_IP_ADDR_MASK
62 # define CYGDAT_REDBOOT_DEFAULT_IP_ADDR_MASK 255, 255, 255, 0
63 #endif
64 #ifndef CYGDAT_REDBOOT_DEFAULT_GATEWAY_IP_ADDR
65 # define CYGDAT_REDBOOT_DEFAULT_GATEWAY_IP_ADDR 0, 0, 0, 0
66 #endif
67
68 ip_addr_t __local_ip_addr = { CYGDAT_REDBOOT_DEFAULT_IP_ADDR };
69 #ifdef CYGSEM_REDBOOT_NETWORKING_USE_GATEWAY
70 ip_addr_t __local_ip_mask = { CYGDAT_REDBOOT_DEFAULT_IP_ADDR_MASK };
71 ip_addr_t __local_ip_gate = { CYGDAT_REDBOOT_DEFAULT_GATEWAY_IP_ADDR };
72 #endif
73
74 static word ip_ident;
75
76 #ifdef CYGSEM_REDBOOT_NETWORKING_USE_GATEWAY
77 /*
78  * See if an address is on the local network
79  */
80 int 
81 __ip_addr_local(ip_addr_t *addr)
82 {
83   return !(
84            ((__local_ip_addr[0] ^ (*addr)[0]) & __local_ip_mask[0]) |
85            ((__local_ip_addr[1] ^ (*addr)[1]) & __local_ip_mask[1]) |
86            ((__local_ip_addr[2] ^ (*addr)[2]) & __local_ip_mask[2]) |
87            ((__local_ip_addr[3] ^ (*addr)[3]) & __local_ip_mask[3]));
88 }
89 #endif
90
91 /*
92  * Match given IP address to our address.
93  * Check for broadcast matches as well.
94  */
95 static int
96 ip_addr_match(ip_addr_t addr)
97 {
98     if (addr[0] == 255 && addr[1] == 255 && addr[2] == 255 && addr[3] == 255)
99         return 1;
100
101     if (!memcmp(addr, __local_ip_addr, sizeof(ip_addr_t)))
102         return 1;
103
104     /*
105      * Consider it an address match if we haven't gotten our IP address yet.
106      * Some DHCP servers will address IP packets to the assigned address
107      * instead of a IP broadcast address.
108      */
109     if (__local_ip_addr[0] == 0 && __local_ip_addr[1] == 0 &&
110         __local_ip_addr[2] == 0 && __local_ip_addr[3] == 0)
111         return 1;
112
113     return 0;
114 }
115
116
117 extern void __tcp_handler(pktbuf_t *, ip_route_t *);
118
119 /*
120  * Handle IP packets coming from the polled ethernet interface.
121  */
122 void
123 __ip_handler(pktbuf_t *pkt, enet_addr_t *src_enet_addr)
124 {
125     ip_header_t *ip = pkt->ip_hdr;
126     ip_route_t  r;
127     int         hdr_bytes;
128
129     /* first make sure its ours and has a good checksum. */
130     if (!ip_addr_match(ip->destination) ||
131         __sum((word *)ip, ip->hdr_len << 2, 0) != 0) {
132         __pktbuf_free(pkt);
133         return;
134     }
135
136     memcpy(r.ip_addr, ip->source, sizeof(ip_addr_t));
137     memcpy(r.enet_addr, src_enet_addr, sizeof(enet_addr_t));
138
139     hdr_bytes = ip->hdr_len << 2;
140     pkt->pkt_bytes = ntohs(ip->length) - hdr_bytes;
141
142     switch (ip->protocol) {
143
144 #if NET_SUPPORT_ICMP
145       case IP_PROTO_ICMP:
146         pkt->icmp_hdr = (icmp_header_t *)(((char *)ip) + hdr_bytes);
147         __icmp_handler(pkt, &r);
148         break;
149 #endif
150
151 #if NET_SUPPORT_TCP
152       case IP_PROTO_TCP:
153         pkt->tcp_hdr = (tcp_header_t *)(((char *)ip) + hdr_bytes);
154         __tcp_handler(pkt, &r);
155         break;
156 #endif
157
158 #if NET_SUPPORT_UDP
159       case IP_PROTO_UDP:
160         pkt->udp_hdr = (udp_header_t *)(((char *)ip) + hdr_bytes);
161         __udp_handler(pkt, &r);
162         break;
163 #endif
164
165       default:
166         __pktbuf_free(pkt);
167         break;
168     }
169 }
170
171
172 /*
173  * Send an IP packet.
174  *
175  * The IP data field should contain pkt->pkt_bytes of data.
176  * pkt->[udp|tcp|icmp]_hdr points to the IP data field. Any
177  * IP options are assumed to be already in place in the IP
178  * options field.
179  */
180 int
181 __ip_send(pktbuf_t *pkt, int protocol, ip_route_t *dest)
182 {
183     ip_header_t *ip = pkt->ip_hdr;
184     int         hdr_bytes;
185     unsigned short cksum;
186     
187     /*
188      * Figure out header length. The use udp_hdr is
189      * somewhat arbitrary, but works because it is
190      * a union with other IP protocol headers.
191      */
192     hdr_bytes = (((char *)pkt->udp_hdr) - ((char *)ip));
193
194     pkt->pkt_bytes += hdr_bytes;
195
196     ip->version = 4;
197     ip->hdr_len = hdr_bytes >> 2;
198     ip->tos = 0;
199     ip->length = htons(pkt->pkt_bytes);
200     ip->ident = htons(ip_ident);
201     ip_ident++;
202     ip->fragment = 0;
203     ip->ttl = 255;
204     ip->ttl = 64;
205     ip->protocol = protocol;
206     ip->checksum = 0;
207     memcpy(ip->source, __local_ip_addr, sizeof(ip_addr_t));
208     memcpy(ip->destination, dest->ip_addr, sizeof(ip_addr_t));
209     cksum = __sum((word *)ip, hdr_bytes, 0);
210     ip->checksum = htons(cksum);
211
212     __enet_send(pkt, &dest->enet_addr, ETH_TYPE_IP);    
213     return 0;
214 }
215
216