root/ar5315_microredboot/microredboot/ecos/packages/redboot/current/src/net/arp.c

Revision 12368, 6.0 kB (checked in by BrainSlayer, 5 months ago)

tftp server added, supports wiligear, ubiquiti and dd-wrt webflash format

Line 
1 //==========================================================================
2 //
3 //      net/arp.c
4 //
5 //      Stand-alone ARP 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, 2003 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 static struct {
59         int waiting;
60         char *eth;
61         char *ip;
62 } arp_req;
63
64 /*
65  * Handle incoming ARP packets.
66  */
67 void __arp_handler(pktbuf_t * pkt)
68 {
69         arp_header_t *arp = pkt->arp_hdr;
70         int hw_type, protocol;
71
72         /*
73          * Only handle ethernet hardware and IP protocol.
74          */
75         protocol = ntohs(arp->protocol);
76         hw_type = ntohs(arp->hw_type);
77         if ((hw_type == ARP_HW_ETHER) && (protocol == ETH_TYPE_IP)) {
78                 /*
79                  * Handle requests for our ethernet address.
80                  */
81                 if (!memcmp(arp->target_ip, __local_ip_addr, 4)) {
82                         if (ntohs(arp->opcode) == ARP_REQUEST) {
83                                 /* format response. */
84                                 arp->opcode = htons(ARP_REPLY);
85                                 memcpy(arp->target_ip, arp->sender_ip,
86                                        sizeof(ip_addr_t));
87                                 memcpy(arp->target_enet, arp->sender_enet,
88                                        sizeof(enet_addr_t));
89                                 memcpy(arp->sender_ip, __local_ip_addr,
90                                        sizeof(ip_addr_t));
91                                 memcpy(arp->sender_enet, __local_enet_addr,
92                                        sizeof(enet_addr_t));
93                                 pkt->pkt_bytes = sizeof(arp_header_t);
94                                 __enet_send(pkt, &arp->target_enet,
95                                             ETH_TYPE_ARP);
96
97                         } else if (ntohs(arp->opcode) == ARP_REPLY
98                                    && arp_req.waiting) {
99                                 if (!memcmp
100                                     (arp_req.ip, arp->sender_ip,
101                                      sizeof(ip_addr_t))) {
102                                         memcpy(arp_req.eth, arp->sender_enet,
103                                                sizeof(enet_addr_t));
104                                         arp_req.waiting = 0;
105                                 }
106                         }
107                 }
108         }
109         __pktbuf_free(pkt);
110 }
111
112 /*
113  * Find the ethernet address of the machine with the given
114  * ip address.
115  * Return 0 and fills in 'eth_addr' if successful,
116  *       -1 if unsuccessful.
117  */
118 int __arp_request(ip_addr_t * ip_addr, enet_addr_t * eth_addr, int allow_self)
119 {
120         pktbuf_t *pkt;
121         arp_header_t *arp;
122         unsigned long retry_start;
123         enet_addr_t bcast_addr;
124         int retry;
125
126         if (!allow_self) {
127                 // Special case request for self
128                 if (!memcmp(ip_addr, __local_ip_addr, 4)) {
129                         memcpy(eth_addr, __local_enet_addr,
130                                sizeof(enet_addr_t));
131                         return 0;
132                 }
133         }
134
135         /* just fail if can't get a buffer */
136         if ((pkt = __pktbuf_alloc(ARP_PKT_SIZE)) == NULL)
137                 return -1;
138
139         arp = pkt->arp_hdr;
140         arp->opcode = htons(ARP_REQUEST);
141         arp->hw_type = htons(ARP_HW_ETHER);
142         arp->protocol = htons(0x800);
143         arp->hw_len = sizeof(enet_addr_t);
144         arp->proto_len = sizeof(ip_addr_t);
145
146         memcpy(arp->sender_ip, __local_ip_addr, sizeof(ip_addr_t));
147         memcpy(arp->sender_enet, __local_enet_addr, sizeof(enet_addr_t));
148         memcpy(arp->target_ip, ip_addr, sizeof(ip_addr_t));
149
150         bcast_addr[0] = 255;
151         bcast_addr[1] = 255;
152         bcast_addr[2] = 255;
153         bcast_addr[3] = 255;
154         bcast_addr[4] = 255;
155         bcast_addr[5] = 255;
156
157         arp_req.eth = (char *)eth_addr;
158         arp_req.ip = (char *)ip_addr;
159         arp_req.waiting = 1;
160
161         retry = 8;
162         while (retry-- > 0) {
163
164                 /* send the packet */
165                 pkt->pkt_bytes = sizeof(arp_header_t);
166                 __enet_send(pkt, &bcast_addr, ETH_TYPE_ARP);
167
168                 retry_start = MS_TICKS();
169                 while ((MS_TICKS_DELAY() - retry_start) < 250) {
170                         __enet_poll();
171                         if (!arp_req.waiting) {
172                                 __pktbuf_free(pkt);
173                                 return 0;
174                         }
175                 }
176         }
177         __pktbuf_free(pkt);
178         return -1;
179 }
180
181 #define NUM_ARP 16
182 static ip_route_t routes[NUM_ARP];
183
184 int __arp_lookup(ip_addr_t * host, ip_route_t * rt)
185 {
186         int i;
187         static int next_arp = 0;
188
189         for (i = 0; i < NUM_ARP; i++) {
190                 if (memcmp(host, &routes[i].ip_addr, sizeof(*host)) == 0) {
191                         // This is a known host
192                         memcpy(rt, &routes[i], sizeof(*rt));
193                         return 0;
194                 }
195         }
196         memcpy(&rt->ip_addr, host, sizeof(*host));
197         if (((*host)[0] == 0xFF) && ((*host)[1] == 0xFF)
198             && ((*host)[2] == 0xFF)) {
199                 memset(&rt->enet_addr, 0xFF, sizeof(&rt->enet_addr));
200                 return 0;
201 #ifdef CYGSEM_REDBOOT_NETWORKING_USE_GATEWAY
202         } else if (!__ip_addr_local(host)) {
203                 // non-local IP address -- look up Gateway's Ethernet address
204                 host = &__local_ip_gate;
205 #endif
206         }
207         if (__arp_request(host, &rt->enet_addr, 0) < 0) {
208                 return -1;
209         } else {
210                 memcpy(&routes[next_arp], rt, sizeof(*rt));
211                 if (++next_arp == NUM_ARP)
212                         next_arp = 0;
213                 return 0;
214         }
215 }
Note: See TracBrowser for help on using the browser.