1 //==========================================================================
5 // Stand-alone minimal BOOTP 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 Red Hat, Inc.
12 // Copyright (C) 2002 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 //==========================================================================
58 #include <net/bootp.h>
62 #define SHOULD_BE_RANDOM 0x12345555
64 /* How many milliseconds to wait before retrying the request */
65 #define RETRY_TIME 1000
66 #define MAX_RETRIES 30
68 static bootp_header_t *bp_info;
70 #ifdef CYGSEM_REDBOOT_NETWORKING_USE_GATEWAY
71 static const unsigned char dhcpCookie[] = {99,130,83,99};
72 static const unsigned char dhcpEndOption[] = {255};
73 static const unsigned char dhcpRequestOption[] = {52,1,3};
77 bootp_handler(udp_socket_t *skt, char *buf, int len,
78 ip_route_t *src_route, word src_port)
81 #ifdef CYGSEM_REDBOOT_NETWORKING_USE_GATEWAY
82 unsigned char *p,*end;
86 b = (bootp_header_t *)buf;
88 memset(bp_info,0,sizeof *bp_info);
89 if (len > sizeof *bp_info)
90 len = sizeof *bp_info;
91 memcpy(bp_info, b, len);
94 // Only accept pure REPLY responses
95 if (b->bp_op != BOOTREPLY)
98 // Must be sent to me, as well!
99 if (memcmp(b->bp_chaddr, __local_enet_addr, 6))
102 memcpy(__local_ip_addr, &b->bp_yiaddr, 4);
103 #ifdef CYGSEM_REDBOOT_NETWORKING_USE_GATEWAY
104 memcpy(__local_ip_gate, &b->bp_giaddr, 4);
106 if (memcmp(b->bp_vend, dhcpCookie, sizeof(dhcpCookie)))
109 optlen = len - (b->bp_vend - ((unsigned char*)b));
112 end = ((unsigned char*)b) + len;
115 unsigned char tag = *p;
124 case TAG_SUBNET_MASK: // subnet mask
125 memcpy(__local_ip_mask,p,4);
127 case TAG_GATEWAY: // router
128 memcpy(__local_ip_gate,p,4);
139 #define AddOption(p,d) do {memcpy(p,d,sizeof d); p += sizeof d;} while (0)
142 * Find our IP address and copy to __local_ip_addr.
143 * Return zero if successful, -1 if not.
146 __bootp_find_local_ip(bootp_header_t *info)
148 udp_socket_t udp_skt;
153 ip_addr_t saved_ip_addr;
154 #ifdef CYGSEM_REDBOOT_NETWORKING_USE_GATEWAY
161 memset(&b, 0, sizeof(b));
163 b.bp_op = BOOTREQUEST;
164 b.bp_htype = HTYPE_ETHERNET;
166 b.bp_xid = SHOULD_BE_RANDOM;
168 #ifdef CYGSEM_REDBOOT_NETWORKING_USE_GATEWAY
171 AddOption(p,dhcpCookie);
172 AddOption(p,dhcpRequestOption);
173 AddOption(p,dhcpEndOption);
175 // Some servers insist on a minimum amount of "vendor" data
176 if (p < &b.bp_vend[BP_MIN_VEND_SIZE]) p = &b.bp_vend[BP_MIN_VEND_SIZE];
177 txSize = p - (unsigned char*)&b;
182 memcpy( saved_ip_addr, __local_ip_addr, sizeof(__local_ip_addr) );
183 memset( __local_ip_addr, 0, sizeof(__local_ip_addr) );
185 memcpy(b.bp_chaddr, __local_enet_addr, 6);
187 /* fill out route for a broadcast */
192 r.enet_addr[0] = 255;
193 r.enet_addr[1] = 255;
194 r.enet_addr[2] = 255;
195 r.enet_addr[3] = 255;
196 r.enet_addr[4] = 255;
197 r.enet_addr[5] = 255;
199 /* setup a socket listener for bootp replies */
200 __udp_install_listener(&udp_skt, IPPORT_BOOTPC, bootp_handler);
203 while (retry-- > 0) {
206 __udp_send((char *)&b, txSize, &r, IPPORT_BOOTPS, IPPORT_BOOTPC);
210 if (__local_ip_addr[0] || __local_ip_addr[1] || __local_ip_addr[2] || __local_ip_addr[3]) {
212 __udp_remove_listener(IPPORT_BOOTPC);
215 } while ((MS_TICKS_DELAY() - start) < RETRY_TIME);
219 __udp_remove_listener(IPPORT_BOOTPC);
221 memcpy( __local_ip_addr, saved_ip_addr, sizeof(__local_ip_addr));