]> git.karo-electronics.de Git - karo-tx-redboot.git/blob - packages/redboot/v2_0/src/net/old_bootp.c
RedBoot TX53 Release 2012-02-15
[karo-tx-redboot.git] / packages / redboot / v2_0 / src / net / old_bootp.c
1 //==========================================================================
2 //
3 //      net/bootp.c
4 //
5 //      Stand-alone minimal BOOTP 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 <redboot.h>
57 #include <net/net.h>
58 #include <net/bootp.h>
59
60 extern int net_debug;
61
62 #define SHOULD_BE_RANDOM  0x12345555
63
64 /* How many milliseconds to wait before retrying the request */
65 #define RETRY_TIME  1000
66 #define MAX_RETRIES   30
67
68 static bootp_header_t *bp_info;
69   
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};
74 #endif
75
76 static void
77 bootp_handler(udp_socket_t *skt, char *buf, int len,
78               ip_route_t *src_route, word src_port)
79 {
80     bootp_header_t *b;
81 #ifdef CYGSEM_REDBOOT_NETWORKING_USE_GATEWAY
82     unsigned char *p,*end;
83     int optlen;
84 #endif
85
86     b = (bootp_header_t *)buf;
87     if (bp_info) {
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);
92     }
93
94     // Only accept pure REPLY responses
95     if (b->bp_op != BOOTREPLY)
96       return;
97     
98     // Must be sent to me, as well!
99     if (memcmp(b->bp_chaddr, __local_enet_addr, 6))
100       return;
101         
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);
105     
106     if (memcmp(b->bp_vend, dhcpCookie, sizeof(dhcpCookie)))
107       return;
108                 
109     optlen = len - (b->bp_vend - ((unsigned char*)b));
110     
111     p = b->bp_vend+4;
112     end = ((unsigned char*)b) + len;
113     
114     while (p < end) {
115         unsigned char tag = *p;
116         if (tag == TAG_END)
117           break;
118         if (tag == TAG_PAD)
119           optlen = 1;
120         else {
121             optlen = p[1];
122             p += 2;
123             switch (tag) {
124              case TAG_SUBNET_MASK:  // subnet mask
125                 memcpy(__local_ip_mask,p,4); 
126                 break;
127              case TAG_GATEWAY:  // router
128                 memcpy(__local_ip_gate,p,4); 
129                 break;
130              default:
131                 break;
132             }
133         }
134         p += optlen;
135     }
136 #endif
137 }
138
139 #define AddOption(p,d) do {memcpy(p,d,sizeof d); p += sizeof d;} while (0)
140
141 /*
142  * Find our IP address and copy to __local_ip_addr.
143  * Return zero if successful, -1 if not.
144  */
145 int
146 __bootp_find_local_ip(bootp_header_t *info)
147 {
148     udp_socket_t udp_skt;
149     bootp_header_t b;
150     ip_route_t     r;
151     int            retry;
152     unsigned long  start;
153     ip_addr_t saved_ip_addr;
154 #ifdef CYGSEM_REDBOOT_NETWORKING_USE_GATEWAY
155     unsigned char *p;
156 #endif
157     int txSize;
158
159     bp_info = info;
160
161     memset(&b, 0, sizeof(b));
162
163     b.bp_op = BOOTREQUEST;
164     b.bp_htype = HTYPE_ETHERNET;
165     b.bp_hlen = 6;
166     b.bp_xid = SHOULD_BE_RANDOM;
167          
168 #ifdef CYGSEM_REDBOOT_NETWORKING_USE_GATEWAY
169     p = b.bp_vend;
170      
171     AddOption(p,dhcpCookie);
172     AddOption(p,dhcpRequestOption);
173     AddOption(p,dhcpEndOption);
174
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;
178 #else
179     txSize = sizeof(b);
180 #endif
181
182     memcpy( saved_ip_addr, __local_ip_addr, sizeof(__local_ip_addr) );
183     memset( __local_ip_addr, 0, sizeof(__local_ip_addr) );
184
185     memcpy(b.bp_chaddr, __local_enet_addr, 6);
186
187     /* fill out route for a broadcast */
188     r.ip_addr[0] = 255;
189     r.ip_addr[1] = 255;
190     r.ip_addr[2] = 255;
191     r.ip_addr[3] = 255;
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;
198
199     /* setup a socket listener for bootp replies */
200     __udp_install_listener(&udp_skt, IPPORT_BOOTPC, bootp_handler);
201
202     retry = MAX_RETRIES;
203     while (retry-- > 0) {
204                 start = MS_TICKS();
205
206                 __udp_send((char *)&b, txSize, &r, IPPORT_BOOTPS, IPPORT_BOOTPC);
207
208                 do {
209                          __enet_poll();
210                 if (__local_ip_addr[0] || __local_ip_addr[1] || __local_ip_addr[2] || __local_ip_addr[3]) {
211                                 /* success */
212                                 __udp_remove_listener(IPPORT_BOOTPC);
213                                 return 0;
214                 }
215                 } while ((MS_TICKS_DELAY() - start) < RETRY_TIME);
216     }
217
218     /* timed out */
219     __udp_remove_listener(IPPORT_BOOTPC);
220     net_debug = 0;
221     memcpy( __local_ip_addr, saved_ip_addr, sizeof(__local_ip_addr));
222     return -1;
223 }
224
225